KB-21EE

S175 Fix Execution v2

13 min read Revision 1
reportscodexhistorical-sync

S175 Fix Execution v2

Date: 2026-04-09
Agent: Codex
Status: P0 COMPLETE, live state diverged from resume prompt
Stop gate: Chờ Desktop xác nhận bỏ qua P1/P2 và chuyển thẳng P3, vì live VPS đã có dedupe law + partial unique index trước khi tôi chạm vào production.

Step 0. Files and KB read

  • .claude/skills/incomex-rules.md
  • search_knowledge("operating rules SSOT")
  • search_knowledge("hiến pháp v4.0 constitution")
  • search_knowledge("vps architecture SSOT")
  • search_knowledge("anti-duplicate Điều 14 duplicate current rows source_id is_current_version")
  • knowledge/current-state/reports/s175-fix-execution.md
  • knowledge/current-state/reports/s175-why-round2-codex.md

3 câu Tuyên ngôn

  1. Vĩnh viễn?
    Với live state ngày 2026-04-09, lớp DB đã chặn đúng bug bằng idx_kd_current_source_id_unique, nhưng writer runtime vẫn chưa atomic. Vì vậy fix vĩnh viễn hiện mới xong 2/3 lớp.

  2. Nhầm được không?
    Tôi đã rollback local file sửa nhầm ở MacBook trước khi vào VPS. Trên VPS tôi chỉ làm P0 read/probe + snapshot, chưa chạy UPDATE, INSERT, CREATE INDEX, hay restart service nào trong phiên này.

  3. 100% tự động?
    Chưa. Khi writer runtime còn dùng _find_by_source_id(limit=1) và chỉ PATCH một row qua Directus API, hệ thống vẫn dựa vào DB constraint để chặn lỗi chứ chưa tự đồng bộ lineage đúng cách trong cùng transaction.

Bước 1. Rollback local nhầm đích

Tracked file bị sửa nhầm ở repo local agent-data-test đã được restore, không đụng các path untracked.

Command:
git -C '/Users/nmhuyen/Documents/Manual Deploy/agent-data-test' status --short

Output before restore:
 M agent_data/directus_sync.py
?? .claude/
?? gae-stop/
?? scripts/classify-legacy-issues.py
Command:
git -C '/Users/nmhuyen/Documents/Manual Deploy/agent-data-test' restore --worktree --staged agent_data/directus_sync.py
Command:
git -C '/Users/nmhuyen/Documents/Manual Deploy/agent-data-test' status --short

Output after restore:
?? .claude/
?? gae-stop/
?? scripts/classify-legacy-issues.py

Bước 2. Xác định đúng runtime trên VPS

2.1 Host, containers, DB, schema

Command:
ssh root@38.242.240.89 hostname

Output:
vmi3080463
Command:
ssh root@38.242.240.89 "docker ps --format '{{.Names}}\t{{.Image}}\t{{.Ports}}'"

Output excerpt:
incomex-agent-data    agent-data-local:latest    8080/tcp
postgres              postgres:16                127.0.0.1:5432->5432/tcp
incomex-directus      directus/directus:11.5     8055/tcp
Command:
ssh root@38.242.240.89 "docker exec postgres psql -U directus -d directus -Atc \"SELECT current_database(), current_schema();\""

Output:
directus|public
Command:
ssh root@38.242.240.89 "docker exec postgres psql -U directus -d directus -Atc \"SELECT table_schema, table_name FROM information_schema.tables WHERE table_name='knowledge_documents' ORDER BY table_schema;\""

Output:
public|knowledge_documents

2.2 Runtime path thật của agent-data

incomex-agent-data không bind-mount source code; chỉ mount credentials.

Command:
ssh root@38.242.240.89 "docker inspect incomex-agent-data --format '{{json .Mounts}}'"

Output:
[{"Type":"bind","Source":"/opt/incomex/docker/credentials/google-credentials.json","Destination":"/app/credentials/google-credentials.json","Mode":"ro","RW":false,"Propagation":"rprivate"}]

Source repo tìm thấy trên VPS:

Command:
ssh root@38.242.240.89 "find /opt/incomex -maxdepth 4 -path '*/agent_data/directus_sync.py' -o -path '*/docker-compose*.yml' -o -path '*/compose*.yml'"

Output:
/opt/incomex/docker/nuxt-repo/docker-compose.local.yml
/opt/incomex/docker/nuxt-repo/docker-compose.override.yml
/opt/incomex/docker/docker-compose.yml
/opt/incomex/docker/agent-data-repo/agent_data/directus_sync.py

Runtime file trong container:

Command:
ssh root@38.242.240.89 "docker exec incomex-agent-data sh -lc 'ls -l /app/agent_data/directus_sync.py'"

Output:
-rw-r--r-- 1 1001 1001 12332 Apr  6 14:49 /app/agent_data/directus_sync.py

Checksum source repo và runtime file khớp nhau:

