pi-gauntlet 7.38.1 → 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.
Files changed (35) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +8 -4
  3. package/extensions/phase-tracker.test.ts +3 -1
  4. package/extensions/phase-tracker.ts +2 -1
  5. package/package.json +2 -2
  6. package/skills/brainstorming/SKILL.md +15 -8
  7. package/skills/brainstorming/gatherer.md +3 -3
  8. package/skills/brainstorming/reference/amendment-surface.md +4 -0
  9. package/skills/brainstorming/reference/menu-layout.md +20 -0
  10. package/skills/brainstorming/reference/pr-subject.md +13 -1
  11. package/skills/brainstorming/reference/spec-finalization.md +12 -8
  12. package/skills/brainstorming/reference/spec-pr.md +62 -0
  13. package/skills/brainstorming/reference/ticket-acceptance.md +3 -1
  14. package/skills/chase-bug/SKILL.md +6 -0
  15. package/skills/check-delivery/SKILL.md +6 -0
  16. package/skills/finishing-a-development-branch/SKILL.md +17 -17
  17. package/skills/finishing-a-development-branch/reference/disposition-protocol.md +2 -1
  18. package/skills/finishing-a-development-branch/reference/spec-pr.md +39 -0
  19. package/skills/gatekeep-pr/reference/batch.md +2 -0
  20. package/skills/gatekeep-pr/reference/cleanup.md +4 -0
  21. package/skills/gatekeep-pr/reference/menus.md +21 -0
  22. package/skills/gatekeep-pr/reference/post-selection-loop.md +2 -0
  23. package/skills/gatekeep-pr/reference/sync.md +6 -0
  24. package/skills/gauntlet-handoff/SKILL.md +8 -4
  25. package/skills/gauntlet-performance/SKILL.md +4 -2
  26. package/skills/gauntlet-resume/SKILL.md +16 -13
  27. package/skills/gauntlet-resume/reference/brief-contract.md +2 -0
  28. package/skills/gauntlet-resume/reference/reconstruction.md +10 -2
  29. package/skills/loop-implementation/SKILL.md +2 -0
  30. package/skills/shape-ticket/SKILL.md +4 -0
  31. package/skills/shape-ticket/reference/repo-audit.md +5 -1
  32. package/skills/subagent-driven-development/stop-note.md +4 -0
  33. package/skills/using-git-worktrees/SKILL.md +5 -1
  34. package/skills/verification-before-completion/reference/conformance-check.md +1 -1
  35. package/skills/writing-plans/SKILL.md +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
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
+
9
+ ## v7.39.0 - 2026-10-28
10
+
11
+ ### Added
12
+
13
+ - Spec gate option 6 `approve, hand off as draft PR`: approves the spec's content only, writes `**Engine:** deferred` under `**Amend-grant:** none`, pushes the branch, opens a draft PR carrying just the spec, and ends the flow without planning. The local branch is kept; a gauntlet-owned worktree is removed, a host-owned checkout is reported. Row 6 is withheld on PR subjects and when the diff against the default branch is not spec-only.
14
+ - `brainstorming #N` on an open PR whose diff is one added spec carrying `**Engine:** deferred` plus banner-only predecessor edits re-presents the gate with options 1/2/4/5 (3 only with a pinned council audit), skipping gather, questionary, scout, and council; approval writes `**Engine:**`, `**Amend-grant:**`, and `**PR:** <owner/repo#N>` as a new commit and chains as today. A spec-only diff without the marker runs the normal brainstorm path with the carried spec as the draft; every other PR keeps the rework path.
15
+ - Finishing a spec with `**PR:**` and no `## Rework record` offers `Push to PR #N and mark it ready for review` and `Push to PR #N, keep it a draft` in place of the create rows (non-force push, no body rewrite; row 1 runs `gh pr ready`), withheld when origin's branch head moved. A spec still marked `**Engine:** deferred` stops finishing and `gauntlet-resume` with `spec approved for handoff only - run brainstorming #N`.
16
+
3
17
  ## v7.38.1 - 2026-10-28
4
18
 
5
19
  ### Changed
package/README.md CHANGED
@@ -36,13 +36,13 @@ pi-gauntlet's only hard dependency is pi-cohort - every gate that dispatches a r
36
36
  Concretely, one change through the gauntlet:
37
37
 
38
38
  0. *(Optional)* Before there's even a spec, `/skill:shape-ticket` can create one tracker issue or repair a comma/whitespace list of issue refs - shaping each into a Context/Problem/Idea/Acceptance Criteria ticket, grounded by a repository audit, an AC integrity check, and a cheap council roast. Repair finishes preparation for all tickets before presenting exact-diff confirmations sequentially in ref order; each approval writes that ticket before the next gate, and may include one optional gated comment for a Reporter note or overlap evidence. The audit checks factual claims, Idea fit, AC mechanisms against cited repo guidance, and already-stated observable legs in configured sibling checkouts. It reports in-motion work and attempts a best-effort scenario through authorized current-system reads, without promising reproduction or a fix; missing access or nothing to observe is reported, not a new approval gate. Implementer detail moves into the gated Reporter note; brainstorming reads that note with the ticket so the spec retains the detail. A failed roast is retried once, then surfaced inline at the gate if it fails again. It's a tool, not a phase: no worktree, no plan/phase tracker, runs from any repo state. The agent may start it on its own when the ask is "file a ticket" or another skill routes there; the write still waits for your yes on the presented diff. Similarly, `/skill:chase-bug` triages a raw bug report into an evidenced verdict - and can hand off to shape-ticket, brainstorming, or a bounded hotfix - before any spec exists.
