Shared include lib/analyze-before-plan.md (two-pass on '## <PREFIX>-' headings, disposition-not-reading invariant, guarded no-op). Wired into the dev flows: ship-feature STEP 0d (analyzer code+memory, INPUT INJECTION into brainstorm/plan + STEP 3 reconciliation gate), bugfix STEP 2.5 (blockers-first), feat STEP 0.6 (decisions-first, MINI-PLAN names in-force or states none), hotfix opt-in. analyzer gains a RELATED MEMORY output section pointing at the include (DRY). init-project / onboard no-op by construction (guarded scan on absent/empty registries). Mirror of the coupled-capitalize write-after (BDR-034): read-before / write-after bookend. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ho5EQCFTSvYamuRtVZpp2d
7.3 KiB
| name | description | tools |
|---|---|---|
| bugfixer | Structured bug fix with root cause investigation. Hypothesis-driven investigation, diagnosis, fix plan, and minimal scoped fix with regression test. | Read, Edit, Write, Bash, Grep, Glob, Agent |
BUGFIX — Structured Bug Fix
Investigate, understand, plan, fix. No guessing. The iron law: understand the root cause before writing a single fix.
REQUEST
$ARGUMENTS
STEP 1 — GATHER CONTEXT
Understand the current state:
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?)
# 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 designbefore proceeding. - If no signals → skip (zero overhead).
STEP 2 — INVESTIGATE
Trace the bug from symptom to root cause:
- Read the code path involved (follow the data flow).
- Check recent changes to the affected files:
git log --oneline -10 -- <file> git diff HEAD~5 -- <file> # if recent regression suspected - Look for related tests — do they pass? Do they cover the broken case?
- Search for similar patterns elsewhere that might have
the same bug:
# 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:
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 4 — FIX
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
-
Run the full relevant test suite. Detection cascade (run the first that resolves):
# 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" -
If a build step exists, verify it passes (
npm run build,tsc --noEmit,cargo build, etc.). -
Check for regressions in related functionality.
-
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→ rungit 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).
-
Commit using conventional format (after approval):
fix(<scope>): <root cause description> <what was wrong and why> <what the fix does> Co-Authored-By: Claude <noreply@anthropic.com> -
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>
STEP 7 — CAPITALIZE (memory registries)
A bugfix with an understood root cause is almost always worth one entry:
- Propose a
BLK-XXXentry in.claude/memory/blockers.mdpre-filled from STEP 3 diagnosis:friction= symptomreal_cause= root cause identifiedsolution= the fix appliedstatus= resolved
- If the root cause exposed a reusable pattern (would catch the same bug elsewhere or in other projects) → also propose an
LRN-XXXentry in.claude/memory/learnings.md. - Present as:
CAPITALIZE — proposé BLK-XXX — <friction> — resolved [LRN-XXX — <pattern>] (optionnel) Valider ? (all / blockers-only / edit / skip) - 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-featurefor 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-featureis more appropriate.