Version. v0.1
Date. 2026-08-01
Author. Claude.ai (drafting session). Approving: Marvin Percival.
Charter. standing-notes/dunin7-standing-authorization-charter-v0_1. No session executes a change request it drafted (§1).
Target. /Users/dunin7/loomworks at main 7e81e30, and /Users/dunin7/loomworks-engine at main a6a3ed6 — two repositories, and §2 explains why.
Baseline. Neither repository is green. Operator Layer: 610 passed, 0 failed, exit code 1, twelve unhandled fetchPlatformLevel rejections. Engine: 1 failed (test_stele_router_mount), the rest passing. The criterion is no new failure and no new unhandled rejection, against sets recorded at Step 0. Exit 0 is not reachable and is not the criterion.
Build-list items. B-28, B-7.
CR number. CR-2026-162. Highest confirmed is CR-2026-161. [EXECUTING SESSION: verify; advance if taken.]
Grounding. inspection-briefs/loomworks-cr-c-step-0-findings-v0_1 — every anchor below comes from it.
Status. Pre-execution.
What changed from the plan. Change request C was scoped as B-6, B-7 and B-28 together. B-6 is split out — see D-1. This CR is the small, surface-facing half, and it ships a user-visible fix and a user-visible capability without waiting for the larger room.
B-28 — contributed Markdown is refused and the work is lost. Two type declarations disagree with what the system actually emits. Two lines.
B-7, first half — there is no way to download a finished render. The engine has served download routes all along. The surface has never called them. A wire, not a build.
B-7, second half — when an older and a newer render sit side by side, nothing says which is current. The surface already receives three fields that bear on it and displays none.
It does not change the engine. The engine is read-only here, for one purpose: confirming the download routes' contracts before the surface calls them. /renders/{id}/download, /content and /files/ are established as existing by the Step 0 read; their exact parameters, response shapes and format-conversion behaviour must be read before an adapter is written against them.
No engine file is edited. No migration. No engine commit. If a route turns out to need changing, halt — that is an engine change request, not this one.
D-1 — B-6, the Shaping room, is split into its own change request.
The Step 0 read establishes that Shaping's engine surface is not what Manifestation's was: it carries a confirm/retire lifecycle, executors, and asynchronous jobs. B-5 needed no engine work, and inheriting that as though the rooms were the same size is the error the findings warn against.
B-6 gets its own scoping and its own Step 0, covering the lifecycle, what the surface must show while a job is running, and whether the shape-type-to-render-type mapping is enforced or merely exposed — the second of the findings' two unread items.
Nothing in this CR is blocked by that split. B-28 and B-7 touch neither Shaping's room nor its adapter.
D-2 — B-28 is fixed at both declarations, and the routing question is opened separately. (Queue entry Q-11, taken.)
text/markdown is registered to the discovery-to-seed skill, which emits source_mode="discovery". The assertion schema declares Literal["text", "voice", "pdf", "image"] at schemas.py:2524 and again at :2806. discovery is emitted and not allowed; text is allowed and emitted by no skill.
Add discovery to both declarations. A fix reaching one leaves the other to fail identically — that is the shape of the defect and the reason it must be stated as two.
Reasoning, and the question deliberately not answered. The findings note that contributed Markdown currently routes through seed extraction, while that registration's own comment says the canonical path is elsewhere. Whether the routing is right is a real question and it is not this one. Making an allowed set match what the system actually emits is not a design commitment — it makes a declaration honest about current behaviour, and if the routing moves later the literal moves with it. The routing question becomes its own build-list item. Deciding it here is the scope absorption C-3 forbids.
What this does not require. Nothing is lost and nothing needs recovering. The assertion is written at contributions.py:268, the response is built after it, and get_db_session rolls back on any exception — so the durable state is as if nothing happened, and the uploaded file row survives, meaning the same file_id re-contributes once the mismatch is fixed. No migration, no backfill, no data repair. The loss is of the person's work, not of their bytes.
D-3 — the currency half is built surface-first, with no engine change. (Queue entry Q-12, taken.)
Renders carry no supersession marker, where Manifestations do. That is a real asymmetry and it is not necessarily this CR's problem. The surface already receives state, created_at and display_number on every render and displays none of them.
Display what is already sent. Then judge whether a marker is still missing.
Reasoning. Building an engine field before establishing that the surface needs it is the wrong order, and the Manifestation precedent is the direct evidence: its staleness marker looked like a build and turned out to be a wire. If, after this CR, the Operator still cannot tell which render is current, the engine marker becomes its own item — informed by what the display revealed rather than by a guess made before it existed.
The honest counter, recorded. Three fields the Operator can interpret is not the same as one field that states the answer. A derived judgement can be wrong in ways a marker cannot. If Step 0 finds that state and display_number cannot distinguish current from superseded — for instance if two renders can hold the same state with no ordering between them — halt and report, because then the surface genuinely cannot say it, and saying it anyway is face 2.
D-4 — the Download control appears only where a download is possible.
RenderingRoom carries a comment recording that no Download button was built because there was no route to call. There is one. The seed's only-show-what-is-available constraint forbids a disabled or greyed control — so the button appears when the render is downloadable and is absent otherwise, never present-and-inert.
And it obeys the room state contract. A download control rendered from a failed read would imply the render exists when no read established that. It appears on populated only.
4.1 B-28 — src/loomworks/api/schemas.py, engine repository. [This is the one exception to §2's read-only engine, and it is two lines.] Add discovery to the source_mode literal at :2524 and at :2806. [EXECUTING SESSION: re-confirm both anchors and sweep for any third declaration of the same literal. A third would fail identically and the findings established two by reading, not by exhaustive sweep.]
> Correction to §2, made explicit. §2 says no engine file is edited. That is wrong as written and this is the exception — B-28's fix is in the engine's schema module. What §2 protects is that no engine behaviour, route or migration changes. Two literals gain a member that the system already emits. A separate engine commit, separate from the surface work.
4.2 The render adapter — a new file in the Operator Layer's lib/api/. The wall does not constrain its name: the Step 0 read establishes that rendering is not a forbidden term and the room may be named for itself throughout. Add it to WIRE_BOUNDARY_FILES per the existing convention.
4.3 RenderingRoom.tsx — the Download control per D-4, and the currency display per D-3.
4.4 The strings for both, asserting the surface where no read stands behind them, per the governing rule.
lib/api/shape.ts and never shaping.ts — the wall reads import specifiers, so a room-named adapter trips every consumer. (Recorded here because it is the trap CR-2026-160 hit, and it is now pre-answered.)unread. It needs a perimeter call the fences forbid, and the defect's mechanism does not depend on it.fetchPlatformLevel rejections — build-list item B-34.Per-step commits. Two repositories, so two commit series — never one commit spanning both. Check the current branch before the first commit in each.
Step 0 — pre-flight and two determinations. Verify both HEADs, both tree states, the CR number. Record both baseline sets — the engine's failure set, and the Operator Layer's failure set and unhandled-rejection set and exit code.
Then settle, by reading:
state, created_at and display_number distinguish a current render from a superseded one? Per D-3's counter. If they cannot, halt and report rather than displaying a judgement the data does not support.
Report both before proceeding. Commit: CR-2026-162 step 0: pre-flight and two determinations
Step 1 — B-28, engine repository, two literals. Suite against the engine baseline.
Commit (engine): CR-2026-162 step 1: allow the discovery source mode
Step 2 — the render adapter, plus its WIRE_BOUNDARY_FILES entry.
Commit (OL): CR-2026-162 step 2: render download adapter
Step 3 — the Download control, per D-4.
Commit (OL): CR-2026-162 step 3: download control on populated renders
Step 4 — the currency display, per D-3 and Step 0's determination.
Commit (OL): CR-2026-162 step 4: render currency display
Step 5 — tests. A test that a discovery contribution is accepted end to end; a test that the Download control is absent on failed and empty and present on populated; a test of the currency display. Assert specific conditions, never a bare Exception.
Commits: per repository.
CHECKPOINT A — report, then proceed. Both baseline comparisons; the tests; a live pass on the dev server showing a Markdown contribution accepted, a render downloaded, and two renders side by side with the current one distinguishable. No Operator confirmation. Halt and queue on: any new failure or rejection; either determination coming back ambiguous; any charter §6 anomaly.
Step 6 — implementation notes, in both repositories, recording both determinations.
CHECKPOINT B — merge and tag, separately per repository. --no-ff in each; tag the Operator Layer render-flow-v0_1 and the engine discovery-source-mode-v0_1. Push both. Authorized under R-2 including the pushes. Deployment is never autonomous (F-1).
source_mode literal declarations accept discovery, and a sweep finds no third.populated only, and never as a disabled or inert control.WIRE_BOUNDARY_FILES; the vocabulary wall passes with no other new exemption.This block names the entry point and the fences. It does not restate §6's steps.
CR-2026-162 — B-28 and B-7. Execution session.
CR: loomworks-record/change-requests/cr-2026-162-render-flow-v0_1.md
Confirm it exists, and that it is the highest version present — numeric sort.
Grounding, read before the CR:
inspection-briefs/loomworks-cr-c-step-0-findings-v0_1.md
Charter dunin7-standing-authorization-charter-v0_1 governs.
Section 6 is the step sequence; follow it there.
TWO REPOSITORIES. /Users/dunin7/loomworks at main 7e81e30 and
/Users/dunin7/loomworks-engine at main a6a3ed6. Separate branches, separate
commit series, separate merges and tags. Never one commit spanning both.
The engine change is TWO LITERALS in schemas.py and nothing else. No route,
no migration, no behaviour. If anything else in the engine needs to change,
halt — that is a different change request.
playground_dev is the live production database and is not touched.
NEITHER BASELINE IS GREEN. The OL exits 1 on twelve fetchPlatformLevel
rejections; the engine has one long-standing failure. Record both baseline sets
at Step 0. "No new failures and no new rejections" is the criterion. Exit 0 is
not reachable.
Step 0 settles two determinations and reports both before any code changes.
The second may legitimately come back as "these fields cannot distinguish
current from superseded" — if so, halt. Do not display a judgement the data
does not support.
Commit to a branch in each repository. Check the current branch before the
first commit in each.
Steps 0 through 5 auto. CHECKPOINT A reports and proceeds on a clean report.
Step 6 auto. CHECKPOINT B merges and tags each repository separately.
Deployment is never yours.
Append the outcome to current-status/dunin7-status-brief at close.
DUNIN7 — Done In Seven LLC — Miami, Florida CR-2026-162 — B-28 and B-7: the lost contribution and the Rendering flow — v0.1 — 2026-08-01 Two literals, one wire, and three fields already arriving unused.