| name | debugging |
| description | Systematic, hypothesis-driven debugging in any language: reproduce, isolate, form falsifiable hypotheses, bisect, find root cause, fix minimally, and lock the fix with a regression test. Use when encountering ANY bug, failing test, crash, flaky behavior, or unexplained output — BEFORE proposing fixes. Also use when a previous fix didn't work or a bug keeps reappearing.
|
| allowed-tools | ["Read","Glob","Grep","Bash"] |
Systematic Debugging
IRON LAW: NO FIX WITHOUT A ROOT CAUSE YOU CAN STATE IN ONE SENTENCE
AND DEFEND WITH EVIDENCE. SYMPTOM-PATCHING IS FORBIDDEN.
The Loop (scientific method)
1. Reproduce
- Get a deterministic reproduction, or measure the failure rate if flaky.
- Capture the exact error, environment, inputs, and versions.
- Can't reproduce → gather more facts (logs, state diffs); do NOT guess-fix.
2. Observe before theorizing
- Read the FIRST error, not the last — downstream errors are noise.
- Read the actual code path and the actual data. Verify assumptions
("is this function even called?") with evidence: logs, debugger,
breakpoints, print probes.
3. Hypothesize (falsifiable, one at a time)
- "X causes Y because Z" — with a prediction the next experiment can refute.
- Prefer the cheapest experiment that can kill the hypothesis.
4. Experiment (one variable at a time)
- Minimize the reproduction: smallest input/code slice that still fails.
- Bisect: by commit (
git bisect), by data (half the input), by code path
(disable half). Each step halves the search space.
- Change ONE thing per run; revert experimental changes afterward.
5. Root cause → minimal fix
- State the root cause in one sentence. If you can't, return to step 2.
- Fix the cause, not the symptom. The fix should make the original
reproduction pass and be explainable.
6. Lock it in
- Add a regression test that fails without the fix and passes with it
(reference the ticket if the repo uses a ticket convention).
- Run the full suite — verify no collateral damage.
- Brief note: cause, fix, and why it can't silently regress.
Escalation Gate
After 3 failed fix attempts: STOP. The mental model is wrong somewhere.
Re-derive assumptions from scratch, write down what is proven vs assumed,
and question the architecture with the user rather than attempting fix #4.
Rationalization Table (STOP signs)
| If you think… | Reality |
|---|
| "Adding this null-check/try-catch makes it go away" | You hid the symptom; the corruption is still upstream |
| "It's probably the framework/compiler" | It is almost never the compiler. Prove it with a minimal case first |
| "It works on my machine / re-run fixed it" | Flakiness IS the bug: race, ordering, time, or shared state |
| "Too urgent for a regression test" | The same bug returning during the incident is slower |
| "Multiple changes at once saves time" | You can no longer attribute the result; you lost information |
Flaky-Failure Playbook
Suspects in order: shared mutable state between tests · time/clock
dependence · async ordering/races · network or filesystem nondeterminism ·
test-order dependence (run isolated vs suite) · hidden randomness (seed it).
Related Skills
| Need | Skill |
|---|
| Writing the regression test | testing |
| Build/run/simulator loops on Apple platforms | xcode-agentic |
| On-device UI reproduction | device-interaction |
| Performance "bugs" (slowness) | performance-engineering |