"Login is broken." Claude Code changes something and login works, but signup now throws. It fixes signup, and the session cookie stops being set. Forty minutes later there are eleven modified files, none of the original error message is left anywhere, and you can no longer say which change was the one that helped.
This is the most expensive failure mode in AI-assisted work, and it starts with a symptom handed over without a way to reproduce it.
The idea
An agent given a symptom and no reproduction will guess, and a guess that half works is worse than one that fails outright: it changes the error, which looks like progress. The way out is to make each attempt falsifiable and cheap to undo. Reproduce the failure yourself, shrink it, read the actual error text, change one thing, and check that one thing.
the circle the line
---------- --------
report the symptom reproduce it yourself, on demand
| |
agent guesses a fix shrink it to the smallest failing case
| |
a different error appears read the real error, top line and file path
| |
paste the new error ---+ change exactly one thing
^ | |
+----------------+ did that one thing fix it?
| |
yes no
| |
commit revert to the last
good commit and restateHow it works
Reproduce before you ask. A failure you cannot trigger on demand cannot be verified as fixed, so every "fixed it" that follows is unfalsifiable. The reproduction is a recipe: the exact steps, the exact input, the exact error text.
Read the real error rather than the summary of it. The first line of a The list of function calls the program was inside when it failed, most recent first, with file names and line numbers. names what went wrong, and the topmost line mentioning a file you wrote is usually where to look. Paste it in full. An agent handed "it errors" invents a cause; an agent handed the trace reads one.
One change at a time. When three edits ship together and the symptom moves, you have learned nothing about which edit did it. Ask for the cause before the fix: "explain why this happens, and do not change anything yet" costs one turn and saves the guess.
Anthropic's Claude Code guidance sets the stopping rule: after two failed corrections, start fresh with a better prompt built from what you learned. By then the The working memory of one conversation, holding every message and file read so far. is full of failed approaches, and the model keeps re-reading its own wrong turns as if they were context.
Reverting is the part people skip. Version control makes the whole session disposable, which is what lets you throw away a bad direction instead of defending it. Version control, plainly covers the mechanics.
What to do
- Commit before you start.
git commit -am "before login fix"gives you a known good point, andgit reset --hard HEADreturns to it exactly. - Write the reproduction into the request: steps, input, and the error pasted in full. Ask for the cause first and the fix second.
- After the second failed fix, revert. Open a fresh session and describe the bug plus everything you ruled out, rather than continuing the conversation that accumulated the failures.
Where it breaks
Some bugs will not reproduce on your machine. Timing bugs, bugs that need real traffic, and bugs that only appear on the production database are real, and the answer there is better evidence rather than more attempts: logs from the moment it failed, the actual request, the actual data.
Reverting also destroys good work when you have not been committing. The cost of the revert is set by how long ago your last commit was, which is the real argument for committing more often than feels necessary.
And a clean reproduction can still point at the wrong layer. When the smallest failing case involves a library you did not write, check its version and its release notes before assuming your own code is at fault.