9b97a862f6
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.
154 lines
6.2 KiB
Markdown
154 lines
6.2 KiB
Markdown
---
|
|
name: debug
|
|
description: 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.
|