Diagnose

SkillDev tools

The disciplined bug-fixing loop: no fix ships without a cause the fixer can state in one plain sentence, with evidence. Use when any fix is about to ship without a nameable cause, when a bug resists its first fix attempt, or when a bug-shaped lane brief points here.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Diagnose skill

What this skill tells your AI

The instructions your AI receives, as published by timharris707/skills in skills/run/diagnose/SKILL.md and read by ahel’s review.

A fix may not ship without a named cause: one plain sentence stating what was wrong, backed by evidence, readable by a non-engineer decider. This skill is the discipline a working lane follows inline when fixing bugs. It is not a lane type of its own, and it deliberately has no binding slots: everything repo-specific already arrived in the lane's brief.

The named-cause test is the trigger, and it binds on every fix. If you can already state the cause in one sentence and point at the evidence, the loop is satisfied: ship. If you cannot, the loop runs, however small the bug looks. "Hard bugs only" is the wrong gate, because the first fix attempt is where the vibes-fix ships: a change that makes the symptom go away for reasons nobody can state.

The loop

Six steps, in order. A failed fix re-enters at the step whose output it disproved, usually the hypothesis list, sometimes the repro itself.

  1. Reproduce red. Write a failing automated test that catches the user's exact symptom, before any fix attempt; it is the loop you iterate against now and the regression test you keep after. Where test infra genuinely cannot reach the bug (timing, a third-party boundary), the recorded fallback is a documented manual repro with exact steps, flagged as a fallback at close-out, never silently substituted.
  2. Minimize proportionately. Shrink the repro until it is tight, fast and deterministic enough to iterate against, cutting one element at a time and re-running after each cut. Tight is the purpose and the stopping point: a two-second deterministic loop is the tool; shrinking past it is polishing the repro instead of finding the cause. Non-deterministic bugs minimize toward a reproduction rate high enough to debug against.
  3. Hypothesize falsifiably. Generate several ranked hypotheses before testing any: a single hypothesis anchors on the first plausible idea. Each is stated so evidence could kill it, skeptic-style: "if X is the cause, then changing Y makes the bug disappear." A hypothesis with no prediction is a vibe; sharpen it or discard it.
  4. Instrument. Evidence gathering precedes any fix attempt. Each probe maps to one hypothesis's prediction, changing one variable at a time: a breakpoint beats ten logs, targeted logs beat logging everything and grepping. Tag every debug probe with one unique prefix so cleanup is a single grep. When a check fails, suspect the observation method before the system: indirect evidence (mtimes, cached screenshots, self-reports) feels cheaper than direct observation and lies more often.
  5. Fix. Only against the hypothesis the instrumentation confirmed. Watch the red test go green.
  6. Regression-test. Re-run the original, un-minimized repro; keep the failing test from step 1 in the suite as the regression test; grep the probe tag out. Then write the closing artifact.

The closing artifact

Two things, and close-out audits check for both:

  • The named cause: one plain sentence a non-engineer decider reads without translation ("the cache key omitted the locale, so two languages shared one entry"), with the evidence that confirmed it.
  • The regression test: the step-1 test, now green in the suite; or the recorded manual-repro fallback with its exact steps, flagged as a fallback.

An unnamed cause is not done, whatever the symptom is doing.

Structural causes feed the friction gate

Sometimes the named cause says the bug is a symptom: a missing seam, a rule duplicated in N places and updated in N−1. The lane still fixes the instance under this skill's own bar, then reports the structural cause as friction, codebase-review's third entry gate, in its close-out summary. The diagnosing lane never expands its own scope to fix the structure: that is a review-and-disposition matter, decided with more information than the lane has.

Where it sits in the pack

  • Lane briefs: orchestrate points bug-shaped items here, so the discipline arrives with the work.
  • Mid-build bugs: implement routes a bug surfacing mid-build here; the named-cause test binds before the lane resumes building.
  • Close-out audit: the orchestrator's audit checks the two closing artifacts on every bug fix; the named cause is what it reads first.
  • Domain memory: where the repo binds domain-memory, a root cause that reveals a standing fact (an assumption the repo held that the bug just proved wrong) is offered to it as a fact record: the same correction class as a decider correcting a session, with reality as the corrector.
  • Deliberately not hooked: handoff GOTCHAS. The durable copy of a diagnosis's lesson is the domain-memory record; writing it into handoff GOTCHAS too would be the same meaning in two places.

Done when (checkable: verify each line before reporting complete)

  • The cause is stated in one plain sentence with its confirming evidence, readable by a non-engineer decider, or no fix shipped.
  • A failing automated test existed before the fix, caught the user's exact symptom, passes after, and stays in the suite as the regression test; where one genuinely could not reach the bug, the recorded manual repro carries exact steps and is flagged as the fallback at close-out.
  • The repro was minimized until tight, fast and deterministic enough to iterate against, and no further.
  • Every hypothesis tested carried a falsifiable prediction, and the fix answers the hypothesis the instrumentation confirmed, not a hunch that survived by making the symptom vanish.
  • The original un-minimized repro no longer reproduces, and a grep of the probe tag comes back empty.
  • A structural cause, where the diagnosis revealed one, is reported as friction toward codebase-review's entry gate, with the instance fixed and the lane's scope unexpanded.
  • Where the repo binds domain-memory: a standing fact revealed by the root cause was offered as a record, or there was none.

Attribution

Adapted from Matt Pocock's diagnosing-bugs (MIT). The six-step spine is his: build a tight feedback loop and watch it go red, minimize by cutting one element at a time, generate ranked falsifiable hypotheses each stating its prediction (his format and several of these phrasings, near-verbatim), instrument one variable at a time with tagged probes rather than logging everything, write the regression test before the fix and re-run the original repro after, and state the confirmed cause so the next debugger learns. So are tight as the loop's quality bar, the reproduction-rate framing for flaky bugs, and the post-mortem handoff of architectural causes to his improve-codebase-architecture, the seed of the friction-gate escalation here.

What this pack changes: the named-cause test as the binding trigger (any fix shipping without a nameable cause, not hard bugs only), the failing-automated-test-first bar with the documented manual repro as a recorded, flagged fallback, proportionate minimize (tight enough to iterate against is the stopping point, not load-bearing minimality for its own sake), the plain-sentence closing artifact audited at lane close-out, the domain-memory feed for standing facts, and the friction-gate rewiring into codebase-review's entry gate with the diagnosing lane's scope pinned.

One line in step 4 (suspect the observation method before the system) is adapted from Lauren Tan's principle-prove-it-works (MIT).

Signals

GitHub stars
21
Forks
4
Last commit
Sep 2026
Hacker News mentions
20
Advanced
Catalog kind
skill
Gateway key
diagnose-timharris707
Source
github.com/timharris707/skills