Files
AILang/skills/debug/SKILL.md
T
Brummel 9b97a862f6 refactor: drop superpowers references in SKILL.md, add .claude/skills/ discovery
The skills are functionally complete and standalone — superpowers
references were attribution-only. Removed so a reader without the
superpowers plugin loaded isn't sent chasing dead links.

Plus: .claude/skills/<name> symlinks so Claude Code's Skill tool can
invoke them by name (analogous to the existing .claude/agents/
symlinks). Discovery section in skills/README.md updated to cover
both symlink sets.
2026-05-09 16:00:22 +02:00

6.2 KiB

name, description
name description
debug Use when a bug surfaces — failing test, segfault, wrong stdout, panic, or any observable misbehaviour. Bug fixes are RED-first TDD; no fix is attempted before the failing test is committed. Mandatory for any bug, including ones that look trivial.

debug — RED-first bug diagnoser

Violating the letter of these rules is violating the spirit.

Overview

Bugs in AILang are diagnosed and fixed by a two-stage handoff: this skill produces the RED test and the cause analysis; the implement skill then drives the fix to GREEN. Skipping the RED stage — even for "trivial" bugs — produces fixes that don't stick and tests that don't exist to catch the next regression.

When to Use / Skipping

Trigger this skill on:

  • a failing cargo test (any crate)
  • wrong stdout from ail run <example>
  • a segfault from a built binary
  • a panic in the compiler
  • a structured diagnostic from ailang-bencher or ailang-architect that names a concrete misbehaviour

Never skipped. A bug without a regression test is a code change, not a fix. Ad-hoc judgement that a bug is "too small for TDD" is the exact failure mode this skill exists to prevent.

The Iron Law

NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST
NO FIX WITHOUT A FAILING TEST FIRST

Both clauses are non-negotiable. The second was formerly the CLAUDE.md "Bug fixes — TDD, always" section before the 2026-05-09 skill-system migration.

The Process — four phases

Each phase must complete before the next starts.

Phase 1 — Root Cause Investigation

  1. Read the error message in full. Stack traces, line numbers, exit codes — none of them get skimmed.
  2. Reproduce with the shortest possible command. If you can't repro reliably, gather more data — do NOT guess.
  3. Check recent changes: git log --oneline -20, git diff <previous-iter-commit>..HEAD.
  4. For multi-component issues (compiler → emitter → linker; or runtime → C glue → binary), instrument every boundary. Find the layer where the data goes wrong before deciding which layer to fix.
  5. Trace data flow backward from symptom to source. Fix at source, not at symptom.

Phase 2 — Pattern Analysis

  1. Find a similar working example in the codebase. What's different?
  2. If the bug is in a pattern (e.g. ADT match lowering, RC drop emission), read the reference implementation completely. No skimming.
  3. List every difference between working and broken — however small.

Phase 3 — Hypothesis and Test

  1. State the hypothesis as a single falsifiable claim: "X is the root cause because Y."
  2. Write the failing test FIRST, before any fix attempt:
    • smallest possible reproducer (E2E in crates/ail/tests/e2e.rs, or unit test in the affected crate)
    • automated, deterministic — same input always same output
    • doc comment names the property the test protects, not just what it does
  3. Run it to confirm it fails on the current code, with the symptom the bug-report described.
  4. Commit the failing test as a separate commit: git commit -m "test: red for <symptom>".

Phase 4 — Hand off to implement

The fix itself is implement's job, run in mini-mode. Hand it:

  • path to the RED-test file
  • 1-2 sentence cause summary from Phase 1
  • hard constraint: "minimal fix, no surrounding cleanup, no opportunistic refactor"

implement runs the GREEN side and commits fix: <symptom>.

Phase 4.5 — 3+ failures = architecture question

If the third hypothesis fails:

STOP. Do not attempt Fix #4.

Three failed fixes in a row indicate the architecture is wrong, not that the latest hypothesis is wrong. Each fix likely revealed new shared state or coupling in a different place. Surface the architecture question to the user; do not guess again.

Handoff Contract

The carrier debug hands to implement:

Field Content
red_test_path absolute path to the failing test file
cause_summary 1-2 sentences naming the file + function + why
constraint "minimal fix, no surrounding cleanup"

Anything else (broader refactor, doc rewrite, new feature) is OUT of scope for the bug-fix iteration and gets queued for a separate one.

Common Rationalisations

Excuse Reality
"The implementer says it's obviously the new tag-extract emit" Confident guesses paper over real causes. Repro, isolate, RED test, then fix.
"Trivial bug, existing tests will catch it if we break something" The existing tests already passed while this bug shipped — by definition they don't cover it.
"30 seconds to repro, 30 seconds to fix, skip the test" 30 seconds to repro is also 30 seconds to capture as a regression fixture. Don't trade durable coverage for nothing.
"I'll write the test after the fix works" Test-after proves nothing about whether the test would have caught the bug pre-fix.
"Two fixes failed; the third hypothesis is the right one" Two failures means the hypothesis space is wrong. STOP, dispatch the debugger agent, do not guess again.
"End-of-day, just push the fix and write the test tomorrow" End-of-day pressure is exactly when shotgun fixes corrupt the tree. Clean tree + open bug > three speculative half-fixes merged.
"Architecture question is for next milestone, fix-and-revisit" Phase 4.5 fires NOW or never. Carrying the wrong shape forward compounds.

Red Flags — STOP and follow process

  • "Quick fix for now, investigate later"
  • "Just try changing X and see if it works"
  • "I see the symptom, let me fix it"
  • "The test is redundant, I manually verified"
  • "Pattern says X but I'll adapt it differently"
  • "One more fix attempt" (when ≥ 2 already failed)

All of these mean: return to Phase 1.

Cross-references

  • Agent dispatched: skills/debug/agents/ailang-debugger.md — carries the actual diagnostic work (read CLAUDE.md / DESIGN.md / JOURNAL, reproduce, write RED test, propose minimal fix).
  • Hand-off target: skills/implement/SKILL.md — runs the GREEN side after the RED test is committed.
  • Project source: former CLAUDE.md "Bug fixes — TDD, always" section is now superseded by this file; CLAUDE.md keeps a one-line pointer.