Version. 0.1
Date. 2026-08-02
Executed by. Claude Code, execution session on DUNIN7-M4.
CR. change-requests/cr-2026-162-render-flow-v0_4.md — confirmed the highest version present (numeric sort; the record holds v0.1 and v0.4, and the gap is deliberate).
Charter. standing-notes/dunin7-standing-authorization-charter-v0_1.
Halt condition. §6 determination 2, as the CR itself specifies: "If they cannot, halt and report rather than displaying a judgement the data does not support."
Status. HALTED AT STEP 0. No code written, in either repository. Both trees clean, both still on main, no branch created.
| Check | Result |
|---|---|
| Operator Layer | main 7e81e30, matches origin/main, tree clean |
| Engine | main a6a3ed6, matches origin/main, tree clean |
| CR number | CR-2026-162 — nothing higher filed |
| Branch discipline | Both repos still on main. Nothing committed, so nothing needed a branch. |
| playground_dev | Never connected to. |
Operator Layer baseline, recorded by name:
Test Files 106 passed (106)
Tests 630 passed (630) 0 failed
Errors 12 unhandled rejections exit code 1
Rejection set by origin: operator/Home.test.tsx ×7, nav/NavBar.test.tsx ×4, nav/AppShell.test.tsx ×1 — all fetchPlatformLevel.
> v0.4's baseline correction earned its keep immediately. The header states 630. v0.1 stated 610, and a Step 0 comparison against that figure would have read as a divergence and halted for nothing. The corrected number matched the observed run exactly.
Engine baseline, recorded by name, run against playground_test:
FAILED tests/test_stele_router_mount.py::test_stele_router_mounts_and_begin_resolves_end_to_end
1 failed, 3459 passed, 68 skipped
The single failure is the long-standing unrelated 401 (build-list B-33), exactly as the CR's header states. Both baseline sets are therefore on record, though neither was needed for this halt — no code was written in either repository.
All three routes exist at a6a3ed6, in api/routers/renders.py:
| Route | Handler | Returns |
|---|---|---|
| GET …/renders/{object_id}/download | download_render_route (:793) | Response with media_type=result.content_type and Content-Disposition: attachment; filename="…" |
| GET …/renders/{object_id}/content | render_content_route (:969) | content in its native shape — inline_dict → JSON, binary_blob → bytes, external_reference → JSON envelope |
| GET …/renders/{object_id}/files/{filename:path} | render_file_route (:1100) | per-file retrieval within a multi-file render |
/download carries the format override the findings described: format: str | None = Query(default=None) — "grab an HTML or MD copy of a render whose declared format is PDF, without producing a second render." Error paths return JSONResponse 404 and 422. Only produced renders can be downloaded.
The authentication question, which looked like a halt and is not. All four render routes — including the list route the surface already calls successfully today — depend on get_contributing_contributor. That reads as a bearer-token contributor path, which the Operator Layer does not use.
It resolves. get_current_contributor (api/deps.py:773) accepts both paths and documents the precedence: "Session cookie (humans). Resolved via the person + membership tables… Synthesizes a Contributor view with kind='human', id=person.id", and "Cookie takes precedence." The Operator's session satisfies it, exactly as it already does for the list route.
No engine route needs changing. D1 does not halt.
The answer is no, and the reason is stronger than the CR anticipated: the engine has no superseded render.
The CR's counter named the trigger as "two renders can hold the same state with no ordering between them." What the read establishes is adjacent but more fundamental.
What was read at a6a3ed6:
engagement/composition_orchestrator.py — the production path — contains zero references to retire, supersede or invalidate. A sweep of the render modules for supersed* returns nothing at all._retire_render (engagement/render.py:12) is "operator-driven retirement" and is called from exactly one place: retire_render_route (api/routers/renders.py:1291). _invalidate_render is drift-routed, fired when an upstream consideration closes.display_number is ordered, but only within a scope. assign_render_display_number (engagement/display_numbers.py:141) is MAX+1 "scoped to (engagement_id, declared_render_type_ref)", with None forming the separate ad-hoc scope.
So two renders of the same declared type sit in produced indefinitely, and neither supersedes the other. The older one is not stale, not replaced, and remains a legitimate downloadable output.
What the three fields can and cannot support:
| Claim | Supported? |
|---|---|
| "this render is newer than that one" (same declared type) | yes — display_number is strictly ordered in that scope |
| "this render is newer" (across declared types, or against an ad-hoc render) | no — separate MAX+1 sequences, not comparable |
| "this render is retired / invalidated" | yes — state says so, but only after an explicit act |
| "this render is current and that one is superseded" | NO — there is no supersession, so there is nothing to be superseded by |
Displaying a current-marker would be face 2 — the surface asserting a status the record has never established. That is precisely what the CR's own honest counter said to halt on, and it is why this halts rather than proceeding to Step 4.
What this means for B-7's second half. The build-list framing is "nothing says which is current." The engine does not have a notion of a current render, so the gap is not that the surface fails to display one — it is that the concept does not exist. B-7's second half rests on a premise the substrate does not carry.
A constructive path exists and is deliberately not taken here. The surface could honestly display recency — display_number ordering within a type, plus created_at and state — which solves the user-facing problem of telling an older output from a newer one without claiming currency. That is a different feature from the one B-7 describes, and choosing it would be resolving an ambiguous determination by choosing, which the kickoff forbids in as many words.
Does a discovery extraction ever reach UploadResultItem or PerFileUploadResponse? No — and the trace is short.
PerFileUploadResponse.source_mode (api/routers/uploads.py:470) is populated from _source_mode_for_selected_chain (:883, defined :501), which reads a fixed map, _SKILL_SOURCE_MODE (:489-498):
image_vision_analysis → image pdf_extraction → pdf
image_ocr → image text_extraction → text
image_metadata → image docx_extraction → text
audio_transcription → voice html_extraction → text
There is no discovery entry, and unmapped skills return None (:508). UploadResultItem is constructed from the same shape (uploads.py:1061).
The upload pipeline and the contribution endpoint use different registries. The upload path dispatches over the detection-chain skills above; discovery_to_seed lives in the contribution endpoint's ExtractionSkillRegistry, registered against text/markdown at skills/registry.py:201. The two never meet.
So the upload-side pair must NOT be changed. Adding discovery there would declare a value that path cannot produce — the exact mirror of the text member that is allowed and emitted by nobody, which D-2 names as half of what made this defect possible in the first place.
D-2's conditional resolves to: two declarations, api/schemas.py:2524 and :2806. Both re-confirmed at a6a3ed6, on AddAssertionRequest and AssertionResponse. No fifth declaration exists — the sweep returns exactly four across src/.
D1 and D3 are settled and favourable. If the Operator resolves D2, the CR can resume with:
> The halt is confined to one step. Three of the four in-scope items are ready to build. Nothing about D2 blocks B-28 or the download half, and a v0.5 could drop or re-scope Step 4 and ship the rest.
Q-13 — does a "current render" exist, and should it?
| | |
|---|---|
| Question | The engine has no supersession for renders: producing one never retires another, and two renders of the same declared type sit in produced indefinitely. B-7's second half asks the surface to say which is current. There is no current. Is the right answer (a) display recency and drop the currency framing, (b) build supersession in the engine so there is a current render, or (c) leave B-7's second half unbuilt? |
| Default | (a) — display recency, re-scope B-7's second half. It solves the Operator-facing problem, uses only fields already sent, asserts nothing the record does not carry, and costs no engine change. |
| Blocks | Step 4 only. |
| Proceeds regardless | B-28 (Step 1), the adapter (Step 2), the Download control (Step 3). |
Q-12 is answered and should be closed. It asked whether renders need an explicit current-marker. They cannot have one derived from what is sent, because nothing is ever superseded — so the question is no longer "surface-first or engine-first" but "does the concept exist at all," which is Q-13.
A v0.5 from a drafting session, carrying:
DUNIN7 — Done In Seven LLC — Miami, Florida CR-2026-162 — Step 0 halt report — v0.1 — 2026-08-02 Nothing is superseded, so nothing is current. The surface was about to say otherwise.