Skip to main content

What We Learned

When the canonical serialisation spec was written (earlier session), 14 test vectors were defined with exact YAML inputs, expected canonical JSON, and expected Blake3 hex digests. In this session, the @stratt/fingerprint package was implemented from scratch — 4 source modules, 98 tests — and achieved 97/98 pass on the very first test run. The single failure was a hardcoded SPUH prefix constant for TV-03: 0x50cf77c8a6196569n instead of 0x50cf77c8a619656dn. A copy error in a test fixture, not an algorithmic bug. All 14 canonical JSON outputs matched exactly. All 14 Blake3 digests matched exactly. NFC normalisation (precomposed vs decomposed Unicode) produced byte-identical output. Tamper detection worked on first attempt.

Why It Matters

The spec-first approach paid a 2x dividend. First, the spec itself forced disambiguation of four corner cases (key sort order, null handling, Unicode normalisation, type resolution) that would have been integration bugs. Second, the test vectors gave the implementation a fixed target — no iteration on “what should the output be?”, only “does my code produce it?”. The implementation session was pure execution: translate the spec’s reference functions into a Bun TypeScript package, write the test harness, run, fix the one typo, done. No design ambiguity, no spec interpretation debates, no “works on my machine” surprises.

The Pattern

Spec → test vectors → implementation → validate. The test vectors are the spec’s executable form. A conforming implementation is one that passes all vectors. This creates a contract between the spec author and the implementer that requires zero coordination — the vectors ARE the coordination. This is especially valuable for A2A (agent-to-agent) workflows: one agent writes the spec and vectors, another implements against them. The interface between the two is a set of deterministic input/output pairs, not prose.

Applicability

Any component where multiple implementations must agree on output: content hashing, serialisation formats, wire protocols, CRDT merge logic. The investment threshold is low — if you can define 5-15 input/output pairs before writing code, do it. The test vectors cost minutes to write and save hours of debugging.