Skip to content
The Operon Library

Volume III · Chapter 10

Intent Anti-Patterns

Over-specification, under-specification, prompt inflation, intent drift, stale constitutions.2026-07-12 · 8 min read

Six months into a spec-driven rollout, a tech lead pulls two artifacts from the same sprint to make a point in a retro. The first is a nine-page specification for a CSV export feature — acceptance criteria, edge-case tables, three revision rounds — that took two engineers a day and a half to review and about forty minutes to implement once it was approved. The second is a four-line spec for a permissions change, “let admins delete other users’ comments,” that three engineers on three separate sessions each implemented differently, and none of the three would have passed either of the other two’s idea of code review. Both artifacts were called specs. Both teams were following the process this volume has been building since Chapter 3. Neither team thought it was doing anything wrong until the retro made the contrast visible.

The two failures share nothing on the surface — one spec was too much, the other too little — but they share a shape underneath. Every practice this volume has recommended can be done badly: writing specs instead of vibe coding (Chapter 3), maintaining a constitution (Chapter 4), running the phase structure (Chapter 5), choosing living or static (Chapter 6), gating work behind plan mode (Chapter 7), layering intent files (Chapter 8), building a spec library and reviewing it like code (Chapter 9). The badly-done version of any of these is not obviously different from the well-done version at the moment it is produced. It becomes visible only in the review time it consumed, the disagreement it failed to prevent, or the divergence it quietly let accumulate. This chapter catalogs five of the most common ways intent architecture goes wrong — not as abstractions to feel bad about, but as symptoms a reviewer can actually check for before the cost compounds.

Every anti-pattern in this catalog is the well-done practice’s evil twin — cheap to mistake for the real thing until the cost has already been paid.

Over-specification

The over-specified spec is easy to spot from the outside once a reviewer knows to look for it: it is longer, in prose, than a competent engineer’s honest estimate of the diff it will produce. It enumerates edge cases the codebase already handles by convention. It pins down data types, variable names, or file layout for a change where none of those choices carries real risk. A reviewer who needs twenty minutes to approve something that will take forty minutes to build is reading an over-specified spec, whether or not anyone in the room ever uses that phrase.

The cause is rarely bad judgment about any one detail. It is a house style that treats “more detail” as strictly safer, without pricing the cost of writing and maintaining that detail against the cost of the ambiguity it removes — which defeats the entire economic case for writing a spec instead of just building the thing. Chapter 7’s plan-mode logic already supplies the right lever here: match spec depth to actual ambiguity and blast radius, not to a uniform template. A one-line schema change on an internal admin tool and a public API contract change do not deserve the same page count, even if the team’s spec template gives them the same headings.

Under-specification

Under-specification is the anti-pattern most likely to hide behind the appearance of rigor. The document exists, has section headings, was reviewed and nominally approved — and still leaves the actual behavior underdetermined. The tell is procedural rather than textual: hand the same spec to two competent engineers independently and ask whether the resulting implementations would each pass the other’s review. If a reviewer genuinely cannot answer without guessing, the spec has quietly reverted to the vibe coding this volume positioned spec-driven development against in Chapter 3 — it has just kept the ceremony and the false confidence of having “written a spec.”

The fix is a definition of done a reviewer can actually check, not a restated goal. “Handle errors gracefully” is a goal; “a malformed CSV row is skipped and logged, not silently dropped or fatal” is a checkable condition. A spec that cannot be reduced to a handful of yes-or-no questions about the finished code has not specified anything — it has described a wish and dressed it in a template.

Prompt inflation

Prompt inflation is what happens to a spec that started reasonable and never got restructured. Each edge case discovered in review gets bolted onto the bottom — one more paragraph, one more caveat, one more “also handle the case where…” — and each addition is individually defensible in isolation. Nobody restructures the document; nobody asks whether the original three sections still organize what are now eleven concerns. A reviewer can usually spot an inflated spec by its shape alone: a short, coherent opening followed by a long tail of patches that reads more like a changelog than a specification.

The mechanism is the same one Volume II described for a session’s working context: information accreting past the point where anyone — human or model — can hold the whole document in view and reason about it coherently, which is exactly what the research on context rot describes at the level of a model’s input window. It is also, structurally, technical debt in Ward Cunningham’s original sense: each patch was individually the fastest path to correctness, and the interest compounds silently until the document costs more to read than it would have cost to rewrite. The fix is not “write it perfectly the first time” — reactive patches are a normal part of discovering what a feature actually requires. The fix is treating a spec that has absorbed more than a few reactive patches as a signal to restructure, the same way an engineer would refactor code that had accreted an equivalent number of one-line fixes, rather than continuing to patch indefinitely.

Intent drift

Intent drift is quieter than the first three anti-patterns, because nothing about the spec itself looks wrong on a read. The document was accurate the day it was written; the implementation has simply moved since. A bug fix lands directly against the code, skipping the spec because it “was just a bug fix.” A follow-up change extends behavior the original spec never anticipated. Months later the spec still describes a version of the system that no longer exists, and nobody notices until a new engineer implements a change that satisfies the spec exactly and breaks production, because production had already diverged from the document they trusted.

