|
| 1 | +# Bugfix Workflow Commands |
| 2 | + |
| 3 | +This directory contains Claude Code commands that implement a **lightweight, diagnosis-first |
| 4 | +workflow for fixing bugs**. It is the bug-shaped counterpart to the heavyweight `/spec:*` |
| 5 | +workflow: where `/spec` runs Requirements → ADR → adversarial review → tasks → implement (right |
| 6 | +for *features*), `/bugfix` runs **Triage → Confirm → Test-first → Fix → Verify** and deliberately |
| 7 | +omits the ADR/requirements/review rounds. |
| 8 | + |
| 9 | +## Why a separate workflow? |
| 10 | + |
| 11 | +Bugs differ from features in one important way: **the root cause is a hypothesis until proven.** |
| 12 | +Issues often arrive with a suggested fix (sometimes from an automated agent), but a suggested fix |
| 13 | +can be wrong, incomplete, or address a *symptom* rather than the cause. `/test-first` jumps |
| 14 | +straight to writing a test for an *assumed* behaviour — it has no gate for *confirming the |
| 15 | +diagnosis first*. |
| 16 | + |
| 17 | +`/bugfix` is essentially `/test-first` wrapped with an explicit **Confirm** gate up front, plus a |
| 18 | +triage step that records the hypothesis. |
| 19 | + |
| 20 | +**Worked example — #4054 (ASB `SessionId` case-sensitivity).** The issue arrived with a plausible |
| 21 | +suggested fix. Before writing any code, Confirm proved the root cause by reading |
| 22 | +`JsonSerialisationOptions` (`PropertyNamingPolicy = JsonNamingPolicy.CamelCase`) — keys are |
| 23 | +camelCased on serialization round-trips — and surfaced a *second* defect the suggested fix only |
| 24 | +partially addressed (reserved-header stripping is also case-sensitive, so reserved keys leak into |
| 25 | +`ApplicationProperties`). Confirming the theory **changed the scope of the fix.** That is exactly |
| 26 | +what the Confirm gate exists to catch. |
| 27 | + |
| 28 | +## Workflow |
| 29 | + |
| 30 | +``` |
| 31 | +┌─────────────────────────────────────────────────────────────────┐ |
| 32 | +│ Bugfix Workflow │ |
| 33 | +└─────────────────────────────────────────────────────────────────┘ |
| 34 | +
|
| 35 | + GitHub Issue / bug report |
| 36 | + │ |
| 37 | + ▼ |
| 38 | + Triage ──────────────► /bugfix:triage [issue-number | description] |
| 39 | + │ (restate symptom, locate code, form hypothesis; |
| 40 | + │ any suggested fix is UNVERIFIED) |
| 41 | + ▼ |
| 42 | + Confirm ─────────────► /bugfix:confirm |
| 43 | + │ ✋ Confirm gate — prove the hypothesis (code-trace |
| 44 | + │ and/or red repro) before any fix; .confirm-approved |
| 45 | + │ (refuted → back to triage) |
| 46 | + ▼ |
| 47 | + Test-first ──────────► /bugfix:test |
| 48 | + │ ✋ delegates to /test-first (approve test in IDE) |
| 49 | + ▼ |
| 50 | + Fix ─────────────────► /bugfix:fix |
| 51 | + │ (minimal change to green, scoped to confirmed cause; |
| 52 | + │ /tidy-first if structural cleanup needed first) |
| 53 | + ▼ |
| 54 | + Verify ──────────────► /bugfix:verify |
| 55 | + │ (run suite; regression test stays; capture root cause, |
| 56 | + │ Fixes #N — no auto-close) |
| 57 | + ▼ |
| 58 | + Pull Request |
| 59 | +``` |
| 60 | + |
| 61 | +## The two gates |
| 62 | + |
| 63 | +| Gate | Where | What it guarantees | |
| 64 | +|------|-------|--------------------| |
| 65 | +| ✋ **Confirm** | `/bugfix:confirm` | The root-cause diagnosis is **proven**, not assumed, and the fix's scope (including any extra defects) is agreed before code is written. The one on-disk marker: `.confirm-approved`. | |
| 66 | +| ✋ **Test approval** | `/bugfix:test` → `/test-first` | The failing regression test is reviewed in the IDE before any implementation (inherited from `/test-first`). | |
| 67 | + |
| 68 | +### Confirm evidence standard — red repro preferred, code-trace allowed |
| 69 | + |
| 70 | +Confirm passes on **either**: |
| 71 | +- an executable **red reproduction** (preferred when the bug reproduces cheaply — pure logic, no |
| 72 | + live infra), **or** |
| 73 | +- a documented **code-trace** that proves the cause (the accepted path when a repro would need a |
| 74 | + real broker/database/etc., as in #4054). |
| 75 | + |
| 76 | +The durable, executable regression test is written later by `/bugfix:test` (via `/test-first`) — |
| 77 | +Confirm itself stays read-only and writes no source. |
| 78 | + |
| 79 | +## Sub-agents & model policy |
| 80 | + |
| 81 | +Modelled on `/spec` (see `.claude/commands/spec/README.md` → "Sub-agents & model policy"): |
| 82 | +reasoning-heavy, read-only steps delegate to a **`Plan`** sub-agent (no file-editing tool, no |
| 83 | +`AskUserQuestion`) which RETURNS its findings as text; the **main agent** owns all user |
| 84 | +interaction (the Confirm gate) and all bookkeeping (writing `bugfix.md`, markers, `gh`, git). |
| 85 | + |
| 86 | +| Command | Sub-agent (type) | Model | Rationale | |
| 87 | +|---------|------------------|-------|-----------| |
| 88 | +| `/bugfix:triage` | Yes — `Plan` (read-only) | **opus** | Diagnostic analysis / locating code | |
| 89 | +| `/bugfix:confirm` | Yes — `Plan` (read-only) | **opus** | Adversarial root-cause proof | |
| 90 | +| `/bugfix:test` | No — delegates to `/test-first` | **sonnet** | Implementation (interactive approval gate) | |
| 91 | +| `/bugfix:fix` | No (main agent) | **sonnet** | Implementation work | |
| 92 | +| `/bugfix:verify` | No (main agent) | — | Mechanical: run suite, prepare commit/PR | |
| 93 | +| `/bugfix:status`, `/bugfix:switch` | No | — | Bookkeeping | |
| 94 | + |
| 95 | +`triage` and `confirm` use `Plan` so the "return as text, don't write the file" rule is hard to |
| 96 | +violate accidentally (no `Write`/`Edit`). `test`/`fix` run in the **main agent** because the |
| 97 | +test-approval gate is interactive and the fix writes source — set the session model to **sonnet** |
| 98 | +for those, matching the implementation policy. |
| 99 | + |
| 100 | +## State model (lightweight — single record + one marker) |
| 101 | + |
| 102 | +``` |
| 103 | +bugfixes/ |
| 104 | +├── .current-bug # tracks the active bug (like specs/.current-spec) |
| 105 | +└── 0001-asb-sessionid-case/ |
| 106 | + ├── .issue-number # linked GitHub issue (optional) |
| 107 | + ├── .confirm-approved # the ONE gate marker |
| 108 | + └── bugfix.md # symptom / hypothesis / root cause / evidence / fix |
| 109 | +``` |
| 110 | + |
| 111 | +Unlike `/spec` (three approval markers), `/bugfix` has a **single** marker (`.confirm-approved`). |
| 112 | +Every other phase is inferred from the content of `bugfix.md`, keeping the workflow light. |
| 113 | + |
| 114 | +### `bugfix.md` sections (filled progressively) |
| 115 | + |
| 116 | +| Section | Filled by | |
| 117 | +|---------|-----------| |
| 118 | +| Symptom, Suspected Location, Root-Cause Hypothesis | `/bugfix:triage` | |
| 119 | +| Confirmed Root Cause, Evidence, Scope Notes | `/bugfix:confirm` | |
| 120 | +| Regression Test | `/bugfix:test` | |
| 121 | +| Fix | `/bugfix:fix` | |
| 122 | +| Status (Triaged → Confirmed → Tested → Fixed → Verified) | each step | |
| 123 | + |
| 124 | +## Commands |
| 125 | + |
| 126 | +### `/bugfix:triage [issue-number | description]` |
| 127 | +Start a bug. Sets up `bugfixes/NNNN-slug/` and `.current-bug`, pulls the issue via `gh`, and (via |
| 128 | +a `Plan` sub-agent) restates the symptom, locates the suspect code, and forms a root-cause |
| 129 | +hypothesis. Any suggested fix is recorded as **UNVERIFIED**. Offers a `bugfix/N-slug` branch. |
| 130 | + |
| 131 | +### `/bugfix:confirm` |
| 132 | +The ✋ Confirm gate. A `Plan` sub-agent proves or refutes the hypothesis by tracing the code |
| 133 | +(and/or describing a red repro), citing `file:line` evidence, and hunts for scope changes / |
| 134 | +additional defects. The main agent writes the findings into `bugfix.md` and asks the user to |
| 135 | +approve the diagnosis; on approval it creates `.confirm-approved`. A refuted hypothesis loops back |
| 136 | +to triage. |
| 137 | + |
| 138 | +### `/bugfix:test` |
| 139 | +Requires `.confirm-approved`. Delegates to `/test-first` to write the failing regression test for |
| 140 | +the confirmed behaviour (and one per additional defect in the Scope Notes). The `/test-first` |
| 141 | +IDE-approval gate applies. |
| 142 | + |
| 143 | +### `/bugfix:fix` |
| 144 | +Requires `.confirm-approved` + a red test. Makes the test green with the **minimal** change scoped |
| 145 | +to the confirmed cause — no speculative edits, no default changes. If structural cleanup is needed |
| 146 | +first, defers to `/tidy-first` (separate `refactor:` commit, then the `fix:` commit). |
| 147 | + |
| 148 | +### `/bugfix:verify` |
| 149 | +Runs the regression test(s) and the broader suite; the regression test stays. Suggests a `fix:` |
| 150 | +commit and PR body that capture the confirmed root cause and link the issue with `Fixes #N` — |
| 151 | +without closing the issue directly (merge closes it). |
| 152 | + |
| 153 | +### `/bugfix:status` |
| 154 | +Lists all bugs and derives each phase from `bugfix.md` + `.confirm-approved`. |
| 155 | + |
| 156 | +### `/bugfix:switch <bug-slug>` |
| 157 | +Switches the active bug (updates `bugfixes/.current-bug`). |
| 158 | + |
| 159 | +## When to use `/bugfix` vs other workflows |
| 160 | + |
| 161 | +- **`/bugfix`** — a defect whose root cause is not yet proven, or that arrived with a suggested fix |
| 162 | + you should verify before trusting. The Confirm gate is the value-add. |
| 163 | +- **`/test-first`** — a small change whose behaviour/cause is already obvious; you just need the |
| 164 | + test-first discipline. |
| 165 | +- **`/tidy-first`** — the change is (or includes) structural cleanup; keep refactor and behaviour |
| 166 | + in separate commits. `/bugfix:fix` calls this when a fix needs cleanup first. |
| 167 | +- **`/spec:*`** — a *feature* or capability needing requirements + ADR design, not a bug fix. |
| 168 | + |
| 169 | +## Related Commands |
| 170 | +- **`/test-first`** — `.claude/commands/tdd/test-first.md` (the test step delegates here) |
| 171 | +- **`/tidy-first`** — `.claude/commands/refactor/tidy-first.md` (the fix step defers here when needed) |
| 172 | +- **`/spec:*`** — `.claude/commands/spec/README.md` (the heavyweight feature workflow this mirrors) |
0 commit comments