bullets: resume-bullet inventory (contract revision 1.7) + find_bullets - #100
Merged
Conversation
The claim-sized middle layer between evidence and rendering:
story (evidence) -> bullet (claim) -> resume line (per-job selection).
Bullets are referenceable, so resume tailoring — Traitprint tooling or any
agent over MCP — selects and orders bullet IDS instead of regenerating
prose.
Schema (revision 1.7, additive): BulletSchema {id, text (non-blank,
<=300), story_ids, skill_ids, theme_tags, source, created_at, updated_at};
ExperienceSchema.bullets (<=20). story_ids form the evidence chain — a
bullet with a resolving story link is demonstrated, one without is
self-reported (evidenced: false on every read surface). Bullets supersede
the free-text accomplishments strings as the structured inventory
(accomplishments remains valid legacy text). Empty lists never reach
frontmatter, so pre-1.7 vaults round-trip byte-identically
(_OMIT_WHEN_EMPTY); the YAML normalizer now recurses into nested mappings
(bullets are the first nested structures carrying timestamps).
Trust layer: each bullet is its own dispute entity (kind "bullet",
labeled by its text) — dangling story_ids/skill_ids raise the standard
dangling_reference flags through _compute_disputes.
Lens relation (no new lens fields, no double-authoring): bullets inherit
emphasis TRANSITIVELY through their skill links — any core-salience link
leads, all-suppressed hides the bullet under that lens, unlinked bullets
stay supporting (_bullet_salience).
Read surface:
- find_bullets tool: query (text+tags), skill (name substring), lens
(slug/id), limit. NO default lens is auto-applied — the inventory stays
complete unless a lens is explicitly named (hiding bullets silently
would defeat "inventory"). Deterministic order: emphasis, evidenced,
newest, id.
- get_profile_summary (detailed): signature experiences carry their
visible bullets (core-first, cap 5, key omitted when none) — lens-aware
like the rest of the summary.
Contract docs: vault-v1 README rule 11 + revision 1.7 history;
$defs/bullet + experienceFrontmatter.bullets in the JSON schema; AGENTS/
README/GEMINI tool surfaces + the MCP serving note (doc-truth suite
green). CHANGELOG entry added.
Deferred to the cloud-coordinated follow-up (flagged per CLAUDE.md):
proposal support for bullets in experience payloads (proposals.py mirrors
cloud vault_propose validation, untouched here), the hosted find_bullets
mirror, and story->bullet generation (mining/BYOK).
1072 tests pass (round-trip byte-identity, hand-edit loads, dispute
flags, lens projection, filters); ruff + mypy clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RdYoLHB9CWNAdf8gZVjShZ
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: afcf974916
ℹ️ 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".
Five Codex findings on #100: - P1: `traitprint vault audit` now reports dangling bullet references (bullet.dangling_story / bullet.dangling_skill, major — same Layer 1 rules as the other cross-links), not just the MCP dispute layer. _audit_experiences gains the story_ids set; findings carry the bullet id and a text excerpt. - P1: the JSON Schema's bullet.text gains pattern "\S" so schema-driven writers reject whitespace-only text exactly like the model validator (Layer-0 contract no weaker than the local model). - P2: experience.thin now counts bullets as role content — a role migrated to bullets-only (empty description/accomplishments) is no longer falsely labeled title-and-date-only. - P2: GEMINI.md no longer lists find_bullets as a HOSTED tool (its mirror hasn't shipped); it is documented as local-only for now, and AGENTS.md's local↔hosted delta says the same. - P2: AGENTS.md's hand-edit frontmatter allowlist documents `bullets` (shape, caps, evidence semantics) — hand-editing is currently the only write path since proposal support is a coordinated follow-up. 1077 tests pass (5 new audit tests incl. bulleted-role-not-thin and resolving-refs-clean); ruff + mypy clean; doc-truth suite green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RdYoLHB9CWNAdf8gZVjShZ
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Experiences get structured bullets: the claim-sized, referenceable middle layer between evidence and rendering —
The inventory is what resume tailoring draws from: Traitprint's own tooling or any agent over MCP selects and orders bullet ids instead of regenerating prose — deterministic, auditable, and provably backed by the vault.
What's in this PR
Schema — vault contract revision 1.7 (additive)
BulletSchema{id, text, story_ids, skill_ids, theme_tags, source, created_at, updated_at};textnon-blank, ≤300 chars; ≤20 bullets per experience, onExperienceSchema.bullets.story_idsare the evidence chain: a resolving link makes the bullet demonstrated; none (or only dangling ones) makes it self-reported — surfaced asevidenced: falseeverywhere it renders, the same trust signal as anevidence_count: 0skill.accomplishmentsstrings as the structured inventory;accomplishmentsstays valid legacy text._OMIT_WHEN_EMPTY, byte-identical round-trip for pre-1.7 vaults, hand-edit tolerant (the YAML normalizer now recurses into nested mappings — bullets are the first nested structures carrying timestamps).Trust layer
bullet, labeled by its text): danglingstory_ids/skill_idsraise standarddangling_referenceflags through_compute_disputesand ride the profile-summary roll-up.Lens relation — the design question this PR answers
corelink leads, all-suppressed hides the bullet under that lens, unlinked bullets staysupporting. One authoring surface (the lens's existingskill_salience), zero double-bookkeeping — the IC lens automatically leads with architecture bullets and hides the Product-Management ones.Read surface
find_bulletstool:query(bullet text + theme tags),skill(name substring over linked skills),lens(slug/id),limit. No default lens is auto-applied — the inventory stays complete unless a lens is explicitly named, because silently hiding bullets would defeat "inventory" (a tailoring agent must see everything it may draw from). Deterministic ordering: emphasis → evidenced → newest → id.get_profile_summary(detailed): signature experiences carry their visible bullets (core-first, cap 5, key omitted when none) — lens-aware like the rest of the summary.Docs — vault-v1 README rule 11 + revision-1.7 history,
$defs/bulletin the JSON schema, AGENTS/README/GEMINI tool surfaces + the MCP serving note (the doc-truth suite pins all of these — green), CHANGELOG entry.Cloud coordination (flagged per CLAUDE.md)
src/traitprint/proposals.pyis untouched — bullets are not yet proposable, because the experience-payload key whitelist mirrors the hostedvault_proposevalidation. Landing in tandem as follow-ups: the hostedfind_bullets+experience_bulletsmirror (GEMINI.md already lists the tool ahead of that PR), proposal-payload support on both servers, and story→bullet generation (mining/BYOK).Verification
1072 tests pass — including round-trip byte-identity (no-bullet vaults gain no key; full bullets survive save→load→save exactly), hand-edited frontmatter loads (incl. YAML-native timestamps + blank-text rejection), per-bullet dispute flags + roll-up labeling, transitive lens emphasis (core-wins-over-mixed, all-suppressed hidden),
find_bulletsfilters + no-default-lens behavior, and lens-aware summary bullets.ruffclean;mypy src/clean on changed files.🤖 Generated with Claude Code
https://claude.ai/code/session_01RdYoLHB9CWNAdf8gZVjShZ
Generated by Claude Code