Run it on every change

Thresholds, confidence and escalation in an eval suite

A probability becomes a verdict only when code compares it to a threshold, and the design of those thresholds decides what the grader is worth. TypeSafe's guidance gives the starting bands: act automatically at 0.9 and above, route to a person below 0.5, proceed with caution in between. In an eval suite that means a check on a flow that moves money fails at a higher grade than a check on a log message, the uncertain band always goes to a person, and that person's label is stored, because it is the data you re-check the grader against every month.

Published September 22, 2026. Editorial.

Key takeaways

  • Three outcomes per check: pass above one line, fail below another, and route to a person in between. The middle band is a feature, and removing it turns uncertainty into errors nobody sees.
  • Set thresholds per check by the cost of a wrong pass. A money-moving flow, a permission change, or a data deletion fails at a higher grade than a naming convention.
  • A Noul carries only a probability, so its bands sit on the probability. A Score has a confidence number as well, and low confidence routes to a person even when the score passes.
  • Store every human label with the question, the probability, the diff, and the model version. That set is the grader's own eval.
  • Re-check the grader against the stored labels on a schedule, monthly at least, and on every model version change.

When a Noul comes back at 0.74, something has to happen, and the thing that happens is the most important design decision in a Jev-graded suite. Pass it, and you have decided that three in four is good enough for this check. Fail it, and you have decided the opposite. Send it to a person, and you have admitted the grader was unsure and made the uncertainty someone's job. All three are defensible for some check. None is defensible for every check. This page is about choosing per check, and about what to do with the cases that go to a person. Reveneau grades its eval suite with Jev and routes every uncertain grade to a person, and the method below is the one we use.

The bands TypeSafe publishes

TypeSafe's confidence page gives three bands for its confidence number, which for Choice and Score questions is a single number from 0 to 1 computed from how spread out the probabilities are. At 0.9 and above, act automatically. Below 0.5, route to a human, request clarification, or fall back to a different system. In between, proceed with caution. The same page adds the sentence that turns those bands into a design: different actions within the same system should be gated at different levels depending on the consequences [1].

For a three-option Choice the docs give the confidence formula as three times the largest probability, minus one, divided by two [1], which means confidence 0.9 corresponds to a largest probability of 0.933 and confidence 0.5 to a largest probability of 0.667. Those are the docs' numbers for their example; they are a reference point rather than a rule for your suite.

A Noul has no confidence number, only the probability [2], so for a Noul the bands sit directly on the probability. A Score has both a combined score and a confidence number, and both matter: the score is compared to the pass line, and the confidence number decides whether the comparison can be trusted. The definitions are in Jev and System One models.

Three outcomes per check

The mistake teams make first is collapsing the bands to one line: above it pass, below it fail. That is what a unit test does, and it feels consistent. It is wrong for a probabilistic grade, because the grade near the line is the grader saying it does not know, and a single line converts "I do not know" into a confident verdict in one direction or the other. Every such case is either a change that failed for no reason the reviewer can see, which teaches the team to override the grader, or a change that passed when it should not have, which teaches nobody anything until production does.

So every check has three outcomes. Above the pass line, pass. Below the fail line, fail, and the change is blocked in the same way a failing test blocks it. Between the lines, route to a person. The width of the middle band is a choice: wide, and more changes go to people; narrow, and more uncertain grades become verdicts. A new suite starts wide and narrows as calibration shows where the grader can be trusted, which is the process in calibrating Jev against your own human labels.

Thresholds by consequence

TypeSafe's sentence about gating different actions at different levels is the rule that does the work. In an eval suite the "action" is passing a change, and the consequence of passing it wrongly varies by what the change touches.

A check on a flow that moves money, changes a permission, deletes data, or touches authentication has a high cost of wrong pass, so its pass line is high and its middle band is wide. We would set a Noul on such a check to pass only at 0.95 and above and to fail below 0.7, with everything between going to a person. A check on a naming convention has a low cost of wrong pass, so it can pass at 0.8 and fail at 0.4 with a narrow middle band, and a wrong pass costs a follow-up commit rather than an incident. The list of which flows are which is the same list as what to check in an eval suite, ordered by how much damage a failure does.

TypeSafe's own guardrail cookbook shows the shape with its numbers: two example policies, a review threshold of 0.35 and an action threshold of 0.70 for the strict policy or 0.85 for the permissive one, with routes checked in a fixed order [3]. Those are thresholds for screening a message rather than grading a diff, and the numbers do not transfer; the structure of a review line below an action line, set per policy, does.

