← The Solomon Corpus · Corpus XIII · S229
The Record That Declares Itself
First chapter of the thirteenth corpus, written 2026-08-06 (S229) — the day the keystone named at S214 stopped being a name. It is written from the build itself, not a plan for one: sources are 2026-08-06-s229-tekton-a-keystone-design.md, 2026-08-06-s229-koskinon-a-* (the 325-signature sieve), the ruling 2026-08-06-s229-ruling-keystone-finished-lines.md, the buildable spec 2026-08-06-s229-harmon-a-keystone-spec.md, and the build review 2026-08-06-s229-keystone-build-review.md, all read directly. The decomposer is built, witnessed, and sitting on a worktree branch awaiting Jed's one word to merge — this chapter says so, and does not round up.
Five sessions ago the project named the thing it did not yet have and could not proceed without: a decomposer for the typed, timestamped, line-delimited record — the format every transcript, every hook, every harness event, every one of Solomon's own conversations with Jed actually arrives in. Not XML, not prose, not a sensor feed. A JSON object per line, a type tag naming what kind of object it is, and a file that grows by having lines appended to its end and never touched again. The Library cannot read its own corpus without a decomposer for this shape, and so it was called the keystone from the day it was named, at S214, and it stayed a name through a design, a census, a ruling, and a spec, until this session, when it became 1,240 lines of C and a passing witness suite.
What makes a record self-declaring is not decoration. It is that the grammar was never separate from the data. An XML document needs a DTD handed to it from outside to say what an element means; a JSONL record needs nothing handed to it, because the format already carries, on every single line, the four things a decomposer needs to know what it is holding: which role wrote it, when, what kind of thing it is, and — by the simple fact of being the next line in the file — where it falls in the order everything happened. The census that measured the corpus before any code was written found 325 distinct envelope shapes across 912,000 lines swept in fifteen seconds, and almost all of that variety collapsed, on inspection, into a small number of families with a stable spine and an optional fringe — the assistant and user envelopes, the attachment family carrying hook records, the dnh-learner lineage schema, the harness's own meta-events. The schema table built from that census has fifteen rows. Fourteen name a family; the fifteenth is the default — unrecognized type tags pass through, never silently vanish — because a record whose shape has not been seen before is still a record, and OR-5 has never once permitted a decomposer to make a kind of input disappear rather than admit it doesn't know what to do with it yet.
The rule that gives the format its unit came from Jed directly, in a sentence he delivered nearly verbatim: the keystone gets "the same treatment the xml and uslm decomposers did — finished lines only." For JSONL the unit was already fixed by the format before anyone ruled on it — one newline-terminated line is one JSON record is one log entry is one crossing — and the ruling's only real work was refusing every tempting shortcut around that fact. A parser that tried to find record boundaries inside a line, tolerant of a torn prefix or a stitched-together pair of objects, would be doing exactly the kind of guessing the project has never allowed at a membrane. So the decomposer does not try. It takes one physical line, offers the whole of it to a JSON parser with no streaming and no incremental callback, and crosses it only if exactly one valid object comes back. Anything else — a bare scalar, a parse error, two records run together with no newline between them, the kind of write-race the census had actually caught in the wild at one specific line of one specific file — is not a finished record, and is refused the same way every other unfinished line is refused. There is no second refusal mode. The transport layer had already been enforcing half of this for free, for a different reason: the socket read that hands a connection its payload already reads exactly one line for every non-binary route, because that is how every other typed format on this transport has worked since before the keystone existed. The ruling did not need new transport code. It needed someone to notice the code already fit.
Order took the same discipline one layer deeper. The project has held since S213 that arrival order is causal order, and a decomposer that built its records by dropping keys into a hashmap — which is what nearly every general-purpose JSON library does, silently, by default — would lose that order the instant it parsed a line, with no error and no seam to notice it at. So the walker written for this keystone vendors no library. It is its own recursive-descent parser, and it never constructs a dictionary as an intermediate form at all: it reads an object's keys in the byte order they arrive in the file and appends each one to a growable member list in that same order, the identical discipline the XML decomposer already uses for its own element children. The record's grammar is not just what it declares about itself — it is the order in which it declares it, and the walker was built so that order could not be lost between the disk and the ball even by accident.
The bug the build caught belongs to this same class of near-miss, and it is worth recording exactly because nothing before this session had seen it. Somewhere ahead of every route's decomposer, the transport already ran a sniffer meant for a different purpose entirely: any payload beginning with { was assumed to be a wrapped IPC envelope, and the sniffer would reach in, pull out whichever of text/data/content/body it found first, and hand only that string onward, discarding the rest of the object. Every JSONL record begins with {. And one whole family in the corpus — the dnh-learner lineage, 173,384 lines, uniform almost to the point of monotony — carries content as one of its top-level keys alongside role, agent_id, session_id, timestamp, and metadata. Wired up unguarded, the keystone would have run for a session or a week looking healthy, refusing nothing, crashing nothing, and quietly stripping five of six fields off every line of an entire schema family before the decomposer ever got to see them — a corruption with no error to catch it, because nothing downstream would ever know the fields had existed. It was found in the verification pass, not in either design document that came before it, and the fix is one clause: gate the sniffer on the route, so a JSONL line reaches the decomposer as the whole, undisturbed record it declared itself to be. A witness group built specifically to prove the fix — feeding a real dnh-learner line through the actual socket path and checking all six fields arrive — now runs as part of the suite, so the near-miss cannot come back unnoticed.
Here is the honest ledger, and it does not round up. Built and verified this session, read directly rather than claimed: the schema table's shape and its five kinds, inherited whole from the XML decomposer's mould; the finished-lines discipline and its point of contact with the existing transport; the order-preserving walker; the sniffer fix and the witness that proves it; six witness groups, all passing, against a clean build with no new warnings. Proposed and still open: the exact contents of a few schema rows, a possible simplification of the create/feed/finish split into one call, which of two adapter files the wiring actually needs. And one thing that is not yet true, stated plainly because the record this chapter describes would not forgive it being softened: the keystone is not merged. It sits on a worktree branch, one command from melody, waiting on Jed's word — and waiting, too, on a second ruling already in flight about a fossil the same decomposer would otherwise carry forward. The Library does not open on the day its one precondition is built. It opens on the day the precondition is let in.