# description
Per-eval-harness-run attestation envelope binding {harness-identity, harness-version, model-identity, dataset, eval-code-commit, results-hash, runner-DID} to a cryptographic chain. Closes SYNTHESIS-acquisition Round 20 P1 [[ai-eval-harnesses]] EV1 ship-first action. Completes the harness tier in the 4-tier eval chain: sandbox (R21 SB1, cycle 307 ip.sandbox.run.attestation.v1) → harness (R20 EV1, THIS) → leaderboard (R15 B1, planned) → tracker (R16 M1, planned). When an eval-harness emits a score that lands on a leaderboard (R15 B1 cp/bench-attest@v1 cross-ref) or a tracker (R16 M1 cpExperimentReceipt), this attestation row sits between them in the audit chain — proving WHICH harness code, WHICH model version, WHICH dataset shape produced WHICH score. Designed for Inspect AI + Promptfoo (post-OpenAI acquisition 2026-03-09) + lm-evaluation-harness (EleutherAI) + DeepEval + RAGAS + TruLens 2.7 + LangSmith Evaluations + Phoenix Arize + Langfuse (post-ClickHouse acquisition Jan-2026) + Galileo (post-Cisco intent-to-acquire Apr-2026) + Patronus + Aporia + MLflow 3.9 Judge Builder + Weave (post-CoreWeave acquisition). One JSON Schema × every eval-harness runtime via a uniform binding shape.

# $comment
Discovery: https://ip.tekton.cc/.well-known/ip-knowledge.json (full descriptor) | Badge: https://ip.tekton.cc/api/badge/v1/attestation/eval.run.attestation.v1/<subjectSha256> (shields.io endpoint) | Free dry-run: POST https://ip.tekton.cc/api/credentials/dry-run with body {kind:"eval.run.attestation.v1", body:<candidate>} (no auth required, validates against this schema) | Bridge: https://ip.tekton.cc/docs/eval-attestation-bridge.md (registry manifest at /api/knowledge/eval/propose vs portable VC envelope produced by /api/credentials/dry-run; field-by-field map from lm-eval-harness results.json to both surfaces; closes the cycle-379 audit dual-eval-schemas P0) | Supply-chain bridge: https://ip.tekton.cc/docs/in-toto-bridge.md (in-toto Statement v1 + SLSA Provenance v1 projection: subject=model by modelVersionSha, resolvedDependencies=dataset/harness/eval-code by sha256, builder=runnerDid; digest bindings are in the signature pre-image, chain.* advisory) | Verification recipe: https://ip.tekton.cc/docs/verification-recipe.md (3-layer trust model + curl trail) | Revocation: https://ip.tekton.cc/credentials/status/v1 (W3C BitstringStatusList v1.0; check bit at credentialStatus.statusListIndex)

# x-controlMappingRefs.$comment
Cycle 685 (RC-600-P1-6 deferred — per-schema controlMappingRefs[]).

# x-controlMappingRefs.iso42001Aims[].note
AI system verification/validation — harnessVersionSha + datasetSha + evalCodeSha + samplingParams + cycle-661 sandboxTaskSetShaEcho cross-attestation invariant

# x-controlMappingRefs.iso42001Aims[].note
AI system records — resultsHash + chain.parentSha256 binds to upward experiment-receipt

# x-controlMappingRefs.iso42001Aims[].note
Data quality — contaminationCheck metadata (Berkeley RDI 2026 defense)

# x-controlMappingRefs.nistAiRmf[].note
Evaluation procedures — full pinning chain

# x-controlMappingRefs.nistAiRmf[].note
GenAI Profile — eval rigor + contamination defense

# x-controlMappingRefs.euAiAct[].note
Development/testing/validation — sandbox-run + eval-run chain (cycle 661 invariant)

# x-controlMappingRefs.iso42001RiskRegister[].note
Treatment cycle 661+673+675 — cross-attestation invariant + advisory warnings + artifactResolvers[]

# properties.schemaVersion.description
Semver of this schema. Bumps to 2.0.0 land at /credentials/eval-run/v2 — v1 stays immutable (see /docs/schema-versioning.md for the cycle-726 canonical bump-mechanics + soft-change-detection contract).

