Index of every page on this site: llms.txt
All skills
obra avatar

/systematic-debugging

@22f0b46 official
by Jesse Vincentobra/superpowers312k stars
27,751
Run it yourself

Use when encountering any bug, test failure, or unexpected behavior, before proposing fixes

Use this Skill: https://skilld.dev/gh/obra/superpowers/systematic-debugging

Nothing lands on disk. Nothing to clean up.

Fork this Skill

Edit a local copy. It keeps the author and licence.

defense-in-depth.md

≈913 tokens on demand. Your agent reads this file only when SKILL.md points to it.

Defense-in-Depth Validation

Overview

When you fix a bug caused by invalid data, adding validation at one place feels sufficient. But that single check can be bypassed by different code paths, refactoring, or mocks.

Core principle: Validate at EVERY layer data passes through. Make the bug structurally impossible.

Why Multiple Layers

Single validation: "We fixed the bug" Multiple layers: "We made the bug impossible"

Different layers catch different cases:

  • Entry validation catches most bugs
  • Business logic catches edge cases
  • Environment guards prevent context-specific dangers
  • Debug logging helps when other layers fail

The Four Layers

Layer 1: Entry Point Validation

Purpose: Reject obviously invalid input at API boundary

function createProject(name: string, workingDirectory: string) {
  if (!workingDirectory || workingDirectory.trim() === '') {
    throw new Error('workingDirectory cannot be empty');
  }
  if (!existsSync(workingDirectory)) {
    throw new Error(`workingDirectory does not exist: ${workingDirectory}`);
  }
  if (!statSync(workingDirectory).isDirectory()) {
    throw new Error(`workingDirectory is not a directory: ${workingDirectory}`);
  }
  // ... proceed
}

Layer 2: Business Logic Validation

Purpose: Ensure data makes sense for this operation

function initializeWorkspace(projectDir: string, sessionId: string) {
  if (!projectDir) {
    throw new Error('projectDir required for workspace initialization');
  }
  // ... proceed
}

Layer 3: Environment Guards

Purpose: Prevent dangerous operations in specific contexts

async function gitInit(directory: string) {
  // In tests, refuse git init outside temp directories
  if (process.env.NODE_ENV === 'test') {
    const normalized = normalize(resolve(directory));
    const tmpDir = normalize(resolve(tmpdir()));

    if (!normalized.startsWith(tmpDir)) {
      throw new Error(
        `Refusing git init outside temp dir during tests: ${directory}`
      );
    }
  }
  // ... proceed
}

Layer 4: Debug Instrumentation

Purpose: Capture context for forensics

async function gitInit(directory: string) {
  const stack = new Error().stack;
  logger.debug('About to git init', {
    directory,
    cwd: process.cwd(),
    stack,
  });
  // ... proceed
}

Applying the Pattern

When you find a bug:

  1. Trace the data flow - Where does bad value originate? Where used?
  2. Map all checkpoints - List every point data passes through
  3. Add validation at each layer - Entry, business, environment, debug
  4. Test each layer - Try to bypass layer 1, verify layer 2 catches it

Example from Session

Bug: Empty projectDir caused git init in source code

Data flow:

  1. Test setup → empty string
  2. Project.create(name, '')
  3. WorkspaceManager.createWorkspace('')
  4. git init runs in process.cwd()

Four layers added:

  • Layer 1: Project.create() validates not empty/exists/writable
  • Layer 2: WorkspaceManager validates projectDir not empty
  • Layer 3: WorktreeManager refuses git init outside tmpdir in tests
  • Layer 4: Stack trace logging before git init

Result: All 1847 tests passed, bug impossible to reproduce

Key Insight

All four layers were necessary. During testing, each layer caught bugs the others missed:

  • Different code paths bypassed entry validation
  • Mocks bypassed business logic checks
  • Edge cases on different platforms needed environment guards
  • Debug logging identified structural misuse

Don't stop at one validation point. Add checks at every layer.

Source: SKILL.md on GitHub

skilld matched fixed text patterns in SKILL.md and file names. Patterns miss obfuscated code.

skilld run checks every file with the same patterns. It asks for approval before it loads a Skill with a behavior marked Needs approval.

1 warning3d5 checks · Risk MEDIUM
  • Gen Agent Trust Hub4d

    The skill provides debugging methodologies and a shell script for identifying problematic tests. A vulnerability in the shell script could allow for command injection if an untrusted search pattern is provided.

  • Socket3d

    No alerts

  • Snyk4d

    Risk: LOW · No issues

  • Runlayer8mo

    2/11 files flagged

  • ZeroLeaks6mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 22f0b46. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 5 days ago.

Activeupdated last month
  • Debugging
  • Testing
  • root-cause-analysis
  • troubleshooting
  • process
  • error-handling
  • verification
  • test-driven-development

README badge

README badge for obra/superpowers/systematic-debugging

Guides investigation of bugs, test failures, and unexpected behavior through four mandatory phases: root cause investigation, pattern analysis, hypothesis testing, and implementation. Emphasizes finding the actual source before attempting fixes, with explicit checks to stop and reassess if three fixes fail without resolution.

Generated from the current SKILL.md.

When should I use this debugging skill instead of just trying fixes?
Use it for any technical issue: test failures, bugs, performance problems, build failures. Especially critical when under time pressure, when you've already tried multiple fixes, or when the issue seems simple. Skipping it when rushing actually wastes more time than following the process.
What does 'root cause investigation' actually involve?
Read error messages completely, reproduce the issue consistently, check recent changes via git diff, and gather diagnostic evidence at component boundaries. For multi-layer systems, add logging at each boundary to show where data flow breaks before proposing any fix.
What should I do if I've tried 3 or more fixes and nothing works?
Stop attempting fixes and question the architecture instead. When multiple fixes each reveal new problems in different places, the issue is likely architectural rather than a simple bug. Discuss with your partner before attempting more fixes.
Do I need to write a test before fixing the bug?
Yes. Phase 4 requires creating a failing test case—automated if possible, otherwise a one-off script. The test must pass after your fix and serve as proof the issue is resolved.
What's the difference between fixing symptoms versus fixing root cause?
Symptom fixes mask the real problem and waste time. Root cause fixes prevent the issue from recurring. The process enforces finding root cause (where bad data originates) before any code changes.

Generated from the current SKILL.md. These answers refresh after source changes.