Problem
capture-event's fresh-capture path (prepareEvent) hand-assembles a raw frontmatter field array and serializes it through a bespoke renderEventNote helper family, instead of composing a KbEvent and rendering it through the record module's renderEvent. It is the last event write path outside the KbEvent contract: the amend path already composes a KbEvent and round-trips through renderEvent/parseEvent, and #853 already moved add-path validation to parseEvent. Because the bespoke renderer orders fields differently from renderEvent, the same event captured then amended silently reorders its frontmatter.
Context
Part of the per-type record architecture epic (#848). Sibling pattern: kb-add composes a KbAssertion and renders via renderAssertion (#852). #853 already removed the generic loadSchema/frontmatterRule/runRules path from capture-event — those symbols no longer exist anywhere in the repo — so this is the composition remainder, not a rule-engine migration.
The add path writes via the collision-safe hard-link writer (writeEvent), which the amend path's overwrite writer (writeNote) cannot replace; so the add path renders to a string via note-io's renderNote and keeps writeEvent.
Proposed solution
Compose a KbEvent in prepareEvent (with repo/skill/model/harness carried in extra, since KbEvent has no typed field for them) and render it via renderEvent → note-io renderNote, deleting the bespoke renderEventNote/renderFlowList/renderScalar/SCALAR_STRINGIFY_OPTIONS family. Retain the post-render re-parse guard through parseEvent, mirroring the amend path.
Acceptance criteria
Must have
Problem
capture-event's fresh-capture path (prepareEvent) hand-assembles a raw frontmatter field array and serializes it through a bespokerenderEventNotehelper family, instead of composing aKbEventand rendering it through the record module'srenderEvent. It is the last event write path outside theKbEventcontract: the amend path already composes aKbEventand round-trips throughrenderEvent/parseEvent, and #853 already moved add-path validation toparseEvent. Because the bespoke renderer orders fields differently fromrenderEvent, the same event captured then amended silently reorders its frontmatter.Context
Part of the per-type record architecture epic (#848). Sibling pattern:
kb-addcomposes aKbAssertionand renders viarenderAssertion(#852). #853 already removed the genericloadSchema/frontmatterRule/runRulespath fromcapture-event— those symbols no longer exist anywhere in the repo — so this is the composition remainder, not a rule-engine migration.The add path writes via the collision-safe hard-link writer (
writeEvent), which the amend path's overwrite writer (writeNote) cannot replace; so the add path renders to a string via note-io'srenderNoteand keepswriteEvent.Proposed solution
Compose a
KbEventinprepareEvent(withrepo/skill/model/harnesscarried inextra, sinceKbEventhas no typed field for them) and render it viarenderEvent→ note-iorenderNote, deleting the bespokerenderEventNote/renderFlowList/renderScalar/SCALAR_STRINGIFY_OPTIONSfamily. Retain the post-render re-parse guard throughparseEvent, mirroring the amend path.Acceptance criteria
Must have
prepareEventcomposes aKbEventand renders it viarenderEvent, not a hand-assembled field array.renderEventNoteand its scalar/list helpers) is removed.renderEventoutput (typed fields first;repo/skill/model/harnessas trailingextrafields).parseEvent.