KB-2DFA

IU CUT VERIFY/APPROVE/CUT Gate Consistency Fix — Summary (PASS 2026-05-27)

7 min read Revision 1
iu-cutverify-approve-cut-gatemig056verify_markapprovecut_applypreflightcomposer-gatedieu44dieu39gate-consistency

IU_CUT_VERIFY_APPROVE_CUT_GATE_CONSISTENCY_FIX_PASS — 2026-05-27

Outcome

IU_CUT_VERIFY_APPROVE_CUT_GATE_CONSISTENCY_FIX_PASS

Mission

Fix the gate design problem surfaced during the Điều 39 flight-test where VERIFY_MARK dry-run reported cut_readiness_ok=true, APPROVE rubber-stamped, and CUT then failed with composer_gate_closed, AND fn_cut_apply falsely wrote cut_run_id + cut_done_at despite zero IUs being created.

Migration

056_iu_cut_verify_approve_cut_gate_consistency_fix.sql — single TX. Four surgical fixes:

  1. fn_iu_cut_preflight_validate — adds Axis E8 composer_gate_open (runtime gate). cut_readiness_ok is now mark_valid AND e8_composer_ok and exposes a new field mark_valid so callers can distinguish manifest correctness from runtime readiness. md5 914e26d625600094.

  2. fn_iu_verify_mark — APPROVE (p_apply=true) is now stronger than dry-run VERIFY. Re-runs preflight at approval time (E8 included) AND adds cut_request cross-binding: must find a cut_request with manifest_staging_record_id=... whose status='marked' and cut_run_id/cut_done_at/cut_verified_at/completed_at are all NULL. md5 c9c0553fc740ff7c.

  3. fn_cut_verify_mark (wrapper) — now respects the inner verdict. Previously transitioned marked→mark_verified purely on p_approve=true, ignoring inner refusal. Now: if inner_ok=false or inner_verdict<>'approved', transitions marked→mark_rejected and threads inner reason into transition metadata. md5 changed to 2b77a680.

  4. fn_cut_apply — re-runs preflight IMMEDIATELY before CUT (E8 included). If preflight refuses, returns refusal WITHOUT transitioning to cut_in_progress. If the alias fn_iu_op_cut returns inner_result.ok=false or applied<>true, transitions cut_in_progress→cut_failed and never writes cut_run_id / cut_done_at. md5 ce488b88007e2097.

Preserved (md5 UNCHANGED) — 7/7 alias contracts intact

function md5
fn_cut_mark_staged_file e85065acb9996623e0ef1f654d991df6
fn_cut_request_transition c392d3e156159852a97889df1af04165
fn_iu_create dcade99af1ef096892748c9f14082e11
fn_iu_cut_from_manifest c5d556bc22cc2d255c0484b5a969ebc5
fn_iu_op_cut 66b813e50205448eb01170aebec614df
fn_iu_op_mark_file ffaa47fff7a906d93060141661080cd4
fn_iu_op_verify_mark bf20bd1929998073865808d17b1dd648

Backups

  • pre: /tmp/pre_verify_approve_cut_gate_fix.dump 84,391,933 B md5 0578a9f58820b29c50f8c3d1c089c9f3
  • post: /tmp/post_verify_approve_cut_gate_fix.dump 84,397,741 B md5 2a454fda2be1f54528aa76991c48d74e
  • delta: +5,808 B (fn bodies only)

Regression — 7/7 PASS (BEGIN/ROLLBACK on Điều 39 manifest 5ef349ac…)

