06 Regression Safety (BEGIN/ROLLBACK)
06 — Regression Safety
All fixtures wrapped in BEGIN; ... ROLLBACK; so nothing persists. Each fixture creates one staging_record + one cut_manifest payload + one coverage_proof payload, calls preflight or verify_mark, then rolls back.
Results matrix
| # | fixture | expected | actual | PASS? |
|---|---|---|---|---|
| F.1 | valid 2-piece law_unit manifest (parent→child, dense positions 1,2, section_type=heading/paragraph, manifest_digest 32-hex, coverage matches) |
ok=true verdict=approved cut_readiness_ok=true axis_a..d=true gates e1..e7=true |
exactly as expected; 0 problems | YES |
| F.2 | single unit_kind=law_section piece |
ok=false verdict=rejected axis_d_ok=false with Axis D problem |
exactly as expected; 1 problem (Axis D) | YES |
| F.3 | piece with empty content_text AND empty canonical_address | e4_title_ok=false E4 problem |
exactly as expected; 1 problem (E4) | YES |
| F.4 | piece with canonical_address = existing IU (D38-DIEU35-S8-P1) |
e2_addr_ok=false address_collisions=1 E2 problem |
exactly as expected; 1 problem (E2 collisions=1) | YES |
| F.5 | piece with section_type='not_a_real_section' |
e1_section_ok=false E1 problem |
exactly as expected; 1 problem (E1) | YES |
| F.6 | fn_iu_verify_mark(p_apply=true) with invalid unit_kind |
ok=false verdict=rejected cut_readiness_ok=false AND lifecycle_after=rejected (NOT approved) |
exactly as expected; gate prevented bad approval | YES (critical) |
| F.7 | fn_iu_verify_mark(p_apply=false) dry-run with invalid unit_kind |
rejected verdict, lifecycle remains pending_review (no mutation) |
exactly as expected | YES |
| F.8 | fn_iu_cut_preflight_validate(p_source_hash='mismatched_hash_bbb') against manifest with source_hash='expected_hash_aaa' |
E0 source_hash mismatch problem | exactly as expected; 1 problem (E0) | YES |
Indexed error strings (proven on live)
Axis D: unit_kind compatibility failed (total=1, missing=0, in_vocab=0) -- every piece.unit_kind must exist in dot_config vocab.unit_kind.*
E1: section_type compatibility failed (total=1, in_vocab=0) -- every piece.section_type must exist in dot_config vocab.section_type.*
E2: canonical_address collision with existing information_unit (collisions=1) -- CUT would refuse via fn_iu_classify_existing
E4: title not derivable on 1 piece(s) -- both first-line(content_text) and canonical_address are empty
E0: source_hash mismatch (expected=expected_hash_aaa, got=mismatched_hash_bbb)
"Postgres text[] || bare literal" lesson re-applied
fn_iu_cut_preflight_validate accumulates text[] problems exclusively via the ARRAY['...'] form (e.g. v_problems := v_problems || ARRAY['Axis D: ...'];), never via v_problems || 'bare literal'. This avoids the operator-resolution gotcha that masked a contract gap in earlier verify_mark work. See [[feedback-postgres-text-array-concat-bare-literal-cast-gotcha]].
State invariants
| invariant | pre-Phase-F | post-Phase-F |
|---|---|---|
information_unit count |
200 | 200 |
iu_vector_sync_point count |
152 | 152 |
iu_staging_record count |
10 | 10 |
dieu39_iu_count |
0 | 0 |
manifest 9fa4685e lifecycle |
approved |
approved |
cut_request 146f1520 status |
mark_verified |
mark_verified |
cut_request 146f1520.cut_run_id |
NULL | NULL |
gate queue.job_substrate.enabled |
false | false |
gate iu_core.composer_enabled |
false | false |
gate queue.heartbeat.enabled |
true | true |
gate queue.dlq.replay_enabled |
false | false |
production_documents |
absent | absent |
pg_cron |
absent | absent |
Forbiddens re-checked against this phase
- No
pg_cron. 2. No worker process started. 3. Noevent_outboxmutation. 4. No Qdrant. 5. Noproduction_documentswrite. 6. Noruntime.phaseflip. 7. No CUT. 8. No VERIFY_CUT. 9. No COMPLETE. 10. No newcut_request. 11. No silent vocab widening. 12. No silent mapping. 13. No alias contract change. 14. No manual manifest patch. 15. No--no-verify/ hook-skip.
Plug into broader pipeline
These fixtures cover happy path + 6 failure modes. A 9th fixture (heading→paragraph parent_local_id pointing outside manifest) would exercise Axis C explicitly; it is logically covered by the existing pre-mig fn_iu_verify_mark Axis C test in the parent root-cause pack and is regression-stable under the new delegation.