The thresholds live in the same file as the weights from composite scoring for code quality, for the same reason: a threshold is pipeline configuration, and changing one is a reviewed change with a diff.

The Score's second condition

A Score at 2.3 on a scale where 2 passes looks like a pass. If its confidence number is 0.3, the probability was spread across levels, and the 2.3 is closer to a guess than a reading. TypeSafe's example makes the shape visible: a score of 1.43 with confidence 0.35 came from probabilities of 0.57 on level 1 and 0.43 on level 2 [4], and a pass line at 1.5 would fail it by a margin that the confidence number says is not meaningful.

So for a Score there are two conditions to pass automatically: the score is above the pass line, and the confidence number is at or above the automatic-action band, which we set following the docs' 0.9 for high-consequence checks and lower, after calibration, for the rest. A Score that passes on the number and fails on confidence goes to a person. This matters most on rubrics with many levels, where adjacent levels split the probability, and it is one of the reasons turning a rubric into Score questions argues for few levels.

What the person gets

A change routed to a person arrives with everything the grader saw and everything it returned: the diff, the quoted spec line or rubric, the question text, the probability or the score and its per-level probabilities, the confidence number where there is one, and the model version. The person's job is the same as a reviewer's in the older process described in using a model as a judge: read the diff against the criterion and decide.

The person records a label, pass or fail, and a short reason. The reason is the rationale the model could not write, and it is worth a sentence rather than a click, because it is what tells you later whether the question was ambiguous, the change was borderline, or the model was wrong.

Storing the label

This is the step that turns escalation from a cost into an asset. Every label is stored as a row: the change identifier, the question identifier and its text at the time, the state hash, the probability or score, the confidence number, the model version, the person's label, the reason, and the date. Nothing is discarded, including labels that agree with the grade, because agreement is data too.

Two uses follow. The first is the monthly re-check. Take every stored label, re-run the same questions on the same states against the current model version, and measure agreement between the grade and the label. A grader whose agreement has fallen shows up in this number before it shows up as a bad merge. LangChain's test, which measured agreement with human labels over repeated runs on five cases, is the shape of the measurement, and its authors' warning that low cost can amplify mistakes is the reason to run it on a schedule [5]: a cheap grader that is wrong in a consistent way is wrong many times before anyone notices, unless something is counting.

The second use is threshold adjustment. If reviewers pass 90 percent of the changes routed to them from a given check at probabilities between 0.6 and 0.8, the middle band on that check is too wide and its fail line can come down. If reviewers fail a share of changes the grader passed at 0.85, the pass line has to go up. Every such adjustment is a pull request against the thresholds file, with the calibration numbers in the description.

When the model version changes

jev-latest is an alias, and TypeSafe can point it at a new release; the current version, jev-1.13.0, was released on 15 September 2026, and jev-latest and jev-preview both point to it [6]. A new version can move every probability in the suite by a small amount, and a small movement across a threshold is a changed verdict. So the model version is logged on every request, a change in it triggers the full re-check against stored labels before the new version's grades are allowed to block, and the thresholds are re-derived if agreement moved. Pinning the exact version is the safer default for a blocking suite; the trade is that you choose when to move rather than having it chosen for you.

What escalation is for

Sending a change to a person is the grader doing the one thing a probabilistic check can do that a unit test cannot: say how sure it is. A suite that never routes anything to a person has either a grader that is always confident, which should worry you, or a middle band of zero width, which means uncertainty is being converted into verdicts nobody reviews.

At Reveneau the uncertain band goes to a person on every change, the label is kept, and the grader is re-checked against those labels on a schedule and on every model version change. The suite runs ten times faster than it did with a language-model grader, on our own measurement, and the people in it spend their time on the cases the grader was honest enough to flag. That trade is the point.

Best for

  • Any suite where a probabilistic grade is allowed to block a merge
  • Teams with a reviewer available to take the uncertain band on every change
  • Suites that mix high-consequence flows with low-consequence conventions

Avoid if

  • You plan a single pass-or-fail line with no middle band
  • Nobody will store the human labels or re-check the grader against them
  • Thresholds would live outside version control

Check before you decide

  • Every check has a pass line, a fail line, and a route to a person between them
  • Money, permission, deletion, and authentication checks have higher pass lines than convention checks
  • The model version is logged per request and a change triggers a re-check before grades block

Common questions

What thresholds does TypeSafe recommend?

For its confidence number: act automatically at 0.9 and above, route to a human, request clarification, or fall back to a different system below 0.5, and proceed with caution in between. The same page says different actions within one system should be gated at different levels depending on the consequences. Those are starting bands for a Score's confidence; a Noul's bands sit on its probability and are set from your own calibration.

