Topic title: [Pre-ERC Discussion] Preregistered Acceptance Criteria
Category: ERCs
Every verification primitive in the agent stack reduces to the same shape:
recompute the result, compare digests. ERC-8274 verifies an
(inputHash, outputHash, proof) triple. ERC-8404 issues a receipt over
REPRODUCED | DIVERGED | CANNOT_RECOMPUTE. ERC-8263 anchors a digest.
Inclusion-proof designs confirm a commitment made earlier. Every one of them
assumes the artifact can be derived a second time.
Almost nothing an agent pays a counterparty for can be derived a second time.
A deliverable generated by a model at temperature above zero does not return the
same bytes twice, and provider-side model revisions break reproduction even at
temperature zero. A document someone had to review. An inspection someone had to
be physically present for. And in the general case, “is this good enough to pay
for” was never a recomputation question — it is a judgement against a standard.
This is not a complaint about ERC-8404. Its own normative text forbids
converting CANNOT_RECOMPUTE into any settleable verdict, which is the correct
guard to have written. The consequence is that every judged outcome parks in
that status permanently, and settlement happens somewhere off the record.
The boundary is not digital versus physical. It is computed versus judged.
What the draft proposes
Before any evidence exists, the paying party registers two things on-chain: a
digest of the acceptance criteria, and a packed list of typed evidence
obligations at two bits each — required, waivable. When the work comes back, the
verifier’s attestation is itemized against that frozen list: for every
obligation, MET, WAIVED, UNMET, or NOT_APPLICABLE.
function preregister(
bytes32 criteriaDigest,
bytes32 taskRef,
uint16 obligationCount,
bytes calldata obligationFlags, // 2 bits per obligation, MSB-first
uint64 expiry
) external returns (bytes32 preregistrationId);
function attestOutcome(
bytes32 preregistrationId,
bytes32 bundleDigest,
bytes32 attestationDigest,
Verdict verdict, // Satisfied | NotSatisfied | Indeterminate | ...
bytes calldata obligationOutcomes // 2 bits per obligation, same order
) external;
One rule carries the whole design: an attestation that declares the outcome
satisfied while a required obligation is recorded UNMET is rejected by the
contract. Not flagged, not down-scored — reverted.
Cost is ceil(2n/8) bytes for n obligations. Eight obligations is two bytes.
Why itemizing is the point
Today a verdict is a uint8, a score, or a complete() call. There is nothing
inside it for a third party to contradict. Itemize it against criteria that
provably predate the evidence and a challenger has something concrete to point
at: obligation 3 is recorded unmet, and you passed the outcome anyway.
“But the deliverable is already hashed”
The opening argument was that most work cannot be recomputed. This one is
stronger, because it holds even where hashing works perfectly.
The thing most people have actually built releases escrow when the digest of the
returned artifact matches a commitment made when the order was accepted — payment
against a hash rather than against a promise. It is a good construction and I am
not arguing against it.
It proves identity: the artifact being paid for is the one that was committed to,
and it cannot be swapped afterwards. It proves nothing about adequacy. A digest
is taken over bytes, not over a requirement. The hash of an artifact that misses
the point matches its commitment exactly as cleanly as the hash of one that
doesn’t.
The tell is the challenge window these designs put after the match. Enumerate what
a challenger can actually raise in it. Substitution — already excluded by the
digest. Non-delivery — already visible, no commitment was ever posted. Lateness —
already in the timestamps. What is left is “was this good enough to pay for”, the
one question the digest never answered. The challenge window is the design
conceding that matching the hash did not settle the matter.
And whoever uses that window is arguing against nothing: no part of the record
states what the artifact was required to contain. It is sharper still where a
design slashes a stake instead of merely withholding payment — withholding leaves
both sides where they started, slashing moves value on a finding nothing on the
record can contradict.
So this is not a niche about physical work. A pure byte-string deliverable can hash
exactly, be committed to before it is revealed, and be anchored beyond dispute, and
the adequacy question is untouched by all three. Freezing the artifact and freezing
the criteria are two different acts, and only the first one has a primitive.
Choosing a judge is a different problem from fixing the criteria
The other reply I expect is “use a weighted verification gate, or have a model
grade the output.” ERC-8353 stakes and weights verifiers over an evidenceHash
and explicitly puts the format of that hash out of scope. It decides who
judges and how their votes aggregate. It never records what the judge was
required to check. A unanimous weighted verdict against unrecorded criteria is
still unfalsifiable.
The off-chain version is worse in one specific way: a grading rubric held in a
prompt can be edited after the output is in hand, and the record retains no
trace of the edit.
Medicine has a name for that. You cannot replay a patient’s course, so a
researcher could report whichever endpoint looked good once the data arrived —
outcome switching. The fix was preregistration, and the ICMJE made trial
registration a condition of publication on 1 July 2005. But registration
alone did not fix it: the COMPare project at CEBM Oxford,
from October 2015 to January 2016, checked trials in five major journals against
their own registry entries and found switching still widespread. A registry stores
a plan and never compares it to the report. The comparison was left to volunteers
reading papers by hand.
Mechanising that comparison is the contribution here. Outcome switching becomes
a revert instead of misconduct someone might notice later.
Why this needs a chain at all
Exactly one claim here needs consensus: that the criteria could not have been
chosen after seeing the evidence. That is a claim about ordering in time, and
off-chain timestamps are backdatable by whoever holds the key. Clinical
preregistration buys ordering by trusting a registrar; an agent, an operator and
a verifier share no registrar. Block ordering substitutes for one. Nothing else
in the design needs a chain.
What this is not
Not identity (ERC-8004), not agent risk scoring
(ERC-8126), not authorization
(ERC-8196), not anchoring
(ERC-8263, ERC-8281),
not escrow (ERC-8183, ERC-8195), not judge selection
(ERC-8353). It composes with them rather than competing: an ERC-8353 gate can
seat its verifiers over these criteria and set its evidenceHash to the bundle
digest.
Tri-state verdicts are not the novelty either. ERC-8126 is Final and already
defines Passed, Failed, Inconclusive. What is new is the conjunction:
criteria frozen before the evidence exists, obligations typed and itemized, and
a contract-level rule that makes the mismatch unrepresentable rather than merely
detectable.
Questions I would like answered before opening a PR
- I have kept
Verdictdeliberately separate from ERC-8126’s
VerificationStatus, on the grounds that the two have different subjects:
Inconclusivereports that a verification layer reached no conclusion about an
agent, whileIndeterminatehere reports that evidence did not resolve a
single outcome against criteria fixed beforehand. The draft forbids mapping
between them in either direction. Is that boundary drawn in the right place, or
is there a case where one should be derivable from the other? - Is two bits per obligation the right encoding, or should the flags live
entirely in the off-chain criteria document with only its digest on-chain?
The design hinges on that choice, and I can argue it either way. - Should waiver authority be named on-chain, or is naming it inside the criteria
document sufficient? - Is there prior art I have missed for freezing acceptance criteria before the
evidence exists, as opposed to attesting after it does?
The draft is written and pre-submission. No number — editors assign those at PR
time against ethereum/ERCs. Happy to paste the
full specification text inline in a reply if that is more useful.