$npx -y skills add neuromechanist/research-skills --skill debuggingUse this skill when the user asks to \"debug\", \"find the root cause\", \"figure out why X fails\", \"investigate this bug\", \"this test is flaky\", \"the build broke\", \"production incident\", \"why is the output wrong\", or when any observed behavior contradicts expected beh
| 1 | # Debugging |
| 2 | |
| 3 | A disciplined root-cause loop. The goal is a stated causal mechanism with |
| 4 | proof, then a fix verified by the exact check that first exposed the problem. |
| 5 | Never fix by guessing, and never make a symptom disappear without knowing why. |
| 6 | |
| 7 | ## The loop |
| 8 | |
| 9 | 1. **Reproduce.** Run the failing thing yourself and capture the exact error, |
| 10 | command, and environment. If you cannot reproduce, stop and gather the |
| 11 | reporter's exact conditions; do not fix blind. Side observations found on |
| 12 | the way get noted and set aside, not chased. |
| 13 | 2. **Trace the intended path.** Before reading logs, read the code/docs to |
| 14 | state what SHOULD happen, step by step. You cannot recognize the broken |
| 15 | step without knowing the intended sequence. |
| 16 | 3. **Check live state.** What is actually on disk, in the database, running as |
| 17 | a process, deployed? A grep that finds no trace of a migration is not proof |
| 18 | it never ran; completed one-off scripts are routinely deleted. Absence in |
| 19 | code is not absence in reality. |
| 20 | 4. **Find the smoking gun.** Logs, CI runs, git history. Cheapest checks |
| 21 | first: installed version vs latest, the artifact's own declared type or |
| 22 | config, the library's supported list. Only conclude "unsupported" or |
| 23 | "impossible" after checking the declared capability directly. |
| 24 | 5. **Prove the mechanism.** Confirm with a live probe, not log trust (example: |
| 25 | the blob that returned 403 in the failing run returns 200 now, so it was a |
| 26 | permission-timing issue, not missing data). A differential test beats an |
| 27 | assumption: when two configurations should differ, run both and compare. |
| 28 | 6. **Only now read source for the WHY**, and state the cause in one sentence |
| 29 | with the evidence that proves it, plus what changes AND what deliberately |
| 30 | does not change because it was not the cause. |
| 31 | 7. **Fix**, minimally. Fix the upstream cause, not the symptom (a service that |
| 32 | dies when the machine sleeps needs the sleep addressed, not a restart |
| 33 | loop). |
| 34 | 8. **Verify with the original failing check**, unchanged. Then run the wider |
| 35 | gates (tests, lint, typecheck). Add a regression test that would have |
| 36 | caught this bug. If recovery of live state was part of the fix, its success |
| 37 | doubles as diagnosis confirmation. |
| 38 | |
| 39 | ## Isolation techniques (when the cause is entangled) |
| 40 | |
| 41 | - **Single-variable toggles**: flip one factor at a time (feature flag, config |
| 42 | bit, environment) and record the result per state. Never attempt a compound |
| 43 | fix while two candidate causes are still entangled. |
| 44 | - **Necessary-but-not-sufficient check**: after any partial fix, re-run the |
| 45 | original failing check. The first improving number is not proof of a |
| 46 | complete fix; say "necessary but not sufficient" and keep going. |
| 47 | - **Ranked compounding causes**: many incidents have several contributing |
| 48 | causes (stale binary + lost race + shared timeout). Enumerate and rank them; |
| 49 | do not stop at the first plausible one. |
| 50 | - **Confound check**: before concluding "the fix did not work" or "the test is |
| 51 | wrong", look for an independent confound (a second process racing the test, |
| 52 | a hook rewriting the file). Re-run clean. |
| 53 | - **Instrumentation-first for weird results**: a flat or extreme result that |
| 54 | fails to discriminate across conditions that should matter is an |
| 55 | instrumentation bug until a targeted, isolated reproduction says otherwise. |
| 56 | Do not report it as a finding, and do not let it block unrelated work while |
| 57 | you wait to reproduce it. |
| 58 | - **Doc-vs-code conflicts**: when documentation (or an Architecture Decision |
| 59 | Record) and code disagree, determine the actual source of truth |
| 60 | empirically (test the code), then fix whichever artifact is wrong, making |
| 61 | the fix more precise about where the invariant is enforced. Never silently |
| 62 | pick a side. |
| 63 | |
| 64 | ## Anti-shortcut gates (hard rules) |
| 65 | |
| 66 | - Never delete, skip, or loosen a failing test to make a suite pass. If a test |
| 67 | is genuinely wrong, prove it (git history: did the tested thing move or |
| 68 | disappear?) and say so explicitly. |
| 69 | - Never add a broad catch, silent fallback, or retry loop to make a symptom |
| 70 | disappear. That converts a loud bug into a silent one. |
| 71 | - Never weaken a designated safety mechanism (rate limit, halt, permission |
| 72 | gate) because it fired. When a guardrail fires during a bad outcome, the |
| 73 | default hypothesis is that the new code is incompatible with a correct |
| 74 | guardrail. Changing the guardrail requires separate, explicit user sign-off. |
| 75 | - Never read or print secrets (.env contents, tokens) while debugging |
| 76 | credential or environment issues; test credentials differentially instead |
| 77 | (call the |