pi-gauntlet 7.40.0 → 7.41.0
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.
- package/CHANGELOG.md +17 -0
- package/README.md +16 -4
- package/agents/code-reviewer.md +2 -0
- package/agents/implementer.md +2 -0
- package/agents/loop-implementer.md +10 -0
- package/agents/plan-writer.md +1 -1
- package/agents/spec-reviewer.md +2 -0
- package/bin/gauntlet-telemetry-seal.mjs +18 -3
- package/bin/gauntlet-telemetry-seal.test.mjs +30 -0
- package/extensions/lib/plan-check.test.ts +116 -0
- package/extensions/lib/plan-check.ts +149 -20
- package/extensions/lib/telemetry-record.test.ts +11 -0
- package/extensions/lib/telemetry-record.ts +7 -0
- package/extensions/phase-tracker.test.ts +201 -3
- package/extensions/phase-tracker.ts +77 -9
- package/extensions/verify-before-ship.test.ts +240 -2
- package/extensions/verify-before-ship.ts +180 -25
- package/package.json +2 -2
- package/skills/brainstorming/SKILL.md +2 -2
- package/skills/brainstorming/gatherer.md +20 -7
- package/skills/brainstorming/reference/amendment-surface.md +13 -1
- package/skills/brainstorming/reference/legs.md +187 -0
- package/skills/brainstorming/reference/pr-subject.md +15 -9
- package/skills/brainstorming/reference/spec-finalization.md +16 -2
- package/skills/brainstorming/reference/ticket-acceptance.md +2 -2
- package/skills/finishing-a-development-branch/SKILL.md +21 -22
- package/skills/finishing-a-development-branch/reference/legs.md +76 -0
- package/skills/gauntlet-handoff/SKILL.md +2 -2
- package/skills/gauntlet-resume/SKILL.md +3 -2
- package/skills/gauntlet-resume/reference/brief-contract.md +40 -6
- package/skills/gauntlet-resume/reference/reconstruction.md +9 -7
- package/skills/gauntlet-resume/reference/seed.md +2 -0
- package/skills/loop-implementation/SKILL.md +89 -2
- package/skills/subagent-driven-development/SKILL.md +12 -0
- package/skills/using-git-worktrees/SKILL.md +59 -22
- package/skills/using-git-worktrees/reference/pr-head.md +36 -15
- package/skills/writing-plans/SKILL.md +16 -1
- package/skills/writing-plans/reference/plan-contract.md +9 -1
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Coordinated finish
|
|
2
|
+
|
|
3
|
+
## Activation and authority
|
|
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.
|
|
6
|
+
|
|
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
|
+
|
|
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
|
+
|
|
11
|
+
## Durable receipts
|
|
12
|
+
|
|
13
|
+
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.
|
|
14
|
+
|
|
15
|
+
Write after each delivery attempt that produced a PR or squash commit, including failed post-squash verification:
|
|
16
|
+
|
|
17
|
+
```text
|
|
18
|
+
attempted-head: <full feature SHA attempted>
|
|
19
|
+
delivered: pr <url> <full delivered PR head> | squash <full squash SHA>
|
|
20
|
+
verification: passed | <actual verification failure>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Choose one `delivered:` alternative. Use `verification: passed` only for successful verification; preserve the error otherwise. Retain the selected spec path, recorded commands, membership and accepted task evidence before stripping the plan, and carry the receipt locations into the brief. On fresh-session retry admit a stripped plan only when every companion has a receipt; validate each receipt rather than inferring delivery from missing files. Recover commands from the spec's recorded contract, not the absent plan.
|
|
24
|
+
|
|
25
|
+
Before checkout-based verification and conformance fan-out, validate receipt identity against the selected spec, repo and recorded delivery choice; reconcile it with the selected action before delivery. Malformed, mismatched or unverifiable receipts leave the leg unlanded; stop on an unavailable boundary rather than creating duplicate delivery. Apply these proofs:
|
|
26
|
+
|
|
27
|
+
| Receipt | Required proof and retry action |
|
|
28
|
+
|---|---|
|
|
29
|
+
| PR | Fetch the receipt URL using `gh pr view <url> --json state,headRefOid` in its repository. Require `OPEN`, head equal to the attempted head, delivered head equal to attempted head, passed verification, and unchanged current feature head when the tree exists. A stale head must re-push the verified branch non-force and update the existing PR, not create another PR. Refresh and rewrite the receipt after success. A closed PR is not a validated skip; stop for disposition. |
|
|
30
|
+
| Squash | Require `verification: passed` and the squash SHA reachable from the primary's default branch: `git -C <primary> merge-base --is-ancestor <squash SHA> <default branch>` must exit 0. Confirm the current attempted feature head when available. For recorded failed post-squash verification, rerun verification, not squash, against the delivered primary state; rewrite the receipt on pass. Require the recorded squash to remain reachable and stop on unrelated primary movement requiring review. |
|
|
31
|
+
|
|
32
|
+
Never use feature-head ancestry as proof of squash delivery. Resolve the actual primary default branch, not an assumed `main`. Treat unexpected Git exits as errors, not negative proofs. Preserve receipts on every failure, including seal failure and cleanup refusal.
|
|
33
|
+
|
|
34
|
+
## Verification and closure - Steps 1 and 3.5
|
|
35
|
+
|
|
36
|
+
Exempt a leg with a validated receipt and a missing worktree from checkout-based verification and conformance. Run fresh checks for every unlanded leg; stop on a missing unlanded worktree. Handle failed-squash verification in the delivered primary through the receipt retry action above; replace feature-checkout checks with that primary verification even when the feature tree still exists.
|
|
37
|
+
|
|
38
|
+
Before Step 4, run every leg's recorded verification set with that leg's worktree as command cwd, except the receipt-proven exemptions above, then perform conformance review with that leg's `cwd`, Rules and owned AC rows. Use original AC indices from `scope:`; shared rows belong to each named owner and unclaimed rows default home. Apply Step 1's hard gate and skip proof independently per leg. Route fixes and commits through `git -C <owning worktree>`, never home's checkout for companion code.
|
|
39
|
+
|
|
40
|
+
Retain each present member's audited head and tree, including staged, unstaged and untracked state. Immediately before delivery compare them to the current checkout; re-verify and re-review every changed leg before its delivery. Apply the same freshness check after disposition fixes and minors fixes. Aggregate closure before presenting one menu; no leg bypasses open dispositions.
|
|
41
|
+
|
|
42
|
+
Apply leg-local `piGauntlet.verifyBeforeShip` evidence to commands targeting that checkout. Read each primary's `.pi/settings.json` by file and merge the preset using the existing settings rules; do not use home's `gauntlet_setting` result or home's successful test flag as companion evidence. Use the recorded verification set, including when a retry has no plan.
|
|
43
|
+
|
|
44
|
+
## Execute one choice - Steps 4 and 5
|
|
45
|
+
|
|
46
|
+
Apply one chosen action to companions in declared sibling order, then home. Preserve every PR, draft and keep worktree and branch. Keep reports all retained locations without strip, seal, delivery or cleanup.
|
|
47
|
+
|
|
48
|
+
For a PR-subject home, compose the supported existing home action with companion delivery: row 1 pushes and edits the existing home PR through its recipe, rows 2-3 retain the existing-PR disclosure and refusal rather than attempting a duplicate, and squash/keep/discard retain their existing disclosures and confirmations. Deliver companions before the supported home ship action; keep absorbed-PR closure authorization separate and unchanged. Do not start fan-out for a home action withheld by preflight.
|
|
49
|
+
|
|
50
|
+
For PR, draft and squash:
|
|
51
|
+
|
|
52
|
+
1. Validate existing receipts first. Skip only receipt-proven delivery. Check freshness for every unlanded leg before its delivery.
|
|
53
|
+
2. Deliver each companion: for PR/draft, push with `git -C <worktree> push -u origin <branch>`, then run `gh pr create` in that worktree's cwd, adding `--draft` on every draft create. On retry of an existing PR use its URL and edit rather than duplicate create. For squash, use the existing Option 3 primary checkout/pull/merge/commit recipe and run that leg's recorded post-squash commands in the primary. Write its receipt even when those commands fail. No companion plan strip or telemetry seal runs.
|
|
54
|
+
3. Collect complete companion results, including validated skips. Capture the spec path and evidence before the home plan strip. Run home's strip-and-seal block with repeated `--leg <repo>=<sha|pr-url>`, one per companion. Never seal partial results. Compare collected `{ repo, sha }` or `{ repo, pr }` entries with an existing seal's `legs:` set; differences stop naming stored and collected results. Retain all receipts when the bin fails and print its output. Never write companion `.pi/gauntlet/telemetry/`.
|
|
55
|
+
4. Deliver home through the selected existing recipe after successful sealing, without running a second seal lacking the companion arguments. For PR-subject row 1 retain the whole-PR base and all body-edit/closure rules. Write home's receipt, including post-squash failures. Run cleanup only for squash, after successful post-squash verification.
|
|
56
|
+
|
|
57
|
+
Put `Home: <repo> <shared branch> <home spec path>` in every companion PR body and squash message. Respect each leg's PR body style. List every companion PR URL in the home PR body (including the existing home PR's rework block), and every companion squash SHA in home's squash message.
|
|
58
|
+
|
|
59
|
+
On the first delivery, verification or seal failure, stop fan-out and preserve delivered work and receipts. Print actual results, including validated skips, in member order:
|
|
60
|
+
|
|
61
|
+
```text
|
|
62
|
+
Shipped: <repo> <sha|pr> ...
|
|
63
|
+
Not shipped: <repo> <reason> ...
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
A squash with failed post-verification belongs under Not shipped with its created SHA and error; do not conceal the commit. Include home when not delivered and every untouched remaining companion. Perform no rollback. A fresh-session retry validates the same receipts before continuing.
|
|
67
|
+
|
|
68
|
+
## Discard and recorded cleanup - Steps 5 and 6
|
|
69
|
+
|
|
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.
|
|
71
|
+
|
|
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.
|
|
73
|
+
|
|
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.
|
|
75
|
+
|
|
76
|
+
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.
|
|
@@ -65,7 +65,7 @@ Apply the first-line grammar in [menu-layout](../brainstorming/reference/menu-la
|
|
|
65
65
|
(`disable-model-invocation: true`), so it is absent from the session skill list.
|
|
66
66
|
Locate it by path: run `pi list`; the indented path under the `pi-cohort` entry
|
|
67
67
|
(`npm:pi-cohort`, or a local path ending in `/pi-cohort`) is the package root. `Read` `<root>/skills/handoff/SKILL.md` and follow its procedure with the
|
|
68
|
-
output option resolved in step 1
|
|
68
|
+
output option resolved in step 1. Read the run home's spec; with multiple members, explicitly supply `Run worktree: <home worktree>` through cohort's "was told to work in" snapshot clause. Pin the snapshot to that path, not the most-recently-used companion and not an `Also seen:` entry. The brief's core (six headings, ending at
|
|
69
69
|
`## Skills loaded`) is cohort's to write, by cohort's rules. No `pi-cohort` entry, or
|
|
70
70
|
the file missing -> STOP: "cohort `handoff` skill not found at
|
|
71
71
|
`<root>/skills/handoff/SKILL.md` - install or upgrade to pi-cohort >= 7.1.0". No
|
|
@@ -85,7 +85,7 @@ Apply the first-line grammar in [menu-layout](../brainstorming/reference/menu-la
|
|
|
85
85
|
- A phase `in_progress` (verify or ship included - resume stops at verify on its own)
|
|
86
86
|
-> append the process-state section exactly as `## Producers` in
|
|
87
87
|
`reference/brief-contract.md` lays it out: both status outputs verbatim
|
|
88
|
-
(`No plan active.` verbatim when there is no plan), the contract's artifact-specific fields, and the gate-history line. Recognize the loop alternative by ledger line 1; read the ledger from the run worktree for its durable last decision. Read the run worktree's spec; when it carries `## Rework record`, copy every top-level PR identity (without the title) and its full pre-rework head, home first in record order, into the optional fields in the contract's producer layout. Without that record, use the ordinary layout. Use only the contract's grammar; write no second state file. Append with a single
|
|
88
|
+
(`No plan active.` verbatim when there is no plan), the contract's artifact-specific fields, and the gate-history line. Recognize the loop alternative by ledger line 1; read the ledger from the run worktree for its durable last decision. Read the run worktree's spec; when it carries `## Rework record`, copy every top-level PR identity (without the title) and its full pre-rework head, home first in record order, into the optional fields in the contract's producer layout; copy the optional top-level rework base after the pairs as the contract specifies. Without that record, use the ordinary layout. For multiple members, read `reference/brief-contract.md` "Coordinated brief grammar" and append its ordered member snapshot, including missing trees and existing receipt paths, in that layout. Keep the core snapshot home-bound. Use only the contract's grammar; write no second state file. Append with a single
|
|
89
89
|
`cat >> "<brief path>" <<'EOF' ... EOF` whose body is that block.
|
|
90
90
|
- Re-read the file tail and confirm it ends with the gate-history line from the
|
|
91
91
|
contract and nothing after.
|
|
@@ -91,12 +91,13 @@ checks 2, 4, 5 do not apply; check 6 runs on the seed's pinned spec path.
|
|
|
91
91
|
cwd with
|
|
92
92
|
`realpath "$(git -C <worktree> rev-parse --path-format=absolute --git-common-dir)"`.
|
|
93
93
|
If they differ, stop, name both paths, and say the resolved worktree belongs to a
|
|
94
|
-
different repository; restart pi in that repository's primary checkout and re-run.
|
|
94
|
+
different repository; restart pi in that repository's primary checkout and re-run. For member-primary entry on a coordinated brief, also print `home is <repo>; restart there`, naming the run home.
|
|
95
95
|
Same-repository worktrees proceed by path: use `git -C <worktree>` for
|
|
96
96
|
worktree Git commands and absolute artifact paths for `Read` and `plan_check`.
|
|
97
|
+
3b. **Coordinated admission.** For a multi-member brief, read and apply `reference/brief-contract.md` "Coordinated admission" before any tracker write: resolve the home spec without inferring approval, compare ordered membership, validate each declared primary/common directory, shared branch and full home tuple, and live-validate receipts before admitting any missing tree. Preserve check 3's home binding.
|
|
97
98
|
4. **Drift notice.** Compare the brief's `HEAD` and `dirty` fields in `## Repo state`
|
|
98
99
|
with the live worktree (`git -C <worktree> rev-parse HEAD`, `git -C <worktree>
|
|
99
|
-
status --porcelain`). Announce differences. Informational, never a stop.
|
|
100
|
+
status --porcelain`). For coordinated briefs apply `reference/brief-contract.md` "Coordinated admission" per leg. Announce differences. Informational, never a stop.
|
|
100
101
|
5. **Skills loaded.** For each name in `## Skills loaded` (none for
|
|
101
102
|
`## Skills loaded: none`): match against the frontmatter `name` of every
|
|
102
103
|
`skills/*/SKILL.md` in this package; `Read` each match's complete file into the
|
|
@@ -27,7 +27,7 @@ Headings, fixed order. A consumer keys on headings, never prose.
|
|
|
27
27
|
| `## Repo state` | one field per line: `toplevel`, `worktree: yes <path>` or `worktree: no`, `branch` (`detached` when none), `HEAD`, `base` (`unknown` when no remote resolves), `dirty: <porcelain>` or `dirty: clean`, `diff-stat` (`unavailable` when base unknown), `test cmd`; any field `unavailable` when its command failed; heading `## Repo state: not a git repo` outside git | always |
|
|
28
28
|
| `## Decisions` | bullets; rejected alternatives marked `rejected:` | always |
|
|
29
29
|
| `## Skills loaded` | frontmatter `name`s; `## Skills loaded: none` when none | always |
|
|
30
|
-
| `## Process state` | `phase_tracker status` then `plan_tracker status` verbatim; `Active task: <name|none>`; optional one or more consecutive `PR: <owner/repo#N>` / `Pre-rework head: <40-char sha>` pairs, one per record group, home first, in record order, only for a PR subject; the line `Gate history not restored - re-validate before advancing.` | only when a phase is `in_progress` and no hotfix flow is in context |
|
|
30
|
+
| `## Process state` | `phase_tracker status` then `plan_tracker status` verbatim; `Active task: <name|none>`; optional one or more consecutive `PR: <owner/repo#N>` / `Pre-rework head: <40-char sha>` pairs, one per record group, home first, in record order, only for a PR subject; optional single `Rework base: <40-char sha>` after all PR pairs; optional coordinated block defined below after that line; the line `Gate history not restored - re-validate before advancing.` | only when a phase is `in_progress` and no hotfix flow is in context |
|
|
31
31
|
|
|
32
32
|
For a loop ledger (line 1 exactly `# Ledger - loop engine`), replace `Active task` with these two fields, retaining both tracker status outputs and the gate-history line:
|
|
33
33
|
|
|
@@ -53,9 +53,9 @@ one blank line, the heading on its own line, a blank line, the `phase_tracker st
|
|
|
53
53
|
output verbatim, a blank line, the `plan_tracker status` output verbatim, a blank line,
|
|
54
54
|
`Active task: <name|none>`, then, only for a PR subject, one or more consecutive
|
|
55
55
|
`PR: <owner/repo#N>` / `Pre-rework head: <40-char sha>` pairs, one per record group,
|
|
56
|
-
home first, in record order, then the gate-history line after the last pair -
|
|
56
|
+
home first, in record order, then optional single `Rework base: <40-char sha>` after all PR pairs, then the optional coordinated block below, then the gate-history line after the last pair, rework-base line, or block -
|
|
57
57
|
unfenced, nothing after.
|
|
58
|
-
For a task plan, set `Active task` to the first `→` task name, else `none` (also for `No plan active.`). For a line-1 ledger, read its path and last decision and use the loop alternative above, retaining the optional PR pairs before the gate-history line. Copy only top-level record pairs, without titles; `Threads:` and record `### PR #<N>` subsections are not brief fields. For N=1 emit one pair; without a Rework record use the ordinary layout.
|
|
58
|
+
For a task plan, set `Active task` to the first `→` task name, else `none` (also for `No plan active.`). For a line-1 ledger, read its path and last decision and use the loop alternative above, retaining the optional PR pairs and rework base before the gate-history line. Copy the full rework base only from the top-level record when present; never invent a boundary for incomplete sync. Copy only top-level record pairs, without titles; `Threads:` and record `### PR #<N>` subsections are not brief fields. For N=1 emit one pair; without a Rework record use the ordinary layout.
|
|
59
59
|
|
|
60
60
|
Example appended block (the fence is documentation; the brief carries no fence):
|
|
61
61
|
|
|
@@ -80,6 +80,38 @@ Active task: W2: producer
|
|
|
80
80
|
Gate history not restored - re-validate before advancing.
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
+
## Coordinated brief grammar
|
|
84
|
+
|
|
85
|
+
For more than one member only, append this block after the optional PR pairs and before the terminal gate-history line. Emit entries in the home spec's `### Leg:` order, home first. Keep the six core headings and `## Repo state` fields unchanged and bound to the run home. Distinguish PR home (the leading PR pair) from run home (the first member); do not infer one from the other.
|
|
86
|
+
|
|
87
|
+
```text
|
|
88
|
+
legs:
|
|
89
|
+
- repo: repo-a
|
|
90
|
+
worktree: <absolute home worktree>
|
|
91
|
+
branch: <shared branch>
|
|
92
|
+
HEAD: <full sha>
|
|
93
|
+
dirty: clean
|
|
94
|
+
- repo: repo-b
|
|
95
|
+
worktree: missing
|
|
96
|
+
branch: <shared branch>
|
|
97
|
+
HEAD: <last recorded full sha or unavailable>
|
|
98
|
+
dirty: unavailable
|
|
99
|
+
receipt: <absolute home-owned receipt path>
|
|
100
|
+
Gate history not restored - re-validate before advancing.
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Keep fields in this order. Use the portable repo identifier from `../../brainstorming/reference/legs.md`. Record the absolute worktree path or the literal `missing` when absent; record live HEAD and porcelain dirt (`clean` when empty), or last recorded HEAD and `unavailable` dirt for a missing tree. Include the optional receipt path only when a delivery receipt exists; transport is not proof. For a live tree without a receipt omit that field. Single-member and legacy briefs carry no coordinated block, leg file, receipt, `--leg` or companion loop.
|
|
104
|
+
|
|
105
|
+
## Coordinated admission
|
|
106
|
+
|
|
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
|
+
|
|
109
|
+
For each companion, parse the home overrides' selected sibling clone URL with shape-ticket's shared parser and use `<home PRIMARY parent>/<NAME>` as its declared primary. Canonicalize that primary's git common directory. Resolve an absent location from the leg's recorded `home:` contract and shared NAME (shared branch with `/` replaced by `-`), not a newly inferred wrapper. Require the companion worktree's canonical git common directory to equal the declared primary's, its live branch to equal the shared branch, and its leg file's full `**Home:**` tuple to equal the run home's repo, shared branch and repo-relative spec path. Stop naming the offending leg and expected/observed path, branch or full tuple. A live tree's branch or tuple mismatch is not informational drift.
|
|
110
|
+
|
|
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
|
+
|
|
113
|
+
For a ship-stage retry with a correctly stripped plan, require every companion receipt to validate live before admitting the missing plan. Restore through the legal brainstorm start/skip, plan start/skip and implement skip sequence to verify, without inventing a plan_check stamp or conformance evidence. Re-validate unlanded home using recorded contracts and original scoped ACs, then run fresh home conformance and finish; use the finishing reference's retry route. Preserve receipts on seal or home delivery failure; do not repair or replace a correctly stripped plan. An absent plan without this fully validated ship retry remains a stop.
|
|
114
|
+
|
|
83
115
|
## Tracker output grammar
|
|
84
116
|
|
|
85
117
|
Must match `formatStatus` in the phase-tracker and plan-tracker extensions.
|
|
@@ -126,8 +158,8 @@ Read the worktree spec's `## Rework record` and compare its top-level `PR:` iden
|
|
|
126
158
|
`brief lists <brief order>, record lists <record order>`, substituting both observed
|
|
127
159
|
ordered lists, before any tracker call. Resolve the spec through reconstruction's
|
|
128
160
|
candidate rules below before this comparison; artifact presence supplies no approval.
|
|
129
|
-
Carry all paired full pre-rework heads downstream in their original order
|
|
130
|
-
reconstruction
|
|
161
|
+
Carry all paired full pre-rework heads downstream in their original order.
|
|
162
|
+
Carry the optional full rework base downstream; reconstruction prefers it over the first pair's head as its scan base. Without optional pairs,
|
|
131
163
|
retain ordinary restoration.
|
|
132
164
|
Preserve the entry checks, standing-grant validation, plan repair, and task snapshot;
|
|
133
165
|
PR identity implies no approval or gate evidence.
|
|
@@ -163,7 +195,9 @@ Honor SKILL.md entry check 6's deferred stop before any process-state arming cal
|
|
|
163
195
|
| implement with ledger | Read ledger line 1; resolve its path-only `**Spec:**` header; run entry checks 1-6, naming check 6 (Grant field); `start brainstorm`; `skip brainstorm` reason `resume: <spec path>`; `start plan`; `plan_check` on the absolute ledger path; on PASS `skip plan` reason `resume: <spec> (loop engine)` using the resolved absolute spec path as `<spec>`; `start implement`; no `plan_tracker init`; apply the shared cap boundary in `reconstruction.md` "Spec with ledger" step 4 before continuation; render cap, rows and decisions; continue at loop step 5. Follow `reconstruction.md` "Spec with ledger" for this self-contained ordered restore. On FAIL stop with findings, never `## Plan repair` or writing-plans. |
|
|
164
196
|
| implement with task plan | `start brainstorm`; `skip brainstorm S`; `start plan`; `plan_check({ planPath })`; on FAIL run `## Plan repair`; on PASS `skip plan R`; `start implement`; `substep` if shown; `plan_tracker init` |
|
|
165
197
|
| verify | `start brainstorm`; `skip brainstorm S`; `start plan`; `plan_check({ planPath })`; on FAIL run `## Plan repair`; on PASS `skip plan R`, then `skip implement R`; `start verify`; `substep` if shown; `plan_tracker init`. Never call `start implement`. |
|
|
166
|
-
| ship | as verify. Restoration stops at verify in_progress: `complete verify` needs a fresh conformance dispatch and `skip verify` would bypass a real gate. Announce that the closure review re-runs before ship |
|
|
198
|
+
| ship | With a correctly stripped coordinated plan, apply "Coordinated admission"'s fully receipt-validated retry route instead of plan repair; otherwise as verify. Restoration stops at verify in_progress: `complete verify` needs a fresh conformance dispatch and `skip verify` would bypass a real gate. Announce that the closure review re-runs before ship |
|
|
199
|
+
|
|
200
|
+
For a coordinated ledger, apply reconstruction's pending companion return boundary before dispatch or verification, including verify/ship restores; record a validated interrupted return before continuing.
|
|
167
201
|
|
|
168
202
|
For a ledger brief, pair by the ledger's path-only `**Spec:**` header, not basename; require the resolved spec under `flowGuards.specDirs` and the ledger under its sibling plans directory. Keep same-repository binding and human confirmation. For every ledger brief apply the shared cap boundary in `reconstruction.md` "Spec with ledger" step 4 before dispatch or verification, retaining its legacy stop and original-phase grant continuation. For verify/ship ledger briefs, use the ledger restore sequence through `skip plan`, then `skip implement R`; `start verify`, with no task tracker. Continue verify/ship ledger briefs in `/skill:loop-implementation` `After the loop` from step 1 (full ledger verification), after the already-restored `start verify`, retaining whole-diff code review, happy path when triggered, fresh conformance review and finishing without task-tracker calls. Ship still stops at verify for fresh conformance.
|
|
169
203
|
|
|
@@ -25,11 +25,11 @@ for a base ref before reading any artifact.
|
|
|
25
25
|
|
|
26
26
|
A pinned spec (seed route, `seed.md`) skips this section.
|
|
27
27
|
|
|
28
|
-
When the brief carries PR pairs, use the first pair's full `Pre-rework head:` SHA
|
|
28
|
+
When the brief carries PR pairs, use its full `Rework base:` SHA as `<base>` when present, else the first pair's full `Pre-rework head:` SHA for spec
|
|
29
29
|
and plan candidate scans instead of the merge-base from "Base"; the PR's earlier
|
|
30
30
|
spec remains input, not an added candidate, so it does not trigger a multi-spec pick.
|
|
31
31
|
Keep pairing, untracked candidates, task evidence, and human confirmation below.
|
|
32
|
-
Without the optional
|
|
32
|
+
Without the optional pairs, including a bare worktree, use the ordinary base.
|
|
33
33
|
|
|
34
34
|
Resolve with `gauntlet_setting({ key: "flowGuards" })`; `<dirs>` below is its `specDirs` plus `planDirs` (each spec dir's sibling `plans` dir), space-separated.
|
|
35
35
|
|
|
@@ -38,8 +38,7 @@ git -C <worktree> diff --diff-filter=A --name-only <base>..HEAD -- <dirs>
|
|
|
38
38
|
git -C <worktree> ls-files --others --exclude-standard -- <dirs>
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
there. Paths returned by these commands are relative to `<worktree>`; resolve them to
|
|
41
|
+
Take files under those directories added after base, plus untracked files there, as candidates. For a brief with PR pairs, also admit the spec whose run-worktree `## Rework record` lists the brief's `PR:` identities, even when tracked at `<base>`; pair it with a task plan at `<planDir>/<same basename>` or a ledger whose `**Spec:**` header resolves to it, whether or not either file was added after `<base>`. Paths returned by these commands are relative to `<worktree>`; resolve them to
|
|
43
42
|
absolute paths under `<worktree>` before reading artifacts, showing paths in prompts,
|
|
44
43
|
or calling `plan_check`. Read candidate contents before choosing. For a PR-list brief,
|
|
45
44
|
read the rework candidate's `## Rework record` and the member-carried spec paths listed
|
|
@@ -52,7 +51,7 @@ Read every plan-directory candidate's first line. A line exactly `# Ledger - loo
|
|
|
52
51
|
from base; count a base-tracked spec so paired as a spec in the route table below.
|
|
53
52
|
The plan commit is the first
|
|
54
53
|
post-base commit that added the plan file: `git -C <worktree> log --diff-filter=A
|
|
55
|
-
--format=%H --reverse <base>..HEAD -- <plan>`, first line. An uncommitted plan has no
|
|
54
|
+
--format=%H --reverse <base>..HEAD -- <plan>`, first line. For a brief with `Rework base:`, when that lookup is empty and `git -C <worktree> cat-file -e <base>:<plan>` exits 0, use the `Rework base:` commit itself as the plan commit. An uncommitted plan has no
|
|
56
55
|
plan commit; treat every task as `pending`.
|
|
57
56
|
|
|
58
57
|
| Candidates | Route |
|
|
@@ -63,6 +62,8 @@ plan commit; treat every task as `pending`.
|
|
|
63
62
|
| one spec with ledger | "Spec with ledger" (takes precedence over a task plan) |
|
|
64
63
|
| one spec with task plan only | "Spec with plan" |
|
|
65
64
|
|
|
65
|
+
For a coordinated brief, use `brief-contract.md` "Coordinated admission" before tracker writes. Resolve the home spec, never a companion leg file, and retain every approval question. For a ship-stage retry whose plan is stripped, use that section's receipt-validated exception rather than proposing a new plan.
|
|
66
|
+
|
|
66
67
|
## Spec without plan
|
|
67
68
|
|
|
68
69
|
Run SKILL.md entry check 6's deferred-header admission on the resolved spec before the approval/handoff question below; apply it to both routes, including the unapproved-draft brainstorming handoff. Keep grant decoding exempt for the unapproved route.
|
|
@@ -93,6 +94,8 @@ After confirmation:
|
|
|
93
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" })`.
|
|
94
95
|
3. Call `plan_check({ planPath: <absolute ledger path> })`. On FAIL, stop with findings, retaining plan in_progress. Start the message with `gauntlet: stuck` followed by the findings reason on that line; never enter `## Plan repair` or writing-plans. On PASS, call `phase_tracker({ action: "skip", phase: "plan", reason: "resume: <spec> (loop engine)" })`, then `phase_tracker({ action: "start", phase: "implement" })`. Use the resolved absolute spec path as `<spec>` in the reason. Never call `plan_tracker init`.
|
|
95
96
|
4. **Shared cap boundary (every ledger restore, before phase continuation).** Read `/skill:loop-implementation`. Skip Entry step 1 entirely; settings resolution and its unavailable-tool stop apply only to fresh seeding. Restore base, verification, iterations, `cap:`, row attempts, funding and retry allowances from the ledger/spec and branch without overwriting it. Render `cap: <n>`, rows, iterations, attempts, funding, retry allowances and all decisions; distinguish the latest operational `row <n> ...` decision from the last physical history line. A dirty tree takes the driver's discard-authorization stop without offering a cap grant. On a clean ledger missing `cap:`, stop with `ledger has no cap: line - seeded under the old loopEngine contract`, even when every row is closed. Use the driver's legacy `cap +N` grant (durable iterations + N), never settings. After the grant continue the original phase: implement at `Before each dispatch`; verify/ship at `After the loop` step 1, never reseed.
|
|
97
|
+
Before continuation on a coordinated ledger, recover the pending companion return boundary. Read the durable `pending:` tuple (target row or seed, repo, pre-dispatch HEAD) and compare that companion's live head. Accept only exactly one new companion commit matching the tuple and carrying its consumed iteration and bounded result evidence. Validate the result, record its SHA and only that leg's target result or seeded state in the home ledger, and remove `pending:` in the home-ledger commit before dispatch. Preserve consumed iterations, attempts and cap; never rerun the recovered row. Unrelated head movement, multiple commits, or missing result evidence stops naming the leg and tuple. With no new commit, use the loop driver's interrupted-dispatch boundary, not a silent redispatch. Apply this boundary before dispatch or verification for every ledger restore.
|
|
98
|
+
|
|
96
99
|
5. Continue at loop step 5, the delivered driver's `Before each dispatch`, with durable iterations and retry data. Never reset counters or reseed a validated seed.
|
|
97
100
|
|
|
98
101
|
## Spec with plan
|
|
@@ -112,8 +115,7 @@ Show, and ask the human to confirm or edit both in one reply:
|
|
|
112
115
|
Uncommitted plan (no
|
|
113
116
|
plan commit): skip this query entirely - there is no range to search - and show
|
|
114
117
|
"plan uncommitted; no task evidence" in its place; every task is proposed `pending`.
|
|
115
|
-
|
|
116
|
-
(plan at or before base): skip the log query, show
|
|
118
|
+
For a plan tracked at the `Rework base:` with no post-base add commit, use that base as the plan commit and query post-base task evidence as above. Otherwise, when the lookup is empty but `git -C <worktree> cat-file -e <base>:<plan>` exits 0, skip the log query, show
|
|
117
119
|
`plan predates base; no post-base task evidence`, every task proposed `pending`.
|
|
118
120
|
2. Uncommitted files: `git -C <worktree> status --porcelain`.
|
|
119
121
|
3. Proposed task statuses: `complete` iff at least one matching commit, else `pending`.
|
|
@@ -4,6 +4,8 @@ Consumed only by `SKILL.md` in this directory, for a one-token `.md` argument cl
|
|
|
4
4
|
as a spec seed. `<seed>` is its `realpath`; `<rel>` is `<seed>` relative to `<primary>`.
|
|
5
5
|
Entry check 1 (idle session) runs first. Then, in order; every stop names the path.
|
|
6
6
|
|
|
7
|
+
Before starting the seed sequence, read the seed's header. A `**Home:**` header marks a companion leg file: stop, name its home repo, branch and spec path, and direct resume to that home. Never create a run from a leg file.
|
|
8
|
+
|
|
7
9
|
1. **Primary session.** `git rev-parse --git-dir --git-common-dir` in the session cwd
|
|
8
10
|
prints two paths; their `realpath`s must agree. Otherwise stop:
|
|
9
11
|
`seed from the primary checkout`.
|
|
@@ -18,6 +18,8 @@ Run this driver in the main session. Carry the absolute implementation worktree
|
|
|
18
18
|
| Otherwise overrides has `## verification-before-completion` | Use its exactly one backticked command; zero or several is a configuration error. |
|
|
19
19
|
| Neither section supplies a command | Discover the project's test entrypoint from its actual manifest/build instructions; print discovery as source. Stop on an unresolved or ambiguous entrypoint. |
|
|
20
20
|
|
|
21
|
+
For more than one `### Leg:` block, apply coordinated Entry below instead of the home-only skeleton and cap calculation. Keep legacy and single-member ledger bytes unchanged, with no coordinated metadata.
|
|
22
|
+
|
|
21
23
|
3. Call `phase_tracker({ action: "skip", phase: "plan", reason: "loop engine" })`.
|
|
22
24
|
4. Require a clean named-branch implementation worktree. Write `<resolved plan dir>/<spec stem>-ledger.md`. Use this grammar with literal values, not placeholders:
|
|
23
25
|
|
|
@@ -41,6 +43,18 @@ Use the actual repo-relative spec path alone in the Spec header. Read base with
|
|
|
41
43
|
|
|
42
44
|
For resume, use the admitted ledger, its base and verification command, and durable iterations and cap instead of overwriting it. Skip Entry step 1 for an admitted ledger; settings apply only to fresh seeding. Render rows, cap and decision history; stop on a dirty tree before dispatch.
|
|
43
45
|
|
|
46
|
+
## Coordinated Entry and resume
|
|
47
|
+
|
|
48
|
+
Read `## Legs` with [the scope grammar](../brainstorming/reference/legs.md#scope-grammar-and-validation) before skeleton commit or dispatch. Require exactly one `scope:` per block: `scope: AC 1, AC 3` or `scope: none`. Reject missing/duplicate scope lines, duplicate indices within a list, malformed tokens and out-of-range original indices through the amendment stop. Include cut original AC indices; never infer ownership from a `design:` mention or path. Default only indices absent from every valid list to home; repeat shared indices in every owner's list.
|
|
49
|
+
|
|
50
|
+
Retain the home skeleton's `**Spec:**`, `verification:`, `iterations:`, `cap:` and `## Decisions` fields and its `plan_check`/commit admission. Read each member's verification from the home spec's `## Legs` `contract:` `- verification:` line before dispatch; keep the existing home verification header.
|
|
51
|
+
|
|
52
|
+
Assign numeric entries in original AC order, then membership order for shared ACs, independent of scope-list order. Leave spec rows untouched and copy each cut disposition to every expanded entry. Keep the four-column table and add `## Leg mapping` with `row | ac | leg`, one mapping per entry exactly once. Reject duplicate/missing mappings. Keep `base:` as home base; record one actual `base repo-a: <sha>` / `seeded repo-a: no` pair per member, including home. Resolve bases with each member's `git -C`, not home HEAD.
|
|
53
|
+
|
|
54
|
+
Compute initial cap as non-cut entry count times `maxIterationsPerRow` plus one seed dispatch per leg with non-cut entries. One shared home/companion AC and one home-only AC produce three entries, two seeds and cap 14 at default 4; a wholly cut third leg adds no seed. All-cut cap stays 1 and exits without seed. Preserve cap after cuts, reopens, amendments, funding and recovery; only an explicit cap grant raises it.
|
|
55
|
+
|
|
56
|
+
Recover pending companion work before generic dirty checks and before any new dispatch. Read the durable home ledger's `pending:` tuple and consumed iteration, selected companion HEAD and saved pre-dispatch state. Reconstruct the pre-dispatch ledger from home `HEAD:<ledger path>` on resume and admit only the expected on-disk iterations bump and tuple against it. Admit only the known iterations bump and exact pending tuple as pre-dispatch dirt; stop on other dirt. Reapply companion return validation below only when exactly one new commit after the recorded HEAD matches attribution and result. Apply the home-ledger commit without another attempt or iteration bump, clear pending and retain prior decisions. Stop preserving state on zero commits, unrelated movement, multiple commits or attribution/result mismatch. Never rerun that row or seed. After a successful parent commit no pending tuple remains, so a subsequent resume cannot duplicate the update.
|
|
57
|
+
|
|
44
58
|
## Before each dispatch
|
|
45
59
|
|
|
46
60
|
Read the ledger and require its `cap:` header before the ordered table, including before rule 1. On a missing header stop with `ledger has no cap: line - seeded under the old loopEngine contract`, even for a completed ledger; use the legacy grant below, never derive cap from settings. Count empty child commits and validation misses only after the latest `loop: retry row <n>` commit. Funding alone resets neither window. Preserve every row's attempts and the total iteration cap. Apply this ordered table, starting here after each return or human decision:
|
|
@@ -57,9 +71,13 @@ Set row allowance to 3 + funded N, increased to the latest `row <n> retry` decis
|
|
|
57
71
|
|
|
58
72
|
Select `seed` until a validated `loop: seed evidence` commit with its `row 0 done` decision and evidence on every non-cut row survives on the branch, independently of `iterations`; otherwise select the still-unresolved human retry target, then the still-failed row named by the previous decision, then first failed row, then first open row. Use the latest operational `row <n> ...` decision for targeting and the child's `previous decision:` input, skipping cap grant history while retaining the entire Decisions section. Durable status beats a decision's suggestion. Keep the retry hint only for its target.
|
|
59
73
|
|
|
74
|
+
For coordinated targeting, select the next unseeded leg with non-cut entries in membership order before ordinary targeting. Use the existing retry/failed/open priority only after those seeds validate. Skip wholly cut legs; never mark foreign legs seeded. Map each numeric target to its original AC and leg via `## Leg mapping`.
|
|
75
|
+
|
|
60
76
|
## Dispatch
|
|
61
77
|
|
|
62
|
-
|
|
78
|
+
For coordinated dispatch, capture home and selected leg heads and save a pre-dispatch ledger snapshot for the expected-dirt comparison. Select the leg worktree as `cwd` and git root, its own base, mapped original AC, `Leg:` and combined spec/task `Rules:` as additive task inputs. Read spec and ledger by absolute home paths. Bump iterations exactly once. Before every companion dispatch, including seed, persist the exact tuple such as `pending: 2 | repo-b | abc1234` (or `pending: seed | repo-b | abc1234`) with actual target, repo and pre-dispatch HEAD in the home ledger. Keep that expected bump/tuple durable on disk before generic dirty checks; admit no other dirt. After persisting the bump and pending tuple, bind `SAVED_LEDGER` to the durable home ledger for companion admission, not the pre-dispatch snapshot. Pass consumed `iteration:` and the exact `pending:` as attribution. Leave home iterations on the existing single child commit path, validating only home entries and home seeded state.
|
|
79
|
+
|
|
80
|
+
For home-only dispatch, record `HEAD_BEFORE`, copy the ledger text, and take i from the current iterations count. Increment `iterations:` before dispatch in the working tree so the child's commit persists it. Create a unique absolute output path with `mktemp` outside the repository. Dispatch exactly one foreground child in the main implementation worktree, not a nested worktree:
|
|
63
81
|
|
|
64
82
|
```text
|
|
65
83
|
subagent({ agent: "loop-implementer", context: "fresh", async: false,
|
|
@@ -75,6 +93,12 @@ Omit the model override; let the persona override or parent inheritance resolve
|
|
|
75
93
|
|
|
76
94
|
## Validate the return
|
|
77
95
|
|
|
96
|
+
For a companion, validate from its commit, not the reply. Require a clean companion and exactly one commit after pending HEAD; require unchanged home HEAD and no home edits except the expected persisted bump/tuple. Match subject `loop: row <n> <status>` or `loop: seed evidence`, exact pending tuple and consumed `iteration:` in the body. Parse only the resulting four-column target row (all and only that leg's non-cut rows for seed), followed by one bounded decision. Apply the evidence and decision bounds below. Reject a wrong target, foreign entry, header changes, fabricated counts, malformed evidence or extra results. Validate seed counts against actual rows and baseline closures; preserve attempts and set only this leg's seeded value to `yes` after every non-cut entry validates. Keep seed misses a human stop. Apply ordinary repair only to the target, retaining consumed iterations and saved cap.
|
|
97
|
+
|
|
98
|
+
After validation update only that leg's target or seed entries, append the validated decision, record companion SHA in evidence, and remove `pending:` in one home-ledger commit. Preserve every other row, header and prior decision. That home-ledger commit (`loop: record <repo> row <n>`) is a parent commit, not a child `loop: row ...` commit: it never counts toward child-only empty-commit stagnation, and a rejected companion return records the rejection in the same parent commit while preserving the pending tuple and every row. Recover interrupted returns by this same validation, never trusted reply text.
|
|
99
|
+
|
|
100
|
+
For home-only returns, apply the following boundary and table. For coordinated home returns apply it only to home entries/seeded state, preserving foreign entries, mappings and bases.
|
|
101
|
+
|
|
78
102
|
1. Require empty `git -C "<worktree>" status --porcelain` and exactly 1 from `git -C "<worktree>" rev-list HEAD_BEFORE..HEAD --count`. On dirty/zero/multiple commits stop, preserving changes and commits. Use `Stopped: iteration <i> left the tree dirty` or `Stopped: iteration <i> added <k> commits`. Read the ledger from HEAD only after this boundary passes.
|
|
79
103
|
2. Validate by dispatched `target`, not iteration number, against the saved copy using this table. Preserve headers including cap and the bumped iterations, row identifiers and prior decisions.
|
|
80
104
|
|
|
@@ -87,9 +111,68 @@ Require ordinary decision grammar `^row <target> (done|failed) \| .{1,200} \| .{
|
|
|
87
111
|
|
|
88
112
|
On an ordinary miss restore every non-target row, headers (including the saved cap) and prior decisions from the saved copy, retaining the incremented iterations. Set the target `failed`, attempts = saved attempts +1, evidence = `iteration <i>: <concrete miss>`. Remove malformed appended decisions and commit `loop: repair row <n>`. Set previous decision to `none`; otherwise use the new conforming line. Two consecutive validation misses stop because the child is not following the contract. A conforming return resets the consecutive-miss count; parent repair commits do not count toward child-only empty stagnation.
|
|
89
113
|
|
|
114
|
+
### Companion commit admission
|
|
115
|
+
|
|
116
|
+
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. On failure preserve pending and stop. On success use the emitted object for the single parent ledger commit described above; never treat it as permission for another dispatch.
|
|
117
|
+
|
|
118
|
+
<!-- companion-return-shell -->
|
|
119
|
+
```bash
|
|
120
|
+
node - "$CHECKOUT" "$PENDING" "$ITERATION" "$SAVED_LEDGER" <<'NODE'
|
|
121
|
+
const fs = require('node:fs');
|
|
122
|
+
const { execFileSync } = require('node:child_process');
|
|
123
|
+
const [root, pending, iteration, savedPath] = process.argv.slice(2);
|
|
124
|
+
const requireThat = (ok, why) => { if (!ok) throw new Error(why); };
|
|
125
|
+
const git = (...args) => execFileSync('git', ['-C', root, ...args], { encoding: 'utf8' }).trim();
|
|
126
|
+
const tuple = /^pending: (seed|\d+) \| (\S+) \| ([a-f0-9]{7,40})$/.exec(pending);
|
|
127
|
+
requireThat(tuple, 'invalid pending');
|
|
128
|
+
const saved = fs.readFileSync(savedPath, 'utf8');
|
|
129
|
+
requireThat(saved.split('\n').filter(line => line.startsWith('pending:')).length === 1 && saved.split('\n').includes(pending) && saved.split('\n').includes(`iterations: ${iteration}`), 'pending already applied or iteration mismatch');
|
|
130
|
+
const [, target, leg, before] = tuple;
|
|
131
|
+
requireThat(git('status', '--porcelain') === '', 'dirty companion');
|
|
132
|
+
requireThat(git('merge-base', '--is-ancestor', before, 'HEAD') === '', 'unrelated HEAD');
|
|
133
|
+
requireThat(git('rev-list', '--count', `${before}..HEAD`) === '1', 'expected one companion commit');
|
|
134
|
+
const commit = git('rev-parse', 'HEAD');
|
|
135
|
+
const message = git('show', '-s', '--format=%B', 'HEAD').split('\n');
|
|
136
|
+
const subject = message.shift();
|
|
137
|
+
requireThat(message.shift() === '', 'missing body separator');
|
|
138
|
+
requireThat(message.shift() === pending, 'pending mismatch');
|
|
139
|
+
requireThat(message.shift() === `iteration: ${iteration}`, 'iteration mismatch');
|
|
140
|
+
const resultLines = message.filter(line => line.trim() !== '');
|
|
141
|
+
const cells = line => line.split(/(?<!\\)\|/).slice(1, -1).map(s => s.trim());
|
|
142
|
+
const table = text => text.split('\n').filter(line => /^\|\s*\d+\s*\|/.test(line)).map(cells);
|
|
143
|
+
const [ledger, mapping] = saved.split('## Leg mapping\n');
|
|
144
|
+
requireThat(mapping, 'missing mapping');
|
|
145
|
+
const map = table(mapping.split('## Decisions')[0]);
|
|
146
|
+
const oldRows = table(ledger);
|
|
147
|
+
requireThat(new Set(map.map(r => r[0])).size === map.length && map.length === oldRows.length && oldRows.every(r => map.some(m => m[0] === r[0])), 'invalid mapping');
|
|
148
|
+
const expected = oldRows.filter(r => map.some(m => m[0] === r[0] && m[2] === leg) && (target === 'seed' ? r[1] !== 'cut' : r[0] === target));
|
|
149
|
+
requireThat(expected.length && expected.every(r => r[1] !== 'cut'), 'foreign or cut target');
|
|
150
|
+
const decision = resultLines.pop();
|
|
151
|
+
const rows = resultLines.map(cells);
|
|
152
|
+
requireThat(rows.length === expected.length && resultLines.every(l => l.startsWith('|') && l.endsWith('|')), 'extra result');
|
|
153
|
+
for (const [i, row] of rows.entries()) {
|
|
154
|
+
const old = expected[i];
|
|
155
|
+
requireThat(row.length === 4 && row[0] === old[0], 'foreign row');
|
|
156
|
+
requireThat((target === 'seed' ? /^(open|done)$/ : /^(done|failed)$/).test(row[1]), 'invalid status');
|
|
157
|
+
requireThat(/^\d+$/.test(row[2]) && Number(row[2]) === Number(old[2]) + (target === 'seed' ? 0 : 1), 'attempt mismatch');
|
|
158
|
+
requireThat(row[3].length > 0 && row[3].split(';').length <= 4 && !/[<>]/.test(row[3]), 'unbounded evidence');
|
|
159
|
+
requireThat(target !== 'seed' || old[1] !== 'done' || row[1] === 'done', 'lost baseline closure');
|
|
160
|
+
}
|
|
161
|
+
if (target === 'seed') {
|
|
162
|
+
requireThat(subject === 'loop: seed evidence', 'seed subject mismatch');
|
|
163
|
+
const d = /^row 0 done \| seeded (\d+) rows, closed (\d+) on baseline \| .{1,200}$/.exec(decision);
|
|
164
|
+
requireThat(d && Number(d[1]) === expected.length && Number(d[2]) === rows.filter(r => r[1] === 'done').length, 'seed counts mismatch');
|
|
165
|
+
} else {
|
|
166
|
+
requireThat(subject === `loop: row ${target} ${rows[0][1]}`, 'row subject mismatch');
|
|
167
|
+
requireThat(new RegExp(`^row ${target} ${rows[0][1]} \\| .{1,200} \\| .{1,200}$`).test(decision), 'invalid decision');
|
|
168
|
+
}
|
|
169
|
+
console.log(JSON.stringify({ sha: commit, rows: resultLines, decision }));
|
|
170
|
+
NODE
|
|
171
|
+
```
|
|
172
|
+
|
|
90
173
|
## Exit verification
|
|
91
174
|
|
|
92
|
-
|
|
175
|
+
For coordinated exit, read each leg's verification from the home spec's `## Legs` `contract:` `- verification:` line and run it once foreground in its owning checkout, with repair routed there; retain home flow policy. Require every leg to pass before completing implement. For legacy/single-member exit, run the ledger's `verification:` command exactly once foreground in the worktree. Failure: human stop `Stopped: verification failed with every row closed`, Problem quoting failing output. Preserve closed rows: no reopening and no automatic rerun. Further work requires a human decision. Success: record verified HEAD and clean status; call `phase_tracker({ action: "complete", phase: "implement" })`, then continue immediately below.
|
|
93
176
|
|
|
94
177
|
## Human stop
|
|
95
178
|
|
|
@@ -110,12 +193,16 @@ Serialize the bare decision as `cap +50 |` with an empty words cell. A cap grant
|
|
|
110
193
|
|
|
111
194
|
For dirty/commit-boundary retry, ask the human to authorize discarding uncommitted changes/resetting to last valid commit. Preserve consumed dispatch count: set iterations to restored HEAD's value +1 before the next normal bump. An interrupted dispatch consumes the same count; recover it from disk/branch rather than silently repeating iteration 0.
|
|
112
195
|
|
|
196
|
+
For coordinated amendments, reconcile by original AC/leg mapping without resetting attempts, iterations or cap. Re-read explicit scope lists after approved ownership amendments and reconcile expanded entries; a disposition-only cut changes neither original indices nor ownership. Preserve unchanged mapped entries and their histories.
|
|
197
|
+
|
|
113
198
|
For ledger amendments use its line-1 discriminant: no plan writer, plan_check or task-tracker lifecycle. Approved deviates/deferred/elsewhere becomes `cut` with disposition evidence; requirement-preserving amendments leave rows unchanged; a re-bounded done row becomes `open` with `reopened by amendment`. Preserve attempts, iterations and cap. Commit spec + ledger as `loop: cut row <n>` or `loop: amend`. Option 4 stops for amendments, option 5 auto-applies amends, redraw always stops and deletes the ledger with the plan. Never cut automatically.
|
|
114
199
|
|
|
115
200
|
## After the loop
|
|
116
201
|
|
|
117
202
|
Read SDD's `After All Tasks Complete`, `../subagent-driven-development/reference/happy-path-run.md`, and `../verification-before-completion/reference/conformance-check.md` IN FULL now with read. Stop on an unreadable reference; do not reconstruct it. Execute this continuation, not the waves engine or a generic verification skill:
|
|
118
203
|
|
|
204
|
+
For coordinated runs, route each verification and review below to every leg with its own base, checkout, Rules and owned original ACs under home flow policy. Re-verify and re-review any changed leg; invoke coordinated finish once from home after every leg passes. Keep single-member/legacy paths free of a companion loop, leg file, `legs:` brief or `--leg` argument.
|
|
205
|
+
|
|
119
206
|
0. Call `phase_tracker({ action: "start", phase: "verify" })`.
|
|
120
207
|
1. Parent full verification uses the ledger command. Reuse the passing exit run only when HEAD and clean/no-change worktree still match. Commit verification-produced tracked changes. Any repair invalidates that run: rerun the full command successfully before the next gate. No task reopen/update is awaited.
|
|
121
208
|
2. Dispatch foreground whole-diff `code-reviewer` per `/skill:requesting-code-review`, from ledger base through committed HEAD, with `SCOPED_TEST_COMMANDS: none`. Apply its fix rounds. Rerun full verification after every repair before re-review/next gate. Carry final SHIP Minor lines verbatim as `whole-diff minors:`, or `whole-diff minors: none`.
|
|
@@ -118,6 +118,14 @@ Implementer prompt templates must instruct subagents to return one of these stat
|
|
|
118
118
|
- Omit `model:` when `closureReview.model` or `specCouncil.chair` is `undefined`; pass an `implModel` string verbatim, and stop with a note when `implModel` is `undefined` (Fix-Loop Rounds).
|
|
119
119
|
- Apply suffix edits such as `:low` only to a runtime-resolved string, never to a name the skill wrote; never write a provider or model name, tier tasks by cost, or swap a pinned model for a cheaper or stronger one.
|
|
120
120
|
|
|
121
|
+
## Leg routing
|
|
122
|
+
|
|
123
|
+
Read `## Legs` in the home spec and [the leg contract](../brainstorming/reference/legs.md). Admit task `Leg:` through `plan_check`; absent means home. Repair `leg-unknown` in the plan, never membership. Keep the existing flat tracker and task indices.
|
|
124
|
+
|
|
125
|
+
Require leg-homogeneous waves. Split a mixed wave into consecutive single-leg waves preserving dependencies before dispatch. Select its owning worktree before capturing `WAVE_BASE_SHA`; use that root for isolation, dispatch `cwd`, `git -C`, snapshots, integration, scoped tests, in-place repair and wave commit. In the following recipes, substitute that root for every implementation worktree placeholder. Keep authoritative spec reads at the absolute home spec path, including companion SR snapshots.
|
|
126
|
+
|
|
127
|
+
Carry `Leg:` and combined spec/task `Rules:` as additive task context to every implementer, spec-reviewer and code-reviewer, including repairs and re-reviews; require reading those files before acting. Resolve rules from the owning checkout, not home. Keep dispatch and acceptance shapes unchanged.
|
|
128
|
+
|
|
121
129
|
## Dispatch
|
|
122
130
|
|
|
123
131
|
For the fan-out + worktree + patch-integration + conflict mechanics, see `dispatching-parallel-agents`.
|
|
@@ -163,6 +171,8 @@ Run every plan task through this loop in a wave of N >= 1 tasks. Run waves in se
|
|
|
163
171
|
- **Lifecycle per task:** `pending → in_progress (wave fan-out) → complete (wave commit)`; keep `in_progress` through exhausted integration or repair attempts pending the human's decision (see [When a Subagent Fails](#when-a-subagent-fails)); use `failed` only for a human-decided terminal failure; `skipped` when the plan drops it as not applicable (terminal, counted done). A rejected `update` names the earlier pending tasks and the legal fixes - record those tasks' true state, never `clear` or re-`init` to move on.
|
|
164
172
|
- **Widget caveat (known, deliberately unfixed).** The persistent `plan_tracker` widget's icon strip (`○ → ✓`) and `(c/total)` count reflect every task, but its trailing *name* shows only the **first** `in_progress` task. Use the icon strip and the `status` action for the full in-flight view; a richer multi-task widget is a separate extension change, out of scope (YAGNI).
|
|
165
173
|
|
|
174
|
+
For an `in-place` wave, dispatch one `implementer` with `cwd` the branch checkout and no `worktree: true`; skip step 4 integration and step 7's `reset --soft` fold, retain the test gate, SR against the branch checkout, and CR, and record the next wave's `WAVE_BASE_SHA` after completion. Repair every SR gap (including initial `NEEDS_REWORK` / `OUT_OF_SCOPE_CHANGES`), stopped chain, test-gate failure, and CR finding with a plain in-place `implementer` in the branch checkout; record Fix-delta trees from that checkout, never use the snapshot/patch-replacement path, and after the gates accept, commit any remaining changes as one new descendant commit on the branch before marking indices `complete`, without amending or running `reset --soft` across the recorded rework base.
|
|
175
|
+
|
|
166
176
|
**Per-wave loop:**
|
|
167
177
|
|
|
168
178
|
1. **Independence check.** Parse the wave's tasks' `Files:` blocks; assert pairwise-disjoint (mechanical, mirroring `wave-file-disjointness`: `Test`/`Test` on one path is not overlap, `Test` vs another task's `Create`/`Modify` is, `Modify`/`Modify` is). Runtime-resource disjointness (DB/schema, port, fixture, external service, shared temp path) is not machine-checkable here — trust the plan's wave grouping, which `writing-plans`' D5 contract guarantees. Either kind of overlap → the wave is mis-grouped; split it into one-task waves and note it.
|
|
@@ -324,6 +334,8 @@ Record its review tree per [Fix delta](#fix-delta) before every parent-dispatche
|
|
|
324
334
|
|
|
325
335
|
## After All Tasks Complete
|
|
326
336
|
|
|
337
|
+
For a coordinated run, execute verification and the following reviews for every leg in its own checkout against its owned original ACs and recorded verification contract, under home flow policy. Keep freshness per leg and route repairs to their owning checkout; repeat invalidated gates there. After every leg passes, finish the coordinated run once from home. Keep legacy and single-member execution free of companion loops, leg files, `legs:` briefs and `--leg` arguments.
|
|
338
|
+
|
|
327
339
|
0. Call `phase_tracker({ action: "start", phase: "verify" })`. (The `implement` phase was started at execution start and auto-completes from `plan_tracker` once all tasks are done; this flow runs its own verify gate instead of `/skill:verification-before-completion`, so it must mark verify itself.)
|
|
328
340
|
1. **Parent full verification.** Run the complete plan-header `**Verification:**` command set foreground in the worktree via `(cd "<worktree>" && <command>)`: tests plus every declared lint, type, format, and build check. A failure must be repaired and the full set rerun successfully before the next step. Before dispatching a verification repair, reopen (`in_progress`) every existing plan-task index whose `Files:` ownership includes its touched files; leave unowned cross-cutting repair work in the verification report. Those indices stay `in_progress` through the successful full rerun **and** step 2's whole-diff review accepting the repair — that acceptance is their completion point, not the passing rerun. Commit any verification-produced tracked changes; use the resulting `HEAD_SHA` in the review task and include the commands/results in its existing `DESCRIPTION`.
|
|
329
341
|
2. **Whole-diff code review.** Only after passing full verification, dispatch one foreground whole-diff `code-reviewer` per `/skill:requesting-code-review` against that committed HEAD, with `SCOPED_TEST_COMMANDS: none`; the reviewer does not repeat the full suite. Act on the verdict per `/skill:requesting-code-review` Fix rounds; carry the final `SHIP` report's Minor finding lines verbatim into the closure block's `whole-diff minors:` section (`verification-before-completion/reference/conformance-check.md` "Closure / conformance"), or `whole-diff minors: none`. Before dispatching a review repair, reopen (`in_progress`) every existing plan-task index whose `Files:` ownership includes its touched files; leave unowned cross-cutting repair work in the review report. Mark each reopened index `complete` only once the repair is re-verified and the re-review accepts it — this is the same completion point step 1's reopened indices wait for, not an extra gate, and the gate order stays full verification -> whole-diff CR -> conformance. Any repair invalidates prior full verification, so rerun the full set successfully before the next gate.
|