| name | systematic-debugging |
| description | Trigger: broken system, 500s, crashes, slow endpoint, failing test, tried multiple fixes. Reproduce first, trace backward, hypothesize once, verify. Skip: new features, refactoring, code review. |
| author | Gonzalo Astudillo |
| version | 1.1.0 |
| date | "2026-04-14T00:00:00.000Z" |
| user-invocable | true |
Systematic Debugging
The Iron Law
NO FIXES WITHOUT REPRODUCTION FIRST.
Reading code reveals what could happen. Running code reveals what actually happens. Never propose a fix based on code analysis alone.
The Three Phases
Phase 1: Reproduce & Observe
- Read the error message thoroughly — the answer is often there
- Write a minimal throwaway script that triggers the failure
- Execute it — document what actually happens (not what you expect)
- Add logging at key points
- Narrow scope through bisection
Do not read multiple files before running anything.
Phase 2: Root Cause Analysis
Only after observing where it breaks:
- Read the relevant code — trace backward from the symptom to the source
- Where does the bad value originate?
- Check recent git history chronologically (not by keyword)
- Compare working vs broken implementations
The loudest component is often not the culprit. In multi-layer systems, silent resource consumers (slow queries, connection drains) cause timeouts downstream — the component throwing errors may be a victim, not the cause.
Phase 3: Fix & Verify
- State one specific hypothesis
- Make minimal, isolated changes
- Convert the reproduction script into a lasting test
- Verify comprehensively — not just the happy path
The 3-Fix Rule
Three failed fix attempts = architectural problem. Stop. Discuss with stakeholders before attempting more patches.
Red Flags — Stop and Restart
- Reading multiple files before running anything
- Proposing a fix from code analysis alone
- Fixing the error location instead of the root cause
- Attempting a 4th fix after 3 failures
- Adding logging after the fact instead of before
Phase 4 (Optional): Document as GitHub Issue
After Phase 3, if the fix is non-trivial or should be tracked, ask:
"¿Convertimos esto en un GitHub issue?"
If yes, generate an issue with this structure:
- Title:
[Bug] <concise description of the broken behavior>
- Problem: What breaks, under what conditions, and the root cause found in Phase 2
- Root Cause: The specific function/invariant/assumption that failed
- TDD Fix Plan: Ordered RED-GREEN cycles
- 🔴 RED: a test that captures the broken behavior (fails today)
- 🟢 GREEN: the minimal code change to make it pass
- Repeat for each distinct behavior that needs fixing
- Acceptance Criteria: Observable behaviors that must hold after the fix
- Out of Scope: What this fix deliberately does NOT address
Use behavior descriptions, not file paths — file paths rot. Describe contracts and invariants.
Decision Gates
| Situation | Action |
|---|
| Error message is clear and actionable | Read it thoroughly before Phase 1 — answer is often there |
| Bug reproduced locally, cause unknown | Full Phase 1–3 cycle |
| Works locally, breaks in prod | Focus Phase 2 on environment diff (env vars, DB state, network) |
| 3 failed fix attempts | Stop. Escalate to Phase 4 / architectural discussion |
| Fix is non-trivial or recurrent | Document as GitHub issue (Phase 4) |
Output Contract
Return exactly 3 artifacts:
- Reproduction case — minimal script or steps that reliably trigger the failure
- Root cause — one sentence: "The bug is in X because Y"
- Fix + evidence — minimal change applied + output showing the reproduction case now passes
Gotchas
- Reading multiple files before running anything = violates Phase 1 — reproduce first, always
- The loudest component (the one throwing errors) is often not the cause — trace backward from symptom
- "I think the issue is in X" without a reproduction script is a hypothesis, not a diagnosis
- Adding logging after the fix is useless — add it before, while reproducing
Supporting Files
- root-cause-tracing.md — How to trace backward through the call chain
- defense-in-depth.md — Validation at each layer to catch problems early