# properties.chain.properties.parentSha256.description
Sha256 of the canonical-JSON bytes of the parent attestation. For an eval.run the parent is typically the ip.experiment.receipt.v1 that produced the model being evaluated; eval.run can also chain DOWNWARD to ip.leaderboard.receipt.v1 (an eval-result is the canonical input the leaderboard ranks). ⚠ Cycle 499 (EHO-493-F7 + RC-480-F2 fan-out): eval.run.attestation.v1 sits between experiment-receipt (above) and leaderboard-receipt (below) in the 5-tier wedge but was OMITTED from the cycle-484 chain.* sweep. Adding it here closes the wedge-traversability gap the eval-harness audit flagged. Same caveat as cycle-493: the platform does NOT verify parent-existence at issuance — a syntactically-valid 64-hex sha256 satisfies this pattern but the bytes may not resolve in any attestation store. Consumers walking the chain MUST resolve parentSha256 against their own attestation registry.

# properties.chain.properties.parentKind.description
Kind identifier of the parent attestation. For ip.eval.run.attestation.v1 the parent is most-naturally an experiment-receipt (the training/fine-tuning run that produced the evaluated model) but can also be a pipeline-facet (an eval over raw upstream data without an intervening experiment).

# properties.chain.properties.parentAttestationId.description
Optional UUID of the parent attestation — convenience for consumers that index by id. parentSha256 is the authoritative cryptographic link.

# properties.chain.description
Cycle 499 (EHO-493-F7 P2 + RC-480-F2 P0 fan-out): uniform upward chain link to the experiment that produced the evaluated model. Complements the existing soft `evalRunIds[]`/`sandboxRunId` downward refs with a SINGLE upward parent so a verifier holding an eval-result can mechanically traverse to its training run + pipeline lineage.

# properties.runId.description
Unique RFC 4122 UUID v4 or v7 — the eval run's canonical identifier. Lets a consumer dedupe across retries + replays and link this attestation to a specific ip.attestation.event.v1 wire row via ipAttestationEventId.

# properties.harnessId.description
Stable handle for the eval harness — e.g. 'inspect-ai', 'promptfoo', 'lm-eval-harness', 'deepeval', 'ragas', 'trulens', 'langsmith-evals', 'phoenix-evals', 'langfuse-evals', 'galileo-evaluate', 'patronus-ai', 'mlflow-evaluate', 'wandb-weave'. Lowercase + hyphen + digit so the value doubles as a URL slug + docker-tag fragment. Communities own their own harnessId namespace; downstream verifiers cross-reference against a community-maintained registry.

# properties.harnessVersionSha.description
Sha256 of the canonical harness-release artifact. For PyPI-published harnesses: sha256 of the wheel file at the resolved version pin. For git-tracked harnesses: sha256 of the git tree at the run-time commit. Verifier walks: download artifact; recompute; compare. Without this binding, a harness author could silently modify scoring logic between submission and publication — the ip.eval.run attestation would still verify against a non-canonical harness.

# properties.modelId.description
Identifier of the model under test. Format is harness-defined and ecosystem-conventional. For OpenAI-compatible APIs: 'gpt-5.5-2026-04-14' or full URL. For HF: 'meta-llama/Llama-3.1-70B-Instruct'. For Anthropic API: 'claude-opus-4-7' or full model+timestamp tag. For local: 'safetensors:<sha>'. CP doesn't enforce naming — the value is opaque to the wire schema; semantic verification is a downstream concern.

# properties.modelVersionSha.description
Optional but recommended: sha256 of the canonical model-weights artifact. For closed-API models where weights aren't accessible, leave absent; the modelId + provider DID are then the only identity anchors. For OSS / on-prem models, sha256 of safetensors / GGUF / etc. — pins which weights actually ran. Defeats the silent-version-bump class of contamination (R19 E1 / R17 I1 cross-ref).

