pi-gauntlet 5.3.6 → 5.3.7

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 CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## v5.3.7 - 2026-09-10
4
+
5
+ - `brainstorming`: the standalone "does this replace a prior spec" question is gone - the gather scout names candidate predecessor specs and round 1 states them; the design is presented in two rounds (architecture/components/data flow, then errors/testing/docs) with one approval each. (#27)
6
+ - `brainstorming`: new `## Amending an approved spec` section - diff + one-line impact approval, `plan_check` re-stamp, redraw test for large changes; `writing-plans`, `subagent-driven-development`, `finishing-a-development-branch` link to it instead of "frozen spec" wording. (#27)
7
+ - `plan_check`: `quote-integrity` treats a required literal equal to the header entrypoint as satisfied by the header, so a spec line carrying both a scoped command and the full-suite entrypoint no longer forces a spec edit. (#27)
8
+ - `brainstorming`, `subagent-driven-development`: Red Flags lists replaced by exact 10-bullet one-sentence lists. (#27)
9
+ - `phase-tracker`: restarting `implement` clears the conformance-dispatch latch, so a verify re-entered after an amendment rewind reruns the closure gate. (#27)
10
+ - `writing-plans`: plan-split decomposition and `brainstorming` first-feature decisions are stated, not confirmed - no standalone approval prompts. (#27)
11
+
3
12
  ## v5.3.6 - 2026-09-08
4
13
 
5
14
  - `plan_check`: new `waiver-literal` check (9 checks) - a `waived:` coverage row whose requirement names an inline code literal fails; `writing-plans` restates the waiver criterion (out of scope **and** excludes work) and requires cross-cutting requirements to list every deciding task. (#25)
package/README.md CHANGED
@@ -36,7 +36,7 @@ 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 or repair a single tracker issue - shaping a raw ask into a Context/Problem/Idea/Acceptance Criteria ticket, gated by an AC integrity check, a cheap council roast, and one human-confirmed write that may include one optional gated Reporter-note comment. 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. It never activates on its own (`disable-model-invocation: true`) - invoke it explicitly. 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. You describe the change. **`brainstorming`** sets up an isolated worktree, explores the codebase, and turns your description into a written spec. 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`; event-driven only — gauntlet never sweeps historical specs). **You read and approve the spec - human gate 1.** No implementation code exists yet.
39
+ 1. You describe the change. **`brainstorming`** sets up an isolated worktree, explores the codebase, and turns your description into a written spec. 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.** No implementation code exists yet.
40
40
  2. **`writing-plans`** decomposes the approved spec into atomic, independently-verifiable tasks, grouped into parallel waves where they don't touch the same files.
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
  4. **verify**: the parent first runs the plan's full verification command set; 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. 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 dense list - one line per decision, plain-language, with its recommended choice inline. Reply `1` to take every recommendation, or `2:` with per-item overrides; a current `CONFORMS` / no-concerns result goes straight to the branch options with no extra conformance sign-off.
@@ -63,7 +63,7 @@ flowchart LR
63
63
 
64
64
  <!-- TODO GIF: a real gauntlet run end to end -->
65
65
 
66
- Everything between gate 1 and gate 2 - task breakdown, implementation, both review passes - runs without you in the loop. That's the mechanism. What follows is the machinery behind it.
66
+ Everything between gate 1 and gate 2 - task breakdown, implementation, both review passes - runs without you in the loop. Changing an approved spec later is a conditional diff-approval stop (brainstorming's `Amending an approved spec`), not a third numbered gate. That's the mechanism. What follows is the machinery behind it.
67
67
 
68
68
  ## Architecture
69
69
 
@@ -380,6 +380,63 @@ test("Verification quote-integrity: task-owned literal check unchanged", () => {
380
380
  assert.ok(qi.some((f) => f.reason.includes("Task 1 body does not contain the required verbatim literal `helperFn()`")));
381
381
  });
382
382
 
383
+ const ENTRYPOINT_SPEC = [
384
+ "# Fixture Spec", // 1
385
+ "", // 2
386
+ "## Testing", // 3
387
+ "Run `node --test extensions/lib/plan-check.test.ts`; the full suite is `npm run verify-all`.", // 4
388
+ ].join("\n");
389
+
390
+ const ENTRYPOINT_PLAN = `# Fixture Plan
391
+
392
+ **Spec:** \`doc/specs/fixture-spec.md\`
393
+
394
+ **Verification:** \`npm run verify-all\`
395
+
396
+ ---
397
+
398
+ ## Wave 1 — Solo
399
+
400
+ Solo: lone remaining task
401
+
402
+ ### Task 1: Scoped test
403
+
404
+ **Spec:** doc/specs/fixture-spec.md § "Testing" L4
405
+
406
+ **Files:**
407
+ - Modify: extensions/lib/fixture-task1.ts
408
+
409
+ Run node --test extensions/lib/plan-check.test.ts and confirm green.
410
+
411
+ ## Spec coverage
412
+
413
+ | anchor | requirement | owner |
414
+ |---|---|---|
415
+ | § "Testing" L4 | scoped test run | Task 1 |
416
+ `;
417
+
418
+ test("quote-integrity: header entrypoint literal on an anchored line is satisfied by the header, not the task body", () => {
419
+ const findings = checkPlan(ENTRYPOINT_PLAN, ENTRYPOINT_SPEC, alwaysTruePort());
420
+ assert.deepEqual(findingsFor(findings, "quote-integrity"), []);
421
+ assert.deepEqual(findingsFor(findings, "header-entrypoint"), []);
422
+ });
423
+
424
+ test("quote-integrity: scoped command on the same anchored line is still required in the task body", () => {
425
+ const mutated = ENTRYPOINT_PLAN.replace(
426
+ "Run node --test extensions/lib/plan-check.test.ts and confirm green.",
427
+ "Run the scoped test and confirm green.",
428
+ );
429
+ const qi = findingsFor(checkPlan(mutated, ENTRYPOINT_SPEC, alwaysTruePort()), "quote-integrity");
430
+ assert.equal(qi.length, 1);
431
+ assert.ok(qi[0].reason.includes("Task 1 body does not contain the required verbatim literal `node --test extensions/lib/plan-check.test.ts`"));
432
+ });
433
+
434
+ test("placeholder-scan: header entrypoint is not a required literal for the task (parity with quote-integrity)", () => {
435
+ const findings = checkPlan(ENTRYPOINT_PLAN, ENTRYPOINT_SPEC, alwaysTruePort());
436
+ assert.deepEqual(findingsFor(findings, "placeholder-scan"), []);
437
+ assert.deepEqual(findings, []);
438
+ });
439
+
383
440
  test("check 3 anchor-resolution: ambiguous heading match (duplicate spec heading)", () => {
384
441
  const dupSpec = SPEC_TEXT.replace('## Testing', '## Design\n\nduplicate section body.\n\n## Testing');
385
442
  const findings = checkPlan(VALID_PLAN, dupSpec, alwaysTruePort());
@@ -367,12 +367,20 @@ function requiredLiteralsForRow(row: CoverageRow, specLines: string[]): string[]
367
367
  return extractLiterals(text);
368
368
  }
369
369
 
370
+ function dropHeaderEntrypoint(literals: string[], parsed: ParsedPlan): string[] {
371
+ const entrypoint = (parsed.header.verificationText ?? "").replaceAll("`", "");
372
+ if (!entrypoint) return literals;
373
+ return literals.filter((lit) => lit !== entrypoint);
374
+ }
375
+
370
376
  function computeRequiredLiteralsPerTask(parsed: ParsedPlan, specLines: string[]): Map<number, string[]> {
371
377
  const map = new Map<number, string[]>();
372
378
  if (!parsed.coverageTableFound) return map;
373
379
  for (const row of parsed.coverageRows) {
374
380
  if (row.ownerMalformed || row.isWaived || row.isMechanical) continue;
375
- const literals = requiredLiteralsForRow(row, specLines);
381
+ const literals = row.isVerification
382
+ ? requiredLiteralsForRow(row, specLines)
383
+ : dropHeaderEntrypoint(requiredLiteralsForRow(row, specLines), parsed);
376
384
  if (literals.length === 0) continue;
377
385
  for (const n of row.ownerTasks) {
378
386
  const arr = map.get(n) ?? [];
@@ -506,11 +514,12 @@ function checkQuoteIntegrity(parsed: ParsedPlan, specLines: string[]): PlanCheck
506
514
  }
507
515
  continue;
508
516
  }
517
+ const taskLiterals = dropHeaderEntrypoint(literals, parsed);
509
518
  for (const n of row.ownerTasks) {
510
519
  const task = taskByNumber.get(n);
511
520
  if (!task) continue;
512
521
  const body = taskBodyText(task, parsed.lines);
513
- for (const lit of literals) {
522
+ for (const lit of taskLiterals) {
514
523
  if (!body.includes(lit)) {
515
524
  findings.push({
516
525
  check: "quote-integrity",
@@ -290,6 +290,46 @@ test("resumed session: closure gate blocks complete verify without a conformance
290
290
  assert.equal(res.details.error, "no conformance-reviewer dispatch observed");
291
291
  });
292
292
 
293
+ test("restarting implement clears a resumed conformance dispatch latch", async () => {
294
+ const h = harness({
295
+ cwd: tempCwd({ piGauntlet: { flowGuards: { enforce: false }, closureReview: { enforce: true } } }),
296
+ branch: [
297
+ ...resumedBranch({ plan: "complete", implement: "complete", verify: "complete", ship: "in_progress" }),
298
+ subagentResult(["conformance-reviewer"]),
299
+ ],
300
+ });
301
+ await h.emit("session_start");
302
+ const tool = h.tools.find((t) => t.name === "phase_tracker")!;
303
+ await tool.execute("t1", { action: "skip", phase: "ship", reason: "amendment reopened Task 1" }, undefined, undefined, h.ctx);
304
+ await tool.execute("t2", { action: "start", phase: "implement", force: true }, undefined, undefined, h.ctx);
305
+ await tool.execute("t3", { action: "skip", phase: "implement", reason: "amendment implementation tested separately" }, undefined, undefined, h.ctx);
306
+ await tool.execute("t4", { action: "start", phase: "verify", force: true }, undefined, undefined, h.ctx);
307
+ const res = (await tool.execute("t5", { action: "complete", phase: "verify" }, undefined, undefined, h.ctx)) as {
308
+ details: { error?: string };
309
+ };
310
+ assert.equal(res.details.error, "no conformance-reviewer dispatch observed");
311
+ });
312
+
313
+ test("replayed implement restart clears a persisted conformance dispatch latch", async () => {
314
+ const h = harness({
315
+ cwd: tempCwd({ piGauntlet: { flowGuards: { enforce: false }, closureReview: { enforce: true } } }),
316
+ branch: [
317
+ ...resumedBranch({ plan: "complete", implement: "complete", verify: "complete", ship: "in_progress" }),
318
+ subagentResult(["conformance-reviewer"]),
319
+ phaseResult("skip", phases({ brainstorm: "skipped", plan: "complete", implement: "complete", verify: "complete", ship: "skipped" })),
320
+ phaseResult("start", phases({ brainstorm: "skipped", plan: "complete", implement: "in_progress", verify: "complete", ship: "skipped" })),
321
+ phaseResult("skip", phases({ brainstorm: "skipped", plan: "complete", implement: "skipped", verify: "complete", ship: "skipped" })),
322
+ phaseResult("start", phases({ brainstorm: "skipped", plan: "complete", implement: "skipped", verify: "in_progress", ship: "skipped" })),
323
+ ],
324
+ });
325
+ await h.emit("session_start");
326
+ const tool = h.tools.find((t) => t.name === "phase_tracker")!;
327
+ const res = (await tool.execute("t1", { action: "complete", phase: "verify" }, undefined, undefined, h.ctx)) as {
328
+ details: { error?: string };
329
+ };
330
+ assert.equal(res.details.error, "no conformance-reviewer dispatch observed");
331
+ });
332
+
293
333
  const taskSnapshot = (tasks: { name: string; status: string }[], isError = false) => ({
294
334
  type: "message",
295
335
  message: { role: "toolResult", toolName: "plan_tracker", isError, details: { tasks } },
@@ -405,6 +405,9 @@ export default function (pi: ExtensionAPI) {
405
405
  if (details && !details.error) {
406
406
  phases = details.phases;
407
407
  gauntletEntered = nextGauntletEntered(gauntletEntered, details.action, details.phases.brainstorm.status);
408
+ if (details.action === "start" && details.phases.implement.status === "in_progress") {
409
+ conformanceDispatched = false;
410
+ }
408
411
  if (details.action === "reset") {
409
412
  conformanceDispatched = false;
410
413
  planCheckStamp = undefined;
@@ -847,6 +850,8 @@ export default function (pi: ExtensionAPI) {
847
850
  }
848
851
  }
849
852
  phases = { ...phases, [params.phase]: transitionPhaseState("in_progress") as PhaseState };
853
+ // A rewind must not inherit the prior verify's conformance latch.
854
+ if (params.phase === "implement") conformanceDispatched = false;
850
855
  gauntletEntered = nextGauntletEntered(gauntletEntered, "start", phases.brainstorm.status);
851
856
  firedGuards.clear();
852
857
  updateWidget(ctx);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-gauntlet",
3
- "version": "5.3.6",
3
+ "version": "5.3.7",
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",
@@ -11,7 +11,7 @@ description: "You MUST use this before any creative work - creating features, bu
11
11
 
12
12
  Help turn ideas into fully formed designs and specs through natural collaborative dialogue.
13
13
 
14
- Identify the target project → set up an isolated worktree → understand current project context → ask questions one at a time → propose 2-3 approaches with trade-offs → present the design in 200-300-word sections, validating each → write spec to disk inside the worktree → user reviews before any implementation.
14
+ Identify the target project → set up an isolated worktree → understand current project context → ask questions one at a time → propose 2-3 approaches with trade-offs → present the design in two rounds → write spec to disk inside the worktree → user reviews before any implementation.
15
15
 
16
16
  ## HARD CONSTRAINT
17
17
 
@@ -63,7 +63,7 @@ Work through the items below **in order**. This is your own checklist to follow,
63
63
  4. **Understand the idea against the draft** — `Read` the draft, verify load-bearing
64
64
  claims against real code, ask questions one at a time, append citable findings
65
65
  5. **Propose 2-3 approaches** — with trade-offs and a recommendation
66
- 6. **Present the design** — in sections, get approval after each
66
+ 6. **Present the design** — in two rounds, one approval each
67
67
  7. **Write the spec** — to `doc/specs/` (see [Filename Convention](#filename-convention)); then mark any known superseded predecessor(s) per [Marking superseded specs](#marking-superseded-specs), at the exact-order position defined in [Spec Self-Review](#spec-self-review-before-user-review-gate)
68
68
  8. **Spec self-review (lint)** — placeholder scan + internal consistency + documentation named, run inline
69
69
  9. **Critique pass (auto-dispatched)** — scope + ambiguity; the spec council via `/skill:roasting-the-spec` when `gauntlet_setting` returns verdict `council` (it applies its apply-set, including any external-ref inlining, to the spec before returning — see [Spec Council](#spec-council-optional)), else a fresh `worker` that applies its own fixes in place
@@ -143,9 +143,7 @@ path.
143
143
  section starts that answer; confirm it before designing from scratch.
144
144
  - Ask questions **one at a time** to refine the idea. Prefer multiple-choice; one
145
145
  question per message. Focus on: purpose, constraints, success criteria, who/what
146
- it touches. Ask once whether the design replaces a prior spec, fully or in part,
147
- so the supersession event is captured before spec-writing (see
148
- [Marking superseded specs](#marking-superseded-specs)).
146
+ it touches.
149
147
  - **Append bar:** append to the draft's `## Appended during questionary` only
150
148
  findings the spec will cite — schema shapes, hard constraints, ticket-vs-code
151
149
  contradictions, user answers that changed scope. Not a log of every grep.
@@ -168,18 +166,14 @@ When sketching the design, prefer:
168
166
  - **Single source of truth** — point at the schema/contract that owns the data (the migration, type definition, or API contract that defines it); don't invent parallel state.
169
167
  - **Explicit error and edge cases** — name them. "Out of scope" is a valid answer, but it has to be stated.
170
168
 
171
- ### 6. Present the design in sections
169
+ ### 6. Present the design in two rounds
172
170
 
173
- Sections of 200-300 words. Ask after each whether it looks right.
171
+ Two rounds, one approval each. Target 300-500 words per round. A revisit after feedback stays inside the same approval point.
174
172
 
175
- Cover at minimum:
173
+ - Round 1: architecture overview, components / responsibilities, data flow, and `supersedes <path>, <scope>` when the draft names a predecessor. Ask once. Approval without correction confirms the predecessor.
174
+ - Round 2: error handling and edge cases, testing approach, `## Documentation impact`. Ask once.
176
175
 
177
- - Architecture overview
178
- - Components / responsibilities
179
- - Data flow (or request flow)
180
- - Error handling and edge cases
181
- - Testing approach
182
- - Documentation impact — a required `## Documentation impact` section. Cite the materiality bar in `reference/documentation-impact.md` by relative path rather than restating its categories, and reproduce its template block verbatim:
176
+ The `## Documentation impact` section is required. Cite the materiality bar in `reference/documentation-impact.md` by relative path rather than restating its categories, and reproduce its template block verbatim:
183
177
 
184
178
  ```markdown
185
179
  ## Documentation impact
@@ -198,18 +192,7 @@ When a ticket ID is given, fetch the ticket and treat it as **guidance, not the
198
192
 
199
193
  ## First-Feature Oversight (Early Project Stages)
200
194
 
201
- For the **first two features** of a new initiative — a new top-level module/package, a new long-lived component, a new persistence/schema area, or any pattern that will repeat — pause and ask the developer to confirm before proceeding on:
202
-
203
- - Directory and module structure decisions
204
- - Naming conventions (public types, files, routes, identifiers)
205
- - New shared abstraction (location, responsibility, boundary)
206
- - Persistence/schema design (entity names, field types, indexing)
207
- - Proposed additions to AGENTS.md or doc/ files
208
-
209
- If the developer hasn't provided guidance, ask explicitly:
210
- > "This is one of the first features in this initiative. Before I proceed, I need your confirmation on: [list specific decisions]."
211
-
212
- After the first two features establish patterns, follow those patterns without gating.
195
+ For the **first two features** of a new initiative (a new top-level module/package, long-lived component, persistence/schema area, or any pattern that will repeat), round 1 lists these decisions explicitly so the user can correct them there: directory and module structure; naming conventions (public types, files, routes, identifiers); new shared abstractions (location, responsibility, boundary); persistence/schema design (entity names, field types, indexing); proposed additions to AGENTS.md or doc/ files. No separate confirmation. After the first two features establish patterns, follow them.
213
196
 
214
197
  ## Anti-Pattern: "Too simple to need a design"
215
198
 
@@ -237,7 +220,7 @@ spec-writing: write the spec at the new path **and delete the old draft file**
237
220
 
238
221
  ## Marking superseded specs
239
222
 
240
- When the new spec replaces a prior spec — fully or in part — and you **already know which one** (from the questionary, the draft, or the request), mark the predecessor. Never search, sweep, or audit the spec corpus for candidates: marking is event-driven authorial knowledge only.
223
+ When the new spec replaces a prior spec — fully or in part — (from the draft's scout recon or the request), mark the predecessor. No mechanical sweep: grep or path-overlap hits never decide supersession.
241
224
 
242
225
  - `edit` the predecessor spec (in the project's spec directory, per [Project Routing](#project-routing)) to insert, after its title line and a blank line, one banner line per successor:
243
226
 
@@ -357,12 +340,26 @@ If you believe the summary needs correcting, do **not** silently rewrite it —
357
340
 
358
341
  Wait for the user. 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 approval, proceed immediately to `/skill:writing-plans` with no further prompt — 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.
359
342
 
343
+ Post-approval changes follow [Amending an approved spec](#amending-an-approved-spec).
344
+
360
345
  After approval, mark the brainstorm phase complete:
361
346
 
362
347
  ```
363
348
  phase_tracker({ action: "complete", phase: "brainstorm" })
364
349
  ```
365
350
 
351
+ ## Amending an approved spec
352
+
353
+ Execute this section in place from any later phase. Do not invoke `/skill:brainstorming` (its entry resets both trackers). Worktree, spec commits, and plan survive.
354
+
355
+ 1. Edit the spec. Show `git --no-pager diff -- <spec path>` and one line of impact (affected plan tasks / waves, or "no plan yet").
356
+ 2. Wait for approval. Change request -> revise, re-show.
357
+ 3. No plan yet -> commit the spec; continue. Plan exists -> update affected anchors and tasks: `plan_tracker` `add` for new tasks, `update` for changed ones; anchor-changed completed tasks go back to `pending` and re-run the task loop. A removed task is deleted from the plan; then re-`init` the tracker with the remaining tasks in wave order and `update` every already-completed task back to `complete` (the only permitted `init` after handoff; never `clear`). Re-run `plan_check` until it passes, commit spec + plan together; continue. A task reopened while `verify` or `ship` is in progress: `phase_tracker({ action: "skip", phase: "<current>", reason: "amendment reopened Task N" })`, then `phase_tracker({ action: "start", phase: "implement", force: true })`; later phases re-enter with `force: true` and rerun in full.
358
+
359
+ Redraw test: the diff changes the problem statement, adds or removes a component, or moves a component boundary -> redraw. A change inside one component (a persistence mechanism, a worker's HTTP client, dropping a fallback and its task) -> amend. State the call in the same message as the diff; the user overrides either way.
360
+
361
+ Redraw: keep the worktree and the approved spec file. `plan_tracker({ action: "clear" })`, `phase_tracker({ action: "reset" })`, `phase_tracker({ action: "start", phase: "brainstorm" })`, delete the plan file, resume at checklist step 4 with the approved spec as the draft (steps 2-3 skipped). Spec-writing overwrites it; the full gate follows.
362
+
366
363
  ## Key Principles
367
364
 
368
365
  - **One question at a time.**
@@ -370,30 +367,21 @@ phase_tracker({ action: "complete", phase: "brainstorm" })
370
367
  - **YAGNI ruthlessly.**
371
368
  - **Design for testability** — clear boundaries enable TDD.
372
369
  - **Explore 2-3 approaches** before settling.
373
- - **Incremental validation** — present in sections, validate each.
370
+ - **Two design rounds** — one approval per round.
374
371
  - **Be flexible** — go back and clarify when something doesn't make sense.
375
372
 
376
373
  ## Red Flags — STOP
377
374
 
378
- - About to write code or start a non-spec edit while this skill is active
379
- - About to dispatch lint, critique, council, or summarizer while the spec file's line 1 is still the context-draft marker
380
- - About to run the spec-writing overwrite without re-reading the draft in the same turn
381
- - About to use `edit` instead of `write` for the spec-writing overwrite
382
- - About to insert a human gate, announcement, or question between gather dispatch and questionary question one
383
- - About to run, deploy, or validate the **proposed change** (vs. observing current behaviour) before the user approved the design
384
- - About to skip the critique pass (council if configured, else fresh worker)
385
- - Critique dispatch (council or worker) failed to complete and you proceeded to the gate anyway
386
- - About to reach the user gate without re-running the placeholder scan after the critique returned
387
- - About to reach the user gate without rendering the spec-only summary (dispatch `spec-summarizer` to a temp file first; a failed/stub/truncated read degrades to a one-line note, it is not silently skipped)
388
- - About to compose the gate message when the summary `Read` was not the last content-producing tool call before it (a following `rm` of the temp file is fine) — a turn boundary between the `Read` and the render lets pi-condense prune the ~9KB read result, reproducing the original bug
389
- - About to present a paraphrased, condensed, or re-sectioned version of the summarizer's output instead of pasting its returned text verbatim — rewriting the summary counts as not rendering it
390
- - About to run the scope or ambiguity checks inline yourself instead of dispatching them (those two are the critique pass, not the inline lint)
391
- - About to skip the self-review pass
392
- - About to proceed to `/skill:writing-plans` before the user has approved the spec (proceeding *after* approval is correct; skipping the gate is the violation)
393
- - About to finish spec-writing for a replacement design without marking the known predecessor (see [Marking superseded specs](#marking-superseded-specs))
394
- - Spec contains `TODO`, `TBD`, or unnamed components
395
- - About to offer a multi-spec split that fails the split test in `../shape-ticket/reference/split-axes.md`, or without its three-line justification per spec
396
- - User said "this is just a small change" and you accepted it without applying the [Anti-Pattern](#anti-pattern-too-simple-to-need-a-design) check
375
+ - Writing or editing anything outside `doc/specs/` while this skill is active.
376
+ - Overwriting the draft without reading it in full in the same turn, or using `edit` for the spec-writing overwrite.
377
+ - Dispatching lint, critique, council, or summarizer while the spec file's line 1 is the context-draft marker.
378
+ - Running the scope or ambiguity checks inline instead of dispatching the critique pass.
379
+ - Reaching the gate after a failed or skipped critique pass, or without re-running the placeholder scan on the applied spec.
380
+ - Composing the gate without the summary `Read` as the last content-producing call, or paraphrasing the summary instead of pasting it verbatim.
381
+ - Inserting a human stop between gather dispatch and questionary question one.
382
+ - Running, deploying, or validating the proposed change before approval.
383
+ - Proceeding to `/skill:writing-plans` before the user approves the spec, or invoking `/skill:brainstorming` to amend an approved spec.
384
+ - Writing a replacement spec without the known predecessor's banner, or offering a multi-spec split that fails `../shape-ticket/reference/split-axes.md`.
397
385
 
398
386
  ## Project overrides
399
387
 
@@ -46,7 +46,12 @@ Scout (always dispatched):
46
46
  > exact paths and line ranges. If a spec you cite carries a supersession marker
47
47
  > (default: a `> **Superseded by:**` banner; the project's overrides may define
48
48
  > another format), follow the successor for the superseded scope and cite it
49
- > instead; cite the old spec only for its unsuperseded sections. End with an
49
+ > instead; cite the old spec only for its unsuperseded sections. Predecessor
50
+ > check: list the project's spec directory, read titles and `**Goal:**` lines,
51
+ > open at most five whose topic matches this request, and name any whose design
52
+ > this request replaces or amends with the section(s) affected -
53
+ > `Predecessor: <path>, <scope>` - or `Predecessor: none`. Judge by topic; shared
54
+ > file paths never decide. End with an
50
55
  > "Open questions that matter for the spec"
51
56
  > section. Compact handoff, not a dump.
52
57
 
@@ -127,7 +127,7 @@ Three tiers, increasing cost — name the tier when a revert is requested:
127
127
  |---|---|---|---|
128
128
  | Cheap | Council edit, reverted at the `brainstorming` gate | Spec isn't yet plan- or code-bearing | Revise spec, re-present |
129
129
  | Light | Conformance fix, reverted at finish | Gap re-opens for a fresh disposition | Revert the `conformance fix Gn` commit(s), re-audit |
130
- | Heavy | Council edit, reverted at finish | Rewrites the already-ratified contract that drove the plan and code | Amend spec → re-approve → regenerate affected plan/code → re-run verify before ship |
130
+ | Heavy | Council edit, reverted at finish | Rewrites the already-ratified contract that drove the plan and code | Amend spec per brainstorming's [Amending an approved spec](../brainstorming/SKILL.md#amending-an-approved-spec) → regenerate affected plan/code → re-run verify before ship |
131
131
 
132
132
  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).
133
133
 
@@ -63,7 +63,7 @@ For each task in `plan_tracker`:
63
63
  6. If quality reviewer finds issues → re-dispatch implementer → re-review. Loop until ✅, within [Fix-Loop Rounds](#fix-loop-rounds).
64
64
  7. After its existing reviews accept the work (and its required commit point), mark that same task index `complete` in `plan_tracker`. A subagent exit or green tests alone are not acceptance.
65
65
 
66
- The spec is frozen at plan time and the orchestrator is its only writer during execution; if you do edit it mid-run, re-run writing-plans' anchor-resolution check before the next wave. An SR unable to read the spec at a cited anchor (missing file, unresolvable heading/range) returns a blocking finding — the contract is spec+task or stop, never a silent fallback to task-only review.
66
+ The orchestrator is the spec's only writer during execution. Amendment trigger: implementer `BLOCKED` citing a spec defect, or a review finding showing the spec (not the code) is wrong -> pause the fix loop, execute brainstorming's [Amending an approved spec](../brainstorming/SKILL.md#amending-an-approved-spec) in place, resume. Code-vs-spec mismatch stays in the SR loop. An SR unable to read the spec at a cited anchor (missing file, unresolvable heading/range) returns a blocking finding — the contract is spec+task or stop, never a silent fallback to task-only review.
67
67
 
68
68
  After all tasks: proceed to [After All Tasks](#after-all-tasks-complete) - it owns parent full verification, then whole-diff code review, then conformance.
69
69
 
@@ -237,27 +237,16 @@ For the fan-out + worktree + patch-integration + conflict mechanics, see `dispat
237
237
 
238
238
  ## Red Flags — STOP
239
239
 
240
- - Writing code yourself instead of dispatching
241
- - Dispatching parallel implementers on overlapping files, or without `worktree: true` outside Parallel-Wave Mode (wave mode is the sanctioned exception: disjoint files + worktree isolation + serial integration)
242
- - Parallelizing a wave whose tasks contend on a shared mutable runtime resource (DB/schema, port, fixture, external service, shared temp path) — that wave was mis-grouped; run those tasks as sequential single-task waves
243
- - Making a subagent read the plan instead of passing task text
244
- - Starting code-quality review before spec compliance is ✅
245
- - Moving to next task with either review still showing issues
246
- - Dispatching fix 3 without a reviewer-emitted qualifying `CONVERGING` verdict at review 3
247
- - Continuing past a `STAGNANT` verdict instead of escalating
248
- - Letting implementer self-review replace external review (both needed)
249
- - Spec-reviewing wave patches inline instead of dispatching `spec-reviewer` per patch — sequential mode's step 3 dispatches it; wave mode must too
250
- - Pausing to "check in" between tasks (continuous execution rule)
251
- - Skipping the `Implementer Status` parse — treating every response as DONE
252
- - Starting on main without explicit user consent
253
- - Dispatching `code-reviewer` before every one of the wave's spec-review verdicts has landed (including fusing SR+CR into one parallel call)
254
- - Dispatching fixes sequentially on a clean HEAD despite a certified (probe-passing, per dispatching-parallel-agents § Fix fan-out) ≥ 2-ID `disjoint` group in the review's `Parallel-safe:` line
255
- - Dispatching `code-reviewer` per task inside a wave (CR binds to the integrated wave diff)
256
- - Dispatching an implementer or code-reviewer without a `SCOPED_TEST_COMMANDS` value (commands or `none`)
257
- - About to run the full verification entrypoint during the implement phase — task and wave gates run scoped, plan-declared commands only; the full set belongs to verify
258
- - Dispatching a verification or review repair before reopening (`in_progress`) the plan-task indices that own its touched files, or completing them on the passing rerun instead of on the accepting whole-diff review
259
- - Dispatching whole-diff CR before parent full verification passes, or conformance before the foreground CR result and any invalidating repair re-verification/re-review are accepted
260
- - Polling, joining, or relaunching an unexpectedly asynchronous gauntlet dispatch instead of stopping and reporting
240
+ - Writing code yourself instead of dispatching.
241
+ - Pausing between tasks for anything other than `NEEDS_CONTEXT`, `BLOCKED`, a fix-loop escalation, a workflow warning, or a spec amendment.
242
+ - Dispatching parallel implementers on overlapping files, on a shared mutable runtime resource, or without `worktree: true`.
243
+ - Making a subagent read the plan, inlining spec excerpts to the spec reviewer, or dispatching without a `SCOPED_TEST_COMMANDS` value.
244
+ - Dispatching `code-reviewer` before every in-scope spec-review verdict is ✅, or per task inside a wave.
245
+ - Moving to the next task with either review still showing issues, or skipping the `Implementer Status` parse.
246
+ - Dispatching fix 3 without a reviewer-emitted `CONVERGING` verdict, or continuing past `STAGNANT` instead of escalating.
247
+ - Running the full verification entrypoint during the implement phase.
248
+ - Dispatching a repair before reopening the plan-task indices that own its files, whole-diff CR before parent verification passes, or conformance before the CR result is accepted.
249
+ - Polling, joining, or relaunching an unexpectedly asynchronous dispatch, or starting on main without explicit user consent.
261
250
 
262
251
  ## Integration
263
252
 
@@ -66,6 +66,7 @@ Then continue with the normal flow below (Scope Check onward, including Recon).
66
66
  - Edit or create any other files: no
67
67
  - Write implementation code: never inside this skill. After Self-Review + `phase_tracker` complete, auto-invoke `/skill:subagent-driven-development` to execute.
68
68
  - Land the plan on `main`: no — the plan commit goes on the worktree branch (same branch as the spec)
69
+ - Edit the approved spec: only via brainstorming's [Amending an approved spec](../brainstorming/SKILL.md#amending-an-approved-spec)
69
70
 
70
71
  ## Scope Check
71
72
 
@@ -74,9 +75,7 @@ Before writing the plan, check the spec one more time:
74
75
  - Does an intermediate state need to be **independently deployable**, under a deploy topology documented in the gauntlet overrides file's `## Deployment` section? Fail closed: undocumented or monolithic topology -> no deployment-driven split.
75
76
  - Is there a **review-risk isolation** reason to land part separately (e.g. a large mechanical rename apart from the behavior change that motivated it)?
76
77
 
77
- If yes, decompose into separate plans and call it out:
78
-
79
- > "The spec covers A and B. I'd split into two plans, executed in order. OK?"
78
+ If yes, decompose into separate plans, executed in order, and state the split and its reason in the handoff message. No approval prompt.
80
79
 
81
80
  Otherwise one plan. Service, contract, or schema count is not a split signal - one concern routinely spans several. The concern test itself lives in `../shape-ticket/reference/split-axes.md` (resolve the path against this skill's own directory) and was applied upstream at spec time; plans do not re-litigate it. A single plan should land in one PR worth of work.
82
81
 
@@ -121,7 +120,7 @@ List the files this implementation will create, modify, or delete. Group by comp
121
120
  - `src/services/legacy_foo.ts`
122
121
  ```
123
122
 
124
- If you can't list the files, the spec isn't ready. Send it back to `/skill:brainstorming`.
123
+ If you can't list the files, the spec isn't ready: amend or redraw per brainstorming's [Amending an approved spec](../brainstorming/SKILL.md#amending-an-approved-spec).
125
124
 
126
125
  ## Wave Grouping
127
126
 
@@ -251,7 +250,7 @@ Each task uses `- [ ]` checkbox steps so execution tools (and humans) can track
251
250
 
252
251
  Every code task carries this step (red -> green -> fmt/lint -> commit). Doc-only tasks omit it unless the project formats Markdown.
253
252
 
254
- **Anchor rules.** The task's `**Spec:**` line cites the plan header's spec path; multiple anchors sit comma-separated on one line (`§ "A" L10-L18, § "C" L40-L44`). Checks key on the `§` marker, so the header's path-only `**Spec:**` line is never matched. Anchors are captured once against the gated spec at plan-writing time — the spec is frozen once planning starts. A task with no anchorable requirement (pure-mechanics chore) omits the `**Spec:**` line entirely (never `**Spec:** none`) and carries a mechanical-task row in `## Spec coverage` — silence is never valid.
253
+ **Anchor rules.** The task's `**Spec:**` line cites the plan header's spec path; multiple anchors sit comma-separated on one line (`§ "A" L10-L18, § "C" L40-L44`). Checks key on the `§` marker, so the header's path-only `**Spec:**` line is never matched. Anchors are captured against the gated spec at plan-writing time; a change to the approved spec follows brainstorming's [Amending an approved spec](../brainstorming/SKILL.md#amending-an-approved-spec), executed in place. A task with no anchorable requirement (pure-mechanics chore) omits the `**Spec:**` line entirely (never `**Spec:** none`) and carries a mechanical-task row in `## Spec coverage` — silence is never valid.
255
254
 
256
255
  ## Spec Coverage Table
257
256