39
- 1. Opt in with `/skill:brainstorming` and describe the change. The command is the reliable discovery-and-entry path; explicit prose requesting brainstorming/the gauntlet also supplies consent when the skill is already loaded or an available instruction or route identifies it. An ordinary implementation request or an agent recommendation is not consent. A leading run of GitHub references (`#N`, `owner/repo#N`, or a `/pull/N` or `/issues/N` URL), separated by whitespace or commas, resolves each reference as a PR first: related open, same-repository, non-fork PRs on one base form one rework subject, including drafts. Admission runs in listed order and relatedness is checked before provisioning; the first retained PR is home, and member heads merge into its existing branch in listed order before the fetched base merges. An unresolved member conflict after its scoped helper aborts that merge and stops the run before any spec, later merge, push, or close. A single non-PR reference follows the ticket path. The first non-reference token starts intent text; mid-sentence references and other ticket/free-text subjects keep their existing paths. The combined code, PR-carried specs, claims, and review threads are the brainstorm input, with each PR's provenance retained; only home's bound ticket supplies acceptance criteria, while member tickets supply context. A single PR retains the same rework path without member merges or a close offer. The combined state is judged against constraints from the fetched current base HEAD, not the fork point or the PRs' proposed policy edits; see the [PR-subject contract](skills/brainstorming/reference/pr-subject.md) and [PR-head worktree owner](skills/using-git-worktrees/reference/pr-head.md). **`brainstorming`** sets up an isolated worktree (on the existing branch for PR rework), explores the codebase, and turns the subject into a written spec - when its recon finds a cited case that the ask is the wrong change (misdiagnosed, wrong-sized, already solved, a band-aid, or cutting across a sound pattern - including a repo convention that is itself debt) and can name the alternative, question one is a framing question (`as framed`, `pivot: <alternative>`, or `smaller or none`); otherwise it opens with one sentence naming what it checked, and every approach it proposes ends with a `Pattern:` line naming what it follows or cuts across; when the run starts from a ticket, the spec carries the ticket's acceptance criteria verbatim, each with a disposition (`in-scope`, `deviates:`, `deferred:`, `venue:`, `elsewhere:` for a row another repo's part delivers), scope cuts come only from your answer to a cut question and are listed at the gate, the conformance gate checks the in-scope ones, and `/skill:check-delivery` verifies `venue:` rows before the prod deploy. A multi-model critique runs on it automatically. If the spec replaces a known prior spec, brainstorming marks the predecessor with a `> **Superseded by:**` banner under its title (default format, syntax overridable via `.pi/gauntlet-overrides.md`; candidates come from brainstorming's scout recon, never a mechanical sweep). **You read and approve the spec - human gate 1.** Before approval, PR rework's sole write/run exception outside the spec directories permits only the base merge, each admitted member-head merge, their conflict helpers' edits to the conflicted files, and their scoped conflict tests; other subjects have no implementation code yet.
39
+ 1. Opt in with `/skill:brainstorming` and describe the change. The command is the reliable discovery-and-entry path; explicit prose requesting brainstorming/the gauntlet also supplies consent when the skill is already loaded or an available instruction or route identifies it. An ordinary implementation request or an agent recommendation is not consent. A leading run of GitHub references (`#N`, `owner/repo#N`, or a `/pull/N` or `/issues/N` URL), separated by whitespace or commas, resolves each reference as a PR first: related open, same-repository, non-fork PRs on one base form one rework subject, including drafts. Admission runs in listed order and relatedness is checked before provisioning; the first retained PR is home, and member heads merge into its existing branch in listed order before the fetched base merges. An unresolved member conflict after its scoped helper aborts that merge and stops the run before any spec, later merge, push, or close. A single non-PR reference follows the ticket path. The first non-reference token starts intent text; mid-sentence references and other ticket/free-text subjects keep their existing paths. The combined code, PR-carried specs, claims, and review threads are the brainstorm input, with each PR's provenance retained; only home's bound ticket supplies acceptance criteria, while member tickets supply context. A single PR retains the same rework path without member merges or a close offer. The combined state is judged against constraints from the fetched current base HEAD, not the fork point or the PRs' proposed policy edits; see the [PR-subject contract](skills/brainstorming/reference/pr-subject.md) and [PR-head worktree owner](skills/using-git-worktrees/reference/pr-head.md). **`brainstorming`** sets up an isolated worktree (on the existing branch for PR rework), explores the codebase, and turns the subject into a written spec - when its recon finds a cited case that the ask is the wrong change (misdiagnosed, wrong-sized, already solved, a band-aid, or cutting across a sound pattern - including a repo convention that is itself debt) and can name the alternative, question one is a framing question (`as framed`, `pivot: <alternative>`, or `smaller or none`); otherwise it opens with one sentence naming what it checked, and every approach it proposes ends with a `Pattern:` line naming what it follows or cuts across; when the run starts from a ticket, the spec carries the ticket's acceptance criteria verbatim, each with a disposition (`in-scope`, `deviates:`, `deferred:`, `venue:`, `elsewhere:` for a row another repo's part delivers), scope cuts come only from your answer to a cut question and are listed at the gate, the conformance gate checks the in-scope ones, and `/skill:check-delivery` verifies `venue:` rows before the prod deploy. A multi-model critique runs on it automatically. If the spec replaces a known prior spec, brainstorming marks the predecessor with a `> **Superseded by:**` banner under its title (default format, syntax overridable via `.pi/gauntlet-overrides.md`; candidates come from brainstorming's scout recon, never a mechanical sweep). **You read and approve the spec - human gate 1.** Options 1/2/4/5 approve and pick an engine; option 6 approves the content only: it writes `**Engine:** deferred` under `**Amend-grant:** none`, pushes the branch, opens a draft PR carrying just the spec, prints the URL, and ends the flow - no plan, no loop, no handoff brief. The branch stays; a gauntlet-owned worktree is removed, a host-owned checkout is reported and left. Option 6 is withheld on a PR subject (`Withheld: draft PR - #N already exists`) and when the branch's diff against the default branch is not spec-only. A later `brainstorming #N` on that PR classifies it from the diff alone: one added spec carrying the marker plus banner-only predecessor edits re-presents the gate with 1/2/4/5 (3 only when the spec commit carries a council audit) and skips gather, questionary, council, and scout; a spec-only diff without the marker prints `spec-only PR without the gate marker - running lint and council` and takes the normal brainstorm path with the carried spec as the draft; any other diff takes the rework path. Approval at that re-gate writes `**Engine:**`, `**Amend-grant:**`, and `**PR:** <owner/repo#N>` as a new commit on the PR branch and chains into planning or the loop as usual. Before approval, PR rework's sole write/run exception outside the spec directories permits only the base merge, each admitted member-head merge, their conflict helpers' edits to the conflicted files, and their scoped conflict tests; other subjects have no implementation code yet.
40
40
  2. By default, **`writing-plans`** decomposes the approved spec into atomic, independently-verifiable tasks, grouped into parallel waves where they don't touch the same files. Experimental approval options 4/5 instead select **`loop-implementation`**: the plan phase is skipped and a stamped acceptance-criteria ledger replaces the task plan. Option 4 retains amendment review; option 5 grants auto-apply amends, with redraws still stopping. See [Loop engine operations](doc/configuration.md#loop-engine-operations).
41
41
  3. **`subagent-driven-development`** executes the plan one task at a time, each in a fresh subagent, behind spec-compliance review then code-quality review. TDD-locked: red, green, refactor. Independent implementation, review, and council batches remain parallel, but their dispatches are foreground: the orchestrator waits for terminal results before accepting work or advancing a phase.
42
42
  The loop alternative to step 3 runs one fresh `loop-implementer` per seed or row iteration, without implement-phase reviewers. It stops for a human decision on stagnation or a failed exit verification; passing full verification with every row closed enters the same verify gates.
43
43
 
