KB-1F28

Dieu43 Phase 4a P1+P2 Report (Skeleton + Bước 1-4 build.sh)

10 min read Revision 1
dieu43phase4ap1-p2reportbuild-shs178-fix12

Đ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):

  1. PG health (directus DB) → SELECT 1
  2. OUTPUT_ROOT từ dot_config.context_pack_output_rootKHÔNG hardcode
  3. 3 folder exist (output_root + .tmp + -staging, Phase 2)
  4. Lock dir writable (context-pack.tmp)
  5. dot_operations.CONTEXT_PACK_BUILD present (Phase 1)
  6. KB API health → curl $AGENT_DATA_URL/health HTTP 200
  7. git_commit 5-tier fallback (repo → RELEASE_VERSION → $RELEASE_SHA → vps_deploy_log → unknown)
  8. Đ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 window
  • pg_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 -c6set -o pipefail treats 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_paths JSONB array qua jq -r '.[]'
  • Loop mỗi path; missing → log_warn + skip; exist → find -maxdepth 3 -type f count + awk max mtime
  • Cache TSV: ${TMPDIR}/dcp-scan-${BUILD_ID}.tsv format path\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_database mentions: ALL trong fallback logic + comments (intended)
  • scan_paths mentions: ALL là dot_config.context_pack_scan_paths reference (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 var KB_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_config PG; 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_get exit 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_database catalog 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_issue chưa có (Đ35 v5.1 BLOCK 4 chưa enact) — script dùng log_issue stub log ra stderr
  • TD-S178-14 (pre-existing): Đ33 §14 spec /opt/incomex/secrets/.env.production không tồn tại; fallback /opt/incomex/docker/.env (có override $KB_ENV_FILE env var)
  • TD-S178-17 (pre-existing): vps_deploy_log table 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