I was reviewing a PR that touched the same handler file in four commits. Commit 2 added a null check around a config read that was crashing staging. Commit 4 rewrote that same block to "clean up the error handling." The null check was gone. The code in commit 4 looked fine on its own.
git blame on the crashing line pointed at commit 4. The agent had overwritten its own fix.
This isn't the agent being careless. It's a structural failure of how long sessions work. After a handful of edits, the agent is no longer reading the file from disk before it rewrites a section. It's working from the version of the file it remembers from the last read, plus the handful of edits it has made in the conversation. If its mental model diverged from what's actually on disk — because you, or a linter, or a parallel edit changed something — the next "rewrite this block" lands on a stale picture.
You see this in three patterns, all of which look like normal diffs:
The cleanup that deletes a fix. "Refactor error handling" rewrites the catch block and drops the null guard that was protecting the line above. Tests still pass because the test fixture was written against the old crash and the agent didn't re-run it after the refactor.
The reformat that drops a line. A "make this consistent with the rest of the file" edit re-emits the whole function from memory. One line from the previous edit silently disappears because the agent's mental snapshot predates it. The diff shows the whole function changing, so the missing line doesn't stand out.
The merge that picks the wrong side. When the agent has been told "we decided to use approach B," and later re-reads the file and sees approach A still there, it may "helpfully" revert to A because that's what's on disk — or, worse, edit the on-disk A while remembering a B, and produce a third thing nobody chose.
The fix that stuck for me is cheap and mechanical: after every third edit in a session, force the agent to re-read the file from disk before touching it again. Not "you already saw this," but literally cat the file into the next turn. Treat the on-disk version as the only source of truth. Conversation memory is a cache; caches drift.
The other cheap guard is to make the agent re-run the relevant test after any "cleanup" or "refactor" edit, even if it swears nothing behavior-changing happened. Most of the silent overwrites I've seen would have been caught by the test going red one commit later.
This is the same reason I keep the API spec as a file on disk rather than letting the agent carry the contract in conversation memory. In Powerduck, the spec is the thing the agent has to re-read against, not a summary it paraphrases after the fifth edit. A contract that lives in a file is a contract that can be diffed. A contract that lives in conversation memory is a contract that gets rewritten by accident.
Where does your agent sessions' state drift first — the file it's editing, or the requirements it's carrying?
Comments
Join the discussionNo comments yet. Be the first to comment.

