pi-gauntlet 8.0.2 → 8.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +7 -5
  3. package/agents/loop-implementer.md +33 -9
  4. package/bin/gauntlet-performance.mjs +10 -1
  5. package/bin/gauntlet-performance.test.mjs +85 -5
  6. package/bin/gauntlet-telemetry-seal.mjs +1 -1
  7. package/extensions/lib/plan-check.test.ts +4 -2
  8. package/extensions/lib/plan-check.ts +1 -1
  9. package/extensions/lib/telemetry-collect.test.ts +13 -6
  10. package/extensions/lib/telemetry-collect.ts +4 -3
  11. package/extensions/lib/telemetry-record.test.ts +14 -0
  12. package/extensions/lib/telemetry-record.ts +2 -2
  13. package/extensions/phase-tracker.test.ts +45 -0
  14. package/extensions/plan-tracker.test.ts +100 -1
  15. package/extensions/plan-tracker.ts +99 -3
  16. package/extensions/telemetry.test.ts +103 -0
  17. package/extensions/telemetry.ts +19 -6
  18. package/package.json +2 -2
  19. package/skills/brainstorming/reference/amendment-surface.md +1 -1
  20. package/skills/finishing-a-development-branch/SKILL.md +5 -5
  21. package/skills/finishing-a-development-branch/reference/legs.md +4 -4
  22. package/skills/finishing-a-development-branch/reference/verification-set.md +34 -0
  23. package/skills/gauntlet-handoff/SKILL.md +1 -1
  24. package/skills/gauntlet-resume/SKILL.md +4 -5
  25. package/skills/gauntlet-resume/reference/brief-contract.md +7 -7
  26. package/skills/gauntlet-resume/reference/reconstruction.md +28 -6
  27. package/skills/loop-implementation/SKILL.md +48 -32
  28. package/skills/loop-implementation/reference/coordinated-legs.md +8 -18
  29. package/skills/verification-before-completion/reference/conformance-check.md +9 -3
