The Infinite Patch Spiral
Every AI fix creates two more bugs because the design is wrong.
What it is
A bug appears. AI patches it. The patch introduces an edge case. AI patches the edge case. That patch breaks an adjacent flow. AI patches that. After a week the function has six special cases, each guarding against the previous patch’s side effects. The design was wrong all along; the patches are sediment.
How it happens
The AI is handed the bug and the local context. It produces a fix that satisfies the immediate symptom. Tests pass, ticket closes. But the bug was a signal that the design’s premise was off — and the patch encodes a workaround for that off-ness, making the original design even harder to see. The next bug, downstream, gets the same treatment. Each patch is locally reasonable; the trajectory isn’t.
AI is especially susceptible because it sees the diff, not the design. It optimizes for “test passes, symptom gone” — the strongest possible signal in the prompt — and it never asks the question that would actually help: should this code exist at all? The human at the keyboard doesn’t ask either, because the patch is in and the queue is full.
Why it’s dangerous
Each patch makes the next refactor harder by encoding more workarounds into the load-bearing assumption that the original design was correct. The function becomes unintelligible — you can’t tell which branches are real requirements and which are scar tissue. Eventually nobody can change anything, because nobody knows which special case is load-bearing for which downstream consumer.
The AI-era hinge: the cost of patching collapsed; the cost of re-thinking did not. So the patch path always wins on the minute-by-minute scoreboard, even when it’s losing on the week-by-week one. Pre-AI, the friction of writing the third patch sometimes triggered the “wait, what are we doing?” conversation. Post-AI, the third patch is as cheap as the first, and the conversation never happens.
How to prevent it
When the next patch in this area lands, stop and ask: are we patching, or are we papering? The signal is concrete — this fix introduces a special case for the previous fix. The new code begins by explaining why the last code didn’t work. That’s the design failing, not a bug being caught, and it’s the moment to step back and ask what the wrong assumption was, not what the next workaround should be.
Scale to stakes: an isolated patch is fine. A function whose recent commits all reference each other is a design problem, and AI can’t solve it for you because the symptom isn’t the problem. The friction signal is the moment every fix here starts with “this works around the previous fix.”
The serious team fix
Three things, reinforcing each other:
- A team habit of stopping when the patches start citing each other. When a fix has to explain why the previous fix didn’t work, the person about to ship it stops and asks the design question explicitly — in writing, in the PR, out loud at standup. Not “what’s the next fix?” but “what was the wrong assumption that produced this chain?” The trigger is friction, not a counter; the rule is named so it survives any individual’s discipline.
- An AI-leveraged hotspot scout. A slash command or agent that scans the recent commit history and surfaces files or functions that have been patched repeatedly. The AI does the diff-archeology nobody has time for; the human decides which hotspots are real signals and which are coincidence. The list becomes the input to the standing “what needs to be redesigned?” conversation.
- Integration tests that target the symptom shape, not the line. When the third patch lands, an integration test that exercises the actual user-visible flow — not the function under repair — makes it visible whether the patch fixed anything or just moved the bug. Without it, the spiral is invisible because each unit test passes against each patch in isolation. The infrastructure makes drift observable instead of inferable.
The shift is: AI can patch faster than the team can notice. The signal isn’t the bug count — it’s how many of the bugs share an address. Make the address visible, and the design conversation gets to happen.