# Structured Problem Resolution

> Use before acting on any troubleshooting or failure signal or proposed diagnosis/fix, including broken or unexpected behavior, failed tests/builds/commands, runtime errors, performance/flaky/regression issues, review/bug-report/human/AI claims, repeated failed attempts, or drift-prone library/API/runtime behavior. Mandatory before diagnosis or fixes; turn signals into current evidence, hypotheses, impact analysis, and verified resolution.

- Skill: `cipradu/structured-problem-resolution` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add cipradu/structured-problem-resolution`
- Raw SKILL.md: https://api.skillmd.com/api/skills/cipradu/structured-problem-resolution/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: cipradu (https://skillmd.com/u/cipradu)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/cipradu/structured-problem-resolution

---


# Structured Problem Resolution

## When to Use

Use this skill when:

- something is failing, broken, slow, flaky, surprising, or different from expected behavior;
- tests, builds, commands, runtime flows, deployments, integrations, or local tooling fail;
- the user asks to fix an error, investigate a bug, explain why something is happening, or evaluate a proposed fix;
- a code review comment, bug report, human suggestion, AI review, linter warning, or external ticket claims something is wrong;
- a previous fix attempt failed, changed the error, reduced but did not eliminate the problem, or introduced a new symptom;
- the cause is not known, the signal may be misleading, or the suggested fix has not been verified against the codebase;
- the answer depends on current library, framework, runtime, package, API, security, platform, browser, database, or third-party behavior.

## Do Not Use

Do not use this skill as the primary workflow when:

- the user wants product definition, an engineering spec, an implementation plan, architecture design, an ADR, or a code review rather than diagnosis;
- the desired behavior is unknown and needs product/spec clarification before a defect can be defined;
- the issue has already been diagnosed with evidence and the remaining work is non-trivial implementation planning or architecture decision-making;
- the request is purely explanatory and does not involve a failure, disputed signal, suggested fix, or unresolved cause.

## Iron Law

Treat every failure, review comment, bug report, and suggested fix as a signal to investigate before changing code. Do not implement from intuition, authority, social pressure, or model memory when the cause or external behavior has not been verified.

Every applicable problem uses all five phases and the full investigation scratch file. Apparent simplicity, a one-line change, confidence, speed pressure, and trusted sources never exempt a problem from evidence, causal analysis, impact analysis, or verification. Record conclusions, assumptions, evidence and concise decision rationale, never private chain-of-thought.

## Core Concept

Signals are hypotheses, not instructions. The job is to convert a signal into evidence, a falsifiable mechanism, an impact-aware fix, and verification. Current external facts must come from current evidence, not training data; local behavior must come from the actual code and runtime, not memory.

## Knowledge Cutoff Guard

Model memory is allowed only to generate search terms and hypotheses. It is not evidence.

Current research is mandatory before relying on any fact that can drift over time:

- package, library, framework, runtime, browser, database, platform, API, CLI, SaaS, cloud, security, or protocol behavior;
- deprecations, latest stable versions, migration guidance, compatibility claims, bug reports, changelog behavior, or security recommendations;
- third-party examples, documentation patterns, or "best practice" claims that may have changed.

If the problem is purely local code behavior, record the local evidence instead: exact error output, reproduction steps, relevant code paths, tests, recent diffs, logs, config, and runtime state. Do not skip the research/evidence gate; record why external/current research is not relevant.

## Why This Matters

Two patterns waste the most time in software development:

**Pattern 1: Guess-and-check debugging.** See error, guess at fix, apply fix, see different error, guess again, apply another fix — now there are two problems. Each uninformed fix attempt risks compounding the problem because you're changing code you don't fully understand. Expert debuggers spend roughly 80% of their time _understanding_ a bug and 20% _fixing_ it. The fix, once you truly understand the problem, is usually straightforward.

**Pattern 2: Blind implementation of feedback.** Receive suggestion, say "good catch!", implement without verifying, introduce regression or fix the wrong thing. This happens because social pressure — from reviewers, bug reporters, or authority figures — bypasses the verification step. The suggestion becomes an unquestioned instruction rather than a hypothesis to evaluate.

Both patterns share the same root failure: **acting before understanding**. This skill provides a unified pipeline that handles any signal — whether it's an error message, a failing test, a code review comment, or a colleague's suggestion — with the same disciplined approach: receive critically, understand thoroughly, fix precisely, verify completely.

Finding the root cause is only half the job. A fix that solves the immediate problem but breaks three other things isn't a fix — it's a trade. Before you change code, understand why the problem exists, and after you propose a fix, reason through its implications. Think in systems, not in patches.

---

## Phase 1: Receive and Evaluate the Signal

Every resolution starts with a signal — something that tells you attention is needed. The signal might be an error message, a failing test, a code review comment, a bug report, or a human's opinion about your code. How you receive and evaluate that signal determines everything that follows.

### Reference Retrieval (Conditional)

Before relying on detailed guidance in a reference, evaluate every row below. Select and read each independently applicable reference before its listed decision; matching multiple rows requires multiple selections. Load only applicable references. Record selected paths and trigger reasons in the full investigation record, or `none applicable` with the basis when no operational row matches. The full method does not require reading unselected references.

| Trigger | Select and read | Required before |
| --- | --- | --- |
| A review, ticket, bug report, vague or solution-framed signal, or multi-item feedback needs detailed evaluation | [signal-evaluation.md](references/signal-evaluation.md) | Phase 1 detailed review/ticket/vague/multi-item evaluation |
| An investigation needs a detailed diagnostic technique beyond this skill's quick reference, including intermittent, environment-dependent, or performance work | [techniques.md](references/techniques.md) | Phase 3 choosing or applying that detailed technique |
| A prior failed fix, speed/authority pressure, anchoring, deference, or thrashing could affect the next hypothesis or fix decision | [cognitive-traps.md](references/cognitive-traps.md) | The pressure-affected hypothesis or fix decision |


The critical discipline: **treat every signal as a hypothesis to verify, not an instruction to follow.** This applies equally to error messages (which can be misleading) and human feedback (which can be wrong).

### Error Messages and Test Failures

These are the most objective signals, but they still require careful reading:

- **Read the full error.** Don't skim. Read the complete error message, the full stack trace, every warning. Error messages frequently contain the exact answer.
- **Parse the stack trace strategically.** Find the first frame in _your_ code (not library/framework code). Read the exception type before the message — `KeyError` vs `TypeError` vs `AttributeError` tells you the category of mistake. In chained exceptions, the root cause is at the bottom.
- **Check what changed.** If something was working and stopped, ask: what changed between when it worked and when it broke? Recent commits, dependency updates, config changes, environment differences.
- **Look for absence.** Don't only look for errors in output — look for expected output that's _absent_. A missing log line tells you where execution stopped.

### Human Feedback, Code Reviews, and Bug Reports

Human input is the trickiest signal because it comes pre-interpreted. A reviewer doesn't say "line 42 executes branch A when the input is null" — they say "this function is broken." A bug reporter doesn't say "the response took 12 seconds" — they say "the API is slow." You receive their **diagnosis**, not their **observations**.

**Strip the diagnosis. Keep the observations.**

Bug report: "The caching layer is broken — users see stale data after deploy."
Reframe as observations: "After deployment at 14:30, some users see pre-deployment data. Resolves after ~10 minutes."

Now you can independently consider: Is it actually a cache issue? Could it be CDN, browser cache, load balancer routing to old instances, or a rolling deploy still completing?

**The "Handed Hypothesis" problem:** When someone tells you "X is wrong, fix it by doing Y," they're handing you a pre-formed hypothesis. Your job is to _test_ that hypothesis, not _implement_ it. The reviewer may be right — but they may also be wrong, missing context, or solving a problem that doesn't exist.

**The "Explain It Back" test:** Before implementing any proposed correction, restate in your own words what the problem is and why the change fixes it. If you cannot do this, you do not understand the feedback well enough to implement it correctly.

### Source Trust Calibration

Not all signals deserve equal trust. Calibrate based on source:

| Source                              | Trust Level                          | Key Risk                                     | Verify How                        |
| ----------------------------------- | ------------------------------------ | -------------------------------------------- | --------------------------------- |
| Error messages / stack traces       | High for facts, can mislead on cause | Symptom far from root cause                  | Trace backward from failure point |
| Your human partner                  | High for intended outcome            | Scope or diagnosis may be unclear            | Verify cause and impact through all phases |
| Domain expert on this code          | High for this area                   | May not know recent changes                  | Cross-reference with tests        |
| General senior engineer             | Medium-High                          | May not know this codebase                   | Verify claims against code        |
| External / OSS reviewer             | Medium                               | Lacks your project's context                 | Verify context assumptions        |
| Junior team member                  | Medium                               | Less experience, but may know recent changes | Same verification as anyone       |
| Automated linters / static analysis | Very High for what they check        | Narrow scope                                 | Verify rule applicability, cause and impact |
| AI-generated review                 | Medium for patterns, Low for context | Poor context awareness                       | Always verify against actual code |

**Expertise is domain-specific.** A brilliant backend engineer may give poor advice about CSS. Evaluate each comment against the reviewer's expertise in the specific area being commented on, not their general reputation.

### The Anti-Sycophancy Principle

This matters whether you're human or AI: **social pressure must never bypass verification.**

The failure pattern: someone with authority says "this is wrong." You feel pressure to agree immediately and fix it. You skip verification. You either implement a wrong fix (making things worse) or fix something that wasn't broken (wasting time and potentially introducing real bugs).

**How to respond to any signal:**

```
NEVER:
- "You're absolutely right!" (before verifying)
- "Great point!" / "Thanks for catching that!" (performative)
- "Let me fix that now" (before understanding)

