Skip to content
The record
Report3 October 20265 min read

Shared data contracts in four languages, with stable schemas that cannot be edited in place

Phase 2 defined 29 entities across 22 schema files, 15 of them stable and hash-locked, implemented them in Rust, C#, TypeScript and PostgreSQL with 133 deterministic mock fixtures, and passed a gate, re-run by the lead, of 1,119 tests and 12,551 fixture checks with none failing.

systemsmethod

What was done

Designed and implemented the shared data contracts that every later part of the platform reads and writes: 29 entities across 22 schema files, of which 15 are stable and hash-locked and 7 are drafts. Each contract has matching Rust, C#, TypeScript and PostgreSQL implementations, and 133 mock fixtures are generated deterministically, so regenerating them changes no byte. The design went through three independent proposals, three judges, a synthesis and two adversarial critique rounds before any code was written; implementation was split across nine agents in dependency order. The lead re-ran the full gate itself: 1,119 tests passed, 0 failed, 1 skipped, plus 12,551 fixture checks.

 schema registry: 22 files
   |
   +-- 15 stable, hash-locked
   |     a change needs a NEW version file
   |
   |     edit a file in place and update its lock
   |       -> compared with the PREVIOUS registry,
   |          not only with itself
   |       -> rejected
   |
   +-- 7 draft
         not locked; may still change

A lock that is only checked against itself can be rewritten along with the file.


Status

Shipped, 3 October 2026 (commits babb496 at 20:42 BST and f4a0b67 at 20:43 BST). The first commit changed 315 files with 104,454 insertions and 1,905 deletions; most of those are generated, hash-locked fixture and schema files, so the line count measures volume, not effort.

The problem

Every later layer of the platform depends on these contracts, and they are shared by four implementations in three languages and a database. An error here propagates everywhere, and agreement between languages has to be shown, not assumed. The specification's principles also had to stop being guidance and become something the data model enforces.

How it was designed

Three designers each produced an independent proposal from a different priority: evidence integrity, offline sync and storage, and the needs of later consumers. Three judges scored them. One synthesis combined the chosen base with the strongest parts of the others, and two adversarial critique rounds found and closed 46 gaps. A lead review then kept every contract exactly as designed but deferred machinery that could not yet be tested against real hardware output to the phases that will first produce it, so that nothing was built that the gate could not test.

The owner, Stephen Ukaegbu, set the specification and made the decisions that governed the phase. The engineering was AI-assisted: Anthropic's Claude Code worked as lead engineer, orchestrating the designer, judge, critic and implementer agents, carrying out the lead review, and re-running the gate itself rather than relying on the agents' reports.

What the contracts enforce

  • Findings must cite evidence, and the kinds of evidence each layer may cite are restricted by the schema.
  • Facts are kept apart from interpretation: raw, derived, finding, interpretation and recommendation are separate record types.
  • Every conclusion records the rule and rule version that produced it.
  • An estimate can never be shown as measured: estimates carry ranges only and can never be marked verified.
  • History never changes silently: revisions are append-only and hash-chained, and stable schema files are immutable.
  • Mock data is labelled at every level, from a single observation up to a whole document, and no fixture contains a single measured value.

The Phase 1 session schema was moved byte-identically and frozen, and the software version moved to 0.2.0 across the core and the agent.

How it was proved

SuitePassedFailedSkipped
Rust7900
C#9200
TypeScript and database94801
Total1,11901

The fixture verifier ran 12,551 further checks, including 326 negative cases (287 schema, 3 envelope, 36 integrity) that must be rejected. The single skip was a registry test that compares against the previous commit, so it could only run once the commit existed.

Cross-language agreement. A shared table of negative cases gives the same verdicts in Rust and TypeScript. Seven migration golden vectors are deep-equal in Rust, TypeScript and the fixture generator's reference implementation. Shared identity and lifecycle vectors give the same results in Rust and TypeScript.

Real hardware and privacy. The real-hardware tests ran on the development laptop as a standard, non-elevated user, with no skips. Six raw serial numbers were checked across nine runs, and none appeared in any output. The working tree was scanned for the laptop's real serial numbers and system UUID, and none were found.

End to end. On the laptop, the core created, continued and closed a session across three saves with a verified parent hash; the agent continued, closed and mirrored it; TypeScript read every revision with no integrity problems; and the PGlite database ingested them as linked revisions of one machine.

After the commit. The registry test activated and passed 28 of 28. An in-place edit of a stable schema, with its lock updated to match, was rejected with "stable files are immutable; a change needs a new version file". The same check showed that the standalone schema-check script would accept that edit, so this protection depends on the TypeScript registry test running in CI. That was recorded in its own commit.

Limitations at the gate

  • The contracts for test executions, telemetry, error collections, evaluations and findings have no real producers yet, so they are exercised only by fixtures.
  • Disks have no identity key yet, identical GPUs cannot be told apart, and Linux has no memory-module inventory.
  • There is still no bootable image, and the Linux target was linted but not executed locally.
  • CI had never run, so neither the Linux root real-hardware step nor the registry check had run where they are meant to.

Open questions

Whether the contracts for test executions, telemetry, evaluations and findings fit real producers has not been shown; so far only fixtures exercise them.


The code

The comparison that makes a stable schema immutable: each locked entry in the previous registry must still be present with the same path, status and hash.

export function registryEvolutionProblems(previous: RegistryFile, current: RegistryFile): string[] {
  const problems: string[] = [];
  const now = new Map(current.schemas.map((e) => [e.id, e]));
  for (const before of previous.schemas) {
    if (before.status !== "stable" || before.sha256 === null) continue;
    const after = now.get(before.id);
    // ... a stable entry that has disappeared is reported as removed ...
    for (const field of ["path", "status", "sha256"] as const) {
      if (after[field] !== before[field])
        problems.push(
          `schemas: stable ${before.id} changed its ${field} from ${before[field]} to ${after[field]} (stable files are immutable; a change needs a new version file)`, // ... section reference trimmed
        );
    }
  }
  // ... append-only checks on the dataset and line-schema lists, then return problems ...
From packages/shared-types/test/support/schemaLint.ts — an excerpt, trimmed to the technique it illustrates.

Not shown. The schemas themselves, the integrity rules and their definitions, the evidence-log line format, the migration internals and the component-identity derivation are internal design and are withheld; the derivation in particular is a privacy control still in use. The real hardware tests' serial-number checks are not quoted.

A published copy. Commit references and internal identifiers have been removed and the operator is not named; the engineering, the counts and the stated limits are unchanged.