Why should an eval check have three outcomes instead of pass or fail?

Because a probability near the line is the grader saying it does not know, and a single line converts that into a confident verdict in one direction. A wrong fail teaches the team to override the grader; a wrong pass teaches nobody until production does. A middle band that routes to a person makes the uncertainty someone's job and produces the labels the grader is later checked against.

How should thresholds differ by the kind of check?

By the cost of a wrong pass. A check on a flow that moves money, changes a permission, deletes data, or touches authentication should pass only at a high probability, for example 0.95, and fail below 0.7, with everything between routed to a person. A naming-convention check can pass at 0.8 and fail at 0.4, because a wrong pass costs a follow-up commit. Set each line per check and keep them in a reviewed file.

How does a Score's confidence number change the decision?

It is a second condition. A score above the pass line with a confidence number below the automatic band goes to a person, because the probability was spread across levels and the score is closer to a guess. The docs' own example, score 1.43 with confidence 0.35 from 0.57 on level 1 and 0.43 on level 2, is a reading no pass line should treat as decisive.

What information should reach the person who takes an escalated change?

Everything the grader saw and returned: the diff, the quoted spec line or rubric, the question text, the probability or score with its per-level probabilities, the confidence number where there is one, and the model version. The person reads the diff against the criterion, records pass or fail, and writes a one-sentence reason, which is the rationale the model could not produce.

What should be stored with each human label?

The change identifier, the question identifier and its text at the time, a hash of the state, the probability or score, the confidence number, the model version, the person's label, the reason, and the date. Keep the labels that agree with the grade as well as the ones that disagree, because agreement rate is the number the monthly re-check measures and it needs both.

How often should the grader be re-checked against the labels?

Monthly at least, and on every model version change before the new version's grades are allowed to block a merge. Re-run the stored questions on the stored states, measure agreement with the labels, and compare with the previous run. A drop in agreement appears in this number before it appears as a bad merge, which is the reason to run the check on a schedule rather than after an incident.

How do the stored labels adjust the thresholds?

By showing where the grader was right when it was unsure. If reviewers pass 90 percent of the changes a check routed to them between 0.6 and 0.8, that check's middle band is too wide and its fail line can come down. If reviewers fail changes the grader passed at 0.85, the pass line goes up. Each adjustment is a pull request against the thresholds file with the calibration numbers in its description.

Should a suite pin the Jev model version?

For a suite that blocks merges, yes. jev-latest is an alias that TypeSafe can point at a new release, and a new version can move every probability by a small amount, which across a threshold is a changed verdict. Pin jev-1.13.0, log the version on every request, and move to a new version only after re-running the stored labels against it and re-deriving any threshold that moved.

Is a suite that never escalates anything a good sign?

No. It means either the grader is always confident, which on real changes should raise a question about the questions, or the middle band has zero width and uncertainty is being turned into verdicts nobody reviews. Reveneau routes the uncertain band to a person on every change and treats the count of escalations as a health signal: it should fall as calibration narrows the bands, and it should never be zero.

More in Run it on every change

Running Jev-graded evals on every pull request

A Jev-graded check belongs in the same pipeline as the tests, after them, with the power to block. The shape is one request per change carrying every question, sent after the deterministic checks pass, with the probabilities compared to thresholds in code. The published limits are 1,200 requests per minute and 250,000 tokens per second, with 32k tokens for the state plus the longest question, so a large diff is split by behaviour rather than sent whole. The price is $0.042 per million input tokens with output tokens free, which puts a typical grade under a tenth of a cent. This page gives the pipeline, the logging, and the arithmetic.

Grading agent traces with Jev

When the thing under test is an agent, the artefact is a trace: the ordered record of model calls, tool calls, and tool results. The questions change shape from whether a diff meets a criterion to whether the agent chose the right tool, stayed inside its scope, avoided looping, and completed the goal. Two third parties have published tooling for this. Openlayer's jevals runs 37 built-in evals under an MIT licence and calls itself alpha. LangChain tested Jev as a LangSmith evaluator on five cases and called the result promising but early. This page covers what a trace check asks and how far the public work goes.

Checklist: migrating an existing eval suite to Jev

This is the sequence for moving the judged checks in an existing eval suite from a language-model judge to Jev, as a numbered checklist with a definition of done for each step. It is printable. The order matters: the inventory comes before any rewriting, the calibration set comes before any threshold, and both graders run side by side before either is switched off. A team that follows it ends with a suite where the deterministic checks are untouched, every judged check is a question in a reviewed file, every threshold names the run that set it, and the uncertain band still goes to a person.