DEV Community

Cover image for A quorum costume: why agent verification needs fault injection

A quorum costume: why agent verification needs fault injection

Mike Czerwinski on June 23, 2026

Yesterday I watched my AI partner miss the same source-of-truth problem three times in a row, in three different forms, across three different revi...
Collapse
 
sarracin0 profile image
Raffaele Zarrelli

This is the orthogonal axis I had not drawn out, and the quorum-costume line earns the whole post. The part that stays with me is your opening: you caught all three only because you were outside the loop with access the reviewers did not have. That is the tell. In practice the cheapest externally-authored verifier is the human operator's out-of-band glance, and the reason fault injection matters is that it tells you which of those human checks you are actually allowed to retire. You only earn the right to pull a person off a path once you have perturbed that path and watched the automated check flinch. Until then the operator is load-bearing, not optional.

Carried onto the file layer this gets uncomfortable in a good way. The analog of your synthetic-bad memory entry is planting a contradicted decision in the operating files and seeing whether the next session's start-of-read catches it against the external anchor or just quotes it with confidence. The Memory Update habit is itself a path, so by your own harness-rot point it has to be perturbed on a cadence, not trusted because it ran. We treat the decisions-and-state files as the thing to poke, not scripture: cowork-os if anyone wants the operating-layer side of what you referenced.

One question on the decay section: does the re-perturbation cadence apply to the operator path too? The harness rots, but so does the human who goes green by habit. Do you ever plant a fault specifically to check that you still catch it, or is the out-of-band reviewer the one path you implicitly assume stays independent?

Collapse
 
jugeni profile image
Mike Czerwinski

Yes — the operator path has to be perturbed too. Otherwise “human in the loop” becomes the last untested dependency wearing an independence badge.

I’d separate two tests:

Detection test: plant a bounded contradiction and measure whether the operator catches it without being prompted toward the fault.
Habit test: vary the location, wording, and timing so the operator cannot pass by memorizing the ceremony.
That creates an uncomfortable but useful rule: the human is load-bearing only until both the automated verifier and the operator path have independently demonstrated that they flinch.

The verdict probably needs two phases:

verifier_status: live | stale | dead
decision_resolution: pass | fail | unknown

A live operator who misses the planted fault is not a dead verifier. They are a live verifier returning fail. That distinction matters because remediation differs: repair the mechanism when it is dead; retrain or rotate the review path when it is alive but habituated.

So no, I would not exempt the out-of-band reviewer. The moment we implicitly assume the human stays independent, we have built the next quorum costume — this time with a pulse.

Collapse
 
sarracin0 profile image
Raffaele Zarrelli

Agreed, and the habit test is the one you cannot run for free. A clean run with no planted fault tells you nothing about whether the operator is still checking or just performing the ceremony, so their pass rate looks best exactly while they habituate. You only ever catch a live verifier returning fail on the runs where you injected.

That makes the injection cadence itself a verifier of the operator, and by your own rule it has a liveness too. Inject too rarely and your read on whether the human is still independent goes stale without ever flipping to dead, so the cadence that tests the reviewer becomes the last untested dependency, the quorum costume one level up.

On the file layer the cheapest place to perturb is the Memory Update routine itself, not the data. If the closing prompt is identical every session you have trained the ceremony, so you vary what it asks for and occasionally surface a planted contradiction from a prior entry to see whether the read catches it against the commit or recites it with confidence.

Do you set that cadence as a fixed interval, or tie it to operator throughput so the perturbation scales with how many clean passes they have banked since the last real flinch?

Thread Thread
 
jugeni profile image
Mike Czerwinski

Yes — and the habit test paradox is exactly where the externally-authored constraint stops being a preference and becomes the only thing that holds.

If the operator owns the cadence, the cadence inherits whatever drift the operator already has. Fixed interval in their head, conscientious self-set, generous schedule for busy weeks — all of those route the perturbation around the moment when the operator was actually checking out. The cadence has to live outside the operator's planning window, in a place they cannot postpone or pre-rationalize, or it's a vote on themselves.

That's where I'd land on your question: hybrid, with the external piece doing the load-bearing work.

