My AI assistant argued for prevention, then implemented detection. The gap between what an agent recommends and what it builds is a contract problem, not a code-review problem.
Originally drafted in December 2025; revised in August 2026: the contract layer described here now travels as portable skills and a thin always-loaded instruction kernel rather than one large CLAUDE.md, and the contracts themselves carry over unchanged.
During a design discussion about file naming in ownwords, the open-source publishing toolkit I wrote about in an earlier case study, my AI assistant made the case for date-prefixed filenames. Two articles with the same slug could no longer collide by accident, because the date makes each filename unique, and the convention is familiar to anyone who has worked with Jekyll. It was the right recommendation, clearly argued. Then it wrote the code: a collision check that stops on a clash, and a flag to push past it.
The recommendation was prevention. The implementation was detection. Nothing in our exchange decided that change. It happened silently, somewhere between the discussion and the diff.
I call this failure mode recommend A, implement B. Once you have a name for it, you see it constantly. It matters because it breaks the assumption most engineers bring to AI collaboration: that the hard part is getting the design right, and the implementation will follow. With an AI collaborator, agreement on the design guarantees nothing about the code.
Why the drift happens
The cause is not carelessness, and it is not a weak model. The AI optimizes locally. During a design discussion, it is optimizing for the correct answer to the question in front of it. During implementation, it is optimizing for completing the immediate task with the least complexity. Different objective, different output.
The gap widens with the size of the change. A single function gets implemented as discussed. A refactoring that requires consistent changes across many files invites shortcuts, because each shortcut reduces the load of the task the AI is actually scoring itself on: finishing.
After months of production work, the instances I catch keep sorting into three shapes. The partial implementation: the AI recommends a complete solution with error handling and edge-case coverage, implements the core path, and leaves the rest for a later that never arrives on its own. The flag substitution: the AI recommends preventing a problem through design, then builds detection plus an override flag, because detection is easier to build. My date-prefix story is this one exactly. And the feature drop: the AI recommends three related capabilities, implements the two straightforward ones, and quietly omits the third, which was the one you needed.
Write the contract down
The countermeasure is a behavioral contract: explicit rules in CLAUDE.md, the persistent context file the assistant reads at the start of every session. Files survive where conversations do not; I covered the mechanics in How Claude’s memory actually works and Context loss and how to prevent it. Here the question is what the file should say. The clause that addresses the drift directly:
### Decision framework
When multiple approaches exist:
1. Identify all options explicitly
2. Recommend the best option, with rationale
3. Implement what you recommend. Never recommend A and implement B
4. If uncertain, ask. Do not default to the simpler option
### Implementation completeness
Before marking any task complete, verify:
- It implements the recommended approach, not an easier alternative
- Edge cases are handled
- No follow-up work is needed for basic functionality
A contract does not guarantee compliance. The AI still optimizes locally, and I still catch drift. What the contract changes is the cost of correction. Without it, catching the gap means re-arguing the design. With it, review takes one sentence: you recommended X and implemented Y, let’s fix that. The standard was agreed before the work started, so pointing at it is the whole conversation.
Features are additive until proven otherwise
A second clause earned its place because of how reliably AI assistants choose subtraction. Offered the choice between keeping two mechanisms and replacing one with the other, the AI picks replacement nearly every time. It looks like good engineering: less code, fewer paths, no redundancy.
But a better solution usually improves the common case while the old one still covers an edge. When date-prefixed filenames landed in ownwords, the assistant’s instinct was to remove the existing overwrite flag, since collisions could no longer happen by accident. That would have broken the deliberate case: a user who wants to overwrite a file on purpose. The naming convention handles accidents. The flag serves intent. The tool needs both.
So the contract says: features are usually additive, not replacements. Before removing an existing capability, answer one question: who was using this, and what do they do now? If you cannot answer it, the removal is not ready.
That is not an argument for backward compatibility, and I want to separate the two because they get confused constantly. In my own projects compatibility is not a goal; I break interfaces when the design is better for it, and “this preserves the existing behavior” carries no weight with me as a reason to choose one design over another. The clause here is narrower and it is about knowledge, not preservation. An assistant proposing a removal has almost never established who is affected by it, because that information usually is not in the codebase. Answer the question and the removal may well be right. Skip it and you are not simplifying, you are guessing with someone else’s work.
Check for precedent before inventing
The third clause: before implementing anything new, search the codebase for how the same problem is already handled, and match it. Without this instruction, the assistant starts from first principles and produces reasonable code that matches nothing around it.
An example with a visible outcome. Ask for an image in a markdown article and, left to its defaults, the assistant reaches for whatever pattern is most common in its training data, such as a linked-image construction with a trailing caption. Meanwhile every existing article in the repository uses plain image syntax with alt text and a title string. Both render. Only one belongs.
The instruction is short: check how existing files handle this case, match the existing style, and if no precedent exists, ask before choosing one. It works because it points the model’s genuine strength, reading and pattern matching, at its habitual gap, which is not looking before writing. This is the same reason the foundation-first pattern works at project scale: examples teach an AI more reliably than specifications do.
Plan first, then hold the work to the plan
Contracts govern standing behavior. For any single non-trivial change, I apply the same idea at smaller scale: agree on a plan before any code gets written.
The loop is simple. Have the assistant read the relevant code and explain how it currently works. Correct its understanding, because there will be something to correct. Write a short implementation plan together: which files change, what new states appear, how the logic flows. Then let it execute the plan step by step. When work spans sessions, the plan goes into a file, for the same reason the contract does.
The payoff mirrors the decision framework’s. Review stops being an open-ended read of unfamiliar diffs and becomes a comparison against an agreed artifact. “Does this match the plan?” is an easier question to answer well than “Is this right?”
Where the contract lives
Behavioral rules accumulate, and where each one goes matters nearly as much as writing it down. The rule I follow: context lives at the level of the work.
My global CLAUDE.md carries what applies to everything I build: the decision framework, additive thinking, the precedent rule. Each repository’s CLAUDE.md carries what is true only there: its conventions, its data format contracts, its integration points. Guidance about a single file stays with that file.
The boundary that took me longest to respect sits between a tool and its users. Because ownwords is open source, its CLAUDE.md has to serve every user, which means generic guidance only: how the tool works, and what to check or ask before operating on a target. Nothing about my machines or my file paths. My site repositories document their own structure and publishing models, and the tool’s file simply says to read the target’s context file before acting.
Mixing the levels fails in both directions. Project files bloat with personal detail no contributor can use, and personal conventions leak into repositories other people depend on. Sorted correctly, each session picks up exactly the contract that governs the work in front of it.
The review comment you get to write
These clauses leave the assistant exactly as capable as it was, and reading the code stays mandatory. What the contract adds is timing: deviation shows up at the moment one sentence corrects it, rather than later, after the shortcut has spread through everything the assistant touched. Each drift becomes a review comment instead of a debugging session.
Synthesis coding, the collaboration discipline this series describes, treats the contract as part of the job. Writing and reviewing the code is one part of that job. Setting the terms the collaboration runs under is the other. When the same thing goes wrong twice, the fix is rarely a better prompt. It is another clause in the contract.
This article is part of the synthesis coding series.
