DỰ THẢO v6 — Entity Enrichment Master + Sửa 5 luật + 12 tài liệu (Council v5)
DỰ THẢO v6 — BẢNG MASTER ENTITY ENRICHMENT + SỬA 5 LUẬT + CẬP NHẬT TÀI LIỆU
Phiên: S178 Fix 30 | Tác giả: Claude Desktop Phạm vi: +1 bảng PG, amend 5 luật, cập nhật 4 tài liệu hỗ trợ Trạng thái: DỰ THẢO v6 — Council vòng 4: Gemini 9.6 APPROVE FINAL (review hời hợt) + GPT 7.8 CHANGES (2 blocker). Desktop rà NT14 soi schema thật. Chờ vòng 5. v5→v6: Fix VI.3 theo đúng schema Đ22 (13 cột), fix PK mapping, fix executor_ref format, fix hc-enrich-seed.sql, +backfill SQL, +2 DOT row đăng ký, +migration order, fix NULL key policy.
I-III. TÓM TẮT + BỐI CẢNH + QUYẾT ĐỊNH
Giữ nguyên v5.
IV. SCHEMA
Giữ nguyên v5. (DEFAULT approved='yes', approved_by='system-birth-seed')
V. CƠ CHẾ — 5 FUNCTION
V.1 — Approved gate
Giữ nguyên v5.
V.2 — Snapshot guard (SET LOCAL)
Giữ nguyên v5.
V.3 — Source_table verify (★v6: sửa HC check name)
CREATE FUNCTION fn_enrichment_verify_source_table() RETURNS TRIGGER AS $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM collection_registry WHERE collection_name=NEW.source_table) THEN
RAISE WARNING 'entity_enrichment: source_table=% chưa đăng ký. Row vẫn tạo, HC-REG phát hiện (Đ36).', NEW.source_table;
END IF; RETURN NEW;
END; $$ LANGUAGE plpgsql;
CREATE TRIGGER trg_enrichment_verify_source BEFORE INSERT OR UPDATE OF source_table ON entity_enrichment FOR EACH ROW EXECUTE FUNCTION fn_enrichment_verify_source_table();
★v6: Sửa "HC-REG-UNREGISTERED" → "HC-REG" (đúng tên check hiện có trong Đ36).
★v6 V.4 — Birth seed (fix PK map + NULL key policy)
PK mapping config (★v6: fix system_health_checks → "code"):
INSERT INTO dot_config(key, value, description) VALUES
('enrichment_pk_map', '{"dot_tools":"code","collection_registry":"collection_name","dot_config":"key","entity_species":"code","dot_domains":"code","normative_registry":"code","meta_catalog":"code","ui_pages":"code","workflow_steps":"code","tasks":"code","agents":"code","system_health_checks":"code"}',
'Mapping source_table → PK column. fn_enrichment_seed đọc runtime. Thêm bảng = UPDATE JSON.')
ON CONFLICT(key) DO NOTHING;
Function (★v6: RAISE WARNING khi NULL key, không silent RETURN):
CREATE FUNCTION fn_enrichment_seed() RETURNS TRIGGER AS $$
DECLARE _pk_col TEXT; _code TEXT; _species TEXT; _comp TEXT; _gov TEXT; _name TEXT; _desc TEXT; _pk_map JSONB;
BEGIN
SELECT value::jsonb INTO _pk_map FROM dot_config WHERE key='enrichment_pk_map';
_pk_col := _pk_map->>TG_TABLE_NAME;
IF _pk_col IS NULL THEN
RAISE WARNING 'fn_enrichment_seed: bảng % chưa có PK mapping. Thêm vào enrichment_pk_map.', TG_TABLE_NAME;
RETURN NEW;
END IF;
_code := (to_jsonb(NEW)->>_pk_col)::text;
IF _code IS NULL THEN
RAISE WARNING 'fn_enrichment_seed: bảng % cột %=NULL. Entity vẫn sinh, HC-ENRICH-SEED phát hiện.', TG_TABLE_NAME, _pk_col;
RETURN NEW;
END IF;
SELECT cr.governance_role INTO _gov FROM collection_registry cr WHERE cr.collection_name=TG_TABLE_NAME;
SELECT scm.species_code INTO _species FROM species_collection_map scm WHERE scm.collection_name=TG_TABLE_NAME AND scm.is_primary=true;
SELECT es.composition_level INTO _comp FROM entity_species es WHERE es.code=_species;
_name := (to_jsonb(NEW)->>'name')::text;
_desc := (to_jsonb(NEW)->>'description')::text;
BEGIN
INSERT INTO entity_enrichment(entity_code, source_table, species_code, composition_level, governance_role, name, name_en, description, provenance, approved, approved_by)
VALUES(_code, TG_TABLE_NAME, _species, _comp, _gov, _name, (to_jsonb(NEW)->>'name_en')::text, _desc, 'PROV-DOT', 'yes', 'system-birth-seed')
ON CONFLICT(entity_code) DO NOTHING;
EXCEPTION WHEN OTHERS THEN
RAISE WARNING 'fn_enrichment_seed: fail % (%) — %. HC-ENRICH-SEED phát hiện.', _code, TG_TABLE_NAME, SQLERRM;
END;
RETURN NEW;
END; $$ LANGUAGE plpgsql;
12 CREATE TRIGGER giữ nguyên v5. Trigger ordering bảng giữ nguyên v5.
V.5 — DOT sync chi tiết
Giữ nguyên v5 (6 bước sync + 5 bước verify).
★v6 VI. AMEND LUẬT — SELF-CONTAINED
★v6 VI.1 — Đ3 (sửa transition clause)
§2.4 — Thay đoạn "Pha ghi dữ liệu: PHẢI đi qua write path hợp pháp có audit: Directus REST API":
"Pha ghi dữ liệu: Enrichment mô tả chi tiết (mức 2, §2.5) PHẢI viết trên bảng entity_enrichment (§2.7), KHÔNG trực tiếp lên entity gốc. DOT sync xuống entity khi approved."
★v6: Bỏ "Giai đoạn chuyển tiếp" — entity_enrichment phải tồn tại trước khi amend luật (IX bước 1 trước bước 4).
§2.5 — Giữ nguyên v5.
+§2.7 — Sửa:
"Hệ thống dùng bảng entity_enrichment (DB directus, governed, governance_infra) làm SSOT metadata enrichment. Schema: code TEXT PK, source_table, species_code FK, jurisdiction FK normative_registry, description, provenance, approved gate, synced_at. Master = nơi viết. Entity gốc = mirror (DOT sync). Chi tiết trigger: Đ4 §2.1.1 (birth seed), Đ22 (3 HC check-code)."
VI.2 — Đ4
Giữ nguyên v5.
★v6 VI.3 — Đ22: 3 check-code — ĐÚNG SCHEMA HIỆN HÀNH
Schema system_health_checks (Đ22 §4.3): code, name, jurisdiction, check_kind, executor_type, executor_ref, threshold_config, severity_on_fail, auto_fix_action, is_active, order_index, description, _dot_origin.
3 INSERT đúng schema:
INSERT INTO system_health_checks(code, name, jurisdiction, check_kind, executor_type, executor_ref, threshold_config, severity_on_fail, auto_fix_action, is_active, order_index, description, _dot_origin) VALUES
('HC-ENRICH-SEED', 'Entity thiếu master enrichment row',
'NRM-LAW-03', 'detect_only', 'sql',
'knowledge__current-state__queries__hc-enrich-seed.sql',
'{}', 'critical', NULL,
true, 200,
'Detect entity governed có row nhưng thiếu entity_enrichment. Detect = báo ngay.',
'dieu3_fix30'),
('HC-ENRICH-DRIFT', 'Master approved chưa sync entity',
'NRM-LAW-03', 'detect_only', 'sql',
'knowledge__current-state__queries__hc-enrich-drift.sql',
'{"max_hours": 1}', 'warn', NULL,
true, 201,
'Detect approved=yes nhưng synced_at < updated_at quá threshold giờ.',
'dieu3_fix30'),
('HC-ENRICH-STALE', 'Enrichment chờ duyệt quá lâu',
'NRM-LAW-03', 'detect_only', 'sql',
'knowledge__current-state__queries__hc-enrich-stale.sql',
'{"max_days": 7}', 'warn', NULL,
true, 202,
'Detect approved=no kéo dài quá threshold ngày.',
'dieu3_fix30')
ON CONFLICT(code) DO NOTHING;
★v6: Dùng đúng 13 cột schema Đ22. executor_ref theo convention knowledge__*. check_kind='detect_only'. severity_on_fail='warn'/'critical'. threshold_config JSONB thay dot_config key riêng.
3 file executor — path KB đúng contract:
knowledge/current-state/queries/hc-enrich-seed.sql:
-- HC-ENRICH-SEED: entity governed có row nhưng thiếu entity_enrichment
-- Dùng enrichment_pk_map thay vì hardcode cột
WITH pk_map AS (
SELECT key AS table_name, value AS pk_col
FROM dot_config, jsonb_each_text(value::jsonb)
WHERE dot_config.key = 'enrichment_pk_map'
),
governed_with_desc AS (
SELECT cr.collection_name
FROM collection_registry cr
JOIN information_schema.columns c ON c.table_name = cr.collection_name AND c.column_name = 'description' AND c.table_schema = 'public'
WHERE cr.governance_role = 'governed'
)
-- Dynamic query per table (executor phải build runtime)
SELECT gwd.collection_name AS source_table, pm.pk_col
FROM governed_with_desc gwd
JOIN pk_map pm ON pm.table_name = gwd.collection_name
WHERE gwd.collection_name NOT IN (
SELECT DISTINCT source_table FROM entity_enrichment
WHERE entity_code IS NOT NULL
);
★v6: Không dùng has_description_column (cột không tồn tại trên view). Dùng information_schema.columns + enrichment_pk_map (dynamic, NT13). Lưu ý: executor SQL detect cấp bảng (bảng nào thiếu coverage), không detect cấp row (quá nặng cho 57K). Detect cấp row = chạy riêng per table.
knowledge/current-state/queries/hc-enrich-drift.sql:
SELECT entity_code, source_table, approved_at, synced_at, updated_at
FROM entity_enrichment
WHERE approved = 'yes'
AND (synced_at IS NULL OR synced_at < updated_at)
AND updated_at < now() - ((threshold_config->>'max_hours')::int * interval '1 hour');
★v6: threshold_config từ system_health_checks row, executor truyền vào. Nếu executor chưa hỗ trợ inject threshold, fallback: AND updated_at < now() - interval '1 hour'.
knowledge/current-state/queries/hc-enrich-stale.sql:
SELECT entity_code, source_table, updated_at
FROM entity_enrichment
WHERE approved = 'no'
AND updated_at < now() - ((threshold_config->>'max_days')::int * interval '1 day');
★v6 VI.4 — Đ36: INSERT đầy đủ
Giữ nguyên v5 (INSERT INTO collection_registry).
VI.5 — Phụ lục Đ3
Giữ nguyên v5.
VI.6 — Guide enrichment: 7 bước
Giữ nguyên v5.
★v6 VI.7 — 2 DOT đăng ký vào dot_tools
INSERT INTO dot_tools(code, name, name_en, description, tier, domain, trigger_type, operation, paired_dot, file_path, status, jurisdiction, _dot_origin) VALUES
('DOT-ENRICH-SYNC', 'Đồng bộ enrichment master → entity', 'Enrichment Master to Entity Sync',
'[A] [enrichment] cron trigger. Đọc entity_enrichment approved=yes chưa sync → UPDATE entity.description + provenance. Debounce 5 phút via max(updated_at). Cặp: DOT-ENRICH-VERIFY. Thuộc Đ3 §2.7.',
'A', 'enrichment', 'cron', 'ENRICHMENT_SYNC', 'DOT-ENRICH-VERIFY',
'opt/incomex/dot/bin/dot-enrichment-sync', 'active', 'NRM-LAW-03', 'dieu3_fix30'),
('DOT-ENRICH-VERIFY', 'Kiểm tra parity master vs entity', 'Enrichment Parity Verify',
'[A] [enrichment] cron trigger. So sánh entity_enrichment.description vs entity.description cho tất cả approved+synced. Drift → fn_log_issue HC-ENRICH-DRIFT. Cặp: DOT-ENRICH-SYNC. Thuộc Đ3 §2.7.',
'A', 'enrichment', 'cron', 'ENRICHMENT_VERIFY', 'DOT-ENRICH-SYNC',
'opt/incomex/dot/bin/dot-enrichment-verify', 'active', 'NRM-LAW-03', 'dieu3_fix30')
ON CONFLICT(code) DO NOTHING;
VII. 12 TÀI LIỆU BỊ ẢNH HƯỞNG
Giữ nguyên v5.
VIII. JURISDICTION MAPPING
Giữ nguyên v5.
★v6 IX. LỘ TRÌNH + MIGRATION ORDER
| Bước | Việc | SQL/Action | Ghi chú |
|---|---|---|---|
| 1a | Seed PK mapping config | INSERT dot_config enrichment_pk_map | Trước trigger |
| 1b | CREATE TABLE entity_enrichment | IV schema | |
| 1c | CREATE 5 functions | V.1-V.4 (fn_enrichment_*) | |
| 1d | CREATE 5 triggers trên entity_enrichment | V.1-V.3 (reset, guard, verify) | |
| 1e | CREATE 12 triggers birth seed | V.4 danh sách | |
| 2a | Backfill 57K rows (★v6 SQL bên dưới) | Script bulk | Giờ thấp điểm |
| 2b | Seed jurisdiction mapping | VIII | |
| 3 | Register 3 check-code + threshold | VI.3 INSERT | Scanner bù birth seed |
| 4 | Amend 5 luật + 1 phụ lục KB | VI.1-5 text | |
| 5 | Đăng ký 2 DOT + deploy script | VI.7 INSERT + tạo file bash | NT12 cặp |
| 6 | Sửa guide enrichment | VI.6 paste 7 bước | TRƯỚC pilot |
| 7 | Pilot 3 tasks qua master | Verify 11 tiêu chí | |
| 8 | Sửa handoff + note docs | VII |
★v6 Backfill SQL (bước 2a)
-- Backfill existing entities → entity_enrichment master
-- Chạy SAU bước 1 (table + triggers + config đã có)
-- Chạy giờ thấp điểm, batch per table
INSERT INTO entity_enrichment(entity_code, source_table, species_code, composition_level, governance_role, name, name_en, description, provenance, approved, approved_by)
SELECT
t.code, '<TABLE_NAME>' AS source_table,
scm.species_code, es.composition_level, cr.governance_role,
t.name, t.name_en, t.description, 'PROV-DOT', 'yes', 'backfill-fix30'
FROM <TABLE_NAME> t
LEFT JOIN collection_registry cr ON cr.collection_name = '<TABLE_NAME>'
LEFT JOIN species_collection_map scm ON scm.collection_name = '<TABLE_NAME>' AND scm.is_primary = true
LEFT JOIN entity_species es ON es.code = scm.species_code
ON CONFLICT(entity_code) DO NOTHING;
-- Lặp cho 12 bảng, thay <TABLE_NAME> bằng tên bảng thật.
-- Bảng dùng PK khác code: thay t.code bằng t.key (dot_config), t.collection_name (collection_registry), v.v. — xem enrichment_pk_map.
-- Agent đọc enrichment_pk_map → gen 12 câu INSERT tự động.
X. TIÊU CHÍ ĐO
Giữ nguyên v5 (11 tiêu chí). ★v6 sửa #1: "count(master) >= count(entities governed có description column)" khớp thực tế.
XI. BIÊN BẢN COUNCIL
Vòng 1-3: giữ nguyên.
Vòng 4
| Reviewer | Điểm | Verdict | Phát hiện chính |
|---|---|---|---|
| Gemini | 9.6 | APPROVE FINAL | Review hời hợt — không check schema Đ22 thật |
| GPT | 7.8 | CHANGES | 2 blocker: VI.3 sai schema + thiếu 2 DOT row. +PK sai 1 (system_health_checks). +backfill thiếu. +NULL key silent |
v6 sửa theo GPT vòng 4:
| Fix | Chi tiết |
|---|---|
| VI.3 rewrite | 13 cột đúng schema Đ22 §4.3. executor_ref convention knowledge__*. check_kind/severity_on_fail đúng enum |
| PK mapping | system_health_checks: "check_code" → "code". workflow_steps giữ "code" (đúng — gen_code tạo 'ND-xxx') |
| hc-enrich-seed.sql | Bỏ has_description_column. Dùng information_schema + enrichment_pk_map dynamic |
| +VI.7 2 DOT row | INSERT dot_tools đầy đủ 13 cột (code, name, tier, domain, trigger, operation, paired, file, jurisdiction...) |
| +Backfill SQL | IX bước 2a: INSERT...SELECT per table, đọc PK từ enrichment_pk_map |
| +Migration order | IX tách 1a→1e rõ dependency |
| NULL key policy | RAISE WARNING thay silent RETURN NEW |
| HC-REG name | Sửa HC-REG-UNREGISTERED → HC-REG (đúng Đ36) |
| VI.1 transition | Bỏ "Giai đoạn chuyển tiếp" (entity_enrichment phải tồn tại trước amend luật) |
DỰ THẢO v6 | Fix 30 | R4: Gemini 9.6 + GPT 7.8 | Fix schema Đ22 + 2 DOT + backfill + migration order | Chờ vòng 5