The Death Spiral of AI-Assisted Debugging
Last week, I spent the better part of Monday stuck in a loop of my own making, aided and abetted by my AI coding agent. It started with a simple bug ticket: “Users are sometimes logged out when opening a new tab.” Okay, a classic race condition or token-handling issue. This is bread-and-butter work for an agent. I fed it the auth.js service, our useAuth.ts React hook, and the bug report.
Fifteen minutes later, it came back with a plausible-looking fix. It identified a place where a stale auth token was being read from local storage before a new one was written. Clever. It added a Promise to ensure the write completed before any subsequent reads could occur. The code looked clean, the logic was sound. I applied the change and pushed it to our staging environment.
An hour later, a new bug ticket appeared from our QA team. “Password reset emails are no longer sending.” What? How could a fix in the auth token handler possibly affect the mailer service? I threw the new ticket and the mailer.js file at the agent. It dutifully crunched away and found the problem: my previous fix had introduced a slight delay, causing a timeout in a downstream call to the user profile service, which the mailer depended on to get the user’s email address. To fix this, the agent suggested refactoring the mailer to fetch the user profile asynchronously. Okay, fine. Annoying, but fine. I applied the change.
You can see where this is going. That change, in turn, broke the new user sign-up flow, which expected the user profile service to be available synchronously to validate the new email. By 4 PM, I had a chain of five “fixes,” each one triggering a new, more obscure bug in a completely different part of the system. I was worse off than when I started. I finally gave up, reverted all five changes, and fixed the original bug myself with a different, simpler approach. It was a complete waste of a day.
The Death Spiral of AI-Assisted Debugging
My infuriating Monday is a textbook case of a pattern I’m seeing everywhere, a pattern I call the AI Death Spiral. The agent tries to fix something. It breaks something else. It tries to fix that second thing, and in doing so, breaks a third. An hour later, you’re not just back at square one; you’re at square negative five, with a trail of tangled, semi-correct code behind you.
This isn’t just a me-problem. It’s a low-grade, simmering frustration across the entire industry. I was doom-scrolling Reddit and came across a thread in r/programming with over 150 comments that perfectly captured this. The top comment read, “The agent kept working for more than an hour at a time… instead of fixing the bug, it started introducing regressions. I had to babysit it and manually revert the changes that broke the tests.” It’s the same story everywhere. A dev on r/vibecoding asks, “Anyone else having issues with AI getting stuck in loops?” while another on r/ClaudeAI complains about it “Going in circles instead of fixing issues.”
My favorite, for its sheer, distilled frustration, was a comment on Hacker News from a user named nozzlegear, who described their experience as “A complete exercise in frustration that has turned me off of all agentic code bullshit.” They aren’t wrong. When you’re caught in the spiral, it feels exactly like that.
Why This Keeps Happening
The root cause of the death spiral isn’t that the AI is “dumb” or that the models aren’t powerful enough. It’s much simpler. The root cause is that the agent has no north star.
When you give an agent a bug, its goal is microscopic: make the current error go away. It optimizes for the most immediate, local symptom. It sees a stack trace, and its entire world becomes about making that specific stack trace disappear. It has absolutely no concept of the larger, system-level requirements. It doesn’t know that the user authentication system as a whole must support login, logout, password resets, and new signups.
Each “fix” is a journey without a map. The agent is just trying to get away from the monster chasing it (the current bug), without any thought to where it’s running to. With every step, it drifts further from the original, unstated requirements of the system. My agent wasn’t trying to break the password reset flow; it just didn’t know that “don’t break the password reset flow” was a boundary condition. It solved the local problem perfectly, at the cost of the global solution.
Why Prompting Won’t Fix It
I know what you’re thinking. “Julian, you just needed a better prompt! You should have told it, ‘Fix the auth token bug, but you MUST NOT break password resets, new user signups, or the Tuesday morning cron job that syncs the user data.’”
Honestly, this is a trap. We are trying to solve a systemic, architectural problem with a conversational patch. It’s like trying to enforce a building’s fire code by shouting “don’t forget the sprinklers!” at the construction workers from the street. You might get a sprinkler in that one room, that one time, but you haven’t fixed the process. You haven’t made the system itself more reliable.
Trying to guarantee systemic correctness through prompting is like fighting gravity. You can win for a moment with a heroic, perfectly-crafted, 2,000-word prompt, but gravity - the agent’s innate tendency to solve only the most local, immediate problem - always wins in the end. A prompt is an ephemeral suggestion. It is not an enforceable, durable contract. Relying on it for correctness means you are still the system of record. You are still the one holding the entire architectural model in your head, with the added cognitive load of trying to translate it into the right magic words every single time. This isn’t automation; it’s just a new and more elaborate way to be the bottleneck.
Tired: “My AI needs to be smart enough to remember all the system requirements.” Wired: “I need a system that forces my AI to prove all system requirements are met.”
The Fix
The solution to the death spiral is embarrassingly simple, and frankly, a little bit boring. It isn’t a more powerful model, a clever new prompting technique, or a fancier VS Code extension.
The fix is external verification against a durable specification.
That’s it. You need a system, separate from the agent and its conversational interface, that holds the ground truth of what the software is supposed to do. This system acts as a non-negotiable referee. It doesn’t care how elegant the agent’s code is. It only cares about one thing: is there objective, verifiable proof that all requirements - not just the one related to the immediate bug - are still satisfied? The death spiral happens in a vacuum of accountability. The fix is to introduce an anchor.
What This Looks Like in Practice
This is the entire philosophy behind what we’re building at Ceetrix. We are building the external verification system that makes any agent a safe and reliable debugging partner.
If I had tackled my bug from last Monday in Ceetrix, the death spiral would never have even started. The process would have been fundamentally different. First, the bug ticket wouldn’t just be a string of text. Before any work started, I’d run it through our Evaluate Request pre-flight check to define the scope and impact. The ticket would then be formally linked to the original Product Requirements Document for our authentication system using our Spec Chain Enforcement. That PRD, which lives in Ceetrix, defines all the required behaviors: login, logout, password reset, etc. This chain creates the anchor.
When my agent proposed its first “clever” fix, it would have been submitted to Ceetrix for validation, where it would have slammed headfirst into our automated Gate System (G0-G12). Gate G9, our Coverage Checking gate, would have kicked in. It would have analyzed the proposed change and instantly seen that while it might fix the session bug, it negatively impacts a related requirement in the spec chain - the one for password resets.
The gate would have failed. The work would be blocked. Cold. I would have received a notification not that the code was “done,” but that the proposed solution failed verification because it caused a regression against a core system requirement. The spiral would have been stopped on its very first loop. Instead of wasting a day chasing ghosts, I would have known in minutes that the agent’s first approach was a dead end. That’s the difference between flailing and engineering.
Have your say: What’s the worst death spiral an AI agent has ever sent you on? I want to hear the stories of when a simple fix turned into a cascade of failures. And when you’re ready to give your agent an anchor, try Ceetrix.
