RP DOT Pivot-Update — 04 Rehearsal (BEGIN..ROLLBACK, 0 mutations, bug found+fixed)
04 — Rehearsal (BEGIN..ROLLBACK on production)
Full log: artifacts/rehearsal_log.txt. Channel: ssh contabo → docker exec -i postgres psql -U directus -d directus. Every run committed nothing.
Method
BEGIN..ROLLBACK on production was chosen over a fresh clone: the refresh trigger
functions are transaction-safe (xact-scoped advisory lock, no NOTIFY/dblink), so an
UPDATE applied then ROLLBACK leaves the database byte-identical while exercising the real
trigger path. The mission lists this as "strongly preferred". The tool's default DRY-RUN
mode performs exactly this internally.
Fingerprint invariant
ENTRY pivot_definitions md5 = 70d6df05501a7de91e24b848168c5b03 n=37 active=35
EXIT pivot_definitions md5 = 70d6df05501a7de91e24b848168c5b03 n=37 active=35 ← IDENTICAL
The 3 composition fixes — DRY-RUN result
| Pivot | species | comp change | AFTER_FIELD | mapping-view composition_status | txn |
|---|---|---|---|---|---|
| PIV-001 | catalog | molecule→atom | atom | match (was mismatch) | ROLLBACK |
| PIV-016 | species | atom→meta | meta | match | ROLLBACK |
| PIV-021 | checkpoint_support | atom→molecule | molecule | match | ROLLBACK |
Each proves the fix is correct against the live governance view, committing nothing.
Rejection / edge battery (10 cases, all correct)
| # | Case | Result |
|---|---|---|
| 1 | invalid field foobar |
reject exit 1 |
| 2 | invalid species not_a_species |
reject exit 1 |
| 3 | composition compound on governed-atom PIV-001 |
reject exit 1 (governed guard) |
| 4 | no-op registry_group=cấu_trúc (PIV-001) |
OK no-change exit 0 |
| 5 | inactive row PIV-020 / MTX-TEST | reject exit 1 (after fix) |
| 6 | unknown registry_group=bogus_zzz |
reject exit 1 |
| 7 | valid in-use registry_group=công_cụ DRY-RUN |
plan + ROLLBACK exit 0 |
| 8 | missing --value / no --auto |
reject exit 1 |
| 9 | nonexistent code PIV-999 | reject exit 1 |
Bug found + fixed during rehearsal (rehearsal earned its keep)
The inactive-row guard compared is_active to 'f', but is_active || '|' casts the
boolean to 'true'/'false' (psql renders a bare boolean as t/f, but a concatenated
one as true/false). The guard therefore never fired — a retired row could have been
updated. Fix: SQL now emits CASE WHEN is_active THEN 'active' ELSE 'inactive' and the
guard checks != 'active'. Re-tested PIV-020 + MTX-TEST → both correctly refused. Tool
redeployed; fingerprint re-verified identical.
Trigger behaviour observed
UPDATE 1 inside each txn fired the statement-level refresh once, with no error and within
normal time. No birth/matrix trigger fired (INSERT-only / matrix_spec NULL). Confirms the
"no refresh explosion" + "integrates with existing trigger behaviour intentionally" reqs.