pi-gauntlet 7.28.0 → 7.30.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 +23 -0
- package/README.md +15 -7
- package/agents/loop-implementer.md +51 -0
- package/bin/gauntlet-performance.mjs +5 -1
- package/bin/gauntlet-performance.test.mjs +19 -3
- package/bin/gauntlet-telemetry-seal.mjs +2 -2
- package/extensions/lib/gauntlet-settings.test.ts +10 -0
- package/extensions/lib/gauntlet-settings.ts +8 -0
- package/extensions/lib/plan-check.test.ts +63 -0
- package/extensions/lib/plan-check.ts +42 -0
- package/extensions/lib/telemetry-record.test.ts +19 -0
- package/extensions/lib/telemetry-record.ts +5 -3
- package/extensions/phase-tracker.test.ts +40 -0
- package/extensions/phase-tracker.ts +6 -2
- package/extensions/telemetry.test.ts +58 -4
- package/extensions/telemetry.ts +21 -12
- package/package.json +2 -2
- package/skills/brainstorming/SKILL.md +11 -7
- package/skills/brainstorming/gatherer.md +33 -2
- package/skills/brainstorming/reference/amendment-surface.md +6 -6
- package/skills/brainstorming/reference/pr-subject.md +51 -0
- package/skills/brainstorming/reference/spec-finalization.md +22 -6
- package/skills/brainstorming/reference/ticket-acceptance.md +2 -2
- package/skills/finishing-a-development-branch/SKILL.md +68 -11
- package/skills/gauntlet-handoff/SKILL.md +1 -2
- package/skills/gauntlet-resume/SKILL.md +7 -4
- package/skills/gauntlet-resume/reference/brief-contract.md +35 -11
- package/skills/gauntlet-resume/reference/reconstruction.md +24 -5
- package/skills/loop-implementation/SKILL.md +124 -0
- package/skills/using-git-worktrees/SKILL.md +3 -3
- package/skills/using-git-worktrees/reference/pr-head.md +74 -0
- package/skills/verification-before-completion/SKILL.md +3 -1
- package/skills/writing-plans/SKILL.md +5 -1
- package/skills/writing-plans/reference/plan-contract.md +4 -0
|
@@ -34,7 +34,9 @@ Then call `phase_tracker({ action: "start", phase: "ship" })`.
|
|
|
34
34
|
|
|
35
35
|
**Hard verification gate.** Tests/format/lint must pass before presenting any options — including Discard. The user's stated intent to throw the branch away does not change whether the diff is in a verifiable state; verifying first surfaces accidental damage to unrelated code before the branch is gone forever. The skip rule below is the only exception.
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
Read the selected run spec before verification. Detect a PR subject only by its `## Rework record`, never by an open PR on `$FEATURE`. Read `PR:` and the full `Pre-rework head:` into `PRE_REWORK_HEAD` from that record; missing pre-head -> stop naming the spec path. Confirm with `gh pr view <N> --json number,url,headRefName,baseRefName,state` (use the record's repository): non-`OPEN` -> stop: `PR #N is <state>; the rework cannot be pushed to it.`; headRefName != `$FEATURE` -> stop naming both branches. Retain baseRefName for Step 3.
|
|
38
|
+
|
|
39
|
+
Recognize a ledger by line 1 exactly `# Ledger - loop engine`. For a ledger, use its `verification:` command throughout finish, including the minors round. For a PR subject with a task plan, use the union of every plan task's `Tests:` commands plus the executable lint/format commands in the header's `**Verification:**` line; treat `none - PR subject, scoped` as no header commands, not an empty task union. Capture this set and accepted-complete task evidence before stripping the plan. Apply the hard gate and skip rule below to this set. For every other subject with a task plan, run the plan header's `**Verification:**` set in the worktree: `(cd "$WORKTREE" && <command>)`. With no plan in this session, run the verification command(s) of the affected services from the gauntlet overrides file or `AGENTS.md` (look for "verification", "CI", or "test" sections).
|
|
38
40
|
|
|
39
41
|
**Skip rule.** Skip the run only when this set passed on a known clean commit in the verify phase of this session and no edit or write landed outside `<telemetry.dir>` since. Check the current tree: `git -C "$WORKTREE" diff --quiet <commit the run passed on> -- . ':!<telemetry.dir>'` must exit 0, and `git -C "$WORKTREE" status --porcelain --untracked-files=all -- . ':!<telemetry.dir>'` must exit 0 with empty output (`<telemetry.dir>` defaults to `.pi/gauntlet/telemetry`). These checks cover committed, staged, unstaged, and untracked changes outside telemetry. Otherwise run it once; a missing verified commit, a failed check, or uncertainty means run.
|
|
40
42
|
|
|
@@ -61,10 +63,12 @@ No documentation prompt here: Documentation impact is decided at spec time (`/sk
|
|
|
61
63
|
|
|
62
64
|
### Step 2: Detect Environment
|
|
63
65
|
|
|
64
|
-
|
|
66
|
+
For a PR subject, use the Step 4 PR menu. For other subjects: detached HEAD (`git -C "$WORKTREE" symbolic-ref -q HEAD` prints nothing) -> reduced 4-option menu (no merge), no cleanup. Otherwise the standard 5 options.
|
|
65
67
|
|
|
66
68
|
### Step 3: Determine Base Branch
|
|
67
69
|
|
|
70
|
+
For a PR subject, set `<base-branch>` to the confirmed `baseRefName` and skip the common-base probe below.
|
|
71
|
+
|
|
68
72
|
```bash
|
|
69
73
|
# Try common base branches
|
|
70
74
|
git -C "$WORKTREE" merge-base HEAD main 2>/dev/null || git -C "$WORKTREE" merge-base HEAD master 2>/dev/null
|
|
@@ -169,7 +173,7 @@ A **heavy** revert is not a menu toggle — say so explicitly to the user before
|
|
|
169
173
|
|
|
170
174
|
### Step 4: Present Options
|
|
171
175
|
|
|
172
|
-
**Amendment digest (both variants).** Before the options, read `git -C "$WORKTREE" log <base-branch>..HEAD --grep '^amend:'` and take the `auto-apply` and `granted` records from those commit bodies. Render, then the options:
|
|
176
|
+
**Amendment digest (both variants).** Before the options, read `git -C "$WORKTREE" log <base-branch>..HEAD --extended-regexp --grep '^(amend:|loop: cut row [0-9]+|loop: amend)'` and take the `auto-apply` and `granted` records from those commit bodies. Render, then the options:
|
|
173
177
|
|
|
174
178
|
```
|
|
175
179
|
Amendments auto-applied (N):
|
|
@@ -178,6 +182,26 @@ Amendments auto-applied (N):
|
|
|
178
182
|
|
|
179
183
|
Omit the block when N = 0.
|
|
180
184
|
|
|
185
|
+
**PR subject - preflight and six-row menu.** Fetch origin with `git -C "$WORKTREE" fetch origin`; stop on failure. Run these proofs in order, against this worktree's HEAD:
|
|
186
|
+
| Proof | Exit 0 | Exit 1 |
|
|
187
|
+
|---|---|---|
|
|
188
|
+
| `git merge-base --is-ancestor <PRE_REWORK_HEAD> HEAD` | Continue | Stop: `PR branch history was rewritten: <PRE_REWORK_HEAD7> is not an ancestor of HEAD; the rework must be re-merged, not rebased.` |
|
|
189
|
+
| `git merge-base --is-ancestor origin/<headRefName> HEAD` | Offer push | Withhold push: `push withheld: origin/<headRefName> is at <sha7>, local HEAD at <sha7>; a non-force push cannot land` |
|
|
190
|
+
Run each proof with `git -C "$WORKTREE"`. Treat every exit other than 0 or 1 as a command error and stop with its output. For a withheld push only, separately prove `git -C "$WORKTREE" merge-base --is-ancestor <PRE_REWORK_HEAD> origin/<headRefName>`: exit 0 appends `(origin moved past the rework's base <PRE_REWORK_HEAD7>)`; exit 1 adds nothing; other exits stop as command errors. Divergence alone proves no origin advance.
|
|
191
|
+
Read and apply [menu-layout](../brainstorming/reference/menu-layout.md) for rendering and numeric replies. Present:
|
|
192
|
+
```
|
|
193
|
+
Implementation complete. What would you like to do?
|
|
194
|
+
|
|
195
|
+
1. Push to the PR branch (PR #N, <headRefName>; appends the rework block to its description)
|
|
196
|
+
2. Push and create a Pull Request (PR #N already exists on this branch; gh refuses a second one)
|
|
197
|
+
3. Push and create a draft Pull Request (same: PR #N already exists)
|
|
198
|
+
4. Squash-merge to <base-branch> (no PR, no surviving branch; orphans PR #N - close it by hand)
|
|
199
|
+
5. Keep the branch as-is (I'll handle it later; nothing is pushed)
|
|
200
|
+
6. Discard this work (removes the worktree and local branch; the PR branch on origin is untouched)
|
|
201
|
+
|
|
202
|
+
Which option?
|
|
203
|
+
```
|
|
204
|
+
Withhold row 1 by omitting it and placing `Withheld: push - <reason>` under the list; retain numbers 2-6. On that withheld menu read a bare reply by its displayed label: `2`-`6` select those rows; `1` or any other number gets the clarifying question naming `2`-`6` (this one menu overrides menu-layout's count-based `1`-`N` range). Recompute preflight on return to the menu. Add no approval gate. Map rows 2-6 to the existing Options 1-5 below, including their confirmation and cleanup rules; row 6 never deletes origin's branch.
|
|
181
205
|
**Normal repo and named-branch worktree — present exactly these 5 options:**
|
|
182
206
|
|
|
183
207
|
Read and apply [menu-layout](../brainstorming/reference/menu-layout.md) before presenting these options and before acting on a numeric reply.
|
|
@@ -213,7 +237,7 @@ Rows 1-2 run the Option 1/2 blocks; row 3 runs the Keep block and row 4 the Disc
|
|
|
213
237
|
|
|
214
238
|
**Don't add explanation** - keep options concise. When the minors line lists findings and the block has no `whole-diff minors fix:` line, add only this line under the menu: `Or reply "fix minors" (or "fix minors F3, F9") for one Minor fix round.` This line is the only addition to the exact numbered options.
|
|
215
239
|
|
|
216
|
-
**Standalone extra reply - `fix minors`.** When the rendered `whole-diff minors` line lists findings, `fix minors` (all) or `fix minors F3, F9` (a subset by `Fn`) is a valid reply beside the numbered options. It dispatches one `implementer` round (`cwd` = the worktree; task = the selected finding lines verbatim; `SCOPED_TEST_COMMANDS` = the plan-header verification set),
|
|
240
|
+
**Standalone extra reply - `fix minors`.** When the rendered `whole-diff minors` line lists findings, `fix minors` (all) or `fix minors F3, F9` (a subset by `Fn`) is a valid reply beside the numbered options. It dispatches one `implementer` round (`cwd` = the worktree; task = the selected finding lines verbatim; `SCOPED_TEST_COMMANDS` = for PR subjects, the executable scoped union captured in Step 1, excluding `none - PR subject, scoped`; for other subjects, the plan-header verification set). For a ledger, supply its `verification:` command instead. For PR subjects, require successful evidence for every supplied command after the fix; failed or missing evidence stops before returning to the menu. Commit `whole-diff minors fix` and return to Step 3.5, where the freshness rule re-audits conformance as for any working-tree change and the regenerated block records the spent round (`whole-diff minors fix: <full SHA>`); Step 4 then re-renders. No code review follows this round: the whole-diff review is an unscoped first review, so its Minors are graded Minors. A block that already carries `whole-diff minors fix:` refuses the reply with "minors round already spent". Any numbered choice ships without them.
|
|
217
241
|
|
|
218
242
|
### Step 5: Execute Choice
|
|
219
243
|
|
|
@@ -221,11 +245,11 @@ Rows 1-2 run the Option 1/2 blocks; row 3 runs the Keep block and row 4 the Disc
|
|
|
221
245
|
|
|
222
246
|
Run this on the feature branch before any landing path. The spec and its telemetry record (`<telemetry.dir>/<spec path with .md -> .yaml>`, default `.pi/gauntlet/telemetry/doc/specs/<spec>.yaml`) are deliverables and ship in the squash; only the plan is stripped. The record is an untracked, git-excluded file until this step commits it (in a plain jj workspace there is no commit; jj snapshots the stamped record into the working-copy change). `<bin>` is `<directory of this skill's SKILL.md>/../../bin`, resolved from the skill's `<location>` in the system prompt.
|
|
223
247
|
|
|
224
|
-
Read the
|
|
248
|
+
Read the existing artifact's path-only `**Spec:**` header (repo-relative, backticks stripped) before removal; pass that value as `--spec`, including for a line-1 ledger. Resolve the spec dirs with `gauntlet_setting({ key: "flowGuards" })` and use their sibling `plans` dirs for plan paths. Enumerate both PLAN_PATH candidates: the task plan paired by basename and `<sibling plans dir>/<spec stem>-ledger.md`. Preserve the spec and telemetry.
|
|
225
249
|
|
|
226
250
|
```bash
|
|
227
251
|
# Plans are ephemeral - if one was committed on this branch, remove it before landing.
|
|
228
|
-
PLAN_PATH
|
|
252
|
+
for PLAN_PATH in <basename-task-plan-path> <sibling-plans-dir>/<spec-stem>-ledger.md; do
|
|
229
253
|
if git -C "$WORKTREE" ls-files --error-unmatch "$PLAN_PATH" >/dev/null 2>&1; then
|
|
230
254
|
git -C "$WORKTREE" rm "$PLAN_PATH" && git -C "$WORKTREE" commit -m "Remove ephemeral plan doc"
|
|
231
255
|
elif [ -f "$WORKTREE/$PLAN_PATH" ] && jj -R "$WORKTREE" root >/dev/null 2>&1; then
|
|
@@ -233,15 +257,46 @@ elif [ -f "$WORKTREE/$PLAN_PATH" ] && jj -R "$WORKTREE" root >/dev/null 2>&1; th
|
|
|
233
257
|
# root: anchors the path at the workspace root - jj resolves bare paths against cwd, not -R.
|
|
234
258
|
jj -R "$WORKTREE" restore --from <base-branch> -- "root:\"$PLAN_PATH\""
|
|
235
259
|
fi
|
|
260
|
+
done
|
|
236
261
|
|
|
237
262
|
# Seal the telemetry record: stamp shipped, compute the diff, commit it once.
|
|
238
263
|
# The bin detects a plain jj workspace (no .git) itself: jj diff, no commit step.
|
|
239
|
-
# --option is pr for Options 1-2 and squash for Option 3; --spec is the
|
|
264
|
+
# --option is pr for Options 1-2 and squash for Option 3; --spec is the artifact header's **Spec:** value (omit when no artifact is known).
|
|
240
265
|
node <bin>/gauntlet-telemetry-seal.mjs --worktree "$WORKTREE" --option <pr|squash> --base <base-branch> --spec <spec path>
|
|
241
266
|
```
|
|
242
267
|
|
|
243
268
|
The seal prints one line per record (`sealed <path>`, `already sealed <path>`) or one bare outcome (`no telemetry run`, `telemetry disabled`) and exits 0; print its stdout verbatim in the ship completion message. Any nonzero exit stops the flow before the first landing command, quoting the bin's line: exit 2 (`no record at <path>`, `unparseable record <path>: <reason>`) means this gauntlet run's recorder never armed or its record is corrupt; exit 1 is a usage, environment, or git/jj failure (`seal failed <path>: <reason>` restored the pre-seal bytes). The user decides; never land without the seal.
|
|
244
|
-
|
|
269
|
+
#### PR-subject row 1: Push to the PR branch
|
|
270
|
+
Capture the scoped verification set and thread evidence before the strip. Refetch unresolved threads with the query owned by [pr-head](../using-git-worktrees/reference/pr-head.md); preserve recorded dispositions, use the table below, and omit threads now resolved on GitHub. Use the query's location rendering.
|
|
271
|
+
| Refetched thread / evidence | Resolution |
|
|
272
|
+
|---|---|
|
|
273
|
+
| Recorded `fix`, matching task title carries id, task accepted by spec and code review and `complete`, exactly one naming commit | `fixed in <sha7>` |
|
|
274
|
+
| Same accepted-complete task, zero or multiple naming commits | `fixed (task "<title>" complete; no single commit names <thread id>)` |
|
|
275
|
+
| Missing or incomplete task; recorded `keep open`; newly opened thread | `still open` |
|
|
276
|
+
| Recorded `decline` | `declined - <reason>` |
|
|
277
|
+
| Successful fetch, empty set | `Threads: none` |
|
|
278
|
+
| Fetch failure | `Threads: not fetched (<reason>)` |
|
|
279
|
+
Count naming commits with `git -C "$WORKTREE" log --first-parent --format=%h --grep '<thread id>' <merge-sha | PRE_REWORK_HEAD>..HEAD` (merge SHA from the record when present). A touched file, grep match, or first-parent filter alone is not completion proof.
|
|
280
|
+
Run the existing strip-and-seal block with `--option pr --base origin/<baseRefName>` and the selected spec; retain its stop-on-error behavior. This seal measures the whole PR, not rework-only; never use PRE_REWORK_HEAD as its base. Then:
|
|
281
|
+
```bash
|
|
282
|
+
git -C "$WORKTREE" update-ref refs/gauntlet/pre-rework/pr-<N> <PRE_REWORK_HEAD>
|
|
283
|
+
git -C "$WORKTREE" push --no-follow-tags origin HEAD:refs/heads/<headRefName>
|
|
284
|
+
```
|
|
285
|
+
Stop on update-ref failure. Report a rejected push once, skip body editing, and return to the menu without retrying or forcing. Preserve the worktree.
|
|
286
|
+
After a successful push, fetch the description fresh with `gh pr view <N> --json body` in the record's repository. Decode the JSON body without trimming or shell command substitution (which loses trailing newlines). Create a scratch body file with `mktemp` outside the repo; write the existing body bytes exactly, then one blank line, then this block:
|
|
287
|
+
```markdown
|
|
288
|
+
## Rework
|
|
289
|
+
|
|
290
|
+
Before: <PRE_REWORK_HEAD> (local ref `refs/gauntlet/pre-rework/pr-<N>` in the rework checkout; the SHA is the portable handle and stays on origin because the push was not forced)
|
|
291
|
+
Spec: <spec path> at <HEAD7>
|
|
292
|
+
Keeps: <from the record>
|
|
293
|
+
Changes: <from the record>
|
|
294
|
+
Dropped claims: <none | one "No longer true: <claim>" line per dropped claim>
|
|
295
|
+
Verification: scoped - <commands>; CI on this push holds the full run. Telemetry: whole PR against <baseRefName>.
|
|
296
|
+
Threads:
|
|
297
|
+
- <path>:<line> - <resolution from the table>
|
|
298
|
+
```
|
|
299
|
+
Put `supersedes the description above` on the block's second line only when every original claim is dropped. Use `Threads: none` or `Threads: not fetched (<reason>)` instead of the list for those outcomes. Run `gh pr edit <N> --body-file <scratch-file>` in the record's repository without another approval. On body fetch/edit failure, keep the push and print the block for manual paste with the error; never replace the description with just the block. Post no review-thread replies, merge no PR, and change no ticket state.
|
|
245
300
|
#### Option 1: Push and Create PR
|
|
246
301
|
|
|
247
302
|
Run the strip-and-seal block above first (plan stripped, telemetry record sealed), then:
|
|
@@ -353,6 +408,7 @@ Removal precedes branch deletion in both options; `git branch -d`/`-D` fails whi
|
|
|
353
408
|
|
|
354
409
|
| Option | Merge | Push | Keep Worktree | Cleanup Branch | Plan strip + record seal |
|
|
355
410
|
|---|---|---|---|---|---|
|
|
411
|
+
| PR row 1. Push to PR branch | - | yes (non-force) | yes | - | yes (whole PR; see row 1 recipe) |
|
|
356
412
|
| 1. Create PR | - | yes | yes | - | yes (guarded, on the branch before push) |
|
|
357
413
|
| 2. Create draft PR | - | yes | yes | - | yes (guarded, on the branch before push) |
|
|
358
414
|
| 3. Squash-merge locally | yes (squash) | - | - | yes (after Step 6 removal) | yes (guarded, on the branch before squash) |
|
|
@@ -369,7 +425,7 @@ A host-owned worktree (Step 6: no `home:` match, or the legacy "Otherwise") keep
|
|
|
369
425
|
|
|
370
426
|
**Open-ended questions**
|
|
371
427
|
- **Problem:** "What should I do next?" is ambiguous
|
|
372
|
-
- **Fix:**
|
|
428
|
+
- **Fix:** Use the Step 4 subject-specific menu
|
|
373
429
|
|
|
374
430
|
**Cleaning up worktree for a PR option (1 or 2)**
|
|
375
431
|
- **Problem:** Remove worktree user needs for PR iteration
|
|
@@ -401,7 +457,7 @@ A host-owned worktree (Step 6: no `home:` match, or the legacy "Otherwise") keep
|
|
|
401
457
|
|
|
402
458
|
## Completion
|
|
403
459
|
|
|
404
|
-
Once the chosen option (Options 1-4
|
|
460
|
+
Once the chosen option (Options 1-4 or PR-subject row 1 - not Discard) is executed successfully, mark the ship phase complete:
|
|
405
461
|
|
|
406
462
|
```
|
|
407
463
|
phase_tracker({ action: "complete", phase: "ship" })
|
|
@@ -416,6 +472,7 @@ Once the merge (and any deploy) has landed, `/skill:check-delivery <ticket-ref>`
|
|
|
416
472
|
- Merge without verifying tests on result
|
|
417
473
|
- Delete work without confirmation
|
|
418
474
|
- Force-push without explicit request
|
|
475
|
+
- Force-push a PR-subject rework; follow its row 1 recipe
|
|
419
476
|
- Remove a worktree before confirming merge success
|
|
420
477
|
- Clean up worktrees you didn't create (provenance check)
|
|
421
478
|
- Retry a failed `destroy:` with `git worktree remove --force`
|
|
@@ -428,7 +485,7 @@ Once the merge (and any deploy) has landed, `/skill:check-delivery <ticket-ref>`
|
|
|
428
485
|
- Verify, or apply the Step 1 skip rule, before offering options
|
|
429
486
|
- Print the `gauntlet-telemetry-seal.mjs` output verbatim in the ship completion message
|
|
430
487
|
- Derive `$PRIMARY` and `$FEATURE` from `<worktree-path>` before presenting the menu
|
|
431
|
-
-
|
|
488
|
+
- Use the Step 4 subject-specific menu
|
|
432
489
|
- Get typed confirmation for Option 5 (Discard)
|
|
433
490
|
- Clean up worktree for Options 3 & 5 (Squash-merge, Discard) only
|
|
434
491
|
- Target `$PRIMARY` with `git -C` for merge, worktree removal, and branch deletion
|
|
@@ -83,8 +83,7 @@ loop: tracker state is extension state no subagent can read.
|
|
|
83
83
|
- A phase `in_progress` (verify or ship included - resume stops at verify on its own)
|
|
84
84
|
-> append the process-state section exactly as `## Producers` in
|
|
85
85
|
`reference/brief-contract.md` lays it out: both status outputs verbatim
|
|
86
|
-
(`No plan active.` verbatim when there is no plan), the
|
|
87
|
-
the first `→` task else `none`, the gate-history line. Append with a single
|
|
86
|
+
(`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 its PR identity (without the title) and full pre-rework head 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
87
|
`cat >> "<brief path>" <<'EOF' ... EOF` whose body is that block.
|
|
89
88
|
- Re-read the file tail and confirm it ends with the gate-history line from the
|
|
90
89
|
contract and nothing after.
|
|
@@ -100,7 +100,7 @@ checks 2, 4, 5 do not apply; check 6 runs on the seed's pinned spec path.
|
|
|
100
100
|
6. **Grant field.** Runs once the route has resolved `<spec path>` - the `S` path that
|
|
101
101
|
`reference/brief-contract.md` "Process-state restore" resolves for `skip brainstorm`
|
|
102
102
|
(process-state briefs), the spec reconstruction resolves and the human approves
|
|
103
|
-
(Spec without plan) or confirms (Spec with plan) (`reference/reconstruction.md`), or
|
|
103
|
+
(Spec without plan) or confirms (Spec with ledger or Spec with plan) (`reference/reconstruction.md`), or
|
|
104
104
|
the pinned `<full-path>/<rel>` of a spec tracked on `main` (`reference/seed.md`) -
|
|
105
105
|
and before that route's first tracker call; the path is carried, never re-resolved.
|
|
106
106
|
Read the spec's header block (between the H1 and the first `##`) through the
|
|
@@ -142,9 +142,12 @@ owning skill **without** its reset-bearing entry:
|
|
|
142
142
|
| Active after restore | Continue in | Entry point |
|
|
143
143
|
|---|---|---|
|
|
144
144
|
| 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) |
|
|
145
|
-
|
|
|
146
|
-
|
|
|
147
|
-
|
|
|
145
|
+
| 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": settings step 1, verification step 2, driver's plan skip step 3, ledger creation step 4, check/commit and implement start step 5; no writing-plans body or task tracker |
|
|
146
|
+
| plan with task engine | writing-plans body | skip its `start plan` call (already in_progress) |
|
|
147
|
+
| implement with line-1 ledger | loop-implementation | complete `reference/reconstruction.md` "Spec with ledger" ordered restore, cited by `reference/brief-contract.md`'s call table: entry checks 1-6, brainstorm start/skip, plan start/check/skip with reason `resume: <spec> (loop engine)`, implement start, no task tracker; state the entire ordered sequence explicitly even when entry checks are already reported as passed; then continue at step 5 (`Before each dispatch`), preserving ledger iterations/retry data; dirty tree stops before dispatch; reuse the existing ledger |
|
|
148
|
+
| 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 |
|
|
149
|
+
| verify with `Ledger:` (including ship-stage ledger briefs restored at verify) | /skill:loop-implementation | read `After the loop` and its references; continue from step 1, full ledger verification, after the already-restored `start verify`; retain whole-diff code review, happy path when triggered, fresh conformance review and finishing; no task-tracker calls |
|
|
150
|
+
| verify without `Ledger:` | verification-before-completion | full conformance gate; nothing carried over |
|
|
148
151
|
|
|
149
152
|
## Red flags — STOP
|
|
150
153
|
|
|
@@ -27,11 +27,19 @@ 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>`; 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 `PR: <owner/repo#N>` and `Pre-rework head: <40-char sha>` lines, present together 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 |
|
|
31
|
+
|
|
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
|
+
|
|
34
|
+
```text
|
|
35
|
+
Ledger: <path>
|
|
36
|
+
Last decision: <line>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Use the ledger path relative to the worktree and the last physical decision line, or `none` for an empty Decisions section. Read the ledger on disk; the brief is a pointer, not a second state carrier. Reject a block mixing these fields with `Active task`, missing either loop field, or carrying task rows with a ledger. Never initialize a task tracker for a ledger.
|
|
31
40
|
|
|
32
41
|
Consumer rules: process state absent -> plain handoff (the consumer starts its
|
|
33
|
-
own process from `## Intent`)
|
|
34
|
-
plan; loading named skills is the consumer's job.
|
|
42
|
+
own process from `## Intent`). Give valid ledger fields precedence over `No plan active.` and run ledger admission. Restore phase-only state for `No plan active.` only with no `Ledger` field. Load named skills as the consumer.
|
|
35
43
|
|
|
36
44
|
A brief is any text whose first line starts `# Handoff:` - a file on disk or pasted
|
|
37
45
|
inline. `## Repo state` is matched by prefix: `## Repo state` or
|
|
@@ -43,8 +51,10 @@ inline. `## Repo state` is matched by prefix: `## Repo state` or
|
|
|
43
51
|
cohort's `handoff` skill wrote, which ends at `## Skills loaded`. Layout, byte-exact:
|
|
44
52
|
one blank line, the heading on its own line, a blank line, the `phase_tracker status`
|
|
45
53
|
output verbatim, a blank line, the `plan_tracker status` output verbatim, a blank line,
|
|
46
|
-
`Active task: <name|none>`, then
|
|
47
|
-
`
|
|
54
|
+
`Active task: <name|none>`, then, only for a PR subject, exactly two lines:
|
|
55
|
+
`PR: <owner/repo#N>` and `Pre-rework head: <40-char sha>`, then the gate-history line -
|
|
56
|
+
unfenced, nothing after.
|
|
57
|
+
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 pair before the gate-history line.
|
|
48
58
|
|
|
49
59
|
Example appended block (the fence is documentation; the brief carries no fence):
|
|
50
60
|
|
|
@@ -104,6 +114,15 @@ Parse stops (print the offending line, make no tracker call):
|
|
|
104
114
|
|
|
105
115
|
## Process-state restore
|
|
106
116
|
|
|
117
|
+
Before any tracker write, read the optional PR identity and fetch its branch with
|
|
118
|
+
`gh pr view <N> --repo <owner/repo> --json headRefName`. Compare `headRefName` with
|
|
119
|
+
`git -C <worktree> branch --show-current`. A mismatch stops with
|
|
120
|
+
`brief names PR #N on <headRefName>, worktree is on <branch>`, substituting the observed PR number and both actual branch names, never literal placeholders; a failed fetch stops
|
|
121
|
+
with its error. Carry the paired full pre-rework head into reconstruction's
|
|
122
|
+
candidate selection. Without the optional pair, retain ordinary restoration.
|
|
123
|
+
Preserve the entry checks, standing-grant validation, plan repair, and task snapshot;
|
|
124
|
+
PR identity implies no approval or gate evidence.
|
|
125
|
+
|
|
107
126
|
Facts that fix the order (from the extensions):
|
|
108
127
|
|
|
109
128
|
- Arming happens only on `start brainstorm`; `reset` disarms; `skip` and `complete`
|
|
@@ -121,7 +140,7 @@ Per-stage call table, keyed by the brief's active phase (`→`). Use
|
|
|
121
140
|
`R = resume: <brief file or "pasted brief">` for plan/implement/verify skips and
|
|
122
141
|
`S = resume: <spec path>` for brainstorm skips. Resolve `<spec path>` as
|
|
123
142
|
`reconstruction.md` "Candidates" does, to an absolute path under the worktree: the single
|
|
124
|
-
`*.md` spec added after base under `flowGuards.specDirs`, or a spec tracked from base when
|
|
143
|
+
`*.md` spec added after the candidate base under `flowGuards.specDirs`, or a spec tracked from that base when
|
|
125
144
|
a plan added after base pairs with it by basename. Zero specs -> stop; more than one ->
|
|
126
145
|
human picks. The consumer carries this path to its entry check 6 and its post-restore
|
|
127
146
|
announcement without re-resolving it.
|
|
@@ -130,13 +149,16 @@ announcement without re-resolving it.
|
|
|
130
149
|
|---|---|
|
|
131
150
|
| brainstorm | `start brainstorm`; `substep` if the brief shows one |
|
|
132
151
|
| plan | `start brainstorm`; `skip brainstorm S`; `start plan`; `substep` if shown |
|
|
133
|
-
| implement | `start brainstorm`; `skip brainstorm
|
|
152
|
+
| 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`; render rows and last decision; 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. |
|
|
153
|
+
| 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` |
|
|
134
154
|
| verify | as implement through `skip plan R`, then `skip implement R`; `start verify`; `substep` if shown; `plan_tracker init` |
|
|
135
155
|
| 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 |
|
|
136
156
|
|
|
137
|
-
`
|
|
157
|
+
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 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.
|
|
158
|
+
|
|
159
|
+
`planPath` (task-plan implement onward): the brief carries none. Resolve as reconstruction does
|
|
138
160
|
(`reconstruction.md`, "Candidates", including its `flowGuards.specDirs` resolution): the
|
|
139
|
-
single plan added after base, paired with `<specDir>/<same basename>` whether that
|
|
161
|
+
single plan added after the candidate base, paired with `<specDir>/<same basename>` whether that
|
|
140
162
|
spec was added after base or tracked from base (`reconstruction.md` "Candidates");
|
|
141
163
|
resolve the selected plan to an absolute path under the worktree before `plan_check`.
|
|
142
164
|
Zero pairs -> stop; more than one -> human picks.
|
|
@@ -165,7 +187,7 @@ End a turn awaiting selection, restoration, or answers with phase `plan` retaine
|
|
|
165
187
|
|
|
166
188
|
### Citation repair
|
|
167
189
|
|
|
168
|
-
Record the plan's state before any write: tracked and clean when `git -C <worktree> ls-files --error-unmatch -- <plan path>` exits 0 and `git -C <worktree> status --porcelain -- <plan path>` prints nothing (index and working copy both match HEAD; a staged edit alone makes it dirty); otherwise copy the file to a temp path outside the
|
|
190
|
+
Record the plan's state before any write: tracked and clean when `git -C <worktree> ls-files --error-unmatch -- <plan path>` exits 0 and `git -C <worktree> status --porcelain -- <plan path>` prints nothing (index and working copy both match HEAD; a staged edit alone makes it dirty); otherwise copy the file to a temp path outside the repository before citation repair writes anything. Any non-empty porcelain output, including staged-only `M <plan path>`, takes this copy path even when tracked and the working copy equals HEAD. Never substitute `git checkout` for the dirty or untracked plan's snapshot or saved-copy restore.
|
|
169
191
|
|
|
170
192
|
Classify every finding against the table by its `check` and `reason`, gathering the row's evidence first. One finding with no row -> stop (below) before any write.
|
|
171
193
|
|
|
@@ -214,7 +236,9 @@ Every restore ends with:
|
|
|
214
236
|
Gate history not restored; re-validating `<task>` before any stage advance
|
|
215
237
|
```
|
|
216
238
|
|
|
217
|
-
|
|
239
|
+
For a ledger, use `ledger rows` as `<task>` and render the current rows and last decision from disk.
|
|
240
|
+
|
|
241
|
+
For a task plan, `<task>` is the brief's `Active task`, else the first in-progress task, else `none`
|
|
218
242
|
(whole-deliverable re-validation). Gate history, closure-review evidence, and fix rounds
|
|
219
243
|
are never inferred or restored; a ship-stage brief resumes at verify.
|
|
220
244
|
|
|
@@ -25,6 +25,12 @@ 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 `Pre-rework head:`, use that full SHA as `<base>` for spec
|
|
29
|
+
and plan candidate scans instead of the merge-base from "Base"; the PR's earlier
|
|
30
|
+
spec remains input, not an added candidate, so it does not trigger a multi-spec pick.
|
|
31
|
+
Keep pairing, untracked candidates, task evidence, and human confirmation below.
|
|
32
|
+
Without the optional pair, including a bare worktree, use the ordinary base.
|
|
33
|
+
|
|
28
34
|
Resolve with `gauntlet_setting({ key: "flowGuards" })`; `<dirs>` below is its `specDirs` plus `planDirs` (each spec dir's sibling `plans` dir), space-separated.
|
|
29
35
|
|
|
30
36
|
```bash
|
|
@@ -35,7 +41,7 @@ git -C <worktree> ls-files --others --exclude-standard -- <dirs>
|
|
|
35
41
|
Candidates are files under those directories added after base, plus untracked files
|
|
36
42
|
there. Paths returned by these commands are relative to `<worktree>`; resolve them to
|
|
37
43
|
absolute paths under `<worktree>` before reading artifacts, showing paths in prompts,
|
|
38
|
-
or calling `plan_check`.
|
|
44
|
+
or calling `plan_check`. Read every plan-directory candidate's first line. A line exactly `# Ledger - loop engine` pairs by its path-only `**Spec:**` header, not basename; resolve that spec under the worktree's configured spec dirs, including a spec tracked from base. Stop on a missing or foreign spec. A task-plan candidate pairs with
|
|
39
45
|
`<worktree>/<specDir>/<same basename>` whether that spec is a candidate or tracked
|
|
40
46
|
from base; count a base-tracked spec so paired as a spec in the route table below.
|
|
41
47
|
The plan commit is the first
|
|
@@ -48,7 +54,8 @@ plan commit; treat every task as `pending`.
|
|
|
48
54
|
| no spec | stop; offer `/skill:brainstorming` or pass the spec: `/skill:gauntlet-resume <specDir>/<name>.md`; no tracker call |
|
|
49
55
|
| more than one spec | the human picks one, then continue below with that spec |
|
|
50
56
|
| one spec, no plan | "Spec without plan" |
|
|
51
|
-
| one spec with
|
|
57
|
+
| one spec with ledger | "Spec with ledger" (takes precedence over a task plan) |
|
|
58
|
+
| one spec with task plan only | "Spec with plan" |
|
|
52
59
|
|
|
53
60
|
## Spec without plan
|
|
54
61
|
|
|
@@ -56,14 +63,26 @@ Ask exactly one question: is this spec approved, or do you select `/skill:brains
|
|
|
56
63
|
with this unapproved spec as the draft? Show the spec path (and the brief's
|
|
57
64
|
`## Intent`/`## Decisions` when present).
|
|
58
65
|
|
|
59
|
-
- Approved: run SKILL.md entry check 6 on `<spec path>` first (a malformed `**Amend-grant:**` line stops here, no tracker call)
|
|
60
|
-
|
|
61
|
-
|
|
66
|
+
- Approved: run SKILL.md entry check 6 on `<spec path>` first (a malformed `**Amend-grant:**` line stops here, no tracker call). Read the spec's `**Engine:**` line and take the matching route:
|
|
67
|
+
- `loop`: call `start brainstorm`, then `skip brainstorm` with reason `resume: <spec path>` to arm the flow before `plan_check`. Carry absolute worktree/spec paths and the resolved plan directory into `/skill:loop-implementation` Entry steps 1-5: resolve settings at step 1 and verification at step 2, retain the driver's `skip plan` at step 3, create the ledger at step 4, then check/commit it and start implement at step 5. Never enter the writing-plans body or initialize a task tracker.
|
|
68
|
+
- `waves` or absent: `start brainstorm`; `skip brainstorm resume: <spec path>`; `start plan`; continue in writing-plans, skipping its `start plan` call.
|
|
62
69
|
- Selected unapproved-draft brainstorming handoff: invoke [`/skill:brainstorming`](../../brainstorming/SKILL.md) with
|
|
63
70
|
the spec as the draft; arm nothing. using-git-worktrees Step 0 detects the existing
|
|
64
71
|
worktree and creates none. A bare "not approved" answer is not consent; wait for
|
|
65
72
|
explicit handoff selection.
|
|
66
73
|
|
|
74
|
+
## Spec with ledger
|
|
75
|
+
|
|
76
|
+
Show the spec and ledger paths, current rows, iterations, last decision, and `git -C <worktree> status --porcelain`. Ask the human to confirm the approved spec and continuation; carry brief Intent/Decisions when present. Keep entry and same-repository checks.
|
|
77
|
+
|
|
78
|
+
After confirmation:
|
|
79
|
+
|
|
80
|
+
1. Read ledger line 1: require `# Ledger - loop engine`. Resolve its path-only `**Spec:**` header to an absolute spec path under the worktree's configured spec directories, not by basename. Run SKILL.md entry checks 1-6 in order, including check 6, **Grant field**, on that spec, before any tracker mutation.
|
|
81
|
+
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" })`.
|
|
82
|
+
3. Call `plan_check({ planPath: <absolute ledger path> })`. On FAIL, stop with findings, retaining plan in_progress; 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`.
|
|
83
|
+
4. Read `/skill:loop-implementation`; resolve its Entry settings/maxIterations without creating or overwriting the ledger. Restore base, verification, iterations, row attempts, funding and retry allowances from the ledger/spec and branch. Render rows and last decision. A dirty tree stops before any dispatch using the driver's dirty-tree stop note; preserve changes for the human.
|
|
84
|
+
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.
|
|
85
|
+
|
|
67
86
|
## Spec with plan
|
|
68
87
|
|
|
69
88
|
Show, and ask the human to confirm or edit both in one reply:
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: loop-implementation
|
|
3
|
+
description: Use after approval selects the loop engine, or when resuming an acceptance-criteria ledger in the implement phase.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Loop implementation
|
|
7
|
+
|
|
8
|
+
Run this driver in the main session. Carry the absolute implementation worktree path as a value; run git with `git -C "<worktree>"` and commands as `(cd "<worktree>" && <command>)`. Use the approved spec and resolved plan directory. Read the spec in full. Keep the original prompt for verify. Never initialize a task tracker or run reviewers inside implement.
|
|
9
|
+
|
|
10
|
+
## Entry
|
|
11
|
+
|
|
12
|
+
1. Read project overrides below. Resolve `gauntlet_setting({ key: "loopEngine" })` and retain `maxIterations` (default 30). Stop on an unavailable settings tool.
|
|
13
|
+
2. Resolve verification once using this ordered table. Print `verification command: <command> (<source>)`.
|
|
14
|
+
|
|
15
|
+
| Observed configuration | Action |
|
|
16
|
+
|---|---|
|
|
17
|
+
| Overrides `## PR gate` contains `- verification command:` | Use that command; source PR gate. |
|
|
18
|
+
| Otherwise overrides has `## verification-before-completion` | Use its exactly one backticked command; zero or several is a configuration error. |
|
|
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
|
+
|
|
21
|
+
3. Call `phase_tracker({ action: "skip", phase: "plan", reason: "loop engine" })`.
|
|
22
|
+
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
|
+
|
|
24
|
+
```markdown
|
|
25
|
+
# Ledger - loop engine
|
|
26
|
+
**Spec:** `doc/specs/example.md`
|
|
27
|
+
base: <HEAD SHA before skeleton>
|
|
28
|
+
verification: <resolved command>
|
|
29
|
+
iterations: 0
|
|
30
|
+
|
|
31
|
+
| row | status | attempts | evidence |
|
|
32
|
+
|---|---|---|---|
|
|
33
|
+
| 1 | open | 0 | |
|
|
34
|
+
|
|
35
|
+
## Decisions
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Use the actual repo-relative spec path alone in the Spec header. Read base with `git -C "<worktree>" rev-parse HEAD`. Index every spec AC in order, including nested disposition lines without treating them as extra ACs; keep row text only in the spec. Initialize explicit/absent `in-scope` and `venue:` rows `open`, attempts 0, evidence empty. Initialize only `deviates:`, `deferred:`, `elsewhere:` rows `cut`, attempts 0, disposition text as evidence. Serialize evidence in one physical table cell, result lines separated by semicolons, pipes escaped, plain text without angle markup.
|
|
39
|
+
5. Call `plan_check({ planPath: <ledger path> })`. Stop with findings as a configuration error. Commit the stamped skeleton as `loop: seed ledger`; call `phase_tracker({ action: "start", phase: "implement" })`.
|
|
40
|
+
|
|
41
|
+
For resume, use the admitted ledger, its base and verification command, and durable iterations instead of overwriting it. Render rows and last decision; stop on a dirty tree before dispatch.
|
|
42
|
+
|
|
43
|
+
## Before each dispatch
|
|
44
|
+
|
|
45
|
+
Read the ledger. 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:
|
|
46
|
+
|
|
47
|
+
| Order | Observed state | Action |
|
|
48
|
+
|---|---|---|
|
|
49
|
+
| 1 | No `open` or `failed` row | Exit verification. All-cut and baseline-complete ledgers exit normally. |
|
|
50
|
+
| 2 | Unresolved row attempts at its allowance | Human stop. Exempt `done` and `cut`, including third-attempt success. |
|
|
51
|
+
| 3 | Last two child row commits both changed no file outside the ledger and no row status | Human stop, regardless of funding. Count child `loop: row ...` commits only, excluding seed and parent repair/retry/cut commits. A decision alone is not progress. |
|
|
52
|
+
| 4 | `iterations` >= `maxIterations` | Human stop naming cap, unresolved rows and attempts, before verification. Seed and interrupted dispatches count. |
|
|
53
|
+
| 5 | Dispatch allowed | Select target by the priority below. |
|
|
54
|
+
|
|
55
|
+
Set row allowance to 3 + funded N, increased to the latest `row <n> retry` decision's `allowed attempts <m>` when larger. Recover spent funding per row as `max(0, attempts - 3)`; a mid-loop grant applies prospectively. Before dispatch on a funded row with attempts >= 3 and spent < N print `funded round <k> of <N> for row <n>`, with k = attempts - 3 + 1. Funding buys neither cap bypass nor empty-commit bypass nor an escalated model. Include `budget: <spent> of <N> spent` in funded stops.
|
|
56
|
+
|
|
57
|
+
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. Durable status beats a decision's suggestion. Keep the retry hint only for its target.
|
|
58
|
+
|
|
59
|
+
## Dispatch
|
|
60
|
+
|
|
61
|
+
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:
|
|
62
|
+
|
|
63
|
+
```text
|
|
64
|
+
subagent({ agent: "loop-implementer", context: "fresh", async: false,
|
|
65
|
+
cwd: <absolute implementation worktree>, output: <unique absolute temp path>,
|
|
66
|
+
outputMode: "file-only",
|
|
67
|
+
acceptance: { level: "none", reason: "the parent validates the ledger and the commit" },
|
|
68
|
+
task: "iteration: <i>\nspec: <absolute spec path>\nledger: <absolute ledger path>\nbase: <base SHA>\ntarget: <row number or seed>\nprevious decision: <new conforming line or none>\nhint: <human hint or none>" })
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
For `target: seed`, explicitly instruct the child to apply its seed contract even when iteration is greater than 0; carry that instruction in the existing `hint` field. Keep the actual consumed count in `iteration`.
|
|
72
|
+
|
|
73
|
+
Omit the model override; let the persona override or parent inheritance resolve it. Carry effects only: one file-reference return, one ledger read, git boundary checks. Never read a child transcript or carry reasoning history. Stop on dispatch error or an async handle; never poll, join or relaunch.
|
|
74
|
+
|
|
75
|
+
## Validate the return
|
|
76
|
+
|
|
77
|
+
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.
|
|
78
|
+
2. Validate by dispatched `target`, not iteration number, against the saved copy using this table. Preserve headers including the bumped iterations, row identifiers and prior decisions.
|
|
79
|
+
|
|
80
|
+
| Target | Required changes | Miss |
|
|
81
|
+
|---|---|---|
|
|
82
|
+
| Seed | All attempts stay 0; only `open` -> `done` status transitions; every non-cut row gets evidence; cut rows unchanged; exactly one new `row 0 done | seeded <k> rows, closed <m> on baseline | <first row to take>` decision. Partial and complete baseline closure both pass. Never `failed`. | Human stop; never automatic seed retry. |
|
|
83
|
+
| Ordinary | Exactly the target row's mutable cells change: status `done` or `failed`, attempts +1, nonempty bounded evidence. Other rows unchanged. Exactly one NEW bounded decision appended, consistent with target and status. | Parent repair below. |
|
|
84
|
+
|
|
85
|
+
Require ordinary decision grammar `^row <target> (done|failed) \| .{1,200} \| .{1,200}$`; an old conforming line is not a new line. Require check name plus at most three result lines in evidence, serialized with semicolons and escaped pipes as in the persona. Reject wrong targets, foreign cells, missing/malformed/new-extra decisions and changed headers.
|
|
86
|
+
|
|
87
|
+
On an ordinary miss restore every non-target row, headers 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.
|
|
88
|
+
|
|
89
|
+
## Exit verification
|
|
90
|
+
|
|
91
|
+
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.
|
|
92
|
+
|
|
93
|
+
## Human stop
|
|
94
|
+
|
|
95
|
+
Leave implement active. Use one screen of plain words: `Stopped on row <n> (<row text>)` for row failures, or the concrete boundary/cap/verification header above. `Problem:` quotes the evidence cell verbatim, identifying the actual spec/code contradiction, failing assertion/output or missing capability, and quotes the last decision line. Include funding budget only when funded. Omit round history, model escalation and reasoning traces.
|
|
96
|
+
|
|
97
|
+
Offer these concrete actions:
|
|
98
|
+
|
|
99
|
+
| Human choice | Durable action |
|
|
100
|
+
|---|---|
|
|
101
|
+
| Retry with hint | Append `row <n> retry | <hint> | allowed attempts <attempts + 1>`, commit `loop: retry row <n>`, resume checks with that target/hint. Never reset attempts or iterations. |
|
|
102
|
+
| Amend | Follow `/skill:brainstorming` amendment surface; cut only through an approved disposition amendment. Reconcile ledger and spec in one commit. |
|
|
103
|
+
| Stop | Keep phase implement and preserve branch state. |
|
|
104
|
+
|
|
105
|
+
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.
|
|
106
|
+
|
|
107
|
+
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 and iterations. 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.
|
|
108
|
+
|
|
109
|
+
## After the loop
|
|
110
|
+
|
|
111
|
+
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:
|
|
112
|
+
|
|
113
|
+
0. Call `phase_tracker({ action: "start", phase: "verify" })`.
|
|
114
|
+
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.
|
|
115
|
+
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`.
|
|
116
|
+
3. Run happy path per the fully read reference when overrides has `## Happy path` or the diff selects a row; use the diff-derived row, not a plan header. Pass summary and outcome to the separate fresh `conformance-reviewer`, along with spec path, verbatim original prompt and full diff. Use spec AC rows against the ledger as the checklist. Follow the reference's partition, concern decomposition, fix rounds and Convergence with the ledger command replacing plan Verification. Keep durable Gn identities in reports, without plan_tracker initialization or lifecycle updates. Rerun full verification after repairs. Resolve closureReview settings and reviewer dispatch per the reference. Reviews happen only after complete implement; none inside the iteration loop.
|
|
117
|
+
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.
|
|
118
|
+
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.
|
|
119
|
+
|
|
120
|
+
## Project overrides
|
|
121
|
+
|
|
122
|
+
If a gauntlet overrides file exists - checked in order: `.pi/gauntlet-overrides.md`, `<repo root>/gauntlet-overrides.md`, `<repo root>/doc/gauntlet-overrides.md`; first found wins - read it once per session - a skill that already has the file's content in context from an earlier skill's read skips the read; a restored session has nothing in context and reads it. Read and apply `## conventions` whenever present, without a relevance judgment. Give this skill's named section precedence over conflicting `## conventions` rules. Use other relevant sections - by name match, by topic (routing, verification, worktrees, etc.), or by workflow convention - to override or extend the instructions above. Project-local `AGENTS.md` is already in context - check it for project-specific routing tables, service paths, and verification commands.
|
|
123
|
+
|
|
124
|
+
The recognized headings, their readers, and the rules an override cannot change are listed in the [configuration front door](../../README.md#project-specific-overrides); an override extends or replaces the step it names and never lifts this skill's HARD CONSTRAINT or MUST text.
|
|
@@ -17,7 +17,7 @@ Git worktrees create isolated workspaces sharing the same repository, allowing w
|
|
|
17
17
|
|
|
18
18
|
## Step 0 — Detect Existing Isolation (REQUIRED)
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
For a caller passing resolved PR values, read [reference/pr-head.md](reference/pr-head.md) now and follow it instead of Steps 0 and 1, before generic linked-worktree reuse. For every other caller, check whether you are **already** inside an isolated worktree. Creating a worktree inside another worktree, or inside a submodule, produces silent corruption.
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
23
|
read -r GIT_DIR GIT_COMMON <<<"$(git rev-parse --path-format=absolute --git-dir --git-common-dir | tr '\n' ' ')"
|
|
@@ -44,7 +44,7 @@ Use `$WORKTREE`, report it in the Step 4 shape (`Worktree ready at <that path>`)
|
|
|
44
44
|
|
|
45
45
|
## Step 1 — Announce, Don't Ask (skill-driven work defaults to a worktree)
|
|
46
46
|
|
|
47
|
-
For gauntlet-driven work — brainstorming, plans, implementation — the worktree is the default, not a question. Announce and proceed:
|
|
47
|
+
For a PR head, use [reference/pr-head.md](reference/pr-head.md) instead of this step. For gauntlet-driven work — brainstorming, plans, implementation — the worktree is the default, not a question. Announce and proceed:
|
|
48
48
|
|
|
49
49
|
> "Setting up an isolated worktree at `<path>` on branch `<branch>` for this work."
|
|
50
50
|
|
|
@@ -177,7 +177,7 @@ If `git symbolic-ref -q HEAD` returns nothing, you're on a detached HEAD. Do not
|
|
|
177
177
|
|
|
178
178
|
## Keeping a Worktree Current
|
|
179
179
|
|
|
180
|
-
For longer-running work the base branch advances:
|
|
180
|
+
For a PR-subject branch, follow [reference/pr-head.md](reference/pr-head.md): merge `origin/<baseRefName>`; never rebase it. For other longer-running work the base branch advances:
|
|
181
181
|
|
|
182
182
|
```bash
|
|
183
183
|
git -C "$WORKTREE" fetch origin
|