44
44
  4. **verify**: the parent first runs the plan's full verification command set (the ledger's `verification:` command for loop); only a passing result permits whole-diff code review, then the **conformance gate**. A review fix invalidates that result, so the parent reruns full verification before the next review or conformance gate. When the overrides file declares a happy path for the touched paths (see [Project-specific overrides](#project-specific-overrides)), the parent runs it once here, between code review and the conformance gate, and the reviewer reads its transcript as runtime evidence - a hang or a failed request shows up in the audit with the transcript quoted - as a gap when an origin clause ties to it, otherwise as a `happy-path: failed - unattributable` line - never as a silent green. The conformance subagent reads the finished code and docs against your *original words* from step 1, not the plan, and reports per-requirement: delivered, partial, missing, drifted, or unauthorized. Unauthorized rows - shipped surface no human input asked for, whether it crept in or was laundered through the spec - follow their recommendation like every other row: a contained removal auto-runs, anything another requirement leans on is deferred with a plain-language "I'd cut it / I'd keep it" recommendation. Inside a brainstorming-entered flow this gate is machine-blocked from being skipped. Compatible executable recommendations auto-run through an isolated fix-and-re-audit loop with no prompt; anything still open surfaces as a numbered decision brief - one item per decision, the problem in plain words first, lettered options each with a one-line consequence, and `Recommended: <letter> - <reason>` or `No recommendation - pick one`. Reply with one line per item (`1. B`), or bare `1` to take every recommendation (no-recommendation items are re-asked by number); a current `CONFORMS` / no-concerns result goes straight to the branch options with no extra conformance sign-off.
45
- 5. **`finishing-a-development-branch`**: PR, draft PR, squash, keep, or discard; PR rework also offers a non-force push to the existing PR branch. That push proves every recorded original head remains an ancestor, preserves history, and appends a `## Rework` block naming absorbed PRs while retaining the original description bytes. Only after a successful push and home-description edit does one gated confirmation show the exact close comments and eligible member targets, linking home; declining or any other finish option leaves members open. Closing never deletes member branches, and finish posts no review-thread replies. Its `Before:` handle includes the full portable pre-rework SHA and the local `refs/gauntlet/pre-rework/pr-<N>` ref in the rework checkout. The [finishing owner](skills/finishing-a-development-branch/SKILL.md#pr-subject-row-1-push-to-the-pr-branch) defines the landing and body-update contract. Once a PR exists, run `/skill:gatekeep-pr <pr>` to verify it before merging - it judges the diff against the spec at the PR's head (the acceptance-criteria dispositions and Design you approved; the PR description when no spec applies) - rows the spec defers or deviates are settled, every other row needs its mechanism (code, tests, docs) - and against the rubric; whatever can be seen only after merge is left to step 6. **Human gate 2** - the only other decision you make.
45
+ 5. **`finishing-a-development-branch`**: PR, draft PR, squash, keep, or discard; PR rework also offers a non-force push to the existing PR branch. A spec whose header carries `**PR:**` (approved at a spec-PR re-gate) and no `## Rework record` replaces the two create rows with `Push to PR #N and mark it ready for review` and `Push to PR #N, keep it a draft` (`Push to PR #N (already ready for review)` when the PR is already ready): both push without force after strip-and-seal, the first then runs `gh pr ready`, neither rewrites the PR body, and both are withheld when origin's branch head is no longer an ancestor of local HEAD. A spec still carrying `**Engine:** deferred` stops finishing (and `gauntlet-resume`) with `spec approved for handoff only - run brainstorming #N` before any phase change, verification, or push. The PR-rework push proves every recorded original head remains an ancestor, preserves history, and appends a `## Rework` block naming absorbed PRs while retaining the original description bytes; the header-linked `**PR:**` push leaves the body untouched. Only after a successful rework push and home-description edit does one gated confirmation show the exact close comments and eligible member targets, linking home; declining or any other finish option leaves members open. Closing never deletes member branches, and finish posts no review-thread replies. Its `Before:` handle includes the full portable pre-rework SHA and the local `refs/gauntlet/pre-rework/pr-<N>` ref in the rework checkout. The [finishing owner](skills/finishing-a-development-branch/SKILL.md#pr-subject-row-1-push-to-the-pr-branch) defines the landing and body-update contract. Once a PR exists, run `/skill:gatekeep-pr <pr>` to verify it before merging - it judges the diff against the spec at the PR's head (the acceptance-criteria dispositions and Design you approved; the PR description when no spec applies) - rows the spec defers or deviates are settled, every other row needs its mechanism (code, tests, docs) - and against the rubric; whatever can be seen only after merge is left to step 6. **Human gate 2** - the only other decision you make.
46
46
  6. *(Optional)* Once the merge lands, `/skill:check-delivery <ref>` can prove delivery - default-branch landing, delivery target, per-AC evidence - before the tracker status advances. Explicit ask only, no auto-chain: deploys commonly lag merges by minutes to hours, so an auto-run would routinely check too early.
47
47
 
48
48
  Only the machine-owned `plan -> implement` and `verify -> ship` handoffs receive a branch-local one-shot nudge after an unexpected settled stop; it is fire-and-forget, does not bypass either human gate, and older Pi hosts without `agent_settled` retain existing behavior.
@@ -54,6 +54,8 @@ flowchart LR
54
54
  T -.-> R
55
55
  B --> G1{{human gate 1:<br/>approve spec}}
56
56
  G1 --> P[plan]
57
+ G1 -.option 6.-> H[draft spec PR]
58
+ H -.brainstorming re-entry.-> G1
57
59
  P --> I[implement<br/>waves + reviews]
58
60
  I --> V[verify]
59
61
  V --> M{{machine gate:<br/>conformance vs<br/>original words}}
@@ -69,7 +71,7 @@ In create mode, `shape-ticket` runs one bounded overlap check after clarificatio
69
71
 
70
72
  Use `/skill:shape-ticket --skip-overlap <ask>` to bypass discovery explicitly. Repair mode never discovers candidates. Bypass still retains source reads, known conflicts, integrity checks, roast, approval, and source revalidation. Incomplete search coverage is disclosed, not treated as proof of no overlap; independent sessions can still race, so this is not a uniqueness guarantee.
71
73
 
72
- Everything between gate 1 and gate 2 - task breakdown, implementation, both review passes - runs without you in the loop. Changing an approved spec later goes through brainstorming's `Amending an approved spec`: a fresh-context reviewer clears evidence-backed factual corrections on its own, escalations reach you as one readable batch, and only a redraw is a full stop - not a third numbered gate. That's the mechanism. What follows is the machinery behind it.
74
+ Everything between gate 1 and gate 2 - task breakdown, implementation, both review passes - runs without you in the loop, once gate 1 picks an engine; option 6 parks the approved spec in a draft PR and planning starts only when someone runs `brainstorming #N` on it and approves at the re-gate. Changing an approved spec later goes through brainstorming's `Amending an approved spec`: a fresh-context reviewer clears evidence-backed factual corrections on its own, escalations reach you as one readable batch, and only a redraw is a full stop - not a third numbered gate. That's the mechanism. What follows is the machinery behind it.
73
75
 
74
76
  ## Architecture
75
77
 
@@ -126,7 +128,7 @@ Run by a human against pi-cohort >= 7.1.0, before a pi-gauntlet release claims t
126
128
  ## Requirements
127
129
 
128
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.
129
- - [pi-cohort](https://github.com/jjuraszek/pi-cohort) >= 7.6.2 - 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.
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.
130
132
 
131
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.
132
134
 
@@ -578,6 +580,8 @@ Anything a wrapper skill contains beyond trigger phrases is misplaced - move it
578
580
 
579
581
  ## Configuring the gates
580
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
+
581
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.
582
586
 
583
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 ?? "", /5 fix round\(s\) used against a cap of 5 \(granted rounds included\); escalate to the human/);
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.38.1",
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.2"
65
+ "pi-cohort": ">=7.6.3"
66
66
  },
67
67
  "dependencies": {
68
68
  "yaml": "^2.9.0"
@@ -34,7 +34,7 @@ Treat the flag as discovery control, not harness authorization. The command reli
34
34
 
35
35
  ## Checklist
36
36
 
37
- Work through the items below **in order**. After a user answer or completed side task, resume the current checklist step and perform the next authorized action in the same turn, advancing once that step's required decisions and approvals are satisfied. Continue until a required question is unanswered, an existing approval is pending, the user explicitly pauses, or a failed required tool or unavailable required resource blocks progress. This is your own checklist to follow, not a `plan_tracker` plan — brainstorming is open-ended exploration, and `plan_tracker` is execution-only (the implement phase). The terminal state is the user review gate; after approval route 1/2 to `/skill:writing-plans` and 4/5 to `/skill:loop-implementation` per the gate. Do not jump ahead of approval, and do not silently drop the critique pass.
37
+ Work through the items below **in order**. After a user answer or completed side task, resume the current checklist step and perform the next authorized action in the same turn, advancing once that step's required decisions and approvals are satisfied. Continue until a required question is unanswered, an existing approval is pending, the user explicitly pauses, or a failed required tool or unavailable required resource blocks progress. This is your own checklist to follow, not a `plan_tracker` plan - brainstorming is open-ended exploration, and `plan_tracker` is execution-only (the implement phase). The terminal state is the user review gate; after approval route 1/2 to `/skill:writing-plans` and 4/5 to `/skill:loop-implementation` per the gate; 6 ends the flow after publishing. Do not jump ahead of approval, and do not silently drop the critique pass.
38
38
 
39
39
  1. **Start brainstorm tracking (fresh epoch)** - as the first action on authorized fresh entry, before reading code, the worktree, or answering the user, reset both trackers and start the phase. A new brainstorm owns a clean slate, so stale phases and tasks from earlier work are cleared; re-entering mid-brainstorm is safe (nothing to lose, same clean slate):
40
40
 
@@ -44,7 +44,7 @@ Work through the items below **in order**. After a user answer or completed side
44
44
  phase_tracker({ action: "start", phase: "brainstorm" })
45
45
  ```
46
46
 
47
- 2. **Set up the worktree** - resolve the leading run per `reference/pr-subject.md`; pass the ordered per-PR array (home first) to `/skill:using-git-worktrees`' PR-head path. Then see [Worktree First](#worktree-first).
47
+ 2. **Set up the worktree** - resolve the leading run per `reference/pr-subject.md`; pass the ordered per-PR array (home first) to `/skill:using-git-worktrees`' PR-head path. For a marked spec PR, follow `reference/spec-pr.md`'s re-gate after provisioning (steps 3-11 skipped); otherwise see [Worktree First](#worktree-first).
48
48
  3. **Gather context** - read [Ticket Handling](#ticket-handling), then follow [`gatherer.md`](gatherer.md) without a human stop.
49
49
  4. **Understand the idea against the draft** - if `reference/ticket-acceptance.md` is not already in context this session (restored entry, or a redraw after a fresh start), read [Ticket Handling](#ticket-handling) before the rest of this step; then see [Understand the idea](#3-understand-the-idea).
50
50
  5. **Propose 2-3 approaches** - see [Explore approaches](#4-explore-approaches).
@@ -55,7 +55,7 @@ Work through the items below **in order**. After a user answer or completed side
55
55
  10. **Re-run placeholder scan** - follow [Spec Self-Review](#spec-self-review-before-user-review-gate).
56
56
  11. **Generate spec summary** - follow [User Review Gate](#user-review-gate).
57
57
  12. **User review gate** - follow [User Review Gate](#user-review-gate).
58
- 13. **Transition** - after approval, invoke `/skill:writing-plans` on 1/2 or `/skill:loop-implementation` on 4/5 per [User Review Gate](#user-review-gate).
58
+ 13. **Transition** - after approval, invoke `/skill:writing-plans` on 1/2 or `/skill:loop-implementation` on 4/5 per [User Review Gate](#user-review-gate); 6 ends the flow after publishing.
59
59
 
60
60
  ## Project Routing
61
61
 
@@ -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, open the first message 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.
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
@@ -164,7 +171,7 @@ Inside an opted-in flow, shared schemas, contracts, and invariants require a spe
164
171
 
165
172
  Write under the routed spec dir: pick the routing prose's dir (overrides file, `AGENTS.md`) when it is one of the resolved dirs, else the one resolved dir from `gauntlet_setting({ key: "flowGuards" })` that already exists in the repo, else the first resolved dir (`doc/specs` under the default). Name ticketed files `YYYY-MM-DD-<ticket-id>-<topic>.md`, otherwise `YYYY-MM-DD-<topic>.md`. Use a filename-safe tracker slug (`E-12345`, `gh-123`), but native references in plan headers and commits. `<topic>` is 3-6 kebab-case words without `-design` or another suffix.
166
173
 
167
- For a PR subject, apply `reference/pr-subject.md`: keep the bound-ticket filename; name an unbound spec `YYYY-MM-DD-pr-<N>-<topic>.md` from the PR title.
174
+ For a PR subject, apply `reference/pr-subject.md`: keep the bound-ticket filename; name an unbound rework spec `YYYY-MM-DD-pr-<N>-<topic>.md` from the PR title; the unmarked spec-only route keeps the carried spec path.
168
175
 
169
176
  Mint the slug once during gather and reuse it. If questionary invalidates it, write to the new path and delete the uncommitted draft.
170
177
 
@@ -178,7 +185,7 @@ Follow [Spec Council](reference/spec-finalization.md#spec-council) for the manda
178
185
 
179
186
  ## User Review Gate
180
187
 
181
- Follow [User Review Gate](reference/spec-finalization.md#user-review-gate) for summary, commit, approval, and automatic planning.
188
+ Follow [User Review Gate](reference/spec-finalization.md#user-review-gate) for summary, commit, approval, and selected-engine transition or option-6 publication.
182
189
 
183
190
  ## Amending an approved spec
184
191
 
@@ -198,13 +205,13 @@ Redraw: keep the worktree and the approved spec file. `plan_tracker({ action: "c
198
205
  - Draft overwrite without the same-turn full read, or overwrite via `edit` ([owner](#spec-self-review-before-user-review-gate)).
199
206
  - Dispatch while line 1 is the context-draft marker ([owner](#spec-self-review-before-user-review-gate)).
200
207
  - Inline scope or ambiguity checks ([owner](#spec-council)).
201
- - Gate after failed/skipped critique or before placeholder re-scan ([owner](#spec-self-review-before-user-review-gate)).
208
+ - Gate after failed/skipped critique or before placeholder re-scan, except the marked spec-PR re-gate ([owner](#spec-self-review-before-user-review-gate)).
202
209
  - Gate without summary `Read` last, or with a paraphrased summary ([owner](#user-review-gate)).
203
210
  - Human stop between gather and question one ([owner](gatherer.md)).
204
211
  - Proposed-change execution before approval ([owner](#hard-constraint)).
205
212
  - Plan before approval; brainstorming invocation for an amend ([owner](#user-review-gate)).
206
213
  - Missing predecessor banner; invalid multi-spec split ([owner](#spec-self-review-before-user-review-gate); [owner](#2-scope-check)).
207
- - Gate reached without the second predecessor pass ([owner](#spec-self-review-before-user-review-gate)).
214
+ - Gate reached without the second predecessor pass, except the marked spec-PR re-gate ([owner](#spec-self-review-before-user-review-gate)).
208
215
  - Approaches before the premise note states a contradicted claim's correction ([owner](#3-understand-the-idea)).
209
216
  - Approaches before the framing question or the holds-statement (either may follow the premise correction in the same message); a holds-statement that names nothing checked ([owner](#3-understand-the-idea)).
210
217
  - Amend without `reference/amendment-surface.md`; waiting after an amend grant; auto-applying a redraw ([owner](#amending-an-approved-spec)).
@@ -125,8 +125,8 @@ Scout (always dispatched):
125
125
  > "Open questions that matter for the spec"
126
126
  > section. Compact handoff, not a dump.
127
127
 
128
- For a PR subject, supply this additional scout block as values from
129
- `reference/pr-subject.md` (keep scout unconditional):
128
+ For a rework PR subject (shape fails), supply this additional scout block as values
129
+ from `reference/pr-subject.md` (keep scout unconditional):
130
130
 
131
131
  > Require every retained PR's title/body, carried specs, and full threads before
132
132
  > gather, including N=1. Stop on query failure: `threads for #<N> not fetched (<gh error>)`.
@@ -230,7 +230,7 @@ convention; slug minted from the initial prompt):
230
230
  <scout output, or the degraded text>
231
231
 
232
232
  ## PR under rework
233
- <PR subject only: every per-PR scout subsection, ordered original heads, threads,
233
+ <rework PR subject only: every per-PR scout subsection, ordered original heads, threads,
234
234
  member-carried spec paths, and supplied Member merge/base values per
235
235
  reference/pr-subject.md; retain these values even when scout failed>
236
236
 
@@ -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
@@ -23,8 +23,20 @@ Parse the PR base repository from `url` and this checkout's repository from `git
23
23
 
24
24
  Append this paragraph only for foreign-repository, fork, and mixed-base failures: To rework these together anyway, merge the heads into one branch by hand, open one PR, and brainstorm that PR.
25
25
 
26
+ ## Spec-PR classifier
27
+
28
+ Immediately after ordered admission and before binding, classify N=1 read-only. Derive ROOT from the absolute git common directory using pr-head's Step 0 submodule guard before fetching. N>1 always follows relatedness and rework. Fetch `git -C "$ROOT" fetch origin <baseRefName> <headRefName>`, resolve `BASE_SHA=$(git -C "$ROOT" rev-parse origin/<baseRefName>)`, and inspect `git -C "$ROOT" diff --name-status <BASE_SHA>...<headRefOid>`. Stop on command errors. Apply [spec-pr.md](spec-pr.md)'s shared shape predicate with pinned BASE_SHA/headRefOid, inspecting modified hunks; read the added spec through `git show <headRefOid>:<path>` before testing its exact deferred header marker.
29
+
30
+ | Observation | Route |
31
+ |---|---|
32
+ | Shape fails | Continue unchanged through bind, gather, scout, and Rework record. |
33
+ | Shape passes, marker absent | Print `spec-only PR without the gate marker - running lint and council`. Provision the one-element admitted PR array through pr-head's checkout, base merge, and Step 4 report with no thread fetch (bypass its `## Fetch unresolved review threads` as on the marked route). Skip ticket binding, context-builder, the PR scout block, and gather; never write a `## Rework record`. Resume at checklist step 4 with the carried spec file at `<worktree>/<path>` as the draft, as a redraw does (recon falls to the questionary); spec-writing overwrites that file at its carried path. Run lint, council, and the gate as for any spec, with 6 withheld (`Withheld: draft PR - #N already exists`). On approval 1/2/4/5 persist `**Engine:**`, `**Amend-grant:**`, and `**PR:** <owner/repo#N>` as a new commit per spec-pr.md's re-gate persistence. |
34
+ | Shape and marker pass | Provision the one-element admitted PR array through pr-head's checkout/base merge/Step 4, then follow spec-pr.md's re-gate. Skip binding and all before-gather thread queries. Treat draft and ready PRs equally. |
35
+
26
36
  ## Relatedness before provisioning
27
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
+
28
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>)`.
29
41
 
30
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.
@@ -41,7 +53,7 @@ Pass an ordered array, home first, of exactly `{ number, url, title, headRefName
41
53
 
42
54
  ## Gather from the PR and fetched base
43
55
 
44
- Require every retained PR's title/body, carried specs, and full threads before spec-writing. Stop before gather on any query failure, N=1 included: `threads for #<N> not fetched (<gh error>)`; name the ref and reason for unreadable title/body/specs too. Discover PR-carried specs per PR with `git diff --name-only <BASE_SHA>...<that PR's headRefOid> -- <each flowGuards.specDirs dir>` using the resolved spec directories. Read every carried spec's contents with `git show <that PR's headRefOid>:<path>` as that PR's stated contract beside its title/body; preserve the owning PR, original head, and path even when multiple PRs carry different versions of the same path. List member-carried spec paths under their PR in `## Problem` so resume can exclude them from new-spec candidates. Only when superseded, name it in `**Predecessor:**` and apply `reference/superseding.md`'s banner; that banner is the allowed spec-directory write.
56
+ Apply this section's thread fetch, carried-spec discovery, scout dispatch, and `## PR under rework` rendering to the rework route only; the unmarked spec-only route skips gather. Require every retained PR's title/body, carried specs, and full threads before spec-writing. Stop before gather on any query failure, N=1 included: `threads for #<N> not fetched (<gh error>)`; name the ref and reason for unreadable title/body/specs too. Discover PR-carried specs per PR with `git diff --name-only <BASE_SHA>...<that PR's headRefOid> -- <each flowGuards.specDirs dir>` using the resolved spec directories. Read every carried spec's contents with `git show <that PR's headRefOid>:<path>` as that PR's stated contract beside its title/body; preserve the owning PR, original head, and path even when multiple PRs carry different versions of the same path. List member-carried spec paths under their PR in `## Problem` so resume can exclude them from new-spec candidates. Only when superseded, name it in `**Predecessor:**` and apply `reference/superseding.md`'s banner; that banner is the allowed spec-directory write.
45
57
 
46
58
  On every merge outcome, including clean, no-op, and unresolved, read constraints using `git show <BASE_SHA>:<path>`: `AGENTS.md`, the first-found overrides file (check `.pi/gauntlet-overrides.md`, `gauntlet-overrides.md`, `doc/gauntlet-overrides.md` in order at BASE_SHA), `REVIEW.md`, and all cited constraint documents. Carry missing-document results explicitly. Use these fetched base-HEAD rules, never fork-point or worktree copies. Treat PR edits to policy documents as proposals recorded under `changes:` or `dropped claims:`, not governing constraints.
47
59
 
@@ -16,8 +16,8 @@ Spec-writing replaces the context draft, in this exact order:
16
16
  Using `edit` at this step is a red flag. The header block (between the H1 and the
17
17
  first `##`) carries `**Amend-grant:** none` directly below `**Goal:**`; a redraw's
18
18
  rewrite carries `none` too - a redraw is a new approval, with no carry-over.
19
- For a PR subject, follow `pr-subject.md`'s spec contract: carry the draft's
20
- `## PR under rework` into `## Rework record` after `## Acceptance criteria`,
19
+ For a rework PR subject (a draft carrying `## PR under rework`), follow `pr-subject.md`'s spec contract:
20
+ carry the draft's `## PR under rework` into `## Rework record` after `## Acceptance criteria`,
21
21
  preserving its repeated PR/Pre-rework head/Threads groups, one per retained PR,
22
22
  home first, each 40-character pre-rework SHA, merge result,
23
23
  keeps/changes/dropped claims, thread dispositions and fetch status, contract exceptions,
@@ -53,7 +53,7 @@ After writing the spec to `<project>/doc/specs/<filename>.md` (per [Filename Con
53
53
  - **Placeholder scan.** Any `TODO`, `TBD`, `<fill in>`, `[example]`, `xxx`? Either resolve them or convert to explicit "Open Questions" with names.
54
54
  - **Internal consistency.** Does Section 4 contradict Section 2? Does the header block carry `**Amend-grant:**` exactly once with the value `none` (the [predicate](amendment-surface.md#standing-grants))? Are component names and field names consistent throughout? If the spec replaces a prior design, confirm the predecessor carries the supersession banner and its href resolves to this spec's final filename.
55
55
  - **Documentation named.** Does the spec name all three classes (feature/user-facing introduced; materially amended; derived/memory invalidated), or an explicit "none" for each? Enforce the materiality bar in `documentation-impact.md` without restating it: each listed doc names the category it clears, none is a code-mirror, amend-over-create was applied, and skill/agent bodies are implementation surface, not doc-impact entries here.
56
- - **Ticket contract present.** Require `## Acceptance criteria` in exactly three forms: ticket provenance (`Ticket <ref>, <heading or "checkbox list">, rows verbatim:`) with verbatim rows and dispositions; drafted provenance (`Drafted from the design, no ticket rows:` or `Drafted from the design, ticket <ref> has no acceptance criteria:`) with at least one `- [ ]` row and a disposition on every row; or the single line `none - ticket not fetched (<reason>)`. Reject `none - no ticket` and `none - ticket has no acceptance criteria` as final bodies. For a PR subject, require the complete `## Rework record` per `pr-subject.md`; absence fails inline lint, including after a full replacement or redraw. Build expected identities and original heads from the provisioning Step 4 report (home plus `MEMBER_HEADS`), not from the record itself. Require each expected identity's `PR:`/`Pre-rework head:`/`Threads:` group with its full matching head and a `### PR #<N>` provenance subsection; reject a missing group or subsection naming the missing PR. Apply the same predicate for N=1.
56
+ - **Ticket contract present.** Require `## Acceptance criteria` in exactly three forms: ticket provenance (`Ticket <ref>, <heading or "checkbox list">, rows verbatim:`) with verbatim rows and dispositions; drafted provenance (`Drafted from the design, no ticket rows:` or `Drafted from the design, ticket <ref> has no acceptance criteria:`) with at least one `- [ ]` row and a disposition on every row; or the single line `none - ticket not fetched (<reason>)`. Reject `none - no ticket` and `none - ticket has no acceptance criteria` as final bodies. For a rework PR subject (a draft carrying `## PR under rework`), require the complete `## Rework record` per `pr-subject.md`; absence fails inline lint, including after a full replacement or redraw. Build expected identities and original heads from the provisioning Step 4 report (home plus `MEMBER_HEADS`), not from the record itself. Require each expected identity's `PR:`/`Pre-rework head:`/`Threads:` group with its full matching head and a `### PR #<N>` provenance subsection; reject a missing group or subsection naming the missing PR. Apply the same predicate for N=1.
57
57
  - **Scope check.** Does every paragraph serve the goal? Cut filler. If something is out of scope, say it's out of scope.
58
58
  - **Ambiguity check.** Is every "we should..." backed by a concrete decision? Replace "we could probably" with "we will" or "we won't".
59
59
 
@@ -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 at the top of the gate. 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.
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>).
@@ -151,12 +152,15 @@ New predecessor candidates at spec-writing: <path> (<title>), ... - index rows a
151
152
  3 - show council dispositions: prints the council audit verbatim, then re-presents this gate. Not an approval.
152
153
  4 - approve, loop engine (experimental): skip the plan; iterate a fresh loop-implementer over the acceptance-criteria ledger; amendments stop for your review as under 1.
153
154
  5 - approve, loop engine, auto-apply amends: as 4 with option 2's amendment grant.
155
+ 6 - approve, hand off as draft PR: approve the spec's content only; push this branch and open a draft PR carrying just the spec; engine and amendment grant are chosen later by whoever runs `brainstorming #N` on that PR. Ends this flow without planning.
154
156
  Add "; fund N fix rounds" (or "N more fix rounds") to 1, 2, 4, or 5 to fund N extra attempts per stagnant loop row or N implement fix rounds past the escalated waves round.
155
157
 
156
158
  Or tell me what to change in the spec, or say "revert applied council edit <X>" to undo a specific applied edit.
157
159
  ```
158
160
 
159
- For zero `- [ ]` rows under `## Acceptance criteria`, render only options 1-3 and explain: "Loop engine unavailable: this spec has no acceptance-criteria rows." The only legal zero-row body is `none - ticket not fetched (<reason>)`; retain its paste-rows affordance. Whenever rows exist, render options 4/5. Keep the worker-path omission of option 3; do not invent a council audit.
161
+ For zero `- [ ]` rows under `## Acceptance criteria`, render only options 1, 2, 3, 6 (PR subject: 1, 2, 3) and explain: "Loop engine unavailable: this spec has no acceptance-criteria rows." The only legal zero-row body is `none - ticket not fetched (<reason>)`; retain its paste-rows affordance. Whenever rows exist, render options 4/5. Keep the worker-path omission of option 3; do not invent a council audit.
162
+
163
+ On every PR subject omit row 6 and print `Withheld: draft PR - #N already exists` under the list, reusing finishing's withheld-row layout; a hidden 6 gets the clarifying question naming rendered choices. Read [spec-pr.md](spec-pr.md) for option-6 reply decoding, publication, and marked-PR re-gating; its published-branch persistence replaces the local amend recipe below on the marked re-gate and the unmarked spec-only route only; a rework PR subject keeps the amend recipe.
160
164
 
161
165
  Render the drafted-only block in the template from the applied spec section, never from the summarizer: copy every row and disposition verbatim. Include it for a fetched ticket without ACs; omit it for ticket-row provenance. Approval ratifies these rows at this gate, with no pre-gate acceptance stop. On reply `3`, keep the block reused verbatim with the briefing; on a row-touching change request, render from the recommitted section; on redraw, render from the re-drafted section.
162
166
 
@@ -180,11 +184,11 @@ Wait for the user. Interpret funded replies with this table before routing chang
180
184
 
181
185
  For every value to persist, read [Standing grants](amendment-surface.md#standing-grants) and run Value decoding. Decode before `edit` or `--amend`; never persist a malformed token. Use the decoded table value in the approval persistence below, including budget-only approvals. In persistence narration, quote the exact resulting `**Amend-grant:**` value in full, including any funding suffix; never substitute an option name or "option-2 description plus suffix" for the persisted text.
182
186
 
183
- On a change request (including a revert), revise the spec and re-present - mint a **fresh** temp path for the re-dispatched summarizer (never reuse a prior round's path, so stale content can never be mistaken for the new summary). On `3` or its label alone: print the audit verbatim from `git -C <abs worktree path> show -s --format=%b HEAD` (never from a held tool result; the body survives the grant's `--amend --no-edit`), then re-present the same gate - the briefing text of the gate message just rendered, reused verbatim (no summarizer re-dispatch, no read of the removed `$SUMMARY_PATH`; if that text is no longer in context, the one-line degrade note takes its place), the `Council:` line, the adjacent lines, the rendered option rows; nothing in the spec or the commit changes. `3` plus a change request is a change request. `3` plus `1`/`2`/`4`/`5` prints and re-presents, and the approval is read only from a clean `1`/`2`/`4`/`5` on the re-presented gate - a reply carrying `3` never grants. A gate-round recommit (change request or revert) re-runs the same heredoc commit with the audit as its body, so HEAD always carries it; on a revert of edit X, move X's `Applied:` line to `Rejected:` with `-> reverted at gate` and recompute the `Council:` counts from the revised audit. On approval - `1`, `approve`, or equivalent prose approves without a grant; `2`, `approve, auto-apply amends`, or equivalent prose approves and grants; `4` approves without a grant; `5` approves and grants using option 2's description - first read [Standing grants](amendment-surface.md#standing-grants) (stop if unreadable). On every approval, `edit` the spec's `**Amend-grant:**` value to the decoded table value for funded replies, otherwise the granting sentence for 2/5 or `none` for 1/4. Write exactly one `**Engine:** loop` for 4/5 or `**Engine:** waves` for 1/2 directly below `**Amend-grant:**` in the header block (readers: absent -> `waves`). Then `git -C <abs worktree path> add -- <spec path>` and `git -C <abs worktree path> commit --amend --no-edit -q`, keeping the council-audit body; confirm `git -C <abs worktree path> show HEAD:<spec path>` contains both fields with the selected values and satisfies the grant predicate and Value decoding. A reply that mixes approval with a change request ("2 but rename the section") is a change request: revise, re-present, and read the grant only from the reply to the re-presented gate. If the amend or the HEAD check fails, stop and report; never proceed as granted. The plan and execution mode are mechanical derivatives, so the only human gate here is spec approval itself. Don't land the spec on `main`; it stays in the worktree and ships in the same squash commit as the implementation.
187
+ On a change request (including a revert), revise the spec and re-present - mint a **fresh** temp path for the re-dispatched summarizer (never reuse a prior round's path, so stale content can never be mistaken for the new summary). On `3` or its label alone: print the audit verbatim from `git -C <abs worktree path> show -s --format=%b HEAD` (never from a held tool result; the body survives the grant's `--amend --no-edit`), then re-present the same gate - the briefing text of the gate message just rendered, reused verbatim (no summarizer re-dispatch, no read of the removed `$SUMMARY_PATH`; if that text is no longer in context, the one-line degrade note takes its place), the `Council:` line, the adjacent lines, the rendered option rows; nothing in the spec or the commit changes. `3` plus a change request is a change request. `3` plus `1`/`2`/`4`/`5` prints and re-presents, and the approval is read only from a clean `1`/`2`/`4`/`5` on the re-presented gate - a reply carrying `3` never grants. A gate-round recommit (change request or revert) re-runs the same heredoc commit with the audit as its body, so HEAD always carries it; on a revert of edit X, move X's `Applied:` line to `Rejected:` with `-> reverted at gate` and recompute the `Council:` counts from the revised audit. On approval - `1`, `approve`, or equivalent prose approves without a grant; `2`, `approve, auto-apply amends`, or equivalent prose approves and grants; `4` approves without a grant; `5` approves and grants using option 2's description - first read [Standing grants](amendment-surface.md#standing-grants) (stop if unreadable). On every implementation approval (1/2/4/5), `edit` the spec's `**Amend-grant:**` value to the decoded table value for funded replies, otherwise the granting sentence for 2/5 or `none` for 1/4. Write exactly one `**Engine:** loop` for 4/5 or `**Engine:** waves` for 1/2 directly below `**Amend-grant:**` in the header block (readers: absent -> `waves`). Then `git -C <abs worktree path> add -- <spec path>` and `git -C <abs worktree path> commit --amend --no-edit -q`, keeping the council-audit body; confirm `git -C <abs worktree path> show HEAD:<spec path>` contains both fields with the selected values and satisfies the grant predicate and Value decoding. A reply that mixes approval with a change request ("2 but rename the section") is a change request: revise, re-present, and read the grant only from the reply to the re-presented gate. If the amend or the HEAD check fails, stop and report; never proceed as granted. The plan and execution mode are mechanical derivatives, so the only human gate here is spec approval itself. Don't land the spec on `main`; it stays in the worktree and ships in the same squash commit as the implementation.
184
188
 
185
189
  Post-approval changes follow [Amending an approved spec](../SKILL.md#amending-an-approved-spec).
186
190
 
187
- After approval, mark the brainstorm phase complete:
191
+ After implementation approval (1/2/4/5), mark the brainstorm phase complete:
188
192
 
189
193
  ```
190
194
  phase_tracker({ action: "complete", phase: "brainstorm" })
@@ -0,0 +1,62 @@
1
+ # Spec-only PR publication and re-gate
2
+
3
+ ## Shared predicate and marker
4
+
5
+ Resolve `gauntlet_setting({ key: "flowGuards" })` and use its `specDirs`. Inspect `git diff --name-status <base>...<head>` and every modified file's hunks against the same pinned endpoints. Require exactly one `A` under a resolved spec dir: the selected spec. Require every other entry to be an `M` under a spec dir that adds only active supersession-banner lines plus adjacent blank lines and removes nothing. Read [superseding.md](superseding.md): use `> **Superseded by:**` by default or the declared override syntax; enforce title-adjacent placement and append-only insertion below existing banners. Reject renames, deletes, multiple additions, non-spec paths, and arbitrary modifications. Evaluate the whole diff, not commit count: earlier implementation, non-default-source changes, and an ignore-file commit all count.
6
+
7
+ Keep shape separate from approval. Read the added spec with `git show <head>:<spec path>`; match `^\*\*Engine:\*\*[ \t]+deferred[ \t]*$` only in the header before the first `## `. Use that marker plus shape for re-gating. Use shape alone for publication. Ignore draft status, labels, PR body, telemetry, and audit presence as classification proof. Route N>1 through rework.
8
+
9
+ ## Publish option 6
10
+
11
+ Decode the reply before writes. A hidden `6` gets the clarifying question naming rendered choices. A funded `6` is malformed: re-present, write nothing. `3` plus `6` prints the audit and re-presents without approval; `6` plus a change request revises and re-presents.
12
+
13
+ On clean `6`, edit `**Amend-grant:** none` and exactly one `**Engine:** deferred` directly below it. A 6 never grants. Stage the spec with `git -C <worktree> add -- <spec path>`, then `git -C <worktree> commit --amend --no-edit -q`; verify both lines through `git -C <worktree> show HEAD:<spec path>`. Stop on failure.
14
+
15
+ Resolve the default base once, never substitute the worktree creation ref:
16
+
17
+ ```bash
18
+ DEFAULT=$(gh repo view --json defaultBranchRef -q .defaultBranchRef.name)
19
+ git -C <worktree> fetch origin "$DEFAULT"
20
+ git -C <worktree> diff --name-status origin/$DEFAULT...HEAD
21
+ ```
22
+
23
+ Prove the shared predicate against `origin/$DEFAULT` before pushing. Stop on command errors. On invalid shape print the offending name-status lines and `origin/$DEFAULT`, retain the amended spec and checkout, and redraw with `Withheld: draft PR - diff against origin/$DEFAULT is not spec-only (<paths>)` replacing 6. Keep implementation approvals available.
24
+
25
+ Push, then create with explicit head/base and the spec H1 as title. Run gh against the worktree repository:
26
+
27
+ ```bash
28
+ git -C <worktree> push -u origin <branch>
29
+ gh pr create --draft --head <branch> --base "$DEFAULT" --title "<spec H1 text>" --body-file - <<'EOF'
30
+ <gate summary verbatim, or the **Goal:** line on the degraded-summary path>
31
+ EOF
32
+ ```
33
+
34
+ | Observation | Action |
35
+ |---|---|
36
+ | Push rejected | Print git output; retain amended spec and checkout; re-present with 6 retryable. |
37
+ | Create fails after push | Print error and pushed branch. Keep brainstorm incomplete and checkout intact. Offer only `6 - retry opening the draft PR` and `Withheld: implementation approvals - the handoff commit is published; an approval would amend it`. |
38
+ | Retry 6 after published handoff | Refresh origin's branch head; require `origin/<branch>` == HEAD. On mismatch print both full SHAs and stop. On equality rerun create only, no push, no amend. |
39
+ | Create succeeds | Print URL before completing brainstorm; then perform ownership-based cleanup below. |
40
+
41
+ After URL output call `phase_tracker({ action: "complete", phase: "brainstorm" })`. Read finishing's [Step 6](../../finishing-a-development-branch/SKILL.md#step-6-cleanup-workspace), using only its ownership test and wrapper selection: resolve home/destroy, legacy native script, or native remove/prune. Disable every branch-deletion step, including within a destroy wrapper: verify the wrapper preserves the branch before running it; stop cleanup and report when it cannot. Never delete the local branch. Report host-owned or failed removal with checkout path and command output; explain that later `brainstorming #N` hits pr-head's checked-out-at-another-path stop until that checkout is gone. Start no plan or loop, produce no handoff brief, and leave telemetry unchanged.
42
+
43
+ ## Re-gate a marked spec PR
44
+
45
+ Reuse [pr-head](../../using-git-worktrees/reference/pr-head.md)'s checkout, base merge, and Step 4 report, not its before-gather thread fetch. Preserve its checked-out-at-another-path stop. On observed `merge: unresolved - <files>`, print `base merge unresolved for PR #N (<files>) - merge origin/<base> by hand in <worktree> and rerun brainstorming #N`; preserve checkout, render no gate, write no approval or repair task.
46
+
47
+ Skip ticket binding, context-builder, review threads, gather, questionary, spec-writing, inline lint, council, worker, and the second predecessor pass. Carry trailing intent as `Intent carried from the command: <text>` beside the gate.
48
+
49
+ Pin the originating audit once on the PR branch:
50
+
51
+ ```bash
52
+ AUDIT_SHA=$(git -C <worktree> log -1 --diff-filter=A --format=%H -- <spec path>)
53
+ git -C <worktree> show -s --format=%b "$AUDIT_SHA"
54
+ ```
55
+
56
+ Recognize an audit only with all `Applied:`, `Deferred:`, and `Rejected:` labels. A drafted-AC repair line alone is not an audit. Count Council from the pinned body; offer row 3 only with that audit and read that same body on 3, never HEAD. Audit absence does not block re-gating.
57
+
58
+ Reuse [User Review Gate](spec-finalization.md#user-review-gate)'s summarizer dispatch, fresh temp path, last content-producing Read, verbatim render, degraded path, and unconditional temp cleanup, but skip its unconditional initial spec commit. Render Scope cuts and drafted rows from the carried spec. Offer 1/2/4/5 and optional 3; with zero AC rows omit 4/5 and explain `Loop engine unavailable: this spec has no acceptance-criteria rows.` Withhold 6 with `Withheld: draft PR - #N already exists`; clarify a 6 reply by naming rendered choices.
59
+
60
+ For a change request, revise and stage the spec and reconciled banners; make a new commit without the old audit body (no new council ran). Re-dispatch the summarizer with a fresh temp path and re-present.
61
+
62
+ For approval 1/2/4/5, decode grant/funding under the ordinary gate. Replace deferred with waves or loop, write the decoded `**Amend-grant:**`, and write exactly one `**PR:** <owner/repo#N>` directly below Engine, lowercasing owner/repo parsed from the admitted PR URL. Stage and make a new commit `spec: select engine and grant for PR #N`; never amend a published commit. Verify all three fields through `git show HEAD:<spec path>` before brainstorm completion and the selected writing-plans/loop-implementation chain. Stop on persistence or verification failure. The unmarked route's gate approval (1/2/4/5) applies this same new-commit persistence: `waves` or `loop` as the engine, the decoded grant, and `**PR:**` directly below `**Engine:**`, never `--amend`.
@@ -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.** `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.
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