KB-1575

P3D Phase 5C2 R1 retry + R2 — Consolidated Status Report (DIEU-35 PASS, DIEU-28 PASS, DIEU-32 BLOCKED)

13 min read Revision 1
p3dphase5c2r1r2consolidatedstatusdieu35dieu28dieu32automated-cutterlessons-learned2026-05-14

P3D Phase 5C2 R1 retry + R2 — Consolidated Status Report

Date (UTC): 2026-05-14 Author: Claude Opus 4.7 (1M, xhigh) Authorization overlay: USER_GO=YES, GPT_FINAL_APPROVAL=YES, V3_SPEC_PATCH_APPROVED=YES, R1_RETRY_AUTHORIZED=YES, CONDITIONAL_R2_AUTHORIZED=YES Controlling prompt: knowledge/dev/laws/dieu44-trien-khai/prompts/agent-phase5c2-retry-r1-and-conditional-r2-patched-v3-2026-05-14.md Mode: BOUNDED WRITE EXECUTION across 3 publications, each in its own transaction.


0. Headline

Publication Source rows Outcome Δ IU Δ UV Δ Birth utc_ts
DIEU-35 (R1 retry) 36 PASS +36 +36 +36 20260514T140804Z
DIEU-28 (R2) 27 PASS +27 +27 +27 20260514T140835Z
DIEU-32 (R2) 23 BLOCKED_BEFORE_BEGIN (4 NULL bodies, all section_type=heading) 0 0 0 20260514T140900Z
TOTAL 86 attempted (63 migrated, 23 deferred) 2 PASS / 1 BLOCKED +63 +63 +63

Final live counts (post-run):

information_unit                          = 75   (= 12 pre + 36 D35 + 27 D28)
unit_version                              = 82   (= 19 pre + 36 D35 + 27 D28)
birth_registry where collection='information_unit' = 75
tac_publication                           = 3    (unchanged)
tac_logical_unit                          = 86   (unchanged)
tac_unit_version                          = 86   (unchanged)
tac_publication_member                    = 86   (unchanged)

tac_source_untouched = true, pre_existing_iu_untouched = true, ui_cutover_performed = false, vector_work_performed = false, bulk_migration_performed = false, v3_patched_semantics_used = true, cross_system_hash_equality_used_as_gate = false.


1. Per-publication results

1.1 DIEU-35 — R1 retry — PASS

  • Detailed report: knowledge/dev/laws/dieu44-trien-khai/reports/p3d-phase5c2-r1-dieu35-retry-patched-v3-execution-report.md
  • Rollback-keys KB: knowledge/dev/laws/dieu44-trien-khai/reports/p3d-phase5c2-dieu-35-rollback-keys-20260514T140804Z.md
  • VPS log: /opt/incomex/logs/p3d-phase5c2-dieu-35-20260514T140804Z.log
  • V-1..V-7 all PASS (incl. patched V-3a/V-3b/V-3c). V-3d cross-system match = 0/36 (report-only).
  • V-8..V-10 all PASS post-COMMIT.
  • Soft-flag D38-DIEU35-S8-P3 (body_char=1) migrated verbatim; no repair attempted.

1.2 DIEU-28 — R2 — PASS

  • Detailed report: knowledge/dev/laws/dieu44-trien-khai/reports/p3d-phase5c2-r2-dieu28-pilot-migration-execution-report.md
  • Rollback-keys KB: knowledge/dev/laws/dieu44-trien-khai/reports/p3d-phase5c2-dieu-28-rollback-keys-20260514T140835Z.md
  • VPS log: /opt/incomex/logs/p3d-phase5c2-dieu-28-20260514T140835Z.log
  • 1 root (D38-DIEU28-ROOT) + 26 children. 8 distinct section_types (all seeded).
  • All gates V-1..V-7 + V-8..V-10 PASS. V-3d cross-system match = 0/27 (report-only).

1.3 DIEU-32 — R2 — BLOCKED_BEFORE_BEGIN

  • Detailed report: knowledge/dev/laws/dieu44-trien-khai/reports/p3d-phase5c2-r2-dieu32-pilot-migration-execution-report.md
  • Cause: 4 source rows have tac_unit_version.body IS NULL (D38-DIEU32-ROOT, D38-DIEU32-S2, D38-DIEU32-S3, D38-DIEU32-S4 — all section_type='heading').
  • Per hard boundary "No automatic content repair" and stop condition "Missing vocab/owner/body > 0", the orchestrator stopped before BEGIN. No transaction opened; no rollback-keys doc generated (none needed).
  • No mutation, no residue. State unchanged.
  • Recommended remediation: upstream TAC fix to populate body for the 4 heading rows (e.g. body = title), then rerun the orchestrator for DIEU-32 only.

