Topic 02

Hand It the Evidence

Debugging

"Sometimes two people get an offer for the same place" is a description. Two log lines 300 milliseconds apart, the class and member identifiers, and the range of commits in which the waitlist was written are evidence. Given the description, the agent guesses from the commonest causes of bugs that sound like that one. Given the evidence, it reasons from what actually happened.

The difference is not politeness or prompt craft. The agent cannot ask the system anything you did not give it a way to ask, so whatever you hand over is the whole of its knowledge about the incident. This page is about choosing what to hand over, and about the two things you must take out first.

Evidence vs Description

A description is your interpretation, already compressed and possibly already wrong. "The sweep sends a duplicate" is a description that has decided which path is at fault. "Offers sometimes go out twice" has decided the problem is duplication, when it might be two different offers for one place. Each compression throws away exactly the detail that would have contradicted it.

Evidence is what the system recorded: a stack trace, log lines with timestamps and request identifiers, the exact failing input, the output of the failing test, the commit range in which the code changed. None of it has been interpreted yet, which is its value. Chapter 4 made the general point that context is the interface; for debugging it is sharper, because the agent has no other window onto the incident. It was not there. Neither, usually, were you, but you can read what the system wrote down.

The Waitlist Evidence

For the double offer, the evidence that matters fits on one screen. The waitlist writes one log line per offer, and the third incident left two of them for the same class, 300 milliseconds apart.

waitlist log, the third incident (identifiers as they appear in production)
2026-10-14T18:02:41.207Z INFO waitlist offer class=C-2291 member=M-10482 path=cancel free_places=1 active_offers=0
2026-10-14T18:02:41.507Z INFO waitlist offer class=C-2291 member=M-11937 path=sweep free_places=1 active_offers=0
What the two lines share, and what sets them apart
Sharedone place, one moment
The same class, C-2291, a full class of 16. The same state read by both: 1 free place, 0 active offers. Two timestamps 300 ms apart, far inside the sweep's 30-second cycle.
Differenttwo writers, two members
Two paths: cancel, the request that freed the place, and sweep, the job that runs every 30 seconds. Two members: M-10482 got the place, and M-11937, next in line, got it too.

That pair alone narrows the field. Both writers recorded "one free place, no active offer", which means each read the class before either had written. If the sweep had read after the cancellation's write, it would have seen one active offer and stopped. The two members are consecutive on the waitlist, which means the second write picked "the next member without an offer" after the first write had landed. The lines do not prove a cause. They rule out most of the stories a description would have allowed, including "the sweep re-sent the same offer", because the members differ.

Everything after the word waitlist is written by the waitlist code you saw on the previous page, one call per offer, in the same format whichever language the booking service is in; the timestamp and level come from the logging setup. That is no accident of this example. The logs worth handing to an agent are the ones somebody decided to write before the incident, with the identifiers and the state that a later reader would need.

Point at the Log, Quote the Lines

Chapter 4's rule applies directly: point the agent at the evidence rather than paraphrasing it. Give it the path to the log file and the waitlist code, and let it read both. Then quote the two lines you already found, so it starts where you are rather than rediscovering them. "The log is in this file; these two lines, 300 milliseconds apart, are the third incident" is a request that saves the agent a search and keeps it from settling on some other pair.

The same goes for every other kind of evidence. Paste the whole stack trace, never "it threw an error somewhere in waitlist". Paste the failing test's full output, not "the test is red". Give the commit range as two identifiers, not "since Kai's change". Each of those can be checked by the agent against the code; each summary can only be believed.

Scrub Before You Hand It Over

Production logs carry what production handles: member names, email addresses, phone numbers, and now and then a token that a careless line logged. Whatever enters the agent's context may leave your machine, and Chapter 12 follows where it goes. So the log excerpt is scrubbed before it enters the session, and the scrubbing keeps the structure the reasoning needs: identifiers, timestamps and the order of events.

The same line before and after scrubbing
before: 2026-10-14T18:02:41.207Z INFO waitlist offer class=C-2291 member=M-10482 name="Dana Okafor" email=dana.okafor@example.com token=ot_5Jx9QwL2 path=cancel free_places=1 active_offers=0
after:  2026-10-14T18:02:41.207Z INFO waitlist offer class=C-2291 member=M-10482 name=<name> email=<email> token=<token> path=cancel free_places=1 active_offers=0

The member identifier stays, because the reasoning depends on two different members and on their order in the waitlist. The name and the email go, because nothing in the bug depends on who the climber is. A good rule: keep what lets the agent tell events apart, drop what lets anyone tell people apart. If an identifier itself is personal, such as an email used as a key, replace it consistently, so the same person maps to the same placeholder throughout the excerpt.

