P3D Pack 1 Phase 3 — Hash Planner Birth Alignment Investigation Report
P3D Pack 1 Phase 3 — Hash Planner Birth Alignment Investigation Report
Date: 2026-05-11 Executor: Claude Opus 4.7 (1M) agent Mode: READ-ONLY INVESTIGATION (SET default_transaction_read_only=on confirmed) Source prompt: knowledge/dev/laws/dieu44-trien-khai/prompts/p3d-pack1-phase3-readonly-hash-planner-investigation-prompt.md (rev3) VPS: 38.242.240.89, container=postgres, db=directus Log: /tmp/p3d-phase3-investigation-20260511-062254.log (on VPS)
Final response
phase_status=BLOCKED
mode=READ_ONLY_INVESTIGATION
no_mutation_performed=true
sha256_available=true
hash_algorithm_tac=discovered
hash_algorithm_tac_details=encode(sha256(convert_to(coalesce(title,'') || '|' || coalesce(body,'') || '|' || coalesce(description,'') || '|' || coalesce(content_profile::text,'{}'),'UTF8')),'hex') — composite pipe-delimited, computed by fn_tac_uv_compute_derived BEFORE INSERT/UPDATE on tac_unit_version. Confirmed match on 10/10 sampled rows.
hash_algorithm_iu=sha256_body
hash_match_hypothesis=IU=sha256(body::UTF8) via fn_content_hash; TAC=sha256(title|body|description|content_profile_or_{}::UTF8) via fn_tac_uv_compute_derived. Both 64-char hex SHA-256 but inputs differ — migration MUST recompute.
planner_unit_kind_resolution=fn_iu_create_plan(p_unit_kind:='law_unit') returns status='unresolved_vocab', would_create=false, issue 'unit_kind: Not in vocab. Available: design_doc_section'. Phase-2 'design_doc_section' was an artifact of positional arg shift (Phase-2 passed 'law_unit' as p_title, leaving p_unit_kind=NULL → auto_single to the only vocab entry).
law_unit_status=missing (vocab.unit_kind only has design_doc_section; no vocab.unit_kind.law_unit row in dot_config)
species_at_birth=absent (species_collection_map has 0 rows for information_unit; fn_birth_registry_auto registers IU with species_code=NULL, composition_level=NULL — verified on all 12 rows)
composition_at_birth=absent (identity_profile has only {title, owner_lookup_ref, primary_section_type_ref} — composition_role never set; universal_edges contains 0 rows for information_unit/unit_version)
parent_child_enforcement=stored_only (information_unit.parent_or_container_ref column exists but is NULL on all 12 rows; no birth-gate enforcement; no edge materialization)
DOT_enrichment_for_IU=registered_only (collection_registry.governance_role='observed', migration_state='pilot', species_code=NULL; entity_labels has 0 labels for IU/UV; no enrichment fields populated)
birth_registry_for_IU=partial (12/12 IU rows registered; species_code/composition_level NULL because species_collection_map empty for IU)
vocab_tables_found=tac_section_type_vocab(17), tac_uv_lifecycle_vocab(4), tac_lu_lifecycle_vocab(3), tac_review_state_vocab(5), tac_publication_type_vocab(10), tac_pub_lifecycle_vocab(4), tac_cs_lifecycle_vocab(7); IU vocab via dot_config: vocab.unit_kind.{design_doc_section}, vocab.section_type.{section}, vocab.publication_type.{design_doc}
source_objects_inspected=fn_content_hash, fn_tac_uv_compute_derived, fn_iu_gateway_write_guard, fn_tac_birth_gate_uv, fn_iu_notif_version, fn_iu_create, fn_iu_create_plan, fn_iu_create_preflight, fn_iu_resolve_default, fn_iu_classify_existing, fn_iu_verify_invariants, fn_iu_birth_gate_layer1, fn_iu_birth_gate_layer2, fn_birth_registry_auto, fn_iu_apply_edit_draft, fn_iu_create_edit_draft; tables: information_unit, unit_version, tac_unit_version, tac_logical_unit, dot_config, birth_registry, collection_registry, species_collection_map, entity_species, entity_labels, label_rules, universal_edges, all tac_*_vocab
next_recommended_action=Stay BLOCKED on TAC→IU migration. Before Phase 4 propose: (a) seed dot_config vocab.unit_kind.law_unit + missing section_types from tac_section_type_vocab; (b) seed species_collection_map for information_unit & unit_version (or accept species_code=NULL post-migration); (c) decide composition_role + parent_or_container_ref strategy for nested TAC structure (logical_unit hierarchy) and whether to materialize universal_edges; (d) define hash reconciliation policy — recompute on migrate (preferred) vs preserve (requires schema change to store both); (e) elevate collection_registry.governance_role for IU from 'observed' to 'governed' if migration is to be authoritative.
log_path=/tmp/p3d-phase3-investigation-20260511-062254.log
Critical blocker notes
-
HASH RECONCILIATION required — TAC and IU hash schemes are both SHA-256/UTF-8/hex but with materially different inputs (composite pipe-delimited vs body-only). A naive TAC→IU body copy will produce a
content_hashthat does NOT match the TAC source row'scontent_hash. Migration policy must explicitly choose: recompute (lose hash continuity), or store TAC-hash separately. -
VOCAB is the planner blocker, not a planner bug — Opus's claim that the planner "silently resolves law_unit → design_doc_section" was a false positive caused by misreading
fn_iu_create_plan's positional signature in the Phase-2 verification call. The planner correctly rejectslaw_unitasunresolved_vocab. The actual blocker is the empty IU vocab (1 unit_kind, 1 section_type, 1 publication_type vs TAC's 17 section types and 10 publication types). -
Native IU birth is Tier-0 only —
fn_iu_birth_gate_layer1enforces only canonical_address, unit_kind∈vocab, lifecycle_status, owner_ref, conformance_status, and 3 identity_profile keys (title, owner_lookup_ref, primary_section_type_ref∈vocab).pub_authority/pub_typeare WARN-only (PILOT).fn_iu_birth_gate_layer2enforces only anchor consistency.fn_iu_verify_invariantshas 5 invariants (i1..i5: IU exists, UV linked, anchors exact, birth_registry row, UV not double-registered). NO species, composition, parent, edge, or label invariants exist at birth. -
species/composition pipeline NOT wired for IU —
species_collection_mapis empty forinformation_unitandunit_version. As a result, all 12 IU rows present inbirth_registryhavespecies_code=NULL,composition_level=NULL.entity_labelshas 0 entries for IU/UV.universal_edges(2199 rows) has 0 IU/UV rows. The semantic-object contract that DOT-119 / downstream enrichment expects is not yet realized for IU. -
TAC is fully outside the birth_registry universe — tac_logical_unit, tac_unit_version, tac_publication have 0 rows in birth_registry, collection_registry, species_collection_map. TAC tables carry only
trg_tac_birth_gate_*andtrg_tac_uv_compute_derivedtriggers; nofn_birth_registry_autotrigger. Migrating TAC content into IU therefore cannot be a transparent rebadge — it requires explicit registration into the species/composition/label pipeline (or an explicit decision to defer that registration). -
collection_registry IU/UV state is "pilot" —
migration_state='pilot',governance_role='observed'(notgoverned),description_policy='structured_exempt',species_code=NULL. The IU collection itself has not yet been promoted to a governed, fully-classified collection.
Evidence summary
Phase-2 schema context (C0)
information_unit: 12 rows; new columnsdoc_code,section_type,section_codepresent, all NULLable, no defaults.unit_version: 19 rows; new columnstitle,description,review_state,provenance,editor,enacted_at,updated_atpresent, all NULLable.tac_unit_version: 86 rows.- Counts identical to Phase 2 report — no row drift.
Hash algorithms (A1–A5)
| Probe | Result |
|---|---|
| sha256 availability | ba9c736f… (works) |
| TAC hash recipe match (10/10 rows) | sha256(title | body | description | content_profile_or_{} :: UTF8) matches content_hash |
| TAC body-only / md5 | does NOT match |
IU match sha256(body :: UTF8) (10/10) |
matches |
IU match fn_content_hash(body) (10/10) |
matches |
| IU md5 | does NOT match |
Function source confirms:
public.fn_content_hash(p_body text) → encode(digest(p_body,'sha256'),'hex')IMMUTABLE.fn_tac_uv_compute_derivedtrigger setsNEW.content_hash := encode(sha256(convert_to(coalesce(NEW.title,'')||'|'||coalesce(NEW.body,'')||'|'||coalesce(NEW.description,'')||'|'||coalesce(NEW.content_profile::text,'{}'),'UTF8')),'hex').
Planner / vocab (B1–B5)
dot_config vocab keys present:
vocab.publication_type.design_doc = design_doc
vocab.section_type.section = section
vocab.unit_kind.design_doc_section = design_doc_section
No vocab.unit_kind.law_unit. No iu_create.default_unit_kind/default_section_type keys (so fn_iu_resolve_default falls into auto_single because each vocab has exactly one entry).
Planner probes (named args):
| input p_unit_kind | status | resolved_unit_kind | would_create |
|---|---|---|---|
law_unit |
unresolved_vocab |
law_unit (echoed input) |
false |
design_doc_section |
plan_ok |
design_doc_section |
true |
unknown_kind |
unresolved_vocab |
unknown_kind |
false |
| (NULL) | plan_ok |
design_doc_section (auto_single) |
true |
Birth gates / invariants (B2–B2c)
fn_iu_create (canonical writer): inserts IU with identity_profile = {title, owner_lookup_ref, primary_section_type_ref [, publication_type_ref]}, then UV with seq=1, then sets anchors, then calls fn_iu_verify_invariants and rolls back on failure.
fn_iu_birth_gate_layer1 (BEFORE INSERT): requires canonical_address, unit_kind∈vocab, lifecycle_status, owner_ref, conformance_status, identity_profile.title, identity_profile.owner_lookup_ref, identity_profile.primary_section_type_ref∈vocab. publication_authority_ref/publication_type_ref are WARN-only (PILOT-ONLY). NO species, composition, parent, edge checks.
fn_iu_birth_gate_layer2 (AFTER INSERT, constraint trigger, deferred): asserts content_anchor_ref non-empty, version_anchor_ref points to a UV of this IU, content_anchor_ref text equals version_anchor_ref::text. NOTHING about species/composition.
fn_iu_verify_invariants: i1_iu_exists, i2_uv_linked, i3_anchors_exact, i4_birth_exists (birth_registry row for information_unit::<id> exists), i5_uv_birth_ok (UV not separately birth-registered when uv strategy='subordinate').
Birth registry / species / labels / edges (D1–D6)
identity_profilekeys distribution across 12 IU rows:{title:12, owner_lookup_ref:12, primary_section_type_ref:12}. Nocomposition_role, nospecies.- All 12 IU rows:
unit_kind=design_doc_section,lifecycle_status=draft,parent_or_container_ref=NULL. universal_edges: 2199 rows total; 0 referencinginformation_unitorunit_version.birth_registryforinformation_unit: 12 rows, all withspecies_code=NULL,composition_level=NULL,governance_role=observed,certified=false,dot_origin='PG:trg_birth_information_unit',status=born.birth_registryforunit_version: 0 rows (UV issubordinatepercollection_registry).birth_registryfor tac_logical_unit / tac_unit_version / tac_publication: 0 / 0 / 0.species_collection_map: 153 rows total; 0 for information_unit, unit_version, or any tac_*.entity_labels: 91544 rows total; 0 for entity_code starting withinformation_unit::orunit_version::.entity_species: 40 rows.collection_registryforinformation_unit: COL-176,governance_role=observed,source_kind=native,species_code=NULL,birth_code_strategy=synthetic_id,description_policy=structured_exempt,storage_role=primary,migration_state=pilot.collection_registryforunit_version: COL-177, same exceptbirth_code_strategy=subordinate.collection_registryfor any tac_*: 0 rows.
Triggers on IU/TAC tables (D6)
information_unit:trg_aa_iu_gateway_write_guard(BEFORE INS/UPD),trg_birth_information_unit(fn_birth_registry_auto),trg_iu_birth_gate_layer1(BEFORE INS),trg_iu_birth_gate_layer2(AFTER INS, constraint, deferrable),trg_iu_updated_at.unit_version:trg_aa_iu_notif_version(AFTER INS),trg_aa_uv_gateway_write_guard(BEFORE INS/UPD).tac_unit_version:trg_tac_birth_gate_uv,trg_tac_enacted_immut,trg_tac_uv_compute_derived. NO fn_birth_registry_auto.tac_logical_unit:trg_tac_birth_gate_lu. NO fn_birth_registry_auto.tac_publication_member:trg_tac_pm_consistency,trg_tac_pm_enacted_lock. NO fn_birth_registry_auto.
Migration recommendation
Migration should remain BLOCKED. Phase 4 must NOT begin TAC→IU body migration until at minimum:
- Hash reconciliation policy decided (recompute vs preserve).
- IU vocab seeded for the unit_kind / section_type / publication_type values that the 86 TAC rows actually use (verify against
tac_logical_unit.section_typeandtac_publication.publication_typedistinct values before seeding). - Decision documented on whether species/composition/labels/edges will be (a) enforced at IU birth post-migration, (b) populated by a backfill, or (c) explicitly deferred — and the relevant
species_collection_map/label_rules/ edge-materialization triggers prepared accordingly. collection_registry.governance_roleforinformation_uniteither remainsobserved(with explicit statement that IU stays pilot post-migration) or is promoted togoverned(in which case missing species_code, missing labels, and birth-gate Tier-0-only become governance gaps that must be closed first).