Debug
Disciplined root-cause loop — reproduce at the cheapest layer that can see the failure class (runtime for runtime-class bugs), isolate, find the true cause, fix it through the normal change gate, and regression-lock it at the lowest layer that reproduces. Consults the project's accumulated learnings first and records new ones.From its SKILL.md
npx -y skills add mckissinger/keel --skill debugAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
5.0 KB, as published. Nobody here has run it
Debug
Find and fix the real cause of a defect, and make sure it can't come back. Debugging is its own session: it does not silently expand scope, and its fix goes through the normal gate (a branch, a pin, a regression test) — never an ad-hoc patch to main.
Before you start
- Consult the project's accumulated learnings first. If the project keeps a durable learnings log (a
lessons/dir,decisions/, the stack profile's Q12 failure-signature table, or other stack-profile gotchas), read the relevant ones — this exact defect class may already be solved. Don't re-derive a known fix. - State the bug as an observation, not a theory. What's the exact symptom, where, and what did you expect instead? If you can't reproduce it, that's step one.
The loop
- Reproduce — at the cheapest layer that can see this failure class. Route by the profile's ladder (Q11): a type/shape error reproduces at the static rung in a second; a logic bug in a unit test; a wiring/interaction bug in a component-render test; only a failure class in the stack's escalation holes needs the real runtime. Escalating past a rung that could have seen the bug wastes the cost gap (the e2e rung runs ~100× slower and flakier — the ⚠ Q11 scar); escalate deliberately, not by habit. Runtime-class bugs still reproduce at runtime: the framework's worst bugs live precisely where the test environment diverges from the real runtime (a component/module-boundary error, a build-transform error, a hydration mismatch — the profile's ⚠ Q3/Q6 divergences), so for those, reproduce by running the real thing (the profile's activation driver against the actual build), never by trusting a green lower rung. Reproduction commands run bounded per the profile's Q12 timeout rule — a hang is a symptom to classify, not a wait. A bug you can't reproduce, you can't verify you fixed.
- Isolate. Narrow to the smallest input/code path that still triggers it. Bisect (git, or by disabling halves). Read the actual values, run the actual checks — don't reason from "the code looks like it would."
- Root cause, not symptom. Name the underlying cause and why it produces the symptom. A fix that makes the symptom disappear without explaining the cause is a patch, and it'll resurface. When two or more root causes stay plausible and the evidence does not discriminate between them, that is a consultable judgment question — dispatch it per
skills/consult/SKILL.md(cited, never restated) rather than committing to the hypothesis you happen to be holding. - Fix through the normal gate — debug owns diagnosis, not landing. Route the fix by one rule: a fix with no design/spec judgment (the change is fully stated by the diagnosis — a wrong constant, an off-by-one, a missing guard) → a
punch-listitem (batched with its peers, one chore PR, one batch pin); a fix needing a spec'd done-condition or any design decision →spec-change(one milestone: branch →implement-milestone→verify-milestone→ pin). This session's output is the diagnosis + regression test handed to whichever lane fits — never an ad-hoc patch tomain, and never a third lane of its own. - Regression-lock it — at the lowest layer that reproduces. Every fix that reflects a defect class graduates into a test that fails before the fix and passes after, written at the cheapest rung that can see it (a unit test for a logic bug, a component-render test for a wiring bug, a no-fixture e2e only for a true runtime-class bug) — so the class is locked in CI where it can't recur silently, at the price of the rung it belongs on. This is the backfill rule: a defect that escaped to a higher rung is the evidence of missing coverage one rung down.
- Record the learning. If the root cause was non-obvious or stack-specific, write it where the project keeps durable learnings: a one-line
lessons/entry, adecisions/note, or — if it's a stack gotcha future verification should always check — an update tospecs/stack-profile.md. The next session inherits it instead of re-debugging.
Boundaries
- One bug, one session. Don't fold "while I'm here" refactors or adjacent fixes into a debug session — note them, spec them separately. Scope creep hides the root cause.
- Verify the fix the way the bug was found. If it took a runtime render to reproduce, it takes a runtime render to confirm — a green unit suite is not proof a runtime bug is fixed.
- The fix is verified like any change. Its
verified:pin comes fromverify-milestone, not from your own say-so in this session.