A Qualification Gate: Computing What a Model Is Allowed to Decide From Its Own Results
Instead of trusting a model or not, RPOMS AI computes per verdict and per criterion what the model has earned the right to say, from a reference run. The policy, the code and the trade-off.
Trust is not a single switch
This is for anyone deploying a model whose accuracy differs by class, which is most models. The usual choices are to trust it or not trust it, with maybe a confidence threshold in between. RPOMS AI needed something finer. Its vision model was reliable at spotting a couple of kinds of damage and unreliable, in a dangerous direction, about whether a router was clean.
The answer was a qualification gate. From a run over the reference set, the system computes what this particular model, with this particular prompt, is allowed to decide. Whatever it has not earned becomes UNCLEAR, and the public sees "check manually". The overall architecture and scores are in A Vision Model That Only Observes. This article is about how the gate itself works.
Two different bars for two different verdicts
The two verdicts carry different risks, so they get different rules. Wrongly passing a damaged unit is the expensive mistake. Wrongly failing a clean one costs a second look.
- ACCEPTABLE is permitted only if the model made zero false accepts on the ten rejected references and got at least two of the three accepted references right. It is one bar for the whole verdict.
- NOT ACCEPTABLE is permitted per rejection criterion. A criterion is allowed only if the model applied it to at least one of that criterion's own rejected references and never applied it to an accepted reference.
The per-criterion rule matters. "The model rejects correctly" is not enough, because a model can reach the right verdict for the wrong reason. In one earlier run, a dented reference was rejected correctly because the model reported scratches on it. Tying each permission to that criterion's own examples means a lucky hit through a different criterion does not qualify anything.
The code
Every reference is first decided with no limits, as UNRESTRICTED, and each result is classified as correct, false accept, false reject or unclear. The permissions are then read off those rows:
const rejectCriteria = ERTH_CRITERIA
.filter((c) => c.outcome === "NOT_ACCEPTABLE")
.map((c) => c.id)
.filter((id) => {
const fired = rows.filter((r) => r.raw === "NOT_ACCEPTABLE" && r.criteria.includes(id));
const wrong = fired.some((r) => r.expected === "ACCEPTABLE");
const ownHit = fired.some(
(r) => r.expected === "NOT_ACCEPTABLE" && ERTH_CRITERIA.find((c) => c.id === id)!.items.includes(r.item),
);
return !wrong && ownHit;
});
const canAccept = rows.length === GOLD_REFERENCE.length && falseAccepts === 0 && correctAccepts >= 2;rows.length === GOLD_REFERENCE.length is a small guard with a large effect. A partial run cannot unlock ACCEPTABLE. If one reference failed to run, the model has not been measured on it, and the gate treats that as not proved.
The decision engine then applies the result. A rejection whose criterion is not in rejectCriteria becomes UNCLEAR with the reason model_not_qualified. An acceptance when canAccept is false becomes UNCLEAR the same way. Both surface as AI_UNCERTAIN, one of the five decision states, so the record shows the model was stopped, not that the rules failed.
Computed, stored and tied to the prompt
Nobody chooses a qualification. It is computed from a server-side run and stored with the model's evaluation record. The browser that triggers an evaluation only says which reference to run next. It never supplies a result. A model with no stored evaluation cannot be approved, shadowed or activated, and until it is evaluated it has the empty qualification: no ACCEPTABLE and no rejection criteria.
The prompt is part of the model's identity. The model id recorded on every inspection is ollama:qwen2.5vl:7b:prompt-3. Change the prompt and it is a different model that must be re-qualified before it can decide anything. That is why cosmetic edits to the prompt file are not made casually: any edit invalidates the evaluation.
What the gate did to this model
For Qwen2.5-VL 7B with the shipped prompt, the computed qualification is canAccept: false, with rejectCriteria limited to multiple visible scratches and a single long visible scratch. Those were the two criteria it applied without error. It may never say ACCEPTABLE.
| On the 13 references (22 Sep 2026) | Correct | Wrong | Unclear |
|---|---|---|---|
| Raw: rules applied, no gate | 3 | 7 (6 false accepts, 1 false reject) | 3 |
| Gated: what the public would see | 2 | 0 | 11 |
The obvious objection is that eleven of thirteen UNCLEAR is useless. The evaluation answers it directly. Eight of those eleven are cases the gate stopped. Removing the gate would turn them into six false accepts, meaning six damaged routers passed, plus one false reject and one correct acceptance. So removing the gate buys one right answer at the cost of six damaged units passing. The UNCLEARs are not caution for its own sake. Each marks an observation that is wrong.
Limits I would not hide
Thirteen examples is far too few for statistics. The code comment calls it "a floor, not a certification", and no accuracy figure is claimed. The gate's job is narrower: to stop a model that has visibly failed the client's own examples from speaking for the client. Passing it proves little. Failing it proves a lot.
The gate also inherits the reference set's gaps. There is no verified photo of a clean router and no borderline case, so real-world behaviour is unknown in either direction. RPOMS AI has no model active in production and has never been used on real line photos. The next step is real, verified inspection photos to evaluate against, not a looser gate. When those exist, the same gate runs on them unchanged.
The work behind this
Related
Keep reading
"Unclear" Is Not One Answer: Five Decision States for an AI Inspection
An AI check that cannot decide can fail for four very different reasons. How RPOMS AI records which one, maps it to what the public sees, and makes a missing mapping a type error.
A Vision Model That Only Observes: Building RPOMS AI Without Letting the Model Decide
A router surface inspector where the vision model reports what it sees and a deterministic rule engine decides. Why the split, what a 7B open model actually scored, the blank-image control that changed the prompt, and a safety gate that turns most answers into "check manually".
Shadow-Testing a Replacement Model With Next.js after(), Without the User Waiting
How RPOMS AI is built to run a candidate model on real requests after the response is sent, record whether it agreed, and never show it. The lifecycle around it, and its limits.