Your agent will "fix" the thing you did on purpose
An incident in our own repository: the agent did its job correctly and broke something anyway, because the reason was in a person's head.
Where this comes from
PR #398 is in our own repository, 2026. The locking behaviour described is services/llm_jobs.py as of this writing. The quote is verbatim from a public Hacker News thread. We have not measured how often this class of failure occurs across projects — this is one incident, described because we have the whole context for it, not a statistic.
What happened
An agent working in our own repository was sent to fix a bug. It fixed the bug. It also found a piece of behaviour that deviated from the obvious convention, decided that was the actual defect, and standardised it.
The deviation was intentional. It had a reason. The reason was in somebody's head and in a decision made weeks earlier, and nowhere in the repository. From where the agent sat it looked exactly like a mistake — and an agent that leaves an obvious mistake in place after touching the file is doing its job badly, so it did not leave it.
the part worth keeping
We caught it in review. The interesting thing is not that it happened; it is that every mitigation people recommend for this failure was already in place, and none of them applied.
The failure is not carelessness
The usual framing is that the agent went out of scope. It did not, really. It was in the file, it was in the function, and the change it made was a defensible improvement to code it had been asked to work on.
The failure is upstream of the agent: nothing distinguished a deliberate deviation from an accidental one. Both look identical in source. A human who has been on the project a year reads the odd branch and thinks "there is probably a reason for that". An agent reads the same branch with no memory of the project and thinks what a new hire thinks on day one — except a new hire asks, and the agent ships.
[The agent] is optimized to get its feature working inside local context, not to improve the codebase as a whole … it slowly fills the repo with debt.
miguelspizza, Hacker News
Local context is the operative phrase. The agent optimises what it can see, and intent that was never written down is not in the set of things it can see.
What we already had, and why none of it caught it
A comment. The standard advice — explain why, not what. It would have worked here, if someone had written one at the moment the decision was made, in the right file, and if no later refactor moved the code away from it. Comments also have no enforcement: an agent can, and routinely does, edit the comment to match the code it just changed. The record and the thing it records sit in the same writable file.
Tests. A test asserting the non-standard behaviour would have gone red, and this is the single most effective mitigation available. It is also the one people skip precisely where they need it most — the odd, one-off, "we do this for a reason" branches are the ones nobody writes a test for, because the reason feels obvious on the day. And a red test still tells you only that the behaviour is expected; the next question is why, and the test does not answer it.
A narrow instruction. Ours was narrow — fix this bug. The change was inside the scope it was given. Scoping stops an agent wandering into billing when you asked about checkout; it does nothing about a change inside the file it was correctly sent to.
`CLAUDE.md`. Ours exists, and it is where build commands and conventions live. It is not where "this endpoint deliberately returns a non-standard shape because of a downstream consumer" lives. Put every such decision in it and it becomes tens of thousands of tokens loaded on every invocation — at which point the agent skims it, and we are back where we started.
What the fix actually has to be
Stated plainly, the requirement is narrow: the intent has to exist as a record the agent reads and cannot quietly rewrite. Three properties, and the third is the one that gets skipped.
- Durable — it survives the session in which it was decided. Chat does not qualify.
- Reachable — the agent gets it as part of its working context, without a human remembering to paste it.
- Not editable by the thing it constrains. A rule in a file the agent can rewrite is a rule until the moment it is inconvenient.
That third property is why "just write it in a markdown file" gets you most of the way and then stops. The file works exactly as long as nobody asks the agent to keep the docs current.
In our system a requirement can be locked, and locked means something specific in the code rather than in the marketing: locked requirements are filtered out of the set handed to the model before generation runs — chosen_reqs = [req for req in existing_reqs if not req.lock]. The model is not asked to rewrite them and cannot return a version that has quietly dropped one. The requirement is served to the agent over MCP alongside its links: what story it came from, what it depends on, what depends on it.
applied to this incident
One pinned requirement stating the deviation and its reason. The agent fixing the bug would have had it in context, along with the fact that something downstream depends on it.
What this does not do
It does not make the agent obedient. An agent that has read a requirement can still contradict it; nothing in an MCP response compels a model. What changes is that the contradiction becomes visible — there is a stated requirement to check the diff against, so the disagreement surfaces in review instead of being discovered by a downstream consumer three weeks later.
It also does nothing for the deviations you never record. If the decision was never articulated at all, no system has it. The realistic claim is narrower than "your agent stops breaking things": the class of failure where the project knew and the agent did not stops being invisible.
For the class where the agent breaks something it genuinely could not have seen — a dependency across a boundary nobody documented — the honest answer remains tests, and the honest observation is that most projects at this size do not have them.
The check that costs nothing
Before an agent touches a file, the question worth asking is not "is this change correct" but "does anything in here look like a mistake that is not one". If the answer takes more than a few seconds, that is a decision living in one person's head — one session away from being standardised out of the codebase by something that is trying to help.
Questions this raises
Why did the agent change code it was not asked to change?
It was asked to work in that file, found what looked like a defect next to the one it was fixing, and fixed both. From its position the deviation and a bug are indistinguishable, because nothing in the repository recorded that the deviation was deliberate.
Would a comment have prevented this?
Possibly, if one had been written at the moment of the decision and survived every later refactor. Comments have no enforcement: the agent has write access to the comment and to the code it describes, so an agent tidying up can bring the comment into line with the change it just made.
What does a locked requirement actually do?
Locked requirements are excluded from the set handed to the model before a generation run, so the model is never asked to rewrite them and cannot return a version with one silently dropped. It is a filter in the generation path, not a UI state.
Entalpa gives your agent one locked source of truth
Structured, traceable requirements your agent reads over MCP — so it works from a curated spec instead of reconstructing your project every session. Free to start, no card, and MCP calls never spend credits.