P3D Pack 1 Read-Only Inventory Report
P3D Pack 1 Read-Only Inventory Report
Date: 2026-05-11 Mode: READ_ONLY_INVENTORY Executed by: Claude Code agent (VPS 38.242.240.89, postgres container) Source prompt: knowledge/dev/laws/dieu44-trien-khai/prompts/p3d-pack1-readonly-inventory-prompt.md
Summary
phase_status=PASS
mode=READ_ONLY_INVENTORY
no_mutation_performed=true
fail_count=0
warn_count=0
log_path=/tmp/p3d-pack1-inventory-20260511-034750.log
report_path=knowledge/dev/laws/dieu44-trien-khai/reports/p3d-pack1-readonly-inventory-report.md
All 12 sections (S0..S12, including S7B) executed without SQL error.
Key findings
S0 — table existence
All six target tables present as ordinary relations (relkind='r'):
tac_publication, tac_publication_member, tac_logical_unit, tac_unit_version, information_unit, unit_version.
S1 — tac_logical_unit
- 13 columns. PK
id uuiddefaultgen_random_uuid().canonical_address text NOT NULL(UNIQUE viatac_logical_unit_canonical_address_key). - Domain columns:
doc_code,parent_id,sort_order,section_type,section_code,owner,identity_profile jsonb,tier,lifecycle_status(defaultdraft_only),created_at/updated_at. - 86 rows. All sampled rows have
lifecycle_status=draft_only. Sample includes D38-DIEU28 tree.
S2 — tac_unit_version
- 20 columns including
body,description,content_hash,lifecycle_status(defaultdraft),review_state(defaultunreviewed),length_flag,length_exception_reason,content_profile jsonb,editor,provenance(defaultPROV-AI),vector_sync_status(defaultpending),vector_synced_at,vector_chunk_count,enacted_at. - 86 rows; all
lifecycle_status=draft. - Note
hash_mismatch_count = 86againstmd5(body). All TAC unit_version rows havecontent_hash IS DISTINCT FROM md5(body). This is consistent with TAC using a different hash algorithm/payload than rawmd5(body)(e.g. trimmed/normalized body or sha256-derived value); not a verdict failure under this read-only check, but flagged so Pack 1 design does not assumecontent_hash == md5(body).
S3 — tac_publication
- 15 columns:
doc_code,version,publication_type,name,owner,description,lifecycle_status(defaultproposed),enacted_at,council_score,approved_by,risk_tier(defaultmedium),publication_profile jsonb. - 3 rows: DIEU-35 v5.2 (S178-FIX23, highest risk), DIEU-32 v1.1, DIEU-28 v2.0. All
lifecycle_status=proposed.enacted_atNULL for all three.
S4 — tac_publication_member
- 6 columns:
id,publication_id,logical_unit_id,unit_version_id(all NOT NULL),render_order(default 0),created_at. - Render orders fully dense: DIEU-35 (36 members, 0..35, 36 distinct), DIEU-32 (23, 0..22, 23 distinct), DIEU-28 (27, 0..26, 27 distinct). No duplicate orders.
S5 — information_unit (native IU)
- 16 columns:
canonical_addressUNIQUE,unit_kind,lifecycle_status(defaultdraft),content_anchor_ref text,version_anchor_ref uuid(FK -> unit_version.id),owner_ref,parent_or_container_ref uuid,conformance_status(defaultopen),identity_profile jsonb,created_by/updated_by NOT NULL,deleted_at,sort_order(nullable). - 12 rows, all pilot/test addresses (
pilot.*,test/p3*), alllifecycle_status=draft,has_parent=falsefor all sampled rows.
S6 — unit_version (native UV)
- 9 columns:
unit_id(FK -> information_unit.id),body NOT NULL,content_hash NOT NULL,version_seq NOT NULL,lifecycle_status(defaultdraft),content_profile jsonb,created_at,created_by NOT NULL. UNIQUE (unit_id,version_seq). - 19 rows, all
lifecycle_status=draft. - Note
hash_mismatch_count = 19againstmd5(body)— same observation as TAC:content_hashis not rawmd5(body). Pack 1 design must not assume that equivalence.
S7 — column comparison (logical unit)
TAC vs IU column overlap: only canonical_address, id, identity_profile, lifecycle_status, sort_order, created_at, updated_at are in both. TAC-only: doc_code, owner, parent_id, section_code, section_type, tier. IU-only: conformance_status, content_anchor_ref, created_by, deleted_at, owner_ref, parent_or_container_ref, unit_kind, updated_by, version_anchor_ref. Names are renamed (parent_id ↔ parent_or_container_ref; owner ↔ owner_ref) and TAC rich-section metadata (section_type/section_code/tier) has no IU counterpart.
S7B — column comparison (unit version)
Overlap: body, content_hash, content_profile, created_at, id, lifecycle_status. TAC-only review/length/vector/provenance fields (description, editor, enacted_at, length_exception_reason, length_flag, logical_unit_id, provenance, review_state, title, updated_at, vector_*, version_number). IU-only: created_by, unit_id, version_seq. Cardinality field renamed (logical_unit_id ↔ unit_id; version_number ↔ version_seq).
S8 — FKs / indexes / triggers
- 13 FKs total. TAC side bound to vocab tables (
tac_*_vocab) forlifecycle_status,review_state,section_type,publication_type. IU side:information_unit.version_anchor_ref->unit_version.id(fk_iu_version_anchor);unit_version.unit_id->information_unit.id. - 37 indexes on the six tables. Both sides have GIN on jsonb profile, btree on lifecycle_status, btree on canonical_address with UNIQUE.
- 13 triggers: TAC has
trg_tac_birth_gate_lu,trg_tac_birth_gate_uv,trg_tac_enacted_immut,trg_tac_uv_compute_derived,trg_tac_pm_consistency,trg_tac_pm_enacted_lock. IU hastrg_aa_iu_gateway_write_guard,trg_birth_information_unit,trg_iu_birth_gate_layer1,trg_iu_birth_gate_layer2,trg_iu_updated_at. UV hastrg_aa_iu_notif_version,trg_aa_uv_gateway_write_guard. Alltgenabled='O'(enabled).
S9 — IU functions
All six expected functions present:
fn_iu_create(text,text,text,text,text,text,text,text,uuid) -> jsonb(9 args)fn_iu_create_plan(text,text,text,text,text,text,text,text,uuid) -> jsonb(9 args)fn_iu_apply_edit_draft(uuid,text,text) -> jsonbfn_iu_edit(text,text,text,text,text,text) -> jsonbfn_iu_save(text,text,text,text,text,text) -> jsonbfn_iu_verify_invariants(text) -> jsonb
S10 — dot_config IU keys
12 keys present. Notable:
- Gateway mode =
enforced; direct_insert_policy =block_after_guard; exempt_policy =none_active. iu_create.gateway.canonical_function=public.fn_iu_create(text,text,text,text,text,text,text,text,uuid)(matches S9 signature).iu_create.gateway.allowed_marker_values=fn_iu_create,fn_iu_apply_edit_draft.iu_edit.policy.default_mode=require_review;iu_edit.schema.version=p3b-v1.
S11 — canonical_address overlap
tac_lu_count=86,iu_count=12,overlap_count=0. No canonical_address is shared between TAC and native IU. The 12 IU rows are pilot/test fixtures (pilot.*,test/p3*); TAC rows are real DIEU-* law addresses.
S12 — publication_member binding
- 86 total members across the 3 publications,
null_lu=0,null_uv=0. All members fully bind bothlogical_unit_idandunit_version_id.
Impact on Pack 1 design (EVOLVE assumptions)
Confirmed assumptions:
- TAC and native IU coexist as distinct schemas; no canonical_address collision today (S11).
- Native IU/UV gateway is enforced (
block_after_guard,enforcedmode) and core IU functions are present and signature-stable (S9, S10). - Birth-gate triggers on both sides are enabled (S8C). Birth gate v2 hash matches Step-1 baseline.
- Publication binding integrity holds: every TAC publication_member has both LU and UV references (S12).
Contradictions / friction points that Pack 1 must address explicitly:
- Hash semantics differ from
md5(body)on bothtac_unit_versionandunit_version(100% mismatch in S2B/S6B). EVOLVE must not promote a "hash equivalence" check; specify the actual hashing rule for migration. - Schema delta is non-trivial. S7/S7B show TAC-rich fields (
section_type,section_code,tier,provenance,review_state,length_*,vector_*,editor,enacted_at,version_number,description) have no native IU/UV counterpart. EVOLVE either drops them, maps them intoidentity_profile/content_profilejsonb, or extends the native schema; current native schema has no place for them. - Lifecycle vocab is FK-bound on TAC side (
tac_*_lifecycle_vocab,tac_review_state_vocab,tac_section_type_vocab,tac_publication_type_vocab). Native IU/UV use plain text with defaults. Cross-table evolution must reconcile these vocabularies before any data move. - Native IU has only pilot/test rows (12 rows, all
pilot.*/test/*). TAC carries the real 86-row DIEU corpus across DIEU-28/32/35. EVOLVE direction (TAC -> native IU) is consistent with the data weight; no surprise content already in native IU that would block migration. - Identifier renames (
parent_id↔parent_or_container_ref,owner↔owner_ref,logical_unit_id↔unit_id,version_number↔version_seq) are pure column-name mappings; no semantic mismatch detected, but Pack 1 mapping table must be explicit.
No fixes attempted. Reporting only as required by the prompt.
Boundaries honored
- No DDL, no DML, no migration.
- No new table/view/trigger/function/index.
- No permission change.
- No Nuxt code, no deploy/restart.
- No DOT-119 execution/rewrite; no
fn_birth_registry_automodification. - No direct write to
information_unit/unit_version. - No "Thông tin" filter added.
- Only mutation: this KB report upload.