Skip to content

feat: vault contract v1.2 — experience skill_links (per-link proficiency)#48

Merged
the-data-viking merged 1 commit into
mainfrom
claude/serene-archimedes-knryzi
Jun 13, 2026
Merged

feat: vault contract v1.2 — experience skill_links (per-link proficiency)#48
the-data-viking merged 1 commit into
mainfrom
claude/serene-archimedes-knryzi

Conversation

@the-data-viking

Copy link
Copy Markdown
Contributor

Summary

Vault contract revision 1.2 — adds optional per-link proficiency to experiences (the Local + contract-schema side; Cloud side is traitprint-cloud's paired PR). Additive: schema_version stays 1, vaults written against 1.0/1.1 remain valid and round-trip byte-identical.

New optional skill_links: [{ skill_id, proficiency? 1–5 }] on experiences only (stories unchanged — proficiency belongs to a multi-year role, not a single STAR anecdote, and it avoids a projection migration on the Cloud side). skill_ids stays authoritative for membership; skill_links only annotates a skill already in skill_ids (stray entries are dropped). Empty skill_links is omitted from frontmatter so 1.1 vaults stay byte-identical.

Changes

  • docs/schema/vault-v1/vault-v1.schema.json: $defs/skillLink, experienceFrontmatter.skill_links, $comment bumped to 1.2; manifest schema_version stays 1. Story $defs untouched.
  • schema.py: SkillLink model + ExperienceSchema.skill_links (default empty); StorySchema untouched.
  • vault_io.py: skill_links in EXPERIENCE_FRONTMATTER_KEYS + omit-when-empty.
  • proposals.py: skill_links in _EXPERIENCE_KEYS only.
  • vault.py / cli.py: add_experience accepts skill_links (filters stray skill_ids); repeatable --skill-link '<uuid>:<1-5>' flag + JSON-batch support.
  • README revision history.

Testing

  • pytest: 622 passed / 3 skipped (exit 0)
  • ruff check: clean (exit 0)
  • mypy: 1 error at cli.py:38 (click.ParamType[UUID]) — pre-existing, confirmed byte-identical on a clean origin/main worktree; not introduced here.
  • Cross-product interop verified against the Cloud branch: Local's PyYAML skill_links render parses correctly on Cloud's frontmatter parser, and Cloud's render parses back through PyYAML + the schema — round-trips in both directions with proficiency preserved.

Pairs with traitprint-cloud's v1.2 PR; they share one authoritative contract spec.

https://claude.ai/code/session_01PsAQUnoLH94f2cbK2dSpox


Generated by Claude Code

…cy annotations)

Additive over 1.1; manifest schema_version stays 1. Adds an optional
`skill_links` array to the experience entity only — `{ skill_id, proficiency? }`
objects that annotate a per-skill proficiency (1-5) for skills already listed
in `skill_ids`. `skill_ids` remains authoritative for membership: links whose
skill_id is not in skill_ids carry no membership effect (dropped by the store
API). Empty `skill_links` is omitted from frontmatter so 1.1 vaults round-trip
byte-identically. Stories are unchanged.

- docs/schema/vault-v1/vault-v1.schema.json: add `$defs/skillLink`
  (additionalProperties:false, reuses shared proficiency def), wire
  `skill_links` into experienceFrontmatter, append 1.2 note to `$comment`.
- docs/schema/vault-v1/README.md: revision-history entry + rule 2 prose,
  bump header to revision 1.2.
- schema.py: new `SkillLink` model; optional `skill_links` on ExperienceSchema.
- vault_io.py: `skill_links` in EXPERIENCE_FRONTMATTER_KEYS; `_OMIT_WHEN_EMPTY`
  so empty collections are dropped from frontmatter.
- proposals.py: `skill_links` in `_EXPERIENCE_KEYS` only.
- vault.py / cli.py: add_experience accepts & filters skill_links; new
  repeatable `--skill-link '<uuid>:<1-5>'` CLI flag + JSON-batch support.
- tests: schema, CRUD round-trip + empty-omit, proposal accept (exp) / reject
  (story); relax the frontmatter-contract test for omit-when-empty keys.

https://claude.ai/code/session_01PsAQUnoLH94f2cbK2dSpox
@the-data-viking the-data-viking enabled auto-merge (squash) June 13, 2026 04:34

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b21cacd36c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/traitprint/schema.py
"""

skill_id: UUID
proficiency: int | None = Field(default=None, ge=1, le=5)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Omit unset link proficiency from serialized vaults

When a link is created with no proficiency (accepted by this model and by bare --skill-link parsing), Pydantic keeps proficiency=None; the existing frontmatter writer uses model_dump(mode="json"), so the vault is written with proficiency: null. The v1.2 JSON Schema only permits an integer when proficiency is present, so a load/save round-trip of an otherwise valid optional-proficiency link produces a vault that schema/cloud validation can reject. Omit None fields inside skill_links before writing, or make the contract explicitly nullable.

Useful? React with 👍 / 👎.

Comment thread src/traitprint/schema.py
description: str = ""
accomplishments: list[str] = Field(default_factory=list)
skill_ids: list[UUID] = Field(default_factory=list)
skill_links: list[SkillLink] = Field(default_factory=list)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Enforce skill_links membership in the model

Since ExperienceSchema is used directly by read_vault_tree and proposal approval, this field accepts and later re-emits skill_links whose skill_id is not in skill_ids; the only filtering is in VaultStore.add_experience. If a hand-edited/synced vault or an add/update_experience proposal carries a stale link, the model preserves a proficiency annotation for a skill that is not exercised in the role, even though v1.2 says such entries are ignored and skill_ids is authoritative. Normalize or drop those links during ExperienceSchema validation so every load/apply path has the same behavior.

Useful? React with 👍 / 👎.

@the-data-viking the-data-viking disabled auto-merge June 13, 2026 04:43
@the-data-viking the-data-viking enabled auto-merge (squash) June 13, 2026 04:58
@the-data-viking the-data-viking merged commit 1067787 into main Jun 13, 2026
4 checks passed
@the-data-viking the-data-viking deleted the claude/serene-archimedes-knryzi branch June 13, 2026 05:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants