Plan 3: recovery re-merge dispatch coherence — submodule scoping on every retry, ADR 0019/0040 cross-reference, rot-proof capture comment - #1117
Merged
Ljferrer merged 10 commits intoJul 26, 2026
Conversation
…ence r1 (3 minor roots auto-fixed: real Scope-paragraph anchors, case-insensitive sweeps, both-routes amendment body) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… rot-proof the gateCaptureClause comment (#1112) A taskType:'submodule' task whose first merge trips a recoverable route was re-dispatched UNSCOPED: the SUBMODULE TASK targetRepo/targetBase paragraph rode only the initial merge-task prompt. The floor-retry re-merge (merge:<taskId>:floor-retry:r<round>), the environment-proceed re-merge and the baseline-proceed re-merge all omitted it, so the refiner would rebase and gate in the SUPERPROJECT on any retry. Fix: append the already-in-scope `submodMergeNote` const as the final prompt segment at each of the three retry dispatches, mirroring the initial merge-task prompt's trailing placement (after the requiresPackaging ternary). No helper, no re-derivation, no dispatch-option, enum, schema or routing change. The const is '' for non-submodule tasks, so every existing non-submodule prompt is byte-identical — no existing prompt-content test moved (932/932 green). No agents/war-refiner.md mirror edit — deliberate, and this is where the auditor adjudicates it. The standing refiner doc's submodule-phase scope sentence already makes the generic claim this change brings the dispatched surface up to: "All merge-task and land-phase steps below run with `<taskWorktree>` and `<_refinery>` rooted in the submodule checkout." "All merge-task ... steps" already covers the retries; the dispatched prompts were the surface that diverged. There is no same-commit standing mirror edit to miss (plan Notes / spec §2). Comment rot-proofing: the gateCaptureClause (D5) header comment enumerated 2 of its 3 consumer sites. Its site list is now count-free — the clause rides the dispatched merge-task prompts whose evidence contract REQUIRES the captured fully-green gate for the post-merge gate-audit (ADR 0024) — and names the captureUses drift guard in workflow-template.test.mjs as the arbiter. Deliberately NOT universally quantified over merge-task prompts: the baseline-proceed re-merge (proceed-over contract) and the class-exempt phase-close polish merge (fail-open discard, feeds no gate-audit seat) legitimately carry no clause, so a universal wording would be false at birth — the same rot class as the enumeration it replaces. No call site added or removed; captureUses stays green at exactly 3. Regression proof: three sibling dispatch-capture tests (never an extension of the T4 #297 threading test, whose header enumeration stays byte-untouched), each driving one recovery route through the harness that already stubs it and reading the captured prompt BY DISPATCH LABEL — asserting both the SUBMODULE TASK marker and the fixture's targetRepo. Per-route RED probe run and restored: removing one route's append REDs exactly that route's test (1 fail / 337 pass, each time). Sub-issue #1112. Plan: docs/plans/2026-07-24-recovery-re-merge-dispatch-coherence.md Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…t class-route record points both ways (#1113) ADR 0019: append `## Amendment (2026-07-24): the environment class-route is superseded by ADR 0040` after the existing References section. It supersedes exactly the environment-classified 0-fix-round env-blocked route — the class-routes-doctrine row in ## Decision and the **Scope.** paragraph's "routes as env-blocked" restatement, both under the single ## Decision heading (ADR 0019 carries no ## Scope heading, per red-team round-1 adjudication). States the live routing completely: one bounded environment-proceed re-run per gate site that must come back fully green (never a proceed-over, ADR 0040 SS C); exhaustion at the merge site HARD-escalates via 'escalate'; exhaustion at the land site falls back to held:land-failed (reason env-blocked) with the retry provably spent. States explicitly that the original Decision text is not retro-edited and that the introduced/baseline routes and the target-derived execution values stand unchanged. Original prose above the amendment is byte-intact. ADR 0040: add one "Supersedes one row of ADR 0019" bullet to ## Relationship to prior ADRs, appended after the existing five (0005, 0025, 0017, 0023, 0024), which are untouched. Same-scope survey: grep -in "env-blocked" over both ADR files adjudicated — every ADR-0019 hit sits either inside byte-intact original text now covered by the amendment, or inside the amendment itself; ADR 0040's own env-blocked mentions are pre-existing and accurate, no edit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…1113 absorb polish) [Minor] Amendment's "Live routing" omits ADR 0040 §(B)'s no-chaining bound — the one live case where 0019's superseded row still governs. Rationale: the amendment stated unconditionally that an environment-classified gate failure "now earns exactly one bounded environment-proceed re-run per gate site", but ADR 0040 §(B) is explicit that a baseline-proceed re-merge/re-land that then fails environment keeps today's routing (soft env-blocked / held:land-failed) and does NOT earn an environment-proceed — so ADR 0019's zero-fix-round env-blocked row survives as the chained-case fallback at both gate sites. A reader landing on 0019 was told a retry is always earned, which is false on that path (the same defect class the landed D21 guard in skill-doc-contracts.test.mjs #1039 polices). Fix: one additive clause appended to the Live routing paragraph naming the never-a-second / never-chained bound and the chained-case fallback. Single file, additive, no anchor change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ub-loop is EITHER-status, requiresTest:true is prompt-shape only
Phase-close coherence sweep, WAR phase 1 "Retry-dispatch scoping + record coherence".
Fixes the one queued finding:
[Nit] New fixture comment overclaims: the floor-retry sub-loop is entered on
EITHER floor status, and requiresTest:true is inert in this stub harness
(task 1.1, skills/war/assets/workflow-template.test.mjs:5019)
Both halves of the old rationale sentence were false against the live engine:
workflow-template.js declares `const FLOOR_STATUSES = ['no-test', 'unpackaged']`
and enters the sub-loop on either (`if (mr && FLOOR_STATUSES.includes(mr.status))`,
whose own comment above reads "on EITHER floor status (no-test OR unpackaged)");
and runNoTestLoop's first Refine call returns `{ mode:'merge-task', status:'no-test' }`
unconditionally, so requiresTest:true changes only the dispatched prompt's
requiresTest ternary here, not route reachability.
Comment-only. The fixture value stays — plan-mandated (docs/plans/2026-07-24-recovery-re-merge-dispatch-coherence.md,
Task 1.1 floor-retry sequencing) and correct; no assertion touched, no test moves
either way. Same comment-overclaim class as the recorded lesson
entry-validation-unconditional-phase-field-check-comment-overclaims-runtime-path.
Gate green at this commit: node --test 'skills/**/*.test.mjs' => 932/932 pass;
26 *.test.sh suites all pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…se-1 into dev/2026-07-24-recovery-re-merge-dispatch-coherence
…40 coherence (#1116) Bump all four release slots in lock-step: .claude-plugin/plugin.json version, .claude-plugin/marketplace.json metadata.version AND plugins[0].version, and the README.md ## Status paragraph (replace-in-place, no badge). Version resolution (End state 9): resolved from the four slots AS THEY STAND at this task's frozen base, never from a plan literal. All four read 0.14.59 at base (landed by this campaign's plan 2, `chore(release): 0.14.59 — standing-record coherence (#1108)`, which is in this branch's history), so the next free patch is 0.14.60. No ref in the repo carries 0.14.60. version-slots.test.mjs is the lock-step arbiter and is green. Release blurb describes the Phase-1 diff as landed, not as planned: - submodMergeNote appended as the final prompt segment at all three retry merge dispatches (merge:<taskId>:floor-retry:r<round>, :environment-proceed, :baseline-proceed); '' off the submodule path, so non-submodule prompts are byte-identical - three new sibling dispatch-capture tests asserting the captured prompt BY DISPATCH LABEL carries the SUBMODULE TASK: marker and the fixture targetRepo - gateCaptureClause (D5) header comment: site enumeration dropped, invariant stated count-free as an evidence-contract property, captureUses named as the arbiter of the site list (still exactly 3 sites) - ADR 0019 dated Amendment (2026-07-24) + ADR 0040 "Supersedes one row of ADR 0019" bullet — the record now points both ways at routing ADR 0040 already shipped The blurb makes NO claim that any recovery route, status enum, or escalation reason changed: land-decision.mjs, every MergeResult status, HARD_ESCALATION_REASONS / KNOWN_LAND_DECISIONS, every dispatch label, and every merge-path floor are untouched by this plan. Its explicit "No behavior change" sentence enumerates exactly those surfaces. Gate run locally and fully green before commit: node --test 'skills/**/*.test.mjs' 932/932 pass, 0 fail; every *.test.sh suite exits 0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…se-2 into dev/2026-07-24-recovery-re-merge-dispatch-coherence
Two type:project lessons from the Release phase of 2026-07-24-recovery-re-merge-dispatch-coherence (landed a84b42d, release 0.14.60): - release-blurb-overstates-guard-semantics — recurrence 6 in the release-blurb precision chain: a colon-scoped **No behavior change:** label is technically true but reads as a headline contradiction when the paragraph's own opening sentence describes a real shipped change. Adds the sharper sub-rule (prefer a scoped label over the fully-generic one). - header-comment-delegates-site-count-to-drift-guard-test-instead-of-enumerating — new pattern: point a shared helper's header comment at the counting drift guard rather than hand-enumerating consumer sites, which is what rotted. Redaction lint clean.
Base automatically changed from
dev/2026-07-24-runbook-and-standing-record-coherence
to
master
July 26, 2026 18:26
This was referenced Jul 27, 2026
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.
Plan 3 of the 2026-07-24-standing-record-and-guard-hardening campaign (stack-and-plow, ADR 0011).
Stacked on plan 2 — base is
dev/2026-07-24-runbook-and-standing-record-coherence(PR #1109), not master.What this closes
After plan 4 rebuilt merge-time gate-failure recovery, three coherence gaps remained — one per layer
of the record. All three are closed here.
SUBMODULE TASK:note —the paragraph rooting a submodule task's rebase and gate in its own checkout via
targetRepo/targetBase— rode only the initial merge-task prompt. AtaskType:'submodule'task whose first merge tripped a recoverable route was re-dispatched pointing at the
superproject. The note now rides all three recovery re-merges in
skills/war/assets/workflow-template.js—merge:<taskId>:floor-retry:r<round>,merge:<taskId>:environment-proceed,merge:<taskId>:baseline-proceed. It is the empty stringoff the submodule path, so every non-submodule prompt stays byte-identical.
gateCaptureClause's header comment had rotted to 2 of its 3 consumer sites. Theenumeration is replaced by a count-free evidence-contract statement naming the
captureUsesdrift guard in
workflow-template.test.mjsas the arbiter of the site list — the enumeration isexactly what rotted, so the fix is to stop enumerating.
env-blockedroute that ADR 0040 replaced, andneither record pointed at the other. Repaired in both directions without retro-editing:
0019 gains a dated
## Amendment (2026-07-24)(original Decision prose byte-intact); 0040's## Relationship to prior ADRsgains one Supersedes one row of ADR 0019 bullet.Proof is by dispatch capture, not source-occurrence counting: three new sibling tests drive a
taskType:'submodule'fixture through each recovery route and assert the prompt located bydispatch label carries both the
SUBMODULE TASK:marker and the fixture'stargetRepo.Phases
43a6dc4; 2/2 merged, unanimous approve, 0 fix rounds, 0 escalations; phase-close polish merged48f93e3a84b42d4; release 0.14.60, four slots in lock-stepEpics #1110 (phase 1) and #1111 (phase 2), both closed
status:done; issue-lifecycle floorassertrc 0 on both. Red-team: CLEARED-WITH-NOTES in one round (
docs/red-team/2026-07-24-recovery-re-merge-dispatch-coherence.md),3 minor roots auto-fixed pre-execution.
Unexecuted backstops
None. The plan declared one deferred validation and it was EXECUTED — PASS @
43a6dc4:Result:
submodMergeNote= 5;env-blocked(case-insensitive) = 6 in ADR 0019 / 5 in ADR 0040, everyhit adjudicated; token hunt = 10 in the js (down from 11 — exactly the removed enumeration sentence)
/ 67 in the test, every js hit adjudicated a keep.
End state 9 was reported SOFT cannot-confirm by the gate-audit (no gate-log artifact threaded to
the end-state pass; an auditor cannot execute the gate) and was closed by the Lead executing
version-slots.test.mjsat the landed tip — 3/3 green, four slots all0.14.60.Follow-ups filed
submodLandNotemissing on both re-landdispatches; polish-merge submodule-awareness undecided; and a pre-existing gap found in flight —
the floor-retry re-merge omits
assert-no-submodule-mutation.shthough two of its own commentspromise "ALL floor invocations (test + packaging + submodule)" (pre-existing since
3b07815c,2026-07-06; confirmed by
git blame, out of slice, reported not edited). This supersedes theplan's "file ONE war-followup" duty — it folds both spec-§9-deferred sites plus the new third.
Source issues
#1032, #1033, #1034 close at the campaign PR per the plan's
## Notesmap (#1032→1.1,#1033→1.2, #1034→1.1) — deliberately not closed here.
One note recorded, not held: the release blurb's colon-scoped
No behavior change:label readsas a headline contradiction against the paragraph's own opening sentence. Strictly read it is true
(every enumerated surface is verifiably untouched) and it is the anti-overclaim device the plan
mandated; the nit is cross-release readability.
be merged before them.
🤖 Generated with Claude Code