KB-1E5D

P3D Pack 1 — Design Addendum (Post-Inventory)

9 min read Revision 1
p3dpack1designaddenduminventorymappingevolvehashvocab

P3D Pack 1 — Design Addendum (Post-Inventory Patch)

Date: 2026-05-11 Author: Opus 4.7 Base: design/p3d-pack1-iu-canonical-contract-and-tac-iu-reconciliation-design.md Inventory: reports/p3d-pack1-readonly-inventory-report.md GPT review: reviews/gpt-review-step1-checkpoint-pack1-inventory-final-before-resume-2026-05-11.md


1. Inventory-Confirmed: EVOLVE Still Valid

  • 0 canonical_address overlap (86 TAC + 12 IU pilot) → clean migration space
  • IU native has gateway + 6 functions + 12 dot_config keys → stronger governance than TAC
  • TAC has richer schema (20 UV cols vs 9 IU UV cols) → IU must be EXTENDED before migration
  • Publication membership (86 members, render_order dense) → separate family, keep as-is

2. Full Column Mapping — TAC Logical Unit ↔ IU information_unit

TAC column IU column Status Action
id (uuid PK) id (uuid PK) ✅ Compatible Map
canonical_address (text UNIQUE) canonical_address (text UNIQUE) ✅ Compatible Map
doc_code (text) ❌ Missing in IU ADD column (structural binding per P5)
parent_id (uuid self-ref) parent_or_container_ref (uuid) ✅ Rename Map (name differs)
sort_order (int) sort_order (int, nullable) ✅ Compatible Map (IU has it, nullable)
section_type (text FK vocab) ❌ Missing in IU ADD column (FK to tac_section_type_vocab)
section_code (text) ❌ Missing in IU ADD column or profile JSONB
owner (text) owner_ref (text) ✅ Rename Map
identity_profile (jsonb GIN) identity_profile (jsonb GIN) ✅ Compatible Map
tier (text) ❌ Missing in IU Profile JSONB (derived/cache)
lifecycle_status (text) lifecycle_status (text) ✅ Compatible Map (vocab reconciliation needed)
created_at / updated_at created_at / updated_at ✅ Compatible Map
unit_kind (text) IU-only Set law_unit for migrated rows
conformance_status (text) IU-only Set open for migrated rows
content_anchor_ref (text) IU-only Compute from UV
version_anchor_ref (uuid FK) IU-only Set to latest UV
created_by / updated_by (text NOT NULL) IU-only Set migration_pack1
deleted_at IU-only NULL

3. Full Column Mapping — TAC unit_version ↔ IU unit_version

TAC column IU column Status Action
id (uuid PK) id (uuid PK) ✅ Compatible Map
logical_unit_id (uuid FK) unit_id (uuid FK) ✅ Rename Map
body (text) body (text NOT NULL) ✅ Compatible Map
content_hash (text) content_hash (text NOT NULL) ⚠️ Same column, different hash algo? Investigate (§4)
version_number (int) version_seq (int) ✅ Rename Map
lifecycle_status (text FK vocab) lifecycle_status (text) ✅ Vocab reconcile needed Map
content_profile (jsonb) content_profile (jsonb) ✅ Compatible Map
created_at created_at ✅ Compatible Map
title (text) ❌ Missing in IU UV ADD column
description (text) ❌ Missing in IU UV ADD column
review_state (text FK vocab) ❌ Missing in IU UV ADD column
provenance (text) ❌ Missing in IU UV ADD column or profile
editor (text) ❌ Missing in IU UV ADD column or profile
enacted_at (timestamptz) ❌ Missing in IU UV ADD column
length_flag (text) ❌ Missing in IU UV Profile JSONB
length_exception_reason (text) ❌ Missing in IU UV Profile JSONB
vector_sync_status (text) ❌ Missing in IU UV ADD column (vector contract)
vector_synced_at (timestamptz) ❌ Missing in IU UV ADD column
vector_chunk_count (int) ❌ Missing in IU UV ADD column
updated_at ❌ Missing in IU UV ADD column
created_by (text NOT NULL) IU-only Set migration_pack1

