Install
$ agentstack add skill-rgnicoara-debug-driven-debug-driven ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Debug-Driven
A structured, hypothesis-driven debugging loop. Instead of immediately guessing a fix, this skill drives a disciplined hypothesis -> instrument -> reproduce -> analyze -> fix -> verify -> cleanup cycle.
Core Philosophy
Never guess. Instrument, observe, then fix.
The best debuggers do not immediately patch code. They:
- Form multiple hypotheses about what could be wrong
- Instrument the code to test each hypothesis with real runtime data
- Let the human reproduce the bug (they are in the loop, not the AI)
- Analyze the evidence and converge on a root cause
- Apply a targeted fix and ask for confirmation
- Clean up all instrumentation
This skill enforces that workflow.
Phase 0: Bug Intake
Before doing anything else, gather what you know. Extract from the user's message:
- Symptom: What is actually happening?
- Expected: What should happen instead?
- Reproduction steps: How to trigger it?
- Stack / environment: Language, framework, relevant files?
- Error output: Any logs, stack traces, error messages already available?
If reproduction steps are missing or unclear, ask. You cannot proceed without them.
Reproduction scripting: If the bug can be triggered by a deterministic sequence (API call, test case, CLI command, browser automation script), write a reproduction script during intake. This script can be re-run by the agent in later cycles without requiring the user to manually reproduce each time. The user should still manually verify the final fix (Phase 6), but intermediate reproduction cycles (Phase 3) can use the script.
Hypothesis Labeling Rules
Hypothesis labels are session-global and monotonic:
- Start the first set at
H1 - Never reuse a label within the same debug session
- After a failed verification, continue from the highest label used so far (
H4,H5, ...) rather than restarting atH1 - If an older hypothesis remains relevant, keep its original label instead of renumbering it
Keep track of the active hypotheses for the current cycle. An active hypothesis is any hypothesis that is still INCONCLUSIVE or newly introduced and not yet ruled out.
New hypothesis labels may ONLY be introduced in two places:
- A Phase 1 cycle (initial or after all hypotheses are ruled out)
- The "Path Forward" section of the Failed-Verification Recovery Template
In both cases, the full Phase 1 format (label + Mechanism + Confirm + Rule out) is required before the label exists. You cannot introduce a new Hn during Phase 4 analysis, Phase 5 fix, or inline in instrumentation code. If analysis reveals a new theory, note it in prose ("this suggests the issue may be in X") and then formally open a Phase 1 cycle to define it.
Phase 1: Hypothesis Generation
Code reading before hypothesizing
Before generating hypotheses, read enough code to form grounded theories — not just the file mentioned in the bug report:
- Start at the symptom: read the code where the bug manifests (the reported file/function)
- Trace one level out: follow the call chain — who calls this function? What does it call? Read those callers/callees
- Check data flow: if the bug involves wrong values, trace where those values originate (config, DB query, API response, user input)
- Look for relevant state: if the component has initialization, lifecycle hooks, or caching, read those paths — bugs often hide in setup code, not in the main logic
Stop when you can articulate at least 3 structurally distinct theories about what could be wrong. You do not need to read the entire codebase — just enough that your hypotheses are grounded in actual code paths, not pure speculation.
Generating hypotheses
Generate at least 3 distinct hypotheses about what could be causing the bug. There is no hard upper limit, but each hypothesis must be structurally distinct — do not pad the list with variations of the same theory.
Format each hypothesis using exactly this structure. Do NOT use numbered lists, paragraphs, headings, or any other layout. Use * bullet prefix and indented sub-fields:
* H1: [Short label — max ~10 words, e.g. "Off-by-one in pagination cursor"]
- Mechanism: [1-2 sentences: how this fault causes the observed symptom]
- Confirm: [What specific log values or behavior would prove this fault exists]
- Rule out: [What specific log values or behavior would prove this fault does NOT exist]
Example:
* H1: Discount rate read from stale cache entry
- Mechanism: The pricing service caches discount rates for 5 minutes. If the rate
was updated after the cache was populated, the old rate is applied to new orders.
- Confirm: Log shows discount_rate=0.0 at cart.js:44 despite DB having rate=0.1
- Rule out: Log shows discount_rate matches the current DB value
Writing precise Confirm / Rule-out criteria: Criteria must name specific expected values or value ranges, not ambiguous states. The agent doing the verdict check will compare log output literally against your criteria — if the criteria say "is false" but the log shows undefined, that is not a match. Write criteria that account for every value the code can actually produce.
- Good:
initialDataFetched is falsy (false, undefined, or null)— covers all cases - Good:
discount_rate === 0.0— exact value - Bad:
initialDataFetched is false— what if it'sundefined? The verdict becomes ambiguous - Bad:
the value is wrong— not specific enough to check mechanically
If you are unsure which exact value to expect, use a range or disjunction (X is one of [a, b, c]) rather than guessing a single value.
Rules:
- Order by plausibility (most likely first)
- Cover structurally distinct failure modes - do not list variations of the same root cause
- At least one hypothesis should be in the reported area, and at least one should cover an upstream or downstream assumption you are NOT sure about
- Do not propose a fix yet - this is purely diagnostic
- Every hypothesis must describe a specific fault — something wrong that causes the symptom. "The recount triggers correctly" or "trace the execution flow" are not hypotheses. If it cannot be phrased as "the bug is caused by [specific fault]", rewrite it or drop it.
- Do NOT offer to skip instrumentation. No matter how confident you are from reading the code, you must instrument and observe runtime evidence before proposing a fix. Code reading produces hypotheses, not conclusions.
- Do NOT shortcut the logging method. Use the correct method for the project type (file-append for non-browser, fetch-to-ingest-server for browser). Do not substitute
console.logto "move faster" or because you are confident - follow the documented flow.
Present the hypotheses to the user as context for what you are about to instrument, then immediately proceed to Phase 2 in the same response. Do not pause, do not ask for feedback, do not ask "what should we do next?", do not offer alternative courses of action. The user will have a chance to intervene during Phase 3 (reproduction) if any hypothesis is wrong.
Phase 2: Instrumentation
Design and inject logging statements that will generate evidence for or against each hypothesis.
Log output method
All debug instrumentation logs to a file (./debug-output.log by default) rather than to stdout or console. This lets the agent read the log file directly after reproduction.
- Non-browser apps -> file-append using the language's native API. See [log-output-recipes.md](references/log-output-recipes.md) for one-liners and full examples per language.
- Browser apps ->
fetch()to the HTTP log ingest server bundled with this skill. See [log-output-recipes.md](references/log-output-recipes.md) for server launch procedure and fetch pattern.
You MUST use the method above for the project type. Do NOT substitute console.log because it seems easier. The only valid reason to use console.log for browser apps is if the user explicitly refused to run the ingest server.
Log format
Every log line MUST start with the hypothesis label, followed by location, data label, and value:
| : | |
The Hn prefix is not optional — it is what makes hypothesis-driven analysis possible. Without it, log lines cannot be filtered by hypothesis, and the Phase 4 mechanical verdict check cannot work. Every _dbg() call or fetch() body must embed the Hn label as the first field in the log string itself, not as a separate argument.
Correct — hypothesis label is part of the string:
_dbg('H1 | auth.js:42 | token_received | ' + JSON.stringify(token));
fetch('http://localhost:' + port + '/log', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: 'H2 | cart.js:88 | discount_rate | ' + rate })
});
Wrong — no hypothesis label, no file:line, freeform arguments:
_dbg('tokenReceived', token); // missing Hn, missing file:line
_dbg('discount', { rate, subtotal }); // missing Hn, missing file:line
If a log line does not match | : | | , it is malformed. Fix it before proceeding.
Log placement strategy
- Log at entry or exit of suspicious functions (capture inputs and outputs)
- Log before or after state mutations (capture before and after values)
- Log inside conditional branches (which path is actually taken?)
- Log loop boundaries if loops are involved (how many iterations? what values?)
Wrapping instrumentation in region blocks
All debug instrumentation MUST be wrapped in #region DEBUG / #endregion DEBUG blocks. This makes cleanup reliable - entire regions can be found and deleted as units.
Use the appropriate region markers for the language:
| Language | Start marker | End marker | |---|---|---| | JavaScript / TypeScript | // #region DEBUG | // #endregion DEBUG | | Python | # region DEBUG | # endregion DEBUG | | C# | #region DEBUG | #endregion DEBUG | | Java / Kotlin | // region DEBUG | // endregion DEBUG | | Go / Rust | // region DEBUG | // endregion DEBUG | | Ruby | # region DEBUG | # endregion DEBUG |
Rules:
- Every piece of debug code (log statements, debug-only imports, temporary variables) goes inside a region block
- Multiple region blocks per file are fine - group by hypothesis
- Never put non-debug production code inside a region block
- The region comment is the outer wrapper; log lines and helpers go inside
Scoping instrumentation
- Add only what is needed to test your hypotheses - do not spam logs everywhere
- If you have 4 hypotheses, group logs by which hypothesis they test
- Each group should be in its own region block
Guardrails:
- Only add instrumentation that is explicitly tied to one or more active hypothesis labels
- Do not add freeform or "just in case" logging with no hypothesis mapping
- If a hypothesis is no longer active, stop adding logs for it unless you explicitly reactivate it with a stated reason
- Every
Hnlabel used in instrumentation must reference a hypothesis that was formally defined in Phase 1 format (short label + mechanism + evidence criteria). You may NOT invent a newHntag in instrumentation code and define the hypothesis later or not at all — that is not a hypothesis, it is freeform logging with a label painted on it. - Instrumentation tests hypotheses, not fixes. If you want to know whether a fix worked, that is Phase 6 (user reproduction). Do not add logging "to see if the fix executes" — that conflates diagnosis with verification and leads to drift.
- Instrumentation is read-only. Debug code observes and logs — it does NOT change application behavior. Do not add
setTimeouttriggers, force-call methods, bypass guards, set flags, inject test data, or modify control flow "to see what happens." If you want to test whether changing behavior X fixes the bug, that is a Phase 5 fix, not Phase 2 instrumentation. Instrumentation that alters the system under observation invalidates the evidence it collects.
After adding instrumentation, tell the user exactly what was added and where.
> For complete per-language examples (Node, Python, Go, Java, C#, Ruby, browser fetch), see [log-output-recipes.md](references/log-output-recipes.md).
Phase 3: Reproduction Request (Interactive Loop)
After adding instrumentation, present an interactive reproduction menu. You MUST use a tool call that blocks execution and waits for the user to select an answer - do NOT just print the choices as text in your response. Use whichever tool your platform provides for asking the user a question with predefined selectable answers (for example, ask, askQuestion, ask_user, or equivalent).
If an automated reproduction script exists (written during Phase 0 or a prior cycle), run it instead of asking the user. Skip the interactive menu and proceed directly to Phase 4. Only use the interactive menu when no reproduction script exists, or for the final verification (Phase 6) which always requires user confirmation.
Question text: > I've added instrumentation to test [H1, H2, H3]. > > Please reproduce the bug using these steps: > 1. [reproduction step 1 from Phase 0] > 2. [reproduction step 2 from Phase 0] > 3. ... > > Debug output will be written to ./debug-output.log. I will read it after you reproduce. > Log handling for this run: [clearing or appending] ./debug-output.log because [brief reason]. > If the app needs a restart or rebuild, do that first. > > After testing, select an option below.
Answer choices:
Issue reproduced -- proceed with analysisMark as fixed
The second option covers the rare case where the bug resolves during instrumentation (e.g., the agent touched a file that triggered a rebuild that fixed a stale cache). In the normal flow, choose option 1.
If your platform does not provide a blocking question tool with selectable answers, present the same prompt and the same two choices as plain text, then wait for the user's reply before continuing.
Behavior:
- "Issue reproduced" -> proceed to Phase 4 (Log Analysis). The agent reads
./debug-output.logdirectly. - "Mark as fixed" -> skip directly to Phase 7 (Cleanup).
Phase 4: Log Analysis
Phase 4 is analysis only — no code changes, no instrumentation edits. If you need more data, the outcome is INCONCLUSIVE and you return to Phase 2. Do not edit source files during Phase 4.
Read ./debug-output.log (or whatever log file path was used). Then:
- Parse the log lines using the
| : | |format — filter by hypothesis label to group related lines - For each active hypothesis, check whether the logs confirm, refute, or leave it inconclusive
- Identify the specific line or value that reveals the root cause
- If the root cause is still unclear, go back to Phase 2 and add more targeted instrumentation
After every analysis round, you MUST present a verdict for every active hypothesis. Every active hypothesis must get exactly one of: CONFIRMED, RULED OUT, or INCONCLUSIVE. No other verdicts are valid. In particular, "CONFIRMED WORKING" is not a verdict — hypotheses describe faults, and a fault is either present (CONFIRMED) or absent (RULED OUT).
How to produce each verdict — mechanical check, not a judgment call:
- Re-read the hypothesis's Confirm field. Does a specific log line match it? If yes -> CONFIRMED candidate.
- Re-read the hypothesis's Rule out field. Does a specific log line match it? If yes -> RULED OUT, even if the behavior "looks related."
- If a log line matches the Rule-out criteria, the verdict cannot be CONFIRMED — full stop. The Rule-out condition is met.
- If neither Confirm nor Rule-out criteria are clearly matched -> INCONCLUSIVE.
Use this exact format for every verdict — one block per hypothesis, with the
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: rgnicoara
- Source: rgnicoara/debug-driven
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.