Design intent when AI writes the code

When design intent confuses the AI

· 5 min read

Design intent is the record of why a system is shaped the way it is: the decision made, the alternatives rejected, the reason one won. This series is about where that why can live so an agent reads it; its oldest home is the architecture decision record, the ADR, and ours had quietly stopped giving single answers.

I gave an agent an ordinary task and let it read the code. It hit a comment: the behaviour here follows ADR-024. Fair enough, go read that decision and honour it. Except we have three files numbered ADR-024, all marked Accepted, all from the same month, on three unrelated parts of the system. From there the agent either picks one and quietly assumes wrong, or burns tokens working out which the comment meant. The reference had stopped resolving to a single answer, and neither of us had noticed.

TL;DR:

  • This rot is AI’s doing. We had about 10 ADRs before agents did the feature work; then a fresh ADR became the cheap default for every change and the log hit 41, with nobody reconciling the overlaps, because two decisions with the same number never collide, they are just two separate files.
  • So of the 41 ADRs, the ones agents wrote since March already reuse 7 numbers, and ADR-024 alone names three Accepted decisions. The reference no longer resolves to one.
  • The danger is the false safety of “our intent is written down” when the written form no longer functions as intent.
  • The test of design intent: can a reader resolve it to exactly one current decision? If not, it’s legacy.

The record lost its integrity

Nobody audited the ADRs. They rotted. The log held about ten decisions through February 2026; then agents took over the feature work: 9 new ADRs in March, 14 in April, the rest through May, 41 in all, written far faster than anyone read them back.

Bar chart: seven ADR numbers written by agents since ADR-019 are each shared by more than one decision; ADR-024 is shared by three, all marked Accepted, against a reference line showing a unique ID should name exactly one

Seven reused numbers, all in ADRs agents wrote from ADR-019 on (March to April 2026). The earlier, hand-written decisions don't collide; the machine-written ones do.

Three shapes of the same rot:

  • One ID, three decisions. The three ADR-024s aren’t near-duplicates a human would merge on sight. They’re three unrelated decisions, different parts of the system, that happen to share a number.
  • Two IDs, one feature. The inverse is quieter. Two Accepted ADRs cover the same feature, a broad original and a later, deeper revision, with neither marked stale and neither linking to the other. Nothing tells the agent the newer one moved the thinking on, so the old decision reads as live as the new.
  • No format to hold onto. Even the headers disagree: # 24., # [ADR-014]., # [ADR-027]. Title:. There’s an ADR-TEMPLATE.md in the folder; nothing checks that anyone used it.
A note on precision: what I measured, and what I didn't

What I measured is the documents: 41 ADRs, 7 reused numbers, re-runnable with ls. Seven is a floor, exact ID clashes only, not the deeper same-feature overlap. I did not measure a resulting bad fix; I never instrumented for “agent followed the wrong ADR”, so this is a named risk, not a logged incident. The failure itself is old, Fred Brooks called it losing conceptual integrity in The Mythical Man-Month in 1975; what AI changed is the volume.

The danger

  • False safety. “We have ADRs” reads as “our intent is captured, we’re covered.” But a record that resolves to three answers rejects no wrong fix. Written-down is not the same as functioning-as-intent, and the checkbox hides the gap.
  • A rotten record is worse than none, and AI wrote this one. With nothing written, the agent asks. With three Accepted answers, it doesn’t know it should: a strong model on a clean context may catch the collision, a weaker or cluttered one takes the first match and runs. The loop is self-inflicted: the same agents generating the ADRs are the ones now tripping on them.
  • Decisions nobody read. An ADR you didn’t read isn’t a decision you made, it’s one the machine made and you rubber-stamped. Generate them faster than you review them and the log fills with contradictions nobody actually chose.

The takeaway

Capturing intent is the easy 20%; keeping it resolvable is the 80% nobody budgets for. Concretely, on Monday:

  • Make duplicate IDs impossible, not discouraged. A pre-commit check that fails on a repeated or missing number, plus an adr new "<title>" script that allocates the ID so no one hand-types it. The ADR conventions assume unique sequential IDs; enforce the assumption instead of trusting it.
  • Mark the winner, retire the rest. When a later ADR revises an earlier one, change the old file’s status and link forward to the new ID in the file, not in a commit message the agent never reads. One decision, one live document.
  • Encode the invariant, don’t describe it. A decision the agent must not violate belongs in a test or a lint rule, not in prose it has to find and obey. It’s the same move that cut our change-failure rate: a tool runs every time; a written rule is advice the agent can skip.
What would change my mind

If I renumber all 41 into a clean, gap-free sequence, dedupe the three 024s, and an agent still applies the wrong decision when it hits a reference to ADR-024, then the numbering was never the problem and the prose is. I’ll run that on the next integration ticket and report it. If clean IDs fix it, the resolvable reference was the design intent all along.

AI didn’t lose our design intent. It generated so much of it, so fast, that the intent stopped pointing anywhere.

Next in this series: the best guardrail is the one you can delete. An AI matcher that kept returning the wrong ID, and why the fix was to remove the check, not add one.