Oracle Debug
Random fixes waste time and create new bugs. Quick patches mask underlying issues.
Core principle: find root cause before a permanent corrective fix. Temporary containment is
appropriate when needed to limit security, production, or data-loss impact.
Violating the letter of this process is violating the spirit of debugging.
The Iron Law
NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST
If you haven't completed Phase 1, you cannot propose fixes.
When to Use
Use for any technical issue:
- Test failures
- Bugs in production
- Unexpected behavior
- Performance regressions
- Build or integration failures
- Intermittent failures
Use this especially when:
- Under time pressure
- "Just one quick fix" seems obvious
- You've already tried multiple fixes
- The previous fix didn't work
- You don't fully understand the issue
The Four Phases
You must complete each phase before proceeding to the next.
Phase 1 — Root Cause Investigation
Before attempting any fix:
Use the project's domain glossary and ADRs to build a clear mental model of the
relevant modules before tracing.
Read error messages carefully. Read the full stack trace, line numbers, file paths, and error codes. Don't skip warnings.
Build a fast feedback loop. If you don't have a fast, deterministic, pass/fail signal for the bug, no amount of code-reading will save you. Spend disproportionate effort here.
Try these in order:
- Failing test at the seam that reaches the bug
- Curl / HTTP script against a running dev server
- CLI invocation with fixture input
- Headless browser script (Playwright/Puppeteer)
- Replay a captured trace (network payload, event log)
- Throwaway harness (minimal subset of the system)
- Property/fuzz loop for "sometimes wrong" bugs
- Bisection harness (e.g.,
git bisect run)
- Differential loop (old vs new version)
- HITL bash script (last resort — structure the human clicks)
Iterate on the loop: make it faster, sharper, and more deterministic. A 30-second flaky loop is barely better than no loop.
Reproduce the bug. Run the loop when safe. Confirm the failure matches what the user
described and capture the exact symptom. When reproduction is unsafe or impossible, use
historical artifacts, static evidence, or targeted telemetry instead.
Check recent changes. git diff, recent commits, new dependencies, config changes, environment differences.
Trace data flow. In multi-component systems, add diagnostic instrumentation at each boundary:
- Record only the minimum fields needed at each component boundary
- Redact credentials, authorization data, session identifiers, personal data, and payloads
- Verify environment/config propagation
- Check state at each layer
Run once to gather evidence, then narrow to the failing component.
Trace backward through the call stack. Where does the bad value originate? What called this with the bad value? Trace up until you find the source. Fix at the source, not at the symptom.
Non-deterministic bugs
The goal is not a clean repro but a higher reproduction rate. Narrow timing windows and vary
one condition at a time. Treat added delay or load as a perturbation, not proof. Do not replay
state-changing traffic, stress production, or collect sensitive artifacts without explicit
authorization and a safe operational plan.
When you genuinely cannot build a loop
Stop and say so explicitly. Ask the user for:
- Access to the environment that reproduces it
- A captured artifact (HAR, log dump, core dump, screen recording)
- Permission to add temporary production instrumentation
Do not claim root cause without evidence you can explain. A safe loop is preferred, but
artifact-based investigation is valid when a loop is unavailable.
Phase 2 — Pattern Analysis
Find the pattern before fixing.
- Find working examples. Locate similar working code in the same codebase.
- Compare against references. If implementing a known pattern, read the reference implementation completely.
- Identify differences. List every difference between working and broken, however small.
- Understand dependencies. What components, config, settings, and assumptions does this code rely on?
Phase 3 — Hypothesis and Testing
Use the scientific method.
Generate 3–5 ranked hypotheses. Single-hypothesis generation anchors on the first plausible idea. Each hypothesis must be falsifiable: state the prediction it makes. Show the ranked list to the user before testing — they often have domain knowledge that re-ranks instantly.
Format: "If <X> is the cause, then <changing Y> will make the bug disappear / <changing Z> will make it worse."
Test one variable at a time. Make the smallest possible change to test the hypothesis.
Instrument mapped to predictions. Each probe must map to a specific prediction. Prefer a debugger/REPL over logs; prefer targeted logs at boundaries over "log everything and grep".
Tag every debug log with a unique prefix, e.g. [DEBUG-a4f2]. Cleanup becomes a single grep.
Performance regressions. Establish a baseline measurement using the least intrusive
evidence available, then bisect. Measure first, fix second.
When you don't know, say so. Don't pretend. Ask for help or research more.
Phase 4 — Implementation
Fix the root cause, not the symptom.
Create a failing test case. The simplest possible reproduction. MUST exist before the fix.
A correct seam is one where the test exercises the real bug pattern as it occurs at the call site. If the only available seam is too shallow, note that the codebase architecture is preventing the bug from being locked down.
Implement a single fix. Address the root cause. One change at a time. No "while I'm here" improvements. No bundled refactoring.
Verify the fix. Does the test pass? Do other tests still pass? Does the original repro no longer reproduce?
If the fix doesn't work:
- STOP
- Count the failed fix attempts
- If < 3: return to Phase 1 with the new information
- If ≥ 3: question the architecture. Pattern problems, hidden coupling, and shared state that each fix reveals are signs of a wrong pattern. Discuss with the user before attempting Fix #4.
Cleanup + post-mortem
Before declaring done:
Red Flags — Stop and Return to Phase 1
If you catch yourself thinking:
- "Quick fix for now, investigate later"
- "Just try changing X and see if it works"
- "Add multiple changes, run tests"
- "Skip the test, I'll manually verify"
- "It's probably X, let me fix that"
- "I don't fully understand but this might work"
- "Pattern says X but I'll adapt it differently"
- "One more fix attempt" (after 2+ failures)
- Each fix reveals a new problem in a different place
All of these mean: stop. Return to Phase 1.
Common Rationalizations
| Excuse |
Reality |
| "Issue is simple, don't need process" |
Simple issues have root causes too. |
| "Emergency, no time for process" |
Systematic debugging is faster than thrashing. |
| "Just try this first, then investigate" |
First fix sets the pattern. Do it right from the start. |
| "I'll write the test after confirming the fix" |
Untested fixes don't stick. Test first proves the bug. |
| "Multiple fixes at once saves time" |
Can't isolate what worked. Causes new bugs. |
| "Reference too long, I'll adapt the pattern" |
Partial understanding guarantees bugs. |
| "I see the problem, let me fix it" |
Seeing symptoms ≠ understanding root cause. |
Quick Reference
| Phase |
Key Activities |
Success Criteria |
| 1. Root cause |
Read errors, build loop, reproduce, trace data flow |
Understand what and why |
| 2. Pattern analysis |
Find working examples, compare |
Identify differences |
| 3. Hypothesis |
Form theory, test minimally |
Confirmed or new hypothesis |
| 4. Implementation |
Failing test, single fix, verify |
Bug resolved, tests pass |
Debug Summary
After each session, summarize:
## Debug Summary
**Problem:** [One sentence]
**Root Cause:** [What actually was wrong]
**Fix:** [How you fixed it]
**Verification:** [Test results]
**Prevention:** [Regression test added? Architectural finding?]
References
- Common bug patterns →
references/bug-patterns.md
- Techniques and safety practices →
references/techniques.md
Structure inspired by obra/superpowers systematic-debugging.
1---2name: oracle-debug3description: Disciplined debugging methodology. Triggers on bug reports, test failures, "debug this", "diagnose this", unexpected behavior, build failures, integration issues, or performance regressions. Find root cause before a permanent corrective fix; contain urgent harm safely first.4---56# Oracle Debug78Random fixes waste time and create new bugs. Quick patches mask underlying issues.910**Core principle:** find root cause before a permanent corrective fix. Temporary containment is11appropriate when needed to limit security, production, or data-loss impact.1213**Violating the letter of this process is violating the spirit of debugging.**1415## The Iron Law1617```18NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST19```2021If you haven't completed Phase 1, you cannot propose fixes.2223## When to Use2425Use for any technical issue:2627- Test failures28- Bugs in production29- Unexpected behavior30- Performance regressions31- Build or integration failures32- Intermittent failures3334**Use this especially when:**3536- Under time pressure37- "Just one quick fix" seems obvious38- You've already tried multiple fixes39- The previous fix didn't work40- You don't fully understand the issue4142## The Four Phases4344You must complete each phase before proceeding to the next.4546---4748## Phase 1 — Root Cause Investigation4950**Before attempting any fix:**5152Use the project's domain glossary and ADRs to build a clear mental model of the53relevant modules before tracing.54551. **Read error messages carefully.** Read the full stack trace, line numbers, file paths, and error codes. Don't skip warnings.562. **Build a fast feedback loop.** If you don't have a fast, deterministic, pass/fail signal for the bug, no amount of code-reading will save you. Spend disproportionate effort here.5758 Try these in order:59 - Failing test at the seam that reaches the bug60 - Curl / HTTP script against a running dev server61 - CLI invocation with fixture input62 - Headless browser script (Playwright/Puppeteer)63 - Replay a captured trace (network payload, event log)64 - Throwaway harness (minimal subset of the system)65 - Property/fuzz loop for "sometimes wrong" bugs66 - Bisection harness (e.g., `git bisect run`)67 - Differential loop (old vs new version)68 - HITL bash script (last resort — structure the human clicks)6970 Iterate on the loop: make it faster, sharper, and more deterministic. A 30-second flaky loop is barely better than no loop.71723. **Reproduce the bug.** Run the loop when safe. Confirm the failure matches what the user73 described and capture the exact symptom. When reproduction is unsafe or impossible, use74 historical artifacts, static evidence, or targeted telemetry instead.754. **Check recent changes.** `git diff`, recent commits, new dependencies, config changes, environment differences.765. **Trace data flow.** In multi-component systems, add diagnostic instrumentation at each boundary:77 - Record only the minimum fields needed at each component boundary78 - Redact credentials, authorization data, session identifiers, personal data, and payloads79 - Verify environment/config propagation80 - Check state at each layer8182 Run once to gather evidence, then narrow to the failing component.836. **Trace backward through the call stack.** Where does the bad value originate? What called this with the bad value? Trace up until you find the source. Fix at the source, not at the symptom.8485### Non-deterministic bugs8687The goal is not a clean repro but a **higher reproduction rate**. Narrow timing windows and vary88one condition at a time. Treat added delay or load as a perturbation, not proof. Do not replay89state-changing traffic, stress production, or collect sensitive artifacts without explicit90authorization and a safe operational plan.9192### When you genuinely cannot build a loop9394Stop and say so explicitly. Ask the user for:9596- Access to the environment that reproduces it97- A captured artifact (HAR, log dump, core dump, screen recording)98- Permission to add temporary production instrumentation99100**Do not claim root cause without evidence you can explain.** A safe loop is preferred, but101artifact-based investigation is valid when a loop is unavailable.102103---104105## Phase 2 — Pattern Analysis106107Find the pattern before fixing.1081091. **Find working examples.** Locate similar working code in the same codebase.1102. **Compare against references.** If implementing a known pattern, read the reference implementation completely.1113. **Identify differences.** List every difference between working and broken, however small.1124. **Understand dependencies.** What components, config, settings, and assumptions does this code rely on?113114---115116## Phase 3 — Hypothesis and Testing117118Use the scientific method.1191201. **Generate 3–5 ranked hypotheses.** Single-hypothesis generation anchors on the first plausible idea. Each hypothesis must be falsifiable: state the prediction it makes. **Show the ranked list to the user before testing** — they often have domain knowledge that re-ranks instantly.121122 > Format: "If `<X>` is the cause, then `<changing Y>` will make the bug disappear / `<changing Z>` will make it worse."1231242. **Test one variable at a time.** Make the smallest possible change to test the hypothesis.1253. **Instrument mapped to predictions.** Each probe must map to a specific prediction. Prefer a debugger/REPL over logs; prefer targeted logs at boundaries over "log everything and grep".126127 **Tag every debug log** with a unique prefix, e.g. `[DEBUG-a4f2]`. Cleanup becomes a single grep.1281294. **Performance regressions.** Establish a baseline measurement using the least intrusive130 evidence available, then bisect. Measure first, fix second.1311325. **When you don't know, say so.** Don't pretend. Ask for help or research more.133134---135136## Phase 4 — Implementation137138Fix the root cause, not the symptom.1391401. **Create a failing test case.** The simplest possible reproduction. MUST exist before the fix.141142 A **correct seam** is one where the test exercises the real bug pattern as it occurs at the call site. If the only available seam is too shallow, note that the codebase architecture is preventing the bug from being locked down.1431442. **Implement a single fix.** Address the root cause. One change at a time. No "while I'm here" improvements. No bundled refactoring.1453. **Verify the fix.** Does the test pass? Do other tests still pass? Does the original repro no longer reproduce?1464. **If the fix doesn't work:**147 - STOP148 - Count the failed fix attempts149 - If < 3: return to Phase 1 with the new information150 - If ≥ 3: **question the architecture**. Pattern problems, hidden coupling, and shared state that each fix reveals are signs of a wrong pattern. Discuss with the user before attempting Fix #4.151152### Cleanup + post-mortem153154Before declaring done:155156- [ ] Original repro no longer reproduces (re-run Phase 1 loop)157- [ ] Regression test passes (or absence of seam is documented)158- [ ] All `[DEBUG-...]` instrumentation removed159- [ ] Throwaway prototypes deleted or moved to a clearly-marked debug location160- [ ] The correct hypothesis is stated in the commit / PR message161- [ ] You asked: "What would have prevented this bug?"162163---164165## Red Flags — Stop and Return to Phase 1166167If you catch yourself thinking:168169- "Quick fix for now, investigate later"170- "Just try changing X and see if it works"171- "Add multiple changes, run tests"172- "Skip the test, I'll manually verify"173- "It's probably X, let me fix that"174- "I don't fully understand but this might work"175- "Pattern says X but I'll adapt it differently"176- "One more fix attempt" (after 2+ failures)177- Each fix reveals a new problem in a different place178179All of these mean: stop. Return to Phase 1.180181## Common Rationalizations182183| Excuse | Reality |184|---|---|185| "Issue is simple, don't need process" | Simple issues have root causes too. |186| "Emergency, no time for process" | Systematic debugging is faster than thrashing. |187| "Just try this first, then investigate" | First fix sets the pattern. Do it right from the start. |188| "I'll write the test after confirming the fix" | Untested fixes don't stick. Test first proves the bug. |189| "Multiple fixes at once saves time" | Can't isolate what worked. Causes new bugs. |190| "Reference too long, I'll adapt the pattern" | Partial understanding guarantees bugs. |191| "I see the problem, let me fix it" | Seeing symptoms ≠ understanding root cause. |192193## Quick Reference194195| Phase | Key Activities | Success Criteria |196|---|---|---|197| 1. Root cause | Read errors, build loop, reproduce, trace data flow | Understand what and why |198| 2. Pattern analysis | Find working examples, compare | Identify differences |199| 3. Hypothesis | Form theory, test minimally | Confirmed or new hypothesis |200| 4. Implementation | Failing test, single fix, verify | Bug resolved, tests pass |201202## Debug Summary203204After each session, summarize:205206```207## Debug Summary208209**Problem:** [One sentence]210**Root Cause:** [What actually was wrong]211**Fix:** [How you fixed it]212**Verification:** [Test results]213**Prevention:** [Regression test added? Architectural finding?]214```215216## References217218- **Common bug patterns** → `references/bug-patterns.md`219- **Techniques and safety practices** → `references/techniques.md`220221Structure inspired by [obra/superpowers systematic-debugging](https://github.com/obra/superpowers).