KB-2AA0

91000x · 02 — Apply 037-039 with surgical drift patches (Phase B PASS)

7 min read Revision 1
iu-core91000xapply037038039drift-patches2026-05-26

91000x · 02 — Apply 037-039 with surgical drift patches

Phase: B
Status: PASS for 037-039 (with patches); 040/041 NOT APPLIED
Date: 2026-05-26

Apply path

All three migrations applied via workflow_admin socket-trust channel:

ssh contabo 'docker exec -i postgres psql -U workflow_admin -d directus -v ON_ERROR_STOP=1' << EOSQL
…migration body…
EOSQL

Each migration was wrapped in BEGIN; … COMMIT;. Any error inside the TX rolls back atomically.

Migration 037 — applied (after 3 retries to discover live drifts)

Original authored body (90000x report 02) FAILED twice in pre-COMMIT state:

Try Error TX Fix
1 iu_core_retention_policy_keep_days_check violated (keep_days=0; live CHECK >=1) rolled back keep_days 0 → 1
2 iu_core_retention_policy_pkey duplicate (D36 Macro A pre-inserted these rows on 2026-05-25 12:48) rolled back added ON CONFLICT (target_table) DO NOTHING
3 dot_iu_command_catalog_category_check violated (maintenance not in {collection,piece,lifecycle,read,health}) rolled back category maintenancelifecycle for both cleanup + unregister
4 none COMMITTED applied

Live D9 deltas (post-apply 037)

post_037 | new_dots | dot_total | lifecycle_chk
----------+----------+-----------+-----------------------------------------------------------------
post_037 |        2 |        32 | CHECK ((lifecycle_status = ANY (ARRAY['pending','pending_review',
                                  'approved','consumed','rejected','expired','cleaned'])))

037 fn body drift discovered after apply (patched in next TX)

Functions fn_iu_staging_cleanup and fn_iu_staging_unregister were CREATEd successfully (plpgsql defers SQL stmt resolution to runtime), but their INSERT INTO dot_iu_command_run (command_name, payload_json, actor, status) would fail at first apply=true call because:

  • payload_json doesn't exist — column is evidence (jsonb, NOT NULL default '{}')
  • status doesn't exist — column is run_status (NOT NULL, vocab {planned,applied,verified,refused,failed})
  • category is required (NOT NULL, vocab {collection,piece,lifecycle,read,health})
  • run_mode is required (NOT NULL, vocab {plan,apply,verify})

Patch via CREATE OR REPLACE (separate TX, atomic):

-- 91000x drift fix
INSERT INTO dot_iu_command_run (command_name, category, run_mode, run_status, mutating, actor, evidence)
VALUES ('dot_iu_staging_cleanup', 'lifecycle', 'apply', 'applied', true, p_actor,
        jsonb_build_object('apply', true, 'ran_at', v_now));

(Similar pattern for unregister.)

Algorithm + axis A/B/C + lifecycle transitions unchanged.

Verification after patch:

dry_run_rows = 0   (cleanup, expected — all 3 existing staging rows within 15d)
unregister_not_found = {"ok": false, "reason": "not_found"}

Migration 038 — applied (with drift patches inline)

Authored body anticipated iu_staging_payload INSERT without byte_len, and same dot_iu_command_run schema mismatch. Applied with patches:

  1. Added byte_len computation (octet_length per part) + INSERT column.
  2. Rewrote dot_iu_command_run INSERT to live schema.
  3. DOT dot_iu_mark_article category 'mark''piece' (live vocab).

After first apply attempt, second drift discovered at runtime in bounded proof:

  • iu_staging_payload_kind_chk vocab is {json,text,blob_ref} — author used 'markdown' for mark_report.
  • iu_staging_payload_exclusive_chk requires payload_kind='text' ⇒ payload_text NOT NULL AND payload_json NULL. Author wrote payload_json with kind=markdown.

Patch via CREATE OR REPLACE:

-- mark_report row: 'markdown' kind not in vocab; rewritten as 'text' going to payload_text
INSERT INTO iu_core.iu_staging_payload (…, part_name, payload_kind, payload_json, payload_text, byte_len, …)
VALUES
  (…, 'cut_manifest',   'json', p_manifest,       NULL,      v_cm_len, …),
  (…, 'mark_report',    'text', NULL,             v_mr_text, v_mr_len, …),
  (…, 'coverage_proof', 'json', p_coverage_proof, NULL,      v_cp_len, …);

Live D9 deltas (post-apply 038)

post_038 | new_dot | dot_total 
----------+---------+-----------
post_038 |       1 |        33

fn_iu_mark_create_manifest created with patched body. Contract identical to authored: same inputs, same return shape ({ok, staging_record_id, lifecycle_status, expires_at, manifest_digest}), same side effects (1 record + 3 payloads + 1 audit), same idempotency.

Migration 039 — applied (with patches)

Same dot_iu_command_run drift patches as 037/038, both in the REJECT path and the APPROVE path. DOT dot_iu_verify_mark_manifest category 'verify''health'.

Axis A/B/C checks, coverage byte-match, 32-hex digest check — all unchanged from author intent.

Live D9 deltas (post-apply 039)

post_039 | new_dot | dot_total 
----------+---------+-----------
post_039 |       1 |        34

Final state after 037+038+039 apply

Object Pre Post Delta
dot_iu_command_catalog rows 30 34 +4
public schema functions 470 474 +4
iu_staging_record_lifecycle_chk vocab size 6 7 +1 (pending_review)
iu_staging_record_consumed_consistency_chk required {consumed_at, consumed_by_run_id} required {consumed_at, consumed_by_run_id, approved_at, approval_doc_id} tightened
iu_staging_record_expiry_ceiling_chk absent expires_at <= created_at + 30d new
iu_core_retention_policy rows 6 6 0 (D36 prior; ON CONFLICT preserved)
All other surfaces (IU, VSP, staging rows, DIEU axes) unchanged

Migrations 040/041 — NOT APPLIED

Authored 040/041 reference live functions and tables that don't match observed live schema across at least 5 dimensions (see 00-summary "The exact gap"). Per user rule "do not re-author 040/041 in this run; do not redesign/re-author from scratch", these migrations are deferred to a 100000x macro that will author corrected bodies against live signatures.

Rollback (per migration)

Migration Rollback DDL (authored in 90000x report 02-04) Notes
037 DROP fn_iu_staging_cleanup + fn_iu_staging_unregister; DELETE 2 catalog rows; DROP 3 CHECKs + restore prior CHECK vocab + consumed-consistency refuses if any row currently in pending_review
038 DROP fn_iu_mark_create_manifest; DELETE catalog row dot_iu_mark_article refuses if any staging row was created by this fn (referenced_iu_ids handling)
039 DROP fn_iu_verify_mark; DELETE catalog row dot_iu_verify_mark_manifest no state to undo (proof was BEGIN/ROLLBACK)

Full rollback bodies in 06-rollback-package.md.

Verdict

Phase B PASS for 037-039 with surgical drift patches. 040/041 deferred (exact gap in 00-summary).

Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/v0.6-iu-core-91000x-apply-mark-to-cut-pipeline-and-proof/02-apply-037-039-with-patches.md