Files
solution-erp/.claude/commands/check-email.md
pqhuy1987 24483935cb [CLAUDE] Docs: S148 — session-model port form hub + /check-email 4 cửa + Sàn-3 dual-accept
Session-model (owner chốt "đối ứng đúng chính xác như hub"):
- Form hub: _context-s-<N>.md (STOCK-map + FLOW append-only + STOCK-touched)
  + _pause-<i>/_tiep-<i> marker 5-trường + _snapshot-<i> + _end (thay closed.md)
- Port /snapshot + scripts/session_scaffold.py (near-verbatim)
  + scripts/session_ctx.py TRIMMED CÓ KHAI (chỉ machine-block + secrets-sweep;
    KHÔNG port jsonl/overhead/cap-getter vì chưa có caller = ghost-wire)
- session-2 migrate sang form hub; session-1 giữ legacy (FROZEN)

Sàn-3 ORPHAN-L:
- DUAL-ACCEPT hub + legacy; glob pause-* KHÔNG khớp _pause-1.md nên không đếm đôi
- VÁ bug có sẵn từ S146: chốt-kết ĐÓNG TRỌN thư-mục (bản cũ c=1 chỉ tha 1 pause,
  lệch chính câu session-end §6.3-bis vẫn nói "mọi pause")
- Fault-inject 10/10 hai chiều + anti-Goodhart

/check-email:
- Wire 4 CỬA phiên (session-start/tiep/session-end/pause), 2 CHẾ-ĐỘ:
  DÒ ~5ms ở cửa dừng-nối (ràng buộc BINDING hub goi-chot §3) ⟂ KÉO ở bookend
- DÒ quét 2 kênh + định tuyến: outbox/se -> /check-email · outbox/all -> /adap-apply
- STAGE-2: 10 thư fan-out verify 2 tuyến 10/10 -> inbox/ai_infra/; backlog root = 0

HANDOFF re-stamp: #1 ĐÓNG (trio đã chạy S144) · #2 đổi trục · #3 anh chốt (a)
+ 4 mục mới (13)-(16); carry #15/#17 đóng, #16 đóng nửa (khai rõ vế còn hở)

H24 tick S147->S148: counter 21->22 CLEAN

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

11 KiB
Raw Blame History

description, argument-hint
description argument-hint
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). <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 /pausecả 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 /tiepphầ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: (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í
(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) 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 đó.

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 đọ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 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 VERBATIMbroadcasts/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>.mdinbox/<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.