Version. 0.1
Date. 2026-08-07
Author. Claude Code (Wave 0 session). Operator: Marvin Percival.
Charter. standing-notes/dunin7-standing-authorization-charter-v0_1.
Scope. Wave 0 investigation 0.2 of standing-notes/loomworks-development-schedule-v0_1. Read-only. No code changed, no database touched, no suite run.
Read against. Surface loomworks at baec093; engine loomworks-engine at afdeff5. Both clean.
No in-line spend-consent pattern exists in the surface. One adjacent pattern exists — an out-of-band approval card in the notification inbox — and it structurally excludes Manifestation by design. Separately, this investigation found a live defect: the Manifestation room's spend context is computed, passed toward the LLM call, and then silently dropped, so the Manifestation LLM call is unmetered today and the route's own 402 handler is unreachable. That changes B-32's premise and is reported here rather than fixed.
The only qualifying component is SpendPauseApprovalCard (src/components/notifications/SpendPauseApprovalCard.tsx). It shows a cost cap line, offers Approve / Decline / Stop-pausing, and on approve POSTs to /operator/notifications/{id}/approve. It mounts from InboxView.tsx when action_type === "spend_pause_approval".
Three reasons it is not the pattern B-32 needs:
src/loomworks/credit/room_gate.py:114 — _PAUSEABLE_ROOMS = frozenset({"shaping", "rendering"}), with the comment at :203 stating Manifestation is excluded because a synchronous call "cannot await an Operator decision without the Phase B sync→job re-architecture." Verified directly.Two hard negatives, both verified by direct grep of the surface:
| Check | Result |
|---|---|
| Any "will cost / estimated cost / confirm spend" language | exactly one hit — src/lib/strings.ts:731, the cap line above |
| Any HTTP 402 handling | zero hits across all of src/ |
Ruled out after inspection, and named so nobody re-checks them: ExhaustionChoiceDialog (post-exhaustion, no cost shown, no spend proceeds), SpendVisibilitySection (retrospective display plus a pause toggle), BalanceChip / TierBadge (display only), GrantDecisionApprovalCard (approves issuance, not spend).
Plainly stated, as the investigation was asked to state it: there is no prior art for "show the cost, take consent, then spend." Building one is net-new.
Re-derive is two routes, both in src/loomworks/api/routers/manifestations.py, registered without a prefix.
POST /engagements/{engagement_id}/manifestations/preview — the metered step
Declared :321, handler :336.
engagement_id only.ManifestationPreviewResponse, api/schemas.py:6337): engagement_id, engagement_version, assertion_count, relationship_count, seed_version (all required); changes_since_last_manifestation: dict | None; proposed_ordering: ManifestationOrderingSchema | None — the LLM-produced grouping, null when there are no committed assertions.rationale: str, groups: [{label, assertion_refs: [{assertion_id, version}]}].:337–341): db session; get_contributing_contributor; get_llm_client_for_engagement; get_manifestation_spend_context.402 on RoomSpendRefusedError with {error, reason, exits} (:364); 503 when no model key (:373); 502 on unparseable/invalid LLM ordering (:378).POST /engagements/{engagement_id}/manifestations/derive — the free step
Declared :396, handler :411, returns 201.
DeriveManifestationRequest with one optional field, organized_groups — the ordering confirmed at preview, echoed back verbatim and stored as given, not re-validated (:107, :422).ManifestationResponse — manifestation_id, version, engagement_version_at_derivation, derived_by, derived_at, counts, seed_version, state: "current"|"superseded", superseded_by_ref, organized_groups.current and supersedes the prior one in the same transaction.
Metered vs free, as the code draws it. The single LLM call is organize_assertions. Metering is not a property of the room but of the key: get_manifestation_spend_context (:282) returns None unless the engagement resolves to a system key, and gated_room_complete (credit/room_gate.py:181) falls through to an unmetered call whenever key_source != "system". Own-key engagements are free; system-key engagements are intended to be metered.
Surface-side starting point: the surface does not call preview or derive at all today (zero hits). src/lib/api/compose.ts implements only two Manifestation reads (:258, :279), and ManifestationRoom.tsx:21 states the room "NEVER re-derives on its own."
preview_manifestation accepts a spend context and never forwards it. Verified by reading all three layers:
manifestations.py:341 (dependency), :363 (spend_context=spend_context).engagement/manifestation.py:400, spend_context: object | None = None.organize_assertions omits it — manifestation.py:463–467 passes only seed, assertions, llm. No spend_context, no db.engagement/manifestation_organization.py:417 — if spend_context is not None and db is not None: … else: bare llm.complete().
Therefore the Manifestation room takes the unmetered path in every case, and the route's 402 handler at manifestations.py:364 is unreachable. Phase 64's gate is wired at the route and implemented in the gate function; the middle link drops it.
Why it survived. tests/test_phase_64_room_gate.py exercises gated_room_complete directly with room="manifestation" (:71, :103) and passes. The unit is tested and correct; the integration from preview_manifestation through to it is not covered. A green suite is consistent with this defect.
Not fixed here — this is a read-only pass, and the fix is a behavior change (it would start charging for something currently free). Reported for its own CR.
CR-2026-187 was scoped as "add a re-derive control with a spend-consent surface in front of it." The honest inputs:
compose.ts, and the surface's first 402 handling.strings.ts:732); or ship the re-derive control with no consent step on the grounds that the call is genuinely free today — which is defensible right now but silently becomes wrong the moment §3 is fixed.DUNIN7 — Done In Seven LLC — Miami, Florida Loomworks — B-32 findings — v0.1 — 2026-08-07