* test(#1960): add failing-first RCA-branching contract + schema-invariant tests Epic #1957 Phase 2A. Source-text-is-the-product contract tests (fishbone >=2 categories, AND-gate, multi-cause root_cause, backward compat, reasoning checkpoint candidate_causes+and_gate fields, debugger-philosophy single-cause note, DEBUG template) plus behavioral schema-invariant checks on two fixtures: two contributing causes (AND-gate yes) -> both recorded; single-cause (AND-gate no) -> one root_cause, identical to today. Failing-first: reference, agent edits, and template note do not yet exist. * feat(#1960): add RCA branching (fishbone + AND-gate) to gsd-debugger Epic #1957 Phase 2A. Guards against 5-Whys single-cause bias: before committing root_cause, the debugger enumerates candidate causes across >=2 Ishikawa categories (code/config/environment/data) and explicitly answers an AND-gate question. When the AND-gate fires, every contributing cause is recorded, so a multi-cause fix no longer recurs via the unaddressed second cause. Resolution.root_cause may hold one OR a small set (additive; single-cause sessions are byte-identical to today). The Structured Reasoning Checkpoint gains candidate_causes + and_gate fields; debugger-philosophy.md adds the single-cause-bias trap. Full rules extracted to gsd-core/references/debugger-rca-branching.md (slim Phase 2 routing + 2 checkpoint fields kept in the agent). INVENTORY + manifest + agent-size baseline + install-parity goldens + AGENTS.md + DEBUG template updated. * fix(#1960): address orthogonal review (AND-gate self-consistency, parity guard, narrowed claim, ripples) - Reference: the collapse rule now enforces AND-gate self-consistency — and_gate=yes with a single confirmed cause is flagged as incomplete (return to Phase 3); a race/timing note clarifies such bugs bridge categories; the 'byte-identical' backward-compat claim narrowed to 'root_cause shape unchanged; reasoning_checkpoint gains 2 fields in every session'. - DEBUG.md: stale 'five-field' mirror prose -> seven-field (parallel-surface drift the reviewer flagged); new debug-session-management parity test pins the field-count claim to the gsd-debugger.md YAML keys (CRLF-safe). - Scalar-assuming consumers of set-valued root_cause updated: session-manager compact summaries (319/332), diagnose-only return (1062), archive entry (1216), ROOT CAUSE FOUND return (1322). - Test: added the AND-gate-yes/single-cause invariant + fixture; rephrased the fixture describe block honestly as a schema-invariant specification. - Phase 2 bullet phrasing clarified ('at hypothesis formation, before the Phase 4 commit'). * test(#1960): parity regex accepts word-form count ('seven-field' or '7-field') * test(#1960): parity regex counts array-valued YAML keys (no inline value) * chore(#1960): backfill changeset pr number (PR #2405)
3.5 KiB
Debugger Philosophy
Evergreen debugging disciplines — applies across every bug, every language, every system. Loaded by gsd-debugger via @file include.
User = Reporter, Claude = Investigator
The user knows:
- What they expected to happen
- What actually happened
- Error messages they saw
- When it started / if it ever worked
The user does NOT know (don't ask):
- What's causing the bug
- Which file has the problem
- What the fix should be
Ask about experience. Investigate the cause yourself.
Meta-Debugging: Your Own Code
When debugging code you wrote, you're fighting your own mental model.
Why this is harder:
- You made the design decisions - they feel obviously correct
- You remember intent, not what you actually implemented
- Familiarity breeds blindness to bugs
The discipline:
- Treat your code as foreign - Read it as if someone else wrote it
- Question your design decisions - Your implementation decisions are hypotheses, not facts
- Admit your mental model might be wrong - The code's behavior is truth; your model is a guess
- Prioritize code you touched - If you modified 100 lines and something breaks, those are prime suspects
The hardest admission: "I implemented this wrong." Not "requirements were unclear" - YOU made an error.
Foundation Principles
When debugging, return to foundational truths:
- What do you know for certain? Observable facts, not assumptions
- What are you assuming? "This library should work this way" - have you verified?
- Strip away everything you think you know. Build understanding from observable facts.
Cognitive Biases to Avoid
| Bias | Trap | Antidote |
|---|---|---|
| Confirmation | Only look for evidence supporting your hypothesis | Actively seek disconfirming evidence. "What would prove me wrong?" |
| Anchoring | First explanation becomes your anchor | Generate 3+ independent hypotheses before investigating any |
| Availability | Recent bugs → assume similar cause | Treat each bug as novel until evidence suggests otherwise |
| Sunk Cost | Spent 2 hours on one path, keep going despite evidence | Every 30 min: "If I started fresh, is this still the path I'd take?" |
| Single-cause (5-Whys) bias | A linear "why → why → why" chain stops at ONE cause; multi-cause failures recur via the unaddressed second cause | Branch across ≥2 Ishikawa categories and answer the AND-gate before committing root_cause (see debugger-rca-branching.md) |
Systematic Investigation Disciplines
Change one variable: Make one change, test, observe, document, repeat. Multiple changes = no idea what mattered.
Complete reading: Read entire functions, not just "relevant" lines. Read imports, config, tests. Skimming misses crucial details.
Embrace not knowing: "I don't know why this fails" = good (now you can investigate). "It must be X" = dangerous (you've stopped thinking).
When to Restart
Consider starting over when:
- 2+ hours with no progress - You're likely tunnel-visioned
- 3+ "fixes" that didn't work - Your mental model is wrong
- You can't explain the current behavior - Don't add changes on top of confusion
- You're debugging the debugger - Something fundamental is wrong
- The fix works but you don't know why - This isn't fixed, this is luck
Restart protocol:
- Close all files and terminals
- Write down what you know for certain
- Write down what you've ruled out
- List new hypotheses (different from before)
- Begin again from Phase 1: Evidence Gathering