One eval run is a measurement that has to stay comparable to every run before it. That constraint — not the model call — is what shapes the pipeline. This page explains the mechanism; the sibling pages render what it produced.
Three gates — selection, multiturn, narration —
share this lifecycle: the same inputs, a per-item measure loop, the same two record tiers, the
same refusals. The loop as drawn — tool schemas → tool call → dispatch/validate → retry — is the
structured pipeline selection and multiturn run; narration
swaps that middle box out: it sends the production narration messages with no tools over a
pass schedule (the temp-0 pass plus the default-temperature passes), grades the prose
against supplied capability results, and its lines record constrained: false.
Where each gate’s oracle comes from differs too — the table further down.
serve.py stages a view rather than serving evals/ directly.Every input that can move a score belongs to exactly one named digest, so a corpus, grading or protocol change can never masquerade in the trend as a prompt or model effect (spec 14 §5a). An offline coverage test fails until each reachable harness module is claimed.
All sha256. Two shapes: a digest over a set of files, and a digest
over live artifacts. Sorting is load-bearing in the first — declaration order cannot change a
digest, only content can.
| digest | construction | moves when |
|---|---|---|
eval_set_sha |
the corpus manifest: sha256 over "<path>:<file sha>"
lines, one per graded set file, in sorted order |
any graded set file is edited |
grading_sha |
the same sha-of-shas shape over the gate’s declared grader and fixture-builder sources | a grader or the fixture it grades against changes |
protocol_sha |
canonical JSON of the protocol scalars, a newline, then sha-of-shas over the gate’s execution sources. The scalar set is closed both ways — a missing scalar is refused, and so is an extra one, which would otherwise be silently dropped from the digest | a scalar (context window, retry budget, constrained flag, temperature, runtime version) or any execution source changes |
prompt_sha |
three component digests over live runtime values — the selection surface, the tool schemas, the narration surface — NUL-separated so concatenation is injective, then combined | what the model reads changes. A comment edit elsewhere in the same module does not move it: the axis covers the surface, not the file |
model_digest |
read from the runtime’s tags endpoint — the manifest digest of the weights themselves | the weights differ. Content-addressed, so the same tag in a different store is the same digest |
One bound is recorded rather than papered over: the production capability layer is the system under test, not a provenance axis. Digesting it would make every line incomparable across any product commit and destroy the trend the ledger exists to draw, so that risk is carried by the re-run clause in LLM-ADR-002/004 — a human obligation, not a hash.
The ledger writer is the sole writer. Every refusal is fail-closed: it raises and appends nothing.
The one place a human is load-bearing, because prose faithful to a typed result is not a computable predicate.
An oracle is whatever decides correct; its one requirement is that it comes from somewhere other than the thing being tested. The three gates are three different answers to that question, which is why they are graded so differently.
| gate | oracle | consequence |
|---|---|---|
selection |
the real dispatch path — hand-authored intent labels, dispatch-verified: the label verifier replays every expected capability + arguments through the live capability layer against the seeded fixture and checks the expected outcome and answer against what it returns | graded mechanically; a label that drifts from what the product computes fails the verifier, so the corpus cannot silently disagree with the product — the hand-authored part is the intent, which is what the gate measures |
multiturn |
the same, over a conversation set | the same — the dangerous mode is a follow-up silently answered against the previous turn’s scope |
narration |
none that is mechanical — the automated grader is a screen, and the verdict is the developer’s | renders measured — never a pass — until an attestation line joins it |
The selection oracle is part of the product, which is fine for
the question the gate asks — it is independent of the model, the system under test. It is not
independent of the product: a wrong dispatch would be graded against confidently. That is the same
bound recorded above, wearing its other hat.
This page renders no measurement and fetches nothing: what it describes does not change from run to
run, and a committed copy of ledger numbers would be a claim the ledger could not back (spec 14 D3,
INV-6). For anything measured, open the Eval Ledger,
the Footprint Ladder, or
the Run Inspector.
Terms — docs/llm-assistant/glossary.md in the repo defines every one of these words once.
Named, not linked: the glossary is outside the staging view this page is served from, so a link here
would point at nothing.
Authorities: docs/llm-assistant/eval-telemetry.md (spec 14) and LLM-ADR-005;
the shapes above are implemented in evals/harness/provenance.py and
evals/harness/ledger.py.