INSTEAD:
- Restate the technical requirement in your own words
- Verify the claim against the actual code
- Ask clarifying questions if anything is unclear
- Push back with technical reasoning if the claim is wrong
- Just start working — actions speak louder than agreement
```

When feedback IS correct, acknowledge it through action:

```
✅ "Fixed. [Brief description of what changed]"
✅ "Good catch — [specific issue]. Fixed in [location]."
✅ [Just fix it and show the result]

❌ "You're absolutely right!"
❌ "Great point! Thanks for catching that!"
❌ Any gratitude expression or performative agreement
```

### Issue, Review, and Ticket Threads

When the signal references an issue, pull request, code-review thread, bug ticket, chat thread, incident, or prior investigation, read the complete available thread before diagnosing from the title or opening description.

Include the original report, every comment, latest updates, reproduction attempts, environment details, screenshots/logs, prior failed fixes, user decisions, and scope pivots. Latest comments often invalidate the opening diagnosis. If the thread is unavailable, ask for the missing content or record the gap; do not diagnose from a summary when the source thread exists but has not been read.

### Diagnostic Scope Checkpoint

For vague, multi-item, media-backed, review/ticket, or solution-framed signals, write a compact scope checkpoint before converging on a hypothesis:

- Observed facts: what was directly seen, measured, logged, recorded, or reported.
- Expected behavior: the explicit requirement, contract, acceptance criterion, or user-observed expectation. If expected behavior is undefined, route to product/spec clarification instead of inventing it during diagnosis.
- Handed diagnosis: the reporter's or reviewer's theory, kept as a hypothesis.
- Requested fix: any proposed patch, command, cleanup, retry, refactor, plan, or workaround, kept separate from the problem.
- Agent inference: what you infer, with a basis label, not as fact.
- Out of scope: adjacent complaints, broad product/design asks, and downstream workflow requests that are not needed to diagnose the current signal.
- One missing fact that changes the next diagnostic action, or `none`.

If a human signal is vague, quote the exact weak phrase and ask one observation-seeking question when the answer materially changes the next diagnostic action. If the answer remains unavailable, record the uncertainty and the next evidence artifact needed rather than converting pressure into edits.

When the Phase 1 selector row applies, read [signal-evaluation.md](references/signal-evaluation.md) before detailed evaluation; it contains the patterns for signal types, multi-item feedback, the four-axis evaluation framework, and push-back.

### Orchestrator Decision And Phase Value

Consume the incoming consequence lane and gate warrants when orchestration has already classified the work. Diagnosis must name the uncertainty, unresolved cause, or acceptance gap it can resolve and how the result can change the next action. Current, applicable evidence may satisfy a phase without repeating its searches or experiments: record the evidence, source identity, applicability and remaining gaps in the full record. Confidence or a prior conclusion alone cannot satisfy a phase. Preserve completed phase evidence when handing off to the next skill or agent; do not restart a completed diagnosis merely because implementation is delegated.

The orchestrator owns classification. This skill may escalate only by returning newly discovered concrete evidence, the affected consequence or gate, and the changed next action for an updated orchestrator decision. Skill or agent preference, artifact type, file count, delegation, or generic uncertainty cannot silently reclassify the task. Without new evidence, preserve the incoming lane and warrants.

---

## Phase 2: Triage

Triage selects the next evidence and authority needed within the full method. It never selects a shorter workflow. There are no Obvious or Simple bypasses and no compact-packet substitute for the full record.

Record what current evidence establishes about the source, causal chain, environment, affected boundaries and available verification. Name unresolved facts and the next observation that can decide them. A mechanical typo still requires inspecting the actual contract and affected callers; its short causal chain may make the entries brief, but does not remove them.

Assess every phase and record its status:

| Phase | Required assessment |
| --- | --- |
| 1 — Receive | Observed versus expected behavior, source/context, proposed diagnosis versus verified facts, and scope |
| 2 — Triage | Known evidence, remaining uncertainty, selected references, authority and next diagnostic action |
| 3 — Investigate | Environment sanity, hypotheses and alternatives, current evidence, causal chain, predictions, feedback loop and contributing factors |
| 4 — Fix | Supported correction and written impact analysis before applying it, or an evidenced no-change/blocked/handoff disposition |
| 5 — Verify | Original-symptom and affected checks, actual results, limitations and honest resolution status |

Use `pending`, `in progress`, `satisfied` with evidence, or `blocked` with the missing prerequisite. An assessed but blocked phase is not completed work. A read-only diagnosis can identify a correction and required verification while recording that neither application nor final verification occurred. If evidence shows no defect or an inapplicable report, record the no-change disposition, its impact and the evidence supporting closure; do not manufacture a correction.

Investigate until the named evidence gaps are resolved or an actual prerequisite blocks further work. Full structure does not require irrelevant external research, unselected techniques, whole-repository reading, every test suite, or invented alternative causes. These choices follow the problem's evidence and affected boundaries; no required analysis may be dropped for brevity or confidence.

When current evidence identifies a structural defect that a local correction cannot resolve — such as contradictory responsibility, contracts or systemic state inconsistency — stop the affected correction and return the evidence to the orchestrator for architecture/scope decisions. Attempt count, record length and diagnostic difficulty alone do not activate architecture, spec, plan or independent review gates. Diagnosis never grants additional mutation or recovery authority.

---

## Phase 3: Investigate

This is the core loop. The discipline: **understand before you change.**

Before a pressure-affected hypothesis or fix decision, select and read [cognitive-traps.md](references/cognitive-traps.md) when its selector row applies. Do not defer that read until after the decision.

### Step 1: Observe (what is actually happening?)

Before forming any theory, gather facts. This is the most important step and the one most often skipped.

**If the signal is an error:** Read it carefully. Note exact line numbers, file paths, variable values. Check what changed recently. Look for what's missing in the output, not just what's present.

**If the signal is human feedback:** Separate observations from interpretations. What did the reviewer actually see vs. what do they think is happening? Re-read the actual code they're commenting on — do not respond from memory or from the reviewer's description of the code.

**Reproduce it.** Can you trigger the problem reliably? If yes, you have a fast feedback loop for testing hypotheses. If no, gather more data about the conditions under which it occurs. For feedback-driven signals: can you reproduce the scenario the reviewer describes?

**Verify environment sanity before deep tracing.** Confirm the right branch, version, dependency set, runtime, config, environment variables, database/service/server state, generated artifacts, build output, and test target. Many failures survive multiple clever theories because the wrong code, stale artifact, missing service, or wrong environment is being exercised.

Classify environment findings before treating them as root cause:

- Blocking failure: the required workflow cannot run until fixed, such as the wrong branch, failed build, missing required service, invalid config, or stale generated artifact that directly affects the signal.
- Optional capability gap: a helpful tool, browser driver, simulator, profiler, or integration is missing, but another valid loop or evidence path exists.
- Unrelated observation: a noisy local issue exists but does not affect the current symptom.

Do not treat a missing optional tool as the diagnosis. Route setup repair only when the failing workflow actually depends on that missing tool.

**Build the feedback loop before testing hypotheses.** The loop is the first investigation product, not a side quest. A feedback loop is a fast, deterministic or high-reproduction, agent-runnable pass/fail signal for the user's actual symptom. It can be a test, command, script, trace replay, browser check, benchmark, or structured manual capture, but it must tell you whether the original symptom is present. If no reliable loop exists, the next task is to build or sharpen the loop, not to guess at fixes.

A usable loop is red-capable, specific, fast enough to iterate, deterministic or measured by reproduction rate, and runnable without hidden human interpretation. You should be able to name one command, script, trace, browser check, or structured manual capture that has already been run at least once and can distinguish the original symptom from nearby failures.

Use the lightest loop that reaches the real bug:

1. Failing test at the seam that exercises the bug: unit, integration, contract, or end-to-end.
2. HTTP/API command against a running service, with exact request, response, status, headers, and relevant logs captured.
3. CLI invocation with a fixture input and expected stdout, stderr, exit code, or output diff.
4. Browser automation for UI failures, asserting on DOM, console, network, storage, and visible state as relevant.
5. Captured trace replay: saved network request, event payload, log sequence, queue message, job input, or data fixture replayed through the smallest real path.
6. Throwaway harness around one service, module, or function with dependencies mocked only at true external boundaries.
7. Property, fuzz, stress, or repeated-run loop when the symptom is intermittent or data-dependent.
8. Bisect or differential loop when a known-good state, prior version, alternate config, or dataset can be compared against the failing state.
9. Structured human-in-the-loop capture only as a last resort, with exact steps, timestamps, observed output, screenshots/logs when useful, and enough structure to compare before and after.

Iterate on the loop itself. Make it faster by narrowing setup, sharper by asserting the specific symptom instead of a broad crash/pass, and more deterministic by controlling time, randomness, filesystem, network, concurrency, and external services where possible. For nondeterministic bugs, the immediate goal is a higher reproduction rate; loop the trigger, add stress, widen timing windows, or capture enough runs to make the failure debuggable.

If you genuinely cannot build a loop, stop and say what you tried. Ask for the missing artifact or access: a reproducing environment, HAR/network capture, log dump, core dump, trace, fixture, screen recording with timestamps, data sample, or permission to add temporary diagnostic instrumentation. Do not proceed as if a hypothesis is confirmed without a loop or equivalent evidence.

For surface-specific feedback loops, record what makes the loop reach the real symptom:

- Browser, dogfood, or UI polish: route/scenario, visible state, DOM, console, network, storage, server logs, side effects, screenshots when useful, and the true end state. A screenshot or "looks better" is supporting evidence, not root-cause proof.
- Mobile or device runtime: build/install/launch state, device or simulator context, runtime logs, screenshots, automation limits, human-verification gaps, and cleanup of temporary state.
- Media or recording reports: observed facts with timestamps, transcript/screenshot/event references, confidence in each inference, and raw media kept local by default.
- Production or external evidence: error payloads, request/trace/correlation IDs, release metadata, log snippets, breadcrumbs, exact timestamps, timezone, source window, latest data considered, and known ingestion lag.

When logs, metrics, screenshots, traces, HAR files, transcripts, config snippets, generated reports, or data samples become evidence, record provenance and safety: source/tool, query or filter shape, source window, timestamp/timezone, redaction status, whether raw data is local-only, and which source is canonical when CI, local reproduction, monitoring, user reports, and database state disagree. Ask for tool/source and query shape, not credentials or secret-bearing connection details.

If you are resuming an investigation, prior scratch files, old issue titles, review comments, failed-fix notes, solution docs, session summaries, logs, and prior learnings are evidence leads, not current truth. Reconcile them against current code, branch/diff, dependency versions, runtime state, generated artifacts, test target, latest thread updates, and the current symptom. Classify the old context as `current/no action`, `stale but correctable`, `contradicted by latest evidence`, `superseded by new symptom`, `missing feedback loop`, `missing environment sanity`, `ambiguous source authority`, or `requires restart from observation`.

**Check what changed.** `git log`, `git diff`, recent dependency updates. The single most productive question for any problem that used to work: what's different between when it worked and when it broke?

**Trace the bad-state transition.** Identify the last point where the relevant state is valid and the first point where it becomes invalid. Observe actual runtime values, database rows, request payloads, config values, files, logs, or traces rather than inferring from how the code reads. Root cause lives where the bad state originates, not where it finally crashes.

### Step 2: Hypothesize (what do you think is happening, and why?)

Form a specific, falsifiable hypothesis. Not "something's wrong with the database" but "the query returns zero rows because the WHERE clause uses the wrong column name."

**Audit assumptions before choosing a theory.** List the concrete beliefs your hypothesis depends on: which code is running, which input shape exists, which dependency behavior applies, which state is present, which caller path executes, which reviewer claim is factual. Mark each one verified or assumed. Unverified assumptions become investigation targets, not hidden premises.

**The mechanism test:** If you can't explain the precise mechanism by which your proposed cause produces the observed symptom, your hypothesis isn't specific enough. "Race condition" is not a hypothesis. "Thread A reads the counter, then Thread B increments and writes, then Thread A overwrites with its stale value" is a hypothesis.

**The causal-chain gate:** A hypothesis must explain the full path from trigger to symptom with no hand-waved links. For each uncertain link, state a prediction that should be visible somewhere else in the system. If the prediction fails but the proposed code change appears to help, you probably found a symptom patch rather than the root cause.

**Generate alternatives.** Consider plausible competing causes before accepting the first hypothesis. Record the handed hypothesis plus at least two independent alternatives, or evidence explaining why the search space is narrower. Do not invent implausible causes to fill a quota.

Cover different plausible axes when relevant: runtime path, data shape, environment/config, recent change, concurrency/time, external dependency, user/input boundary, and stale artifact or source window. Each candidate needs the observation it explains and the evidence that would disprove it.

**State it explicitly.** Write the hypothesis, evidence and prediction in the investigation scratch file. Update that same record when evidence changes; a conversation summary does not replace it.

Label the basis for every material claim: `observed`, `reproduced`, `local-code`, `external-current`, `prior-learning`, `reasoned`, or `unsupported`. Reasoned claims can guide the next probe; they are not proof. Absence claims such as no reproducer, no callers, no similar bug, no external research needed, no regression risk, or no residual risk require evidence for the search space checked.

**If the hypothesis came from someone else** (reviewer, bug reporter, colleague): treat it the same as your own hypothesis. It needs evidence before you act on it. Their authority doesn't make it correct — only evidence does.

### Step 3: Research and Evidence Check (what is already known?)

**This step is mandatory.** Now that you have a hypothesis and alternative candidates, gather evidence before you start experimenting. Research means seeking evidence outside your memory. For external or drift-prone behavior, use current external sources. For purely local code behavior, use codebase/runtime evidence and record why external research is not relevant.

Many issues — especially those involving libraries, frameworks, version upgrades, configuration, or infrastructure — have already been encountered and solved by someone else. Five minutes of research can save hours of guessing.

**What to check:**

- The exact error message, quoted verbatim — this is your highest-signal search
- Your hypothesis + the library/framework name + version
- GitHub issues on the relevant repositories
- The library's changelog or release notes if a version change is involved
- Local code paths, tests, recent diffs, config, logs, runtime state, and reproduction steps when the issue is project-local
- Prior learning or solution records, if the repository has them, for similar exact errors, symptoms, root causes, components, failed attempts, and prevention notes. Treat them as hypothesis sources that may be stale, not as proof.

**When to use current external research:** Always when the answer depends on library, framework, runtime, package, API, security, browser, database, platform, SaaS, cloud, protocol, deprecation, migration, compatibility, or "best practice" claims. Even if you think you know the answer, verify anyway. You might find that the behavior changed, the API was deprecated, the known workaround is obsolete, or your initial intuition is wrong.

**When local evidence is enough:** When the hypothesis is about this repository's own code, data flow, configuration, tests, or recent diffs and no external behavior claim is needed. In that case, record the local evidence and explicitly write `External/current research not required because <reason>`.

**How to research:** Use the `research` subagent (subagent_type: "research") when external/current evidence is required and the environment permits delegation. If the research agent is not available or fails, fall back to whatever search/web/docs tools the environment provides (WebSearch, WebFetch, MCP tools, Context7, official docs, package repositories, changelogs, issue trackers, etc.). If you need follow-up questions or deeper investigation from a prior research result, resume the previous research agent session rather than starting a new one when the harness supports it.

**What to do with the results:**

- If you find the answer: verify its applicability and causal prediction, complete contributing-factor and impact analysis, then apply only an authorized correction
- If you find related issues but no direct answer: use them to refine your hypotheses before testing in Step 4
- If you find nothing: record the searched scope and remaining uncertainty. No search results do not prove the cause is local or unknown elsewhere. Proceed to Step 4
- If local evidence is sufficient: cite the exact files, commands, outputs, or runtime observations that support the hypothesis

**The bias you're fighting:** There is a strong pull toward figuring things out from first principles — reading code, forming theories, running experiments. This feels productive but is often catastrophically wasteful. The error message you're staring at may have a documented upstream fix. The library bug you're trying to work around may have a GitHub issue with a specific version boundary. Your training data may describe old behavior. Check before acting.

**Structural enforcement:** Every investigation records research/evidence results in the full scratch file before Step 4 or corrective source edits. Record current external findings when external behavior matters, or local evidence plus why external research is not relevant. Existing sufficient current evidence may be cited without repeating its acquisition. Missing evidence blocks the dependent action; apparent simplicity never waives this gate.

### Step 4: Test (gather evidence for or against)

Design the _smallest_ experiment that would confirm or disprove your hypothesis.

**Prefer observation over modification.** Use authorized read-only inspection before changing behavior. Temporary diagnostic instrumentation must be bounded, reversible, recorded and safe for the affected data and runtime. It cannot disguise a correction or authorize sensitive reads, external writes or behavior changes.

**Instrument narrowly.** Prefer debugger/REPL inspection when available. If you add temporary logs or probes, each one must distinguish a specific hypothesis and use a unique searchable prefix such as `[DEBUG-<short-token>]` so cleanup is mechanical. Never "log everything and grep." For performance problems, establish a baseline measurement first; use timing harnesses, profilers, query plans, resource metrics, or benchmarks rather than intuition-heavy logging.

**One variable at a time.** If you change multiple things, you won't know which one mattered. Make one change, observe the result, then decide your next move.

**Try to disprove, not confirm.** The most dangerous debugging error is confirmation bias — interpreting ambiguous evidence as supporting your hypothesis. Actively look for evidence that would prove you wrong. Ask: "What would I expect to see if my hypothesis is _incorrect_?"

**What the result means:**

- **Hypothesis confirmed:** Proceed to Step 5, then to Phase 4 (Fix).
- **Hypothesis disproven:** This is progress. You've eliminated a possibility. Return to Step 2 with new information.
- **Evidence ambiguous:** Your experiment wasn't targeted enough. Design a more specific one. Do not treat ambiguous evidence as confirmation.

If an experiment, probe, or attempted fix contradicts your prediction, explicitly invalidate or refine the hypothesis in the scratch file before trying the next thing. Do not retry variants of the same theory unless new evidence changes the theory.

For measurable investigations such as performance, flakiness, repeated failed fixes, quality scores, or proxy metrics, define the baseline, target, hard gates, diagnostics, acceptance threshold, repetition or variance policy, and immutable measurement asset before changing code. A single faster run, one passing flaky test, a prettier screenshot, or a better proxy score is not proof when variance, correctness, accessibility, security, or data integrity guardrails can regress. Record each probe outcome as confirmed, disproven, degenerate, error, timeout, deferred, or inconclusive.

When a command or API mutation has ambiguous external-state impact, do not infer state from exit code or stdout alone. If a mutation times out, returns 5xx, returns 202/pending, fails after partial work, or returns a success artifact that might be wrong or empty, capture stdout, stderr, exit code, target state, fallback path, idempotency support, and authoritative readback before retrying or declaring completion. Record each affected system as applied, absent, failed, pending, or unknown; do not imply that a later failure rolled back a confirmed earlier write. Compensation, reversal, deletion, or another consequential recovery mutation requires its own authority and must not be inferred from authority to diagnose or apply the original fix. Separate stale/precondition failures, invalid payload errors, false-success outputs, and ambiguous post-write failures.

### Step 5: Understand Contributing Factors

Before jumping to a fix, step back and understand _why this problem exists_. The root cause tells you _what_ is wrong. The contributing factors tell you _how it got that way_ — and that understanding is what separates a lasting fix from a patch that trades one problem for another.

**Ask:** How did this code end up in a problematic state?

- Was it a design decision that didn't account for this use case?
- Was it a refactoring that changed behavior without updating all callers?
- Was it an assumption that was once true but no longer is?
- Was it a copy-paste from another context where it worked differently?
- Was it a gap in test coverage that let this slip through?

**Ask:** Is this a pattern or a one-off?

- Does the same mistake exist elsewhere in the codebase? If so, flag it.
- Is the contributing factor systemic (e.g., the codebase routinely mutates shared data) or isolated?

For feedback-driven problems: Was the reviewer identifying a one-off issue or a recurring pattern? Understanding this changes the scope of the fix.

### Techniques by Situation

Practical starting points for common scenarios. When the Phase 3 selector row applies, select and read [techniques.md](references/techniques.md) before choosing or applying its detailed technique.

**"I don't know where the problem is"**

- **Binary search (Wolf Fence):** Insert a check at the midpoint of the suspect code path. State correct there? Problem is in the second half. Repeat. O(log n) instead of O(n).
- **git bisect:** Binary search through commit history to find the introducing commit. Automate with `git bisect run <test-command>`.
- **Subtractive debugging:** Remove components one at a time (comment out middleware, disable plugins, stub functions with hardcoded returns). When the problem disappears, the last removed component is involved.
- **Minimal reproducible example:** Strip away everything not needed to trigger the problem. The process of minimizing often reveals the cause.

**"I know where but not why"**

- **Backward tracing:** Start at the failure point and trace backward. Where does the bad value originate? What called this function with this argument? Keep going up the call chain until you find the source.
- **State snapshots:** Log the complete relevant state at key transition points. Format consistently so you can compare expected vs actual.
- **Watchpoints:** If your debugger supports it, set a hardware breakpoint on a variable. The debugger pauses exactly when that value changes, showing what modified it and from where.

**"It only fails sometimes"**

- **Identify the conditions:** What differs between passing and failing runs? Timing, data, environment, test ordering?
- **For race conditions:** Use sanitizers (ThreadSanitizer, AddressSanitizer) or deterministic replay tools (`rr`).
- **For flaky tests:** Run the failing test in isolation first. If it passes alone, it's being polluted by another test. Binary search for the polluter.
- **Increase determinism:** Mock time, seed random number generators, control concurrency.

**"It works locally but fails elsewhere"**

- **Diff the environments:** Systematically compare runtime versions, env vars, config files, OS, network, permissions, disk space, and dependency versions.
- **Reproduce the environment:** Run the same container image locally.
- **Add diagnostic output on failure:** Configure CI/deployment to dump env vars, process lists, disk and memory usage, and relevant state only on failure.

**"It's a performance problem"**

- **Measure first, don't guess.** Get a baseline measurement. Is the CPU saturated (compute-bound) or idle (I/O or contention-bound)? The answer determines your entire investigation strategy.
- **Flame graphs** for CPU-bound is

…(truncated)
