--- name: bugfix effort: high description: | Structured bug fix with root cause investigation. For bugs where the cause isn't immediately obvious, spans multiple files, or requires careful analysis before fixing. Includes hypothesis-driven investigation and a fix plan. Trigger: "bugfix", "debug this", "fix this bug", "pourquoi ca marche pas", "investigate and fix", "find and fix", "root cause + fix". For obvious 1-2 file fixes → use /hotfix instead. For bugs that need investigation only (no fix) → use /analyze. argument-hint: allowed-tools: - Read - Edit - Write - Bash - Grep - Glob - Agent --- # /bugfix — root-cause orchestrator (reflection inline, execution dispatched) 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. EFFORT SHIFTS: follow `$HOME/.claude/lib/effort-shift.md` (BDR-107): medium when a dispatch span starts, own level before challenge synthesis, low at the bookkeeping tail, max at escalation; every shift goes in the same message as the step's first tool call, a lone Skill call is a no-op. ## 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 -- ``` ## 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`; INCOMPLETE → tell the user to run `/profile design`; SIGN-IN REQUIRED → design-gate.md §3 (ask `! 21st login`, wait) 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 -- git diff HEAD~5 -- # 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 : ROOT CAUSE: EVIDENCE: BLAST RADIUS: FIX PLAN: 1. — 2. — [3. — add/update test for this case] RISK: ``` - 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. On resume: `Skill(effort-high)` first, sent with the next tool call (effort-shift: turn reset). - Then run pass B of `$HOME/.claude/lib/contract-interview.md` against the FIX PLAN: every VISIBLE / PUBLIC NAME / SCOPE choice it settles that the bug report left open → one batch of questions, before STEP 3b. The trivial fast-path is not exempt: a 1-line fix with a visible choice still asks. ## STEP 3b — CHALLENGE THE FIX PLAN (before the contract) `Skill(effort-high)` first (effort-shift: own level before the challenge; send it in the same message as the challenger dispatch). Unless the fix is the trivial 1-2 line case STEP 3 already fast-paths, the DIAGNOSIS + FIX PLAN is a reflection worth attacking before it hardens into a contract. Persist it to `.claude/tasks/plans/--.md`, then run `$HOME/.claude/lib/challenge-plan.md` with `PLAN` = that file, `KIND` = `build-plan`, `SCOPE` = the FIX PLAN files, `CONSTRAINTS` = the STEP 2 in-force BDR/LRN/BLK dispositions. Three blind challengers attack it (correctness = is the root cause right; robustness = blast radius / regressions; simplicity = is the fix minimal); RE-THINK every aspect a BLOCKER lands, re-challenge once if the plan materially changed. STEP 3.5 writes the contract from the REVISED plan. Print a CHALLENGE SUMMARY (BLOCKERs addressed / deferred / lenses returned), folding any deferred BLOCKER into the STEP 3 approval gate. ## 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. Pass A only here (pass B ran at STEP 3); a clear, reproduced bug asks nothing. It writes the contract to `.claude/tasks/contracts/--.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: ``` Skill(effort-medium) # effort-shift: dispatch span starts; send with the Agent call below in ONE message Agent(subagent_type="bugfixer") prompt: "CONTRACT: DIAGNOSIS: FIX PLAN: BRANCH: 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` → route on its `CLASS:` per MID-RUN CLARIFICATION in `$HOME/.claude/lib/contract-interview.md`: visible / public-name / scope → ask the user, verbatim; internal → decide HERE (max 2 such round-trips → escalate). Append the answer to the contract `[gated]` and to the plan, re-dispatch a FRESH bugfixer with plan + decision. - `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 0 — deterministic floor, no dispatch: `bash ~/.claude/lib/gates.sh run "$CONTRACT"` executes the criteria's declared oracles fail-closed (the regression-test criterion included). UNMET → re-dispatch a FRESH bugfixer with the NOT-MET rows verbatim — no verifier is spent on a red floor; own budget, max 3 → escalate. MET → GATE 1. - 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 + a free floor run + 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) : DIFF : MESSAGE : fix(): 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(): ``` 4. Print summary: ``` BUGFIX COMPLETE BUG : ROOT CAUSE : FILE(S) : TEST(S) : REGRESSION : ``` ## STEP 7 — DOC SYNC (automatic) Dispatch the doc pipeline (BDR-077 — audit judgment on opus, patch on the sonnet pin, gate HERE): 1. `Agent(subagent_type="doc-syncer", model="opus")` — `MODE: audit` + `auto-mode scope: `. 2. Silence (NONE) → done. `[MINOR]` PATCH PLAN → re-dispatch `Agent(subagent_type="doc-syncer")` with `MODE: patch` + the plan verbatim (no gate — auto behavior preserved; a `SHAPE ESCALATION` in its report comes back here, gated as SIGNIFICANT). 3. SIGNIFICANT → gate here (`Apply? yes / no / select`), then `MODE: patch` with the approved subset. **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 — — resolved [LRN-XXX — ] (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 English AND caveman — fragments, articles dropped, code/IDs/quoted errors verbatim — per CLAUDE.md "Memory registries" (Always English, always caveman). 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`. `Skill(effort-low)` first (effort-shift: bookkeeping tail; send it in the same message as the memory-commit command). **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). A skill-mandated executor is exempt from the doctrine's "don't delegate few-tool-call work" rule (CLAUDE.md "Workflow" names that exception: skill-mandated dispatches run as written). - 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.