Skip to content

15 min read

An acceptance signal has to come from outside the weights

On this page

The first attempt at a gate on the payments drafter was the cheapest one available: after each revision, ask the model whether the new draft is better than the old one, and keep it if the answer is yes. On 120 revisions where a domain expert had independently labelled the change as an improvement or a regression, that gate accepted 71 of the 74 improvements, which sounds excellent until you read the other row. It also accepted 39 of the 46 regressions. A gate that says yes to 92% of everything is a rubber stamp with a latency cost of 1.3 seconds and a bill of $0.9 per thousand requests.

That 92% is the two rows added together: 71 accepted improvements plus 39 accepted regressions is a hundred and ten acceptances out of 120 labelled revisions. Splitting it back apart is what shows why the gate is worthless. It accepts roughly nineteen improvements in twenty and roughly seventeen regressions in twenty, and the whole value of a gate lies in the difference between those two rates. A gate whose answer barely depends on which kind of change it is looking at is a function of almost nothing, and a function of almost nothing can be replaced by a constant at no loss — which is exactly what "accept everything" is, and it costs nothing to run. Compare the numbers this chapter reaches later for a cross-family judge, roughly nineteen in twenty against roughly one in four, and the difference between a gate and a stamp is visible without any further statistics.

The failure is the same one chapter 2 measured, arriving in a different place. The comparison "is B better than A" is answered by the weights that wrote both A and B, and a revision they produced is, by construction, a revision they consider an improvement — that is why the reviser emitted it. Self-scoring a revision asks the model to disagree with itself across two calls, and the disagreement rate is low precisely on the cases where it would matter.

What can actually score one draft against another

Everything usable has the same property: some part of the judgement comes from outside the weights that produced the text. There are five recognisable families, and they differ less in accuracy than in what fraction of your requests they can say anything about at all.

signalwhat it catchescoverage on this trafficadded latencyerror correlation with the writer
objective check — schema validation, unit tests, compiler, arithmetic recheckformat and computation defects, contract violations100% of format, 12% of content5–90 msnone
tool or retrieval verification — every claim matched to a retrieved snippetunsupported and contradicted claims56% (tickets with retrieval)300 ms + 1 calllow
judge that is not the writer — different family, fresh context, explicit rubricreasoning, completeness, tone, self-contradiction100%1.1 s + 1 callmoderate
heuristic on the artifact — length delta, entity consistency, reading level, required sectionsdrift, inflation, dropped sections, changed numbers100%under 10 msnone
human — sampled review, or blocking review on a sliceanything0.5% sampledminutes to hoursnone

Coverage is the column that decides architecture, and it is the one usually left out of these comparisons. A verifier — any check outside the model that can say whether a draft is acceptable, from a schema validator to a person — that is right 95% of the time about 12% of your requests leaves 88% of them ungated, and what happens in that 88% is a design decision you have to make on purpose. Retrieval verification is strong on the payments drafter's policy questions because every factual claim about fees or windows should trace to a snippet that was fetched, and it says nothing at all about a ticket asking how to phrase a refund notice to a customer, because there is nothing to trace.

Read the coverage column as a partition rather than as five separate percentages, because that is how the traffic actually divides. Retrieval verification covers 56% of these tickets, so on the remaining 44% there is nothing to trace and that family is silent. The judge row says 100%, which means a judge could speak on all of it — nothing about a request stops a rubric judge from scoring the answer. So the ungated 44% is not a limit the traffic imposes; it is a limit somebody chose, by deploying the judge on some slices and not on others. That distinction between a requirement and a decision is the one to hold on to, because a requirement is argued with by changing the world and a decision is argued with by reading the code, and only one of those takes an afternoon.

