S175 Fix Execution
S175 Fix Execution — P0 Backup & Dedupe Plan
Date: 2026-04-09
Agent: Codex
Status: P0 COMPLETE — P1/P2/P3/P4 NOT STARTED
Stop gate: Chờ Desktop duyệt plan dedupe trước khi chạy transaction đầu tiên.
Bước 0 — Checkpoint đã đọc
- Skill:
.claude/skills/incomex-rules.md - KB:
search_knowledge("operating rules SSOT") - KB:
search_knowledge("hiến pháp v4.0 constitution") - KB:
search_knowledge("S175 duplicate rows schema hardening directus agent-data") - Reports tham chiếu:
knowledge/current-state/reports/s175-why-round2-codex.md,knowledge/current-state/reports/s175-why-round2-gemini.md
3 câu Tuyên ngôn cho mission này
-
Vĩnh viễn?
Có, nếu và chỉ nếu fix đủ 3 lớp: dọn duplicate current rows hiện hữu, chặn schema ở DB, và đổi writer sang atomic path. P0 này mới hoàn tất lớp chuẩn bị và chặn nhầm trước khi đụng data. -
Nhầm được không?
P0 dùng snapshot SQL + bảng KEEP/ARCHIVE explicit theo từngid. Chưa có duyệt của Desktop thì không chạyUPDATE, nên hiện tại chưa có rủi ro half-state. -
100% tự động?
Sau khi được duyệt, P1/P2/P3 phải chạy bằng SQL/script có verify. Không có bước “xem rồi chỉnh tay từng row” trong production.
Executive Summary
P0 đã hoàn tất backup và inventory. Live DB ngày 2026-04-09 không còn đúng giả định 9 law docs / 18 rows trong prompt nữa. Hiện tại có:
- 13 duplicate
source_idgroups trongagentdata:knowledge/dev/laws/% - 26 current law rows liên quan P1 nếu giữ scope theo Agent Data law sync
- 3 duplicate
READMEgroups ngoài scope luật, tổng 6 current rows, sẽ chặn một globalUNIQUE(file_path)nếu không xử lý cùng phiên - 15 current rows có
source_id IS NULL - 0 current rows có
file_path IS NULL
Kết luận P0 của tôi:
- KEEP candidate cho 13 law groups là row có slug canonical
dev-laws-* - ARCHIVE candidate là row legacy
dev-architecture-*hoặc slug cũ tương đương - Với scope hẹp đúng prompt, P2 nên ưu tiên partial unique trên
source_idcho current rows non-null, không phảifile_path, vìfile_pathsẽ kéo thêm 3 README groups ngoài scope vào cùng migration
Tôi chưa chạy P1. Chỉ mới snapshot + lập plan + dừng đúng gate phê duyệt.
P0 Snapshot
Snapshot file: s175-knowledge_documents-pre-fix-20260409.sql
Size: 4,242,295 bytes
Timestamp local: Apr 9 13:42:42 2026
Evidence:
Command:
ssh root@38.242.240.89 "docker exec postgres pg_dump -U directus -d directus -t public.knowledge_documents --column-inserts --inserts" > reports/s175-knowledge_documents-pre-fix-20260409.sql
stat:
/Users/nmhuyen/Documents/Manual Deploy/web-test/reports/s175-knowledge_documents-pre-fix-20260409.sql 4242295 bytes Apr 9 13:42:42 2026
Evidence chính dùng để lập plan
1. Duplicate law groups thực tế
Command:
ssh root@38.242.240.89 "docker exec postgres psql -U directus -d directus -Atc \"SELECT source_id, file_path, count(*) FILTER (WHERE is_current_version) AS current_count, count(*) AS total_count FROM public.knowledge_documents WHERE source_id LIKE 'agentdata:knowledge/dev/laws/%' GROUP BY 1,2 HAVING count(*) FILTER (WHERE is_current_version) > 1 ORDER BY file_path;\""
Output:
agentdata:knowledge/dev/laws/dieu26-pivot-law.md|knowledge/dev/laws/dieu26-pivot-law.md|2|2
agentdata:knowledge/dev/laws/dieu28-display-technology-law.md|knowledge/dev/laws/dieu28-display-technology-law.md|2|2
agentdata:knowledge/dev/laws/dieu29-classification-law.md|knowledge/dev/laws/dieu29-classification-law.md|2|2
agentdata:knowledge/dev/laws/dieu30-regression-protection-law.md|knowledge/dev/laws/dieu30-regression-protection-law.md|2|2
agentdata:knowledge/dev/laws/dieu31-system-integrity-law.md|knowledge/dev/laws/dieu31-system-integrity-law.md|2|2
agentdata:knowledge/dev/laws/dieu32-approval-law.md|knowledge/dev/laws/dieu32-approval-law.md|2|2
agentdata:knowledge/dev/laws/dieu33-postgresql-law.md|knowledge/dev/laws/dieu33-postgresql-law.md|2|2
agentdata:knowledge/dev/laws/dieu34-workflow-law.md|knowledge/dev/laws/dieu34-workflow-law.md|2|2
agentdata:knowledge/dev/laws/dieu35-dot-governance-law.md|knowledge/dev/laws/dieu35-dot-governance-law.md|2|2
agentdata:knowledge/dev/laws/dieu37-governance-organization-law.md|knowledge/dev/laws/dieu37-governance-organization-law.md|2|2
agentdata:knowledge/dev/laws/dieu38-normative-document-law.md|knowledge/dev/laws/dieu38-normative-document-law.md|2|2
agentdata:knowledge/dev/laws/label-law.md|knowledge/dev/laws/label-law.md|2|2
agentdata:knowledge/dev/laws/nd-36-01-semantic-relationship-infrastructure.md|knowledge/dev/laws/nd-36-01-semantic-relationship-infrastructure.md|2|2
2. Nullability để chọn khóa P2
Command:
ssh root@38.242.240.89 "docker exec postgres psql -U directus -d directus -Atc \"SELECT column_name, is_nullable FROM information_schema.columns WHERE table_schema='public' AND table_name='knowledge_documents' AND column_name IN ('source_id','file_path','is_current_version');\""
Output:
is_current_version|NO
file_path|YES
source_id|YES
Command:
ssh root@38.242.240.89 "docker exec postgres psql -U directus -d directus -Atc \"SELECT count(*) FILTER (WHERE is_current_version AND source_id IS NULL), count(*) FILTER (WHERE is_current_version AND file_path IS NULL), count(*) FILTER (WHERE is_current_version) FROM public.knowledge_documents;\""
Output:
15|0|622
3. File-path duplicate blocker ngoài scope luật
Command:
ssh root@38.242.240.89 "docker exec postgres psql -U directus -d directus -Atc \"SELECT file_path, count(*) FROM public.knowledge_documents WHERE is_current_version AND file_path IS NOT NULL GROUP BY 1 HAVING count(*) > 1 ORDER BY count(*) DESC, file_path LIMIT 30;\""
Output excerpt:
knowledge/current-state/README.md|2
knowledge/current-tasks/README.md|2
knowledge/dev/laws/dieu26-pivot-law.md|2
...
knowledge/dev/laws/nd-36-01-semantic-relationship-infrastructure.md|2
knowledge/other/README.md|2
Chi tiết 3 README groups:
298||knowledge/current-state/README.md|current-state|Trạng thái Hiện tại|1|t|2026-03-03 00:08:54
345|agentdata:knowledge/current-state/README.md|knowledge/current-state/README.md|current-state-readme|Current State|1|t|
299||knowledge/current-tasks/README.md||Việc đang làm|1|t|2026-03-03 00:08:55
346|agentdata:knowledge/current-tasks/README.md|knowledge/current-tasks/README.md|current-tasks-readme|Việc đang làm|1|t|
301||knowledge/other/README.md|other|Tài liệu Khác|1|t|2026-03-03 00:08:58
347|agentdata:knowledge/other/README.md|knowledge/other/README.md|other-readme|Other|1|t|
4. Canonical slug rule của writer hiện tại
agent_data/directus_sync.py:60-71:
def _make_slug(doc_id: str) -> str:
slug = doc_id
for prefix in ("docs/", "knowledge/"):
if slug.startswith(prefix):
slug = slug[len(prefix):]
break
slug = slug.removesuffix(".md")
slug = slug.lower().replace("/", "-").replace(" ", "-").replace("_", "-")
slug = slug.strip("-")
return slug
Với path hiện tại knowledge/dev/laws/dieu31-system-integrity-law.md, slug canonical tạo ra là dev-laws-dieu31-system-integrity-law, không phải dev-architecture-system-integrity-law.
5. Agent Data KB hiện tại bám slug dev-laws-*
MCP batch-read cho 13 path luật scope S175 cho thấy metadata hiện tại đều ở namespace knowledge/dev/laws/...; sampled results:
knowledge/dev/laws/dieu26-pivot-law.md→ revision1, titleĐiều 26: LUẬT PIVOT — v4.0, tags cólaw,dieu-26knowledge/dev/laws/dieu31-system-integrity-law.md→ revision1, tags códieu-31knowledge/dev/laws/dieu38-normative-document-law.md→ revision1, tags códieu-38knowledge/dev/laws/label-law.md→ revision1, tagslaw,dieu-24knowledge/dev/laws/nd-36-01-semantic-relationship-infrastructure.md→ revision5, tagsenacted-p1,s175
Điểm quan trọng:
- 12/13 docs sampled từ KB hiện tại đang revision
1, nên rowdev-laws-*revision1không mâu thuẫn với Agent Data hiện tại - NĐ-36-01 là ngoại lệ: KB revision
5, còn current Directus tốt hơn trong 2 row làid=1091revision4;id=1074revision2còn xa hơn
P0 Dedupe Plan — KEEP vs ARCHIVE
Tiêu chí KEEP
file_pathđúng path hiện tại trong Agent Data KBslugđúng canonical rule từ_make_slug(current_path)=>dev-laws-*- Với cùng path, row có canonical slug được KEEP ngay cả khi row legacy có
version_numbercao hơn, vì row legacy không còn có thể được current writer sinh ra từ path hiện tại nữa - Riêng NĐ-36-01: KEEP row canonical và mới hơn (
id=1091), dù nó vẫn stale so với Agent Data rev5; stale này sẽ được P3 sửa sau khi writer atomic vào chỗ
Tiêu chí ARCHIVE
sluglegacydev-architecture-*hoặc slug cũ không còn derivable từknowledge/dev/laws/...- Row là “ghost current” của lineage cũ nhưng vẫn đang
is_current_version=true - P1 chỉ đổi
is_current_version=false, không xoá
Bảng plan
| Source ID | KEEP | ARCHIVE | Lý do giữ |
|---|---|---|---|
agentdata:knowledge/dev/laws/dieu26-pivot-law.md |
1080 |
854 |
1080.slug=dev-laws-dieu26-pivot-law đúng canonical path hiện tại |
agentdata:knowledge/dev/laws/dieu28-display-technology-law.md |
1081 |
986 |
1081 đúng canonical dev-laws-*; metadata khớp KB hiện tại |
agentdata:knowledge/dev/laws/dieu29-classification-law.md |
1082 |
748 |
1082 đúng canonical dev-laws-*; row 748 là slug cũ dev-architecture-* |
agentdata:knowledge/dev/laws/dieu30-regression-protection-law.md |
1083 |
752 |
1083 đúng canonical dev-laws-* |
agentdata:knowledge/dev/laws/dieu31-system-integrity-law.md |
1084 |
763 |
1084 đúng canonical dev-laws-*; KB current revision là 1 |
agentdata:knowledge/dev/laws/dieu32-approval-law.md |
1085 |
874 |
1085 đúng canonical dev-laws-* |
agentdata:knowledge/dev/laws/dieu33-postgresql-law.md |
1086 |
875 |
1086 đúng canonical dev-laws-*; KB current revision là 1 |
agentdata:knowledge/dev/laws/dieu34-workflow-law.md |
1087 |
880 |
1087 đúng canonical dev-laws-* |
agentdata:knowledge/dev/laws/dieu35-dot-governance-law.md |
1088 |
960 |
1088 đúng canonical dev-laws-*; row 960 giữ lineage cũ |
agentdata:knowledge/dev/laws/dieu37-governance-organization-law.md |
1089 |
993 |
1089 đúng canonical dev-laws-* |
agentdata:knowledge/dev/laws/dieu38-normative-document-law.md |
1090 |
1004 |
1090 đúng canonical dev-laws-*; KB current revision là 1 |
agentdata:knowledge/dev/laws/label-law.md |
1079 |
586 |
1079 đúng canonical dev-laws-label-law; tags mới có law,dieu-24 |
agentdata:knowledge/dev/laws/nd-36-01-semantic-relationship-infrastructure.md |
1091 |
1074 |
1091 đúng canonical dev-laws-*, revision/date mới hơn 1074; 1074 là row cũ partial title |
P1 Execution Proposal (CHƯA CHẠY)
Nếu Desktop duyệt đúng plan trên, P1 sẽ chạy một transaction duy nhất:
BEGINUPDATE public.knowledge_documents SET is_current_version=false WHERE id IN (854,986,748,752,763,874,875,880,960,993,1004,586,1074);- Verify trong cùng session:
SELECT source_id, COUNT(*) FROM public.knowledge_documents WHERE is_current_version=true AND source_id IN (...) GROUP BY 1 HAVING COUNT(*)>1;
COMMIT
Rollback nếu lệch:
ROLLBACKnếu transaction chưa commit- Nếu commit lỗi verify sau đó, dùng snapshot s175-knowledge_documents-pre-fix-20260409.sql để restore table về pre-P1 state
P2 Recommendation (CHƯA IMPLEMENT)
Recommendation
Cho scope hẹp của S175 hiện tại, tôi đề xuất:
CREATE UNIQUE INDEX CONCURRENTLY idx_kd_current_source_id_unique
ON public.knowledge_documents (source_id)
WHERE is_current_version = true AND source_id IS NOT NULL;
Vì sao chưa chọn file_path
file_pathmạnh hơn trên lý thuyết vì hiện tạicurrent file_path NULL = 0- Nhưng live DB còn 3 README duplicate groups ngoài scope prompt
- Nếu dùng
UNIQUE(file_path) WHERE is_current_version=true, migration sẽ bị block cho đến khi dọn luôn 6 README rows này - Prompt hiện khóa scope vào schema constraint + writer atomic + dọn duplicate rows đang bàn cho agent-data law sync, không yêu cầu mở rộng sang README cleanup
Ý nghĩa
source_idpartial unique chặn đúng lớp bug mà S175 đang gặp: Agent Data sync cho cùng logical document tạo >1 current rows- README/null-
source_iddrift phải được ghi rõ là residual khác, không được nuốt
P3 Writer Atomic Proposal (CHƯA IMPLEMENT)
Tôi chưa sửa code, nhưng P0 xác nhận đúng chỗ phải thay:
agent_data/directus_sync.py:124-141hiện lookupsource_idvớilimit=1agent_data/directus_sync.py:253-286hiện chỉ PATCH 1 row hoặc fallback createagent_data/directus_sync.py:171-193luôn build payloadis_current_version=True
P3 trong PR sau khi được duyệt phải làm:
- Resolve canonical current row theo
source_id - Trong một transaction:
- demote current rows cũ của
source_id - upsert canonical row
- demote current rows cũ của
- Fail giữa chừng => rollback sạch
Files Evidence đã tạo trong P0
- s175-knowledge_documents-pre-fix-20260409.sql
- s175-law-duplicate-current-rows-20260409.tsv
- s175-readme-duplicate-current-rows-20260409.tsv
- s175-fix-execution-progress.md
Stop Gate
P0 xong. Tôi không chạy P1 cho đến khi Desktop duyệt một trong hai hướng:
- Hướng hẹp đúng prompt: xử lý 13 law groups/26 rows + partial unique theo
source_id - Hướng rộng hơn: xử lý luôn 3 README groups để có thể dùng
file_pathpartial unique trong cùng PR
Hiện tại không có half-state nào trên VPS.