Files
solution-erp/.claude/workflows/runs
2026-08-08 12:11:52 +07:00
..
2026-08-07 17:01:30 +07:00
2026-08-07 17:01:30 +07:00

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. (🧊 sổ _ledger.md 2-nhịp RETIRED H18-B S100 — đo bắt-thật 0/15 lifetime + mode-A coverage 0/8; orphan-authority = folder-scan L1/L2 dưới.) 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🧊 retired H18-B S100 (KHÔNG ghi beat mới; ledger frozen giữ lịch-sử. Orphan-authority = folder-scan L1/L2).
  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).


taskList snapshot (H22 — ghi TRƯỚC launch)

Sàn WAL-cho-workflow (Harness-22 S111) — chống đốt-lại-token + mất-memory khi chết GIỮA workflow. Điều-kiện áp: run WAL-hóa = ≥3 task HOẶC ước chạy >5 phút (khớp ../README.md FLIP-policy) → BẮT BUỘC RUN-TRACE + 2 vật-liệu dưới ghi xuống đĩa TRƯỚC/NGAY-SAU launch:

  • Section ## taskList snapshot trong run.md — ghi TRƯỚC khi phóng. Mỗi run.md PHẢI có section này liệt-kê từng task sắp phóng: (role · label · prompt-gist 1-dòng) — đủ vật-liệu để /tiep relaunch-cắt-gọt các task CÒN LẠI mà KHÔNG cần transcript cũ. (= "snapshot tham-số" mục ⑤ broadcast H22: ghi {danh-sách-task · spec} xuống đĩa trước launch.)
  • Dòng WAL wf: (5 trường) — ghi NGAY SAU launch vào .claude/WAL.md, lead điền runId khi engine trả về: wf:<mục-đích> run=<run-folder> runId=<id|pending> args=<snapshot-ref> done=<k>/<N> harvested=<yes|no|partial>run= trỏ runs/<run-id>/; args= trỏ section ## taskList snapshot trong run.md (KHÔNG nhét spec dài vào WAL); done=<k>/<N> + harvested=partial cập-nhật khi harvest-liền mỗi task xong.
  • 🔴 memory-pack KHÔNG snapshot (X6): re-derive TƯƠI lúc /tiep — snapshot memory-pack cũ sẽ lỗi-thời sau khi đã harvest phần đã-xong.

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 folder-check (🧊 ledger-check retired H18-B S100) em-main @P1, lúc mở run mới (TRƯỚC scaffold) scan runs/*/: nếu run TRƯỚC còn folder có run.mdthiếu <stage>-synthesis.md (hoặc synthesis 0-byte) → gom + đóng nó TRƯỚC khi mở run mới. (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 = folder có run.md mà KHÔNG có <stage>-synthesis.md (hoặc synthesis 0-byte) → báo + giải-quyết. (🧊 tiêu-chí ledger- retired H18-B S100; run cũ S71 dual-accept harvest/<stage>-synthesis.md.)
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) — 🧊 RETIRED H18-B S100 (nguyên-văn dưới GIỮ làm lịch-sử — dời-đi không xoá; orphan-authority = folder-scan C5 L1/L2; đảo-ngược = gỡ marker này + marker _ledger.md header + restore mandate C2-step-2)

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".
  • 🔴 ĐIỂM MÙ CỦA CHÍNH VAI ĐIỂM DANH — vai điểm danh KHÔNG tự soi được mình (khoản sàn GĐ-2(v), adopt S180/W2). Vật chứng của một vai sinh ra SAU khi vai đó chạy xong; nên bất kỳ vai nào đi điểm danh vật chứng — kể cả scripts/artifact-integrity.ps1, kể cả ring2-audit — đều không nằm trong phạm vi tự soi của chính nó. Một lượt soi đơn độc luôn để hở đúng phần cuối cùng nó vừa đẻ ra. Phủ chỗ hở đó cần hai chân, thiếu chân nào cũng hở: (a) vai thứ hai CÙNG PHIÊNcloseout-sentinel.ps1 chạy cặp {harvest-curator, tooling-auditor} vô-điều-kiện, và ring2-audit PIN đích danh run-folder tươi (cấm glob-latest), chính chữ "pin đích danh" là thứ cho phép vai-sau soi vật-chứng-của-vai-trước; (b) lượt soi ở ĐẦU PHIÊN SAU — bookend @open (session-start.md) bắt phần lọt qua đêm. 🔸 Khai thẳng chân (b) đang YẾU, đo được, đừng đọc thành đã-đủ: nhịp thì có, chỉ thị thì không. Đo 2026-08-07: grep -cE 'run-folder|runs/' .claude/agents/lead-stale-auditor.md = 0 (control-dương cùng tệp: grep -c FLAG = 4 ⇒ lệnh chạy đúng, 0 là 0 THẬT); lead-gap-auditor.md = 1 hit, mà hit đó là dòng mô tả lớp gap-incident-unrecorded (:39), không phải lệnh đọc run-folder phiên trước. ⇒ cặp bookend có chạy đúng nhịp nhưng spec của cả hai vai không hề bảo chúng soi RUỘT vật chứng lượt chạy phiên trước. Cái đang phủ (b) trên thực tế chỉ là closeout-sentinel M5 (delta thư mục vai) + nhip-no-probe run-chua-gomcả hai đều không đọc ruột tệp. Nợ này có tên, giao gói-B persona của W3; tới khi nó đóng, đừng ghi (v) là đã phủ trọn.

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 ../hmw.js — đồng-bộ 2 chỗ: đây · ../hmw.js; 🧊 chỗ thứ-3 _ledger.md retired H18-B S100, header nó giữ bản frozen)

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) + folder-scan orphan L1/L2 (🧊 ledger-scan retired H18-B S100) — 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.