Build a feedback loop for a hard or performance bug, and classify every bug already observed by a user or production. Use when a defect resists the first obvious fix, reproduces intermittently, spans component boundaries, or has escaped to a user or production; reach for it early, so the loop decides where to look.
Installs into .claude/skills of the current project.
Sponsors
SSkills DirectorySkills Directory
Know which skills are safe — weekly.
SSkills DirectorySkills Directory
Is that skill safe to install?
Are you the author of Diagnosing Bugs?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/byheaven-diagnosing-bugs)
---
name: diagnosing-bugs
description: Build a feedback loop for a hard or performance bug, and classify every bug already observed by a user or production. Use when a defect resists the first obvious fix, reproduces intermittently, spans component boundaries, or has escaped to a user or production; reach for it early, so the loop decides where to look.
---
# Diagnosing Bugs
A fix is done when a command that observes the user's exact failure goes red before it and green after it. **Building that feedback loop is the skill; everything after is mechanical.** Build it as early as the bug allows: a theory formed from the code before anything observes the failure tends to fix the wrong thing, while a loop turns each theory into a quick yes or no. Reading code to find where and how to observe the failure is part of building it.
## Phase 1 — Build the feedback loop
Construct one command that observes the failure. Candidate forms, preferred first: failing test → curl/CLI script with fixture diff → headless browser probe → replayed captured trace → disposable harness → property/fuzz loop → bisect harness → last resort, a human-in-the-loop script that tells the user exactly what to click and captures the result, whose capture then feeds an agent-runnable replay.
Phase 1 is complete only when you can state **one command you have already run at least once** (show the invocation and redacted output) and all four hold:
- **Red-capable** — it asserts the user's exact symptom, not merely "no error".
- **Deterministic** — pin time, seed randomness; for flaky bugs the goal is a raised reproduction rate (loop it 100×, parallelize, add pressure), not a clean repro.
- **Fast** — as fast as the bug allows, since every probe and every hypothesis reruns it.
- **Agent-runnable** — you can run it yourself without a human.
If the loop truly cannot be built, ask the user as [Asking](../task-owner/references/runtimes.md#asking) says: "I could not build a command that reproduces this bug. I tried: <what was tried>. Can you give me <environment access, a capture, or production instrumentation>?"
Redact secrets everywhere: literals become `<REDACTED>`, loops read from environment variables, captures quote only the signal-bearing lines.
## Phase 2 — Reproduce and minimize
Confirm the loop is red on the failure the user described — fixing the wrong bug is the expensive version of fixing nothing. Then minimize the repro until what remains makes the cause clear.
## Phase 3 — Hypotheses
Hold several ranked, falsifiable hypotheses rather than anchoring on the first plausible idea. Each carries a prediction: "if X is the cause, changing Y makes the bug disappear." A hypothesis without a prediction is a vibe — discard or sharpen it.
## Phase 4 — Instrument
Every probe tests a specific prediction, so its result moves one hypothesis; every debug line you add is gone before handover. Performance problems branch here: measure a baseline first, then bisect.
## Phase 5 — Fix with a regression test
Fix where the system first went wrong. A guard at the crash site is the fix only when the state it handles is legitimate; when that state should never exist, find what produced it.
Before fixing, turn the minimized repro into a failing test — but only where a correct seam exists. If the only available seam is too shallow to observe the real trigger chain, the test buys false confidence; the missing seam is itself a finding — record it and hand it to architecture work instead. With a seam: watch the test go red → fix → watch it go green → re-run the original unminimized loop from Phase 1.
## Phase 6 — Clean up
- Original repro no longer reproduces.
- Regression test passes, or the missing-seam finding is recorded.
- Every debug line added during the investigation removed.
- Disposable harnesses deleted.
- The winning hypothesis written into the commit/PR message for the next debugger.
- When the deciding fact took a deep dig to find, the cheap always-on signal that would have shown it at first look is proposed in the report; adding it is a separate decision.
If the bug reached a user or production, cleanup also classifies the escape against the project's behavior registry (its registered behavior assertions) at the pre-escape source ref; a project with no separate registry registers behavior in its product documentation and tests, so classify against those:
- `registered-assertion-regression` — the failing behavior already contradicted a registered assertion at that ref; evidence names the immutable ref, product-doc path, and assertion line.
- `new-behavior-gap` — no registered assertion covered the behavior at that ref; the repair registers one with its executable carrier or explicit carrier/registry gap, and evidence names both the before ref and the new registration.
Persist the result atomically as one event: when and where (user or production) the escape was observed, its class, and its evidence. It goes on the owning task record in the fields the project's task-record rule defines, or, with no task record, in the evidence the task's report links, such as its pull request. A worker returns that exact payload to the task owner instead of writing the record itself. Commit/PR prose preserves the winning hypothesis but does not replace this event. Phase 6 remains incomplete while a known user or production escape lacks its durable classification.