All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m16s
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>
138 lines
16 KiB
Markdown
138 lines
16 KiB
Markdown
# `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 diff` → **audit 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-*` và `*-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:
|
|
|
|
```bash
|
|
# 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.
|