[ evidence ]

How it works

the machine, end to end

// architecture

How a run becomes a record

Six stages. Each one leaves bytes the next stage can check. Nothing in the pipeline is trusted; everything is verified.

The pipeline

1
Record

The session runs inside a VM we control, on a pinned agent build. Sensors are declared before the run starts: hook events on the tool surface (every tool call and its result) and a boundary view from outside the guest (filesystem walk before and after; network capture is planned, not shipped).

->
2
Chain

Every observation becomes a transcript entry, and every entry carries the hash of the one before it. Delete, reorder, or edit a single byte anywhere in the run and the chain stops agreeing with itself.

->
3
Control

Controls are registered before the run and proven inside it: each one is armed, shown reachable, calibrated, and its outcome is observed. A bundle that cannot show its controls worked is invalid, not clean. A quiet run returns INCONCLUSIVE, never a pass.

->
4
Sign

Two ed25519 keys, operator and reviewer, in minisign's native format. The verifier enforces that they are distinct keys. The public keys ship in the bundle set and are pinned by their own calendar receipt.

->
5
Anchor

At run start the record carries a drand quicknet receipt (public randomness nobody precomputed). At close, both anchor digests go to the OpenTimestamps calendars, which aggregate them into the Bitcoin chain. The fingerprints are permanent; the content stays off-chain and deletable.

->
6
Verify

Anyone runs the verifier: stdlib-only Python, offline, no installs. Nineteen named rules over the file set, the schema, the chain, the controls, the citations, the beacon, the anchors, and the signatures. Every rejection names its rule.

What the verifier checks

The nineteen rules, grouped by what they protect. The full definitions are in the spec that ships in the sample zip.

FILE_SET nothing missing, nothing extra
PARSE + SCHEMA every document well-formed and in shape
REDACTION forbidden in this format, checked
CHAIN + ORDER the hash chain and sequence hold
HEARTBEAT sensors were alive the whole run
COMMITMENT the frozen documents match the seq-0 vows
BEACON the randomness receipt binds to the run window
ANCHOR the calendar receipts commit to these digests
ARMED + STILL_ARMED + CALIBRATION controls worked during the run
REACHABILITY a control that fired had a real path to fire
EXTERNAL_MATCH + SINK boundary effects agree with the transcript
CITATION + TAXONOMY every verdict claim cites an entry that exists
SIGNATURE both signatures verify against the published keys

The proof it works, not the promise

The tamper corpus is the test the format is scared of: twenty-two forged bundles, each violating exactly one rule, each rejected with the rule named. The real run is a recorded Claude Code session that took a baited .secrets directory; the control fired and three independent witnesses (stdout, argv, hook spool) agree. A quiet control run returned INCONCLUSIVE, which is what a quiet run is supposed to return.

All of it is in the public set: /evidence/sample. Download, unzip, python3 -m verify. If you have the minisign CLI, the signatures cross-check with a tool we did not write; the recipe is in KEYS.md inside the zip.

What it does not do

  • It does not see everything. Coverage is measured and printed in the bundle; blind spots are named, not hidden.
  • It does not prove the model behaved. It proves what the declared sensors saw, and that those sensors were working.
  • Anchors bind time, not identity. The signing keys are published and pinned, and one human currently holds both roles; that is in the bundle's independence block, in writing.
  • Content never goes on-chain. Fingerprints are permanent; bundles stay files you can delete.

Back to agent session evidence or the sample set.