For implementers, 5 September 2026
Until today this site explained the format and left you to write it. That is a project: work out the required members from prose, get the digest rule right unaided, and find out whether you have finished by asking somebody. Two files make it an afternoon, and neither of them needs anything else of ours at runtime.
testimony_emit.py is one standard-library file with no dependencies, MIT licensed, meant to be copied into your repository rather than depended on.
from testimony_emit import Record
r = Record()
r.scope(acts=True, description="Support agent. Refunds to 500 EUR.")
e = r.evidence(kind="api", source="crm://customers/8842")
r.belief(subject="customer:8842", proposition="requested_refund",
asserted_by={"id": "agent", "kind": "agent"}, evidence=[e])
d = r.decision(action_type="issue_refund", risk_class="high",
risk_source="registry",
proposed_by={"id": "agent", "kind": "agent"},
verdict="permitted", executed=True)
r.approval(decision=d, approver={"id": "sam@example.com", "kind": "human"},
identity_source="auth-session")
r.seal()
print(r.jsonl())
That reaches TR-4. It refuses at the point of the mistake rather than leaving you to find it from a validator after the run is over:
a refused action cannot also have executed risk_source: 'model' is the proposing side of the same system the approver is the proposer, 'agent'. An agent's own credential signing off its own action meets every other requirement and is worth nothing 'corp-sso' is not a known source. Use one of auth-session, api-key, jwt, ... or 'x-corp-sso' to declare your own
What it cannot check is what no emitter can. Whether the evidence you cite is what you say it is, whether the risk class really came from a registry, whether the name in an approval came from the session it claims. Those are attestations, the specification says so, and the validator reports them as attestations rather than counting them as proof.
The conformance corpus is 47 records and the verdict each one should get. The runner takes your command and compares.
python3 conformance/run.py --command "python3 my_validator.py --json {file}"
47 of 47 agree with the reference
run.py imports nothing of ours. Copy it into your
repository and run it in your own CI, which is the only kind of
conformance claim this project is willing to make about anybody.
Your implementation reaches the same verdict as the reference on all 47 cases. It does not mean the same check names, the same wording, or the same number of checks. Those are this project's prose, and a corpus that compared them would be testing whether you had transliterated somebody else's file rather than implemented a specification. An independent implementation is the entire point, so the comparison is deliberately blind to everything except the answer.
It is also not a certificate. It is a statement about 47 cases, and the specification is larger than any 47 cases.
digest-of-nothing is sixty-four zeros where a digest
should be. anchor-over-another-record carries a genuine,
correctly signed RFC 3161 token issued over a different record.
Both reached TR-4 in this project's own reference validator until 5 September 2026, because it checked that an integrity entry carried a digest and never that the digest was the digest of the record. An implementation that accepts either has the same hole, which is why they are in the corpus rather than in a changelog.
You almost certainly have the timestamps and the actions. The four things a log usually lacks, in the order they cost you:
There are two implementations and both are this author's, one in Python and one in TypeScript, written separately and compared against each other on every case. That is not an independent implementation in the sense that matters, and the Internet-Draft says so in its implementation status section rather than leaving you to notice.
If you build one, it is the most useful thing that could happen to this format, and you do not need to tell anybody or ask for anything. The licence is MIT for the tooling and CC BY 4.0 for the specification.
A case you fail is not necessarily your bug. If you have read the specification and reached a different answer, that disagreement is worth more than the corpus is: open an issue naming the case. The reference has been wrong before, the specification has been vaguer than it knew, and two of the checks exist because somebody said so.