O

systematic-debugging

by obra

A four-phase debugging workflow that forces root-cause investigation before any fix, with concrete tools for flaky tests, validation, and test pollution.

Stars0
Favorites0
Comments0
CategoryDebugging
Install Command
npx skills add https://github.com/obra/superpowers --skill systematic-debugging
Overview

Overview

What is systematic-debugging?

The systematic-debugging skill is a structured, four-phase process for debugging any technical issue: test failures, production bugs, flaky tests, performance problems, build errors, or integration failures.

Instead of trying "one quick fix" or editing code at the first error line, this skill forces you to investigate root cause first, then design and validate a durable fix. It is backed by practical patterns and scripts from a real codebase, including TypeScript condition-based waiting helpers and a Bash script to find test polluters.

Core principle and Iron Law

The heart of systematic-debugging is simple:

  • Core principle: Always find root cause before attempting fixes. Symptom-only fixes are failures.

  • The Iron Law:

    NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST
    

If you have not completed the investigation phase, you do not propose or apply fixes. This is designed to resist time pressure, guesswork, and "just this once" rationalizations.

Who is this skill for?

systematic-debugging is aimed at:

  • Developers working in JavaScript/TypeScript projects who want reliable, reproducible fixes
  • Test and QA engineers dealing with flaky behavior, random timeouts, and polluted test state
  • CI/CD and tooling engineers diagnosing intermittent build or integration failures
  • Tech leads and reviewers who want a shared, rigorous process for debugging work

It fits best if you care about high-quality root-cause analysis more than quickly patching symptoms.

What problems does it solve?

Use the systematic-debugging skill when you need to:

  • Investigate test failures that keep reappearing after "fixes"
  • Track down flaky tests that depend on arbitrary timeouts or race conditions
  • Understand unexpected behavior instead of just silencing errors
  • Diagnose performance problems or slow, timing-sensitive flows
  • Debug build or integration failures that only happen in CI or under load
  • Find which test pollutes state or leaves unwanted files/directories behind

The repository also includes:

  • condition-based-waiting.md and condition-based-waiting-example.ts for replacing setTimeout/sleep with robust condition-based waiting in TypeScript
  • defense-in-depth.md for adding validation at multiple layers so specific bugs become structurally impossible
  • find-polluter.sh, a Bash helper to locate the exact test that creates unwanted files or state
  • root-cause-tracing.md to trace errors back through the call chain to the true origin

When is systematic-debugging a good fit?

systematic-debugging is a strong fit when:

  • You are under time pressure and tempted to guess at fixes
  • An issue keeps resurfacing despite multiple attempts
  • You want a repeatable debugging workflow for yourself or your team
  • You are stabilizing a flaky test suite or cleaning up polluted test environments

It may be less suitable if:

  • You only need a quick, one-off code generation or refactor without investigation
  • You are debugging outside the technical domains described (e.g., non-technical process issues)
  • You are unwilling to follow a stepwise process and prefer ad-hoc experimentation

If your goal is "fast patch now, accept rework later", this process will feel strict. If your goal is "fix it once, correctly", systematic-debugging is designed for you.

How to Use

Installation and setup

To install the systematic-debugging skill into a compatible agent or tools environment, use the provided npx command:

npx skills add https://github.com/obra/superpowers --skill systematic-debugging
``

This pulls the skill definition and its supporting documents and scripts from the `obra/superpowers` repository under `skills/systematic-debugging`.

After installation:

1. Open the `systematic-debugging` skill in your agent or skills UI.
2. Ensure your workspace has access to your project repository, test commands, and logs.
3. Confirm you can view the bundled markdown guides and scripts:
   - `SKILL.md`
   - `condition-based-waiting.md`
   - `defense-in-depth.md`
   - `root-cause-tracing.md`
   - `find-polluter.sh`

### Files and components to know
For installation decisions and day-to-day use, these files are the most important:

- **`SKILL.md`** – Defines the full four-phase systematic debugging process, rules, and anti-patterns. This is the core of the skill.
- **`condition-based-waiting.md`** – Explains how to replace arbitrary timeouts in tests with condition-based waiting.
- **`condition-based-waiting-example.ts`** – TypeScript utilities like `waitForEvent` that implement condition-based waiting against a `ThreadManager` and event types.
- **`defense-in-depth.md`** – Shows how to apply multi-layer validation (entry point, business logic, environment guards, logging) to make whole classes of bugs impossible.
- **`find-polluter.sh`** – A Bash script that iterates tests to find which file creates a given path (state pollution).
- **`root-cause-tracing.md`** – Walks through tracing a bug back from a stack trace to the original trigger, then combining with defense-in-depth.
- **`CREATION-LOG.md`** – A meta-log explaining how the framework was extracted and hardened; useful for understanding design intent, less critical for daily use.

For **JavaScript/TypeScript** developers, the TypeScript example and Bash script can often be adapted directly into your project.

### Running the four-phase workflow
The `systematic-debugging` process is organized into four required phases (as described in `SKILL.md`). You must complete each one before moving on.

#### Phase 1 – Root cause investigation
Before touching any code, configuration, or tests:

- **Read error messages and logs carefully.**
  - Do not skim stack traces or warnings.
  - Capture line numbers, file paths, and error codes.
- **Reproduce the issue consistently.**
  - Establish a minimal, reliable reproduction command.
  - Note what inputs and environment factors are required.

You do not propose or implement fixes in this phase. The goal is understanding: what exactly is failing, where, and under what conditions.

#### Phase 2 – Pattern analysis
Once reproduction is reliable:

- Vary one factor at a time (inputs, configuration, environment) to see what changes the outcome.
- Look for boundaries: values or conditions where behavior flips from passing to failing.
- Use logs, assertions, or temporary instrumentation to narrow down the failing path.

By the end of Phase 2, you should understand the shape of the problem and the conditions that trigger it, not just the final error message.

#### Phase 3 – Hypothesis and design
Now you can form a hypothesis:

- State clearly what you believe the root cause is (data flow, missing validation, timing issue, wrong path, etc.).
- Design a **single, focused** change that would address that root cause.
- Plan how you will validate the hypothesis using your reproduction steps.

If the hypothesis fails, you return to investigation/analysis instead of stacking more speculative fixes.

#### Phase 4 – Implementation and validation
Only after a clear hypothesis do you modify code or configuration:

- Apply the smallest change that directly addresses the root cause.
- Run the minimal reproduction and then the broader test suite.
- Use guidance from:
  - `defense-in-depth.md` to add validation at multiple layers
  - `root-cause-tracing.md` to be sure you’re fixing the true source
- Confirm the fix is robust (e.g., works under load, in CI, and for edge cases identified in Phase 2).

If the fix does not behave as expected, you do **not** pile on more changes; you return to earlier phases.

### Using the debugging utilities in your project

#### Condition-based waiting for flaky tests (JavaScript/TypeScript)
Flaky tests that rely on `setTimeout` or `sleep` often break when machines are slower, faster, or under load. `condition-based-waiting.md` and `condition-based-waiting-example.ts` show a better pattern: wait for the condition you care about.

Typical migration:

