SuperAPI AI Directory

diagnose

General & other

View repository

Updated 10-16 09:54

About this skill

Diagnose

A discipline for difficult bugs. Only skip phases when you explicitly state the reason.

When exploring the codebase, use the project's domain glossary to build a clear mental model of the relevant modules, and obey all project rules:

  • docs/rules/ — project rules (RULES). All RULES are project-level constraints that must be obeyed during diagnosis and fixing: subsequent hypotheses, instrumentation, and fixes must not conflict with any rule.

Phase 1 — Establish a feedback loop

This is the core skill. Everything else is mechanical. If you have a fast, deterministic, agent-runnable pass/fail signal to detect the bug, you can find the cause—bisection, hypothesis testing, and instrumentation all merely consume that signal. If you don't, no amount of staring at the code will save you.

Invest disproportionate effort here.Be aggressive. Be creative. Refuse to give up.

Ways to build a feedback loop—try roughly in this order

  1. Failing test—at any seam that can reach the bug: unit, integration, end-to-end.
  2. Curl / HTTP script—send requests to the running dev server.
  3. CLI invocation—with fixed input, diff stdout against a known-correct snapshot.
  4. Headless browser script(Playwright / Puppeteer)—drive the UI, assert on the DOM/console/network.
  5. Replay captured trace. Save the real network requests/payloads/event logs to disk; replay them through the code path in an isolated environment.
  6. One-off test harness. Start the minimal subset of the system (one service, mock dependencies), and execute the buggy code path with a single function call.
  7. Property/fuzz loop. If the bug is "sometimes outputs wrong", run 1000 random inputs to find the failure pattern.
  8. Bisection tooling. If the bug appeared between two known states (commit, dataset, version), automate "start at state X, check, repeat" so that git bisect run。
  9. Differential loop. Run the same input through the old version and the new version (or two configurations) separately and diff the outputs.
  10. HITL bash script. Last resort. If a human must click, use scripts/hitl-loop.template.sh to drivethem, so the loop remains structured. The captured output is fed back to you.

Establish the correct feedback loop, and the bug is already 90% solved.

Iterate on the loop itself

Treat the loop as a product. Once you havealoop, ask:

  • Can it be faster? (Cache setup, skip irrelevant initialization, narrow the test scope.)
  • Can the signal be clearer? (Assert the specific symptom, not "didn't crash".)
  • Can it be more deterministic? (Fix time, set random seeds, isolate the filesystem, freeze the network.)

A 30-second flaky loop is almost as bad as no loop. A 2-second deterministic loop is a debugging superpower.

Nondeterministic bugs

The goal is not a clean reproduction, buta higher reproduction rate. Trigger the loop 100 times, parallelize, add stress, narrow the time window, inject sleeps. A bug with a 50% reproduction rate is debuggable; 1% is not—keep increasing the reproduction rate until it is debuggable.

When you truly cannot establish a loop

Stop and state it explicitly. List what you tried. Ask the user for: (a) access to an environment that can reproduce it, (b) captured artifacts (HAR files, log dumps, core dumps, timestamped screen recordings), or (c) permission to add temporary production instrumentation.Do notcontinue hypothesizing without a loop.

Do not enter phase 2 until you are confident the loop is reliable.

Phase 2 — Reproduce

Run the loop. Observe the bug appear.

Confirm:

  • The loop produces theuserfailure mode described—not another failure that happens to be nearby. Wrong bug = wrong fix.
  • The failure is reproducible across multiple runs (or, for nondeterministic bugs, the reproduction rate is high enough to support debugging).
  • You have captured the exact symptom (error message, incorrect output, slow response time) so that later phases can verify the fix actually resolved it.

Do not continue before reproducing the bug.

Phase 3 — Hypothesis

Before testing any hypothesis, generate 3-5 ranked hypotheses. Single-hypothesis generation anchors on the first plausible idea.

Each hypothesis must befalsifiable: state the prediction it makes.

Format: "If is the cause, then <changing Y> will make the bug disappear / <changing Z> will make it worse."

If you cannot state a prediction, the hypothesis is just intuition—discard it or sharpen it.

Show the ranked list to the user before testing. They often have domain knowledge that can immediately reorder it ("we just deployed a change to #3"), or know hypotheses they have already ruled out. A low-cost checkpoint that saves a lot of time. Do not block waiting—if the user is away, continue in your order.

Phase 4 — Instrumentation

Each probe must map to a specific prediction in phase 3.Change only one variable at a time.

Tool preferences:

  1. Debugger / REPL inspection—if the environment supports it. One breakpoint beats ten logs.
  2. Targeted logging—at the boundaries that distinguish hypotheses.
  3. Never "log everything and then grep".

Label every debug log, using a unique prefix such as [DEBUG-a4f2]. Final cleanup becomes a single grep. Unlabeled logs persist; labeled logs get deleted.

Performance branch. For performance regressions, logging is usually the wrong tool. Instead: establish baseline measurements (timing tools,performance.now(), profiler, query plan), then bisect. Measure first, fix later.

Phase 5 — Fix + regression test

Before fixingbeforeWrite a regression test — but only if there isthe right seam。

The right seam means the test can execute at the call pointthe real bug pattern's location. If the only available seam is too shallow (the bug requires multiple callers but there is only a single-caller test, and the unit test cannot reproduce the call chain that triggers the bug), writing a regression test there will only create false confidence.

If the right seam does not exist, that itself is a finding. Record it. The codebase architecture is preventing the bug from being pinned down. Flag this for the next phase.

If the right seam exists:

  1. Turn the minimized reproduction into a failing test at that seam.
  2. Watch it fail.
  3. Apply the fix.
  4. Watch it pass.
  5. Verify the fix complies with all RULES. Green but violating any rule counts as incomplete — go back and redo it. If a deviation from a rule is truly necessary, do not violate it silently: explicitly flag the conflict, explain the reason, and let the user decide.
  6. Rerun the phase 1 feedback loop against the original (unminimized) scenario.

Phase 6 — Cleanup + Postmortem

Before declaring completion, you must complete:

  • The original reproduction no longer reproduces (rerun the phase 1 loop)
  • The regression test passes (or the missing seam has been recorded)
  • All [DEBUG-...] instrumentation has been removed (grep prefix)
  • One-off prototypes have been deleted (or moved to a clearly marked debug location)
  • The final correct hypothesis has been stated in the commit / PR message — so the next debugger can learn from it

Then ask: what could have prevented this bug? If the answer involves architectural changes (no good test seam, tangled callers, hidden coupling), after the fix is completeafterwardrecord specific follow-up improvement suggestions, not before — you now have more information than you did at the start.

If the bug exposed a constraint that is invisible in the code and that the next person will step on again(implicit invariants, call-order requirements, operations that must appear in pairs), propose solidifying it as a root docs/rules/ under a RULES entry, so the constraint is explicitly discoverable from then on.