The person should not have to ask you to check what actually happened. Before you name a cause or propose a fix for something observed, establish the cause from the record of what ran, try to break it, and have it reviewed in a fresh context.
Look at what actually ran
Start from the record, not the story about it. Depending on the problem, that is the session transcript and the instructions and skills it actually loaded, logs, CI runs and the revisions they ran on, process and lock state, and the deployed version. A process name, a status message, a teammate's note, a PR description, or a file that should have been loaded is a lead until the record confirms it. So is what the person told you: confirm it in the record and cite the record. When a record names its own owner or writer, such as a lock file, a PID file, or a load event, cite it; it outranks inference from names and process trees.
Do not stop at the first explanation that fits. Raise every candidate the evidence suggests. A cause says why it happened, not only what happened: for each confirmed link, ask what produced or allowed it, such as an instruction, an input, or a check that never ran, and follow that back while the evidence reaches. When the outcome broke a constraint, find where that constraint should have been stated or checked and was not, such as a brief that never said it, and name each fact it left out. There is no fixed number of candidates.
Use read-only probes. Diagnosis does not authorize killing processes, releasing locks, editing, rewriting history, or publishing.
Try to break every candidate
Run two probes on each candidate explanation and keep both results:
- Falsification: look for the observation that would be impossible if the candidate were true, such as an ordering, a timestamp, a load event, an identical hash, or a probe that tells two candidates apart, and check it.
- Truthiness: reread each source you cite and confirm it says what you claim, about the object and time you claim. A source that only repeats someone's belief is a lead, not evidence.
Put the times from every source on one timeline: when each candidate started, when the record last changed, when the symptom began. An order a candidate cannot fit rules it out; report the times that decided it.
A candidate that fails either probe is ruled out by the observation that broke it.
Get a fresh review
Before returning, have the result reviewed in a fresh agent context: a subagent
when the host has one, otherwise a separate CLI run such as claude -p or
codex exec. Use the reviewer the caller names. Read
references/fresh-review.md before starting it.
The reviewer gets the symptom, the surviving explanation or the gap, where each piece of evidence lives, and each ruled-out candidate with what ruled it out. It reads the sources itself, tries to break the explanation, and returns agree or disagree with its evidence. A disagreement that holds reopens the investigation.
A review counts only when the reviewer ran and wrote its verdict to a file that you cite by its exact path. Read that file and report the verdict it holds. Before starting it, look through your tools for one that runs a worker, subagent, or command and returns its output, and use that. Recording a request, or waiting when no reviewer was started, is not a review. A read-only boundary on the investigation does not forbid a read-only reviewer; starting one changes nothing. When a route returns no verdict file, try the next one. Without a verdict file to cite, the result is unreviewed, whatever else happened.
When you are the reviewer, do not start another review. Read the named sources yourself, write your verdict and its evidence once, through the verdict tool your host gives you or to a file when it has none, and return that path. A tool that only records a request to write did not write the file; the write counts when it returns the path. Do not also record or copy it anywhere else. That one write is part of the review, not a change to what is under investigation.
Stop
Stop only when one of these holds:
- One explanation survives both probes and the fresh review, and every other candidate you raised is ruled out with evidence.
- The evidence runs out. Report what is missing, where you looked, and which candidates remain open, without choosing between them.
Report
Keep it short:
- the surviving explanation as a cause, back to its earliest supported link, or the gap;
- the evidence, each item with its source and the value that decides between candidates, such as a timestamp, exit code, hash, load event, or setting;
- each fact the person stated that the explanation relies on, with the record that confirmed or contradicted it;
- each ruled-out candidate, including the first explanation that seemed to fit and any the person or a document offered, with the observation that ruled it out;
- the falsification and truthiness results for each candidate, with the observation each rests on;
- which reviewer ran, by route and model, its verdict, and the exact path of its verdict file, or that the result is unreviewed.
Propose a fix only after this, and only for the surviving cause.