# properties.datasetSha.description
Sha256 of the canonical dataset bytes the harness ran the model against. For public benchmarks (MMLU, HELM, etc.): sha256 of the canonical release. For private/held-out splits: sha256 of the held-out subset. For RAG evals: sha256 of the corpus + query set. For multi-file datasets: sha256 of the canonical-stringified manifest listing each file's individual sha. Without datasetSha, a harness could swap easy questions for hard between runs.

# properties.evalCodeSha.description
Sha256 of the canonical eval-code bytes — the actual scoring logic, prompts, judge prompts, rubrics, post-processing. For Inspect AI: sha of the .eval file. For Promptfoo: sha of promptfooconfig.yaml. For lm-eval-harness: sha of the task definition file. For RAGAS: sha of the metric configuration. The point: when an attestation later says 'this model scored 0.85 on MMLU', a downstream verifier can re-run the exact same eval-code against the exact same dataset and reproduce the score.

# properties.submittedAt.description
Epoch milliseconds when the eval run was submitted to the harness. Matches the existing submittedAt + signedAt + receivedAt convention used across CP manifests.

# properties.completedAt.description
Epoch milliseconds when the harness completed scoring + emitted the result. Optional — some harnesses (Promptfoo CI mode, Inspect AI synchronous) emit submittedAt + result together; others (lm-eval-harness with model_args=tensor_parallel) timestamp both. When present, completedAt >= submittedAt.

# properties.runnerDid.description
DID of the entity that ran the eval. did:web for institutional runners (Scale Labs / Princeton HAL / Apollo Research / AISI / OpenAI Internal); did:key for individual researcher submissions. The DID resolves to a JWKS that can verify the `signature` field below. LOAD-BEARING for the eval tier's independence: an eval is INDEPENDENT only when runnerDid is a party DISTINCT from the model's owner/vendor (see modelOwnerDid). A vendor running an eval on its OWN model (runnerDid == modelOwnerDid) is a SELF-EVALUATION, not independent third-party evidence — the dry-run emits a non-blocking `self_eval` advisory in that case (cycle 1170).