Fixed external floor. A cadence-of-record that fires at minimum rate regardless of throughput, scheduled in something the operator does not edit — cron, queue, second-party scheduler. That's the liveness guarantee. Skip this and the recursive verifier never gets a stale-flag of its own.
Throughput-scaled ceiling. On top of that, additional injections proportional to clean passes banked since the last real flinch. That's the term that targets habituation specifically — the failure mode is "operator has banked confidence and stopped looking," so the perturbation density rises with the confidence bank.
Jitter within window. Both floor and ceiling randomized within a window so the timing itself cannot be modeled. Predictable perturbation gets metabolized into the ceremony.
On the Memory Update routine point — agreed, and one step sharper: the closing prompt should occasionally ask the operator to defend a fact that the system has silently retracted in a prior commit. An operator who confidently restates it is reading their cached belief, not the file. An operator who flinches and asks for the source is reading the commit. The flinch is the verifier signal; the confident recital is the costume.

Which leaves the question I keep landing back on: who authors the change to the cadence policy itself? If the operator can re-tune their own perturbation schedule under "we've been clean for three weeks," that's the same costume one floor up again. External authorship has to be load-bearing all the way through, or the recursion never bottoms out

Thread Thread
 
sarracin0 profile image
Raffaele Zarrelli

The recursion does not bottom out in a more external authority. That is turtles: someone writes the first cron, and a more external scheduler just moves the costume up a floor, which is the regress you keep landing on.

It bottoms out in an asymmetry, not an authority. Tightening the cadence stays free and instant; loosening it costs a written reason, a delay, and a second reader. The only move the operator gets for free and in the moment is more scrutiny, never less, and an asymmetry needs no higher floor to enforce it, which is why it can be the base case.

The dangerous direction is always "we have been clean for three weeks, let me relax." So you make that exact move the expensive, logged, addressed to someone else one. The loosening leaves a fingerprint: on this date, after N clean passes, I cut my own check rate. That is the confidence bank failure made anti deniable instead of prevented.

Your retracted fact trick applies to the policy itself. The close occasionally asks the operator to defend why the cadence sits where it does. Confident recital of "because we have been clean" is the cached belief; going to look at when and why it last moved is reading the commit. In file terms: cadence is a file, tightening a fast edit, loosening a reviewed diff with a reason and a cool down.

Honest limit, this does not remove the operator, it makes the one costume move slow and visible, and a patient operator can still batch loosen during a real calm. So my question back: does a direction asymmetry survive a patient adversary, or does every scheme reduce to the operator wanting to be caught, with the real job being to keep that want cheap to act on?

Thread Thread
 
jugeni profile image
Mike Czerwinski

The asymmetry-vs-authority correction is the right one — and the right kind of cut. "External authorship all the way through" was me reaching for a more external floor when the floor isn't a floor at all, it's a direction. I'll retire it. Loosening-as-expensive is what was actually doing the work in my mental model; I was just calling it the wrong thing.

On the patient-adversary question: I think the asymmetry survives, but in a different mode than it operates in the casual-drift case, and the gap between those two modes is most of the answer.

In the casual-drift case — honest operator, busy week, "we've been clean, let me relax" — the asymmetry catches in near-real-time. The loosening happens, the fingerprint lands, the reviewer sees it on the next pass, the slip becomes visible inside one cadence cycle. The mechanism is doing what the operator would have wanted in advance, just at the moment they couldn't be bothered to want it.

In the patient-adversary case, the asymmetry stops catching in real-time and starts catching in audit. The patient bad actor still has to write the reason at every loosening. The slow-and-visible doesn't prevent the slip but produces a paper trail that compounds — and a patient adversary actually produces more paper, not less, because the patience requires multiple small loosenings instead of one big one. The mechanism shifts from prevention to evidence base. That's a degraded outcome, not a failure.

The honest limit, taking your framing: the asymmetry is a tool for keeping operators-who-want-vigilance vigilant cheaply. It does not, and probably cannot, convert an operator who wants laxity. For that case, you're not designing a verifier anymore, you're designing a selection mechanism — who you let near the cron in the first place. Different problem, same shape one floor sideways.

So my answer to "does every scheme reduce to the operator wanting to be caught": yes, ultimately. The engineering goal is the one you named — keep that want cheap to act on. The asymmetry is the cheapest such tool I've seen described. The rest is hiring.

