
TL;DR
- Eval status should only signal a broken measurement, never a bad business result.
- Business results like accuracy and drift belong in metrics, not pass/fail status.
- Keep the judge in the app, the record in an append-only ledger, the alarm separate.
- Grade against human-approved values and only items the app can still affect.
- Self-checks must be tested by deliberately breaking evals to prove FAIL actually fires.
An eval should grade what the system actually did in production, every day. When it fails, it should be able to say exactly one thing: the measurement itself is broken. Business results such as accuracy, drift and miss counts belong in metrics, and they never set the pass/fail status. Put a business result into the status field and the alarm starts firing for two unrelated reasons. Within a week, nobody can tell which one woke them up. We built our outcome evals for production around that rule, and this piece covers how they work, where each part lives, and what we learned building them.
What we grade
In November 2026 we put scheduled outcome evals on five production apps of an order pipeline we run on the SyscallAI platform. More are planned. Each one grades a result the app produced against something outside the app:
- Scheduled work in one app, compared against the live system of record.
- Live order status of recently touched orders, compared against the app's own latest decision, checked hourly.
- Field verdicts from a quality-check app, compared against the values a human approved.
- Document extraction, graded only against human-approved final values.
- Portal access scopes, compared against the system of record's contacts.
Code-health scans run alongside these evals. They answer a different question: is the code getting worse? The outcome evals ask whether the app did the right thing to real orders today. Unit tests and code review can't answer that, because they never see today's orders. We've written before about why review alone can't keep up with AI-written code. Outcome evals are the layer that watches what the code does after it ships.
Three jobs, three places
An eval does three jobs. It grades, it records the grade, and it raises the alarm when something goes wrong. We put each job in a different place so that a failure in one can't hide inside another.
The judge lives inside each app. The grading script sits in the subject app because grading needs the app's own logic. That includes how the app scopes an order, how it names a field, and which states count as final. A judge rebuilt from outside would have to reimplement that logic, and the copy would drift from the original.
The record lives in an Evals module in our ERP. Every eval writes one append-only receipt per period, and the first result stands. A rerun can't quietly overwrite a bad morning with a good afternoon. The ERP never grades and never reads an app's database. It holds receipts and nothing else, which makes it a ledger nobody can tune.
The alarm lives in our error-tracking service. Each eval checks in to a cron monitor there, and the monitor routes to a team chat channel. If an eval doesn't check in, the missed check-in is itself the stale alarm. A dead eval can't pass silently because the absence of a check-in is a signal.
What FAIL is allowed to mean
Each receipt carries one of three statuses, and we define them narrowly on purpose.
PASS means the eval ran completely and its own self-check held.
FAIL means the eval found its own result wrong. That happens in one of three ways. A conservation count broke, so items went into the grading and didn't come out. An independent re-check disagreed with the first pass. Or the set of items the eval graded differed from an independently derived set.
ERROR means the eval couldn't run.
Every business result goes in metrics: drift counts, accuracy, agreement rates. A bad day for the business never sets FAIL.
This is the design decision we'd defend hardest. Suppose accuracy dips and that dip sets FAIL. The on-call person now has to work out whether the app got worse or the eval broke. Those two answers lead to opposite responses. One means fix the app. The other means distrust every number the eval produced. When FAIL means only "this instrument is wrong," the response is always the same: stop trusting the reading and repair the gauge. The business numbers then get read where they belong, alongside trends and context, by someone who wants to know how the operation is doing. That's also why we stopped building screens for watching and kept dashboards only as receipts.
The grading rules we learned building them
1. Grade against human-approved outcomes
The extraction eval grades only against final values a human approved. We never grade against a field that echoes the system's own value back. If the app writes a value and a downstream field copies it, comparing the two measures the copy and tells you nothing about whether the value was right. An eval that grades the system against itself always agrees, and that agreement carries no information.
2. Grade the population that can still move
The first production dry run of one eval read the entire order history. The headline number it produced was meaningless, because closed orders from long ago swamped everything that could still change. We limited that eval to orders the system of record still shows as open. An eval should grade the items the app can still affect. Everything else is history, and history belongs in a report.
3. Know which system is the authority for each field
Some fields are set by the system of record according to its own policy. When one of those values changes, the change doesn't show the app was wrong. The authority simply moved the value. We report those changes separately and keep them out of the error headline. If you can't say which system owns a field, you can't say what a disagreement on that field means. So work out ownership field by field before you write the comparison.
4. Measure the measurement
One of our own older quality metrics counted machine-stamped reviews as if a human had reviewed them. When we fixed the count, the reported rate went down. The number had been inflated by its own definition, and nothing in its output showed that. Every eval in this set runs a self-check because of lessons like this one. An instrument needs its own test, and FAIL is reserved for the day that test breaks. We've made the broader case for measuring the checker before trusting it.
5. Dry-run against production, read-only, before going live
Every outcome eval ran as a dry run against production, read-only, before it posted a single receipt. The dry run is where the order-history problem in rule 2 showed up. It's also where one status-agreement eval agreed on 102 of 102 orders. That result told us the comparison logic lined up with reality before anyone relied on it. Read-only has to be enforced and not just intended, which is a lesson we learned the hard way and wrote up in a dry run against shared production isn't safe.
The first full day
On November 8, 2026, the first full day, five outcome evals and two code-health scans posted seven receipts to the ERP. All seven were PASS.
A PASS says the instruments work. Each eval ran to completion and its self-check held. What the metrics say about the business is a separate conversation. That separation is the point of the design. A green status lets us trust the numbers the eval produced. It doesn't grade the business. The business gets read in the metrics, by someone asking business questions.
Where we could be wrong
Our design depends on the self-checks catching real instrument failures. A self-check that is too weak produces PASS on a broken eval, and the whole status scheme rests on that check. Our confidence would change on one piece of evidence: deliberately breaking an eval's grading and seeing whether FAIL fires. We'd tighten every self-check that missed. Until each eval has faced that test, a PASS means "the checks we wrote held." We say it in exactly those words.
Build it into the operation
Outcome evals belong to the operation they grade. The judge needs the app's own logic. The record has to sit outside the app. The alarm has to fire on silence as well as on failure. This kind of work fits the operation it measures because it's modeled on how the operation already runs, and it goes in incrementally: one app, one eval, one dry run at a time.
If your production apps report green while nobody can say what green means, we should talk. Book a discovery call.