Tests and machinery that prove implementations obey LogLine-Foundation/canon.
canon = canonical minimal form
conformance = proof that engines obey
engine = implementation / runtime
registry = publication / versioning
docs = human explanation
This repo is conformance. It is allowed — required, even — to have schemas, vectors, fixtures, verifiers, generators, and tests. None of these belong in canon. canon stays one file, dry, importable.
| path | role |
|---|---|
schemas/ |
Machine-readable specs (JSON Schema 2020-12). Each canon file gets a .schema.json. |
vectors/receipt/valid/ (and other layers) |
Receipts that MUST pass conformance. Hashes computed correctly. |
vectors/receipt/invalid/ (and other layers) |
Receipts that MUST fail conformance. Each filename names the violation. |
hash-profiles/ |
Specifications of canonicalization + hash algorithms referenced from the schema. |
fixtures/ |
Convenience: one canonical valid + one canonical invalid for fast-dev import. |
tools/ |
Reference verifier (verify-receipt.mjs, Node, zero deps). Implements the schema rules manually — not a JSON-Schema-validator-based implementation. See note below. |
| canon | schema | vectors | verifier |
|---|---|---|---|
logline.receipt.v0 |
schemas/logline.receipt.v0.schema.json |
✅ valid (9) + invalid (12) | tools/verify-receipt.mjs |
The reference verifier in
tools/verify-receipt.mjsis intentionally zero-dependency and implements the schema policy by hand. This keeps the conformance suite auditable in one read. The JSON Schema is the specification of the rules; the verifier is one implementation of them. Production engines should validate againstschemas/logline.receipt.v0.schema.jsonusing an audited JSON Schema validator (ajvin JS,jsonschemain Rust, etc.) AND run the conformance suite.
# verify a single receipt
node tools/verify-receipt.mjs vectors/receipt/valid/dan-rested.json
# run full conformance (all valid pass, all invalid fail)
node tools/verify-receipt.mjs --suite
# fill in hashes for a receipt draft (writes back to the file)
node tools/verify-receipt.mjs --fill drafts/my-receipt.jsontuple_hash = sha256(jcs(pick: 9 slots)) → pure act, identity of the action
content_hash = sha256(jcs(all_except: [id, hashes])) → interpreted act:
receipt_version + 9 slots + json_canonicalization + AUX
envelope_hash = sha256(jcs({content, transport})) → transported package, lives ONLY on the Envelope wrapper
Three independent hashes, three independent purposes. Two receipts with the same tuple_hash but different content_hash are the same act, different interpretations — useful signal for audit and for diffing AI decompositions of the same natural-language input.
envelope_hash deliberately does not live inside the receipt. It is a property of transport. A receipt at rest has no envelope; a receipt in transit is wrapped by exactly one envelope at a time, computed by the sender, verified by the receiver.
Three top-level field names are explicitly forbidden in v0 receipts, even though additionalProperties: true permits free-form AUX:
| field | reason |
|---|---|
result |
Earlier drafts placed execution results inside the receipt. v0 keeps the receipt narrow: a receipt records an act, not its outcome. Outcomes are separate records that content-address back via this receipt's id. |
evidence |
Same rationale. Evidence is attached, not embedded — it lives in its own evidence store, content-addressed by id. |
transport |
Transport metadata lives ONLY on the Envelope wrapper. A receipt at rest has no transport. |
The schema enforces this with "propertyName": {"not": {}} for each forbidden name. The verifier rejects with a named error. Three invalid vectors (legacy-{result,evidence,transport}-field.json) prove the rule.
Any other top-level field is fair AUX and is included in content_hash.
The LogLine-Foundation/canon repository contains the unresolved canon mold — a JSON shape that documents the canonical form, not a valid receipt.
In the canon mold:
idis the literal pointer string"hashes.content_hash"- all hash fields may be empty strings
- the file is importable as a canonical mold, not valid as an emitted receipt
In an emitted receipt (what conformance validates):
idis REQUIRED and MUST be the resolved 64-char lowercase hexcontent_hashhashes.tuple_hashandhashes.content_hashMUST be resolved 64-char lowercase hex- the file is consumable as an instance: passes the JSON Schema, verifies under the reference verifier
The canon mold therefore does not pass vectors/receipt/valid/ (and other layers). It documents shape; conformance proves engines obey that shape. Both are consumable — the canon as a mold, the receipt as an instance. They live in different repos.
- Pin a SHA of this repo (or of
canon+conformancejointly). - Build-time: download
schemas/logline.receipt.v0.schema.jsonandvectors/, verify SHA, cache. - Generate types from schema (
typify→ Rust,json-schema-to-typescript→ TS, etc). - Run the test suite against your engine — every vector in
vectors/receipt/valid/(and other layers) must verify, every vector invectors/receipt/invalid/(and other layers) must be rejected with the violation named in its filename.
If your engine passes, you may declare conformance with logline.receipt.v0. Otherwise you do not.
The vectors/valid/aux-*.json set stress-tests the canonicalization step independently of the act semantics:
| vector | exercises |
|---|---|
aux-nested.json |
nested objects, mixed arrays inside AUX |
aux-unicode.json |
em-dash, accented characters, emoji above BMP (🌙 = surrogate pair), control characters (\t, \n) |
aux-key-order.json |
mixed-case keys, underscore-prefixed keys, reverse-alphabetic insertion order — JCS MUST sort |
aux-number-decimal.json |
integer, decimal, negative decimal, Number.MAX_SAFE_INTEGER, zero, small decimal — JCS number formatting per ES6 §7.1.12.1 |
aux-array-order.json |
arrays preserve insertion order (JCS does NOT sort arrays), nested arrays, mixed-type arrays |
A JSON.stringify-based "verifier" will fail every one of these. Any engine that passes the full suite has at minimum a serious JCS implementation.
tools/verify-receipt.rs— Rust port of the reference verifier (planned)compatibility/— third-party engine results against this suite (planned).github/workflows/conformance.yml— CI runner (planned)package.jsonwithnpm testmapping to--suite(planned)- Further edge-case vectors: exponent boundaries, negative zero, deeply-nested structures, NFC/NFD Unicode normalization (planned)
These are roadmap, not promises. Nothing in this repo claims to be present unless it is in the table above.