NT-010 — The shape of the platform
Three drawings and what checks each one. The README shows what an operator installs; this note shows what happens inside it, and how the pictures are kept from drifting away from the code.
A diagram that disagrees with the code is worse than no diagram. It reads as authoritative and nothing fails when it stops being true. So each drawing below names what proves it, and where a drawing has no accuser this note says so rather than leaving the reader to assume one exists.
One run, from start to record
Section titled “One run, from start to record”The fold is the whole design. A run has no stored state — the state is a
pure function of the steps recorded so far, so a worker that dies mid-run is
replaced by another that reads the same ledger and reaches the same place. It is
also why the ledger has no UPDATE and no DELETE: a correction is a new step,
because amending an old one would change the answer the fold gives about the
past.
The Gate sits between the proposal and the effect, always. There is no path from a model’s suggestion to a business system that does not pass through it, and the decision is appended before the effect happens rather than after — so a crash between the two leaves a record that something was allowed, never a mystery effect with no decision behind it.
What proves it: the engine tests drive this loop against an in-memory ledger, and the gate tests drive the seven checks and four verdicts directly. The ordering claim — decision appended before effect — is asserted in the runner’s tests.
Which package may know which
Section titled “Which package may know which”Arrows are “may import”. Nothing points the other way: domain is what
everything is built on, so it is built on nothing of ours and on no third party
except one named exception — Unicode normalisation, because memory identity is
wrong without it and the standard library does not ship the table.
Interfaces are declared by the consumer. engine declares the Ledger and
ContentStore it needs, and ledger implements them without importing
engine — which is why the arrow can point inward while the dependency of
meaning points outward.
What proves it: internal/arch/layering_test.go walks the import graph and
fails on a reverse arrow or a third-party import inside domain. It reads
production files for direction and every file for purity: a domain test that
reaches for a driver has put the driver in the package’s world, but a ledger
test that imports engine is asserting at compile time that it satisfies
engine.ContentStore — the layering being proved rather than broken.
What is written where
Section titled “What is written where”The split is not about size. Tool arguments, tool results and closing answers
routinely carry personal data, and run_steps is the one table an erasure
request can never reach. The current engine therefore writes those three by
reference and digest, never inline. The digest is enough for an auditor to
prove which bytes were used without those bytes surviving to prove it.
This is deliberately narrower than saying that no personal or authored text
ever reaches the ledger. Scope and conversation identifiers, policy evidence,
human decision notes and stable failure summaries are part of the audit record.
There is also one historical exception: runs recorded before closing answers
moved to the content store keep RunFinishedPayload.Outcome inline. The chain
is immutable, so readers retain that legacy field while current writers never
populate it.
When the bytes are erased, anything resting on them is marked rather than left
looking sound: a governed memory whose evidence was erased becomes
source_erased and stops being recalled.
What proves it: TestAdvance_erasableContentStaysOutsideTheLedger runs a tool
and finishes a run with distinct argument, result and answer markers. It proves
that none enters a step payload, that every reference resolves before erasure,
and that none resolves afterwards. The retention and erasure tests in
internal/admin, and the memory reconciliation suite, drive an erased source
through to the memory that cited it. The legacy outcome reader has its own
compatibility test.