pi-gauntlet 7.39.0 → 7.40.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 +6 -0
- package/README.md +3 -1
- package/extensions/phase-tracker.test.ts +3 -1
- package/extensions/phase-tracker.ts +2 -1
- package/package.json +2 -2
- package/skills/brainstorming/SKILL.md +8 -1
- package/skills/brainstorming/reference/amendment-surface.md +4 -0
- package/skills/brainstorming/reference/menu-layout.md +20 -0
- package/skills/brainstorming/reference/pr-subject.md +2 -0
- package/skills/brainstorming/reference/spec-finalization.md +3 -2
- package/skills/brainstorming/reference/ticket-acceptance.md +3 -1
- package/skills/chase-bug/SKILL.md +6 -0
- package/skills/check-delivery/SKILL.md +6 -0
- package/skills/finishing-a-development-branch/SKILL.md +11 -11
- package/skills/finishing-a-development-branch/reference/disposition-protocol.md +2 -1
- package/skills/gatekeep-pr/reference/batch.md +2 -0
- package/skills/gatekeep-pr/reference/cleanup.md +4 -0
- package/skills/gatekeep-pr/reference/menus.md +21 -0
- package/skills/gatekeep-pr/reference/post-selection-loop.md +2 -0
- package/skills/gatekeep-pr/reference/sync.md +6 -0
- package/skills/gauntlet-handoff/SKILL.md +8 -4
- package/skills/gauntlet-performance/SKILL.md +4 -2
- package/skills/gauntlet-resume/SKILL.md +10 -1
- package/skills/gauntlet-resume/reference/reconstruction.md +7 -1
- package/skills/loop-implementation/SKILL.md +2 -0
- package/skills/shape-ticket/SKILL.md +4 -0
- package/skills/shape-ticket/reference/repo-audit.md +5 -1
- package/skills/subagent-driven-development/stop-note.md +4 -0
- package/skills/using-git-worktrees/SKILL.md +5 -1
- package/skills/verification-before-completion/reference/conformance-check.md +1 -1
- package/skills/writing-plans/SKILL.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v7.40.0 - 2026-10-28
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Skill-owned turns carry machine-readable `gate`, `question`, `done`, and `stuck` first lines, with a gate inventory and reply contract for programmatic callers. (#92)
|
|
8
|
+
|
|
3
9
|
## v7.39.0 - 2026-10-28
|
|
4
10
|
|
|
5
11
|
### Added
|
package/README.md
CHANGED
|
@@ -128,7 +128,7 @@ Run by a human against pi-cohort >= 7.1.0, before a pi-gauntlet release claims t
|
|
|
128
128
|
## Requirements
|
|
129
129
|
|
|
130
130
|
- [pi-coding-agent](https://github.com/earendil-works/pi) ≥ 0.85.1 - tested minimum for sequential `phase_tracker` tool execution, which persists a tracker update before a later tool call in the same model message.
|
|
131
|
-
- [pi-cohort](https://github.com/jjuraszek/pi-cohort) >= 7.6.
|
|
131
|
+
- [pi-cohort](https://github.com/jjuraszek/pi-cohort) >= 7.6.3 - required peer package, including binary-safe worktree patches; it also lets a persona with `subagent` in `tools:` start with inherited extensions ([pi-cohort #26](https://github.com/jjuraszek/pi-cohort/issues/26)), which multi-PR `gatekeep-pr` needs. Skills that dispatch agents (`requesting-code-review`, `subagent-driven-development`, `dispatching-parallel-agents`, `writing-plans`, `forge-skill`, `shape-ticket`, `roasting-the-spec`) call `subagent({})`, which pi-cohort provides. pi-gauntlet does not vendor the dispatch tool; without pi-cohort those skills have nothing to call. Gauntlet execution dispatches explicitly use `async: false`; do not enable pi-cohort's incompatible `forceTopLevelAsync` setting. See pi-cohort's [dispatch configuration](https://github.com/jjuraszek/pi-cohort/blob/main/doc/configuration.md) for that setting's owner and semantics. A wave of N >= 1 tasks dispatches its implementers and first spec reviews as one chain call. `subagent-driven-development` stops before dispatch on unsupported installs; there is no older-runtime fallback.
|
|
132
132
|
|
|
133
133
|
Both packages must be listed in your `.pi/settings.json#packages` array (pi adds them automatically when you `pi install`). pi-gauntlet and pi-cohort are versioned independently but release together whenever dispatch semantics change - pin compatible versions of both. At each pi-gauntlet release, set the pi-cohort peer minimum and README floor together to the newest released pi-cohort version; `/skill:release` checks the registry before proceeding.
|
|
134
134
|
|
|
@@ -580,6 +580,8 @@ Anything a wrapper skill contains beyond trigger phrases is misplaced - move it
|
|
|
580
580
|
|
|
581
581
|
## Configuring the gates
|
|
582
582
|
|
|
583
|
+
Settled skill-owned turns carry a machine-readable first line identifying a gate, question, or terminal outcome. Programs answering these turns use the [gate inventory and reply contract](doc/gate-contract.md); the rendered row bodies define valid replies.
|
|
584
|
+
|
|
583
585
|
Choose experimental loop options 4/5, configure the iteration cap and worker model, and operate the planless ledger through [Loop engine operations](doc/configuration.md#loop-engine-operations). Waves remains the default.
|
|
584
586
|
|
|
585
587
|
| Want to ... | Read |
|
|
@@ -1567,7 +1567,9 @@ test("cap guard: default 5 waves pass, the sixth is blocked with the escalation
|
|
|
1567
1567
|
}
|
|
1568
1568
|
const blocked = await firstCallResult(h, "c6", implementerWave(1));
|
|
1569
1569
|
assert.equal(blocked?.block, true);
|
|
1570
|
-
assert.match(blocked?.reason ?? "",
|
|
1570
|
+
assert.match(blocked?.reason ?? "", /^Conformance fix loop: 5 fix round\(s\) used against a cap of 5 \(granted rounds included\); escalate to the human/);
|
|
1571
|
+
assert.ok((blocked?.reason ?? "").includes("Start the escalation message with the line: gauntlet: gate=verification-before-completion/step-6"));
|
|
1572
|
+
assert.doesNotMatch(blocked?.reason ?? "", /^gauntlet:/);
|
|
1571
1573
|
});
|
|
1572
1574
|
|
|
1573
1575
|
test("cap guard: maxFixRounds 0 blocks the first wave; 1 blocks the second; a chain implementer is cap-checked and counted", async () => {
|
|
@@ -255,7 +255,8 @@ const fixRoundCapBlockReason = (used: number, cap: number, settingsPath: string)
|
|
|
255
255
|
'phase_tracker({ action: "grant_fix_rounds", rounds: <N>, reason: "<their words>" }).\n' +
|
|
256
256
|
`Last resort: set piGauntlet.closureReview.enforce: false in ${settingsPath} (disables all closure guards; ` +
|
|
257
257
|
"applies on the next tool call, no restart - a gauntlet_setting read in the same message sees the write; " +
|
|
258
|
-
"a repo closureReview block replaces the preset's whole block, so restate model and maxFixRounds alongside)."
|
|
258
|
+
"a repo closureReview block replaces the preset's whole block, so restate model and maxFixRounds alongside). " +
|
|
259
|
+
"Start the escalation message with the line: gauntlet: gate=verification-before-completion/step-6";
|
|
259
260
|
|
|
260
261
|
const closureModelBlockReason = (model: string, missing: number, total: number): string =>
|
|
261
262
|
`Blocked: ${missing} of ${total} conformance-reviewer ${total === 1 ? "dispatch" : "entries"} ` +
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-gauntlet",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.40.0",
|
|
4
4
|
"description": "Opinionated, gated workflow skills, subagent personas, and runtime extensions for the pi coding agent.",
|
|
5
5
|
"author": "Jacek Juraszek",
|
|
6
6
|
"type": "module",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"test": "node scripts/ci.mjs"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
|
-
"pi-cohort": ">=7.6.
|
|
65
|
+
"pi-cohort": ">=7.6.3"
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
68
|
"yaml": "^2.9.0"
|
|
@@ -89,6 +89,8 @@ If any test fails, offer no split. Never split by service, package, repo, layer,
|
|
|
89
89
|
|
|
90
90
|
### 3. Understand the idea
|
|
91
91
|
|
|
92
|
+
Write exactly `gauntlet: question` alone at column zero on the first physical line, followed by a newline, for every waiting question, before any premise correction or `The framing holds: ...` sentence. Never append a colon to the marker. Follow the [first-line rule](reference/menu-layout.md).
|
|
93
|
+
|
|
92
94
|
Clarify freely. For a PR subject, run the framing check against the PR's diff as the ask (`reference/pr-subject.md`).
|
|
93
95
|
|
|
94
96
|
`Read` the gathered draft unconditionally before question one. Treat it as a helper, not a fence: verify load-bearing claims from primary code, and confirm whether the codebase or ecosystem already solves the problem.
|
|
@@ -98,6 +100,7 @@ Ask one question per message, about purpose, constraints, success, and affected
|
|
|
98
100
|
Bad: `May I treat those two acceptance criteria as location-only deviations? Recommendation: yes`
|
|
99
101
|
Good:
|
|
100
102
|
```text
|
|
103
|
+
gauntlet: question
|
|
101
104
|
The two ACs name a path that moved; the spec keeps them in-scope with the new path as a Design clause. Which surface owns the refresh?
|
|
102
105
|
A) the extension
|
|
103
106
|
B) a new bin
|
|
@@ -112,13 +115,14 @@ Before approaches, state in chat the supported, disproved, corrected, and unveri
|
|
|
112
115
|
Before question one, verify the draft's `Framing:` line against primary code and add your own recon. This check adds to the premise verification above and never replaces it: trace every consumer, caller, and data path the ask's constraints name, including retained loaders and every repro and verification step's implicit dependencies, before writing the holds-statement or the question; check those dependencies with the lookup the repo or spec names, and name the traces and dependencies in the holds-statement, not only the files read. A framing concern exists when you can state a cited case that the ask is misdiagnosed, wrong-sized, already solved, a band-aid where the root cause is reachable, or cuts across a sound pattern - including a repo convention that is itself the debt - and can name the alternative it implies; an objection without an alternative is a lead to investigate, not a concern. With a concern, question one is the framing question in the questionary format:
|
|
113
116
|
|
|
114
117
|
```text
|
|
118
|
+
gauntlet: question
|
|
115
119
|
A) as framed
|
|
116
120
|
B) pivot: <named alternative> - <cited reason>
|
|
117
121
|
C) smaller or none: <what ships, or what happens if nothing ships>
|
|
118
122
|
Recommendation: <letter> - <why>
|
|
119
123
|
```
|
|
120
124
|
|
|
121
|
-
For a band-aid concern, put the root-cause alternative in B. Without a concern,
|
|
125
|
+
For a band-aid concern, put the root-cause alternative in B. Without a concern, follow the marker with one sentence naming what was checked - `The framing holds: checked <x>, <y>` - and continue to the first ordinary question; a scout objection that yielded no alternative is named among the things checked.
|
|
122
126
|
|
|
123
127
|
After any premise correction in the same message, ask the framing question or give the holds-statement. Ask the framing question at most once per brainstorm, including after pushback; the user's reply is final, and later doubts on the same point go to Open Questions or a `Pattern:` line. Recommend; never pivot without the reply. A ticket-recorded decision on the exact point follows the ticket rule above; an adopted decision records `Framing: kept (ticket <id>)`. A pivot never rewrites AC rows: rows it no longer satisfies take `deviates:` dispositions, and a pivot that changes the topic re-mints the slug.
|
|
124
128
|
|
|
@@ -127,6 +131,7 @@ Record the outcome in the draft under `## Appended during questionary` as `Frami
|
|
|
127
131
|
Bad: `The ask adds another settings path - should we? Recommendation: no`
|
|
128
132
|
Good:
|
|
129
133
|
```text
|
|
134
|
+
gauntlet: question
|
|
130
135
|
The ask adds a second settings path beside the resolver that already owns every setting (settings/resolver.ts:11).
|
|
131
136
|
A) as framed
|
|
132
137
|
B) pivot: a key under the existing resolver - one read path, no new boundary
|
|
@@ -146,6 +151,8 @@ Prefer clear testable boundaries, YAGNI, existing conventions when they are soun
|
|
|
146
151
|
|
|
147
152
|
### 6. Present the design in two rounds
|
|
148
153
|
|
|
154
|
+
Start the message with `gauntlet: question` alone at column zero on the first physical line, followed by a newline, for each round's approval question. Never append a colon to the marker. Follow the [first-line rule](reference/menu-layout.md).
|
|
155
|
+
|
|
149
156
|
Use two rounds, targeting 300-500 words each, with one approval each; revisions remain within that approval point. Ask once per round; round-1 approval without correction confirms the predecessor. Round 1 covers architecture, responsibilities, data flow, and `supersedes <path>, <scope>` when applicable. Round 2 covers errors, edges, tests, and `## Documentation impact`. In round 2, read and apply [Documentation impact](reference/documentation-impact.md), including its verbatim template; cite that portable relative path in the spec; do not restate its categories. Ask the user when doc impact is unclear. Unreadable -> stop the step with a blocking error. Cite the draft's `Docs touched:` entries as candidates for "Materially amended existing docs"; admit or drop each by that owner's materiality bar, never list them automatically. In round 1, carry chosen `Removes:`/`Adds:` into Design as exhaustive `Remove:`/`Add:` imperatives naming every moving part; route unlisted parts through `reference/amendment-surface.md`. In round 2, write `## Tests`: one `<observable> - <test name or file>` per acceptance row and Design edge/error clause; `<observable> - none: <why>` for untestable.
|
|
150
157
|
|
|
151
158
|
## Ticket Handling
|
|
@@ -104,11 +104,14 @@ Fail closed: a dispatch error, an async handle, a silence-kill, or a missing or
|
|
|
104
104
|
|
|
105
105
|
## 4. Human batch - one menu
|
|
106
106
|
|
|
107
|
+
Follow the [first-line rule](menu-layout.md).
|
|
108
|
+
|
|
107
109
|
Decide every recommendation and its reason before writing the menu text: the menu text is written after the recommendation is decided, never while deciding it. Never leak deliberation: `recommended: custom? Hmm. Dispositions: fix-now ... Actually, the amended spec makes G2 ...`.
|
|
108
110
|
|
|
109
111
|
Render only escalated and prefiltered items; `<N>` counts them. Build the opening sentence from the prepared item's `what` and `why`; take the human-call sentence from the prefilter rule or reviewer's escalate reason in plain words, with `Reviewer:` verbatim beneath it. Nothing symbol-dense above the fold; each item's `old -> new` sits under `Details`, after the footer. This menu's grammar governs the amendment batch only; brainstorming's questionary formats (the labeled recommendation question and the ticket cut question) keep their own rules - including the cut question's re-ask after a cancelled repair, re-rendered in full with the row unchanged.
|
|
110
112
|
|
|
111
113
|
```
|
|
114
|
+
gauntlet: gate=brainstorming/human-batch
|
|
112
115
|
Spec amendments: <N> need your call - from <trigger>; applying as recommended <reopens | adds | removes> <task ids | no tasks>; no phase change.
|
|
113
116
|
|
|
114
117
|
1. <title> - <what>. <why>
|
|
@@ -208,6 +211,7 @@ Eight synthetic items modelled on one real run. Items 1-5 and 8 reach the review
|
|
|
208
211
|
The reviewer clears items 1-5; nothing is applied yet. The batch renders items 6-8 (items 1-5 apply together with the accepted ones after the reply):
|
|
209
212
|
|
|
210
213
|
```
|
|
214
|
+
gauntlet: gate=brainstorming/human-batch
|
|
211
215
|
Spec amendments: 3 need your call - from Task 7 BLOCKED; applying as recommended reopens Tasks 4, 6; no phase change.
|
|
212
216
|
|
|
213
217
|
1. Fewer announcements per fetch - the acceptance criterion drops from at least 3 to at least 1. Lowers the bar you set.
|
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
## First-line rule
|
|
2
|
+
Start each settled, skill-owned turn at column zero of the whole assistant message with exactly one lowercase marker line:
|
|
3
|
+
|
|
4
|
+
| Kind | Grammar | Use |
|
|
5
|
+
|---|---|---|
|
|
6
|
+
| gate | `gauntlet: gate=<skill>/<id>( recommended=<token>)?` | Render an inventoried skill template that waits for a reply. |
|
|
7
|
+
| question | `gauntlet: question` | Ask one questionary-format question or a skill-named yes/no question and wait. |
|
|
8
|
+
| done | `gauntlet: done <outcome>` | Report the skill's terminal outcome with nothing awaited. |
|
|
9
|
+
| stuck | `gauntlet: stuck <reason>` | End the skill without its outcome and without an advancing reply. |
|
|
10
|
+
|
|
11
|
+
Use `[A-Za-z0-9.-]+` for `<skill>`, `<id>`, and outcome tokens. Set `<skill>` to the owning directory under `skills/`, including for reference files; set `<id>` to the gate's step or section label in kebab-case. Write `<outcome>` as comma-separated bare tokens or `key=value` tokens with no spaces. Write `<reason>` as free text to the end of the line.
|
|
12
|
+
|
|
13
|
+
Classify a turn that any proper reply can advance as a gate or question, never `done` or `stuck`. Place the marker before all prose, including premise corrections, summaries, and mandatory framing; retain the existing prose and question format (`A)` options and `Recommendation:`) after it. Use the lowercase `gauntlet:` marker without a leading slash; treat the `/gauntlet:` slash-command namespace as unrelated.
|
|
14
|
+
|
|
15
|
+
For `recommended=`, use only the number of the displayed row tagged `[recommended]`; omit it for untagged and item-letter menus, including per-item `Recommended: <letter>` lines. Let the displayed row text define accepted replies; omit `picks=`.
|
|
16
|
+
|
|
17
|
+
Mark a combined batch/menu or closure digest/options message once with its parent template's marker: `gauntlet: gate=gatekeep-pr/batch-summary` or `gauntlet: gate=finishing-a-development-branch/step-4`, respectively. Give a nested skill's ask its own skill id. Give a terminal report turn and a later new-skill gate turn their own kinds.
|
|
18
|
+
|
|
19
|
+
Omit markers from ordinary answers, gates invented outside skill templates, and intermediate reports followed by automatic continuation without a human turn. Treat verification's Closure / conformance before finishing, subagent-driven-development's Continuous Execution, and loop-implementation's After the loop as intermediate, not terminal; mark the gate the continuation renders instead.
|
|
20
|
+
|
|
1
21
|
## Exposure
|
|
2
22
|
A numbered option list directly after an ordered list with only a blank line merges under CommonMark, displaying `N+1.`-`N+k.` after `N` preceding items. This control renders the options as `4.`-`6.`:
|
|
3
23
|
```markdown
|
|
@@ -35,6 +35,8 @@ Immediately after ordered admission and before binding, classify N=1 read-only.
|
|
|
35
35
|
|
|
36
36
|
## Relatedness before provisioning
|
|
37
37
|
|
|
38
|
+
Start the message with `gauntlet: question` alone at column zero on the first physical line, followed by a newline, when asking the relatedness question, before premise correction or framing. Never append a colon to the marker. Follow the [first-line rule](menu-layout.md).
|
|
39
|
+
|
|
38
40
|
For N>1, fetch every admitted PR's title/body with `gh pr view <N> -R <owner/repo> --json title,body` and actual diff with `gh pr diff <N> -R <owner/repo>`. On failure stop before provisioning naming the ref and observed reason: `<ref>: title/body not fetched (<gh error>)` or `<ref>: diff not fetched (<gh error>)`.
|
|
39
41
|
|
|
40
42
|
Group by the hunks' behavior, contract, or defect, using titles and bodies as stated intent, not shared paths. Treat unrelated hunks in one file as separate concerns and related hunks across files as one concern. Define groups here, not through shape-ticket's split axes. For one group continue; for multiple groups ask one question in the questionary format: a lead-in naming the concerns, one lettered option per group with its PRs and shared concern on its own line, then `Recommendation:` on its own final line recommending the initial-home group. Offer no all option. For an answer naming no offered group, re-ask once, then stop.
|
|
@@ -121,15 +121,16 @@ If the council path ran, the body is its audit (`Coverage:` when present, then `
|
|
|
121
121
|
Evaluate the summary in two stages (the **Degrade path** referenced in each is defined just below):
|
|
122
122
|
|
|
123
123
|
1. **From the dispatch tool result, before the `Read`.** If the result is **not** an `"Output saved to: <path> (<N> KB, <M> lines)"` reference (an exit-0 save error returns the save error plus a `Full reply preserved at` / `not preserved` pointer, no inline output), or the reference reports under ~500 bytes, or over ~45 KB (the `Read` truncates at 50KB / 2000 lines, so a larger file cannot render whole) - skip the `Read` and take the degrade path. Use the reference's reported figures; do not re-derive them.
|
|
124
|
-
2. **The `Read` itself, as the last content-producing tool call before composing the gate.** `Read` `$SUMMARY_PATH` and paste its contents verbatim
|
|
124
|
+
2. **The `Read` itself, as the last content-producing tool call before composing the gate.** `Read` `$SUMMARY_PATH` and paste its contents verbatim immediately after the gate marker. If the `Read` fails, returns 0 bytes, or reports truncation - take the degrade path. The `Read` must be last: pi-condense does not protect a `/tmp` read, so any turn boundary between the `Read` and the render lets the read result be pruned, reproducing the bug.
|
|
125
125
|
|
|
126
126
|
**Degrade path** - reach the gate with a one-line "summary generation failed" note; never paraphrase from the file-only reference, never render a stub as the canonical summary.
|
|
127
127
|
|
|
128
128
|
Either way - summary rendered or degraded - then `rm "$SUMMARY_PATH"` (unconditional cleanup; harmless if the file was never created, since it lives outside the worktree under the OS temp dir).
|
|
129
129
|
|
|
130
|
-
Paste the summary verbatim, unedited in the template below; use adjacent lines for the `Council:` counts, unresolved ambiguities, and every `Missing from the spec` entry; render the `Scope cuts:` line yourself from the spec's `## Acceptance criteria` section - every `deferred:`, `deviates:`, and `venue:` row, `none` when there is none - never from the summary; the audit itself is shown only on row 3:
|
|
130
|
+
Follow the [first-line rule](menu-layout.md). Paste the summary verbatim, unedited in the template below; use adjacent lines for the `Council:` counts, unresolved ambiguities, and every `Missing from the spec` entry; render the `Scope cuts:` line yourself from the spec's `## Acceptance criteria` section - every `deferred:`, `deviates:`, and `venue:` row, `none` when there is none - never from the summary; the audit itself is shown only on row 3:
|
|
131
131
|
|
|
132
132
|
```
|
|
133
|
+
gauntlet: gate=brainstorming/user-review-gate
|
|
133
134
|
<spec-only summary read back from the temp file - pasted verbatim, unedited>
|
|
134
135
|
|
|
135
136
|
Spec written and committed to <project>/doc/specs/<filename>.md (worktree: <path>).
|
|
@@ -19,7 +19,9 @@ Ticket <ref>, <heading or "checkbox list">, rows verbatim:
|
|
|
19
19
|
|
|
20
20
|
Under `Ticket <ref>, <heading or "checkbox list">, rows verbatim:`, the section names the ticket contract only; the spec's own requirements stay in Design. Keep every provenance form flat - a row's repo lives in its disposition token, never in a heading. Disposition is exactly one of `in-scope`, `deviates: <why>`, `deferred: <where>`, `venue: <env> - <observation>`, `elsewhere: <repo>`; default `in-scope`. For ticket rows, never edit the row text: an ambiguous row stays `in-scope` with the chosen reading written as a Design clause, and a moved path or a workflow artifact (spec, plan, changelog, telemetry file) is a Design clause too, never a disposition and never asked. A row under a repo group that is not this repo is `elsewhere: <repo>`, stated, never asked; a group matching no repo asks `A) this repo B) elsewhere: <name> C) repair the ticket - /skill:shape-ticket <ref>`. Replace `<name>` with the supplied unmatched group heading verbatim in option B, not a request to name a repo. Name a `venue:` row's enabling change in Design; `venue:` states where the observation can happen and is never `prd`, `prod`, or `production` - a row observable only in production is a wrong row. An `in-scope` row is a requirement as written; disposition reasons are never normative for the plan or the reviewer, so a `deviates:` reason that adopts part of a row restates that part as a Design clause. A `deferred:` destination is a tracker ref (`#N`, `owner/repo#N`, `ABC-123`), a spec path, or a URL; a prose destination with none of these is a gap at the PR gate.
|
|
21
21
|
|
|
22
|
-
**Cut question.**
|
|
22
|
+
**Cut question.**
|
|
23
|
+
|
|
24
|
+
Start the message with `gauntlet: question` alone at column zero on the first physical line, followed by a newline, before premise correction or framing. Never append a colon to the marker. Follow the [first-line rule](menu-layout.md). `deviates:` and `deferred:` come only from the user's answer to this question; never propose one. Ask it, in the questionary format, when the user's prompt or an answer raises dropping or changing a row, or when code, a cited contract, or the user shows a row is wrong or impossible: `A) in-scope - <reading> B) deviates: <why> C) deferred: <where> D) repair the ticket - /skill:shape-ticket <ref> <row and evidence>`, `Recommendation:` A or D with the reason the row ships in this gauntlet; B and C are never recommended. On D, run `/skill:shape-ticket <ref> <row and evidence>` (repair mode per `shape-ticket/SKILL.md:43`, its own confirm gate), then re-fetch the ticket, replace the gather draft's `## Ticket acceptance criteria (verbatim)` block, and re-extract; a cancel at that gate returns to this question with the row unchanged. Carry the full question and the user's answer of every question that offered a disposition into the council's `Human input` block. The gate lists every `deferred:`, `deviates:`, and `venue:` row on its `Scope cuts:` line (`spec-finalization.md`). A disposition changes in any later phase - a reviewer finding `recommended: rescope` at the finish gate, a wrong row noticed mid-implementation, or a ticket edited after approval when the user asks - through [Amending an approved spec](../SKILL.md#amending-an-approved-spec) (`amendment-surface.md`); the row text still never changes. For ticket rows, preserve the ticket contract: Never author acceptance criteria on the ticket's behalf; that is `/skill:shape-ticket`'s job.
|
|
23
25
|
|
|
24
26
|
## Row production at spec-writing
|
|
25
27
|
|
|
@@ -150,6 +150,8 @@ checkpoint 2) stops the skill.
|
|
|
150
150
|
|
|
151
151
|
### 4. Verdict menu (human gate 1)
|
|
152
152
|
|
|
153
|
+
Start the message with `gauntlet: gate=chase-bug/verdict-menu` before the fault story or verdict in every variant. Append ` recommended=<n>` using the actual rendered number of the tagged recommended row; preserve the existing eligibility, omission, and recommendation rules.
|
|
154
|
+
|
|
153
155
|
Present the verdict as a **plain-language fault story**, not a wall of evidence.
|
|
154
156
|
|
|
155
157
|
**Verdict shape.** Write for a reader who does not know the code the bug
|
|
@@ -285,6 +287,10 @@ in step 5. Delegated skills' gates (e.g. shape-ticket's) are not counted.
|
|
|
285
287
|
|
|
286
288
|
### 5. Response to origin (human gate 2)
|
|
287
289
|
|
|
290
|
+
Start the message with `gauntlet: gate=chase-bug/response-to-origin` before the channel and exact draft when awaiting `send it`. Apply [menu-layout](../brainstorming/reference/menu-layout.md), preserving that exact confirmation token. Keep the marker outside the response payload.
|
|
291
|
+
|
|
292
|
+
Start the message with `gauntlet: done responded` after sending. Start the message with `gauntlet: done summary` for the terminal summary. Start the message with `gauntlet: done draft` for the terminal copy-paste draft, including a push-failure fallback. A handoff to brainstorming, shape-ticket, or hotfix is not an ending: continue into its next gate without an intermediate terminal marker.
|
|
293
|
+
|
|
288
294
|
Branch on the response target recorded in step 1 (possibly set mid-chase by an
|
|
289
295
|
explicit ask).
|
|
290
296
|
|
|
@@ -7,6 +7,8 @@ description: Use only when explicitly asked to prove delivery of a named merged
|
|
|
7
7
|
|
|
8
8
|
## Quick reference
|
|
9
9
|
|
|
10
|
+
Start the message with `gauntlet: stuck` followed on that line by the concrete stop reason for every STOP branch below. Start the message with `gauntlet: done already-recorded` for an already-terminal ticket with the delivery already recorded; preserve the no-write rule.
|
|
11
|
+
|
|
10
12
|
| Situation | What happens |
|
|
11
13
|
|---|---|
|
|
12
14
|
| Ref unreadable, or repo mismatch with no repo group naming this repo | STOP - abort, no write |
|
|
@@ -251,6 +253,10 @@ code evidence - a legitimate outcome, not a failure.
|
|
|
251
253
|
|
|
252
254
|
## Confirmation gate and the batched write
|
|
253
255
|
|
|
256
|
+
Start the message with `gauntlet: gate=check-delivery/confirmation-gate` before evidence and the exact payload on both the success approval and failure findings-comment ask. Keep this line outside every tracker payload: `Delivered: <sha>` remains the first line of the evidence comment.
|
|
257
|
+
|
|
258
|
+
Start the message with `gauntlet: done delivered` when the batched write landed. Start the message with `gauntlet: done already-recorded` for idempotent delivery. Start the message with `gauntlet: done manual` when the write halves are emitted for manual execution. Start the message with `gauntlet: stuck` followed on that line by the concrete reason once the findings-comment gate is answered or no comment is offered; use this for any partial write failure too. A declined success write ends with `gauntlet: stuck write declined`.
|
|
259
|
+
|
|
254
260
|
Any `unexplained gap` or failed stage -> **failure path**: no status
|
|
255
261
|
advance, no delivery comment, no marker. The findings may be offered as a
|
|
256
262
|
**findings comment** (no `Delivered:` line, so it never trips idempotency) -
|
|
@@ -85,11 +85,10 @@ When the sentinel carries a `happy-path:` line, print it directly under `Closure
|
|
|
85
85
|
|
|
86
86
|
**Pre-menu amendment funnel (GAPS only).** Before rendering the carried-open menu, `read` and run [`amendment-surface.md` § Conformance entry](../brainstorming/reference/amendment-surface.md) over the inventory once: gaps with `recommended: accept`, verdict `DRIFTED` or `PARTIAL`, not `UNAUTHORIZED`, whose `origin` is not an acceptance criterion are drafted as `accept-into-spec` items (the edit built from `origin` + `evidence`) and sent to the reviewer in one call; cleared items apply and land as one batch commit, the spec is re-audited, the inventory regenerated. Only concerns the re-audit actually closed drop out; sibling concerns in the same gap keep their rows and dispositions. Survivors and every other gap render as ordinary rows below - one menu, never two.
|
|
87
87
|
|
|
88
|
-
**Carried-open (`status: GAPS (N open)`).** Read `reference/disposition-protocol.md` and follow it for the carried-open render grammar, the response grammar, and the 9-step execute order. Render the human decision menu in the shape below; print the `Conformance: N decisions needed before shipping.` header below the item list, followed by the sentinel's informational lines (`happy-path:`, `Deferred/deviates per spec:`, `whole-diff minors:`) when present, in that order, above the reply instruction - a `failed - attributed to G<n>,...` value names the rows whose evidence is the transcript, a `rescope` recommendation on such a row means the failure lies in code the change never owned - drive the dispositions per that reference, then print the summary render and continue to Step 4. If that reference file cannot be read, stop and surface a blocking error — do **not** improvise the grammar from memory.
|
|
89
|
-
|
|
90
|
-
Representative carried-open render (multi-concern gap split to `e2e`; single-concern gap `cache`; `UNAUTHORIZED` gap `auth`):
|
|
88
|
+
**Carried-open (`status: GAPS (N open)`).** Read `reference/disposition-protocol.md` and follow it for the carried-open render grammar, the response grammar, and the 9-step execute order. Render the human decision menu in the shape below; print the `Conformance: N decisions needed before shipping.` header below the item list, followed by the sentinel's informational lines (`happy-path:`, `Deferred/deviates per spec:`, `whole-diff minors:`) when present, in that order, above the reply instruction - a `failed - attributed to G<n>,...` value names the rows whose evidence is the transcript, a `rescope` recommendation on such a row means the failure lies in code the change never owned - drive the dispositions per that reference, then print the summary render and continue to Step 4. If that reference file cannot be read, stop and surface a blocking error — do **not** improvise the grammar from memory. Read and apply [menu-layout](../brainstorming/reference/menu-layout.md). Start the message with `gauntlet: gate=finishing-a-development-branch/carried-open` alone on the first output line, without `recommended=`; put item 1 on the next line, before summaries. Representative carried-open render (multi-concern gap split to `e2e`; single-concern gap `cache`; `UNAUTHORIZED` gap `auth`):
|
|
91
89
|
|
|
92
90
|
```
|
|
91
|
+
gauntlet: gate=finishing-a-development-branch/carried-open
|
|
93
92
|
1. Source-image E2E validation - not run; blocked (HYDRA1.png, HTTP 401), so the branch ships without its end-to-end evidence.
|
|
94
93
|
The spec requires this validation, but HYDRA1.png is unavailable; decide whether it stays in scope for this branch.
|
|
95
94
|
what: The spec's Verification section gains a line deferring the source-image E2E run until the image is available.
|
|
@@ -157,9 +156,7 @@ Three tiers, increasing cost — name the tier when a revert is requested:
|
|
|
157
156
|
A **heavy** revert is not a menu toggle — say so explicitly to the user before proceeding, and do not present it as equivalent-effort to the light tier. The council audit that lets the human identify revert candidates lives in the `brainstorming` spec commit message body (not a committed spec section).
|
|
158
157
|
|
|
159
158
|
### Step 4: Present Options
|
|
160
|
-
|
|
161
|
-
**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:
|
|
162
|
-
|
|
159
|
+
Start the message with `gauntlet: gate=finishing-a-development-branch/step-4` alone on the first output line, followed by a newline before any closure summary or amendment digest. Emit exactly one marker and no `recommended=`; preserve the full subject-specific menu, including on return from `fix minors`. Read and apply [menu-layout](../brainstorming/reference/menu-layout.md). **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:
|
|
163
160
|
```
|
|
164
161
|
Amendments auto-applied (N):
|
|
165
162
|
- <title> - <what changed>
|
|
@@ -175,6 +172,7 @@ Omit the block when N = 0.
|
|
|
175
172
|
Run the first proof for every recorded original head, home first; the first exit 1 stops with the table's exact message naming that PR's SHA. Run the second proof only for home. 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.
|
|
176
173
|
Read and apply [menu-layout](../brainstorming/reference/menu-layout.md) for rendering and numeric replies. Present:
|
|
177
174
|
```
|
|
175
|
+
gauntlet: gate=finishing-a-development-branch/step-4
|
|
178
176
|
Implementation complete. What would you like to do?
|
|
179
177
|
|
|
180
178
|
1. Push to the PR branch (PR #N, <headRefName>; appends the rework block to its description)
|
|
@@ -192,6 +190,7 @@ Withhold row 1 by omitting it and placing `Withheld: push - <reason>` under the
|
|
|
192
190
|
Read and apply [menu-layout](../brainstorming/reference/menu-layout.md) before presenting these options and before acting on a numeric reply.
|
|
193
191
|
|
|
194
192
|
```
|
|
193
|
+
gauntlet: gate=finishing-a-development-branch/step-4
|
|
195
194
|
Implementation complete. What would you like to do?
|
|
196
195
|
|
|
197
196
|
1. Push and create a Pull Request
|
|
@@ -208,6 +207,7 @@ Which option?
|
|
|
208
207
|
Read and apply [menu-layout](../brainstorming/reference/menu-layout.md) before presenting these options and before acting on a numeric reply.
|
|
209
208
|
|
|
210
209
|
```
|
|
210
|
+
gauntlet: gate=finishing-a-development-branch/step-4
|
|
211
211
|
Implementation complete. You're on a detached HEAD (externally managed workspace).
|
|
212
212
|
|
|
213
213
|
1. Push as new branch and create a Pull Request
|
|
@@ -252,7 +252,7 @@ node <bin>/gauntlet-telemetry-seal.mjs --worktree "$WORKTREE" --option <pr|squas
|
|
|
252
252
|
|
|
253
253
|
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.
|
|
254
254
|
#### PR-subject row 1: Push to the PR branch
|
|
255
|
-
Capture the scoped verification set and accepted-complete task/thread evidence before the strip. Refetch threads per recorded PR using the paginated single-`$n` query (one invocation per PR) owned by [pr-head](../using-git-worktrees/reference/pr-head.md); retain PR attribution and use the query's location rendering. For home, use the table below and omit threads now resolved on GitHub. For members, copy recorded dispositions and mark newly resolved or newly opened states from the refresh; never use home's first-parent history as member-fix proof.
|
|
255
|
+
For the close-absorbed-PR question, start the message with `gauntlet: gate=finishing-a-development-branch/pr-subject-row-1`. Read and apply [menu-layout](../brainstorming/reference/menu-layout.md). Do not report `done pushed` while this gate awaits an answer. Capture the scoped verification set and accepted-complete task/thread evidence before the strip. Refetch threads per recorded PR using the paginated single-`$n` query (one invocation per PR) owned by [pr-head](../using-git-worktrees/reference/pr-head.md); retain PR attribution and use the query's location rendering. For home, use the table below and omit threads now resolved on GitHub. For members, copy recorded dispositions and mark newly resolved or newly opened states from the refresh; never use home's first-parent history as member-fix proof.
|
|
256
256
|
| Refetched thread / evidence | Resolution |
|
|
257
257
|
|---|---|
|
|
258
258
|
| Recorded `fix`, matching task title carries id, task accepted by spec and code review and `complete`, exactly one naming commit | `fixed in <sha7>` |
|
|
@@ -290,6 +290,7 @@ Instantiate `Absorbs:` from every non-home pair in record order; omit it for N=1
|
|
|
290
290
|
Only after a successful push and successful home body edit, refresh each member with `gh pr view <N> -R <owner/repo> --json state,headRefOid`. Fetch each refreshed head that is not yet local (`git -C "$WORKTREE" fetch origin <current headRefOid>`; for a fork member use its head repository URL) before the ancestry test. Skip and name a member whose head fetch fails: `#14 skipped: head <sha7> not fetchable`. Require state `OPEN` and `git -C "$WORKTREE" merge-base --is-ancestor <current headRefOid> <pushed home head>` exit 0. Exclude and name ineligible members: `#14 skipped: head moved to <sha7>, not in home` or `#14 skipped: state CLOSED`. Treat unexpected Git exits and failed refreshes as errors, withhold closure and report the reason; merge nothing implicitly.
|
|
291
291
|
Ask nothing when none qualify or N=1. Otherwise render one gated question before marking ship complete. Instantiate each actual eligible target and its exact comment using its recorded pre-rework SHA7 and home's number/URL; the two-member rendering is:
|
|
292
292
|
```text
|
|
293
|
+
gauntlet: gate=finishing-a-development-branch/pr-subject-row-1
|
|
293
294
|
Close the absorbed PRs with these comments?
|
|
294
295
|
#13: "Reworked into #12 (<home url>) by the gauntlet; this PR's commits are merged there and remain reachable as <#13 pre-rework sha7>."
|
|
295
296
|
#14: "Reworked into #12 (<home url>) by the gauntlet; this PR's commits are merged there and remain reachable as <#14 pre-rework sha7>."
|
|
@@ -361,9 +362,9 @@ Report: "Keeping branch <name>. Worktree preserved at <path>." The telemetry rec
|
|
|
361
362
|
**Don't cleanup worktree.**
|
|
362
363
|
|
|
363
364
|
#### Option 5: Discard
|
|
364
|
-
|
|
365
|
-
**Confirm first:**
|
|
365
|
+
Read and apply [menu-layout](../brainstorming/reference/menu-layout.md). Start the message with `gauntlet: question` alone on the first output line, followed by a newline before the typed-confirmation text. **Confirm first:**
|
|
366
366
|
```
|
|
367
|
+
gauntlet: question
|
|
367
368
|
This will permanently delete:
|
|
368
369
|
- Branch <name>
|
|
369
370
|
- All commits: <commit-list>
|
|
@@ -457,8 +458,7 @@ A host-owned worktree (Step 6: no `home:` match, or the legacy "Otherwise") keep
|
|
|
457
458
|
- **Fix:** Never `git rm` under the telemetry dir. Until the seal the record is untracked and git-excluded, so a plan strip cannot reach it; after the seal it is a committed deliverable.
|
|
458
459
|
|
|
459
460
|
## Completion
|
|
460
|
-
Once the chosen option (Options 1-4 or PR-subject row 1 - not Discard) is executed successfully, mark the ship phase complete:
|
|
461
|
-
|
|
461
|
+
Start the final outcome message with exactly one terminal line before summaries. Start the message with `gauntlet: done pr-created` after successful normal or draft PR creation. Start the message with `gauntlet: done merged` after successful squash-merge and post-merge verification. Start the message with `gauntlet: done kept` after Keep. Start the message with `gauntlet: done discarded` only after typed discard authorization and successful discard. Start the message with `gauntlet: done pushed` after successful PR-subject push and body edit, only after the close-member gate is answered or no members qualify. Start the message with `gauntlet: stuck` followed on that line by a short concrete reason for an executed operation that fails, before error evidence or a return menu. Do not combine a terminal marker with a gate marker in one message; a subsequent menu starts a new gate message. Pending choices, implementation stalls and conformance escalation are not terminal outcomes. Read and apply [menu-layout](../brainstorming/reference/menu-layout.md). Preserve strip, seal, cleanup and ship-state rules below; terminal reporting does not complete ship after Discard or failure. Once the chosen option (Options 1-4 or PR-subject row 1 - not Discard) is executed successfully, mark the ship phase complete:
|
|
462
462
|
```
|
|
463
463
|
phase_tracker({ action: "complete", phase: "ship" })
|
|
464
464
|
```
|
|
@@ -4,9 +4,10 @@ Consumed by `finishing-a-development-branch` Step 3.5 on the **GAPS branch only*
|
|
|
4
4
|
|
|
5
5
|
**Carried-open render (numbered brief).** Read the `## Closure / conformance` block. The menu text is written after the recommendation is decided, never while deciding it. Negative example: `recommended: custom? Hmm. Dispositions: fix-now ... Actually, the amended spec makes G2 ...`.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Read and apply [menu-layout](../../brainstorming/reference/menu-layout.md). Start the message with `gauntlet: gate=finishing-a-development-branch/carried-open` alone on the first output line, without `recommended=`. Put item 1's plain-words problem sentence on the next line, before summaries or metadata. Render one numbered item per decision unit (a gap by default; a `Gn/Cn` concern only where the reference split it):
|
|
8
8
|
|
|
9
9
|
```text
|
|
10
|
+
gauntlet: gate=finishing-a-development-branch/carried-open
|
|
10
11
|
<n>. <plain title> - <what is unresolved and what it costs, one sentence>.
|
|
11
12
|
<why this is a human call, one sentence>.
|
|
12
13
|
A) <option> - <one-line consequence>
|
|
@@ -14,6 +14,8 @@ Gather each PR with `gh pr view --json number,author,headRefOid,headRefName,base
|
|
|
14
14
|
|
|
15
15
|
## Provision serially
|
|
16
16
|
|
|
17
|
+
Start the message with `gauntlet: question` when asking unresolved create tokens or the set-wide other-author confirmation. Apply [menu-layout](../../brainstorming/reference/menu-layout.md), preserving the one yes for the set. Keep private `REPORT`, `CONFLICTING`, `FAILED`, and `STOPPED` child results unchanged; mark only the parent user-facing turn.
|
|
18
|
+
|
|
17
19
|
Fetch origin once with `git fetch origin`; for each fork PR, run `git fetch origin pull/<N>/head:pr-<N>` only when no worktree holds a local `pr-<N>` branch, and otherwise leave the reuse row's `git fetch origin pull/<N>/head` + `git merge --ff-only FETCH_HEAD` to that PR's provisioning step. Apply assessment's gitignore-first rule before built-in creation when the resolved home is inside the primary; sibling homes need no edit. Provision in roster order, one at a time. No concurrent primary fetch or worktree add is allowed, regardless of cohort concurrency.
|
|
18
20
|
|
|
19
21
|
Reuse assessment's provisioning table unchanged: reuse an expected branch at any path, fast-forward only, stop on dirt, divergence, local-only commits, or foreign operations; never repurpose a foreign branch at the default path. Resolve keyed home/create/destroy with `<name>` = `pr-<N>`, shell-quote tokens, check the created path in `git worktree list --porcelain`, and verify `HEAD == headRefOid`. A non-zero create marks that PR failed; never fall back to worktree add. Ask unresolved create tokens in the parent once per token, never execute unresolved placeholders. Isolate `failed - provisioning - <reason>` with no child; continue siblings. A provisioning retry re-provisions only after the obstacle clears.
|
|
@@ -20,6 +20,10 @@ Consequence clause for the menu row (`decision-menu.md`): `remove <worktree.path
|
|
|
20
20
|
|
|
21
21
|
## Non-final stop
|
|
22
22
|
|
|
23
|
+
Follow the [shared layout](../../brainstorming/reference/menu-layout.md).
|
|
24
|
+
|
|
25
|
+
Start the message with `gauntlet: stuck` followed on that line by the reason: use the obstacle's `stuck - ` text as the reason, or `stopped at <template id>` for initial, assess-terminal, and contract-exception. On a failed reset/assertion use the actual error instead. Put cleanup results below that one first line.
|
|
26
|
+
|
|
23
27
|
Enter here for `stop` on the initial, assess-terminal, obstacle, or contract-exception menu. On a `rebased locally` head, run `git -C <worktree.path> reset --hard <pre_head>` first; assert `HEAD == <pre_head>` and a clean tree. Stop on a failed assertion.
|
|
24
28
|
|
|
25
29
|
Reuse step 1's primary and keyed ownership computation: resolve `home:` and the `<name>` pattern against `$PRIMARY`, and pass both the pattern and `worktree.path` through `realpath`. Keep the primary even when clean; print `worktree: kept - primary at <path>`.
|
|
@@ -17,6 +17,8 @@ Read with `decision-menu.md` at step 6. Select the template from this state map;
|
|
|
17
17
|
|
|
18
18
|
Render every menu in full from its template: the verdict line, every available row, and the hint line. Never narrate or summarize a menu; do not substitute "the initial template applied; the human picked 2" for its rendering. Quote a numeric pick only after the rendered menu.
|
|
19
19
|
|
|
20
|
+
Append ` recommended=<n>` to each gate line using the actual rendered number of its tagged recommended row. Emit one first line per turn; when combining batch summary and child menus, emit only the parent `gatekeep-pr/batch-summary` line. Keep runtime guard text, including any quoted escalation instruction, inside the obstacle body, never as a second standalone marker.
|
|
21
|
+
|
|
20
22
|
Render flat numbers through [menu-layout](../../brainstorming/reference/menu-layout.md); preserve its bare-numeric mapping. Put exactly one `[recommended]` on an available row and `stop` last. Put `show evidence` in every hint line, never in a row. Include every omission reason from `decision-menu.md`. A menu rendered under `deliver` before an exit condition, other than the contract-exception template, is a red flag; so is a menu not rendered from these templates, two recommendations, stop not last, or no evidence hint.
|
|
21
23
|
|
|
22
24
|
Render terminal cleanup consequences through `cleanup.md`; use `skipped - needs a landed change` for merge-SHA-dependent overrides in the row text and result block.
|
|
@@ -28,6 +30,7 @@ Use `viewer.is_author` (`viewer.login == pr.author.login`) and `author_is_bot` f
|
|
|
28
30
|
Offer `assess`, eligible `deliver`, eligible `deliver with nits`, then `stop`. Recommend deliver for the human's own PR, assess for someone else's; when delivery is omitted on an own PR, recommend assess. Omit deliver with nits with zero nits, and both delivery rows with cap zero, missing helpers, or non-pushable/unreadable head; name each reason, including `Not offered: deliver (needs push to <head_url>:<head_ref>)`. For someone else's/bot PR change the sync consequence to "merge main into the branch". Map `deliver with nits` to stored `deliver-nits`.
|
|
29
31
|
|
|
30
32
|
```text
|
|
33
|
+
gauntlet: gate=gatekeep-pr/initial recommended=2
|
|
31
34
|
Verdict: not ready - 2 blockers, 1 nit
|
|
32
35
|
|
|
33
36
|
Pick one:
|
|
@@ -41,40 +44,58 @@ Course holds until the final menu; `show evidence` prints the full record.
|
|
|
41
44
|
|
|
42
45
|
## final
|
|
43
46
|
|
|
47
|
+
Start the message with `gauntlet: gate=gatekeep-pr/final`.
|
|
48
|
+
|
|
44
49
|
Offer available `merge`, `approve`, `fix nits` when nits remain and the course excluded them, `reply` when drafted replies exist, then `stop`. Recommend merge for own PR; recommend approve for someone else's when available, else merge; with neither available recommend stop. Omit merge on a draft with `Not offered: merge (draft)` or below WRITE with `Not offered: merge (needs WRITE on <owner>/<repo>)`. Omit approve on drafts and own PRs. Authorize exactly one delivery iteration for fix nits, leaving course unchanged (`post-selection-loop.md` `### Next action`). Hint: `Type a number; show evidence prints the full record.` Print one compact `Evidence:` line above the `Delivers:` line naming the source (`CI (source: ci)` or the local run), the head SHA, each run and its checks with their conclusions, the binding-pending count, and `merge_state_status`; put the same record in the `show evidence` hint's parenthetical.
|
|
45
50
|
|
|
46
51
|
## assess terminal
|
|
47
52
|
|
|
53
|
+
Start the message with `gauntlet: gate=gatekeep-pr/assess-terminal`.
|
|
54
|
+
|
|
48
55
|
Offer available `deliver` (switch course), `approve` only on someone else's non-draft PR with zero blockers, `reply` for drafted thread replies, then `stop` `[recommended]`. Hint: `Type a number; show evidence prints the full record.`
|
|
49
56
|
|
|
50
57
|
## obstacle
|
|
51
58
|
|
|
59
|
+
Start the message with `gauntlet: gate=gatekeep-pr/obstacle`.
|
|
60
|
+
|
|
52
61
|
For undispositionable BLOCKED with no local repair, use this template even with course unset: keep stop last and `[recommended]`, with no wait row, no sync promise, and no approve row. Describe eligible deliver only as retrying after the failed prerequisite changes; promise no automatic sync. Reserve the course-unset initial assess/deliver/stop template for a pending-only report when its sole withhold is a not-yet-resolved binding CI check; source blockers still use initial under the state map.
|
|
53
62
|
|
|
54
63
|
Print the concrete obstacle and retained failed prerequisites. Keep the `Delivers:` line in the obstacle report. Offer eligible `deliver`, `approve workflow run` only for the held-run permission case, `assess` (switch course), then `stop` `[recommended]`. Feed the `Evidence:` line from the verifier record's resolved source, never from the raw check or run rollup - render a `source: pending` record as `Evidence: pending (<binding check> binding; head <sha>)`, and when `course` is unset render the deliver row as `deliver - set course to deliver; <one clause naming what retries>, no round charged` instead of `resume the retained course`. Render ordinary obstacle continuation as `deliver - resume the retained course; <one clause naming what retries>, no round charged`. For every non-timeout deliver selection, add exactly `2 x maxFixRounds` to both caps and persist before work, preserving usage. Append `add <n> to each cap` (`+2 x maxFixRounds`, with cumulative usage/caps) to the row even below both caps. On timeout describe exactly one additional watch window instead, with neither cap extended. An unchanged prerequisite re-exits even after extension. Print exactly one `Evidence:` line before the verdict, naming the resolved evidence source and assessed head per `report.md` (for example `Evidence: CI (run 7001, test_unit and build_image green on 9c1e4f2)`). Include `check <name> flaky | real | ci-broken` in the hint for failing checks; flaky followed by a numeric deliver selection can resume. Hint: `Type a number; show evidence prints the full record (<source summary>)`. Replace `<source summary>` with the same source summary used in `Evidence:`, including the CI run, check outcomes, and assessed head when CI is the source.
|
|
55
64
|
|
|
56
65
|
## contract exception
|
|
57
66
|
|
|
67
|
+
Start the message with `gauntlet: gate=gatekeep-pr/contract-exception`.
|
|
68
|
+
|
|
58
69
|
Print the concrete proposed contract change before the rows. Offer `accept contract change`, `preserve contract` `[recommended]`, then `stop`. Render preserve's consequence as "reject the proposal, keep <named requirement>, and resume authorized implementation repair within it". Route through `post-selection-loop.md` `### Contract decision`; show evidence settles nothing. Hint: `Type a number; show evidence prints the full record.`
|
|
59
70
|
|
|
60
71
|
## own merge
|
|
61
72
|
|
|
73
|
+
Start the message with `gauntlet: gate=gatekeep-pr/own-merge`.
|
|
74
|
+
|
|
62
75
|
After this run's merge returns `MERGED`, offer `cleanup` `[recommended]` until attempted, `post coverage to ticket` when issue and scope rows exist, `post coverage to PR`, then `stop`. Suppress each successful post for the rest of the run; a failed post keeps its row and prints the error. A post re-renders this template, never tears down or ends the run, and runs no compare-and-swap. After cleanup removes its row recommend the first available post, else stop. Hint: `Type a number; show evidence prints the full record.`
|
|
63
76
|
|
|
64
77
|
## merge queued
|
|
65
78
|
|
|
79
|
+
Start the message with `gauntlet: gate=gatekeep-pr/merge-queued`.
|
|
80
|
+
|
|
66
81
|
After this run's merge returns a state other than `MERGED`, offer `wait` - re-run `gh pr view <N> --json state,mergeCommit` `[recommended]`, then `stop`. Render `The merge is queued, so coverage posts wait. (<state>)`. A MERGED read records pr.state and pr.merge_commit and renders own merge; OPEN or another state keeps this template. Run no CI watch. Hint: `Type a number; show evidence prints the full record.`
|
|
67
82
|
|
|
68
83
|
## approved
|
|
69
84
|
|
|
85
|
+
Start the message with `gauntlet: gate=gatekeep-pr/approved`.
|
|
86
|
+
|
|
70
87
|
When `approved_head` equals the assessed head, offer `cleanup` `[recommended]` until attempted, then `stop`; recommend stop after cleanup. Hint: `Type a number; show evidence prints the full record.`
|
|
71
88
|
|
|
72
89
|
## closed PR
|
|
73
90
|
|
|
91
|
+
Start the message with `gauntlet: gate=gatekeep-pr/closed-pr`.
|
|
92
|
+
|
|
74
93
|
When state is not OPEN at step 1 or mid-course, offer `cleanup` `[recommended]` until attempted, then `stop`; recommend stop after cleanup. Keep this distinct from this run's own merge. Hint: `Type a number; show evidence prints the full record.`
|
|
75
94
|
|
|
76
95
|
## batch summary
|
|
77
96
|
|
|
97
|
+
Start the message with `gauntlet: gate=gatekeep-pr/batch-summary`.
|
|
98
|
+
|
|
78
99
|
For a recovered `CONFLICTING` child, offer only safe `retry` and `stop`, with `show evidence` hint-only. Render `retry - re-dispatch this PR's assessment with the same record` `[recommended]` only after `batch.md`'s clean-recovery and no-rebase checks pass; otherwise omit retry with its recorded reason and recommend stop. Keep stop last; offer no update branch or merge base rows. Hint: `Type a number; show evidence prints the full record.`
|
|
79
100
|
|
|
80
101
|
Let the `batch.md` parent render its current summary rows and each child's template from this file. Keep terminal posts and queued-merge wait parent-owned, including after worktree removal; suppress successful posts and retain failed posts. Preserve the parent's row consequences and admission/queue semantics. Put stop last and exactly one recommendation. Hint: `Type a number; show evidence prints the full record.`
|
|
@@ -187,6 +187,8 @@ Before posting or committing any external payload - review bodies, replies, comm
|
|
|
187
187
|
|
|
188
188
|
### Teardown
|
|
189
189
|
|
|
190
|
+
Start the message with `gauntlet: done approved` for stop on approved. Start the message with `gauntlet: done merged` for stop on own-merge. Start the message with `gauntlet: done closed-pr` for stop on closed-pr. Start the message with `gauntlet: done final` for stop on final. Start the message with `gauntlet: done merge-queued` for stop on merge-queued. Put the checkout path and local branch below the terminal line. A report Verdict above a menu is not a terminal. Start the message with `gauntlet: stuck` followed by the actual error on any hard assertion failure, including a delegated fix-wave restore/assert failure, and end with the actual error; do not render a continuation menu.
|
|
191
|
+
|
|
190
192
|
Delegate non-final stop (initial, assess terminal, obstacle, contract exception) to `cleanup.md` `## Non-final stop`. Keep terminal cleanup behind its own pick; terminal stop leaves the checkout as found and reports its path and local branch. Render cleanup only on terminal templates; never run cleanup steps 2-4 for a non-final stop.
|
|
191
193
|
|
|
192
194
|
Delete the run record, temporary description body files, every helper output and its log_path on every handled terminal exit. Drop unapplied drafts. Never discover authority in a new session.
|
|
@@ -8,6 +8,8 @@ Read from SKILL.md step 2b, only when `--rebase` was passed. Input: the step-1 d
|
|
|
8
8
|
|
|
9
9
|
## Preconditions
|
|
10
10
|
|
|
11
|
+
Start the message with `gauntlet: gate=gatekeep-pr/sync-preconditions` for the stop-only menu below. Render numbered `stop` with `show evidence` hint-only through [menu-layout](../../brainstorming/reference/menu-layout.md).
|
|
12
|
+
|
|
11
13
|
Check in order after step 2. A terminal stop - here, at `## Baseline`, or at `## Push` - closes the `sync` stage `failed`, prints the reason, offers `stop` and `show evidence` only, and runs no step 3; on such a stop `show evidence` prints the digest's head-dependent fields and the `sync` record.
|
|
12
14
|
|
|
13
15
|
1. The harness has a helper facility (SKILL.md `## Harness notes`); none -> terminal stop before any write: `sync: stopped - no helper facility for conflict resolution and review`.
|
|
@@ -26,6 +28,8 @@ Refresh `headRefOid` with `gh pr view <N> --json headRefOid` and set `<pre_head>
|
|
|
26
28
|
|
|
27
29
|
## Other-author confirmation
|
|
28
30
|
|
|
31
|
+
Start the message with `gauntlet: question` before the fixed block and yes/no ask. Apply [menu-layout](../../brainstorming/reference/menu-layout.md), preserving the typed yes/no contract.
|
|
32
|
+
|
|
29
33
|
When `pr.author.login` differs from `gh api user --jq .login`, or that login is `unreadable`, print this fixed block verbatim, one line per point, before any rewrite:
|
|
30
34
|
|
|
31
35
|
```text
|
|
@@ -67,6 +71,8 @@ On a `rebased locally` head the forge re-read returns `<pre_head>` as `headRefOi
|
|
|
67
71
|
|
|
68
72
|
## Failure path
|
|
69
73
|
|
|
74
|
+
Start the message with `gauntlet: stuck` followed on that line by the actual error on a restore/assert mismatch, and end the run. Keep ordinary recovered failures on their existing continuation path.
|
|
75
|
+
|
|
70
76
|
Triggers: an unresolved stop, `open` for any reason other than a failing scoped test in a file outside the list, residue, a non-zero `rebase` or `--continue` without unmerged paths, a reviewer Critical or Moderate finding, a push rejected by server policy. Restore `<pre_head>`: `git rebase --abort` while the rebase is in progress, `git reset --hard <pre_head>` after it completed; assert `HEAD == <pre_head>` and a clean `git status --porcelain` - a mismatch is a hard stop with the error, never a silent continue. Record `sync: failed - <reason>` with reason one of `unresolved stop in <commit7>`, `implementer returned open`, `residue outside conflicted files`, `rebase failed: <first line>`, `reviewer: <top finding>`, `push rejected: <first server line>`. Close the `sync` stage `skipped` and continue to step 3 on the unsynced head; step 5 records what remains and renders the initial or terminal template from `menus.md`.
|
|
71
77
|
|
|
72
78
|
## Sync record
|
|
@@ -17,7 +17,7 @@ ending at `## Skills loaded`). Only this package knows what `phase_tracker` and
|
|
|
17
17
|
the layout fixed by `reference/brief-contract.md` (`## Producers`). Runs in the main
|
|
18
18
|
loop: tracker state is extension state no subagent can read.
|
|
19
19
|
|
|
20
|
-
**Announce at start:** "I'm using the gauntlet-handoff skill to write a resumable handoff brief."
|
|
20
|
+
**Announce at start (after the marker on marked messages):** "I'm using the gauntlet-handoff skill to write a resumable handoff brief."
|
|
21
21
|
|
|
22
22
|
## Boundaries
|
|
23
23
|
|
|
@@ -31,8 +31,10 @@ loop: tracker state is extension state no subagent can read.
|
|
|
31
31
|
|
|
32
32
|
## Sequence
|
|
33
33
|
|
|
34
|
+
Apply the first-line grammar in [menu-layout](../brainstorming/reference/menu-layout.md).
|
|
35
|
+
|
|
34
36
|
1. **Resolve the target.**
|
|
35
|
-
- `--out` and `--key` both given -> STOP: they are exclusive in cohort's grammar.
|
|
37
|
+
- `--out` and `--key` both given -> STOP: they are exclusive in cohort's grammar. Start the message with `gauntlet: stuck` followed by the exclusivity reason on that line.
|
|
36
38
|
- `--out <path>` -> resolve to an absolute path against the session cwd
|
|
37
39
|
(`node -p "require('path').resolve(process.argv[1])" -- "<path>"`); that is the
|
|
38
40
|
form passed to cohort.
|
|
@@ -52,7 +54,7 @@ loop: tracker state is extension state no subagent can read.
|
|
|
52
54
|
```
|
|
53
55
|
|
|
54
56
|
`BRANCH` empty (detached HEAD) or equal to `DEFAULT` -> STOP asking for `--key` or
|
|
55
|
-
`--out` (a default-branch key would collide across flows).
|
|
57
|
+
`--out` (a default-branch key would collide across flows). Start the message with exactly `gauntlet: question` on its own line, with no suffix.
|
|
56
58
|
- A derived key has every `/` replaced by `-` (`hotfix/x` -> `hotfix-x`) so the file
|
|
57
59
|
lands flat in the default directory. A human-given `--key` is passed verbatim.
|
|
58
60
|
- With `--key`, cohort writes `<tmpdir>/pi-handoff/<key>.md`, `<tmpdir>` from
|
|
@@ -87,7 +89,9 @@ loop: tracker state is extension state no subagent can read.
|
|
|
87
89
|
`cat >> "<brief path>" <<'EOF' ... EOF` whose body is that block.
|
|
88
90
|
- Re-read the file tail and confirm it ends with the gate-history line from the
|
|
89
91
|
contract and nothing after.
|
|
90
|
-
7. **Report.**
|
|
92
|
+
7. **Report.**
|
|
93
|
+
|
|
94
|
+
Start the message with `gauntlet: done brief-written`. Print the path and `/skill:gauntlet-resume <path>`. When a section was
|
|
91
95
|
appended and the brief's `worktree:` field is `no`, resume's entry check 2 needs an
|
|
92
96
|
override: print `/skill:gauntlet-resume <path> <override>` where `<override>` is the
|
|
93
97
|
run worktree from step 1 when one was found, else the session checkout root,
|
|
@@ -22,15 +22,17 @@ The CLI parses and aggregates; you reason. Never open a telemetry YAML record yo
|
|
|
22
22
|
|
|
23
23
|
## Reply - exactly this, in this order
|
|
24
24
|
|
|
25
|
+
Start the message with `gauntlet: gate=gauntlet-performance/reply-exactly-this-in-this-order`. Follow the [shared marker and reply mapping rules](../brainstorming/reference/menu-layout.md); append `recommended=<row number>` only when a rendered row carries `[recommended]`.
|
|
26
|
+
|
|
25
27
|
1. **Recommendation** (2-4 sentences). One claim, led by the run that exemplifies it: quote its `spec` slug, `run_id`, and the 1-3 numbers that carry the claim. When `grants` is the evidence, call it the fix-round proxy. If no version group has `shipped >= 2`, the recommendation is "sample too small" with the `n`/`shipped` counts per version.
|
|
26
28
|
2. **Cornerstones**: 3-5 bullets of aggregate facts from `by version` - corpus size, truncated count, the p50s and model tallies that moved between versions.
|
|
27
29
|
3. **Council assessment**: Render this block independently of the version sample gate, even when item 1 says "sample too small". If the digest prints `no council data in selected records`, render only `council: no data`. If the most recent roster has fewer than 5 runs, render only `council: <roster> - not enough runs to assess (N of 5)`. Otherwise render one line per `flag:` of the most recent roster as the roster-change recommendations; when an older roster exists, add one line comparing the two rosters' `uniq_appl_nonminor/run` and rejected share as groups. Compare rosters as groups, never a member across rosters.
|
|
28
30
|
4. **Menu**, numbered, at most 3 items, rendered exactly as:
|
|
29
|
-
- `1. render report` - ask for a target path;
|
|
31
|
+
- `1. render report` - ask for a target path; Start the message with `gauntlet: question` for this ask. Write markdown there: the digest verbatim, then the recommendation and cornerstones above. If the file exists, ask before overwriting. Start the message with `gauntlet: question` for this overwrite ask. Write nothing unless this item is chosen.
|
|
30
32
|
- `2. open recommendation as ticket` - hand the claim and its numbers to `/skill:shape-ticket`; never create a ticket directly.
|
|
31
33
|
- `3. drill into <slug>` - re-run the CLI with `--json` and show that run's fields.
|
|
32
34
|
|
|
33
|
-
Nothing else: no preamble, no restated digest, no file written before item 1 is chosen.
|
|
35
|
+
Nothing else beyond the marker and prescribed body: no preamble, no restated digest, no file written before item 1 is chosen.
|
|
34
36
|
|
|
35
37
|
## Project overrides
|
|
36
38
|
|
|
@@ -17,7 +17,7 @@ worktree whose spec/plan artifacts are reconstructed into tracker state
|
|
|
17
17
|
(`reference/reconstruction.md`), a spec seed (`reference/seed.md`). Every check runs
|
|
18
18
|
before any tracker mutation; every stop names the offending path, field, or line.
|
|
19
19
|
|
|
20
|
-
**Announce at start:** "I'm using the gauntlet-resume skill to continue an interrupted flow."
|
|
20
|
+
**Announce at start (after the marker on marked messages):** "I'm using the gauntlet-resume skill to continue an interrupted flow."
|
|
21
21
|
|
|
22
22
|
## Boundaries
|
|
23
23
|
|
|
@@ -41,6 +41,9 @@ precedence).
|
|
|
41
41
|
|
|
42
42
|
Read and apply [menu-layout](../brainstorming/reference/menu-layout.md) before presenting these options and before acting on a numeric reply.
|
|
43
43
|
|
|
44
|
+
For the discovery menu, start the message with the marker specified below. Start the message with `gauntlet: gate=gauntlet-resume/discovery`.
|
|
45
|
+
For no briefs and every stop route in the table, end without mutation. Start the message with `gauntlet: stuck` followed by the existing reason on that line.
|
|
46
|
+
|
|
44
47
|
| Input | Route |
|
|
45
48
|
|---|---|
|
|
46
49
|
| no tokens, no pasted text | discovery: `<tmpdir>` via `node -p "require('os').tmpdir()"`; candidates are the regular files directly under `<tmpdir>/pi-handoff/` ending `.md` (non-recursive) whose line 1 starts `# Handoff:`; sorted by mtime, newest first; displayed one per line as `<n>. <title line> - <worktree: field value> - <mtime ISO-8601>` with `worktree: unavailable` when the field is absent; the human picks `<n>` (a single candidate is still confirmed); none -> STOP "no handoff briefs found under <tmpdir>/pi-handoff" |
|
|
@@ -66,6 +69,8 @@ foreign-repo brief stops there.
|
|
|
66
69
|
|
|
67
70
|
## Entry checks
|
|
68
71
|
|
|
72
|
+
For an entry-check stop, start with the terminal marker and retain the offending path, field, or line. Start the message with `gauntlet: stuck` followed by the reason on that line.
|
|
73
|
+
|
|
69
74
|
In order. All before any tracker mutation; entry check 1 is read-only. A spec
|
|
70
75
|
seed runs check 1 here, then `reference/seed.md`, which runs check 3 itself;
|
|
71
76
|
checks 2, 4, 5 do not apply; check 6 runs on the seed's pinned spec path.
|
|
@@ -112,6 +117,8 @@ checks 2, 4, 5 do not apply; check 6 runs on the seed's pinned spec path.
|
|
|
112
117
|
|
|
113
118
|
## Dispatch
|
|
114
119
|
|
|
120
|
+
For the `worktree: no` brainstorming offer, keep the explicit-selection wait. Start the message with exactly `gauntlet: question` on its own line, with no suffix.
|
|
121
|
+
|
|
115
122
|
| Input | Route |
|
|
116
123
|
|---|---|
|
|
117
124
|
| brief with `## Process state` | process-state restore - `reference/brief-contract.md` "Process-state restore" |
|
|
@@ -129,6 +136,8 @@ re-derive the record.
|
|
|
129
136
|
|
|
130
137
|
## Post-restore continuation
|
|
131
138
|
|
|
139
|
+
A successful restore is an automatic handoff, not a terminal report; let the resumed skill own the next ask and its marker. Keep the brief fields unchanged and infer no approval. After citation repair of a plan that was dirty or untracked before repair, state explicitly that the repair stays in the working copy and lands with the next task commit; run no `git add` or repair commit, per `reference/brief-contract.md` "Citation repair".
|
|
140
|
+
|
|
132
141
|
After a successful restore, print the closing line from `reference/brief-contract.md`
|
|
133
142
|
(gate history not restored; the task to re-validate), then on its own line exactly one of `Standing grant active: <sentence>` or `No standing grant.` from check 6 (nothing when grant decoding was skipped), then continue in the stage's
|
|
134
143
|
owning skill **without** its reset-bearing entry:
|
|
@@ -67,6 +67,8 @@ plan commit; treat every task as `pending`.
|
|
|
67
67
|
|
|
68
68
|
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.
|
|
69
69
|
|
|
70
|
+
Start the message with exactly `gauntlet: question` on its own line, with no suffix. Apply [menu-layout](../../brainstorming/reference/menu-layout.md).
|
|
71
|
+
|
|
70
72
|
Ask exactly one question: is this spec approved, or do you select `/skill:brainstorming`
|
|
71
73
|
with this unapproved spec as the draft? Show the spec path (and the brief's
|
|
72
74
|
`## Intent`/`## Decisions` when present).
|
|
@@ -81,18 +83,22 @@ with this unapproved spec as the draft? Show the spec path (and the brief's
|
|
|
81
83
|
|
|
82
84
|
## Spec with ledger
|
|
83
85
|
|
|
86
|
+
Start the message with exactly `gauntlet: question` on its own line, with no suffix. Apply [menu-layout](../../brainstorming/reference/menu-layout.md).
|
|
87
|
+
|
|
84
88
|
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.
|
|
85
89
|
|
|
86
90
|
After confirmation:
|
|
87
91
|
|
|
88
92
|
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.
|
|
89
93
|
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" })`.
|
|
90
|
-
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`.
|
|
94
|
+
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`.
|
|
91
95
|
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.
|
|
92
96
|
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.
|
|
93
97
|
|
|
94
98
|
## Spec with plan
|
|
95
99
|
|
|
100
|
+
Start the message with exactly `gauntlet: question` on its own line, with no suffix. Apply [menu-layout](../../brainstorming/reference/menu-layout.md).
|
|
101
|
+
|
|
96
102
|
Show, and ask the human to confirm or edit both in one reply:
|
|
97
103
|
|
|
98
104
|
1. Per task, in plan order: the commits after the plan commit that touch any path in
|
|
@@ -93,6 +93,8 @@ Run the ledger's `verification:` command exactly once foreground in the worktree
|
|
|
93
93
|
|
|
94
94
|
## Human stop
|
|
95
95
|
|
|
96
|
+
Read and apply [menu-layout](../brainstorming/reference/menu-layout.md). Start the message with `gauntlet: question` at every human stop, including the discard/reset authorization ask for a dirty or commit-boundary return. Put it alone on the first output line, followed by a newline before the stop text, without a driver-state preamble, wrapper or code fence. These decisions are neither done nor stuck outcomes.
|
|
97
|
+
|
|
96
98
|
Leave implement active. Use one screen of plain words: `Stopped on row <n> (<row text>)` for row failures, or the concrete boundary/cap/verification header above. `Problem:` quotes the evidence cell verbatim, identifying the actual spec/code contradiction, failing assertion/output or missing capability, and quotes the last decision line. Include funding budget only when funded. At every stop print `Preserve every row's attempts and the total iteration cap.` Omit round history, model escalation and reasoning traces.
|
|
97
99
|
|
|
98
100
|
Offer these concrete actions. Offer `cap +N` only at a clean cap or legacy missing-cap stop; dirty-tree and commit-boundary stops keep discard authorization and never offer `cap +N`. When both the row allowance and total cap are exhausted, list independent funding and cap offers despite rule 2 priority. Take separate replies: funding follows the spec's `**Amend-grant:**` contract, cap follows the row below; define no combined syntax.
|
|
@@ -67,6 +67,8 @@ Read and apply `reference/repo-audit.md` now in both modes (resolve against this
|
|
|
67
67
|
|
|
68
68
|
### 3 - Interactive questioning
|
|
69
69
|
|
|
70
|
+
Start the message with `gauntlet: question` before the current clarification. Apply [menu-layout](../brainstorming/reference/menu-layout.md), preserving one free-text question at a time.
|
|
71
|
+
|
|
70
72
|
One question at a time, only when intent is unclear or no AC is derivable; in repair, wait for all audits and ask in ref order. Never fabricate Context, Problem, or ACs to avoid asking.
|
|
71
73
|
|
|
72
74
|
### 4 - Draft
|
|
@@ -146,6 +148,8 @@ Complete the current ticket's write before presenting the next ticket. Immediate
|
|
|
146
148
|
|
|
147
149
|
## AC integrity gate
|
|
148
150
|
|
|
151
|
+
Start the message with `gauntlet: question` for the recoverable hard-stop draft and targeted recovery question, singleton runs included. Apply [menu-layout](../brainstorming/reference/menu-layout.md); keep approval unavailable. While awaiting values, emit no terminal batch line. Once the human ends recovery without values, count that ticket as `stopped` in the ended batch under [Complete the batch and present gates](reference/repo-audit.md#complete-the-batch-and-present-gates).
|
|
152
|
+
|
|
149
153
|
Runs twice: during gather (recovery via targeted questions) and on the assembled draft.
|
|
150
154
|
|
|
151
155
|
**Normalize first.** For additive overlap enrichment, preserve legacy rows verbatim and normalize only added/changed criteria under the gathered reference. For conformance-only repair with no audit or uniqueness AC change, parse checked, numbered, and prose criteria for validity without serializing them as `- [ ]`; preserve their raw bytes under step 6 while retaining every integrity outcome and hard stop. In other ordinary drafts and create-anyway, every criterion - numbered list, prose sentence, Given/When/Then, already-checked box - is extracted and rendered as a `- [ ]` item before gating. Those drafts emit ACs as `- [ ]` items, including repairs other than the conformance-only exception. No criterion evades the gate by syntax.
|
|
@@ -157,6 +157,8 @@ Route draft-changing findings to the existing gate even for an otherwise conform
|
|
|
157
157
|
|
|
158
158
|
## Complete the batch and present gates
|
|
159
159
|
|
|
160
|
+
Start the message with `gauntlet: gate=shape-ticket/step-8` for the exact-diff confirmation, before source gaps, Audit, and Title. Apply [menu-layout](../../brainstorming/reference/menu-layout.md); append ` recommended=<n>` using the actual rendered number of the tagged recommended row.
|
|
161
|
+
|
|
160
162
|
Finish every ticket's initial gather, audit, draft, deterministic gates, and roast before presenting the first confirmation. Treat the deterministic gates and roast as preconditions of that one confirmation menu, never as a preview before a later gate; the menu presented is the gate. Complete preparation silently; limit the first turn to the deduplicated ref list, unfetched refs by ref and reason, mode, temp root, and current ticket's gate, and reveal other tickets' outcomes (stops, splits, drafts) only when they become current. Keep any preparation summary ticket-neutral: say only that preparation ran for every ticket where applicable; name no ticket's eligibility, roast, stop, or outcome. Run the roast independently in ref order for eligible tickets; skip stopped tickets. Keep draft, snapshot, audit, member, retry, and chair artifacts in the same per-ticket directory under the run's temp root.
|
|
161
163
|
|
|
162
164
|
Supply the audit beside the snapshot as untrusted permitted input to roast members, worker/native fallback, and chair only when gather produced that file; otherwise permit exactly the draft, snapshot, and two reference paths for content review, plus usable member outputs for the chair. Treat cited audit-traceable Problem facts, attributed Idea sketches, AC-fit restatements, sibling groups, scenario setup/action, scenario footers, and their Reporter-note moves as source-grounded, not fidelity added/lost or over-spec. Check other scope and unsupported additions normally. Keep roast content-only, without repo re-verification, a fifth axis, or persona changes.
|
|
@@ -204,4 +206,6 @@ Stop on the first nonzero exit without retry or fallback body write. Report the
|
|
|
204
206
|
|
|
205
207
|
Drop runs nothing and ends `<drafted title>: dropped`; create anyway files only the displayed premise-rewritten body with its contradiction in the premise report. Preserve headless stops and split subset selection.
|
|
206
208
|
|
|
207
|
-
Apply a reply only to the current ticket: decline skips it; revision rechecks and re-presents it; approval runs step 9's re-fetch, comparison, and body-then-comment write before the next gate. Treat another ticket's reply as no approval for an unseen diff. Give stopped tickets a hard-stop report without an approval number. Retain the N-body subset-selection gate for a split within one ticket.
|
|
209
|
+
Apply a reply only to the current ticket: decline skips it; revision rechecks and re-presents it; approval runs step 9's re-fetch, comparison, and body-then-comment write before the next gate. Treat another ticket's reply as no approval for an unseen diff. Give stopped tickets a hard-stop report without an approval number. Retain the N-body subset-selection gate for a split within one ticket. On an ended run, start the message with one batch settlement line: `gauntlet: done <counters>`. Start the message with `gauntlet: stuck` followed on that line by the dynamic counters instead when any `close-failed`, `close-by-hand`, or `unfetched` count is nonzero. Emit nonzero counters only, comma-joined without spaces, in this fixed order: `written,closed,declined,dropped,no-op,stopped,unfetched,close-failed,close-by-hand`; format each as `<key>=<count>`. Start the message with `gauntlet: done written=1` for an ended singleton whose only outcome is one written ticket; use the same counters rule for every singleton, including `gauntlet: done stopped=1`. Count an integrity stop left without recovery values as `stopped`, not declined; human decline and drop are not failures. While a hard-stop recovery question remains active, emit `gauntlet: question` and no settlement line. Keep ended stopped items settled, without reopening questions or offering new writes.
|
|
210
|
+
|
|
211
|
+
Preserve one line per ref below the settlement line: `<ref>: written | closed | close failed (<operation>: <reason>) | close by hand | dropped | declined | stopped | no-op | unfetched` (use the drafted title for create).
|
|
@@ -6,7 +6,10 @@ Emit when no escalation model resolves, the escalated dispatch errors, its one e
|
|
|
6
6
|
|
|
7
7
|
## Template
|
|
8
8
|
|
|
9
|
+
Read and apply [menu-layout](../brainstorming/reference/menu-layout.md). Start the message with `gauntlet: question` alone on the first output line, followed by a newline before the stop note; this is an implementation decision, not a done or stuck outcome.
|
|
10
|
+
|
|
9
11
|
```
|
|
12
|
+
gauntlet: question
|
|
10
13
|
Stopped on task <n> (<title>)[; escalated round on <implModel> did not resolve it].
|
|
11
14
|
|
|
12
15
|
Problem: <one sentence: what is wrong and why it remains unresolved>
|
|
@@ -37,6 +40,7 @@ Pick one, or give another fix.
|
|
|
37
40
|
## Example
|
|
38
41
|
|
|
39
42
|
```
|
|
43
|
+
gauntlet: question
|
|
40
44
|
Stopped on task 4 (retry policy for the outbound client); escalated round on <provider>/<model>:high did not resolve it.
|
|
41
45
|
|
|
42
46
|
Problem: `RetryPolicy.next()` returns 0 ms for the first retry, but the client treats 0 as "no
|
|
@@ -154,7 +154,9 @@ The check: bare `git status --porcelain` — untracked files count as dirty. Nev
|
|
|
154
154
|
|
|
155
155
|
**Clean** → proceed (create the worktree if not yet created, then Step 4).
|
|
156
156
|
|
|
157
|
-
**Dirty
|
|
157
|
+
**Dirty**:
|
|
158
|
+
|
|
159
|
+
Start the message with `gauntlet: question` alone at column zero on the first physical line, followed by a newline. Never append a colon to the marker. Follow the [first-line rule](../brainstorming/reference/menu-layout.md). Report the porcelain output verbatim and ask whether to clean up first (stash/commit) or proceed. Never run tests as a fallback; never auto-stash or auto-clean. On fresh paths the ask is about base hygiene — a user who *meant* the dirt to be part of the base commits it, and creation proceeds from the new HEAD. On the Step 0 path the ask is "continue working in a dirty workspace?" — the dirt is already in the workspace, not merely beside it.
|
|
158
160
|
|
|
159
161
|
**Provenance note (report-only, never a gate).** Fresh-creation paths only — never Step 0 (an already-linked worktree was branched in some earlier invocation; there is no "created from" to compare this run). Resolve the default branch as `git symbolic-ref --short refs/remotes/origin/HEAD` with the leading `origin/` stripped; compare that short name to the source checkout's `git branch --show-current`. If they differ and the user did not name a base in the request, append one declarative line to the Step 4 report: `Note: branching from <ref>, not <default>.` — execution continues, no confirmation is awaited. If resolution fails (no remote, no `origin/HEAD`), skip the note silently. No other default-branch machinery.
|
|
160
162
|
|
|
@@ -173,6 +175,8 @@ Every later skill takes `<full-path>` as a value: dispatch `cwd: "<full-path>"`,
|
|
|
173
175
|
|
|
174
176
|
## Detached HEAD
|
|
175
177
|
|
|
178
|
+
Start the message with `gauntlet: question` alone at column zero on the first physical line, followed by a newline, for the branch/base choice. Never append a colon to the marker. Follow the [first-line rule](../brainstorming/reference/menu-layout.md).
|
|
179
|
+
|
|
176
180
|
If `git symbolic-ref -q HEAD` returns nothing, you're on a detached HEAD. Do not create a worktree from this state — first ask the user whether to branch from the current commit or from `main`.
|
|
177
181
|
|
|
178
182
|
## Keeping a Worktree Current
|
|
@@ -176,7 +176,7 @@ Per round:
|
|
|
176
176
|
that omits `model:` when `closureReview.model` is set, and warns (non-blocking)
|
|
177
177
|
on one whose model differs. Mark every `Gn` the re-audit reports `DELIVERED`
|
|
178
178
|
`complete`; open ones stay `in_progress`.
|
|
179
|
-
6. **Converge or continue**: verdict `CONFORMS` → Convergence below. Open gaps
|
|
179
|
+
6. **Converge or continue**: verdict `CONFORMS` → Convergence below. Start the message with `gauntlet: gate=verification-before-completion/step-6` alone on the first output line, followed by a newline before the human escalation text, including Convergence cap exhaustion. Read and apply [menu-layout](../../brainstorming/reference/menu-layout.md); ask for explicit funding of additional rounds. Emit this proactively, independent of any runtime guard error. Keep verification incomplete; emit no done or stuck line here or at intermediate closure. Open gaps
|
|
180
180
|
within the cap → re-partition (per the rule above) and start the next
|
|
181
181
|
round. Cap (`gauntlet_setting({ key: "closureReview" }).maxFixRounds`,
|
|
182
182
|
default `5`, floors negatives at `0`, normalizes missing or non-integer values to `5`) reached
|
|
@@ -70,7 +70,7 @@ The main loop never writes the plan. One fresh `plan-writer` child does the reco
|
|
|
70
70
|
No `output:`, no `model:` (`subagents.agentOverrides.plan-writer.model` applies when set, else the child inherits the main loop). The `acceptance` line is required: without it pi-cohort appends a structured-report contract that the child's one-line reply would fail. Fill the five paths and, when step 6 or an amendment supplies one, append a `Findings:` or `Amend:` block after the template; compose nothing else.
|
|
71
71
|
4. The dispatch errored, returned an async handle, or left the plan path missing or empty: stop and report. There is no parent-authored fallback.
|
|
72
72
|
5. `plan_check({ planPath: "<abs plan path>" })` in the parent. This is the stamping call; run it whichever line the child replied with.
|
|
73
|
-
6. Branch on the pair (child reply, parent check):
|
|
73
|
+
6. Branch on the pair (child reply, parent check). Start the message with `gauntlet: question` alone at column zero on the first physical line, followed by a newline, for every user-facing baseline-failure, dirty-source, or contract question, including a second verbatim `FAIL`. Never append a colon to the marker. Follow the [first-line rule](../brainstorming/reference/menu-layout.md):
|
|
74
74
|
- `PLAN WRITTEN` + `PASS` -> step 7.
|
|
75
75
|
- `OPEN QUESTIONS` + any result -> read the section; absent or exactly `- none` takes the `PLAN WRITTEN` branch. For substantive rows, use the table below. On a pause retain phase `plan` as `in_progress` and its substep; no stamp or `plan_tracker` init.
|
|
76
76
|
|