v0.48.0
[0.48.0] — 2026-08-27
Added
- Six report-only role specs —
qa,ux,analyst,exa-researcher,architect,security-reviewer— now each state their own turn budget inside their own spec file, and a new automated check keeps that number honest (T-728) — if you ever change one of these roles' turn-budget cap, you now must change it in two places at once: the frontmatter cap itself, and the matching number written into that same spec's own "Budget awareness" section.scripts/test-agent-spec-sync.jsnow fails the whole test suite the moment those two numbers disagree, or if the set of six covered roles changes without a matching section being added or removed — so a drifted cap or a forgotten section is caught before it ships, not discovered later in a truncated report. Each of these six specs now self-counts its own tool calls against its stated number, converges on a partial-but-real report at roughly 80% of that budget instead of running to the cliff where the report itself gets cut off, and still honours a brief-lineTurn budget:override when the Main Agent supplies one.
Changed
qa's turn budget rose from 20 to 40 andarchitect's from 25 to 50, after evidence that both roles were hitting their prior caps mid-report with the write-up lost, not the underlying work (T-727) — a multi-run evidence table showed truncated runs, when resumed, made zero or almost zero new tool calls before producing their report: the research was already done, and only the final write-up was cut off by the cap. The new caps land below the full formula-derived ceiling, applying the same discount this project has already used for this role class's read-heavy tool-call over-counting, rather than granting the raw formula output unconditionally.docs/AGENT_SPEC.mdgains a canonical "Budget awareness" section, theTurn budget:brief line is reframed as an override/retry channel rather than the primary source of the number, and thetool_useslogging denominator is now spelled out explicitly (T-729) — the self-stated-budget mechanism T-728 shipped into six role specs now has one documented home explaining the roster rule (which roles are covered and why) and why making the brief-line field mandatory was rejected in favor of embedding the number in each spec instead — recorded as DR-014 indocs/core/DECISIONS.md. Because most roles now state their own default budget, theTurn budget:brief line is described as a way to override that default or retry after a cap-hit, not as the only place the number can come from.CLAUDE.md's per-spawn logging convention now states plainly that thetool_uses: N/capdenominator is the role's own frontmattermaxTurnsat spawn time, so a logged cap that doesn't match must name its source.
[0.47.3] — 2026-08-23
- The T-718 CHANGELOG-omission advisory no longer fires on a release bump-and-fold commit that touches only
scripts/mavp-version.jsandpackage.jsonalongsideCHANGELOG.mditself (T-724) — a shape-based exemption, not a path exemption: it recognizes the §5 version-ritual file set specifically, so a standalonepackage.jsondependency change (noCHANGELOG.mdfold) still fires, and a ritual commit that also smuggles in another shipped file still fires too.
[0.47.2] — 2026-08-23
Entries below carrying the inline marker (shipped in v0.47.1, documented late) — and only those — describe normative rules that were already in force at that tag: v0.47.1's CHANGELOG.md section covered only T-710 and froze the moment the tag was cut (docs/PUBLIC_RELEASE_STRATEGY.md §5 — "Frozen-section rule"), so their notes could not be added to it afterwards. The ## [0.47.1] section is left exactly as shipped; the marked entries are the correction record. If you are reading a marked entry under a later version heading, the rule it describes did not arrive in that version — it has been in force since v0.47.1. Every unmarked entry is an ordinary release note: the change it describes first ships in the version this section is published under.
Added
- Before booking
mergedon a task with no QA stage, the Main Agent now owes one executed check against the report's weakest unverified claim (T-712, T-713; shipped inv0.47.1, documented late) —docs/core/ORCHESTRATION_RULES.mdgains a "Booking-time claim verification (merge duty — before bookingmergedon a task with no QA stage)" section, the return-side sibling of the existing Executed-check rule that governs claims written before a spawn. Its premise: a prose characterization of runtime behavior is a runtime claim. "Fails silently", "never blocks", "exits 0", "warns and continues", "degrades to a no-op" are assertions with an executable check behind them, and being written as prose in a sub-agent's report rather than as an assertion in a test does not change what they are — a report is not evidence for its own factual claims, it is the set of claims to be checked. On a task withartifactorunitverification type,CLAUDE.md's "Verification types" convention waives the QA agent pass, so whatever the Main Agent accepts is what ships. Before bookingmergedon such a task, identify the report's factual claims that have no execution behind them and run the cheapest disconfirming check against the weakest one: one grep at the named function, one run of the named command, one read of the docstring the claim characterizes — not an exhaustive re-verification. If the weakest claim survives, the report has earned the rest of its trust; if it does not, nothing else in the report is trusted until it is corrected. Weakest, not pre-flagged: verification attention already follows the brief's own risk annotations, so the unflagged claim is the one that arrives unverified — the failure mode is thorough verification in exactly the place already marked as risky while an unanticipated claim rides through beside it, which is why the rule says to deliberately exclude the claims the brief pre-flagged when choosing the target. This is explicitly not "reaching in": the orchestrator discipline forbids the Main Agent from doing the sub-agent's work, but verifying a sub-agent's claims before making them durable is a merge-gate action, and on a QA-less task it is the only gate that exists. The incident it closes (2026-08-23, T-708/T-709): anartifact-verified report characterized a code path as "a silent-degradation question" and that characterization merged into a living normative doc a reviewer reads as fact — while the code prints a red WARNING at the moment of the skip and its own docstring says "never a silent skip", one grep from the code the sweep had just read. DR-013 indocs/core/DECISIONS.mdrecords the ruling behind the section, and itsDocumented in:line now names the section itself, completing the forward reference (T-713). --close-sessionnow warns when a just-completed task's evidence commit touched a ship-classified file but the task is never mentioned inCHANGELOG.md(T-718) — printed once, non-blocking, before the results table in both interactive and non-interactive modes; silent when the task is already mentioned, or when git,scripts/publish-manifest.json, orCHANGELOG.mditself is unavailable. Never changes the exit code or the session-commit contract.
Changed
- The T-718 CHANGELOG-omission advisory no longer flags a commit that touches only
CHANGELOG.md(T-721) — its first live run at wave 94's close proved a self-referential false positive: a commit that writes a release note tripped the check asking whether the release note mentions it (T-716, T-719), while a genuinely undocumented ship-touching commit (T-717) still fires correctly.CHANGELOG.mdis now exempted at the advisory's own ship-intersection check via a named constant; a commit touchingCHANGELOG.mdalongside another ship-classified file is unaffected and still fires. - Per-operator memory is now the residual codification route rather than one that fits everything, and the codification mandate governs any durable lesson — not only ones written up in an RCA (T-711, DR-013; shipped in
v0.47.1, documented late) —docs/core/RCA_CODIFICATION.mdroutes every root cause to exactly one of five durable mechanisms, but gave route (c), the per-operator memory-index entry, only a fit test. That test is unfalsifiable in practice: every lesson is rememberable, so route (c) fits every cause, and it is the one route that costs no task, no architect gate and no review — so absent a precedence rule the cheapest route silently won every tie, and on 2026-08-23 a framework-portable lesson went to memory instead of into the framework. The deciding test is now portability: would this lesson be equally true for a different operator running this framework on a different machine? Yes → framework-level: the cause must route to a.claude/rulesedit proposal, a role-spec proposal viaSKILL_PROPOSALS/, an armed recheck, or a mechanical enforcement change, and memory may then hold at most a pointer — an entry naming theT-NNNor artifact that actually carries the rule. No → operator-scoped: memory is the correct and only sensible home. This is a tie-break, not a ban and not a ranking of all five routes — operator-personal lessons (a language preference, this machine's git identity, this operator's permission posture) legitimately live in memory, and route (c) remains optional infrastructure: an operator whose harness provides no memory index at all loses nothing, because nothing framework-level may ever live only there. What the rule forbids is the one direction that hurts adopters — a lesson that would hold for any operator going only to memory, where it is invisible to adopters, invisible to the reflection loop indocs/SKILL_OPTIMIZATION.md(which mines task outcomes, never memory), and not greppable over the repo. The same routing table and test now govern any durable lesson, including one noticed mid-session with no RCA behind it: the mid-session reflex "I should write this down so I remember it next time" is itself the trigger to run the portability test — before the memory entry is written, not after — and a framework-level verdict owes a task registered through the normal architect gate, with writing it to memory not a substitute and smallness not a reason to skip the gate. Enforcement is deliberately pull-consumed — no validator check and no hook, because a memory write lands outside the repo tree where nothing observes it and portability is a semantic property no matcher could judge — with a compensating observable form: a memory entry recording a framework-portable lesson must name inline the task or artifact that carries the rule, so a pointer with no carrier named is the visible failure.templates/RCA_TEMPLATE.mdandCLAUDE.md's "RCA-to-codification" convention carry one-line pointers to the tie-break. - The version-bump trigger and the release-note trigger are now explicitly separate, so a doc-only wave can owe a release note while owing no version bump (T-717) —
docs/PUBLIC_RELEASE_STRATEGY.md§5's per-wave bullet previously said a doc-only wave needs no version bump "and therefore no changelog entry either — the two triggers stay in lockstep". They are not in lockstep, and that clause was the codified cause of a real gap: wave 93 changed fiveship-classified files, shipping normative rules to adopters insidev0.47.1with no release note at all — correctly, by the rule's own text. The two triggers now read separately. A version bump is owed by script or capability changes, per §5's unchanged bump policy. A release note is owed by any wave that changes content classifiedshipinscripts/publish-manifest.json, including a doc-only wave: such a wave owes no bump, but the rules it changed reach adopters on the next mirror sync regardless of the version stamp, and a rule that arrives unannounced is a rule adopters have no reason to look for. Because every path'sship/excludeclassification is already recorded in the manifest, "does this wave owe a note?" is mechanically decidable rather than a judgment call. When a bump accompanies the note, the note opens the new numbered section as before; when no bump accompanies it, it goes under## [Unreleased]and is folded into the next numbered section at the next bump.CLAUDE.md's "Version bump" convention keeps "Doc-only waves need no bump" verbatim and gains the matching note-owed clause pointing at §5. The rule caught its own author: T-717's commit changedCLAUDE.md— itselfship-classified — and left no release note, the T-718 advisory flagged the omission at the next wave close, and this entry is that note.