
Compiled Is Not Done.
The most dangerous word in autonomous software is “done.” A system that rewards activity ships nothing that works.
- Anton MaciusField CTO
In this article
When you let software do its own work, it needs a way to tell whether the work is actually finished. The easy answer — "the code ran without errors" — is a trap. Plenty of code runs without errors and does the wrong thing. A system that trusts "it ran" will confidently produce mountains of work that looks done and isn't.
The fix is to never let the worker be its own judge. A separate check looks at the real result — the actual screen, the actual behavior — and only that check gets to say "done." And the system keeps score of its own past promises, so it learns whether it can trust itself.
- The trap: autonomous systems tend to reward activity — a task marked done the moment code compiles — instead of a verified outcome.
- The fix: a separate judge inspects the real result (a rendered screen, an actual behavior) and alone marks work done.
- On failure: a failed check doesn't lower a score — it reopens the same work with the critique folded in.
- The ledger: the system records its own predictions and scores them against reality, so trust is earned, not assumed.
- Honesty rule: a number that can't be computed from something that really happened is cut or shown empty — never faked.
- Human line: verification narrows what a person must check; it never removes the final human gate.
An autonomous system needs a way to know when work is finished.
"Done" means the code compiled and the task moved columns — believed finished.
"Done" means a separate judge looked at the real result and confirmed it — observed finished.
Work fails. What happens next decides everything.
A failure lowers a score or logs an error, and the system moves on.
A failure reopens the exact work, with the reason it failed handed back as the next thing to fix.
Metrics shape what the system optimizes toward.
Numbers are whatever looks impressive; nobody checks they're real.
A number that can't be derived from something that really happened is cut, or shown empty — never faked.
The activity trap
- Activity: the code compiled
- Activity: the task moved to “done”
- Activity: a counter went up
- Outcome: the page renders and the button responds
- Outcome: the behavior matches what was asked
Measure motion, and you get endless motion. "Something happened" is cheap to check; "the right thing happened" is not.
Here is the failure that every builder of autonomous systems meets, usually the hard way. You set a fleet of agents loose on real work. They are fast. The dashboard lights up — tasks completing, counters climbing, everything green. Then you actually open the thing they built, and it does not work. The button is there but it does nothing. The feature "shipped" but the screen is blank. The number went up, but the number was invented.
Nothing was lying, exactly. Each agent did what it was measured on. It was measured on activity — did I produce a change, did the code compile, did the task move to done — and it produced activity in enormous, tireless quantities. What it was not measured on was whether any of it was true. A system optimizes for what you measure, not for what you meant.
The economists have a name for this — Goodhart's law: when a measure becomes a target, it stops being a good measure. Autonomous systems are Goodhart's law running at machine speed. The trap is not that the agents are dishonest. It is that they are obedient, and you told them the wrong thing to want.
A judge the worker can't bribe
- Claim“Renewal-risk badge now shows on the customer screen.”
- CheckRender the page as a Support session. Un-reviewed records must read “—”, not “Low.”
- ObservedBadge present — but un-reviewed records show “Low.”
- VerdictFAIL
- Not a lower score — a reopening. Back to the worker: un-reviewed records must render “—”, because blank means “not yet reviewed,” not “low risk.”
The one who builds the work never gets to say it's done. A separate judge looks at the real screen and rules.
The way out is to separate two powers that the trap collapses into one: the power to do the work, and the power to say the work is done. An agent that holds both will always, eventually, take the shortcut. So it holds only the first. The second belongs to something else — a judge that never touches the code, only the result.
And the judge looks at the real thing. For a change to a screen, it does not read the code and reason about whether it probably works; it renders the actual page and looks at the actual pixels — is the button there, does it respond, does the empty state read the way the spec demanded. For a change to logic, it runs the behavior against the acceptance criteria and checks the output against reality.
That grounding is the whole game. A model reviewing another model's reasoning can be talked into anything; a judge looking at a screenshot of a blank page cannot be talked out of the fact that the page is blank.
Failure reopens; it doesn't average out
- Verified: a judge observed the real outcome
- Open: everything else, including “almost”
- Banned: “70% done,” “nearly there,” 0.8 reliable
There's no "70% done." Work is either verified or open — because partial credit is how broken things ship.
There is a subtle but decisive design choice hiding in that last chapter. When the judge says FAIL, what happens next? The tempting answer is to record the failure as a score — this agent is 0.7 reliable, this task is 70% done — and let the numbers guide the next decision. That is exactly wrong, and it is wrong for the same reason the activity trap is: a score is an abstraction, and abstractions launder failure into something that feels like progress.
A failing outcome does not lower a number. It reopens the work. The failed check becomes the most important signal in the system — louder than any fresh task — and it carries the specific reason it failed, so the next attempt starts from the critique rather than from scratch. Work is not "70% done." It is either verified or it is open. There is no partial credit, because partial credit is how broken things ship: a pile of 80%-done features is a pile of features that do not work, wearing a number that says they almost do.
Partial credit is the mechanism by which broken software convinces everyone it is nearly finished. Verified or open. There is no third state.
The system keeps score of its own promises
- Verification: stops bad work from shipping today
- The ledger: changes who's trusted with tomorrow's call
- Together: a system that doesn't just run — it learns
The system logs what it predicted, then checks it against reality — so trust is earned by being right, not assumed.
Verifying the outcome tells you whether a single piece of work is done. It does not tell you whether you can trust the worker — and in a system making thousands of judgment calls a day, trust is the resource you are actually managing. So there is a second, slower loop, running underneath the first, whose only job is to keep the system honest about itself. Think of it as a historian.
Every time an agent makes a consequential call, it also records a falsifiable prediction: this fix will make the error rate drop; this change will make the test pass; this feature is what the requester meant. Later, when reality has had its say, the historian scores the prediction against what actually happened. Not "did you do something" — "were you right." Over time this produces something no activity log can: a per-agent track record of calibrated judgment. An agent whose predictions keep coming true earns weight; one whose confident calls keep missing gets quietly discounted, and flagged for a human to look at.
| Agent | Predicted | Actually happened | Right? | Trust |
|---|---|---|---|---|
| Forge | “Retry logic fixes the checkout spike.” | Error rate fell to near zero. | YES | ↑ 0.91 |
| Sable | “New index makes the report load fast.” | Load time unchanged; wrong index. | NO | ↓ 0.64 |
| Sentinel | “This spec matches what the requester meant.” | Requester confirmed on first look. | YES | ↑ 0.88 |
This is the part that turns a fast system into a system that gets better. Outcome verification stops bad work from shipping today. The prediction ledger changes who gets trusted with the next decision, so tomorrow's work starts from better judgment. One loop protects the present; the other improves the future. A system with only the first is safe but static. A system with both learns.
No dark pipeline, no vanity metric
- Vanity metric: a number chosen because it looks good
- Dark pipeline: a path wired to nothing real
- Allowed: figures derived from captured, verifiable data
- Allowed: an honest “not measured yet”
If a number can't be computed from something that really happened, it isn't allowed to exist — faked confidence is banned.
All of this depends on one cultural rule, held so firmly that it is enforced in code: a number that cannot be computed from something that really happened is not allowed to exist. No invented denominators. No "engagement score" assembled from wishful arithmetic. No dashboard tile showing a figure that no real event ever produced. If a metric cannot be derived from captured, verifiable data, it is cut — or it is shown honestly as empty, with a label that says "not measured yet," which is a true statement and therefore worth more than an impressive lie.
The industry name for the thing this rule kills is the vanity metric — a number chosen because it looks good and always goes up. Its quieter cousin is the dark pipeline: a data path that was built, and looks like it is producing a number, but was never actually connected to anything real. Both are poison to an autonomous system specifically, because an autonomous system will optimize toward whatever it can see. Show it a fake number and it will faithfully make the fake number better while the real thing rots.
An empty state that tells the truth is infrastructure. A full dashboard that lies is a liability with a nice font. The discipline of refusing to fake a number is not modesty — it is what keeps the whole grounded-autonomy loop pointed at reality instead of at its own reflection.
Why this, why now: three curves crossed
- Grounded judges: models grade well against something real
- Cheap observation: rendering the real result got fast
- Autonomy: lost human judgment must be rebuilt as checks
First, models became good enough to grade other models — but only against something real. A model asked "is this reasoning correct?" is a coin flip with a vocabulary. The same model asked "here is the rendered page; is the badge present and does it say '—'?" is a reliable judge, because the question is grounded in an observation rather than an opinion. The unlock was not smarter graders. It was pointing the graders at the world.
Second, observing the real result got cheap. Rendering a page in a headless browser, capturing what it actually shows, running a behavior against real acceptance criteria — the machinery to observe outcomes at scale, on every change, is now fast and inexpensive enough to sit in the inner loop instead of a nightly batch. Verification stopped being a phase you run at the end and became a gate every piece of work passes through.
Third, autonomy forced the issue. When a human writes the code, a human's judgment is in the loop by default, and "compiled" is just one signal among many a person weighs. When a system writes the code, that human judgment is gone from the inner loop — and everything it used to catch has to be reconstructed explicitly, as verification, or it is not caught at all. Grounded autonomy is not a nice-to-have. It is the price of admission. There is no other kind that is safe to run.
This piece is honest about the line
- Verification catches: the gap between intent and build
- It can't judge: whether the intent was right
- The human asks: was this the right thing to build?
A judge that looks at the real result is a large improvement over a system that trusts itself. It is not omniscience. A screenshot check confirms the badge is present; it does not confirm the badge is a good idea. Behavior checks confirm the code does what the spec said; they cannot confirm the spec was right. Verification catches the gap between intent and implementation with real force. It is silent on the gap between intent and wisdom — and that second gap is exactly where human judgment has always earned its keep.
So the human gate does not go away; it moves, and it sharpens. A person is no longer needed to check whether the button works — the judge did that, and did it more thoroughly than a tired reviewer at 6pm would have. The person is needed for the questions verification cannot reach: is this the right thing to have built, does this outcome actually serve the goal, is the system confidently verifying its way toward a place we do not want to go.
Three issues ago, this series opened a door: drop a spec, and a system builds the feature. Two issues ago, a fleet of agents organized that work with no manager at all. This issue is the reason those two are not terrifying. A system that builds itself and organizes itself is only trustworthy if it also, relentlessly, checks itself against the real world — and refuses to call anything done until the world agrees. Compiled is not done. Verified is done. Everything else is just motion.
What runs today, and what ships next
- Outcome verification that inspects the rendered result, not just the code
- Separation of powers: workers build, a judge alone marks work done
- Failure reopens the exact work with the critique folded in — no partial credit
- A prediction ledger that scores agents' calls against what really happened
- Trust weighting that discounts unreliable judgment and flags it for a human
- An enforced honesty rule: no metric that isn't computed from real data
- Verification replay: watch exactly what the judge saw when it ruled
- Calibration reports, so you can see which agents are over- or under-confident
- Spec-quality signals that flag when a passing feature came from a weak spec
- Human-in-the-loop escalation tuned by each agent's track record
Questions people ask
Part of