04 — Expanded BEGIN..ROLLBACK Rehearsal (2 passes, both GREEN)
title: 04 — Expanded BEGIN..ROLLBACK Rehearsal date: 2026-05-31 verdict: GREEN ×2 · zero net mutation
04 — Expanded BEGIN..ROLLBACK Rehearsal
Two transactions on workflow_admin, each -v ON_ERROR_STOP=1 with
SET LOCAL lock_timeout='3s'; statement_timeout='30s'; idle_in_transaction_session_timeout='60s',
each terminated by ROLLBACK. Raw output in doc 14 (E11, E12).
Pass 1 — read-only view/function layer (the commit-ready pack, doc 03)
| question | answer |
|---|---|
| compiled? | Yes — all 6 objects (5 views + 1 STABLE fn) created without error |
| rows? | leaf 160 · count_integrity 160 · drift 3 · living_lists 160 · tree 37 · fn 1/call |
| invariant reproduced? | Yes — 160 / Σrec 2,002,041 / Σact 2,001,909 / net_gap 132 / drift 3 / unverified 5 / orphans 0 |
| drift closure? | Yes — leaf net_gap 132 == Σ(v_count_drift.gap) 132 (no leakage) |
| coverage honest? | Yes — pivot_backed 21 / pivot_missing 139 (not hidden) |
| classification works? | Yes — balanced 152 · unmeasured 5 · model_a_surplus_recheck 1 · model_b_unregistered_candidate 1 · model_b_phantom_candidate 1 |
| fn behaves? | Yes — CAT-006 → 309/163/pivot 309; CAT-023 → 985,472/985,471/pivot 985,472 |
| risk? | low — pure read-layer; no base table touched; lock/stmt timeouts bounded the tx |
| rollback proof? | Clean — POST: 0 views, 0 fn, idle_in_tx 0 |
| commit-ready? | YES (gated on RG1+RG2) |
Pass 2 — additive proposals (gated; rehearsed for validity)
| structure | result | gate |
|---|---|---|
registry_pin (CREATE + 2 INSERT) |
created; 2 rows; CHECK scope IN (global,user,role,team) confirmed |
RG5/P8 |
display_policy threshold table |
created; PG-resolved ceiling → 28/160 exceed (no literal 50 in query) | RG5/P7 |
| parent_code drill-wiring (CTE overlay, no base mutation) | 13 edges → 37 roots → 24 roots / 6 parents / 0 dangling | P-DRILL |
| PIV-500 grand-total candidates | 4 disagreeing totals surfaced: 2,002,041 / 2,001,909 / 1,719,958 / 2,003,754 | RG3/P5 |
| rollback proof | Clean — POST2: 0 new tables, idle_in_tx 0 | — |
Pass 2 deliberately used a CTE overlay for parent_code (a SELECT, not an UPDATE) so it does NOT fire
trg_pivot_def_refresh. The real wiring UPDATE/INSERT statements (doc 05) fire that trigger and must run off-peak inside their own gated macro.
Net mutation proof
Entry == exit on object existence (0→0) for both passes; idle-in-transaction 0 throughout; no COMMIT issued; no base table altered; no row persisted. ZERO net mutation.
Why this clears RG8 (rollback plan)
Additive-only, BEGIN..ROLLBACK-first, reversible by 999_rollback.sql, no forward-only step, no
data transformation. The teardown was demonstrated, not asserted.