Your AI Coding Assistant Has No Memory of Why
Comprehension Debt
A pull request lands. Two approvals, tests green, CI blue. It ships on a Tuesday. Three weeks later thereās an incident. Somebody opens the file and finds a branch nobody remembers discussing. It handles a rare case, and handles it wrong. You ask the author what itās for. They squint at it. They wrote it. They canāt tell you why.
This isnāt a story about a bad engineer. Every engineer I know has been that author, including me. The code I understand least in anything I ship is the code I generated fastest, and it is almost always the code furthest from the domain Iām strongest in. On my home turf a bad suggestion smells wrong immediately. Two directories over, it just looks like code. So we get faster and we understand less, and the two facts donāt feel connected because they show up in different places: velocity on a dashboard, confusion in a postmortem, six weeks apart. Theyāre connected.
The Thing We Donāt Have a Word For
We have a word for code we understood and shipped anyway: technical debt. Itās a good word precisely because it names a decision: someone weighed the shortcut, took it, and, in the good case, wrote down what it would cost to unwind. Debt implies a lender, a balance, and a plan. You can put it on a roadmap. You can argue about it with a straight face.
What we donāt have a word for is code that entered the system without ever passing through anyoneās understanding. Call it comprehension debt. Itās the gap between what your codebase does and what your team can explain. The difference that matters: technical debt is a liability you chose, and comprehension debt is a liability you acquired. Nobody decided. Thereās no ticket, no comment, no // TODO: this is a hack because. The commit looks exactly like the commits around it.
Thatās the whole problem: it is invisible at the moment itās created and expensive at the moment itās discovered, and those two moments are far enough apart that nobody connects them. Itās also invisible to every metric on your squadās dashboard. Velocity canāt see it. Deployment frequency canāt see it. Coverage especially canāt see it - generated tests will happily assert the behavior of generated code, and the pair will be wrong together, forever, in perfect agreement. If your dashboard measured comprehension debt, youād have noticed it accumulating a year ago. It doesnāt, so youāll notice it during an incident. Nobodyās bonus depends on comprehension.
The Mechanism
Thatās the vocabulary. Hereās the mechanism. AI didnāt make the code worse. It deleted the steps.
The common version of this complaint is that AI writes bad code. Thatās wrong, and being wrong makes it useless as an argument. You say āAI writes bad code,ā someone shows you a clean, idiomatic, well-factored function, and the conversation is over. You lost, and you were right about something, but not that.
The vendors say superpowers. The critics say slop. Both are talking about the code, and the code was never the problem.
Hereās what happened. Building software used to be a sequence. Not a waterfall, but a sequence with real steps in it. You figured out the problem. You argued about what ādoneā meant. You sketched a design and someone senior poked holes in it. You wrote down what youād accept. Then you built it. Some of those steps took ten minutes and lived on a whiteboard. Fine. They still happened, and each one left something behind: a decision, a constraint, a written-down definition of done. The residue of those steps was understanding, distributed across the people who took them.
AI collapsed that sequence into one step. Prompt in, implementation out. We have a name for the one-step version now: vibe coding. Itās an honest name, which I appreciate - it tells you exactly how much of the process survived. And notice what got skipped. Not the coding. The coding is the one part that got faster. What got skipped is everything upstream of it: the problem framing, the design argument, the acceptance criteria. Those were never in the code, so a model trained on code never learned they existed.
You are asking for the output of step five while providing the input to step one, and the model does not object. It cannot know that steps two through four are missing. It has never objected to anything. It has no memory of why. It was never shown a why. It was shown a hundred million whats.
The insidious part is the asymmetry of the evidence. A skipped design conversation produces no artifact. There is no file in the repo called the-argument-we-didnt-have.md. So the absence leaves no trace inside the codebase: the diff looks the same whether the design was debated for an hour or never considered at all. The only difference is in someoneās head, and if the step was skipped, it isnāt in anyoneās head either.
āJust Be More Disciplinedā Is Not a Control
The obvious answer is that we should think before we type. Everybody already knows this. I know it. Early in my career I sat in a code review where someone made me defend a design for the better part of an hour, and I remember that design today. I remember very little else from that job. I still skip the step. Not always. But more than I did two years ago, and the reason is structural.
The environment offers no resistance. Skipping the design conversation has no immediate cost and an immediate benefit: the PR is up, the ticket moves, the dashboard is green, and the cost arrives in six weeks disguised as an unrelated incident. Any behavior with an instant reward and a deferred, misattributed penalty will win against your intentions. Thatās not a moral failure. Itās a feedback loop, and you donāt fix feedback loops with willpower. You fix them by changing what the environment permits. Nobody measuring you has ever asked whether you understood it. They ask how many.
Thatās the only interesting question here: what would it look like if the steps couldnāt be skipped?
Waves
Iām part of the team thatās been building an answer, so read the rest with that bias in mind: I helped build the tool, and Iām the person least qualified to tell you it works. The tool is called nWave. It runs inside Claude Code - same harness you already have, no new thing to adopt. The idea is simple: put the sequence back, name the steps, and make each one produce an artifact you have to look at.
Seven waves:
- Discover the problem.
- Diverge on approaches.
- Discuss until there are user stories and acceptance criteria.
- Design the architecture.
- Plan the delivery path.
- Distill the acceptance tests.
- Deliver the code, test-first.
Only the last two are mandatory: every feature ends with acceptance tests and test-driven code, and the five upstream waves are optional, because a bug fix doesnāt need market discovery and pretending otherwise is how methodologies die. And when you genuinely donāt know whether a mechanism will work, you timebox a probe and find out before you design around it. The answer is a finding, which is an artifact like any other.
Three things about this matter more than the wave list, which is the least interesting part:
- Each wave leaves an artifact. This is the actual mechanism. The reason a skipped step is invisible is that it produces nothing; the fix is to make every step produce something. A user story. A design document. A Given-When-Then scenario. Now the absence is visible, because the file is either there or it isnāt, and you can review a file.
- The gates are deterministic. Not an LLM grading an LLM, which is a lovely way to generate confident nonsense at scale. The checks are hooks: code that inspects the artifacts and blocks or doesnāt. A test that fails for the wrong reason doesnāt count as red. A commit without a test doesnāt pass. The machineās opinion is not consulted.
- Nothing runs unsupervised end to end. Each wave stops and hands you its output. You approve, or you donāt. It is, by design, slightly annoying.
Where the Human Goes
Here is the objection Iād raise if I were reading this, and Iād raise it hard: you just described a system that orchestrates AI agents through the entire lifecycle, and youāre pitching it as a defense against over-delegating to AI. That sounds like an arsonist selling smoke detectors.
The distinction Iād argue for is where the human is required versus merely permitted. Today youāre permitted to review AI output. Youāre permitted to think about the design first. Permission is not a control. What actually happens is that permission decays into habit, and habit decays toward whatever is cheapest. The waves exist to force decisions to surface at the points where theyāre cheap to make and expensive to skip: what are we building, what does done mean, what shape should this take, what will we accept. Those are judgment calls, and nothing in the system can make them for you; the AI can draft, propose, argue, and generate, but it cannot proceed past a step you havenāt ratified. Thatās the whole design. Not autonomy. Checkpoints.
Whether it delivers on that is a separate question, and one I canāt answer for you from inside the tool I helped build.
What It Costs
Itās slower. Per feature, unavoidably slower, and anyone who tells you their methodology is free is selling you something. Youāre paying, in wall-clock time and in tokens, for steps you were previously skipping for free. Thatās the entire trade: you move the cost from the incident, where itās expensive and unpredictable and hits you at 2am, to the design conversation, where itās cheap and scheduled.
This is a good trade in exactly the situations where the incident is expensive. Which means itās the wrong tool for a lot of work. A throwaway script, a personal project where you are the entire audience, anything nobody will ever have to explain: put the ceremony down and go fast. Thereās no comprehension debt if thereās nothing to comprehend.
It earns its cost where āship fast and fix laterā runs into something that doesnāt accept ālaterā as an answer. Payment rails. Anything with a compliance audit at the end of it. Anything where the edge case you didnāt think about is somebodyās money, or worse. If you work in one of those places you already know the feeling of shipping something you canāt fully explain, and you already know it doesnāt get better on its own.
The Ask
Iām not going to tell you to adopt this. Youāve been doing this for years and you donāt need a framework from a stranger on the internet. There are already several.
What Iād actually like is for you to open the repo and tell me where the methodology is wrong. The next post gets concrete: what a single wave looks like when you run it, and why the acceptance tests come from a different agent than the implementation.
sh -c "$(curl -fsSL https://raw.githubusercontent.com/nWave-ai/nWave/main/scripts/install/install.sh)"
Yes, thatās a curl piped into a shell, and if your instinct is to read the script first rather than run it, good: thatās the entire thesis of this post applied to me. Itās here. It prefers uv, falls back to pipx, installs the CLI, then runs the installer. If youād rather not pipe anything into a shell, pip install nwave-ai && nwave-ai install reaches the same place. Reach for uv if you can: itās the recommended path, and pip and pipx are supported fallbacks rather than equals.
The waves are Markdown. The gates are Python. All of it is readable in an evening, which is deliberate: a tool that asks you to trust it more than you can inspect it has the same problem as the AI itās trying to discipline.
In the meantime, one question worth carrying into your next PR review: can the author explain why? If the answer is no, the code shipped anyway. It always does. Thatās the part that should bother you.
Comments
No comments yet. Start the discussion.