# properties.modelOwnerDid.description
OPTIONAL DID of the OWNER/VENDOR of the evaluated model (the party whose model this is — e.g. did:web:openai.com for an openai/* model). Cycle 1170 (adversarial-auditor aa-1168-P1): pre-1170 the eval-tier independence claim ('an independent party ran this eval') was structurally inexpressible — there was no owner field to compare against runnerDid, so a vendor self-grading its own model (did:web:anthropic.com evaluating anthropic/claude-*) raised NO warning, the canonical leaderboard-gaming risk. Populate this with the model owner's DID to make 'runner != owner' a CHECKABLE in-band fact. When modelOwnerDid == runnerDid the run is a SELF-EVALUATION (structurally valid — a vendor MAY publish its own eval — but NOT independent third-party evidence); the dry-run emits a non-blocking `self_eval` advisory (mirrors review's subjectAuthorDid self_review + governance's self_audit). Omit when the owner DID is unknown — but then runner-independence is NOT in-band verifiable. ⚠ NOT in the embedded `signature` pre-image (cycle 1170, same posture as review.subjectAuthorDid per cycle 1155): an offline signature-only verifier can have modelOwnerDid rewritten/deleted undetected, so for tamper-evident runner-independence verify the full-body W3C DataIntegrityProof envelope at /credentials/<sha>/v1, not the embedded signature.

# properties.results.description
Harness-emitted scoring output. Format is harness-defined (different metric schemas across MMLU vs HELM vs RAGAS vs LangSmith). When present, the `resultsHash` below MUST be the sha256 of canonical-JSON(results) — so downstream verifiers can confirm the results body wasn't tampered with after signing. Optional because some workflows defer results to an external store (ipAttestationEventId then carries the pointer).

# properties.resultsHash.description
Sha256 of canonical-JSON(results). Required when `results` is present; lets a verifier re-derive the hash from the cached results body without re-running the eval. Functions identically to a Merkle root for the run's score payload.

# properties.scaffoldDelta.description
Optional scaffold-delta metric per R15 P1: GAIA Claude Sonnet 4.5 documented a 7pp scaffold delta with Princeton HAL. When the harness uses a scaffold layer (multi-shot reasoning, tool-use orchestration), this field surfaces the delta between bare-model performance and scaffolded performance so downstream consumers can compare apples-to-apples across reports that name the same model but use different scaffolds.

# properties.contaminationCheck.properties.method.description
Contamination-check methodology applied. 'none' = harness didn't run a contamination check (acceptable for live-eval-time post-cutoff datasets); explicit so downstream consumers know what assurance level they have.

# properties.contaminationCheck.properties.overlapRatio.description
When method is n-gram-match or embedding-similarity: fraction of dataset items that overlap with the model's training corpus (when knowable). When method is canary-string: fraction of canaries the model surfaced verbatim (high = contamination evidence).

# properties.contaminationCheck.description
Optional contamination-check metadata. R15 P1 LMArena scandal (2025-04 36-Llama-4-variants) + R21 P2 Berkeley RDI 2026 (8 benchmarks exploitable to ~100%) establish contamination as the load-bearing concern in eval attestation. When the harness ran a check, surfacing the method + overlapRatio lets downstream readers weight the eval-result-attestation accordingly.

# properties.judgesDigest.description
When the harness uses LLM-as-judge scoring (Promptfoo + RAGAS + DeepEval + LangSmith all support this), the canonical digest of the judges manifest. Chains to the same judgesDigest field used in CP's brief/artifact/eval-result manifests (cycle-303 derivationRecipes documentation applies — sorted by judge identifier, lexicographic ascending; projection includes (id, agentTag, weight, judgeTier|'', judgeIntelligenceScore|0, judgeIpCidr|'', receivedAt)).

# properties.sandboxRunId.description
When the eval ran inside a sandbox (R21 SB1 ip.sandbox.run.attestation.v1; cycle 307), the runId of the sandbox-run attestation. This is the upward chain link — eval-run (this) → sandbox-run (SB1) → wire-event-row (R11 T1). A downstream verifier can walk both attestations and confirm consistency: sandbox.taskSetSha must match the eval-run's datasetSha for the same eval pass. ENFORCEMENT (cycle 661, EHO-659-F1 P0 closure): when sandboxRunId is present, sandboxTaskSetShaEcho is REQUIRED (see below) and MUST equal datasetSha. The dry-run validator at POST /api/credentials/dry-run rejects with code='sandbox_taskset_mismatch' otherwise; the schema-level allOf conditional makes the prose contract enforceable bytes so an adversarial vendor can't chain a fabricated sandbox→eval pair that names datasetSha=MMLU-full but sandboxRunId pointing at a sandbox attestation with taskSetSha=MMLU-easy-subset (the Berkeley RDI 2026 / LMArena 2025-04 contamination pattern).

# properties.sandboxTaskSetShaEcho.description
Cycle 661 (EHO-659-F1 P0 closure): when sandboxRunId is present on an eval-run attestation, the issuer MUST echo back the sandbox attestation's taskSetSha here. The allOf conditional below enforces sandboxTaskSetShaEcho === datasetSha — the sandbox-attestation contract says taskSetSha identifies the task set the sandbox actually scored; the eval-run says datasetSha is the canonical bytes the model was evaluated against. If they don't match, the cross-attestation chain is broken (the sandbox scored a different task set than the eval-run claims) and the platform refuses the chain at dry-run + propose time. Pre-cycle-661 this invariant was documented only in prose; an adversarial vendor could chain mismatched sandbox + eval attestations and both validated clean. ECHO rather than RESOLVE because the platform doesn't (today) walk the attestation store at validate-time — the issuer is on the honor system to populate the echo correctly, but the schema-level conditional makes lying about it require BOTH a mismatched sandbox AND a mismatched eval signature pre-image. Future cycles may add server-side resolution (sandboxRunId → attestation store → real taskSetSha lookup) as defense-in-depth.

# properties.ipAttestationEventId.description
When this eval run was emitted as a ip.attestation.event.v1 row (R11 T1) to the platform's Kafka/Tinybird/ClickHouse pipeline, the eventId of that wire row. Lets a consumer cross-reference an eval-run attestation back to the per-event audit log without re-deriving any hash.

# properties.signature.description
Ed25519 signature (128 hex chars = 64 raw bytes) over the canonical-JSON bytes of (runId ⊕ harnessId ⊕ harnessVersionSha ⊕ modelId ⊕ modelVersionSha? ⊕ datasetSha ⊕ evalCodeSha ⊕ submittedAt ⊕ runnerDid ⊕ resultsHash? ⊕ scaffoldDelta? ⊕ contaminationCheck? ⊕ judgesDigest? ⊕ sandboxRunId? ⊕ ipAttestationEventId?). Verify against the publicKey published in the runnerDid's JWKS. RFC 8037 (Ed25519 in JWS) canonicalization rules apply: JCS (RFC 8785) ordering on the inner object. ⚠ INTEGRITY GAP (aa-824-P0-1, cycle 848 honest disclosure): `chain.*` and `extra` are presently OUTSIDE this signature pre-image. A wire-path or post-hoc rewrite of `chain.parentSha256` / `chain.parentKind` / `chain.parentAttestationId` does NOT invalidate this `signature`. Offline verifiers using `signature`+`publicKey` (the documented embedded-verification path) MUST treat `chain.*` as ADVISORY pointer-shape, NOT cryptographically bound to this attestation. For full-integrity verification including chain pointers, fetch the W3C DataIntegrityProof envelope from /credentials/<sha>/v1 and verify against the proof.cryptosuite=eddsa-jcs-2022 signature (which signs the FULL canonical-JSON body including chain). Cycle-484 added the chain block; cycles 778-784 swept it; the signature pre-image was not re-derived. Migration target: v2 schema slug ($id pin per cycle-462). See cycles 825-829 (5/5 wedge-tier ring) + cycle 830 (verification-recipe.md dual-path teaching) for the canonical write-up; cycle 848 fans this disclosure to the 12 remaining chain-bearing leaf schemas in one batch.

# properties.publicKey.description
Ed25519 public key (32 raw bytes = 64 hex) corresponding to the signature above. Verifier MAY prefer to resolve via runnerDid's JWKS — this field exists for offline / embedded verification when network resolution is unavailable.

# properties.samplingParams.description
Inference-time sampling configuration used during the eval run. Cycle 404 (A/B-comparator AB-403-4 P1 fix): HELM / lm-evaluation-harness / MTEB all emit these and reproducibility is impossible without them. lm-eval's `gen_kwargs` map directly here; HELM's `decoding_parameters` likewise. Without sampling params, the same model+code+dataset combination can disagree at the third decimal place across re-runs — defeating the chain-of-custody claim that 'skeptic can re-run + check the chain'.

# properties.samplingParams.properties.temperature.description
Sampling temperature. 0 = deterministic greedy decoding; 1 = default for most APIs; values above 1 increase entropy. lm-eval-harness `--gen_kwargs temperature=...`; OpenAI/Anthropic API `temperature`. Re-runs at different temperatures are NOT comparable for benchmark scoring.

# properties.samplingParams.properties.topP.description
Nucleus sampling cutoff (top-p). 1.0 = no truncation; lower values restrict the token candidate set. OpenAI/Anthropic API `top_p`; lm-eval `--gen_kwargs top_p=...`.

# properties.samplingParams.properties.topK.description
Top-k candidate truncation. 0 = no truncation. HuggingFace `top_k`; not exposed on every API but recorded for re-runs against local models.

# properties.samplingParams.properties.maxTokens.description
Maximum tokens generated per response. lm-eval `--gen_kwargs max_new_tokens=...`; OpenAI `max_completion_tokens`; Anthropic `max_tokens`. Affects timeout boundary + truncation behavior on long-form answers.

# properties.samplingParams.properties.seed.description
PRNG seed for sampling determinism. lm-eval `--seed`; HF Transformers `set_seed()`. Re-run with the same seed should reproduce token-for-token on temperature>0 paths when the API honors it (some APIs ignore seed; record what was REQUESTED).

# properties.samplingParams.properties.numFewShot.description
Number of in-context examples prepended to each prompt. lm-eval `--num_fewshot`; HELM `adapter.num_train_trials`. Same model + same eval-code can differ by 30 percentage points across MMLU-0shot / MMLU-5shot / MMLU-25shot — REPRODUCIBILITY IS IMPOSSIBLE without this field. The single highest-leverage addition in cycle 404.

# properties.samplingParams.properties.nSamples.description
Number of dataset items actually scored. HELM `num_eval_instances`; lm-eval typically `len(dataset)` minus skipped items. Distinguishes a partial run (smoke-test on N=100) from a full eval (N=14042 for MMLU). Without this, score variance can't be assessed.

# properties.samplingParams.properties.nTrials.description
Number of sampling trials per item. For temperature>0 evals where score = mean over k samples per question (HumanEval pass@k, MATH best-of-N). Defaults to 1 for greedy decoding.

# properties.samplingParams.properties.generationKwargs.description
Open slot for harness-specific generation kwargs not covered above (stop sequences, presence/frequency penalties, repetition penalty, custom sampling configs). lm-eval `--gen_kwargs` parses to this shape. Consumers MUST tolerate unknown keys (forward-compat). KEEP small (~10 fields max); promote to top-level if a key becomes widely used across harnesses.

# properties.mtebTaskType.description
MTEB (Massive Text Embedding Benchmark, EleutherAI / HuggingFace) task category. Cycle 404 (AB-403-4 P1 fix). MTEB leaderboards stratify by task type — a score of '0.65 nDCG@10' is only meaningful when paired with the task category that defines the metric. Required field when harnessId='mteb'; optional otherwise. The 10 enum values match MTEB 1.x's TaskType taxonomy (https://github.com/embeddings-benchmark/mteb#tasks).

# properties.extra.description
Open extension slot — harness-specific payload (hardware spec, inference-engine version, batch size). Consumers MUST ignore unknown keys (forward-compat policy mirrors ip.attestation.event.v1 + ip.sandbox.run.attestation.v1). NOTE: sampling parameters (temperature/topP/seed/numFewShot/etc.) and MTEB task type have been promoted to first-class fields in cycle 404 — prefer `samplingParams` and `mtebTaskType` over stuffing them here.

# properties.equivalenceClassSha256.description
Cycle 503 (eval-harness-operator EHO-493-F5 P1 fix): optional cross-harness join key. Sha256 of the canonical-JSON {modelId, datasetSha, mtebTaskType?} triple — collapses the same {model, benchmark} evaluation across DIFFERENT harnesses (lm-evaluation-harness, Inspect-AI, DeepEval, OpenCompass, mteb-engine) into a single equivalence class. Pre-cycle-503 a comparator running 'how do harnesses agree on Llama-4-70B against MMLU-Pro' had to join 5 unrelated rows by string-matching modelId + datasetSha client-side; with this field, a server-side index or downstream consumer can group attestations by equivalenceClassSha256 directly. mtebTaskType is INCLUDED in the hash when present (an mteb harness running 'Classification' vs 'Retrieval' against the same model+dataset is a DIFFERENT equivalence class — the leaderboard scores aren't comparable). Issuer derives this by canonicalizing the sub-object then sha256-hashing; the platform's dry-run + propose surfaces emit the computed value alongside the attestation so an issuer can verify their derivation matches the server's recipe. Optional for back-compat — pre-cycle-503 attestations don't carry the field; consumers join on (modelId, datasetSha, mtebTaskType?) tuple as the fallback.

# properties.artifactResolvers.description
Cycle 675 (eval-harness-operator EHO-659-F5 P1 closure): optional URI hints the issuer commits alongside each sha-bound artifact (harnessVersionSha, datasetSha, evalCodeSha, modelVersionSha, sandboxVersionSha echoed via sandboxTaskSetShaEcho) so a verifier can bootstrap re-run without out-of-band knowledge of where each sha resolves. Pre-cycle-675 the schema described the verifier-path as 'walk: download artifact; recompute; compare' — but the platform exposes no /api/artifacts/by-sha/<sha256> resolver, and held-out dataset splits have no public mirror. A regulator handed an eval-run attestation couldn't bootstrap re-run; the 'skeptic can re-run' claim from /.well-known/ip-knowledge.json assumed the skeptic ALREADY had the artifacts. This array IS issuer-asserted, NOT platform-verified: the platform does not fetch the URI at issuance + does not recompute the sha. Consumers re-fetch + recompute themselves — the URI is just a HINT pointing where to start. Mismatch between the issuer's hint and the actual bytes is the verifier's signal to refuse the attestation. See /docs/verification-recipe.md §'L4: Artifact resolution' for the full trust model.

# properties.artifactResolvers.items.properties.sha256.description
The 64-hex sha256 this URI resolves to. MUST equal one of the attestation's sha-bound fields (harnessVersionSha / datasetSha / evalCodeSha / modelVersionSha / sandboxTaskSetShaEcho / etc.) — the verifier cross-references by sha-match to identify which artifact this resolver hints at.

# properties.artifactResolvers.items.properties.uri.description
HTTPS URI where the issuer believes the canonical bytes (whose sha256 matches the sha256 field above) can be re-fetched. Common patterns: 'https://files.pythonhosted.org/packages/...whl' for PyPI wheels (lm-evaluation-harness, Inspect AI, Promptfoo packages); 'https://huggingface.co/datasets/<repo>/resolve/<commit>/<file>' for HF Hub datasets; 'https://github.com/<org>/<repo>/releases/download/<tag>/<artifact>' for GitHub-released eval-code; 'ipfs://<cid>' for IPFS-pinned artifacts (decentralized fallback when the primary mirror disappears). The platform does NOT validate that the URI resolves; honest-disclosure mirrors the cycle-493 parentSha256 posture.

# properties.artifactResolvers.items.properties.artifactRole.description
Which sha-bound field this resolver targets. Lets a verifier filter the resolver array by role (e.g. 'show me only the modelWeights URIs') without re-deriving the role from the sha. datasetHeldOutSplit is distinct from dataset because held-out splits typically have NO public mirror — issuer SHOULD provide an HTTPS URI with operator-side auth proof OR an ipfs:// fallback; 'other' is the escape hatch.

# properties.artifactResolvers.items.properties.mirror.description
Optional canonical-mirror classifier — lets a consumer route to the right resolver library (pip cache for pypi, huggingface_hub for hf hub, etc.) without parsing the URI host. operator-private flags that the URI requires the issuer's own auth (HF private dataset, S3 with bucket policy) — the verifier needs out-of-band credentials.

# properties.artifactResolvers.items.properties.freshAsOf.description
Optional epoch ms when the issuer last verified the URI resolved to the expected sha256. Sets the verifier's expectation: 'this hint was good as of T; if you fetch today and get a different sha, the mirror has moved.' Pre-2020-01-01 timestamps are sanity-rejected.

# allOf[].$comment
Cycle 498 (eval-harness-operator EHO-493-F3 P1 fix): the cycle-404 mtebTaskType field's description has always claimed 'Required field when harnessId=mteb' but no allOf branch enforced it. An MTEB attestation could omit mtebTaskType and still validate clean — defeating the cycle-404 contract that MTEB leaderboards need the task category to interpret the metric. This conditional makes the documentation load-bearing.

# allOf[].$comment
Cycle 661 (eval-harness-operator EHO-659-F1 P0 closure): when sandboxRunId is present, sandboxTaskSetShaEcho is REQUIRED. The dry-run validator separately enforces sandboxTaskSetShaEcho === datasetSha (a JSON Schema can require field presence but can't easily express equality between two sibling fields without burning a $data ref — handled at the validator layer in app/api/credentials/dry-run/route.ts). This conditional makes the echo field's presence load-bearing at the schema layer; the equality check is the validator layer's job.

# allOf[].$comment
Cycle 1058 (schema-prober P1-2 fix): resultsHash.description has always said 'Required when results is present', and the dry-run validator recomputes sha256(canonical(results)) === resultsHash when BOTH are present (resultsHashMismatch) — but nothing enforced PRESENCE, so a body with results + no resultsHash validated clean, leaving the inlined results body un-tamper-evident (a downstream verifier has no hash to check against). This conditional makes the documented requirement load-bearing at the schema layer (Ajv enforces it on dry-run AND on any stock third-party verifier); the content-equality check stays the validator layer's job.