pi-gauntlet 6.2.0 → 7.0.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.
@@ -0,0 +1,128 @@
1
+ # Spec finalization
2
+
3
+ ## Spec Self-Review (Before User Review Gate)
4
+
5
+ Spec-writing replaces the context draft, in this exact order:
6
+
7
+ 1. `Read` the draft in full - **immediately before** the overwrite. Without this, a
8
+ pruned questionary plus a full-replacement `write` destroys the only copy of the
9
+ gathered context at the moment it feeds the spec.
10
+ 2. Write the spec with the `write` tool (**full replacement**) at the spec path.
11
+ Using `edit` at this step is a red flag.
12
+ 3. **Immediately after the write**, confirm line 1 of the file is no longer
13
+ `# CONTEXT DRAFT - NOT A SPEC - fully replaced at spec-writing` - before
14
+ dispatching lint, critique, council, or summarizer. The phase-tracker commit
15
+ guard is a backstop, not the primary check.
16
+ 4. **After the line-1 check**, run the second predecessor pass. Compose a query from
17
+ the spec's H1 terms, then the terms of every H2 that is not a template heading
18
+ (Problem, Acceptance criteria, Design, Errors and edge cases, Tests, Documentation
19
+ impact, Out of scope, Open questions), then the `**Goal:**` line's terms - same
20
+ token rules as the scout, deduplicated, cut at 15. Run
21
+ `(cd <abs worktree path> && node <SPEC_INDEX> --query '<terms>' --limit 5 --exclude <spec path relative to the worktree>)`
22
+ with `<SPEC_INDEX>` resolved as in `../gatherer.md`. Take the `live` rows and drop every
23
+ path the draft's `Predecessor:` line(s) named (retained from the step-1 read). Carry
24
+ the remainder to the gate as one adjacent line:
25
+ `New predecessor candidates at spec-writing: <path> (<title>), ... - index rows are a hint; code is the source and an absent row proves nothing.`
26
+ or `New predecessor candidates at spec-writing: none.` A non-zero exit degrades to
27
+ `Second predecessor pass unavailable: <first stderr line>`; it never blocks the gate
28
+ or the commit. "yes, <path> is a predecessor" at the gate is a change request that
29
+ adds the `supersedes <path>, <scope>` clause and the banner, then re-presents the gate.
30
+ 5. **After the second predecessor pass and before the inline lint**, `edit` any known
31
+ predecessor spec to insert its supersession banner (see
32
+ [Marking superseded specs](superseding.md)). This position is fixed:
33
+ the banner is written after any slug rename, so it always cites the final path.
34
+
35
+ After writing the spec to `<project>/doc/specs/<filename>.md` (per [Filename Convention](../SKILL.md#filename-convention)) and before showing it to the user, run a self-review pass. Read all six bullets first, then act.
36
+
37
+ - **Placeholder scan.** Any `TODO`, `TBD`, `<fill in>`, `[example]`, `xxx`? Either resolve them or convert to explicit "Open Questions" with names.
38
+ - **Internal consistency.** Does Section 4 contradict Section 2? Are component names and field names consistent throughout? If the spec replaces a prior design, confirm the predecessor carries the supersession banner and its href resolves to this spec's final filename.
39
+ - **Documentation named.** Does the spec name all three classes (feature/user-facing introduced; materially amended; derived/memory invalidated), or an explicit "none" for each? Enforce the materiality bar in `documentation-impact.md` without restating it: each listed doc names the category it clears, none is a code-mirror, amend-over-create was applied, and skill/agent bodies are implementation surface, not doc-impact entries here.
40
+ - **Ticket contract present.** Does `## Acceptance criteria` exist with either verbatim ticket rows plus dispositions or one `none - <reason>` line? Presence is enforced here, at authoring, and nowhere later.
41
+ - **Scope check.** Does every paragraph serve the goal? Cut filler. If something is out of scope, say it's out of scope.
42
+ - **Ambiguity check.** Is every "we should..." backed by a concrete decision? Replace "we could probably" with "we will" or "we won't".
43
+
44
+ The first four are the inline **lint**: run them here and fix what they surface. The last two are the **critique pass**, dispatched per [Spec Council](#spec-council). After it returns, re-run the placeholder scan over the applied spec; if a predecessor banner exists, confirm its `<scope>` still matches and reconcile it; carry any ambiguity the critique could not resolve to the [User Review Gate](#user-review-gate).
45
+
46
+ ## Spec Council
47
+
48
+ Before dispatching the worker below, resolve `documentation-impact.md` relative to this loaded reference as one absolute `<DOCUMENTATION_IMPACT_GUIDELINE>` path value. Pass that value in the worker task; do not add it to the spec.
49
+
50
+ After the inline lint and before the user review gate, **brainstorming owns the critique-pass gate**; council **apply mechanics** live in `/skill:roasting-the-spec` (single source of truth - link, don't restate). Resolve the council with `gauntlet_setting({ key: "specCouncil" })` - the tool returns the merged (repo-over-preset) value as `{ verdict, members, chair, malformed, warning, errors }`. **Do not** hand-roll a settings read. When `verdict` is `"council"`, the council *is* the critique pass - invoke `/skill:roasting-the-spec` automatically (no offer, no prompt), passing `members`/`chair`; also pass the verbatim human input (the original prompt, any ticket AC snapshot - the raw rows under the gather draft's `## Ticket acceptance criteria (verbatim)` heading, never the spec's section, which holds the author's dispositions - and the questionary answers that changed scope) - roasting-the-spec forwards it to members and chair as the `Human input (verbatim; off-limits for over-spec)` block; it applies its apply-set and returns the audit (Applied/Deferred/Rejected). When `verdict` is `"worker"`, dispatch the worker below. If `malformed` is true or `errors` is non-empty, emit the `warning`/error as one line, then branch strictly on `verdict` - `malformed` can accompany *either* verdict (e.g. a bad `chair` with valid `members` still returns `council`), so never infer the worker path from `malformed` alone. If `gauntlet_setting` is unavailable, stop and report - never fall back to a manual bash/JSON settings merge. The already-applied council edits (or the worker's in-place fixes) ride in the same worktree commit. The conceptual precedence rule lives in `../../verification-before-completion/reference/settings-precedence.md`.
51
+
52
+ When `verdict` is `"worker"`, dispatch one fresh `worker` that applies the scope + ambiguity checks and fixes them in place:
53
+
54
+ ```
55
+ subagent({ agent: "worker", context: "fresh", async: false, cwd: "<abs worktree path, from the using-git-worktrees Step 4 report>", task:
56
+ "Problem statement: <the problem the spec addresses + the user's stated intent>.\n" +
57
+ "Read the spec at <abs path to doc/specs/...>. Edit ONLY that file.\n" +
58
+ "The portable citation `reference/documentation-impact.md` in the spec is the pi-gauntlet guideline at <DOCUMENTATION_IMPACT_GUIDELINE>, not a consumer doc; do not flag it as an external reference, and preserve it - never remove it as redundant or replace it with the resolved absolute path.\n" +
59
+ "Apply two checks and fix what you find in place: (1) Scope - does every paragraph serve the goal? Cut filler;\n" +
60
+ "state out-of-scope explicitly. (2) Ambiguity - is every 'we should' a concrete decision?\n" +
61
+ "Replace 'we could probably' with 'we will'/'we won't'. Also inline any load-bearing\n" +
62
+ "external reference (ticket AC, commit SHA, doc) already given to you in the problem\n" +
63
+ "statement above; if the spec relies on one not provided here, flag it (do NOT fetch) in\n" +
64
+ "your summary. Return a summary of what you changed, and flag any ambiguity you could NOT\n" +
65
+ "safely resolve." })
66
+ ```
67
+
68
+ `worker`'s model resolves from `subagents.agentOverrides.worker.model` in `settings.json` (unset -> inherits the main loop); the dispatch passes no `model:`.
69
+
70
+ ## User Review Gate
71
+
72
+ After self-review and the critique pass (council or worker, both already applied to the spec - see [Spec Council](#spec-council)), dispatch the spec-only summarizer over the **applied** spec, then commit the spec on the worktree branch and stop. The summary is folded into the one human gate, not a new gate.
73
+
74
+ Mint an absolute temp path outside the worktree (so it is never committed), then dispatch the summarizer on a fresh context, reading only the spec, writing to that path via file-only output (no `model:` - it inherits the main loop unless a preset sets `subagents.agentOverrides.spec-summarizer.model`):
75
+
76
+ ```bash
77
+ SUMMARY_PATH=$(mktemp "${TMPDIR:-/tmp}/gauntlet-spec-summary.XXXXXX") # absolute, portable across GNU/BSD mktemp
78
+ ```
79
+
80
+ ```
81
+ subagent({ agent: "spec-summarizer", context: "fresh", async: false, cwd: "<abs worktree path, from the using-git-worktrees Step 4 report>",
82
+ output: "<SUMMARY_PATH>", outputMode: "file-only", task:
83
+ "Summarize the spec at <abs path to doc/specs/...> for the user review gate. Read ONLY that file." })
84
+ ```
85
+
86
+ `<SUMMARY_PATH>` above is a placeholder in the dispatch object; it means substitute the value of the shell variable `$SUMMARY_PATH` set above. The steps below use `$SUMMARY_PATH` (the shell form) once the value is in hand.
87
+
88
+ Then commit the spec - staging any predecessor spec edited per [Marking superseded specs](superseding.md) alongside it; a change request at the gate that renames, materially revises, or drops the spec also reconciles the predecessor's banner before recommitting. This commit is **unconditional**: the summary is only a gate aid, so a degraded or missing summary never blocks it. If the council path ran, include its audit (`Coverage:` when present, then `Applied:` / `Deferred:` / `Rejected:`, verbatim from `/skill:roasting-the-spec`'s return) in the **commit message body** - this is the durable, non-contractual record a finish-time revert reads back; the audit is never a committed spec section. Evaluate the summary in two stages (the **Degrade path** referenced in each is defined just below):
89
+
90
+ 1. **From the dispatch tool result, before the `Read`.** If the result is **not** an `"Output saved to: <path> (<N> KB, <M> lines)"` reference (e.g. an exit-0 save error returns the full inline output plus an "Output file error" line - the prunable shape, no file to read), or the reference reports under ~500 bytes, or a size grossly disproportionate to the spec (under ~2% of its byte size), or over ~45 KB (the `Read` truncates at 50KB / 2000 lines, so a larger file cannot render whole) - skip the `Read` and take the degrade path. Use the reference's reported figures; do not re-derive them.
91
+ 2. **The `Read` itself, as the last content-producing tool call before composing the gate.** `Read` `$SUMMARY_PATH` and paste its contents verbatim at the top of the gate. If the `Read` fails, returns 0 bytes, or reports truncation - take the degrade path. The `Read` must be last: pi-condense does not protect a `/tmp` read, so any turn boundary between the `Read` and the render lets the ~9KB read result be pruned, reproducing the bug.
92
+
93
+ **Degrade path** - reach the gate with a one-line "summary generation failed" note; never paraphrase from the file-only reference, never render a stub as the canonical summary.
94
+
95
+ Either way - summary rendered or degraded - then `rm "$SUMMARY_PATH"` (unconditional cleanup; harmless if the file was never created, since it lives outside the worktree under the OS temp dir).
96
+
97
+ Paste the summary verbatim, unedited in the template below; use adjacent lines for the audit, unresolved ambiguities, and every gap-footer entry:
98
+
99
+ ```
100
+ <spec-only summary read back from the temp file - pasted verbatim, unedited>
101
+
102
+ Spec written and committed to <project>/doc/specs/<filename>.md (worktree: <path>).
103
+
104
+ Coverage: <N> of <M> members reported; <slug>: <reason> (line present only when coverage was partial)
105
+ Applied: [<severity>] <cluster> - raised-by: [<slugs>] -> <edit>
106
+ Deferred: [<severity>] <cluster> - raised-by: [<slugs>] -> <where it belongs>
107
+ Rejected: [<severity>] <cluster> - raised-by: [<slugs>] -> <one-line reason>
108
+ (one line per item, exactly as returned by roasting-the-spec - `Applied: none` / `Deferred: none` / `Rejected: none` when a list is empty; omit the audit lines when the worker path ran, not the council)
109
+
110
+ <unresolved ambiguities; every gap-footer entry from the summary>
111
+ New predecessor candidates at spec-writing: <path> (<title>), ... - index rows are a hint; code is the source and an absent row proves nothing.
112
+
113
+ Please review. Approve to proceed, tell me what to change in the spec, or say "revert applied council edit <X>" to undo a specific applied edit. Reply "auto-apply amends" - every later amend-class change in this flow then applies without review, scope changes included; redraws and the spec gate still stop. "approve, auto-apply amends" does both.
114
+ ```
115
+
116
+ If you believe the summary needs correcting, do **not** silently rewrite it - re-dispatch the summarizer or note the discrepancy as an adjacent line beneath the verbatim block.
117
+
118
+ **Revert valve.** "Revert applied council edit X" is a normal change request: revise the spec to undo edit X, re-dispatch the summarizer with a **fresh** temp path (per the re-dispatch rule below), and re-present the gate. This is cheap here - the spec is not yet plan- or code-bearing.
119
+
120
+ 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; first read [Standing grants](amendment-surface.md#standing-grants) (stop if unreadable) and record any grant. 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.
121
+
122
+ Post-approval changes follow [Amending an approved spec](../SKILL.md#amending-an-approved-spec).
123
+
124
+ After approval, mark the brainstorm phase complete:
125
+
126
+ ```
127
+ phase_tracker({ action: "complete", phase: "brainstorm" })
128
+ ```
@@ -0,0 +1,18 @@
1
+ # Ticket Handling
2
+
3
+ A ticket is guidance, not sole truth. Fetch it; propose scope, approach, or acceptance changes when code disagrees, and record deviations in the spec. Implied requirements in the ticket body (Context, Problem, Idea) land in the spec body as any other requirement; the ticket's explicit acceptance criteria land verbatim in the section below.
4
+
5
+ **Extract the ticket's ACs.** When the ticket body has a heading matching `/acceptance criteria/i`, every list item under it until the next heading is an AC (numbered, bullet, or checkbox) and no other list in the body is. When there is no such heading, every top-level checkbox row in the body is an AC, except rows under a `Post-deployment housekeeping`, `Out of scope`, or `Follow-up` heading. Otherwise the ticket has no ACs. A nested list under an AC row rides with its parent as one row; an AC heading holding prose and no list makes each paragraph one row. Carry checked and unchecked rows alike, all written `- [ ]`. Take the rows from the gather draft's `## Ticket acceptance criteria (verbatim)` heading; when the ticket was not fetched, the gate summary shows the `none` line so the user can paste the rows, which then become rows.
6
+
7
+ **Write the section in every spec**, after `## Problem`:
8
+
9
+ ```markdown
10
+ ## Acceptance criteria
11
+
12
+ Ticket <ref>, <heading or "checkbox list">, rows verbatim:
13
+
14
+ - [ ] <row text copied verbatim>
15
+ <disposition>
16
+ ```
17
+
18
+ The heading `## Acceptance criteria` names the ticket contract only; the spec's own requirements stay in Design. Disposition is exactly one of `in-scope`, `deviates: <why>`, `deferred: <where>`, `venue: <env> - <observation>`; default `in-scope`. Never edit the row text: a wrongly stated row is `deviates: <why>`, an ambiguous row stays `in-scope` with the chosen reading written as a Design clause. Name a `venue:` row's enabling change in Design. An `in-scope` row is a requirement as written; disposition reasons are never normative for the plan or the reviewer, so a `deviates:` reason that adopts part of a row restates that part as a Design clause. Defer a row only when the shipped change operates without it - cost is never a reason; a hard but direct AC stays `in-scope` and ships. Ask a `deviates:`/`deferred:` decision only when it changes what the user observes once the change ships, offering the dispositions themselves as the options (`A) in-scope B) deviates: <why> C) deferred: <where>`); a deviation caused by a workflow artifact (spec, plan, changelog, telemetry file) or a moved path is stated in the disposition, not asked. Name every disposition in the gate summary; `venue:` states where the observation can happen and is not a scope decision. A disposition changes in any later phase - a reviewer finding `recommended: rescope` at the finish gate, a wrong row noticed mid-implementation, or a ticket edited after approval when the user asks - through [Amending an approved spec](../SKILL.md#amending-an-approved-spec) (`amendment-surface.md`); the row text still never changes. With no ticket, or a ticket without ACs, the section body is the single line `none - no ticket`, `none - ticket has no acceptance criteria`, or `none - ticket not fetched (<reason>)`. Never author acceptance criteria on the ticket's behalf; that is `/skill:shape-ticket`'s job.
@@ -277,7 +277,7 @@ any handoff:
277
277
  - File a ticket chosen -> shape-ticket runs its own gate first -> draft the
278
278
  response citing the new ticket link -> gate 2 -> done.
279
279
  - Brainstorm now chosen -> draft the response first ("confirmed, investigating
280
- now - fix to follow") -> gate 2 -> **then** hand off to `/skill:brainstorming`.
280
+ now - fix to follow") -> gate 2 -> **then** hand off to [`/skill:brainstorming`](../brainstorming/SKILL.md).
281
281
  - Hotfix now chosen -> hand off to `hotfix.md` first; on completion, draft the
282
282
  response citing `fixed in <SHA>` or the PR link -> gate 2 (`send it`) -> done.
283
283
  Gate 2 fires once. On abort, `hotfix.md` returns to the step-4 menu; step 5
@@ -343,7 +343,7 @@ action renders the verdict as a **summary to the human**, then the skill ends
343
343
  shape-ticket is cancelled at its gate, render the summary without a ticket
344
344
  link.
345
345
  - Brainstorm now chosen -> render the summary -> **then** hand off to
346
- `/skill:brainstorming`.
346
+ [`/skill:brainstorming`](../brainstorming/SKILL.md).
347
347
  - Hotfix now chosen -> hand off to `hotfix.md`; on completion render the
348
348
  summary citing `fixed in <SHA>` or the PR link -> done. On abort, return to
349
349
  the step-4 menu.
@@ -32,6 +32,9 @@ Post-merge **detective control**: proves an issue's work actually shipped -
32
32
  landed on the default branch, reached its delivery target, holds against its
33
33
  acceptance criteria - before the tracker status advances. It is not a
34
34
  quality gate; CI and the gauntlet gates already ran. It verifies **delivery**.
35
+ It takes no input from `/skill:gatekeep-pr`: nothing the pre-merge gate
36
+ rendered is read or trusted here. ACs are re-extracted from the ticket in
37
+ stage 0 and the shipped SHA is re-derived in stage 1.
35
38
 
36
39
  **Core principle:** every ambiguity resolves toward "stop loudly, write
37
40
  nothing." An unreadable ticket, an unresolvable deliverable set, a commit
@@ -373,6 +376,7 @@ unset (no body edits).
373
376
  | "The ticket says done in a comment" | Ticket narrative is not evidence; only SHA-pinned code or target observations count |
374
377
  | "Just move it to Done, the human can reopen" | Never a terminal status - acceptance is the human's move, not this skill's |
375
378
  | "The AC was only synthesized, so the gap can't block" | Under `synthesized AC gaps: block`, a synthesized AC runs the same verdict matrix as an authored one - an unexplained gap blocks |
379
+ | "The PR gate already checked this AC" | The gate judged the mechanism pre-merge; this control observes delivery at the shipped SHA from the ticket's own ACs |
376
380
 
377
381
  ## Red flags - STOP
378
382
 
@@ -394,6 +398,8 @@ unset (no body edits).
394
398
  - Striking an AC line the gate approval did not ratify as `proposed descope`
395
399
  - Applying a body edit by replaying the gather-time snapshot instead of
396
400
  patching the re-fetched body
401
+ - Using a PR body, PR review comment, or pre-merge gate report as the AC list
402
+ or as AC evidence
397
403
 
398
404
  ## Project overrides
399
405
 
@@ -1,207 +1,69 @@
1
1
  ---
2
2
  name: gatekeep-pr
3
- description: Use when gating a pull request before it merges - whether you authored it or are reviewing someone else's work. Consent-gated - verification is read-only, every externally visible mutation (fix commits, pushes, reviews, merges) waits for explicit selection.
3
+ description: Use when gating a pull request before it merges - whether you authored it or are reviewing someone else's work. Judges whether the diff delivers the mechanism each acceptance criterion needs (code, tests, docs) and conforms to the review rubric; what can be seen only after merge belongs to /skill:check-delivery. Consent-gated - every mutation (fixes, pushes, reviews, merges, tracker comments) waits for an explicit menu pick.
4
4
  disable-model-invocation: true
5
5
  argument-hint: "<pr> [issue-ref] (e.g. 123, or 123 gh-45)"
6
6
  ---
7
7
 
8
8
  # gatekeep-pr
9
9
 
10
- Verify, don't trust. A PR description is a claim, not proof: over-claimed coverage,
11
- hallucinated references, and "tests pass" that were never rerun are the normal case,
12
- not the exception - especially on generated code. Gather evidence, accept green CI on
13
- the exact assessed head as verification evidence (run the project's own verification
14
- command only as the fallback), review the diff against a rubric, and present a
15
- deterministic, authorship-aware menu. Authorship sets which row carries
16
- `[recommended]`; it never changes which rows are offered.
17
-
18
- **Consent gate.** The only actions performed before a menu row is picked are:
19
- read-only gathering, provisioning the worktree, and applying uncommitted, worktree-local
20
- doc-drift fixes discovered as a blocking finding. Every other action - code fixes,
21
- pushes, reviews, comments, merges - happens only on explicit selection.
22
-
23
- **Residual risk.** Running the verification command executes PR code with the
24
- operator's ambient credentials. There is no sandbox. Run this skill only against PRs
25
- you are willing to execute.
10
+ Verify, don't trust: a PR description is a claim, and over-claimed coverage, hallucinated references, and "tests pass" that never ran are the normal case on generated code. Judge the mechanism only - whether code, tests, and docs at the assessed head make each promised behavior possible - and leave what can be seen only after merge (a staging run, production data, an external system) to `/skill:check-delivery`. Nothing mutates before a menu pick: steps 1-5 read, provision a worktree, and draft; fixes, pushes, reviews, comments, merges, and tracker writes happen only on explicit selection. Running the verification command executes PR code with your ambient credentials and no sandbox - gate only PRs you are willing to execute.
26
11
 
27
12
  ## Arguments
28
13
 
29
- - PR number or URL. If omitted: `gh pr view --json number,url` on the current branch;
30
- no PR found there -> STOP and report.
31
- - Optional issue reference. If omitted: infer from `closingIssuesReferences`, then
32
- branch name, PR title, body, or commits. None found -> judge the PR against its
33
- stated intent only; never invent acceptance criteria.
34
-
35
- ## Configuration resolution
36
-
37
- Apply per concern, first match wins, evaluated unconditionally - never delegated to
38
- a wrapper skill:
39
-
40
- 1. **Repo root `REVIEW.md`** (rubric concerns only). Wins over the shipped
41
- baseline and reviewer-persona defaults on any conflict.
42
- 2. **Gauntlet overrides file** (3-location discovery, first found wins): the
43
- `## PR gate` section (verification command, `timeout minutes`, `requires credentials`, issue
44
- fetch, worktree wrapper, merge policy, `local verification`, `ci checks`). An existing `## verification-before-completion`
45
- section is an accepted equivalent source for the verification command.
46
- 3. **Repo documentation** - an explicitly documented command or tool (e.g. `AGENTS.md`'s
47
- canonical test entrypoint, a documented worktree wrapper, a documented tracker CLI,
48
- or documented merge policy/branch rules). Reading documentation is not inference.
49
- Discovery-only: never tell consumers to add gatekeep-pr configuration here.
50
- 4. **Ask the user.** Never guess from lockfiles, file heuristics, or vibes.
51
-
52
- The `## PR gate` overrides schema (all keys optional except the verification command,
53
- which is required unless documented elsewhere):
54
-
55
- ```markdown
56
- ## PR gate
57
- - verification command: <command> # required unless documented elsewhere
58
- - timeout minutes: 15 # optional; default 15
59
- - requires credentials: false # optional; true => skill reports "not run" as missing evidence
60
- - local verification: always # optional; default (absent) = CI-first; "always" forces the local run even when exact-head CI is green
61
- - ci checks: <comma-separated check names> # optional; narrows which checks count as evidence; absent = all checks on the assessed head
62
- - worktree wrapper: <command> # optional
63
- - issue fetch: <command with <ref> placeholder> # optional, replaces gh issue view
64
- - merge policy: squash | merge-commit # optional
65
- ```
66
-
67
- **Thin-wrapper contract.** A consumer wrapper skill is a pure proxy: trigger phrases
68
- plus "follow `/skill:gatekeep-pr`" - zero configuration data. All customization lives
69
- in the repo's `REVIEW.md` (rubric) and the gauntlet overrides file's `## PR gate`
70
- section (everything else); anything a wrapper carries beyond trigger phrases is
71
- misplaced and belongs in one of those two homes instead.
72
-
73
- Read the ladder from the **merge-base of the PR's base branch**, never from
74
- the PR's head tree - a PR cannot weaken its own rubric or swap the command that will
75
- gate it. Recipe: `MB=$(git merge-base origin/<baseRefName> <headRefOid>)`, then for
76
- each ladder source `git show "$MB:<path>"` (e.g. `git show "$MB:REVIEW.md"`,
77
- `git show "$MB:AGENTS.md"`). A plain cwd read (`cat REVIEW.md`, reading the file open
78
- in the PR worktree) is invalid for any ladder source - it reads the PR's head, exactly
79
- what this rule forbids - even when the assessment happens to run from inside the PR's
80
- worktree. Exception: if the PR itself changes `REVIEW.md` or the overrides file, that
81
- diff is review subject matter, surfaced as a finding - it is not applied to this run's
82
- configuration.
83
-
84
- ## Progress tracking
85
-
86
- Use `plan_tracker`, never `phase_tracker`. Init with the first four stages:
87
- `gather`, `provision worktree`, `resolve evidence`, `claim-check`. While
88
- `claim-check` is `in_progress`, `add` one task per material claim as the
89
- Verifier enumerates them and record each verdict: a matched claim ->
90
- `complete`, a contradicted claim -> `failed` (shown crossed, error color).
91
- Once every claim is terminal and `claim-check` is closed, `add` `review` and
92
- `consent menu` and continue. Never init stages ahead of the claims: the
93
- tracker rejects a verdict recorded behind a still-pending stage. A
94
- failed stage or claim stays `failed` while the skill stops at the menu -
95
- never marked complete to move on. On a harness without the `plan_tracker`
96
- tool: fall back to a plain checklist (or skip if none is available);
97
- functionality is unchanged either way.
98
-
99
- ## Assess
100
-
101
- Run four phases in order - gather, provision worktree, verify then review, integrate.
102
- Read `reference/assessment.md` and `reference/findings.md` now.
103
-
104
- ## Verdict
105
-
106
- Three states: **blocking findings** (failed gate, contradicted material claim, a
107
- merge-proof unverifiable claim, `partial`/`missing` AC coverage, scope creep when an
108
- issue is linked, committed doc drift, anything the merged rubric maps to blocking),
109
- **follow-ups only** (never gate merge), or **clean**.
110
-
111
- **Merge preconditions** (all must hold):
112
-
113
- - gate green with every blocking finding fixed, not deferred
114
- - verification evidence present per the brief's Evidence resolution table (a CI claim
115
- or a green local run - a table-sanctioned CI skip is evidence, not missing;
116
- "not run" blocks only when the table required a fallback run that didn't happen)
117
- - `mergeable == MERGEABLE` (`UNKNOWN` after the one post-provision re-poll withholds
118
- merge, same as `CONFLICTING`)
119
- - no undispositioned failing check in the resolved set, no pending required check
120
- - evidence pasted with clean provenance
121
- - worktree clean and synced with the remote head (fixes pushed first)
122
- - explicit selection with a head compare-and-swap that passes
14
+ - PR number or URL; omitted -> resolved from the current branch per `verification-brief.md` Section A.
15
+ - Optional issue reference; omitted -> resolved in step 1 (`verification-brief.md` Section A) and fetched in step 2; none found -> judge the PR's stated intent only, never invent acceptance criteria.
123
16
 
124
- Define `<bin>` = `<directory of this skill's SKILL.md>/../../bin`. Merge execution
125
- per `reference/post-selection-loop.md` `### Merge course`.
17
+ ## Steps
126
18
 
127
- ## Report
19
+ Run every step inline; dispatch per `reference/assessment.md` when pi-cohort is present. Each step reads the sibling(s) its row names and produces exactly one output.
128
20
 
129
- The rendered report is terse by design: deciding factor, evidence lines, ID'd
130
- findings, menu. No restating diffs, no narration, no recap prose.
21
+ | Step | Read now | Output | Tracker stage |
22
+ |---|---|---|---|
23
+ | 1 Gather | `verification-brief.md` Section A | PR digest: metadata, diff, checks, comments, worktree discovery | `gather` |
24
+ | 2 Provision + configure | `reference/assessment.md` | provisioned worktree; config resolved from the merge-base; ticket fetched; AC rows extracted per `../brainstorming/reference/ticket-acceptance.md` | `provision` |
25
+ | 3 Verify | `verification-brief.md` Section B | evidence record (CI-first) and one disposition per material claim | `verify` |
26
+ | 4 Review | `verification-brief.md` Section C | reviewer findings and the internal comment ledger | `review` |
27
+ | 5 Integrate + report | `reference/findings.md`, then `reference/report.md` | AC outcomes, blockers, nits, drafted payloads, the rendered report | `report` |
28
+ | 6 Menu | `reference/decision-menu.md` | the menu under the verdict line, exactly one `[recommended]` | `menu` |
29
+ | 7 Loop | `reference/post-selection-loop.md` | the executed pick; re-entry until `merge` or `stop` | (re-opens the re-entered stage) |
131
30
 
132
- ```markdown
133
- ## Outcome
134
- <one line + the deciding factor>
31
+ Re-entry: a fix wave's own push re-enters step 4 after re-running step 3's claim check without a second verification pass (the wave's single pass already covered the pushed SHA); any other head move re-enters step 3; an unchanged head re-enters step 5.
135
32
 
136
- ## Evidence
137
- <CI path: satisfying check name(s)/conclusion/sha/url; local path: verbatim command + raw_tail per run; claims checked; resolved-set check dispositions>
138
-
139
- ## Findings (blocking)
140
- Blocking findings (P#):
141
- P1. **<source_ref>** - <defect>. Fix: <concrete change> | Action: <disposition/what unblocks>. [code | test | spec | security | performance | quality]
142
- Requirement/doc drift (linked issue, committed doc drift, or spec conflict):
143
- L1. <doc-drift | spec-conflict | outdated-AC | missing-behavior> -> <action>
144
-
145
- ## Comment-thread replies
146
- C1. <thread ref> -> <drafted reply> (already-addressed | reasonable | judgment-call)
147
- C2. <thread ref> -> <superseded by C<new> | withdrawn | pending <run url> | reviewer failed (<conclusion>) <run url>>
148
-
149
- ## Non-blocking follow-ups
150
- F1. **<source_ref>** - <action>. Owner: <pr-author | tracker | human>
151
-
152
- ## Decision
153
- <action vocabulary + numbered courses>
154
-
155
- ## Drafted fixes / review
156
- <payloads, each keyed by its finding ID>
157
- ```
158
-
159
- Consent table and courses per `reference/decision-menu.md`.
160
-
161
- ## Decide
162
-
163
- Render `## Decision` from the consent table for the PR's author and state. Read
164
- `reference/decision-menu.md` now.
165
-
166
- ## Act
167
-
168
- The menu is a state machine that loops until merge or an explicit stop. Read
169
- `reference/post-selection-loop.md` now.
33
+ ## Progress tracking
170
34
 
171
- ## Output done-check
35
+ Use `plan_tracker`, never `phase_tracker`. `init` with the first three stages of the table. In step 3 `add` one task per material claim and record each verdict: `complete` matched, `failed` contradicted, `skipped` unverifiable-pre-merge. Once every claim is terminal and `verify` is closed, `add` the remaining three stages - the tracker rejects a verdict recorded behind a still-pending stage. A failed stage or claim stays `failed` while the skill stops at the menu. Without a `plan_tracker` tool, keep a plain checklist; behavior is unchanged.
172
36
 
173
- Before posting or committing any externally persisted payload - review bodies,
174
- thread replies, commit subjects, tracker comments - re-read it against:
37
+ ## Wording rules
175
38
 
176
- - ASCII only: `-`, `...`, straight quotes.
177
- - No headings or template scaffolding on payloads under ~150 words - bullets and
178
- prose carry short content.
179
- - Review findings are file:line-specific where one exists, else keyed to the
180
- finding's `source_ref`, and end on the fix or asked action, not a recap.
181
- - Empty sections say "None"; never invent content to fill a section.
39
+ These bind every rendered report, menu, and external payload (review bodies, replies, commit subjects, tracker comments). A `## comms style` section in the overrides file extends them.
182
40
 
183
- The check governs external payloads only - the skill's own rendered report keeps
184
- its fixed headings regardless of length. Project rules extend this list via the
185
- overrides file - see Project overrides.
41
+ 1. One item is one or two whole sentences: what is wrong, then why it matters. No fragments, no field separators.
42
+ 2. Name the behavior, not the artifact: "retries forever" beats "attempts counter not incremented".
43
+ 3. Locators trail in parentheses (`file:line`, check name, doc path), never inside the sentence.
44
+ 4. No category tags, severity words, or IDs in prose - the section heading is the severity, the list number is the ID.
45
+ 5. Report only non-conformance; passing checks, covered ACs, and matched claims print only under `show evidence`.
46
+ 6. Omit empty sections.
47
+ 7. `Delivers` is always present and names which ACs this PR covers and which observable half is checked after merge.
48
+ 8. The verdict is one line in the fixed form.
49
+ 9. Menu rows start with a verb a human types, carry one clause of consequence, and exactly one row is `[recommended]`; compose grammar lives in the hint line only.
50
+ 10. ASCII only, American English, no hedges on checked facts, no intensifiers.
186
51
 
187
52
  ## Red flags - STOP
188
53
 
189
- - Approving your own PR - owner: `reference/decision-menu.md` `## Consent table`
190
- - Any mutation (fix, push, review, merge) without an explicit menu selection - owner: **Consent gate** (intro)
191
- - Pasting paraphrased evidence instead of verbatim `raw_tail` - owner: `reference/assessment.md` `## Phase 4 - Integrate`
192
- - A provenance mismatch (worktree, `run_cwd`, or `head_sha`) noticed and ignored - owner: `reference/assessment.md` `## Phase 4 - Integrate`
193
- - Merging around an undispositioned blocking finding or failing-check `P#` - owner: `reference/findings.md` `## Dispositions`
194
- - Reading configuration (rubric, verification command, or ladder sources) from the PR's head instead of the base branch's merge-base - owner: `## Configuration resolution`
195
- - Renumbering or reusing a finding ID between menu rounds - owner: `reference/findings.md` `## IDs`
196
- - Presenting findings without IDs, or a blocking verdict with no `P#`/`L#` - owner: `reference/findings.md` `## IDs`
197
- - A `## Decision` rendered without its action vocabulary - owner: `reference/decision-menu.md` `## Actions`
198
- - Treating `[quality]` or `[performance]` as a downgrade signal on a `P#` - only an explicit Phase-4 flaky disposition excepts a failing-check `P#` from the unfixed-blocker set, never a category tag - owner: `reference/findings.md` `## Triage`
199
- - A course (pre-composed or custom) bundling a push-producing action with `merge-*` - owner: `reference/decision-menu.md` `## Courses`
200
- - A pre-composed course, or a custom row, composing an action the overlay or the cell lists as unavailable - `merge-squash anyway` / `merge-commit anyway` on a reviewer-withheld merge is the sanctioned exception; GitHub-refused rows stay uncomposable - owner: `reference/decision-menu.md` `## Fork overlay`, `## Pending-reviewer overlay`
201
- - Batching a file-less `P#` (a claim or a gate command as `source_ref`, no draft touching a file) into a parallel dispatch - a claim `P#` with a drafted file edit is worktree-fixable and batches - dispatching parallel implementers over batches that share a file, or letting a fix-wave child run git commands or a verification pass in the shared worktree, or dispatching a fix-wave child with `worktree: true` - owner: `reference/post-selection-loop.md` `### Fix wave`
202
- - A second execution of the verification command, a second push, or pushing fix commits after a red gate, within one fix wave - re-running Verify/Review to re-confirm claims and annotate IDs is not a second gate execution - owner: `reference/post-selection-loop.md` `### Fix wave`
203
- - Posting or committing an external payload without the output done-check - owner: `## Output done-check`
54
+ - Any mutation (fix, push, review, comment, merge, tracker write) without an explicit menu pick - owner: the intro.
55
+ - A code or doc edit sitting in the worktree when a menu renders - owner: `reference/findings.md` `## Drafted payloads`.
56
+ - Blocking on an AC's observation half, or on a PR-body claim the gate cannot check - owner: `reference/findings.md` `## AC outcomes`.
57
+ - `impossible` without all four conditions and a source read this run - owner: `reference/findings.md` `## AC outcomes`.
58
+ - Deferring behavior the ticket promises to a later PR: it is a blocker or an explicit tracker split, nothing else - owner: `reference/findings.md` `## Namespaces`.
59
+ - Reading the rubric, the verification command, or any ladder source from the PR's head instead of the base branch's merge-base - owner: `reference/assessment.md` `## Configuration`.
60
+ - Raw command output, drafted payloads, or internal IDs in the rendered report - owner: `reference/report.md`.
61
+ - An open-PR menu without `fix` (a merged or closed PR offers `show evidence` and `stop` only), without `show evidence`, with two `[recommended]`, or with `stop` not last - owner: `reference/decision-menu.md`.
62
+ - A second verification pass or a second push inside one fix wave - owner: `reference/post-selection-loop.md` `### Fix wave`.
63
+ - Approving your own PR - owner: `reference/decision-menu.md` `## Consent table`.
64
+ - Merging around an undispositioned failing check or a pending required check - owner: `reference/findings.md` `## Dispositions`.
65
+ - A claim verdict recorded behind a pending tracker stage - owner: `## Progress tracking`.
204
66
 
205
67
  ## Project overrides
206
68
 
207
- If a gauntlet overrides file exists - checked in order: `.pi/gauntlet-overrides.md`, `<repo root>/gauntlet-overrides.md`, `<repo root>/doc/gauntlet-overrides.md`; first found wins - read it. Read and apply `## conventions` whenever present, without a relevance judgment. Give this skill's named section precedence over conflicting `## conventions` rules. Use other relevant sections - by name match, by topic (routing, verification, worktrees, etc.), or by workflow convention - to override or extend the instructions above. Project-local `AGENTS.md` is already in context - check it for project-specific routing tables, service paths, and verification commands. A `## comms style` section in the overrides file extends the output done-check with project rules.
69
+ If a gauntlet overrides file exists - checked in order: `.pi/gauntlet-overrides.md`, `<repo root>/gauntlet-overrides.md`, `<repo root>/doc/gauntlet-overrides.md`; first found wins - read it. Read and apply `## conventions` whenever present, without a relevance judgment. Give this skill's named section precedence over conflicting `## conventions` rules. Use other relevant sections - by name match, by topic (routing, verification, worktrees, etc.), or by workflow convention - to override or extend the instructions above. Project-local `AGENTS.md` is already in context - check it for project-specific routing tables, service paths, and verification commands. `## PR gate` keys are read in step 2 (`reference/assessment.md`); `## comms style` extends the wording rules.