Problem
The record-type schema declares an immutable: boolean per record type (event is true, assertion is false), but nothing reads it. kb-edit never gates on it, recall (kb-retrieve) ignores it, and validation never enforces it. So immutable: true is a declared-but-unconsumed field that implies an enforced write-once guarantee while providing none — a trust gap, since anyone reading the schema reasonably assumes the flag does something.
This ticket originally proposed making kb-edit honor the flag. Investigation showed enforcement would protect almost nothing: recall ranks events on captured-at and a repo-keyed recurrence count, never on updated; no kb-edit operation touches those recall-critical fields; the gate would be advisory only (a hand-edit, sed, or merge bypasses it); and freezing tags would actively degrade recall, since tags are a live recall signal that benefits from curation. Removing the false signal is the honest fix.
Context
- The flag is declared in
RecordTypeSchema (packages/kb/src/types.ts), set in default-schema.ts, parsed in load-schema.ts, and materialized into seed schemas via render-seeds.ts and bundle-skill-helpers.ts.
- Events stay write-once in practice without the flag: capture-event only ever creates event records, and its SKILL.md already states "Captures are write-once: there is no edit or re-capture step." That guidance, not the schema flag, is what keeps events write-once.
- The field lists already encode the lifecycle shape:
event omits updated/last-verified/superseded-by from its required and optional sets. The boolean was a fuzzier restatement of that.
- If genuine enforcement is ever wanted, the right mechanism is optional-allowlist validation (reject undeclared frontmatter fields), driven by the existing field lists. Tracked separately, not part of this change.
Proposed solution
Remove immutable from the schema vocabulary and every place that declares, parses, or materializes it. kb-edit is deliberately out of scope: it never read the flag, so its behavior is identical before and after, and adding an event-mutation guard was considered and declined (it would either resurrect the advisory enforcement we're removing or introduce an inconsistent partial check). capture-event's write-once narrative stays accurate, since it describes the helper's create-only write rather than the flag. An on-disk .kb/schema.yaml that still declares immutable: continues to load: the zod record-type shape strips the unknown key rather than rejecting it, so existing stores are unaffected.
Acceptance criteria
Must have
Should have
Dependencies
Problem
The record-type schema declares an
immutable: booleanper record type (eventistrue,assertionisfalse), but nothing reads it. kb-edit never gates on it, recall (kb-retrieve) ignores it, and validation never enforces it. Soimmutable: trueis a declared-but-unconsumed field that implies an enforced write-once guarantee while providing none — a trust gap, since anyone reading the schema reasonably assumes the flag does something.This ticket originally proposed making kb-edit honor the flag. Investigation showed enforcement would protect almost nothing: recall ranks events on
captured-atand arepo-keyed recurrence count, never onupdated; no kb-edit operation touches those recall-critical fields; the gate would be advisory only (a hand-edit,sed, or merge bypasses it); and freezingtagswould actively degrade recall, since tags are a live recall signal that benefits from curation. Removing the false signal is the honest fix.Context
RecordTypeSchema(packages/kb/src/types.ts), set indefault-schema.ts, parsed inload-schema.ts, and materialized into seed schemas viarender-seeds.tsandbundle-skill-helpers.ts.eventomitsupdated/last-verified/superseded-byfrom its required and optional sets. The boolean was a fuzzier restatement of that.Proposed solution
Remove
immutablefrom the schema vocabulary and every place that declares, parses, or materializes it. kb-edit is deliberately out of scope: it never read the flag, so its behavior is identical before and after, and adding an event-mutation guard was considered and declined (it would either resurrect the advisory enforcement we're removing or introduce an inconsistent partial check). capture-event's write-once narrative stays accurate, since it describes the helper's create-only write rather than the flag. An on-disk.kb/schema.yamlthat still declaresimmutable:continues to load: the zod record-type shape strips the unknown key rather than rejecting it, so existing stores are unaffected.Acceptance criteria
Must have
immutableis removed fromRecordTypeSchemaand from the default schema's record types.load-schemano longer parses or normalizesimmutable, and a.kb/schema.yamlthat still declaresimmutable:loads successfully with the key ignored.render-seeds, the bundled capture-event store schema inbundle-skill-helpers.ts) no longer emitimmutable:.immutableare updated or removed, and the schema-compat behavior above is covered by a test.Should have
packages/kb/README.md's schema documentation is updated to dropimmutable. Narrative write-once/immutable language describing capture-event's create-only write is left intact where still accurate.Dependencies
immutable) and Validate a store schema against the generic kb-skill contract #746.