Add eval-result predicate (AI/ML evaluation results) - #575
Conversation
Signed-off-by: kraxo <kraxo@b7n0de.com>
|
I've checked the example I posted in #565 against the PR's final field set. All required fields are present and typed as specified, threshold is a decimal string, subjectProfile is receipt, and the optional receipt and harness blocks match. One migration note: the example carries the provisional predicateType https://b7n0de.com/attestation/eval-result/v0.1 — on merge it should re-emit under the in-toto.io URI. I'll regenerate it against the merged version. |
|
Thanks for checking your example against the final field set, and for confirming the fields line up on your side too. Agreed on the predicateType. The current https://b7n0de.com/attestation/eval-result/v0.1 is provisional. On merge I will move the spec header (Type URI and Version) and every example statement to the in-toto.io namespace, so the type reads https://in-toto.io/attestation/eval-result/v0.1, and I will add the redirect line per the new-predicate guidelines. Final name, version and file placement per your directory convention. If you prefer something different, I will match it. Once it lands, please regenerate your example against the merged predicateType. Both implementations re-emitting under the same type keeps the canonical bytes and content roots agreeing byte for byte, and that is the part worth preserving. |
Signed-off-by: kraxo <kraxo@b7n0de.com>
Signed-off-by: kraxo <kraxo@b7n0de.com>
Signed-off-by: kraxo <kraxo@b7n0de.com>
|
Three corrections pushed, all additive, one file, +12/-2:
All three came out of the discussion in #565 with @ppcvote and @Ganador1. DCO and Kusari Inspector are green. The lint workflow is waiting on maintainer approval, so markdownlint has not run here; locally it is clean with the version pinned in @in-toto/attestation-maintainers could you approve the workflow run, and could this go on the agenda for the next maintainers meeting? Happy to adjust anything, including splitting the three corrections into separate PRs if you would rather review them apart. |
The PR description scopes anchors[] out deliberately, but the spec text still carried the field in the schema block and in the field list. External time anchors are not eval-specific and belong in their own discussion after this PR lands. Signed-off-by: kraxo <kraxo@b7n0de.com>
proofbundle discards the exact score after the comparison; the frozen v0.1 evidence class is THRESHOLD_VERDICT_VERIFIED. Without an observed value a generic consumer can authenticate the verdict but cannot recompute it, so the field description no longer reads as a recomputable relation. Signed-off-by: kraxo <kraxo@b7n0de.com>
The previous wording (how much a pass is worth) read more normative than the field is. The value is the issuer's own declaration; external corroboration belongs in separately referenced evidence. Signed-off-by: kraxo <kraxo@b7n0de.com>
|
Read the three corrections against the diff. They address the concern, and the third one is a better answer than the field I suggested.
Stating the non-claim costs producers nothing and cannot go stale, whereas a The general absence rule reads correctly to me:
One optional refinement, non-blocking and easy to scope out. The non-claim is symmetric, but its consequences are not, and a consumer deciding how much to lean on
Both of the safety-shaped examples in the doc ( Thanks for tracing the |
The non-claim itself is symmetric; what follows from it is not. For a claim about what the subject achieves, an under-detecting harness understates the subject. For a claim about what it withholds or refuses, the same harness yields passed: true for a subject that did not withhold it. This is a property of the document, not general advice: the first use case is refusal_rate >= 0.98, the second is release gating, and the single embedded example carries that same claim. All three sit on the second side, so a reader who takes the non-claim seriously and then looks at the example is standing exactly in that case. Descriptive, no RFC 2119 keyword — it adds no obligation. Signed-off-by: kraxo <kraxo@b7n0de.com>
Signed-off-by: kraxo <kraxo@b7n0de.com>
|
Agreed, and thank you for the careful read. The second branch is not hypothetical in this document. The private-model use case and the inline example both use What the document does not fix is which class the harness counts as a positive, and the direction of the error follows from that rather than from the wording of the claim. So the note stays conditional. My first attempt at it did not: it asserted that the examples above and below fall on the second side, which the predicate does not establish. I have replaced it with the form below. It is under Non-claims as informative text, without a normative keyword:
That keeps the consequence tied to the semantics of the measured event rather than assuming one universal direction for every metric or positive-class convention. After this commit I will hold the diff stable for maintainer review, apart from changes requested during review. Broader detector-characterization work remains separate. And on the harness mismatch, credit is still yours. Treating the digest binding as a premise is what exposed the gap between the worked example and the spec text. I would not have inspected that boundary otherwise. |
|
Worked-example update relevant to the anchors[] discussion: the transparency log referenced in the eval-result examples now takes public submissions and issues offline proof bundles. An eval bundle's sha256 can be notarized with one POST; the receipt carries an RFC 6962 inclusion proof and a c2sp.org/tlog-proof bundle under a 7-witness quorum, so a reviewer can re-verify an anchors[] target fully offline. |
|
Thanks for the update, and it lands on the right side of the scope line for this PR. I verified one of that log's proof bundles independently before replying, an existing leaf rather than one I submitted, so this exercises the read and verify path and not the For this PR nothing changes. The diff has been stable since 35c83da. |
|
The diff has been stable since 35c83da, and this is a design question rather than another 1. Role separation: producer, evaluator, verifier. 2. Should the salted commitments be mandatory only for private profiles? 3. Generic evidence references instead of the Appendix — one open alternative rather than a proposal: Two process asks, repeating the ones from two weeks ago rather than adding new ones: |
Closes the ask in #565 (proposal discussion since 2026-07-03), as offered there on 2026-07-18.
What this adds
eval-result.mdper the ITE-9 template plus one line in the predicate directory: a predicatefor signed, offline-verifiable AI/ML evaluation results. A claim is a machine-checkable
metric <comparator> thresholdverdict over N samples, with salted model/dataset commitments,an optional per-sample RFC 6962 Merkle root, an optional pre-registration binding, and an
explicit
assuranceLevel(self_attested | third_party | reproduced | enclave_attested).Protobuf bindings follow as a separate PR, per the SVR precedent (#470 -> #519 -> #537).
Changes since the initial submission
Additive, all in the one file, all out of the discussion in #565 and in this thread:
harnessgained an optional
digestbinding the exact harness artifact; a general rule that absence ofan optional field means no claim is made and consumers MUST NOT synthesize a default from it;
an explicit non-claim that this predicate does not establish that the harness or grader is fit
for purpose;
passedstated as a signed threshold verdict;assuranceLevelmarked asissuer-declared;
anchors[]removed (887708f); and an informative note on the asymmetricconsequences of the harness non-claim. The diff has been stable since
35c83da.Why a new predicate
Discussed in #565: test-result carries PASSED|WARNED|FAILED plus test names but no
metric/threshold/dataset digests, commitments or per-sample structure; SVR's property list
would need a schema re-invented inside a free-form field. eval-result keeps the claim shape
fixed so a policy engine can evaluate "did model M clear threshold X on benchmark Y" without
parsing prose out of a system card.
Scope, pinned
Metric evidence only. Not an agent-decision attestation, not an action authorization, no
decision fields will be added (boundary suggested by @clementineCU in #565 and kept). A
separate decision-oriented predicate MAY reference signed eval-result statements by digest.
The attestation proves who signed which claim and that it verifies offline, not that the
metric is true, the benchmark well designed, or the model safe.
Maturity evidence
decision-crossimpl-schema-conformantin the conformance corpus: an independently implemented decision receipt binds an eval-result evidence statement by digest, both implementations agree byte-for-byte on canonical bytes and content roots (decision root97e1d74b…), recorded schema-conformant against the published schema, vendored as pure data with permanent attributionTwo design points flagged for review
the DigestSet definition as an immutable reference). Its sha256 is a documented binder over
commitments, Merkle root and timestamp, marked by an explicit
subjectDigestNote. Asoffered in New predicate proposal: eval-result (AI/ML evaluation results) #565: the receipt-as-subject digest-set question stays open for review here,
and we are happy to switch to a custom digest-set key before merge if you prefer.
contentRootAlg, naming thecanonicalization the content root is computed over; ignorable by generic consumers per the
spec's parsing rules.
Note
anchors[](external time anchors over a canonical root, drafted with @MarkovianProtocol in#565) is deliberately NOT part of this PR. The thread consensus is that it is not
eval-specific and belongs as a shared optional field; we would bring it as its own
discussion if there is interest.
DCO signed. markdownlint last ran clean locally at
f2c26cb(pinned 0.49.1, rc=0); therepository lint workflow is still awaiting maintainer approval, so it has not run here. Happy
to adjust naming, casing or file placement to match directory conventions.