DUNIN7 · LOOMWORKS · RECORD
record.dunin7.com
Status Current
Path inspection-briefs/loomworks-b32-findings-v0_1.md

Loomworks — B-32 findings: does a spend-consent surface already exist? — v0.1

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.


Verdict, in one line

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.


1. Prior art: one component, and it does not fit

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:

  1. It is out-of-band, not in-line. The engine parks a job, writes a notification, and the Operator approves later from the inbox. There is no in-request "show cost → confirm → proceed" flow anywhere in the surface.
  2. It excludes Manifestation on purpose. 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.
  3. It shows a cap, not an estimate of the specific call.

Two hard negatives, both verified by direct grep of the surface:

| Check | Result | |---|---| | Any "will cost / estimated cost / confirm spend" language | exactly one hitsrc/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.

2. The engine's re-derive seam — enough detail to wire against

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.

POST /engagements/{engagement_id}/manifestations/derive — the free step

Declared :396, handler :411, returns 201.

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."

3. The live defect this investigation found

preview_manifestation accepts a spend context and never forwards it. Verified by reading all three layers:

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.

4. What this means for Wave 3

CR-2026-187 was scoped as "add a re-derive control with a spend-consent surface in front of it." The honest inputs:


DUNIN7 — Done In Seven LLC — Miami, Florida Loomworks — B-32 findings — v0.1 — 2026-08-07