diff --git a/agents/bugfixer.md b/agents/bugfixer.md index f07dff5..3a7ecbc 100644 --- a/agents/bugfixer.md +++ b/agents/bugfixer.md @@ -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 -- -``` - -## 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 -- - 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 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 : -ROOT CAUSE: -EVIDENCE: -BLAST RADIUS: - -FIX PLAN: - 1. — - 2. — - [3. — add/update test for this case] - -RISK: +BUGFIX-EXEC REPORT +STATUS : DONE | NEED-DECISION | BLOCKED +FILE(S) : +TEST(S) : +SMOKE : +NOTES : ``` - -- 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/--.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) : - 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). - -6. Commit using conventional format (after approval): - ``` - fix(): - - - - ``` -7. Print summary: - ``` - BUGFIX COMPLETE - BUG : - ROOT CAUSE : - FILE(S) : - TEST(S) : - REGRESSION : - ``` - -## STEP 6 — DOC SYNC (automatic) - -Load `$HOME/.claude/agents/doc-syncer.md`. -Execute in automatic mode: -`auto-mode scope: ` - -**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 — — 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 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. diff --git a/lib/tests/loops-light.test.sh b/lib/tests/loops-light.test.sh index 4d023db..61e0de4 100644 --- a/lib/tests/loops-light.test.sh +++ b/lib/tests/loops-light.test.sh @@ -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" diff --git a/lib/verify-secure-loop.md b/lib/verify-secure-loop.md index ed3e682..4a12f3b 100644 --- a/lib/verify-secure-loop.md +++ b/lib/verify-secure-loop.md @@ -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`. diff --git a/skills/bugfix/SKILL.md b/skills/bugfix/SKILL.md index 069d264..f22fdb1 100644 --- a/skills/bugfix/SKILL.md +++ b/skills/bugfix/SKILL.md @@ -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 -- +``` + +## 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 -- + 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. + +## 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/--.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: +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` → 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) : + 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) + +Load `$HOME/.claude/agents/doc-syncer.md`. +Execute in automatic mode: +`auto-mode scope: ` + +**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 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. diff --git a/skills/hotfix/SKILL.md b/skills/hotfix/SKILL.md index 66e04d9..21f8ec2 100644 --- a/skills/hotfix/SKILL.md +++ b/skills/hotfix/SKILL.md @@ -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.