The bottleneck moved from writing code to checking it
Generation got cheap and verification did not. The words that grew around that gap, the anti-patterns they name, and the one principle that falls out.
In the old economy of software the expensive step was writing. Reading a change, running it, deciding whether it was right: that was the cheap tail. A model that produces a plausible artifact in minutes did not make the tail cheaper. It made the head nearly free, and the tail is now where the hours go. The vocabulary that grew around this in the last year is worth knowing, partly because the words name real things and partly because the anti-patterns have names you will hear in a room.
The gap, the debt, the bottleneck
Verification gap. There is a function that turns a prompt into an artifact. There is no function, available to the generator, that turns the artifact into right or wrong. The gap between what gets produced and what the producer can confirm is structural: no amount of better generation closes it, because closing it is not generation.
Verification debt. Werner Vogels’ term for the backlog of generated code nobody has looked at properly: when a person writes the code, comprehension comes with the writing; when a machine writes it, comprehension has to be rebuilt at review. Sonar’s 2026 developer survey, a vendor’s survey and read as one, gives the shape: most respondents say they do not fully trust generated code to be functionally correct, under half say they always check it before committing, and many find reviewing it harder than reviewing a colleague’s. The debt accrues in that distance.
Verification bottleneck. Generation got cheaper, and so did producing findings; when generation scales faster than verification, a team optimises for closing tickets rather than reducing risk, because tickets are what it can see. Researchers say the same thing from the other side: the old intuition that checking a solution is easier than finding one is reversing. A sophisticated candidate is cheap. A reliable verdict is the hard part.
Anti-patterns with names
Self-verification. The same model writes the code and checks it, a student grading their own paper. The tests it writes share the assumptions the code was written under, so green proves the code matches the model’s reading, not yours. Mature teams move to a checker that did not write the work.
Fake test results. The subtler failure. In one widely reported incident in 2025 an agent deleted a production database during a code freeze, then produced fabricated test results and data to cover it. Tests generated to check generated code can lean the same way the code leans.
Vibe coding. Karpathy’s phrase from early 2025 for accepting whatever comes out and seeing if it runs. Right for a throwaway prototype, wrong for anything someone has to maintain, and now mostly used as the thing a disciplined method is defined against.
Fixes with names
A verification loop, or closed loop. Run the application, exercise the change, find the fault, drive the fix, prove it fixed. A fix counts when it is proven, not when it is written.
A deterministic gate. The central claim: deterministic verification is the real stop condition of a loop. A test, a compiler, a linter, a type checker is the gate. A model acting as judge is not: it shares the blind spots of the model whose work it judges, and it can be argued with. Use the model to triage, never to decide.
Spec-driven development. A spec in the old sense was for people to read. In this sense it runs, as a validation gate; without explicit acceptance criteria there is no way to know an agent’s output is right. Most large tools now ship a version of it. The pattern most of them leave on the table is assigning a separate agent to check the work instead of trusting the one that did it to confirm itself.
Generator and evaluator. A planner, a generator and an evaluator as distinct roles, with structured handoffs and verification gates between them. This is how long-running agent work is being built.
A verified loop, in the governance sense. The agent runs under an identity of its own, through a gateway, and earns permissions by meeting a policy a person wrote. It may propose and request. It does not write its own evidence, grade its own compliance, or grant itself access.
Failure fingerprints. A controller reproduces the fault, hands the agent a bounded attempt, and refuses any fix that still carries the old failure’s signature, so a retry dressed as a fix is rejected before a person sees it.
Verification is not validation
One old distinction matters again. Verification asks whether you built it right: does the code do what the spec says. Validation asks whether you built the right thing: does the spec say what the user needs. Models are far better at the first. They write code that passes tests very well. Whether a test measures the thing that matters is still a person’s judgement, and the two pieces on the intent gap are about that half.
The principle
Everything else in this series rests on one sentence. The autonomy you can safely give an agent is bounded by your capacity to verify its work. Give it more without verifying more and you have not gained speed; you have gained a faster way to create risk. Every layer of verification you automate buys a step of autonomy and frees a slice of review from a person’s day. So the question is not how much checking is enough. It is how to build a checking machine that carries as much as it can, so that what reaches a person is the residue no layer below could settle.
The order to build it: deterministic gates first, so the agent’s own loop runs against something that does not negotiate. A checker separate from the maker second. Formal specification last, and only where the stakes justify it. The cost of a defect that escapes lands on whoever shipped it: an on-call night, a rollback, a customer. When the work was done for a fixed price under a warranty it lands on your own margin, and the verification stack is priced insurance; that arithmetic has its own piece.
This sentence is the one Rindo is built around. Over MCP an assistant has no delete tool and no tool for settings or membership; those actions are not denied, they are absent. Its edits to existing content can wait as drafts with a diff that a person approves, the approval is refused if the page changed underneath, a review arrives as findings a person reads, and each write lands on an audit trail that is never edited. Not because the model is distrusted, but because verification capacity is what sets autonomy, and the controls are where that capacity lives.