Verification systems usually record the answer and discard the question.
That is the hole.
A verifier can pin inputs, hash artifacts, sign a verdict, and write everything into an append-only log. The record can prove that a certain checker produced a certain result over a certain blob. It still may not prove that the checker asked the right question. The predicate itself can remain outside the record: what property was tested, at what operating point, under which acceptance rule, against which stratum of cases.
That missing predicate is the verification.
A Signature Is Attribution
A signature attributes a claim. It does not validate the choice of claim.
If a signed record says passed, the signature can establish that the producer of the verdict emitted that bit. It can also make tampering visible. Given the public key, artifact digest, and signed payload, a third party can check whether the record has been altered.
That is useful. It is also smaller than it looks.
"The checker ran and was not tampered with" and "the checker checked the right thing" are different assertions. The first fits inside cryptographic machinery. The second lives upstream of the signature. Arithmetic cannot reach it.
Suppose a model output is evaluated by a checker. The log stores the prompt hash, output hash, checker version, container digest, and signed verdict. The verdict says acceptable. Later, a consumer asks what acceptable meant. Did it mean exact match against a reference answer, semantic equivalence above a score, absence of forbidden tokens, consistency with a schema, or a business rule with exceptions? If that predicate was never pinned, the record answers a different question. It says who signed the verdict. It does not say whether the verdict was falsifiable.
Cryptography moves the boundary upstream. It protects what entered the signed envelope. Anything outside that envelope remains a matter of private judgment, convention, or memory. A system can have perfect signatures and still be unable to prove that the signed statement was the statement that mattered.
This failure is easy to miss because signatures feel final. They create a clean bit of evidence. The problem is that evidence about an underspecified claim is still underspecified evidence.
Predicate Selection After the Result
Post-hoc predicate selection is the software analogue of choosing a hypothesis after seeing the data.
If the predicate is authored after the result is visible, almost any verdict can be made satisfiable. A failing output passes under a weaker similarity threshold. A safety verdict slides from "no disallowed behavior" to "no disallowed behavior under this taxonomy version and severity cutoff." Each individual move can sound reasonable. Together they turn verification into fitting.
The order matters.
A predicate chosen before the result exists has a different evidentiary status from a predicate selected after the terrain is visible. The bytes may be identical. The timing changes what the record can prove. If the predicate came later, the signed verdict is compatible with selection over possible questions. If the predicate came first, a third party can replay the sequence and detect mismatch.
The fix has a known shape: pre-registration.
Pin the predicate before the result exists. Put the predicate hash, the predicate body, or a content-addressed reference into the record before the checker sees the artifact being judged. Include enough data to bind the acceptance rule. Then later, when the verdict appears, the log can show ordering rather than ask for belief.
This does not require exotic machinery. An append-only log can record a predicate_registered entry containing the checker identity, predicate digest, operating point, acceptance rule, and intended input class. A later verdict_emitted entry can reference that predicate entry by digest and log index. Schema names are negotiable. What has to hold is that the predicate exists as a committed object before the result can influence it.
Without that ordering, the log records a conclusion with ceremony around it.
The Operating Point Is Part of the Predicate
Thresholds are predicates too.
A common failure mode is to treat the operating point as configuration and the rest of the check as the real verifier. That split is false. If the checker says "pass when score is at least 0.82," then 0.82 is part of the question. Move it to 0.79 and the system is asking something else.
The damage gets worse across heterogeneous difficulty.
A single global threshold applied to mixed request classes silently averages populations that should be scored separately. Easy cases, ambiguous cases, adversarial cases, and long-context cases do not occupy the same distribution. A global cutoff can make an accuracy number look like a discrimination ceiling when it is only one operating point flattening several strata into one scalar.
Consider a classifier evaluated across two strata. In one stratum, scores separate cleanly. In the other, correct and incorrect cases overlap. A global threshold produces one pass rate and one failure rate. The aggregate number can imply that the checker has reached its limit. In fact, one stratum may tolerate a stricter threshold while another needs a different rule or should be reported separately. The hidden decision was to collapse them.
That decision belongs in the record.
The log should say which stratum a case belonged to, which threshold applied, how that threshold was selected, and which acceptance rule consumed the score. "Score equals 0.81" is an observation. "Accepted because the threshold for this stratum is 0.80 under rule semantic_equivalence_v4" is a verdict.
Those are different records.
This matters for replay. A third party should be able to recompute the score, find the applicable operating point, apply the acceptance rule, and arrive at the same verdict. If the threshold is hidden in a deployment flag, command line override, notebook cell, or service default, replay becomes archaeology. The signed verdict may still verify. The judgment will not.
Shared Decision Rules Create Shared Fate
Running several checkers does not automatically create independent verification.
Different machines, builds, providers, and implementations can still amount to one checker if they share one acceptance rule. Diversity in substrate buys little when the judgment is identical. The common-mode failure is in the predicate.
This is not theoretical neatness. Knight and Leveson's 1986 N-version programming experiment is the canonical warning: independently produced implementations still failed in correlated ways on hard inputs. Hard inputs are hard for everyone. Independence at the code level did not eliminate shared failure modes.
Verification systems recreate the same trap when they diversify execution while centralizing judgment.
Picture three checkers. One runs locally, one runs in a hosted environment, one runs inside a separate build. Each has a different binary and a different signing key. All three call the same acceptance rule: pass if normalized similarity exceeds a single global threshold. For borderline cases, the system has three signatures and one opinion.
The infrastructure looks diverse. The verdict is not.
A stronger design records predicate identity per checker and makes disagreement meaningful. One checker might use an exact structural invariant. Another might use a calibrated score per stratum. A third might check monotonicity over generated variants. If those predicates are pinned independently, disagreement exposes something useful. If all three wrap the same hidden rule, the append-only log will collect redundant confidence.
Redundancy is not independence.
Idempotency has the same shape. Retrying the same predicate across more infrastructure is good for availability. It is weak evidence for correctness. If the question is wrong, idempotent replay makes the wrong answer repeat cleanly.
Make the Predicate a Record Field
The repair is concrete: make the predicate a first-class field in the verification record.
Do not bury it in checker code, deployment config, prose policy, or an issue thread. The record should bind at least four things: the artifact under test, the checker that executed, the predicate that was asked, and the verdict produced. The predicate should include the operating point and acceptance rule. If scoring is stratified, the stratum selection rule belongs there too.
A minimal record might contain:
{
"artifact_digest": "sha256:...",
"checker_digest": "sha256:...",
"predicate_digest": "sha256:...",
"predicate": {
"name": "semantic_equivalence",
"version": "4",
"stratum_rule": "request_classification_v2",
"operating_points": {
"short_factual": 0.93,
"long_reasoning": 0.87,
"ambiguous_instruction": 0.91
},
"acceptance_rule": "score >= operating_point_for(stratum)"
},
"verdict": "pass",
"score": 0.89,
"stratum": "long_reasoning",
"signature": "..."
}
The exact shape will vary. The invariant should not.
The predicate is committed before the result. The verdict references that committed predicate. The log contains enough information for replay without cooperation from whoever ran the check.
That last phrase is the test.
A third party who was absent when the check ran should be able to reconstruct the verdict from the log alone and disagree. Disagreeing matters. If the third party can only verify the signature, then the record is about attribution. If the third party can recompute the verdict and say "this should have failed under the pinned rule," then the record is falsifiable.
That is the bar.
The record also needs ordering. If the same append-only log contains both predicate registration and verdict emission, the verifier can check that the predicate entry precedes the result. If the predicate is stored by digest in another content-addressed system, the log still needs a prior commitment to that digest. Otherwise the predicate can be rewritten around the result and presented as if it had always been there.
There is an honest limit here. Pinning the predicate does not make the predicate correct. A pinned wrong question is still a wrong question.
What pinning buys is exposure. The wrong question becomes public and attributable, which means it can be argued with. It can be compared against requirements. It can fail review because the threshold flattened strata, or because the acceptance rule ignored a class of errors that someone downstream cares about. That is a much better failure than a private decision rule hiding behind a valid signature.
Current verification records are often too pleased with their own hashes. They preserve artifacts while letting the actual judgment float outside the evidence boundary. The result is a signed answer to an unknown question.
Tomorrow, pick one verification log and try to replay a verdict with no access to runtime config, private notes, service defaults, or cooperation from the producer. If the predicate, threshold, stratum rule, and acceptance rule are not all in the record before the result, the log is recording what someone concluded.
Top comments (1)
Great read! Three practical gaps I'm still chewing on:
Replay is not guaranteed – The post says anyone with the log can recompute the verdict. But LLM checkers are non‑deterministic (temperature, GPU ops, API drift). Same digest, different score. Without deterministic execution, falsifiability stays theoretical.
The predicate isn't the full question – A JSON threshold is pin‑able. Custom evaluation code isn't. To truly replay, you'd need the entire runtime closure (dependencies, OS, library versions). predicate_digest alone doesn't capture that.
M-of-N ≠ independent judgment – If all N verifiers share the same underlying model or API, they'll fail together on hard cases. Diversity in infrastructure doesn't create diversity in reasoning.
Until verifiable execution (TEEs, ZK) or predicate‑level diversity is enforced, we're still trusting the verifier — just with better signatures.
Curious how v0.2 plans to tackle these.