Skip to content

Chapter 6: Debugging & Verification

Debugging is not guessing. It is a systematic, evidence-based process. Superpowers enforces a structured approach to debugging that eliminates the most common failure modes: random fix attempts, incomplete verification, and premature completion claims.


The 4-Phase Debugging Process

Every bug investigation must follow these four phases in order. Skipping a phase is not allowed.

Phase 1: Root Cause Investigation

Before writing a single line of fix code, you must fully understand the problem.

  1. Read the error carefully. Copy the full error message, stack trace, and any surrounding context. Do not paraphrase — work with the exact text.
  2. Reproduce the failure. Run the failing test or trigger the bug manually. A bug you cannot reproduce is a bug you cannot fix reliably.
  3. Check recent changes. Run git log --oneline -20 and git diff HEAD~5 to identify what changed recently. Most bugs are introduced by recent changes.
  4. Trace the data flow. Follow the data from its entry point through every transformation until you find where it diverges from the expected value.

Rule: Do not hypothesize until you have completed the investigation phase. Evidence before theory.


Phase 2: Pattern Analysis

Once you have reproduced the bug, look for patterns.

  1. Find working examples. Locate similar code paths in the codebase that work correctly. The difference between the working and broken code is likely the bug.
  2. Compare differences. Use a systematic diff — types, nullability, async handling, error propagation, side effects.
  3. Check timing. Many bugs are race conditions, initialization order issues, or async/await mistakes. Ask: does this work synchronously but fail asynchronously? Does it work the first time but fail on retry?

Phase 3: Hypothesis and Testing

With evidence gathered, you can now form and test a hypothesis.

  1. State your hypothesis explicitly. Write it down: "I believe the bug is caused by X because of evidence Y."
  2. Test one variable at a time. Never change two things simultaneously. If your fix doesn't work, you won't know which change was responsible.
  3. Document your results. Record what you tested, what you expected, and what actually happened. This log prevents you from re-testing the same incorrect hypothesis.

Phase 4: Implementation

You now know the root cause. Implement the fix properly.

  1. Create a failing test first. Write a test that reproduces the exact bug. It must fail before your fix and pass after.
  2. Implement the minimal fix. Change only what is necessary to fix the identified root cause. Do not refactor, do not improve unrelated code.
  3. Verify no regressions. Run the full test suite. The fix must not break anything that was previously passing.

The 3 Failures Rule

If you have attempted 3 or more fixes and the bug persists, STOP immediately.

Three failed fix attempts is not a sign to try harder — it is a diagnostic signal. It means you are treating symptoms, not root causes. At this point:

  • The problem is almost certainly an architecture issue, not a line-level bug
  • Continuing to attempt fixes will make the codebase worse
  • You must escalate: write a plan, redesign the affected module, or seek a second perspective

This rule prevents the common failure pattern of "fix-a-fix-a-fix" that accumulates technical debt and makes codebases unmaintainable.


The Single Fix Rule

Never fix multiple things simultaneously.

When you encounter a bug, you may notice other problems nearby. Resist the urge to fix them all at once. Why?

  • You cannot isolate which change fixed the original bug
  • You cannot attribute a new failure to a specific change
  • Your test coverage becomes unclear
  • Code review becomes impossible

Fix one thing. Verify it. Commit it. Then move to the next issue.


Verification Before Completion

This is one of the Iron Laws of Superpowers:

"NO COMPLETION CLAIMS WITHOUT FRESH VERIFICATION EVIDENCE"

You may not say "fixed", "done", "working", or any equivalent phrase unless you have just run verification and have the output in front of you. This is not optional.

The 5-Step Verification Gate

Every completion claim must pass through this gate:

StepActionWhat It Means
IDENTIFYName the specific thing you are verifying"I am verifying that the login flow passes all tests"
RUNExecute the actual verification commandnpm test -- --testPathPattern=auth
READRead the complete outputDo not skim. Read every line.
VERIFYConfirm the output matches success criteriaAll tests pass, no warnings, expected behavior observed
CLAIMOnly now state that the work is complete"Tests pass. The fix is verified."

If any step fails, you return to the debugging process. You do not claim completion.


Red Flags to Watch For

These phrases and behaviors indicate that verification has been skipped:

Red FlagWhat It Signals
"This should work"No verification has been performed
"It's probably fine"Assumption without evidence
"I think it's fixed"Subjective belief, not objective verification
"The tests should pass"Tests have not been run
Trusting a previous report without re-runningStale data — things change
Summarizing output instead of showing itPossible selective reading or hallucination
Fixing the test instead of the codeCovering up a bug, not resolving it

When you catch yourself about to say any of these phrases, stop. Run the verification. Then report what the output actually says.


Putting It All Together

A proper debugging session looks like this:

1. Bug reported: "User login fails with 401"
2. Phase 1: Reproduce → check git log → trace auth middleware
3. Phase 2: Find working endpoint → compare headers → identify: JWT token missing "Bearer " prefix in one code path
4. Phase 3: Hypothesis: "The mobile client sends raw token, desktop sends 'Bearer TOKEN'. Backend expects 'Bearer'."
   Test: Manually send raw token → 401. Send with "Bearer" prefix → 200. Confirmed.
5. Phase 4: Write test for raw token input → implement normalization in auth middleware → run full suite → 847 tests pass, 0 fail
6. Verification gate: IDENTIFY "auth tests" → RUN `npm test` → READ output → VERIFY 0 failures → CLAIM "Fixed."

Systematic debugging is slower in the short term and dramatically faster across a project's lifetime. Guessing is the enemy of reliable software.