Skip to main content
An implementation in any language must reach the same identities. Conformance is therefore something you run, not something you claim.
The corpus is not owned here. It is published at gaussia-labs/boltzmann-conformance as spec-level data, and vendored into this package at the version golden.CORPUS_VERSION names. The authority is the corpus; this SDK is one of its consumers, and CI fails if the vendored copy drifts.That split matters. While these files lived here, their location, naming and shape were governed by a Python package layout, and “conforming” quietly degraded into “matches pyboltzmann, bugs included”. A vector this SDK cannot reproduce is now a disagreement to resolve, not a file to edit.

Golden vectors, for any language

The vectors ship inside the wheel as plain JSON, so a non-Python implementation can read them from an installed pyboltzmann without this SDK running any of its own code — or read them straight from the corpus repository, which needs no install at all.
The identity files cover the whole chain from a payload to a version identifier. Agree on all of them and two clients share a brain; disagree on any and they do not, whatever else they implement. The authenticity files cover a different failure: divergence there is not silent identity drift but a verifier accepting what another refuses, which is worse.
A published vector never changes. A case whose expected output would change is either a bug in whatever produced it, or a new serialization identifier — never a corrected vector. Editing one silently would let two implementations agree with the corpus at different times and disagree with each other.

The schema registry

schema_version sits inside the envelope and therefore inside block_id, so “registered” cannot mean “whatever this deployment implements”. The registered set is the companion document the corpus publishes:
A block is written under the oldest registered schema its payload satisfies, and the proposer does not get to choose. Writing under the newest instead would let a new schema silently re-version every block written afterwards, including blocks that use nothing it added. Defining a block class registers its schema with this process, which is not the same thing as the schema being registered with the protocol. When the two disagree, the SDK says so:
It warns rather than refuses. Defining a schema is how one comes to be proposed for registration, so an exception would make the SDK unusable for the work that precedes it — the failure being guarded against is doing it silently, and ending up with a per-deployment registry by accident.

The behavioral suite, for Python

A Python implementation inherits the suite directly. These are pytest classes — collect them and they run against your code, so they need pytest:
Without it, importing one tells you so. The vectors above are unaffected: they need neither pytest nor any extra.
Two suites need no hook at all, because they test the SDK’s own invariants over your types:

What each suite asserts

  • The three levels of hashes are not interchangeable, and parsing refuses the wrong level rather than coercing it.
  • Canonicalization erases the order a mapping was built in.
  • Floats and unsafe integers are refused inside a payload.
  • block_id matches the published vectors, which other languages also read.
  • The root is a function of the set: two parties that assembled the same blocks obtain the same root.
  • Duplicates collapse — a set of content-addressed blocks cannot hold the same block twice.
  • An empty composition still has a well-defined root.
  • Every leaf proves into the root, at every tree size.
  • A proof does not verify against another root.
  • Every published signatures.json case reaches its stated verdict: the paper’s worked cases — admission by quorum, self-admission failing with no pin, retirement standing where compromise withdraws — as executable oracles over your store.
  • Signing never changes a snapshot’s identity: detached means detached.
  • Needs the [authenticity] extra, because authorized without the mathematics is the one claim this role must never make.
  • Dropping yields a new root, and does not disturb the earlier one.
  • Episodic refuses to drop — append-only by protocol, not by policy.
  • A diff reports exactly what an incremental update must fetch.
  • Storing identical bytes twice is a no-op.
  • Every memory type round-trips, decoding back to an equal block with the same identity.
  • A missing block is an error, not an empty result.
  • Corruption is detected: bytes that do not hash to their digest are refused.
  • A store must not normalize — non-canonical bytes do not decode.
  • A tombstoned block is distinguishable from a missing one.
  • Deleting reclaims both the bytes and the record of them.
  • The store can enumerate what it holds, which is what mark-and-sweep needs.
  • Satisfies the BrainReader contract, and reports what is installed.
  • A module that is not installed is an error, never an empty module.
  • Resolves members; refuses to resolve a non-member however it is stored.
  • Proves membership, and a proof does not verify against another root.
  • Verifies itself, and reports resolvability three ways.
  • search returns verified data and not prose, reports the roots it verified against, and honours a memory-type filter.
  • No match is an answer and not an error.
  • An unregistered index is refused rather than faked.

Fixtures

Two helpers build valid blocks, so a suite does not need your constructors:

What the SDK asserts about itself

Two tests in the repository are worth knowing about, because they constrain what this package may ever ship:
  • No NotImplementedError stubs. An unimplemented function is worse than an interface: it looks callable and is not.
  • Nothing declared and unreachable. Every type, enum member and constant is produced by something.
Together they mean the public surface is exactly what works — there is no aspirational API.