Receipts are an open format
A receipt is the dated file behind every published number. Nothing about it is private: any test tool can write one, and any tool can read one.
In short
A public format
The format is published as a schema anyone can check a receipt against, with a plain companion document beside it.
Run, or only claimed
A receipt says how far it can be trusted. One level means the tool that wrote it ran and scored the tests itself and kept a fingerprint of every answer. Another means the results were brought in from elsewhere and cannot be checked that way.
Bring your own results
Driftproof converts results from neighbouring test tools into receipts, and writes a small summary file other tools can read. Your own test tool can write receipts too.
The precise contract for tool authors, with the field names, levels and commands, is folded below.
The precise contract
The interop contract in full: schema, levels, converters and commands
Receipts are an open format.
A receipt is a hash-verified, dated record of a skill's with-vs-without eval run - and nothing about it is proprietary. Any harness is encouraged to emit receipts; any tool can consume them. This page is the interop contract: the schema, the honesty rules, the import converters, and the lightweight summary interchange.
The schema
The machine-readable contract is the JSON Schema (draft 2020-12), served at its canonical $id:
https://driftproofhq.com/spec/receipt.schema.json - receipt spec v0.13; the interop fields for imported results arrived as an additive revision in v0.3.1, v0.9 added what an imported receipt says about its source: the harness that produced the answers, the imported document and its sha256, and a notice for each thing the source did not record; v0.10 added which answer a run judged, its reply alone or its reply with the files it wrote; v0.11 added the preset a smoke run was made under, which no reader gives a verdict; and v0.13 adds the figures a source printed, hashed with the repository, the commit and each file read, beside a mark that the source gives aggregates only, so no reader gives that receipt a verdict
The human companion is spec/RECEIPT.md, and the full field-mapping guide for the import/export converters is interop.md. Validate any receipt with driftproof validate <file> or any draft-2020-12 validator. Prior schema versions (v0.1 to v0.12, v0.3.1 among them) are frozen in the repo; a receipt validates against the schema its own schema_version names.
DECLARED vs TESTED - the distinction that keeps receipts honest
Every receipt names its verification_level, and the two levels that matter for interop are not interchangeable:
TESTED- an eval suite was executed and judged under the emitting harness's control, with the full evidence chain: skill + suite content hashes, a sha256 of every generation that was graded, and a sha256 of every judge sample a verdict rests on. The schema enforces this - a receipt claimingTESTEDwithout the evidence chain does not validate.DECLARED- someone asserts results they cannot bind to hashed evidence. This is exactly what an import is: Driftproof did not run, hash, or judge another tool's generations, so a converted receipt is that tool's declaration, recorded faithfully - surfaceexternal, sourceimported/<tool>, hashes omitted rather than fabricated.
The consequence is structural, not cosmetic: drift verdicts are computed only between TESTED receipts. driftproof diff reports NOT MEASURED when either side is below TESTED, and a DECLARED receipt's badge reads not measured - declared numbers are context, never band-verified evidence. There is no path from a declaration to a verdict except running the suite.
Importing from neighboring tools
Working converters ship in the CLI for two neighboring skill-eval tools, for Anthropic's two eval formats, for Harbor job directories and for NVIDIA's skill benchmark cards:
driftproof import <results.json> --from agent-skills-eval
driftproof import <results.json> --from skillgrade
driftproof import <results-dir or aggregate-result.json> --from claude-plugin-eval
driftproof import <benchmark.json or iteration-dir> --from skill-creator
driftproof import --from harbor --with <job> --without <job>
driftproof import <checkout> --from nvidia-cards --commit <sha>
- agent-skills-eval - a test runner for agentskills.io-style skills (the same suite lineage Driftproof consumes). Its with/without-skill, per-assertion binary grading maps onto receipt cases with a real delta; single-grade cases are imported as single-sample (no bands, and the diff says so).
claude plugin eval- Claude Code's own eval command (2.1.269 and later) writesaggregate-result.json. The unit is the plugin, every skill it carries loaded at once. Each run is one draw; errored runs are kept out and listed with their reasons; a skill-fired indicator is recorded beside the score, never inside it.- skill-creator
benchmark.json- the document skill-creator's benchmark mode writes, and skill-up writes one per iteration. Runs are grouped by eval id, and each iteration imports as its own receipt. - Harbor job directories - one job run with the skill and one without, as the user declares them. Each trial's own
result.jsonis read, never a file inside a trial folder. Cases are keyed by task id and checksum, the delta is recomputed from the rewards of finished trials that carry one, over the tasks both jobs ran under the same verifier and timeout settings, and every trial or task left out is listed with its reason. - NVIDIA/skills benchmark cards - a git checkout at the commit given, its
benchmarks.jsonand eachBENCHMARK.md. The cards give one score and one uplift per dimension and agent, so each receipt carries those figures as the card prints them, with the commit and each file's git blob sha1, and the markaggregates_only: no verdict is read from it. Driftproof records the files it read and does not attest the author. - skillgrade - "unit tests for your agent skills": N trials per task, weighted graders, a 0–1 reward. Trials are genuine repeated runs, so per-trial rewards map onto
samples[]honestly. skillgrade has no baseline mode, so the imported receipt carries an empty baseline and anullcomparison - never a fabricated zero-baseline delta.
The full field mappings - including what is assumed where the upstream tool documents semantics but not a frozen schema - are in the interop guide.
The lightweight interchange: summary-json
Most consumers don't want the whole evidence chain - they want the verdict. driftproof export <receipt.json> --to summary-json emits a minimal, stable, flat summary (driftproof/summary v1): skill, model + provider + surface, with/baseline bands, delta ± uncertainty, the effect-floor verdict (PASSED / NO_EFFECT / REGRESSED / NOT_MEASURED), verification level, source, the receipt hash it summarizes, and an optional report URL. Keys are frozen; additions bump format_version. The exact shape is in the interop guide and snapshot-tested in the repo's gate.
A summary kept in a receipt directory is named <receipt base>.summary.json, which export --out <dir> does; badge <dir> and decide skip it by that name and its format, and under any other name read it as a receipt and refuse it, exit 4.
Emitting receipts from your own harness
If you run agent-skill evals, emitting receipts costs you a JSON serializer and buys your users a portable, self-verifying, dated record. Two honest paths:
- You ran a with/without suite yourself and can hash the generations and judge outputs → emit
TESTED, and the schema will hold you to the evidence chain. - You're converting or asserting results you can't hash → emit
DECLAREDwith surfaceexternaland omit the hashes - exactly whatdriftproof importdoes.
The receipt_hash is a self-hash over the canonical form (sorted keys, no insignificant whitespace) with the field itself removed - integrity, not yet authenticity; key signatures are the spec's stated next step. Questions, or want an emit-receipts PR for your tool? Open an issue - converters and PRs are offered, not demanded.
One format, two honest levels, and a hard wall between them: declarations are recorded, verdicts are earned by running the suite. That is the whole interop policy.