pi-gauntlet 4.0.1 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,52 @@
1
1
  # Changelog
2
2
 
3
+ ## v4.2.0 - 2026-07-04
4
+
5
+ Documents become first-class origin requirements, the post-execution review stack
6
+ is deduplicated, and this repo now dogfoods its own workflow (GitHub #1 + folded-in B/C/D/E).
7
+
8
+ - **Part A - docs as first-class origin.** New shared reference
9
+ `skills/brainstorming/reference/documentation-impact.md` defines a materiality
10
+ bar (seven inclusion categories + a litmus test, an anti-flooding exclusion list,
11
+ and amend-over-create) so only meaningful docs earn a place. `brainstorming` gets
12
+ a required `## Documentation impact` spec section (three classes: introduced /
13
+ materially amended / derived-memory invalidated); `writing-plans` turns doc updates
14
+ into real tasks + a trailing doc-only wave; `conformance-check.md` names spec docs
15
+ as origin requirements the existing pass already verifies. No new pass or agent.
16
+ - **Part B - review-stack dedup.** `subagent-driven-development`'s post-execution
17
+ stack collapses from a duplicated whole-diff review to one `requesting-code-review`
18
+ plus the separate `conformance-reviewer`; the auto-fired project-audit supplement
19
+ is removed (consumers re-wire via `.pi/gauntlet-overrides.md` or run it manually).
20
+ `agents/code-reviewer.md` severity and `README.md` are decoupled from the example
21
+ self-audit skill. Execution-phase per-task/per-wave reviews are untouched.
22
+ - **Part C - ephemeral-plan parity.** `finishing-a-development-branch` now strips the
23
+ plan doc before the PR push (guarded `git ls-files --error-unmatch`), symmetric with
24
+ the squash-merge path; the plan never lands on base.
25
+ - **Part D - self-hosting mandate.** `AGENTS.md` mandates the full gauntlet for this
26
+ repo's own non-trivial changes and reframes the direct-edit recipes as implement-phase
27
+ mechanics.
28
+ - **Part E - file-placement convention.** `writing-skills` codifies dispatch-payload
29
+ templates as `SKILL.md` siblings vs deep guidance in `reference/` (destination, not format).
30
+
31
+ ## v4.1.0 - 2026-07-02
32
+
33
+ - **`closureReview` now resolves repo-local first.** The verify-step skills
34
+ (`subagent-driven-development`, `verification-before-completion/reference/conformance-check.md`)
35
+ resolve `piGauntlet.closureReview.model`/`maxFixRounds` from a repo's
36
+ `.pi/settings.json` over the agent preset, **whole-object** - matching how the
37
+ `phase-tracker.ts` guard already reads `pi.settings` (pi replaces the whole
38
+ `closureReview` block when a repo defines it). Previously they read the preset
39
+ only, so a repo-local `closureReview.model` was silently ignored and the
40
+ conformance gate ran on the parent's model.
41
+ - **New shared reference `skills/verification-before-completion/reference/settings-precedence.md`.**
42
+ States the two-file source order and the whole-object merge rule once; `specCouncil`
43
+ and `closureReview` both resolve the same way and both point at it. `roasting-the-spec`
44
+ and `brainstorming` replace their duplicated lookup prose with a pointer.
45
+ - **Closure guard upgraded from presence-check to match-check.** A
46
+ `conformance-reviewer` dispatch that omits `model:` is still blocked; one whose
47
+ `model:` differs from the configured `closureReview.model` now gets a non-blocking
48
+ warning appended to the result. Gated by `closureReview.enforce` as before.
49
+
3
50
  ## v4.0.1 - 2026-07-02
4
51
 
5
52
  No content change. Smoke-tests the tag-triggered CI publish path (OIDC trusted publishing to npm) added in v4.0.0's release machinery commit.
package/README.md CHANGED
@@ -15,10 +15,10 @@ brainstorm → plan → implement → verify → ship
15
15
  1. **`brainstorming`** — every change starts here. Sets up an isolated worktree, explores the codebase, and turns the idea into a written spec under `doc/specs/`. A multi-model critique runs automatically before you read it (`roasting-the-spec` when a council is configured, else one fresh `worker`). **Hard gate:** no implementation code is written until you approve the spec.
16
16
  2. **`writing-plans`** — derives an implementation plan from the approved spec, decomposed into atomic, independently-verifiable tasks (grouped into parallel waves when they're file- and resource-disjoint). Auto-chains into execution.
17
17
  3. **`subagent-driven-development`** — executes the plan one atomic task at a time, each in a **fresh subagent**, behind a **two-stage review**: spec compliance first (`spec-reviewer`), then code quality (`code-reviewer`). The `implementer` persona is TDD-locked (RED→GREEN→REFACTOR). You orchestrate; you never hand-write the code.
18
- 4. **verify** — after the last task: a whole-diff review (`requesting-code-review`, plus any project-specific `self-audit` supplement), then the `conformance-reviewer` closing-loop gate that confronts the delivered code **and** docs against the *origin* (spec + your verbatim original prompt), not the plan. The phase-tracker **blocks `complete verify`** until a conformance dispatch has run, and on a successful `complete verify` (ship still pending) injects an advisory to invoke `finishing-a-development-branch` immediately without a redundant "ready to finish?" prompt - or to reopen verify if a requirement decision is still open.
18
+ 4. **verify** — after the last task: a whole-diff review (`requesting-code-review`), then the `conformance-reviewer` closing-loop gate that confronts the delivered code **and** docs against the *origin* (spec + your verbatim original prompt), not the plan. The phase-tracker **blocks `complete verify`** until a conformance dispatch has run, and on a successful `complete verify` (ship still pending) injects an advisory to invoke `finishing-a-development-branch` immediately without a redundant "ready to finish?" prompt - or to reopen verify if a requirement decision is still open.
19
19
  5. **`finishing-a-development-branch`** — squash / PR / keep / discard. This menu is the single human decision gate at the end, mirroring spec approval at the start.
20
20
 
21
- Spec, plan, and implementation all live in the **same worktree** and ship as **one squash commit**.
21
+ Spec, plan, and implementation are all developed in the **same worktree**. The squash commit ships spec and implementation; the plan is ephemeral and is stripped before any landing path.
22
22
 
23
23
  **Supporting skills** slot in as the pipeline needs them: `using-git-worktrees` (isolation, before the spec), `test-driven-development` (inside every implementer), `dispatching-parallel-agents` (wave fan-out), `systematic-debugging` (when something breaks), `receiving-code-review` (when you get feedback), `writing-skills` (authoring more of these).
24
24
 
@@ -162,7 +162,7 @@ Unset → provider default thinking for that model. `conformance-reviewer` and t
162
162
 
163
163
  ### Conformance gate model
164
164
 
165
- `conformance-reviewer` ships without a `model:` in its frontmatter — like the spec-council personas, its model is supplied per preset so each profile points the last correctness gate at the strongest reasoning model its providers can reach. The verify-step skills read it from `piGauntlet.closureReview.model` and inject it **call-site** on the conformance dispatch (the same mechanism the spec-council chair uses). Add it to each preset's `settings.json`:
165
+ `conformance-reviewer` ships without a `model:` in its frontmatter — like the spec-council personas, its model is supplied per preset so each profile points the last correctness gate at the strongest reasoning model its providers can reach. The verify-step skills resolve `piGauntlet.closureReview.model` **repo-local first** (a repo's `.pi/settings.json` overrides the preset whole-object - defining `closureReview` there replaces the preset's entire block, so set every leaf you need together) and inject it **call-site** on the conformance dispatch (the same mechanism the spec-council chair uses). Add it to each preset's `settings.json` (or a repo's `.pi/settings.json` to override per repo):
166
166
 
167
167
  ```json
168
168
  {
@@ -174,7 +174,7 @@ Unset → provider default thinking for that model. `conformance-reviewer` and t
174
174
 
175
175
  Frontmatter pins `thinking: xhigh` and `defaultContext: fresh` (the gate always runs cold, with max reasoning) and `thinking` is not call-site overridable, so the config supplies only `model`. If `closureReview.model` is unset the dispatch omits `model:` and the gate inherits the parent's model; if the configured model is unreachable it retries once inherited.
176
176
 
177
- When `closureReview.model` **is** set, the phase-tracker enforces call-site injection: a `subagent` dispatch of `conformance-reviewer` that omits `model:` is **blocked at tool-call time** (before it runs) so the gate can never silently degrade to the parent's builder model. The documented one-retry fallback still works - pass the inherited model *explicitly* and it is allowed; only a bare omission is blocked. Disabling `closureReview.enforce` disables this guard too.
177
+ When `closureReview.model` **is** set, the phase-tracker match-checks call-site injection: a `subagent` dispatch of `conformance-reviewer` that omits `model:` is **blocked at tool-call time** (before it runs) so the gate can never silently degrade to the parent's builder model, and a dispatch whose `model:` **differs** from the configured value gets a non-blocking **warning** appended to the result (drift is surfaced, not blocked). The documented one-retry fallback still works - pass an explicit model and it runs (with a warning if it differs). Disabling `closureReview.enforce` disables this guard too.
178
178
 
179
179
  `closureReview.enforce` (default `true`) controls the phase-tracker gate that
180
180
  blocks `complete verify` until the conformance-reviewer has run; set `false` to
@@ -202,7 +202,7 @@ If you want to know what's in each persona before using it, see [`agents/`](./ag
202
202
  - `members` (required) — roster of `provider/model` strings; council size = array length, one critique per model. Empty or absent → the council never runs; brainstorming falls back to a single fresh-`worker` critique (scope + ambiguity, auto-applied).
203
203
  - `chair` (optional) — model for the consolidating synthesizer; defaults to the inherited model when omitted.
204
204
 
205
- Rosters are per-preset: each pi profile (`agent`, `agent.anthropic`, `agent.bedrock`, …) reads its own `settings.json`, so list only models that profile's providers can reach. The two personas it dispatches — `spec-council-member` and `spec-council-synthesizer` — are model-free; their model is injected per task from this config.
205
+ Rosters resolve **repo-local first**: a repo's `.pi/settings.json` overrides the preset (whole-object — the first file that defines `specCouncil` wins), otherwise each pi profile (`agent`, `agent.anthropic`, `agent.bedrock`, …) reads its own `settings.json`. List only models the resolving config's providers can reach. The two personas it dispatches — `spec-council-member` and `spec-council-synthesizer` — are model-free; their model is injected per task from this config.
206
206
 
207
207
  ## Extensions
208
208
 
@@ -40,7 +40,8 @@ Findings:
40
40
  Complexity: net -<N> lines (omit if nothing to cut)
41
41
  ```
42
42
 
43
- Severity (aligned with the `self-audit` skill):
43
+ Severity:
44
+
44
45
  - **Critical** — must fix before merge (data loss, security, broken correctness on a common path, broken contract).
45
46
  - **Moderate** — should fix; open for discussion (significant but not strictly blocking).
46
47
  - **Minor** — nit, style, preference, suggestion.
@@ -98,19 +98,21 @@ const branchBlockReason = (phase: Phase): string =>
98
98
  "To override, set piGauntlet.flowGuards.enforce: false.";
99
99
 
100
100
  // Closure-review model guard: when piGauntlet.closureReview.model is configured,
101
- // a conformance-reviewer dispatch MUST inject that model call-site. The persona ships
102
- // model-free, so a bare omission silently inherits the parent session's builder model -
103
- // defeating the point of an independent closing gate on a different model. Walk the
104
- // single / tasks / chain / parallel dispatch shapes and report any conformance-reviewer
105
- // entry that carries no model. An explicit model (even a fallback) is fine; only a bare
106
- // omission is caught - that preserves the documented "retry once inherited" escape hatch,
107
- // which the orchestrator takes by passing the inherited model explicitly.
108
- const conformanceEntriesMissingModel = (input: unknown): boolean => {
109
- const entries: { agent?: unknown; model?: unknown }[] = [];
101
+ // a conformance-reviewer dispatch should inject that model call-site. The persona
102
+ // ships model-free, so a bare omission silently inherits the parent session's
103
+ // builder model - defeating the point of an independent closing gate. Walk the
104
+ // single / tasks / chain / parallel dispatch shapes and collect the model of every
105
+ // conformance-reviewer entry (undefined = absent/empty/non-string). A bare omission
106
+ // is BLOCKED; an explicit model that differs from the configured one is WARNED
107
+ // (non-blocking), preserving the documented retry-with-fallback hatch while
108
+ // surfacing drift.
109
+ const conformanceModels = (input: unknown): (string | undefined)[] => {
110
+ const models: (string | undefined)[] = [];
111
+ const norm = (m: unknown) => (typeof m === "string" && m.trim() ? m.trim() : undefined);
110
112
  const collect = (node: unknown): void => {
111
113
  if (!node || typeof node !== "object") return;
112
114
  const o = node as Record<string, unknown>;
113
- if (typeof o.agent === "string") entries.push({ agent: o.agent, model: o.model });
115
+ if (o.agent === "conformance-reviewer") models.push(norm(o.model));
114
116
  for (const key of ["tasks", "chain", "parallel"] as const) {
115
117
  const v = o[key];
116
118
  if (Array.isArray(v)) for (const item of v) collect(item);
@@ -118,19 +120,28 @@ const conformanceEntriesMissingModel = (input: unknown): boolean => {
118
120
  }
119
121
  };
120
122
  collect(input);
121
- return entries.some((e) => e.agent === "conformance-reviewer" && !e.model);
123
+ return models;
122
124
  };
123
125
 
124
- const closureModelBlockReason = (model: string): string =>
125
- `Blocked: conformance-reviewer dispatched without a model while ` +
126
- `piGauntlet.closureReview.model is set to "${model}".\n` +
126
+ const closureModelBlockReason = (model: string, missing: number, total: number): string =>
127
+ `Blocked: ${missing} of ${total} conformance-reviewer ${total === 1 ? "dispatch" : "entries"} ` +
128
+ `omitted a model while piGauntlet.closureReview.model is set to "${model}".\n` +
127
129
  `The persona ships model-free, so a bare omission silently inherits this session's ` +
128
130
  `builder model - the closing gate would then run on the same model that built the work, ` +
129
- `not the independent one the preset pins. Re-dispatch with model: "${model}" injected ` +
130
- `call-site. If that model is unreachable, pass an explicit fallback model (the documented ` +
131
- `one-retry escape hatch) - only a bare omission is blocked.\n` +
131
+ `not the independent one configured (repo .pi/settings.json, else the preset). Re-dispatch ` +
132
+ `with model: "${model}" injected call-site on every conformance-reviewer entry. If that ` +
133
+ `model is unreachable, pass an explicit fallback model (the documented one-retry escape ` +
134
+ `hatch) - only a bare omission is blocked.\n` +
132
135
  `To disable this gate, set piGauntlet.closureReview.enforce: false.`;
133
136
 
137
+ const closureModelMismatchWarning = (configured: string, mismatched: string[]): string =>
138
+ `⚠️ conformance-reviewer dispatched with ${mismatched.length === 1 ? "model" : "models"} ` +
139
+ `${mismatched.map((m) => `"${m}"`).join(", ")} while ` +
140
+ `piGauntlet.closureReview.model is set to "${configured}".\n` +
141
+ `If this is the documented one-retry fallback (the configured model was ` +
142
+ `unreachable), ignore this. Otherwise the closing gate is running on an ` +
143
+ `unintended model - re-dispatch with model: "${configured}".`;
144
+
134
145
  const brainstormWriteWarning = (specDirs: string[]): string =>
135
146
  "⚠️ Writing outside the spec directory during the brainstorm phase.\n" +
136
147
  `Brainstorming may only edit the spec under ${specDirs.join(", ")}. Implementation\n` +
@@ -317,8 +328,19 @@ export default function (pi: ExtensionAPI) {
317
328
  // Only execution-mode dispatches carry a model; management/control modes
318
329
  // (action: list/get/create/update/delete/status/...) execute nothing, so skip them.
319
330
  const hasAction = !!(event.input as { action?: unknown })?.action;
320
- if (model && !hasAction && conformanceEntriesMissingModel(event.input)) {
321
- return { block: true, reason: closureModelBlockReason(model) };
331
+ if (model && !hasAction) {
332
+ const configured = model.trim();
333
+ const models = conformanceModels(event.input);
334
+ if (models.length > 0) {
335
+ const missing = models.filter((m) => m === undefined).length;
336
+ if (missing > 0) {
337
+ return { block: true, reason: closureModelBlockReason(configured, missing, models.length) };
338
+ }
339
+ const mismatched = [...new Set((models as string[]).filter((m) => m !== configured))];
340
+ if (mismatched.length > 0) {
341
+ pendingGuardWarnings.set(event.toolCallId, closureModelMismatchWarning(configured, mismatched));
342
+ }
343
+ }
322
344
  }
323
345
  }
324
346
 
@@ -377,6 +399,11 @@ export default function (pi: ExtensionAPI) {
377
399
  pi.on("tool_result", async (event) => {
378
400
  if (event.toolName === "subagent") {
379
401
  if (qualifiesAsClosureDispatch(event.details)) conformanceDispatched = true;
402
+ const warning = pendingGuardWarnings.get(event.toolCallId);
403
+ if (warning) {
404
+ pendingGuardWarnings.delete(event.toolCallId);
405
+ return { content: [{ type: "text" as const, text: warning }, ...event.content] };
406
+ }
380
407
  return undefined;
381
408
  }
382
409
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-gauntlet",
3
- "version": "4.0.1",
3
+ "version": "4.2.0",
4
4
  "description": "Opinionated, gated workflow skills, subagent personas, and runtime extensions for the pi coding agent.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -78,7 +78,7 @@ The spec is the **first commit in a dedicated worktree**, not a separate commit
78
78
  2. Switch into the worktree.
79
79
  3. From there, write the spec, run self-review, commit, hand off.
80
80
 
81
- Spec doc, plan doc, and implementation all live in the same worktree and ship together as a single squash commit (see `/skill:finishing-a-development-branch`).
81
+ Spec doc, plan doc, and implementation are all developed in the same worktree; the squash ships the spec and the implementation, with the ephemeral plan stripped before landing (see `/skill:finishing-a-development-branch`).
82
82
 
83
83
  **Exception:** trivial one-off edits the user explicitly asks for outside this skill flow (e.g. "fix this typo") do not require a worktree.
84
84
 
@@ -140,7 +140,16 @@ Cover at minimum:
140
140
  - Data flow (or request flow)
141
141
  - Error handling and edge cases
142
142
  - Testing approach
143
- - Documentation impact — name each doc that changes (README, AGENTS.md, CHANGELOG, API contracts, inline docs), or write "none". Doc updates ship in the same commit and are verified against the spec by the conformance gate.
143
+ - 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:
144
+
145
+ ```markdown
146
+ ## Documentation impact
147
+ - Feature / user-facing docs introduced: <list, or "none">
148
+ - Materially amended existing docs: <list, or "none">
149
+ - Derived / memory docs invalidated: <routers / AGENTS.md sections / topic guides / indexes, or "none">
150
+ ```
151
+
152
+ Each entry answers with a doc name, "none", or "deferred: <trigger>". A new standalone `.md` appears only where no existing doc already owns the topic. Project-specific doc taxonomy goes in a `## documentation` block in `.pi/gauntlet-overrides.md` (no new settings key; guidance only). Doc updates ship in the same commit and are verified against the spec by the conformance gate.
144
153
 
145
154
  Be ready to go back and clarify when something doesn't make sense.
146
155
 
@@ -188,7 +197,7 @@ After writing the spec to `<project>/doc/specs/<filename>.md` (per [Filename Con
188
197
 
189
198
  - **Placeholder scan.** Any `TODO`, `TBD`, `<fill in>`, `[example]`, `xxx`? Either resolve them or convert to explicit "Open Questions" with names.
190
199
  - **Internal consistency.** Does Section 4 contradict Section 2? Are component names and field names consistent throughout?
191
- - **Documentation named.** Does the spec state which docs change (or an explicit "none")?
200
+ - **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 `reference/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.
192
201
  - **Scope check.** Does every paragraph serve the goal? Cut filler. If something is out of scope, say it's out of scope.
193
202
  - **Ambiguity check.** Is every "we should…" backed by a concrete decision? Replace "we could probably" with "we will" or "we won't".
194
203
 
@@ -215,14 +224,7 @@ After the critique pass returns, scan it for load-bearing external references be
215
224
 
216
225
  ## Spec Council (Optional)
217
226
 
218
- After the inline lint and before the user review gate, **brainstorming owns the critique-pass gate**: resolve `piGauntlet.specCouncil` from **two** settings files, repo-local first, and select the path.
219
-
220
- Lookup order (first file that **defines** `specCouncil` wins — do not merge across files):
221
-
222
- 1. `<repo-root>/.pi/settings.json` — repo root from `git rev-parse --show-toplevel` (the worktree root inside a worktree). A repo that defines `specCouncil` overrides the preset, even with empty `members` (explicit "no council here").
223
- 2. `$PI_CODING_AGENT_DIR/settings.json` — agent preset; consulted only when the repo file does not define `specCouncil`.
224
-
225
- Both files may contain comments — read them, don't strict-parse. **Expand `$PI_CODING_AGENT_DIR`; never substitute a hardcoded project path for it** (reading the repo `.pi/settings.json` as if it were the preset file is the classic miss — repo-local and preset are different files). **When `members` is non-empty, the council *is* the critique pass — invoke `/skill:roasting-the-spec` automatically (no offer, no prompt).** When it is absent or empty, run the fresh-`worker` critique instead (see [Spec Self-Review](#spec-self-review-before-user-review-gate)); if `specCouncil` is present but malformed, emit one warning line and fall back to the worker. Approved council edits (or the worker's in-place fixes) are applied to the spec and ride in the same worktree commit as the rest of this skill's output.
227
+ After the inline lint and before the user review gate, **brainstorming owns the critique-pass gate**: resolve `piGauntlet.specCouncil` **repo-local first** — the repo's `.pi/settings.json` overrides the agent preset, **whole-object** (the first file that defines `specCouncil` wins; an empty `members` there is an explicit "no council here"). Full source order and mechanics: `verification-before-completion/reference/settings-precedence.md`. **Expand `$PI_CODING_AGENT_DIR`; never substitute a hardcoded project path for it.** **When `members` is non-empty, the council *is* the critique pass — invoke `/skill:roasting-the-spec` automatically (no offer, no prompt).** When it is absent or empty, run the fresh-`worker` critique instead (see [Spec Self-Review](#spec-self-review-before-user-review-gate)); if `specCouncil` is present but malformed, emit one warning line and fall back to the worker. Approved council edits (or the worker's in-place fixes) are applied to the spec and ride in the same worktree commit as the rest of this skill's output.
226
228
 
227
229
  ## User Review Gate
228
230
 
@@ -0,0 +1,134 @@
1
+ # Documentation Impact: the Materiality Bar
2
+
3
+ The shared materiality bar for a spec's "Documentation impact" section. Several
4
+ skills cite this doc by relative path rather than restating its rules.
5
+
6
+ ## Governing principle
7
+
8
+ The governing principle: document what the code cannot tell you.
9
+
10
+ The "Documentation impact" section is a **filter with a default of "none,"** not
11
+ a prompt to produce documentation. A doc earns a line in that section only when
12
+ it clears one of the categories below. Absence is the expected outcome for most
13
+ changes - most changes touch no product-facing doc at all.
14
+
15
+ ## Scope + the three doc classes
16
+
17
+ The section tracks **product-facing docs**: README, `AGENTS.md`, CHANGELOG,
18
+ external / API contracts, and genuinely-new standalone guidance docs.
19
+
20
+ Skill and agent bodies, and their `reference/` sub-docs, are **implementation
21
+ surface** - the deliverable itself, tracked in the plan's file list - **not**
22
+ doc-impact entries. Listing them here would just restate the diff.
23
+
24
+ Within that scope, a spec's Documentation impact section enumerates three
25
+ classes:
26
+
27
+ - **Feature / user-facing docs introduced** - a new doc the change adds.
28
+ - **Materially amended existing docs** - an existing product doc that gains a
29
+ new section or a changed contract.
30
+ - **Derived / memory docs invalidated** - router entries (`AGENTS.md` sections),
31
+ topic guides, taxonomy indexes that go stale because of this change.
32
+
33
+ ## The seven inclusion categories
34
+
35
+ These seven categories gate classes 1 and 2 (feature/user-facing introduced;
36
+ materially amended) - selection by importance. Class 3 (derived/memory
37
+ invalidated) uses a different, lighter test; see "Gating class 3" below.
38
+
39
+ A doc earns its place in classes 1-2 only by clearing at least one of these.
40
+ Categories are not mutually exclusive; one match is sufficient.
41
+
42
+ **Litmus test for every category:** would a competent teammate need this
43
+ written down to safely operate or extend the system without reading the diff
44
+ or the code? If the code (or its tests) already answers it, it fails the bar.
45
+
46
+ - **Major procedures / conventions** - how work is done here (workflow, review,
47
+ release discipline).
48
+ - **Operations / tunable parameters** - env vars, thresholds, feature flags,
49
+ runbook / recovery steps. PASS: a new `PI_LENS_MAX_FILES` threshold, its
50
+ default, and when to change it. FAIL: restating that a function reads an
51
+ env var - the code already says that.
52
+ - **Communication contracts / integrations** - API / wire / queue contracts,
53
+ cross-component boundaries.
54
+ - **Architecture** - module boundaries, data flow, structural decisions.
55
+ - **Major definitions** - the canonical definition of a load-bearing domain
56
+ term, concept, or invariant that multiple components depend on and no single
57
+ code location fully owns. PASS: the canonical meaning of a domain term
58
+ several components rely on. FAIL: a one-line type alias the code already
59
+ names in full.
60
+ - **Non-obvious rationale / decisions that outlive the PR** - the "why," and
61
+ why not the obvious alternative. PASS: why a simpler, obvious approach was
62
+ rejected, recorded so it is not re-litigated later. FAIL: a restatement of
63
+ what the chosen code does.
64
+ - **Security, data-access & permissions** - trust boundaries, who can access
65
+ what, data-handling and permission decisions.
66
+
67
+ ## Gating class 3
68
+
69
+ Class 3 ("Derived / memory docs invalidated") is not gated by the seven
70
+ categories above. A router entry, topic guide, or taxonomy index is
71
+ invalidated by drift, not selected by topical weight. The test is: an
72
+ existing doc's content is now wrong or misleading because of this change.
73
+ If so, it belongs in class 3 regardless of whether it would clear any of the
74
+ seven categories. A citing skill (for example `writing-plans`, which sources
75
+ doc-update tasks from this section) must not apply the seven-category filter
76
+ to class 3 entries.
77
+
78
+ ## Exclusion / anti-pattern list
79
+
80
+ None of the following clears the bar, no matter how it is framed:
81
+
82
+ - Per-symbol or per-module narration.
83
+ - Restating signatures, types, or schemas the code already owns.
84
+ - "How it works" prose that reading the code answers directly.
85
+ - Anything that would need an edit on every code change - the code-mirror
86
+ tell: if a doc rots the moment the function it describes changes, it was
87
+ never documentation, it was a copy.
88
+
89
+ In-code doc comments such as RDoc/JSDoc are out of scope for this bar; it
90
+ governs standalone `.md` docs only, and the same "no code-mirror" rule
91
+ applies to both: a narrow markdown file that mirrors one function or one
92
+ module fails the bar the same way an inline doc comment would.
93
+
94
+ ## Amend over create
95
+
96
+ Clearing the bar does not default to a new file. **Extend the canonical
97
+ existing doc that owns the topic.** When ownership is ambiguous, extend the
98
+ most specific existing doc that already discusses the surrounding topic; a
99
+ new standalone `.md` is justified only when zero existing docs mention the
100
+ topic at all - this is the anti-proliferation rule, and it is why most
101
+ changes that clear the bar still show up under "materially amended," not
102
+ "introduced."
103
+
104
+ ## The section template
105
+
106
+ Reproduce this block exactly in a spec's "Documentation impact" section:
107
+
108
+ ```markdown
109
+ ## Documentation impact
110
+ - Feature / user-facing docs introduced: <list, or "none">
111
+ - Materially amended existing docs: <list, or "none">
112
+ - Derived / memory docs invalidated: <routers / AGENTS.md sections / topic guides / indexes, or "none">
113
+ ```
114
+
115
+ Each entry answers with a doc name, `"none"`, or `"deferred: <trigger>"` (for
116
+ example, `CHANGELOG.md - deferred: release`, when a doc changes on a known
117
+ later event and should not be flagged as missing before that event fires).
118
+
119
+ ## Referenced by
120
+
121
+ Keep this list in sync with the skills that cite this doc:
122
+
123
+ - `brainstorming` section 6 and its Spec Self-Review check.
124
+ - `writing-plans` - sources doc-update tasks from the spec's Documentation
125
+ impact section.
126
+ - `verification-before-completion/reference/conformance-check.md` - docs named
127
+ here are origin requirements the conformance pass verifies.
128
+ - `finishing-a-development-branch` Step 1's doc-impact pointer.
129
+
130
+ ## Project-specific taxonomy
131
+
132
+ This doc is generic. Project-specific doc taxonomy (which docs a given
133
+ project treats as canonical for which topic) lives in a project's
134
+ `.pi/gauntlet-overrides.md`, in a `## documentation` section - not here.
@@ -42,7 +42,7 @@ Stop. Don't proceed to Step 2.
42
42
 
43
43
  **If tests pass:** Continue to Step 2.
44
44
 
45
- No documentation prompt here: doc impact is decided at spec time (`/skill:brainstorming` section 6) and has already shipped in the diff by the time you reach finishing.
45
+ No documentation prompt here: Documentation impact is decided at spec time (`/skill:brainstorming` section 6, gated by `brainstorming/reference/documentation-impact.md`) and has already shipped in the diff by the time you reach finishing.
46
46
 
47
47
  ### Step 2: Detect Environment
48
48
 
@@ -154,6 +154,12 @@ git branch -d <feature-branch>
154
154
  #### Option 2: Push and Create PR
155
155
 
156
156
  ```bash
157
+ # Plans are ephemeral - if one was committed on this branch, remove it before the PR diff is opened.
158
+ PLAN_PATH=doc/plans/<plan-file>.md # or <service>/doc/plans/<plan-file>.md
159
+ if git ls-files --error-unmatch "$PLAN_PATH" >/dev/null 2>&1; then
160
+ git rm "$PLAN_PATH" && git commit -m "Remove ephemeral plan doc"
161
+ fi
162
+
157
163
  # Push branch
158
164
  git push -u origin <feature-branch>
159
165
 
@@ -235,12 +241,12 @@ git worktree prune # Self-healing: clean up any stale registrations
235
241
 
236
242
  ## Quick Reference
237
243
 
238
- | Option | Merge | Push | Keep Worktree | Cleanup Branch |
239
- |--------|-------|------|---------------|----------------|
240
- | 1. Squash-merge locally | yes (squash) | - | - | yes |
241
- | 2. Create PR | - | yes | yes | - |
242
- | 3. Keep as-is | - | - | yes | - |
243
- | 4. Discard | - | - | - | yes (force) |
244
+ | Option | Merge | Push | Keep Worktree | Cleanup Branch | Plan-doc removal |
245
+ |---|---|---|---|---|---|
246
+ | 1. Squash-merge locally | yes (squash) | - | - | yes | yes (unconditional) |
247
+ | 2. Create PR | - | yes | yes | - | yes (guarded, before push) |
248
+ | 3. Keep as-is | - | - | yes | - | - |
249
+ | 4. Discard | - | - | - | yes (force) | - |
244
250
 
245
251
  ## Common Mistakes
246
252
 
@@ -272,7 +278,7 @@ git worktree prune # Self-healing: clean up any stale registrations
272
278
  - **Problem:** Accidentally delete work
273
279
  - **Fix:** Require typed "discard" confirmation
274
280
 
275
- **Skipping the plan-doc deletion in Option 1**
281
+ **Skipping the plan-doc deletion in Options 1 and 2 (any path that lands on base)**
276
282
  - **Problem:** Plan docs are ephemeral and shouldn't land on `<base-branch>`. Forgetting `git rm doc/plans/<plan-file>.md` ships scaffolding to main.
277
283
  - **Fix:** The plan stays in the deleted branch's git history (`git log --all -- doc/plans/...`). Spec stays on `<base-branch>`; plan does not.
278
284
 
@@ -295,6 +301,7 @@ phase_tracker({ action: "complete", phase: "ship" })
295
301
  - Clean up worktrees you didn't create (provenance check)
296
302
  - Run `git worktree remove` from inside the worktree
297
303
  - Present finish options while a conformance gap is open and undispositioned
304
+ - Skip the guarded plan-doc removal before push on Option 2 when a plan doc was committed
298
305
 
299
306
  **Always:**
300
307
  - Verify tests before offering options
@@ -24,12 +24,7 @@ This skill may read anything and edit **only** the spec under `doc/specs/`. It d
24
24
 
25
25
  ## Configuration and gating
26
26
 
27
- Resolve `piGauntlet.specCouncil` from **two** settings files, repo-local first:
28
-
29
- 1. `<repo-root>/.pi/settings.json` (repo root = `git rev-parse --show-toplevel`, which inside a worktree is the worktree root). **If this file defines `specCouncil`, it wins** — even an empty `members` here is an explicit "no council for this repo".
30
- 2. `$PI_CODING_AGENT_DIR/settings.json` (agent preset) — consulted **only** when the repo file does not define `specCouncil` at all.
31
-
32
- The first file that defines the key wins; do not merge member lists across files. Do not hardcode a project path in place of `$PI_CODING_AGENT_DIR` — expand the env var. The resolved config looks like:
27
+ Resolve `piGauntlet.specCouncil` **repo-local first** — the repo's `.pi/settings.json` overrides the agent preset, **whole-object** (the first file that defines `specCouncil` wins outright; an empty `members` there is an explicit "no council for this repo"). Full source order, mechanics, and the per-key granularity rule live in `verification-before-completion/reference/settings-precedence.md`. Do not hardcode a path in place of `$PI_CODING_AGENT_DIR` — expand the env var. The resolved config looks like:
33
28
 
34
29
  ```json
35
30
  {
@@ -60,7 +60,7 @@ For each task in `plan_tracker`:
60
60
  6. If quality reviewer finds issues → re-dispatch implementer → re-review. Loop until ✅.
61
61
  7. Mark task complete in `plan_tracker`.
62
62
 
63
- After all tasks: dispatch a final reviewer over the full diff. Then [After All Tasks](#after-all-tasks-complete).
63
+ After all tasks: run the whole-diff code review (`requesting-code-review`). Then [After All Tasks](#after-all-tasks-complete).
64
64
 
65
65
  ## Implementer Status
66
66
 
@@ -86,8 +86,7 @@ Pi-subagents accepts a per-task `model` override. Use it.
86
86
  | Hard / novel / large surface | Most capable | New subsystem, complex algorithm, cross-service contract change |
87
87
  | Spec review | Default | Reads diff + spec, mechanical comparison |
88
88
  | Code-quality review | Most capable | Judgment call on naming, design, complexity |
89
- | Final reviewer | Most capable | Whole-PR-scope review |
90
- | Conformance / closure | Most capable | Whole-deliverable-vs-origin intent gate (`conformance-reviewer`; model from `piGauntlet.closureReview.model`, injected call-site) |
89
+ | Conformance / closure | Most capable | Whole-deliverable-vs-origin intent gate (`conformance-reviewer`; model from `piGauntlet.closureReview.model`, resolved repo-first whole-object, injected call-site) |
91
90
 
92
91
  ```ts
93
92
  subagent({
@@ -112,8 +111,8 @@ subagent({ agent: "spec-reviewer", task: "<diff range + spec excerpt + ask: does
112
111
  subagent({ agent: "code-reviewer", task: "<diff range + ask: production-ready?>" })
113
112
 
114
113
  // closing-loop conformance (origin vs deliverable) — its OWN dispatch, never fused with code quality
115
- // model from piGauntlet.closureReview.model (read $PI_CODING_AGENT_DIR/settings.json); omit to inherit
116
- subagent({ agent: "conformance-reviewer", model: /* piGauntlet.closureReview.model from config, else omit to inherit */, task: "<spec path + verbatim original prompt + full diff vs main; per conformance-check.md>" })
114
+ // model from piGauntlet.closureReview.model — resolve repo-local .pi/settings.json over the preset, whole-object (see verification-before-completion/reference/settings-precedence.md); omit to inherit
115
+ subagent({ agent: "conformance-reviewer", model: /* piGauntlet.closureReview.model, repo-first per settings-precedence.md, else omit to inherit */, task: "<spec path + verbatim original prompt + full diff vs main; per conformance-check.md>" })
117
116
  ```
118
117
 
119
118
  Prompt templates live alongside this SKILL.md:
@@ -188,11 +187,10 @@ For the fan-out + worktree + patch-integration + conflict mechanics, see `dispat
188
187
  ## After All Tasks Complete
189
188
 
190
189
  0. Call `phase_tracker({ action: "start", phase: "verify" })`. (The `implement` phase was started at execution start and auto-completes from `plan_tracker` once all tasks are done; this flow runs its own verify gate instead of `/skill:verification-before-completion`, so it must mark verify itself.)
191
- 1. Dispatch the final reviewer over the full diff (already covered in [The Process](#the-process) step "After all tasks").
192
- 2. **Run an audit pass automatically.** Run `/skill:requesting-code-review` against the worktree's full diff vs `main`. Then, if the project ships a project-specific audit skill (e.g., `.agents/skills/self-audit/`), run it as an optional supplement (it adds project-specific checks and fixes, not a replacement). Address Critical and Moderate findings before handoff. Do not ask the user just run it.
193
- 3. **Close the loop conformance check.** The audit in step 2 is plan-vs-code (single-step); it inherits any requirement the plan already dropped. Before marking verify complete, dispatch a fresh-context **`conformance-reviewer`** — its **own** dispatch, never fused into the step-1 final review — to confront the deliverable (code **and** docs) against the *origin* the spec **and** the original prompt per `verification-before-completion/reference/conformance-check.md`. Pass the spec path, the verbatim original prompt, and the full diff. On `GAPS`, do not auto-fix or auto-proceed: run the remediation loop in `verification-before-completion/reference/conformance-check.md` "When the check finds gaps" (disposition menu isolated fix waves bounded delta re-audit, capped by `piGauntlet.closureReview.maxFixRounds`). Only when the verdict is `CONFORMS` (or every gap is dispositioned) call `phase_tracker({ action: "complete", phase: "verify" })`.
194
- 4. Summarize what was implemented (tasks completed, files changed, test counts, self-audit verdict). Give the closing loop its **own section** `Closure / conformance: CONFORMS` (or `GAPS` with each gap and its disposition) so the user sees intent-fidelity as a first-class line before any finishing decision, not buried in the audit verdict.
195
- 5. **Proceed to finishing — no confirmation prompt.** When the verdict is `CONFORMS` (or every gap is dispositioned), invoke `/skill:finishing-a-development-branch` immediately. Its Step 4 menu (squash / PR / keep / discard) is the human gate; a separate "ready to finish?" prompt only stacks a second stop in front of it. Open gaps are already owned by step 3, so nothing is left to decide here. Manual testing is a follow-up after the finishing choice (on `<base-branch>` after a squash-merge, or on the PR branch), never a reason to hold this gate.
190
+ 1. **Run the whole-diff code review.** Dispatch `/skill:requesting-code-review` against the worktree's full diff vs `main` (already covered in [The Process](#the-process) step "After all tasks"). Address Critical and Moderate findings before handoff. (Consumers wanting an in-flow project-specific audit re-add it as an explicit step in `.pi/gauntlet-overrides.md`, or run `/self-audit` manually.)
191
+ 2. **Close the loop conformance check.** The review in step 1 is plan-vs-code (single-step); it inherits any requirement the plan already dropped. Before marking verify complete, dispatch a fresh-context **`conformance-reviewer`** — its **own** dispatch, never fused into the step-1 review — to confront the deliverable (code **and** docs) against the *origin* the spec **and** the original prompt — per `verification-before-completion/reference/conformance-check.md`. Pass the spec path, the verbatim original prompt, and the full diff. On `GAPS`, do not auto-fix or auto-proceed: run the remediation loop in `verification-before-completion/reference/conformance-check.md` "When the check finds gaps" (disposition menu isolated fix waves → bounded delta re-audit, capped by `piGauntlet.closureReview.maxFixRounds`). Only when the verdict is `CONFORMS` (or every gap is dispositioned) call `phase_tracker({ action: "complete", phase: "verify" })`.
192
+ 3. Summarize what was implemented (tasks completed, files changed, test counts, code-review verdict). Give the closing loop its **own section** — `Closure / conformance: CONFORMS` (or `GAPS` with each gap and its disposition) so the user sees intent-fidelity as a first-class line before any finishing decision, not buried in the review verdict.
193
+ 4. **Proceed to finishing no confirmation prompt.** When the verdict is `CONFORMS` (or every gap is dispositioned), invoke `/skill:finishing-a-development-branch` immediately. Its Step 4 menu (squash / PR / keep / discard) is the human gate; a separate "ready to finish?" prompt only stacks a second stop in front of it. Open gaps are already owned by step 2, so nothing is left to decide here. Manual testing is a follow-up after the finishing choice (on `<base-branch>` after a squash-merge, or on the PR branch), never a reason to hold this gate.
196
194
 
197
195
  ## Red Flags — STOP
198
196
 
@@ -2,7 +2,12 @@
2
2
 
3
3
  Tests passing proves the code runs. It does **not** prove the code does what was
4
4
  asked. This check confronts deliverables (code **and** docs) against the
5
- requirements.
5
+ requirements. Docs named in a spec's "Documentation impact" section - any of
6
+ the three classes (introduced, materially amended, derived/memory invalidated) -
7
+ are origin requirements the same as code: a missing or drifted doc from that
8
+ section is a conformance gap, not a code-review nit. See
9
+ `../../brainstorming/reference/documentation-impact.md` for what that section
10
+ contains and how its entries are scoped.
6
11
 
7
12
  ## Why this is distinct from code review
8
13
 
@@ -36,14 +41,14 @@ whole-PR code-quality review. Fusing the two subordinates intent-coverage to a
36
41
  code-quality system prompt and compresses the conformance result to an
37
42
  afterthought. Code quality is one dispatch; conformance is another.
38
43
 
39
- The persona ships model-free. Read the active preset's settings at
40
- `$PI_CODING_AGENT_DIR/settings.json` for `piGauntlet.closureReview.model` and
41
- inject it **call-site** on the dispatch (`model:` if set, else omit to inherit the
42
- parent's model) — the same mechanism the spec-council chair uses. If the configured
43
- model is unreachable, retry once with the inherited model. Point it at the strongest
44
- reasoning model the preset can reach this is the last correctness gate.
45
- `thinking` stays frontmatter-pinned at `xhigh` and is not call-site overridable, so
46
- the config supplies only `model`.
44
+ The persona ships model-free. Resolve `piGauntlet.closureReview.model` **repo-local
45
+ first** — the repo's `.pi/settings.json` overrides the agent preset, whole-object (see
46
+ sibling `settings-precedence.md`) — and inject it **call-site** on the dispatch
47
+ (`model:` if set, else omit to inherit the parent's model) — the same mechanism the
48
+ spec-council chair uses. If the configured model is unreachable, retry once with the
49
+ inherited model. Point it at the strongest reasoning model the resolved config can
50
+ reach — this is the last correctness gate. `thinking` stays frontmatter-pinned at
51
+ `xhigh` and is not call-site overridable, so the config supplies only `model`.
47
52
 
48
53
  Self-checking in the main session is the fallback when delegation isn't possible.
49
54
 
@@ -197,7 +202,8 @@ still-open with its prior verdict, or introducing `Gn+1`.
197
202
 
198
203
  - The re-audit dispatch carries the **same call-site `model:` injection** as the initial
199
204
  audit (when `piGauntlet.closureReview.model` is set, the phase-tracker closure guard
200
- requires every `conformance-reviewer` dispatch to specify `model:`).
205
+ blocks a `conformance-reviewer` dispatch that omits `model:`, and warns — non-blocking —
206
+ on one whose model differs from the configured value).
201
207
  - New or still-open gaps within the cap re-enter the menu above.
202
208
  - **Cap: read `piGauntlet.closureReview.maxFixRounds`** (default `2`; missing/non-integer
203
209
  → `2`; `< 0` → `0`). `0` = audit-only: `GAPS` renders an accept/rescope-only menu and any
@@ -0,0 +1,44 @@
1
+ # Settings precedence: repo-local first
2
+
3
+ How to resolve a `piGauntlet.<key>` settings value that both a repo and an agent
4
+ preset may define. Both the spec-critique gate (`specCouncil`) and the conformance
5
+ gate (`closureReview`) use this rule; it is stated once here.
6
+
7
+ ## Source order (both keys)
8
+
9
+ Read two files, **repo-local first**:
10
+
11
+ 1. `<repo-root>/.pi/settings.json` - repo root from `git rev-parse --show-toplevel`
12
+ (inside a worktree this is the worktree root).
13
+ 2. `$PI_CODING_AGENT_DIR/settings.json` - the agent preset.
14
+
15
+ Mechanics for both files: they may contain comments - read them, do not pipe
16
+ through a strict JSON parser. Expand `$PI_CODING_AGENT_DIR`; never substitute a
17
+ hardcoded path for it (reading the repo `.pi/settings.json` as if it were the
18
+ preset is the classic miss - they are different files). On a malformed repo-local
19
+ file, the reading agent emits one warning line in its response and falls back to
20
+ the preset.
21
+
22
+ ## Merge granularity (same for both keys): whole-object
23
+
24
+ Both `specCouncil` and `closureReview` resolve **whole-object**: if the repo file
25
+ defines the key at all, that definition **replaces** the preset's entirely; the two
26
+ are never merged leaf-by-leaf. If the repo file does not define the key, the
27
+ preset's value is used unchanged.
28
+
29
+ This is not a pi-gauntlet convention - it is exactly what pi's own settings merge
30
+ does. `deepMergeSettings` (pi's `SettingsManager`) merges only the **top-level**
31
+ Settings keys (of which `piGauntlet` is one) by a one-level spread
32
+ `{ ...preset.piGauntlet, ...repo.piGauntlet }`. That spread replaces each
33
+ **second-level** key (`closureReview`, `specCouncil`, `flowGuards`) wholesale when
34
+ the repo defines it; it does **not** recurse into that key's leaves. So the
35
+ `phase-tracker.ts` closure guard (which reads `pi.settings.piGauntlet.closureReview.model`)
36
+ and the skills (which read repo-first, whole-object) resolve the same value.
37
+
38
+ **Caveat - partial definitions drop siblings.** Because the replace is
39
+ whole-object, a repo file that sets only *one* leaf of a key silently drops the
40
+ preset's other leaves for that key. A repo `closureReview: { "model": "..." }` with
41
+ no `enforce`/`maxFixRounds` makes those fall back to their code defaults
42
+ (`enforce` true, `maxFixRounds` 2), **not** to the preset's values. Define every
43
+ leaf you care about together in the file that owns the key. (Sibling keys like
44
+ `specCouncil` are unaffected - only the key the repo redefines is replaced.)
@@ -85,6 +85,10 @@ Group tasks into **waves** so the executor can parallelize independent work (see
85
85
 
86
86
  **Runtime-resource disjointness.** File-disjoint is necessary but not sufficient: two tasks with disjoint files that both mutate the same DB, bind the same port, or share a fixture are **not** parallel-safe and must land in different waves. The executor auto-selects parallel for *every* multi-task wave, so this grouping is the sole parallel-safety guarantee — there is no selection-time judgment downstream. No new mandatory per-task syntax; when a shared runtime resource is the reason two file-disjoint tasks sit in different waves, record it in an inline note on the later wave.
87
87
 
88
+ **Doc tasks.** Doc updates are real plan tasks, not an afterthought. Task-local docs (a doc that only describes the file(s) a task already touches) ride with that task. Cross-cutting or index docs (README, `AGENTS.md`, topic guides, taxonomy indexes) sequence into a dedicated trailing doc-only wave — last wave by convention, file-disjoint from every code task so the pairwise-disjoint wave contract holds.
89
+
90
+ **Doc-wave collision rule.** Amend-over-create (see `brainstorming/reference/documentation-impact.md`) concentrates edits into hub docs like README and `AGENTS.md`. A doc wave with ≥2 tasks auto-selects Parallel-Wave Mode, which requires pairwise-disjoint files — so doc tasks that land on the *same* file merge into one task rather than splitting. A single-task trailing doc wave is the expected shape, not a smell.
91
+
88
92
  ```markdown
89
93
  ## Wave 1 — Foundations
90
94
 
@@ -189,7 +193,7 @@ Every plan failure mode:
189
193
  - ❌ "Similar to Task N" — repeat the code. Implementers (and subagents with fresh context) may read tasks out of order; pointing at a sibling task is not a substitute for showing the code.
190
194
  - ❌ References to types, functions, methods, or fields not defined in any task in this plan. If it shows up in Task 5, it must be introduced by Task 1–4 or already exist in the codebase (with a file:line citation).
191
195
  - ❌ `[fill in]`, `<example>`, `xxx` markers anywhere in the doc.
192
- - ❌ "Probably also need to update the docs" — either yes (which doc) or no.
196
+ - ❌ "Probably also need to update the docs" — either yes (which doc) or no. Docs are named plan tasks, sourced from the spec's Documentation impact section (materiality bar in `brainstorming/reference/documentation-impact.md`).
193
197
 
194
198
  If a decision is genuinely open, put it in an explicit **Open Questions** section at the top and resolve before execution starts.
195
199
 
@@ -197,7 +201,7 @@ If a decision is genuinely open, put it in an explicit **Open Questions** sectio
197
201
 
198
202
  After drafting the plan and before announcing it complete, run three checks yourself. This is a checklist you run yourself — not a subagent dispatch.
199
203
 
200
- - **Spec coverage.** Cross-reference the spec's components/decisions/constraints against the plan. Does every spec section map to one or more tasks? If a spec decision has no implementation task, the plan is missing work or the spec was overspecified.
204
+ - **Spec coverage.** Cross-reference the spec's components/decisions/constraints against the plan. Does every spec section map to one or more tasks? If a spec decision has no implementation task, the plan is missing work or the spec was overspecified. Each Documentation impact entry maps to a plan task (or explicit "none").
201
205
  - **Placeholder scan.** Grep the doc for `TODO`, `TBD`, `xxx`, `[fill in]`, `<example>`, `etc.`, "probably", "something like". Resolve or convert each into an explicit Open Question.
202
206
  - **Type / API consistency.** Function signatures and field names that appear in multiple tasks must match exactly. The plan is its own contract — internal contradictions surface as bugs during execution.
203
207
  - **Wave disjointness.** For every multi-task wave, confirm the tasks' `Files:` sets are pairwise disjoint **and** that no two tasks contend on a shared mutable runtime resource (DB/schema, port, fixture, external service, shared temp path). Either kind of overlap = mis-grouped wave; split or re-order before handoff.
@@ -36,11 +36,14 @@ Each skill directory contains:
36
36
  SKILL.md # required entry point
37
37
  reference/ # optional progressive-disclosure files
38
38
  <topic>.md # read directly when SKILL.md points at it
39
- <supporting>.md # prompt templates, examples
39
+ examples.md # read directly when SKILL.md points at it
40
+ <supporting>.md # prompt templates (dispatch payloads)
40
41
  ```
41
42
 
42
43
  `reference/` is the pi pattern for keeping SKILL.md tight while still shipping deep guidance. See `.pi/skills/test-driven-development/reference/` and `.pi/skills/systematic-debugging/reference/` for working examples.
43
44
 
45
+ Prompt templates and other dispatch payloads - files filled in and passed wholesale into a subagent `task` - live as siblings of SKILL.md, not under `reference/`. See `requesting-code-review/code-reviewer.md` and the three `subagent-driven-development/*-prompt.md` files. The decision criterion is destination, not format: a file passed wholesale into a subagent's `task` is a sibling; a file read at a decision point for deep guidance, examples, or rationale is `reference/`. Some older skills (`systematic-debugging`, `test-driven-development`) keep deep-guidance `*.md` files flat as siblings, predating the `reference/` convention (obra/superpowers lineage) - that is descriptive history, not a mandate to move them.
46
+
44
47
  ### Reference Files Bundled With This Skill
45
48
 
46
49
  Read directly when SKILL.md tells you to (path is given inline). The progressive-disclosure pattern is *which file to read when*, not a special tool: