skills/root-cause-tracing/SKILL.md
Use when an error appears deep in the call stack, when invalid data reaches a function and the source is unclear, or when you need to find which test or code path triggers a problem
npx skillsauth add BubbleBuffer/superpawers root-cause-tracingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Bugs often manifest deep in the call stack (file created in wrong location, database opened with wrong path, command run in wrong directory). Your instinct is to fix where the error appears, but that's treating a symptom.
Core principle: Trace backward through the call chain until you find the original trigger, then fix at the source.
digraph when_to_use {
"Bug appears deep in stack?" [shape=diamond];
"Can trace backwards?" [shape=diamond];
"Fix at symptom point" [shape=box];
"Trace to original trigger" [shape=box];
"BETTER: Also add defense-in-depth" [shape=box];
"Bug appears deep in stack?" -> "Can trace backwards?" [label="yes"];
"Can trace backwards?" -> "Trace to original trigger" [label="yes"];
"Can trace backwards?" -> "Fix at symptom point" [label="no - dead end"];
"Trace to original trigger" -> "BETTER: Also add defense-in-depth";
}
| Step | Action | Key Question | |------|--------|-------------| | 1. Observe | Note the error message and location | What exactly failed? | | 2. Immediate Cause | Find the code that directly triggered the error | What line produced the bad value? | | 3. Trace Up | Follow the call chain backward one level | What called this function? | | 4. Keep Tracing | Continue up the chain checking each caller | Where did the invalid value come from? | | 5. Original Trigger | Identify the first function that introduced bad data | What test or code path started this? |
Error: git init failed in /project/packages/core
What code directly causes this?
await execFileAsync('git', ['init'], { cwd: projectDir });
WorktreeManager.createSessionWorktree(projectDir, sessionId)
-> called by Session.initializeWorkspace()
-> called by Session.create()
-> called by test at Project.create()
What value was passed?
projectDir = '' (empty string!)cwd resolves to process.cwd()Where did empty string come from?
const context = setupTest(); // Returns { tempDir: '' }
Project.create('name', context.tempDir); // Accessed before beforeEach!
When you can't trace manually, add instrumentation:
async function dangerousOperation(directory: string) {
const stack = new Error().stack;
console.error('DEBUG dangerous operation:', {
directory,
cwd: process.cwd(),
nodeEnv: process.env.NODE_ENV,
stack,
});
await execFileAsync('some-cmd', ['init'], { cwd: directory });
}
Critical: Use console.error() in tests (not logger - may not show)
Run and capture:
npm test 2>&1 | grep 'DEBUG dangerous operation'
Analyze stack traces:
If something appears during tests but you don't know which test:
Use the bisection script find-polluter.sh in this directory:
./find-polluter.sh '.git' 'src/**/*.test.ts'
Runs tests one-by-one, stops at first polluter. See script for usage.
digraph principle {
"Found immediate cause" [shape=ellipse];
"Can trace one level up?" [shape=diamond];
"Trace backwards" [shape=box];
"Is this the source?" [shape=diamond];
"Fix at source" [shape=box];
"Add validation at each layer" [shape=box];
"Bug impossible" [shape=doublecircle];
"NEVER fix just the symptom" [shape=octagon, style=filled, fillcolor=red, fontcolor=white];
"Found immediate cause" -> "Can trace one level up?";
"Can trace one level up?" -> "Trace backwards" [label="yes"];
"Can trace one level up?" -> "NEVER fix just the symptom" [label="no"];
"Trace backwards" -> "Is this the source?";
"Is this the source?" -> "Trace backwards" [label="no - keeps going"];
"Is this the source?" -> "Fix at source" [label="yes"];
"Fix at source" -> "Add validation at each layer";
"Add validation at each layer" -> "Bug impossible";
}
NEVER fix just where the error appears. Trace back to find the original trigger.
console.error() not logger - logger may be suppressednew Error().stack shows complete call chaindata-ai
Use when a request involves multiple steps or files, or when an approved design must be turned into a detailed implementation plan
development
Use when deciding which SuperPawers skill should govern a new task or workflow step, before taking any other action
development
Use when starting feature work that needs git isolation or before writing committed spec, plan, or code artifacts
development
Use when a task list exists or is being created for multi-step implementation work, whether from a formal plan or an ad-hoc breakdown