Ranked Hypotheses With Distinguishing Checks

Given good evidence, an agent will still tell the first story that fits, and it tells it fluently. The request that keeps the session honest asks for several stories and a way to choose between them: list the causes consistent with these two lines, most likely first, and for each one the observation that would rule it out.

Asking for hypotheses that can be ruled out, not for the answer
Youthe request
Here are the two offer lines from the third incident and the commit range for the waitlist. List the causes consistent with them, most likely first. For each, give the check that would rule it out. Do not change any code.
The agentthe answer, abridged
1. Both paths read before either wrote; ruled out if the paths read and write in one storage call.
2. The sweep ignores offers made in the last second; ruled out if the sweep reads offers with no time filter.
3. Two sweep processes ran at once; ruled out if one of the two lines came from a cancellation.

Then the checks are run, by you or by the agent, and they are cheap. The third hypothesis dies on the evidence already in hand: one line says cancel, the other sweep. The second dies on one read of the sweep's query. The first survives, and it is exactly the interleaving the step-driven test on the previous page forces. A single hypothesis would have looked equally convincing; the ranked list is what showed the other two were weaker.

What Only People Know

Some evidence was never written to any log. It lives in the team's heads: the timeline of the three incidents, what was deployed in the week before each, how often the sweep runs, that it has only ever happened in full classes, that Kai merged a two-second guard after the first one and it happened twice more anyway. Each of those facts prunes the space of causes, and none of them exists for the agent until it is in the request.

Write them down in plain sentences at the top of the session. "It happens only in full classes" alone points at the step that decides a place is free. "The guard did not stop it" tells the agent that timing between the paths is not the whole story. The agent is good at combining facts; it cannot combine facts it was never given.

Misconceptions
  • "A clear description saves the agent time." It saves words and costs accuracy, because your interpretation may already be the wrong hypothesis, and the agent will build on it rather than question it.
  • "Paste the whole log." A log of 50,000 lines fills the context, pushes earlier instructions out, and buries the two that matter. Hand the agent the file to read and quote the lines you found.
  • "The agent can look at production itself." Only with access you gave it, and that access is a security decision for Chapter 12. Usually you carry the evidence over, scrubbed.
  • "Logs are safe to give my own assistant." What enters the context may leave the machine, so names, email addresses and tokens come out before the excerpt goes in.
  • "One hypothesis that fits is enough." Several causes fit two log lines. The check that rules the others out is what selects one, and without it the first fluent story wins by default.
Why It Matters
  • Hand over raw evidence, meaning traces, log lines with timestamps, inputs and the commit range, before any interpretation of it. The agent can check evidence against the code; it can only believe a summary.
  • Scrub personal data and secrets from logs before they enter the context, and keep identifiers, timestamps and order. Those carry the reasoning; names and emails never do.
  • Ask for ranked hypotheses, each with the observation that would rule it out. Running cheap checks beats debating plausible stories.
  • Tell the agent what only the team knows: what changed, when the bug happens and when it does not. Facts that are not in the request do not exist for it.

Knowledge Check

Which request gives the agent evidence rather than a description?

  • "Offers are sometimes sent twice; the sweep is probably re-sending them, so please check the sweep"
  • "These two offer lines for class C-2291, 300 ms apart, are the third incident; the log is here"
  • "The double offer is a timing problem in the waitlist; find where the timing goes wrong"
  • "Kai says the waitlist misbehaves under heavy load; investigate the waitlist module for any problems"

You are about to paste an incident log excerpt into the session. What should you remove, and what must stay?

  • Remove the member identifiers and keep the names, since names make the excerpt easier to follow
  • Remove the timestamps and keep everything else, since timestamps reveal when members climb
  • Remove names, email addresses and tokens; keep identifiers, timestamps and the order of events
  • Remove nothing, since the assistant runs on your machine and the excerpt never leaves it

Why ask the agent for several ranked hypotheses, each with a check that rules it out, instead of its single best explanation?

  • Two log lines fit several causes, and cheap checks pick the right one instead of the most fluent
  • A longer answer uses more of the context window, which in turn makes the agent reason more carefully
  • The agent is required to produce at least three hypotheses before it may propose any fix at all
  • Ranked lists can be pasted straight into the team's incident report without any further editing work

Which piece of context can only the team supply?

  • The full stack trace from the failed request, copied from the error tracker's incident page
  • The two offer log lines from the third incident, with their timestamps and member identifiers
  • The commit range in which the waitlist code was written, taken from the repository's history
  • That it has only ever happened in full classes, and that the guard did not stop it

You got correct