Command:
ssh root@38.242.240.89 "sha256sum /opt/incomex/docker/agent-data-repo/agent_data/directus_sync.py && docker exec incomex-agent-data sha256sum /app/agent_data/directus_sync.py"

Output:
ee96135ca2415b87c4b47e6abe6c1546e47057956a6b7edf6e3c717fe56979f0  /opt/incomex/docker/agent-data-repo/agent_data/directus_sync.py
ee96135ca2415b87c4b47e6abe6c1546e47057956a6b7edf6e3c717fe56979f0  /app/agent_data/directus_sync.py

Docker compose hiện dùng image build sẵn:

Command:
ssh root@38.242.240.89 "sed -n '1,220p' /opt/incomex/docker/docker-compose.yml"

Relevant excerpt:
  agent-data:
    image: agent-data-local:latest
    container_name: incomex-agent-data

Bước 3. Snapshot mới trên chính VPS

Command:
ssh root@38.242.240.89 "mkdir -p /root/backup"
ssh root@38.242.240.89 "date -u +%Y%m%dT%H%M%SZ"

Output:
20260409T072635Z
Command:
ssh root@38.242.240.89 "docker exec postgres pg_dump -U directus -d directus -t public.knowledge_documents --column-inserts --inserts > /root/backup/s175-knowledge_documents-20260409T072635Z.sql"
Command:
ssh root@38.242.240.89 "stat -c '%n|%s bytes|%y' /root/backup/s175-knowledge_documents-20260409T072635Z.sql && sha256sum /root/backup/s175-knowledge_documents-20260409T072635Z.sql"

Output:
/root/backup/s175-knowledge_documents-20260409T072635Z.sql|4258637 bytes|2026-04-09 09:26:49.568041976 +0200
8c75e945887821e64dbe607b6a3f21b2451723fdb914cfc0ca1edc54dd567889  /root/backup/s175-knowledge_documents-20260409T072635Z.sql

Bước 4. Live inventory ngày 2026-04-09

4.1 Tổng số row hiện tại

Command:
ssh root@38.242.240.89 "docker exec postgres psql -U directus -d directus -Atc \"SELECT count(*) AS total_rows, count(*) FILTER (WHERE is_current_version) AS current_rows, count(*) FILTER (WHERE is_current_version AND source_id IS NULL) AS current_source_id_null, count(*) FILTER (WHERE is_current_version AND file_path IS NULL) AS current_file_path_null FROM public.knowledge_documents;\""

Output:
623|610|15|0

4.2 Law duplicate groups

Live state không còn 13 law duplicate groups như prompt resume nữa.

Command:
ssh root@38.242.240.89 "docker exec postgres psql -U directus -d directus -Atc \"SELECT count(*) FROM (SELECT source_id FROM public.knowledge_documents WHERE is_current_version AND source_id LIKE 'agentdata:knowledge/dev/laws/%' GROUP BY source_id HAVING count(*) > 1) s;\""

Output:
0

Law scope hiện có 36 current rows và 49 total rows:

Command:
ssh root@38.242.240.89 "docker exec postgres psql -U directus -d directus -Atc \"SELECT count(*) FILTER (WHERE is_current_version), count(*) FROM public.knowledge_documents WHERE source_id LIKE 'agentdata:knowledge/dev/laws/%';\""

Output:
36|49

Evidence cho thấy 13 cặp law trong P0 cũ đã bị demote đúng kiểu KEEP dev-laws-*, ARCHIVE dev-architecture-* trước khi tôi vào phiên này:

Command:
ssh root@38.242.240.89 "docker exec postgres psql -U directus -d directus -Atc \"SELECT source_id || '|' || id || '|' || slug || '|' || version_number || '|' || is_current_version FROM public.knowledge_documents WHERE source_id LIKE 'agentdata:knowledge/dev/laws/%' ORDER BY source_id, is_current_version DESC, id;\""

Output excerpt:
agentdata:knowledge/dev/laws/dieu26-pivot-law.md|1080|dev-laws-dieu26-pivot-law|1|true
agentdata:knowledge/dev/laws/dieu26-pivot-law.md|854|dev-architecture-dieu26-new-registries-counting-law-draft|10|false
agentdata:knowledge/dev/laws/dieu31-system-integrity-law.md|1084|dev-laws-dieu31-system-integrity-law|1|true
agentdata:knowledge/dev/laws/dieu31-system-integrity-law.md|763|dev-architecture-system-integrity-law|4|false
agentdata:knowledge/dev/laws/nd-36-01-semantic-relationship-infrastructure.md|1091|dev-laws-nd-36-01-semantic-relationship-infrastructure|4|true
agentdata:knowledge/dev/laws/nd-36-01-semantic-relationship-infrastructure.md|1074|dev-architecture-nd-36-01-semantic-relationship-infrastructure-draft|2|false

4.3 README duplicate groups

3 README duplicate groups vẫn còn nguyên, đúng scope hẹp:

