P11A Information Unit Schema Inventory Report
P11A — Information Unit Schema Inventory Report
Date: 2026-05-01 Phase: P11A (TAC Inventory — Design vs Production) Verifier: Opus (design docs) + Agent (VPS read-only) Mode: Read-only inventory. Zero mutation. Verdict: TAC core layer structurally complete. Smart layers (metadata profile, relation edges, vector contract, checkers, topic view) have design docs but no production proof yet.
1. Executive Summary
Đã có:
- 14 TAC tables (4 core + 2 change-set + 8 vocab/config) — fully enforced with 7 trigger functions, 41 indexes, vocab-driven FKs
- 3 publications / 86 units / 86 versions / 86 members — 1:1:1 clean
- 3 JSONB profile columns (identity_profile, content_profile, publication_profile) — GIN indexed, currently empty
{} - Vector sync tracking columns on
tac_unit_version(status, synced_at, chunk_count) universal_edgestable exists (2199 rows, 22 source / 10 target collections) — potential home for TAC relation edges
Thiếu:
- JSONB profiles chưa được populate (all =
{}) - Không có TAC edges trong universal_edges (chưa verify sample, nhưng schema chưa reference tac_* collections)
- Directus UI metadata hoàn toàn trống (0 fields, 0 relations registered)
- Qdrant/vector tables không tồn tại trong PG (expected external)
- Không có checker/DOT nào specific cho TAC ngoài birth gate
- Không có topic labels/vocabulary
- Change-set tables tồn tại nhưng chưa có row counts (likely empty)
2. Design vs Production — Gap Matrix
Gap Classification
| Code | Meaning |
|---|---|
| A | Có và đang dùng production |
| B | Có schema/table nhưng chưa populate hoặc chưa proof |
| C | Có thể lắp bằng JSONB/table hiện tại, không cần migration |
| D | Cần schema migration hoặc table mới |
| E | Defer — chưa cần hoặc chưa có design doc đủ |
Matrix
| # | Requirement | Source Doc | Production State | Gap |
|---|---|---|---|---|
| 1 | tac_publication table |
P5/G6, LSL-01 | ✅ 3 rows, 15 cols, PK+UNIQUE+2FK, vocab-driven | A |
| 2 | tac_logical_unit table |
P5/G6, 02C1 | ✅ 86 rows, 13 cols, PK+UNIQUE+3FK+birth gate trigger | A |
| 3 | tac_unit_version table |
P5/G6, 02C1 | ✅ 86 rows, 20 cols, PK+UNIQUE+3FK+3 triggers | A |
| 4 | tac_publication_member table |
P5/G6, LSL-01 | ✅ 86 rows, 6 cols, PK+UNIQUE+3FK+2 triggers | A |
| 5 | canonical_address (immutable identity) |
02C1 §6.1, LSL-01 | ✅ UNIQUE constraint on tac_logical_unit.canonical_address |
A |
| 6 | parent_id + sort_order (tree) |
02C1 §3 | ✅ self-FK on parent_id, sort_order integer, partial index | A |
| 7 | section_type (vocab-driven) |
02C1 §5.2 | ✅ FK → tac_section_type_vocab.code (11 cols incl word limits) |
A |
| 8 | content_hash (body fingerprint) |
02C1 §5.2 | ✅ tac_unit_version.content_hash text col, computed by fn_tac_uv_compute_derived |
A |
| 9 | lifecycle_status + review_state |
02C1 §5.2, L5 | ✅ Both vocab-driven FK on LU and UV, enacted immutability trigger | A |
| 10 | vector_sync_status tracking |
02C1 §5.2 | ✅ 3 columns + partial index on UV. But no Qdrant table in PG | B — tracking exists, sync not proven |
| 11 | Change-set management | L5, P5/G6 | ✅ tac_change_set + tac_change_set_member tables exist, schema complete |
B — tables exist, likely 0 rows |
| 12 | Birth gate enforcement | L4, P5/G6 | ✅ tac_birth_gate_config + 2 trigger functions |
A |
| 13 | Vocab tables (7 vocabularies) | P5/G6 | ✅ 7 vocab tables, all PK on code, all FK-referenced |
A |
| 14 | JSONB identity_profile (LU) |
P5/G6, C2 | ⚠️ Column exists + GIN index, but all values = {} |
B — schema ready, populate needed |
| 15 | JSONB content_profile (UV) |
P5/G6, C2 | ⚠️ Column exists + GIN index, but all values = {} |
B — schema ready, populate needed |
| 16 | JSONB publication_profile (Pub) |
P5/G6, C2 | ⚠️ Column exists + GIN index, but all values = {} |
B — schema ready, populate needed |
| 17 | Relation edges (unit↔unit) | 02C1 §4-5, Addendum §4 | ⚠️ universal_edges exists (2199 rows) but no TAC edges verified |
C — can use universal_edges, needs populate |
| 18 | edge_type vocabulary |
02C1 §5.3, Addendum §4 | ⚠️ universal_edges.edge_type column exists. No TAC-specific edge_type vocab table |
C — universal_edges has the column, vocab values TBD |
| 19 | Edge metadata (confidence/provenance) | 02C1 §5.3, Đ39 | ✅ universal_edges has confidence, provenance(jsonb), valid_time(tstzrange), status |
C — infrastructure ready, needs TAC edges |
| 20 | Profile metadata by doc_type | 02C1 §5.2, C2 | ⚠️ JSONB profiles exist but structure/validation undefined | C — can use existing JSONB, needs schema definition |
| 21 | Topic labels | LSL-01 Label layer | ❌ No topic label table, no label_rules for TAC | D — needs design + possible table/vocab |
| 22 | Entity mentions in units | Addendum §2.3 | ❌ No entity extraction infrastructure for TAC | E — aspirational, no design doc |
| 23 | Numeric claims extraction | Addendum §2.3, GPT Gap D | ❌ No numeric claim infrastructure | E — aspirational |
| 24 | Version reference tracking | Addendum §2.3, GPT Gap D | ❌ No version reference tracking | E — aspirational |
| 25 | Code/workflow bindings | Addendum §2.3 | ❌ No text↔code binding infrastructure for TAC | E — aspirational |
| 26 | Vector payload contract | LSL-01, Addendum §5 | ❌ No Qdrant config in PG. vector_sync columns track state only | D — needs Qdrant config + payload contract |
| 27 | TAC-specific checker/DOT | GPT Gap D | ⚠️ fn_tac_log_checker_issue exists but no drift/consistency checkers |
D — function exists, checker logic TBD |
| 28 | Directus UI field registration | Operational | ❌ 0 rows in directus_fields for tac_* | D — needs registration pass |
| 29 | Directus relation registration | Operational | ❌ 0 rows in directus_relations for tac_* | D — needs registration pass |
| 30 | BOM/component bindings | 02C2 (if exists) | ❌ No BOM table for TAC | E — 02C2 not found |
3. Gap Summary by Classification
| Gap | Count | Items |
|---|---|---|
| A — có và đang dùng | 13 | #1-9, #12-13, core TAC + birth gate + vocab |
| B — có schema, chưa proof | 4 | #10 vector tracking, #11 change-set, #14-16 JSONB profiles |
| C — lắp được bằng infra hiện tại | 4 | #17-20 relation edges + profile metadata (dùng universal_edges + JSONB) |
| D — cần migration/registration | 5 | #21 topic labels, #26 vector contract, #27 checker, #28-29 Directus UI |
| E — defer | 4 | #22-25 entity/numeric/version-ref/code-binding, #30 BOM |
Tỷ lệ: 13 A + 4 B + 4 C = 21/30 items có thể dùng hoặc lắp được mà KHÔNG cần schema migration mới.
4. Key Architectural Findings
4.1 JSONB Profile là cơ hội lớn nhất
3 JSONB columns (identity_profile, content_profile, publication_profile) đã có GIN index, đang trống {}. Đây là nơi metadata thông minh (topic, entity, numeric claim, version ref) có thể sống ngay mà không cần ALTER TABLE. Chỉ cần:
- Define JSON schema cho từng profile type
- Populate bằng Agent/AI extraction
- Query bằng
@>operator (GIN-optimized)
4.2 Universal edges là nhà cho TAC relations
universal_edges đã có đủ columns: source/target collection+id+code, edge_type, confidence, provenance(jsonb), valid_time(tstzrange), status, metadata(jsonb). Chỉ cần INSERT edges với source_collection='tac_logical_unit' — không cần table mới.
4.3 Directus UI gap là cosmetic, không structural
0 rows trong directus_fields/relations có nghĩa Directus admin UI render generic columns. PG layer hoạt động 100%. Registration pass là operational task, không ảnh hưởng data integrity.
4.4 Vector sync là "bản vẽ có, nhà chưa xây"
Columns vector_sync_status, vector_synced_at, vector_chunk_count trên tac_unit_version + partial index = tracking infrastructure ready. Nhưng không có Qdrant table/config trong PG. Vector materialization expected ngoài PG (Qdrant container).
5. Top 3 Next Proofs (Đề xuất)
Proof 1: JSONB Profile Population (Priority: HIGH)
Tại sao: 3 JSONB columns là quick win lớn nhất — infrastructure 100% ready (columns + GIN indexes), chỉ cần populate. Biến 86 units từ "thẻ trắng" thành "thẻ có nhãn".
Scope: Define JSON schema cho content_profile trên 86 unit_versions. Populate bằng AI extraction (topics, key entities, section summary). Read-only proof query: "tìm tất cả units về database schema across 3 publications."
Risk: Low — JSONB update, không đổi DDL.
Proof 2: TAC Relation Edges (Priority: HIGH)
Tại sao: universal_edges sẵn sàng. 02C1 §4-5 + Addendum §4 đã define edge types. Cross-unit references (VD: D35 §4.1 references D32 §2.1) là giá trị cốt lõi của "miếng thông tin sống".
Scope: Extract 10-20 obvious cross-references between 86 units. INSERT vào universal_edges. Proof query: "unit A references unit B" + "broken reference detection".
Risk: Medium — cần define edge_type vocab + populate carefully.
Proof 3: Directus UI Registration (Priority: MEDIUM)
Tại sao: 0/0 field/relation registration = Directus admin unusable cho TAC. Cần ít nhất basic field interfaces (JSONB editor, relation pickers) để human governance.
Scope: Register fields + relations cho 4 core TAC tables. Operational task, không ảnh hưởng PG.
Risk: Low — Directus metadata only.
6. Hình tượng
P10D chứng minh: cắt sách thành thẻ ✅, cất vào tủ PG ✅, lấy ra ghép lại ✅.
P11A mở tủ kiểm:
- Thẻ đã có khung (schema) ✅ — 14 bảng, 7 triggers, 41 indexes
- Thẻ có chỗ dán nhãn (JSONB profiles) ✅ — nhưng chưa dán nhãn nào
- Có hộp đựng dây nối (universal_edges) ✅ — nhưng chưa có dây nào nối giữa các thẻ TAC
- Máy photocopy (vector) có nút bấm ✅ — nhưng chưa nối điện
- Kệ nhãn chủ đề (topic) — chưa có kệ
- Directus (bảng điều khiển) — đã cắm ổ nhưng chưa gắn công tắc
Kết luận: nhà đã có dây, có ổ, có khung. Chưa gắn bóng đèn.
P11A Information Unit Schema Inventory | 2026-05-01 | Opus + Agent | READ-ONLY