Systematic Debugging
Trigger phrases: "debug", "root cause", "why is this failing", "intermittent bug", "can't reproduce", "is broken", "crashes"
One rule holds the whole skill together: no fix without a confirmed root cause. A patch that makes the symptom
disappear without a proven cause is not a fix — it's a coin flip that hides the bug until it returns somewhere worse.
This skill is the discipline that turns "try things until it works" into "understand, then change one thing."
Kit adaptation (local, .claude/): Distinct from iterate (a self-correction loop over a task) and reflect
(meta-review of an approach) — this skill is for a defect. §4 Prohibitions apply; a fix still goes through the
project's review/test gates. Don't disable a test or a gate to make a symptom pass (that is masking, not fixing).
The loop (do them in order — skipping a step is why bugs come back)
- Reproduce — a reliable, minimal repro. Can't reproduce → that IS the first problem; see
references/techniques.md (intermittent/heisenbug).
- Isolate — shrink the surface until the failure is in the smallest possible slice (bisect commits, halve the input, disable half the system).
- Hypothesize — state ONE falsifiable cause: "X fails because Y." Write it down. A vague hunch is not a hypothesis.
- Test the hypothesis — the cheapest observation that would disprove it (a log, a breakpoint, a probe). If it survives, you have the cause; if not, back to 3.
- Confirm the root cause — you can explain the full chain symptom←…←cause, and you can turn the bug on and off by touching the cause.
- Fix — the smallest change at the cause (not the symptom). Consider what else shares that cause.
- Verify — the original repro now passes, a regression test locks it, and nothing nearby broke.
Checklist
Anti-patterns (each is guess-driven patching wearing a disguise)
- Shotgun debugging — changing several things at once; now you can't tell what mattered. One change at a time.
- Symptom patching — a
try/catch, a null-guard, a retry that swallows the failure without explaining it.
- "It works now" without knowing why it broke — the bug is dormant, not dead.
- Blaming the environment/flake before isolating — sometimes true, but only after step 2, never as the first move.
- Deleting/skipping the failing test to go green — that is masking; the gate exists to catch exactly this.
Techniques by symptom
Bisecting (git + input + system), instrumentation vs. debugger, intermittent/heisenbugs (timing, state, ordering,
resource), the hypothesis log, and when to stop and ask for a second pair of eyes: references/techniques.md.
Invariant rules
- No fix without a confirmed root cause — the one rule; everything else serves it.
- One change at a time — isolate cause and effect; never shotgun.
- Fix the cause, not the symptom — a guard that hides the failure is not a fix.
- Lock it with a regression test — the repro becomes a test so it can't silently return.
- Never mask to go green — don't disable a test/gate/assertion to make the symptom pass.
1---2name: systematic-debugging3description: Root-cause a bug before touching a fix: reproduce, isolate, form and test a hypothesis, confirm the cause, then fix and verify. Stops guess-driven patching. For persistent, intermittent, or "already tried a few things" bugs.4---56# Systematic Debugging78<!-- routing-eval reads this line; it lives in the BODY so the always-on skill LISTING stays inside9 Claude Code's budget (1% of the context window) — an overflowing listing gets descriptions10 truncated or dropped, which strips the very keywords a match depends on. -->11Trigger phrases: "debug", "root cause", "why is this failing", "intermittent bug", "can't reproduce", "is broken", "crashes"1213One rule holds the whole skill together: **no fix without a confirmed root cause.** A patch that makes the symptom14disappear without a proven cause is not a fix — it's a coin flip that hides the bug until it returns somewhere worse.15This skill is the discipline that turns "try things until it works" into "understand, then change one thing."1617> **Kit adaptation (local, .claude/):** Distinct from `iterate` (a self-correction loop over a *task*) and `reflect`18> (meta-review of an approach) — this skill is for a *defect*. §4 Prohibitions apply; a fix still goes through the19> project's review/test gates. Don't disable a test or a gate to make a symptom pass (that is masking, not fixing).2021## The loop (do them in order — skipping a step is why bugs come back)221. **Reproduce** — a reliable, minimal repro. Can't reproduce → that IS the first problem; see `references/techniques.md` (intermittent/heisenbug).232. **Isolate** — shrink the surface until the failure is in the smallest possible slice (bisect commits, halve the input, disable half the system).243. **Hypothesize** — state ONE falsifiable cause: "X fails because Y." Write it down. A vague hunch is not a hypothesis.254. **Test the hypothesis** — the cheapest observation that would *disprove* it (a log, a breakpoint, a probe). If it survives, you have the cause; if not, back to 3.265. **Confirm the root cause** — you can explain the full chain symptom←…←cause, and you can turn the bug on and off by touching the cause.276. **Fix** — the smallest change at the cause (not the symptom). Consider what else shares that cause.287. **Verify** — the original repro now passes, a regression test locks it, and nothing nearby broke.2930## Checklist31- [ ] Reliable repro captured (exact steps/input/env)32- [ ] Failure isolated to the smallest slice33- [ ] One falsifiable hypothesis written down34- [ ] Hypothesis tested by observation (not by applying a fix and seeing)35- [ ] Root cause confirmed (can toggle the bug via the cause; full chain explained)36- [ ] Fix at the cause + regression test added37- [ ] Original repro passes; no new failures3839## Anti-patterns (each is guess-driven patching wearing a disguise)40- **Shotgun debugging** — changing several things at once; now you can't tell what mattered. One change at a time.41- **Symptom patching** — a `try/catch`, a null-guard, a retry that swallows the failure without explaining it.42- **"It works now"** without knowing *why* it broke — the bug is dormant, not dead.43- **Blaming the environment/flake** before isolating — sometimes true, but only *after* step 2, never as the first move.44- **Deleting/skipping the failing test** to go green — that is masking; the gate exists to catch exactly this.4546---4748## Techniques by symptom49Bisecting (git + input + system), instrumentation vs. debugger, intermittent/heisenbugs (timing, state, ordering,50resource), the hypothesis log, and when to stop and ask for a second pair of eyes: **`references/techniques.md`**.5152## Invariant rules531. **No fix without a confirmed root cause** — the one rule; everything else serves it.542. **One change at a time** — isolate cause and effect; never shotgun.553. **Fix the cause, not the symptom** — a guard that hides the failure is not a fix.564. **Lock it with a regression test** — the repro becomes a test so it can't silently return.575. **Never mask to go green** — don't disable a test/gate/assertion to make the symptom pass.