05 Điều 39 Invalid Manifest Now Caught at VERIFY (no mutation)
05 — Điều 39 Invalid Manifest Now Caught at VERIFY (no mutation)
Target
cut_request_id = 146f1520-aaa2-4bda-af2c-06a8f76cd36a
manifest staging_record_id = 9fa4685e-d35a-45d4-aee7-aa2836785ca5
manifest lifecycle_status = approved
manifest piece count = 16
unit_kind distribution = law_section × 16
cut_request status = mark_verified
cut_run_id = NULL
Preview run (read-only, no mutation)
Command:
SELECT jsonb_pretty(public.fn_iu_cut_preflight_validate(
'9fa4685e-d35a-45d4-aee7-aa2836785ca5'::uuid,
NULL,
'phase_e_test'
));
Verbatim output:
{
"ok": false,
"gates": {
"e2_addr_ok": true,
"e4_title_ok": true,
"e6_digest_ok": true,
"e1_section_ok": true,
"e3_pubtype_ok": true,
"e7_coverage_ok": true,
"e5_local_uniq_ok": true
},
"counts": {
"pieces": 16,
"title_bad": 0,
"unit_kind_missing": 0,
"address_collisions": 0,
"unit_kind_in_vocab": 0,
"local_piece_id_total": 16,
"publication_type_bad": 0,
"local_piece_id_unique": 16,
"section_type_in_vocab": 16
},
"verdict": "rejected",
"problems": [
"Axis D: unit_kind compatibility failed (total=16, missing=0, in_vocab=0) -- every piece.unit_kind must exist in dot_config vocab.unit_kind.*"
],
"axis_a_ok": true,
"axis_b_ok": true,
"axis_c_ok": true,
"axis_d_ok": false,
"checked_at": "2026-05-27T04:37:52.650728+00:00",
"checked_by": "phase_e_test",
"cut_readiness_ok": false,
"staging_record_id": "9fa4685e-d35a-45d4-aee7-aa2836785ca5",
"lifecycle_status_at_check": "approved"
}
Interpretation
- One isolated failure: Axis D only. Every other axis and gate passes — including E2 (no canonical_address collision against the 200 existing IUs), E1 (all 16 section_types resolve in
vocab.section_type.*), E4 (titles derivable), E5 (local_piece_ids unique), E6 (manifest_digest 32-hex), E7 (coverage_bytes=29393 matches source_bytes). - This is the strict refusal behaviour mandated by the parent policy: do NOT silently map
law_section → law_unit; surface the contract violation with an indexed error. lifecycle_status_at_check=approvedconfirms the read-only nature — the manifest was NOT mutated.
Why fn_iu_verify_mark itself did not run on 9fa4685e
fn_iu_verify_mark has a precondition: lifecycle_status='pending_review'. Manifest 9fa4685e is approved (set by an older verify_mark before mig 054), so verify_mark refuses with lifecycle must be pending_review. The new preflight function deliberately accepts any lifecycle so it can be used as a forensic / inspection tool.
To bring this stuck request unstuck, see 07-next-state-machine-rollback-policy.md. The current mig does NOT mutate Điều 39 state.
What did NOT happen (forbiddens honored)
- No CUT (
fn_iu_op_cut/fn_iu_cut_from_manifestnot called). - No new
cut_requestrow. - No new staging record for Điều 39.
- No silent vocab widening (
law_sectionnot added tovocab.unit_kind.*). - No silent mapping (manifest's
unit_kindnot rewritten). - Manifest 9fa4685e bytes not touched.
cut_run_idremains NULL.- IU count for Điều 39 stays at 0.
What WILL happen on the next attempt
When the operator (or rebuilt Codex/Agent) re-MARKs Điều 39 with unit_kind=law_unit for all 16 pieces, fn_cut_mark_staged_file will accept it (mig 054 Axis D check passes), fn_iu_verify_mark will call preflight which returns ok=true, the lifecycle moves to approved, and CUT can run successfully — no further migrations needed for the normal happy path.
The unresolved blocker is the state-machine rollback gap from mark_verified, addressed in 07.