The Regression Ratchet Has No 'Done'

A test suite only encodes the attacks someone already ran. It raises the floor and says nothing about the ceiling, so QA becomes a permanent red team.

Part 7: The Regression Ratchet Has No 'Done'THE CONSTRAINT IS THE WORKAOCYBERPART SEVENThe Regression RatchetHas No 'Done'THE REGRESSION RATCHETJUSTIN DONNARUMAAOCYBER.AI

SQLite ships with a test suite that dwarfs the thing it tests. The core library is on the order of 150,000 lines of C. The tests that guard it run to more than ninety million lines (by the project’s own accounting, roughly six hundred times as much test code as library code) with 100% MC/DC branch coverage, the same standard mandated for Level A avionics software under DO-178B. It is plausibly the most thoroughly tested software in wide use. And it is not done. Every time a new failure surfaces in the wild, a new test gets written and the suite grows again, because the suite does not certify that SQLite is correct. It records, exhaustively, every way SQLite was ever found to be wrong.

That distinction (between a record of past failures and a proof of correctness) is the thing almost every conversation about testing quietly gets wrong, and it is about to matter far more than it used to. A test suite is a monument. Each stone in it marks a specific failure that already happened, once, to someone, and got memorialized so it can never happen unnoticed again. Add all the stones you like and you have a taller monument to the past; you do not have a statement about the future. A test suite only ever encodes the attacks someone already ran; it raises the floor and says nothing about the ceiling, which is why “done” in QA was always a fiction, and AI just ends the pretense.

What follows: why a suite is a floor and never a ceiling, why AI turns testing into a permanent adversarial process rather than a phase with an end, and why the entire value of that process hinges on one thing a human has to force.

The strongest version of “a well-tested system is finished”

The counterargument has real teeth, and SQLite is its best evidence. For a bounded, closable component (a pure function, a parser, an arithmetic routine) you genuinely can approach exhaustiveness. If the input space is enumerable and the correctness predicate is total, a suite with full branch coverage really does pin the behavior down; there is a meaningful sense in which such a component is tested, and SQLite’s near-mythical reliability is the payoff for pursuing that limit harder than anyone else. So the claim “a well-tested system is finished” is not empty. For the closable core of a system, testing can asymptote toward done, and pretending otherwise ignores a real and hard-won engineering achievement.

The limit it hits is the difference between covering the code and covering the threat space. Full branch coverage means every line has run under some input; it does not mean every input has been tried, and the inputs that matter are supplied by an adversary or by reality after you ship: exactly the open-problem frontier that never closes. You can finish testing the code. You cannot finish testing against a world that keeps generating inputs you didn’t imagine, and almost every real system lives partly in that world.

The category error

The mistake is reading the test suite as a measure of correctness (a ceiling, a statement of how good the system is) when it is a record of failures, a floor, a statement of how bad it is no longer allowed to be. Those feel similar and are opposite. A green suite tells you that none of the specific ways you’ve already been burned can burn you again silently. It tells you nothing whatsoever about the ways you haven’t been burned yet, which are the only ones that can still hurt you. Every passing run is a report on history. The ceiling (the space of failures nobody has discovered) is not measured by the suite, because by definition the suite contains only what someone already found.

Which reframes what testing is in an AI world. If attacks can be generated cheaply and continuously (by fuzzers, by adversarial models, by the red-team discipline of the previous post) then testing stops being a phase you complete before shipping and becomes a permanent process that runs as long as the system is alive: keep generating attacks, keep finding the failures that were always latent, keep converting each one into a standing check. The suite ratchets. The floor rises, one memorialized failure at a time, and it never stops rising because the supply of undiscovered failures is not something you exhaust. There is no state called “done.” There is only “the floor is higher than it was last week,” forever.