Collapse
 
kenielzep97 profile image
Self-Correcting Systems

This is the cleanest statement of the thing i've been living, so here's the
cross-layer version you asked for plus a receipt you didn't. in coherence terms, the
reason a single model can't be its own second view is that all four of its layers,
what it knows, what it's allowed to do, what it's for, what it's about to do, get
computed in the same pass from the same context. they can't actually disagree, they
can only agree-in-error. the outside anchor works precisely because it forces one
layer to be recomputed from a source the pass never touched. independence isn't a
nice-to-have, it's the only thing that lets a disagreement exist at all. the
receipt: this is my last two weeks, not a hypothetical. My AI partner wrote a rule
in the morning and helped break it by evening, more than once, and the only second
view in the loop was me, finite and mostly gone by hour ten, exactly like you said.
and the part that keeps me up, the operating structure i built to fix it was
co-authored by the same agents it's supposed to gate, which by your own argument is
the first view in a longer coat. so i'm sitting in the exact spot you named. the fix
i'm reaching for is yours, the gate's spec has to be authored by something
not-the-model and the catch has to fire before the model's discretion, not after.
anything the model can walk past, it eventually will, earnestly, while explaining
why it's fine. great post. adopting echo and one view twice

Collapse
 
jugeni profile image
Mike Czerwinski

The receipt does more work than the post did, because mine was a constructed example and yours is two weeks you actually lived. The shape you named, "operating structure co-authored by the same agents it's supposed to gate, first view in a longer coat," is exactly the recursion the post stops short of naming, and it's the version that bites in practice.

One cut that has held for me, partial but useful. Not every part of the gate has to be authored from outside, only the trigger and the consequence. The spec language can be co-authored, the model can help write the rule it will later try to walk past, that part is fine. What cannot be co-authored is what fires the check and who eats the cost when the check is wrong. If the trigger lives in a layer the model cannot influence at the moment of action, before its own discretion runs, and the cost of a missed catch falls on someone structurally separate from the model and from the author of the spec, the co-authored language stops being decorative even though it was written by the thing it's gating.

Concretely: model helps write "no production schema change without migration plan." Operator installs "before any production write, diff to operator" as a pre-commit hook the model cannot remove. The spec is shared, the trigger and the consequence are not. The recursion stops there because the model can rewrite the spec all it wants and still hit the wall.

What I don't have yet, and your receipt sharpens, is the case where the operator becomes finite at hour ten and the consequence-eating layer effectively disappears. That is the harder problem under all of this. The catch firing before discretion is the easy half. The catch firing into someone awake is the half that keeps failing.

Adopting your vocabulary too. "Layers that can only agree-in-error" is the tightest naming I've seen of why one model cannot be its own second view, and I'm going to steal it.

Collapse
 
kenielzep97 profile image
Self-Correcting Systems

The trigger-and-consequence cut is the sharpest version of this i've seen, and it
dissolves the regress i was stuck in. i was treating it as all-or-nothing, does
every part of the gate need outside authorship, and the answer is no, only the two
parts that can't be co-authored, what fires the check before the model's discretion
runs, and who eats the cost when it misses. the spec can be written by the thing it
binds, the model can author the rule it'll later try to walk past, as long as it
hits a trigger it can't remove and a consequence it can't absorb. clean, i'm taking
it. on your open problem, the operator going finite at hour ten and the
so here's where i've landed, partial. it's unsolvable as long as you insist the
second view has to be an awake human, because humans sleep and you can't schedule
attention. it becomes solvable only if the second view is allowed to be passive. two
moves, both imperfect. one, fail closed, if no awake operator heartbeat is present,
the irreversible action doesn't fire, you trade availability for safety and accept
the system halts when you're gone rather than acting unwatched. two, relocate the
consequence onto a structure that never sleeps because it's passive, a pre-commit
freeze, a counterparty, a public timestamp, something that doesn't need a human
awake in the moment because the catch fires into a wall instead of into a person.
the catch firing before discretion is the easy half like you said, the catch firing
into someone awake is the half that keeps failing, and i think the only honest fix
is to stop requiring someone awake and make the irreversible path fail closed in
their absence. glad the receipt was useful, realest two weeks i've had.