4. Hash Semantics — MUST RESOLVE BEFORE MIGRATION

Finding: 86/86 TAC UV + 19/19 IU UV have content_hash ≠ md5(body).

Investigation needed (Phase 2 preflight):

-- Discover actual hash algorithm
SELECT content_hash, md5(body), length(content_hash),
       content_hash = md5(body) AS md5_match,
       content_hash = encode(sha256(body::bytea), 'hex') AS sha256_match
FROM tac_unit_version LIMIT 3;

-- Same for IU native
SELECT content_hash, md5(body), length(content_hash),
       content_hash = md5(body) AS md5_match
FROM unit_version LIMIT 3;

Possible explanations: (a) SHA-256 instead of MD5, (b) hash includes title+description+profile (per P5 design §5.2), (c) normalized/trimmed body before hash.

Rule: Migration must preserve existing hash for TAC rows. IU UV hash computation rule must be documented and applied consistently.

5. TAC-Rich Fields Handling Strategy

Category Fields Strategy Rationale
Universal (every unit needs) title, description, review_state, enacted_at, updated_at ADD columns to IU UV Core workflow fields, query/filter critical
Universal (governance) provenance, editor ADD columns to IU UV Audit trail
Vector contract vector_sync_status, vector_synced_at, vector_chunk_count ADD columns to IU UV Per unified vector contract SSOT
Structural (law-specific) section_type, doc_code ADD columns to IU LU Filter/query critical for law_unit
Nice-to-have section_code, tier, length_flag, length_exception_reason Store in profile JSONB Derived/cache, not query-critical

Total new columns: ~8 on information_unit (if doc_code + section_type added) + ~9 on unit_version.

6. Vocab Reconciliation

Vocab table TAC usage IU native usage Reconciliation
tac_lifecycle_vocab (LU) FK from tac_logical_unit.lifecycle_status Plain text, default draft IU ADD FK to same vocab OR create shared vocab
tac_lifecycle_vocab (UV) FK from tac_unit_version.lifecycle_status Plain text, default draft Same
tac_review_state_vocab FK from tac_unit_version.review_state N/A (no column) ADD column + FK
tac_section_type_vocab FK from tac_logical_unit.section_type N/A (no column) ADD column + FK
tac_publication_type_vocab FK from tac_publication.publication_type N/A (separate family) Keep as-is

Recommendation: Rename vocab tables to drop tac_ prefix (e.g., lifecycle_vocab, review_state_vocab, section_type_vocab) since they're universal, not TAC-specific. Or keep tac_ prefix and add FK from IU to same tables.

7. Publication Membership — Preserved As-Is

tac_publication + tac_publication_member remain separate tables (publication is a different family). During EVOLVE migration, tac_publication_member.logical_unit_id will point to the new IU row (same UUID if we INSERT with explicit id).

Key: Migration must preserve UUID PK values so publication_member FK bindings remain valid.

8. Phase 2 Scope (DDL Extend IU Schema)

Phase 2 adds columns to IU native, does NOT migrate data yet.

Table New columns Default Nullable
information_unit doc_code TEXT NULL YES (non-law units don't have doc_code)
information_unit section_type TEXT NULL YES (+ FK to section_type_vocab later)
information_unit section_code TEXT NULL YES
unit_version title TEXT NULL YES (backfill for existing pilot rows)
unit_version description TEXT NULL YES
unit_version review_state TEXT 'unreviewed' YES
unit_version provenance TEXT 'PROV-AI' YES
unit_version editor TEXT NULL YES
unit_version enacted_at TIMESTAMPTZ NULL YES
unit_version updated_at TIMESTAMPTZ now() NO (add trigger)
unit_version vector_sync_status TEXT 'pending' YES
unit_version vector_synced_at TIMESTAMPTZ NULL YES
unit_version vector_chunk_count INT 0 YES

Not in Phase 2: data migration, view creation, TAC table modification, vocab rename.


Pack 1 Design Addendum | Post-Inventory | 2026-05-11 | Opus 4.7

Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/design/p3d-pack1-design-addendum-post-inventory-2026-05-11.md