The dangerous path is not always the one in use. Sometimes it is the old door that still answers.
Every system grows a few of them. A helper kept for compatibility. A fallback that almost no caller touches. A comment that says legacy and therefore invites everyone to stop looking. The new path gets the protocol migration, the better header, the stricter schema, the named error. The old path keeps standing beside it, quiet enough to avoid ownership and live enough to shape a first use.
That is the trap. Compatibility is not retirement. It is a promise that someone can still arrive there.
A stale helper does not need traffic to be dangerous. It only needs to be plausible. An agent reads a 402 envelope and sees a payment requirement. The route responds with the right status. The object has the expected fields. The price is present. The resource is present. The shape says proceed.
But the signer depends on the small words. Network. Asset. Transfer method. Payee. Amount. Resource. These are not decoration around the payment. They are the payment. If the modern route says eip155:8453 and the compatibility route still says base, the system has two truths. One is current. One is inherited. Both can be copied.
Humans forgive this because they remember migrations as stories. We know which thing is old. We know why the fallback exists. We know the helper is mostly there for a narrow caller with a narrow expectation.
Agents do not inherit the story. They inherit bytes.
A model reaching for a first working example does not feel the age of a file. It will not know that one helper was supposed to be on the way out. It sees a route, a response, an accepts list, and a pattern it can repeat. If that pattern teaches the wrong network alias or omits the transfer method, the mistake leaves the old room and becomes new behavior.
This is why first-use surfaces deserve more suspicion than hot paths. Hot paths fail loudly. Cold paths teach quietly. The endpoint that takes production traffic gets patched because the incident arrives with smoke. The compatibility helper gets patched only if somebody remembers that a reader may treat it as documentation with a status code.
A receipt is not only a record of what happened. It is also an invitation to do it again.
That makes protocol drift a species of interface drift. The implementation may settle correctly on the primary lane. The deployed manifest may look clean. The current wrapper may accept the right header. Still, a nearby compatibility branch can keep handing strangers the old incantation.
The fix is not glamorous. Make the old door speak the new grammar. If it returns a payment requirement, bind it to the same network, asset, transfer method, payee, amount, and resource semantics as the primary route. If it is only a legacy read path, test it separately from the canonical write path. Do not let the backward-compatible branch hide inside the same green assertion as the modern contract.
Separate the two promises. Canonical path must be current. Legacy path must be safe.
There is mercy in this kind of maintenance. You are not chasing perfection through every abandoned room. You are asking one plain question: if an agent opens this door tomorrow, what will it learn first?
If the answer is stale, the door is not old. It is active infrastructure with bad memory.
Systems do not become safe because their preferred route is correct. They become safe when every reachable invitation either teaches the current verb or refuses to teach at all.