Build on the verifier.
Anything built on it is one of two things: a tool that produces a record, or a tool that checks one. This is the shortest route from nothing to a verdict.
Start with the two rolesTwo roles.
- Emitter
- Produces the record: the inputs as they were, the claimed output, a manifest with every file's SHA-256 digest, and the rule it ran under.
- Receiver
- Holds its own pinned copy of the rule, runs the verifier on the record on its own machine, and acts on the verdict: OK, REJECT or ERROR.
Every tool anyone builds is one or the other, or both. The rule is yours. The verifier checks one thing: that the output is the deterministic result of the committed inputs under the committed rule.
Five steps.
Pick a deterministic workflow
Same inputs, same rule, same answer, every time. A total, a lookup, a rule table, a log replay, a build. Not a model call.
In the repo:
examples/, 54 pilots, one shape each.Write the rule
One JSON spec: the output type, the primitive that recomputes it, and the comparator. The receiver keeps its own copy and pins it by digest.
In the repo:
examples/climate_emission_minimal/spec_pinned/climate.spec.jsonBuild the bundle
A directory: the inputs, the claim under
outputs/, the rule copy underspec/, andmanifest.jsonwith every digest. The emitter SDK writes it.In the repo:
audit_bundle/emitterandexamples/climate_emission_minimal/_build_bundle.pyRun the verifier
Offline, on the receiver's own machine, with the receiver's own copy of the spec and the kit. The bundle is the one input.
veriker --bundle-dir bundle --spec-anchor receiver/climate.spec.json --primitives receiver/auditor_kit.py --verdict-out verdict.jsonIn the repo:
veriker/cli/verify.py, orpython -m verikerAct on the verdict
Exit 0 is OK. Exit 1 is REJECT: the record is bad. Exit 2 is ERROR: the verifier could not conclude. ERROR never becomes OK. The verdict file carries the reason codes.
In the repo:
VERIFIER_CONTRACT.mdandaudit_bundle/plugins/REASON_CODES.md
Three tracks.
Same five steps, three depths. Pick the one that matches how you work.
With an assistant
- Tell it the number you want checked. Ask whether the same inputs always give the same answer. If not, pick again.
- Paste the climate spec file and ask for one like it. Check that the primitive it names is in the appendix below.
- Paste the climate build script and ask for one for your files. Check that it writes only the files you listed.
- Run the command yourself, on your own machine, and read the exit code. Never take its word that the run passed.
- Paste a REJECT back and ask what the reason code means. The appendix lists the codes a first build usually meets.
In Python
- Start from the closest shipped pilot: climate for a sum, tabular for a group-by, event log replay for a log of events.
- Copy its spec file from
spec_pinned/. Rename the output type. Keep the comparatorexactunless you can say why. - Copy its build script and swap in your data. Keep
BundleContentandwrite_bundleas they are: they do the digests. - Copy
auditor_kit.pyif your rule names a primitive the verifier does not ship, and pass it with the--primitivesflag. - Change one byte of an input and run. Fix its digest in the manifest and run again. The second run is the one that counts.
Into a system
- Start at the step that already writes a number someone must answer for: a total, a score, an eligibility result.
- The receiving side writes the spec and pins it by digest. The producer gets a copy of it and no authority over it.
- The emitter hooks in where that number is written. It snapshots the inputs and writes the claim and the manifest.
- The receiver runs the verifier on its own machine with its own spec and kit. Those, and the verdict, never leave it.
- Gate on the exit code and keep the verdict file. Route 1 and 2 apart: 1 is about the record, 2 is about the verifier.
What it does not do.
AI and LLM outputs are never re-run. For those the record is show-its-work: the sources used, the criteria applied, the quotes made, each a file the verifier can hash and a span it can re-check against its source. The rule is yours. OK means the output is the deterministic result of the committed inputs under the committed rule, nothing more. It does not say the inputs were true, that the rule was the right rule, or that anything is compliant.
Appendix.
The bundle
bundle/
manifest.json every file's digest, spec pins, declared outputs
spec/ the bundle's copy of the rule, not authoritative
inputs/ the committed inputs, as they were
outputs/ the claimed value, one file per output
Eight manifest keys are required at every schema version: schema_version, bundle_id, created_at, files, spec_files, cross_refs, payload and typed_checks. An entry under outputs names an output_id, a type and the spec it conforms_to. The claim itself sits in outputs/<output_id>.json as {"value": ...}. Anything on disk that the manifest does not list is a REJECT.
Primitives
26 ship with the verifier. 19 are Tier A, a general shape or a public standard, tested against a producer implementation written independently. 4 are Tier B, a reference implementation and not a standard. 3 are Tier C, certificate checkers that test a committed witness and never solve. A rule that names a primitive outside this set needs a kit passed with --primitives; without one the run ends UNKNOWN_PRIMITIVE and fails closed.
| Primitive | What it recomputes | Tier |
|---|---|---|
anticheat_adjudication_recompute | First matching rule, with a default | A |
audio_recompute | Voice-activity segment boundaries | B |
auto_ubi_recompute | Aggregate features, classify by threshold | A |
bom_recompute | Bill-of-materials rollup over a lockfile | A |
build_real_compiler_recompute | Real compiler build digest | A |
build_recompute | Build artifact digest over sources | A |
climate_emission_recompute | Multiply and sum, fixed order | B |
dp_recompute | Seeded Laplace-noise aggregate | A |
event_log_replay_recompute | Event-log replay to a record digest | A |
fea_vonmises_recompute | Scalar with tolerance, von Mises stress | A |
fea_witness_certificate | Witness plus certificate | C |
fea_witness_certificate_u_norm_2 | Witness plus certificate, 2-norm | C |
fea_witness_certificate_u_norm_inf | Witness plus certificate, max norm | C |
fintech_audit_recompute | All-pairs predicate to a verdict list | A |
fp_ml_recompute | Floating-point ML inference | A |
healthcare_diagnosis_recompute | Fire every rule, collect the results | A |
kg_recompute | Knowledge-graph derivation | A |
ml_recompute | ML metric | A |
prior_auth_recompute | First matching rule, with a default | A |
raster_recompute | Geospatial zonal count | A |
scrabble_recompute | Dictionary membership | B |
sheet_derivation_replay | One stated operation over a workbook | A |
sheet_query_recompute | Closed-world query over a workbook | A |
spectra_span_recompute | Extractive span | B |
streaming_recompute | Streaming window aggregation | A |
tabular_recompute | Group-by with sum and count | A |
Comparators
Seven, and a rule may name no other. exact. scalar_epsilon, a number within a pinned tolerance. set, multiset equality, blind to order. text_normalized, text under one allowlisted normalization profile. structured, a structure under one allowlisted schema. rational_band and rational_sqrt_band, an exact rational from a certificate primitive within a pinned band, decided without floats.
Reason codes you meet first
118 codes are emitted by the distribution. Every one is documented in REASON_CODES.md, and a test fails when one is missing. These are the ones a first build hits.
| Code | What happened | Verdict |
|---|---|---|
BAD_FILE_SHA | A file's bytes no longer match its manifest digest | REJECT |
EXTRA_FILE_NOT_IN_MANIFEST | A file on disk that no manifest entry declares | REJECT |
FRAGMENT_MISQUOTE | A quoted span does not match its source | REJECT |
RE_DERIVATION_MISMATCH | The recompute ran and disagreed with the claim | REJECT |
UNKNOWN_TYPE | The output's type is in no anchored spec: a swapped rule | REJECT |
UNKNOWN_PRIMITIVE | The rule names a primitive no kit or distribution holds | REJECT |
MalformedManifest | The manifest does not parse | REJECT |
WORK_SET_VIOLATION | The bundle did not deliver exactly the outputs you named | REJECT |
VERIFIER_INCOMPLETE | Outputs declared, but you passed no spec anchor | ERROR |
SPEC_ANCHOR_ARG_INVALID | Your spec path resolves inside the bundle | ERROR |
PRIMITIVES_ARG_INVALID | Your kit path resolves inside the bundle | ERROR |
The flags that matter
--bundle-dir- The record. Must hold
manifest.json. --spec-anchor- Your copy of the rule, one or more files. Without it a bundle that declares outputs cannot be judged, and the run ends ERROR.
--primitives- Your kit, a Python module that registers the primitives your rule names. It is code and runs with your authority, so hold it like the spec.
--work-set- The complete list of outputs the bundle must deliver, each pinned to its type. Without it the producer chooses which claims arrive.
--verdict-out- Writes the full verdict as JSON on every exit path. Unsigned by design: trust comes from re-running the verifier, not from the file.
--require-rederivation- Turns "nothing was recomputed" from a note into a failure.
--unsafe-run-bundle-pack- Runs code shipped inside the bundle. Off by default, for disposable hosts only, never together with a spec anchor.
The quickstart is on Developers. The recorded example runs, with their exit codes, are listed in commands.txt.
Find out more.
Half an hour on Google Meet, or an email.