Files
solution-erp/.claude/commands/check-email.md
pqhuy1987 a3776eaac4 [CLAUDE] Docs: thi hanh tron plan adap dot-2 (P2/P3/P5/P7i + W4 + khoan 5/6)
Chu du an chot 6 cau @S181; so quyet-dinh o
runs/2026-08-07-S180-adap-upgrade-pack-phased/owner-decisions-07-08-2026-dot-2.md

- P2=PB-2 sua luat da ratify du 2 SITE (tiep.md §3-bis canonical + pause.md
  b6 chi TRO). Cau cam san-3 GIU NGUYEN, chi them ranh REQUEST ⟂ TASK.
- W4: docs/governance/so-yeu-cau-chu-du-an.md 3 khoi, ma YC/ST/PN vinh vien.
  Config: tiep_reload.sources 8->9 + owner_request_verbatim_char_cap.
  nhip-no-probe ve-5 "so-yc treo/nhac2+", fault-inject 5/5, phan biet
  chua-co-du-lieu ⟂ treo 0. Ky luat ghi-NGAY + A5 cam CLAUDE.md + rules.md §6.0.
- P5: ACTIVE-MARKS §LT3 luat tu-tri 3 bac + mark RC-...-07-08-2026-20-57-48.
- P7(i): docs/governance/expensive-runs-view.md derive-view 5 cot.
- P3=B: niem phong _sealed_P3B_S181 (forward-only). Phep thu A10 da co rang
  (fault-inject: class tu che => exit 2; class hop le => exit 0).
- Khoan 6: scripts/naming-baseline.json = NGUON, script chi doc.
  Fault-inject 6/6 hai chieu. 7/7 baseline xanh. 0 byte non-ASCII.
- Khoan 5: broadcasts/_index.md +cot "ap" cuoi hang, backfill 42/4/23 = 69.
- W3 acceptance 6/6 dong + va defect con-tro bang-19-cua (view-stale-status).

Con treo: P8/W4b, W5, P7 ve (ii), VK-5, P3 hoi-to hay forward-only.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 21:25:50 +07:00

