Files
solution-erp/.claude/workflows/runs/README.md
pqhuy1987 18fced6695
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m16s
[CLAUDE] Workflow: adopt Harness-10 flat-refine + checklist-v2 + sleep-recovery-cmd (re-audit 3-workflow)
Re-audit Harness-8/9/10/10-refine + checklist v1/v2 + hmw vs canonical AI_INFRA
(mandate Harness-9 B1+B2): audit wf_13868efb-ea7 -> implement wf_ac43b5ff-7d1 ->
review wf_d482e10d-5dd. SE was BEHIND Harness-10 flat.

- run-trace SUBFOLDER->FLAT: hmw.js (:103 subMd + :52 schema + H4.5->H8 drift) +
  workflows/README full-rewrite + runs/README + session-start/end + agents/README
  Upgrade S72 + _ledger; 5 old S71 runs KEEP subfolder (C8 dual-accept). node --check OK.
- adopt 2 pending broadcasts (checklist-v2 + h10-flat-detector-refine).
- port /sleep-recovery-memory-l2 (A8, J2-tailored SE-only, floor intact, live skill).
- detector refine-b TAILORED-OUT (SE Workflow-tool no-CLI-bypass; containment
  git-diff+tracked+orphan-scan G-015).
- REVIEW (B2) caught 2 IMPLEMENT-self-assess missed (hmw.js:52 schema-stale +
  sleep-cmd auto-check un-wired overclaim) -> fixed (auto-check WIRED: budget.json
  +last_sleep_at + session-start/end INFORM). +3 minor fixed.
