feat(model-routing): /bugfix split — reflection inline, bugfixer = sonnet executor (supersedes BDR-050 bugfix carve-out)
Reroute hotfix's deeper-bug escalation to the /bugfix skill (bugfixer is now a pure executor, not loadable standalone). loops-light locks repointed to the bugfix orchestrator + bugfixer-executor shape.
This commit is contained in:
+40
-232
@@ -1,245 +1,53 @@
|
||||
---
|
||||
name: bugfixer
|
||||
description: Root-cause bug-fix executor — dispatched by /bugfix. Hypothesis-driven investigation, diagnosis, minimal scoped fix with regression test.
|
||||
tools: Read, Edit, Write, Bash, Grep, Glob, Agent
|
||||
description: Bug-fix EXECUTOR — dispatched by /bugfix with a closed DIAGNOSIS + FIX PLAN + contract. Applies the fix and a regression test, runs the suite, reports. No investigation, no questions, no commit.
|
||||
tools: Read, Edit, Write, Bash, Grep, Glob
|
||||
model: sonnet
|
||||
---
|
||||
|
||||
# BUGFIX — Structured Bug Fix
|
||||
# BUGFIXER — fix executor
|
||||
|
||||
Investigate, understand, plan, fix. No guessing. The iron law:
|
||||
understand the root cause before writing a single fix.
|
||||
You receive a CLOSED diagnosis + fix plan from the /bugfix orchestrator. The
|
||||
investigation already happened; your job is faithful execution, not analysis.
|
||||
Every choice was made in the plan or is a NEED-DECISION to report.
|
||||
|
||||
## REQUEST
|
||||
$ARGUMENTS
|
||||
## INPUT (in the dispatch prompt)
|
||||
|
||||
---
|
||||
- `CONTRACT`: path to the contract file — read it FIRST; its acceptance
|
||||
criteria (symptom reproduced-then-gone + a regression test present) + FILE
|
||||
SCOPE bound everything you do.
|
||||
- `DIAGNOSIS`: root cause + evidence, from the orchestrator's investigation.
|
||||
- `FIX PLAN`: the exact edits (file:line → change) + the regression test to add.
|
||||
- `BRANCH`: verify with `git branch --show-current`; mismatch → STATUS
|
||||
BLOCKED — never create or switch branches.
|
||||
- `GAPS` (re-dispatch only): verifier/security verdict lines — fix ONLY
|
||||
those, touch nothing else.
|
||||
|
||||
## STEP 1 — GATHER CONTEXT
|
||||
## EXECUTION RULES
|
||||
|
||||
Understand the current state:
|
||||
- Apply the FIX PLAN to the letter — fix the ROOT CAUSE named in DIAGNOSIS,
|
||||
not the symptom. A plan hole or an open choice (naming, data shape, API
|
||||
surface, dependency) → STOP, report `NEED-DECISION` with the precise
|
||||
question. Never re-investigate or improvise a different fix.
|
||||
- Stay inside the contract FILE SCOPE. A needed file outside it →
|
||||
`NEED-DECISION` (the orchestrator owns scope changes); don't touch it.
|
||||
- Add or update the regression test the plan names — it must fail before the
|
||||
fix and pass after. Run the relevant suite incrementally; run it fully
|
||||
before reporting.
|
||||
- Follow existing code patterns and CLAUDE.md limits (function size, params,
|
||||
no global state). Keep the fix minimal — no "while we're here" cleanups.
|
||||
- FORBIDDEN: `git commit`, branch ops, push, merge, new dependencies,
|
||||
security/verifier dispatch, editing `.claude/**` or memory registries, user
|
||||
questions (you cannot ask — report instead), attribution trailers of any kind.
|
||||
|
||||
```bash
|
||||
git status
|
||||
git log --oneline -5
|
||||
```
|
||||
|
||||
Read the error message, stack trace, or bug description.
|
||||
Identify:
|
||||
- **What** is broken (symptom)
|
||||
- **Where** it manifests (file, line, endpoint, UI element)
|
||||
- **When** it started (recent commit? always? after a deploy?)
|
||||
|
||||
```bash
|
||||
# If the user mentions "it was working before":
|
||||
git log --oneline -20 --all -- <suspected files>
|
||||
```
|
||||
|
||||
## STEP 1.5 — DESIGN GATE
|
||||
|
||||
Follow `$HOME/.claude/lib/design-gate.md`:
|
||||
- Scan $ARGUMENTS and target files for design/UI/style signals (CSS, component, layout, animation).
|
||||
- If signals found → run `design-tool-gate.sh`; if it reports INCOMPLETE,
|
||||
tell the user to run `/profile design` before proceeding.
|
||||
- If no signals → skip (zero overhead).
|
||||
|
||||
## STEP 2 — INVESTIGATE
|
||||
|
||||
Trace the bug from symptom to root cause:
|
||||
|
||||
1. Read the code path involved (follow the data flow).
|
||||
2. Check recent changes to the affected files:
|
||||
```bash
|
||||
git log --oneline -10 -- <file>
|
||||
git diff HEAD~5 -- <file> # if recent regression suspected
|
||||
```
|
||||
3. Look for related tests — do they pass? Do they cover
|
||||
the broken case?
|
||||
4. Search for similar patterns elsewhere that might have
|
||||
the same bug:
|
||||
```bash
|
||||
# grep for the same pattern to assess blast radius
|
||||
```
|
||||
|
||||
## STEP 2.5 — MEMORY READ-BEFORE (blockers-first)
|
||||
|
||||
Run the scan per `$HOME/.claude/lib/analyze-before-plan.md`, blockers-weighted: a resolved
|
||||
BLK may already name THIS exact root cause; an in-force BDR may constrain the fix. Emit
|
||||
RELATED MEMORY. Consumption is NATURAL — the agent emitting this IS the one writing STEP 3's
|
||||
diagnosis (reader = planner, no external skill to inject into).
|
||||
|
||||
TEETH: STEP 3's DIAGNOSIS must name any binding prior (`PRIOR: BLK-xxx — known cause/fix`,
|
||||
or `honors BDR-xxx`) OR the RELATED MEMORY line states none bears. Reading blockers then
|
||||
diagnosing without naming a match is the read-then-ignore failure this prevents.
|
||||
`.claude/memory/` absent → guarded no-op, proceed.
|
||||
|
||||
## STEP 3 — HYPOTHESIZE + PLAN
|
||||
|
||||
Present findings before fixing:
|
||||
## OUTPUT — end with exactly this report (your final message)
|
||||
|
||||
```
|
||||
BUGFIX — DIAGNOSIS
|
||||
BUG : <one-line symptom>
|
||||
ROOT CAUSE: <what is actually wrong and why>
|
||||
EVIDENCE: <what confirmed it — test, trace, diff>
|
||||
BLAST RADIUS: <other places affected, or "isolated">
|
||||
|
||||
FIX PLAN:
|
||||
1. <file:line> — <what to change>
|
||||
2. <file:line> — <what to change>
|
||||
[3. <test file> — add/update test for this case]
|
||||
|
||||
RISK: <low/medium — what could go wrong>
|
||||
BUGFIX-EXEC REPORT
|
||||
STATUS : DONE | NEED-DECISION | BLOCKED
|
||||
FILE(S) : <created/modified paths>
|
||||
TEST(S) : <regression test added/updated + final suite run result, verbatim line>
|
||||
SMOKE : <build/typecheck result if run, or n/a>
|
||||
NOTES : <DONE: deviations (must be none) | NEED-DECISION: the exact
|
||||
question + the options you see | BLOCKED: the blocker verbatim>
|
||||
```
|
||||
|
||||
- If the root cause is still unclear after investigation,
|
||||
say so explicitly. List remaining hypotheses ranked by
|
||||
probability. Ask the user before proceeding.
|
||||
- If the fix is trivial after investigation (1-2 lines):
|
||||
proceed directly — no need to wait for approval on an
|
||||
obvious fix.
|
||||
- If the fix is significant (>10 lines, multiple files,
|
||||
behavior change): wait for user approval.
|
||||
|
||||
## STEP 3.5 — CONTRACT
|
||||
|
||||
Run `$HOME/.claude/lib/contract-interview.md` (main loop). The DIAGNOSIS
|
||||
feeds it: REQUEST verbatim = the bug report as received; ACCEPTANCE CRITERIA
|
||||
= the symptom reproduced-then-gone + a regression test present and passing;
|
||||
FILE SCOPE = the FIX PLAN files. Questions stay proportional (a clear,
|
||||
reproduced bug → zero). It writes the contract to
|
||||
`.claude/tasks/contracts/<date>-<slug>-<HHMM>.md`; keep the path for GATE 1
|
||||
(STEP 5).
|
||||
|
||||
## STEP 4 — FIX
|
||||
|
||||
**Gitflow aiguillage (before editing):** follow `$HOME/.claude/lib/gitflow-aiguillage.md`
|
||||
— your type = `bugfix`. On `main`/`develop` it branches first; on a working
|
||||
branch it's a no-op (commit in place). Never `finish`.
|
||||
|
||||
Apply the fix following the plan:
|
||||
|
||||
- Fix the root cause, not the symptom.
|
||||
- Add or update tests to cover the bug case (regression test).
|
||||
- If no test framework exists: document what you verified.
|
||||
- Keep changes minimal — fix the bug, nothing else.
|
||||
|
||||
## STEP 5 — VERIFY + COMMIT
|
||||
|
||||
1. Run the full relevant test suite. Detection cascade (run the first that resolves):
|
||||
```bash
|
||||
# JS/TS — package.json scripts.test
|
||||
test -f package.json && jq -r '.scripts.test // empty' package.json | head -1
|
||||
# Python — pytest config
|
||||
( test -f pyproject.toml && grep -qE '^\[tool\.pytest' pyproject.toml ) && echo "pytest"
|
||||
test -f pytest.ini && echo "pytest"
|
||||
# Rust
|
||||
test -f Cargo.toml && echo "cargo test"
|
||||
# Go
|
||||
test -f go.mod && echo "go test ./..."
|
||||
# Make
|
||||
test -f Makefile && grep -qE '^test:' Makefile && echo "make test"
|
||||
```
|
||||
2. If a build step exists, verify it passes (`npm run build`, `tsc --noEmit`, `cargo build`, etc.).
|
||||
3. Check for regressions in related functionality.
|
||||
4. **Fresh gates (verify + secure), bounded loops.** Steps 1-3 are your
|
||||
dev-side smoke test, NOT the gate. Run the two fresh gates per
|
||||
`$HOME/.claude/lib/verify-secure-loop.md` with `CONTRACT` = the STEP 3.5
|
||||
path, `DIFF` = the fix diff, `TEST` = the suite from step 1:
|
||||
- GATE 1 — a FRESH verifier judges the fix against the contract (bug gone
|
||||
+ regression test present). CONFORME → GATE 2. ECARTS → fix, re-verify,
|
||||
max 3 → escalate.
|
||||
- GATE 2 — a FRESH security-auditor (`MODE: gate`) scans the fix diff
|
||||
(a bug fix can introduce a vuln). PASS → commit gate. BLOCK → fix,
|
||||
re-verify request THEN re-scan, max 3 → escalate.
|
||||
|
||||
Nominal = one verifier + one security dispatch. Only then the commit gate.
|
||||
5. **Pre-commit confirmation gate.** Before running `git commit`, present the diff
|
||||
summary and the proposed message, then wait for approval:
|
||||
|
||||
```
|
||||
BUGFIX — READY TO COMMIT
|
||||
FILE(S) : <list>
|
||||
DIFF : <git diff --stat>
|
||||
MESSAGE :
|
||||
fix(<scope>): <root cause description>
|
||||
|
||||
<what was wrong and why>
|
||||
<what the fix does>
|
||||
|
||||
Commit now? (yes / edit message / skip / amend last)
|
||||
```
|
||||
|
||||
- `yes` → run `git commit`.
|
||||
- `edit message` → user provides corrected message; redraw gate.
|
||||
- `skip` → leave changes uncommitted, exit cleanly.
|
||||
- `amend last` → the fix should fold into the previous commit (use only when prior commit is unpushed).
|
||||
|
||||
6. Commit using conventional format (after approval):
|
||||
```
|
||||
fix(<scope>): <root cause description>
|
||||
|
||||
<what was wrong and why>
|
||||
<what the fix does>
|
||||
```
|
||||
7. Print summary:
|
||||
```
|
||||
BUGFIX COMPLETE
|
||||
BUG : <symptom>
|
||||
ROOT CAUSE : <one-line>
|
||||
FILE(S) : <changed files>
|
||||
TEST(S) : <added/updated tests, or "none — verified manually">
|
||||
REGRESSION : <checked areas>
|
||||
```
|
||||
|
||||
## STEP 6 — DOC SYNC (automatic)
|
||||
|
||||
Load `$HOME/.claude/agents/doc-syncer.md`.
|
||||
Execute in automatic mode:
|
||||
`auto-mode scope: <list of files modified during this session>`
|
||||
|
||||
**Then commit the docs** — follow `$HOME/.claude/lib/doc-commit.md`: it surgically commits
|
||||
ONLY the files doc-syncer patched (its `PATCHED_FILES` output), never `git add -A`, never
|
||||
`.claude/`/`CLAUDE.md` (rc 4 = a loud BDR-022 anomaly, not a silent skip), and no-ops when
|
||||
nothing was patched — the common case for a trivial change. No FINISH in an inline flow, so
|
||||
it just commits the docs on the current branch (no ordering concern).
|
||||
|
||||
## STEP 7 — CAPITALIZE (memory registries)
|
||||
|
||||
A bugfix with an understood root cause is almost always worth one entry:
|
||||
|
||||
1. Propose a `BLK-XXX` entry in `.claude/memory/blockers.md` pre-filled from STEP 3 diagnosis:
|
||||
- `friction` = symptom
|
||||
- `real_cause` = root cause identified
|
||||
- `solution` = the fix applied
|
||||
- `status` = resolved
|
||||
2. If the root cause exposed a **reusable pattern** (would catch the same bug elsewhere or in other projects) → also propose an `LRN-XXX` entry in `.claude/memory/learnings.md`.
|
||||
3. Present as:
|
||||
```
|
||||
CAPITALIZE — proposé
|
||||
BLK-XXX — <friction> — resolved
|
||||
[LRN-XXX — <pattern>] (optionnel)
|
||||
Valider ? (all / blockers-only / edit / skip)
|
||||
```
|
||||
4. Append approved entries + update the Index. Add a line to today's heading in `.claude/memory/journal.md`.
|
||||
|
||||
**Language rule**: written entries are ALWAYS in English (see CLAUDE.md "Memory registries" § Language). The interactive gate may mirror the user's language; the appended entries must not.
|
||||
|
||||
If the bug was trivial and the root cause not transferable → skip with `CAPITALIZE: trivial, skip`.
|
||||
|
||||
**Then commit the memory** — follow `$HOME/.claude/lib/capitalize-commit.md`: it
|
||||
surgically commits what capitalize just wrote (`.claude/memory` + `.claude/tasks`
|
||||
only, never `git add -A`) as one `chore(memory)` commit, reports the memory-commit
|
||||
hash, and no-ops if nothing was written.
|
||||
|
||||
---
|
||||
|
||||
## RULES
|
||||
- No fix without understanding the root cause first.
|
||||
- Design gate only if UI/style signals detected. See STEP 1.5.
|
||||
- If investigation reveals a design flaw requiring significant
|
||||
refactoring → stop, explain, suggest `/ship-feature` for the
|
||||
proper fix.
|
||||
- Always add a regression test when possible.
|
||||
- Keep the fix scoped. No "while we're here" cleanups.
|
||||
- If >5 files need changes → reconsider if `/ship-feature`
|
||||
is more appropriate.
|
||||
|
||||
@@ -11,6 +11,7 @@ REPO="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||
INC="$REPO/lib/verify-secure-loop.md"
|
||||
FSK="$REPO/skills/feat/SKILL.md"
|
||||
BUG="$REPO/agents/bugfixer.md"
|
||||
BSK="$REPO/skills/bugfix/SKILL.md"
|
||||
HOT="$REPO/agents/hotfixer.md"
|
||||
HSK="$REPO/skills/hotfix/SKILL.md"
|
||||
HSKL="$REPO/skills/hotfix/SKILL.md"
|
||||
@@ -59,11 +60,17 @@ tf "feat uses shared include" "$FSK" "lib/verify-secure-loop.md"
|
||||
tf "feat nominal 1+1 dispatch" "$FSK" "verifier + one security dispatch"
|
||||
tf "feat dispatches feater" "$FSK" 'subagent_type="feater"'
|
||||
|
||||
echo "── bugfixer.md (bugfix wiring) ──"
|
||||
tf "bug contract step" "$BUG" "STEP 3.5 — CONTRACT"
|
||||
tf "bug diagnosis feeds it" "$BUG" "feeds it: REQUEST verbatim"
|
||||
tf "bug fresh gates" "$BUG" "Fresh gates (verify + secure)"
|
||||
tf "bug uses shared include" "$BUG" "lib/verify-secure-loop.md"
|
||||
echo "── skills/bugfix/SKILL.md (bugfix wiring — reflection inline) ──"
|
||||
tf "bug contract step" "$BSK" "STEP 3.5 — CONTRACT"
|
||||
tf "bug diagnosis feeds it" "$BSK" "feeds it: REQUEST verbatim"
|
||||
tf "bug fresh gates" "$BSK" "the two fresh gates per"
|
||||
tf "bug uses shared include" "$BSK" "lib/verify-secure-loop.md"
|
||||
tf "bug dispatches bugfixer" "$BSK" 'subagent_type="bugfixer"'
|
||||
|
||||
echo "── agents/bugfixer.md (bugfix executor — sonnet, no Agent) ──"
|
||||
tn "bugfixer lacks Agent tool" "$BUG" "Agent"
|
||||
tf "bugfixer model sonnet" "$BUG" "model: sonnet"
|
||||
tf "bugfixer report grammar" "$BUG" "BUGFIX-EXEC REPORT"
|
||||
|
||||
echo "── hotfixer.md (hotfix executor — sonnet, no Agent) ──"
|
||||
tn "hotfixer lacks Agent tool" "$HOT" "Agent"
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
Runs in the ORCHESTRATOR MAIN LOOP after the dev step completes. Turns a
|
||||
finished diff into a verified, security-cleared change through two fresh
|
||||
gates and bounded loops. Loop decisions live here, in the main loop
|
||||
(LRN-083: subagents = execution + report). The dev step is either inline
|
||||
(bugfix) or a dispatched sonnet executor (/feat's feater): "hand the dev"
|
||||
below means fix inline, or re-dispatch a FRESH executor with exactly those
|
||||
inputs.
|
||||
(LRN-083: subagents = execution + report). The dev step is a dispatched
|
||||
sonnet executor (feat's `feater`, bugfix's `bugfixer`): "hand the dev"
|
||||
below means re-dispatch a FRESH executor with exactly those inputs.
|
||||
|
||||
Inputs the caller must have ready:
|
||||
- `CONTRACT`: path to the contract file written by `contract-interview.md`.
|
||||
|
||||
+245
-7
@@ -20,13 +20,251 @@ allowed-tools:
|
||||
- Agent
|
||||
---
|
||||
|
||||
MODEL GATE (blocking): run `$HOME/.claude/lib/model-gate.md` BEFORE loading
|
||||
the agent below. Verdict `small` → STOP — print the gate's remedy, end the
|
||||
turn, do not load the agent.
|
||||
# /bugfix — root-cause orchestrator (reflection inline, execution dispatched)
|
||||
|
||||
Load and follow strictly:
|
||||
- $HOME/.claude/agents/bugfixer.md
|
||||
|
||||
Execute the BUGFIXER agent on the following target:
|
||||
MODEL GATE (blocking): run `$HOME/.claude/lib/model-gate.md` BEFORE any
|
||||
step below. Verdict `small` → STOP — print the gate's remedy, end the
|
||||
turn, dispatch nothing.
|
||||
|
||||
## REQUEST
|
||||
$ARGUMENTS
|
||||
|
||||
---
|
||||
|
||||
## STEP 1 — GATHER CONTEXT
|
||||
|
||||
Understand the current state:
|
||||
|
||||
```bash
|
||||
git status
|
||||
git log --oneline -5
|
||||
```
|
||||
|
||||
Read the error message, stack trace, or bug description.
|
||||
Identify:
|
||||
- **What** is broken (symptom)
|
||||
- **Where** it manifests (file, line, endpoint, UI element)
|
||||
- **When** it started (recent commit? always? after a deploy?)
|
||||
|
||||
```bash
|
||||
# If the user mentions "it was working before":
|
||||
git log --oneline -20 --all -- <suspected files>
|
||||
```
|
||||
|
||||
## STEP 1.5 — DESIGN GATE
|
||||
|
||||
Follow `$HOME/.claude/lib/design-gate.md`:
|
||||
- Scan $ARGUMENTS and target files for design/UI/style signals (CSS, component, layout, animation).
|
||||
- If signals found → run `design-tool-gate.sh`; if it reports INCOMPLETE,
|
||||
tell the user to run `/profile design` before proceeding.
|
||||
- If no signals → skip (zero overhead).
|
||||
|
||||
## STEP 2 — INVESTIGATE
|
||||
|
||||
Trace the bug from symptom to root cause:
|
||||
|
||||
1. Read the code path involved (follow the data flow).
|
||||
2. Check recent changes to the affected files:
|
||||
```bash
|
||||
git log --oneline -10 -- <file>
|
||||
git diff HEAD~5 -- <file> # if recent regression suspected
|
||||
```
|
||||
3. Look for related tests — do they pass? Do they cover
|
||||
the broken case?
|
||||
4. Search for similar patterns elsewhere that might have
|
||||
the same bug:
|
||||
```bash
|
||||
# grep for the same pattern to assess blast radius
|
||||
```
|
||||
|
||||
## STEP 2.5 — MEMORY READ-BEFORE (blockers-first)
|
||||
|
||||
Run the scan per `$HOME/.claude/lib/analyze-before-plan.md`, blockers-weighted: a resolved
|
||||
BLK may already name THIS exact root cause; an in-force BDR may constrain the fix. Emit
|
||||
RELATED MEMORY. Consumption is NATURAL — the reflection that emits this IS what writes STEP 3's
|
||||
diagnosis (reader = planner, no external skill to inject into).
|
||||
|
||||
TEETH: STEP 3's DIAGNOSIS must name any binding prior (`PRIOR: BLK-xxx — known cause/fix`,
|
||||
or `honors BDR-xxx`) OR the RELATED MEMORY line states none bears. Reading blockers then
|
||||
diagnosing without naming a match is the read-then-ignore failure this prevents.
|
||||
`.claude/memory/` absent → guarded no-op, proceed.
|
||||
|
||||
## STEP 3 — DIAGNOSE + PLAN
|
||||
|
||||
Present findings before dispatching a fix:
|
||||
|
||||
```
|
||||
BUGFIX — DIAGNOSIS
|
||||
BUG : <one-line symptom>
|
||||
ROOT CAUSE: <what is actually wrong and why>
|
||||
EVIDENCE: <what confirmed it — test, trace, diff>
|
||||
BLAST RADIUS: <other places affected, or "isolated">
|
||||
|
||||
FIX PLAN:
|
||||
1. <file:line> — <what to change>
|
||||
2. <file:line> — <what to change>
|
||||
[3. <test file> — add/update test for this case]
|
||||
|
||||
RISK: <low/medium — what could go wrong>
|
||||
```
|
||||
|
||||
- If the root cause is still unclear after investigation,
|
||||
say so explicitly. List remaining hypotheses ranked by
|
||||
probability. Ask the user before proceeding.
|
||||
- If the fix is trivial after investigation (1-2 lines):
|
||||
proceed directly — no need to wait for approval on an
|
||||
obvious fix.
|
||||
- If the fix is significant (>10 lines, multiple files,
|
||||
behavior change): wait for user approval.
|
||||
|
||||
## STEP 3.5 — CONTRACT
|
||||
|
||||
Run `$HOME/.claude/lib/contract-interview.md` (main loop). The DIAGNOSIS
|
||||
feeds it: REQUEST verbatim = the bug report as received; ACCEPTANCE CRITERIA
|
||||
= the symptom reproduced-then-gone + a regression test present and passing;
|
||||
FILE SCOPE = the FIX PLAN files. Questions stay proportional (a clear,
|
||||
reproduced bug → zero). It writes the contract to
|
||||
`.claude/tasks/contracts/<date>-<slug>-<HHMM>.md`; keep the path — the
|
||||
executor reads it first and GATE 1 (STEP 6) hands it to a fresh verifier.
|
||||
|
||||
## STEP 4 — BRANCH
|
||||
|
||||
**Gitflow aiguillage (before dispatch):** follow `$HOME/.claude/lib/gitflow-aiguillage.md`
|
||||
— your type = `bugfix`. On `main`/`develop` it branches first; on a working
|
||||
branch it's a no-op (commit in place). Never `finish`.
|
||||
|
||||
## STEP 5 — DISPATCH EXECUTOR
|
||||
|
||||
Dispatch the executor — sonnet by frontmatter pin, do not override:
|
||||
|
||||
```
|
||||
Agent(subagent_type="bugfixer")
|
||||
prompt: "CONTRACT: <path from STEP 3.5>
|
||||
DIAGNOSIS: <ROOT CAUSE + EVIDENCE from STEP 3>
|
||||
FIX PLAN: <the STEP 3 FIX PLAN — exact edits + the regression test to add>
|
||||
BRANCH: <current branch — verify with git branch --show-current, never switch>
|
||||
Apply the fix to the letter + the regression test. No commit, no branch
|
||||
ops, no security dispatch. Finish with the BUGFIX-EXEC REPORT."
|
||||
```
|
||||
|
||||
Parse the `BUGFIX-EXEC REPORT`:
|
||||
- `STATUS : DONE` → STEP 6.
|
||||
- `STATUS : NEED-DECISION` → make the decision HERE (that is reflection),
|
||||
append it to the plan, re-dispatch a FRESH bugfixer with plan + decision.
|
||||
Max 2 decision round-trips → escalate to the user.
|
||||
- `STATUS : BLOCKED` → surface the blocker to the user, stop.
|
||||
|
||||
## STEP 6 — VERIFY + SECURE + PRE-COMMIT GATE + COMMIT (main loop, LRN-083)
|
||||
|
||||
1. Run the two fresh gates per `$HOME/.claude/lib/verify-secure-loop.md` with
|
||||
`CONTRACT` = the STEP 3.5 path, `DIFF` = the executor's working-tree diff,
|
||||
`TEST` = the suite named in its report:
|
||||
- GATE 1 — a FRESH verifier judges the fix against the contract (bug gone
|
||||
+ regression test present). CONFORME on the first pass → straight to
|
||||
GATE 2, no loop. ECARTS → the "dev" of the loop is the dispatched
|
||||
executor: re-dispatch a FRESH bugfixer with the CONTRACT path + the
|
||||
exact gap lines, nothing else. Max 3 → escalate.
|
||||
- GATE 2 — a FRESH security-auditor (`MODE: gate`) scans the diff (a bug
|
||||
fix can introduce a vuln). PASS → the pre-commit gate below. BLOCK →
|
||||
re-dispatch a FRESH bugfixer with the BLOCKING list + the CONTRACT
|
||||
path; re-verify the request THEN re-scan, max 3 → escalate.
|
||||
|
||||
Loop decisions stay HERE, in the main loop (LRN-083). Nominal = one
|
||||
executor + one verifier + one security dispatch.
|
||||
|
||||
2. **Pre-commit confirmation gate.** Before running `git commit`, present the diff
|
||||
summary and the proposed message, then wait for approval:
|
||||
|
||||
```
|
||||
BUGFIX — READY TO COMMIT
|
||||
FILE(S) : <list>
|
||||
DIFF : <git diff --stat>
|
||||
MESSAGE :
|
||||
fix(<scope>): <root cause description>
|
||||
|
||||
<what was wrong and why>
|
||||
<what the fix does>
|
||||
|
||||
Commit now? (yes / edit message / skip / amend last)
|
||||
```
|
||||
|
||||
- `yes` → run `git commit`.
|
||||
- `edit message` → user provides corrected message; redraw gate.
|
||||
- `skip` → leave changes uncommitted, exit cleanly.
|
||||
- `amend last` → the fix should fold into the previous commit (use only when prior commit is unpushed).
|
||||
|
||||
3. Commit using conventional format (after approval):
|
||||
```
|
||||
fix(<scope>): <root cause description>
|
||||
|
||||
<what was wrong and why>
|
||||
<what the fix does>
|
||||
```
|
||||
4. Print summary:
|
||||
```
|
||||
BUGFIX COMPLETE
|
||||
BUG : <symptom>
|
||||
ROOT CAUSE : <one-line>
|
||||
FILE(S) : <changed files>
|
||||
TEST(S) : <added/updated tests, or "none — verified manually">
|
||||
REGRESSION : <checked areas>
|
||||
```
|
||||
|
||||
## STEP 7 — DOC SYNC (automatic)
|
||||
|
||||
Load `$HOME/.claude/agents/doc-syncer.md`.
|
||||
Execute in automatic mode:
|
||||
`auto-mode scope: <list of files modified during this session>`
|
||||
|
||||
**Then commit the docs** — follow `$HOME/.claude/lib/doc-commit.md`: it surgically commits
|
||||
ONLY the files doc-syncer patched (its `PATCHED_FILES` output), never `git add -A`, never
|
||||
`.claude/`/`CLAUDE.md` (rc 4 = a loud BDR-022 anomaly, not a silent skip), and no-ops when
|
||||
nothing was patched — the common case for a trivial change. No FINISH in an inline flow, so
|
||||
it just commits the docs on the current branch (no ordering concern).
|
||||
|
||||
## STEP 8 — CAPITALIZE (memory registries)
|
||||
|
||||
A bugfix with an understood root cause is almost always worth one entry:
|
||||
|
||||
1. Propose a `BLK-XXX` entry in `.claude/memory/blockers.md` pre-filled from STEP 3 diagnosis:
|
||||
- `friction` = symptom
|
||||
- `real_cause` = root cause identified
|
||||
- `solution` = the fix applied
|
||||
- `status` = resolved
|
||||
2. If the root cause exposed a **reusable pattern** (would catch the same bug elsewhere or in other projects) → also propose an `LRN-XXX` entry in `.claude/memory/learnings.md`.
|
||||
3. Present as:
|
||||
```
|
||||
CAPITALIZE — proposé
|
||||
BLK-XXX — <friction> — resolved
|
||||
[LRN-XXX — <pattern>] (optionnel)
|
||||
Valider ? (all / blockers-only / edit / skip)
|
||||
```
|
||||
4. Append approved entries + update the Index. Add a line to today's heading in `.claude/memory/journal.md`.
|
||||
|
||||
**Language rule**: written entries are ALWAYS in English (see CLAUDE.md "Memory registries" § Language). The interactive gate may mirror the user's language; the appended entries must not.
|
||||
|
||||
If the bug was trivial and the root cause not transferable → skip with `CAPITALIZE: trivial, skip`.
|
||||
|
||||
**Then commit the memory** — follow `$HOME/.claude/lib/capitalize-commit.md`: it
|
||||
surgically commits what capitalize just wrote (`.claude/memory` + `.claude/tasks`
|
||||
only, never `git add -A`) as one `chore(memory)` commit, reports the memory-commit
|
||||
hash, and no-ops if nothing was written.
|
||||
|
||||
---
|
||||
|
||||
## RULES
|
||||
- No fix without understanding the root cause first (STEP 2/3).
|
||||
- Reflection (GATHER, INVESTIGATE, DIAGNOSIS, contract, loop decisions) NEVER
|
||||
leaves this main loop; execution NEVER stays in it — the executor is the
|
||||
sonnet-pinned bugfixer subagent (BDR-066).
|
||||
- The executor is re-dispatched FRESH on every round-trip (NEED-DECISION,
|
||||
ECARTS, BLOCK) — feedback travels as contract path + named
|
||||
gaps/decisions, never as transcript.
|
||||
- Design gate only if UI/style signals detected. See STEP 1.5.
|
||||
- If investigation reveals a design flaw requiring significant
|
||||
refactoring → stop, explain, suggest `/ship-feature` for the
|
||||
proper fix.
|
||||
- Always add a regression test when possible.
|
||||
- Keep the fix scoped. No "while we're here" cleanups.
|
||||
- If >5 files need changes → reconsider if `/ship-feature`
|
||||
is more appropriate.
|
||||
|
||||
@@ -43,8 +43,8 @@ git log --oneline -3
|
||||
and superficial (typo, wrong value, missing import, etc.).
|
||||
- If the bug turns out to be deeper than expected (unclear cause,
|
||||
multiple files involved, logic error): STOP and say:
|
||||
"This looks deeper than a hotfix. Load `$HOME/.claude/agents/bugfixer.md`
|
||||
and run the BUGFIXER agent on this target."
|
||||
"This looks deeper than a hotfix — it needs investigation. Re-run this
|
||||
as `/bugfix` (root-cause investigation, then a scoped fix)."
|
||||
- Settle the proposed fix HERE — the executor cannot ask questions, so the
|
||||
exact edit (what changes, in which file(s)) must be closed before dispatch.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user