91 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
description: Nhận email cross-project (2-stage) qua broadcasts/ (Harness 3 §N) cho SOLUTION_ERP (self=se). Verify hash đối chứng. §J2. Adopt AI_INFRA Harness 3 (2026-06-07).
argument-hint: <from_project | all>
---
# /check-email <from_project> — nhận email cross-project (Harness 3 · self=`se`)
> 🔴 Kênh DUY NHẤT (§N) · **pull-copy** chỉ ghi repo MÌNH (§J2). self=`se`. Path map: xem `send-email`. Detail: AI_INFRA `broadcasts/README.md` §Harness 3.
## Tham số
- `$1` = from_project (BẮT BUỘC) ∈ 6 others, hoặc `all` = quét cả 6.
## Nhịp chạy — 🔴 4 CỬA PHIÊN (owner chốt S148, 2026-07-24)
> 🔴 **Đây là NHÀ CANONICAL của "khi nào chạy `/check-email`".** 4 file lệnh cửa **chỉ TRỎ vào đây** rồi gọi lệnh; **CẤM chép luật sang** (B1 — chép 4 nơi = 4 nguồn sự-thật).
**Anh chốt @S148:** *"mỗi session end/start luôn — vì 1 session giờ có thể kéo dài 2-3 phiên qua 2-3 ngày."*
⇒ nhịp neo vào **SỰ-KIỆN PHIÊN**, **KHÔNG** vào đồng-hồ ngày. Lý-do anh nêu là lý-do kỹ-thuật đúng: một phiên-LOGIC trải nhiều cửa-sổ nhiều ngày ⇒ ngưỡng-theo-ngày **không map** được vào nhịp làm việc thật.
🔴 **Vì sao 4 cửa chứ không 2 — lead MỞ RỘNG từ câu chữ, khai thẳng để anh bác được:** cửa VÀO có 2 và cửa RA có 2.
| | cửa-1 | cửa-2 |
|---|---|---|
| **VÀO** | `/session-start` (phiên mới) | `/tiep` (nối phiên-logic) |
| **RA** | `/session-end` (đóng sổ) | `/pause` (dừng chủ-động) |
Chỉ cắm 2 cửa `session-start`/`session-end` thì **đúng ca anh đang lo VẪN LỌT**: phiên S148 vào bằng `/tiep`, phiên trước ra bằng `/pause`**cả hai lần đều không check**. Mà chính câu *"1 session kéo 2-3 phiên"* hàm ý các phiên GIỮA vào bằng `/tiep`**phần lớn cửa nằm ở nhánh `/tiep`**, không ở `/session-start`. Phủ 4 cửa mới đạt được điều anh nói.
### 🔴 HAI CHẾ-ĐỘ — sửa @S148 sau khi đọc thư `goi-chot-owner-nam-khoan` khoản 3 (BINDING)
> **Lead tự bắt vi-phạm của chính mình:** bản đầu @S148 cắm **PULL đầy-đủ** vào cả 4 cửa. Thư hub `2026-07-19-Governance-goi-chot-owner-nam-khoan` §3 là **ràng-buộc thiết-kế CỨNG**, verbatim: *"bất kỳ van/gate/phép-đo nào về sau cũng **KHÔNG ĐƯỢC** chặn hoặc làm chậm các cửa **dừngnốicheckpoint**"*, floor: *"bước nào nặng (spawn agent, đo đạc lớn, **quét rộng**) đang nằm trong đường pause-tương-đương là **vi-phạm**: dời nó về **closeout/bookend**"*. ⇒ `/pause` + `/tiep` **là đúng 2 cửa đó**.
> 🔴 **Hub bắt ĐO chứ không đoán** (SELF-CHECK: *"Đo wall-clock một lần — điểm dừng phải rẻ"*). **Đo @S148, 3 lượt:** **dò** (list 6 repo + so id) = **66ms lạnh / 45ms nóng**; **kéo** (copy + hash + `python stamp_verify.py`) = python-startup **~200500ms × số thư**. ⇒ **dò KHÔNG nặng, kéo MỚI nặng.** Nên vá đúng là **tách 2 chế-độ**, KHÔNG phải bỏ cửa — bỏ cửa sẽ mất đúng thứ anh cần (phiên giữa vào bằng `/tiep`).
| chế-độ | cửa | làm gì | chi-phí |
|---|---|---|---|
| **DÒ** (detect-only) | `/tiep` · `/pause` | list + so id → in `thu-moi: se=X all=Y`. 🔴 **KHÔNG copy · KHÔNG hash · KHÔNG python.** X hoặc Y > 0 ⇒ nêu **1 dòng** rồi đi tiếp, để bookend kéo | ~5ms |
| **KÉO** (đầy-đủ) | `/session-start` · `/session-end` | `se>0`**`/check-email`** STAGE 1 (copy + verify 2 tuyến + log `_index`) · `all>0`**`/adap-apply`** | theo số thư |
🔴 **DÒ PHẢI QUÉT CẢ HAI KÊNH — đây là kẽ thật, và nó nằm ở NHỊP chứ không ở tool:** `outbox/se` (directed, → `/check-email`) **VÀ** `outbox/all` (fan-out, → `/adap-apply`). Không có nhánh `all` thì **10 broadcast đợt adap-11 nằm im 5 ngày** (07-18→07-23) — ca đã xảy ra thật, không phải giả-định. **DÒ chỉ ĐẾM và ĐỊNH TUYẾN, không kéo** ⇒ vẫn rẻ.
🔸 **Watermark cho `outbox/all`:** bỏ qua id ≤ **`2026-07-15`** — 51 file mốc 06-02→07-15 là lớp *đã-adopt-đọc-tại-chỗ* (`/adap-apply` đọc thẳng bên AI_INFRA, **KHÔNG đòi copy** ⇒ vắng mặt trong inbox là **BÌNH THƯỜNG**, không phải nợ). Không có watermark thì mỗi lượt DÒ kêu 51 cái rồi tự bị bỏ qua.
🔒 **Bất-biến:** việc NẶNG chỉ sống ở **bookend**. Ai thêm bước vào đường `/pause`·`/tiep` sau này **phải đo wall-clock trước**, đúng câu hỏi hub đặt: *"có làm điểm dừng đắt lên không"***TRƯỚC** khi bàn giá-trị của bước đó.
## BƯỚC 0 — TIỀN KIỂM ĐẦU CỬA (chỉ đọc, chi phí ~0, **KHÔNG chặn**)
🔴 Chạy **TRƯỚC** DÒ/KÉO: `powershell.exe -ExecutionPolicy Bypass -File scripts/tien-kiem-cua.ps1 -Cua check-email` → in **1 dòng** `TIEN-KIEM: …`.
🔴 **KHÔNG CHẶN** — lỗi ⇒ `tien-kiem loi (khong chan)` → đi tiếp; máy **luôn `exit 0`** (cổng chặn = W3b, chưa chốt).
🔸 Chọn cửa đóng gần nhất bằng **dấu thời gian TRONG tệp**, không tin `mtime`. `THIEU-TAP` = 0/2 nguồn đọc được, **cấm đọc thành "sạch"**. Nhãn bước lệch: `docs/governance/ritual-labels.md`.
🔸 **Đã tuân bất-biến `:41` ngay trên:** wall-clock đo TRƯỚC khi cắm (S180 W3) — ròng **~194 ms**, rẻ hơn `nhip-no-probe.ps1` (**~281 ms**) vốn đã được chấp nhận ở `/pause`·`/tiep`. **KHÔNG cắm bước này vào `/pause`·`/tiep`** (hai cửa đó đã có probe; thêm nữa là làm điểm dừng đắt lên).
**Cách chạy ở mỗi cửa — `/check-email all`:**
- 🟢 **Không có thư mới ⇒ 1 dòng, im lặng đi tiếp.** KHÔNG báo-cáo dài, KHÔNG chờ anh.
- 🔴 **FAIL-SOFT, CẤM chặn nghi-thức:** lỗi bất-kỳ (repo bên kia không có trên máy · path đổi · thiếu python) ⇒ in `check-email loi (khong chan)` rồi **ĐI TIẾP**. Cùng khuôn `nhip-no-probe.ps1`: một bước MỚI **không bao giờ được phép** làm hỏng nghi-thức đã chạy tốt.
- Có thư ⇒ chạy trọn **STAGE 1** (copy + verify hash). **STAGE 2** (move → `processed`) đi theo việc xử-lý, **KHÔNG ép** trong cùng lượt.
**Quan-hệ với vế-4 `pull-cach` (`nhip-no-probe.ps1`) — ĐỔI VAI:** trước định làm **chuông báo** (cần ngưỡng `pull_warn_days`). Nay 4 cửa là cơ-chế CHÍNH ⇒ `pull-cach` thành **chỉ-báo sức-khoẻ của chính nghi-thức**: số ngày cứ leo trong khi phiên vẫn mở/đóng đều đặn ⇒ **nghi-thức đang bị chạy tắt**, chứ không phải hub im. 🔒 **`pull_warn_days` CỐ Ý để TRỐNG** — anh không đặt số @S148, và script cấm tự chế mặc-định.
🔸 **Giới-hạn giữ khai (đo @S148):** vế-4 mạnh với **quãng im DÀI**, yếu với **trễ-kéo NGẮN** — ca hub-gửi-giục 07-18 chỉ `N=2` mới bắt, mà `N=2` nằm ngay trên trung-vị ⇒ kêu gần như liên-tục. Đừng kỳ vọng `pull-cach` chặn tái-diễn ca đó; **4 cửa mới là thứ chặn nó.**
## Quy trình 2-STAGE (audit qua folder)
**STAGE 1 — Nhận (đọc → inbox root, PENDING):**
1. Validate `$1`.
2. READ `<from>/broadcasts/outbox/se/*.md` (message gửi **đích danh** se).
🔴 **CHỈ `outbox/se` — ĐÚNG, đừng "sửa" thành đọc cả `outbox/all`.** Hai kênh, hai tool, hai sổ:
| kênh | nội dung | tool kéo | sổ theo dõi |
|---|---|---|---|
| `outbox/se/` | thư **directed** (`to: se`) | **`/check-email`** (file này) | `broadcasts/_index.md` §INBOUND |
| `outbox/all/` | **fan-out** (`to: all-fit`) | **`/adap-apply`** ([`adap-apply.md:14`](adap-apply.md) đọc **thẳng tại chỗ**) | **KHÔNG** vào `_index` — xem header `_index.md` dòng 7 |
🧊 **Vết sai @S148 — giữ làm bài học:** lead đọc `C14-disposition-per-khoan.md:21` (@S144) khai *"kẽ đã bịt: `/check-email` bước 2 chỉ đọc `outbox/se`, không nhắc `outbox/all`"***tin bản tóm-tắt** → sửa bước này thành đọc cả 2 kênh. **Sai:** `outbox/all` chưa bao giờ là việc của `/check-email`. Kiểm ngược bằng máy: **22/22** thư `outbox/se` đều có dòng `_index`, **thiếu 0** ⇒ tool này vốn **không hề thủng**. 🔴 **Hai lỗi chồng nhau, cả hai đều là *tin chữ thay vì đo*:** C14 tuyên "đã bịt" một kẽ **không tồn tại**, rồi lead vá một tool **không hỏng**.
🔴 **Kẽ THẬT nằm ở NHỊP, không ở tool:** không cửa phiên nào **dò** `outbox/all` ⇒ 10 broadcast fan-out nằm im **5 ngày**. Vá đúng = **DÒ 2 kênh ở cửa phiên rồi ĐỊNH TUYẾN** (§"Nhịp chạy" trên), KHÔNG phải nhét kênh này vào STAGE 1 của tool kia.
3. Mỗi file CHƯA có trong inbox (so id): **COPY VERBATIM**`broadcasts/inbox/<id>.md` (**root = pending**). [repo MÌNH §J2]
4. **Verify đối chứng:** (a) **whole-file** `Get-FileHash` copy == nguồn (byte-identical = tuyến CHÍNH); (b) **body** recompute `SHA256(body)` == `content_sha256` khai ở frontmatter.
**4(b) — đầu-đọc stamp KHOAN-DUNG (adopt S141, ghim S142):**
- 🔴 **ƯU TIÊN chạy SCRIPT, đừng tự chế lệnh rút hash:** `python scripts/stamp_verify.py <file>`**bản port LOCAL trong repo này** (KHÔNG trỏ hub-path `AI_INFRA/scripts/...` nữa; hub-path chỉ còn là nguồn **re-pull** khi hub đổi §N canon). Script in `declared / canonical / no-strip` + verdict; **exit 0 = OK**, exit 1 = có MISMATCH. Nó còn tách được `WRONG-METHOD` (stamp bằng biến-thể no-strip) khỏi `MISMATCH` thật — thứ mắt thường không phân biệt nổi.
- **Rút hash declared — PIN mẫu KHOAN-DUNG:** `content_sha256:\s*"?([0-9a-fA-F]{8,64})"?` — phủ **CẢ 3 dạng đang sống trên đĩa**: (i) **có-ngoặc** `content_sha256: "abc..."` · (ii) **không-ngoặc** `content_sha256: abc...` · (iii) **rút-gọn ≥8-hex** (so bằng **tiền-tố**, KHÔNG đòi bằng độ-dài).
- 🔴 **CẤM mẫu quote-strict `content_sha256:\s*([0-9a-fA-F]+)`** — nó **whiff ngay ký-tự `"` đầu tiên** ⇒ hash có-ngoặc rút ra rỗng ⇒ đọc thành "không khớp" ⇒ **FALSE-TAMPER**. Bẫy ĐÃ GẶP, không phải giả-định: S141 suýt kết oan tamper cả ba trên ba thư mà cả ba đều lành. Mẫu chặt hơn ở đây **KHÔNG** an-toàn hơn — nó chỉ đổi lỗi "bỏ sót" thành lỗi "vu oan".
- **Body canonical** (khớp ĐÚNG `scripts/stamp_verify.py`): `$txt=[Text.Encoding]::UTF8.GetString([IO.File]::ReadAllBytes($f)) -replace "^\uFEFF",""; (($txt -replace "\r","") -split "(?m)^---\s*$",3)[2] -replace "^\n",""` → SHA256-UTF8. 🔴 **CẤM `Get-Content -Raw` cho hash** — PS 5.1 đọc UTF-8-no-BOM bằng ANSI → mojibake → **false-tamper** (S125).
- ✗ → **nghi VERIFIER TRƯỚC** (chạy `python scripts/stamp_verify.py <file>` + test 1 sibling known-good; verifier fail cả sibling ⇒ lỗi tool, KHÔNG phải tamper); vẫn ✗ → **flag tamper, KHÔNG move**, báo anh.
5. Log `_index.md` §INBOUND: `received · id · <from> → se · status=pending · folder=(root) · sha256(12) · verify=✓`.
**STAGE 2 — Xử lý xong → archive (PROCESSED):**
6. Sau khi xử lý → **MOVE** `inbox/<id>.md``inbox/<from>/<id>.md`.
7. Update `_index.md`: `status=processed · folder=<from>`.
## Audit (anh)
`ls broadcasts/inbox/*.md` (root) = **pending chưa xử lý** (backlog hiện ngay) · `inbox/<proj>/` = **đã xử lý**.
## Luật
🔴 §N single-channel · 🔴 §J2 pull-copy chỉ-ghi-inbox-MÌNH (KHÔNG push repo bên kia) · **KHÔNG sửa** file copy (bằng chứng) · PHẢI committed · verify-hash trước move.