Anchoring on old code
June 16, 2026
The question
In spec-driven code generation, the source of truth is a specification tree. Code is a derived artifact — generated, not authored. When a spec changes, the code is regenerated by an AI agent that receives the spec chain as context.
So, the question is: when regenerating code, should the agent also see the previously generated code?
This is not a minor implementation detail. Showing the agent its previous output is the foundation of how AI-assisted software engineering works today. The standard loop — agent sees existing code, receives a signal, improves incrementally — is the model behind every major AI coding tool. Each iteration builds on the last. In Confinement, we described feeding the existing artifact as the methodology's one deliberate exception to strict chain-only generation. Across multiple projects using Code from Spec, we have explored both approaches and found that the answer is less straightforward than it seems.
What goes well
There are real benefits to showing the agent its previous output.
The first is stability. The agent compares the spec against the existing code and changes only what the spec requires. Helper function names, variable naming style, code organization — all remain stable between generations. Diffs are small and reflect only the spec change. When only the artifact tag hash needs updating (an upstream change cascaded but the spec for this node did not change), the agent recognizes there is nothing to change and produces the same file with a new hash. This is the common case in cascade-only regenerations, and it works well. Small diffs also make human review practical — most teams are not yet ready to trust AI-generated code without reading it, and reviewing a targeted change is fundamentally different from re-reading an entire file.
The second is continuous improvement. When the agent sees its previous output, each generation can improve on the last — better naming, simpler structure, small optimizations, bug fixes — without rewriting everything. This is the incremental loop that defines AI-assisted development today: start from the current state, make it better. Removing the existing artifact means every generation starts from zero, with no memory of what worked before.
The third is codebase maturity. Code that has been running in production accumulates value that is not captured in the spec: it has survived real traffic, edge cases, and operational incidents. Every line that remains unchanged is a line that does not need to be re-tested, re-reviewed, or re-validated. Regenerating from scratch discards that accumulated confidence and reopens the entire surface area for new bugs — even if the new code is correct with respect to the spec, it has no operational history.
What goes wrong
When the agent receives both the spec chain and the existing artifact, it might anchor on the code. We have observed this across projects and models: when the spec changes but the existing code reflects the old spec, the agent sometimes preserves what it sees rather than follow what the spec now says. Names that were renamed in the spec keep their old form. Values that were corrected stay at their previous value. Patterns that were replaced by simpler alternatives survive through workarounds. When this happens, the agent does not disagree with the spec — it simply does not process the change.
This does not happen every time. But when it does, the pattern is consistent: the existing artifact is present and the spec change is ignored. Removing the existing artifact and regenerating from scratch produces correct code. We cannot say how often it occurs — only that we have encountered it repeatedly, and that the remedy is always the same.
The exact mechanism is unclear, but three hypotheses fit what we observe.
The first is inverted reasoning. The generation prompt tells the agent that the spec chain is authoritative and the existing artifact is a starting point. But the agent may reverse the direction of analysis: instead of reading the spec and generating code, it reads the existing code and checks whether the spec contradicts it. The code becomes the premise; the spec becomes the delta. This inversion produces correct results when the spec has not changed — which is the common case — but fails silently when the spec has changed and the agent, reasoning from the code, does not notice the difference.
The second is positional. In the current chain assembly, the existing artifact comes after the spec chain — it is the last thing the agent sees before generating. Recency bias in language models is well documented: content that appears later in the context tends to carry more weight. More than that, language models learn from conversations, and conversations have a direction — what comes later corrects, refines, or supersedes what came before. When the code appears after the spec, the model may interpret it not as the object to be rewritten, but as the most recent resolution of the conversation. The spec defines intent, but the code has the last word. If the order were reversed — existing artifact first, spec chain last — the spec would be the most recent signal, and the agent might give it more weight. This hypothesis is interesting because, unlike the other two, it suggests a concrete and testable mitigation that does not change the methodology — only the order of presentation.
The third may be the most important. Every spec has ambiguities — small gaps where the spec does not prescribe a specific choice and the agent must use judgment. When the existing artifact is present, those ambiguities are already resolved: the previous generation made a choice, and the code embodies it. The agent does not need to decide — the decision is already there. This looks like good behavior: the agent is using available evidence to resolve uncertainty. The problem is that the previous decision may have been made under a different spec, or may have been wrong to begin with. The old code does not just anchor the agent on old behavior — it silently eliminates the ambiguity that would have forced the agent to re-read the spec and make a fresh judgment.
Anchoring is hard to detect
When the instruction is to use the existing artifact as a starting point and change only what is needed, the intention is stability. In practice, "only the changes needed" may become "change as little as possible." When anchoring occurs, the spec change is not applied, but the artifact tag hash is updated. The staleness detection system reports "up to date." The code compiles. Many tests pass. The change is simply absent.
This matters because one of the goals of spec-driven generation is to not have to read the generated code. The spec defines behavior, the agent generates code, tests validate the result. This model depends on failures being detectable — and silent non-changes are the hardest failures to detect.
Compare the two failure modes. Generation from scratch may produce code that diverges from the spec — the agent misunderstands something and generates incorrect code. But it tried. The error manifests as a failing test: "expected X, got Y." You trace back to the spec, find the ambiguity, fix it.
Generation with an existing artifact may produce code that silently preserves old behavior. When anchoring happens, the agent does not misunderstand the spec — it never processes the change. Debugging "implemented wrong" means following the logic until it diverges. Debugging "did not implement" means first discovering that the change is absent — which requires the exact right test. And if the test was also generated from a spec that anchored on old patterns, even the test may not catch it.
Why we want to keep the existing artifact
Generation from scratch would eliminate anchoring entirely. But it would also give up everything described in "What goes well": stability, continuous improvement, codebase maturity, and the accumulated confidence that eventually makes human review unnecessary. These are not conveniences — they are structural requirements of a methodology that treats code as a derived artifact. If every generation produces different code, someone has to read it every time. The codebase never matures. The goal of not having to review generated code becomes unreachable.
There is another reason. Not all generation failures are anchoring failures. Sometimes the spec is correct and the agent simply generates wrong code — a wrong function call, a misread interface, a subtle logic error. Regenerating from scratch may produce the same error again, or a different one; the agent has no memory of what went wrong. But regenerating with the existing artifact plus a directional signal — the compilation error, the failing test, a description of what is wrong — lets the agent converge toward the correct output. Each iteration gets closer. This is the standard AI-assisted development loop, and it only works if the agent can see what it produced last time.
Generation from scratch has no convergence mechanism. It is a fresh roll of the dice every time. Generation with the existing artifact, given the right feedback, converges.
Where we are
The ideal is to generate with the existing artifact and eliminate anchoring. The benefits of keeping the artifact in context are clear; the challenge is making it safe.
This points to a set of problems worth solving: how to make the agent reliably prioritize the spec over the existing code; whether changing the order of presentation — spec after code, not before — reduces anchoring; and how to provide the agent with an explicit delta of what changed in the spec, so it does not have to discover the difference on its own.
These are open problems. But the direction is clear: we do not want to choose between stability and correctness. We want both.
Code from Spec