Dieu43 Phase 4a P1+P2 Report (Skeleton + Bước 1-4 build.sh)
Đ43 Phase 4a P1+P2 Report — Skeleton + Bước 1-4 build.sh
Date: 2026-04-17 UTC+7
Phiên: S178 Fix 12 Phase 4a P1+P2
Agent: Claude CLI qua SSH contabo
Spec: Đ43 v1.2 FINAL rev 3 (KB rev 20) §6 Bước 1-4 + §6.X CẤM HARDCODE
CHECKPOINT
Đã đọc: Đ43 v1.2 rev 3 §5+§6 (8 bước)+§6.X; HP v4.6.2 13 NT (NT2/4/8/11/12/13); HP S176 (4 DB + 3 lớp); Đ33 §13 ngoại lệ bootstrap + §14 auth; Đ41 VPS-SSOT; memory #29 rà 3 tầng (phiên này chỉ tầng code bash).
1. DB + LỚP ĐÃ KHAI (HP S176)
| DB | Lớp | Thực tế phiên này |
|---|---|---|
directus |
KHO | R dot_operations, dot_tools, context_pack_*, normative_registry, birth_registry, meta_catalog, dot_config; W context_pack_requests (Bước 2) |
incomex_metadata |
NÃO | (P3+P4 phiên sau: R kb_documents cho laws_index section + templates/queries) |
postgres catalog |
— | R pg_database cho db_count khi whitelist rỗng (NT11) |
Gateway: docker exec psql -U directus (RW) + -U context_pack_readonly (RO cross-DB). Trust auth qua Unix socket container, không cần password (TD-S178-14: /opt/incomex/secrets/.env.production chưa có).
2. 3 SUB-STAGE KẾT QUẢ
Stage A — Skeleton + 8 function stub — ★ PASS
| Pass criterion | Evidence |
|---|---|
--help đầy đủ |
17-line usage, 6 options (--help, --dry-run, --trigger-source, --repair, --build-id, --verbose), 4 exit codes |
| shellcheck 0 ERROR 0 WARNING | warn_exit=0 err_exit=0 (44 SC2317 info-only, accepted per prompt) |
| 8 function declared §6 | precheck, try_lock, query_pg, scan_fs, generate, validate, publish, release |
| Header comment đầy đủ metadata | @version 0.1-skeleton, @spec, @paired-dot dot-context-pack-verify.sh, @db-access 3-DB table, @gateway, @exit-codes, @scope, @bootstrap |
| Arg parse reject invalid | --bogus → exit 2; --trigger-source=badcode → exit 2; valid enums 6 per §5.1 |
Stage B — Bước 1 PRECHECK + Bước 2 TRY-LOCK — ★ PASS
Bước 1 PRECHECK (8 kiểm tra, §6 giữ v1.1):
- PG health (directus DB) →
SELECT 1 OUTPUT_ROOTtừdot_config.context_pack_output_root— KHÔNG hardcode- 3 folder exist (output_root + .tmp + -staging, Phase 2)
- Lock dir writable (context-pack.tmp)
dot_operations.CONTEXT_PACK_BUILDpresent (Phase 1)- KB API health →
curl $AGENT_DATA_URL/healthHTTP 200 - git_commit 5-tier fallback (repo → RELEASE_VERSION → $RELEASE_SHA → vps_deploy_log → unknown)
- Đ41 §6.5 on-deploy gate (permissive WARN khi vps_deploy_log missing)
Bước 2 TRY-LOCK (§6 v1.1):
dedupe_bucket = date_trunc('hour', now())— hourly windowpg_try_advisory_lock(43, 1)→ acquire/busy decision- Busy → INSERT request status='skipped' detail='{"reason":"coalesced"}' → exit 0
- OK → INSERT request status='running' detail={"build_id":...} RETURNING id → LOCK_HELD=1
- trap EXIT releases lock best-effort
Race test evidence (fresh, non-dry):
Run 1 (lock held manually via background psql session):
[SKIP] advisory_lock(43,1) BUSY — coalesce skip
[OK] coalesce-skip request inserted
Row: id=6 | trigger=on_demand | status=skipped | detail={"reason":"coalesced"}
Run 2 (lock free):
[OK] advisory_lock(43,1) acquired
[INFO] build_id=20260417-093306-05d047
[OK] request_id=7 inserted (status=running)
Row: id=7 | status=running | detail={"build_id":"20260417-093306-05d047"}
Bug phát hiện + fix trong Stage B:
- SIGPIPE 141 khi gen build_id với
tr -dc 'a-z0-9' </dev/urandom | head -c6—set -o pipefailtreats head closing as failure. - Fix: dùng bash
$RANDOM+printf '%04x%02x'— pure bash, không pipe. Build ID format:YYYYMMDD-HHMMSS-<6hex>.
Stage C — Bước 3 QUERY PG + Bước 4 SCAN FS — ★ PASS
Bước 3 QUERY PG (sources per prompt §3 + §6):
| Metric | Source | Value (live VPS) |
|---|---|---|
| law_count | normative_registry |
40 |
| dot_count | dot_tools |
272 |
| entity_count | birth_registry |
42867 |
| species_count | meta_catalog |
161 |
| db_count | dot_config.context_pack_scan_db_whitelist length OR pg_database catalog exclude (postgres, template0, template1) khi rỗng (NT11) |
3 (from catalog) |
Reads qua role context_pack_readonly (Phase 1.5 P10 DEFAULT PRIVILEGES cross-DB).
Bước 4 SCAN FS:
- Đọc
dot_config.context_pack_scan_pathsJSONB array quajq -r '.[]' - Loop mỗi path; missing →
log_warn+ skip; exist →find -maxdepth 3 -type fcount + awk max mtime - Cache TSV:
${TMPDIR}/dcp-scan-${BUILD_ID}.tsvformatpath\ttotal\tnewest_mtime - awk pattern thay
sort | headđể tránh SIGPIPE dưới pipefail
Runtime-config test 1 — scan_paths:
BEFORE: ["/opt/incomex/dot/bin","/opt/incomex/web/app","/opt/incomex/deploy","/opt/incomex/scripts"]
→ scan_fs: scanned=277 skipped=2 (web/app + deploy missing)
UPDATE: value = value || '["/tmp/test-phase4a"]'::jsonb (RUNTIME, no restart)
AFTER: ["/opt/incomex/dot/bin","/opt/incomex/web/app","/opt/incomex/deploy","/opt/incomex/scripts","/tmp/test-phase4a"]
→ scan_fs: scanned=277 skipped=2 (including new path recognized: /tmp/test-phase4a total=0)
★ PASS — path mới có hiệu lực NGAY, không restart script.
Runtime-config test 2 — scan_db_whitelist:
[] → db_count=3 via pg_database catalog (NT11 fallback)
["directus"] → db_count=1 via whitelist length
[] → db_count=3 via pg_database catalog (fallback restored)
★ PASS — both directions runtime-configurable.
Grep hardcode verification:
pg_databasementions: ALL trong fallback logic + comments (intended)scan_pathsmentions: ALL làdot_config.context_pack_scan_pathsreference (intended)/opt/incomex/literal paths outside dot_config: CHỈ trong TD comment kb_env_load (bootstrap paradox — env file path để connect PG; có override env varKB_ENV_FILE)- Magic numbers (3/4/8/9999) literal trong code: 0
3. FILE STATE
- VPS:
/opt/incomex/dot/bin/dot-context-pack-build.sh- 567 lines, 19234 bytes (ước lượng)
- Owner
incomex:incomex, mode 750 - Bash
set -euo pipefail+ trap ERR/EXIT + pipefail
- KB backup:
knowledge/dev/laws/dieu43-migrations/dot-context-pack-build-stage-ABC-snapshot.sh(revision 1)
4. TUÂN THỦ 13 NT (rà 3 tầng memory #29)
Phiên này có tầng code bash (không DDL/data seed mới → skip 2 tầng DDL/data):
- NT1 SSOT: config trong
dot_configPG; script không cache locally. - NT2+NT4: Mọi value runtime (OUTPUT_ROOT, scan_paths, whitelist) từ
dot_config. Test runtime-config 1+2 chứng minh UPDATE có hiệu lực NGAY. - NT3 (bootstrap E): Script chạy manual trong dev phase, register Phase 5 (Đ33 §13 exception)
- NT5: retry_policy §5.9 có sẵn trong
dot_config(chưa implement ở Bước 8, P4 phiên sau) - NT7 dual-trigger: Support 6 trigger_source per §5.1 (cron + on_demand + on_deploy + on_law_enact + on_dot_register + system_init)
- NT8 Assembly First: Query PG reference tables qua role chính thức; không dùng view phái sinh
- NT9 fail-fast:
dot_config_getexit 1 khi key thiếu; CẤM${var:-default}fallback - NT10 PG native: advisory_lock, JSONB parse qua jq, date_trunc SQL
- NT11 khai tối thiểu:
pg_databasecatalog fallback thay hardcode số DB - NT12 paired DOT: Header comment @paired-dot dot-context-pack-verify.sh (Phase 4b)
- NT13 PG native: pg_try_advisory_lock, pg_advisory_unlock, jsonb_build_object, RETURNING id
5. TECHNICAL DEBT (TD) PHÁT SINH / CÒN NGUYÊN
- TD-S178-12 (pre-existing):
fn_log_issuechưa có (Đ35 v5.1 BLOCK 4 chưa enact) — script dùnglog_issuestub log ra stderr - TD-S178-14 (pre-existing): Đ33 §14 spec
/opt/incomex/secrets/.env.productionkhông tồn tại; fallback/opt/incomex/docker/.env(có override$KB_ENV_FILEenv var) - TD-S178-17 (pre-existing):
vps_deploy_logtable chưa có — git_commit luôn rơi tier 5 'unknown' + WARN; on-deploy gate permissive
6. TIẾN ĐỘ + DỰ KIẾN
| Phase | Status | Lines |
|---|---|---|
| Stage A skeleton + 8 stub | ✅ DONE | 324 |
| Stage B Bước 1+2 | ✅ DONE | ~500 |
| Stage C Bước 3+4 | ✅ DONE | 567 |
| P3 Bước 5 generate + 2 checksum | ⏸️ | ước ~250 thêm |
| P3 Bước 6 validate | ⏸️ | ước ~100 thêm |
| P4 Bước 7 2-phase publish + repair | ⏸️ | ước ~200 thêm |
| P4 Bước 8 release | ⏸️ | ước ~50 thêm |
| Total ước sau P4 | ~1150-1200 lines |
Phase 4a P1+P2 xong = ~47% file cuối (theo prompt mục tiêu 45%).
7. CẤM TUÂN
- ✅ KHÔNG Bước 5-8 implement (stubs giữ)
- ✅ KHÔNG sửa luật Đ43 / migration SQL Phase 1.5/1.6
- ✅ KHÔNG publish thật (không symlink, không KB upload except backup sau stage)
- ✅ KHÔNG register DOT (Phase 5)
- ✅ KHÔNG install cron (Phase 6)
- ✅ KHÔNG viết verify.sh (Phase 4b)
- ✅ KHÔNG hardcode (grep clean + 2 runtime-config tests chứng minh)
- ✅ 3 stage gate nghiêm ngặt: A→B→C với Desktop duyệt giữa mỗi bước
8. KẾT LUẬN
Phase 4a P1+P2 PASS. Script skeleton + 4/8 bước chạy end-to-end dry-run, 2 tests runtime-config chứng minh §6.X CẤM HARDCODE tuân, race test chứng minh advisory lock + coalesce-skip đúng §6 Bước 2.
Sẵn sàng Phase 4a P3 (Bước 5 GENERATE + 2 checksum, Bước 6 VALIDATE — CORE Đ43, ước thêm ~350 dòng).
Report by Claude CLI — S178 Fix 12 Phase 4a P1+P2 — 2026-04-17