Decision Record evidence

The evidence is what it refuses.

A record format cannot be demonstrated by a record that passes. Anyone can produce one of those. What is worth showing is the set of records that should be refused, each one built on purpose, run through the verifier, and published with whatever the verifier actually said.

The acceptance set

Fourteen ways to refuse this record

examples/acceptance/ACCEPTANCE.md in the repository is a list of fourteen attacks and defects, each with the command that produces it and the verifier's answer. A row edited on disk. A decider attestation altered and the record signed again by the producer, who holds that key. Rows deleted from the middle and the chain recomputed. A record that names a conformance version its own run did not establish. An exclusion list that does not close the gap it claims to. The producer's own key enrolled as an independent witness.

The file is produced by bash examples/acceptance/run.sh, which runs every case and captures what came back. A hand-written expected output appears nowhere in it, and the full output of every step sits beside it under examples/acceptance/out/, so the claim and the artefact are the same bytes.

Case 2

One row edited, and what stops being knowable

Row 4's outcome flipped from what the decider said. Nothing else touched.

dr.verify, over a tampered record

python3 -m dr.verify examples/acceptance/out/tampered-row \
  --registry examples/keys/registry.json \
  --replay emitters.toolgate \
  --decider-registry examples/keys/deciders.json

What that prints

examples/acceptance/out/tampered-row

  OK      document       format_version 2 shape, and payload_hash recomputes from the canonical payload
  OK      signing_trust  key 'example-2026-10' is active in the registry
  OK      signature      the signature verifies over the payload
  FAILED  chain          row 4: row_hash does not re-derive (stored 'sha256:ac1bbde70de85ec58a2e64fa719dab4c1fb4577cccd56942b6ce3f6ee1dcb2ac', computed 'sha256:825900f99529499419ed5d04a2622c2a8afb2f2e3b115e9e077c94a869ba1aab')
  UNKNOWN decisions      not computed: the rows were not established
  UNKNOWN profile        not computed: the rows were not established
  UNKNOWN correctness    not computed: the rows were not established
  UNKNOWN retained       not computed: the rows were not established
  UNKNOWN replay         not computed: the rows were not established
  UNKNOWN invocation     not computed: the rows were not established
  UNKNOWN stream         not computed: the rows were not established
  UNKNOWN completeness   not computed: the rows were not established
  UNKNOWN receipts       not computed: the rows were not established
  UNKNOWN witness        not computed: the rows were not established

VERDICT: FAILED

Read the unknowns, not the failure

One property failed: the chain, naming the row and printing both hashes. That part is unremarkable. The part worth reading is the ten lines under it.

Every property that depended on the rows reports UNKNOWN, with the reason, rather than reporting a result computed over rows that did not re-derive. A verifier that kept going would have produced ten more answers, and every one of them would have been a statement about bytes it had just been told not to trust. Unknown is not a softer failure here. It is the verifier declining to say something it does not know.

Worked records

Nine records, built by the emitters in the repository

Both profiles

Production records, which carry no labels and claim no correctness, and benchmark records, which carry labels and whose correctness figure recomputes from them.

Streams

Consecutive records linked by hash, so a reader can tell that the second follows the first and that nothing was removed between them.

Receipts

Records with receipts held by the subject of a decision, which is the one mechanism that can refute a record for something it does not contain.

Run it

Every case, on your machine

Python 3 and one dependency. The script runs all fourteen and writes the captures.

the whole acceptance set

git clone https://github.com/SDL-HQ/sdl-decision-record.git
cd sdl-decision-record && pip install cryptography
bash examples/acceptance/run.sh

What a passing acceptance set does not establish

That the verifier refuses fourteen things nobody has thought of a fifteenth. The set is a floor, not a proof, and it grows when somebody finds a case it misses. What it does establish is that the refusals are reproducible by a reader rather than asserted here.