135 lines
15 KiB
Markdown
135 lines
15 KiB
Markdown
---
|
||
description: /tiep — recovery MỘT đường cho MỌI kiểu gián-đoạn (Harness-22 WAL session-continuity). §0 = NHÀ CANONICAL của Sàn-3 "sổ trống ≠ sạch" (3 bậc + DUAL-ACCEPT orphan, dạng-3 retired S123; session-start BƯỚC 0.7 chỉ TRỎ vào đây, không chép). Rồi đọc .claude/WAL.md → chạy verify + git status → ground-truth thắng → nối chain từ next; mục wf: → relaunch workflow ĐÃ-CẮT-GỌT. Cặp với /pause.
|
||
argument-hint: (không tham số)
|
||
---
|
||
|
||
# /tiep — recovery MỘT đường cho MỌI kiểu gián-đoạn (Harness-22 WAL session-continuity)
|
||
|
||
> Đây là **đường recovery DUY-NHẤT** để nối lại mạch việc dở sau **bất-kỳ kiểu gián-đoạn nào** — hết giới-hạn, crash, tắt máy, đổi tài-khoản, hay chết giữa một workflow. Gõ `/tiep` (kể cả khi user chỉ nói "làm tiếp" bằng text thường).
|
||
> Cặp với **`/pause`**. Đặt tên `/tiep` để tránh đè lệnh dựng-sẵn (`/resume`, `/continue`).
|
||
|
||
Thực-hiện **tuần-tự**: §0 (sàn) → §1 → §2 → §3 → §4.
|
||
|
||
---
|
||
|
||
## 0. 🔴 Sàn-3 canonical — **"sổ trống ≠ sạch"** (ĐỊNH-NGHĨA MỘT CHỖ DUY-NHẤT)
|
||
|
||
> 🔴 **Đây là định-nghĩa DUY-NHẤT của "còn việc dở không?".** `/session-start` **BƯỚC 0.7 chỉ TRỎ vào đây**, CẤM chép logic sang (B1 con-trỏ-canonical). Hai điểm-vào (`/tiep` + `0.7`) **PHẢI gọi cùng một định-nghĩa** — nếu không, hai đường sẽ trả lời khác nhau về cùng một sự thật.
|
||
>
|
||
> **Vì sao sàn này tồn-tại:** WAL trống **KHÔNG** hàm ý sạch. Suy thẳng *"chain rỗng ⇒ không có mạch dở ⇒ dừng"* là **BUG**, và nó **đã từng sống ngay trong chính file này** (`tiep.md:15` cũ) + `session-start.md:51` — lead mắc thật, không phải giả-định.
|
||
|
||
### Vì sao WAL trống không đủ: hook có **3 điểm mù**
|
||
|
||
`.claude/hooks/wal-flush.ps1:7` tự-commit **3 path** ở turn-boundary: `.claude/WAL.md` · `.claude/agent-memory/` · `.claude/workflows/runs/`.
|
||
⇒ Hai tín-hiệu trực-giác nhất — **"cây bẩn"** và **"có commit chưa đẩy"** — đều **MÙ đúng 3 vùng đó**: hook vừa dọn sạch cây, vừa biến việc-dở thành `wal:` commit trông như nhiễu.
|
||
⇒ Nên phải soi bằng **tín-hiệu hook KHÔNG chạm tới được**.
|
||
|
||
### 🔴 BẬC MẠNH — thấy **1 trong 4** ⇒ **HỎI LẠI ANH**, KHÔNG tự kết-luận sạch
|
||
|
||
| # | Tín-hiệu | Vì sao đáng tin | Lệnh |
|
||
|---|---|---|---|
|
||
| **①** | **Orphan run-folder**: `runs/<id>/` có `run.md` mà **không có bản-ghi-kết-quả** (xem DUAL-ACCEPT dưới) | **git-independent — miễn-nhiễm hook hoàn-toàn** (đọc đĩa, không đọc git) | xem block dưới |
|
||
| **②** | `origin/main..HEAD` có commit **KHÔNG** phải `wal:` | hook **không bao giờ sinh** loại commit này ⇒ có = người làm thật ⇒ không mù | `git log --format='%s' origin/main..HEAD \| grep -qv '^wal:'` |
|
||
| **③** | `closing:` treo trong WAL | = Sàn-2 sentinel (xem §0.b) | `grep -q '^closing:' .claude/WAL.md` |
|
||
| **④** | `wal:`-commit **chưa đẩy** có đụng `.claude/workflows/runs/` | 🔴 **thu-hồi một phần điểm mù**: dù `WAL.md` bị **xoá trắng**, **commit của chính hook vẫn tố-giác** rằng một run đã được dựng | `git log --name-only --format='%s' origin/main..HEAD \| grep -q 'workflows/runs/'` |
|
||
|
||
#### ① DUAL-ACCEPT — 2 dạng bản-ghi-kết-quả TÍNH LÀ ĐÓNG *(dạng-3 RETIRED @S123 — xem dưới)*
|
||
|
||
> 🔴 **Nấc chuẩn (S122):** câu hỏi là **"đã harvest chưa"** — một câu hỏi về **NỘI DUNG**. Nếu chỉ đo **TÊN FILE** thì detector đo *cái dễ đo*, không phải *cái cần đo*. Đo thật @S122: **8 dương-giả / 25 run = 32%**, trong đó folder **ghi chép đầy-đủ nhất** (`pe-negative-quote`: có cicd PASS + bundle-hash + smoke 200 + 6 stage `[x]`) **vẫn** bị xếp orphan. ⇒ nhận dạng-2 là làm detector **ĐÚNG**, KHÔNG phải làm nó **dễ dãi**.
|
||
|
||
```bash
|
||
for d in .claude/workflows/runs/*/; do
|
||
[ -f "$d/run.md" ] || continue # không có run.md ⇒ không phải run ⇒ bỏ qua
|
||
found=0
|
||
# dạng-1 — file PHẲNG (hiện-hành, h10-refine). `-s` = tồn-tại VÀ khác 0-byte.
|
||
for f in "$d"/*-synthesis.md; do [ -s "$f" ] && found=1 && break; done
|
||
[ $found -eq 1 ] && continue
|
||
# dạng-2 — C8 legacy. VERBATIM `workflows/README.md:19`:
|
||
# "C8: 5 run cũ S71 (h10-invest…h910-curate) giữ sub-md/+harvest/ (đừng rewrite
|
||
# history); close-gate chấp nhận CẢ HAI dạng."
|
||
for f in "$d"/harvest/*-synthesis.md; do [ -s "$f" ] && found=1 && break; done
|
||
[ $found -eq 1 ] && continue
|
||
echo "ORPHAN: $d"
|
||
done
|
||
```
|
||
|
||
> 🧊 **dạng-3 RETIRED @S123 (anh chốt) — nhánh `grep -qiE '^#+[[:space:]]*synthesis' "$d/run.md"` đã GỠ.**
|
||
> **Đo trước khi gỡ, 2 phép độc-lập (harvest-curator + lead), khớp nhau:** bỏ nhánh dạng-3 ⇒ **0 folder** thành orphan. Lý do lộ ở đối-chứng: **cả 6 folder** từng dựa dạng-3 (`S112`×4 · `S113` · `S114`) **nay đều có flat `*-synthesis.md`** sau retro-harvest `22ea8c5` ⇒ dạng-1 bắt hết, dạng-3 **dư-thừa hoàn-toàn**.
|
||
> 🔴 **LUẬT retire (phát-biểu ĐÚNG — S123 review bắt bản đầu viết sai):** **gỡ một nhánh legacy khi tập di-sản của nó RỖNG; giữ khi CÒN người thụ-hưởng.** dạng-3 → **0 folder** ⇒ gỡ. dạng-2 → **5 folder** ⇒ giữ. Miễn-trừ C8 (*tha di-sản*) hết hiệu-lực **đúng lúc hết di-sản để tha**, không sớm hơn.
|
||
> ⚠️ **Bản đầu S123 viết lý-do là:** *"doc CẤM viết mới mà máy VẪN NHẬN ⇒ cấm-bằng-trí-nhớ ⇒ gỡ"*. **Nghe xuôi nhưng SAI** — reviewer áp thẳng nó cho **dạng-2**: `workflows/README.md` cũng ghi dạng-2 = *"legacy C8 — nhận, **cấm viết mới**"* ⇒ **cùng hình-dạng** ⇒ theo lý-do đó thì **phải gỡ luôn dạng-2** ⇒ **5 folder S71 thành orphan** ⇒ ép rewrite history mà **chính C8 cấm**. ⇒ **Lý-do viết ra ≠ lý-do thật đang vận-hành.** Bài: **áp luật vừa viết cho nhánh ANH EM — vỡ thì luật sai, không phải nhánh sai.**
|
||
> 🔸 **Hệ-quả phụ (thật, nhưng KHÔNG phải lý-do):** sau khi gỡ, luật và máy nói cùng một câu về dạng-3 ⇒ hết cần trí-nhớ để NÊU. Đó là **cái được**, không phải **cái biện-minh**.
|
||
|
||
> 🧪 **Block này ĐÃ fault-inject trên cây tạm — S122 9/9 PASS, RE-VERIFY @S123 sau khi gỡ dạng-3: 7/7 PASS**, chứng có RĂNG cả 2 chiều:
|
||
> **FLAG đúng** → orphan-thật · flat 0-byte · C8 0-byte · 🔴 **run.md có `## Synthesis` mà KHÔNG có flat** (ca này **S122 IM, S123 FLAG** — chính là hiệu-lực của việc retire).
|
||
> **IM đúng** → dạng-1 · dạng-2 · folder không có `run.md`.
|
||
> 🔴 Ca *"0-byte"* là ca **anti-Goodhart** — thiếu nó thì happy-path vẫn xanh mà sàn đã thủng.
|
||
> 🧊 2 ca S122 nay **hết nghĩa** (`dạng-3` IM · `"synthesis" giữa câu văn` FLAG) — cả hai đo nhánh đã gỡ. Giữ lại làm **chứng lịch-sử**, KHÔNG phải test đang chạy.
|
||
|
||
> ⚠️ **KHAI THẲNG 2 giới-hạn (đừng đọc thành "đã kín"):**
|
||
> 1. **Dạng-4 KHÔNG máy nào bắt được — lập-luận CÒN ĐÚNG, ví-dụ ĐÃ LỖI-THỜI.** Nhận dạng-4 = phải chấp-nhận "bất-kỳ run.md nào có vẻ nói về kết-quả" ⇒ **quá lỏng, thành vô-nghĩa** ⇒ dạng-4 **để nguyên cho người phán**, KHÔNG cơ-khí-hoá. Đây vẫn là **kẽ CÒN LẠI**.
|
||
> 🧊 **Nhưng ví-dụ minh-hoạ thì đã chết — đính-chính @S123:** bản S122 viết *"`pe-negative-quote` ghi kết-quả rải trong `## Stages` + `## wf run-id`… **không phải chuyện đã xử**"*. Đo lại: `22ea8c5`@**14:28** đã thêm `implement-synthesis.md` **8.249B** cho đúng folder đó ⇒ nay nó là **dạng-1**, máy bắt được. Mà câu văn kia viết ở `dfa3dae`@**14:48 — SAU 20 phút**. ⇒ **doc khai "chưa xử" cho đúng thứ chính tác-giả nó vừa xử xong** (stale-at-birth).
|
||
> 🔴 **Vì sao phải đính-chính chứ không xoá cả mục:** người đọc grep `pe-negative-quote` → thấy flat-file → kết-luận *"cảnh-báo này sai"* → **vứt luôn cái caveat còn đúng**. Ví-dụ chết kéo theo lập-luận sống. Đây là class **`acceptance literal tự-lão-hoá`** (S121): neo lập-luận vào một literal cụ-thể thì literal đổi là lập-luận mất uy-tín oan. **Bài rút ra: neo vào TÍNH-CHẤT** (*"run.md kể kết-quả mà không có heading `synthesis` nào"*), **đừng neo vào TÊN FOLDER**.
|
||
> 2. **Dual-accept = lưới PHÁT-HIỆN cho bản CŨ, KHÔNG phải giấy phép VIẾT bản MỚI.** Đúng khuôn C8 đã dùng sẵn (*tha di-sản, cấm viết mới kiểu cũ*). 🔴 **Run MỚI BẮT BUỘC ghi dạng-1** (`<stage>-synthesis.md` phẳng) — `workflows/README.md:17` thiết-kế **tên file mang nghĩa** (RAW `sub-` ⟂ VERIFIED `-synthesis.md`); dạng-3 phá đúng thiết-kế đó. Đo @S122: cùng ngày 07-12, `h22-wal-adopt` ghi dạng-1 còn `S112-*` ghi dạng-3 ⇒ **thói-quen không nhất-quán, KHÔNG phải migration**.
|
||
> ✅ **@S123 khoảng-cách doc-vs-máy này ĐÃ ĐÓNG:** trước đây doc *cấm* dạng-3 mà detector *nhận* ⇒ cấm bằng trí-nhớ. Nay **gỡ nhánh dạng-3** ⇒ luật và máy nói **cùng một câu**. Di-sản không kêu oan (6 folder cũ đều đã có flat), mà tái-sinh thì **máy bắt được ngay**.
|
||
|
||
### 🟡 BẬC TRUNG-BÌNH — nhiều file bẩn **NGOÀI** 3 path hook persist
|
||
|
||
🔴 **PHẢI loại nhiễu EOL TRƯỚC khi đếm** — repo có ~188 file dính EOL-only diff; không loại thì bậc này **LUÔN KÊU** ⇒ tự vô-hiệu-hoá.
|
||
Bẩn ngoài 3 path + không phải EOL-only ⇒ **NÊU**, hỏi lại nếu nhiều.
|
||
|
||
### ⚪ BẬC YẾU — bẩn thô (`git status --porcelain` khác rỗng)
|
||
|
||
Tín-hiệu **YẾU NHẤT**, dùng cuối. 🔴 **`porcelain` rỗng KHÔNG phải bằng-chứng sạch** — đo thật @S122: **git MÙ hoàn-toàn với thư-mục RỖNG**, nên 2 probe-dir tồn-tại trên đĩa suốt mà `porcelain` vẫn rỗng ⇒ **dương-giả**. Công-cụ quét-đĩa thấy, git không thấy.
|
||
|
||
### Kết-luận sàn
|
||
|
||
- Bậc MẠNH thấy **≥1** ⇒ **HỎI LẠI ANH** (nêu rõ tín-hiệu nào, đường-dẫn nào). **CẤM tự kết-luận "sạch".**
|
||
- **Cả 4 tín-hiệu MẠNH đều im** + WAL chain rỗng/toàn `[x]` ⇒ *mới* được báo "**không có mạch dở**" và **DỪNG SẠCH**.
|
||
|
||
## 0.b Sàn-2 — đọc sentinel `closing:` (self-heal)
|
||
|
||
- `session-end` ghi `closing: S<nn> @<ts>` vào WAL ở **BƯỚC 0** (trước mọi flush); xoá ở **`§6.4`**.
|
||
- ⇒ **Thấy `closing:` treo = phiên trước bị cắt GIỮA lúc đóng sổ** (không phải đóng xong).
|
||
- **Self-heal:** `closing:` treo **NHƯNG** cả 4 tín-hiệu MẠNH khác đều im + ground-truth sạch ⇒ **dọn dấu 1 lần, đi tiếp** (không bắt anh xử tay).
|
||
- `closing:` treo **VÀ** có tín-hiệu MẠNH khác ⇒ **HỎI LẠI**.
|
||
|
||
---
|
||
|
||
## 1. Đọc `.claude/WAL.md`
|
||
- Đọc file `.claude/WAL.md`.
|
||
- **Chain rỗng / toàn `[x]` / file không tồn-tại ⇒ 🔴 CHƯA ĐƯỢC KẾT-LUẬN GÌ.** Bắt buộc chạy **§0 bậc MẠNH** trước:
|
||
- Có tín-hiệu MẠNH ⇒ **HỎI LẠI ANH** (sổ trống nhưng đĩa nói còn việc — đúng ca sàn này sinh ra để bắt).
|
||
- 4/4 tín-hiệu MẠNH im ⇒ báo "**không có mạch dở**" và **DỪNG SẠCH**. KHÔNG bịa việc.
|
||
- *(🧊 Bản trước S122 suy thẳng "chain rỗng ⇒ dừng sạch" — **đó là bug**, chính là thứ Sàn-3 vá.)*
|
||
|
||
## 2. Đối-chứng ground-truth
|
||
- Chạy **TOÀN BỘ** lệnh trong `verify:`.
|
||
- VÀ đọc thêm `git status` + disk **run-folder liên-quan** — **per-turn ≠ per-task (N9):** các *return* của agent có thể mất khi phiên chết, NHƯNG file **per-agent trên đĩa vẫn còn**; nên đọc đĩa, đừng chỉ tin returns.
|
||
- So kết-quả thực-tế với `chain:`.
|
||
|
||
## 2.5 TICK counter + dòng-nợ (H24 — TICK TRƯỚC, dòng-nợ SAU; Item 1(b)+2 S135)
|
||
- **TICK** `.claude/governance/.session-counter.json` **theo contract** (idempotent — NO-OP nếu cùng nhãn-phiên/cùng HEAD) — 🔴 **CON-TRỎ `session-start.md §2.1.8`, CẤM chép logic tick** (B1 canonical). Nhãn `/tiep` = **nhãn-phiên MỚI** (label-convention §2.1.8) ⇒ tick fire NGAY cửa vào, OVERDUE @9 hiện tại đây thay vì đợi cuối phiên.
|
||
- **Dòng-nợ (SAU tick — n-3):** gọi `powershell.exe -ExecutionPolicy Bypass -File scripts/nhip-no-probe.ps1` in dòng-nợ 3-vế (vế-1 nhịp-kiểm đọc post-tick). 🔴 **probe KHÔNG chặn điểm dừng**: lỗi → in `probe-loi (khong chan)` → đi tiếp.
|
||
|
||
## 3. Ground-truth thắng WAL
|
||
- **LỆCH** (kết-quả `verify:` / `git status` mâu-thuẫn `chain:`) → **TIN GROUND-TRUTH**: sửa WAL cho khớp thực-tế, **báo chỗ lệch** cho user, RỒI MỚI chạy tiếp. KHÔNG mù-quáng chạy theo chain sai.
|
||
- **KHỚP** → thực-thi từ **`next:`**, nối chain theo thứ-tự các mục còn `[!]` / `[ ]`.
|
||
|
||
## 4. Mục `[!]` dạng `wf:` → nhánh recovery-workflow
|
||
Nếu mục dở là một dòng `wf:` (chết giữa workflow) → relaunch **ĐÃ-CẮT-GỌT**, KHÔNG chạy lại từ đầu:
|
||
1. Đọc **run-folder** + `## taskList snapshot` trong `run.md` (danh-sách-task + nội-dung spec đã snapshot lúc phóng).
|
||
2. Lấy **bằng-chứng task-nào-đã-xong** bằng cách **grep run-id trong log-phiên** (glob đường-dẫn — đây là grep ĐÍCH-DANH một chuỗi, **KHÔNG** nạp lại toàn-bộ transcript).
|
||
3. **Harvest-hồi-tố** phần đã xong: lead verify rồi append trí-nhớ, **đánh-dấu harvest partial-honest**.
|
||
4. **RELAUNCH** workflow chỉ với **các task CÒN LẠI** + memory-pack **DẪN-XUẤT-LẠI TƯƠI** (🔴 CẤM dùng snapshot memory-pack cũ — nó lỗi-thời sau khi đã harvest phần xong).
|
||
5. Resume-theo-run-id (nếu engine có) = **bonus CHỈ trong cùng phiên** (SAME-SESSION-ONLY) — 🔴 **CẤM claim nó chạy cross-session**; mặc-định dùng relaunch-đã-cắt-gọt.
|
||
|
||
Xong nhánh workflow thì vận-hành bình-thường tiếp (lead cập-nhật WAL sau mỗi subtask đổi trạng-thái).
|
||
|
||
---
|
||
|
||
🔒 **CẤM tuyệt-đối:**
|
||
- **CẤM giả-định** một bước đã xong nếu `verify:` KHÔNG chứng-minh.
|
||
- **CẤM nạp lại transcript cũ** — WAL + ground-truth (`verify:` + `git status` + đĩa) là ĐỦ; nếu thiếu thông-tin thì **HỎI anh**, đừng đoán.
|
||
|
||
ℹ️ **Field `session:`:** khác phiên hiện-tại là **BÌNH-THƯỜNG** — đó chính là use-case của `/tiep` (nối qua phiên / đổi acc). CHỈ cảnh-báo khi `updated:` **mới hơn cả lúc phiên hiện-tại bắt đầu** (dấu-hiệu có một phiên khác đang chạy song-song trên cùng repo).
|