2. Patched V-3 semantics — verified live

The previous R1 attempt (reports/p3d-phase5c2-r1-dieu35-pilot-migration-execution-report.md) was rolled back because V-3 conflated two distinct concerns: IU-side hash consistency and cross-system hash equality. The patched V-3 separates these:

Sub-gate Spec Live evidence (this run) Result
V-3a IU-side hash consistency uv.content_hash = fn_content_hash(uv.body) 36/36 + 27/27 PASS
V-3b Body preservation uv.body = tac_unit_version.body (byte-equality) 36/36 + 27/27 PASS
V-3c TAC hash provenance content_profile.src_content_hash = tac_unit_version.content_hash 36/36 + 27/27 PASS
V-3d Cross-system hash equality uv.content_hash = tac_unit_version.content_hash 0/36 + 0/27 NOT A GATE — report only

Conclusion: TAC and IU use different hashing schemes (TAC's algorithm includes structured content beyond body). The patched semantics correctly capture content fidelity at the byte level and preserve the original TAC hash as provenance, while accepting cross-system hash divergence as expected.


3. Hard-boundary compliance summary

Boundary DIEU-35 DIEU-28 DIEU-32
No DDL / schema / trigger / fn / birth-system change
No direct INSERT to IU/UV (only fn_iu_create) n/a (no tx)
No TAC writes
No UI cutover / Nuxt / Directus / config
No vector / Qdrant mutation / reindex
No event_outbox / IU event emission
Pre-existing 12 pilot/test IU untouched
No pattern-matching DELETE ✅ (no rollback needed) ✅ (no rollback needed) n/a
No auto content repair ✅ (S8-P3 1-char body preserved) ✅ (4 NULL bodies left untouched)
Only DIEU-35/28/32 in scope

4. Toward automated cutter: lessons learned for "Cắt luật A"

This run proves that the migration can be operationalized as a small, deterministic, parametric tool. The orchestrator's stage structure is the prototype for Cắt luật A (a future automated cutter for any TAC publication into native IU/UV).

4.1 What this run proves

  1. Source discovery is FK-deterministic. The 4-table join tac_publication → tac_publication_member → tac_logical_unit → tac_unit_version, filtered by doc_code, plus a single recursive CTE for hierarchy depth, is enough to reconstruct the full mapping. No hand-crafted SQL per publication is needed.
  2. Segmentation / mapping is a function of source row + static rules. Per-row payload (p_canonical_address, p_title, p_body, p_section_type, p_owner_ref) plus three constants (p_unit_kind='law_unit', p_publication_type='law', p_actor) and p_parent_ref=NULL for D3a hybrid covered both DIEU-35 (12 distinct section types, 36 rows) and DIEU-28 (8 distinct section types, 27 rows) without per-publication branching.
  3. Vocab validation is one read query. A single WITH d AS (DISTINCT section_type WHERE doc_code=…) + NOT EXISTS vocab.section_type.<value> is sufficient. R1 retry confirmed 0 missing vocab for DIEU-35; R2 confirmed 0 missing for DIEU-28 and DIEU-32.
  4. fn_iu_create batches cleanly inside a single DO loop. 36 + 27 rows committed in ≤1s wall-clock each. The function's internal fn_iu_verify_invariants call doubles as inline gate. No external batching framework needed.
  5. Rollback-key dual-write (KB + VPS log) before COMMIT is fully operational as a primitive: a long-lived docker exec -i postgres psql session driven by a Python orchestrator handles the pause-and-persist pattern. Both publications wrote rollback bundles successfully; both were post-COMMIT verified intact (V-10 PASS).
  6. Patched V-3 hash semantics are the right abstraction. V-3a/V-3b/V-3c separate concerns cleanly; V-3d as report-only captures the legacy divergence without gating.
  7. Exact-source preservation is enforceable. Body bytes passed tac_unit_version.body → fn_iu_create p_body → unit_version.body unchanged for all 63 migrated rows. V-3b is the canonical content-fidelity test.
  8. Edge / provenance hooks live in JSONB. identity_profile.tac_provenance/tac_hierarchy/rendering + content_profile.src_* carries enough metadata for future enrichment passes (parent FK backfill, render reconciliation, edge graph creation) without re-touching the IU/UV row layout.

4.2 What must become tooling

For "Cắt luật A" to handle arbitrary publications without per-run scripting, these capabilities should be extracted into a reusable DOT tool (e.g. dot-iu-cutter or dot-tac-to-iu):

  1. Parametric preflight gate runner taking --doc_code → exits with a structured gate report. Inputs: (g_tac_tables_exist, g_publication_exists, g_member_count, g_render_order_contiguous, g_owner_null, g_body_null, g_collision_count, g_vocab_coverage, g_fn_iu_create_present, g_gateway_enforced, g_edit_policy, g_birth_trigger, g_species_map, g_preexisting_iu). Hard fail on any required gate. Report soft flags.
  2. Mapping artifact emitter (R0-equivalent) producing the per-row JSON artifact + summary. Read-only.
  3. Bounded transaction runner with patched V-3 + V-1/V-2/V-4..V-7 + post-COMMIT V-8/V-9/V-10. Dual-write rollback keys before COMMIT. Exact-key rollback path if post-COMMIT fails.
  4. NULL-body / NULL-owner / collision policy as a tool flag, not a code branch — e.g. --on_null_body=block|skip|sythesize_from_title. Default block (current behavior). Synthesize variants would be GPT-reviewed exceptions.
  5. Rollback-keys writer abstraction that handles both KB upload (via MCP API or directus) and VPS log file. Reusable across publications.
  6. Report writer that emits per-publication and consolidated reports from the orchestrator's summary JSON.
  7. Idempotency by capturing pre-state hash (TAC counts + canonical_address set) and refusing to rerun a publication that's already migrated unless --force-reapply is set.
  8. Hierarchy enrichment pass as a separate later tool (dot-iu-parent-fk-enrich) that walks identity_profile.tac_hierarchy.src_parent_canonical_address and populates information_unit.parent_or_container_ref post-migration once all rows exist. Out of scope for the cutter itself.

4.3 Edge cases this run exposed

  • NULL bodies for heading-only rows (DIEU-32): treat as upstream data-quality concern. Cutter should --on_null_body=block by default. A future variant --on_null_body=synthesize_title is GPT-reviewable, but would lose strict V-3b byte-preservation (would need a separate V-3b_synthesized sub-gate).
  • TAC content_hash uses different algorithm than fn_content_hash — confirmed across DIEU-35 + DIEU-28 (0% cross-system hash match across 63 rows). Cutter must NOT gate on V-3d.
  • Single-character body rows (DIEU-35 S8-P3): valid input; fn_iu_create accepts; all gates pass; soft-flag for human review only.
  • D3a hybrid p_parent_ref=NULL is the correct default at create time. Hierarchy lives in JSONB; parent FK enrichment is a separate pass.

"Cắt luật A" design (dot-iu-cutter v0.1) — DOT-registered, parametric, read+write, with exhaustive gate matrix; mandatory dual-write rollback; reusable per publication. Build it as the operationalization of this orchestrator. Validated by this run on 2 of the 3 currently-live TAC publications (63/86 source rows migrated).


5. Required final response fields (consolidated)

phase5c2_retry_r1_status=PASS
r2_dieu28_status=PASS
r2_dieu32_status=BLOCKED_BEFORE_BEGIN
total_publications_committed=2
total_iu_created_committed=63
total_uv_created_committed=63
total_birth_created_committed=63
tac_source_untouched=true
pre_existing_iu_untouched=true
ui_cutover_performed=false
vector_work_performed=false
bulk_migration_performed=false
v3_patched_semantics_used=true
cross_system_hash_equality_used_as_gate=false
rollback_reports=[
  "knowledge/dev/laws/dieu44-trien-khai/reports/p3d-phase5c2-dieu-35-rollback-keys-20260514T140804Z.md",
  "knowledge/dev/laws/dieu44-trien-khai/reports/p3d-phase5c2-dieu-28-rollback-keys-20260514T140835Z.md"
]
execution_reports=[
  "knowledge/dev/laws/dieu44-trien-khai/reports/p3d-phase5c2-r1-dieu35-retry-patched-v3-execution-report.md",
  "knowledge/dev/laws/dieu44-trien-khai/reports/p3d-phase5c2-r2-dieu28-pilot-migration-execution-report.md",
  "knowledge/dev/laws/dieu44-trien-khai/reports/p3d-phase5c2-r2-dieu32-pilot-migration-execution-report.md"
]
consolidated_report_path=knowledge/dev/laws/dieu44-trien-khai/reports/p3d-phase5c2-r1-r2-consolidated-status-report.md
next_recommended_action=GPT_REVIEW_R1_R2_RESULTS_THEN_START_AUTOMATED_CUTTER_DESIGN

P3D Phase 5C2 R1+R2 Consolidated Status | 2026-05-14 | 63/86 rows migrated · 2/3 publications PASS · DIEU-32 BLOCKED upstream data-quality. Toward "Cắt luật A" automated cutter.

Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/reports/p3d-phase5c2-r1-r2-consolidated-status-report.md