@@ -0,0 +1,34 @@
1
+ # Finish verification set
2
+
3
+ Read this reference at Step 1, before the skip proof and before stripping any plan. Retain the resolved set and accepted-complete task evidence through delivery.
4
+
5
+ ## Resolve the set
6
+
7
+ | Subject | Set |
8
+ |---|---|
9
+ | Ledger (line 1 exactly `# Ledger - loop engine`), including a recovered pre-strip ledger | Read [the loop skill's `## Gate set`](../../loop-implementation/SKILL.md#gate-set) at its absolute path with `read`. Use that set's membership, ordering, deduplication and `## Leg mapping` ownership. Apply its missing `checks:` stop, never a full-command fallback. |
10
+ | Rework PR subject with a task plan | Use the union of every plan task's `Tests:` commands plus the executable lint/format commands in the header's `**Verification:**` line; treat `none - PR subject, scoped` as no header commands, not an empty task union. Capture this set and accepted-complete task evidence before stripping the plan. Apply the hard gate and skip rule below to this set. |
11
+ | Every other subject with a task plan | Run the plan header's `**Verification:**` set in the worktree: `(cd "$WORKTREE" && <command>)`. |
12
+ | No artifact, including no recovered ledger | With no plan in this session, run the verification command(s) of the affected services from the gauntlet overrides file or `AGENTS.md` (look for "verification", "CI", or "test" sections). |
13
+
14
+ For a ledger, record the resolved set as an ordered list of (leg, command) pairs. Retain each leg's worktree and primary: execute in its worktree before squash and its primary after squash. Supply the gate set as `SCOPED_TEST_COMMANDS` to the minors child, with each command's owning checkout.
15
+
16
+ At finish's first gate-set execution site, mint `LOG_DIR=$(mktemp -d)` once for this session; reuse it for every finish rerun. Do not rely on a verify-session shell variable. Follow the loop skill's foreground, fail-fast execution and one-line exit reporting. For a human stop, quote at most `tail -n 20` from the failing log, alongside its exit line. Commit verification-produced tracked changes, or stop; record the verified HEAD and clean status only afterward. Retain Step 1's scoping caveat and failure stop.
17
+
18
+ For ledger commands outside a checkout's configured test-command matcher, verify-before-ship may warn; do not run the full suite to clear the warning. Keep CI responsible for the full run.
19
+
20
+ ## Skip proof
21
+
22
+ **Skip rule.** Skip the run only when this set passed on a known clean commit in the verify phase of this session and no edit or write landed outside `<telemetry.dir>` since. Check the current tree: `git -C "$WORKTREE" diff --quiet <commit the run passed on> -- . ':!<telemetry.dir>'` must exit 0, and `git -C "$WORKTREE" status --porcelain --untracked-files=all -- . ':!<telemetry.dir>'` must exit 0 with empty output (`<telemetry.dir>` defaults to `.pi/gauntlet/telemetry`). These checks cover committed, staged, unstaged, and untracked changes outside telemetry. Otherwise run it once; a missing verified commit, a failed check, or uncertainty means run.
23
+
24
+ Apply the proof independently in each owning checkout. Post-squash verification is mandatory; the skip proof does not cover a changed primary tree.
25
+
26
+ ## Post-strip recovery
27
+
28
+ For an authorized ledger restore, read [pending recovery](../../gauntlet-resume/reference/reconstruction.md#pending-recovery) at its absolute path with `read` and apply it before pre-strip-source recovery or verification; a missing parent record alone is not an absent pre-strip source.
29
+
30
+ For a fresh-session retry after a ledger was stripped, recover the committed pre-strip ledger that supplied Step 1's rows and `## Leg mapping`: `git -C <home> show <strip commit>^:<ledger path>`. Locate the removal in that ledger path's history; use the home primary when the home worktree is absent. Reconstruct the gate pairs from that ledger, never from the spec's `contract:` `- verification:` lines. Keep the recovered artifact read-only and apply the same `checks:` admission. On a missing or ambiguous source, stop naming the ledger path; do not take the no-plan fallback. Preserve coordinated receipt validation and delivery exemptions from [coordinated finish](legs.md).
31
+
32
+ ## Post-squash execution
33
+
34
+ For Option 3, run each delivered leg's retained pairs in order as `(cd "<leg primary>" && <command>) > "$LOG_DIR/gate-<i>.log" 2>&1`, one command per pair, retaining its gate index and fail-fast exit reporting. For coordinated delivery, run only the just-squashed leg's pairs at that leg's delivery step; every remaining leg gets its own post-squash run when delivered. A failed-squash receipt retry runs those same pairs against the delivered primary, not the feature worktree, and never repeats the squash. Retain the Step 1 command set and execution form for non-ledger subjects.
@@ -80,7 +80,7 @@ Apply the first-line grammar in [menu-layout](../brainstorming/reference/menu-la
80
80
  append nothing; report a plain hotfix handoff and go to step 7. Checked before the
81
81
  trackers: chase-bug never touches tracker state, and a stale armed flow appended here
82
82
  would steer resume away from its hotfix route.
83
- 6. **Append.** `phase_tracker({ action: "status" })`, then `plan_tracker({ action: "status" })`.
83
+ 6. **Append.** `phase_tracker({ action: "status" })`, then `plan_tracker({ action: "status" })`. Never refresh or mutate either tracker; copy its observed task rows, including ledger and conformance tasks, through the shared contract.
84
84
  - No phase `in_progress` -> append nothing; say the brief is a plain handoff.
85
85
  - A phase `in_progress` (verify or ship included - resume stops at verify on its own)
86
86
  -> append the process-state section exactly as `## Producers` in
@@ -24,8 +24,7 @@ before any tracker mutation; every stop names the offending path, field, or line
24
24
  - Reads: anything.
25
25
  - Writes: `phase_tracker` / `plan_tracker` state after every check passes and every
26
26
  human question is answered; the plan file, only through `reference/brief-contract.md`
27
- `## Plan repair`; on the seed route, what `/skill:using-git-worktrees`
28
- writes. Never a spec copy, rename, or marker commit.
27
+ `## Plan repair`; the ledger through `reference/reconstruction.md` pending recovery and the loop driver's admission/repair contract; on the seed route, what `/skill:using-git-worktrees` writes. Never a spec copy, rename, or marker commit.
29
28
  - Never: `git worktree add` directly; worktree creation by resume itself only on
30
29
  the seed route, only through `/skill:using-git-worktrees`; infer approval from
31
30
  artifact presence; restore
@@ -146,11 +145,11 @@ owning skill **without** its reset-bearing entry:
146
145
  | Active after restore | Continue in | Entry point |
147
146
  |---|---|---|
148
147
  | brainstorm | [brainstorming checklist](../brainstorming/SKILL.md#checklist) | on-disk state decides the step: draft marker on line 1 of the spec file -> step 4; spec title -> step 8. Never `/skill:brainstorming` entry (it resets both trackers) |
149
- | approved spec with `**Engine:** loop`, no ledger | loop-implementation | after check 6, arm with `start brainstorm`, then `skip brainstorm resume: <spec path>` before driver admission; carry absolute worktree/spec paths and plan directory through Entry steps 1-5 per `reference/reconstruction.md` "Spec without plan": label Entry steps 1-5 explicitly in the response as Entry step 1: resolved settings; Entry step 2: verification; Entry step 3: driver's plan skip; Entry step 4: clean named-branch check and ledger creation; Entry step 5: `plan_check`, commit and implement start; no writing-plans body or task tracker |
148
+ | approved spec with `**Engine:** loop`, no ledger | loop-implementation | after check 6, arm with `start brainstorm`, then `skip brainstorm resume: <spec path>` before driver admission; carry absolute worktree/spec paths and plan directory through Entry steps 1-5 per `reference/reconstruction.md` "Spec without plan": label Entry steps 1-5 explicitly in the response as Entry step 1: resolved settings; Entry step 2: verification; Entry step 3: driver's plan skip; Entry step 4: clean named-branch check and ledger creation; Entry step 5: `plan_check`, commit and implement start; no writing-plans body or task tracker initialization; refresh by ledger path after implement starts |
150
149
  | plan with task engine | writing-plans body | skip its `start plan` call (already in_progress) |
151
- | implement with line-1 ledger | loop-implementation | complete `reference/reconstruction.md` "Spec with ledger" ordered restore, cited by `reference/brief-contract.md`'s call table: entry checks 1-6, brainstorm start/skip, plan start/check/skip with reason `resume: <spec> (loop engine)`, implement start, no task tracker; state the entire ordered sequence explicitly even when entry checks are already reported as passed; then continue at step 5 (`Before each dispatch`), applying the shared cap boundary in reconstruction step 4 before continuation and preserving ledger cap, iterations/retry data; dirty tree stops before dispatch; reuse the existing ledger |
150
+ | implement with line-1 ledger | loop-implementation | complete `reference/reconstruction.md` "Spec with ledger" ordered restore, cited by `reference/brief-contract.md`'s call table: entry checks 1-6, brainstorm start/skip, plan start/check/skip with reason `resume: <spec> (loop engine)`, implement start, pending recovery, then one ledger-path refresh, no `init`; state the entire ordered sequence explicitly even when entry checks are already reported as passed; then continue at step 5 (`Before each dispatch`), applying the shared cap boundary in reconstruction step 4 before continuation and preserving ledger cap, iterations/retry data; recover home or companion returns before refresh and any unresolved dirty-tree stop; reuse the existing ledger |
152
151
  | implement with task plan | subagent-driven-development | re-validate `<task>` first (re-run its `Tests:`), then the task loop from the first non-complete task |
153
- | verify with `Ledger:` (including ship-stage ledger briefs restored at verify) | /skill:loop-implementation | apply the shared cap boundary in `reference/reconstruction.md` "Spec with ledger" step 4 before verification; render cap and restored ledger state; read `After the loop` and its references; continue from step 1, full ledger verification, after the already-restored `start verify`; retain whole-diff code review, happy path when triggered, fresh conformance review and finishing; no task-tracker calls |
152
+ | verify with `Ledger:` (including ship-stage ledger briefs restored at verify) | /skill:loop-implementation | after `start verify`, restore the saved mixed task list with `init` as `reference/brief-contract.md` specifies, then pending recovery and one ledger-path refresh through the shared cap boundary in `reference/reconstruction.md` "Spec with ledger" step 4; legacy briefs without tasks go directly to refresh; render cap and observed task/ledger state; read `After the loop` and its references; continue from `After the loop` step 1, the gate set per the loop skill's `## Gate set`; let that skill own execution, with no resume-owned gate run; retain whole-diff code review, happy path when triggered, fresh home conformance review and finishing; never start implement or synthesize Gn completion |
154
153
  | verify without `Ledger:` | verification-before-completion | full conformance gate; nothing carried over |
155
154
 
156
155
  ## Red flags — STOP
@@ -36,7 +36,7 @@ Ledger: <path>
36
36
  Last decision: <line>
37
37
  ```
38
38
 
39
- Use the ledger path relative to the worktree and the last physical decision line, or `none` for an empty Decisions section. Read the ledger on disk; the brief is a pointer, not a second state carrier. Reject a block mixing these fields with `Active task`, missing either loop field, or carrying task rows with a ledger. Never initialize a task tracker for a ledger.
39
+ Use the ledger path relative to the worktree and the last physical decision line, or `none` for an empty Decisions section. Read the ledger on disk; the brief is a pointer, not a second ledger state carrier. Permit task rows beside a ledger: copy `plan_tracker status` verbatim, including the dispatched row's `in_progress` status and any conformance tasks with their observed statuses. Never infer task state from the brief's prose. Reject a block mixing these fields with `Active task` or missing either loop field.
40
40
 
41
41
  Consumer rules: process state absent -> plain handoff (the consumer starts its
42
42
  own process from `## Intent`). Give valid ledger fields precedence over `No plan active.` and run ledger admission. Restore phase-only state for `No plan active.` only with no `Ledger` field. Load named skills as the consumer.
@@ -106,11 +106,11 @@ Keep fields in this order. Use the portable repo identifier from `../../brainsto
106
106
 
107
107
  Run resume entry check 3 against the run home unchanged. Resolve the home spec through Candidates, retaining human approval/confirmation requirements; artifact presence supplies no approval. Before any tracker write, compare ordered brief membership with the home spec's `### Leg:` blocks exactly; name the missing, extra or reordered leg and both lists on mismatch. Use `../../brainstorming/reference/legs.md` for membership, companion-file and scope grammar; keep no duplicate grammar here.
108
108
 
109
- For each companion, parse the home overrides' selected sibling clone URL with shape-ticket's shared parser and use `<home PRIMARY parent>/<NAME>` as its declared primary. Canonicalize that primary's git common directory. Resolve an absent location from the leg's recorded `home:` contract and shared NAME (shared branch with `/` replaced by `-`), not a newly inferred wrapper. Require the companion worktree's canonical git common directory to equal the declared primary's, its live branch to equal the shared branch, and its leg file's full `**Home:**` tuple to equal the run home's repo, shared branch and repo-relative spec path. Stop naming the offending leg and expected/observed path, branch or full tuple. A live tree's branch or tuple mismatch is not informational drift.
109
+ For each companion, parse the home overrides' selected sibling clone URL with shape-ticket's shared parser and use `<home PRIMARY parent>/<NAME>` as its declared primary. Canonicalize that primary's git common directory. Resolve an absent location from the leg's recorded `home:` contract and shared NAME (shared branch with `/` replaced by `-`), not a newly inferred wrapper. Render that derivation in the stop: name the recorded `home:` pattern and the shared NAME it was resolved from, and state that the pattern locates the tree without authorizing its recreation, a synthesized receipt or inferred approval. Require the companion worktree's canonical git common directory to equal the declared primary's, its live branch to equal the shared branch, and its leg file's full `**Home:**` tuple to equal the run home's repo, shared branch and repo-relative spec path. Stop naming the offending leg and expected/observed path, branch or full tuple. A live tree's branch or tuple mismatch is not informational drift.
110
110
 
111
111
  Admit a missing companion tree only after live receipt validation under `../../finishing-a-development-branch/reference/legs.md`. A copied receipt alone proves nothing. Announce per-leg HEAD and dirty drift against live trees without stopping; identify each leg. Keep approval, standing-grant validation, arming order and task snapshots unchanged. Dispatch task `Leg:` work in that leg's checkout, not the home by default.
112
112
 
113
- For a ship-stage retry with a correctly stripped plan, require every companion receipt to validate live before admitting the missing plan. Restore through the legal brainstorm start/skip, plan start/skip and implement skip sequence to verify, without inventing a plan_check stamp or conformance evidence. Re-validate unlanded home using recorded contracts and original scoped ACs, then run fresh home conformance and finish; use the finishing reference's retry route. Preserve receipts on seal or home delivery failure; do not repair or replace a correctly stripped plan. An absent plan without this fully validated ship retry remains a stop.
113
+ For a ship-stage retry with a correctly stripped plan, require every companion receipt to validate live before admitting the missing plan. Restore through the legal brainstorm start/skip, plan start/skip and implement skip sequence to verify, without inventing a plan_check stamp or conformance evidence. Re-validate unlanded home using recorded contracts and original scoped ACs; for a ledger subject, recover gate pairs from the committed pre-strip ledger per [finish verification-set.md](../../finishing-a-development-branch/reference/verification-set.md#post-strip-recovery), not the spec's full verification contract. Then run fresh home conformance and finish; use the finishing reference's retry route. Preserve receipts on seal or home delivery failure; do not repair or replace a correctly stripped plan. An absent plan without this fully validated ship retry remains a stop.
114
114
 
115
115
  ## Tracker output grammar
116
116
 
@@ -192,14 +192,14 @@ Honor SKILL.md entry check 6's deferred stop before any process-state arming cal
192
192
  |---|---|
193
193
  | brainstorm | `start brainstorm`; `substep` if the brief shows one |
194
194
  | plan | `start brainstorm`; `skip brainstorm S`; `start plan`; `substep` if shown |
195
- | implement with ledger | Read ledger line 1; resolve its path-only `**Spec:**` header; run entry checks 1-6, naming check 6 (Grant field); `start brainstorm`; `skip brainstorm` reason `resume: <spec path>`; `start plan`; `plan_check` on the absolute ledger path; on PASS `skip plan` reason `resume: <spec> (loop engine)` using the resolved absolute spec path as `<spec>`; `start implement`; no `plan_tracker init`; apply the shared cap boundary in `reconstruction.md` "Spec with ledger" step 4 before continuation; render cap, rows and decisions; continue at loop step 5. Follow `reconstruction.md` "Spec with ledger" for this self-contained ordered restore. On FAIL stop with findings, never `## Plan repair` or writing-plans. |
195
+ | implement with ledger | Read ledger line 1; resolve its path-only `**Spec:**` header; run entry checks 1-6, naming check 6 (Grant field); `start brainstorm`; `skip brainstorm` reason `resume: <spec path>`; `start plan`; `plan_check` on the absolute ledger path; on PASS `skip plan` reason `resume: <spec> (loop engine)` using the resolved absolute spec path as `<spec>`; `start implement`; pending recovery, then one ledger-path refresh, no `init`; apply the shared cap boundary in `reconstruction.md` "Spec with ledger" step 4 before continuation; render cap, rows and decisions; continue at loop step 5. Follow `reconstruction.md` "Spec with ledger" for this self-contained ordered restore. On FAIL stop with findings, never `## Plan repair` or writing-plans. |
196
196
  | implement with task plan | `start brainstorm`; `skip brainstorm S`; `start plan`; `plan_check({ planPath })`; on FAIL run `## Plan repair`; on PASS `skip plan R`; `start implement`; `substep` if shown; `plan_tracker init` |
197
197
  | verify | `start brainstorm`; `skip brainstorm S`; `start plan`; `plan_check({ planPath })`; on FAIL run `## Plan repair`; on PASS `skip plan R`, then `skip implement R`; `start verify`; `substep` if shown; `plan_tracker init`. Never call `start implement`. |
198
198
  | ship | With a correctly stripped coordinated plan, apply "Coordinated admission"'s fully receipt-validated retry route instead of plan repair; otherwise as verify. Restoration stops at verify in_progress: `complete verify` needs a fresh conformance dispatch and `skip verify` would bypass a real gate. Announce that the closure review re-runs before ship |
199
199
 
200
- For a coordinated ledger, apply reconstruction's pending companion return boundary before dispatch or verification, including verify/ship restores; record a validated interrupted return before continuing.
200
+ Apply reconstruction's pending recovery before dispatch or verification on every ledger restore, including verify/ship. Use the home return contract for a home tuple and the companion protocol only for an actual multi-member companion; record a validated interrupted return before continuing.
201
201
 
202
- For a ledger brief, pair by the ledger's path-only `**Spec:**` header, not basename; require the resolved spec under `flowGuards.specDirs` and the ledger under its sibling plans directory. Keep same-repository binding and human confirmation. For every ledger brief apply the shared cap boundary in `reconstruction.md` "Spec with ledger" step 4 before dispatch or verification, retaining its legacy stop and original-phase grant continuation. For verify/ship ledger briefs, use the ledger restore sequence through `skip plan`, then `skip implement R`; `start verify`, with no task tracker. Continue verify/ship ledger briefs in `/skill:loop-implementation` `After the loop` from step 1 (full ledger verification), after the already-restored `start verify`, retaining whole-diff code review, happy path when triggered, fresh conformance review and finishing without task-tracker calls. Ship still stops at verify for fresh conformance.
202
+ For a ledger brief, pair by the ledger's path-only `**Spec:**` header, not basename; require the resolved spec under `flowGuards.specDirs` and the ledger under its sibling plans directory. Keep same-repository binding and human confirmation. For every ledger brief apply the shared cap boundary in `reconstruction.md` "Spec with ledger" step 4 before dispatch or verification, retaining its legacy stop and original-phase grant continuation. For verify/ship ledger briefs, use the ledger restore sequence through `skip plan`, then `skip implement R`; `start verify`; restore the full saved task list with `plan_tracker init` (names, order and mixed statuses unchanged), then apply pending recovery and one ledger-path refresh through reconstruction step 4. A legacy ledger brief without task rows goes directly to refresh after phase restoration and pending recovery. Never call `start implement` on this route or invent completed Gn tasks; refresh replaces only ledger entries and preserves every non-ledger name/status. Never send a ledger task list through task-plan repair, even on a failed ledger check. Continue verify/ship ledger briefs in `/skill:loop-implementation` `After the loop` step 1 (the gate set per the loop skill's `## Gate set`), after the already-restored `start verify`; let that skill own execution, with no resume-owned gate run, retaining whole-diff code review, happy path when triggered, fresh conformance review and finishing. Ship still stops at verify for fresh conformance.
203
203
 
204
204
  `planPath` (task-plan implement onward): the brief carries none. Resolve as reconstruction does
205
205
  (`reconstruction.md`, "Candidates", including its `flowGuards.specDirs` resolution): the
@@ -267,7 +267,7 @@ Resume never edits the spec or writes an Open Question itself; the dispatched pl
267
267
  "Exact" restoration binds: the active phase identity and substep, and the plan task list
268
268
  (names, order, statuses) verbatim. Prior phases show `⊘ (resume: ...)` regardless of the
269
269
  brief's glyph - skip-arming is the mechanism and completing priors would fabricate gated
270
- history. `No plan active.` -> no `init` call.
270
+ history. For a ledger, restore the saved mixed list only on verify/ship, then refresh its ledger entries from disk; on implement, refresh without `init`. `No plan active.` -> no `init` call; a ledger still refreshes.
271
271
 
272
272
  Before `init`, validate feasibility against the tracker's own rules:
273
273
 
@@ -75,7 +75,7 @@ with this unapproved spec as the draft? Show the spec path (and the brief's
75
75
  `## Intent`/`## Decisions` when present).
76
76
 
77
77
  - Approved: honor SKILL.md entry check 6's deferred stop before any arming; run SKILL.md entry check 6 on `<spec path>` first (a malformed `**Amend-grant:**` line stops here, no tracker call). Read the spec's `**Engine:**` line and take the matching route:
78
- - `loop`: call `start brainstorm`, then `skip brainstorm` with reason `resume: <spec path>` to arm the flow before `plan_check`. Carry absolute worktree/spec paths and the resolved plan directory into `/skill:loop-implementation` Entry steps 1-5: resolve settings at step 1 and verification at step 2, retain the driver's `skip plan` at step 3, create the ledger at step 4, then check/commit it and start implement at step 5. Never enter the writing-plans body or initialize a task tracker.
78
+ - `loop`: call `start brainstorm`, then `skip brainstorm` with reason `resume: <spec path>` to arm the flow before `plan_check`. Carry absolute worktree/spec paths and the resolved plan directory into `/skill:loop-implementation` Entry steps 1-5: resolve settings at step 1 and verification at step 2, retain the driver's `skip plan` at step 3, create the ledger at step 4, then check/commit it, start implement and refresh by ledger path at step 5. Never enter the writing-plans body or initialize a derived task list.
79
79
  - `waves` or absent: `start brainstorm`; `skip brainstorm resume: <spec path>`; `start plan`; continue in writing-plans, skipping its `start plan` call.
80
80
  - Selected unapproved-draft brainstorming handoff: invoke [`/skill:brainstorming`](../../brainstorming/SKILL.md) with
81
81
  the spec as the draft; arm nothing. using-git-worktrees Step 0 detects the existing
@@ -90,13 +90,35 @@ Show the spec and ledger paths, current rows, iterations, last decision, and `gi
90
90
 
91
91
  After confirmation:
92
92
 
93
- 1. Read ledger line 1: require `# Ledger - loop engine`. Resolve its path-only `**Spec:**` header to an absolute spec path under the worktree's configured spec directories, not by basename. Run SKILL.md entry checks 1-6 in order, including check 6, **Grant field**, on that spec, before any tracker mutation.
93
+ 1. Read ledger line 1: require `# Ledger - loop engine`. Resolve its path-only `**Spec:**` header to an absolute spec path under the worktree's configured spec directories, not by basename. Run SKILL.md entry checks 1-6 in order, including check 6, **Grant field**, on that spec, before any tracker mutation. Run Pending recovery's read-only admission-evidence check below.
94
94
  2. Call `phase_tracker({ action: "start", phase: "brainstorm" })`, then `phase_tracker({ action: "skip", phase: "brainstorm", reason: "resume: <spec path>" })`, then `phase_tracker({ action: "start", phase: "plan" })`.
95
- 3. Call `plan_check({ planPath: <absolute ledger path> })`. On FAIL, stop with findings, retaining plan in_progress. Start the message with `gauntlet: stuck` followed by the findings reason on that line; never enter `## Plan repair` or writing-plans. On PASS, call `phase_tracker({ action: "skip", phase: "plan", reason: "resume: <spec> (loop engine)" })`, then `phase_tracker({ action: "start", phase: "implement" })`. Use the resolved absolute spec path as `<spec>` in the reason. Never call `plan_tracker init`.
96
- 4. **Shared cap boundary (every ledger restore, before phase continuation).** Read `/skill:loop-implementation`. Skip Entry step 1 entirely; settings resolution and its unavailable-tool stop apply only to fresh seeding. Restore base, verification, iterations, `cap:`, row attempts, funding and retry allowances from the ledger/spec and branch without overwriting it. Render `cap: <n>`, rows, iterations, attempts, funding, retry allowances and all decisions; distinguish the latest operational `row <n> ...` decision from the last physical history line. A dirty tree takes the driver's discard-authorization stop without offering a cap grant. On a clean ledger missing `cap:`, stop with `ledger has no cap: line - seeded under the old loopEngine contract`, even when every row is closed. Use the driver's legacy `cap +N` grant (durable iterations + N), never settings. After the grant continue the original phase: implement at `Before each dispatch`; verify/ship at `After the loop` step 1, never reseed.
97
- Before continuation on a coordinated ledger, recover the pending companion return boundary. Read the durable `pending:` tuple (target row or seed, repo, pre-dispatch HEAD) and compare that companion's live head. Accept only exactly one new companion commit matching the tuple and carrying its consumed iteration and bounded result evidence. Validate the result, record its SHA and only that leg's target result or seeded state in the home ledger, and remove `pending:` in the home-ledger commit before dispatch. Preserve consumed iterations, attempts and cap; never rerun the recovered row. Unrelated head movement, multiple commits, or missing result evidence stops naming the leg and tuple. With no new commit, use the loop driver's interrupted-dispatch boundary, not a silent redispatch. Apply this boundary before dispatch or verification for every ledger restore.
95
+ 3. Call `plan_check({ planPath: <absolute ledger path> })`. On FAIL, stop with findings, retaining plan in_progress. Start the message with `gauntlet: stuck` followed by the findings reason on that line; never enter `## Plan repair` or writing-plans. On PASS, call `phase_tracker({ action: "skip", phase: "plan", reason: "resume: <spec> (loop engine)" })`, then `phase_tracker({ action: "start", phase: "implement" })`. Use the resolved absolute spec path as `<spec>` in the reason. Restore implement through refresh, not `init`.
96
+ 4. **Shared cap boundary (every ledger restore, before phase continuation).** Read `/skill:loop-implementation`. Skip Entry step 1 entirely; settings resolution and its unavailable-tool stop apply only to fresh seeding. Restore base, verification, iterations, `cap:`, row attempts, funding and retry allowances from the ledger/spec and branch without overwriting it. Apply pending recovery below before the refresh, including home returns whose child commit removed the tuple. On unrecoverable attribution or before-image, stop before refresh; otherwise retain any recovery stop for reporting after projection. Call `plan_tracker({ action: "refresh", path: <absolute ledger path> })` exactly once after phase restoration and recovery, before any unresolved dirty-tree stop or dispatch. On verify/ship, restore the saved mixed task list first as `brief-contract.md` specifies; on implement, use no `init`. On refresh failure, stop with its findings and leave the existing task list untouched. Read `plan_tracker status` and report its exact observed state, never an inferred list.
97
+ Render `cap: <n>`, rows, iterations, attempts, funding, retry allowances and all decisions; distinguish the latest operational `row <n> ...` decision from the last physical history line. Report a retained recovery stop now, with no redispatch. Any remaining dirty tree takes the driver's discard-authorization stop without offering a cap grant. On a clean ledger missing `cap:`, stop with `ledger has no cap: line - seeded under the old loopEngine contract`, even when every row is closed; projection does not require cap. Use the driver's legacy `cap +N` grant (durable iterations + N), never settings. After the grant continue the original phase: implement at `Before each dispatch`; verify/ship at `After the loop` step 1, never reseed.
98
+ 5. Continue at loop step 5, the delivered driver's `Before each dispatch`, with durable iterations and retry data; an all-closed ledger completes implement through refresh and takes `After the loop` step 0. Keep an allowance-stopped row `failed` and a cap stop without an active row; render a row whose `pending:` tuple is restored or retained as `row <n> in_progress (pending tuple restored)`. Never reset counters or reseed a validated seed.
98
99
 
99
- 5. Continue at loop step 5, the delivered driver's `Before each dispatch`, with durable iterations and retry data. Never reset counters or reseed a validated seed.
100
+ ### Pending recovery
101
+
102
+ Recover before dispatch or verification on every ledger restore. Run the read-only admission-evidence check below before phase/task restoration on every ledger route, including briefs; resolve its human question before any tracker call. Apply recovery writes only at the ordered pending-recovery step. Read the durable `pending:` tuple (target row or seed, repo, pre-dispatch HEAD); the parent's uncommitted iterations bump plus tuple is expected dispatch dirt, not a reason to skip recovery.
103
+
104
+ With no `pending:` on disk, inspect home commit history before any refresh. Find the latest home child row/seed commit that changed this ledger, even when unrelated commits follow it; read its subject and body with `git -C <worktree> log --format=%H -- <ledger path>` and `git -C <worktree> show -s --format=%B <sha>`. Exclude returns superseded by a parent admission/repair or approved ledger mutation proven by the evidence below; never replay those over the parent's current ledger.
105
+
106
+ Treat ordinary home admission as a refresh with no parent commit or ledger mutation. Prove a later parent repair or approved mutation from its actual ledger diff, not its subject alone. Use a saved post-admission snapshot only with its observed HEAD and clean `dirty` state: the brief's core fields plus task rows, or existing parent admission/refresh output bound to that checked HEAD. Require the child to be an ancestor of the saved HEAD, that HEAD to be an ancestor of live HEAD, and the ledger to be unchanged from the saved HEAD through live HEAD and the working tree. Match the snapshot's ledger task names/statuses to that HEAD's tuple-free ledger. Treat a matching snapshot as settled evidence and retain the current ledger without replaying the old dispatch. Terminal rows, a verify phase label or the child's attribution alone prove no admission.
107
+
108
+ For an unsuperseded home return, recover the commit body's first two lines as the exact `pending:` tuple and consumed `iteration:`. Require the tuple's home identity and target to match the spec and subject, its pre-dispatch SHA to be an ancestor of live HEAD, and its consumed count to equal the committed ledger's iterations and pre-dispatch ledger's iterations +1. Read the before-image at that SHA, not at `HEAD^`. On missing, malformed or mismatched attribution, or unavailable pre-dispatch bytes, stop before refresh, dispatch or verification; name the commit and failed check rather than inferring admission from terminal rows. With no home child return to recover, retain the existing ledger restore path.
109
+
110
+ Revalidate a clean, exactly-one-commit return through the home row below. For later commits or dirty changes, require settled evidence above or a parent return record/human confirmation that admission was still pending when those changes occurred. Without either, history alone cannot distinguish interruption from admitted work followed by verification changes. Start the message with `gauntlet: question` on its own line and ask: `Was home return <sha> admitted before the later commits or dirty changes, or did the session stop before admission?` Name the candidate and live HEAD. Keep ledger bytes, counters and task list unchanged while awaiting the answer: no refresh and no target/tuple restoration.
111
+
112
+ | Confirmed admission state | Action |
113
+ |---|---|
114
+ | Confirmed settled | Preserve the current ledger and continue normal restore; require fresh verification/conformance, not historical gate credit. |
115
+ | Confirmed interrupted | Validate the entire `<pre-dispatch HEAD>..HEAD` range, never just `HEAD^..HEAD`, through the home row below. Render the interrupted/ambiguous-history answer in one sentence: validate the full `<HEAD_BEFORE>..HEAD` range (using the recovered pre-dispatch SHA, including later commits), restore row <n> to its pre-dispatch open/attempts 0 cells with the tuple before refresh on boundary rejection, state that iterations stay at the recovered count and child commits/changes are kept; use the saved cells for any other pre-dispatch status/attempts, or all dispatched non-cut rows for seed. Use the recovered tuple/count without another bump or a new commit. |
116
+ | Still unknown | Stop without mutation; ask for the missing admission evidence, never turn uncertainty into a discard/reset decision. |
117
+
118
+ | Tuple target | Recovery |
119
+ |---|---|
120
+ | Home leg or single-member `home` | Reconstruct the pre-dispatch ledger from `HEAD:<ledger path>` when HEAD is the tuple SHA, otherwise from `<pre-dispatch HEAD>:<ledger path>`. Compare live HEAD with that SHA. Admit exactly one new home commit with subject `loop: row <n> <status>` or `loop: seed evidence` only through the driver's `## Validate the return`: require a clean tree and the bounded row/decision result, allowing only the consumed iteration and pending removal header deltas. Clear the tuple through the admitted close or ordinary-miss repair. With zero new commits, keep the tuple and consumed iteration and take the interrupted-dispatch stop. Unrelated movement or multiple commits stop without redispatch or double counting. For a rejected terminal child result, restore the target row and the tuple in the working-tree ledger from the pre-dispatch copy before refresh (all dispatched non-cut rows for seed); preserve other child changes, child commits and consumed iterations for the human's discard/reset decision. |
121
+ | Actual multi-member companion | Apply `/skill:loop-implementation` `reference/coordinated-legs.md` `## Resume`: require unchanged home HEAD and exactly one new companion commit with tuple attribution and bounded result evidence. Validate and record only that leg's target result or seeded state and SHA, removing the tuple in the home-ledger commit; never rerun the recovered row. Zero, unrelated or multiple commits and missing evidence take that protocol's stop, preserving attempts, consumed iterations and cap. |
100
122
 
101
123
  ## Spec with plan
102
124
 
@@ -5,7 +5,7 @@ description: Use after approval selects the loop engine, or when resuming an acc
5
5
 
6
6
  # Loop implementation
7
7
 
8
- Run this driver in the main session. Carry the absolute implementation worktree path as a value; run git with `git -C "<worktree>"` and commands as `(cd "<worktree>" && <command>)`. Use the approved spec and resolved plan directory. Read the spec in full. Keep the original prompt for verify. Never initialize a task tracker or run reviewers inside implement.
8
+ Run this driver in the main session. Carry the absolute implementation worktree path as a value; run git with `git -C "<worktree>"` and commands as `(cd "<worktree>" && <command>)`. Carry the approved spec path and resolved plan directory. Keep the original prompt for verify. Never run reviewers inside implement. Use `plan_tracker({ action: "refresh", path: <absolute ledger path> })` for every refresh; pass only the path and let the extension derive the view. After every admitted `loop:` commit (child or parent), refresh once; the seed refresh follows implement start below.
9
9
 
10
10
  ## Entry
11
11
 
@@ -18,7 +18,9 @@ Run this driver in the main session. Carry the absolute implementation worktree
18
18
  | Otherwise overrides has `## verification-before-completion` | Use its exactly one backticked command; zero or several is a configuration error. |
19
19
  | Neither section supplies a command | Discover the project's test entrypoint from its actual manifest/build instructions; print discovery as source. Stop on an unresolved or ambiguous entrypoint. |
20
20
 
21
- On fresh entry and on every ledger restore, for a spec whose `## Legs` section has more than one `### Leg:` block, read `reference/coordinated-legs.md` IN FULL now with read; stop on an unreadable reference naming its path, never reconstruct it. On fresh entry apply its `## Entry` section instead of the home-only skeleton and cap calculation below. On a restore apply its `## Resume` section before the dirty-tree stop and before any pending recovery. Keep legacy and single-member ledger bytes unchanged, with no coordinated metadata.
21
+ At seed and at an authorized restore, before entering the dispatch loop, read the spec in full. Decode `**Amend-grant:**` through [amendment-surface Value decoding](../brainstorming/reference/amendment-surface.md). Capture the decoded grant, ordered leg membership, each leg's absolute checkout paths and combined spec/task Rules for dispatch and handoff; use home for zero or one leg.
22
+
23
+ At seed and at an authorized restore, when the held membership has more than one leg, read `reference/coordinated-legs.md` IN FULL now with read at its absolute path; stop on an unreadable reference naming its path, never reconstruct it. On fresh entry apply its `## Entry` section instead of the home-only skeleton and cap calculation below. On a restore apply its `## Resume` section before the dirty-tree stop and before any pending recovery. Keep legacy and single-member ledger bytes unchanged, with no coordinated metadata.
22
24
 
23
25
  3. Call `phase_tracker({ action: "skip", phase: "plan", reason: "loop engine" })`.
24
26
  4. Require a clean named-branch implementation worktree. Write `<resolved plan dir>/<spec stem>-ledger.md`. Use this grammar with literal values, not placeholders:
@@ -28,6 +30,7 @@ On fresh entry and on every ledger restore, for a spec whose `## Legs` section h
28
30
  **Spec:** `doc/specs/example.md`
29
31
  base: <HEAD SHA before skeleton>
30
32
  verification: <resolved command>
33
+ checks: commands
31
34
  iterations: 0
32
35
  cap: <n>
33
36
 
@@ -39,29 +42,35 @@ cap: <n>
39
42
  ```
40
43
 
41
44
  Use the actual repo-relative spec path alone in the Spec header. Read base with `git -C "<worktree>" rev-parse HEAD`. Index every spec AC in order, including nested disposition lines without treating them as extra ACs; keep row text only in the spec. Initialize explicit/absent `in-scope` and `venue:` rows `open`, attempts 0, evidence empty. Initialize only `deviates:`, `deferred:`, `elsewhere:` rows `cut`, attempts 0, disposition text as evidence. Compute cap once as (rows not initialized cut) * maxIterationsPerRow + 1, including the seed dispatch. Write `cap:` immediately after `iterations: 0`: 24 non-cut rows at default 4 yield 97; all-cut yields 1 and exits through rule 1 without a seed dispatch. Later cuts, reopens and requirement-preserving amendments leave cap unchanged; redraw deletes the ledger and reseeds it. Serialize evidence in one physical table cell, result lines separated by semicolons, pipes escaped, plain text without angle markup.
42
- 5. Call `plan_check({ planPath: <ledger path> })`. Stop with findings as a configuration error. Commit the stamped skeleton as `loop: seed ledger`; call `phase_tracker({ action: "start", phase: "implement" })`.
45
+ 5. Call `plan_check({ planPath: <ledger path> })`. Stop with findings as a configuration error. Commit the stamped skeleton as `loop: seed ledger`; call `phase_tracker({ action: "start", phase: "implement" })`, then `plan_tracker({ action: "refresh", path: <absolute ledger path> })`, including all-cut ledgers with no seed dispatch.
46
+
47
+ For resume, use the admitted ledger, its base and verification command, and durable iterations and cap instead of overwriting it. Skip Entry step 1 for an admitted ledger; settings apply only to fresh seeding. Apply `/skill:gauntlet-resume` pending recovery before refresh and any unresolved dirty-tree stop. Render rows, cap and decision history; stop on a dirty tree before dispatch.
48
+
49
+ ## Driver holds
50
+
51
+ After seeding, restrict driver reads during implement to the ledger (including saved or committed ledger snapshots), the child's return file (one file reference), git boundary commands (`status --porcelain`, `rev-list --count`, `rev-parse`, `show -s --format=%b` for commit bodies), skill resources at their absolute paths and the overrides file. Keep rows by status, iterations, cap, the last decision, the decoded amendment grant and each leg's checkout path for dispatch, handoff and stops. Use Entry's captured grant and membership throughout the loop.
43
52
 
44
- For resume, use the admitted ledger, its base and verification command, and durable iterations and cap instead of overwriting it. Skip Entry step 1 for an admitted ledger; settings apply only to fresh seeding. Render rows, cap and decision history; stop on a dirty tree before dispatch.
53
+ Never read the spec, source files, test output or logs inside the implement loop. Never diagnose a failure's cause; carry the child's evidence into the next dispatch or human stop. The only log-read exception is the last 20 lines at the human stop in After the loop step 1. Leave spec reads for seed, authorized restore and the amendment action below, outside the loop.
45
54
 
46
55
  ## Before each dispatch
47
56
 
48
- For a spec whose `## Legs` section has more than one `### Leg:` block, read `reference/coordinated-legs.md` IN FULL now with read; stop on an unreadable reference naming its path, never reconstruct it. Apply its `## Resume`, `## Targeting and dispatch`, `## Companion return validation`, `### Companion commit admission`, `## Exit verification` and `## Amendments` sections together with this driver; never apply `## Entry` here.
57
+ When the held membership has more than one leg, read `reference/coordinated-legs.md` IN FULL now with read at its absolute path; stop on an unreadable reference naming its path, never reconstruct it. Apply its `## Resume`, `## Targeting and dispatch`, `## Companion return validation`, `### Companion commit admission` and `## Amendments` sections together with this driver; never apply `## Entry` here.
49
58
 
50
- Read the ledger and require its `cap:` header before the ordered table, including before rule 1. On a missing header stop with `ledger has no cap: line - seeded under the old loopEngine contract`, even for a completed ledger; use the legacy grant below, never derive cap from settings. Count empty child commits and validation misses only after the latest `loop: retry row <n>` commit. Funding alone resets neither window. Preserve every row's attempts and the total iteration cap. Apply this ordered table, starting here after each return or human decision:
59
+ Read the ledger and require its `checks:` line per ## Gate set, then its `cap:` header before the ordered table, including before rule 1. On a missing header stop with `ledger has no cap: line - seeded under the old loopEngine contract`, even for a completed ledger; use the legacy grant below, never derive cap from settings. Count empty child commits and validation misses only after the latest `loop: retry row <n>` commit. Funding alone resets neither window. Preserve every row's attempts and the total iteration cap. Apply this ordered table, starting here after each return or human decision:
51
60
 
52
61
  | Order | Observed state | Action |
53
62
  |---|---|---|
54
- | 1 | No `open` or `failed` row | Exit verification. All-cut and baseline-complete ledgers exit normally. |
63
+ | 1 | No `open` or `failed` row | Refresh; require implement complete; continue at ## After the loop step 0. All-cut and baseline-complete ledgers exit here. |
55
64
  | 2 | Unresolved row attempts >= allowance | Apply row escalation below, otherwise human stop. Exempt `done` and `cut`, including third-attempt success. |
56
65
  | 3 | Last two child row commits both changed no file outside the ledger and no row status | Human stop, regardless of funding. Count child `loop: row ...` commits only, excluding seed and parent repair/retry/cut commits. A decision alone is not progress. |
57
66
  | 4 | `iterations` >= `cap` | Human stop naming the header cap value and every open/failed row with its attempts, before dispatch and before verification. Seed and interrupted dispatches count. |
58
67
  | 5 | Dispatch allowed | Select target by the priority below. |
59
68
 
60
- Set row allowance to 3 + funded N, increased to the latest `row <n> retry` decision's `allowed attempts <m>` when larger. Recover spent funding per row as `max(0, min(attempts, 3 + N) - 3)`; a mid-loop grant applies prospectively. Before dispatch on a funded row with attempts >= 3 and spent < N print `funded round <k> of <N> for row <n>`, with k = attempts - 3 + 1. Funding buys neither cap bypass nor empty-commit bypass nor an escalated model. Include `budget: <spent> of <N> spent` in funded stops.
69
+ When a refresh leaves implement active at rule 1, take the matching human stop; never start verify. Set row allowance to 3 + funded N, increased to the latest `row <n> retry` decision's `allowed attempts <m>` when larger. Recover spent funding per row as `max(0, min(attempts, 3 + N) - 3)`; a mid-loop grant applies prospectively. Before dispatch on a funded row with attempts >= 3 and spent < N print `funded round <k> of <N> for row <n>`, with k = attempts - 3 + 1. Funding buys neither cap bypass nor empty-commit bypass nor an escalated model. Include `budget: <spent> of <N> spent` in funded stops.
61
70
 
62
- Decode the current `**Amend-grant:**` through [amendment-surface Value decoding](../brainstorming/reference/amendment-surface.md). A budget-only grant gives no amend permission or escalation. At rule 2, hard boundaries and rules 3-4 win before escalation: cap or child-only stagnation stops without dispatch. Preserve `STAGNANT`, `REJECT`, closureReview and grant_fix_rounds boundaries; this is implement permission, not verify credit.
71
+ Use the held decoded amendment grant. A budget-only grant gives no amend permission or escalation. At rule 2, hard boundaries and rules 3-4 win before escalation: cap or child-only stagnation stops without dispatch. Preserve `STAGNANT`, `REJECT`, closureReview and grant_fix_rounds boundaries; this is implement permission, not verify credit.
63
72
 
64
- With amend permission and no existing durable `row <n> escalated` decision, resolve `gauntlet_setting({ key: "escalationLoop" })` and require `implModel`; unavailable tool or undefined model stops with the missing capability in Problem. Append `row <n> escalated | implModel round | allowed attempts <attempts + 1>`, commit parent `loop: escalate row <n>`, print `escalated round for row <n>`, and dispatch exactly once through the normal loop-implementer target, bump and validation path. This decision grants only this round, not a repeatedly matching old allowance. Exclude the parent escalation commit from child-only stagnation; it starts no new window. Recover identity from the ledger on resume; unrecoverable means spent. Retry, funding and amendments never erase or rearm it. Dispatch errors, non-DONE and validation failures consume it before any recommendation decision.
73
+ With amend permission and no existing durable `row <n> escalated` decision, resolve `gauntlet_setting({ key: "escalationLoop" })` and require `implModel`; unavailable tool or undefined model stops with the missing capability in Problem. Append `row <n> escalated | implModel round | allowed attempts <attempts + 1>`, commit parent `loop: escalate row <n>`, print `escalated round for row <n>`, and dispatch exactly once through the normal loop-implementer target, bump and validation path. Exclude this parent commit from child-only stagnation; it starts no new empty-child or validation-miss window. Treat the escalated decision as exactly one round without raising the standing allowance. Recover identity from the ledger on resume; unrecoverable means spent. Retry, funding and amendments never erase or rearm it. Dispatch errors, non-DONE and validation failures consume it before any recommendation decision.
65
74
 
66
75
  For attempts 5 with fund 2, append `row 2 escalated | implModel round | allowed attempts 6`, commit `loop: escalate row 2`, print `escalated round for row 2`, then attempt 6; attempts 4 and 5 paid the two funded rounds, spent remains 2. Clamp funding as above even beyond allowance, retaining prospective grants. The amend-permission escalated round is the only `implModel` dispatch.
67
76
 
@@ -69,7 +78,7 @@ Select `seed` until a validated `loop: seed evidence` commit with its `row 0 don
69
78
 
70
79
  ## Dispatch
71
80
 
72
- For home-only dispatch, record `HEAD_BEFORE`, copy the ledger text, and take i from the current iterations count. Increment `iterations:` before dispatch in the working tree so the child's commit persists it. Create a unique absolute output path with `mktemp` outside the repository. Dispatch exactly one foreground child in the main implementation worktree, not a nested worktree:
81
+ For home dispatch, record `HEAD_BEFORE`, save the ledger before the iterations bump and tuple write, and retain the current `iterations:` count as i. Send `iteration: i` using the current pre-bump `iterations:` count and write `iterations: i + 1` before dispatch; admission requires the child commit body to carry `i + 1`, read from the bumped ledger header. State that difference when rendering a dispatch or admission: the task line carries the pre-bump count by design, the body line and `ITERATION` carry the consumed count `i + 1`, and the two never compare to each other. Record the dispatch identity separately and write `pending: <row or seed> | <repo> | <HEAD sha>` using `home` for zero or one spec leg, the actual member identifier for coordinated runs, and the selected checkout's HEAD. Persist the consumed count and tuple before every home or companion dispatch; then refresh. Commit nothing extra. Create a unique absolute output path with `mktemp` outside the repository. Dispatch exactly one foreground child in the main implementation worktree, not a nested worktree:
73
82
 
74
83
  ```text
75
84
  subagent({ agent: "loop-implementer", context: "fresh", async: false,
@@ -79,41 +88,33 @@ subagent({ agent: "loop-implementer", context: "fresh", async: false,
79
88
  task: "iteration: <i>\nspec: <absolute spec path>\nledger: <absolute ledger path>\nbase: <base SHA>\ntarget: <row number or seed>\nprevious decision: <new conforming line or none>\nhint: <human hint or none>" })
80
89
  ```
81
90
 
82
- For `target: seed`, explicitly instruct the child to apply its seed contract even when iteration is greater than 0; carry that instruction in the existing `hint` field. Keep the actual consumed count in `iteration`.
91
+ For `target: seed`, explicitly instruct the child to apply its seed contract even when iteration is greater than 0; carry that instruction in the existing `hint` field. Keep the actual consumed pre-bump count in `iteration`.
83
92
 
84
93
  Omit the model override except on an escalated round (`model: <implModel>`); let the persona override or parent inheritance resolve it. Carry effects only: one file-reference return, one ledger read, git boundary checks. Never read a child transcript or carry reasoning history. Stop on dispatch error or an async handle; never poll, join or relaunch.
85
94
 
86
95
  ## Validate the return
87
96
 
88
- For home-only returns, apply the following boundary and table.
89
-
90
- 1. Require empty `git -C "<worktree>" status --porcelain` and exactly 1 from `git -C "<worktree>" rev-list HEAD_BEFORE..HEAD --count`. On dirty/zero/multiple commits stop, preserving changes and commits. Use `Stopped: iteration <i> left the tree dirty` or `Stopped: iteration <i> added <k> commits`. Read the ledger from HEAD only after this boundary passes.
91
- 2. Validate by dispatched `target`, not iteration number, against the saved copy using this table. Preserve headers including cap and the bumped iterations, row identifiers and prior decisions.
97
+ For home returns, apply the following boundary and table. Never project terminal child results before clean/exactly-one-commit admission.
98
+ 1. Require empty `git -C "<worktree>" status --porcelain` and exactly 1 from `git -C "<worktree>" rev-list HEAD_BEFORE..HEAD --count`. On dirty/zero/multiple commits restore the pre-dispatch target cells from the saved copy and use the separately recorded dispatch identity to restore the `pending:` tuple in the working ledger; for seed restore all dispatched non-cut rows. Preserve consumed iterations and all other child changes and commits. Refresh before the discard/reset stop. Use `Stopped: iteration <i> left the tree dirty` or `Stopped: iteration <i> added <k> commits`. Read the ledger from HEAD only after this boundary passes.
99
+ 2. Validate by dispatched `target`, not iteration number, against the saved copy using this table. Require the commit body's first two lines to match the exact dispatched `pending:` tuple and consumed `iteration:` (saved iterations +1), using the persona's home attribution contract for row and seed alike. Admit only `iterations` +1 and removal of the dispatched `pending:` line; reject every other header change, including cap. Preserve row identifiers and prior decisions.
92
100
 
93
101
  | Target | Required changes | Miss |
94
102
  |---|---|---|
95
103
  | Seed | All attempts stay 0; only `open` -> `done` status transitions; every non-cut row gets evidence; cut rows unchanged; exactly one new `row 0 done | seeded <k> rows, closed <m> on baseline | <first row to take>` decision. Partial and complete baseline closure both pass. Never `failed`. | Human stop; never automatic seed retry. |
96
104
  | Ordinary | Exactly the target row's mutable cells change: status `done` or `failed`, attempts +1, nonempty bounded evidence. Other rows unchanged. Exactly one NEW bounded decision appended, consistent with target and status. | Parent repair below. |
105
+ | Seed or ordinary | No committed tuple remains. | A retained committed tuple is an ordinary miss after boundary admission, not a boundary rejection. |
97
106
 
98
107
  Require ordinary decision grammar `^row <target> (done|failed) \| .{1,200} \| .{1,200}$`; an old conforming line is not a new line. Require check name plus at most three result lines in evidence, serialized with semicolons and escaped pipes as in the persona. Reject wrong targets, foreign cells, missing/malformed/new-extra decisions and changed headers.
99
108
 
100
- On an ordinary miss restore every non-target row, headers (including the saved cap) and prior decisions from the saved copy, retaining the incremented iterations. Set the target `failed`, attempts = saved attempts +1, evidence = `iteration <i>: <concrete miss>`. Remove malformed appended decisions and commit `loop: repair row <n>`. Set previous decision to `none`; otherwise use the new conforming line. Two consecutive validation misses stop because the child is not following the contract. A conforming return resets the consecutive-miss count; parent repair commits do not count toward child-only empty stagnation.
101
-
102
- ## Exit verification
103
-
104
- For legacy/single-member exit, run the ledger's `verification:` command once foreground in the worktree. Failure uses `Stopped: verification failed with every row closed`, Problem quoting failing output.
105
-
106
- Apply hard boundaries first; at cap use the cap stop without repair. With amend permission, `iterations < cap`, resolved `escalationLoop.implModel` and no spent `loop: repair verification` identity, bump iterations once and record `HEAD_BEFORE`. Dispatch exactly one `implementer` with `model: <implModel>`, `context: "fresh"`, `async: false`, the implementation worktree as cwd and its Rules, failing output, absolute spec path and the exact verification command. Require a clean tree and exactly one commit after HEAD_BEFORE; dirty/zero/multiple commits use existing boundary stops preserving count and state. Require all ledger rows unchanged, preserving cap and prior decisions. The child's sole commit includes the already-bumped ledger; after validation parent commits `loop: repair verification`, using an empty parent marker when no dirt remains. This marker is once per flow.
107
-
108
- Rerun that command once. Never spend verify-phase credits. A second failure retains the original header plus `escalated round spent`, then goes through Human stop. Dispatch error or non-DONE consumes the round before a decision; preserve the consumed count and stop. Recover spent identity from the parent commit on resume; interrupted or unrecoverable identity is spent, never add a carrier or fabricate success. With no permission or spent identity: no reopening and no automatic rerun. Missing settings/model stops with the capability in Problem. On success record verified HEAD and clean status; call `phase_tracker({ action: "complete", phase: "implement" })`, then continue immediately below.
109
+ On an ordinary miss restore every non-target row, headers (including the saved cap) and prior decisions from the saved copy, retaining the incremented iterations. Set the target `failed`, attempts = saved attempts +1, evidence = `iteration <i>: <concrete miss>`. Clear `pending:`, remove malformed appended decisions and commit `loop: repair row <n>`, then refresh. Set previous decision to `none`; otherwise use the new conforming line. Two consecutive validation misses stop because the child is not following the contract. A conforming return resets the consecutive-miss count; parent repair commits do not count toward child-only empty stagnation.
109
110
 
110
111
  ## Human stop
111
112
 
112
113
  Read and apply [menu-layout](../brainstorming/reference/menu-layout.md). Start the message with `gauntlet: question` at every human stop, including the discard/reset authorization ask for a dirty or commit-boundary return. Put it alone on the first output line, followed by a newline before the stop text, without a driver-state preamble, wrapper or code fence. These decisions are neither done nor stuck outcomes.
113
114
 
114
- Leave implement active. Use one screen of plain words: `Stopped on row <n> (<row text>)` for row failures, or the concrete boundary/cap/verification header above. `Problem:` quotes the evidence cell verbatim, identifying the actual spec/code contradiction, failing assertion/output or missing capability, and quotes the last decision line. Include funding budget only when funded. At every stop print `Preserve every row's attempts and the total iteration cap.` Name `escalated round spent` when applicable; omit round history and reasoning traces.
115
+ Implement-phase stops only: leave implement active and use the row/cap offers below. For verify stops use the menus in After the loop, retaining verify active. Use one screen of plain words: `Stopped on row <n>` for row failures, or the concrete boundary/cap/verification header. `Problem:` quotes the evidence cell and last decision line verbatim; attribute any spec/code contradiction, failing assertion/output or missing capability to that evidence, without investigating it. Include funding budget only when funded. At every stop print `Preserve every row's attempts and the total iteration cap.` Name `escalated round spent` when applicable; omit round history and reasoning traces.
115
116
 
116
- Offer these concrete actions. Offer `cap +N` only at a clean cap or legacy missing-cap stop; dirty-tree and commit-boundary stops keep discard authorization and never offer `cap +N`. When both the row allowance and total cap are exhausted, list independent funding and cap offers despite rule 2 priority. Take separate replies: funding follows the spec's `**Amend-grant:**` contract, cap follows the row below; define no combined syntax.
117
+ Offer these concrete actions. At a clean cap stop offer `cap +N` alongside the standard `Retry with hint`, Amend and Stop options. Only the verify-step-1 verification-failure stop restricts its menu to amend/stop. Offer `cap +N` only at a clean cap or legacy missing-cap stop; dirty-tree and commit-boundary stops keep discard authorization and never offer `cap +N`. When both the row allowance and total cap are exhausted, list independent funding and cap offers despite rule 2 priority. Take separate replies: funding follows the spec's `**Amend-grant:**` contract, cap follows the row below; define no combined syntax.
117
118
 
118
119
  | Human choice | Durable action |
119
120
  |---|---|
@@ -126,20 +127,35 @@ Serialize the bare decision as `cap +50 |` with an empty words cell. A cap grant
126
127
 
127
128
  For dirty/commit-boundary retry, ask the human to authorize discarding uncommitted changes/resetting to last valid commit. Preserve consumed dispatch count: set iterations to restored HEAD's value +1 before the next normal bump. An interrupted dispatch consumes the same count; recover it from disk/branch rather than silently repeating iteration 0.
128
129
 
129
- For ledger amendments use its line-1 discriminant: no plan writer, plan_check or task-tracker lifecycle. Approved deviates/deferred/elsewhere becomes `cut` with disposition evidence; requirement-preserving amendments leave rows unchanged; a re-bounded done row becomes `open` with `reopened by amendment`. Preserve attempts, iterations and cap. Commit spec + ledger as `loop: cut row <n>` or `loop: amend`. Option 4 stops for amendments, option 5 auto-applies amends, redraw always stops and deletes the ledger with the plan. Cut only through the amendment surface, including its standing-grant section 5.
130
+ Outside the dispatch loop, perform authorized amendment actions under the amendment surface's own reads. After the amendment commit, re-decode the grant and refresh the held membership, checkout paths and Rules from the updated spec before returning to the loop; apply this to funding and standing-grant amendments too. Leave the `**Amend-grant:**` header grammar unchanged.
131
+
132
+ Retry, cut, amend, raise-cap and escalate commits never clear the tuple. For ledger amendments use its line-1 discriminant: no plan writer or plan_check; refresh after the amendment commit. Approved deviates/deferred/elsewhere becomes `cut` with disposition evidence; requirement-preserving amendments leave rows unchanged; a re-bounded done row becomes `open` with `reopened by amendment`. Preserve attempts, iterations and cap. Commit spec + ledger as `loop: cut row <n>` or `loop: amend`. Option 4 stops for amendments, option 5 auto-applies amends, redraw always stops and deletes the ledger with the plan. Cut only through the amendment surface, including its standing-grant section 5.
130
133
 
131
134
  End every stop with `Recommendation: <option> - <why>` or `Recommendation: none - <why>`. An unnamed repair is none. Under amend permission take only a named authorized amend: print `took recommendation: amend for row <n>`, apply amendment-surface section 5 (including its audit), commit `loop: amend` / `loop: cut row <n>`, then return to the ordered table. Whitespace-normalize the row evidence cell and compare with evidence already auto-resolved on that row; repetition renders `Recommendation: none - evidence repeats row <n>`. Recover this evidence from amendment/ledger history; missing history never authorizes a repeated action. A cut leaves the stop; an unresolved row at allowance stops again, not a free retry. Retry, more attempts, cap +N and redraw wait for the human. Fix-first enters `/skill:shape-ticket`'s own gate, never an automatic separate repair. Hard boundaries never auto-take recommendations.
132
135
 
136
+ ## Gate set
137
+
138
+ Require a `checks:` line before each dispatch and at every gate-set site, including finish Step 1. On a missing line stop with `ledger has no checks: line - seeded under the old contract` and offer `stop` only; the human restarts by hand on a fresh baseline. Never migrate, automatically reseed or fall back to `verification:`.
139
+
140
+ Resolve the set as the deduplicated union of (owning checkout, command) pairs over every non-cut `done` row. Take the command from the first evidence segment up to the first unescaped semicolon; `failed` rows contribute nothing. Order pairs by ledger row number after deduplication: the first row contributing a pair fixes its position. Resolve ownership from the ledger, never the spec: `## Leg mapping` (`row | ac | leg`) names the leg whose checkout owns each expanded row. With no mapping, run every row at home. The same command in two checkouts is two pairs and runs in both, including shared-AC rows. For an all-cut ledger print `gate set empty - every row cut` and continue.
141
+
142
+ Use the executing process's `LOG_DIR` for every run and rerun: the parent's session directory minted at verify step 0, or the child's own temporary directory per the conformance ledger-subject override. Run each pair as `(cd "<checkout>" && <command>) > "$LOG_DIR/gate-<i>.log" 2>&1`, foreground, one at a time. Print `gate <i> exit <code> <log path>` and keep nothing else from output. Fail-fast: the first nonzero exit ends the run; later pairs do not run. That exit line and log are the single failure for the stop and repair task. Pass only when every pair ran and exited 0. Add no format rule for evidence commands: a non-runnable first segment fails like any command (exit 127 in its log).
143
+
144
+ Run the complete set at verify step 1, after every whole-diff fix round, at every conformance test site per its ledger-subject override, and at finish Step 1. Only the escalated repair's rerun selects the failing checkout's pairs. Across these sites run zero invocations of the ledger's `verification:` or any leg's `contract:` `- verification:` command; retain the header as the command CI runs. Pass the failing command, its checkout, exit code and log path into later fix-round machinery, never pasted output.
145
+
133
146
  ## After the loop
134
147
 
135
148
  Read SDD's `After All Tasks Complete`, `../subagent-driven-development/reference/happy-path-run.md`, and `../verification-before-completion/reference/conformance-check.md` IN FULL now with read. Stop on an unreadable reference; do not reconstruct it. Execute this continuation, not the waves engine or a generic verification skill:
136
149
 
137
150
  For coordinated runs, route each verification and review below to every leg with its own base, checkout, Rules and owned original ACs under home flow policy. Re-verify and re-review any changed leg; invoke coordinated finish once from home after every leg passes. Keep single-member/legacy paths free of a companion loop, leg file, `legs:` brief or `--leg` argument.
138
151
 
139
- 0. Call `phase_tracker({ action: "start", phase: "verify" })`.
140
- 1. Parent full verification uses the ledger command. Reuse the passing exit run only when HEAD and clean/no-change worktree still match. Commit verification-produced tracked changes. Any repair invalidates that run: rerun the full command successfully before the next gate. No task reopen/update is awaited.
141
- 2. Dispatch foreground whole-diff `wave-reviewer` per `/skill:requesting-code-review`, from ledger base through committed HEAD, with `SCOPED_TEST_COMMANDS: none`. Apply its fix rounds. Rerun full verification after every repair before re-review/next gate. Carry final SHIP Minor lines verbatim as `whole-diff minors:`, or `whole-diff minors: none`.
142
- 3. Run happy path per the fully read reference when overrides has `## Happy path` or the diff selects a row; use the diff-derived row, not a plan header. Pass summary and outcome to the separate fresh `conformance-reviewer`, along with spec path, verbatim original prompt and full diff. Use spec AC rows against the ledger as the checklist. Follow the reference's partition, concern decomposition, fix rounds and Convergence with the ledger command replacing plan Verification. Keep durable Gn identities in reports, without plan_tracker initialization or lifecycle updates. Rerun full verification after repairs. Resolve closureReview settings and reviewer dispatch per the reference. Reviews happen only after complete implement; none inside the iteration loop.
152
+ 0. Call `phase_tracker({ action: "start", phase: "verify" })`. Mint `LOG_DIR=$(mktemp -d)` once for this verify session; a resumed session mints a new one at its first gate-set site.
153
+ 1. Run the gate set per ## Gate set. Require every pair to pass. Commit verification-produced tracked changes, including gate-produced changes. Any repair invalidates that run: apply the rerun scope below before the next gate. No task reopen/update is awaited.
154
+ On failure use `Stopped: verification failed with every row closed`, `Problem:` naming `gate <i> exit <code> <log path>` and quoting at most the last 20 lines of that log with `tail -n 20`; this human-stop excerpt is the driver's only log read. Keep verify active and implement complete; offer amend or stop only, no `Retry with hint` or `cap +N`. Apply hard boundaries first; at cap stop without repair. With amend permission, `iterations < cap`, resolved `escalationLoop.implModel` and no spent `loop: repair verification` identity, bump iterations once and record `HEAD_BEFORE` in the failing leg. Dispatch exactly one `implementer` with `model: <implModel>`, `context: "fresh"`, `async: false`, the implementation worktree as cwd and its Rules (the failing leg's for coordinated runs), absolute spec path, failing command, its checkout, exit code and log path, never pasted output. The repair child reads the log to derive the files to touch. For a stale selector, name the row whose command no longer selects its test and restore the test or its name so the recorded command selects it again; never edit ledger evidence. Require a clean tree and exactly one commit after HEAD_BEFORE; dirty/zero/multiple commits stop preserving count and state. Require all ledger rows unchanged, preserving mapping, cap and prior decisions. The home child's sole commit includes the already-bumped ledger; a companion child commits its leg only. After validation parent commits `loop: repair verification` with the bumped home ledger, using an empty parent marker when no dirt remains. Refresh after admitted commits. This marker is once per flow.
155
+ Rerun the failing checkout's gate pairs once using ## Gate set's log redirection and fail-fast rule. After the failing checkout's rerun passes, run the original fail-fast run's still-unexecuted pairs from other checkouts in ledger order under the same redirection before recording verified HEAD. Never spend verify-phase credits. A second failure retains the original header plus `escalated round spent`, then stops with the verify menu. Dispatch error or non-DONE consumes the round before a decision; preserve the consumed count and stop. Recover spent identity from the parent commit on resume; interrupted or unrecoverable identity is spent, never add a carrier or fabricate success. With no permission or spent identity: no reopening and no automatic rerun. Missing settings/model stops with the capability in Problem. On success record verified HEAD and clean status for every leg.
156
+ 2. Dispatch foreground whole-diff `wave-reviewer` per `/skill:requesting-code-review`, from ledger base through committed HEAD, with `SCOPED_TEST_COMMANDS: none`. Apply its fix rounds. Rerun the complete gate set after every fix round before re-review/next gate. Carry final SHIP Minor lines verbatim as `whole-diff minors:`, or `whole-diff minors: none`.
157
+ 3. Run happy path per the fully read reference when overrides has `## Happy path` or the diff selects a row; use the diff-derived row, not a plan header. Pass summary and outcome to the separate fresh `conformance-reviewer`, along with spec path, verbatim original prompt and full diff. Use spec AC rows against the ledger as the checklist. Follow the reference's partition, concern decomposition, fix rounds and Convergence with the gate set replacing plan Verification at every test site per the reference's ledger-subject override. Use normal conformance Gn tasks on the same tracker and keep durable Gn identities in reports. Rerun the complete gate set after repairs. Resolve closureReview settings and reviewer dispatch per the reference. Reviews happen only after complete implement; none inside the iteration loop.
158
+ On an approved re-bound (`reopened by amendment`), refresh and stop with `Stopped: row <n> reopened by amendment during verify`; offer authorize the row's return to ledger implementation or stop. On approval apply the normal Before each dispatch boundaries, then Dispatch, Validate the return and refresh with verify still active and no phase reset; close on disk and rerun step 1 before continuing verify. Keep completion blocked until closure; never substitute a tracker write for the ledger return.
143
159
  4. Complete verify only on current CONFORMS or valid carried-open deferred inventory per the reference. A started positive-cap fix loop blocking/failing/exhausting with an open fix gap stops, never completes verify. Summarize rows closed, iterations consumed, files changed, test counts and review verdict. Emit exact `## Closure / conformance` schema from the reference: `status: CONFORMS (0 open)` or `status: GAPS (N open)`, then `audited-base: <full HEAD SHA>`, happy-path exactly when run, Deferred/deviates per spec exactly when applicable, all gap/concern fields unchanged, auto-applied fix commits index and whole-diff minors. Read its whole-diff-minors companion when directed. Never rename fields.
144
160
  5. Immediately invoke `/skill:finishing-a-development-branch <abs worktree path>`. Its menu is the human gate; do not add a ready-to-finish prompt.
145
161
 
@@ -1,10 +1,12 @@
1
- Read this reference with the loop driver for a spec whose `## Legs` section has more than one `### Leg:` block.
1
+ Read this reference with the loop driver when its held membership has more than one leg.
2
2
 
3
3
  ## Entry
4
4
 
5
- Read `## Legs` with [the scope grammar](../../brainstorming/reference/legs.md#scope-grammar-and-validation) before skeleton commit or dispatch. Require exactly one `scope:` per block: `scope: AC 1, AC 3` or `scope: none`. Reject missing/duplicate scope lines, duplicate indices within a list, malformed tokens and out-of-range original indices through the amendment stop. Include cut original AC indices; never infer ownership from a `design:` mention or path. Default only indices absent from every valid list to home; repeat shared indices in every owner's list.
5
+ At seed, read `## Legs` with [the scope grammar](../../brainstorming/reference/legs.md#scope-grammar-and-validation) before skeleton commit. Require exactly one `scope:` per block: `scope: AC 1, AC 3` or `scope: none`. Reject missing/duplicate scope lines, duplicate indices within a list, malformed tokens and out-of-range original indices through the amendment stop. Include cut original AC indices; never infer ownership from a `design:` mention or path. Default only indices absent from every valid list to home; repeat shared indices in every owner's list.
6
6
 
7
- Retain the home skeleton's `**Spec:**`, `verification:`, `iterations:`, `cap:` and `## Decisions` fields and its `plan_check`/commit admission. Read each member's verification from the home spec's `## Legs` `contract:` `- verification:` line before dispatch; keep the existing home verification header.
7
+ Retain the home skeleton's `**Spec:**`, `verification:`, `checks: commands`, `iterations:`, `cap:` and `## Decisions` fields and its `plan_check`/commit admission. Use the driver's gate set grouped by `## Leg mapping` for verification; keep the home verification header as the CI command.
8
+
9
+ For coordinated exit, apply the driver's `## Gate set` and `## After the loop` step 1 in verify, routing each pair through its mapped checkout. Keep `loop: repair verification` once per flow, not per failing leg. Success only after every leg passes; retain each verified HEAD and clean status.
8
10
 
9
11
  Assign numeric entries in original AC order, then membership order for shared ACs, independent of scope-list order. Leave spec rows untouched and copy each cut disposition to every expanded entry. Keep the four-column table and add `## Leg mapping` with `row | ac | leg`, one mapping per entry exactly once. Reject duplicate/missing mappings. Keep `base:` as home base; record one actual `base repo-a: <sha>` / `seeded repo-a: no` pair per member, including home. Resolve bases with each member's `git -C`, not home HEAD.
10
12
 
@@ -12,19 +14,19 @@ Compute initial cap as non-cut entry count times `maxIterationsPerRow` plus one
12
14
 
13
15
  ## Resume
14
16
 
15
- Recover pending companion work before generic dirty checks and before any new dispatch. Read the durable home ledger's `pending:` tuple and consumed iteration, selected companion HEAD and saved pre-dispatch state. Reconstruct the pre-dispatch ledger from home `HEAD:<ledger path>` on resume and admit only the expected on-disk iterations bump and tuple against it. Admit only the known iterations bump and exact pending tuple as pre-dispatch dirt; stop on other dirt. Reapply companion return validation below only when exactly one new commit after the recorded HEAD matches attribution and result. Apply the home-ledger commit without another attempt or iteration bump, clear pending and retain prior decisions. Stop preserving state on zero commits, unrelated movement, multiple commits or attribution/result mismatch. Never rerun that row or seed. After a successful parent commit no pending tuple remains, so a subsequent resume cannot duplicate the update.
17
+ Use the held membership and checkout paths captured by the driver's Entry at seed or authorized restore. Recover pending companion work before generic dirty checks and before any new dispatch. Read the durable home ledger's `pending:` tuple and consumed iteration, selected companion HEAD and saved pre-dispatch state. Reconstruct the pre-dispatch ledger from home `HEAD:<ledger path>` on resume and admit only the expected on-disk iterations bump and tuple against it. Admit only the known iterations bump and exact pending tuple as pre-dispatch dirt; stop on other dirt. Reapply companion return validation below only when exactly one new commit after the recorded HEAD matches attribution and result. Apply the home-ledger commit without another attempt or iteration bump, clear pending and retain prior decisions. Stop preserving state on zero commits, unrelated movement, multiple commits or attribution/result mismatch. Never rerun that row or seed. After a successful parent commit no pending tuple remains, so a subsequent resume cannot duplicate the update.
16
18
 
17
19
  ## Targeting and dispatch
18
20
 
19
21
  For coordinated targeting, select the next unseeded leg with non-cut entries in membership order before ordinary targeting. Use the existing retry/failed/open priority only after those seeds validate. Skip wholly cut legs; never mark foreign legs seeded. Map each numeric target to its original AC and leg via `## Leg mapping`.
20
22
 
21
- For coordinated dispatch, capture home and selected leg heads and save a pre-dispatch ledger snapshot for the expected-dirt comparison. Select the leg worktree as `cwd` and git root, its own base, mapped original AC, `Leg:` and combined spec/task `Rules:` as additive task inputs. Read spec and ledger by absolute home paths. Bump iterations exactly once. Before every companion dispatch, including seed, persist the exact tuple such as `pending: 2 | repo-b | abc1234` (or `pending: seed | repo-b | abc1234`) with actual target, repo and pre-dispatch HEAD in the home ledger. Keep that expected bump/tuple durable on disk before generic dirty checks; admit no other dirt. After persisting the bump and pending tuple, bind `SAVED_LEDGER` to the durable home ledger for companion admission, not the pre-dispatch snapshot. Pass consumed `iteration:` and the exact `pending:` as attribution. Leave home iterations on the existing single child commit path, validating only home entries and home seeded state.
23
+ For coordinated dispatch, capture home and selected leg heads and save a pre-dispatch ledger snapshot before the iterations bump and tuple write for the expected-dirt comparison. Select the leg worktree as `cwd` and git root, its own base, mapped original AC, `Leg:` and combined spec/task `Rules:` as additive task inputs. Pass absolute home spec and ledger paths for the child to read; the driver reads only the ledger. Read the current `iterations:` count as i. Before every dispatch, home or companion including seed, persist the exact tuple such as `pending: 2 | repo-b | abc1234` (or `pending: seed | repo-b | abc1234`) with actual target, member repo and pre-dispatch HEAD in the home ledger. Keep that expected bump/tuple durable on disk before generic dirty checks; admit no other dirt. After persisting the bump and pending tuple, bind `SAVED_LEDGER` to the durable home ledger for companion admission, not the pre-dispatch snapshot. Send `iteration: i` as the saved pre-bump dispatch index (for i = 2, send `iteration: 2`), not the consumed count; write `iterations: i + 1` before dispatch; admission requires the child commit body to carry `i + 1`, read from the bumped ledger header. State that difference when rendering a dispatch or admission: the task line carries the pre-bump count by design, the body line and `ITERATION` carry the consumed count `i + 1`, and the two never compare to each other. Pass the exact `pending:` as attribution. Leave home iterations on the existing single child commit path, validating only home entries and home seeded state, with tuple removal in the admitted home commit. Apply the driver's pre-dispatch refresh after the durable write.
22
24
 
23
25
  ## Companion return validation
24
26
 
25
27
  For a companion, validate from its commit, not the reply. Require a clean companion and exactly one commit after pending HEAD; require unchanged home HEAD and no home edits except the expected persisted bump/tuple. Match subject `loop: row <n> <status>` or `loop: seed evidence`, exact pending tuple and consumed `iteration:` in the body. Parse only the resulting four-column target row (all and only that leg's non-cut rows for seed), followed by one bounded decision. Apply the evidence and decision bounds in the driver's `## Validate the return` table. Reject a wrong target, foreign entry, header changes, fabricated counts, malformed evidence or extra results. Validate seed counts against actual rows and baseline closures; preserve attempts and set only this leg's seeded value to `yes` after every non-cut entry validates. Keep seed misses a human stop. Apply ordinary repair only to the target, retaining consumed iterations and saved cap.
26
28
 
27
- After validation update only that leg's target or seed entries, append the validated decision, record companion SHA in evidence, and remove `pending:` in one home-ledger commit. Preserve every other row, header and prior decision. That home-ledger commit (`loop: record <repo> row <n>`) is a parent commit, not a child `loop: row ...` commit: it never counts toward child-only empty-commit stagnation, and a rejected companion return records the rejection in the same parent commit while preserving the pending tuple and every row. Recover interrupted returns by this same validation, never trusted reply text.
29
+ After validation update only that leg's target or seed entries, append the validated decision, record companion SHA in evidence, and remove `pending:` in one home-ledger commit. Preserve every other row, header and prior decision. That home-ledger commit (`loop: record <repo> row <n>`) is a parent commit, not a child `loop: row ...` commit: it never counts toward child-only empty-commit stagnation; only the companion's own commits are counted at the boundary. Record a rejected companion return in the same parent commit while preserving the pending tuple and every row. Recover interrupted returns by this same validation, never trusted reply text.
28
30
 
29
31
  For coordinated home returns apply it only to home entries/seeded state, preserving foreign entries, mappings and bases.
30
32
 
@@ -87,18 +89,6 @@ console.log(JSON.stringify({ sha: commit, rows: resultLines, decision }));
87
89
  NODE
88
90
  ```
89
91
 
90
- ## Exit verification
91
-
92
- For coordinated exit, read each leg's verification from the home spec's `## Legs` `contract:` `- verification:` line and run it once foreground in its owning checkout. Require every leg to pass before completing implement.
93
-
94
- With amend permission, `iterations < cap`, resolved `escalationLoop.implModel` and no spent `loop: repair verification` identity, bump home iterations once and record `HEAD_BEFORE` in the failing leg. Dispatch exactly one `implementer` with `model: <implModel>`, `context: "fresh"`, `async: false`, that leg's cwd/Rules, failing output, absolute home spec path and exact leg verification command.
95
-
96
- Require all ledger rows unchanged, preserving mapping, cap and prior decisions. The home child's sole commit includes the already-bumped home ledger; after validation parent commits `loop: repair verification`, using an empty parent marker when no dirt remains. A companion child commits its leg only; parent commits the bumped home ledger as `loop: repair verification`, preserving rows and mapping. This marker is once per flow, not per failing leg.
97
-
98
- Rerun that command once in the failing leg only. Never spend another leg's verification or verify-phase credits.
99
-
100
- Success only after every leg passes: record verified HEAD and clean status.
101
-
102
92
  ## Amendments
103
93
 
104
94
  For coordinated amendments, reconcile by original AC/leg mapping without resetting attempts, iterations or cap. Re-read explicit scope lists after approved ownership amendments and reconcile expanded entries; a disposition-only cut changes neither original indices nor ownership. Preserve unchanged mapped entries and their histories.