Correlation with the generator's errors is the second column that matters and the reason a judge from a different model family — a model from another vendor or training lineage, rather than a second call to the one that wrote the draft — is worth its extra call. Two models trained on overlapping data still share many priors, the leanings about what a plausible answer looks like that a model brings to a text before it reads a word of it, so a cross-family judge is not independent in the statistical sense; it is decorrelated enough to catch a portion of what the writer cannot see. On the 120 labelled revisions, a rubric judge from a different family accepted 68 of 74 improvements and 11 of 46 regressions, which is a usable gate. Its cost is that it disagrees with the human label on 14% of cases in both directions, and those disagreements are not evenly distributed — they cluster on long answers where the rubric's completeness dimension and the human's judgement diverge.

That 14% is the two rows read the other way up, and it is worth assembling because the assembly is what shows the two error kinds are not interchangeable. Of the 74 improvements the judge accepted 68, so it refused six of them. Of the 46 regressions it accepted 11. Six plus eleven is seventeen decisions out of a hundred and twenty that went against the human label, which is the 14%. What the figure licenses is a statement about this labelled sample: roughly one gated decision in seven would be overruled by the expert who produced the labels. What it does not license is treating the seventeen as one quantity. Refusing an improvement costs you the improvement and leaves the incumbent, which is a draft somebody already judged acceptable. Accepting a regression puts a worse answer in front of a merchant. A gate tuned to make the total smaller, with no view on the mix, will happily trade the second kind for the first.

The heuristic row is the one teams skip because it looks unserious, and on this system it was the highest-value line in the table per unit of effort. Three rules written in an afternoon caught most of the damage the loop was doing: any currency amount, percentage or day count present in the previous draft must still be present unless a finding quoted it, the answer must retain a paragraph naming the escalation path, and the length must not grow by more than 15%. The first of those alone rejected 61 revisions across the 300-ticket set, of which 54 were the failure that opened chapter 1 — a correct figure dissolving into a vaguer phrase while some other paragraph was being fixed. None of it requires a model call and all of it runs in under ten milliseconds, which means it can gate every request including the ones no scored signal covers.

The ratio inside that sentence is the interesting part. Roughly nine in ten of what the currency rule rejected was the specific defect chapter 1 opened on, which is a precision figure for a rule that took an afternoon and consults no model. The reason it can be that precise is that the rule does not judge anything. It asks whether a string of digits present before is present after, and unless a finding quoted that span, there is no legitimate reason for it to have gone. What the figure does not tell you is the rule's recall, because 61 rejections across 300 tickets says nothing about how many figure-dissolving revisions slipped past — a number rewritten to a different number rather than to a phrase passes this rule untouched.

Human review sits at the bottom of the table with 0.5% coverage and belongs there for cost reasons, but the sampled fraction does work that nothing else does: it is the only signal that can tell you the other four have drifted. A weekly sample of 40 gated decisions, labelled by someone who knows the domain, is what produced the 120 labelled revisions this chapter opened with, and that dataset is what makes every other row's accuracy a number rather than an assumption.

Those two figures close on each other, which is worth noticing because it prices the whole chapter. Forty labelled decisions a week reaches a hundred and twenty in three weeks, so every accuracy figure quoted above rests on three weeks of one person's sampled reading. That is cheap, and it is also the reason the intervals around 71 of 74 and 11 of 46 are wide. The right conclusion is not that the numbers are untrustworthy; it is that they support a decision between a rubber stamp and a usable gate, and they do not support tuning a margin to two decimal places.

The offline curve and the runtime gate are different instruments

The per-pass curve in chapter 2 was produced by a rubric judge on a frozen set with three repetitions, at a cost of roughly 12 minutes of wall clock and $9 per full grid. Nothing about that procedure survives contact with a live request. There is no label, there is one sample rather than three, there is a latency budget measured in seconds, and the decision is not "how good is this configuration on average" but "does this specific revision replace this specific draft".

offline evaluation setruntime gate
question it answersis this configuration better on averageis this revision better than this draft
unita set of casesone request
labelsavailable, human or curatednone
repetitions3+ per configuration1
budgetminutes, dollars per gridmilliseconds to ~2 s, cents
acceptable signalexpensive judge, human reviewcheap check, heuristic, one judge call
failure modeoverfitting the set through prompt tuningaccepting a regression on this request

