Use when something is broken, failing, flaky, or slow and the cause is not yet known. Reproduce, narrow, then one falsifiable hypothesis at a time under a three-hypothesis ceiling; regression test before the fix; a guard so it cannot recur silently. Produces a fixed-shape Diagnosis. Production incidents restore service first.
Skill: Debugging Architect — Diagnosis Without the Spiral
Apply Guidelines Skill — load the guidelines-meta skill before proceeding.
Profile section owned: §Guardrails → Known blind spots (Guidelines §5). Every root cause that a green pipeline failed to catch gets written there, so the next change is checked against it.
Why this skill exists: debugging is the one activity where an agent reliably makes things worse. The failure mode is not being wrong — it's being wrong repeatedly and confidently, changing five things at once, and leaving a codebase that's harder to reason about than before it started. Every rule below exists to stop that.
Operational Constraints (Strict)
Reproduce before you theorise. A bug you cannot reproduce is a bug you cannot verify you fixed. If it can't be reproduced, that is the finding — say so and pivot to §Unreproducible.
Change one thing at a time. Each pass alters exactly one variable and predicts the result before running. Two simultaneous changes make a passing result uninterpretable.
Hard pass ceiling (Guidelines §16). Three hypotheses tested and disproved → stop. Do not start a fourth. State what's been ruled out, name the assumption most likely wrong, and ask one diagnostic question. This is §17's debug-spiral rule made binding: "still broken" three turns running means the frame is wrong, not that the next guess needs more effort.
Never fix by weakening. Deleting an assertion, loosening a tolerance, adding a skip, widening a mock, or wrapping the symptom in a try/catch is not a fix — it is the bug plus concealment (Testing Architect constraint 3).
No speculative fixes. "This might help" is not a fix. If you can't state why the change makes the symptom impossible, you haven't found the cause. Changes that "seem to help" without an explanation are the beginning of the spiral, not the end of it.
Revert your own probes. Debug logging, temporary instrumentation, and narrowing scaffolds come out before you're done — or are called out explicitly if deliberately kept.
Production first, diagnosis second. If users are affected, deployment-architect's Rollback Mode runs first. Restore service, then debug the artifact at leisure. Production is not a debugging environment.
Git and golden-file guards are enforced by the plugin's PreToolUse hook (Guidelines §9, §10): every git write, gh publish, --no-verify, and snapshot update is denied by the runtime; read-only inspection stays open. git bisect is a branch-moving operation and is denied like the rest — surface the command for the user, or use a read-only equivalent.
What to Read, and When
The six phases below are the spine and apply to every run. These are read on demand:
Read
When
${CLAUDE_SKILL_DIR}/references/flaky.md
The failure is intermittent. Different discipline: you are proving a rate, not a state.
${CLAUDE_SKILL_DIR}/references/unreproducible.md
It cannot be reproduced. Ship instrumentation, not a guess.
Running the gates after the fix — and §3 when a test "passes but the feature is broken".
module-propagation
The fix touches shared shape, a public API, or an origin.
module-findings
Stating confidence in a root cause.
Phase 1 — Establish the Symptom
Answer these before touching code. Guessing here costs whole sessions.
Question
Why it matters
What exactly happens, and what was expected?
"It doesn't work" is not a symptom. Get the actual output, error, or wrong value.
What's the smallest input that triggers it?
Reduction is diagnosis — a shrinking repro usually names the cause on its own.
When did it last work?
A known-good point converts an open search into a bounded one.
What changed since?
Code, dependency, data, config, environment, clock, or a service you don't own.
Deterministic or intermittent?
Intermittent means state, ordering, timing, or concurrency — see §Flaky.
Where does it not happen?
Passing locally but failing in CI is itself a diagnosis: environment, not logic.
Get the real error text. Not a paraphrase — the stack trace, the failing assertion, the actual value. A paraphrased error has already lost the detail that identifies the cause.
Phase 2 — Narrow Before Hypothesising
Resist the first plausible theory. Cut the search space first; a bisected search beats an inspired guess, and it works when you have no intuition at all.
Bisect along whichever axis is cheapest here:
Time — which commit introduced it? git bisect is the tool; surface the commands, don't run them (§8). A git log over the suspect paths is often enough.
Code path — does the failure survive when a layer is removed? Call the unit directly, bypass the framework, stub the collaborator.
Data — does it fail for all inputs or one shape? Empty, boundary, unicode, very large, null, pre-migration rows.
Environment — local vs. CI vs. deployed. Runtime version, env vars, timezone, locale, filesystem case-sensitivity, network egress.
Config — does it fail with defaults? A wrong flag is a common and invisible cause.
The layer question, asked early: is this your code, your usage of a dependency, the dependency itself, or the environment? Each has a different fix and a different owner, and mixing them up wastes the most time.
Phase 3 — One Hypothesis at a Time
For each pass, write these three lines before running anything:
Hypothesis: <the specific mechanism you believe causes this>
Prediction: if true, <this exact observable> will happen
Test: <the single change or probe that discriminates>
Rules:
The prediction must be falsifiable. "It'll probably work better" tests nothing. "The value will be undefined at line 42" is a real test.
A disproved hypothesis is progress — record it. The list of ruled-out causes is the most valuable artifact of a hard debug session, and it's what makes handing over possible.
Confidence gate (module-findings §2). Before declaring a root cause, self-score: is this proven or merely consistent with the evidence? Below ~80, say so plainly and keep it labelled as a theory. A confidently-stated wrong diagnosis is worse than an honest "not certain yet" — the user acts on it.
Count the passes. At three disproved hypotheses, stop (§3). Not a suggestion.
Check the known blind spots first — the profile's §Guardrails list, plus implementing-architect's protocols. A startling number of "impossible" bugs are: a stale template binding that type-check can't see, a test double missing a method, a config declared in one environment but not another, or a cache serving a previous build.
Phase 4 — Prove the Cause
Before fixing, close the loop both ways:
Explain the whole symptom. A cause that explains most of it is usually adjacent to the real one. Unexplained residue means you're not done.
Make it appear and disappear on demand. Toggle the cause; the symptom must follow. That's proof, not correlation.
Explain the "why now" — if this code is old, what changed to expose it? Skipping this is how the same bug returns in a different shape.
Phase 5 — Fix It Once
Write the failing test first, per the testing-architect skill. It must fail for the right reason — run it before the fix and read the failure. A regression test that would pass without the fix is decoration.
Fix the cause, not the symptom. If the honest fix is large, say so and let the user choose between a scoped mitigation (labelled as such, with the real fix as a follow-up) and doing it properly now. Never disguise a mitigation as a fix.
Smallest change that removes the cause (Guidelines §2, §3). Do not refactor the surrounding area because you were in there.
Check propagation. If the fix touches shared shape, a public API, or an external origin, load the module-propagation skill and run the matching protocol — bug fixes hit the same mirror sites features do, with less scrutiny.
Run the gates per the module-gate-battery skill, once as a batch.
Remove your probes (§6).
Phase 6 — Make It Impossible to Recur Silently
The step that separates debugging from firefighting. A fix nobody can accidentally undo is worth more than the fix itself.
The regression test stays. Named for the bug's behaviour, not its ticket.
If a gate should have caught this and didn't, that is a finding about the gates: write it into the profile's §Guardrails → Known blind spots, in one line, phrased as what to check next time.
If the class can recur elsewhere, add it to §Recurring Propagation Sites so future changes get swept.
If it was a production incident, hand the guard to deployment-architect — a pre-flight check is cheaper than a second outage.
If the root cause was a wrong assumption in a plan, say so; that's feedback for planning-architect, not shame.
Quality Checklist Before Claiming "Fixed"
Reproduced before diagnosing — or explicitly reported as unreproduced.
Narrowed before hypothesising; the search was cut, not guessed at.
Each pass changed one variable with a written, falsifiable prediction.
Stopped and reassessed at three disproved hypotheses rather than continuing.
Root cause explains the whole symptom, and toggling it toggles the symptom.
Failing test written first, and it failed for the right reason.
Fix addresses the cause; any mitigation is labelled a mitigation.
Nothing was weakened — no deleted assertion, loosened tolerance, added skip, or swallowed exception.
Propagation protocol run if the fix touched shared shape, a public API, or an origin.
Debug probes removed.
Blind spot written to the profile if a gate should have caught this.
Confidence stated honestly; an unproven cause is labelled unproven.
No git add, commit, push, or bisect — commands surfaced for the user.
v1.0 — version history in CHANGELOG.md
1---2name: debugging-architect3description: Use when something is broken, failing, flaky, or slow and the cause is not yet known. Reproduce, narrow, then one falsifiable hypothesis at a time under a three-hypothesis ceiling; regression test before the fix; a guard so it cannot recur silently. Produces a fixed-shape Diagnosis. Production incidents restore service first.4---56# Skill: Debugging Architect — Diagnosis Without the Spiral78> **Apply Guidelines Skill** — load the `guidelines-meta` skill before proceeding.9> **Profile section owned:** §Guardrails → Known blind spots (Guidelines §5). Every root cause that a green pipeline failed to catch gets written there, so the next change is checked against it.101112**Why this skill exists:** debugging is the one activity where an agent reliably makes things worse. The failure mode is not being wrong — it's being wrong *repeatedly and confidently*, changing five things at once, and leaving a codebase that's harder to reason about than before it started. Every rule below exists to stop that.1314---1516## Operational Constraints (Strict)17181. **Reproduce before you theorise.** A bug you cannot reproduce is a bug you cannot verify you fixed. If it can't be reproduced, that is the finding — say so and pivot to §Unreproducible.192. **Change one thing at a time.** Each pass alters exactly one variable and predicts the result *before* running. Two simultaneous changes make a passing result uninterpretable.203. **Hard pass ceiling (Guidelines §16).** Three hypotheses tested and disproved → **stop**. Do not start a fourth. State what's been ruled out, name the assumption most likely wrong, and ask one diagnostic question. This is §17's debug-spiral rule made binding: "still broken" three turns running means the *frame* is wrong, not that the next guess needs more effort.214. **Never fix by weakening.** Deleting an assertion, loosening a tolerance, adding a skip, widening a mock, or wrapping the symptom in a `try/catch` is not a fix — it is the bug plus concealment (Testing Architect constraint 3).225. **No speculative fixes.** "This might help" is not a fix. If you can't state *why* the change makes the symptom impossible, you haven't found the cause. Changes that "seem to help" without an explanation are the beginning of the spiral, not the end of it.236. **Revert your own probes.** Debug logging, temporary instrumentation, and narrowing scaffolds come out before you're done — or are called out explicitly if deliberately kept.247. **Production first, diagnosis second.** If users are affected, `deployment-architect`'s Rollback Mode runs *first*. Restore service, then debug the artifact at leisure. Production is not a debugging environment.258. **Git and golden-file guards are enforced by the plugin's PreToolUse hook** (Guidelines §9, §10): every git write, `gh` publish, `--no-verify`, and snapshot update is denied by the runtime; read-only inspection stays open. `git bisect` is a branch-moving operation and is denied like the rest — surface the command for the user, or use a read-only equivalent.2627---2829## What to Read, and When3031The six phases below are the spine and apply to every run. These are read on demand:3233| Read | When |34|---|---|35| `${CLAUDE_SKILL_DIR}/references/flaky.md` | The failure is intermittent. Different discipline: you are proving a *rate*, not a state. |36| `${CLAUDE_SKILL_DIR}/references/unreproducible.md` | It cannot be reproduced. Ship instrumentation, not a guess. |37| `${CLAUDE_SKILL_DIR}/references/diagnosis-format.md` | Writing up the result. |38| `module-gate-battery` | Running the gates after the fix — and §3 when a test "passes but the feature is broken". |39| `module-propagation` | The fix touches shared shape, a public API, or an origin. |40| `module-findings` | Stating confidence in a root cause. |4142---4344## Phase 1 — Establish the Symptom4546Answer these before touching code. Guessing here costs whole sessions.4748| Question | Why it matters |49|---|---|50| **What exactly happens, and what was expected?** | "It doesn't work" is not a symptom. Get the actual output, error, or wrong value. |51| **What's the smallest input that triggers it?** | Reduction *is* diagnosis — a shrinking repro usually names the cause on its own. |52| **When did it last work?** | A known-good point converts an open search into a bounded one. |53| **What changed since?** | Code, dependency, data, config, environment, clock, or a service you don't own. |54| **Deterministic or intermittent?** | Intermittent means state, ordering, timing, or concurrency — see §Flaky. |55| **Where does it *not* happen?** | Passing locally but failing in CI is itself a diagnosis: environment, not logic. |5657**Get the real error text.** Not a paraphrase — the stack trace, the failing assertion, the actual value. A paraphrased error has already lost the detail that identifies the cause.5859---6061## Phase 2 — Narrow Before Hypothesising6263Resist the first plausible theory. Cut the search space first; a bisected search beats an inspired guess, and it works when you have no intuition at all.6465**Bisect along whichever axis is cheapest here:**6667- **Time** — which commit introduced it? `git bisect` is the tool; **surface the commands, don't run them** (§8). A `git log` over the suspect paths is often enough.68- **Code path** — does the failure survive when a layer is removed? Call the unit directly, bypass the framework, stub the collaborator.69- **Data** — does it fail for all inputs or one shape? Empty, boundary, unicode, very large, null, pre-migration rows.70- **Environment** — local vs. CI vs. deployed. Runtime version, env vars, timezone, locale, filesystem case-sensitivity, network egress.71- **Config** — does it fail with defaults? A wrong flag is a common and invisible cause.7273**The layer question, asked early:** is this *your code*, *your usage of a dependency*, *the dependency itself*, or *the environment*? Each has a different fix and a different owner, and mixing them up wastes the most time.7475---7677## Phase 3 — One Hypothesis at a Time7879For each pass, write these three lines **before** running anything:8081```82Hypothesis: <the specific mechanism you believe causes this>83Prediction: if true, <this exact observable> will happen84Test: <the single change or probe that discriminates>85```8687Rules:88- **The prediction must be falsifiable.** "It'll probably work better" tests nothing. "The value will be `undefined` at line 42" is a real test.89- **A disproved hypothesis is progress** — record it. The list of ruled-out causes is the most valuable artifact of a hard debug session, and it's what makes handing over possible.90- **Confidence gate** (`module-findings` §2). Before declaring a root cause, self-score: is this *proven* or merely *consistent with the evidence*? Below ~80, say so plainly and keep it labelled as a theory. A confidently-stated wrong diagnosis is worse than an honest "not certain yet" — the user acts on it.91- **Count the passes.** At three disproved hypotheses, stop (§3). Not a suggestion.9293**Check the known blind spots first** — the profile's §Guardrails list, plus `implementing-architect`'s protocols. A startling number of "impossible" bugs are: a stale template binding that type-check can't see, a test double missing a method, a config declared in one environment but not another, or a cache serving a previous build.9495---9697## Phase 4 — Prove the Cause9899Before fixing, close the loop both ways:1001011. **Explain the whole symptom.** A cause that explains most of it is usually adjacent to the real one. Unexplained residue means you're not done.1022. **Make it appear and disappear on demand.** Toggle the cause; the symptom must follow. That's proof, not correlation.1033. **Explain the "why now"** — if this code is old, what changed to expose it? Skipping this is how the same bug returns in a different shape.104105---106107## Phase 5 — Fix It Once1081091. **Write the failing test first**, per the `testing-architect` skill. It must fail for the *right reason* — run it before the fix and read the failure. A regression test that would pass without the fix is decoration.1102. **Fix the cause, not the symptom.** If the honest fix is large, say so and let the user choose between a scoped mitigation (labelled as such, with the real fix as a follow-up) and doing it properly now. Never disguise a mitigation as a fix.1113. **Smallest change that removes the cause** (Guidelines §2, §3). Do not refactor the surrounding area because you were in there.1124. **Check propagation.** If the fix touches shared shape, a public API, or an external origin, load the `module-propagation` skill and run the matching protocol — bug fixes hit the same mirror sites features do, with less scrutiny.1135. **Run the gates** per the `module-gate-battery` skill, once as a batch.1146. **Remove your probes** (§6).115116---117118## Phase 6 — Make It Impossible to Recur Silently119120The step that separates debugging from firefighting. A fix nobody can accidentally undo is worth more than the fix itself.121122- **The regression test stays.** Named for the bug's behaviour, not its ticket.123- **If a gate should have caught this and didn't**, that is a finding about the *gates*: write it into the profile's §Guardrails → Known blind spots, in one line, phrased as what to check next time.124- **If the class can recur elsewhere**, add it to §Recurring Propagation Sites so future changes get swept.125- **If it was a production incident**, hand the guard to `deployment-architect` — a pre-flight check is cheaper than a second outage.126- **If the root cause was a wrong assumption in a plan**, say so; that's feedback for `planning-architect`, not shame.127128---129130## Quality Checklist Before Claiming "Fixed"131132- [ ] Reproduced before diagnosing — or explicitly reported as unreproduced.133- [ ] Narrowed before hypothesising; the search was cut, not guessed at.134- [ ] Each pass changed one variable with a written, falsifiable prediction.135- [ ] Stopped and reassessed at three disproved hypotheses rather than continuing.136- [ ] Root cause explains the **whole** symptom, and toggling it toggles the symptom.137- [ ] Failing test written first, and it failed for the right reason.138- [ ] Fix addresses the cause; any mitigation is labelled a mitigation.139- [ ] Nothing was weakened — no deleted assertion, loosened tolerance, added skip, or swallowed exception.140- [ ] Propagation protocol run if the fix touched shared shape, a public API, or an origin.141- [ ] Debug probes removed.142- [ ] Blind spot written to the profile if a gate should have caught this.143- [ ] Confidence stated honestly; an unproven cause is labelled unproven.144- [ ] **No `git add`, `commit`, `push`, or `bisect`** — commands surfaced for the user.145146---147148_v1.0 — version history in CHANGELOG.md_
Run npx skillmds@latest add matis-dev/debugging-architect in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
Use when something is broken, failing, flaky, or slow and the cause is not yet known. Reproduce, narrow, then one falsifiable hypothesis at a time under a three-hypothesis ceiling; regression test before the fix; a guard so it cannot recur silently. Produces a fixed-shape Diagnosis. Production incidents restore service first. It is listed under Coding & Dev Tools on SkillMD.
This skill has not completed SkillMD's automated safety review yet. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
matis-dev (@matis-dev) published this skill. Their other Agent Skills are listed on their SkillMD profile.