- em-main containment-check caught 1 reviewer residual-write (raw-Workflow no
  writeGuard) -> revert (reverse-finding #4). B3 self-correct: runs path 14->22.
- sleep-recovery-memory-l2 all = NO-OP (all periods already gisted). last_sleep_at set.

0 production code. State unchanged: Mig 53 / 88 tables / 306 test / 68 gotcha / menu 54
/ bundle BgNCjwsG/CBvh0vtf. adap-report + email ai_infra (5f511fe5c0f2).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 14:04:03 +07:00

16 KiB

runs/ — Run-trace convention (Harness-10 · cấu trúc PHẲNG)

Mục đích: mỗi workflow fan-out (RUN-TRACE mode) ghi lại 1 dấu-vết hoàn-chỉnh trong runs/<run-id>/ git TRACKED — plan + per-sub detail + bản-gom — cộng sổ _ledger.md 2-nhịp. TRACKED nghĩa là mọi write trong run-folder hiện trong git diffaudit trực-tiếp, không cần tin lời agent return. Adopt AI_INFRA Harness-10 (anh 06-18) + DELTA h10-flat-detector-refine (06-18). Convention cha: ../README.md.

🆕 REFINE 06-18 — cấu trúc PHẲNG. Trước đây mỗi run-folder có 2 thư mục con (sub-md/ + harvest/). NAY mọi vết tích nằm phẳng cùng MỘT cấp trong runs/<run-id>/; phân biệt bản-thô (raw, per-sub) vs bản-đã-soát (verified, gom) bằng TÊN file, KHÔNG bằng thư mục con. Lý do: engine (hmw.js JS-sandbox no-fs) chỉ tạo artifact ở một cấp một cách tự nhiên — bỏ thư-mục-con sâu thì xoá luôn một điểm-hay-quên ngay tại gốc (không còn thư-mục-con-để-quên-dựng).

run-id = YYYY-MM-DD-h<NN>-<slug> (vd 2026-06-18-harness-audit-invest). Nhiều run cùng ngày → slug phân-biệt stage (-invest / -implement / -review).


C1 — Cấu trúc PHẲNG (mỗi runs/<run-id>/ — file cùng MỘT cấp)

runs/<run-id>/
├── run.md                       ← (1) PLAN — em main @P1: meta + mục-tiêu + agents-table + guards + status OPEN→CLOSE
├── sub-<role>-<i>.md            ← (2) PER-SUB raw — 1 file/sub/turn, prefix `sub-` (vd sub-investigator-codebase-0.md)
├── sub-<role>-<i>.md                (fan-out cùng-role → đánh số -0 / -1 …)
└── <stage>-synthesis.md         ← (3) GOM verified — em main: bản-gom 1 turn, suffix `-synthesis.md` (vd invest-synthesis.md)

Phân-biệt raw vs verified bằng TÊN, KHÔNG bằng subfolder:

Loại Quy-ước TÊN Ai ghi Nội-dung
PLAN run.md (cố định) em main @P1 nguồn-sự-thật của run: workflow run-id (evidence B3 wf_…), adap/mandate, checkpoint, opened, input-spec (nếu nối stage trước), agents-table (# · role · task), guards áp cho sub, output-path, status OPEN→CLOSE.
PER-SUB (raw) prefix sub-sub-<role>-<i>.md write-sub tự ghi @P2 · read-only sub → em main scribe @P3 full working detail 1 sub. 1 sub-MD / role / turn (cùng-role → -0/-1). Read-only sub (CHỈ Bash) KHÔNG Bash-write MD (mojibake) → trả findings+subMdPath, em main single-writer.
GOM (verified) suffix -synthesis.md<stage>-synthesis.md em main per-turn (C4) gom sub-*+findings → 5-trục integrity → build-spec/synthesis.

🟢 Quy-tắc nhận-diện: file bắt đầu bằng sub- = bản-thô (per-sub); file kết bằng -synthesis.md = bản-đã-soát (gom). run.md = plan. Không cần mở file/không cần subfolder để biết loại — đọc TÊN là đủ. (Khớp ../hmw.js inject path: engine ghi-direct runs/<run-id>/sub-<role>-<i>.md, KHÔNG sub-md/….)

Live dogfood: 2026-06-18-harness-audit-invest/ = run.md + audit-synthesis.md CHỈ (KHÔNG subfolder, KHÔNG raw sub-audit-*.md) — vì 1 auditor fail-no-StructuredOutput + 2 truncated → em main self-gate ground-truth từ đĩa, không có raw-sub để scribe (xem audit-synthesis.md:4). Ví-dụ tên sub-<role>-<i>.md là minh-hoạ QUY-TẮC-ĐẶT-TÊN, KHÔNG phải artifact bắt-buộc mỗi run. Run 2026-06-18-harness-fix-implement/ mới có đủ raw (sub-impl-sleepcmd.md + sub-impl-runsreadme.md + implement-synthesis.md) = full flat set điển-hình.


C2 — Scaffold run.md ở OPEN (em main @P1, TRƯỚC khi invoke Workflow)

hmw.js chạy JS-sandbox no-filesystem → KHÔNG tự tạo folder/file. Em main PHẢI Write @P1:

  1. Tạo run-folder + PLAN: runs/<run-id>/run.md (điền plan đầy-đủ). 🆕 KHÔNG cần mkdir sub-md/ / harvest/ / .gitkeep — file sub-**-synthesis.md sẽ sinh ra phẳng cùng cấp trong cùng folder đó (engine + em main ghi 1 cấp).
  2. Ghi OPEN-beat vào runs/_ledger.md (1 dòng, closed=⏳).
  3. (nối stage) trỏ input spec: trong run.md sang <stage>-synthesis.md của run trước (vd implement đọc invest-synthesis.md).

🔴 C2 là fragile-point. Quên scaffold = run chạy nhưng KHÔNG có dấu-vết = lỗ-hổng âm-thầm (không lỗi, không cảnh-báo — chỉ thiếu file). 3-layer (C5) là lưới giảm-thiểu, KHÔNG khoá-cứng. Xem C7. 🆕 Cấu trúc phẳng bỏ 1 trong 2 điểm-hay-quên (không còn subfolder-to-forget); dư-lượng còn lại = vẫn phải tự ghi <stage>-synthesis.md mỗi run (close-gate C5/L3 bắt nếu thiếu).


C3 — Git-tracked: VERIFY 2 nấc tách-bạch (chỗ hay nhầm)

Run-folder PHẢI git TRACKED (re-include qua .gitignore:83 !.claude/**, last-match-wins). Verify ĐỦ 2 nấc — đừng dừng ở nấc 1:

# Nấc (i) — GỠ-KHỎI-IGNORE (tracked-eligible): exit != 0 = KHÔNG bị ignore
git check-ignore .claude/workflows/runs ; echo "exit=$?"     # SE: exit=1 ✓ (không ignore)

# Nấc (ii) — THẬT-SỰ-COMMIT: liệt-kê ra file = đã `git add`/commit
git ls-files .claude/workflows/runs | wc -l                   # SE: 22 ✓ (non-empty = đã commit)
  • Nấc (i) check-ignore exit != 0 = thư-mục KHÔNG nằm trong ignore (tracked-eligible). ⚠️ Mới là đủ-điều-kiện-track, CHƯA chắc đã commit.
  • Nấc (ii) ls-files non-empty = thật-sự có file trong index (đã git add/commit). 🔴 eligible ≠ committed: một folder check-ignore exit!=0 NHƯNG ls-files rỗng = chưa hề commit (bằng-chứng sống tại AI_INFRA chính trường-hợp này). PHẢI chạy CẢ 2 lệnh.
  • 🔴 ĐÚNG PATH mới đáng tin. Path đúng = .claude/workflows/runs (đầy-đủ từ repo-root). Bare runs/ (tên trần) là path SAI — ở repo khác, git check-ignore runs từ repo-root có thể trả exit 0 (match nhầm rule khác / không match negation .claude/**) → đọc sai thành "bị ignore". (Quan-sát SE: cả runs lẫn .claude/workflows/runs đều trả exit=1 vì .gitignore SE không có rule runs trần — nhưng ĐỪNG dựa may-rủi đó: luôn dùng path đầy-đủ .claude/workflows/runs.)
  • Bẫy exit-code khi dùng -v: git check-ignore -v <path> trả exit 0 cho CẢ ignore lẫn negation (!.claude/**) → đừng đọc exit của -v để kết-luận; dùng dạng không--v ở trên (exit!=0 = không ignore) hoặc && echo IGNORED || echo NOT.

C4 — Per-turn primary (gom NGAY, không đợi session-end)

Gom là việc của turn, không defer. Sau MỖI fan-out turn → em main đọc sub-*+findings → ghi <stage>-synthesis.md liền trong turn đó (chính file synthesis này là bằng-chứng). Lợi: detail tươi, không mất qua nén-context; session-end chỉ VERIFY (không tái-tạo). Đây là đường CHÍNH (primary); gom toàn-bộ @session-end (L3) chỉ là lưới an-toàn (safety-net), KHÔNG phải đường chính.


C5 — 3-layer anti-miss (lưới chống bỏ-sót — KHÔNG khoá-cứng-cùng-lúc-fire)

Layer Khi Làm gì
L1 in-run ledger-check em-main @P1, lúc mở run mới (TRƯỚC scaffold) đọc _ledger.md: nếu run TRƯỚC còn closed=⏳ (OPEN-beat chưa CLOSE / thiếu <stage>-synthesis.md) → gom + CLOSE nó TRƯỚC khi mở run mới. (Engine no-fs → KHÔNG đọc được ledger → L1 là convention EM-MAIN, KHÔNG phải hmw.js prompt. hmw.js chỉ emit C4 per-turn return-instruction cho sub tại writeGuard.)
L2 session-start orphan-scan đầu session (session-start.md §2.1.1 H2) scan runs/*/ tìm orphan = OPEN-beat (ledger closed=⏳) mà KHÔNG có <stage>-synthesis.md → báo + giải-quyết (C6).
L3 session-end close-gate cuối session (session-end.md §L.b(f) H2) VERIFY per-turn gom đã xong cho mọi runs/<id>/ (idempotent — KHÔNG re-APPEND, chống DUPLICATE-HARVEST) + 5-trục GATE backstop trước khi commit. 🆕 close-gate chấp nhận CẢ 2 dạng (old-subfolder + new-flat) trong giai-đoạn chuyển — xem C8.

3 layer độc-lập, fire ở 3 thời-điểm khác nhau (run-open @P1 / session-start / session-end) — KHÔNG layer nào do engine enforce (hmw.js no-fs), cả 3 là convention em-main/H2. → giảm xác-suất sót, KHÔNG triệt-tiêu. Sót ở P1 (C2) cùng blind-spot với L1 (đều @P1) → chỉ bắt MUỘN ở L2 (session sau) / L3 (close-gate).


C6 — Ledger 2-nhịp + orphan resolution (_ledger.md)

Sổ tất-cả run, 1 bảng. Mỗi run 2 lần ghi (2-nhịp):

  • OPEN-beat (@P1, lúc scaffold): thêm dòng | <run-id> | <workflow> | <opened> | ⏳ | <agents> | ⏳ | <stage>-synthesis.md |.
  • CLOSE-beat (lúc đóng run): điền closed timestamp + verdict (PASS/FAIL + 1 dòng + wf_…) + harvest (path file synthesis ✓).

closed=⏳ = đang chạy (OPEN chưa CLOSE).

Orphan = dòng ledger closed=⏳ nhưng run thực-tế đã xong/bỏ (session bị kill, agent die-0-byte, quên CLOSE-beat). Giải-quyết-CỨNG (không để treo):

  1. Điều-tra đĩa THẬT: run.md status + có file sub-*? + có <stage>-synthesis.md? + git-log workflow wf_….
  2. Đóng tay nếu run thật-sự xong: điền CLOSE-beat (timestamp + verdict + harvest path).
  3. Đánh-dấu aborted nếu run bỏ-dở: verdict = ⚠️ ABORTED — <lý-do>, ghi rõ phần nào hoàn-thành (recover qua git/disk/prod truth, KHÔNG tin agent return-message).

C7 — 🔴 CAVEAT trung-thực (no-overclaim)

  • Engine no-fs → scaffold KHÔNG tự-động. hmw.js (JS-sandbox no-filesystem) KHÔNG tạo được folder/file. Run-trace dựa 100% vào em-main: scaffold run.md @P1 (C2) + tự ghi <stage>-synthesis.md mỗi run (C4). Không có cơ-chế nào ép tạo file. NOT fully-autonomous — đây là hard-gate-trên-INPUT (em main tự dựng khung + tự bơm tham-số đầu/cuối mỗi run), KHÔNG phải engine tự-động.
  • Cấu trúc phẳng giảm fragile từ 2 → 1, KHÔNG triệt-tiêu. Bỏ subfolder xoá được điểm-hay-quên "dựng sẵn sub-md/+harvest/" (engine giờ ghi 1 cấp, no subfolder-to-forget). NHƯNG còn dư-lượng: em-main VẪN phải nhớ ghi <stage>-synthesis.md mỗi run (close-gate L3 bắt nếu thiếu). Điểm-yếu giảm 1-trong-2, chứ không biến mất → C2 vẫn bắt-buộc.
  • 3-layer = LƯỚI, KHÔNG khoá-cứng-cùng-lúc-fire. L1/L2/L3 bắt lỗi sau khi việc đã xảy ra (post-hoc) hoặc nhắc dựa-trên-input em-main-bơm — giảm xác-suất sót, KHÔNG chặn tại-đúng-thời-điểm-fire. Phòng-thủ-nhiều-lớp, KHÔNG bảo-đảm tuyệt-đối.
  • G-015 no-overclaim — TRACKED ≠ read-only-ENFORCED. Run-folder git-tracked KHÔNG biến sub thành read-only: sub vẫn giữ Bash (write-channel mở — ghi-ngoài-repo git-diff mù / curl Qdrant). Containment THẬT (model dưới) = em-main single-writer + git-diff(in-repo) + chunk-count(RAG), defense-in-depth — KHÔNG sandbox cứng, KHÔNG claim "ENFORCED".

C8 — MIGRATION (run cũ giữ subfolder · close-gate chấp-nhận CẢ 2 dạng)

🔴 KHÔNG viết lại lịch-sử. 5 run-folder S71 đã chốt giữ NGUYÊN cấu trúc cũ sub-md/ + harvest/ (đã commit, KHÔNG đụng):

2026-06-18-h10-invest/      (run.md + sub-md/ + harvest/invest-synthesis.md)     ← cũ, GIỮ
2026-06-18-h10-implement/   (run.md + sub-md/ + harvest/implement-synthesis.md)  ← cũ, GIỮ
2026-06-18-h10-review/      (run.md + sub-md/ + harvest/review-synthesis.md)      ← cũ, GIỮ
2026-06-18-h910-finalize/   (run.md + sub-md/ + harvest/finalize-synthesis.md)   ← cũ, GIỮ
2026-06-18-h910-curate/     (run.md + sub-md/ + harvest/curate-synthesis.md)     ← cũ, GIỮ
2026-06-18-harness-audit-invest/  (run.md + audit-synthesis.md)                  ← 🆕 FLAT
  • Run MỚI từ refine 06-18 → dùng FLAT (sub-<role>-<i>.md + <stage>-synthesis.md cùng cấp). Run CŨ → để yên (đừng gom-lên-cấp/đừng xoá subfolder — re-writing history vô-ích + làm bẩn git-log).
  • 🟢 Close-gate (L3) ACCEPT BOTH suốt giai-đoạn chuyển: verify gom ở harvest/<stage>-synthesis.md (dạng cũ) HOẶC <stage>-synthesis.md phẳng (dạng mới). Không fail run cũ chỉ vì thiếu file-phẳng.
  • 2 nấc track (C3) áp cho CẢ 2 dạng: check-ignore exit!=0 + ls-files non-empty.

Containment model (PHẢI khớp _ledger.md + ../hmw.js — đồng-bộ 3 chỗ: đây · _ledger.md · ../hmw.js)

Run-folder runs/<run-id>/ được git TRACKED → mọi write HIỆN trong git-diff = audit trực-tiếp. Containment: tracked-change NGOÀI runs/<run-id>/ VÀ NGOÀI code-disjoint đã giao = vi-phạm (thay model Harness-2 B6 "mọi tracked-change = vi-phạm"). G-015 no-overclaim: TRACKED ≠ read-only-enforced — sub vẫn giữ Bash (write-channel mở), containment THẬT = em-main single-writer + git-diff(in-repo) + chunk-count(RAG).


Anti-bypass detector — SE TAILORED-OUT (quyết-định có chủ-đích, anh chốt)

Refine 06-18 (b) đề-xuất làm-chặt một bộ-dò chống-lách-engine (soi nhật-ký/mã xem có run nào né engine chuẩn không) theo 3 chức-năng. SE quyết-định KHÔNG hiện-thực bộ-dò này — đã CÂN-NHẮC và thấy N/A cho threat-model của SE. Giữ trung-thực, KHÔNG overclaim "đã có anti-bypass detector".

Lý-do tailored-out:

  • SE chạy workflow qua Anthropic Workflow tool (hmw.js invoke), KHÔNG có bề-mặt-lách kiểu CLI-launcher. AI_INFRA threat-model giả-định một node-CLI launcher (đường-vòng chạy lén engine) cần bộ-dò canh. SE không có launcher như vậy → không có "đường-vòng" để dò.
  • Containment SE đã đủ bằng cơ-chế khác (G-015 defense-in-depth): git diff commit-gate (mọi write tracked HIỆN trong diff) + run-folder git-tracked (audit trực-tiếp) + _ledger.md orphan-scan (L2/L3) — backstop THẬT (không phải prompt). Bộ-dò pattern-match thêm = trùng-lặp, không bịt lỗ mới.

3 chức-năng refine — CÂN-NHẮC rồi N/A cho SE:

Chức-năng refine (b) Áp SE? Vì sao
(1) Whitelist launcher hợp-lệ N/A SE không có launcher-wrapper quanh engine → không có gì để whitelist.
(2) Khớp đa-dạng biến-thể path tới engine N/A SE invoke engine qua Workflow tool (1 đường duy-nhất), không có path-variant để khớp.
(3) Neo KHOÁ-khởi-chạy-thật (đừng match tên-engine lẫn trong script) + acceptance theo QUAN-HỆ N/A Không có log-scan detector → không có chỗ neo launch-key. Acceptance-by-relation (hợp-lệ ≠ vi-phạm, hợp-lệ tăng dần OK) là nguyên-tắc tốt nhưng chỉ áp được khi CÓ detector.

🔴 No-overclaim: SE KHÔNG claim đã adopt anti-bypass detector. SE claim: đã đọc + cân-nhắc 3 chức-năng, chọn tailored-out vì threat-model SE không có CLI-launcher-bypass-surface; containment dựa git-diff + run-folder-tracked + ledger-orphan-scan (G-015). Nếu sau này SE thêm launcher-wrapper → re-visit quyết-định này.