Why adding a feature breaks what was working
The last time I watched a working feature break for no reason, I had done it to myself, in a single prompt. I asked an agent to refactor a module, and while it was in there, to add some timing instrumentation so I could finally see how slow the thing really was. Two requests, one delegation. It came back, the diff looked reasonable, I took it. A path that had worked the day before stopped working that afternoon.
the prompt that changed two things at once
The two requests felt like one errand. The refactor was structural: it reshaped how the module did its work, moving logic around so it would be easier to extend later. The instrumentation was a measurement add-on: wrap a few calls, record how long they took, print it somewhere I could read. Both were reasonable on their own. Bundling them felt efficient. One trip, one review, one commit, done.
The efficiency was a trap, and the trap sprung the moment something broke. Two things had changed in that diff, and the break could have come from either one. I had handed myself a problem with two unknowns and no way to hold one still while I tested the other.
four rounds of debugging the wrong question
I tried to fix it in place, which is the instinct, and the instinct was wrong. Round one, I assumed the instrumentation was wrapping a call incorrectly and changing its timing or its return. Round two, I assumed the refactor had moved a dependency out from under something that still expected it. Round three, I went looking for an interaction between the two. Round four, I tried to peel the instrumentation back out on its own, except it was threaded through the same lines the refactor had touched, so there was no clean seam to cut along.
Every round failed for the same reason. I was debugging the interaction of two variables while telling myself it was one. The move that finally worked was the one I should have started with: throw the whole change away, return to the last known-good state, and redo it as two separate steps. Refactor first. Confirm the broken path worked again. Then add the instrumentation on top of a thing I already trusted. The break was in the refactor. Alone, it would have taken five minutes to find, because there would have been exactly one suspect. This is why I no longer bundle instrumentation, or any measurement add-on, with a structural change. The bundle is what costs you the bisect.
this is the same bug you hit when you add a feature
That was my own self-inflicted version. The one most vibe coders live with is the same disease at a different scale, and it has a name now: the spaghetti point. You add feature number eleven and feature number nine breaks. You ask the agent to fix a bug and a different, unrelated thing stops working. It reads like your vibe coded project turned on you.
Most of the time, it is the bundle problem again. You re-prompt a working module: add this, and while you are here, also handle that. The agent does not touch only the lines you pointed at. It reads the whole prompt, optimizes for the whole prompt, and rewrites whatever it decided was in scope, including code you never asked it to change. That is the mechanism behind why AI keeps changing your code. Now two or three things have moved in a single step, and when an unrelated path falls over you cannot bisect it, because there is no single change to bisect against. The agent has no memory of feature nine's contract. It sees this prompt, this file, right now. The blast radius is whatever it quietly decided to touch, and you find the edges of it by getting hurt.
isolate the change before you integrate it
The discipline that prevents the spaghetti point is change isolation, and it is the cheapest insurance a vibe coder can buy. One delegation, one concern. A feature is one change. A refactor is a different change. Instrumentation is a third. Each one goes in by itself, against a baseline you have already confirmed still works, so that when something breaks the suspect list has exactly one name on it. The cost of skipping this is not the break. It is the un-bisectable break, the one that eats four rounds instead of five minutes.
This has to be deliberate because the model will not supply it for you. The agent optimizes each prompt in isolation and holds no standing commitment to the architecture between calls. It is not keeping feature nine safe while it builds feature eleven; it is not aware feature nine exists unless this prompt put it there. So the thing that protects the old contract while you write the new code cannot live inside the prompt. It lives outside the prompt, in a spec that writes the invariants down where the next change has to respect them, and in the plain habit of moving one variable at a time. When vibe coding creates brittleness debt is the slow-motion version of the same failure: change after change interacting with context that only ever existed in a prompt that is now gone.
what to actually do
The practices are small and they compound:
One concern per delegation. If you catch yourself typing "also," stop, and make the "also" its own request. The word "also" is where most blast radius gets bought.
Keep a known-good baseline. Commit or snapshot the working state before each change, so a rollback is one command instead of an archaeology dig. Half the pain of a bad change is not having a clean place to retreat to.
Read the diff before you accept it. The break you cannot afford is the line you did not ask for. If the agent edited a file outside the concern you handed it, that is not a bonus, that is the warning.
Never bundle a refactor or instrumentation with a feature. Land the structural change, confirm the old paths still pass, then build the new thing on top of something you already trust.
Let the spec carry the invariants. Feature eleven cannot silently violate feature nine if feature nine's contract is written down somewhere the next change is forced to read. This is the whole reason the spec sits outside the prompt instead of inside it, and it is the same backbone behind how to stop AI from breaking your project.
If you are a vibe coder and every new feature seems to knock over an old one, that is not bad luck and it is not the AI being dumb. It is missing change isolation, and it is fixable. If you want a second set of eyes on it, /work-with-us: send me the build and the last handful of breaks, and I can scope a pass that finds where the blast radius is leaking, or a spec-first rebuild that writes the contracts down so the next feature cannot quietly take out the last one. Work with VibeKoded.
Adding a feature is supposed to be additive. When it stops being additive, the fix is almost never a smarter prompt. It is changing one thing at a time, so that when something breaks, the change that broke it is the only one left standing in the room.