Date. 2026-08-14 · CR. change-requests/cr-2026-213-loomworks-turn-kinds-single-source-v0_1.
State. Built and tested, both repos. HALTED before tag and push. Engine main local commit 53af982; surface main local commit 6ee64fd (neither pushed; no tags). Built at the exact baselines (engine 3c925ba, surface 322a216, both clean). E0128's before-state 422 was probed and observed at Step 0, per the kickoff.
The enumeration (§0.1 — the point, and the halt clause went unneeded): orchestration/turn_kinds.py — six constants + the frozenset, ONE source. The three writer modules construct kinds from the constants; record_turn refuses an unregistered kind at the write (unwritable, not unreadable); and the fence test introspects the read union's Literal tags and holds them identical to the enumeration — tag N+1 dies at build time. The enumeration was NOT harder than the member and the degrade — it was a 40-line leaf module and five import lines; the halt clause never came close.
The degrade (§0.2 — not optional, built): the history read validates each turn individually; a payload the union can't parse (another deploy's vocabulary — the skew the write guard can't reach) projects as structured_data: null with the turn's text served, and the loss is logged with the kind named — skew observable, never silent. One poison turn never again costs a page.
The invisibility mechanism (§0.3 — recorded where the next person will meet it): on SaveOfferStructuredData's own docstring, in turn_kinds.py's module doc, and in the TS mirror's comment — save_offer is absent from ConverseResponse by design, so live worked and only reload broke; live correctness and reload correctness are different claims; verify persistence through the history read. Every persistence test in this CR obeys its own lesson: all assertions go through the route.
The surface (§1.C, decided at Step 1): the mirror member — typed, no renderer (the offer's prose is the visible half); renderers switch on known kinds and ignore the rest, so a future unknown kind renders nothing and breaks nothing.
Engine: 4 new tests — the identity fence; the write-time refusal; the save_offer round-trip through the history route (E0128's shape — observed failing as the live 422 before the build); the degrade (a raw-SQL "from_the_future" turn — record_turn now refuses it, which is itself the point — served with text intact and marker nulled, the readable sibling untouched). All observed failing first (collection-level). Full suite 3733 passed / 68 skipped (13 mid-build failures caught and fixed: an import injected into a TYPE_CHECKING block — found by the suite, not by the smoke); ruff clean; mypy at the 537 baseline EXACTLY (verified by message-level diff, not count — the refactor's five new trivials cleaned, one pre-existing error's shape preserved). Surface: tsc clean; lint clean (the standing local gate); 808/808.
GET /operator/conversation-history?project_id=<E0128> — the morning's 422 is a 200: all 10 turns served, total_count 10, the save_offer marker valid (assertion_display_number: 1), the turn texts intact. No data change — the turn was always valid; only the reader's vocabulary was behind.cr-2026-213-e0128-history.png."Unwritable rather than unreadable" is the ruling improved on rather than followed — the ask was a shared enumeration; the build moved the failure to write-time (the runtime guard) and to build-time (the fence test). The third instance of the same move: CR-2026-204's AST test, CR-2026-205's source-scrape, and now the kinds fence — the pattern, named as ruled: a contract that must hold over source constructs gets enforced against the source, not against exercised paths.
Kind C as expected: vocabulary and read-path plumbing; no seed contact. Null finding recorded.
Tags both repos; push; watch (verdicts read DIRECTLY — the standing lesson); redeploy; then the acceptance that is the Operator's: E0128's history readable in production — the record that being unreadable was the finding.
DUNIN7 — Done In Seven LLC — Miami, Florida — CR-2026-213 Checkpoint A — v0.1 — 2026-08-14 The writer stopped minting what the reader never learned; the fence holds them to one vocabulary; and the page never again belongs to its worst turn.