systematic-debugging
Find the root cause of a bug before changing any code.
- Use it when
- Whenever something is already broken or behaving unexpectedly - a failing or flaky test, crash, exception, stack trace, regression, build break, performance problem or integration failure - and especially when guessing at a fix is tempting. Not for writing new features or reviewing code that works.
- What kind it is
- A written method: it lays out how the work is done and what to check along the way.
- Size
- 1,508 words. The whole text loads when the skill fires; only the 58-word description is always loaded.
- Starts with
- Ask for the job it describes.
How it is organised
What’s inside
The skill’s top-level sections, in order. The bar is each section’s share of the 1,508 words, so you can see where the weight sits before reading.
- 1The rule185 words
- 2Four phases567 words
- 3Three failed fixes means look at the design70 words
- 4Techniques for particular situations133 words
- 5Stop and go back to phase 1 if you catch yourself thinking124 words
- 6Excuses you will hear yourself make151 words
- 7When the investigation finds no single cause85 words
- 8Quick reference93 words
How it runs
4 phases, in order
The skill names these phases in its headings. Open the text for what each one asks of you and what it holds back until you have answered.
- find the cause
- compare with what works
- one hypothesis at a time
- fix the cause
The skill itself
Read it before you install it
systematic-debugging/SKILL.md · 1,508 wordsDownloadSkill on GitHub ↗--- name: systematic-debugging description: Find the root cause of a bug before changing any code. Use whenever something is already broken or behaving unexpectedly - a failing or flaky test, crash, exception, stack trace, regression, build break, performance problem or integration failure - and especially when guessing at a fix is tempting. Not for writing new features or reviewing code that works. license: MIT --- # Systematic debugging When something breaks, the fastest-feeling move is to edit the line where the error appears and run it again. That usually fixes where the problem shows up, not where it starts. The symptom goes quiet, the cause stays, and it comes back somewhere harder to see. ## The rule ``` NO FIX WITHOUT A ROOT CAUSE YOU CAN EXPLAIN ``` If you cannot say "this fails because X, and here is the evidence", you are not ready to propose a fix. Finish phase 1 first. A fix you cannot explain is a guess, and a guess adds a variable instead of removing the broken one. The process matters most when it feels least affordable: - **Under time pressure.** A wrong guess extends the outage and you still have to debug afterward. - **When one quick fix looks obvious.** The obvious fix is often the symptom. Two minutes confirming the cause costs less than two minutes patching. - **After a fix did not work.** A failed fix is data, not a reason to stack a second guess on it. - **When you do not fully understand the problem.** "I don't understand X yet" is the right state to be in before phase 1. Say it. Do not paper over it. "It is a simple bug" is not an exception. Simple bugs have causes too, and the process is quick when the bug really is simple. ## Four phases Finish each one before starting the next. ### Phase 1: find the cause Do this before touching any code. 1. **Read the error properly.** The whole message and stack trace, line numbers, file paths, error codes. Errors often name the cause outright. 2. **Reproduce it on demand.** What are the exact steps? Does it happen every time? If you cannot reproduce it, you cannot confirm a fix later, so gather more data instead of guessing. 3. **Check what changed.** Recent commits and diffs, new dependencies, config or environment differences. "It worked before" means something changed. Find it. 4. **Instrument the boundaries of a multi-part system.** For a chain such as CI, build, sign, or request, service, database, do not guess which part is at fault. At each boundary log what goes in and what comes out, and check that config and environment values arrived intact. Run it once and let the output show where it breaks. Then investigate that part. 5. **Trace the bad value backward.** When the error is deep in a call stack, ask where the bad value came from and what called this code with it. Keep going up until you reach the origin, and fix it there, not where it blew up. If you cannot trace it by reading, add a temporary log or a stack trace at the point where the bad value first appears. Phase 1 is done when you can state what is failing and why, with evidence. ### Phase 2: compare with what works 1. **Find a working example** of something similar in the same codebase. 2. **Read the reference completely** if you are following a pattern. Do not skim and do not adapt from memory. 3. **List every difference** between working and broken, however small. Do not decide "that cannot matter". 4. **Understand the dependencies:** what settings, config, environment and assumptions does the code need? ### Phase 3: one hypothesis at a time 1. **State it.** "I think X is the cause because Y." Write it down. Be specific. 2. **Test it with the smallest change** that could prove it wrong. One variable at a time. Never fix several things at once. 3. **Check the result.** It worked: go to phase 4. It did not: form a new hypothesis. Do not add more fixes on top of the failed one. 4. **If you do not know, say so** and research or ask. Do not pretend. ### Phase 4: fix the cause 1. **Write a failing test that reproduces the bug**, the simplest one you can. Use an automated test if the project has a framework, and a small script if it does not. The `test-driven-development` skill covers how. Have this before the fix. 2. **Make one fix** for the cause you found. No "while I'm here" cleanups and no bundled refactoring. 3. **Verify.** The test passes, nothing else broke, and the original problem is actually gone. Run the whole suite and check the original symptom directly. 4. **If the fix did not work, stop and count.** Fewer than three attempts: go back to phase 1 with what you just learned. Three or more: do not try a fourth. Question the design, below. If you were handed this work by another agent or a person, report back as blocked with your evidence instead of trying a fourth fix yourself, so the one who owns the decision can make it. ## Three failed fixes means look at the design Suspect the architecture when each fix reveals a new shared-state or coupling problem somewhere else, when fixes would need a large refactor, or when each fix creates new symptoms elsewhere. That is not a failed hypothesis. It is a design that keeps producing the bug. Stop patching, ask whether the pattern is sound or whether you are continuing out of inertia, and raise it with the user before another fix. ## Techniques for particular situations **Bad data arriving from far away.** After you find the origin, also validate at the layers between the origin and the failure, so the same bad value is rejected early next time instead of travelling. Fixing it at the source and checking it along the way together make the bug structurally hard to repeat. **Flaky or timing-dependent tests.** Do not guess at a delay. Wait for the actual condition: poll until the thing you need is true, with a timeout and a clear failure message. An arbitrary sleep hides the race instead of fixing it. **One test breaks another.** The first test is leaving state behind. Bisect: run the suspect pair, then halve the set of tests that run before the failing one until the polluter is alone. Fix the state it leaks. ## Stop and go back to phase 1 if you catch yourself thinking - "Quick fix for now, investigate later." - "Let me just try changing X and see." - "I'll make several changes and run the tests." - "I'll skip the test and check it by hand." - "It's probably X." Said from the symptom alone. - "I do not fully understand it, but this might work." - Listing fixes before you have traced the data. - "One more attempt", after two failed ones. Other people's questions are signals too. "Is that actually happening?" means you assumed without checking. "Will that show us where it breaks?" means gather evidence first. "Stop guessing" means you are proposing fixes without understanding. "Are we stuck?" means the current approach is not working, so change it instead of repeating it. ## Excuses you will hear yourself make | Excuse | Reality | |---|---| | "It is simple, no process needed" | Simple bugs have causes, and the process is fast for them. | | "It is an emergency" | Guessing and re-guessing is slower than finding the cause. | | "Try this first, then investigate" | The first fix sets the pattern. Start the right way. | | "I will write the test after the fix works" | Untested fixes do not stick. Writing the test first proves it. | | "Several fixes at once saves time" | You cannot tell which one worked, and you add new bugs. | | "The reference is long, I will adapt the pattern" | Partial understanding produces bugs. Read all of it. | | "I can see the problem" | Seeing a symptom is not understanding the cause. | | "One more attempt" | After two failures, question the design. | ## When the investigation finds no single cause Sometimes a thorough investigation shows the problem really is environmental, timing-dependent or external. Then you have completed the process, and that is a legitimate result. Write down what you checked and ruled out, handle it properly (a retry, a timeout, a clear error message, waiting on the condition), and add logging so a recurrence leaves evidence. Be honest, though: most "there is no root cause" conclusions are really "I stopped investigating too early". Check that you traced the data flow before you reach for this. ## Quick reference | Phase | What you do | Done when | |---|---|---| | 1. Find the cause | Read the error, reproduce, check changes, instrument boundaries, trace backward | You can say what fails and why, with evidence | | 2. Compare | Find working examples, list every difference | You know what differs | | 3. Hypothesize | One theory, smallest test | It is confirmed, or you have a new theory | | 4. Fix | Failing test, one fix, verify | The bug is gone and the suite is green |
The second audit
What we found in the sources
It keeps the four-phase process of the version most others derive from (obra/superpowers), makes it stand alone, and removes claims no source backs up. Every source below was read at the commit the auditor recorded. Nothing was taken from a source without a permissive license.
What each source contributed
- obra/superpowers ↗ · Primary basis · MIT
The rule (no fix without a root cause), the four phases, instrumenting component boundaries, the three-failed-fixes-means-question-the-design rule, the red-flags list, the excuses table and the quick reference.
- phmatray/ai-migration-kit ↗ · Structure and wording · MIT
The framing that a symptom fix hides the cause, the sharper trigger description with an explicit "not for" clause, the point that "I don't understand yet" is the correct starting state, the "no single cause is a legitimate result, but check you did not stop early" section, and the list of companion techniques (tracing, defense in depth, condition-based waiting, bisecting for a polluting test).
- lsy041015/orchestra ↗ · Added idea · MIT
When you were handed the work, report blocked with the evidence instead of making a fourth attempt.
What changed
- The description says what the skill does and what it is not for, with the symptoms that should trigger it. Upstream's was only "Use when encountering any bug, test failure, or unexpected behavior, before proposing fixes".
- The four companion techniques (tracing a value backward, defense in depth, waiting on a condition, bisecting a test that pollutes state) were separate files in the sources. They are now short sections in the skill so a lone copy is complete. These were written fresh from the one-line descriptions the sources give; the companion files themselves were not fetched or read.
- Dropped every statistic. Upstream says "95% of no-root-cause cases are incomplete investigation", and older clones add a "Real-World Impact" table of timings and success rates. No source gives a basis for any of those numbers. The qualitative point is kept.
- Fixed upstream's dangling pointer "see Phase 4.5" (the section is Phase 4, step 5), and removed the "superpowers:" namespace on the skills it names.
- Replaced "your human partner" with "the user" or "a person", and the section of user catch-phrases with the same signals in neutral wording.
- Removed the macOS code-signing example for boundary logging in favor of a description that works for any chain of components.
Problems found in the sources
- obra/superpowers: The description gives only the trigger. The skill points to three companion files and to skills by a "superpowers:" namespace, so a lone copy has dangling references. It cites "Phase 4.5", which does not exist (the section is Phase 4, step 5). It states "95% of no-root-cause cases are incomplete investigation" with no basis given.
- jsonlee12138/agent-team: Adds a "Real-World Impact" section: 15 to 30 minutes versus 2 to 3 hours, and a 95% versus 40% first-time fix rate. No source or measurement is given. The same table appears in gylove1994/superpowers-deepseek-v4.
- gylove1994/superpowers-deepseek-v4: Adds an instruction to invoke confirming-worktree-before-edit before any edit, a skill that is not part of this one. Cannot be satisfied without it.
- phmatray/ai-migration-kit: Names companion files (root-cause-tracing.md, defense-in-depth.md, condition-based-waiting.md, find-polluter.sh) and says they are in the same directory, but only SKILL.md was audited, so a lone copy points at files that are not there.
What was dropped
- The "Real-World Impact" timings and success rates found in older clones (see findings).
- The worktree hard-gate added by gylove1994/superpowers-deepseek-v4, which depends on a skill that is not here.
- The Codex-delegation machinery of mzored/superpowers-cc-to-codex, which is tied to those tools.
Read but not used (9)
- VictorStochero/fluxo-orca: Upstream with only the skill names re-pointed (identical apart from two lines).
- gylove1994/superpowers-deepseek-v4: Upstream plus the worktree gate, an opening sentence and the unsourced statistics.
- jnmetacode/superpowers-zh: A Chinese translation of upstream.
- leodorareluctant259/superpowers-zh: A Chinese translation of upstream.
- cheng6563/litepowers: A short Chinese-language summary (about 1 KB).
- jsonlee12138/agent-team: Upstream with its skill names changed plus the unsourced statistics.
- mzored/superpowers-cc-to-codex: A port that hands investigation and fixes to Codex tools, invocable only on request. Its header says it diverges from upstream deliberately.
- sitien173/superpowers-ccg: A very short summary that leaves delegation and the regression-test cycle to other skills.
- thepragmaticbear/bearpaws: Upstream recast in XML tags and shortened.
Left out for license (5)
No license is declared on these, so nothing was taken from them: Athyrr/aikit, Fintama/swisper-superpowers, Itzalive/resistance-ai, lukekeith/builder, orkeren21/shipshape.
Same text, wherever you work
Use it where you work
Copy the folder into your skills directory, then ask for the job or type its start command.
- Download
SKILL.mdwith the button above, and put it in a folder namedsystematic-debugging. - Zip the folder.
- In Claude, open Settings → Skills and upload the zip.
SKILL.md is plain Markdown. Copy the text and paste it as the system prompt or the first message. It will not trigger by itself there; you start it.