Correct is a file in the repository, not a maintainer's opinion.
Warrant records what an agent decided so that someone else can verify it without trusting the system that wrote it. The repository is built the same way. The specification, the conformance vectors, the shared policy cases and a differential test between the two SDKs define what correct means, so a change is merged on what the gates say, whether a person or a coding agent wrote it.
Apache 2.0 for the code · CC BY 4.0 for the specification · no contributor licence agreement
What correct means here
Three files decide, and both SDKs run all three.
A Python-sealed record must verify in JavaScript and the reverse, byte for byte. Nothing about that is left to review.
conformance/adr-vectors.json pins the canonical form, the content hashes, the seal, the signature messages, the key ids and the Merkle proofs. conformance/admissibility-cases.json pins the seven admissibility rules and the lifecycle, reason codes and messages included. conformance/policy-cases.json pins the CEL expressions both policy engines must evaluate identically, and the three they are known to disagree on.
The vectors are generated from the reference implementation and never edited by hand. A change to one is a change to the specification, and the pull request has to say why.
$ cd python && python -m venv .venv
$ .venv/bin/pip install -e ".[dev]" && .venv/bin/pytest
... passed, skips printed with their reasons
$ cd ../js && npm ci && npm test && npm run typecheck
... ok
$ python scripts/differential.py --seed 7 --count 500
seed 7: 500 values and 500 records agree in both directionsFor people
What is worth doing, in order of value.
- A verifier in Go, Rust, Java, .NET or Swift. The bytes it must produce are already in the repository.
- A finding: a record one SDK seals and the other rejects, a CEL expression the two policy engines evaluate differently, or a sentence in the specification the code does not match.
- An adapter for an agent framework or a decision model, behind the boundaries the existing adapters respect.
- An issue labelled good first issue, port, adapter or spec.
The second item is the most useful thing this repository can receive. File it with the record, the expression or the sentence attached, and say whether the other SDK agrees.
For coding agents
The same gates, and an instruction file written for you.
AGENTS.md at the root of the repository is the operational subset of the contributing guide: the commands in order, what green looks like, what never to touch, and the order to make the vector groups pass when the task is a port.
Say in the pull request that an agent wrote the change and which model. It is not held against the change. It tells the reviewer what to read for, and the reviewer reads agent-written changes for three things in particular.
- Fields or behaviours that were assumed rather than read from the schema or the specification
- Tests that assert what the implementation does rather than what the specification says
- A failing test made to pass by weakening the test
The template asks
What was wrong before. What changed. What you ran, as the exact commands and their final lines. Which vectors or cases cover it. What you could not verify.
The last field is worth more than a long "what I ran". A pull request that says it could not run the PostgreSQL tests is fine. One that implies it ran them when it did not is not.
Issues labelled agent-friendly are specified completely by vectors or tests.
Port the verifier
Five vector groups, in this order, and your language has a verifier.
A verifier reads an export, one record per line, and an issuer's public keys, and reports whether the chain is intact and every signature valid. It needs neither SDK. Make each group pass before the next.
| 1. canonical | RFC 8785 canonical JSON: ECMAScript number formatting, keys sorted by UTF-16 code unit |
| 2. salted | SHA-256 content hashes, with and without a salt |
| 3. seal, and its three variants | The record hash over the body without the seal, the previous-hash chain, and the Ed25519 signature message |
| 4. key | The key id derived from a public key; key sets with not_before and revoked_at are in the spec |
| 5. merkle and checkpoint_message | RFC 9162 roots, inclusion and consistency proofs, and the checkpoint signing message |
Then verify an export produced by the SDK and reject it again with one byte changed. Open an issue with the port template when the first group passes; a verifier whose seal group passes gets linked from the README. Go, Rust and Java each have an open issue.
The gates
What continuous integration proves on every pull request.
| schema-in-sync | The JSON Schema in schema/ is byte-identical to the copies inside both packages |
| python, on 3.10, 3.12 and 3.13 | The Python suite passes against PostgreSQL and the package builds |
| js, on Node 18, 20 and 22 | The JavaScript suite passes, the type declarations compile, the package packs |
| differential | 20,000 random records sealed in Python verify in JavaScript, and the reverse, on a fresh seed every run |
| action | The replay GitHub Action produces exactly the documented outcomes against the lending gallery |
Questions go in Discussions. A record that verifies when it should not goes through SECURITY.md, privately, never the issue tracker.