Command:
ssh root@38.242.240.89 "docker exec postgres psql -U directus -d directus -Atc \"SELECT count(*) FROM (SELECT file_path FROM public.knowledge_documents WHERE is_current_version AND file_path LIKE 'knowledge/%/README.md' GROUP BY file_path HAVING count(*) > 1) s;\""

Output:
3
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 file_path HAVING count(*) > 1 ORDER BY count(*) DESC, file_path;\""

Output:
knowledge/current-state/README.md|2
knowledge/current-tasks/README.md|2
knowledge/other/README.md|2
Command:
ssh root@38.242.240.89 "docker exec postgres psql -U directus -d directus -Atc \"SELECT id || '|' || coalesce(source_id,'') || '|' || file_path || '|' || coalesce(slug,'') || '|' || coalesce(title,'') || '|' || version_number || '|' || is_current_version FROM public.knowledge_documents WHERE is_current_version AND file_path IN ('knowledge/current-state/README.md','knowledge/current-tasks/README.md','knowledge/other/README.md') ORDER BY file_path, id;\""

Output:
298||knowledge/current-state/README.md|current-state|Trạng thái Hiện tại|1|true
345|agentdata:knowledge/current-state/README.md|knowledge/current-state/README.md|current-state-readme|Current State|1|true
299||knowledge/current-tasks/README.md||Việc đang làm|1|true
346|agentdata:knowledge/current-tasks/README.md|knowledge/current-tasks/README.md|current-tasks-readme|Việc đang làm|1|true
301||knowledge/other/README.md|other|Tài liệu Khác|1|true
347|agentdata:knowledge/other/README.md|knowledge/other/README.md|other-readme|Other|1|true

Bước 5. Schema constraint live

Partial unique index theo source_id đã tồn tại trên production trước khi tôi can thiệp:

Command:
ssh root@38.242.240.89 "docker exec postgres psql -U directus -d directus -Atc \"SELECT indexname || '|' || indexdef FROM pg_indexes WHERE schemaname='public' AND tablename='knowledge_documents' ORDER BY indexname;\""

Output excerpt:
idx_kd_current_source_id_unique|CREATE UNIQUE INDEX idx_kd_current_source_id_unique ON public.knowledge_documents USING btree (source_id) WHERE ((is_current_version = true) AND (source_id IS NOT NULL))
idx_knowledge_documents_knowledge_documents_slug_unique|CREATE UNIQUE INDEX idx_knowledge_documents_knowledge_documents_slug_unique ON public.knowledge_documents USING btree (slug)
knowledge_documents_pkey|CREATE UNIQUE INDEX knowledge_documents_pkey ON public.knowledge_documents USING btree (id)

Kết luận: live VPS đã hoàn thành mục tiêu P2 trước phiên này.

Bước 6. Writer runtime hiện tại

Writer runtime/source trên VPS vẫn là bản cũ, chưa atomic:

  • _find_by_source_id(... limit: 1) vẫn còn trong /opt/incomex/docker/agent-data-repo/agent_data/directus_sync.py
  • nhánh handle_document_created/handle_document_updated vẫn PATCH đúng directus_id đầu tiên hoặc POST mới qua Directus API
  • chưa có bước UPDATE ... SET is_current_version=false trong cùng transaction ở source repo/runtime hiện đang chạy

Evidence source excerpt:

async def _find_by_source_id(
    client: httpx.AsyncClient, source_id: str
) -> dict[str, Any] | None:
    ...
        params={
            "filter[source_id][_eq]": source_id,
            "fields": "id,title,source_id,file_path",
            "limit": 1,
        },

Kết luận P0

P0 đã xong và cho kết quả khác prompt resume:

  • Local file sửa nhầm đã rollback sạch.
  • Snapshot mới đã nằm trên VPS tại /root/backup/s175-knowledge_documents-20260409T072635Z.sql.
  • knowledge_documents live hiện không còn law duplicate current groups.
  • 3 README duplicate groups vẫn còn nguyên.
  • Partial unique index idx_kd_current_source_id_unique đã tồn tại.
  • Writer runtime trên VPS vẫn là bản cũ, chưa atomic.

Hướng tiếp theo đề xuất

Vì live state đã tự vượt qua P1 và P2 trước phiên này, bước hợp lý tiếp theo là:

  1. Bỏ qua P1 vì không còn 13 law groups để dedupe.
  2. Bỏ qua P2 vì partial unique index đã live.
  3. Chuyển sang P3: sửa writer runtime ở /opt/incomex/docker/agent-data-repo/agent_data/directus_sync.py, rebuild image agent-data-local:latest, restart incomex-agent-data.
  4. Sau đó chạy P4 hardtests, đồng thời xác nhận 3 README groups vẫn còn nguyên.

OR / NT-09 check

  • Không đoán runtime path. Đã xác minh bằng container path + checksum source/runtime.
  • Không tạo half-state. Phiên này chưa thay dữ liệu production.
  • Không cần update OR trong P0. Lý do: chưa phát hiện luật mới, chỉ xác minh live diverged state.