Universal Measurement Framework — Thiết Kế Kỹ Thuật PG v2.0
Universal Measurement Framework — Thiết Kế Kỹ Thuật PG
Version: v2.0 | Ngày: 2026-03-24 | Session: S132 Tác giả: Anh Huyên (tầm nhìn kiến trúc), Claude Desktop (thiết kế kỹ thuật) Nguyên tắc: "Tạo 1 thứ tiêu chuẩn rồi dùng lại mãi mãi" (Huyên S132) Thay thế:
dieu31-pg-technical-design.md v1.0— v1 quá hẹp (riêng Điều 31)
I. TẦM NHÌN: TẠI SAO CẦN FRAMEWORK PHỔ QUÁT
Hiện trạng — mỗi luật "tự chế"
- Điều 26: 17 triggers + verify_counts() + v_registry_counts
- Điều 28: birth_registry + birth triggers
- Điều 31: system_issues + runner scripts
Tầm nhìn 1 năm — 100+ luật, 50+ loại đo lường
Nếu mỗi luật tạo riêng triggers/functions/views → PG thành "con quái vật chậm chạp" (Huyên S132).
Giải pháp — 3 lớp kiến trúc
- Lớp A: Mỗi luật = 1 collection SSOT (đơn giản, độc lập)
- Lớp B: 1 framework đo lường phổ quát (shared, dùng lại mãi mãi)
- Lớp C: PG triggers real-time (giữ 17 trigger đếm, ổn định, KHÔNG tạo thêm)
Thêm luật mới = 1 collection + rows config. KHÔNG viết code. Thêm đo lường mới = 1 row config. KHÔNG viết code.
II. LỚP A — MỖI LUẬT = 1 COLLECTION SSOT
Mỗi luật sở hữu data riêng trong collection riêng. Đơn giản, trực quan, dễ code, độc lập.
| Luật | Collection SSOT | Chứa gì |
|---|---|---|
| Điều 26 (Đếm) | meta_catalog | Danh mục + số lượng entities |
| Điều 28 (Khai sinh) | birth_registry | Bản khai sinh mọi entity |
| Điều 29 (Species) | species_collection_map | Mapping loài↔collection |
| Điều 31 (Toàn vẹn) | system_issues | Vấn đề phát hiện |
| Điều 32 (Layer) | (tương lai) | Config 5 layer cho mọi dòng |
| ... | ... | ... |
law_catalog — Bảng danh mục luật (meta-SSOT)
CREATE TABLE law_catalog (
law_code TEXT PRIMARY KEY, -- 'dieu26', 'dieu31', 'dieu32'
law_name TEXT NOT NULL, -- 'Luật Đếm', 'Luật Toàn Vẹn'
law_version TEXT NOT NULL, -- 'v2.1.1', 'v1.3'
ssot_collection TEXT, -- 'meta_catalog', 'system_issues'
ssot_document TEXT, -- path trong Agent Data
status TEXT NOT NULL DEFAULT 'active'
CHECK (status IN ('draft', 'active', 'deprecated')),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
Ý nghĩa: 1 nơi tra cứu mọi luật, collection của nó, document SSOT. Agent mới → SELECT * FROM law_catalog → biết hệ thống có gì.
III. LỚP B — UNIVERSAL MEASUREMENT FRAMEWORK
Nguyên tắc cốt lõi
Thêm đo lường mới = thêm 1 row. KHÔNG viết trigger/function/view mới. Framework code viết 1 lần, chạy mãi mãi.
Bảng 1: measurement_registry — "Cần đo gì?"
CREATE TABLE measurement_registry (
-- Identity
measurement_id TEXT PRIMARY KEY, -- 'MSR-D26-001'
measurement_name TEXT NOT NULL, -- 'meta_catalog count vs SELECT COUNT'
law_code TEXT NOT NULL REFERENCES law_catalog(law_code),
-- PHƯƠNG PHÁP (★ từ methodology v2.0)
method SMALLINT NOT NULL CHECK (method IN (1, 2)),
-- 1 = PG kiểm PG (Bài toán 1 — chạy hoàn toàn trong PG)
-- 2 = PG vs External (Bài toán 2 — cần runner bên ngoài)
-- Nguồn chân lý (LUÔN là PG)
source_query TEXT NOT NULL, -- SQL lấy giá trị chân lý
-- So sánh với
target_type TEXT NOT NULL CHECK (target_type IN (
'pg_query', -- Bài toán 1: PG query khác
'pg_function', -- Bài toán 1: PG function
'nuxt_api', -- Bài toán 2: Nuxt endpoint
'nuxt_page', -- Bài toán 2: Nuxt rendered page
'agent_data', -- Bài toán 2: Agent Data API
'directus_api' -- Bài toán 2: Directus API
)),
target_query TEXT NOT NULL, -- SQL, URL, hoặc endpoint
-- Phân loại (taxonomy chuẩn ngành — bao quát)
category TEXT NOT NULL CHECK (category IN (
'completeness', -- ĐỦ chưa?
'consistency', -- KHỚP chưa?
'currency', -- MỚI chưa?
'validity', -- HỢP LỆ chưa?
'liveness' -- SỐNG chưa?
)),
-- Vận hành
severity TEXT NOT NULL DEFAULT 'warning'
CHECK (severity IN ('critical', 'warning', 'info')),
comparison TEXT NOT NULL DEFAULT 'strict_equals'
CHECK (comparison IN (
'strict_equals', 'eventual_equals',
'exists', 'not_exists', 'within_window', 'always_fail'
)),
enabled BOOLEAN NOT NULL DEFAULT true,
auto_generated BOOLEAN NOT NULL DEFAULT false,
-- Trạng thái run gần nhất (trigger tự cập nhật)
last_run_at TIMESTAMPTZ,
last_result TEXT CHECK (last_result IN ('pass', 'fail', 'error', NULL)),
last_evidence JSONB,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_msr_law ON measurement_registry(law_code);
CREATE INDEX idx_msr_method ON measurement_registry(method);
CREATE INDEX idx_msr_enabled ON measurement_registry(enabled) WHERE enabled = true;
Bảng 2: measurement_log — "Kết quả đo"
CREATE TABLE measurement_log (
-- Identity
run_id TEXT NOT NULL,
measurement_id TEXT NOT NULL REFERENCES measurement_registry(measurement_id),
run_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
-- Kết quả
result TEXT NOT NULL CHECK (result IN ('pass', 'fail', 'error')),
source_value TEXT, -- Giá trị PG (chân lý)
target_value TEXT, -- Giá trị so sánh
delta TEXT, -- Sai lệch cụ thể
evidence JSONB, -- Chi tiết đầy đủ
PRIMARY KEY (run_id, measurement_id)
);
-- Partition theo tháng (tránh bảng phình to)
-- Phase 2: ALTER TABLE measurement_log PARTITION BY RANGE (run_at);
-- Trigger: sau mỗi log → tự cập nhật measurement_registry.last_*
CREATE OR REPLACE FUNCTION update_measurement_status()
RETURNS TRIGGER AS $$
BEGIN
UPDATE measurement_registry SET
last_run_at = NEW.run_at,
last_result = NEW.result,
last_evidence = jsonb_build_object(
'source', NEW.source_value,
'target', NEW.target_value,
'delta', NEW.delta
),
updated_at = NOW()
WHERE measurement_id = NEW.measurement_id;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trg_update_measurement
AFTER INSERT ON measurement_log
FOR EACH ROW EXECUTE FUNCTION update_measurement_status();
Function 1: run_internal_measurements() — Bài toán 1, chạy TRONG PG
CREATE OR REPLACE FUNCTION run_internal_measurements(
p_law_code TEXT DEFAULT NULL, -- NULL = chạy tất cả
p_run_id TEXT DEFAULT NULL -- NULL = auto-generate
)
RETURNS TABLE (
measurement_id TEXT,
measurement_name TEXT,
law_code TEXT,
source_value TEXT,
target_value TEXT,
result TEXT,
delta TEXT
) AS $$
DECLARE
rec RECORD;
src_val TEXT;
tgt_val TEXT;
v_run_id TEXT;
BEGIN
v_run_id := COALESCE(p_run_id, 'internal-' || to_char(NOW(), 'YYYYMMDD-HH24MISS'));
FOR rec IN
SELECT * FROM measurement_registry
WHERE enabled = true
AND method = 1 -- Chỉ Bài toán 1
AND (p_law_code IS NULL OR measurement_registry.law_code = p_law_code)
LOOP
BEGIN
EXECUTE rec.source_query INTO src_val;
EXECUTE rec.target_query INTO tgt_val;
measurement_id := rec.measurement_id;
measurement_name := rec.measurement_name;
law_code := rec.law_code;
source_value := src_val;
target_value := tgt_val;
IF src_val = tgt_val THEN
result := 'pass';
delta := '0';
ELSE
result := 'fail';
delta := COALESCE(src_val, 'NULL') || ' ≠ ' || COALESCE(tgt_val, 'NULL');
END IF;
-- Ghi log (trigger tự cập nhật measurement_registry)
INSERT INTO measurement_log (run_id, measurement_id, run_at, result, source_value, target_value, delta)
VALUES (v_run_id, rec.measurement_id, NOW(), result, src_val, tgt_val, delta);
RETURN NEXT;
EXCEPTION WHEN OTHERS THEN
measurement_id := rec.measurement_id;
measurement_name := rec.measurement_name;
law_code := rec.law_code;
source_value := SQLERRM;
target_value := NULL;
result := 'error';
delta := 'QUERY ERROR';
INSERT INTO measurement_log (run_id, measurement_id, run_at, result, source_value, target_value, delta)
VALUES (v_run_id, rec.measurement_id, NOW(), 'error', SQLERRM, NULL, 'QUERY ERROR');
RETURN NEXT;
END;
END LOOP;
END;
$$ LANGUAGE plpgsql;
Cách dùng:
-- Chạy TẤT CẢ measurements Bài toán 1 (mọi luật)
SELECT * FROM run_internal_measurements();
-- Chỉ chạy measurements của Điều 26
SELECT * FROM run_internal_measurements('dieu26');
-- Chỉ chạy measurements của Điều 31
SELECT * FROM run_internal_measurements('dieu31');
Function 2: verify_framework_health() — SSOT tự kiểm tra
CREATE OR REPLACE FUNCTION verify_framework_health()
RETURNS TABLE (
issue_type TEXT,
severity TEXT,
detail TEXT
) AS $$
BEGIN
-- 1. Luật active nhưng không có measurement nào
RETURN QUERY
SELECT 'law_no_measurements'::TEXT, 'warning'::TEXT,
'Luật ' || lc.law_code || ' không có measurement nào'
FROM law_catalog lc
LEFT JOIN measurement_registry mr ON mr.law_code = lc.law_code AND mr.enabled = true
WHERE lc.status = 'active' AND mr.measurement_id IS NULL;
-- 2. Collection governed không có measurement nào
RETURN QUERY
SELECT 'collection_blind_spot'::TEXT, 'critical'::TEXT,
'Collection ' || mc.collection_name || ' (' || mc.code || ') không có measurement'
FROM meta_catalog mc
LEFT JOIN measurement_registry mr ON mr.source_query LIKE '%' || mc.collection_name || '%'
WHERE mc.governed = true AND mr.measurement_id IS NULL;
-- 3. Measurement enabled nhưng stale >26h
RETURN QUERY
SELECT 'stale_measurement'::TEXT, 'warning'::TEXT,
'Measurement ' || mr.measurement_id || ' không chạy ' ||
ROUND(EXTRACT(EPOCH FROM NOW() - mr.last_run_at)/3600)::TEXT || 'h'
FROM measurement_registry mr
WHERE mr.enabled = true AND mr.last_run_at < NOW() - INTERVAL '26 hours';
-- 4. Measurement trỏ vào bảng không tồn tại
RETURN QUERY
SELECT 'orphan_measurement'::TEXT, 'critical'::TEXT,
'Measurement ' || mr.measurement_id || ' source_query tham chiếu bảng không tồn tại'
FROM measurement_registry mr
WHERE mr.enabled = true
AND NOT EXISTS (
SELECT 1 FROM information_schema.tables t
WHERE mr.source_query LIKE '%' || t.table_name || '%'
AND t.table_schema = 'public'
);
-- 5. Bảng mới trong PG chưa có trong meta_catalog
RETURN QUERY
SELECT 'untracked_table'::TEXT, 'warning'::TEXT,
'Bảng ' || t.table_name || ' mới trong PG, chưa có trong meta_catalog'
FROM information_schema.tables t
LEFT JOIN meta_catalog mc ON mc.collection_name = t.table_name
WHERE t.table_schema = 'public' AND t.table_type = 'BASE TABLE'
AND mc.code IS NULL
AND t.table_name NOT LIKE 'directus_%'
AND t.table_name NOT LIKE 'pg_%'
AND t.table_name NOT IN ('spatial_ref_sys', 'measurement_registry',
'measurement_log', 'law_catalog');
-- 6. Coverage tổng
RETURN QUERY
SELECT 'coverage_report'::TEXT, 'info'::TEXT,
'Coverage: ' ||
(SELECT COUNT(DISTINCT law_code) FROM measurement_registry WHERE enabled = true) ||
' luật, ' ||
(SELECT COUNT(*) FROM measurement_registry WHERE enabled = true) ||
' measurements, ' ||
(SELECT COUNT(*) FROM measurement_registry WHERE enabled = true AND last_result = 'pass') ||
' pass, ' ||
(SELECT COUNT(*) FROM measurement_registry WHERE enabled = true AND last_result = 'fail') ||
' fail';
END;
$$ LANGUAGE plpgsql;
Cách dùng:
-- 1 câu lệnh → biết toàn bộ framework có đúng không
SELECT * FROM verify_framework_health();
-- 0 rows severity='critical' = FRAMEWORK ĐÚNG ✓
Materialized View: Dashboard tổng hợp
CREATE MATERIALIZED VIEW mv_measurement_dashboard AS
SELECT
mr.law_code,
lc.law_name,
COUNT(*) FILTER (WHERE mr.enabled) AS total_measurements,
COUNT(*) FILTER (WHERE mr.last_result = 'pass') AS pass_count,
COUNT(*) FILTER (WHERE mr.last_result = 'fail') AS fail_count,
COUNT(*) FILTER (WHERE mr.last_result IS NULL) AS never_run,
CASE
WHEN COUNT(*) FILTER (WHERE mr.last_result IS NOT NULL) > 0
THEN ROUND(100.0 * COUNT(*) FILTER (WHERE mr.last_result = 'pass') /
COUNT(*) FILTER (WHERE mr.last_result IS NOT NULL), 1)
ELSE 0
END AS pass_rate_pct,
MIN(mr.last_run_at) AS oldest_run,
MAX(mr.last_run_at) AS newest_run
FROM measurement_registry mr
JOIN law_catalog lc ON lc.law_code = mr.law_code
WHERE mr.enabled = true
GROUP BY mr.law_code, lc.law_name;
CREATE OR REPLACE FUNCTION refresh_measurement_dashboard()
RETURNS VOID AS $$
BEGIN
REFRESH MATERIALIZED VIEW mv_measurement_dashboard;
END;
$$ LANGUAGE plpgsql;
Nuxt chỉ cần: SELECT * FROM mv_measurement_dashboard → dashboard toàn bộ hệ thống.
IV. LỚP C — PG TRIGGERS REAL-TIME (GIỮ NGUYÊN)
17 triggers đếm hiện có = HIỆU QUẢ, GIỮ NGUYÊN.
Phân biệt rõ:
| Triggers (Lớp C) | Measurements (Lớp B) | |
|---|---|---|
| Khi nào | Data thay đổi (INSERT/DELETE) | Theo lịch hoặc on-demand |
| Mục đích | Đếm real-time (entity_count) | Verify, compare, check |
| Số lượng | 17-20 (ổn định, ít thay đổi) | 50→500+ (thêm config rows) |
| PG load | Rất nhỏ (1 UPDATE per event) | Nhỏ (scheduled SELECTs) |
| Thêm mới | Chỉ khi thêm collection mới | Thêm 1 row, không viết code |
KHÔNG tạo thêm triggers cho loại đo lường mới. Triggers = chỉ đếm. Mọi thứ khác = measurement_registry.
V. SCALING — TẠI SAO PG KHÔNG THÀNH QUÁI VẬT
| Yếu tố | Số lượng hiện tại | Dự kiến 1 năm | PG load |
|---|---|---|---|
| Triggers (Lớp C) | 17 | ~25 | Tiny — mỗi trigger = 1 UPDATE |
| measurement_registry rows | 0 (chưa tạo) | 500+ | Zero khi idle — chỉ là DATA |
| measurement_log rows | 0 | ~500/ngày | Nhỏ — partition theo tháng |
| run_internal_measurements() | - | 1-2 lần/ngày | ~500 SELECTs = <1 giây trên PG 16 |
| mv_measurement_dashboard | - | REFRESH 1-2 lần/ngày | <100ms |
So sánh: 500 rows trong measurement_registry = giống 500 rows trong meta_catalog. PG xử lý hàng triệu rows dễ dàng. Không tạo triggers mới = không tạo overhead mới.
VI. SEED DATA — DÙN LẠI CÁI ĐÃ CÓ
Existing infrastructure → đăng ký vào framework phổ quát:
-- Law catalog
INSERT INTO law_catalog VALUES
('dieu26', 'Luật Đếm', 'v2.1.1', 'meta_catalog', 'knowledge/dev/architecture/counting-law.md', 'active'),
('dieu28', 'Luật Khai Sinh', 'v1.0', 'birth_registry', 'knowledge/dev/architecture/birth-registry-law.md', 'active'),
('dieu29', 'Luật Species', 'v1.1', 'species_collection_map', 'knowledge/dev/architecture/species-taxonomy-complete.md', 'active'),
('dieu31', 'Luật Toàn Vẹn', 'v1.3', 'system_issues', 'knowledge/dev/architecture/system-integrity-law.md', 'active');
-- Dùng lại verify_counts() (đã có, chỉ đăng ký)
INSERT INTO measurement_registry VALUES
('MSR-D26-001', 'verify_counts = 0 mismatch', 'dieu26', 1,
'SELECT COUNT(*) FROM verify_counts() WHERE status != ''OK''',
'pg_query', 'SELECT 0',
'consistency', 'critical', 'strict_equals', true, false),
-- Dùng lại meta_catalog coverage (đã có)
('MSR-D26-002', 'meta_catalog coverage = governed collections', 'dieu26', 1,
'SELECT COUNT(*) FROM meta_catalog WHERE governed = true',
'pg_function', 'SELECT COUNT(DISTINCT collection_name) FROM meta_catalog WHERE governed = true AND entity_count > 0',
'completeness', 'warning', 'strict_equals', true, false),
-- Dùng lại birth_registry check
('MSR-D28-001', 'birth_registry tổng = meta_catalog tổng', 'dieu28', 1,
'SELECT COUNT(*) FROM birth_registry',
'pg_query', 'SELECT SUM(entity_count) FROM meta_catalog WHERE governed = true',
'consistency', 'warning', 'strict_equals', true, false),
-- Điều 31: PG vs Nuxt (Bài toán 2 — cần runner)
('MSR-D31-001', 'Registries L1 total khớp PG', 'dieu31', 2,
'SELECT SUM(entity_count) FROM meta_catalog WHERE governed = true',
'nuxt_api', '/api/registry/counts',
'consistency', 'critical', 'strict_equals', true, false),
('MSR-D31-002', 'Species count UI khớp PG', 'dieu31', 2,
'SELECT COUNT(*) FROM meta_catalog WHERE species_code IS NOT NULL',
'nuxt_api', '/api/registry/species-summary',
'consistency', 'warning', 'strict_equals', true, false),
-- WATCHDOG
('MSR-D31-WATCHDOG', 'WATCHDOG — runner sống', 'dieu31', 2,
'SELECT 1', 'nuxt_api', 'ALWAYS_FAIL',
'liveness', 'critical', 'always_fail', true, false);
Ý nghĩa: verify_counts(), meta_catalog checks, birth_registry checks — tất cả ĐÃ CÓ, chỉ ĐĂNG KÝ vào framework. Không viết lại. Vẻ đẹp = dùng lại.
VII. TÓM TẮT KIẾN TRÚC
┌─────────────────────────────────────────────────┐
│ LỚP A: LAW COLLECTIONS (SSOT) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌───┐ │
│ │meta_cata.│ │birth_reg.│ │species_ │ │...│ │
│ │(Điều 26) │ │(Điều 28) │ │map (Đ29) │ │ │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └─┬─┘ │
│ └────────────┼────────────┼──────────┘ │
│ ▼ │
│ ┌─────────────────────────────────────────┐ │
│ │ law_catalog (danh mục luật) │ │
│ └─────────────────┬───────────────────────┘ │
└────────────────────┼────────────────────────────┘
│
┌────────────────────▼────────────────────────────┐
│ LỚP B: UNIVERSAL MEASUREMENT │
│ ┌─────────────────────────────────────────┐ │
│ │ measurement_registry (config) │ │
│ │ MSR-D26-001, MSR-D31-001, ... 500+ │ │
│ └──────────────────┬──────────────────────┘ │
│ │ │
│ ┌──────────────────▼──────────────────────┐ │
│ │ run_internal_measurements() — Bài toán 1│ │
│ │ (runner bên ngoài) — Bài toán 2│ │
│ └──────────────────┬──────────────────────┘ │
│ │ │
│ ┌──────────────────▼──────────────────────┐ │
│ │ measurement_log (kết quả) │ │
│ └──────────────────┬──────────────────────┘ │
│ │ │
│ ┌──────────────────▼──────────────────────┐ │
│ │ verify_framework_health() — tự kiểm tra │ │
│ │ mv_measurement_dashboard — tổng hợp │ │
│ └─────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────┐
│ LỚP C: PG TRIGGERS (real-time, giữ nguyên) │
│ 17 triggers: entity_count++ / entity_count-- │
│ KHÔNG thêm triggers mới cho measurements mới │
└─────────────────────────────────────────────────┘
VIII. THAM CHIẾU
- Phương pháp luận 2 bài toán:
search_knowledge("dieu31 methodology 2 bài toán") - Luật Điều 31:
search_knowledge("system integrity verification law") - Nguyên tắc: "Tạo 1 thứ tiêu chuẩn dùng lại mãi mãi" (Huyên S132)
- Nguyên tắc: "PG không thành quái vật" — triggers ổn định, measurements = config (Huyên S132)
- Tiền lệ: DirectusTable.vue (1 component → mọi bảng), Điều 32 (1 khung → mọi dòng)