Dieu43 Phase 4a P0 Design Plan v1.2 rev 2
Đ43 Phase 4a — P0 Design Plan (v1.2 rev 2)
Date: 2026-04-17 UTC+7
Script target: /opt/incomex/dot/bin/dot-context-pack-build.sh
Agent: Claude CLI, S178 Fix 12
Luật nền: Đ43 v1.2 FINAL rev 2 (KB rev 10), HP v4.6.2 (rev 23), Đ33 §13, Đ35 v5.1, Đ41
0. CHECKPOINT — Đã đọc
- Đ43 v1.2 rev 2 §0+§3+§5.2-5.9+§6 (8 bước + §6.X)+§7+§8+§9+§11 (17 bước bootstrap)
- HP v4.6.2 — 13 NT (đặc biệt NT2/NT4/NT10/NT11/NT12/NT13)
- Đ33 §13 — DOT template
- Đ35 v5.1 §4.1 schema 11 fields + §5.1 CẤM POST partial
- Đ41 — VPS-as-SSOT
- Handoff S178 Fix 11 FINAL — đặc biệt §2.2 rà NT 3 tầng
- Phụ lục Đ43 §3.4 Phase 4a
- 2 Phase 2 scripts (pattern shebang/trap/logging/11-fields header)
1. VPS SNAPSHOT (state hiện tại, trước P1)
1.1 — Filesystem (Phase 2 đã done)
/opt/incomex/context-pack/ incomex:incomex 755 (main, empty)
/opt/incomex/context-pack.tmp/ incomex:incomex 755 (temp, empty)
/opt/incomex/context-pack-staging/ incomex:incomex 755 (staging, empty)
/opt/incomex/dot/bin/dot-dieu43-fs-init.sh 138 lines (Tier B, Phase 2)
/opt/incomex/dot/bin/dot-dieu43-fs-verify.sh 124 lines (Tier A, Phase 2)
/opt/incomex/dot/bin/archive/
- README.md (invalidate note)
- dot-context-pack-build-v1-1-INVALIDATED-2026-04-17.sh (v1.1 archived)
1.2 — PG directus DB (Phase 1 đã done — SCHEMA v1.1)
- context_trigger_sources: 6 rows
- dot_operations: 20 rows
- context_pack_requests: 0 rows
- context_pack_manifest: 0 rows
- context_pack_sections: 0 rows (FK v1.1 CHECK enum, SẼ cần migrate v1.2 FK section_code)
- v_context_pack_latest: view (v1.1)
1.3 — v1.2 extensions CHƯA tồn tại
- Tables:
context_pack_section_definitionsMISSING,context_pack_health_checksMISSING,dot_configMISSING (xem Q1 dưới) - Role:
context_pack_readonlyMISSING - Config: 7 dot_config keys Đ43 §5.9 MISSING
1.4 — Tools OS VPS
| Tool | Status |
|---|---|
| sha256sum | OK (coreutils 9.4) |
| curl | OK 8.5.0 |
| jq | OK 1.7 |
| ln | OK (atomic rename support) |
| find / stat / awk / sed / realpath | OK |
| docker (postgres container) | OK, psql 16.13 |
| python3 | OK (có thể dùng cho rendering) |
| mmdc (Mermaid CLI) | MISSING (fallback grep) |
| shellcheck | MISSING |
1.5 — KB Agent Data
- Endpoint:
https://vps.incomexsaigoncorp.vn/api(health 200) - Auth:
X-API-Keyheader từ/opt/incomex/docker/.env(AGENT_DATA_API_KEY+AGENT_DATA_URL) - Endpoints chính:
GET /documents/{id}?full=true,POST /documents?upsert=true,GET /health,GET /kb/list?prefix=
2. THIẾT KẾ SCRIPT — THÀNH PHẦN + TRÁCH NHIỆM
Script chia 10 module logic (1 file .sh duy nhất, section rõ ràng bằng comment banner):
| # | Module | Trách nhiệm | Bước §6 |
|---|---|---|---|
| M1 | Bootstrap | shebang, set -euo pipefail, globals, arg parse, usage, log helpers, error trap, exit trap (lock release), load KB env |
— |
| M2 | PG client | run_pg_rw() (user=directus/incomex cho write) + run_pg_ro() (role=context_pack_readonly cho SQL executor); table_exists(), role_exists() |
— |
| M3 | KB client | kb_get_document(path) → body, kb_upload(path, body, mime), kb_health() |
7a/7d |
| M4 | Config loader | dot_config_get(key) → JSONB text, dot_config_list_array(key) → bash array, fail-fast khi key thiếu (CẤM fallback §6.X) |
— |
| M5 | Precheck | PG health, KB health, 5-tier git_commit fallback, on-deploy gate (Đ41 §6.5) | Bước 1 |
| M6 | Lock + request | pg_try_advisory_lock(43,1), INSERT request (running/skipped), retry_count logic per §5.9 context_pack_retry_policy |
Bước 2 |
| M7 | Data gathering | query_pg() đọc context_pack_scan_db_whitelist → loop (rỗng → pg_database catalog NT11); scan_fs() đọc context_pack_scan_paths |
Bước 3+4 |
| M8 | Section engine | ★ Core — query section_definitions WHERE is_active=true ORDER BY order_index, dispatch data_source (pg_query/filesystem_scan/static/kb_query/custom), áp render_config contract (§5.7 P9 key whitelist, FAIL-FAST key lạ), render template từ template_kb_path (path whitelist), output $OUTPUT_ROOT/$build_id/$output_filename; SQL executor cho kb_query áp 5 guard §5.8 P8 |
Bước 5 (gen) |
| M9 | Checksum + validate | logical_checksum (strip <!-- VOLATILE HEADER ... --> block) + file_checksum (full sha256); validate min/max từ section_definitions, format validators theo format col; compare logical với v_context_pack_latest → skip unchanged |
Bước 5 (chk) + Bước 6 |
| M10 | Publish + release + repair | 7a upload KB staging (path dynamic), 7b PG TX manifest+sections (KHÔNG partial), 7c symlink swap atomic (ln -sfn), 7d promote KB live (diff-by-checksum), 7e finalize UPDATE, 7f compensate KB fail (no cross-rollback), 7g repair mode, Bước 8 release |
Bước 7+8 |
2.1 — Main flow
parse_args -> load_kb_env -> M5 precheck -> M6 lock -> M7 gather
-> M8 generate-sections -> M9 checksum+validate -> (compare_unchanged? exit 0)
-> M10 publish(7a..7e) -> release(8) [EXIT trap unlock]
Alternative: --repair-publish -> M10 repair_publish -> exit
2.2 — Output structure trong $OUTPUT_ROOT/<build_id>/
File list + sizes đều ĐỘNG từ context_pack_section_definitions. Seed v1.2 có 8 file nhưng KHÔNG hardcode: script render tất cả row is_active=true.
2.3 — Header volatile marker convention
- Opening:
<!-- VOLATILE HEADER — excluded from logical_checksum -->(có text trailing) - Closing:
<!-- END VOLATILE HEADER --> - Logical checksum strip regex (sed):
/<!-- VOLATILE HEADER/,/<!-- END VOLATILE HEADER -->/d(anchor opening loosely, closing exact) — đúng spec §7.1 v1.1 giữ nguyên v1.2
3. RUNTIME REQUIREMENTS
3.1 — Phase 1.5 BẮT BUỘC chạy TRƯỚC khi script build test được end-to-end
(Phase 1.5 KHÔNG thuộc scope Phase 4a)
| Artifact | Mô tả | Block phase nào |
|---|---|---|
Table dot_config |
Schema đầy đủ (key TEXT PK, value JSONB, description TEXT) — Đ35 v5.1 §4.1 KHOẢN 1B mô tả nhưng CHƯA có trên VPS | P3 skeleton test, P5 live test |
| Seed 7 dot_config keys Đ43 §5.9 | context_pack_scan_paths, scan_db_whitelist, watched_key_patterns, retry_policy, mode, output_root, grace_period_days | P3 live test |
context_pack_section_definitions + seed 8 rows + 2 CHECK path whitelist |
Seed §5.7 | P3 live test (script query to render) |
context_pack_health_checks + seed 9 rows builtin + 1 CHECK SQL path whitelist |
Seed §5.8 | Phase 4b (verify.sh), không block build.sh |
Role context_pack_readonly + GRANT DEFAULT PRIVILEGES cross-DB (directus + incomex_metadata) per §11 Bước 6.4 |
P10 rev 2 | P3 live test khi có section data_source='kb_query' (M8 SQL executor) |
Schema migrate context_pack_sections: v1.1 CHECK enum → v1.2 FK section_code -> section_definitions.code |
§5.4 | Bước 7b INSERT sections (P4) |
Schema migrate context_pack_requests: thêm retry_count, next_retry_at, last_error cols |
§5.2 | Bước 8 retry logic (P5) |
3.2 — Quyền + DB access
- OS user chạy script:
incomex(1001) — cron sẽ chạy dưới user này (Phase 6). Manual invocation root OK tạm. - PG users cần:
directus@directus— INSERT/UPDATE/SELECT trêncontext_pack_*,dot_configincomex@incomex_metadata— SELECTkb_documents(read-only đã có)context_pack_readonlycross-DB — CHỈ dùng cho M8 SQL executor khidata_source=kb_query
- KB API:
AGENT_DATA_API_KEYtừ/opt/incomex/docker/.env
3.3 — Trace cho Phase 4b (verify.sh paired)
Build script phải để lại artifacts verify.sh đọc được:
context_pack_manifestrow với 2 checksum đầy đủcontext_pack_sections8+ rows vớifile_checksum_sha256khớp FS- Symlink
$OUTPUT_ROOT/current+previousvalid - KB mirror path tương ứng
kb_document_pathcolumn health_status+publish_stepcolumns để §9 H9 check state consistency
4. ĐIỂM DỄ GÃY NHẤT + XỬ LÝ
| # | Rủi ro | Hậu quả | Cách xử lý |
|---|---|---|---|
| R1 | Checksum logical WRONG regex — dư/thiếu strip 1 ký tự | Logical checksum thay đổi mỗi run → compare unchanged KHÔNG BAO GIỜ skip → build storms cron 3h vô ích vĩnh viễn | Unit test trong P3: render 2 file cùng content khác timestamp → assert logical EQUAL + file DIFFER. Fixture pin regex. |
| R2 | Template rendering trong bash thuần | Bash sed/awk khó substitute JSONB nested + escape đúng cho markdown/JSON/Mermaid | Plan: dùng python3 inline one-liner (có sẵn OS, không Node dependency). Bash load data, python render. Q4 cần Desktop confirm. |
| R3 | SQL injection qua render_config/data | User-controlled config → data exfil | Config JSONB admin-only write qua dot-config-* DOT. KHÔNG dùng config value làm SQL string. M8 SQL executor chỉ load từ KB path whitelist + 5 guard §5.8. render_config.filters dùng như bash dict lookup, không concat SQL. |
| R4 | 2-phase publish half-state | Mất điện giữa 7c và 7e → FS live + DB staging → H9 CRITICAL | 7g repair 2 branch: (A) FS+KB OK → finalize UPDATE; (B) FS mismatch → ln -sfn previous + UPDATE failed. Idempotent. |
| R5 | KB API flaky | 1 file upload fail → state lệch | 7a atomic batch 8 file: any fail → cleanup staging + abort trước 7b. 7d partial fail → kb_mirror='failed', KHÔNG rollback FS. Retry via context_pack_retry_policy queue. |
| R6 | dot_config fallback vi phạm §6.X P2 | Ẩn lỗi config | dot_config_get() FAIL-FAST, exit 1 + log_fatal. CẤM pattern ${var:-default} cho config values. |
| R7 | Bootstrap paradox: dot_config chưa tồn tại | Script không chạy được lần đầu | M5 precheck verify dot_config table + 7 keys. Thiếu → exit 3 + log hướng dẫn "chạy Phase 1.5 trước". |
| R8 | KB key format / vs __ drift |
Sync pipeline normalize mâu thuẫn §6 wording | Dùng patterns từ dot_config.context_pack_watched_key_patterns. Script normalize pattern REPLACE(pattern, '/', '__') nếu PG dùng __. Q6. |
| R9 | Mermaid validate không có mmdc | H7 fallback grep miss syntax errors tinh vi | P3 fallback: grep -qE '^(graph|flowchart)' + balanced brackets. TD-S178-15 retrofit. |
| R10 | section_count manifest không khớp file rendered | CHECK > 0 v1.2 nhưng nếu 1 section fail validate thì 7 hay 8? | M10 7b trong TX: section_count := COUNT(*) FROM section_definitions WHERE is_active=true. Nếu 1 section render fail → abort toàn build trước 7a. Confirm Q5. |
5. CHIA P1-P5 + REVIEW FOCUS
P1 — Skeleton (15 phút)
- Shebang +
set -euo pipefail+ error/exit traps - Header comment ~35 dòng: purpose, luật, paired, 11 fields Phase 5 v1.2 (cron_schedule là seed mặc định, domain=
context.pack, operation=CONTEXT_PACK_BUILD), exit codes, TD list - M1+M2+M3+M4 skeleton stubs: bootstrap + PG/KB/config helpers đủ cho M5 gọi được
- M5-M10 function stubs in "TODO"
- Arg parse:
--help,--dry-run,--trigger-source=<code>,--repair-publish,--verbose,--build-id=<id>(mới — repair mode target 1 build cụ thể?) - Tests: bash -n, --help, no-flag dry-run, unknown flag exit 2, invalid trigger exit 2, --repair-publish bypass, --dry-run PG down exit 3
- Desktop review: header + flow order + exit codes + 11 fields v1.2
P2 — Bước 1-4 (20 phút)
- M4 config loader fail-fast
- M5 precheck: PG/KB health, 5-tier git_commit, on-deploy gate, verify 7 dot_config keys + dot_config table
- M6 try-lock + INSERT request + retry_count §5.9
- M7 query_pg (scan_db_whitelist loop → pg_database catalog) + scan_fs (scan_paths array)
- Tests: dry-run Bước 1-4, PG down exit 3, lock busy coalesce, on-deploy gate missing, dot_config key missing fail-fast
- Desktop review: config loader FAIL-FAST + §6.X compliance
P3 — Bước 5 GENERATE + 2 CHECKSUM ★ CRITICAL (25 phút)
- M8 section engine: query section_definitions, dispatch data_source (pg_query/kb_query/filesystem_scan/static/custom), render_config contract FAIL-FAST key lạ, template path whitelist, output dynamic filename
- Builtin pg_query handlers: project_map, dot_registry, entities_overview, db_map, architecture_mmd, project_map_json (6 sections)
- kb_query handler with 5 guard §5.8 for SQL executor
- M9 checksum: logical (sed strip) + file (full)
- Tests: render 8 section live data; checksum unit (same content diff timestamp = logical EQUAL file DIFFER); render_config key lạ FAIL-FAST; path không whitelist REJECT; SQL có DELETE REJECT; SQL timeout 30s abort
- Desktop review KỸ P3 — 2 checksum + 5 guard là nhạy cảm nhất
P4 — Bước 6 VALIDATE + Bước 7 PUBLISH ★★ SENSITIVE NHẤT (25 phút)
- Validate min/max size, format validators, compare logical skip unchanged
- 7a upload KB staging atomic batch (any fail → cleanup + abort)
- 7b PG TX: INSERT manifest (section_count động) + 8 sections, KHÔNG partial
- 7c atomic symlink swap (ln -sfn current + previous)
- 7d promote KB diff-by-checksum
- 7e finalize UPDATE live
- 7f compensate KB fail (no cross-rollback)
- 7g repair (detect post_fs_pre_db_finalize >15min → finalize OR rollback symlink, idempotent)
- Tests: dry-run 7a-7e, real publish test build_id (manual cleanup), 7f giả lập KB fail, 7g giả lập state lệch, atomic swap test
- Desktop review CỰC KỲ KỸ P4
P5 — Bước 8 + edge cases + integration (15 phút)
- release: advisory_unlock, UPDATE request done, UPDATE dot_tools.last_executed (stub-safe cho Phase 5 register sau)
- Retry §5.9 retry_policy on fail
- Edge: PG/KB down, disk full, lock busy 2 instances, concurrent manifest insert, empty DB, timeout >10min
- Idempotent verify: dry-run 2 consecutive = unchanged skip
- shellcheck (hoặc justify warnings)
P6 — Report + backup + cleanup (10 phút)
- Upload
knowledge/dev/laws/dieu43-migrations/dot-context-pack-build.shmirror - Upload
knowledge/current-state/reports/phase4a-report.md13 tiêu chí - Cleanup
/tmp/dieu43-*, DELETE test rows
6. CÂU HỎI CẦN DESKTOP TRẢ LỜI TRƯỚC P1
Q1 — dot_config table CHƯA tồn tại trên VPS
Đ35 v5.1 §4.1 KHOẢN 1B mô tả bảng + function fn_is_in_grace_period dùng bảng này. Handoff §1.5 ghi "7 rows dot_config keys" (nghe như bảng có sẵn chỉ cần seed). Thực tế: SELECT ... FROM dot_config -> relation "dot_config" does not exist.
Quyết định cần:
- (a) Phase 1.5 tạo bảng + seed 7 keys trước Phase 4a tiếp
- (b) Nhét CREATE TABLE vào build.sh bootstrap (VI PHẠM tách biệt — script build không nên DDL)
- (c) Tạo ngay trong P0 như side-task
Q2 — Role context_pack_readonly cross-DB GRANT
Ai/phase nào tạo role + GRANT? Role cluster-level, cần superuser. VPS không có postgres role. -U workflow_admin có là superuser? Cần verify Phase 1.5.
Q3 — On-deploy gate với vps_deploy_log vẫn missing (TD-S178-17)
Trigger on_deploy + table missing:
- (a) permissive (log WARN, tiếp build) — Fix 11 P2 đã chọn
- (b) strict (log_skip, exit 0)
Confirm v1.2 giữ (a)?
Q4 — Template rendering engine
- (a) Bash sed/awk substitute (ASCII-safe only)
- (b) python3 inline (mượn python có sẵn OS)
- (c) khác
render_config.placeholder_style v1.2 seed = 'mustache' → (a) không support. Chọn (b)? Mustache engine nào? Hay thay default sang simpler?
Q5 — section_count trong INSERT manifest với partial render fail
Nếu 1/8 section validate fail (Bước 6):
- abort toàn build (giữ live cũ) — vote của CLI theo §6.X "CẤM partial"
- render 7/8 với section_count=7
Q6 — KB key format normalize (/ vs __)
Agent Data kb_documents.key dùng __. Script:
- (a) Pattern từ
context_pack_watched_key_patternsđã normalize__trong JSONB - (b) Script tự normalize
/→__khi dùng - (c) Đợi sync pipeline fix (TD-S178-18)
Q7 — Rev 2 P10 + P11 DDL artifacts
P10 cross-DB GRANT + P11 trigger function — ai làm? Phase 1.5 hay Phase 7 (trigger install)?
7. TUÂN THỦ LUẬT — CHECKLIST
7.1 — §6.X P1-P11 CẤM HARDCODE
| Điểm | Module | Compliance plan |
|---|---|---|
| CẤM hardcode section list | M8 | Query section_definitions WHERE is_active=true |
| CẤM hardcode folder list | M7 scan_fs | Đọc dot_config.context_pack_scan_paths |
| CẤM hardcode DB list | M7 query_pg | Đọc scan_db_whitelist, rỗng → pg_database catalog |
| CẤM hardcode law pattern | M8 laws_index | Đọc watched_key_patterns JSONB |
| CẤM hardcode min/max size | M9 validate | Đọc min_size_bytes/max_size_bytes per row |
| CẤM hardcode health threshold | Phase 4b (ngoài scope) | build.sh KHÔNG set health_status qua hardcode |
| CẤM hardcode output root | M1+M8+M10 | Đọc output_root, apply $OUTPUT_ROOT |
| CẤM fallback hardcode default | M4 config loader | FAIL-FAST khi key thiếu, exit 1 |
| CẤM switch-case hardcode check names | Phase 4b | Không ảnh hưởng build.sh |
| CẤM executor_type='sql' không 5 guard | M8 kb_query | Áp đủ 5 guard §5.8 |
| P10 GRANT từng table | Phase 1.5 ngoài scope | Build.sh chỉ DÙNG role, không GRANT |
| P11 WHEN bind pattern | Phase 7 trigger install | Không ảnh hưởng build.sh |
7.2 — 13 NT HP v4.6.2
| NT | Compliance |
|---|---|
| NT1 SSOT | Mọi config từ dot_config + reference tables |
| NT2 Tự động 100% | Thêm section = INSERT row, không sửa code |
| NT3 DOT 100% | Script này LÀ DOT, register Phase 5 |
| NT4 Thay đổi = config | dot_config UPDATE → hiệu lực ngay build sau |
| NT5 Tự phát hiện | retry_policy + health_checks + compare unchanged |
| NT7 Dual-trigger | cron + 4 secondary triggers |
| NT8 Assembly First | Query PG → render → KB upload |
| NT9 Không chắc = sai | FAIL-FAST; 7 Q trên cần trả lời trước P1 |
| NT10 PG Native | section_definitions + health_checks + dot_config sống PG |
| NT11 Khai tối thiểu | pg_database catalog thay hardcode 3 DB |
| NT12 DOT cặp | Paired dot-context-pack-verify (Phase 4b) — §3.3 trace |
| NT13 PG Native | Advisory lock PG native, JSONB config |
7.3 — Rà NT 3 tầng (memory #29)
Plan nào CÓ THỂ lọt tầng 2 DDL? Câu trả lời: KHÔNG — build.sh không làm DDL, chỉ dùng.
- Tầng 1 code: bash — rà bằng shellcheck ở P5
- Tầng 2 DDL: N/A build.sh
- Tầng 3 data seed: N/A build.sh (tạo row runtime qua INSERT — idempotent, không seed cứng)
8. SCOPE CLARIFY
Phase 1.5 là implicit prerequisite của Phase 4a. Nếu không tạo Phase 1.5 trước P3, P3 tests block ở precheck "dot_config missing".
Đề nghị:
- Option A: Desktop ra prompt Phase 1.5 TRƯỚC P1 — tạo
dot_config+ role + section_definitions + health_checks + migrate v1.1→v1.2 schema - Option B: CLI P1+P2 với test "PG missing" mock OK, dừng trước P3; Desktop chạy Phase 1.5 rồi CLI tiếp P3
- Option C: Script build.sh tự detect thiếu → stub config bằng env var cho dry-run test
CLI vote Option A vì separation of concerns (schema DDL ≠ DOT script).
P0 Design Plan — Đ43 Phase 4a v1.2 rev 2 — Claude CLI S178 Fix 12 — 2026-04-17