This is the direct cost Chapter 6 flagged as the risk of choosing a static plan over a living spec: a static plan is disposable by design, so nobody expects it to track reality after implementation — but if the team keeps consulting it as documentation anyway, the choice to make it disposable and the habit of still trusting it are working against each other. The fix is not universally “make every spec living”; Chapter 6 was explicit that static plans have a real place. The fix is that whichever choice a team makes, it needs an explicit answer to one question: who notices when the code and the spec disagree, and how. A code owner assigned to the spec file, a check that flags a spec untouched since its linked files last changed, or simply an accepted policy that specs for finished features are archived rather than consulted — any of these closes the gap. An undecided answer to that question is what intent drift actually is.

Stale constitutions

A constitution, in this volume’s sense from Chapter 4, is meant to be the standing document a spec inherits from without restating — the project’s non-negotiable principles, foundational enough that they should not need relitigating in every spec review. The anti-pattern is a constitution written once, early, in the enthusiasm of adopting the practice, and never revisited as the project’s real constraints changed. The tell is easy to check directly: pull up the constitution file’s last-modified date and compare it against the project’s own commit history. A constitution untouched for a year in an actively changing codebase is a strong candidate for describing beliefs the team no longer actually holds.

Software does not fail because it ages. It fails because the documentation stops aging with it.

On Parnas’s 1994 diagnosis of software aging

David Parnas named the general phenomenon three decades before AI-assisted engineering existed: software ages not only because its code changes but because its documentation fails to adapt with it, leaving inconsistent or outdated guidance that active maintainers quietly learn to route around. A stale constitution is the standing-document equivalent of a compliance policy nobody has read since it was published — everyone in the room has informally learned which parts to ignore, but the document itself keeps getting cited by newcomers, and by every AI session that dutifully loads it as context, since a constitution file is exactly the kind of standing instruction that current tooling guidance says gets read at the start of every session. The fix is scheduling, not vigilance: a constitution needs a periodic review on a calendar, tied to a real trigger — a major architecture change, a new team lead, a quarter boundary — because “update it when it feels stale” is precisely the judgment call that never fires on its own.

Five anti-patterns, one diagnostic

The five share a common diagnostic shape: a symptom a reviewer can notice from outside the document, a plausible cause that explains why competent people produced it anyway, and a fix that is a practice change rather than a one-time cleanup. The table is meant to be checked against a real spec, not just read once.

Anti-patternSymptomRoot causeFix
Over-specificationSpec takes longer to write and review than the change would take to buildUniform house style treats more detail as strictly saferMatch depth to ambiguity and blast radius (Ch. 7), not a template
Under-specificationTwo engineers implement it differently and each passes their own reviewGoal restated with no checkable definition of doneRequire conditions a reviewer can verify yes/no against finished code
Prompt inflationCoherent opening followed by a long tail of reactive patchesEach addition individually defensible; document never restructuredTreat more than a few reactive patches as a signal to restructure
Intent driftSpec accurately describes a version of the system that no longer existsCode changed (bug fix, follow-up) without the spec being updatedAssign explicit ownership for spec/code divergence — person, check, or archival policy
Stale constitutionsConstitution’s last edit predates the project’s real current constraintsWritten once early, never revisited as constraints changedCalendar-based review tied to a real trigger, not “update when it feels stale”

None of the five is fatal on its own, and none requires new tooling to catch — only the discipline of checking a spec, a prompt, or a constitution against these symptoms with the same rigor a team already applies to code review. The five together are also, not coincidentally, an inventory of every place this volume has argued a standing document can go wrong: too much structure, too little, unmanaged growth, unmanaged drift, and unmanaged age. Prompting was never the skill this volume was arguing for; specifying was — and a catalog of the ways specifying fails is what makes “we write specs now” something closer to an engineering practice than a slogan a team repeats at standup.

For Discussion

  1. Pull up your project’s constitution file, or its nearest equivalent, right now — when was it last edited, and does that date line up with when your team’s real constraints last changed?
  2. Take the five most recently written specs on your team: how many would survive the under-specification test — two engineers implementing independently, each producing work that would pass the other’s review?
  3. Who, or what — a person, a process, or nobody — currently notices when a spec and the code it describes have quietly diverged?

References

  1. establishedUnderstanding Spec-Driven Development: Kiro, spec-kit, and TesslMartin Fowler · 2025-09
  2. establishedContext Rot: how increasing input tokens impacts LLM performanceChroma Research · 2025-07
  3. establishedSoftware Aging — documentation and guidance failing to adapt alongside changing codeDavid L. Parnas, Proceedings of the 16th International Conference on Software Engineering (ICSE) · 1994-05
  4. establishedspec-kit — constitution, specify, plan, tasks phase structureGitHub · 2025-09
  5. establishedHow Claude remembers your project — CLAUDE.md loaded at the start of every sessionAnthropic, Claude Code documentation · 2026-01
  6. establishedTechnical Debt — the interest-accrual metaphor for unrefactored, patched-over decisionsMartin Fowler (bliki), attributing the original metaphor to Ward Cunningham · 2019-05
  7. emergingUnclear or poorly defined initial requirements as a leading driver of scope creepProject Management Institute · 2024