pi-gauntlet 4.12.2 → 4.13.1
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 +9 -0
- package/README.md +107 -2
- package/package.json +1 -1
- package/skills/gatekeep-pr/SKILL.md +271 -29
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v4.13.1 - 2026-08-20
|
|
4
|
+
|
|
5
|
+
- `gatekeep-pr`: dense output protocol - stable append-only finding IDs (`P#` blocking fixes, `L#` requirement/doc drift, `C#` verdict-neutral thread replies, `F#` owned follow-ups), bare-verb action vocabulary with selection grammar (`all`, ranges, exclusions), normative per-cell course table (one `[recommended]`, custom last, push and merge never bundled), fix-wave execution (file-disjoint batches, parallel edit-only implementers, one gate/re-review/push per wave), output done-check for external payloads with a `## comms style` overrides hook.
|
|
6
|
+
|
|
7
|
+
## v4.13.0 - 2026-08-20
|
|
8
|
+
|
|
9
|
+
- Claude Code plugin marketplace (gh-11): new `.claude-plugin/marketplace.json` exposes exactly three tracker-facing skills (`shape-ticket`, `gatekeep-pr`, `check-delivery`) to Claude Code in place - plugin `gauntlet`, marketplace `pi-gauntlet`, consumer setting `"enabledPlugins": {"gauntlet@pi-gauntlet": true}`. Exclusivity rests on `source: "./"` + `strict: false` + specific subdir paths; `"agents": []` suppresses the default `agents/` scan so pi personas never register as CC agents. Zero skill-body edits; the directory is excluded from the npm tarball and never read by pi.
|
|
10
|
+
- `scripts/ci.mjs`: new marketplace guard - identity pins (`gauntlet`@`pi-gauntlet`), source/strict/agents assertions, scan-leak entry ban, allowlist path + frontmatter existence checks, bundle-local `.md` reference integrity for allowlisted skills, and a negative npm-pack assertion for `.claude-plugin/`.
|
|
11
|
+
- README: new "Use from Claude Code" section - consumer settings snippet, register/install/enable distinction, `CLAUDE.md` symlink advice, folder-trust gotcha, and an 11-step smoke-test cookbook.
|
|
3
12
|
## v4.12.2 - 2026-08-19
|
|
4
13
|
|
|
5
14
|
- New `skills/shape-ticket/reference/split-axes.md`: the shared split test for tickets and specs - identity test (same precipitating failure / mooted outcome = one concern), user-observable outcome test, closed axis list with pass/fail examples, Never-axis list (fix location, service/repo/layer/team, "keep tickets small"), discovery-conversion exemption, fail-closed release-timing precondition gated on a documented `## Deployment` overrides section.
|
package/README.md
CHANGED
|
@@ -69,7 +69,7 @@ Everything between gate 1 and gate 2 - task breakdown, implementation, both revi
|
|
|
69
69
|
|
|
70
70
|
pi-gauntlet ships three kinds of pieces, layered on top of pi-cohort's dispatch:
|
|
71
71
|
|
|
72
|
-
- **16 skills** - the workflow logic. Thirteen activate automatically when pi sees the matching kind of task, and each one gates the next: `brainstorming`, `writing-plans`, `roasting-the-spec`, `test-driven-development`, `subagent-driven-development`, `dispatching-parallel-agents`, `verification-before-completion`, `systematic-debugging`, `requesting-code-review`, `receiving-code-review`, `using-git-worktrees`, `finishing-a-development-branch`, `writing-skills`. Three more are explicit-invocation-only (`disable-model-invocation: true`): `shape-ticket` creates or repairs one tracker issue per run against a Context/Problem/Idea/Acceptance-Criteria template, gated by an AC integrity check, a cheap council roast, and a single human-confirmed write - run it with `/skill:shape-ticket`. `gatekeep-pr` is consent-gated pre-merge verification of a PR against its issue - read-only gathering, running the project's verification command, a rubric-based review, then a deterministic authorship-aware menu; nothing mutates (fixes, pushes, reviews, merges) until you pick a row - run it with `/skill:gatekeep-pr <pr>`. `check-delivery` is a post-merge detective control: proves an issue actually shipped (default-branch landing, delivery target, per-AC evidence) before its tracker status advances; it never writes a terminal status - run it with `/skill:check-delivery <ref>`.
|
|
72
|
+
- **16 skills** - the workflow logic. Thirteen activate automatically when pi sees the matching kind of task, and each one gates the next: `brainstorming`, `writing-plans`, `roasting-the-spec`, `test-driven-development`, `subagent-driven-development`, `dispatching-parallel-agents`, `verification-before-completion`, `systematic-debugging`, `requesting-code-review`, `receiving-code-review`, `using-git-worktrees`, `finishing-a-development-branch`, `writing-skills`. Three more are explicit-invocation-only (`disable-model-invocation: true`): `shape-ticket` creates or repairs one tracker issue per run against a Context/Problem/Idea/Acceptance-Criteria template, gated by an AC integrity check, a cheap council roast, and a single human-confirmed write - run it with `/skill:shape-ticket`. `gatekeep-pr` is consent-gated pre-merge verification of a PR against its issue - read-only gathering, running the project's verification command, a rubric-based review, then a deterministic authorship-aware menu with stable finding IDs (P#/L#/C#/F#) and numbered pre-composed courses (fixes execute as a single parallel-safe wave: one gate run, one re-review, one push); nothing mutates (fixes, pushes, reviews, merges) until you pick a row - run it with `/skill:gatekeep-pr <pr>`. `check-delivery` is a post-merge detective control: proves an issue actually shipped (default-branch landing, delivery target, per-AC evidence) before its tracker status advances; it never writes a terminal status - run it with `/skill:check-delivery <ref>`.
|
|
73
73
|
- **7 subagent personas** - the specialized child agents the skills dispatch via pi-cohort: `implementer`, `code-reviewer`, `spec-reviewer`, `conformance-reviewer`, `spec-summarizer`, `spec-council-member`, `spec-council-synthesizer`. See [doc/personas.md](./doc/personas.md) for what each one does and why its permissions are scoped the way they are.
|
|
74
74
|
- **3 runtime extensions** - the enforcement layer. `plan-tracker` and `phase-tracker` are tools skills call to track progress (with a TUI widget); `verify-before-ship` is a hook that warns if you push or open a PR without a passing test run since your last edit; a phase-tracker flow guard reminds on implement-phase commits missing spec/code review. See [doc/configuration.md](./doc/configuration.md) for the settings each one reads.
|
|
75
75
|
|
|
@@ -124,6 +124,109 @@ cd ~/path/to/your/repo && pi install -l ~/repos/pi-gauntlet
|
|
|
124
124
|
cd ~/repos/pi-gauntlet && npm run link-agents # local-path installs skip npm install; run this once
|
|
125
125
|
```
|
|
126
126
|
|
|
127
|
+
## Use from Claude Code
|
|
128
|
+
|
|
129
|
+
Three skills are exposed to Claude Code via the plugin marketplace at
|
|
130
|
+
`.claude-plugin/marketplace.json`: **shape-ticket**, **gatekeep-pr**, and
|
|
131
|
+
**check-delivery**. They are harness-portable by design - every pi-specific
|
|
132
|
+
mechanic they touch (`plan_tracker`, `gauntlet_setting`, `subagent()`) carries
|
|
133
|
+
an inline fallback, so they run on Claude Code's native facilities. This is the
|
|
134
|
+
supported set. Not exposed, in two classes: (a) genuinely pi-bound surface -
|
|
135
|
+
the full gated pipeline (brainstorming -> writing-plans ->
|
|
136
|
+
subagent-driven-development -> verify -> finish), the spec council, the
|
|
137
|
+
conformance gate, flow guards, verify-before-ship, and all `piGauntlet.*`
|
|
138
|
+
settings, which depend on pi extensions; (b) runtime-neutral skills
|
|
139
|
+
(e.g. `systematic-debugging`, `receiving-code-review`, `using-git-worktrees`) that
|
|
140
|
+
are simply out of scope for this channel, not incompatible - re-adding one is a
|
|
141
|
+
one-line allowlist append. For Claude-Code-native equivalents of the
|
|
142
|
+
methodology skills, see [obra/superpowers](https://github.com/obra/superpowers).
|
|
143
|
+
|
|
144
|
+
### Setup
|
|
145
|
+
|
|
146
|
+
Add to your repo's `.claude/settings.json`:
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{
|
|
150
|
+
"extraKnownMarketplaces": {
|
|
151
|
+
"pi-gauntlet": {
|
|
152
|
+
"source": { "source": "github", "repo": "jjuraszek/pi-gauntlet" }
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
"enabledPlugins": { "gauntlet@pi-gauntlet": true }
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Add `"ref": "vX.Y.Z"` to the source object to pin a tag; the default tracks the
|
|
160
|
+
default branch. Claude Code merges settings entries whole (no field-level
|
|
161
|
+
merge), so teams layering managed settings must carry the full objects.
|
|
162
|
+
|
|
163
|
+
Registration, installation, and enablement are distinct steps in Claude Code:
|
|
164
|
+
`extraKnownMarketplaces` registers the marketplace, `enabledPlugins` records
|
|
165
|
+
enablement intent. If a fresh machine shows the plugin as known but not
|
|
166
|
+
installed, run `/plugin install gauntlet@pi-gauntlet` once. Alternative path
|
|
167
|
+
without touching settings.json: `/plugin marketplace add jjuraszek/pi-gauntlet`,
|
|
168
|
+
then install.
|
|
169
|
+
|
|
170
|
+
Invocation: `/gauntlet:shape-ticket` (or bare `/shape-ticket` when unambiguous).
|
|
171
|
+
|
|
172
|
+
Project instructions: Claude Code reads `CLAUDE.md`, pi reads `AGENTS.md` - a
|
|
173
|
+
symlink keeps one source of truth: `ln -s AGENTS.md CLAUDE.md`. The gauntlet
|
|
174
|
+
overrides ladder (`.pi/gauntlet-overrides.md` -> `gauntlet-overrides.md` ->
|
|
175
|
+
`doc/gauntlet-overrides.md`) works unchanged on Claude Code - it is a plain
|
|
176
|
+
file read.
|
|
177
|
+
|
|
178
|
+
**Trust gotcha:** the marketplace auto-activates only after you trust *that
|
|
179
|
+
exact repo folder* in interactive Claude Code. Trusting a parent folder,
|
|
180
|
+
`claude -p`, or SDK runs in untrusted folders silently skip
|
|
181
|
+
`extraKnownMarketplaces` with no error.
|
|
182
|
+
|
|
183
|
+
### Smoke test
|
|
184
|
+
|
|
185
|
+
1. Create a scratch repo and add the marketplace config:
|
|
186
|
+
|
|
187
|
+
mkdir -p /tmp/cc-smoke/.claude && cd /tmp/cc-smoke && git init
|
|
188
|
+
cat > .claude/settings.json <<'EOF'
|
|
189
|
+
{
|
|
190
|
+
"extraKnownMarketplaces": {
|
|
191
|
+
"pi-gauntlet": {
|
|
192
|
+
"source": { "source": "github", "repo": "jjuraszek/pi-gauntlet" }
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
"enabledPlugins": { "gauntlet@pi-gauntlet": true }
|
|
196
|
+
}
|
|
197
|
+
EOF
|
|
198
|
+
|
|
199
|
+
2. Start Claude Code interactively in that directory: `claude`
|
|
200
|
+
3. When prompted, trust the folder (this exact folder - trust is what activates
|
|
201
|
+
the marketplace; there is no separate marketplace prompt).
|
|
202
|
+
4. Run `/plugin` and confirm: marketplace `pi-gauntlet` is listed, plugin
|
|
203
|
+
`gauntlet` is enabled. If it shows as known but not installed, run
|
|
204
|
+
`/plugin install gauntlet@pi-gauntlet` and re-check.
|
|
205
|
+
5. Confirm exactly three skills are registered under the plugin (via the
|
|
206
|
+
`/plugin` details view): shape-ticket, gatekeep-pr, check-delivery.
|
|
207
|
+
6. Invoke `/gauntlet:shape-ticket` with a deliberately two-concern ask (e.g.
|
|
208
|
+
"shape a ticket: CSV import for operators, plus a partner-facing status
|
|
209
|
+
API") so the skill deterministically consults its
|
|
210
|
+
`reference/split-axes.md` before proposing a split. Expected: skill
|
|
211
|
+
activates, reads the reference file, reaches its tracker capability ladder
|
|
212
|
+
without erroring on missing pi tools. Stop at the first human gate; write
|
|
213
|
+
nothing to any tracker.
|
|
214
|
+
7. Invoke `/gauntlet:gatekeep-pr` in the scratch repo (which has no PR).
|
|
215
|
+
Expected: the skill activates and stops at its configuration/verification
|
|
216
|
+
ladder reporting nothing to gate - no error about missing pi tools, no
|
|
217
|
+
mutation.
|
|
218
|
+
8. Invoke `/gauntlet:check-delivery` with no deliverable reference. Expected:
|
|
219
|
+
the skill activates and asks for / reports a missing deliverable set - a
|
|
220
|
+
reported skip, not a pass, and no pi-tool error.
|
|
221
|
+
9. Negative check: type `/gauntlet:brainstorming`. Expected: no such skill -
|
|
222
|
+
the allowlist excluded it.
|
|
223
|
+
10. Optional validator pass: `claude plugin validate .` from a checkout of
|
|
224
|
+
pi-gauntlet (strict mode if available). Expected: no schema errors.
|
|
225
|
+
11. Agent check: type `@gauntlet:` in the mention typeahead (or open the
|
|
226
|
+
plugin's details). Expected: the plugin registers no agents - `"agents": []`
|
|
227
|
+
in the marketplace entry suppresses the default `agents/` scan of the
|
|
228
|
+
repo's pi personas.
|
|
229
|
+
|
|
127
230
|
## Project-specific overrides
|
|
128
231
|
|
|
129
232
|
The skills shipped here are generic on purpose - they describe *how* to TDD, brainstorm, debug, request review, etc., without naming your services, your CI command, or your worktree wrapper. When you need that level of detail, drop a file at `.pi/gauntlet-overrides.md` in your repo. The skills read it at runtime and merge sections that match the skill's name or topic:
|
|
@@ -259,7 +362,9 @@ customization lives in two places, never in the wrapper itself:
|
|
|
259
362
|
|
|
260
363
|
An existing `## verification-before-completion` overrides section is an accepted
|
|
261
364
|
equivalent source for the verification command only; all other PR-gate keys
|
|
262
|
-
still live under `## PR gate`.
|
|
365
|
+
still live under `## PR gate`. A `## comms style` section in the same overrides
|
|
366
|
+
file extends gatekeep-pr's output done-check (rules applied to review bodies,
|
|
367
|
+
replies, tracker comments, and commit subjects before posting).
|
|
263
368
|
|
|
264
369
|
Anything a wrapper skill contains beyond trigger phrases is misplaced - move it to
|
|
265
370
|
`REVIEW.md` or the overrides file instead.
|
package/package.json
CHANGED
|
@@ -165,10 +165,18 @@ verification command may write to the tree while the Reviewer reads it):
|
|
|
165
165
|
claim is a blocking finding. An `unverifiable-pre-merge` claim used as merge proof
|
|
166
166
|
(appears in the PR body's evidence/result/test-plan content) is blocking; stated as
|
|
167
167
|
an explicit post-merge observation instead, it is a non-blocking follow-up.
|
|
168
|
-
- **Required CI checks:** a failing
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
168
|
+
- **Required CI checks:** a failing **required** status check withholds merge from
|
|
169
|
+
every pre-composed course until the user explicitly dispositions it - flaky
|
|
170
|
+
(proceed via the custom row) or real (it blocks); it mints a `P#`. A **pending**
|
|
171
|
+
required check (still running - the normal case, not a defect) is **wait-until-
|
|
172
|
+
green, not dispositionable**: it mints no `P#`, is never flaky/real-dispositioned,
|
|
173
|
+
and the withhold auto-lifts the moment it turns green - or, if it instead fails,
|
|
174
|
+
converts into an undispositioned failing check with its own `P#` at that point.
|
|
175
|
+
While pending, the report notes it under Evidence and every merge course simply
|
|
176
|
+
does not render (a pending-only PR is not a blocking verdict - findings groups can
|
|
177
|
+
all read "None" - the recommended course falls to `stop` or `review-comment`,
|
|
178
|
+
never a merge course, until it resolves). Non-required checks are informational,
|
|
179
|
+
listed in Evidence only.
|
|
172
180
|
- **Doc drift:** when the review finds committed doc drift as a **blocking** finding,
|
|
173
181
|
the orchestrator applies the doc fixes itself, in the provisioned worktree (created
|
|
174
182
|
or reused), as part of assessment - real edits, uncommitted, worktree-local. The
|
|
@@ -208,8 +216,8 @@ issue is linked, committed doc drift, anything the merged rubric maps to blockin
|
|
|
208
216
|
|
|
209
217
|
**Merge preconditions** (all must hold): gate green with every blocking finding fixed,
|
|
210
218
|
not deferred; `mergeable == MERGEABLE` (`UNKNOWN` after the one post-provision
|
|
211
|
-
re-poll withholds merge, same as `CONFLICTING`); no undispositioned failing
|
|
212
|
-
check; evidence pasted with clean provenance; worktree clean and synced with the remote
|
|
219
|
+
re-poll withholds merge, same as `CONFLICTING`); no undispositioned failing or
|
|
220
|
+
pending required check; evidence pasted with clean provenance; worktree clean and synced with the remote
|
|
213
221
|
head (fixes pushed first); explicit selection with a head compare-and-swap that
|
|
214
222
|
passes. A merge selection while any precondition fails is refused, naming the failing
|
|
215
223
|
precondition, and the menu re-renders - never a dead end, never a silent merge. Merge
|
|
@@ -229,14 +237,17 @@ are never bundled into one selection.
|
|
|
229
237
|
| any | draft PR | assessment rows only; merge and approve rows absent until ready-for-review |
|
|
230
238
|
| any | merged / closed | report-only; no mutation rows |
|
|
231
239
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
240
|
+
The consent table above remains the single oracle for what may be offered; the
|
|
241
|
+
Decision rendering section defines how its rows render as actions and numbered
|
|
242
|
+
courses. Rows GitHub would refuse (branch protection, missing permissions,
|
|
243
|
+
`viewerPermission` too low) are listed as unavailable with the reason. Approving
|
|
244
|
+
your own PR is not offered. Nothing executes until explicit selection.
|
|
237
245
|
|
|
238
246
|
## Output
|
|
239
247
|
|
|
248
|
+
The rendered report is terse by design: deciding factor, evidence lines, ID'd
|
|
249
|
+
findings, menu. No restating diffs, no narration, no recap prose.
|
|
250
|
+
|
|
240
251
|
```markdown
|
|
241
252
|
## Outcome
|
|
242
253
|
<one line + the deciding factor>
|
|
@@ -245,21 +256,171 @@ Approving your own PR is not offered. Nothing executes until explicit selection.
|
|
|
245
256
|
<verbatim command + raw_tail per run; claims checked; CI rollup with required-check disposition>
|
|
246
257
|
|
|
247
258
|
## Findings (blocking)
|
|
248
|
-
|
|
259
|
+
Blocking findings (P#):
|
|
260
|
+
P1. **<source_ref>** - <defect>. Fix: <concrete change> | Action: <disposition/what unblocks>. [code | test | spec | security | performance | quality]
|
|
261
|
+
Requirement/doc drift (linked issue, committed doc drift, or spec conflict):
|
|
262
|
+
L1. <doc-drift | spec-conflict | outdated-AC | missing-behavior> -> <action>
|
|
263
|
+
|
|
264
|
+
## Comment-thread replies (existing discussion - verdict-neutral)
|
|
265
|
+
C1. <thread ref> -> <drafted reply> (already-addressed | reasonable | judgment-call)
|
|
249
266
|
|
|
250
267
|
## Non-blocking follow-ups
|
|
251
|
-
<
|
|
268
|
+
F1. **<source_ref>** - <action>. Owner: <pr-author | tracker | human>
|
|
252
269
|
|
|
253
270
|
## Decision
|
|
254
|
-
<
|
|
271
|
+
<action vocabulary + numbered courses - see Decision rendering>
|
|
255
272
|
|
|
256
273
|
## Drafted fixes / review
|
|
257
|
-
<
|
|
274
|
+
<payloads, each keyed by its finding ID>
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**ID rules:**
|
|
278
|
+
|
|
279
|
+
- `<source_ref>` is a `file:line` where one exists, else the disputed thing (a
|
|
280
|
+
quoted PR-body claim, a failing gate command, a required check name).
|
|
281
|
+
- **Precedence:** Phase 4 and the merged rubric decide blocking vs. follow-up (the
|
|
282
|
+
severity translation, AC coverage, claims, and required-check rules above); this
|
|
283
|
+
section only chooses **which namespace** (`P#` / `L#` / `F#`) renders that
|
|
284
|
+
decision. Category tags and the triage bar below never override an upstream
|
|
285
|
+
blocking classification - a Phase-4 Moderate is always blocking (`P#` or `L#`
|
|
286
|
+
per Total mapping), never demoted to `F#` by tag or by judgment call.
|
|
287
|
+
- **Total mapping:** every blocking element of the Verdict maps to a `P#` or `L#` -
|
|
288
|
+
a blocking verdict with "None" in both groups is a rendering bug. Concretely:
|
|
289
|
+
failed gate -> `P#` `[test]` referencing the gate command; contradicted or
|
|
290
|
+
merge-proof-unverifiable material claim -> `P#` `[spec]` referencing the claim;
|
|
291
|
+
scope creep with a linked issue -> `L#` `spec-conflict`; committed doc drift ->
|
|
292
|
+
`L#` `doc-drift`; `partial` AC coverage -> `L#` `outdated-AC`; `missing` AC
|
|
293
|
+
coverage -> `L#` `missing-behavior`. `L#` covers exactly the drift the Verdict
|
|
294
|
+
already blocks on (committed doc drift, AC coverage, spec conflict); it widens
|
|
295
|
+
nothing. Code-level spec bugs (the diff contradicts the spec) are `P#` `[spec]`;
|
|
296
|
+
requirement/doc mismatches (the spec or docs are stale relative to intent) are
|
|
297
|
+
`L#`.
|
|
298
|
+
- **Required checks close by disposition, not by fix:** an undispositioned failing
|
|
299
|
+
required check is `P#` `[test]` referencing the check name; it is never a target
|
|
300
|
+
of a worktree `fix`. The user's Phase-4 disposition annotates the same ID rather
|
|
301
|
+
than closing it outright: dispositioned **flaky** -> annotate
|
|
302
|
+
`(dispositioned: flaky)`; this annotation excepts the `P#` from the unfixed-blocker
|
|
303
|
+
set - it no longer counts against "every `P#` blocks" or the merge precondition
|
|
304
|
+
"every blocking finding fixed", and the merge path is Phase 4's explicit flaky
|
|
305
|
+
disposition via the custom row. Dispositioned **real** -> annotate
|
|
306
|
+
`(dispositioned: real)` and the `P#` keeps blocking until the check is green.
|
|
307
|
+
- **Severity is decided at triage, not by the category tag:** a finding lands in
|
|
308
|
+
`P#` only when it must be fixed before merge (correctness, security, material
|
|
309
|
+
performance trap, a convention the repo enforces); improvements that don't
|
|
310
|
+
change merge correctness are `F#`, whatever their category. `[quality]` on a
|
|
311
|
+
`P#` is a category, never a downgrade - every `P#` blocks. This triage bar governs
|
|
312
|
+
findings the orchestrator originates itself; it never re-triages a classification
|
|
313
|
+
Phase 4 already made (see Precedence above).
|
|
314
|
+
- `C#` replies are verdict-neutral drafts: they never block and never gate merge;
|
|
315
|
+
nothing posts until selected.
|
|
316
|
+
- `F#` items carry an owner so follow-ups don't evaporate; when no tracker tool
|
|
317
|
+
resolved, the report itself is their durable home.
|
|
318
|
+
- **IDs are append-only for the run's lifetime:** minted at first assessment,
|
|
319
|
+
never renumbered, never reused. A resolved finding keeps its ID annotated
|
|
320
|
+
`(fixed in <sha>)`; later rounds continue each namespace's sequence.
|
|
321
|
+
- Empty groups say "None".
|
|
322
|
+
|
|
323
|
+
"Drafted fixes / review" holds, per finding ID, the concrete edit (for `fix`), the
|
|
324
|
+
reviewed doc-drift edit (for `push-docs`, keyed to its `L#`), or the reply text
|
|
325
|
+
(for `reply`) - each keyed to its finding ID, one selection mapping 1:1 to its
|
|
326
|
+
payload. A posted review body is not itself a finding: it is composed at post time
|
|
327
|
+
from the ID'd `P#`/`L#` findings being addressed - one summary sentence, then the
|
|
328
|
+
numbered findings, ending on the fix or asked action - and occupies its own
|
|
329
|
+
non-finding slot of this section.
|
|
330
|
+
|
|
331
|
+
## Decision rendering
|
|
332
|
+
|
|
333
|
+
`## Decision` has two parts: the action vocabulary, then the numbered courses.
|
|
334
|
+
|
|
335
|
+
**Action vocabulary** (bare verbs; availability constraints inline):
|
|
336
|
+
|
|
337
|
+
```markdown
|
|
338
|
+
Actions (compose freely in the custom row):
|
|
339
|
+
fix <P#s|all> apply blocking fixes in worktree, re-run gate, push (in-repo PRs only)
|
|
340
|
+
push-docs push already-applied doc-drift edits (only when uncommitted
|
|
341
|
+
reviewed doc edits exist
|
|
342
|
+
in the worktree)
|
|
343
|
+
merge-squash | merge-commit (preconditions per Verdict;
|
|
344
|
+
never bundled with a push)
|
|
345
|
+
request-changes | review-comment | approve (approve: never own PR)
|
|
346
|
+
reply <C#s> post drafted thread replies
|
|
347
|
+
tracker <act> tracker action (only when a tracker tool resolved)
|
|
348
|
+
stop leave the PR as-is / report-only exit
|
|
258
349
|
```
|
|
259
350
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
351
|
+
A `+ tracker <act>` suffix is available on any mutation course when a tracker tool
|
|
352
|
+
resolved.
|
|
353
|
+
|
|
354
|
+
**Selection grammar:** ID sets accept `all`, ranges (`P1-P4`), comma lists
|
|
355
|
+
(`P1,P3`), and exclusions (`all but P2`).
|
|
356
|
+
|
|
357
|
+
**Numbered courses** - a normative rendering of the consent table (never a second
|
|
358
|
+
offer source): per author x state cell, exactly one `[recommended]` course first,
|
|
359
|
+
the custom row always last. Courses are **atomic across pushes**: no course,
|
|
360
|
+
pre-composed or custom, bundles a push-producing action (`fix`, `push-docs`) with
|
|
361
|
+
`merge-*`; after a fix wave the menu re-renders with merge as row 1.
|
|
362
|
+
|
|
363
|
+
| Author | State | Courses (first = `[recommended]`) |
|
|
364
|
+
|---|---|---|
|
|
365
|
+
| you | clean / follow-ups only | 1. merge-squash; 2. merge-commit; 3. stop; 4. review-comment (post no-blockers note) |
|
|
366
|
+
| you | blocking | 1. fix (worktree-fixable P#s only - `all` covers only those) [+ push-docs when uncommitted doc edits exist]; 2. push-docs (alone, when doc edits exist); 3. stop; 4. review-comment (post findings). When no P# is worktree-fixable (blocking is required-check-only or L#-only), course 1 (fix) is not rendered: push-docs becomes first when doc edits exist, else stop is first |
|
|
367
|
+
| you | blocking, post-fix re-render (gate green, preconditions hold) | 1. merge-squash; 2. merge-commit; 3. stop; 4. review-comment |
|
|
368
|
+
| someone else | clean / follow-ups only | 1. approve; 2. merge-squash (offered-unrecommended); 3. review-comment (no-blockers note) |
|
|
369
|
+
| someone else | blocking | 1. request-changes; 2. fix all (courtesy, their branch - omitted when nothing is worktree-fixable); 3. reply <C#s> (omitted when the `C#` group is None); 4. review-comment |
|
|
370
|
+
| bot author | any | someone-else's rows for the same state; review actions recommended |
|
|
371
|
+
| any | draft | 1. request-changes / review-comment / reply <C#s> (omit the reply course when the `C#` group is None) / stop - `[recommended]` follows the same authorship rule as the non-draft cells, **except** on your own draft PR `request-changes` is never recommended (you cannot request changes on your own PR any more than you can approve it); the fallback recommendation there is `review-comment` when findings exist, else `stop`. Custom present but cannot compose `merge-*`/`approve`/`fix`/`push-docs` until ready-for-review |
|
|
372
|
+
| any | merged / closed | 1. stop; report-only, no other mutation courses at all; Custom present but cannot compose `merge-*`/`approve`/`fix`/`push-docs`/`request-changes`/`review-comment`/`reply`/`tracker` - nothing remains actionable |
|
|
373
|
+
|
|
374
|
+
**Fork overlay:** the consent-table fork row renders as an overlay on the authorship
|
|
375
|
+
cells (push/merge/fix absent; approve also dropped when the viewer authored the PR) -
|
|
376
|
+
it is not a distinct authorship cell. It overlays whichever authorship row above
|
|
377
|
+
applies (you vs. someone else), removing `fix`, `push-docs`, and `merge-*` (never
|
|
378
|
+
available on a fork). When you authored the fork PR, `approve` is
|
|
379
|
+
also dropped (never offered on your own PR) - fork|you|clean renders
|
|
380
|
+
`review-comment`/`stop` only; fork|you|blocking renders
|
|
381
|
+
`request-changes`/`review-comment`/`stop` (the someone-else courtesy fix-on-their-
|
|
382
|
+
branch course is also absent, since it is your own PR). A fork PR authored by someone
|
|
383
|
+
else uses the someone-else cells above with `fix`/`push-docs`/`merge-*` removed.
|
|
384
|
+
|
|
385
|
+
**Required-check gate on merge courses:** an undispositioned failing **or pending**
|
|
386
|
+
required check withholds every pre-composed course containing `merge-*` (per the
|
|
387
|
+
Verdict merge preconditions) - none render, whatever the author/state cell says. A
|
|
388
|
+
pending check mints no `P#` and is wait-until-green, not dispositionable (see Phase
|
|
389
|
+
4); a failing one mints a `P#` and takes a disposition. A **flaky** disposition does
|
|
390
|
+
not restore merge to a pre-composed course; merge proceeds only via the custom row
|
|
391
|
+
naming the disposition explicitly. A **real** disposition, or an unresolved pending
|
|
392
|
+
check, keeps every merge course withheld until the check is green - a pending-only
|
|
393
|
+
render is not itself a blocking verdict (findings groups may all read "None"); the
|
|
394
|
+
recommended course falls to `stop` or `review-comment` in the meantime. This never
|
|
395
|
+
falls through to the clean cell's recommended `merge-squash` - a required-check
|
|
396
|
+
failure or pend means the PR is not in the clean state to begin with.
|
|
397
|
+
|
|
398
|
+
Rows a cell offers but GitHub would refuse (branch protection, missing permission)
|
|
399
|
+
render listed-but-unavailable with the reason. Zero mutation courses is a legal
|
|
400
|
+
render (merged/closed) - the menu still appears, carrying findings and `stop`.
|
|
401
|
+
|
|
402
|
+
Example render (golden fixture 1 - own PR, blocking findings including committed doc
|
|
403
|
+
drift, so uncommitted reviewed doc edits exist):
|
|
404
|
+
|
|
405
|
+
```markdown
|
|
406
|
+
Pick one:
|
|
407
|
+
1. fix all (P1-P10) + push-docs [recommended]
|
|
408
|
+
2. push-docs (docs only, hold code fixes)
|
|
409
|
+
3. stop (leave as-is)
|
|
410
|
+
4. review-comment (post findings, act later)
|
|
411
|
+
5. Custom - compose: e.g. "fix P1-P8,P10 + push-docs" or "reply C1 + tracker comment"
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
Golden fixture 2 - the post-fix re-render after course 1's gate re-run passes:
|
|
415
|
+
|
|
416
|
+
```markdown
|
|
417
|
+
Pick one:
|
|
418
|
+
1. merge-squash [recommended]
|
|
419
|
+
2. merge-commit
|
|
420
|
+
3. stop (leave as-is)
|
|
421
|
+
4. review-comment
|
|
422
|
+
5. Custom
|
|
423
|
+
```
|
|
263
424
|
|
|
264
425
|
## Post-selection loop
|
|
265
426
|
|
|
@@ -267,22 +428,83 @@ The menu is a state machine, not a one-shot report:
|
|
|
267
428
|
|
|
268
429
|
1. **Compare-and-swap before every external write:** re-fetch `headRefOid`, `state`,
|
|
269
430
|
`mergeable`. Any change since assessment invalidates the current state - re-sync
|
|
270
|
-
the worktree, re-run Phase 3, re-render the menu.
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
431
|
+
the worktree, re-run Phase 3, re-render the menu. **Exception:** a course's own
|
|
432
|
+
push updates the assessed head to the pushed SHA as part of that course's
|
|
433
|
+
execution - this self-inflicted head move does not invalidate the course; the
|
|
434
|
+
next CAS check runs against the new head on the next external write.
|
|
435
|
+
2. Execute only the selected course. **Fix wave** (`fix <set>`): first filter the
|
|
436
|
+
selected set to worktree-fixable `P#`s - drop any `P#` closed by disposition
|
|
437
|
+
(an undispositioned required-check failure is never a `fix` target; a **flaky**
|
|
438
|
+
disposition already excepts it) - and route file-less `P#`s (a claim or a gate
|
|
439
|
+
command as `source_ref`, no draft touching a file) to run inline/sequentially,
|
|
440
|
+
never as part of a parallel file-batch.
|
|
441
|
+
|
|
442
|
+
For the remaining worktree-fixable set, batch by the **union of files each
|
|
443
|
+
finding's drafted edit in `## Drafted fixes / review` touches** (fallback to
|
|
444
|
+
the `source_ref` file only when a finding has no draft) - findings whose
|
|
445
|
+
drafts share a file share a batch.
|
|
446
|
+
|
|
447
|
+
**Child contract (same for 1 batch or many):** children are `implementer`
|
|
448
|
+
dispatches - `subagent({ agent: "implementer", context: "fresh", cwd: <PR
|
|
449
|
+
worktree> })`, matching Inline-first execution's persona-naming style; this is
|
|
450
|
+
the pi-cohort optimization path, inline is always valid per that section. The
|
|
451
|
+
orchestrator owns commit, gate, and push - never a child. Every dispatched
|
|
452
|
+
child gets `cwd` = the PR worktree, **`worktree: true` forbidden** (a separate
|
|
453
|
+
isolated worktree breaks the shared-tree contract - see Inline-first
|
|
454
|
+
execution); is **edit-only, no git commands, no verification runs**; and its
|
|
455
|
+
task is that batch's `P#` lines **plus the drafted edit already keyed to each
|
|
456
|
+
ID** in `## Drafted fixes / review` - the child applies the consented payload,
|
|
457
|
+
it does not re-solve the finding. Below the cutoff (<= 2 worktree-fixable findings), the orchestrator
|
|
458
|
+
applies inline instead of dispatching - the no-cohort path stays available at
|
|
459
|
+
any batch count per Inline-first execution. Above the cutoff, when more than
|
|
460
|
+
one batch results, dispatch the batches' children **in parallel**, all under
|
|
461
|
+
the same contract.
|
|
462
|
+
|
|
463
|
+
Once every dispatched/inline batch returns, the orchestrator commits the golden
|
|
464
|
+
course as one local commit set - the code fixes plus any already-applied
|
|
465
|
+
reviewed doc edits selected alongside them (one commit, or one per batch
|
|
466
|
+
sequentially; subjects name the fixes) - then re-runs the gate **once**. **On
|
|
467
|
+
green**, push **once**; gate and push are per-wave invariants, never per-fix or
|
|
468
|
+
per-batch. **On red**, do not push: leave the commit(s) local, re-render with
|
|
469
|
+
the unresolved `P#`s still open, and warn that unpushed fix commits sit in the
|
|
470
|
+
worktree exactly like unpushed doc edits (see Teardown). Doc fixes (`push-docs`
|
|
471
|
+
alone) follow the same green-gate-then-push rule: stage + commit (subject names
|
|
472
|
+
what is documented), re-run the gate, push only on green. Reviews, replies, and
|
|
473
|
+
tracker actions -> `gh pr review` / `gh api` / the tracker tool, non-interactive,
|
|
474
|
+
with the drafted payload for the selected IDs.
|
|
475
|
+
3. After any mutation that can change readiness (fix wave pushed, docs pushed, PR
|
|
476
|
+
head moved), re-run the claim-check and Review on the synced worktree: claims
|
|
477
|
+
are re-checked against the new head and findings are re-rendered, but the
|
|
478
|
+
verification command itself is **not** re-executed here - step 2's gate run
|
|
479
|
+
already was the wave's one and only execution of it. Re-render the report:
|
|
480
|
+
each selected `P#`/`L#` confirmed resolved is annotated `(fixed in <sha>)`
|
|
481
|
+
under its original ID; unresolved ones stay open unchanged; new findings
|
|
482
|
+
continue the sequence. Merge, if now available, renders as row 1.
|
|
278
483
|
4. Loop until the user selects merge or an explicit stop/no-action row.
|
|
279
484
|
|
|
280
485
|
**Teardown:** merge success -> tear down the worktree, whether it was reused or
|
|
281
486
|
created (the sync precondition guarantees no local-only work is stranded, and the
|
|
282
487
|
branch is gone remotely). A non-merge stop: offer teardown of a **created** worktree
|
|
283
488
|
(never autonomous; warn if unpushed doc edits would be discarded); a **reused**
|
|
284
|
-
worktree is left as found - if unpushed doc edits
|
|
285
|
-
let the user choose
|
|
489
|
+
worktree is left as found - if unpushed doc edits **or unpushed fix commits from a
|
|
490
|
+
red-gate hold** remain in it, say so explicitly and let the user choose
|
|
491
|
+
leave-or-discard.
|
|
492
|
+
|
|
493
|
+
## Output done-check
|
|
494
|
+
|
|
495
|
+
Before posting or committing any externally persisted payload - review bodies,
|
|
496
|
+
thread replies, commit subjects, tracker comments - re-read it against:
|
|
497
|
+
|
|
498
|
+
- ASCII only: `-`, `...`, straight quotes.
|
|
499
|
+
- No headings or template scaffolding on payloads under ~150 words - bullets and
|
|
500
|
+
prose carry short content.
|
|
501
|
+
- Review findings are file:line-specific where one exists, else keyed to the
|
|
502
|
+
finding's `source_ref`, and end on the fix or asked action, not a recap.
|
|
503
|
+
- Empty sections say "None"; never invent content to fill a section.
|
|
504
|
+
|
|
505
|
+
The check governs external payloads only - the skill's own rendered report keeps
|
|
506
|
+
its fixed headings regardless of length. Project rules extend this list via the
|
|
507
|
+
overrides file - see Project overrides.
|
|
286
508
|
|
|
287
509
|
## Red flags - STOP
|
|
288
510
|
|
|
@@ -293,7 +515,27 @@ let the user choose leave-or-discard.
|
|
|
293
515
|
- Merging around an undispositioned blocking finding or required-check failure
|
|
294
516
|
- Reading configuration (rubric, verification command, or ladder sources) from the
|
|
295
517
|
PR's head instead of the base branch's merge-base
|
|
518
|
+
- Renumbering or reusing a finding ID between menu rounds
|
|
519
|
+
- Presenting findings without IDs, a blocking verdict with no `P#`/`L#`, or a
|
|
520
|
+
`## Decision` rendered without its action vocabulary
|
|
521
|
+
- Treating `[quality]` or `[performance]` as a downgrade signal on a `P#` - only
|
|
522
|
+
an explicit Phase-4 flaky disposition excepts a required-check `P#` from the
|
|
523
|
+
unfixed-blocker set, never a category tag
|
|
524
|
+
- A course (pre-composed or custom) bundling a push-producing action with
|
|
525
|
+
`merge-*`
|
|
526
|
+
- A pre-composed course, or a custom row, composing an action the overlay or the
|
|
527
|
+
cell lists as unavailable
|
|
528
|
+
- Batching a file-less `P#` (a claim or a gate command as `source_ref`, no draft touching a file)
|
|
529
|
+
into a parallel dispatch - a claim `P#` with a drafted file edit is
|
|
530
|
+
worktree-fixable and may batch - dispatching parallel implementers over
|
|
531
|
+
batches that share a file, or letting a fix-wave child run git commands or a
|
|
532
|
+
verification pass in the shared worktree, or dispatching a fix-wave child with
|
|
533
|
+
`worktree: true`
|
|
534
|
+
- A second execution of the verification command, a second push, or pushing fix
|
|
535
|
+
commits after a red gate, within one fix wave - re-running Verify/Review to
|
|
536
|
+
re-confirm claims and annotate IDs (step 3) is not a second gate execution
|
|
537
|
+
- Posting or committing an external payload without the output done-check
|
|
296
538
|
|
|
297
539
|
## Project overrides
|
|
298
540
|
|
|
299
|
-
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. Any sections relevant to this skill - by name match, by topic (routing, verification, worktrees, etc.), or by workflow convention - 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.
|
|
541
|
+
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. Any sections relevant to this skill - by name match, by topic (routing, verification, worktrees, etc.), or by workflow convention - 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.
|