Version. 0.1 · Date. 2026-08-11 · Author. Claude Code (drafting, from the disclaimer scoping) / Marvin Percival (approving).
Target. /Users/dunin7/loomworks-engine AND /Users/dunin7/loomworks (the live surface — loomworks-ui is the stale one), both branch main.
Baseline. Engine 64610b4, surface 35a49c9. CC confirms at Step 0.
Companion to. inspection-briefs/loomworks-ungated-chat-disclaimer-scoping-v0_1 (record 34c27cc) and inspection-briefs/loomworks-ungated-chat-production-and-creation-batch-v0_1 (record c9edc3a) — where this CR and the briefs disagree, the briefs govern, verified against code.
Charter. Autonomous regime. Status. DRAFT — awaiting the gate. Do not execute.
A. The channel fact, on the wire and in the record. New field composition on ConverseResponse and new nullable TEXT column composition on conversation_turns (own column, the organized_view_citation precedent — structured_data holds one payload of things the turn produced; this is a fact about the turn's channel). Vocabulary, enumerated in full now (pre-flight shape 4): 'model_prose' and 'server_composed'. TEXT + CHECK constraint admitting exactly those two. Single source of truth: one constants pair in orchestration, imported by writer, migration test, and schema — never retyped.
B. Every branch stamps it — the assignment is exhaustive, not detected. Server-composed: cold-open greeting, completeness-check bypass, delegated responses (all _companion_error-built replies — denials, all-claim acks, held/committed acks, orient), the no-key fallback, the blank-reply substitution (6b), account-status replies. Model prose: path (b) generate_response output. Edge named and chosen: RESPONDER_FALLBACK (and the tier-voice-augmented path-b replies) arrive through generate_response and stamp model_prose even though the fallback string is server-authored — the marker's claims (not a Shape, no provenance, not in Memory) are true of them regardless; channel, not authorship, is what the marker asserts.
C. Persistence and projection. record_turn gains the composition kwarg; /operator/conversation-history projects the column. **Null stays meaningful: every turn written before this CR reads null = unrecorded, and the surface must render null as absent — never as server_composed, never as a marker.** (The B-52 empty-vs-null discipline, applied to a column.)
D. The surface marker (/Users/dunin7/loomworks). Companion turns whose composition is model_prose render one standing marker element — a small, persistent label in the turn's frame, not a sentence in the transcript text. Ruled wording basis: chat text — not a Shape, carries no provenance, not in Memory or the record (short label + the full sentence on disclosure is Step 3's design; the content of the claim is settled). Frontend disciplines apply: strings in strings.ts, no string concatenation in UI text, logical CSS, ONE-WIDTH law. Turns with server_composed or null render nothing.
content). It stabilizes nothing for B-86 — CR-2026-203 and CR-2026-205 carry that program; this CR deliberately does not.ask_about_past_input and the other LLM-voiced informational intents are path (b): their replies stamp model_prose and carry the marker even when sources are attached. Correct — the sources are system facts; the prose around them is still chat text..next intact).
Engine: every branch's stamp pinned (one test per branch arm of the converse dispatch — cold-open, completeness, delegated, orient, no-key, blank-fallback, path-b); persistence round-trip; history projection; CHECK constraint rejects a third value; null on pre-CR rows untouched by backfill (no backfill — deliberately). Surface (vitest, tests/components/lib/ per the B-71 collection rule if adapter-shaped): marker renders on model_prose, absent on server_composed AND null; strings from strings.ts. Fence: the trivial-small-talk turn carries it (unconditional pinned).
Kind C expected: the marker reads the pipeline branch, writes a turn column, and renders — no seed contact on any path. Checked at Step 1 (the delegated branch carries seed-derived draft content through it; the marker itself reads none of it). A null finding is an entry; recorded either way.
| Step | What | Mode |
|---|---|---|
| 0 | Pre-flight — baselines confirmed, both trees clean. | Auto |
| 1 | Verify branch inventory §1B against code (every ConverseResponse construction site enumerated — none unstamped); tests written and observed failing. | Auto |
| 2 | Engine: constants, migration, stamps, record_turn, projection. | Auto |
| 3 | Surface: marker component + strings + history wiring. | Auto |
| 4 | Both suites; ruff; mypy; surface vitest. Eye-test: a model-prose turn and a server-composed turn observed live with the marker present/absent (standing eye-test discipline). | Auto |
| A | Checkpoint. | Checkpoint |
| 5 | Tag cr-2026-204-chat-provenance-marker (engine) + surface commit. Push both. Watch both runs and report. Redeploy the surface per the recorded procedure. | Auto |
ConverseResponse construction site enumerated at Step 1 and stamped — a construction site with no stamp fails the suite (constructor-level default is not used; explicit at every site so a future branch cannot silently inherit a wrong value).
Execute CR-2026-204 v0.1 at change-requests/cr-2026-204-loomworks-chat-
provenance-marker-v0_1.md in loomworks-record. Confirm CR number and
both baselines first. Two repos: engine + /Users/dunin7/loomworks (NOT
loomworks-ui).
§0 is settled: structured marker, unconditional, no detector. If you
find yourself inspecting reply content to decide whether to mark, stop
— that is the ruled-out design.
The stamp is explicit at every ConverseResponse construction site; no
constructor default. Null means unrecorded and renders as absent —
never backfill, never render null as server_composed.
Each test observed failing first. The small-talk fence test is the
ruling in test form: a "hello" turn carries the marker.
DUNIN7 — Done In Seven LLC — Miami, Florida CR-2026-204 — the chat-provenance marker — v0.1 — 2026-08-11 The channel says what it is; absence is never a claim.