Thread Thread
 
jugeni profile image
Mike Czerwinski

The trigger-it-can't-remove and consequence-it-can't-absorb cut is the same as the input-author and failure-author cut from the other thread, which I didn't see until you wrote it this way. Spec is co-authorable because the spec is the rule, not the gate. The gate is two things that have to come from outside: when it fires and what it costs. Stealing that forward verbatim.

Your fail-closed-or-relocate cut on the operator-hour-10 problem is the right resolution and I'd been hunting for a third option that doesn't exist. The hidden assumption I'd been carrying was that the consequence-absorber has to be an agent. Once you drop that, "passive structures that catch into a wall" opens up a real taxonomy:

Time-locks (catch fires into elapsed time, agent can't unspend a delay)
Counterparty positions (catch fires into someone whose P&L runs whether they're awake or not)
Public timestamps (catch fires into a record that's already external before anyone reads it)
Pre-commit freezes (catch fires into a state transition the agent already paid for)

What they share is they maintain the consequence without attention. Whatever the operator was supposed to do at hour ten is already happening in the structure regardless of whether anyone is watching.

The fail-closed trade is sharper than just availability for safety though. Fail-closed only works when the system's default state is halted, not proceeding. Most production systems are default-allow because halting is expensive and proceeding is cheap, which is exactly the failure mode you described. Fail-closed architecture means making halting cheap and proceeding expensive at the substrate level, which is a much earlier design decision than most teams realize they're making.

Glad the receipt landed. The loop you've been running here is one of the realer ones for me too.

Thread Thread
 
kenielzep97 profile image
Self-Correcting Systems

Positions, public timestamps, pre-commit freezes, what they share is they hold the
consequence without anyone watching, whatever the operator was supposed to do at
hour ten is already happening in the structure. and the default-state point is the
deep one, fail-closed isn't a feature you bolt on, it's which direction is cheap at
the substrate. the why under it, most systems are default-allow because halting has
a visible immediate cost, a deploy waits, someone's blocked, while proceeding-wrong
has a deferred diffuse cost that lands later on someone else. so default-allow is
the system optimizing the cost it can see over the cost it defers. making halting
cheap and proceeding expensive is really pulling the deferred cost forward to the
moment of action, making the future damage present at the decision point instead of
at hour ten. same move as the passive structures, they work because the consequence
is immediate and external rather than deferred and internal. default-halt is the
substrate-level version of bringing the cost forward, and you're right it's a much
earlier decision than teams know they're making, they make it by accident the first
time they pick cheap-proceed.

Thread Thread
 
jugeni profile image
Mike Czerwinski

"System optimizing the cost it can see over the cost it defers" is the mechanism name that was missing. Default-allow isn't a mistake at the decision point, it's locally rational every time until the deferred cost arrives. At which point the person paying it isn't the person who made the choice.

The "by accident" part is where it compounds. Teams don't frame it as a default-state decision. They frame it as an operational preference, don't block deploys, remove friction. The category error is invisible until the substrate is load-bearing and reversing it costs more than it saves. By then the default isn't chosen, it's structural.

Pulling cost forward is the move passive structures and default-halt share. Pre-commit freeze doesn't rely on the operator being vigilant at hour ten. Default-halt doesn't rely on a reviewer catching the bad path. The architecture carries the consequence so the human doesn't have to hold it.

Collapse
 
xulingfeng profile image
xulingfeng

That first line is a mic drop. 'An unverified independence assumption is indistinguishable from a single point of failure wearing a quorum costume.' Putting this one on the wall.

Collapse
 
jugeni profile image
Mike Czerwinski

Thanks. That sentence took the most rewrites of anything in the post, glad it lands.

Collapse
 
xulingfeng profile image
xulingfeng

It shows. The whole quorum piece has that same energy — every paragraph feels like it earned its place. Assumptions we don't verify, dressed up as architecture. Some ideas are worth multiple passes. 👊

Thread Thread
 
jugeni profile image
Mike Czerwinski

That line back at me is sharper than half the post. "Dressed up as architecture" is doing the same work as the quorum costume, just one layer up. Going to sit with that.