```typescript
// ❌ Before: guessing timing
await new Promise(r => setTimeout(r, 50));
const result = getResult();
expect(result).toBeDefined();

// ✅ After: waiting for condition
await waitFor(() => getResult() !== undefined);
const result = getResult();
expect(result).toBeDefined();

The provided condition-based-waiting-example.ts includes helpers like:

export function waitForEvent(
  threadManager: ThreadManager,
  threadId: string,
  eventType: LaceEventType,
  timeoutMs = 5000
): Promise<LaceEvent> { /* ... */ }

Adapt these patterns to your own test infrastructure:

  1. Copy or reimplement the utilities into your project’s test helpers.
  2. Replace arbitrary setTimeout/sleep calls with condition-based waits.
  3. Re-run your test suite to confirm reduced flakiness.

This directly supports the systematic-debugging goal of eliminating root causes instead of randomly stretching timeouts.

Finding polluted tests with find-polluter.sh

If your tests leave behind extra files or directories or otherwise pollute state, find-polluter.sh helps you locate the exact test responsible.

Usage (from your project root, adjusting arguments as needed):

./find-polluter.sh <file_or_dir_to_check> <test_pattern>

# Example
./find-polluter.sh '.git' 'src/**/*.test.ts'

The script will:

  • Discover test files matching the pattern
  • Run them one by one with npm test <file>
  • After each run, check whether the target file or directory now exists
  • Stop and report the first test that created it, with commands to rerun and inspect that test

This fits into Phase 1 and Phase 2 of systematic-debugging by providing a reliable way to reproduce and isolate state pollution.

Applying defense-in-depth validation

When your investigation reveals a bug caused by invalid data or assumptions, defense-in-depth.md recommends placing validation at several layers:

  • Entry point validation – Reject obviously invalid input at boundaries (APIs, CLI, UI handlers).
  • Business logic validation – Ensure data makes sense for specific operations.
  • Environment guards – Prevent dangerous operations in the wrong environment or path.
  • Diagnostic logging – Provide useful context if something slips through.

For example, validating a workingDirectory argument:

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
}

Use these patterns when implementing Phase 4 fixes to ensure the bug cannot easily reappear through a different code path.

When not to use this skill

It may be better to skip or defer systematic-debugging if:

  • You are prototyping and intentionally accepting throwaway code and bugs
  • The issue is trivial and fully understood (for example, a known typo caught during development) and does not justify the full four-phase rigor
  • You only need sample utilities (like condition-based waits) and not the broader process

Even in these cases, the Iron Law is a useful check: if you find yourself stacking multiple guesses, it’s time to switch to systematic-debugging.

FAQ

What does systematic-debugging actually change in my workflow?

Instead of jumping straight from error message to code edits, systematic-debugging forces you through investigation, pattern analysis, and hypothesis before implementation. In practice this means:

  • You capture a reliable reproduction before touching code
  • You vary conditions to understand the problem space
  • You write one focused fix per validated hypothesis

The result is fewer reverts, fewer hidden regressions, and more predictable debugging time.

How do I install the systematic-debugging skill?

Use the npx skills command:

npx skills add https://github.com/obra/superpowers --skill systematic-debugging

After installation, open the skill in your agent or skills directory, then review SKILL.md for the full process and the supporting markdown files for patterns and examples.

Does systematic-debugging support JavaScript and TypeScript debugging?

Yes. While the framework itself is language-agnostic, the repository includes concrete JavaScript/TypeScript-focused utilities:

  • condition-based-waiting-example.ts for condition-based waiting in tests
  • Patterns in defense-in-depth.md and root-cause-tracing.md illustrated with TypeScript examples
  • find-polluter.sh, which assumes npm test by default and works well with typical JS/TS test runners

You can adapt these utilities to your project structure and tooling.

Can I use systematic-debugging for flaky test automation?

Yes. This is one of its strongest use cases. Combine:

  • The four-phase process from SKILL.md to investigate and understand flakiness
  • condition-based-waiting.md and the TypeScript example to replace timing guesses with condition-based waits
  • find-polluter.sh to find tests that pollute state or create unexpected files

Together, these tools help you convert unreliable tests into stable, deterministic checks.

Is systematic-debugging only for tests, or also for production bugs?

The process applies to any technical issue:

  • Test failures and flakiness
  • Production bugs and incidents
  • Performance problems
  • Build and integration failures

The examples and utilities lean toward testing and development workflows, but the phases and principles are explicit about covering production scenarios as well.

What if I’m under time pressure and just need a quick fix?

The skill is written specifically to resist the "just one quick fix" impulse. It argues that:

  • Rushing without root-cause investigation leads to thrashing and rework
  • Fixes that only treat symptoms often create new issues

In practice, taking a few minutes to follow Phase 1 and Phase 2 usually saves time overall, even during urgent incidents.

Do I have to follow all four phases every single time?

The intent of systematic-debugging is that skipping phases is an exception, not the norm. For minor, fully understood issues (for example, a small refactor where you immediately spot the mistake), you might compress the steps. But if:

  • The issue is recurring
  • You don’t fully understand why it happens
  • Previous fixes have failed

…then the full four-phase process is strongly recommended.

How does root-cause tracing relate to defense-in-depth?

root-cause-tracing.md helps you follow a bug from the visible error back through call chains to the original trigger. defense-in-depth.md then shows how to prevent similar bugs by:

  • Fixing at the true source
  • Adding validation at multiple layers

For example, if git init fails in the wrong directory, tracing shows which function passed the wrong path, and defense-in-depth adds validation and guards so invalid paths are rejected earlier.

Can I use the skill without copying any code from the repo?

Yes. The core value of systematic-debugging is the structured debugging process described in SKILL.md. You can:

  • Follow the phases and rules directly in your own environment
  • Apply the investigation and analysis patterns to any language or stack

The TypeScript and Bash helpers are optional accelerators, especially for JS/TS and Unix-like environments.

Where can I explore everything included in systematic-debugging?

After installation, open the Files or repository view for obra/superpowers under skills/systematic-debugging. Key files to inspect are:

  • SKILL.md
  • condition-based-waiting.md
  • condition-based-waiting-example.ts
  • defense-in-depth.md
  • root-cause-tracing.md
  • find-polluter.sh

These give you the complete systematic-debugging workflow plus concrete tools for debugging and test stabilization.

Ratings & Reviews

No ratings yet
Share your review
Sign in to leave a rating and comment for this skill.
G
0/10000
Latest reviews
Saving...