And here is the hinge the whole post turns on. A ratchet is only worth building if each click generalizes. When an attack lands and you convert it to a regression test, you can memorialize the instance (this exact payload, this exact byte sequence, this exact tenant pair) or you can memorialize the class: any unsanitized input reaching the query builder, any cross-tenant read, any unbounded allocation from user input. An AI, asked to add a regression test for a bug, will overwhelmingly write the instance test, because the instance is what it was shown and the instance is what “a test for this bug” literally means. The instance test is nearly worthless: it guards one point in a space of failures and leaves the rest of the class wide open, while presenting a reassuring green check that says the bug is handled. Generalizing the finding to its class is the human’s job, and it is not clerical; it is the same act of seeing the underlying constraint that this series has been about from the first post. The machine finds the attack. The human names the class it belongs to. Skip that step and your ratchet clicks without gripping.

The Regression Ratchet Has No DoneAn ascending staircase of memorialized failure classes (SQL-injection, cross-tenant-read, unbounded-allocation, auth-bypass) each a gold step. A dashed gold floor line hugs the tops of the steps and rises one class at a time, forever. Far above, a dashed muted ceiling line marks the failures nobody has found yet: unknown and unmeasured. A side callout contrasts an instance test, which guards one point and is near-worthless, against a class test, where the ratchet grips.The Regression Ratchet Has No ‘Done’The suite only encodes failures you've already had. It raises the floor and is silent on the ceiling.CEILING — THE FAILURES NOBODY HAS FOUND YETunknown · unmeasuredSQL-injectionclassCross-tenant-readclassUnboundedallocation classAuth-bypassclass↑ FLOOR — rises one class at a time, forever.INSTANCE TESTA test for the exact payload.Guards one point — near-worthless.CLASS TESTA test for the whole failure class.The ratchet grips.AI writes the instance by default.A human must force the class.The floor keeps rising. The ceiling was never yours to reach. There is no done.aocyber.ai · DevFlow · AOSentry
The Regression Ratchet Has No Done

What this means in practice

QA becomes a standing red-team, not a gate. You staff it as an ongoing contest: automated adversarial probing runs continuously, humans decide which invariants to attack this cycle and which are worth the compute, and every landed attack is audited for one thing above all: was it generalized to its failure class, or patched as a single instance? The metric that matters is not “how many tests do we have” or “is the build green.” It is “is the floor rising in classes, or are we accumulating a museum of individual payloads that makes the board look green while the class stays open?” A thousand instance tests can hide a completely undefended class behind a wall of passing checks. That is the failure mode AI makes cheap and tempting, because generating a thousand instance tests is now nearly free, and each one feels like progress.

What this requires architecturally

The permanent-ratchet shape is most visible in security, because security never gets to declare done. A layer like AOSentry (the governance and guardrail layer inside AOCore) is architected as exactly this: every request and response inspected, continuously, with a hash-chained, tamper-evident audit trail of what was seen and what was decided, and new attack classes folded into the guardrails as they emerge. There is no version of that product that ships and retires, because the threat space it guards is open and keeps producing new inputs. The audit chain is the ratchet’s memory; the continuous inspection is the ratchet’s mechanism. The same logic applies to any quality process that faces an open frontier: the infrastructure worth building is infrastructure that assumes the work never ends and keeps a durable, auditable record of every failure class it has learned to catch, so the floor you paid to raise stays raised.

What to do

Stop treating your test suite as a scoreboard and start treating it as a ratchet with a maintenance obligation. Give up “done” as a goal for anything facing real users or real adversaries; replace it with “the floor rose this quarter, in classes.” Run adversarial testing as a permanent process rather than a pre-launch phase, and put a human audit on the one step machines get wrong: every finding generalized to its class before it enters the suite, never patched as a lone instance. Watch specifically for the green board built from a thousand instance tests, because AI makes that board cheap to build and it is the most convincing lie in the whole discipline.

A test suite is a monument to failures you’ve already had. The useful question was never whether the monument is finished; it isn’t, and it can’t be. The question is whether each new stone marks a whole class of failure or a single one, and whether you’ve made peace with the fact that you will be adding stones for as long as the system lives. The floor keeps rising. The ceiling was never yours to reach. There is no done.

← Back to Blog