DUNIN7 · LOOMWORKS · RECORD
record.dunin7.com
Status Current
Path phases/phase-66-spend-visibility-and-pause/loomworks-phase-66-cr-spend-visibility-and-pause-v0_1.md

Phase 66 — Spend Visibility and the Pause Preference — Change Request

Version. 0.1 Date. 2026-05-30 CR identifier. CR-2026-096 (next after CR-2026-095; verify against the registry at Step 0 and advance if taken) Phase. 66 — Spend Visibility and the Pause Preference (the Operator-facing surface Phase 64 left out) Repos affected. DUNIN7/loomworks (Operator Layer frontend) primary; DUNIN7/loomworks-engine (substrate — pause-preference field, async park/resume, one read endpoint); DUNIN7/loomworks-record. Tag at completion. phase-66-spend-visibility-and-pause on the repos changed. Drawn from. phases/phase-66-spend-visibility-and-pause/loomworks-phase-66-scoping-note-spend-visibility-and-pause-v0_2.md and …-cr-drafting-handoff-v0_2.md. All Operator decisions are settled in the scoping note; this CR is execution. Pre-flight (§6 of the scoping note) is folded in below and not re-verified, except for one new finding (§3.3) surfaced while drafting.


Plain-language summary

What this CR does. Phase 64 built the spend mechanism — the gate, the metering, the FIFO draw-down — as substrate only. A pipeline run today spends silently after a one-time up-front authorization; the Operator sees nothing at spend time. This CR builds what the Operator sees and approves:

  1. Spend visibility, every metered room — after a run, the Operator sees its actual per-run cost and the resulting balance movement.
  2. A spend-pause preference, defaulted on — async Shaping and Rendering spend parks before debiting and surfaces an approval card. The card shows the cost cap ("up to N credits"), not the exact cost, because the exact cost is unknowable before the model runs. The card carries approve / decline / stop-pausing; the third turns the preference off in place. The visibility surface then shows the actual cost after the run. A new Operator is taught the cost model by approving spend, and graduates themselves off pause from inside the card.

What it does NOT do. It does not pause synchronous Manifestation spend — that needs a sync-request→job re-architecture, deferred to Phase B. Manifestation shows-and-proceeds; the help text says so plainly.

