GridWork
Derivation

Second-reader records

How derivation subjects are hashed, independently reviewed, and published with scope and verdict.

CLEANROOM.md rule 4: every change touching the paths in .github/cleanroom-paths.txt gets an independent fresh-context review before it reaches main. This directory is where those reviews are recorded, and cleanroom-gate in CI is what makes skipping one visible.

The subject digest

A record is named after its subject — a SHA-256 over every gated path the change touches paired with that file's blob hash at HEAD, plus the text of every registry row those files' Derivation: markers cite:

docs/derivation/reviews/<subject>.md

Get it for the current branch:

git diff --no-renames --name-only origin/main...HEAD | ./tools/cleanroom-gate.sh --subject

(If the branch also edits SPECS.md or CAPTURES.md, the gate needs a base to diff their rows against: prepend CLEANROOM_BASE="$(git merge-base origin/main HEAD)" to the cleanroom-gate.sh end of the pipe. CI exports it on every run.)

The digest covers gated files and the rows they cite, so committing the record does not change it — but editing any gated file afterwards does, and the gate goes red again. That is the point: a review is bound to the content it actually read, and cannot be carried across a rewrite of that content.

The registry half of a citation gets the same treatment, because a review checks that a marker and its row agree — binding only the file half would leave the row free to move under a record that vouched for the pair. Editing a row a gated file cites, even in a change that touches no gated path, re-opens review of the files citing it: the gate diffs registry rows against CLEANROOM_BASE and treats the citing files as touched, and it refuses a registry edit it has no base to judge. A row nothing cites stays free to add or fix — pre-seeding is meant to be cheap, and stays so.

