What You Deleted Is Invisible to Your Coding Agent
You spent Tuesday afternoon deleting a dead utility module. You cleaned up the imports, ran the type checker, watched CI go green, and merged the PR. Wednesday morning, a fresh agent session looks at the same code, decides the codebase is "missing" a small helper, and writes the dead module back in — same name, same shape, slightly different style. The reviewer who approved the deletion yesterday now has to remember why they killed it, find the conversation that justified it, and explain it again. The agent is not malfunctioning. It is doing exactly what its context says to do.
This is the structural reliability problem of coding agents that nobody is solving with prompt engineering: the agent's context starts from the repository's current state, but not from the history of why that state is what it is. The file you removed leaves no trace the agent can see. The dependency you migrated away from is just another package on npm. The flaky test you intentionally deleted is a coverage gap waiting to be "fixed." Absence — the negative space of decisions you made — is invisible.
Git diff is not the rationale, and the agent does not read it anyway
The first instinct is to point at git log. Surely the agent can run git log -- path/to/dead-module.ts and find the deletion commit. In practice this fails on two layers.
The shallower failure: most agent sessions don't reach for git history unsolicited. Their default behavior is to read the current state of the files and write changes against that snapshot. Asking an agent to scan the last six months of history before adding a utility helper isn't a workflow that emerges from the tool — it has to be prompted into existence. By the time you remember to prompt it, the helper is already written.
The deeper failure: even when the agent does look at history, git only tells it what changed, not why. A commit message that says "remove unused payment idempotency layer" is a fact about the code, not a record of the decision. The thing you actually need to know — that the layer existed because of a Black Friday incident two years ago where double-charging blew up production for 4,200 customers — was discussed in Slack, captured in a postmortem doc, alluded to in a PR thread, and never made it back into anything the next agent session can grep. Git history is a stream of deltas. The rationale is the negative space around those deltas, and nobody writes that down in the place the agent can find.
This is why "just add a CLAUDE.md with the conventions" doesn't fix it. Convention files describe positive rules — what to do, which patterns to follow. They rarely enumerate the things that were considered, tried, rejected, or surgically removed. The half of your engineering knowledge that lives in the word "no" has no canonical home in the repo.
A taxonomy of what gets re-proposed
If you watch a team using coding agents for a few weeks, the same failure patterns repeat. They sort cleanly into categories, and the categories matter because the fix for each is different.
The first is re-created utilities. Someone removed a humanizeDuration helper because it was duplicating logic from a library you'd standardized on. A week later, a different agent session writes its own formatDuration because the codebase visibly "doesn't have one." The agent isn't wrong about the gap — it's wrong about the gap being a problem.
The second is re-added dependencies. You ripped out moment.js six months ago in favor of native Intl plus date-fns. Today's agent solves a new locale-formatting task by reaching for the most popular package its training data knows about, which is still moment. The migration cost is now back in your queue.
The third is restored tests. The agent notices a function with no test, writes one, and reintroduces the exact assertion someone deleted two months ago because it was testing implementation detail that had since changed, or because the test was flaky in a way that masked real regressions. The new test "passes," which makes it harder to argue against keeping it.
The fourth is re-merged services or modules. You separated two pieces of code on purpose — different deploy cadence, different scaling profile, different blast radius — and the agent reads them as two files that could trivially share a base class. The refactor PR makes the diff smaller and reads as a clean win on the dashboard. It also undoes a decision that took an outage to reach.
The fifth, subtler one is resurrected dead branches in logic. The agent sees an if that returns early and "simplifies" it, removing a guard that was added because exactly one customer's data shape happens to hit it. The bug it prevented does not exist in any test, because the test would need that customer's data. The guard came from a one-line fix that lived only in a Linear ticket.
All five share a structure: the agent is reasoning correctly about what is present and reasoning blindly about what was deliberately removed.
The artifact you actually need: a record of negative decisions
The right mental model is that the codebase encodes positive decisions and your communication channels encode negative ones. The agent only has access to the codebase. So if you want the agent to respect negative decisions, the codebase has to start carrying them.
- https://www.me2resh.com/blog/agent-decision-records
- https://github.com/me2resh/agent-decision-record
- https://github.com/anthropics/claude-code/issues/15222
- https://www.mahdiyusuf.com/why-your-coding-agent-keeps-undoing-your-architecture/
- https://www.augmentcode.com/guides/session-end-spec-update-ai-agents
- https://dev.to/pickuma/why-ai-agents-forget-memory-decay-and-context-contamination-explained-44kd
- https://rickpollick.com/blog/adr-comeback-anchoring-agentic-engineering-teams
- https://github.com/archgate/cli
- https://www.anthropic.com/engineering/claude-code-best-practices