The load-bearing piece. The async park/resume mechanism is net-new substrate (Phase 64's jobs run to completion or fail; nothing parks for an Operator decision and resumes). It gets its own checkpoint (Step 3).

One scope adjustment found while drafting (§3.3). The scoping note assumed visibility needs no substrate change. It needs a thin one: the actual per-run cost is currently exposed by no endpoint (only aggregate balance via /me/credits). Step 1 therefore adds a small read endpoint. Balance movement is frontend-derivable; the cost figure is not.

What the Operator does. Review this CR; on approval it goes to Claude Code, which builds across the numbered steps with a halt at the Step 3 checkpoint.


1. Purpose

Phase 64 (CR-2026-095, tag phase-64-pipeline-spend-credit-gate, manifest v0.45) shipped the pipeline-spend gate as substrate only — the CR names "No Operator Layer frontend" in §1, §3.1, §23. Phase 66 builds the Operator-facing surface that completes the loop: the Operator sees spend, and — until they choose otherwise — approves async spend before it debits.

The design is an Operator-set preference, not an inferred gate (the scoping-note discovery trajectory §7 records why every inference required a substrate signal that does not exist on the hot path — decisively, no committed/purchased credit exists yet, so the funding-source distinction a gate would key on is empty). The Operator declares the behavior; the gate obeys.


2. Scope

2.1 In scope (Phase A)

  1. Visibility surface (all metered rooms). After a run, show the actual per-run cost and the balance movement. Requires a thin read endpoint (§3.3) plus the frontend surface. Ships regardless of the pause preference's state.
  2. Spend-pause preference (person-level, default ON). A new persons field mirroring exhaustion_preference's shape plus a server_default so it defaults on. Settings toggle + PATCH /me/settings.
  3. Async park-and-surface (Shaping + Rendering). When pause is on, async spend parks before debit and surfaces an approval card. Net-new job state + approval-driven resume (Step 3, own checkpoint).
  4. Approval card. Shows the cost cap (input tokens + max_tokens ceiling), not exact cost. Carries approve / decline / stop-pausing; the third writes the preference off.
  5. Re-enable affordance on the visibility surface (turning pause off is not a one-way door).

2.2 Out of scope — Phase B (queued)

2.3 Out of scope — future phases


3. Prerequisites

3.1 Baseline

3.2 Confirmed substrate facts (scoping §6 / CC pre-flight — do NOT re-verify)

3.3 NEW finding surfaced at draft (adjusts Step 1 — report-if-scope-shifts)

The actual per-run cost is exposed by no endpoint today. Only GET /me/credits exists (aggregate per-asset balance); the converse response does not carry the spent cost; gated_room_complete computes credit_debit but discards it (it returns the CompletionResult, not the debit — room_gate.py:130). The consumption flows are written to credit.flows but nothing surfaces them.

Therefore the scoping note's "no substrate change is required for visibility" (§2.1) holds only for balance movement (derivable from /me/credits before/after). The actual per-run cost figure is net-new substrate. Resolution (recommended): Step 1 adds a thin read endpoint GET /me/spend returning recent consumption transactions (per transaction_id: room, credit asset_id, credit_debit, occurred_at, and the balance-after) — additive, read-only, serves both the per-run cost and the balance movement cleanly. Alternative, lighter: thread credit_debit out of gated_room_complete onto the room's produced event so the existing room read path carries it. Step 0 confirms the choice with the Operator.

3.4 Step 0 — pre-flight

CC re-confirms baseline + §3.2 names at the build SHA, resolves the §3.3 read-endpoint choice, confirms no spend_pause/park-state structures pre-exist, and archives this CR to docs/phase-crs/ (engine) and docs/phase-crs/-equivalent. Halt-and-amend if the §3.2 load-bearing items (gate seam, job dispatch, ApprovalCard registry) diverge.


4. Architecture decisions (carried from the scoping note — settled)


5. Build detail

5.1 Visibility (Step 1)

5.2 Spend-pause preference field (Step 2)

5.3 Async park/resume (Step 3 — CHECKPOINT, the load-bearing build)

5.4 Approval card (Step 4)

5.5 Settings + re-enable (Step 5)


6. Migrations


20. Build steps and checkpoints

Auto-mode posture: Steps proceed in auto-mode; the Step 3 checkpoint halts for Operator confirmation; the final tag executes after Operator approval.

  1. Step 0 — pre-flight (§3.4). Confirm baseline + names; resolve the §3.3 read-endpoint choice and the §5.4 off-switch-mechanism choice; archive CR. Halt on §3.2 architectural divergence.
  2. Step 1 — visibility surface + GET /me/spend (§5.1). Engine read endpoint + frontend readout + re-enable affordance shell. Ships value alone; no pause dependency.
  3. Step 2 — spend-pause preference field (§5.2). Migration 0077 (default ON), ORM, /me payload, PATCH /me/settings.
  4. Step 3 — async park/resume (§5.3) — ★ CHECKPOINT ★ (the load-bearing build). pending_approval state (migration 0078), pre-debit park branch (shaping/rendering only — must not touch Manifestation), approval-driven re-cost resume (D7), decline path. Halt and report at Checkpoint: park parks before debit, approve resumes-and-spends ≤ cap, decline ends with no debit, Manifestation untouched, shaping + render both covered, suite green.
  5. Step 4 — approval card + dispatcher wiring (§5.4). Card action_type='spend_pause_approval', three actions, off-switch on approve.
  6. Step 5 — settings toggle + re-enable + help text (§5.5).
  7. CHECKPOINT (final) — CC reports: visibility shows actual cost + balance movement; default-on confirmed; pause parks async spend pre-debit and surfaces the cap; approve resumes (≤ cap), decline no-debit, stop-pausing flips the preference; Manifestation shows-and-proceeds; suite green (two pinned unchanged). Operator confirms.
  8. Step 6 — tag phase-66-spend-visibility-and-pause (post-checkpoint, after Operator approval).

20.1 Halt thresholds (handoff §5)

20.2 Seed check (handoff §6)

Confirm alignment with loomworks-candidate-seed-v0_9: default-on pause = "the Operator approves spend" as the out-of-box stance (seed: "the system surfaces and signals; the Operator approves"); in-card off-switch = Operator authority to relax; "only show what is available" = cards stop appearing when pause is off. If any requirement would introduce an automatic spend state-transition the Operator has not authorized, raise it against the seed before implementing (the gate already requires up-front authorization; pause adds, not removes, Operator control — so this is expected to pass).


21. Acceptance criteria

  1. GET /me/spend returns the person's recent consumption (per-run credit_debit, room, asset, time); the visibility surface shows actual per-run cost + balance movement, all metered rooms.
  2. persons.spend_pause exists, TEXT CHECK ('on','off'), defaults 'on'; existing rows backfilled 'on'; PATCH /me/settings updates it; migration 0077 round-trips.
  3. With pause on, an async Shaping or Rendering run parks before debit (pending_approval) and surfaces an approval card showing the cost cap ("up to N"); no debit before approval.
  4. Approve resumes the run; it spends and the actual debit is ≤ the displayed cap; the visibility surface shows the actual cost.
  5. Decline ends the run with no debit; the Operator sees the decline.
  6. Stop-pausing flips spend_pause to 'off' (in place) and resumes; subsequent async runs spend without a card.
  7. With pause off, async spend proceeds and is shown, not paused.
  8. Synchronous Manifestation never parks — it shows-and-proceeds; the park branch does not touch its path; help text states the gap.
  9. Settings toggle mirrors ExhaustionPreferenceSection; the re-enable affordance turns pause back on from the visibility surface.
  10. Migration 0078 (park state) round-trips; pending_approval distinct from awaiting_external.
  11. Suite green (engine + frontend; two pinned engine failures unchanged; no new skips); alembic head 0078.

22. Post-CR state

Engine: GET /me/spend; persons.spend_pause (default on); pending_approval job state + approval-driven re-cost resume; alembic 0078. Operator Layer: a spend-visibility surface (actual cost + balance movement + re-enable), an approval card (cap + approve/decline/stop-pausing), a settings toggle. The Operator now sees spend on every metered room and approves async spend until they graduate themselves off. Manifestation pause remains Phase B. Tag phase-66-spend-visibility-and-pause.

23. What this CR does not build

(Restated for Checkpoint clarity.) Synchronous Manifestation pause (Phase B); funding-source/commitment-keyed gate; per-lot/"free credits remaining" readouts; credit purchase (Phase 65); real-currency cost display; multi-Operator approval delegation.

24. Kickoff prompt for the Claude Code session


Read CR-2026-096 (Phase 66 — Spend Visibility and the Pause Preference) at
loomworks-record/phases/phase-66-spend-visibility-and-pause/loomworks-phase-66-cr-spend-visibility-and-pause-v0_1.md,
and the scoping note + handoff v0.2 beside it.

Phase 66 builds the Operator-facing surface Phase 64 left out: spend visibility on
every metered room, and a default-ON spend-pause preference that parks async
Shaping/Rendering spend behind an approval card showing the cost CAP (exact cost is
unknowable pre-run), with an in-card off-switch. Manifestation shows-and-proceeds
(pause is Phase B). Primary repo loomworks (frontend); substrate changes in
loomworks-engine (the spend read endpoint, the spend_pause field, the async
park/resume). Baseline: engine main 95e072d / alembic 0076; OL main 1ce2542.

Run Step 0 pre-flight per §3.4 — confirm the §3.2 names hold at the build SHA,
resolve the §3.3 read-endpoint choice and the §5.4 off-switch mechanism, archive
the CR. HALT and amend if the gate seam, async job dispatch, or ApprovalCard
registry diverge.

Build Steps 0–5 per §20. STEP 3 (async park/resume) IS ITS OWN CHECKPOINT — halt
there and report before continuing. Resume strategy is RE-COST (re-dispatch the
agent after approval) unless caching proves necessary (§20.1 fork). The park branch
MUST NOT touch the synchronous Manifestation path. Halt thresholds per §20.1; seed
check per §20.2. Then the final checkpoint halts for Operator confirmation; tag at
Step 6 after approval.

Implementation notes after the final checkpoint:
docs/phase-impl-notes/phase-66-implementation-notes-v0_1.md
Tag (post-checkpoint): phase-66-spend-visibility-and-pause.

DUNIN7 — Done In Seven LLC — Miami, Florida Phase 66: Spend Visibility and the Pause Preference — CR-2026-096 v0.1 — 2026-05-30