debugging
Debugging
The Iron Law
Never propose a fix without first identifying the root cause. "Quick fix now, investigate later" is forbidden -- it creates harder bugs. This applies ESPECIALLY under time pressure, when "just one quick fix" seems obvious, or when multiple fixes have already failed. Those are the moments this process matters most.
Trivially obvious bugs are their own root cause -- state the cause and fix directly. A bug is trivially obvious only when the cause is in the error message (e.g., ModuleNotFoundError: no module named foo, a typo in a string literal). If the error shows where something fails but not why (e.g., TypeError: Cannot read 'id' of undefined), it is not trivially obvious -- investigate why the value is undefined.
Root Cause Analysis
Root cause identification is the core deliverable of debugging -- not the fix itself.
- Trace backward: Start at the symptom, walk the call chain in reverse to find where behavior diverges from expectation
- Differential analysis: Compare working vs broken state across dimensions (code version, data, environment, timing, configuration)
- Regression hunting: Use
git bisectto pinpoint the exact commit that introduced the issue - Evidence-based: Document root cause with
file:linereferences, log output, and concrete reproduction proof. Root cause = the earliest point where behavior diverged from expectation, stated with evidence at least two levels deep (not just "it failed here" but "it failed here because X was null, and X was null because Y never set it") - Competing hypotheses: When the cause is ambiguous, generate multiple hypotheses and rank by evidence strength (see Escalation section below)