Two scope notes, said plainly. The diff feeding the gate must be produced with --no-renames (CI's is): default rename detection folds a modify-plus-rename into one line naming only the new path, which is exactly how a registry edit would vanish from the input — the reviewer of this mechanism defeated its first version that way. And the binding covers table rows, not the prose around them: the sentences that govern how a row is read stay rule 4's reader's job, like every other claim in this repository.

Writing one

subject=$(git diff --no-renames --name-only origin/main...HEAD | ./tools/cleanroom-gate.sh --subject)
cp docs/derivation/reviews/TEMPLATE.md "docs/derivation/reviews/$subject.md"

Fill in subject:, reviewer:, session: (the reviewing session's opaque id — an id, never a path), and tick all four checks. Commit it in the same branch. The gate verifies the file exists, that it declares the matching subject, that it names a reviewer and an opaque reviewing-session id, and that all four checks are ticked — and, separately, that every gated source file in the change carries a resolving Derivation: marker. The seven records that predate the session: field are the only grandfathered subjects; their session ids are permanently unrecoverable.

What the reviewer does

Read the gated diff cold — without the implementing session's context — and check exactly the four things rule 4 names:

  1. citations — every non-obvious terminal behavior carries a Derivation: marker naming a permitted source by ID, from ../SPECS.md (public specifications) or ../CAPTURES.md (registered observations).

    The gate already proved every cited ID resolves and that no gated source file is unmarked, so do not re-check that by hand. Check what the gate cannot: that each marker sits on the behavior it describes, and that the cited source actually says what the code does. A marker citing a real spec for the wrong behavior passes the gate and fails this check — that is the case you are here for.

    Derivation: none — <reason> is a claim you check like any other. It says the file derives nothing, and the gate can only confirm that a reason was written, never that it is true. Read the file and decide: does it spawn a process, parse a byte, supervise a session, or encode any terminal behavior at all? If it does, the declaration is false, and that is a blocker at the same severity as a wrong section number — and easier to miss, because a none invites you to stop reading. It is the one marker that earns more scrutiny than a citation, not less.

  2. framing — no source-derived framing: no comment, name, or structure that reads as transcribed from another implementation rather than from a specification.

  3. references — no other project named as a comparand, and no capture cited by path. Captures are referenced by registered ID and SHA-256, never otherwise.

    Write this one up as the class searched and the hit count — "terminal-tooling comparand class (5 terms): 0 hits" — never the query terms. Naming them publishes the exact strings the check exists to keep out of this repository, in the one artifact nobody reviews a second time. The shape is required at authoring time precisely so it is not something to catch afterwards.

    Give the term count when you ran the grep and know it; leave it out when you don't. Never reconstruct one — a count inferred from the length of a list you are deleting is a number nobody can check, in a record whose only value is that its numbers are checkable. "Class: 0 hits" is complete; an invented "(5 terms)" is worse than silence.

    A name already registered as a permitted source in ../SPECS.md is not a query term and is not redacted — cite it. Where a project appears both as a registered protocol and as an implementation, saying which one you checked IS the finding, and collapsing it into a class count deletes the answer to a question the registry itself raises.

  4. leak./tools/leak-scan.sh green.

A behavior with no citable permitted source is an escalation, not a guess.

What this proves, and what it does not

It proves a review ran against this exact content, that its record was written at commit time rather than reconstructed after a question was raised, and that every citation resolves.

It does not prove the reviewer was independent. This repository has one maintainer; GitHub does not permit a pull-request author to approve their own pull request, so a required-review rule would not create a gate here — it would only make main unmergeable. Independence is procedural: the reviewer is a fresh-context session with no exposure to the implementing session's context. Claiming the narrower thing truthfully is worth more than claiming a stronger control that a single-maintainer repository cannot deliver.

Published records

DateScopeRecord
2026-08-11The receipted reverse input path — a consumer's keystrokes carried to the child over the host's existing outbound connection, validated against a declared byte count and two ceilings then forwarded verbatim, plus a cursor coordinate added to the wire snapshot; all five gated host files verified under Derivation: none, with registry.rs's touches-no-process-directly qualifier traced through the injected spawn factory rather than taken on its face1840c3a…
2026-08-10The capability-gated raw PTY fallback — strict JSON headers paired with adjacent opaque payloads, byte-exact replay and typed resize events, bounded retention, and demonstrated queue/socket backpressure; all six gated host files verified as original repository-local coordination under Derivation: nonec2efaa4…
2026-08-09The interned styled-frame wire — a frame-scoped style table with per-row runs and a batch-scoped table on every delta, the strict decoder's refusals judged as arithmetic before allocation, and the publish budget re-derived to exact blank-frame arithmetic; all four gated host files verified under Derivation: none and the three untouched terminal-interface citations re-checked in placefab45a2…
2026-08-09The three engine-in-a-pane silences bound as markers — the stdio pane's no-guarantee statement, the stream-scoped readiness sentence, and the plugin-set inference refusal; every quote and every claimed absence verified in both directions against the live registered documents4ea294b…
2026-08-09The arrangement reproduced from the ledger — a deterministic client rebuild from workspace_node rows alone with sessions bound and geometry defaulted on every pass; both gated files verified under Derivation: none, every mapping rule checked as a first-party choice against the projection schemaa1fbd7a…
2026-08-09The detach residue — a consumer disconnect demonstrated invisible to the child (no SIGHUP, no end-of-file, no discarded pending input, a clean self-exit) and the attach verb's no-authorization boundary statement verified as first-party; all three terminal-interface citations checked against the registered documentf65f77c…
2026-08-09The scrollback read path — an absolute-window selection read over retained rows and one viewer's offset-from-live history position with reflow clamping; the new module verified under Derivation: none and the whole-screen doc correction confirmed behavior-neutral3127669…
2026-08-09Job-control conformance over the shipped PTY session — controlling terminal and foreground group, INTR/QUIT/SUSP, SIGTTIN/SIGTTOU, and SIGWINCH each demonstrated against the sentence that states it — plus the size relay completed in both directions; every new marker verified against its registered document1928d32…
2026-08-09The workspace input grammar — leader, one-shot command mode, and the palette, with the DEFAULTS lineage table binding every default to a registry row or an explicit original marker; four real citations verified against their registered documentsd07f2e1…
2026-08-09The workspace structural floor — the workspace/tab/split-pane model with create/navigate/resize/close, its geometry solver, and the chrome-driven furniture painting; both new gated files verified under Derivation: none458af03…
2026-08-08The PrivateDevices PTY-refusal claim registered as CAP-005 and cited by the host unit, plus the kill() marker's complete chapter-11 pseudo-terminal enumeration — discharging the previous record's two findingsf4bb40b…
2026-08-07The attach hookup — per-session publisher tasks forwarding snapshot and deltas over the kernel socket, the POSIX-TERM hangup marker on kill(), and the discharge of the previous record's five findings120a78b…
2026-08-06The host session runtime — thread-per-session supervision, engine-frame-to-wire conversion, and transcript command origination — plus the three citation rewordings discharging the previous record's findings636b4d0…
2026-08-04The engine-adapter normalization trait — three adapters onto one LifecycleFact/EngineStatus vocabulary, all three new modules under Derivation: none, and the retraction of the ACP-Agent claim9c43c51…
2026-08-04Typed styled cells on the delta — SGR attribute fidelity, the underline-colour extension, and the cell-vs-grapheme segmentation split registered as CAP-0046c756f1…
2026-08-03gwk-pty-host kernel-client runtime — envelope framing, command origination, dispatch-node and ingest families; all eight files under Derivation: none80e0a53…
2026-08-03First Derivation: markers for the six gated gwk-parity runner/bin files, and the /// outer-doc marker form5bc949e…
2026-08-03gwk-pty-host skeleton crate, and rule 3's Derivation: none declaration form2340dbf…
2026-08-02Claude control-channel --verbose fix, CAP-003, and parity-runner hardening08ad472…
2026-08-01Codex app-server adapter, typed protocol handling, and vendored schema provenance214ce08…
2026-07-30Initial PTY engine crate, toolchain pins, and first derivation marker29b2277…
2026-08-01Claude adapter stream parsing, control channel, cost mapping, and approval relay7b9d5b7…
2026-08-01Initial render/control halves for the opencode, Claude, and Codex adaptersa447d09…
2026-08-01PTY sessions, replay/conformance fixtures, and complete capture-tree enforcementd4cfef6…
2026-08-01opencode event-bus normalization and per-child cost extractione250724…

On this page