debug
Skill45 starsChanged 4 days agoMITView on GitHub
This skill should be used when investigating bugs, unexpected behavior, test failures, or any code that does not work as expected - enforces systematic root cause analysis before any fix
- Installs packages
192 other projects use a version of this.
Adopted by
Most recently taken up by
- PeanutGT/NutsSkillstheir own version, first seen Nov 8, 2026
- jskswamy/skillstheir own version, first seen Nov 8, 2026
- Firzus/agent-skillstheir own version, first seen Nov 8, 2026
- domengabrovsek/agent-configtheir own version, first seen Nov 8, 2026
- domengabrovsek/claudetheir own version, first seen Nov 8, 2026
- microsoft/veronatheir own version, first seen Nov 8, 2026
Used with
Projects with it also use add-discord, add-slack and 10 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
MicrosoftSkilladd-discord
Add Discord bot channel integration via Chat SDK.
Also in 11 projects that use this
MicrosoftSkilladd-slack
Add Slack channel integration via Chat SDK.
Also in 11 projects that use this
- +10 more from microsoft
Other versions192 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 192
- Yeachan-Heo/oh-my-claude-sisyphus★ 41ksame name
- Yeachan-Heo/oh-my-claudecode★ 41ksame name
- anthropics/knowledge-work-plugins★ 35ksame name
- gavrielc/nanoclaw★ 31ksame name
- nanocoai/nanoclaw★ 31ksame name
- qwibitai/nanoclaw★ 31ksame name
- openai/symphony★ 27ksame name
- FalkorDB/FalkorDB★ 10ksame name
- NVIDIA/TensorRT-Model-Optimizer★ 5.6ksame name
- NVIDIA/Model-Optimizer★ 5.6ksame name
182 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository43 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- build-unplannedSkill
- check-specs-alignmentSkill
- create-tasksSkill
- design-architectureSkill
- design-it-twiceSkill
- design-productSkill
- domain-modelingSkill
- doubt-driven-developmentSkill
- finalize-taskSkill
- groundwork-checkSkill
- groundwork-helpSkill
- handoffSkill
- implement-taskSkill
- instrument-observabilitySkill
- just-do-itSkill
- just-do-it-swarmingSkill
- plan-taskSkill
- review-prSkill
- select-projectSkill
- setup-repoSkill
- shipSkill
- skillsSkill
- source-architecture-from-codeSkill
- source-product-specs-from-codeSkill
- source-ux-design-from-codeSkill
- split-architectureSkill
- split-specsSkill
- staged-rolloutSkill
- statuslineSkill
- swarm-debugSkill
- swarm-design-architectureSkill
- task-validation-loopSkill
- test-driven-developmentSkill
- understanding-feature-requestsSkill
- use-git-worktreeSkill
- using-groundworkSkill
- ux-designSkill
- validateSkill
- vertical-sliceSkill
- work-on-next-taskSkill
- work-onSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
52 rules. 0 are common, 47 are distinctive, and 5 are very specific to this project.
0
Common
Most of the 175 edited versions we read keep these.
47
Distinctive
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 13
Core principle: If you can't explain why the bug happens, you don't know if your fix is correct.
- Very specific: line 22
If effort is low or medium (i.e.
- Distinctive: line 23
If you are not Opus (1M context), you MUST show the recommendation prompt - regardless of effort level.
- Distinctive: line 41
If the user selects "Cancel — I'll switch first": output the switching commands above and stop.
- Distinctive: line 67
Don't "try a quick fix to see if it works"
- Distinctive: line 68
Don't change multiple things hoping one helps
- Distinctive: line 69
Don't fix symptoms instead of causes
- Distinctive: line 70
Don't skip reproduction because "it's obvious"
- Distinctive: line 104
Read the system. Check your assumptions.
- Distinctive: line 106
Before investigating the bug, understand the code it lives in.
- Distinctive: line 109
Read the relevant source files end-to-end (not just the failing line)
- Distinctive: line 112
Check the obvious: dependencies installed?
- Distinctive: line 113
Read error messages completely — stack traces, line numbers, all of it
- Distinctive: line 114
Use git to fetch recent changes
- Distinctive: line 131
Don't guess which layer is broken.
- Distinctive: line 158
Don't assume the obvious is fine.
- Distinctive: line 164
If you can't reproduce it, you can't prove you fixed it.
- Distinctive: line 167
Create a minimal reproduction (smallest input that triggers the bug)
- Distinctive: line 168
Run it. Watch it fail. Note the exact output.
- Distinctive: line 169
Run it again. Confirm it fails the same way.
- Distinctive: line 170
Add instrumentation (logging, breakpoints) if the failure path is unclear
- Distinctive: line 171
Document the reproduction steps in the debug journal
- Distinctive: line 181
Before proceeding to Phase 3, your debug journal MUST contain:
- Distinctive: line 186
Static code reading is NOT reproduction: If you have only read source files and formed theories about what might happen, you are still in …
- Distinctive: line 192
Check timing/race conditions
- Distinctive: line 194
Add logging and wait for it to recur
- Distinctive: line 195
Don't guess. If you can't reproduce it, you can't fix it.
- Distinctive: line 198
Add temporary logging/instrumentation to the actual code FIRST
- Distinctive: line 199
Ask the user to trigger the bug with your instrumentation in place
- Distinctive: line 200
Read the instrumented output — this is your reproduction evidence
- Distinctive: line 201
Do NOT proceed to Phase 3 based on code reading alone
- Distinctive: line 202
If instrumentation isn't possible either, document WHY in the journal and escalate to your human partner for reproduction assistance
- Distinctive: line 212
Test the hypothesis. One change at a time.
- Distinctive: line 228
When dispatching subagents for parallel investigation:
- Distinctive: line 238
Don't combine hypotheses ("maybe it's A and B together")
- Distinctive: line 239
If you changed two things and it worked, you don't know which one fixed it
- Distinctive: line 299
Run the failing test — it must pass now
- Distinctive: line 300
Run the full test suite — nothing else broke
- Distinctive: line 303
Check for related code paths — could the same bug exist elsewhere?
- Distinctive: line 317
3-fix limit: If your third fix attempt fails, stop and escalate.
- Distinctive: line 368
Use that literal resolved path everywhere for the rest of the session — including in every subagent prompt — so the path can never drift …
- Very specific: line 372
One-time migration: if a legacy journal for this slug exists at the unscoped repository-root location .debug/{slug}.md while {{debug_dir}} …
- Distinctive: line 430
Update the journal as you work: Every hypothesis, every test, every result goes in the journal.
- Distinctive: line 443
Rule: Never fix based on an unverified root cause: If your confidence is "unverified," you're guessing.
- Distinctive: line 477
Rule: Treat pushback as data, not criticism.
- Distinctive: line 518
Document what was investigated and eliminated: Every hypothesis tested, every result observed.
- Distinctive: line 530
If there are gaps, go back and fill them.
- Very specific: line 538
Read the profile endpoint handler, the user service, and the database query.
- Distinctive: line 540
Check the plug: database connected, service running, other endpoints working fine.
- Very specific: line 564
Test: Read getUserProfile — it does user.preferences.theme with no null check.
- Very specific: line 582
Test fails with TypeError: Cannot read property 'theme' of null.
- Distinctive: line 608
No exceptions without your human partner's permission.
“Common” is measured: kept by at least 6 in 10 of the 175 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Debugging
Overview
Find the root cause. Prove it. Then fix it.
Core principle: If you can't explain why the bug happens, you don't know if your fix is correct.
Violating the letter of the rules is violating the spirit of the rules.
Pre-flight: Model Recommendation
Your current effort level is {{effort_level}}.
Skip this step silently if effort is high, xhigh, or max (the scale is low < medium < high < xhigh < max, so xhigh and max are already above high) AND you are Opus (1M context).
If effort is low or medium (i.e. below high), you MUST show the recommendation prompt — regardless of model.
If you are not Opus (1M context), you MUST show the recommendation prompt - regardless of effort level.
Otherwise → use AskUserQuestion:
{
"questions": [{
"question": "Do you want to switch? Falsifiable hypothesis formation and resisting the temptation to jump to fixes benefit from deeper reasoning.\n\nTo switch: cancel, run `/model opus[1m]` and `/effort high`, then re-invoke this skill.",
"header": "Recommended: Opus (1M context) at high effort",
"options": [
{ "label": "Continue" },
{ "label": "Cancel — I'll switch first" }
],
"multiSelect": false
}]
}If the user selects "Cancel — I'll switch first": output the switching commands above and stop. Do not proceed with the skill.
When to Use
Always:
- Test failures
- Unexpected behavior
- Error messages
- Regressions
- "It works on my machine" situations
Exceptions (ask your human partner):
- Typos and obvious one-character fixes
- Configuration value changes with known correct values
Thinking "I already know the fix"? Stop. That's guessing, not debugging.
The Iron Law
NO CODE CHANGES UNTIL YOU CAN EXPLAIN THE ROOT CAUSEThink you know the fix? Prove the root cause first. Then fix.
No exceptions:
- Don't "try a quick fix to see if it works"
- Don't change multiple things hoping one helps
- Don't fix symptoms instead of causes
- Don't skip reproduction because "it's obvious"
Understand first. Fix second. Period.
Five-Phase Workflow
digraph debugging {
rankdir=LR;
understand [label="UNDERSTAND\nRead the system", shape=box, style=filled, fillcolor="#cce5ff"];
reproduce [label="REPRODUCE\nMake it fail", shape=box, style=filled, fillcolor="#ffcccc"];
isolate [label="ISOLATE\nDivide and\nconquer", shape=box, style=filled, fillcolor="#fff3cc"];
fix [label="FIX\nMinimal change\n+ failing test", shape=box, style=filled, fillcolor="#ccffcc"];
verify [label="VERIFY\nProve it's fixed", shape=box, style=filled, fillcolor="#ccccff"];
escalate [label="ESCALATE\nReport to human", shape=box, style=filled, fillcolor="#ffccee"];
journal [label="DEBUG JOURNAL\n{{debug_dir}}/{slug}-xxxxxx/journal.md", shape=note, style=filled, fillcolor="#f0f0f0"];
understand -> reproduce;
reproduce -> isolate;
isolate -> fix;
fix -> verify;
verify -> fix [label="fix failed\n(max 3)"];
verify -> escalate [label="3 fixes\nfailed"];
understand -> journal [style=dashed];
reproduce -> journal [style=dashed];
isolate -> journal [style=dashed];
fix -> journal [style=dashed];
verify -> journal [style=dashed];
}Phase 1: UNDERSTAND
Read the system. Check your assumptions. Don't touch anything yet.
Before investigating the bug, understand the code it lives in. Your mental model is a hypothesis — treat it as one.
Required steps:
- Read the relevant source files end-to-end (not just the failing line)
- Trace the code path from input to failure
- Identify what the code should do vs. what it does
- Check the obvious: dependencies installed? correct branch? config valid? environment correct?
- Read error messages completely — stack traces, line numbers, all of it
- Use git to fetch recent changes
- For multi-component systems (API → service → database, CI → build → deploy), instrument at each boundary before forming hypotheses. Run once, collect evidence from every layer, then analyze where the chain breaks.
Example — multi-layer instrumentation:
System: Frontend → API Gateway → Auth Service → Database
Step 1: Add logging at each boundary (request in, response out)
Step 2: Trigger the failure once
Step 3: Read the logs layer by layer:
- Frontend sent correct request ✓
- API Gateway forwarded correctly ✓
- Auth Service received request ✓
- Auth Service → Database query returned empty result ✗
- Auth Service returned 500 to Gateway
Conclusion: Problem is between Auth Service and Database.
Now investigate that specific boundary.Don't guess which layer is broken. Let the evidence from all layers tell you.
<Good>
```
Read the full function. Trace the call chain from the API endpoint
through the service layer to the database query. Found that
`getUserById` is called with a string ID but the query expects
an integer. The type mismatch happens at the controller layer.
```
Reads the system, traces the path, identifies the discrepancy
</Good><Bad>
```
The error says "invalid input" so I'll add input validation
to the endpoint.
```
Didn't read the code, didn't trace the path, guessed at a fix
</Bad>Check the plug:
- Is the service running?
- Is the database connected?
- Are environment variables set?
- Is the right version deployed?
- Did a dependency update break something?
Don't assume the obvious is fine. Verify it.
Phase 2: REPRODUCE
Make it fail. Consistently. On demand.
If you can't reproduce it, you can't prove you fixed it. Observation before theory — watch what actually happens, don't theorize about what might happen.
Required steps:
- Create a minimal reproduction (smallest input that triggers the bug)
- Run it. Watch it fail. Note the exact output.
- Run it again. Confirm it fails the same way.
- Add instrumentation (logging, breakpoints) if the failure path is unclear
- Document the reproduction steps in the debug journal
Reproduction checklist:
- Can trigger the bug on demand
- Same failure every time (or documented intermittent pattern)
- Minimal reproduction — removed everything not needed to trigger it
- Exact error output recorded
Phase 2 Gate — MANDATORY
Before proceeding to Phase 3, your debug journal MUST contain:
- The exact command/steps you executed (not theorized about)
- The exact error output you observed (not inferred from code)
- Confirmation this matches the user-reported symptoms
Static code reading is NOT reproduction. If you have only read source files and formed theories about what might happen, you are still in Phase 1.
Simulation is NOT reproduction. Writing scripts that mimic what the code would do (e.g., Node.js scripts simulating CoffeeScript logic, Python scripts simulating import resolution) is theorizing, not reproducing. Run the actual code path instead.
Can't reproduce?
- Check environment differences
- Check timing/race conditions
- Check data-dependent paths
- Add logging and wait for it to recur
- Don't guess. If you can't reproduce it, you can't fix it.
Can't execute directly? (GUI app, external service, no local environment)
- Add temporary logging/instrumentation to the actual code FIRST
- Ask the user to trigger the bug with your instrumentation in place
- Read the instrumented output — this is your reproduction evidence
- Do NOT proceed to Phase 3 based on code reading alone
- If instrumentation isn't possible either, document WHY in the journal and escalate to your human partner for reproduction assistance
Phase 3: ISOLATE
Narrow the search space. One variable at a time.
Form hypotheses. Make them falsifiable. Test them. Eliminate possibilities systematically — don't jump to conclusions.
Required steps:
- Form a specific, falsifiable hypothesis: "The bug occurs because X. If I do Y, I should see Z."
- Test the hypothesis. One change at a time.
- Record the result: confirmed or eliminated.
- Repeat until the root cause is isolated.
Investigation Techniques
| Technique | When to Use | How |
| Binary search | Large code path, unknown location | Comment out half the code path. Bug gone? It's in that half. Repeat. |
| Differential debugging | Worked before, broken now | Compare working vs. broken state. git bisect, diff configs, diff dependencies. |
| Minimal reproduction | Complex system, many variables | Strip away components until the simplest case that still fails. |
| Working backwards | Clear error, unclear cause | Start at the error. Trace backwards through the call chain. |
| Rubber duck | Stuck, circular thinking | Explain the bug out loud, step by step. The gap in your explanation is the gap in your understanding. |
Spawning Investigation Subagents
When dispatching subagents for parallel investigation:
- Pass context forward — Include files already read and findings so far in the subagent prompt, not just "investigate X"
- Specify concrete actions — "Run
pip install --target $(mktemp -d)and return the error output" not "explore the dependency setup" - Require reproduction — Subagents must execute the failing operation, not just read code
- Reference the debug journal — Pass the literal resolved journal path (not the
{slug}pattern) and tell the subagent to read it first so it doesn't repeat prior work - Validate findings — If a subagent returns without direct evidence (only file reads, no command output), run the reproduction yourself before accepting its conclusions
One thing at a time:
- Change one variable per test
- Revert changes that didn't help
- Don't combine hypotheses ("maybe it's A and B together")
- If you changed two things and it worked, you don't know which one fixed it
<Good>
```
Hypothesis: The timeout occurs because the connection pool is exhausted.
Test: Log active connections before the failing request.
Result: 50/50 connections active. Confirmed — pool exhaustion.
Next: Why aren't connections being released?
```
Falsifiable hypothesis, tested, confirmed, asks next question
</Good><Bad>
```
Might be a timeout issue. Let me increase the timeout to 30s.
Also bump the connection pool to 100. And add a retry.
```
Three changes at once, no hypothesis, no understanding
</Bad>Phase 4: FIX
State the root cause. Write a failing test. Make the minimal fix.
You've isolated the root cause. Now prove it with a test, then fix it.
Required steps:
- State the root cause — Write it in the debug journal with a verification level (see Verification Levels below)
- Write a failing test — Invoke
Skill(skill="groundwork:test-driven-development")and follow the TDD cycle. The test must reproduce the exact bug. - Minimal fix only — Change the least amount of code to fix the root cause. Don't refactor. Don't "improve" nearby code. Don't fix other bugs you noticed.
- One change at a time — If the fix requires multiple changes, make them incrementally.
<Good>
```
Root cause: getUserById passes string ID to SQL query that
expects integer. Connection pool exhaustion is a symptom —
queries hang waiting for type coercion timeout.Fix: Parse ID to integer at the controller layer before passing to the service.
Root cause stated, explains the symptom chain, minimal targeted fix
</Good>
<Bad>Fixed the timeout by:
- Increasing pool size to 200
- Adding parseInt to 5 different endpoints
- Refactoring the connection manager
- Adding retry logic to all database calls
Shotgun fix, no root cause stated, changes way beyond the bug
</Bad>
## Phase 5: VERIFY
Prove the fix works. Prove nothing else broke. Get a fresh perspective.
**Required steps:**
1. Run the failing test — it must pass now
2. Run the full test suite — nothing else broke
3. Re-run the original reproduction — the bug is gone
4. Review your fix with fresh eyes — does it actually address the root cause, or mask it?
5. Check for related code paths — could the same bug exist elsewhere?
**Verification checklist:**
- [ ] Failing test now passes
- [ ] Full test suite passes
- [ ] Original reproduction no longer triggers the bug
- [ ] Fix addresses root cause (not symptoms)
- [ ] No unrelated changes included
- [ ] Related code paths checked for same bug
**Fix didn't work?** Go back to Phase 3. Your root cause analysis was wrong. Don't patch the patch — re-investigate.
## Escalation Rules
**3-fix limit.** If your third fix attempt fails, stop and escalate.
Three failed fixes means your root cause analysis is wrong. More attempts won't help — you need a different perspective.
**Question the architecture.** Three failed fixes often signal something deeper than an incomplete investigation. The bug may exist because the design is fundamentally unsound — a race condition baked into the concurrency model, a data integrity problem caused by a missing constraint, a failure mode that the architecture doesn't account for. When you escalate, shift the question from "help me fix this bug" to "is this design sound?"
**Escalation output format:**
```markdown
## Escalation: [Bug Description]
### What I tried
| # | Hypothesis | Fix Attempted | Result |
|---|-----------|---------------|--------|
| 1 | [hypothesis] | [what you changed] | [what happened] |
| 2 | [hypothesis] | [what you changed] | [what happened] |
| 3 | [hypothesis] | [what you changed] | [what happened] |
### Eliminated hypotheses
- [hypothesis]: eliminated because [evidence]
### What I know
- [confirmed fact with evidence]
### Could this be architectural?
[If 3 fixes failed, consider whether the bug reflects a design problem, not just a code problem. What assumption does the current architecture make that might be wrong?]
### Recommended next step
[specific suggestion for the human partner]Revert all failed fix attempts. Leave the codebase clean.
Debug Journal
Maintain a persistent debug journal at an invocation-unique path — the slug plus this run's identity — never at a fixed slug-only name. Concurrent debugging of the same bug in the same project would silently overwrite a fixed journal; a unique path gives every invocation its own intact record, and prior work is found by slug prefix when resuming.
{{debug_dir}} resolves inside the selected project's root (mirroring {{plans_dir}}), so the same bug slug in two monorepo projects produces two distinct journal locations instead of colliding at the repository root.
Derive the slug once, at the start of Phase 1: kebab-case of the bug's one-line description, truncated to 40 characters (e.g. "login timeout on token refresh" → login-timeout-on-token-refresh). Then allocate the journal's run directory once — an atomically unique mktemp directory keyed on the slug:
mkdir -p {{debug_dir}}
grep -qxF '.debug/' .gitignore 2>/dev/null || printf '.debug/\n' >> .gitignore
RUN_DIR="$(mktemp -d "{{debug_dir}}/${SLUG}-XXXXXX")"
JOURNAL_PATH="$RUN_DIR/journal.md"The .gitignore pattern is unanchored, so it covers debug directories at any project depth; the append is idempotent.
Use that literal resolved path everywhere for the rest of the session — including in every subagent prompt — so the path can never drift between derivations, and return it in your final output and any handoff so the next session can adopt it directly.
Resuming prior work on the same slug: find earlier run directories by slug prefix — ls -dt {{debug_dir}}/${SLUG}-*/ — and read the journal inside. If more than one match exists, do not silently pick one: use the literal journal path from your handoff, or ask the user which run to continue. Then continue writing to your own invocation-unique journal (never a shared current pointer, never the older file).
One-time migration: if a legacy journal for this slug exists at the unscoped repository-root location .debug/{slug}.md while {{debug_dir}} points elsewhere, move it into a fresh run directory with two visible commands and say so — do not keep reading the legacy location:
RUN_DIR="$(mktemp -d "{{debug_dir}}/{slug}-migrated-XXXXXX")"
mv .debug/{slug}.md "$RUN_DIR/journal.md" # legacy location migration# Debug: {slug}
## Status
[Active | Root Cause Found | Fixed | Escalated]
## Symptoms
- [What the user or test reported]
- [Exact error messages]
- [When it started / what changed]
## Reproduction
### Command Executed
[The exact command you ran — NOT theoretical steps, NOT code you read]
### Actual Output
[Paste the exact error/output you observed when you ran it]
### Expected Output
[What should have happened instead]
### Matches User Report?
[Yes/No — does this reproduce the same symptoms the user described?]
## Hypotheses
### Active
- [ ] [Hypothesis]: [How to test it]
### Eliminated
- [x] [Hypothesis]: Eliminated because [evidence]
## Evidence Log
| # | Action | Observation | Conclusion |
|---|--------|-------------|------------|
| 1 | [what you did] | [what happened] | [what it means] |
## Root Cause
**Verification level:** [Verified | Corroborated | Unverified]
[Root cause statement]
[Evidence that confirms it]
## Fix
[What was changed and why]
## Resolution
[Final status, test references, PR link]Update the journal as you work. Every hypothesis, every test, every result goes in the journal. When context compacts, the journal remains.
Verification Levels
Root cause claims require a confidence level. This prevents false confidence and forces honest assessment.
| Level | Meaning | Required Before Fix? |
| Verified | Root cause proven by direct evidence (test reproduces it, fix resolves it, revert re-introduces it) | Yes — proceed to fix |
| Corroborated | Multiple independent observations support it, but no single definitive proof | Yes — proceed to fix with extra caution |
| Unverified | Single observation or logical inference only | No — gather more evidence first |
| Contradicted | Evidence conflicts with the hypothesis | No — eliminate this hypothesis |
Rule: Never fix based on an unverified root cause. If your confidence is "unverified," you're guessing. Go back to Phase 3.
Common Rationalizations
| Excuse | Reality |
| "I already know the fix" | Then prove the root cause first. Takes 2 minutes if you're right. |
| "Let me just try this quick fix" | Quick fixes become permanent. Understand first. |
| "The fix is obvious" | Obvious fixes for wrong root causes create new bugs. |
| "I'll investigate after I fix it" | You won't. And you can't verify a fix you don't understand. |
| "It's just a typo / off-by-one" | Verify. "Just a typo" has been wrong more times than right. |
| "I changed 3 things and it works now" | You don't know which one fixed it. Revert two. |
| "Reproducing is too hard, let me just fix it" | If you can't reproduce it, you can't verify the fix. |
| "I don't need a journal for something this simple" | Simple bugs that need journals are the ones that spiral. |
| "The tests pass, so it's fixed" | Tests pass ≠ root cause addressed. The symptom might be masked. |
| "Let me add a retry / increase the timeout" | That's masking, not fixing. Find why it fails. |
| "It works on my machine" | Then your machine isn't the one with the bug. Reproduce there. |
| "I've been debugging this for hours, let me just ship it" | Sunk cost. Escalate instead of shipping a guess. |
| "I'll simulate the logic to understand it" | Run the actual code. Simulation scripts are theories, not evidence. |
| "The subagent explored the codebase thoroughly" | Did it run the failing operation? Reading files is Phase 1, not Phase 3. |
Signals From Your Human Partner
During interactive debugging, your human partner's reactions are a signal channel. Frustration and redirection mean your process is off — not that the human is being difficult.
| What they say | What it means | What to do |
| "Is that not happening?" | You assumed something without verifying | Go back and verify with evidence |
| "Stop guessing" | You're proposing fixes without understanding | Return to Phase 1 — read the system |
| "We're going in circles" / frustrated tone | Your approach isn't working | Step back. Re-read from scratch. Your mental model is wrong. |
| "Did you actually check?" | You claimed something without evidence | Gather evidence first, then report what you found |
| "That's not the problem" | You're investigating the wrong thing | Ask what they're seeing. Their context is broader than yours. |
| "Just revert" | Your fixes are making things worse | Revert everything. Return to Phase 2 with a clean slate. |
Rule: Treat pushback as data, not criticism. If your human partner redirects you, the most productive response is to follow the redirect — not to defend your hypothesis.
Red Flags — STOP and Go Back to Phase 1
- Changing code without stating the root cause
- Multiple changes at once ("let me try a few things")
- Fix attempt #4+
- "I think it might be..." without a falsifiable test
- Increasing timeouts, pool sizes, or retry counts as a "fix"
- Adding error suppression (empty catch blocks, silent fallbacks)
- Can't explain why the fix works
- Fix is larger than the bug warrants
- Fixing a different bug than the one you started with
- No reproduction case
- No failing test
- Skipping the debug journal
- Forming hypotheses based only on code reading without running anything
- Writing simulation scripts instead of running the actual failing code
- Spawning investigation subagents without specifying what to execute
All of these mean: Stop. Go back to Phase 1. Understand the system.
When Stuck
| Problem | Solution |
| Can't reproduce | Check environment, timing, data. Add logging. Wait for recurrence. |
| Hypothesis keeps being wrong | Step back. Re-read the code from scratch. Your mental model is wrong. |
| Fix works but don't understand why | Revert. That's not a fix, it's an accident. Investigate why it works. |
| Too many variables | Simplify. Remove components until you find the minimal failing case. |
| Intermittent failure | Add instrumentation. Look for race conditions, timing, external state. |
| Stuck in a loop | Rubber duck. Explain the bug step by step. The gap is the clue. |
| Bug disappeared | It's hiding. Check if something else changed. Don't declare victory. |
| Fix breaks other tests | Your fix is wrong, or the other tests reveal a deeper issue. Investigate. |
When Investigation Finds No Root Cause
Sometimes systematic investigation legitimately concludes without a clear root cause — environmental issues, timing-dependent failures, external service flakiness, or bugs that disappear under observation. This is rare, but it happens.
When you genuinely cannot identify the root cause:
- Document what was investigated and eliminated. Every hypothesis tested, every result observed. This prevents the next investigator from repeating your work.
- Implement appropriate handling. Retry logic, timeouts, clearer error messages, or monitoring — not as a "fix," but as resilience for a known-unknown failure mode. Be explicit that this is mitigation, not a root cause fix.
- Add instrumentation for recurrence. Logging, metrics, or alerts that will capture more data when the failure happens again. Design the instrumentation to answer the specific questions you couldn't answer this time.
- Record in the debug journal with status "Inconclusive." Include what you know, what you don't, and what data would resolve it.
- Communicate honestly. Tell your human partner what you investigated, what you eliminated, and that you couldn't pin it down — not a vague "it should be fine now."
Caveat: 95% of "no root cause found" conclusions are actually incomplete investigations. Before declaring inconclusive, honestly assess:
- Did you complete all five phases?
- Did you actually reproduce the failure, or just read the code?
- Did you test falsifiable hypotheses, or just form opinions?
- Is the journal thorough, or are there gaps?
If there are gaps, go back and fill them. "Inconclusive" is a legitimate outcome — but only after exhausting the process, not instead of it.
Example: Full Walkthrough
Bug report: "API returns 500 on user profile page for some users"
Phase 1: UNDERSTAND
Read the profile endpoint handler, the user service, and the database query. The endpoint calls getUserProfile(id) which joins users and preferences tables.
Check the plug: database connected, service running, other endpoints working fine.
Phase 2: REPRODUCE
curl -s localhost:3000/api/profile/42 # 200 OK
curl -s localhost:3000/api/profile/107 # 500 Internal Server ErrorConsistent. User 42 works, user 107 fails. Minimal reproduction found.
Error log: TypeError: Cannot read property 'theme' of null
Phase 3: ISOLATE
Hypothesis 1: User 107 has a null preferences record.
Test: Query the database directly.
SELECT * FROM preferences WHERE user_id = 107;
-- Empty result setResult: Confirmed — user 107 has no preferences row.
Hypothesis 2: The JOIN returns null for preferences, and the code doesn't handle it.
Test: Read getUserProfile — it does user.preferences.theme with no null check.
Result: Confirmed. The LEFT JOIN returns null preferences, and the code assumes it exists.
Root cause: getUserProfile accesses preferences.theme without null-checking the join result. Users without a preferences row trigger a TypeError.
Verification level: Verified (direct evidence: null row + no null check + exact error match).
Phase 4: FIX
Failing test:
test('returns default theme when user has no preferences', async () => {
const user = await createUser({ id: 999 }); // no preferences row
const profile = await getUserProfile(999);
expect(profile.theme).toBe('default');
});Test fails with TypeError: Cannot read property 'theme' of null. Correct failure.
Fix:
const theme = user.preferences?.theme ?? 'default';Test passes.
Phase 5: VERIFY
- Failing test passes: yes
- Full test suite: all green
curl localhost:3000/api/profile/107: 200 OK, theme is "default"- Fix addresses root cause: null preferences handled
- Checked other code paths:
preferences.languagehas same bug — filed separate issue
Done.
Final Rule
Root cause identified → Fix with failing test → Verify fix
Otherwise → not debugging, just guessingNo exceptions without your human partner's permission.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

