| name | investigate |
| description | Structured root-cause debugging with scope lock. Enforces hypothesis-driven investigation before any fixes. Use for bugs, crashes, unexpected behavior, or production incidents. Triggers: investigate, debug, root cause, diagnose, incident. |
Investigate — Root Cause Debugging
Adapted from gstack's /investigate. Enforces rigorous debugging methodology aligned with SIMPLED's "no bandaids" rule.
Iron Law
NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST.
If you catch yourself about to write a fix before completing Phase 1-3, STOP.
Phase 1: Collect Symptoms
-
Ask the user to describe:
- What happened (expected vs actual)
- When it started (or was first noticed)
- How to reproduce (steps, environment)
-
Gather evidence (delegate to subagents for large codepaths):
- Read the relevant source code
- Check recent changes:
git log --oneline -20 -- <affected-files>
- Check for related issues:
git log --oneline --all --grep="<keyword>" -10
- Read error logs if available
-
Reproduce deterministically — if the bug can't be reproduced, say so and gather more data before proceeding.
Phase 2: Scope Lock
After forming an initial hypothesis:
- Identify the affected module/directory
- Activate freeze mode — restrict edits to that directory only
- Announce:
Scope locked to <directory>/. All edits will be restricted to this boundary until the investigation concludes.
This prevents scope creep during debugging. If the root cause turns out to be elsewhere, explicitly widen the scope with justification.
Phase 3: Hypothesize and Test
Form a root cause hypothesis — not a symptom description:
Root cause hypothesis: [specific mechanism that causes the bug]
Common Pattern Library
| Pattern | Symptoms | Investigation Path |
|---|
| Race condition | Intermittent, timing-dependent | Check async/concurrent code, add logging with timestamps |
| Nil/null propagation | Crash on access, "undefined is not..." | Trace data flow backward from crash site |
| State corruption | Works initially, breaks after action X | Check mutation points, verify immutability |
| Integration mismatch | Works in isolation, fails end-to-end | Check API contracts, serialization, type coercion |
| Configuration drift | Works locally, fails in env X | Diff configs, check env vars, feature flags |
| Stale cache | Correct after clear, wrong after time | Check cache invalidation, TTL, key generation |
Hypothesis Testing
- Add temporary diagnostic logging or assertions to confirm/deny
- Run the reproduction steps
- If hypothesis confirmed → proceed to Phase 4
- If hypothesis denied → form new hypothesis
Three-Strike Rule
If 3 consecutive hypotheses fail, STOP and escalate:
Three hypotheses tested, none confirmed. The root cause is not obvious.
Options:
- Search online for this error pattern (recommended)
- Widen the investigation scope
- Ask for additional context from the user
- Bring in a second opinion (subagent with fresh perspective)
Phase 4: Fix Root Cause
Only after root cause is confirmed (not "suspected"):
-
Fix the root cause, not the symptom
- Ask: "Does this make the bug impossible, or just less likely?"
- If "less likely" → it's a bandaid. Keep digging.
-
Minimal diff — change only what's necessary to fix the root cause
-
Write a regression test that:
- Fails WITHOUT the fix (verify by mentally or actually reverting)
- Passes WITH the fix
- Tests the specific root cause mechanism, not just the symptom
-
Run full test suite — ensure no regressions
Phase 5: Verification Report
After fixing, produce a structured report:
## Debug Report
**Symptom:** [what was observed]
**Root cause:** [specific mechanism — WHY it happened]
**Fix:** [what was changed and why this eliminates the root cause]
**Evidence:** [how we confirmed the root cause — logs, tests, reproduction]
**Regression test:** [test name and what it covers]
**Related:** [any related code that should be reviewed but wasn't changed]
Red Flags (STOP if you catch yourself doing these)
- Saying "quick fix for now" or "temporary workaround"
- Proposing a fix before tracing the full data flow
- Each fix revealing a new problem (symptom chasing)
- Adding defensive code (try/catch, null checks) around the crash site instead of fixing why the bad value arrives
- Blaming "flaky tests" without investigating the flakiness
Integration with Existing Workflow
- Uses
/freeze internally for scope lock — will auto-activate
- Follows
rules/debugging.md "Search Before Debugging" — will search online after 2 failed steps
- Subagent delegation per SIMPLED rules — large codepath reading goes to subagents
- Commit message format:
fix: <root-cause description> per rules/git-workflow.md