From asynkron-devtools
Systematic debugging techniques for unclear root causes. Uses test bombs (hypothesis elimination) and layered tests (pipeline stage isolation) to narrow down failures.
How this skill is triggered — by the user, by Claude, or both
Slash command
/asynkron-devtools:systematic-debug [bug description][bug description]The summary Claude sees in its skill listing — used to decide when to auto-load this skill
| Technique | Use when | Finds |
| Technique | Use when | Finds |
|---|---|---|
| Test Bomb | Root cause is unclear, multiple suspects | Which component/area is broken |
| Layered Test | System has a pipeline, output is wrong but stage is unclear | Which pipeline stage is broken |
| Both together | Complex bug in a pipeline system | Test bomb narrows the component, layered test pinpoints the stage |
A test bomb is a systematic debugging technique. Instead of writing one big test or guessing at the root cause, you:
H1_, H2_, H3_, etc.Each test is independent, fast, and documents exactly what it's proving or disproving.
/// TEST BOMB: Systematic elimination of suspected causes for [BUG DESCRIPTION].
public class [BugName]TestBomb(ITestOutputHelper output)
{
private readonly ITestOutputHelper _output = output;
// --- Section 1: [Area Name] ---
/// H1: [describe what you're testing and what pass/fail means]
[Fact(Timeout = 10000)]
public async Task H1_FirstHypothesis()
{
// Arrange — minimal setup for this one hypothesis
// Act — trigger the specific behavior
// Assert — one clear assertion
_output.WriteLine($"H1 Result: {result}");
Assert.Equal(expected, actual);
}
/// H2: [describe what you're testing]
[Fact(Timeout = 10000)]
public async Task H2_SecondHypothesis()
{
// ...
}
// --- Section 2: [Next Area] ---
/// H3: [describe what you're testing]
[Fact(Timeout = 10000)]
public async Task H3_ThirdHypothesis()
{
// ...
}
}
// TEST BOMB: Systematic elimination of suspected causes for [BUG].
describe('[BugName] Test Bomb', () => {
// --- Section 1: [Area Name] ---
// H1: [describe hypothesis]
test('H1_FirstHypothesis', async () => {
// ...
expect(actual).toBe(expected);
});
// H2: [describe hypothesis]
test('H2_SecondHypothesis', async () => {
// ...
});
});
# TEST BOMB: Systematic elimination of suspected causes for [BUG].
class TestBugNameTestBomb:
"""Systematic elimination of suspected causes for [BUG]."""
def test_h1_first_hypothesis(self):
"""H1: [describe hypothesis]"""
# ...
assert actual == expected
def test_h2_second_hypothesis(self):
"""H2: [describe hypothesis]"""
# ...
// TEST BOMB: Systematic elimination of suspected causes for [BUG].
func TestH1_FirstHypothesis(t *testing.T) {
// H1: [describe hypothesis]
// ...
if actual != expected {
t.Errorf("H1: got %v, want %v", actual, expected)
}
}
func TestH2_SecondHypothesis(t *testing.T) {
// H2: [describe hypothesis]
// ...
}
# C# / .NET
dotnet test --filter "FullyQualifiedName~TestBomb"
# TypeScript
npx vitest run --grep "Test Bomb"
# Python
pytest -k "TestBomb" -v
# Go
go test -run "TestH[0-9]+" -v ./...
| Pattern | Meaning |
|---|---|
| All pass | Bug is elsewhere — expand your hypotheses |
| All fail | Fundamental setup issue — check H1 carefully |
| One section fails | Root cause is in that area |
| Scattered failures | Multiple issues, or a shared dependency is broken |
| H1 passes, H3 fails | The difference between H1 and H3 isolates the cause |
A layered test isolates bugs in systems that process data through sequential stages. Instead of only testing the final output, you test each intermediate stage independently — so you know exactly where the pipeline breaks.
Input → Stage1 → Stage2 → Stage3 → Stage4 → Output
L0 L1 L2 L3 L4 L5
If L3 fails but L1 and L2 pass, the bug is in Stage3.
Source → Lexer → Parser → AST → Semantic Analysis → Code Gen → Output
L0 L1 L2 L3 L4 L5 L6
Request → Auth → Validation → Business Logic → Serialization → Response
L0 L1 L2 L3 L4 L5
Raw Data → Extract → Transform → Validate → Load → Query Result
L0 L1 L2 L3 L4 L5
Raw Data → Preprocessing → Feature Engineering → Model → Post-processing → Output
L0 L1 L2 L3 L4 L5
Source → Dependency Resolution → Compilation → Linking → Packaging → Artifact
L0 L1 L2 L3 L4 L5
/// LAYERED TESTS: Isolate which pipeline stage causes [BUG].
///
/// L1: [First stage] - does it produce correct intermediate output?
/// L2: [Second stage] - does it transform correctly?
/// L3: [Third stage] - does it handle the edge case?
/// L4: [Final stage] - full end-to-end assertion
/// L5: Side-by-side comparison of passing vs failing case
public class [BugName]LayeredTest(ITestOutputHelper output)
{
// ================================================================
// LAYER 1: [First Stage Name]
// ================================================================
/// L1_A: [what you're checking at this stage]
[Fact(Timeout = 10000)]
public async Task L1_A_Description()
{
// Get the intermediate output after stage 1
// Assert its structure/content is correct
}
// ================================================================
// LAYER 2: [Second Stage Name]
// ================================================================
/// L2_A: [what you're checking at this stage]
[Fact(Timeout = 10000)]
public async Task L2_A_Description()
{
// Get the intermediate output after stage 2
// Assert its structure/content is correct
}
// ================================================================
// LAYER N: Side-by-side comparison
// ================================================================
/// LN: Compare passing vs failing case at the broken layer
[Fact(Timeout = 10000)]
public async Task LN_ComparePassingVsFailing()
{
output.WriteLine("=== PASSING CASE ===");
// Run the passing input through the pipeline, log intermediate state
output.WriteLine("=== FAILING CASE ===");
// Run the failing input through the pipeline, log intermediate state
output.WriteLine("Compare the traces above to see the difference!");
}
}
// LAYERED TESTS: Isolate which pipeline stage causes [BUG].
describe('[BugName] Layered Test', () => {
// --- Layer 1: [First Stage] ---
test('L1_A_Description', () => {
const intermediate = stage1(input);
expect(intermediate).toMatchObject(expected);
});
// --- Layer 2: [Second Stage] ---
test('L2_A_Description', () => {
const intermediate = stage2(stage1(input));
expect(intermediate).toMatchObject(expected);
});
// --- Comparison ---
test('LN_ComparePassingVsFailing', () => {
console.log('=== PASSING CASE ===');
const passing = runPipeline(passingInput);
console.log(JSON.stringify(passing, null, 2));
console.log('=== FAILING CASE ===');
const failing = runPipeline(failingInput);
console.log(JSON.stringify(failing, null, 2));
});
});
# LAYERED TESTS: Isolate which pipeline stage causes [BUG].
class TestBugNameLayered:
"""Isolate which pipeline stage causes [BUG]."""
# --- Layer 1: [First Stage] ---
def test_l1_a_description(self):
"""L1_A: [what you're checking]"""
intermediate = stage1(input_data)
assert intermediate == expected
# --- Layer 2: [Second Stage] ---
def test_l2_a_description(self):
"""L2_A: [what you're checking]"""
intermediate = stage2(stage1(input_data))
assert intermediate == expected
| Pattern | Meaning |
|---|---|
| All layers pass | Bug is in integration between stages, not individual stages |
| L1 fails | Problem is at the first stage — likely input parsing |
| L1-L2 pass, L3 fails | Bug is in stage 3 — inspect L2 output going into L3 |
| Only last layer fails | All stages work individually — check final assembly |
| Intermittent failures | Likely state leaking between stages or timing issue |
Test bombs:
H1_CatchBlockReturnsUndefined not H1_TestLayered tests:
L1_A_, L2_A_, etc. — makes the progression obviousnpx claudepluginhub asynkron/asynkron-skills --plugin asynkron-devtoolsEnforces systematic root cause analysis for bugs, test failures, unexpected behavior, and regressions via five-phase workflow: Understand, Reproduce, Isolate, Fix, Verify.
Systematic debugging methodology for finding and fixing bugs through root cause analysis. Covers reproduce-investigate-hypothesize-fix-prevent workflow, evidence-based diagnosis, and bug category strategies.
Enforces systematic root cause analysis before fixes for bugs, test failures, unexpected behavior, performance issues, and build failures.