pi-gauntlet 8.4.9 → 8.4.11

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.
@@ -24,7 +24,7 @@ git -C <worktree> diff --name-status origin/$DEFAULT...HEAD
24
24
 
25
25
  Prove the shared predicate against `origin/$DEFAULT` before pushing. Stop on command errors. On invalid shape print the offending name-status lines and `origin/$DEFAULT`, retain the amended spec and checkout, and redraw with `Withheld: draft PR - diff against origin/$DEFAULT is not spec-only (<paths>)` replacing 6. Keep implementation approvals available.
26
26
 
27
- Push, then create with explicit head/base and the spec H1 as title. Run gh against the worktree repository:
27
+ Push, then create with explicit head/base and the spec H1 as title. Pass the summary verbatim through the quoted heredoc shown below, including its literal delimiter in narrated commands. Run gh against the worktree repository:
28
28
 
29
29
  ```bash
30
30
  git -C <worktree> push -u origin <branch>
@@ -40,7 +40,28 @@ EOF
40
40
  | Retry 6 after published handoff | Refresh origin's branch head; require `origin/<branch>` == HEAD. On mismatch print both full SHAs and stop. On equality rerun create only, no push, no amend. |
41
41
  | Create succeeds | Print URL before completing brainstorm; then perform ownership-based cleanup below. |
42
42
 
43
- After URL output call `phase_tracker({ action: "complete", phase: "brainstorm" })`. Read finishing's [Step 6](../../finishing-a-development-branch/SKILL.md#step-6-cleanup-workspace), using only its ownership test and wrapper selection: resolve home/destroy, legacy native script, or native remove/prune. Disable every branch-deletion step, including within a destroy wrapper: verify the wrapper preserves the branch before running it; stop cleanup and report when it cannot. Never delete the local branch. Report host-owned or failed removal with checkout path and command output; explain that later `brainstorming #N` hits pr-head's checked-out-at-another-path stop until that checkout is gone. Start no plan or loop, produce no handoff brief, and leave telemetry unchanged.
43
+ After URL output call `phase_tracker({ action: "complete", phase: "brainstorm" })`, then run [Draft-PR cleanup](#draft-pr-cleanup) once for home. Start no plan or loop, produce no handoff brief, and leave telemetry unchanged.
44
+
45
+ ### Draft-PR cleanup
46
+
47
+ Bind `<repo>` and `<branch>` from the recorded block, `<primary>` to that repo's primary, and `<tree>` to the session's home worktree. For a legacy spec without `## Legs`, use the repo and branch just pushed and the recipe's worktree. For companions, locate `<tree>` by [Locate a leg tree](legs.md#locate-a-leg-tree), not the carried Worktree First path; on lookup failure run no destroy or branch deletion, report `<repo>: kept <branch> - <lookup reason>`, and continue.
48
+
49
+ 1. Require `git -C <tree> branch --show-current` to print `<branch>`. Read `git -C <tree> ls-remote --exit-code --heads origin refs/heads/<branch>`, `git -C <tree> rev-parse HEAD`, and `git -C <primary> rev-parse refs/heads/<branch>`. Pin the SHA only on exit 0 with all three SHAs equal. Otherwise keep tree and branch and report the reason below.
50
+ 2. Select ownership and destruction through finishing's [Step 6](../../finishing-a-development-branch/SKILL.md#step-6-cleanup-workspace), using the recorded contract for a spec with Legs and the overrides reread only for a legacy spec. A recorded block with `home:` keeps its pattern ownership test. Without `home:`, run its recorded `destroy:` from the primary on the located tree, with `<name>` set to the folder basename and `<branch>` to the recorded branch; resolve other tokens before execution. Neither `home:` nor `destroy:` means host-owned: keep both. Never fall back to native removal after a refused or failed wrapper. Before running a branch-deleting wrapper, require its source to delete only after the tree is gone and only at the pinned commit or behind a check refusing a tip the remote does not hold; refuse unguarded deletion.
51
+ 3. After destruction, whatever its exit, read `git -C <primary> worktree list --porcelain`, the folder's on-disk presence, and `git -C <primary> rev-parse -q --verify refs/heads/<branch>`. Count the tree removed only when neither listed nor on disk; otherwise keep any remaining branch. Decide from read-back, never the destroy exit alone.
52
+ 4. With the tree removed and the ref still present, compare its tip to the pinned SHA. Keep a moved ref; otherwise run `git -C <primary> update-ref -d refs/heads/<branch> <pinned SHA>`, never `git branch -D`. Read back the ref after deletion to report its actual state. A guarded wrapper that already deleted it needs no second deletion.
53
+ 5. Report from the observed tree and branch state:
54
+
55
+ | State | Report |
56
+ |---|---|
57
+ | Tree removed, branch deleted | `<repo>: removed <path>, deleted <branch>` |
58
+ | Both remain | `<repo>: kept <path> and <branch> - <reason>` |
59
+ | Tree removed, branch remains | `<repo>: removed <path>, branch <branch> kept - <reason>` |
60
+ | Tree remains, branch gone | `<repo>: kept <path>, branch <branch> deleted - <output>` |
61
+
62
+ Use the observed reason: `tree is on <current branch or detached>, not <branch>`, `origin/<branch> is at <sha>, tree is at <sha>`, `<branch> is at <sha>, tree is at <sha>`, `origin/<branch> is missing` (ls-remote exit 2), `remote lookup failed: <output>` (other nonzero exit), `host-owned`, `destroy deletes <branch> unguarded`, or `removal failed: <output>`. For a removed tree with a retained branch, report `<branch> moved to <sha>` or the update-ref output. A nonzero destroy exit with the tree removed still proceeds to step 4; append ` - destroy exited <code>: <output>` to the report.
63
+
64
+ Attempt every leg regardless of another cleanup outcome, companions in declared order then home. For a retained tree outside a recorded `home:`'s resolved path, explain that later `brainstorming #N` stops on a branch checked out at another path; a no-`home:` tree is reused by continuation. Run no cleanup when PR creation fails.
44
65
 
45
66
  ### Coordinated publication passes
46
67
 
@@ -61,23 +82,34 @@ Publish companions in declared order from the preflight observations:
61
82
 
62
83
  Then run home's existing push/create recipe. Home push/create failures keep its failure rows and also list published companions; never roll back. After home create failure freeze the published handoff commit: the create-only retry above does not amend or push any member or rerun publication passes. On success print `pushed: <repo> origin/<branch>` for each companion before the single home URL, then complete brainstorm.
63
84
 
64
- Clean companions in declared order, then home. Apply finishing Step 6's ownership test and wrapper selection to each recorded contract (legacy without Legs keeps its reread). Verify every wrapper preserves its branch before execution; refuse unsafe wrappers without native fallback. Report each host-owned/refused/failed removal with repo, path and command output, leave its branch intact, and attempt all remaining cleanups even after refusal. Keep branches everywhere, including after owned built-in remove/prune. Write no receipt, companion PR, telemetry or brief.
85
+ Run [Draft-PR cleanup](#draft-pr-cleanup) for companions in declared order, then home, retaining each leg's report even after another leg's refusal. Write no receipt, companion PR, telemetry or brief.
65
86
 
66
87
  ### Coordinated marked settlement
67
88
 
68
89
  Use only the N>1 context observed by pr-subject's marked classifier at the original PR head. Preserve home's provisioned tree on every stop. Read the committed Legs in order; reject missing repo/branch/contract, mismatched shared branches or invalid blocks without falling into ordinary sibling discovery.
69
90
 
70
- 1. Settle only recorded companions with [legs.md](legs.md)'s first-found home overrides at `BASE_SHA` (`git show <BASE_SHA>:<overrides path>`), sibling parser and `<home PRIMARY parent>/<NAME>` paths. Match repo identifiers before probing paths; validate declaration, checkout, stored origin identity and nonhome canonical path. Never activate unrecorded siblings or infer membership from existing PRs. On no match stop: `leg <repo> matches no sibling declaration in <overrides path>`.
71
- 2. Preflight every companion before creating or syncing any companion: run `git -C <PATH> fetch origin` in its primary, then `git -C <PATH> ls-remote --exit-code --heads origin refs/heads/<branch>`. Exit 2 means missing: take the missing-remote stop below even when a stale `origin/<branch>` still resolves. Exit 0 proves live existence; require the recorded shared `origin/<branch>`. On any fetch failure or other lookup exit stop naming member and command output, never diagnose absence. Resolve its own settings/overrides home/create with legs.md's preset/default rules. Compare both portable values with the recorded contract. Stop on drift: `contract drift for <repo>: recorded <key>: <recorded value>, resolved <current value>; amend the recorded contract or restore the repo convention, then rerun brainstorming #N`. Never silently choose between them. Resolve a user amendment through the existing home-plus-companion reconciliation path.
72
- 3. Permit fetch/tracking-ref updates during preflight, but no worktree add, local branch/ref update or merge. A missing last declaration/remote prevents provisioning even the first companion. On missing remote say `origin/<branch> is missing in <repo>; on the machine that ran option 6, push <branch> from that companion's checkout, then rerun brainstorming #N`. For recovery, first verify the leg file's commit with `git log -1 --format=%H refs/heads/<branch> -- <spec-dir>/<home spec filename>` in the retained tree or primary without checking out or modifying the primary, then run `git push -u origin <branch>` from that existing branch and rerun. No commit anywhere means an incomplete handle: stop; regenerate nothing. An unrelated branch-tip commit does not prove the file exists.
73
- 4. After every companion passes, invoke using-git-worktrees once each with explicit `ROOT` = primary, shared `BRANCH`, `REMOTE_BRANCH=existing`. Use pr-head's companion mode and race backstop; carry each Step 4 report, including `Base sync recovered: <sha7>` and its proof. Never construct companion PR fields, pre-rework refs, thread queries or `MEMBER_HEADS`. Do not bypass wrapper safety (`-b`/`-B` falls back to native existing-branch creation) or invent a second provisioning path.
91
+ 1. Settle only recorded companions with [legs.md](legs.md)'s first-found home overrides at `BASE_SHA` (`git show <BASE_SHA>:<overrides path>`), sibling parser and `<home PRIMARY parent>/<NAME>` paths. Match repo identifiers before probing paths; validate declaration, checkout and stored origin identity. Canonicalize both PATH and home PRIMARY, compare them explicitly, and stop on equality before any companion provisioning. Never activate unrecorded siblings or infer membership from existing PRs. On no match stop: `leg <repo> matches no sibling declaration in <overrides path>`.
92
+ 2. Preflight every companion before creating or syncing any companion: run `git -C <PATH> fetch origin` in its primary, then `git -C <PATH> ls-remote --exit-code --heads origin refs/heads/<branch>`. Exit 2 means missing: take the missing-remote stop below even when a stale `origin/<branch>` still resolves. Exit 0 proves live existence; require the recorded shared `origin/<branch>`. On any fetch failure or other lookup exit stop naming member and command output, never diagnose absence. Resolve its own settings/overrides with legs.md's preset/default rules. Compare portable values by the table below. Stop on drift: `contract drift for <repo>: recorded <key>: <recorded value>, resolved <current value>; amend the recorded contract or restore the repo convention, then rerun brainstorming #N`. Never silently choose between them. Resolve a user amendment through the existing home-plus-companion reconciliation path.
93
+ 3. Permit fetch/tracking-ref updates during preflight, but no worktree add, local branch/ref update or merge. A missing last declaration/remote prevents provisioning even the first companion. On missing remote use pr-head's [Missing remote recovery](../../using-git-worktrees/reference/pr-head.md#missing-remote-recovery): check the local branch's file-scoped log in the primary before choosing the push or restore ending.
94
+ 4. After every companion passes, invoke using-git-worktrees once each with explicit `ROOT` = primary, shared `BRANCH`, `REMOTE_BRANCH=existing`. Use pr-head's companion mode and race backstop; carry each Step 4 report, including `Base sync recovered: <sha7>` and its proof. Never construct companion PR fields, pre-rework refs, thread queries or `MEMBER_HEADS`. Apply pr-head's [Recorded no-home provisioning](../../using-git-worktrees/reference/pr-head.md#recorded-no-home-provisioning) for a block without `home:`; keep the `-b`/`-B` native fallback only for a block with `home:`. Invent no second provisioning path.
74
95
  5. On unresolved companion base merge stop: `base merge unresolved for <repo> (<files>) - merge origin/<base> by hand in <worktree> and rerun brainstorming #N`. Keep all trees and refs; on every stop print `Preserved created legs:` listing home and every already-provisioned companion, with repo and path. Never remove any on retries. Preserve home's recovered base-sync proof even if a later companion stops; rerun using the same home recovery path.
75
96
 
76
- At gate readiness list every Worktree First path home first, then companions in recorded order. Offer the ordinary AC-dependent 1/2/4/5 choices and optional pinned audit 3 below, and `Withheld: draft PR - #N already exists`. Keep ordinary pinned-audit and approval persistence below; no companion approval record or second council.
97
+ Compare the recorded contract before provisioning:
98
+
99
+ | Recorded field | Current value |
100
+ |---|---|
101
+ | Keyed or built-in `create:` | Step 1a's resolved portable `create:`. |
102
+ | Discovered-script `create:` | Step 1b's native-tool/script discovery in that primary, rendered through [Record portable templates](legs.md#record-portable-templates), not Step 1a's built-in default. |
103
+ | Recorded `home:` | The current creator's `home:`; when none, print the drift stop with `resolved absent`. |
104
+ | No `home:` recorded | Skip home comparison. |
105
+
106
+ For a script-placed leg with an unwanted recorded `home:`, require a user-approved amendment dropping that line from both the home block and companion file through their existing reconciliation path. Rewrite nothing automatically.
107
+
108
+ At gate readiness render each observed Step 4 report in full, home first then companions in recorded order: `Worktree ready at <path>`, `Branch: <branch>`, Base and Base SHA, and the observed `merge:` outcome. Include each returned `create: override skipped (contains -b)` and `Base sync recovered:` line; preserve home's PR and Pre-rework head lines only on home. Inside the rendered gate block, explicitly print `Worktrees: <home repo> <home path>, <companion repo> <companion path>, ...` naming every Worktree First path, home first then each companion in recorded order, never home alone. Render these values, not a promise to include them. Offer the ordinary AC-dependent 1/2/4/5 choices and optional pinned audit 3 below, and `Withheld: draft PR - #N already exists`. Keep ordinary pinned-audit and approval persistence below; no companion approval record or second council.
77
109
 
78
110
  ## Re-gate a marked spec PR
79
111
 
80
- Reuse [pr-head](../../using-git-worktrees/reference/pr-head.md)'s checkout, base merge, and Step 4 report, not its before-gather thread fetch. Preserve its checked-out-at-another-path stop. On observed `merge: unresolved - <files>`, print `base merge unresolved for PR #N (<files>) - merge origin/<base> by hand in <worktree> and rerun brainstorming #N`; preserve checkout, render no gate, write no approval or repair task.
112
+ Reuse [pr-head](../../using-git-worktrees/reference/pr-head.md)'s checkout, base merge, and Step 4 report, not its before-gather thread fetch. Preserve its checked-out-at-another-path stop for recorded `home:` blocks and unmarked subjects; use its no-home provisioning rows for a marked home without `home:`. On observed `merge: unresolved - <files>`, print `base merge unresolved for PR #N (<files>) - merge origin/<base> by hand in <worktree> and rerun brainstorming #N`; preserve checkout, render no gate, write no approval or repair task.
81
113
 
82
114
  For observed N>1 carried Legs, finish [coordinated marked settlement](#coordinated-marked-settlement) after home's Step 4 report and before rendering the gate. For zero/one block keep the home-only route unchanged.
83
115
 
@@ -380,11 +380,11 @@ If confirmed: Cleanup worktree (Step 6), then, if Step 6 removed the worktree, `
380
380
 
381
381
  **Only runs for the Squash-merge and Discard options (3 and 5).** The PR, draft PR, and Keep options always preserve the worktree.
382
382
 
383
- Use recorded `contract:` lines when the spec carries `## Legs`, including one member; apply the recorded cleanup authority from the Step 1 reference. For a legacy spec without `## Legs`, read the gauntlet overrides file now (ladder in Project overrides) and its `## using-git-worktrees` section as the cleanup contract (keys written like `## cleanup` items: `using-git-worktrees/SKILL.md` Step 1a).
383
+ Use recorded `contract:` lines when the spec carries `## Legs`, including one member; apply [recorded cleanup ownership](reference/legs.md#recorded-cleanup-ownership) before the keyed path below. For a legacy spec without `## Legs`, read the gauntlet overrides file now (ladder in Project overrides) and its `## using-git-worktrees` section as the cleanup contract (keys written like `## cleanup` items: `using-git-worktrees/SKILL.md` Step 1a).
384
384
 
385
385
  **Keyed contract** - the section has at least one of `- home:`, `- create:`, `- destroy:`:
386
386
 
387
- 1. Resolve `home:` against `$PRIMARY` (absent -> `$PRIMARY/.worktrees/<name>`; an absolute value is used as-is). `<name>` must appear exactly once, inside one path segment that may carry a literal prefix or suffix; otherwise stop and name the line.
387
+ 1. Resolve `home:` against `$PRIMARY` (absent in legacy overrides only -> `$PRIMARY/.worktrees/<name>`; an absolute value is used as-is). `<name>` must appear exactly once, inside one path segment that may carry a literal prefix or suffix; otherwise stop and name the line.
388
388
  2. Ownership match: canonicalize both sides (`realpath`) and compare `$WORKTREE` to the resolved pattern, treating the `<name>` segment as `<prefix>*<suffix>` where `*` matches the remainder of that one segment. The text `*` matched is `NAME` - the creation identifier (`jacek/fix-x` was created as `jacek-fix-x`; `home: ../acme-mono-<name>` recovers `fix-x` from `acme-mono-fix-x`). A pattern that cannot isolate one segment -> stop and report.
389
389
  3. Match and `destroy:` set -> run it from `$PRIMARY` with `<name>` -> `'NAME'` and `<branch>` -> `'$FEATURE'`, each value one single-quoted shell word (`'...'`, an embedded `'` escaped), any other `<token>` resolved from context or asked once, never executed raw. Non-zero exit -> print its output, keep the branch, end this step; never fall back to `git worktree remove --force`. On success, run no `git worktree remove` or `prune`; continue to `git -C "$PRIMARY" branch -D "$FEATURE"`.
390
390
  4. Match and no `destroy:` -> `git -C "$PRIMARY" worktree remove "$WORKTREE"` then `git -C "$PRIMARY" worktree prune`; after success, continue to `git -C "$PRIMARY" branch -D "$FEATURE"`.
@@ -442,7 +442,7 @@ A host-owned worktree (Step 6: no `home:` match, or the legacy "Otherwise") keep
442
442
 
443
443
  **Cleaning up harness-owned worktrees**
444
444
  - **Problem:** Removing a worktree the harness created causes phantom state
445
- - **Fix:** Only clean up worktrees that match the `home:` pattern of `## using-git-worktrees`, or - on the legacy path - under `.worktrees/`, `~/.worktrees/<project>/`, or paths produced by a project-native worktree script
445
+ - **Fix:** Apply [recorded cleanup ownership](reference/legs.md#recorded-cleanup-ownership) for specs with `## Legs`; otherwise use Step 6's overrides or legacy ownership proof
446
446
 
447
447
  **No confirmation for discard**
448
448
  - **Problem:** Accidentally delete work
@@ -488,8 +488,8 @@ Once the merge (and any deploy) has landed, `/skill:check-delivery <ticket-ref>`
488
488
  - Get typed confirmation for Option 5 (Discard)
489
489
  - Clean up worktree for Options 3 & 5 (Squash-merge, Discard) only
490
490
  - Target `$PRIMARY` with `git -C` for merge, worktree removal, and branch deletion
491
- - Run `git -C "$PRIMARY" worktree prune` after removal
492
- - Match `$WORKTREE` against the `home:` pattern of `## using-git-worktrees` before removing anything when the keyed contract is active
491
+ - Run `git -C "$PRIMARY" worktree prune` only after owned built-in removal
492
+ - Match `$WORKTREE` against `home:` for recorded blocks that have it; apply Step 6's default only to legacy overrides
493
493
  - Surface the closure / conformance verdict as its own section before the options menu
494
494
 
495
495
  ## Project overrides
@@ -2,12 +2,22 @@
2
2
 
3
3
  ## Activation and authority
4
4
 
5
- Read the home spec's `## Legs` once at Step 1. Use the membership, portable identifiers, scope validation and path resolution in [the leg grammar](../../brainstorming/reference/legs.md). Resolve selected primaries from home's declared siblings and worktrees from the brief or recorded `home:` pattern. Validate branch, repository identity and each companion's full `**Home:**` tuple before acting. Admit a missing delivered worktree only through a validated receipt below.
5
+ Read the home spec's `## Legs` once at Step 1. Use the membership, portable identifiers, scope validation and [Locate a leg tree](../../brainstorming/reference/legs.md#locate-a-leg-tree) rules in the leg grammar. Resolve selected primaries from home's declared siblings; keep the session's home worktree and locate companions by recorded branch, regardless of a brief path or `home:`. Validate branch, repository identity and each companion's full `**Home:**` tuple before acting. Admit a missing delivered worktree only through a validated receipt below.
6
6
 
7
7
  Use recorded `contract:` lines for every spec with `## Legs`, including one member. Amend the home block and affected companion file before using a changed contract; do not reread overrides to replace it. For one member, return to the ordinary finish steps using that block's contract: keep exactly one `### Leg:`, no companion artifact, `legs:` brief block, receipt, `--leg` argument or companion loop. For no `## Legs`, use the ordinary home-only flow and Step 6's overrides reread.
8
8
 
9
9
  For more than one member, apply the following steps instead of the home-only verification, delivery and cleanup mechanics. Keep Step 3.5's disposition protocol, the home's review policy, Step 4 menu and confirmations. Keep machine-local paths out of committed bodies and messages.
10
10
 
11
+ ## Recorded cleanup ownership
12
+
13
+ Apply this table to every recorded block, including a one-member spec, before Step 6's keyed path. Keep legacy specs without `## Legs` on the finish-time overrides reread. Use the recorded cleanup worktree command in preference to `destroy:` and retain the configured teardown hook's existing semantics; never replace recorded authority from current overrides.
14
+
15
+ | Block | Cleanup |
16
+ |---|---|
17
+ | Has `home:` | Apply Step 6's existing ownership pattern match and recovered `<name>`, then `destroy:` or owned built-in removal; preserve unmatched host-owned trees and branches. |
18
+ | No `home:`, has `destroy:` | Run the recorded command from the leg's primary against the located tree: set `<name>` to its folder basename and `<branch>` to the recorded branch, each as one single-quoted shell word using Step 6's escaping; resolve other tokens from context or ask once. After the command, whatever its exit, read `git -C <primary> worktree list --porcelain`, test the folder's existence, and read `git -C <primary> rev-parse -q --verify refs/heads/<branch>`. Treat the tree as removed only when neither listed nor on disk. After confirmed removal, delete a remaining branch through finish's existing `git -C <primary> branch -D <branch>` step; otherwise keep it. Report the observed tree/ref state and any command failure, not success from exit alone. Run no built-in remove or prune fallback on any outcome. Draft-PR cleanup uses its own gated branch deletion instead. |
19
+ | Neither | Keep the host-owned tree and branch; run no cleanup command and report ownership. |
20
+
11
21
  ## Durable receipts
12
22
 
13
23
  Keep one home-owned file per delivered leg at `<home git common dir>/gauntlet/receipts/<spec filename>/<repo>`, where `<home git common dir>` is `git -C <home worktree> rev-parse --path-format=absolute --git-common-dir` (the home primary's `.git`, e.g. `/work/repo-a/.git/gauntlet/receipts/shared.md/repo-b`) - never inside any worktree, so a removed home tree never takes a receipt with it. Include the full spec filename, including `.md`, and preserve repo path segments; create directories before writing. Git metadata is never tracked, so no exclude entry is needed. Treat them as flow restoration artifacts, not telemetry, approval evidence or proof without validation.
@@ -67,10 +77,10 @@ A squash with failed post-verification belongs under Not shipped with its create
67
77
 
68
78
  ## Discard and recorded cleanup - Steps 5 and 6
69
79
 
70
- List every member's branch, commit count, and worktree path as a resolved absolute path (the brief's or the recorded `home:` pattern expanded for this branch, e.g. `/work/repo-b/.worktrees/feature-shared-change`; never a pattern or placeholder) before one typed `discard` confirmation. Obtain exact confirmation once for the run, then clean every member, home included, through its recorded contract regardless of other members' refusals. Do not strip or seal for discard.
80
+ List every member's branch, commit count, and located worktree path as a resolved absolute path (e.g. `/work/repo-b/trees/fix-x`; never a pattern or placeholder), or the lookup failure reason in place of a path, before one typed `discard` confirmation. Obtain exact confirmation once for the run, then clean every member, home included, through its recorded contract regardless of other members' refusals. Do not strip or seal for discard.
71
81
 
72
- For cleanup, use the recorded `## cleanup` worktree command, else `destroy:`, with the configured teardown hook using pi-cohort's existing semantics, else the owned built-in matched against that leg's recorded `home:`. Execute from that leg's primary. Expand recorded `<name>` and `<branch>` as single shell words using Step 6's escaping and ownership proof; resolve other tokens before execution. Never use `git worktree remove` past a wrapper or hook failure. Leave unmatched host-owned trees and their branches preserved.
82
+ For cleanup, apply [Recorded cleanup ownership](#recorded-cleanup-ownership) from each leg's primary. Retain its read-back rule even after a wrapper failure; a hook refusal leaves the wrapper unrun. Never bypass a wrapper or hook with `git worktree remove`.
73
83
 
74
- Clean companions in declared order, then home. Report a refusal as that leg's `failed` line, leave the tree intact, and continue the remaining cleanup attempts and the remaining report lines. After squash, stop only the refused companion's cleanup and attempt every remaining companion's recorded contract from its own primary; on any companion cleanup failure, skip home's cleanup and report `<home repo>: preserved - companion cleanup failed` to retain the home checkout for a fresh-session retry via /skill:gauntlet-resume. Delete a branch only after successful removal of its worktree. Run prune only for successful owned built-in removal, not after a wrapper. Report each repo's actual removed, preserved or failed state.
84
+ Clean companions in declared order, then home. Report a refusal as that leg's `failed` line with its observed tree/ref state, preserve anything remaining, and continue the remaining cleanup attempts and report lines. After squash, stop only the refused companion's cleanup and attempt every remaining companion's recorded contract from its own primary; on any companion cleanup failure, skip home's cleanup and report `<home repo>: preserved - companion cleanup failed` to retain the home checkout for a fresh-session retry via /skill:gauntlet-resume. Delete a branch only after successful removal of its worktree. Run prune only for successful owned built-in removal, not after a wrapper. Report each repo's actual removed, preserved or failed state.
75
85
 
76
86
  Remove receipts only after home delivery and all required cleanup succeed, and report that removal in one explicit line (`Home delivery and required cleanup succeeded; receipts removed`). Receipts live in the home primary's git dir, so worktree removal never touches them; when any required cleanup failed, report `receipts retained - required cleanup failed` and leave every receipt in place for the retry. PR/draft success has no cleanup requirement and preserves every worktree, so its receipts are removed right after the home PR lands. Keep retains receipts for later validation. Mark ship complete only after the chosen action succeeds for every member; never mark discard as shipped.
@@ -147,7 +147,7 @@ owning skill **without** its reset-bearing entry:
147
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) |
148
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 |
149
149
  | plan with task engine | writing-plans body | skip its `start plan` call (already in_progress) |
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 against the unmigrated ledger, clean-tree migration, final allowance validation, 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 allowance boundary in reconstruction step 4 before continuation and preserving iterations/attempts/retry decisions; defer migration through recovery stops; 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 against the unmigrated ledger, clean-tree migration, final allowance validation, 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 allowance boundary in reconstruction step 4 before continuation and preserving iterations/attempts/retry decisions; defer migration through missing-history or dirty-tree stops; reuse the existing ledger |
151
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 |
152
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 against the unmigrated ledger, clean-tree migration, final allowance validation and one ledger-path refresh through the shared allowance boundary in `reference/reconstruction.md` "Spec with ledger" step 4; legacy briefs without tasks omit init, not recovery/migration; render allowance 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 |
153
153
  | verify without `Ledger:` | verification-before-completion | full conformance gate; nothing carried over |
@@ -106,7 +106,7 @@ 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. 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.
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. For a brief's `worktree: missing`, apply [Locate a leg tree](../../brainstorming/reference/legs.md#locate-a-leg-tree) using the declared primary and recorded branch. Use a found tree as the companion worktree for the remaining admission checks. On lookup failure, report that rule's repo, branch and reason; state that an empty lookup authorizes no recreation, receipt or approval, retaining live receipt admission below for a missing delivered tree. Keep an explicit brief `worktree:` path as recorded and validate it without replacing it from the lookup. 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
 
@@ -94,12 +94,12 @@ After confirmation:
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
95
  3. Admit exactly one positive safe-integer `cap:` or `allowance:` header; both or neither is `ledger header malformed: <observed header lines>`, requiring human repair by hand. Call `plan_check({ planPath: <absolute ledger path> })` with legacy-compatible admission. 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
96
  4. **Shared allowance boundary (every ledger restore, before phase continuation).** Read `/skill:loop-implementation`. Skip Entry step 1's allowance seeding; restore base, verification, iterations, row attempts and decisions from the ledger without reseeding. Resolve `gauntlet_setting({ key: "loopEngine" })` exactly once at the driver's authorized-restore grant boundary and retain `escalateAfter` in driver memory for this run; share this read with step 4.2, never refresh it inside the loop. On an unavailable tool, stop before any dispatch or write with `cannot resolve escalation threshold: settings tool unavailable (loopEngine.escalateAfter)`. Apply the following order on bare-worktree and brief routes alike:
97
- 1. Apply pending recovery below against the unmigrated ledger, including home returns whose child commit removed the tuple. Validate the original one-commit `<pre-dispatch HEAD>..HEAD` range against its unchanged before-image. For companions, retain unchanged home HEAD and admit the expected iterations-bump-plus-tuple dirt. On unrecoverable attribution or before-image, stop before refresh. Resolve ambiguous-history admission before tracker calls as required below. Apply the driver's ownership-fenced interrupted recovery before migration; migration changes neither admission ranges nor the home HEAD used for recovery.
98
- 2. Migrate only an admitted, clean, tuple-free ledger with no retained recovery stop. With `cap:` and no `allowance:`, reuse the single restore-boundary settings read and replace the cap line with `allowance: <maxIterationsPerRow>`. Commit only that header replacement as parent `loop: migrate allowance`; preserve iterations, every attempts cell and all decisions. With an existing allowance, use it without allowance resolution or a migration commit; the restore read supplies `escalateAfter` only. Defer migration through any retained recovery stop or dirty tree; after authorized recovery reaches a clean tuple-free tree, migrate before the next dispatch or verification.
99
- 3. Require `allowance:` and no `cap:` before continuation, including for all-closed ledgers; otherwise stop with `ledger has no allowance: line - resume through /skill:gauntlet-resume`. For a retained recovery stop or unresolved dirty tree, defer this final validation with migration and project the unmigrated ledger solely to report the stop.
100
- 4. Call `plan_tracker({ action: "refresh", path: <absolute ledger path> })` exactly once after phase restoration, recovery and eligible migration/final validation, 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.
101
- Render the allowance header, rows, iterations, attempts, effective allowances and all decisions; distinguish the latest operational `row <n> ...` decision from the last physical history line. Compute each effective allowance as the header plus one per matching retry decision; ignore the retry's audit ceiling. Keep `cap +N` history as inert text and restore no funded rounds. For a recovered pending tuple with a recoverable before-image, apply the driver's ## Interrupted recovery below allowance before continuation; require exclusive checkout provenance and confirmed owned-job exits before any reset. Report unresolved cleanup or ownership with the driver's recovery-incomplete header, saved unresolved-row counts and discard-authorization menu, preserving changes and making no redispatch. Keep unrecoverable before-image and ambiguous-history stops. Resume the original phase only after this boundary: implement at `Before each dispatch`; verify/ship at `After the loop` step 1.
102
- 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. A migrated unresolved row at or above its effective allowance stops under rule 2 without an attempt; keep an allowance-stopped row `failed`. 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.
97
+ 1. Apply pending recovery below against the unmigrated ledger, including home returns whose child commit removed the tuple. Validate the original one-commit `<pre-dispatch HEAD>..HEAD` range against its unchanged before-image. For companions, retain unchanged home HEAD and admit the expected iterations-bump-plus-tuple dirt. With a recoverable on-disk tuple and before-image, treat wrong attribution, unexpected home dirt and home movement as interrupted boundaries; reset the selected companion and home through common recovery before the home-only repair. Stop before refresh only when the tuple or before-image is unrecoverable. Resolve ambiguous-history admission before tracker calls as required below. Apply the driver's unconditional interrupted recovery before migration; migration changes neither admission ranges nor the home HEAD used for recovery.
98
+ 2. Migrate only a clean, tuple-free ledger after admission or completed interrupted recovery. With `cap:` and no `allowance:`, reuse the single restore-boundary settings read and replace the cap line with `allowance: <maxIterationsPerRow>`. Commit only that header replacement as parent `loop: migrate allowance`; preserve iterations, every attempts cell and all decisions. With an existing allowance, use it without allowance resolution or a migration commit; the restore read supplies `escalateAfter` only. Defer migration through a missing-history stop or the dirty-tree stop; after recovery reaches a clean, tuple-free tree, migrate before the next dispatch or verification.
99
+ 3. Require `allowance:` and no `cap:` immediately after step 4.2 (including right after committing `loop: migrate allowance`) and before the single `plan_tracker refresh` in step 4.4, including for all-closed ledgers; otherwise stop with `ledger has no allowance: line - resume through /skill:gauntlet-resume`, and state this post-migration validation step explicitly on every non-deferred route. For a missing-history stop or unresolved dirty tree, defer this final validation with migration and project the unmigrated ledger solely to report the stop.
100
+ 4. Call `plan_tracker({ action: "refresh", path: <absolute ledger path> })` exactly once for the restore after phase restoration, recovery, eligible `loop: migrate allowance` commit and step 4.3's post-migration `allowance:`/`no cap:` validation, 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.
101
+ Render the allowance header, rows, iterations, attempts, effective allowances and all decisions; distinguish the latest operational `row <n> ...` decision from the last physical history line. Compute each effective allowance as the header plus one per matching retry decision; ignore the retry's audit ceiling. Keep `cap +N` history as inert text and restore no funded rounds. For an interrupted return with a recovered pending tuple and before-image, apply the driver's [## Interrupted recovery](../../loop-implementation/reference/interrupted-recovery.md) without a human turn. Preserve the already-consumed iteration, count the failed attempt once, and return to the ordered table after repair; check allowance only there. Keep unrecoverable before-image and ambiguous-history stops. Resume the original phase only after this boundary: implement at `Before each dispatch`; verify/ship at `After the loop` step 1.
102
+ 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. A migrated unresolved row at or above its effective allowance stops under rule 2 without an attempt; keep an allowance-stopped row `failed`. Only at a missing-history stop, render a row whose `pending:` tuple stays on disk as `row <n> in_progress (pending tuple restored)`. Never reset counters or reseed a validated seed.
103
103
 
104
104
  ### Pending recovery
105
105
 
@@ -111,18 +111,18 @@ Treat ordinary home admission as a refresh with no parent commit or ledger mutat
111
111
 
112
112
  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.
113
113
 
114
- 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.
114
+ 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. List the commits in `<pre-dispatch HEAD>..HEAD` and every dirty path before accepting an answer. State explicitly: answering `interrupted` discards those commits and dirty files through `reset --hard <pre-dispatch HEAD>` and `clean -fd`. Keep ledger bytes, counters and task list unchanged while awaiting the answer: no refresh and no target/tuple restoration.
115
115
 
116
116
  | Confirmed admission state | Action |
117
117
  |---|---|
118
118
  | Confirmed settled | Preserve the current ledger and continue normal restore; require fresh verification/conformance, not historical gate credit. |
119
- | Confirmed interrupted | Validate the entire `<pre-dispatch HEAD>..HEAD` range, never just `HEAD^..HEAD`, through the home row below. Use the recovered tuple and before-image without another bump. Confirmation that admission was interrupted proves no ownership of later writes: apply the driver's ## Interrupted recovery only with retained exclusive checkout/write provenance and owned-job exit evidence. Missing evidence preserves child and unrelated changes at recovery incomplete; project saved row cells without overwriting the ledger. A completed recovery writes the parent repair with iterations at the recovered consumed count. |
119
+ | Confirmed interrupted | Validate the entire `<pre-dispatch HEAD>..HEAD` range, never just `HEAD^..HEAD`, through the home row below. Use the recovered tuple and before-image without another bump. Apply the driver's unconditional interrupted recovery to a rejected boundary, including later writes; write the failed attempt from the saved ledger with iterations at the recovered consumed count, refresh and return to the ordered table. Use the disclosed `interrupted` answer as authorization for that recovery. |
120
120
  | Still unknown | Stop without mutation; ask for the missing admission evidence, never turn uncertainty into a discard/reset decision. |
121
121
 
122
122
  | Tuple target | Recovery |
123
123
  |---|---|
124
- | 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. Route zero new commits, multiple commits, dirty or non-DONE returns through the driver's ## Interrupted recovery against the tuple HEAD and its ledger before-image. Require exclusive checkout provenance and verified process identity/exit before reset; after clean/zero-commit observations write the repair with the already-consumed iteration, clear pending and continue at Before each dispatch. Preserve every change at recovery incomplete when ownership or cleanup is unresolved. Unrelated movement, attribution mismatch or an unrecoverable before-image stops without redispatch or double counting. |
125
- | 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, then validate its result. Record that leg's admitted rows, decisions or seeded state and SHA, removing the tuple in the home-ledger commit; never rerun the recovered row or its admitted extras. Route dirty, zero/multiple-commit or non-DONE boundaries through that reference's ownership-fenced interrupted recovery, using the companion tuple HEAD and saved home ledger; preserve state on unrelated movement, attribution mismatch, unrecoverable before-image or unresolved ownership/cleanup; route post-boundary result-validation misses through ordinary `loop: repair row <n>` or seed `loop: repair seed` repair in that protocol, clear `pending:` and preserve the consumed iteration. |
124
+ | 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, with no second iteration bump or repeated attempt increment. Clear the tuple through the admitted close or ordinary-miss repair. Route zero new commits, multiple commits, dirty or non-DONE returns through the driver's `## Interrupted recovery` against the tuple HEAD and its ledger before-image. Use the driver's job checks and reset/clean procedure without a provenance or process-exit gate; write the repair with the already-consumed iteration, clear pending and continue at Before each dispatch. Route reset/repair-write failures through the driver's counted failure pass, never dispatching from the wrong HEAD. With a recoverable tuple and before-image, route wrong attribution through the driver's `## Interrupted recovery` without a human turn. Stop only for an unrecoverable tuple or before-image, without redispatch or double counting. |
125
+ | 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, then validate its result. Record that leg's admitted rows, decisions or seeded state and SHA, removing the tuple in the home-ledger commit; never rerun the recovered row or its admitted extras. Route dirty, zero/multiple-commit or non-DONE boundaries through that reference's unconditional interrupted recovery, using the companion tuple HEAD and saved home ledger; reset the companion to the tuple HEAD and home to the saved home HEAD; commit the repair only in home. With a recoverable tuple and before-image, route wrong attribution, unexpected home dirt and home movement through that same interrupted recovery. Preserve state only on an unrecoverable tuple or before-image; route post-boundary result-validation misses through ordinary `loop: repair row <n>` or seed `loop: repair seed` repair in that protocol, clear `pending:` and preserve the consumed iteration. |
126
126
 
127
127
  ## Spec with plan
128
128
 
@@ -23,7 +23,7 @@ At seed and at an authorized restore, before entering the dispatch loop, read th
23
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 at step 4 instead of the home-only skeleton below, using step 4's resolved allowance seed value. 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.
24
24
 
25
25
  3. Call `phase_tracker({ action: "skip", phase: "plan", reason: "loop engine" })`.
26
- 4. Require a clean named-branch implementation worktree. Read the literal `run allowance: <n>` line from the invoking approval turn: it carries the approved `; allowance N` (or comma) suffix. Use that value over step 1's setting; with no carrier use `maxIterationsPerRow`. Print `allowance: <n> (reply)` or `allowance: <n> (setting)` with the seeded header. Ignore the carrier once a ledger exists; resume uses its header only. Write `<resolved plan dir>/<spec stem>-ledger.md`. Use this grammar with literal values, not placeholders:
26
+ 4. Require a clean named-branch implementation worktree. With dirty status and no `pending:` tuple, take ## Human stop before writing the ledger. Read the literal `run allowance: <n>` line from the invoking approval turn: it carries the approved `; allowance N` (or comma) suffix. Use that value over step 1's setting; with no carrier use `maxIterationsPerRow`. Print `allowance: <n> (reply)` or `allowance: <n> (setting)` with the seeded header. Ignore the carrier once a ledger exists; resume uses its header only. Write `<resolved plan dir>/<spec stem>-ledger.md`. Use this grammar with literal values, not placeholders:
27
27
 
28
28
  ```markdown
29
29
  # Ledger - loop engine
@@ -48,7 +48,7 @@ For resume, use the admitted ledger, its base and verification command, and dura
48
48
 
49
49
  ## Driver holds
50
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, `log --format=%s <base>..HEAD` for repair counts), retained dispatch/write provenance, the child's jobs file, OS process start identity and command, `ps -o pgid= -p <pid>`, `kill`, skill resources at their absolute paths and the overrides file. Keep rows by status, iterations, allowance, the last decision, the decoded amendment grant and each leg's checkout path for dispatch, handoff and stops. Use Entry's captured grant, row dispositions and membership throughout the loop.
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, `log --format=%s <base>..HEAD` for repair counts), the child's jobs file, OS process start identity and command, `ps -o pgid= -p <pid>`, `kill`, skill resources at their absolute paths and the overrides file. Keep rows by status, iterations, allowance, the last decision, the decoded amendment grant and each leg's checkout path for dispatch, handoff and stops. Use Entry's captured grant, row dispositions and membership throughout the loop.
52
52
 
53
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. Inside the implement loop, end a turn only with a stop header from ## Human stop; follow every intermediate report with the next ordered-table action in the same turn. 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.
54
54
 
@@ -56,8 +56,6 @@ Never read the spec, source files, test output or logs inside the implement loop
56
56
 
57
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.
58
58
 
59
- Read [action-spend durability](reference/action-spend.md) in full now; carry retained repair accounting into this dispatch, including seed and companions.
60
-
61
59
  Read the ledger and require its `checks:` line per ## Gate set.
62
60
 
63
61
  Read the ledger and require `allowance:` and no `cap:` before the ordered table, including for seed and completed ledgers; otherwise stop with `ledger has no allowance: line - resume through /skill:gauntlet-resume`. Keep `iterations:` as a dispatch counter only; it bounds nothing. Count each row's empty child commits and validation misses only after the latest of `loop: retry row <n>` for that row, `loop: amend`, or any `loop: cut row <n>`; an admitted amendment starts new windows for every row because it changed what rows are measured against. Raising allowance resets neither window. Recover both windows from branch history on resume. Preserve every row's attempts and spent escalation. Before the ordered table, route each admitted failed target through ## Unreachable returns once at admission (including companions), or on resume when admitted but not yet routed; follow that reference's answered-stop rule after human decisions. Apply this ordered table, starting here after each return or human decision:
@@ -83,7 +81,7 @@ With the resolved model, append `row <n> escalated | implModel round | allowed a
83
81
 
84
82
  ## Dispatch
85
83
 
86
- For home dispatch, record `HEAD_BEFORE`, save the ledger before the iterations bump and tuple write, and retain the current `iterations:` count as i. Retain dispatch/write provenance and background-launch records for ## Interrupted recovery; a clean boundary and one child alone never establish exclusive ownership. 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:
84
+ 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:
87
85
 
88
86
  ```text
89
87
  subagent({ agent: "loop-implementer", context: "fresh", async: false,
@@ -95,15 +93,13 @@ subagent({ agent: "loop-implementer", context: "fresh", async: false,
95
93
 
96
94
  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`.
97
95
 
98
- 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. Route a dispatch error or non-DONE return, including a silence kill, through ## Interrupted recovery. An async handle still stops; never poll or join it. Redispatch only through the ordered table after completed recovery.
96
+ 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. Route a dispatch error (including `Request aborted` or any tool-reported `error: <text>`, even with an empty return file) or non-DONE return, including a silence kill, through ## Interrupted recovery. An async handle still stops; never poll or join it. Redispatch only through the ordered table after completed recovery.
99
97
 
100
98
  ## Validate the return
101
99
 
102
- Read [action-spend durability](reference/action-spend.md) in full now; preserve action records through admission and every validation-miss repair below.
103
-
104
100
  For home returns, apply the following boundary and table. Never project terminal child results before clean/exactly-one-commit admission.
105
- 1. Require a DONE return, empty `git -C "<worktree>" status --porcelain` and exactly 1 from `git -C "<worktree>" rev-list HEAD_BEFORE..HEAD --count`. Route dispatch errors, non-DONE, killed, dirty and zero/multiple-commit returns through ## Interrupted recovery, not result admission. Read the ledger from HEAD only after this boundary passes.
106
- 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 allowance. Preserve row identifiers and prior decisions.
101
+ 1. Require a DONE return, empty `git -C "<worktree>" status --porcelain` and exactly 1 from `git -C "<worktree>" rev-list HEAD_BEFORE..HEAD --count`. 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. Route dispatch errors, non-DONE, killed, dirty, zero/multiple-commit and wrong-attribution returns through ## Interrupted recovery, not result admission. Read the ledger from HEAD only after this boundary passes.
102
+ 2. Validate by dispatched `target`, not iteration number, against the saved copy using this table. Admit only `iterations` +1 and removal of the dispatched `pending:` line; reject every other header change, including allowance. Preserve row identifiers and prior decisions.
107
103
 
108
104
  | Target | Required changes | Miss |
109
105
  |---|---|---|
@@ -129,11 +125,13 @@ Read [interrupted recovery](reference/interrupted-recovery.md) in full now; appl
129
125
 
130
126
  ## Human stop
131
127
 
132
- 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.
128
+ Read and apply [menu-layout](../brainstorming/reference/menu-layout.md). Start the message with `gauntlet: question` at every human stop, including discard authorization for a dirty tree with no dispatch pending. 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.
133
129
 
134
- Implement-phase stops only: leave implement active and use the row 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/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. At every human stop, including allowance, missing-model, dirty-tree, commit-boundary, interrupted-dispatch and exit-verification stops, list every `open` or `failed` row after the header as `row <n>: <attempts> of <effective allowance>`, then print `Preserve every row's attempts.` Compute each denominator from the ledger using Before each dispatch; keep retry increments in `## Decisions`, never a new table column. Use restored pre-dispatch row cells at rejected-return stops, not unadmitted child results. With no open or failed rows, omit row lines but retain the preservation sentence. Name `escalated round spent` when applicable; omit round history and reasoning traces.
130
+ Implement-phase stops only: leave implement active and use the row 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/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. At every human stop, including allowance, missing-model, dirty-tree and exit-verification stops, list every `open` or `failed` row after the header as `row <n>: <attempts> of <effective allowance>`, then print `Preserve every row's attempts.` Compute each denominator from the ledger using Before each dispatch; keep retry increments in `## Decisions`, never a new table column. Render repaired row cells after recovery, never unadmitted child results. With no open or failed rows, omit row lines but retain the preservation sentence. Name `escalated round spent` when applicable; omit round history and reasoning traces.
135
131
 
136
- For stops not handled by ## Unreachable returns: Offer retry and `rows +N` only at row stops (allowance or missing-model) or seed exhaustion, alongside Amend and Stop. The recovery-incomplete stop keeps discard authorization only, never budget offers; the verify-step-1 verification-failure stop keeps amend/stop only. A budget increase never bypasses those gates.
132
+ For stops not handled by ## Unreachable returns: Offer retry and `rows +N` only at row stops (allowance or missing-model) or seed exhaustion, alongside Amend and Stop. The dirty-tree stop with no dispatch pending keeps discard authorization only, never budget offers; the verify-step-1 verification-failure stop keeps amend/stop only. A budget increase never bypasses those gates.
133
+
134
+ For non-empty `status --porcelain` with no `pending:` tuple at entry step 4 or on resume, render `Stopped: dirty tree with no dispatch pending`, list the dirty paths, and offer `discard` or Stop only, never budget offers. Before typed discard, make no tree or ledger writes, reset, clean or dispatch. On a typed `discard` run `git -C "<checkout>" reset --hard HEAD` and `git -C "<checkout>" clean -fd`, then resume the sequence the stop suspended: at fresh entry continue Entry step 4's ledger write and step 5 (`plan_check`, `loop: seed ledger`, implement start, refresh); on a restore finish eligible migration, final allowance validation and the refresh, then continue at `## Before each dispatch` in implement or `## After the loop` step 1 in verify. Never jump to the ordered table before a ledger is seeded and admitted. Any other reply preserves the tree and keeps the stop open.
137
135
 
138
136
  | Human choice | Durable action |
139
137
  |---|---|
@@ -144,7 +142,7 @@ For stops not handled by ## Unreachable returns: Offer retry and `rows +N` only
144
142
 
145
143
  Serialize the bare decision as `rows +50 |` with an empty words cell. Raising allowance resets neither window (empty-child or validation-miss); exclude `loop: raise allowance` from child-commit counting. Use Before each dispatch's window rule for retry and admitted amendments.
146
144
 
147
- Recover interrupted returns through ## Interrupted recovery before dispatch. At recovery incomplete, ask for explicit discard authorization naming the unresolved ownership or cleanup; a budget reply authorizes no discard. Preserve spent escalation and the consumed dispatch count through recovery: iterations = restored HEAD's value +1, before the next normal bump. Recover from disk/branch, never repeat iteration 0.
145
+ Recover interrupted returns through ## Interrupted recovery before dispatch, without a human turn. Preserve spent escalation and the consumed dispatch count through recovery: iterations = restored HEAD's value +1, before the next normal bump. Recover from disk/branch, never repeat iteration 0.
148
146
 
149
147
  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 row dispositions, 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.
150
148
 
@@ -152,6 +150,8 @@ Retry, cut, amend, raise-allowance and escalate commits never clear the tuple. F
152
150
 
153
151
  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, `rows +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.
154
152
 
153
+ Never invent a stop, a menu, an option or an approval the spec's gate did not ask for, and never write a ruling on what the spec authorizes into a task's `hint:` field.
154
+
155
155
  ## Gate set
156
156
 
157
157
  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:`.
@@ -171,13 +171,13 @@ For coordinated runs, route each verification and review below to every leg with
171
171
  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.
172
172
  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.
173
173
  Count `repairs` as home `loop: repair verification` commits since ledger base, plus one for a `pending: verify` tuple with no admitted repair commit. Use the shared ledger allowance, with no per-row retry increments. Recover this count from branch history and disk on every resume; match marker bodies to pending tuples to avoid counting one dispatch twice. Recover an outstanding tuple before any new gate run or dispatch, including the last reserved repair at allowance.
174
- On failure automatically repair while `repairs < allowance` under approval option 4 and option 5 alike; never consult amend permission or gate on iterations. Keep verify active and implement complete. Resolve `gauntlet_setting({ key: "escalationLoop" })`; require its non-empty `implModel`, including the resolver's main-loop fallback. Missing settings/model stops with `Problem: escalationLoop.implModel unavailable`, without a bump or marker. Save the home ledger and home/failing-leg HEADs, retain dispatch/write and background-launch provenance, then bump iterations once and write `pending: verify | <repo> | <HEAD>` on disk before dispatch, using the failing leg's identity (single-leg `home`) and HEAD. Treat only that bump/tuple as expected home dirt. Dispatch exactly one `implementer` with `model: <implModel>`, `context: "fresh"`, `async: false`, failing checkout cwd and Rules, absolute spec path, failing command, checkout, exit code and log path, never pasted output. Pass the exact pending tuple and consumed `iteration:` for the first two commit-body lines, plus the failing leg's base and pre-bump iteration for jobs-file identity. Require retained launch/no-launch evidence and the jobs records in ## Interrupted recovery. Apply [action-spend durability](reference/action-spend.md) to this repair and inject the persona's step-5 action authorization/accounting contract, including pre-launch reservations, without its row mutation protocol; require action-spend records after tuple/iteration in the repair commit body. Include this blocking-call contract in the repair task: bound every blocking command with `timeout -k 30 <n>`, n <= 600; background and poll longer work. Read [loop-implementer's Evidence command](../../agents/loop-implementer.md#evidence-command) and copy its first three paragraphs verbatim into that task, omitting its row/seed ledger protocol. The repair child reads the log to derive the files to touch; for a stale selector restore the test or its name, never ledger evidence.
175
- Require DONE, a clean failing checkout and exactly one commit after HEAD_BEFORE, matching the task's tuple/iteration attribution. Require all ledger rows unchanged, preserving attempts, mapping, allowance and prior decisions. The home child's sole commit includes the already-bumped ledger with pending retained; a companion child commits its leg only, leaving home HEAD and expected dirt unchanged. Remove `pending:` only in the parent repair marker: commit `loop: repair verification` in home with the consumed iteration and exact tuple in its body, recording the admitted child SHA. Refresh after admission. On killed, error, non-DONE, dirty, zero/multiple-commit or invalid repair returns, apply ## Interrupted recovery steps 1-3 to the failing checkout, not its numbered-row/seed budget or step 4. Preserve the saved row cells and already-consumed iteration; after owned jobs exit and the boundary is clean, clear pending in an empty `loop: repair verification` marker (no repair code), with tuple, iteration and interruption reason in its body. For companions require unchanged home HEAD and expected-only dirt, and write the marker only in home. On missing provenance, ambiguous attribution/before-image or failed cleanup, retain state at the recovery-incomplete stop; the pending reservation remains consumed. On resume, admit a matching clean single repair commit or recover the interrupted return by this same path without another bump; an already admitted matching marker needs no second marker.
174
+ On failure automatically repair while `repairs < allowance` under approval option 4 and option 5 alike; never consult amend permission or gate on iterations. Keep verify active and implement complete. Resolve `gauntlet_setting({ key: "escalationLoop" })`; require its non-empty `implModel`, including the resolver's main-loop fallback. Missing settings/model stops with `Problem: escalationLoop.implModel unavailable`, without a bump or marker. Save the home ledger and home/failing-leg HEADs, then bump iterations once and write `pending: verify | <repo> | <HEAD>` on disk before dispatch, using the failing leg's identity (single-leg `home`) and HEAD. Treat only that bump/tuple as expected home dirt. Dispatch exactly one `implementer` with `model: <implModel>`, `context: "fresh"`, `async: false`, failing checkout cwd and Rules, absolute spec path, failing command, checkout, exit code and log path, never pasted output. Pass the exact pending tuple and consumed `iteration:` for the first two commit-body lines, plus the failing leg's base and pre-bump iteration for jobs-file identity. Inject the persona's step-5 action authorization without its row mutation protocol. Include this blocking-call contract in the repair task: bound every blocking command with `timeout -k 30 <n>`, n <= 600; background and poll longer work. Read [loop-implementer's Evidence command](../../agents/loop-implementer.md#evidence-command) and copy its first three paragraphs verbatim into that task, omitting its row/seed ledger protocol. The repair child reads the log to derive the files to touch; for a stale selector restore the test or its name, never ledger evidence.
175
+ Require DONE, a clean failing checkout and exactly one commit after HEAD_BEFORE, matching the task's tuple/iteration attribution. Require all ledger rows unchanged, preserving attempts, mapping, allowance and prior decisions. The home child's sole commit includes the already-bumped ledger with pending retained; a companion child commits its leg only, leaving home HEAD and expected dirt unchanged. Remove `pending:` only in the parent repair marker: commit `loop: repair verification` in home with the consumed iteration and exact tuple in its body, recording the admitted child SHA. Refresh after admission. On killed, error, non-DONE, dirty, zero/multiple-commit, wrong-attribution or invalid repair returns, read `${TMPDIR:-/tmp}/loop-<failing leg's base SHA>-<pre-bump iteration>.jobs` using the repair task's identity, not home's base, and apply ## Interrupted recovery steps 1-2 to the failing checkout at its saved HEAD. For a companion also reset home to the saved home HEAD with `reset --hard` and `clean -fd`. Write exactly one empty `loop: repair verification` marker in home (no repair code): stage only the ledger with saved row cells, the already-consumed iteration and no `pending:`, and put tuple, iteration and interruption reason in the body, with no second bump. A non-empty `status --porcelain` after reset blocks neither the marker nor the rerun. Apply interrupted recovery's failure pass with the verification repair count to a failed reset of either checkout or an unwritten marker; require the marker's parent to be the saved home HEAD. On resume, admit a matching clean single repair commit or recover the interrupted return by this same path without another bump; an already admitted matching marker needs no second marker.
176
176
  Rerun the failing checkout's gate pairs once using ## Gate set's log redirection and fail-fast rule after each admitted or recovered repair. After that rerun passes, run the original fail-fast run's still-unexecuted pairs from other checkouts in ledger order before recording verified HEAD. On resume run the complete gate set in a fresh session LOG_DIR. A new failure in any leg returns to the repair-count check; do not reopen rows or reset the count. Never spend verify-phase credits. On failure at `repairs >= allowance`, render `Stopped: verification failed with every row closed` with `repairs: <k> of <allowance>` and `Problem:` naming `gate <i> exit <code> <log path>` and quoting at most the last 20 lines 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 `rows +N`. Use the same restricted menu for missing capabilities. On success record verified HEAD and clean status for every leg.
177
177
  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`.
178
178
  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.
179
179
  When the conformance fix-round cap blocks (`<used> fix round(s) used against a cap of <cap>`) or the reference's step 6 asks at its cap, read `<used>` from that text. Under amend permission with `<used>` below the ledger allowance: when the block is live, call `phase_tracker({ action: "grant_fix_rounds", rounds: <allowance - used>, reason: "<Amend-grant sentence verbatim>" })`, print `funded <allowance - used> conformance rounds under the grant`, and continue the fix loop; when `closureReview.enforce` is false, continue without a call. With `<used>` at or above the allowance, an error reply, or no amend permission, take the reference's step-6 stop. Never call the tool as a probe or store a grant counter; never count rounds yourself. The next block's `<used>` includes granted rounds, so a second block at the allowance stops; a resumed run with unspent credits continues without a block or another grant. Leave the cap and settings unchanged.
180
- 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.
180
+ On an approved re-bound (`reopened by amendment`), use the held grant. Without amend permission, refresh and stop with `Stopped: row <n> reopened by amendment during verify`; offer authorize the row's return to ledger implementation or stop. Under amend permission, continue without a second authorization. For the granted continuation or the option-4 approval, apply the normal Before each dispatch boundaries, including exhausted-row rule 2, 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. During verify, dispatch the reopened row as a one-task `tasks` call carrying the same `## Dispatch` fields (agent, context fresh, async false, cwd, output, outputMode, acceptance, task text, and `model` only on an escalated round), with no `worktree:`; the closure guard counts it as one fix round against the conformance cap funded above. Keep the tuple write, iteration bump, `## Validate the return` and interrupted recovery exactly as for any dispatch. Keep completion blocked until closure; never substitute a tracker write for the ledger return.
181
181
  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.
182
182
  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.
183
183
 
@@ -14,7 +14,7 @@ Use the same allowance seed value and source echo as the home driver's Entry ste
14
14
 
15
15
  ## Resume
16
16
 
17
- Use the held membership and checkout paths captured by the driver's Entry at seed or authorized restore. Route `pending: verify` through the driver's After the loop step 1 before the row/seed admission below. 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. Apply the home-ledger commit without another attempt or iteration bump, clear pending and retain prior decisions. Route interrupted boundaries (dirty, zero/multiple commits, dispatch error or non-DONE) through ## Companion return validation's ownership-fenced recovery; keep unrelated movement and attribution mismatch as state-preserving stops; route post-boundary result-validation misses through ordinary `loop: repair row <n>` or seed `loop: repair seed` repair below, clear `pending:` and preserve the consumed iteration. 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. Route `pending: verify` through the driver's After the loop step 1 before the row/seed admission below. 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. Classify interrupted boundaries before applying clean-return admission checks. For a clean return admit only the known iterations bump and exact pending tuple as home dirt. Route wrong attribution, unexpected home dirt and home movement through common interrupted recovery when the tuple and before-image are recoverable. Reapply companion return validation below only when exactly one new commit after the recorded HEAD matches attribution. Apply the home-ledger commit without another attempt or iteration bump, clear pending and retain prior decisions. Route interrupted boundaries (dirty, zero/multiple commits, dispatch error or non-DONE) through ## Companion return validation's common interrupted recovery; include unrelated movement and attribution mismatch among interrupted boundaries; route post-boundary result-validation misses through ordinary `loop: repair row <n>` or seed `loop: repair seed` repair below, clear `pending:` and preserve the consumed iteration. After a successful parent commit no pending tuple remains, so a subsequent resume cannot duplicate the update.
18
18
 
19
19
  ## Targeting and dispatch
20
20
 
@@ -26,13 +26,13 @@ For coordinated dispatch, capture home and selected leg heads and save a pre-dis
26
26
 
27
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 four-column row lines followed by decision lines. For ordinary returns require the target (`done` or `failed`, attempts +1) plus zero or more same-leg `open` -> `done` extras with attempts unchanged. Require nonempty bounded evidence and exactly one matching bounded decision for each changed row, target decision first, under the driver's `## Validate the return` table; admit extras beside a failed target without policing worker order or adding a command-format check. For seed require all and only that leg's non-cut rows, at least one with evidence, and one bounded seed decision; admit unchanged open rows with empty evidence. Reject a wrong target, foreign entry, changed cut/done extra, header changes, fabricated counts, malformed evidence or unmatched/duplicate rows or decisions. Validate seed counts against nonempty evidence cells and baseline closures; require zero attempts and set only this leg's seeded value to `yes` after the complete row set validates. Route seed validation misses after boundary admission through the driver's seed repair count: commit `loop: repair seed` in home with the concrete miss in the body, write no returned rows or decisions, clear `pending:`, leave this leg's seeded value `no` and preserve foreign state. Retain consumed iterations and saved allowance; apply the driver's seed count and hint rule to retry this leg below allowance or stop at allowance. A validated seed resets the validation-miss window. Route ordinary validation misses after boundary admission through the driver's ordinary repair: set only the target `failed` with attempts +1 and `iteration <i>: <miss>` evidence, append its repair decision, clear `pending:` and commit `loop: repair row <n>` in home. Preserve every non-target row and prior decision from the saved copy, consumed iterations and saved allowance; count the miss in the existing two-miss window.
28
28
 
29
- After validation write every admitted row and append every validated decision to the home ledger, record companion SHA in evidence, and remove `pending:` in one home-ledger commit. Use the target's decision as the next dispatch's `previous decision:`, never an extra's. 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. For rejected results apply the post-boundary repair above. For interrupted boundaries, apply the driver's ## Interrupted recovery immediately and on resume: require unchanged home HEAD and expected-only bump/tuple dirt, exclusive companion checkout/write provenance, accounted-for writers and matching jobs-file process identity before signaling or reset. Reset only the selected companion to its `HEAD_BEFORE`, using its base/iteration jobs file; require confirmed job exits and clean/zero-commit observations. Restore the saved home ledger with consumed iterations, preserve foreign rows, mappings, bases and seeded flags, clear pending and commit `loop: repair row <n>` or `loop: repair seed` only in home. Increment only the numbered target's attempts once; seed leaves rows unchanged. Refresh and return to the driver's ordered table or seed count without double counting. Missing provenance, missing before-image, unexpected home changes, unresolved cleanup or ambiguous attribution stops with state preserved, not a reset based on commit timing. Recover from boundary evidence, never trusted reply text.
29
+ After validation write every admitted row and append every validated decision to the home ledger, record companion SHA in evidence, and remove `pending:` in one home-ledger commit. Use the target's decision as the next dispatch's `previous decision:`, never an extra's. 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. For rejected results apply the post-boundary repair above. For interrupted boundaries, apply the [common interrupted recovery](interrupted-recovery.md) three-step rule and failure pass immediately and on resume, using the selected companion's base and pre-bump iteration jobs file. Reset and clean the selected companion to its `HEAD_BEFORE` and home to the saved home HEAD; write the repair commit only in home. For the failure pass use the companion HEAD for the reset check and the saved home HEAD for the ledger-only commit boundary. Restore the saved home ledger with consumed iterations, preserve foreign rows, mappings, bases and seeded flags, clear pending and commit `loop: repair row <n>` or `loop: repair seed`. Increment only the numbered target's attempts once; seed leaves rows unchanged. Refresh and return to the driver's ordered table or seed count without double counting. Recover from boundary evidence, never trusted reply text.
30
30
 
31
31
  For coordinated home returns apply it only to home entries/seeded state, preserving foreign entries, mappings and bases.
32
32
 
33
33
  ### Companion commit admission
34
34
 
35
- Require the unchanged home HEAD and expected-only home dirt boundary above, then run this read-only admission recipe on both immediate returns and pending recovery. Set `CHECKOUT` to the companion root, `PENDING` to the exact persisted tuple including `pending:`, `ITERATION` to the consumed count and `SAVED_LEDGER` to the durable home ledger after the iterations bump and pending write, including on recovery. Use the pre-dispatch snapshot only for the expected-dirt comparison. Classify boundary failures before running this recipe: route dirty/zero/multiple-commit interrupted returns through the ownership-fenced recovery above; preserve pending and stop on unrelated movement or attribution mismatch. On a seed validation miss after the boundary passes apply the seed repair above. On an ordinary validation miss after the boundary passes apply ordinary repair above, not the boundary stop. On success use the emitted object for the single parent ledger commit described above; never treat it as permission for another dispatch.
35
+ For clean returns require the unchanged home HEAD and expected-only home dirt boundary above, then run this read-only admission recipe on both immediate returns and pending recovery. Set `CHECKOUT` to the companion root, `PENDING` to the exact persisted tuple including `pending:`, `ITERATION` to the consumed count and `SAVED_LEDGER` to the durable home ledger after the iterations bump and pending write, including on recovery. Use the pre-dispatch snapshot only for the expected-dirt comparison. Classify boundary failures before running this recipe: route dirty/zero/multiple-commit returns, unrelated home movement, unexpected home dirt and attribution mismatch through the common interrupted recovery above. Preserve a stop only for an unrecoverable tuple or before-image. On a seed validation miss after the boundary passes apply the seed repair above. On an ordinary validation miss after the boundary passes apply ordinary repair above, not the boundary stop. On success use the emitted object for the single parent ledger commit described above; never treat it as permission for another dispatch.
36
36
 
37
37
  <!-- companion-return-shell -->
38
38
  ```bash
@@ -1,10 +1,11 @@
1
1
  # Interrupted recovery
2
2
 
3
- Treat dispatch error, non-DONE, silence kill, dirty tree and zero/multiple commits as interrupted returns. Use the saved pre-dispatch ledger and checkout `HEAD_BEFORE`; on resume use the tuple's HEAD and its ledger before-image (the saved home HEAD for a companion). Keep an unrecoverable before-image or ambiguous attribution at the recovery stop with state preserved. Apply this procedure under options 4 and 5 alike, only below the numbered target's effective allowance or the seed repair-count allowance; at exhaustion take rule 2 or the seed stop without another dispatch.
3
+ Treat dispatch error, non-DONE, silence kill, dirty tree, zero/multiple commits and wrong attribution as interrupted returns. Use the saved pre-dispatch ledger and checkout `HEAD_BEFORE`; on resume use the tuple's HEAD and its ledger before-image (the saved home HEAD for a companion). Recover without a human turn under approval options 4 and 5 alike. Recovery itself is unconditional; check the numbered target's effective allowance or seed repair count only after committing the repair.
4
4
 
5
- 1. Establish exclusive checkout provenance before destructive recovery. Require retained dispatch and write provenance identifying every changed path and commit as this child's output, with every writer accounted for and quiescent except owned jobs to terminate below. A clean `HEAD_BEFORE`, one dispatched child, path substrings and commit timing prove no ownership. Missing provenance, concurrent or unattributed writes take the recovery-incomplete stop with all changes preserved; do not reset or clean. Read and apply [action-spend durability](action-spend.md) before any restoration or deletion; retain confirmed executions and conservative reservations for the repair body, including seed.
6
- 2. Read `${TMPDIR:-/tmp}/loop-<base SHA>-<iteration i>.jobs`: process lines are `<pid> <process-start-identity> <command>`, with OS-observed start identity captured at launch, not record-write time; preserve action-record lines under action-spend durability. Treat an absent or empty file as no jobs only with retained evidence that the child launched no background work. For each live pid require matching start identity and command plus `ps -o pgid= -p <pid>` equal to pid; a replacement group leader is not owned. Recheck all three immediately before signaling. Unavailable identity or mismatch stops without signaling. For a confirmed owned group send `kill -TERM -- -<pid>`, wait at most 10 s, use `kill -KILL -- -<pid>` for a surviving group after another identity recheck, then require `kill -0 <pid>` to fail. An already exited job needs affirmative exit evidence, not an unavailable identity mistaken for exit. Signal neither the driver's shells nor unrecorded processes. Print `terminated <k> child jobs` when k > 0; delete the jobs file only after every listed job is confirmed exited and action accounting is durable in the admitted result or repair commit body.
7
- 3. After exclusive provenance and job exit are both established and action accounting is retained, use the driver's shell: `git -C "<worktree>" reset --hard HEAD_BEFORE`, then `git -C "<worktree>" clean -fd` (leave ignored files alone). Require empty `git -C "<worktree>" status --porcelain` and 0 from `git -C "<worktree>" rev-list HEAD_BEFORE..HEAD --count`.
8
- 4. Write the ledger from the saved copy with `iterations:` = saved +1 and no `pending:`. For a numbered target set only that row `failed`, attempts = saved attempts +1, evidence `iteration <i>: interrupted - <reason>` plus retained action records; preserve every other row and all prior decisions, including spent escalation. Use `killed after silence`, `dispatch error: <text>`, `dirty tree`, `<k> commits` or `non-DONE` as the concrete reason. Commit `loop: repair row <n>` with retained action records in its body, refresh and return to the ordered table; rule 2 stops a repaired row at allowance. For seed leave every row cell and decision unchanged, commit `loop: repair seed` with `seed interrupted: <reason>` and retained action records in the body, refresh and apply the seed count in ## Validate the return. Never append a fabricated child decision.
5
+ 1. Read `${TMPDIR:-/tmp}/loop-<base SHA>-<iteration i>.jobs`; process lines are `<pid> <process-start-identity> <command>`. An absent or empty jobs file means no jobs to terminate. For each listed live job require matching start identity and command plus PGID equal to the pid; recheck identity, command and group leader before each signal. Send `kill -TERM -- -<pid>`, wait at most 10 s, then send `kill -KILL -- -<pid>` to a surviving matching group. When any identity, command or group-leader check fails, identity is unavailable, or the job is already gone, skip that job and continue recovery. A job still alive after KILL and missing launch history do not block recovery. Signal neither the driver's shells nor unrecorded processes. Print `terminated <k> child jobs` when k > 0, counting observed exits, then delete the jobs file.
6
+ 2. Use the driver's shell: `git -C "<worktree>" reset --hard HEAD_BEFORE`, then `git -C "<worktree>" clean -fd` (leave ignored files alone). Continue even when files remain after reset; the next return is validated as usual.
7
+ 3. Write the ledger from the saved copy with `iterations:` = saved +1 and no `pending:`. For a numbered target set only that row `failed`, attempts = saved attempts +1, evidence `iteration <i>: interrupted - <reason>`; preserve every other row and all prior decisions, including spent escalation. Use `killed after silence`, `dispatch error: <text>` (for any tool-reported `error: <text>` such as `Request aborted`, even when the return file is empty), `dirty tree`, `<k> commits`, `wrong attribution` or `non-DONE` (for a completed non-error return lacking DONE) as the concrete reason. Commit `loop: repair row <n>`, refresh and return to the ordered table in the same turn; rule 2 stops a repaired row at allowance. For seed leave every row cell and decision unchanged, commit `loop: repair seed` with `seed interrupted: <reason>` in the body, refresh and apply the seed count in ## Validate the return. Never append a fabricated child decision.
9
8
 
10
- On unresolved provenance, action accounting or cleanup render `Stopped: iteration <i> recovery incomplete - <what>` with the discard-authorization menu below. Name the observed failure, such as `checkout ownership unproven`, `action execution uncertain`, `background launch history unavailable`, `job <pid> not owned`, `job <pid> still running` or `tree dirty after reset`. Preserve remaining changes, pending identity and consumed iteration; consume no attempt and make no repair commit. Project saved pre-dispatch row cells at this stop without overwriting unadmitted work. For a companion apply [coordinated recovery](coordinated-legs.md#companion-return-validation) to its checkout and write the repair only in home.
9
+ Failure pass: when `git -C "<worktree>" rev-parse HEAD` differs from `HEAD_BEFORE` after step 2, or the step 3 commit is not written, dispatch nothing and run steps 2-3 again from the saved copy. Count each pass once more against the same allowance: the row's effective allowance, seed count or verification repair count, held with the saved copy while no commit can land. End the passes when a ledger-only repair commit lands on `HEAD_BEFORE`, recording the one consumed attempt as step 3 states, or when the held count reaches the allowance; render the existing row, seed or verification exhaustion stop with that count. Stage only the ledger path for the repair; never use any other HEAD as the next dispatch's `HEAD_BEFORE`.
10
+
11
+ For a companion apply [coordinated recovery](coordinated-legs.md#companion-return-validation) to its checkout and write the repair only in home.