# scenario expected actual
T1 preflight live composer=false cut_readiness_ok=f, mark_valid=t, E8 problem present
T2 VERIFY_MARK dry-run composer=false verdict=rejected, mark_valid=t, cut_readiness_ok=f, E8
T3 fn_cut_verify_mark(p_approve=true) composer=false verdict=rejected, status=mark_rejected, inner_ok=f; manifest→rejected
T4 fn_cut_apply composer=false verdict=refused, refusal_code=preflight_refused; cut_request unchanged (status=mark_verified, cut_run_id=NULL, cut_done_at=NULL); IU count 200
T5 composer=true flip (BEGIN/ROLLBACK) preflight verdict=approved, e8_composer_ok=t
T6 bogus unit_kind still refused Axis D axis_d_ok=f, problem present
T7 forbiddens snapshot iu=200, vsp=152, eo=139900, prod_docs=absent, composer=false, queue.job=false, hb=true

Forbiddens — 15/15

no live CUT · no IU created · no Qdrant · no production_documents · no pg_cron · no broad worker · no vocab widening · no silent value mapping · no MARK/CUT alias body change · no new cut_request · no runtime.phase flip · no event_outbox mutation (delta 0) · no manual jsonb_set on Điều 39 manifest in live state · no destructive --force / git reset --hard · no Điều 39 re-MARK in this macro

Current Điều 39 state (Phase G — untouched)

  • cut_request_id = c7133284-a579-4266-aed8-c91f75a22283
  • status = cut_failed (preserved as audit)
  • cut_run_id = c42ebc50-20eb-459e-9099-eb46638f63b1 (LEGACY fake state from pre-fix bug — kept for audit)
  • cut_done_at = 2026-05-27 05:45:54.928814+00 (LEGACY fake state — kept for audit)
  • cut_verified_at = NULL · completed_at = NULL
  • manifest 5ef349ac… lifecycle_status = approved (LEGACY — not consumed)
  • ready_for_cut_now = false (E8 closed under live composer=false)
  • iu_dieu39_count = 0

The pre-fix fake cut_run_id + cut_done_at on a cut_failed request are LEFT IN PLACE deliberately: this macro is read-only on the existing audit record and the new code prevents the same pathology going forward.

Carry-forwards

  • CF-1 (MEDIUM) — Backfill cleanup for the legacy fake cut_run_id/cut_done_at on cut_request c7133284…: best done as part of IU_CUT_DIEU39_RETRY plan (Phase H 07). Schema option: fn_cut_request_clear_phantom_cut_state(p_cut_request_id) gated on status='cut_failed' AND completed_at IS NULL.
  • CF-2 (LOW)iu_staging_record_approved_consistency_chk requires approved_at/by/doc_id to be all-NULL or all-non-NULL with lifecycle_status in {approved, consumed}. Document this constraint in the runbook (currently surprises BEGIN/ROLLBACK reverts).
  • CF-3 (HIGH) — Composer gate is now the only runtime gate in E8. Add additional runtime gates (iu.composer.write_enabled, runtime.phase ∈ {…}, etc.) once their semantics stabilise.
  • CF-4 (HIGH)IU_CUT_DIEU39_RETRY plan (see 07-next-dieu39-retry-plan.md) once composer gate is opened intentionally.

KB reports — 8/8 in this folder

  1. 00-summary.md (this file)
  2. 01-hard-gate-baseline-backup.md
  3. 02-root-cause-classification.md
  4. 03-preflight-runtime-gate-fix.md
  5. 04-approve-stronger-gate-fix.md
  6. 05-cut-apply-failure-state-fix.md
  7. 06-regression-results.md
  8. 07-next-dieu39-retry-plan.md
  • Extends [[project_iu_cut_verify_mark_cut_readiness_gate_pass_2026_05_27]] (mig 055 — preflight + verify_mark delegation)
  • Extends [[project_iu_cut_dieu39_unit_kind_root_cause_and_contract_fix_partial_2026_05_27]] (mig 054 — Axis D unit_kind)
  • Generalises [[feedback_verify_mark_must_delegate_to_fn_iu_cut_preflight_validate]] — VERIFY/APPROVE/CUT all delegate to preflight; E8 added as runtime gate.
Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/v0.6-iu-cut-verify-approve-cut-gate-consistency-fix/00-summary.md