IU-0 Description Policy Tiering — Runtime Investigation Report (F6 Preflight)
IU-0 Description Policy Tiering — Runtime Investigation Report
- Date: 2026-05-04
- Mode: Read-only investigation (F6 preflight)
- Source design:
knowledge/dev/laws/dieu44-trien-khai/design/13-iu0-description-policy-tiering-and-pack2b-f6-preflight.md - Scope: Q1–Q11 + 5-option comparison. No DDL, no patches. HARD STOP after report.
- Environment: VPS
38.242.240.89, containerpostgres, dbdirectus(PostgreSQL).
Q1 — entity_species schema
(a) Output:
| column | type | nullable | default |
|---|---|---|---|
| id | integer | NO | seq |
| sort | integer | YES | |
| user_created/date_created/user_updated/date_updated | |||
| code | varchar | NO | |
| species_code | varchar | NO | |
| display_name | varchar | NO | |
| composition_level | varchar | NO | |
| management_mode | varchar | NO | 'governed' |
| prefix | varchar | YES | |
| description | text | YES | |
| status | varchar | NO | 'active' |
| _dot_origin | varchar | YES | 'DIRECTUS' |
| parent_id | integer | YES | |
| depth | integer | YES | 1 |
| kg_metadata | jsonb | YES | '{}'::jsonb |
(b) Note: No description_policy / description_tier / metadata_policy field. But there IS a kg_metadata jsonb field — could carry policy as a JSONB key without DDL.
(c) Implication: Encoding policy at species-level is feasible via kg_metadata. But species ≠ collection: multiple collections may map to one species (and IU tables currently aren't in species_collection_map, so species-keyed encoding can't reach IU as-is).
Q2 — collection_registry schema
(a) Output (25 cols):
id, status, sort, user_created, date_created, user_updated, date_updated, code, name, name_en, description, classification, owner, collection_name, "group", icon, field_count, has_note, purpose, _dot_origin, storage_role, governance_role, source_kind, migration_state, species_code
(b) Note: No JSONB column. No extra_metadata, no config, no description_policy. Closest existing slot: classification varchar (currently NULL for all 11 sampled rows including IU tables) and purpose varchar. governance_role already encodes governed|observed|excluded|locked|law_artifact.
(c) Implication: Option 1 (DDL description_policy) is required if encoding lives on collection_registry. Option 2 (JSONB key in extra_metadata) is NOT FEASIBLE without DDL — the column does not exist. Re-using classification would conflate semantics (its current intended use is unclear from data — all NULL).
Q3 — entity_labels, taxonomy_facets, label/facet hits
(a) Output:
entity_labels cols: id, entity_code, label_code, assigned_by, rule_id, assigned_at.
taxonomy_facets cols: id, code, name, description, cardinality, max_labels_per_entity, sort, status.
Label codes matching DESC|POLICY|TIER → 0 rows.
Facets matching description|policy|tier|desc → 1 row: FAC-PROV — Description Provenance.
(b) Note: No existing label encodes policy/tier. There is one provenance facet, but it tracks PROV-DOT/PROV-AI/PROV-HUMAN, not policy tiers. The label system is per-entity_code, not per-collection — using it for collection-wide policy would require attaching one label per row, which is the wrong granularity.
(c) Implication: Option 4 (label/facet) feasible without DDL but wrong granularity for collection-level policy. Would need a new facet (FAC-DESC-POLICY?) and label codes; coverage would be per entity, not per table.
Q4 — dot_config description-related keys
(a) Output (5 keys):
| key | value | description |
|---|---|---|
| description_enforcement_mode | warn |
Đ4 §2.1 warn/block toggle |
| description_min_length | 30 |
Đ3 §2.1 min length |
| dot_tools_description_min_length | 50 |
per-table override |
| h11b_exclude_species | ["system_issue"] |
JSON array species_code (Đ3 §2.5) |
| hc_heal_description_basic_autofix_enabled | true |
H11a auto-heal gate |
(b) Note: Only existing tiering mechanism = h11b_exclude_species (singular system_issue). Note plural mismatch with memory (["system_issues"] would not match — verify species_code spelling at integration time).
(c) Implication: Option 5 (extend h11b_exclude_species) works without DDL but only addresses H11b side, NOT H11a, NOT the birth guard. Option 3 (new dot_config JSON array, e.g. description_policy_map) is feasible without DDL.
Q5 — v_entity_full_classification + H11a/H11b runtime findings
(a) View columns (14): entity_code, source_table, entity_type, name, description, description_length, status, domain, tier, paired_dot, governance_role, species_code, composition_level, description_provenance.
H11a findings: 0 rows (no governed entity has empty description).
H11b findings (11 source tables):
| source_table | h11b | prov_dot | no_prov_legacy |
|---|---|---|---|
| system_issues | 1941 | 1941 | 0 |
| collection_registry | 149 | 149 | 0 |
| meta_catalog | 130 | 130 | 0 |
| ui_pages | 37 | 37 | 0 |
| dot_tools | 29 | 29 | 0 |
| entity_species | 23 | 23 | 0 |
| workflow_steps | 8 | 8 | 0 |
| table_registry | 7 | 7 | 0 |
| agents | 6 | 6 | 0 |
| tasks | 3 | 3 | 0 |
| taxonomy_facets | 3 | 3 | 0 |
(b) Note: View has tier column (already!) — possibly carries Đ43 tier-A/B/C. All H11b findings have provenance PROV-DOT (no legacy NULL). system_issues dominates — exactly the operational table the design wants tier-B-exempted.
(c) Implication: A tier column already exists in the view. If v_entity_full_classification.tier source can be extended with description-tier semantics, no DDL needed. Need to inspect the view definition to see what feeds tier.
Q6 — fn_description_birth_guard source + triggers
(a) Function (key parts):
SELECT governance_role INTO _gov_role
FROM collection_registry
WHERE collection_name = TG_TABLE_NAME;
IF _gov_role = 'governed' THEN
_desc := btrim(COALESCE((to_jsonb(NEW)->>'description')::text, ''));
IF _desc = '' THEN
-- 4-tier dot_config template lookup (level-specific → table → level → default)
-- and fn_render_description_template(_tpl, _ctx)
END IF;
END IF;
-- C1-C3 enforcement (warn|block):
SELECT value INTO _mode FROM dot_config WHERE key='description_enforcement_mode';
SELECT value::int INTO _min_len FROM dot_config WHERE key='description_min_length';
SELECT value::int INTO _table_min FROM dot_config WHERE key=TG_TABLE_NAME||'_description_min_length';
IF _gov_role IS NULL THEN warn-or-block "chưa đăng ký"
IF _gov_role = 'excluded' THEN RETURN NEW;
-- if desc empty/short/gaming: block iff governed && mode=block
Triggers attached (21): agents, checkpoint_sets, checkpoint_types, collection_registry, dot_tools, meta_catalog, modules, system_issues, table_registry, tasks, ui_pages, workflow_change_requests, workflow_steps, workflows, taxonomy_facets, taxonomy, entity_species, dot_domain_rules, law_jurisdiction, apr_action_types, apr_request_types. All tgenabled='O' (origin/active).
(b) Note: Function knows only governance_role. No tier knowledge. information_unit and unit_version are NOT in the trigger list yet — birth guard hasn't been attached to IU. Function uses (to_jsonb(NEW)->>'description') — works only if column exists; for IU0 (no description column on information_unit), the expression returns NULL/'' and would always trip auto-gen + min-length enforcement.
(c) Implication: To honor tier semantics, fn must be extended with a tier lookup regardless of where tier lives (collection_registry column, JSONB, dot_config, label, or h11b_exclude expansion). The lookup is one extra SELECT — performance-wise all options are equivalent at function level. Tier B must short-circuit BOTH the auto-gen branch AND the C1-C3 enforcement branch.
Q7 — IU table description/profile columns
(a) Output:
information_unit ALL columns: id, canonical_address, unit_kind, lifecycle_status, content_anchor_ref, version_anchor_ref, owner_ref, parent_or_container_ref, conformance_status, identity_profile (jsonb), created_at, updated_at, created_by, updated_by, deleted_at.
unit_version desc/profile cols: content_profile (jsonb), description (text).
(b) Note: information_unit has NO description column. It carries identity_profile jsonb instead. unit_version has both description AND content_profile jsonb. This is the structural asymmetry the design flagged: IU is "structured-only," uv has free-text description plus structured profile.
(c) Implication: If birth guard is attached to information_unit while it stays governed, the function will always observe empty desc → enforcement fail. Tier B exemption is functionally required, not just preference, for IU. For unit_version, tier B must skip BOTH H11a and the birth guard's min-length rule even though description exists, because content lives in content_profile.
Q8 — collection_registry JSONB/config columns
(a) Output: 0 rows (no jsonb, no extra*, no config*).
(b) Note: Confirmed: extra_metadata does NOT exist on collection_registry. (Memory-line "extra_metadata is established idiom" refers to other registries, not this one.)
(c) Implication: Option 2 is NOT FEASIBLE without DDL. It collapses into Option 1 (DDL a JSONB column first, then key inside).
Q9 — H11 runtime registration
(a) system_health_checks cols: code, name, jurisdiction, check_kind, executor_type, executor_ref, threshold_config (jsonb), severity_on_fail, auto_fix_action, is_active, order_index, description, _dot_origin.
H11* rows:
| code | name | type | ref | threshold | sev | active |
|---|---|---|---|---|---|---|
| H11 | Description Coverage | sql | …health-h11-description-coverage.sql | {"warn_threshold":0} |
warn | f |
| H11a | Description Basic Missing | sql | …h11a-description-basic-missing.sql | {"threshold":0,"comparator":"eq","result_field":"h11a_total"} |
critical | t |
| H11b | Description Detail Missing | sql | …h11b-description-detail-missing.sql | {"threshold":0,"comparator":"eq","result_field":"h11b_total"} |
warn | t |
(b) Note: H11 (legacy) inactive; H11a/b active. Both are SQL-driven KB queries. threshold_config jsonb is available — could carry exclusion lists per check, but logic is in the SQL file, not the config.
(c) Implication: Tier policy must reach H11a/H11b at the SQL level (the KB query files), or via a filter in v_entity_full_classification. No code change needed in Directus — only the KB query SQL.
Q10 — Directus metadata + collection_registry totals
(a) Output:
directus_fieldsexists with full schema.- collection_registry rows: 166 total.
- governance_role distribution:
governed 34, observed 67, excluded 60, locked 3, law_artifact 2. directus_fieldsforcollection_registry: 24 fields registered (matches PG schema 1:1).
(b) Note: Adding a new column via DDL also requires registering it in directus_fields for UI visibility — non-trivial admin work but well-trodden path. governance_role split shows scope manageable: only 34 governed collections need explicit policy (others default safely).
(c) Implication: DDL+Directus registration is a known recipe; no blocker. With only 34 governed collections, a config-array (Option 3) listing tier-B tables is small/maintainable.
Q11 — Encoding without DDL — current state
(a) Output:
dot_config.h11b_exclude_species=["system_issue"].species_collection_mapfor IU tables: 0 rows (IU tables not mapped to any species).- (Skipped collection_registry.extra_metadata query — Q8 confirmed column absent.)
Bonus — collection_registry for relevant tables:
| collection | governance_role | species_code | classification | migration_state |
|---|---|---|---|---|
| birth_registry | governed | NULL | NULL | unclassified |
| collection_registry | governed | NULL | NULL | unclassified |
| dot_tools | governed | NULL | NULL | pilot |
| entity_labels | excluded | NULL | NULL | pilot |
| entity_species | governed | NULL | NULL | unclassified |
| information_unit | observed | NULL | NULL | pilot |
| meta_catalog | governed | NULL | NULL | unclassified |
| modules | governed | NULL | NULL | unclassified |
| system_issues | governed | NULL | NULL | unclassified |
| taxonomy_facets | governed | NULL | NULL | unclassified |
| unit_version | observed | NULL | NULL | pilot |
(b) Note: IU + unit_version currently observed (not yet governed), so birth-guard attachment hasn't fired the IU-0 problem yet — the design's concern is preflight for when they flip to governed in Pack 2B. species_code is uniformly NULL across these rows; a species-keyed mechanism (Option via entity_species.kg_metadata or h11b_exclude_species) needs species_code populated first.
(c) Implication: Lowest-friction encoding TODAY is dot_config (Option 3 / extension of Option 5). Anything species-keyed needs a backfill of collection_registry.species_code first.
5-Option Comparison
| # | Option | Feasibility | DDL? | Performance | Maintainability |
|---|---|---|---|---|---|
| 1 | DDL description_policy column on collection_registry |
High | Yes (1 col + Directus field reg) | 1 lookup per trigger fire (already done) — zero added cost | Highest: schema-self-documenting, queryable, RBAC via Directus, joinable in views |
| 2 | JSONB key in collection_registry.extra_metadata |
NOT FEASIBLE without DDL — column does not exist | Yes (add JSONB col first) | Same as Option 1 | Lower than Option 1: no schema constraints, harder to enforce enum |
| 3 | dot_config JSON array (e.g. description_policy_map) |
High | No | One extra SELECT … WHERE key=… in trigger; jsonb @> lookup; ~negligible |
Medium: text key, no FK, easy to drift; works today, no Directus admin work |
| 4 | Label/facet system (entity_labels + taxonomy_facets) | Medium | No (data-only inserts) | Per-row label scan in fn — extra subquery; manageable but slowest | Low for collection-level use: wrong granularity (per-entity, not per-collection); needs new facet + per-row label maintenance |
| 5 | Extend h11b_exclude_species |
Partial | No | Same as Option 3 | Lowest scope: only addresses H11b. Does NOT address H11a or birth guard. Currently uses species_code keys; IU tables unmapped to species → would need h11b_exclude_collections parallel key, drifting away from the species concept |
Pragmatic ranking (read-only observation, no recommendation)
- Option 1 is the cleanest endpoint (schema as SSOT) but requires DDL + Directus field registration + APR.
- Option 3 is the lowest-friction starting point and doesn't require DDL; tier mapping lives in
dot_config.description_policy_mapJSON, andfn_description_birth_guard+ H11a/H11b SQL all read from one place. - Option 5 alone is insufficient — the design problem spans all three surfaces (H11a, H11b, fn_description_birth_guard), and the existing key only covers H11b.
- Option 2 is gated on DDL identical in cost to Option 1, while losing schema-level constraints — strictly dominated.
- Option 4 is mismatched in granularity for a per-collection policy.
Cross-cutting findings (reportable, not actionable here)
- IU0 reality:
information_unithas nodescriptioncolumn; currentfn_description_birth_guardwould auto-fire empty-desc auto-gen + min-length enforcement on every INSERT once IU flips governed. - H11a is currently green (0 findings). H11b is heavy (system_issues=1941, collection_registry=149) — the cleanup goal aligns with the tier B exemption proposal.
v_entity_full_classificationalready exposes atiercolumn. Recommend (in next session) inspectingpg_get_viewdef('v_entity_full_classification')to learn what currently feedstierand whether it can carry description tier without DDL.h11b_exclude_speciesvalue is["system_issue"](singular). Verify againstentity_species.species_codespelling before relying on it.species_collection_mapempty for IU tables. Any species-keyed approach (Option 5) requires backfill first.- fn_description_birth_guard not yet attached to IU tables — the 21 attached triggers do not include
information_unitorunit_version. Design's preflight concern is correctly anticipatory.
HARD STOP
Per investigation directive: NO patch proposed, NO Pack 2B opening, NO DDL, NO function/trigger edit, NO admin_fallback creation. Investigation closes here pending GPT/User review of this report.