Every row of that table is a consequence of one difference, and naming it makes the rest predictable. Offline, the unit is a set and you may look at it as often as you like; at runtime the unit is one request and you get one look. From "a set" follows the availability of labels, because a set can be labelled once and reused, while a live request has no label at the moment the decision is due. From "one look" follows the single repetition, and from the single repetition follows the loss of the noise floor: a runtime gate cannot rerun the comparison three times to find out whether the difference it is seeing is real. From the latency budget follows the restriction to cheap signals. The two instruments are not a strong version and a weak version of the same thing; they answer different questions and one of them is not available when the other is.

The two are related in one direction: the offline set is where you calibrate the runtime gate. The margin, the veto list, the maximum pass count and the choice of scored signal are all parameters, and the offline set with its labels is the only place you can measure what they do. The gate that ships is then the cheap approximation whose behaviour you have characterised, and re-measuring it on a fresh set periodically is what catches the drift between the two.

The same move that makes a gate possible is what extends the useful pass count from chapter 2. A pass whose critique includes a failing test name, a retrieved snippet that contradicts a sentence, or a cross-family judge's rubric breakdown is a pass carrying information the weights did not have, and that information does not run out after two rounds the way introspection does. On a code-generation task with a test suite in the loop, passes stay productive as long as tests keep failing, which is a completely different curve driven by the environment rather than by the model's beliefs. The reason the payments drafter plateaus at two is that its critique step is pure introspection on 44% of traffic.

Where this is the wrong tool

An external signal is not a correctness oracle, and treating it as one moves the failure rather than removing it. Citation coverage measures whether sentences trace to retrieved text, so an answer that faithfully cites a stale policy snippet scores perfectly while being wrong. A test suite scores the code against the tests, so a revision that special-cases the test inputs passes the gate. A rubric judge scores against the rubric, and rubrics reward length, structure and confident phrasing more than their authors intend. Each of these signals is a proxy, and a loop that optimises against a proxy for enough passes will find the gap between the proxy and the thing you wanted.

The practical consequence is that gate quality and pass count interact. A weak proxy with three passes is usually fine, because three passes cannot exploit much. The same proxy with fifteen passes and an aggressive margin will hand you an answer that scores 0.99 on citation coverage by quoting the retrieved snippets almost verbatim and answering a slightly different question than the merchant asked. This is the loop version of reward hacking, the general failure in which a system optimises whatever is being scored until the score and the goal it was standing in for come apart, and the defence is a cap and a veto list rather than a better proxy.

The mechanism behind that interaction is worth one more step, because it explains why the defence is a cap rather than a better proxy. Every pass is an attempt to raise the score, and the gate accepts only attempts that succeed, so the sequence of accepted drafts is monotonically increasing on the proxy by construction. Where the proxy and the goal agree, that climb is progress. Where they come apart, the climb continues anyway, because nothing in the loop can see the goal. The number of passes is therefore the number of opportunities to walk along the gap, and capping it caps the distance travelled. A better proxy narrows the gap and does not close it, and the next proxy has a gap of its own.

There is also a class of task where none of the five families has any purchase: open-ended judgement where the answer's quality is genuinely a matter of the reader's context, such as how firmly to word a decline notice to a merchant who has been a customer for six years. For those, the honest design is a single pass, a human in the review path for a sampled fraction, and no loop at all.

With a signal in hand, the loop can finally be given a rule about what to return, and the rule is more than "stop after three passes" — the curve in chapter 2 was a mean over 300 tickets, and the pass at which any individual ticket peaks is a distribution rather than a number.

Reflection / self-critique loop — read the current version at https://daviddominguez.dev/learn/en/reflection-self-critique-loop/an-acceptance-signal-has-to-come-from-outside-the-weights

Back to top