Design intent is the antidote to a narrow AI fix
An agent solves the ticket in front of it, well, and without ever asking whether the solution fights the architecture. Nothing in the ticket mentions the architecture. This series is about the one thing that can push back, and about the four places it can live.
TL;DR:
- The narrow fix is not an AI defect. It is what you get when the only context is the ticket, and it is what most humans do on their first week too.
- Design intent is the record of why, and it only works if it sits where the agent already reads.
- There are four places to put it, and they trade off against each other in one predictable way.
- The cheaper an expression of intent is to write, the easier it is to ignore. That is the whole finding, and every post in this series is one of the four.
- Only the running code cannot be ignored, and it is the only place that requires deleting code rather than adding words.
Where this came from
The series exists because of a comment. After the first post I published, Chavdar Baykov asked the question that turned out to be the interesting one. He is a principal architect at a payments company. His question was not “does AI write good code”, but where the reasoning behind a system now lives.
I have spent four posts answering it with our own receipts, and this is the map of them.
The four places
Design intent can live in four places. They are ordered here by how much it costs to write one, which happens to be the reverse of how well it holds.
| Where it lives | Cost to write | Cost to ignore |
|---|---|---|
| A document | An afternoon | Nothing |
| An instruction file | A paragraph | A little |
| Memory and retros | Automatic | Varies |
| The running code | A rewrite | Impossible |
That inversion is the finding. Every cheap home for intent is cheap precisely because nothing enforces it, and enforcement is the entire job.
One: a document
The oldest home, and the one every team already has. We had 41 architecture decision records by May 2026, up from about ten before agents.
Then agents started writing them, faster than anyone read them. Eight numbers ended up used more than once, one of them three times. A reference to a record no longer resolved to a single decision.
The document did not become wrong. It became unable to give one answer, which for an agent is the same thing.
When design intent confuses the AI has the count and the mechanism. Its follow-up, make supersession machine-readable, has the fix, and that fix also arrived from a reader rather than from me.
Two: an instruction file
The file the agent reads before touching anything, and the one that feels like the answer. Anthropic’s own documentation says the quiet part out loud: Claude “treats them as context, not enforced configuration”. Your CLAUDE.md is code, and it rots like code has the receipts, including the rule file we scoped to a path that matched nothing.
Three: memory and retros
The semi-dynamic tier, where what the agent learned yesterday is written down for tomorrow. It is the newest of the four and the one I trusted least. I held the post back until I had numbers rather than worries.
The failure modes turned out to be the ones I feared. Accumulated learnings contradict each other over time. Memory grows without bound and pays the same per-turn bill as the instruction file. A wrong note gets recalled with the authority of a right one.
Teaching the agent what it learned yesterday has the count. Three written answers to one question in eight days, all three still loading every session, and a post that went live unreviewed between them. What held in the end was not a better note. It was a build check.
Four: the running code
The last place, and the only one an agent cannot route around.
Our matching pipeline asked a model to return a database identifier, and the model kept returning the identifier of the adjacent row. It was reasoning correctly and answering the wrong question, at roughly one in ten at the worst point.
We wrote a guard to catch it, which is the normal move. The better fix was to stop asking the model for identifiers at all. Code resolves them from the name the model did get right. That change deleted the guard entirely.
An invariant expressed as a shape in the pipeline does not need to be read, honoured, or remembered.
This has a name outside AI work. Alexis King’s “Parse, don’t validate” puts it as a rule: “Use a data structure that makes illegal states unrepresentable.” The best guardrail is the one you can delete is the full story.
How to choose
Not by preference. By what the mistake costs.
If getting it wrong is expensive, spend the rewrite
Anything that corrupts data, spends money, or reaches a customer belongs in the running code. Words are the wrong tool for an invariant, no matter how well written or how prominently placed.
If it is a preference, an instruction file is honest
Naming conventions, review tone, which library to reach for first. These genuinely are preferences, an agent mostly honours them, and a violation costs a comment rather than an incident. Keep the file short, because you pay for it every turn.
If it is history, a document is right, but make it resolvable
Why we rejected the obvious approach in 2025 cannot be expressed as a constraint. It belongs in a record. Give that record a unique identifier and a machine-readable chain, or it will stop answering within a year.
Whatever you pick, add the check that proves it is loaded
The recurring failure across all four places is not a bad rule. It is a rule that silently does nothing: a path glob matching no files, a document nobody can resolve, a guard nothing invokes. Break it on purpose once and watch it fail, or you do not know it is alive.
Conclusion
An agent will not fight your architecture on purpose. It will simply not know there is one, and every place you can tell it costs the opposite of what it is worth.
What would change my mind: this ordering claims that moving an invariant further down the four reduces violations. Suppose a team moves one from prose into a pipeline constraint and the violation rate holds. Then the place was never the variable. Measure it per invariant before rewriting a pipeline on my say-so.
That is the series: four places, one trade-off, and a post underneath each of them.
Methodology & limitations (click to expand)
Data sources
Every figure here is carried over from a post in this series, where it is sourced and bounded in full. The record count and duplicate numbers come from 41 architecture decision records read directly. The matcher figure is my own recollection from the period, and is flagged as such in the post it belongs to.
Prior art
Three of the four places are somebody else’s idea, and naming them is the point: this post orders existing practice, it does not invent any of it.
- Documenting Architecture Decisions, Michael Nygard, 2011. The document. The format, and the reason a record is kept rather than deleted once it is superseded.
- How Claude remembers your project, Anthropic. The instruction file and memory, from the vendor. It states this post’s thesis in its own words, that instruction files are “context, not enforced configuration”, and sends you to a hook for anything that must hold regardless.
- Parse, don’t validate, Alexis King, 2019. The running code, and the older name for it: “Use a data structure that makes illegal states unrepresentable.” The guard we deleted is that argument with a bill attached.
Definitions and bounds
- “Four places” is my taxonomy, not an industry one. It describes where intent actually sat in our system. A team with a different toolchain would draw the list differently.
- The cost columns are ordinal, not measured. They rank the four places against each other from experience. There is no timing study behind them and they should not be read as one.
What this does not show
- No controlled comparison. I did not run the same task against a system with and without each of the four. The claim that enforcement beats expression rests on four cases from one archive.
- The memory receipts come from my own tooling, not the platform archive, which never had that tier at all.
Get new posts by email
One email per post, about two a month. The numbers and the caveats, same as here. No sequence, no pitch, unsubscribe in one click.
Almost there. Check your inbox and click the link to confirm.
That did not go through. Try again, or email [email protected] and I will add you by hand.
No tracking pixels. I never pass the address on. How this is handled.