Kế hoạch — Sửa rẻ / Nhập UI v0 (Rev 6): 2 bảng PG + BỘ KIT + Definition of Done + NO-VECTOR + đường ống vận hành (7 quyết định ĐÃ CHỐT)
KẾ HOẠCH — "SỬA RẺ" / NHẬP UI v0 (Rev 6)
2 bảng PG nháp + BỘ KIT "túi thuốc đóng sẵn" (đã có ở JS → chuyển PG) + đường ống vận hành + NO-VECTOR + report bằng khuôn có sẵn
TRẠNG THÁI:
HOLD_PRE_FLIGHT— 7 quyết định §11 ĐÃ CHỐT (Owner 2026-07-06); Rev 6 hoàn thiện theo GPT simplify-locks + đồng bộ nhãn. CHƯA chạy DDL/DML, CHƯA tạo seed/kit artifact, CHƯA soạn prompt execution. Bước kế: Claude Code (claude-go, VPS, read-only) đọc bản này, chạy PRE-FLIGHT GATES (§9) + đi bộ lại B1→B6 → báo cáo KB → chỉnh doc nếu cần → chỉ khi TẤT CẢ gate xanh mới bàn mở G1. Tác giả: Fable (Reviewer #3). Ngày: 2026-07-06. Rev 6. Liên kết bằng chứng:
- Codex review (HOLD):
knowledge/dev/laws-new/kestra/sua-re/nhap-ui/codex-review-ke-hoach-nhap-ui-v0-rev2.md- Rà soát TƯƠNG THÍCH hệ thống (Fable, 2026-07-06):
knowledge/dev/laws-new/kestra/sua-re/nhap-ui/compat-review-2026-07-06.md- GPT review simplify (2026-07-06):
knowledge/dev/laws-new/kestra/sua-re/nhap-ui/gpt-review-rev6-simplify-2026-07-06.md- Handoff phiên:
knowledge/dev/laws-new/kestra/sua-re/handoff-2026-07-06.md- KIT SỐNG (đã đọc-verify trên VPS):
/opt/incomex/docs/mcp-writes/ui-preview/→SUA-RE-README.md(README kit, "START HERE", luật nghiệm thu §3) +concept-ledger.js(v0.5, 13 thẻ) +ui-contracts.js(v0.1-chot2, 30 usage = 27 matched + 2 candidate + 1 review) +verify-contracts.js. Cùng mốc2026-07-06T03:53:44Z.
0. MỤC TIÊU (một câu) + ANTI-GOAL
Mục tiêu: Cowork vẽ UI thoải mái; PG đếm đầu mối / khử trùng / so khái niệm cũ-mới RẺ, để Cowork KHÔNG tốn công kiểm điểm hợp đồng thông tin. Bộ 2 bảng + đường ống + kit là phương tiện, không phải đích.
ANTI-GOAL (Owner nhấn rất nhiều lần — đặt trên mọi thứ):
- ĐỪNG đẻ quái vật. Không có DOT nào đi đọc / quét / OCR / đếm lại UI — đó chính là con quái vật. Cowork vừa vẽ nên biết thừa nó tạo trường gì và để làm gì (User nhắc được
purpose). Cây cầu DUY NHẤT từ "Cowork biết" sang "PG đếm được" là một cái FORM Cowork điền. - Đơn giản không phải mục đích tự thân — nó là cách giữ số bước đủ ít để soi được từng bước có GAP hay không. Rủi ro nằm ở từng bước (kể cả bước đơn giản nhất). Một việc khả thi = đủ đơn giản và không có GAP trong quy trình vận hành. Kế hoạch cũ "trên trời" vì không ai đi bộ từng bước vận hành — Rev 4/5/6 sửa đúng chỗ đó (§3, §3A, §3B).
- KHÔNG đẻ kit mới. Kit đã tồn tại ở thời JS (
SUA-RE-README.md+ schemaui-contracts.js+renderUIContract+verify-contracts.js). Việc của ta = chuyển kit sang PG, giữ nguyên triết lý, đổi đúng một bước. - Khuôn
/reports(PG view →v_report_*→ Nuxt) ĐÃ XONG production (PG Census = ví dụ sống). TÁI DÙNG, không rebuild, không thiết kế UI mới. - Mọi thứ CHỐT phải hạ xuống KB (file này hoặc file cùng thư mục) — không để chết trong chat.
1. NGUYÊN TẮC BẤT DI (chống phình lại)
- 100% DOT cho DDL + ghi PG (cổng
dot-pg-atomic-apply). Fable/MCP chỉ READ PG. Không psql tay, không sửa schema bằng Directus UI. - PG → app chỉ qua Directus/Nuxt bằng KHUÔN CÓ SẴN (đăng ký collection +
table_registry+ SharedDirectusTable). Không Codex ở Nuxt. - v0 chỉ 2 bảng. Không bảng scan/alias/ui/history riêng.
- v0 chỉ exact / alias / ILIKE. KHÔNG
pg_trgm, KHÔNG Qdrant, KHÔNG fuzzy auto-match. Máy chỉ GỢI Ý; Owner QUYẾT cái mới. - KHÔNG XÂY MỚI nếu khuôn/kit có sẵn kham được. Vượt ra → DỪNG, hỏi Owner.
- Cowork chỉ khai QUAN SÁT THÔ (§3, §3A). Không tự gán khóa/dedupe/match. Kit PG rút NGẮN việc Cowork: bỏ KHỬ-TRÙNG + KHỚP-SỔ tay (đúng "tốn công kiểm điểm" cần diệt) cho PG+Owner.
- Đồ nháp phải chui vùng NO-VECTOR (§7) — enforcement bằng policy thật, không chỉ nhãn.
2. HAI BẢNG (schema hội tụ) — DB directus, tên _nhap, status='draft'/'active'
(Lý do DB directus: các ổ cắm tích hợp + khuôn reports đều ở đó; để incomex_metadata phải FDW cross-DB.)
Bảng 1 — sua_re_khai_niem_nhap (DANH MỤC = ĐỊNH NGHĨA, 1 bản/khái niệm)
| Cột | Kiểu | Ghi chú |
|---|---|---|
id |
bigserial PK |
hợp khuôn (khuôn dùng id; balo dùng stt → khuôn xử được PK khác, nhưng id ít ma sát nhất). |
concept_key |
text UNIQUE |
Id NGỮ NGHĨA (role.nguoi_lap) — đồng tiền tham chiếu xuyên hệ. Giữ cứng unique ở DB nếu tool cho. |
ten |
text NOT NULL |
Tên hiển thị. |
concept_kind |
text NOT NULL |
Enum đúng 6 loại của sổ: workflow, step, task, field, role, org. Đổi tên từ loai (tránh đụng "loài"=entity_species). Là từ vựng NHÃN-UI, KHÔNG phải species (compat-review Ⓑ). |
mo_ta |
text NOT NULL |
Định nghĩa chuẩn. Gate ≥15 (§2-guard). |
ranh_gioi |
text |
KHÔNG-phải-gì. |
aliases |
jsonb default [] |
Tên gọi khác. |
match_policy |
text |
GIỮ — 2 thẻ họ thời gian/trạng thái mang review (phanh chống-khớp-nhầm). Thẻ vắng = auto. |
status |
text default draft |
seed 'chot'→'active'. Enum draft/active/retired. |
note, date_created, date_updated |
Lý lịch. |
KHÔNG bê vào bảng: locations (bảng usage CHÍNH LÀ locations chuẩn hóa), examples/non_examples/id_rules (giữ trong seed artifact). Bảng mảnh mà không mất gì.
Bảng 2 — sua_re_ui_khai_niem_nhap (NƠI DÙNG = bảng kê từng UI/scan)
| Cột | Kiểu | Ghi chú |
|---|---|---|
id |
bigserial PK |
hợp khuôn. |
item_key |
text UNIQUE |
CỔNG SINH tất định (G-F): hash(ui_id, scan_id, location_or_index, raw_label). location trống → dùng INDEX của item trong items[] làm fallback. Cowork KHÔNG bịa khóa. item_key chỉ cần UNIQUE trong một scan. |
ui_id |
text NOT NULL |
= surface_id (master-list-quy-trinh-v1). |
ui_file |
text |
File thật. |
scan_id |
text NOT NULL |
CỔNG sở hữu = hash CANONICAL JSON của companion (§3A). Không đổi → cùng scan_id → no-op; đổi → scan mới. |
scan_at |
timestamptz |
|
is_current |
boolean default true |
Bản mới nhất của ui_id. Scan lại → bản cũ false. |
raw_label |
text NOT NULL |
Nhãn thô Cowork khai. |
purpose |
text NOT NULL |
Cọc neo. Gate ≥15 (§2-guard). Thiếu/ngắn = fail import. |
location |
text |
Vị trí trong UI (tùy — thiếu thì item_key dùng index). |
dedupe_key |
text NOT NULL |
= duplicate_group: matched → concept_key; pending → pending.<hash(raw_label chuẩn hóa + purpose)> (KHÔNG chỉ raw_label — cùng "Trạng thái" hai nghĩa khác không được gộp; overcount an toàn hơn undercount sai). "Số khái niệm phân biệt" chính xác cho matched, xấp xỉ cho pending. |
concept_id |
bigint FK→sua_re_khai_niem_nhap(id) |
null nếu chưa matched. Resolve lúc import (G-G). |
owner_concept_id |
bigint FK, nullable |
Owner GHIM. Nguồn sự thật cho matched khi Owner đã quyết. |
decision_note |
text |
Owner ghi VÌ SAO (§3A B5). |
near_concepts |
jsonb |
Mảng {concept_key, why, confidence} — theo concept_key, KHÔNG ép FK id số. |
date_created, date_updated |
match_status KHÔNG lưu cột enum — SUY TRONG VIEW (§4): owner_concept_id có → matched; concept_id khớp → matched; alias/ILIKE → review; còn lại → candidate; vừa import chưa khớp → raw. (Fallback nếu G-A cản: lưu enum {raw,matched,candidate,review} — bỏ deferred.)
MẶC ĐỊNH KHÔNG TÁCH HISTORY: current + history sống chung một bảng usage (scan_id + is_current). KHÔNG tách bảng history riêng trừ khi Claude Code trích được luật dòng chảy cấm cụ thể (§9 G-J) — tách = phức tạp hóa. Tiền lệ: IU iu_staging_record versioning trong một bảng, được chấp nhận.
GATE TOÀN VẸN (biến luật → ràng buộc máy; nơi đặt = §9 G-D)
purpose/mo_ta≥15: DBCHECKnếu tool cho; không thì import-gate FAIL CỨNG. Không dời/bỏ qua. ≥15 chỉ là sàn cơ học.dedupe_keyNOT NULL,concept_key/item_keyUNIQUE giữ cứng DB nếu được; tool không kham → import UPSERT theo khóa nghiệp vụ. Idempotency KHÔNG dời verify.- Re-scan = UPSERT trong import (KHÔNG DOT bất biến, KHÔNG bảng scan): lật
is_current=falsebản cũ → chèn mớiis_current=true, atomic. - Registry idempotent (G2/G3): precheck + readback (map CHƯA có unique DB, đã có cặp trùng — KHÔNG cậy
ON CONFLICT).
3. VÒNG VẬN HÀNH THỰC TẾ ⭐ (đi bộ từng bước — trái tim kế hoạch)
Hình tượng: đã thiết kế cái kho (2 bảng). Phần này thiết kế phiếu nhập kho, ai viết phiếu, cổng nào nhận, thủ kho so hàng cũ/mới. Thiếu đường ống này thì hệ chết vì vận hành, không phải vì schema.
B1 — Cowork vẽ/sửa UI. Đủ điều kiện. Không GAP.
B2 — Cowork điền FORM (UI_SCAN_JSON). (khâu SỐNG-CÒN) Khai CHỈ QUAN SÁT THÔ: raw_label, purpose(≥15), location, đoán type_guess/proposed_concept_key. KHÔNG tự gán dedupe_key/match_status/concept_id. Chống-quên = Definition of Done + coverage (§3A). Chưa từng thử → G1b.
B3 — FORM vào PG qua CỔNG. Nhận → kiểm (purpose≥15) → sinh scan_id+item_key → UPSERT → lật is_current, atomic. Cổng KHÔNG đọc lại UI. Ưu tiên dot-pg-atomic-apply + lớp kiểm mỏng (G-A/G-I). Seed = scan #0.
B4 — PG so cũ/mới = VIEW SUY. exact/alias→matched; ILIKE→review; không thấy→candidate; máy gợi ý, Owner quyết. Owner tạo concept mới → candidate cũ tự khớp lại.
B5 — Owner quyết. 3 action duy nhất: map_existing (set owner_concept_id=concept có sẵn) / create_new (insert concept vào bảng 1 + set owner_concept_id) / keep_pending (để null). Ghi owner_concept_id + decision_note qua dot-pg-atomic-apply. Chưa decision-DOT → G3.
B6 — Sửa nút. Màu/layout/icon → KHỎI. Label/field/filter/drawer → quét toàn UI. Sửa companion → nội dung đổi → hash đổi → scan mới → lật cũ. Tự động.
3A. BỘ KIT "TÚI THUỐC ĐÓNG SẴN" ⭐ — ĐÃ CÓ ở JS, chuyển sang PG
Ý Owner: mỗi UI cần chỗ riêng để lắp vào; đóng gói chuẩn như túi thuốc gia đình — có UI là khoác vào, khai tối thiểu, quét được data là đủ. Kit đã tồn tại (
SUA-RE-README.md: "Quy trình sống trong FILE (git), không sống trong prompt hay trong đầu ai"). Việc của ta = giữ kit, đổi bước ② sang PG.
🔑 ĐIỀU KIỆN NGHIỆM THU — Definition of Done [GAP quan trọng nhất]
Chính là luật nghiệm thu §3 của
SUA-RE-README.md, cập nhật cho PG. Đây là câu biến "Cowork nhớ điền form" thành điều kiện nghiệm thu.
UI_DONE = (UI file tồn tại) + (companion .scan.json cạnh UI) + (companion PASS validation)
UI mới/sửa lớn THIẾU companion hợp lệ = UI CHƯA XONG.
Cưỡng chế hai lớp: (a) LUẬT — câu nghiệm thu trên nằm trong README kit (agent đọc START HERE); (b) MÁY DÒ — coverage report (dưới) liệt kê UI thiếu companion / companion chưa import → "quên" thành nhìn thấy được. Luật cấm, dò lộ.
Ba phần của kit (dựng MỘT lần, mọi UI khoác)
| Phần | Thời JS (đã có) | Thời PG |
|---|---|---|
| README gốc | SUA-RE-README.md — START HERE, 6 bước, luật nghiệm thu §3 |
GIỮ file; sửa: bước ② "KÊ-UI" → điền companion + chạy cổng; ③④ KHỬ-TRÙNG/KHỚP-SỔ bỏ khỏi việc Cowork (PG+Owner lo); ⑥ → SELECT đếm. Cập nhật luật §3 = Definition of Done trên. |
| Slot mỗi UI | 1 object surface trong ui-contracts.js |
companion <ui_file>.scan.json cạnh UI — CHỈ quan sát. |
| Công cụ quét | renderUIContract + verify-contracts.js |
cổng import + view đếm/khớp + report page (§5). |
Khoác kit cho một UI (tối giản)
- Copy
ui-scan.template.json→ điền quan sát tối thiểu → lưuui-preview/<ui_file>.scan.json. 2. Chạy cổng. Xong. Không bảng/DOT mới cho mỗi UI.
KHAI TỐI THIỂU
Bắt buộc: ui_id + mỗi item {raw_label, purpose(≥15)}. Chừng đó ĐỦ để PG đếm. location/type_guess/proposed_concept_key = gợi ý tùy.
UI_SCAN_JSON — TEMPLATE (ui-scan.template.json, chuẩn duy nhất)
{
"ui_id": "master-list-quy-trinh-v1",
"ui_name": "Master list quy trình",
"ui_file": "master-list-quy-trinh-v1.html",
"scan_reason": "new_ui | major_edit | label_field_change",
"items": [
{
"raw_label": "Người lập",
"purpose": "Người hoặc DOT đã tạo ra bản ghi/định nghĩa đang xem (created_by), hệ ghi tự động",
"location": "drawer.header.nguoi_lap",
"type_guess": "role",
"proposed_concept_key": "role.nguoi_lap"
}
]
}
Cowork CHỈ điền: raw_label, purpose, location, type_guess, proposed_concept_key. KHÔNG điền: item_key, dedupe_key, concept_id, match_status, scan_id.
Nơi lưu — companion cạnh UI, BÁO CÁO vào KB
- Companion vận hành: cạnh UI —
/opt/incomex/docs/mcp-writes/ui-preview/<ui_file>.scan.json. Lịch sử do PG giữ (is_current=false) → không cần thư mụcscans/. [CHỐT §11-5] - Báo cáo/mốc quyết định vào KB: seed freeze, kết quả G1b, log import, quyết định Owner → lưu KB (thư mục
sua-re/). Không copy mọi companion vào KB, nhưng mốc + báo cáo phải vào KB (bộ nhớ dài hạn).
scan_id = hash CANONICAL JSON [GAP 2]
Cổng tính scan_id = hash(canonical_json(companion)): sort keys · trim string · bỏ field volatile (nếu có) · chỉ hash field nội dung thật. KHÔNG hash raw text file (tránh scan giả do khoảng trắng/thứ tự key). Không đổi nội dung → cùng scan_id → import no-op; đổi → scan mới, lật is_current cũ.
Coverage report — nguồn so TỪ FILESYSTEM, scope rõ [GAP 5]
Hai phép rẻ (ls + SELECT), chỉ chạy trong root /opt/incomex/docs/mcp-writes/ui-preview/, loại trừ archive/, backup/, generated/, test* (Claude Code xác nhận dir + pattern — G-I):
- File
*.html(UI) KHÔNG có companion.scan.json→ chưa khoác kit (quên khai). - Companion chưa import PG current → chưa chạy cổng.
v0: coverage là AUDIT/OUTPUT của cổng hoặc pre-flight — CHƯA publish
/reports. Chỉ kiểm UI/companion trong root này — không cố phát hiện mọi UI toàn hệ (tránh lời hứa giả).
Artefact kit cần tạo/sửa ở G1 (nhỏ)
SỬA SUA-RE-README.md (bước ②/③④/⑥ + luật §3 = Definition of Done); TẠO ui-scan.template.json. Công cụ = cổng + view + report (§5).
3B. ĐI BỘ VẬN HÀNH — HỎI/ĐÁP (gộp câu GPT + câu tương tự)
| Vi-bước | Câu hỏi | Đáp đơn giản nhất |
|---|---|---|
| Sắp vẽ | Làm sao biết phải khai? | SUA-RE-README.md START HERE + Definition of Done. Không trông trí nhớ. |
| Phải thuộc 13 khái niệm? | Không. Khai mù: thô + đoán. | |
| Điền | Khai gì tối thiểu? | ui_id + mỗi item {raw_label, purpose≥15}. |
| KHÔNG điền gì? | item_key/dedupe_key/concept_id/match_status/scan_id. |
|
| Lưu | Companion ở đâu? | Cạnh UI. Báo cáo/mốc → KB. |
| Cổng | Ai kích hoạt? | 1 DOT quét docroot mọi *.scan.json → validate → import. |
scan_id/item_key? |
scan_id = hash canonical JSON; item_key = hash(ui_id,scan_id,location_or_index,raw_label). | |
| So | Cách / hiển số? | VIEW suy; matched=chính xác, pending=tạm (không show tổng như chắc 100%). |
| Owner | 3 action? | map_existing/create_new/keep_pending → owner_concept_id+decision_note. |
| Quên? | Nguồn UI kỳ vọng? | Filesystem, scope ui-preview root + exclude. |
| Sửa nút | Chạy lại? | Màu/layout/icon → khỏi; label/field/filter/drawer → quét toàn UI. |
| Xong chưa? | Definition of Done? | UI file + companion + validation PASS. Thiếu companion = chưa xong. |
| Nháp có vector? | KHÔNG — chui vùng no-vector qua policy (§7). |
Câu tương tự (Fable): 2 UI cùng raw_label nghĩa khác → per-UI dùng WHERE ui_id; cross-UI dùng concept_id(matched) → non-issue. Cowork đoán key trùng → view bắt (ILIKE→review). Catalog lớn lên? → chỉ qua Owner create_new; Cowork KHÔNG ghi catalog. Kit sửa ở đâu? → một chỗ (git).
4. VIEW / SELECT ĐẾM (5–7 câu, trên 13 concept — không pg_trgm)
- Đếm khái niệm phân biệt 1 UI (current):
count(DISTINCT dedupe_key) WHERE ui_id=:ui AND is_current. 2. Thô→sau khử trùng:count(*)vscount(DISTINCT dedupe_key). 3. Khớp/treo: view suymatch_status. 4. Hàng chờ chốt:WHERE match_status IN ('candidate','review') AND is_current+ purpose + near_concepts. 5. Dùng ở bao nhiêu nơi:GROUP BY concept_id → count(DISTINCT ui_id). 6. Lịch sử mô tả 1 khái niệm: mọipurposetheoscan_at(gồm bản cũ). 7. Matrix khái niệm×UI: view XUẤT ra, không lưu.
5. REPORT (G2) — bằng khuôn có sẵn + tách matched/pending
SỬA recon Rev 2: thực địa có HAI khuôn: (a) list sống từ collection (
view_sqlNULL, VDtbl_loai→entity_species,tbl_balo_*→balo_thuc_thePKstt); (b) report TÍNH TOÁN từview_sql→v_report_*snapshot (VDtbl_report_pg=PG Census). Mission cần = khuôn (b), y hệt PG Census.
v_report_sua_re → dot-report-publish → /reports/report-sua-re. Report PHẢI tách: matched_count (chính xác) vs pending_count (tạm, theo pending.<hash(raw_label+purpose)>, cần Owner chốt). KHÔNG một tổng như chắc 100%. Không Nuxt, không UI mới, không làm trước khi import xong. (Lưu ý: report page = collection registered → phải có vector policy false, §7.)
6. GIAI ĐOẠN (chuỗi giảm rủi ro — chứng minh INTAKE trước khi dựng bề mặt)
- G1a — nạp + đếm: freeze seed → nạp 13 concept + 30 usage (scan #0) → SELECT đếm thô. (Chứng minh schema+import+đếm; 30 dòng council soạn → chưa chứng minh B2.)
- G1b — CỬA THỬ BẮT BUỘC: Cowork xuất
UI_SCAN_JSONcho UI THẬT (theo template), đẩy qua cổng. PASS khi: (1) companion đúng template; (2) cổng KHÔNG sửa tay form; (3) mọipurpose≥15; (4) import thành scan mới (is_currentđúng); (5) SELECT trả: thô / sau dedupe / matched-review-candidate; (6) ≥1 item được gợi ý review/candidate HOẶC xác nhận matched. Thiếu bất kỳ → FAIL, chưa mở G2. [CHỐT §11-2] - G2 — report page:
v_report_sua_re→/reports/report-sua-re(tách matched/pending). - G3 — nếu cần: cổng quyết định chuyên dụng,
species_collection_map,balo_thuc_the, list chi tiết. - HOÃN tuyệt đối:
pg_trgm, Qdrant, fuzzy auto-match, tab UI thật.
7. FORK tạo bảng: Path A (mặc định — [CHỐT §11-4]) / Path B — + NO-VECTOR
Chọn đường theo NGUYÊN TẮC ĐƠN GIẢN: đơn giản KHÔNG phải "cố dùng tool có sẵn bằng mọi giá" — đơn giản là đường ít bước / ít rủi ro / ít patch tùy biến nhất.
- PATH A (mặc định — CHỈ chọn nếu pre-flight CHỨNG MINH đủ 4 điều): (1)
dot-collection-createtạo được 2 bảng/collection ĐÚNG SHAPE (JSONB/FK/unique/CHECK); (2) có rollback rõ (G-B); (3) gắn đượccollection_registry_vector_policy vector_eligible=false(G-C); (4) KHÔNG cần nhiều patch tùy biến. Đủ 4 → A (table + collection + registry). Lằn ranh cứng: G1 CHỈ tới "2 collection/bảng + seed import + SELECT đếm" — KHÔNG report-publish/list/balo/species-map. - PATH B (nếu A phải vá nhiều / không đủ 4 điều): DOT nhỏ tạo bảng PG-thuần, hoãn Directus+species sang G2. (PG-thuần chưa đăng ký collection → KHÔNG bị vector pipeline nhìn thấy → inherently no-vector ở G1.)
- Không ép A bằng mọi giá: nếu A thành bụi rậm (vá nhiều lớp) → B đơn giản hơn, chọn B.
🔒 NO-VECTOR — vùng cách ly nháp (khóa Owner + GPT)
CÂU CHỐT: Sửa-rẻ / nhập UI v0 là vùng nháp NO-VECTOR. SPE-NVS chỉ là NHÃN quản trị; enforcement BẮT BUỘC là
collection_registry_vector_policyvớivector_eligible=false+semantic_search_eligible=falsecho MỌI collectionsua_re_*_nhap. KHÔNG có policy này thì CHƯA được đăng ký collection.
- Quy tắc: mọi
sua_re_*_nhapmặc định no-vector. Chỉ khi Owner chốt thành hợp đồng thông tin / tri thức chính thức mới xét đưa sang vùng vector. - Vì sao bắt buộc: data ở đây = concept nháp, candidate/review chưa duyệt,
purposeCowork khai, scan cũ/mới, pending tạm,near_conceptschỉ gợi ý. Lọt embedding/semantic search = rác nghĩa (hỏi hệ sau này kéo ra khái niệm nháp / mô tả lệch / candidate chưa chốt). Đúng thứ D36 sinh ra để cấm. - KHÔNG vector (v0):
sua_re_khai_niem_nhap,sua_re_ui_khai_niem_nhap, companion.scan.json, seed artifact, candidate/review, scan history, report đếm sửa-rẻ. - Có thể xét vector SAU: hợp đồng thông tin đã chốt, tài liệu thiết kế chính thức, định nghĩa đã promote ra vùng chính thức.
- Theo Path: A (tạo collection ngay) → gắn policy false NGAY sau khi tạo, không chờ. B (PG-only, chưa collection) → chưa cần policy ở G1; khi nào đăng ký thành collection thì PHẢI gắn (cùng câu chốt).
- Yên tâm (Owner xác nhận): vùng né vector đã có sẵn & proven —
iu_staging_record/iu_staging_payloadđang nằm trong đó (vector_eligible=false), luật D36 verify PASS nhiều lần. Ta chỉ dùng đúng cửa (policy row), không đẻ cơ chế mới. Agent dùng yên tâm.
8. XÂY MỚI TỐI THIỂU vs DÙNG LẠI
Dùng lại tối đa: PG · Directus/report (khuôn (b)) · dot-collection-create · cổng dot-pg-atomic-apply · kit SUA-RE-README.md (giữ, sửa 1 bước) · collection_registry_vector_policy (cửa no-vector sẵn có) · Cowork prompt/template (không parser).
Mới tối thiểu: (1) ui-scan.template.json; (2) lớp kiểm intake bọc cổng (có thể không phải DOT mới); (3) view v_report_sua_re; (4) [G3] đường quyết định. Tối thiểu để VẬN HÀNH.
9. PRE-FLIGHT GATES (Claude Code trả lời — KÈM output thật, READ-ONLY; KHÔNG thiết kế lại)
Mỗi gate: PASS/HOLD/FAIL + bằng chứng thật. Đọc seed + infra từ VPS LIVE (Codex "seed missing" vì checkout local stale — seed sống ở path đầu doc; không đi tìm). Claude Code CHỈ soi + báo PASS/HOLD/FAIL, KHÔNG redesign.
- G-A
dot-collection-create: đọc source +--help/--dry-run. Tạo CHÍNH XÁC gì (table? collection? registry? meta? birth? species? permissions?). Kham JSONB? UNIQUE? FK? CHECK(purpose≥15)? CHỌN/HOÃN species? Soi 1 collection đã tạo. - G-B rollback: đường LÙI CHUẨN của tool. Không rõ → gate ĐỎ.
- G-C vector-exclusion: no-vector KHÔNG do loài — do
collection_registry_vector_policy(viewv_collection_vector_eligibilitymặc địnhCOALESCE(...,true)= opt-out). Xác nhận:dot-collection-createđể mặc định eligible hay tự set policy? insert exclusion (vector_eligible=false, semantic_search_eligible=false) cho 2 collection chạy được + idempotent + precheck (policy có unique trêncollection_registry_id?). SPE-NVS map = nhãn tùy, riêng. - G-D BẢNG ĐẶT CHỖ constraint: {
concept_keyunique,item_keyunique,concept_idFK,purpose≥15, enumconcept_kind, (nếu lưu)match_status} → DB / import-gate / verify-SELECT. Unique+UPSERT KHÔNG dời verify. - G-E seed purpose: ĐO THẬT 43 chuỗi, đếm ký tự sau trim, liệt kê <15.
- G-F
item_key: xác nhậnhash(ui_id, scan_id, location_or_index, raw_label)(location trống → index). Tính thử 30 khóa → 30 UNIQUE, 0 va chạm. - G-G FK resolution: resolve 27 matched về 13 concept; 3 dòng → null. concept_key nào không khớp?
- G-H map giá trị seed:
status 'chot'→'active';concept_kind6 loại;match_status3 giá trị. - G-I intake gate + kit: (1)
dot-pg-atomic-applyNHẬN file JSON companion + validate(purpose≥15) + UPSERT + lậtis_current— hay cần lớp/DOT mỏng? Nếu không nhận JSON trực tiếp → agent chuyển JSON→SQL rồi atomic apply được không? (2) cổng glob*.scan.jsondocroot được không (hay truyền path)? (3) scan_id canonical-JSON + item_key index-fallback cài được không? (4) coverage 2 phép + scope rootui-preview/+ excludearchive/backup/generated/testchạy bằngls+SELECT — xác nhận dir + pattern THẬT. - G-J dòng chảy data [MỚI Rev 6]: usage table giữ current+history một bảng (
is_current) có bị luật dòng chảy Đ22–Đ45 (Nguyên tử/Log/Action không trộn) cấm không? Mặc định GIỮ 1 bảng (tiền lệ IUiu_staging_record); CHỈ tách history nếu trích được điều luật cấm cụ thể — nêu rõ số điều. Không tự tách. - AUDIT PHỨC TẠP HÓA (ngang hàng audit rủi ro): chỗ nào nặng hơn cần? bỏ cột/guard/bước nào mà KHÔNG mất mission? NGƯỢC LẠI: chỗ nào CẮT quá tay (mất "sửa nhiều lần"/cọc seed-purpose-scan)?
- AUDIT RỦI RO: Directus track JSONB+FK? SharedDirectusTable render? khuôn dùng
primary_keyhay épid?v_report_pgtự đếm thêm 2 bảng → tác dụng phụ? Va chạm tên (collection/table_id/page_url)? Permissions collection mới? Artefact nào CHỈ có trên VPS? - Khuyến nghị Path A/B DỨT KHOÁT dựa G-A/G-B/G-C (đủ 4 điều §7 → A; thiếu → B).
- Đầu ra: verdict từng gate + bảng đặt chỗ (G-D) + "PHỨC TẠP HÓA THỪA"/"CẮT QUÁ TAY" + Path A/B + "Rev 6 PHẢI sửa/bổ sung gì". Upload KB:
knowledge/dev/laws-new/kestra/sua-re/nhap-ui/claude-code-infra-eval-2026-07-06.md.
10. v0 TUYỆT ĐỐI KHÔNG LÀM (rào quái vật)
- KHÔNG parser/OCR/quét DOM. KHÔNG DOT "đi đọc/đếm lại UI" (chính con quái vật).
- KHÔNG fuzzy auto-match (chỉ exact/alias→matched). KHÔNG
pg_trgm/Qdrant. - KHÔNG decision-DOT (→G3). KHÔNG report đẹp. KHÔNG species-map/balo (→G2/G3). KHÔNG tab UI thật.
- KHÔNG 3 DOT custom lớn. KHÔNG rollback DOT riêng nếu tool có đường lùi chuẩn. KHÔNG bảng scan riêng. KHÔNG bảng history riêng (trừ khi luật cấm current+history — G-J). KHÔNG 4 index. KHÔNG species mới.
- KHÔNG đẻ kit mới (giữ
SUA-RE-README.md). KHÔNG thư mụcscans/(companion cạnh-UI + PG đủ). - KHÔNG để đồ nháp vào vector (bắt buộc policy false nếu có collection — §7).
- Cowork v0 khai-mù. KHÔNG rebuild reports/Nuxt từ local stale.
11. QUYẾT ĐỊNH — ĐÃ CHỐT (Owner 2026-07-06, theo đề xuất council)
| # | Quyết định | Chốt |
|---|---|---|
| 1 | Cowork chỉ khai QUAN SÁT THÔ (không tự gán dedupe/match) | ✔ YES |
| 2 | G1b (Cowork xuất FORM thật) là CỬA BẮT BUỘC trước khi dựng bề mặt | ✔ YES |
| 3 | match_status SUY trong view |
✔ YES (fallback lưu enum nếu tool cản) |
| 4 | Path A mặc định (dot-collection-create) — CHỈ nếu đủ 4 điều §7 | ✔ YES (sau pre-flight PASS; thiếu → Path B) |
| 5 | Companion <ui_file>.scan.json cạnh UI |
✔ YES |
| 6 | scan_id = hash canonical JSON companion |
✔ YES |
| 7 | Coverage v0 từ filesystem (ui-preview root + exclude) = audit/output | ✔ YES |
Khóa vận hành (GPT, Owner chuyển tiếp): Definition of Done (UI thiếu companion = chưa xong) · scan_id canonical JSON · item_key location-or-index · pending dedupe = hash(raw_label+purpose) · coverage scope+exclude, chưa /reports · companion cạnh-UI + báo cáo vào KB · Owner decision 3 action · NO-VECTOR bằng collection_registry_vector_policy vector_eligible=false (SPE-NVS = nhãn), KHÔNG có policy thì chưa đăng ký collection · KHÔNG tách history trừ khi luật cấm (G-J) · Path A chỉ chọn nếu ít-patch.
Đã chốt trước: id PK+business key · không loài mới · không Nuxt G1 · không workflow cho 2 bảng · DB directus · giữ match_policy · giữ scan_id/is_current · purpose/dedupe bắt buộc · near_concepts jsonb · decision_note · giữ kit.
12. RỦI RO + ROLLBACK
- Cowork quên FORM → Definition of Done (luật) + coverage (dò). - 2 SSOT (JS+PG): migrate xong JS đóng băng. - Auto-match mạnh: exact/alias/ILIKE; fuzzy chỉ gợi ý. - dedupe pending sập: hash(raw_label+purpose), overcount an toàn hơn undercount; report tách. - Draft lọt vector = rác nghĩa: enforce
collection_registry_vector_policy vector_eligible=false(§7), KHÔNG chỉ nhãn SPE-NVS. - Draft hiểu nhầm chính thức:_nhap,status=draft. - Trùng loài/collection/report: idempotent precheck+readback. - Rollback: đường lùi CHUẨN của tool (G-B).
13. CHANGELOG + COUNCIL TRACE
Rev 5 → Rev 6 (rà soát TƯƠNG THÍCH hệ thống + GPT simplify-locks + đồng bộ nhãn):
- [Đồng bộ nhãn] toàn file thống nhất Rev 6 / HOLD_PRE_FLIGHT (title, metadata, output §9); bỏ
[Rev 5]rải rác trong thân — lịch sử version chỉ giữ ở changelog. - [NO-VECTOR — câu chốt Owner+GPT] §7 ghi rõ:
sua_re_*_nhaplà vùng nháp no-vector; enforcement =collection_registry_vector_policy vector_eligible=false + semantic_search_eligible=false; KHÔNG có policy thì chưa đăng ký collection; SPE-NVS = nhãn. + danh sách no-vector / có-thể-vector-sau. Vùng né vector đã proven (iu_staging_*, D36 PASS) — agent dùng yên tâm. - [Path A conditional] A chỉ chọn nếu pre-flight chứng minh đủ 4 điều (shape/rollback/vector-policy/ít-patch); vá nhiều → Path B. "Đơn giản = ít bước/rủi ro/patch nhất, không cố dùng tool bằng mọi giá."
- [Không tách history] mặc định 1 bảng usage (scan_id+is_current); chỉ tách nếu Claude Code trích luật cấm cụ thể → thêm gate G-J.
- [Coverage] v0 = audit/output, chưa publish
/reports. - [Claude Code] nhấn read-only + KHÔNG redesign; G-I thêm nhánh JSON→SQL fallback.
- [BẮT BUỘC từ compat-review] Sửa cơ chế no-vector §7: (đã áp) SPE-NVS = nhãn, no-vector thật = policy row. Không xung đột kiến trúc:
meta_catalogKHÁC TẦNG (kho vs nhãn-UI); tênsua_re*/report-sua-resạch (0 va chạm, query thật).concept_kind≠ species.
Rev 4 → Rev 5 (khóa 7 lỗ vận hành GPT — không sửa kiến trúc): thêm Definition of Done; scan_id canonical JSON; item_key location-or-index; pending dedupe hash(raw_label+purpose); coverage scope+exclude; companion cạnh-UI + báo cáo KB; Owner 3 action; §11 chốt; gate G-I.
Rev 3→4 (tóm): §3A Bộ Kit (kit ĐÃ CÓ ở JS), §3B walk-through, decision_note, PASS G1b, tách matched/pending, coverage-filesystem.
Rev 2→3 (tóm): PK id bigserial+business key; loai→concept_kind; near_concepts jsonb; match_status suy view; recon reports (2 khuôn); bỏ 3-DOT/rollback-DOT/scan-invariant/4-index; thêm §3 vòng vận hành + G1b. (Rev cũ ở lịch sử revision.)
GIỮ (cọc sống còn): scan_id/scan_at/is_current · purpose≥15 gate cứng · dedupe_key=duplicate_group · seed freeze artifact có lý lịch+hash · match_policy · 100% DOT · kit sống trong file · mọi CHỐT vào KB · đồ nháp no-vector.
Council trace: Owner = bảo vệ đơn giản, "đừng đẻ quái vật", bắt nhìn vận hành từng bước + rà tương thích + mọi chốt vào KB; xác nhận vùng né vector proven. GPT = giữ scan/seed/purpose + 7+7 GAP vận hành (Definition of Done) + simplify-locks (Path A conditional, no-vector policy, không tách history). Fable = tool-verify (seed sống bác "seed missing"; PG Census; SUA-RE-README.md phát hiện kit đã có; rà tương thích: no-vector = policy chứ không phải loài, meta_catalog khác tầng, tên sạch). Codex = 3 blocker (PK/seed/DOT) từ recon.
GUARD ĐƠN GIẢN (đọc cuối, nhớ đầu)
v0 = 2 bảng + kit đóng sẵn (README + companion) + cổng ghi sẵn có + vài SELECT/1 view + đúc report bằng khuôn cũ. HẾT. Vượt ra → DỪNG, hỏi Owner. Phức tạp = thất bại. Không có DOT nào đi đọc lại UI — Cowork điền phiếu. Kit đã có sẵn — chỉ khoác vào. UI thiếu companion hợp lệ = UI chưa xong. Đồ nháp phải chui vùng no-vector bằng policy thật.