feat(followups): mutation + ex-ante creation verbs (CHARTER-01 — closes #355, #360) - #376
Merged
Merged
Conversation
…#360) Closes the last flows that required hand-editing the CLI-parsed registry. - `followups note FU-NNN "<text>" [--source ID]` — dated annotation appended to Notes. The field is single-line by parser contract, so annotations compose onto the existing value; --source records what motivated it. - `followups set-status FU-NNN <status>` — status AND counters in one step, closing the desync window recount exists to clean up after. An out-of-vocabulary status is refused, not written: the parser is lenient, so a typo would not fail — it would silently drop the entry from every counter. `promoted` redirects to `followups promote`, which writes the TDE the status points at. - `followups new --title … --origin "CHARTER-NN §Scope"` — an entry declared ex-ante, before any AILOG exists. The id is assigned atomically and printed, so a Charter cites an entry that EXISTS: ids are minted max+1 at extraction, so the adopter's forward-referenced FU-011 would have been handed to an unrelated entry by the next `drift --apply`. All three refuse to write a registry with parse warnings — a surgical edit against a mis-read structure can corrupt neighbouring entries. One shared recompute-and-write path (`write_recounted`) backs every mutating verb, and `recount` now uses it too, so it stays the idempotent check on their arithmetic rather than a second implementation. The schema needed no change: `origin_class` already carried `ex-ante-planning` and `source_hash` is not a schema property. The vocabulary for the ex-ante case existed; only the creation path was missing. Also fixes two pre-existing shape defects in the shared write helpers, which every drift/promote/verify write had been degrading the registry with: `set_entry_field` collapsed an entry's trailing blank line (gluing it to the next `## Bucket:` heading) and `insert_into_bucket` omitted the blank line before the following section. Documented as R6 (new, not in Charter). fw-4.37.0 / cli-3.39.0. CHARTER-01 closed; AILOG-2026-07-26-001. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Closes #355. Closes #360. Executes CHARTER-01 (declared in #374) — the repo's first executed Charter since self-adoption.
Ships as fw-4.37.0 / cli-3.39.0.
The three verbs
followups note FU-NNN "<text>" [--source ID]Notesis single-line by parser contract, so annotations compose onto the existing value;--sourcekeeps them attributable instead of undated prose.followups set-status FU-NNN <status>recounttwo-step desyncs the moment you forget the second half, leaving the counters quietly lying about the backlog. Now one step.followups new --title … --origin "CHARTER-NN §Scope"set-statusrefuses rather than damages: an out-of-vocabulary status is rejected, because the parser is lenient — a typo would not fail, it would silently drop the entry from every counter.promotedredirects tofollowups promote, which also writes the TDE that gives the status something to point at.Why
newis a correctness fix, not ergonomics: ids are mintedmax(existing) + 1at extraction time, so the adopter's forward-referencedFU-011(cited three times in CHARTER-06 with nothing reserving it) would have been handed to an unrelated entry by the nextdrift --apply, silently repointing those citations.newassigns the id atomically and prints it, so by the time the Charter cites it the entry exists.All three refuse to write a registry with parse warnings — a surgical edit against a structure the parser mis-read can corrupt neighbouring entries.
Two findings worth flagging
The schema needed no change — and that reframes #360. The Charter declared the schema conditionally ("confirm the ex-ante shape validates; adjust
$defs.entryif not"). It validates unchanged:origin_classalready carriesex-ante-planningin its enum, andsource_hashis not a schema property at all. The vocabulary for the ex-ante case already existed; only the creation path was missing.Two pre-existing defects in shared write helpers (R6, new — not in Charter).
set_entry_fieldcollapsed an entry's trailing"\n\n"to"\n", gluing the edited entry to the next## Bucket:heading, andinsert_into_bucketappended entries with no blank line before the following section. Both are shared, so everydrift --apply/promote/verifywrite had been reshaping the registry a little. Making field writes routine vianoteis what exposed them. Fixed at the root with regression tests rather than worked around.What stayed deferred
Both options the Charter declared out of scope remain so, and nothing in execution argued otherwise: no id-reservation primitive (#360 Option C — atomic
newcloses the window by construction; a reservation registry would be a second source of truth for id assignment) and no Charter-scanning indrift(Option B — its dedup is keyed on an AILOG-derivedSource-hash).Verification
cargo test: 38 groups green. 10 new integration tests + 5 new unit tests, including the byte-identical-file assertion after a refused write, the "a followingrecountfinds nothing to do" assertion, and the R4new-then-driftno-duplicate check.cargo clippy -p straymark-cli: no warnings in the three new modules.gen_codex_skills --check: in sync.new→note→set-status→recountreports "already in sync" →list→driftdoes not re-extract. Then the guard: a malformed### FU-heading makesnoteexit 1 with nothing written.straymark validate . --include-charters→ 0 errors.charter drift CHARTER-01→ 1 omission + 14 expansions, all four causes documented in## Closing notesin this same PR (the atomic-update convention), including the one worth naming: the Charter declared the Gemini/.agentskill mirrors as "regenerated by the same generator" —gen_codex_skillsonly emits.codex, so those two are hand-maintained and were hand-synced. The reconnaissance discipline ([adopter] Charter scope declared against assumed (un-read) code — propose a code-reconnaissance gate at charter creation #210) had been applied to the files but not to the mechanism that maintains them.Framework: pattern doc + template +
/straymark-followupsskill (all 4 agent surfaces) ×3 locales. Docs: CLI-REFERENCE ×3 locales,CLAUDE.md, version tables,CHANGELOG.md. Governed AILOG:AILOG-2026-07-26-001.🤖 Generated with Claude Code