Preserve the task definition
Use Hugging Face Datasets for loading, revision pinning, transforms, streaming and storage. Multivon’sCaseManifest is a small snapshot of the selected evaluation cases; it does
not replace your dataset pipeline. For grouped random splits, use established
splitters such as GroupShuffleSplit
and supply the resulting assignments here for leakage validation.
Two prompts can be identical while their source documents, expected answers,
or permitted actions differ. case_id names a case across edits; its content
digest detects edits. Without an explicit ID, the digest supplies the ID.
revision is an optional human label. Changing a label without updating
revision still changes the digest.
CaseManifest detaches cases from mutable input objects, rejects duplicate IDs,
and requires every case to belong to exactly one split when splits are supplied.
Cases with the same source_id cannot cross split boundaries. It cannot infer
that two differently named sources are related: supply source groups from your
data pipeline. Group paraphrases, page variants, and repeated sessions before
selecting held-out data.
Bring a Hugging Face dataset
Installmultivon-eval[datasets] from the development checkout. Load or transform
your dataset with the upstream library, then adapt a bounded evaluation set:
datasets.load_dataset(..., revision=COMMIT_SHA) and record
the repository and commit in provenance. A branch name can move. The bridge
preserves upstream cache fingerprints, but they are not semantic case IDs.
It accepts native split dictionaries and iterable datasets, and raises when a
selection exceeds max_cases (10,000 by default). Select or sample upstream;
the bridge will not silently truncate a dataset or decide your sampling policy.
load_jsonl and save_jsonl preserve tool expectations, traces, reference
outputs, IDs, revisions, and source groups. Unknown fields are rejected with
a line number. Metadata must be portable JSON; nonfinite numbers and lossy
non-string object keys are rejected. Materialize callable reference_output
values before exporting. Validation-only references do not enter the execution
case digest; the full dataset manifest still preserves string references.
Compare compatible cases
New reports pair unique case IDs only when content digests match. Reordering cases is safe. Changing context, expected answers, metadata, tags, tool expectations, or revisions makes the case unpaired. Explicit duplicate IDs are ambiguous and cannot support a paired test. Old reports without identity remain readable and show diagnostic prompt pairs. They do not produce a McNemar p-value or pass--fail-on-regression by default.
If you have independently verified their case definitions, use
--allow-legacy-identity to explicitly trust the old prompt pairing. The warning
remains in the comparison artifact. Prefer rerunning both versions on a frozen
dataset.
Grader dependency contracts (development)
The 0.19.0 dependency protocol extends suite locks beyond case identity. It records portable public settings and digests of private grader settings, inherited judge settings, the local Python source digest, Python/platform details and installed distribution names/versions using Python’s standard library. Judgeextra settings are hashed
rather than copied verbatim; common credential-like configuration names are also hashed.
Tuple/regex type markers prevent lossy JSON coercion from hiding configuration changes.
Reports still contain task data and public configuration. This is deliberately conservative: even an unrelated
package version change makes the environment differ.
Custom graders and opaque fields such as callbacks or Pydantic validator classes
need an explicit declaration before comparisons can be verified:
dependencies={} explicitly declares none.
Pass files={"schema": "schemas/invoice.json"} to bind an existing local artifact.
Named files are rehashed from their bytes for each snapshot; local file paths do
not enter the report. Missing files remain explicit issues. A declaration is your
assertion of completeness, not automatic discovery or validation of its contents.
For external model artifacts, declare the actual model revision as well as its
loader package. Pydantic JSON Schema alone does not capture custom validators.
Synchronous, parallel, asynchronous, imported-output and regrading runs retain a
pre-run lock and check it again afterward. Live runners prepare graders first.
For imported-output grading and regrading, explicitly call any required
grader.prepare() before the run to freeze generated criteria. These paths do
not add preparation calls, including when saved model-error trials need no grading.
Observed drift blocks verified comparisons and retains the post-run lock for inspection. Unknown dependencies, missing locks, legacy locks
without this protocol or a digest mismatch also make comparison gates
indeterminate. The legacy identity override applies only to reports with no
retained identity/trials and no lock; it cannot bypass recorded dependency drift.
Re-run both sides with the new protocol when migrating old locks.
These snapshots cannot observe changes restored between snapshots. Source hashes
cover on-disk Multivon Python files, not loaded bytecode or all third-party/native
files. Installed package metadata is not a verified build manifest. Remote model
aliases can change without their names changing, and callbacks can read undeclared
globals or services. Run from an immutable checkout/environment and retain native
provider logs. Declared compatibility is not complete experiment reproducibility.
cases_hash retains its legacy input/expected/context subset; strict case pairing
uses the full execution case digest separately.
Target and runner configuration (development)
report.execution records target settings before and after execution, plus runner
repeat, retry, concurrency and gate settings. Each retained trial has its own
trial.data["execution"]. With a provider journal, capture-start events persist
the corresponding execution snapshot before the target runs. Reports saved by
save_json retain the same snapshot as the returned report.
Built-in adapter snapshots include model, system prompt, sampling temperature,
output limit, portable request extras and selected routing settings. Supplied
native SDK clients expose selected public endpoint/timeout/retry settings;
custom client properties are not invoked for inspection. SDK defaults are not
resolved by constructing another client. Use the native HTTP events for actual
serialized requests and observed attempts.
Runner settings record the tracer’s class, not its internal configuration; declare
external tracing dependencies when they affect target behavior.
Declare a custom target’s implementation, configuration and external artifacts:
declare_target returns a wrapper and preserves synchronous/asynchronous and
case-aware calling conventions. It does not change the callable’s behavior or
discover closure state, runtime model weights, global services or custom client
hooks. Missing files and unrecordable configuration remain explicit issues. The
snapshot cannot detect a change that is restored between observations.
Comparison output lists execution_changes and execution_notes. A different
target is an expected experimental intervention, so it does not invalidate paired
case/grader statistics by itself. Unknown target configuration produces a note;
it is not an invented identity or proof of controlled causality. An observed
within-run target/file change invalidates a controlled comparison and suppresses
McNemar inference. Grader/case compatibility retains its separate strict rules.
Regrading labels the new execution as saved-output grading and preserves original
target snapshots in inherited_execution; it makes no new target calls.
For native adapters, adapter.with_system_prompt("new prompt") now returns a
copy of the same adapter with the replacement prompt and intact context handling.
The SDK client remains shared. Custom adapters must implement their own prompt
semantics; the old generic wrapper silently ignored the supplied prompt.
Inspect and regrade every attempt
Each new execution stores immutableTrialRecord snapshots with case input,
evaluation-time case data, output, trace, per-grader reasons and metadata,
latency, status, retry attempt, and repeated-run position. Aggregates remain
available, but no longer replace individual outputs. All retry attempts are
retained, including failed attempts before a successful retry.
regrade makes no target calls. Configured LLM graders can still make paid
judge calls. The result contains one row per original trial, including retry
attempts, with a parent_trial digest. These correlated rows are not an
independent sample for confidence intervals. Regrading with NotEmpty in this
example tests only whether text exists; it cannot establish decision accuracy.
Model errors remain model errors during regrading. Imported outputs without
measured target latency skip latency checks. Pass latencies_ms to
run_on_cases when those measurements are available. Legacy reports never
invent missing trials or individual scores from aggregate means.
Current evidence boundaries
- Development provider capture retains observed native requests, retries and usage on supported transports (see below). Unsupported/custom transports and missing responses remain explicit gaps; snapshots alone cannot establish full request or billing coverage.
- Arbitrary user callbacks can mutate inputs or external state. Snapshots do not provide process isolation or undo side effects. Existing case-level retries rerun the target; use them only when that is safe.
- Nonportable custom metadata leaves evaluation results available but sets
evidence_error. Those reports cannot establish verified identity or be regraded through this API. - Hashes detect accidental changes; they are not trusted signatures.
- Artifacts contain prompts, outputs, traces, and metadata. Keep confidential application data in your own controlled storage.
Retain provider attempts (development)
Built-in OpenAI and Anthropic clients use their SDK’s HTTP client factories and native retries. HTTPX hooks retain each serialized request, response body and unmodified native usage object. Trial evidence includes case identity, attempt, repeat position and target/judge role; preparation and reliability calls outside trials belong to the run capture. An arbitrary custom callback’s role may remain unknown. Evidence hashes detect edits; they are not third-party attestations.provider_evidence snapshot. Report-level evidence is
snapshotted before reporting and gates, so its state remains open; the journal
records the later run closure or exception. The saved and returned report use the
same snapshot. Regrading preserves parent evidence separately from new requests.
For a supplied SDK HTTPX client, attach
provider_http_hooks() (or
provider_http_hooks(asynchronous=True)) as its event_hooks. Keep SDK factory
defaults and your existing TLS/authentication settings. Google supports an
explicit httpx_async_client in native HttpOptions; the library leaves its
default async transport selection unchanged. Do not treat an empty capture as
proof that a custom callback made no API calls.
Missing responses or usage remain unknown, including retries that returned an
HTTP error without usage. The default report.costs tracker remains a partial
successful-text-judge estimate. Use the separate
provider accounting workflow to reconcile a closed
journal with upstream pricing and an explicit coverage declaration. Native
cache/reasoning/tool fields remain available; these estimates are not invoices.
The SQLite journal reuses native transactions with WAL and full synchronous
writes. One actual child-process SIGKILL test retained the pre-dispatch request
after reopening the journal. This does not test machine power loss, prove remote
execution or authorize automatic replay of side effects. Continue to use an
established runner such as Inspect for recovery scheduling.
Authentication headers and credential URL values are excluded, but prompts,
outputs, inline media and provider error content may contain sensitive data.
Treat reports and journals as private evaluation artifacts. Capture is currently
in memory unless a journal is supplied; it has no retention or size quota.
A frozen live smoke study
retained requests and native usage for 4/4 Anthropic calls; regrading two saved
targets made zero requests. Both strict target checks failed on punctuation and
remain failed in the artifacts. This validates a narrow capture path, not judge
accuracy or complete accounting.
