pi-gauntlet 5.2.2 → 5.3.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,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v5.3.0 - 2026-09-04
|
|
4
|
+
|
|
5
|
+
- `chase-bug`: the real-bug verdict menu gains a fourth row, "Implement hotfix now", for small, evidenced, urgent fixes - a middle ceremony tier between the trivial carve-out and the full gauntlet. It hands off to the new companion `skills/chase-bug/hotfix.md`: dedicated `hotfix/<slug>` worktree, one implementer (TDD), one code review as the last mutation gate, an advisory conformance pass, then an unpushed squash commit on the default branch with guaranteed worktree/branch cleanup (or a PR when the pick says "as a PR"). Three safety invariants (no schema/persistence change, no public-contract change, one-commit rollback) gate the row's availability; three judgment predicates steer `[recommended]`. Triage itself stays read-only; the row is reachable only through the verdict menu. Zero changes to finishing, SDD, verification, extensions, or ci.mjs. Spec: `doc/specs/2026-09-03-chase-bug-hotfix.md`.
|
|
6
|
+
|
|
7
|
+
## v5.2.3 - 2026-09-01
|
|
8
|
+
|
|
9
|
+
- Isolated `subagent` dispatch examples now mint an OS-temp report directory and use absolute `output:` paths, preventing reports from being captured in and deleted with throwaway worktrees. The parallel-dispatch Output capture guidance now distinguishes that isolated failure mode from non-isolated shared-working-tree commit/overwrite risk. Fixes #23. Spec: `doc/specs/2026-09-01-gh-23-absolute-report-paths.md`.
|
|
10
|
+
|
|
3
11
|
## v5.2.2 - 2026-09-01
|
|
4
12
|
|
|
5
13
|
- `linear` skill: the once-per-session `linearis issues usage` sweep no longer requires authentication. `usage` prints local help and makes no API call, so gating it on `auth status` skipped the cheap staleness check exactly when the agent was already degraded; it now runs whenever the binary is present. Also drops a dead "or the MCP path is in use" skip clause - the sweep sits inside the present-binary branch, and MCP is the fallback only when the binary is missing. Prose only, no code or config surface. Follow-up to #22; spec `doc/specs/2026-09-01-gh-22-linear-cli-verification.md` amended to match.
|
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ pi-gauntlet's only hard dependency is pi-cohort - every gate that dispatches a r
|
|
|
35
35
|
|
|
36
36
|
Concretely, one change through the gauntlet:
|
|
37
37
|
|
|
38
|
-
0. *(Optional)* Before there's even a spec, `/skill:shape-ticket` can create or repair a single tracker issue - shaping a raw ask into a Context/Problem/Idea/Acceptance Criteria ticket, gated by an AC integrity check, a cheap council roast, and one human-confirmed write that may include one optional gated Reporter-note comment. A failed roast is retried once, then surfaced inline at the gate if it fails again. It's a tool, not a phase: no worktree, no plan/phase tracker, runs from any repo state. It never activates on its own (`disable-model-invocation: true`) - invoke it explicitly. Similarly, `/skill:chase-bug` triages a raw bug report into an evidenced verdict - and can hand off to shape-ticket or
|
|
38
|
+
0. *(Optional)* Before there's even a spec, `/skill:shape-ticket` can create or repair a single tracker issue - shaping a raw ask into a Context/Problem/Idea/Acceptance Criteria ticket, gated by an AC integrity check, a cheap council roast, and one human-confirmed write that may include one optional gated Reporter-note comment. A failed roast is retried once, then surfaced inline at the gate if it fails again. It's a tool, not a phase: no worktree, no plan/phase tracker, runs from any repo state. It never activates on its own (`disable-model-invocation: true`) - invoke it explicitly. Similarly, `/skill:chase-bug` triages a raw bug report into an evidenced verdict - and can hand off to shape-ticket, brainstorming, or a bounded hotfix - before any spec exists.
|
|
39
39
|
1. You describe the change. **`brainstorming`** sets up an isolated worktree, explores the codebase, and turns your description into a written spec. A multi-model critique runs on it automatically. If the spec replaces a known prior spec, brainstorming marks the predecessor with a `> **Superseded by:**` banner under its title (default format, syntax overridable via `.pi/gauntlet-overrides.md`; event-driven only — gauntlet never sweeps historical specs). **You read and approve the spec - human gate 1.** No implementation code exists yet.
|
|
40
40
|
2. **`writing-plans`** decomposes the approved spec into atomic, independently-verifiable tasks, grouped into parallel waves where they don't touch the same files.
|
|
41
41
|
3. **`subagent-driven-development`** executes the plan one task at a time, each in a fresh subagent, behind spec-compliance review then code-quality review. TDD-locked: red, green, refactor.
|
|
@@ -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
|
-
- **17 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`, `requesting-code-review`, `receiving-code-review`, `using-git-worktrees`, `finishing-a-development-branch`, `writing-skills`, `linear` (reads/searches/comments on/manages Linear tickets via the `linearis` CLI; owns all linearis mechanics and the `## Issue tracker` overrides schema; tracker-facing skills route to it). Four 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, verification evidence resolved CI-first (green checks on the exact assessed head count as evidence; the project's verification command runs only as fallback), 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>`. `chase-bug` is human-only bug triage: read-only root-cause discovery to an evidenced verdict menu (real bug -> ticket/brainstorm/respond; five negative verdicts), then a gated response to the reporter for addressable origins (GitHub issue / tracker ticket) and a rendered verdict summary otherwise - it never fixes during triage - run it with `/skill:chase-bug`.
|
|
72
|
+
- **17 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`, `requesting-code-review`, `receiving-code-review`, `using-git-worktrees`, `finishing-a-development-branch`, `writing-skills`, `linear` (reads/searches/comments on/manages Linear tickets via the `linearis` CLI; owns all linearis mechanics and the `## Issue tracker` overrides schema; tracker-facing skills route to it). Four 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, verification evidence resolved CI-first (green checks on the exact assessed head count as evidence; the project's verification command runs only as fallback), 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>`. `chase-bug` is human-only bug triage: read-only root-cause discovery to an evidenced verdict menu (real bug -> ticket/brainstorm/hotfix/respond; five negative verdicts), then a gated response to the reporter for addressable origins (GitHub issue / tracker ticket) and a rendered verdict summary otherwise - it never fixes during triage; the hotfix row hands off to `skills/chase-bug/hotfix.md` after the menu - run it with `/skill:chase-bug`.
|
|
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. phase-tracker also registers plan_check, a deterministic plan linter (8 mechanical plan-vs-spec checks) whose pass stamp gates implement-start inside a gauntlet flow. See [doc/configuration.md](./doc/configuration.md) for the settings each one reads.
|
|
75
75
|
|
|
@@ -89,7 +89,7 @@ pi-gauntlet is **opinionated**: every non-trivial change is *meant* to ride this
|
|
|
89
89
|
|
|
90
90
|
**Use it** for any change with more than one moving part: a feature, a refactor across files, anything where "what did we actually agree to build" matters by the time it's done.
|
|
91
91
|
|
|
92
|
-
**Don't use it** for a one-line fix, a typo, or a throwaway spike you're going to discard. The gates have real overhead - a spec, a plan, a conformance check - and that overhead isn't worth paying for a change trivial enough to just make.
|
|
92
|
+
**Don't use it** for a one-line fix, a typo, or a throwaway spike you're going to discard. The gates have real overhead - a spec, a plan, a conformance check - and that overhead isn't worth paying for a change trivial enough to just make. Between that carve-out and the full pipeline sits one middle tier: `chase-bug`'s hotfix row - a small, evidenced, urgent fix landed as an unpushed squash, entered only through the triage verdict menu.
|
|
93
93
|
|
|
94
94
|
## Requirements
|
|
95
95
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: chase-bug
|
|
3
|
-
description: Use when a human hands you a bug report to triage - a Slack paste, tracker ticket, GitHub issue, or described symptom - and the goal is an evidenced verdict (real bug, not-a-bug, cannot reproduce, already fixed or reported)
|
|
3
|
+
description: Use when a human hands you a bug report to triage - a Slack paste, tracker ticket, GitHub issue, or described symptom - and the goal is an evidenced verdict (real bug, not-a-bug, cannot reproduce, already fixed or reported); triage itself never fixes - a real-bug verdict may hand off to a bounded hotfix after the menu.
|
|
4
4
|
disable-model-invocation: true
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -8,13 +8,16 @@ disable-model-invocation: true
|
|
|
8
8
|
|
|
9
9
|
## Overview
|
|
10
10
|
|
|
11
|
-
Triage a bug report to an evidenced verdict
|
|
11
|
+
Triage a bug report to an evidenced verdict. Triage never
|
|
12
|
+
fixes; a real-bug verdict may hand off to a bounded hotfix (hotfix.md) after
|
|
13
|
+
the menu.
|
|
12
14
|
|
|
13
15
|
## Boundaries
|
|
14
16
|
|
|
15
17
|
- Reads: anything - code, history, tracker, origin text.
|
|
16
18
|
- Writes: `$TMPDIR` scratch only (repro captures, notes), plus at most one gated push to the
|
|
17
|
-
origin's response channel at the very end
|
|
19
|
+
origin's response channel at the very end; after a valid hotfix pick: the hotfix
|
|
20
|
+
worktree and one default-branch squash commit, per hotfix.md.
|
|
18
21
|
- Does NOT: touch tracked files; touch tracker state (never closes, relabels, or
|
|
19
22
|
reassigns an existing issue).
|
|
20
23
|
- The zero-mutation invariant below mechanically enforces tracked-file immutability
|
|
@@ -25,7 +28,8 @@ Triage a bug report to an evidenced verdict, never a fix.
|
|
|
25
28
|
|
|
26
29
|
## Hard constraint
|
|
27
30
|
|
|
28
|
-
**No verdict without evidenced root cause; no fix
|
|
31
|
+
**No verdict without evidenced root cause; no fix during
|
|
32
|
+
triage. After a valid hotfix pick, writes follow hotfix.md.** (write surface: see
|
|
29
33
|
Boundaries; enforcement: see the zero-mutation invariant below.)
|
|
30
34
|
|
|
31
35
|
The invariant is baseline-relative, checked at three points. Never revert
|
|
@@ -41,17 +45,24 @@ pre-existing work - only ever revert damage this skill caused.
|
|
|
41
45
|
rendering the summary). Re-run the same command and confirm it still matches
|
|
42
46
|
the baseline.
|
|
43
47
|
|
|
48
|
+
**Handoff check** (hotfix row only). Immediately before handing off to
|
|
49
|
+
`hotfix.md`, run the same command on the primary checkout and require it to
|
|
50
|
+
match the baseline. Checkpoint 3 still runs at skill end, on the primary
|
|
51
|
+
checkout: a landed squash
|
|
52
|
+
commit and a restored branch leave tracked porcelain clean, so the invariant
|
|
53
|
+
holds literally on both exits.
|
|
54
|
+
|
|
44
55
|
## When to Use
|
|
45
56
|
|
|
46
57
|
- A human pastes a bug report (Slack message, tracker ticket, GitHub issue, plain
|
|
47
58
|
description of broken behavior) and wants to know whether it is real.
|
|
48
59
|
- The ask is "is this a bug" / "can we reproduce this" / "what's causing this",
|
|
49
60
|
not "fix this".
|
|
61
|
+
- An evidenced, urgent "fix this" request also enters
|
|
62
|
+
here - triage stops at the menu, where the hotfix row is offered.
|
|
50
63
|
|
|
51
64
|
## When NOT to Use
|
|
52
65
|
|
|
53
|
-
- The report already has an evidenced root cause and the ask is to implement a
|
|
54
|
-
fix - exit into `/skill:brainstorming` directly.
|
|
55
66
|
- The item is an already-shaped ticket ready for implementation, not a report
|
|
56
67
|
needing triage.
|
|
57
68
|
|
|
@@ -153,33 +164,64 @@ Render **only the matching action set** - never merge real-bug and negative-verd
|
|
|
153
164
|
menus into one list. The human may **overrule the verdict in prose** - that is a
|
|
154
165
|
change request, not a menu row.
|
|
155
166
|
|
|
156
|
-
**Real bug** -
|
|
157
|
-
`[recommended]
|
|
167
|
+
**Real bug** - four actions (all rendered unless noted), exactly one tagged
|
|
168
|
+
`[recommended]`. Untracked origin:
|
|
158
169
|
|
|
159
170
|
```
|
|
160
|
-
1. [ ] File a ticket -
|
|
161
|
-
with this evidence.
|
|
171
|
+
1. [ ] File a ticket - /skill:shape-ticket, seeded with this evidence.
|
|
162
172
|
2. [ ] Brainstorm now - /skill:brainstorming with this evidence as the seed.
|
|
163
|
-
|
|
173
|
+
3. [ ] Implement hotfix now - follow hotfix.md; add "as a PR" for a PR.
|
|
174
|
+
4. [ ] Respond to reporter only.
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Tracker/GitHub origin (ticket row omitted as today, renumbered):
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
1. [ ] Brainstorm now - /skill:brainstorming with this evidence as the seed.
|
|
181
|
+
2. [ ] Implement hotfix now - follow hotfix.md; add "as a PR" for a PR.
|
|
164
182
|
3. [ ] Respond to reporter only.
|
|
165
183
|
```
|
|
166
184
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
carries `[recommended]`.
|
|
185
|
+
Unaddressable variants adjust the last row's label exactly as today. Exactly
|
|
186
|
+
one `[recommended]` preserved. The eligibility line renders under the menu:
|
|
187
|
+
`eligible` or `not eligible: <predicate>`, from the predicate evaluation below.
|
|
171
188
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
189
|
+
For unaddressable origins, the last action reads `Finish with rendered summary`
|
|
190
|
+
instead of "Respond to reporter only", and the Brainstorm handoff happens after
|
|
191
|
+
the rendered summary instead of gate 2.
|
|
175
192
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
193
|
+
**Predicates and row availability.** Evaluate the six predicates in
|
|
194
|
+
`hotfix.md` once, here, from the root cause - a prediction of the fix shape
|
|
195
|
+
(read-only judgment). A failed safety invariant (1-3) renders the row as
|
|
196
|
+
`Implement hotfix now - unavailable: <invariant>`: never pickable, never
|
|
197
|
+
`[recommended]`; a pick of it is a change request. Judgment predicates (4-6)
|
|
198
|
+
only steer `[recommended]` and the eligibility line.
|
|
199
|
+
|
|
200
|
+
Heuristic for the `[recommended]` tag - rows top-down, first match wins:
|
|
201
|
+
|
|
202
|
+
| Situation | `[recommended]` |
|
|
203
|
+
|---|---|
|
|
204
|
+
| Pressing or trivially fixable, all predicates pass | Hotfix now |
|
|
205
|
+
| Pressing, any predicate fails | Brainstorm now |
|
|
206
|
+
| Trivially fixable, any predicate fails | Brainstorm now |
|
|
207
|
+
| Real but deferrable | File a ticket (tracker-origin: respond-only) |
|
|
208
|
+
| Blocked on another party | Respond-only |
|
|
209
|
+
|
|
210
|
+
Respond-only renders as "Finish with rendered summary" for unaddressable
|
|
211
|
+
origins. Root cause found but the fix cost is unclear still stays a
|
|
212
|
+
**real-bug** verdict - state the uncertainty plainly in the fault story, do
|
|
213
|
+
not downgrade the verdict to hedge on cost.
|
|
214
|
+
|
|
215
|
+
**Hotfix handoff.** On a hotfix pick, write the handoff record to
|
|
216
|
+
`$TMPDIR/hotfix-<slug>.md`: `delivery-mode` (`squash`, or `pr` when the pick
|
|
217
|
+
says "as a PR"); the evidence pack (fault story; trigger, observed, and
|
|
218
|
+
expected values from Phase 1; repro command; `file:line`; falsification
|
|
219
|
+
result); `slug` (kebab-case, from the symptom); origin type and response
|
|
220
|
+
target (step 1); the predicate evaluation. Run the handoff check (see the
|
|
221
|
+
zero-mutation invariant), then follow `hotfix.md`, which reads only this
|
|
222
|
+
record. On a hotfix abort, `hotfix.md` runs its baseline re-check and this
|
|
223
|
+
menu re-renders - the same gate, re-fired: with the hotfix row when the abort
|
|
224
|
+
created nothing, without it otherwise.
|
|
183
225
|
|
|
184
226
|
**Negative verdicts** - exactly five, each with its own named citation source:
|
|
185
227
|
|
|
@@ -236,6 +278,10 @@ any handoff:
|
|
|
236
278
|
response citing the new ticket link -> gate 2 -> done.
|
|
237
279
|
- Brainstorm now chosen -> draft the response first ("confirmed, investigating
|
|
238
280
|
now - fix to follow") -> gate 2 -> **then** hand off to `/skill:brainstorming`.
|
|
281
|
+
- Hotfix now chosen -> hand off to `hotfix.md` first; on completion, draft the
|
|
282
|
+
response citing `fixed in <SHA>` or the PR link -> gate 2 (`send it`) -> done.
|
|
283
|
+
Gate 2 fires once. On abort, `hotfix.md` returns to the step-4 menu; step 5
|
|
284
|
+
then runs for the new pick, the draft citing the abort reason.
|
|
239
285
|
- Respond-only, or any negative verdict -> draft -> gate 2 -> done.
|
|
240
286
|
|
|
241
287
|
**Draft template:**
|
|
@@ -298,6 +344,9 @@ action renders the verdict as a **summary to the human**, then the skill ends
|
|
|
298
344
|
link.
|
|
299
345
|
- Brainstorm now chosen -> render the summary -> **then** hand off to
|
|
300
346
|
`/skill:brainstorming`.
|
|
347
|
+
- Hotfix now chosen -> hand off to `hotfix.md`; on completion render the
|
|
348
|
+
summary citing `fixed in <SHA>` or the PR link -> done. On abort, return to
|
|
349
|
+
the step-4 menu.
|
|
301
350
|
- Finish with rendered summary chosen -> render the summary -> done.
|
|
302
351
|
|
|
303
352
|
**Summary template** (same four fields as the draft - the difference is
|
|
@@ -319,7 +368,7 @@ rendered is out of skill scope - the skill has ended.
|
|
|
319
368
|
|
|
320
369
|
| Verdict | Citation source | Response next-step |
|
|
321
370
|
|---|---|---|
|
|
322
|
-
| Real bug | Falsification test run + passed | Ticket link, fix branch, or ack |
|
|
371
|
+
| Real bug | Falsification test run + passed | Ticket link, squash SHA, fix branch, or ack |
|
|
323
372
|
| `not-a-bug` | Contract satisfied (spec/schema/API doc) | Explain the contract |
|
|
324
373
|
| `intended-behavior` | Decision record (design doc/ADR/commit) | Point to the decision |
|
|
325
374
|
| `cannot-replicate` | Phase 1 repro attempts, missing input named | Ask reporter for missing input; offer discovery ticket |
|
|
@@ -337,11 +386,14 @@ falls through to the 404 handler.
|
|
|
337
386
|
Proof: `curl /widgets/` -> 404 | src/router.ts:88 | expected match, got none
|
|
338
387
|
|
|
339
388
|
1. [ ] File a ticket - /skill:shape-ticket, seeded with the above.
|
|
340
|
-
2. [
|
|
341
|
-
3. [
|
|
389
|
+
2. [ ] Brainstorm now - /skill:brainstorming with the above as the seed.
|
|
390
|
+
3. [x] Implement hotfix now - follow hotfix.md; add "as a PR" for a PR. [recommended]
|
|
391
|
+
4. [ ] Respond to reporter only.
|
|
392
|
+
|
|
393
|
+
eligible - all predicates pass
|
|
342
394
|
```
|
|
343
395
|
|
|
344
|
-
(The example assumes an addressable origin - action
|
|
396
|
+
(The example assumes an addressable origin - action 4's label is the addressable one.)
|
|
345
397
|
|
|
346
398
|
**Negative-verdict example** (citation-source contrast):
|
|
347
399
|
|
|
@@ -361,7 +413,7 @@ nested resources" (the decision that made it so).
|
|
|
361
413
|
|
|
362
414
|
| Excuse | Reality |
|
|
363
415
|
|---|---|
|
|
364
|
-
| "Trivial fix, faster to just do it" | Fixing during triage is
|
|
416
|
+
| "Trivial fix, faster to just do it" | Fixing during triage is forbidden - the hotfix row after the menu is the sanctioned path |
|
|
365
417
|
| "Root cause is obvious, skip falsification" | Obvious and evidenced are different things - run the test or report it blocked |
|
|
366
418
|
| "Reporter is waiting, skip the gate" | The gate is what makes the response trustworthy - urgency is not a bypass |
|
|
367
419
|
| "I already know there's no prior report" | A guess isn't a search - use the ladder or declare it unreachable |
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# Hotfix (chase-bug supplementary)
|
|
2
|
+
|
|
3
|
+
Consumed only by `SKILL.md` in this directory, at the real-bug menu handoff. Input:
|
|
4
|
+
the handoff record at `$TMPDIR/hotfix-<slug>.md` - read nothing else about the bug.
|
|
5
|
+
Automatic end to end: the menu pick was the consent. The only human gate left is
|
|
6
|
+
chase-bug's `send it`, reached in step 10 below.
|
|
7
|
+
|
|
8
|
+
## Boundaries
|
|
9
|
+
|
|
10
|
+
- Reads: anything.
|
|
11
|
+
- Writes: the hotfix worktree; exactly one squash commit on `<default>`, made in the
|
|
12
|
+
primary checkout with a clean index, `<orig-branch>` restored after; `$TMPDIR`.
|
|
13
|
+
- Does NOT: run tests or create files in the primary checkout; push without an
|
|
14
|
+
explicit request; touch tracker state; commit on the source checkout during setup;
|
|
15
|
+
touch pre-existing dirt or any resource this run did not create.
|
|
16
|
+
|
|
17
|
+
## Ownership
|
|
18
|
+
|
|
19
|
+
Two flags, `created-worktree` and `created-branch`, set only when `git worktree add`
|
|
20
|
+
succeeds (it creates both). Every destructive command below is gated on its flag.
|
|
21
|
+
|
|
22
|
+
## Procedure
|
|
23
|
+
|
|
24
|
+
1. **Read the record; print the eligibility line.** Reprint the menu-time
|
|
25
|
+
evaluation verbatim: `eligible` or `not eligible: <predicate>`. Never
|
|
26
|
+
re-derive, never block.
|
|
27
|
+
2. **Resolve before mutating.** `SCOPED_TEST_COMMANDS`: the gauntlet overrides
|
|
28
|
+
file's verification section (`## verification-before-completion`, or a section
|
|
29
|
+
matching the verification topic), else `AGENTS.md` or the project's documented
|
|
30
|
+
test command. The full project test target is acceptable. Add the record's repro
|
|
31
|
+
command when present. No exact command -> abort (pre-land). Draft the implementer
|
|
32
|
+
task text from the record; not writable -> abort (pre-land). Nothing exists yet.
|
|
33
|
+
3. **Worktree.** From the primary checkout:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
PRIMARY_ROOT=$(git rev-parse --show-toplevel)
|
|
37
|
+
DEFAULT=$(git symbolic-ref --short refs/remotes/origin/HEAD) && DEFAULT=${DEFAULT#origin/}
|
|
38
|
+
BASE_SHA=$(git rev-parse "$DEFAULT")
|
|
39
|
+
ORIG_BRANCH=$(git branch --show-current)
|
|
40
|
+
git status --porcelain > "$TMPDIR/hotfix-<slug>.baseline"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Abort (pre-land, nothing created) when: `git rev-parse --git-dir` differs from
|
|
44
|
+
`git rev-parse --git-common-dir` (inside a linked worktree); `DEFAULT` empty
|
|
45
|
+
(never guess a squash target); `ORIG_BRANCH` empty (detached HEAD); `git status
|
|
46
|
+
--porcelain --untracked-files=no` non-empty; `git check-ignore -q .worktrees/`
|
|
47
|
+
fails (never commit on the source checkout); `git show-ref --verify -q
|
|
48
|
+
refs/heads/hotfix/<slug>` succeeds or `.worktrees/hotfix/<slug>` exists (never
|
|
49
|
+
reuse, never force); `git worktree add` itself failing (creation failure).
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
git worktree add ".worktrees/hotfix/<slug>" -b "hotfix/<slug>" "$DEFAULT"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Success sets both flags. Run the project's dependency install inside the
|
|
56
|
+
worktree. Every dispatch below: `cwd` = the worktree path, the record path in the
|
|
57
|
+
task text, `output:` (when used) an absolute `$TMPDIR` path.
|
|
58
|
+
4. **Implement.** One `implementer`, fork context:
|
|
59
|
+
|
|
60
|
+
> Read `$TMPDIR/hotfix-<slug>.md`; the evidence pack is also inlined here:
|
|
61
|
+
> <evidence pack>. The evidence pack replaces plan and spec; do
|
|
62
|
+
> not report BLOCKED for a missing plan. TDD: write the regression test, run it,
|
|
63
|
+
> confirm it fails, then the minimal fix (dependency-bump fallback: the repro
|
|
64
|
+
> re-run is the regression evidence). SCOPED_TEST_COMMANDS: <commands>. Commit on
|
|
65
|
+
> `hotfix/<slug>` before reporting. End with the SDD status line verbatim.
|
|
66
|
+
|
|
67
|
+
`DONE` -> step 5. `DONE_WITH_CONCERNS` -> step 5 unless a concern names a safety
|
|
68
|
+
invariant -> abort. `NEEDS_CONTEXT` or `BLOCKED` -> abort. A regression command
|
|
69
|
+
named in the report joins `SCOPED_TEST_COMMANDS` only if it uses the resolved
|
|
70
|
+
command's runner.
|
|
71
|
+
5. **Test.** Run `SCOPED_TEST_COMMANDS` in the worktree. Red -> one implementer
|
|
72
|
+
retry -> red -> abort.
|
|
73
|
+
6. **Verify (advisory).** One fresh `conformance-reviewer`. Its entire origin, in
|
|
74
|
+
the task text, located as `prompt`:
|
|
75
|
+
|
|
76
|
+
> R1: the trigger `<trigger>` now yields `<expected>` (was `<observed>`).
|
|
77
|
+
> R2: regression evidence exists (test or repro re-run).
|
|
78
|
+
> R3: the diff stays inside the envelope: files implementing the mechanism at
|
|
79
|
+
> the recorded `file:line`, the regression test, and (dependency exception)
|
|
80
|
+
> manifest + lockfile.
|
|
81
|
+
|
|
82
|
+
Parent filter: only rows located as `prompt` count; a row sourced from a spec
|
|
83
|
+
file or ticket is not-a-gap. Real gaps -> one implementer round -> re-run step
|
|
84
|
+
5 -> no second audit; unfixable -> abort. Dispatch failure or malformed output
|
|
85
|
+
-> note it, continue.
|
|
86
|
+
7. **Review - last mutation gate.** One fresh `code-reviewer` over
|
|
87
|
+
`<base-sha>..HEAD` in the worktree. Task text: the record path,
|
|
88
|
+
`SCOPED_TEST_COMMANDS`, invariants 1-3 and predicates 4-6 as named review items
|
|
89
|
+
(a predicate miss is Moderate unless it trips an invariant). `SHIP` -> step 8.
|
|
90
|
+
`FIX_FIRST` -> one implementer round fixing every Critical and Moderate ->
|
|
91
|
+
re-run step 5 -> one re-review; `SHIP` -> step 8, else abort. `REJECT` or any
|
|
92
|
+
invariant violation -> abort, no round. Dispatch failure or malformed output ->
|
|
93
|
+
one redispatch, then abort.
|
|
94
|
+
8. **Finish.** Branch on the record's `delivery-mode`: `squash` -> squash path;
|
|
95
|
+
`pr` -> PR path. Every command from `PRIMARY_ROOT`. Squash path, by state:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
cd "$PRIMARY_ROOT"
|
|
99
|
+
[ -z "$(git status --porcelain --untracked-files=no)" ] || land_abort
|
|
100
|
+
[ "$(git rev-parse "$DEFAULT")" = "$BASE_SHA" ] || land_abort # base moved: never touch <default>
|
|
101
|
+
git checkout "$DEFAULT" || land_abort # pre-squash ends here
|
|
102
|
+
git merge --squash "hotfix/<slug>" || { git reset --hard "$BASE_SHA"; land_abort; }
|
|
103
|
+
git diff --cached --quiet && { git reset --hard "$BASE_SHA"; land_abort; } # empty squash
|
|
104
|
+
git commit -m "fix: <slug>" -m "<fault story>" || { git reset --hard "$BASE_SHA"; land_abort; }
|
|
105
|
+
[ "$(git rev-parse HEAD^{tree})" = "$(git rev-parse "hotfix/<slug>^{tree}")" ] \
|
|
106
|
+
|| { git reset --hard "$BASE_SHA"; land_abort; } # proven; never reset after this line
|
|
107
|
+
SHA=$(git rev-parse HEAD)
|
|
108
|
+
[ "$ORIG_BRANCH" = "$DEFAULT" ] || git checkout "$ORIG_BRANCH" # failure: report, commit stays
|
|
109
|
+
git worktree remove --force ".worktrees/hotfix/<slug>" && git worktree prune \
|
|
110
|
+
&& git branch -D "hotfix/<slug>" # failure: keep commit, report residual
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
`git branch -D` is forced by construction: a squash commit never has the branch
|
|
114
|
+
tip as ancestor, so `-d` always refuses; the proven tree is the loss guard. The
|
|
115
|
+
commit stays **unpushed**. Report: `$SHA`; revert line `git checkout <default>
|
|
116
|
+
&& git reset --hard <base-sha>` (unpushed) or `git revert <sha>` (after any
|
|
117
|
+
push); `git status --porcelain` diff against the baseline (expected none); a
|
|
118
|
+
push nudge.
|
|
119
|
+
|
|
120
|
+
PR path, cwd = the worktree: `git push -u origin hotfix/<slug>` - failure ->
|
|
121
|
+
report branch + worktree path, no URL, preserve. `gh pr create --base <default>
|
|
122
|
+
--head hotfix/<slug>` - `gh` missing or failing after one retry -> report the
|
|
123
|
+
pushed branch and compare URL. Worktree and branch preserved; print the closing
|
|
124
|
+
line.
|
|
125
|
+
9. **Cleanup evidence.** Squash exit and pre-land aborts: `git worktree list`
|
|
126
|
+
without the hotfix entry; `git branch --list hotfix/<slug>` empty; porcelain
|
|
127
|
+
delta vs baseline none. PR exit and land-stage aborts: both present, plus
|
|
128
|
+
`git worktree remove --force .worktrees/hotfix/<slug> && git branch -D hotfix/<slug>`.
|
|
129
|
+
10. **Response.** chase-bug step 5 rules apply unchanged: addressable -> draft
|
|
130
|
+
citing `fixed in <SHA>` or the PR link -> `send it`; unaddressable -> summary.
|
|
131
|
+
Abort never reaches this step - it returns to the menu.
|
|
132
|
+
|
|
133
|
+
## Eligibility predicates
|
|
134
|
+
|
|
135
|
+
Evaluated once by `SKILL.md` at menu time from the root cause; re-checked against
|
|
136
|
+
the diff in step 7.
|
|
137
|
+
|
|
138
|
+
Safety invariants (row availability):
|
|
139
|
+
|
|
140
|
+
1. No schema, migration, or persistence change.
|
|
141
|
+
2. No public API, contract, or config-shape change.
|
|
142
|
+
3. Rollback is reverting one commit - no data or state side effects.
|
|
143
|
+
|
|
144
|
+
Judgment predicates (`[recommended]` only; Moderate review items):
|
|
145
|
+
|
|
146
|
+
4. Existing code only - new files limited to the regression test.
|
|
147
|
+
5. Dependencies unchanged, one exception: a patch/minor bump whose upstream issue or
|
|
148
|
+
changelog names the symptom, diff = manifest + lockfile, no call-site change.
|
|
149
|
+
Replacement, major/breaking upgrade, new dependency -> fails.
|
|
150
|
+
6. Regression evidence writable in the existing harness (bump fallback: the repro).
|
|
151
|
+
|
|
152
|
+
## Abort
|
|
153
|
+
|
|
154
|
+
Both classes end with the baseline re-check, then chase-bug step 4 re-renders.
|
|
155
|
+
|
|
156
|
+
**Pre-land** (steps 2-7): unresolvable commands or task text; setup precondition
|
|
157
|
+
unmet; `NEEDS_CONTEXT`/`BLOCKED` or a concern naming an invariant; red after retry;
|
|
158
|
+
unfixable conformance gap; review `REJECT`, invariant violation, or a non-`SHIP`
|
|
159
|
+
re-review.
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
[ "$created_worktree" = 1 ] && git worktree remove --force ".worktrees/hotfix/<slug>"
|
|
163
|
+
git worktree prune
|
|
164
|
+
[ "$created_branch" = 1 ] && git branch -D "hotfix/<slug>"
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Nothing else is touched. The re-rendered menu keeps the hotfix row when neither
|
|
168
|
+
flag was set, omits it otherwise.
|
|
169
|
+
|
|
170
|
+
**Land-stage** (step 8 before *proven*, after review `SHIP`): base moved, checkout failure, empty
|
|
171
|
+
squash, merge/commit failure, tree mismatch. `git reset --hard <base-sha>` only when
|
|
172
|
+
this run moved `<default>` (squash-applied or later) and `<default>` is checked
|
|
173
|
+
out (the step 8 lines do
|
|
174
|
+
exactly that); on base moved `<default>` is never touched and both SHAs are
|
|
175
|
+
reported. Restore `<orig-branch>`. Preserve worktree and branch (reviewed work).
|
|
176
|
+
Report path, tip SHA, closing line. The menu re-renders without the hotfix row.
|
|
177
|
+
|
|
178
|
+
**Baseline re-check**: `git status --porcelain --untracked-files=no` matches the
|
|
179
|
+
triage baseline; full porcelain delta reported; `<default>` == `<base-sha>` asserted
|
|
180
|
+
only when this run touched `<default>`. Pre-existing dirt is never touched.
|
|
181
|
+
|
|
182
|
+
## Harness fallback
|
|
183
|
+
|
|
184
|
+
No `subagent` tool and no personas (the Claude Code marketplace ships `agents: []`):
|
|
185
|
+
run the duties inline, same order. Write the failing regression test, confirm red,
|
|
186
|
+
minimal fix, confirm green, commit on `hotfix/<slug>`. Self-review the diff against
|
|
187
|
+
the record, invariants 1-3, predicates 4-6. Run `SCOPED_TEST_COMMANDS`. Apply the
|
|
188
|
+
abort classes as written. Finish and report per steps 8-9.
|
|
189
|
+
|
|
190
|
+
## Red Flags - STOP
|
|
191
|
+
|
|
192
|
+
- Any mutation before every step 3 precondition passes
|
|
193
|
+
- Reusing or force-replacing an existing `hotfix/<slug>` branch or path
|
|
194
|
+
- `git reset --hard` after *proven*, on `<orig-branch>`, or inside the worktree
|
|
195
|
+
- Re-running tests in the primary checkout
|
|
196
|
+
- Merging onto a moved base
|
|
197
|
+
- Landing a diff the last review did not see
|
|
198
|
+
- Pushing without an explicit request
|
|
@@ -183,7 +183,11 @@ Parallel dispatch rides on the `subagent` tool (the pi-cohort package). Mechanic
|
|
|
183
183
|
- **Filesystem isolation** — `worktree: true` runs each task in its own git worktree so concurrent edits can't collide. Requires clean git state; each task's diff returns separately for you to integrate. Omit it for read-only investigations.
|
|
184
184
|
- **Worktree base / `cwd`** — under `worktree: true` the base commit is `HEAD` resolved from the **top-level `cwd`**, which defaults to the orchestrator's process cwd. When you orchestrate from inside a git worktree, pass that worktree's absolute path as the top-level `cwd`, or children branch from the wrong checkout. Don't set per-task `cwd` with `worktree: true` — it must equal the shared cwd or the run errors.
|
|
185
185
|
- **Agent choice** — `worker` is the pi-cohort builtin generalist. Use a persona (`implementer`, `code-reviewer`) when you want its system prompt and tool profile. Persona frontmatter (tools, thinking, context) is fixed; only `model`, `task`, `output`, `reads`, `progress`, `skill` are callable per task.
|
|
186
|
-
- **Output capture**
|
|
186
|
+
- **Output capture** - `output: "<file>"` writes a task's summary to a file instead of inline; add `outputMode: "file-only"` for large results. When a batch uses `worktree: true`, each `output:` path must be absolute and outside every isolated checkout; a relative report is captured as helper work and then deleted with the checkout. In a non-isolated batch, a relative report lands in the shared working tree and risks being committed or overwritten by a later task.
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
REPORT_DIR=$(mktemp -d)
|
|
190
|
+
```
|
|
187
191
|
|
|
188
192
|
```ts
|
|
189
193
|
subagent({
|
|
@@ -191,9 +195,9 @@ subagent({
|
|
|
191
195
|
worktree: true, // isolate edits; omit for read-only investigations
|
|
192
196
|
concurrency: 3,
|
|
193
197
|
tasks: [
|
|
194
|
-
{ agent: "worker", task: "Fix + explain failures in src/a.test.ts", output: "a.md" },
|
|
195
|
-
{ agent: "worker", task: "Fix + explain failures in src/b.test.ts", output: "b.md" },
|
|
196
|
-
{ agent: "worker", task: "Fix + explain failures in src/c.test.ts", output: "c.md" },
|
|
198
|
+
{ agent: "worker", task: "Fix + explain failures in src/a.test.ts", output: "<REPORT_DIR>/a.md" },
|
|
199
|
+
{ agent: "worker", task: "Fix + explain failures in src/b.test.ts", output: "<REPORT_DIR>/b.md" },
|
|
200
|
+
{ agent: "worker", task: "Fix + explain failures in src/c.test.ts", output: "<REPORT_DIR>/c.md" },
|
|
197
201
|
],
|
|
198
202
|
})
|
|
199
203
|
```
|
|
@@ -185,6 +185,10 @@ Auto-selected at handoff by `writing-plans` (any wave with ≥2 tasks) when the
|
|
|
185
185
|
|
|
186
186
|
**Set `cwd` to your worktree — resilience-critical.** This whole workflow runs *inside* a worktree, but the `subagent` tool resolves the worktree base from the **top-level `cwd`**, which defaults to the orchestrator's process cwd — the *primary* checkout (usually `main`), not the worktree. Omit `cwd` and `worktree: true` branches every child from the primary checkout's HEAD: the children never see your spec, plan, or prior-wave commits, and integration runs against the wrong baseline. Pass the worktree's absolute path as the top-level `cwd`. Do **not** set per-task `cwd` under `worktree: true` — pi-cohort requires it to equal the shared cwd and errors otherwise. (Clean-tree is enforced here too — `resolveRepoState` rejects a dirty tree — which is why each wave commits before the next.)
|
|
187
187
|
|
|
188
|
+
```bash
|
|
189
|
+
REPORT_DIR=$(mktemp -d)
|
|
190
|
+
```
|
|
191
|
+
|
|
188
192
|
```ts
|
|
189
193
|
subagent({
|
|
190
194
|
context: "fresh",
|
|
@@ -193,8 +197,8 @@ subagent({
|
|
|
193
197
|
concurrency: 4, // default; cap = wave size
|
|
194
198
|
tasks: [
|
|
195
199
|
// do NOT set per-task cwd under worktree:true — it must equal the top-level cwd or the run errors
|
|
196
|
-
{ agent: "implementer", task: "<task text + owned files + SCOPED_TEST_COMMANDS + status protocol>", output: "wave1-task1.md" },
|
|
197
|
-
{ agent: "implementer", task: "<task text + owned files + SCOPED_TEST_COMMANDS + status protocol>", output: "wave1-task2.md" },
|
|
200
|
+
{ agent: "implementer", task: "<task text + owned files + SCOPED_TEST_COMMANDS + status protocol>", output: "<REPORT_DIR>/wave1-task1.md" },
|
|
201
|
+
{ agent: "implementer", task: "<task text + owned files + SCOPED_TEST_COMMANDS + status protocol>", output: "<REPORT_DIR>/wave1-task2.md" },
|
|
198
202
|
],
|
|
199
203
|
})
|
|
200
204
|
```
|