HARVEST: GATE-FAIL-5

# sub-harvest-curator-open-S189 — H2 harvest-MD integrity @open (phiên-LOGIC L15)

> Vai: `harvest-curator` (H2, read-only + propose-only — single-writer = lead, B3 VERIFY→APPEND).
> Run-folder: `.claude/workflows/runs/2026-08-10-S189-bookstart-open/` · 2026-08-10 · vòng V1 @open.
> Kỷ-luật ghi: APPEND TỪNG MỤC ngay khi chốt (chống #53 — lượt return trước của tao bị cắt giữa câu, việc KHÔNG mất, đo lại từ đĩa).
> Kết thúc hợp lệ = dòng `== HẾT ==` ở CUỐI file (dùng, không phải nhắc).

**Verdict: GATE-FAIL — 5 finding** (2 HIGH · 1 MED · 2 LOW) · 5 trục: Coverage ❌FAIL · Completeness 🔶 · Fidelity ✅STRONG · Placement ✅ · Corruption ✅.

---

## 0. Số LEAD KHAI (`_end`) vs số TAO ĐẾM — đối chứng

Ba con số dưới đây là **lead khai**, không phải tao đo. Tao đếm lại từ đĩa:

| Khai (lead `_end`) | Tao đếm được | Khớp? | Lệnh tái-lập |
|---|---|---|---|
| S187 = **19 file + `implement-synthesis.md`** | **19** non-synthesis + **1** synthesis = **20** | ✅ **KHỚP CHÍNH XÁC** | `ls -1 runs/2026-08-10-S187-duyet-hd-tu-khkk/ \| grep -v synthesis \| wc -l` → 19 |
| S188 = **10 file + `bookend-close-synthesis.md`** | **13** non-synthesis + **1** synthesis = **14** | ❌ **LỆCH −3** → F-03 | `ls -1 runs/2026-08-10-S188-bookend-close/` → 14 dòng |
| @close S188 **"seed 12 diary"** | **12** `MEMORY.md` trong `c7b7ca45` | ✅ **KHỚP CHÍNH XÁC** | `git show --name-only --format='' c7b7ca45 -- '.claude/agent-memory/*/MEMORY.md' \| grep -c MEMORY.md` → 12 |

🔴 **"seed 12 diary" ĐÚNG ở tầng FILE nhưng KHÔNG có nghĩa "đã phủ hết vai đã chạy"** — xem F-01. Đây đúng loại bẫy tao tự dính @S181: đo **TÊN/SỐ FILE** ra đẹp, đo **VAI NÀO CÒN THỦNG** ra xấu.

---

## 1. COVERAGE — ❌ **FAIL** (14/18 vai = 78%)

**Cột-A dựng theo luật vá @S181-F03** = HỢP của {vai có sub-file trong run-folder} ∪ {vai có VERDICT trong WAL chain} — KHÔNG lấy từ bảng dẫn-xuất, KHÔNG lấy riêng run-folder (nếu chỉ lấy run-folder thì phiên không-mở-folder sẽ cho `A∖B=∅` = **ĐẠT-ảo do cấu trúc**).

- Cột-A S187 (7 vai, từ 17 sub-file): `cicd-monitor` · `implementer-backend` · `implementer-frontend` · `investigator-codebase` · `reviewer` · `back-end-reviewer-style` · `test-specialist` → **7/7 CÓ landing** ✅
- Cột-A S188 (11 vai, từ 13 file): `ctx-audit` · `harvest-curator` · `lead-gap-auditor` · `lead-stale-auditor` · `ring1-audit` · `ring2-audit` · `ring5-audit` · `tooling-auditor` · `harness-audit` · `harness-eval` · `harness-refine` → **7/11 CÓ landing**
- **TỔNG: 14/18 = 78%** (đo NỘI DUNG: `grep -c 'S188'` + `grep -c 'S187'` trên từng `MEMORY.md`, đối chiếu 2 commit closeout — KHÔNG đo tên file, KHÔNG đo mtime).

### 🔴 F-01 (HIGH) — 4 vai chạy THẬT @S188, diary nhận **0 chữ**: **42.975 B mồ côi**

| Vai | Sub-file trên đĩa | Byte | mtime | `S188` trong MEMORY.md | Entry cuối THẬT |
|---|---|---|---|---|---|
| `ring2-audit` | `sub-ring2-audit-close.md` | **18.195** | 21:19 | **0** | S186 |
| `ring5-audit` | `sub-ring5-audit-close.md` | **11.282** | 21:08 | **0** | S185 |
| `harness-audit` | `harness-audit-return.md` | **10.664** | 21:30 | **0** | S186 |
| `ctx-audit` | `sub-ctx-audit-close.md` | **2.834** | 20:22 | **0** | S186 |

- Kiểm nhãn thay thế (chống dương-giả do đổi nhãn): cả 4 vai đều **0 hit** cho `S187` lẫn `S188`; `grep -o 'S1[0-9][0-9]' | sort -u | tail` cho max = **S186 / S185**. Không phải "ghi bằng nhãn khác" — là **không ghi**.
- Kiểm bằng git (chống tin-lời-khai): `git log --since='2026-08-10 00:00' -- .claude/agent-memory/<vai>/MEMORY.md` → `ring5-audit` chỉ có `38896120` @04:08 (seed S185); `ring2-audit`/`harness-audit`/`ctx-audit` chỉ có `5a77f4f1` @18:20 — và `5a77f4f1` **numstat = +1/−0** cho ring2 & harness-audit, dòng thêm là **entry S186** (backfill muộn), `ctx-audit` +18/−44 = **nén**, không phải append S188.
- 3/4 file **kết thúc SẠCH** (`== HẾT ==` ở dòng cuối) và **mang verdict đầy đủ** ⇒ đây **KHÔNG phải** ca "sub chết giữa chừng nên không có gì để gom". Việc làm xong, chữ nằm trên đĩa, chỉ là **không ai mang về nhà**.

### 🔴 F-02 (HIGH) — Cơ-chế: chữ về **lời kể của lead**, không về **nhà của vai**

Commit `ef1d4fbb` (21:30, "chạy-bù") và `.claude/WAL.md` **kể tên + verdict** đúng 3 vai đang thủng:

> WAL: *"ring5 1Đ5T→lật 6 `tự ý bỏ` + SÓT-1 · ring2 lần-3 2Đ1T2KC → HOÀN 8 class tally từ git 5a77f4f1 · harness-audit gộp 4Đ2T1KC"*

Nhưng `ef1d4fbb` seed diary cho **4 vai KHÁC**: `harness-refine` · `harvest-curator` · `reviewer` · `ring1-audit`. **0/3** vai được kể tên nhận chữ.

⇒ Phát biểu cơ-chế (truy được, không dừng ở triệu-chứng): **narrative-capture ≠ memory-landing.** Findings được chưng vào *commit message + WAL* — hai bề mặt **lead đọc**, không phải bề mặt **vai đọc lúc spawn**. Hệ quả đo được: lượt spawn tới của `ring5-audit` nạp L1 **2.474 B / entry cuối S185**, hoàn toàn không biết mình vừa *"lật 6 nhãn tự-ý-bỏ + RCA ONESHOT-S188"*.

**Đề xuất (propose-only):** phép chặn = luật gom lấy danh-sách từ **`ls runs/<id>/`** (GỐC) ∪ **WAL verdict-row**, rồi **đối chiếu từng vai** với `grep -c '<nhãn phiên>' agent-memory/<vai>/MEMORY.md` — vai nào 0 thì **không được đóng gate**. (Cùng họ với phép chặn tao đề @S173: *"lấy từ FOLDER, không lấy từ BẢNG"*.)

---

## 2. COMPLETENESS — 🔶 PASS-with-flags

### F-04 (LOW) — `sub-ctx-audit-close.md` trượt **hợp-đồng do chính nó khai**

- File tự khắc luật ở **dòng 5**: *"Verdict tổng ở §CHỐT cuối file. Kết thúc hợp lệ = dòng `== HẾT ==`"*.
- Dòng cuối THẬT = `---`. File **2.834 B / 48 dòng**.
- 🔴 **Bẫy thước tao suýt dính:** `grep -c '== HẾT =='` trả **1** ⇒ đọc vội thành "có terminator". Hit đó nằm ở **dòng 5** = câu **NHẮC luật** (mention), không phải **DÙNG** (use). Thước đúng = **dòng cuối non-empty**, không phải đếm hit. (Đúng lớp citation-trap use⟂mention tao đã ghi ở m#20.)
- Giảm nhẹ: verdict **có** ở dòng 31 (`verdict: dat=9 TRUOT=0 co=2 bo-qua-co-khai=0`) ⇒ mất phần đuôi, không mất kết luận.

### F-05 (LOW, **tự tố**) — file của CHÍNH TAO cũng thiếu terminator

`sub-harvest-curator-close.md` (S188, 15.334 B): `grep -c` ra **4** hit `== HẾT ==` nhưng **dòng cuối** là câu đang dở *"…tức tao đang làm việc với trí nhớ khuy…"* ⇒ 4 hit đều là mention. Tao **cùng lỗi** với vai tao đang chấm. Ghi vào đây để lead thấy mẫu đủ rộng, không phải bệnh riêng `ctx-audit`.

**Đo trọn 11 file S188** (dòng cuối non-empty): kết `== HẾT ==` = **3** (`ring2-audit` · `ring5-audit` · `harness-audit`) / **8 file còn lại không**. Chỉ 2 file **tự khai** hợp-đồng terminator (`ctx-audit`, `harvest-curator`) nên chỉ 2 file đó bị tính TRƯỢT; 6 file kia **không bị buộc** (không khai luật) ⇒ ghi nhận, **không** tính finding — tránh áp luật cho vai chưa nhận luật.

### Spawn-record 4-field
13 vai có entry S187/S188 đều mang cấu trúc `{task · verdict · learned · surprise}` + nhãn `[LEAD SEED ON-BEHALF]` + `nguồn runs/...`. **0 vai thiếu field.** ✅

---

## 3. FIDELITY — ✅ **STRONG** (0 dấu hiệu bịa, không escalate `reviewer`)

Đối chiếu **lời khai của lead** với **chữ trên đĩa**, byte-level:

| Claim (WAL / commit) | Đĩa | Kết |
|---|---|---|
| *"ring2 lần-3 **2Đ1T2KC**"* | `sub-ring2-audit-close.md` dòng cuối: `**RING2: 2Đ · 1T · 2KC**` | ✅ khớp |
| *"harness-audit gộp **4Đ2T1KC**"* | `harness-audit-return.md` dòng cuối: `**HARNESS-AUDIT (gộp): 4Đ · 2T · 1KC**` | ✅ khớp |
| *"seed 12 diary"* | 12 `MEMORY.md` trong `c7b7ca45` | ✅ khớp |
| *"19 file"* (S187) | 19 non-synthesis | ✅ khớp |
| *"W10 dry-run Dev PASS 5/5"* (STATUS:6) | `sub-w10-dryrun.md` dòng cuối: `**W10: PASS — 5/5 bước.**` + `== HẾT ==` | ✅ khớp |

⇒ Lead **KHÔNG bịa**. Mọi verdict được kể đều truy về đúng dòng trên đĩa. Vấn đề của phiên là **đường ĐI của chữ** (F-01/F-02), **không phải độ THẬT của chữ**.

### F-03 (MED) — riêng con số "10 file" (S188) không tái-lập được ở bất kỳ thời điểm nào

- Đĩa hiện tại: **13** non-synthesis + 1 synthesis = **14**.
- Tại thời điểm `bookend-close-synthesis.md` sinh (20:43): đếm theo mtime chỉ có **8** non-synthesis.
- ⇒ **10** không khớp mốc 20:43 (8), cũng không khớp mốc cuối (13). 5 file land SAU synthesis (21:08 → 21:30, đợt chạy-bù).
- Đây là **m#12 mẫu-số-có-ngày-đo** ở dạng nặng hơn: số không chỉ *cũ*, mà **không ứng với instant nào**. Không phải bịa — nhiều khả năng đếm giữa chừng rồi không đo lại. **Đề xuất:** con số file trong `_end` phải sinh bằng `ls | wc -l` chạy **sau** file cuối cùng, hoặc ghi kèm giờ-đo.

---

## 4. PLACEMENT — ✅ PASS

- **29** role-dir dưới `.claude/agent-memory/` (đếm bằng `find -mindepth 1 -maxdepth 1 -type d`, **không** dùng `cut -d/ -f3` — guard m#11 chống nuốt `memory-budget.json` + `.mfe-state.json`).
- Mọi delta S187/S188 nằm **đúng nhà** của vai. **0** ca lệch nhà.
- **Empty-dir residue = 0** (`find .claude -type d -empty`). Dùng `find`, **không** dùng git — git **mù thư-mục rỗng** (m#13, bài S122).
- **0** stray `<runfolder>/.claude/...` (lỗi cwd-relative).

---

## 5. CORRUPTION — ✅ PASS (baseline cập nhật)

**Thước có CONTROL DƯƠNG** (luật tao tự đặt sau F-04@S181 — `grep -P` từng chết `rc=2` mà stderr chui vào file kết quả, đẻ ra `FILES=1` trông hợp lệ):

- Control: file `/tmp/ctrl.md` (15 B) chứa 1 byte-sequence `EF BF BD` → máy đếm **bắt được 1 hit** ⇒ **thước SỐNG**, `rc=0`. Không có control thì kết quả "sạch" là vô nghĩa.
- Phép đo: `perl` mở `<:raw`, đếm `/\xEF\xBF\xBD/g` (byte-mode). **KHÔNG** dùng `grep -P`.
- 🔴 Khai rõ **mẫu-số có mệnh-đề-loại-trừ** (m#20): universe = `find .claude docs -name '*.md' -type f`.

**Kết quả: 26 hit / 13 file** (đã trừ control). So baseline tao ghi @S172 (**24 hit / 11 file**) ⇒ **Δ +2 hit / +2 file**. Mở cả 2 ca mới, **cả 2 LÀNH**:

- `docs/gotchas.md:1101` — nằm trong câu mô tả *triệu chứng* sqlcmd codepage mangle (`H? th?ng trung th?`) = **mention**.
- `runs/2026-08-09-S185-bookend-close/sub-ring1-audit.md:150` — trích **bằng chứng** từ archive: *"console showed `C?ng` = sqlcmd codepage mangle … **NOT data corruption**"* = **mention**, và chính nó đang dán nhãn use⟂mention.

⇒ **0 corruption THẬT.** Toàn bộ 26 hit là **quoted-evidence cố ý** (m#9). **Baseline mới đề xuất cho phiên sau: 26 hit / 13 file** trên universe `.claude ∪ docs`.

---

## 6. Orphan run-folder — ✅ **0 THẬT / 93 folder có `run.md`** (universe 96 dir)

- Thước: folder có `run.md` mà **không có file nào chứa chữ `synthesis`** với size > 0.
- 🔴 Dùng `-name '*synthesis*'` (**substring**), **KHÔNG** dùng glob `*-synthesis.md` neo ở ĐUÔI — bài S162-F02: file `...-synthesis-clone-s160.md` có chữ sau `synthesis` nên glob neo-đuôi trượt, và "sửa theo chẩn đoán cũ không hết bệnh".
- **DUAL-ACCEPT** thoả cả 2 dạng: dạng-1 phẳng `<run>/*-synthesis.md` · dạng-2 legacy C8 `<run>/harvest/<stage>-synthesis.md` (5 run cũ 2026-06-18) — `find -type f` quét đệ quy nên phủ luôn dạng-2.
- Máy trả **1** orphan = `2026-08-10-S189-bookstart-open` (1 file, chỉ `run.md`) — **chính là folder của phiên này, đang IN-PROGRESS** ⇒ **KHÔNG tính orphan** (đúng luật brief; và không đọc vắng-mặt thành hỏng).
- 3 dir không có `run.md` ⇒ ngoài phạm vi (spec-only, tiền lệ S153 đã phân loại).

⇒ **Orphan thật = 0.** S187 có `implement-synthesis.md` (4.469 B) · S188 có `bookend-close-synthesis.md` (4.684 B). Cả hai ĐÓNG.

---

## 7. 0-byte + file cụt (gotcha #53) — ✅ SẠCH

- `find .claude/agent-memory -type f -size 0` → **0**. Không vai nào bị closeout-truncate.
- `find .claude/workflows/runs -type f -size 0` → **10**, **toàn bộ là `.gitkeep`** trong 5 run cũ 2026-06-18 (`harvest/` + `sub-md/`) ⇒ **lành**, đúng như S153 đã phân loại.
- Không dùng riêng `-size 0` để kết luận (m#2 partial-write ≠ 0-byte): đã kiểm **dòng cuối non-empty** của 11 file S188 + `sub-w10-dryrun.md` (77 dòng, kết `**W10: PASS — 5/5 bước.**` + `== HẾT ==`) ⇒ terminates clean.

---

## 8. Ngưỡng read-limit L1 — **ĐÃ ĐO ĐƯỢC**, và câu trả lời đảo dấu so với đo theo BYTE

🔴 **Đây là chỗ tao suýt phát ra finding SAI.**

**Nấc bằng chứng (khai đủ, không đoán):**
1. Canonical đọc được trong repo: `.claude/agent-memory/memory-budget.json` → `/tiers/l1_hot/autoinject_cap_bytes` = **25600** (số nguyên, không có nhập nhằng đơn vị) · `soft_cap_bytes` = 30720.
2. `HANDOFF:54` datum @S187: hook tự bắn cảnh báo *"over its **24.4KB** read limit … Rewrite it to under **17.1KB**"*; `harness-audit` re-chạy 4 instrument (~90 ô, 87 khớp byte-exact) chốt ngưỡng ≈ **24.986 KÝ-TỰ** (= 24,4×1024).
3. `HANDOFF:54` cũng khai thẳng: **hook cắt nằm NGOÀI repo (0 hit trong `scripts/` + config)** ⇒ **chưa ai đọc được nguồn chân lý trực tiếp**. Kết luận dựa 4 đường độc lập.

**Cái tao đo:** đơn vị cắt là **KÝ-TỰ**, mà file diary là tiếng Việt UTF-8 **đa-byte** ⇒ byte ≠ char, tỉ lệ ~1,10–1,18. Đo cả 2 cột (`perl -CSD`, decode UTF-8):

| Vai | bytes | **chars** | % của 24.986 |
|---|---|---|---|
| `lead-gap-auditor` | 27.639 | **24.118** | 96,5% |
| `ring2-audit` | 26.652 | **23.078** | 92,4% |
| `lead-stale-auditor` | 24.975 | **21.988** | 88,0% |
| `reviewer` | 24.473 | **21.421** | 85,7% |
| `harvest-curator` (tao) | 21.308 | **19.481** | 78,0% |

⇒ **0/29 vai vượt ngưỡng.** Max = `lead-gap-auditor` 96,5%.

🔴 **Nếu tao chấm theo BYTE vs 25.600 thì đã tố SAI 2 vai** (`lead-gap-auditor` 27.639 và `ring2-audit` 26.652 đều "vượt") — trong khi tính theo **ký-tự** cả hai **an toàn**. Đây là lỗi **ĐƠN VỊ của thước**, tự bắt trước khi ghi.

**Về nhập nhằng ×1000 vs ×1024** (lead dặn cấm đoán): tao **không cần chọn** — kết luận **đứng ở CẢ HAI**: ×1024 → ngưỡng 24.986, max 24.118 = 96,5% (dưới); ×1000 → ngưỡng 24.400, max 24.118 = 98,8% (vẫn dưới). Nhập nhằng **không đổi verdict**. Cái **chưa đo được** và tao **không đoán**: giá-trị hằng-số thật bên trong hook (file ngoài repo, không đọc được) — chỉ có chữ *"24.4KB"* do chính hook in ra.

**Đóng cờ cũ của chính tao:** entry S188 tao ghi *"L1 của tao 29.776 B VƯỢT read-limit ⇒ bị cắt THẬT; self-compact DUE"*. Nay `harvest-curator` = 21.308 B / **19.481 ch (78,0%)**, `archive/2026-07.md` chạm 21:01 trong `ef1d4fbb` ⇒ **self-compact ĐÃ CHẠY, cờ ĐÓNG**. Tương tự `reviewer`: 27.013 ch (108,1%) @S187 → **21.421 ch (85,7%)** ⇒ **đóng**. Hai vai từng bị cắt thật nay **hết bị cắt**. Vẫn > self-target 17,1KB (soft) — mức **khuyến nghị**, không phải vi phạm.

---

## 9. "Đã soi mà SẠCH" — phân biệt trục ĐẠT với trục CHẾT-NON

Liệt kê để lead thấy trục nào **có ca, đo, ra sạch** — khác trục **vacuous-PASS vì không có gì để đo**:

| Hạng mục | Mẫu-số THẬT | Kết | Có phải vacuous? |
|---|---|---|---|
| Orphan run-folder | 93 folder có `run.md` (universe 96) | 0 orphan | **KHÔNG** — mẫu-số lớn, thước substring |
| Corruption | 26 hit / 13 file, universe `.claude ∪ docs` | 0 thật, 26 mention | **KHÔNG** — có hit, đã mở đọc từng ca mới |
| Control dương của thước corruption | 1 file control | bắt 1/1, rc=0 | **KHÔNG** — chứng thước sống |
| 0-byte agent-memory | 29 vai | 0 | **KHÔNG** |
| 0-byte runs/ | 10 hit | 10/10 là `.gitkeep` | **KHÔNG** — đã phân loại từng ca |
| Empty-dir | quét `.claude` bằng `find` | 0 | **KHÔNG** — git mù chỗ này nên phải `find` |
| Placement | 29 role-dir | 0 lệch nhà | **KHÔNG** |
| Fidelity | 5 claim đối chiếu byte-level | 5/5 khớp | **KHÔNG** |
| Read-limit L1 | 29 vai, đo char | 0 vượt | **KHÔNG** — và đã lật được kết-luận-sai theo byte |
| Spawn-record 4-field | 13 entry | 13/13 đủ field | **KHÔNG** |

---

## 10. Thước TỰ BẮT trong lượt này (ghi để không tái phạm)

1. **Đơn-vị thước** (§8): byte vs ký-tự → suýt tố oan 2 vai. Ngưỡng nào phát biểu bằng "KB" phải hỏi **KB của cái gì** trước khi so.
2. **use⟂mention trên terminator** (F-04): `grep -c '== HẾT =='` = 1 nhưng hit đó là câu **nhắc luật**. Thước đúng = **dòng cuối non-empty**.
3. **Regex trích vai quá hẹp**: tao quét `vai \`x\`` → 20/28 file ra `<NO vai DECLARED>`, suýt thành finding *"file thiếu khai vai"*. Mở file ra đọc thì vai **có khai**, chỉ khác dạng (`Vai: ring5-audit` · `# ring2-audit @close` · `> Vai KIỂM độc-lập`). **Hỏng thước, không hỏng file** ⇒ **BỎ**, không báo cáo.
4. **Control dương trước khi tin số 0** — giữ nguyên từ S181.

---

## 11. ĐỀ XUẤT cho lead (propose-only — tao KHÔNG ghi, lead VERIFY→APPEND, B3)

**Ưu tiên 1 — đóng 42.975 B mồ côi (F-01).** Gom 4 sub-file → APPEND spawn-record 4-field vào đúng nhà:
- `.claude/agent-memory/ring2-audit/MEMORY.md` ← `sub-ring2-audit-close.md` (18.195 B; verdict `2Đ·1T·2KC` + HOÀN 8 class tally)
- `.claude/agent-memory/ring5-audit/MEMORY.md` ← `sub-ring5-audit-close.md` (11.282 B; lật 6 nhãn *"tự ý bỏ"* + RCA ONESHOT-S188) — **ưu tiên cao nhất**: L1 vai này mới 2.474 B, gần rỗng, mà việc thì nặng
- `.claude/agent-memory/harness-audit/MEMORY.md` ← `harness-audit-return.md` (10.664 B; verdict `4Đ·2T·1KC`)
- `.claude/agent-memory/ctx-audit/MEMORY.md` ← `sub-ctx-audit-close.md` (2.834 B; `dat=9 TRUOT=0 co=2`)

🔴 **DEDUP bắt buộc trước khi APPEND** (harvest chạy cả per-turn lẫn close-gate): 4 vai này hiện `grep -c 'S188'` = **0** ⇒ **an toàn, chưa từng APPEND**, không có rủi ro double-append. Đã kiểm.

**Ưu tiên 2 — vá cơ-chế (F-02):** gate đóng phiên phải đối chiếu **từng vai** trong {`ls runs/<id>/`} ∪ {WAL verdict-row} với `grep -c '<nhãn>' agent-memory/<vai>/MEMORY.md`; vai nào = 0 thì **chưa được đóng**. Chặn đúng lớp bệnh: kể-tên-trong-commit không tính là đã-gom.

**Ưu tiên 3 (MED, F-03):** số file trong `_end` sinh bằng `ls | wc -l` chạy **sau** file cuối, hoặc ghi kèm giờ-đo.

**Ưu tiên 4 (LOW, F-04/F-05):** luật END-line — file nào tự khai hợp-đồng terminator thì phải **dùng** `== HẾT ==` ở dòng cuối; kiểm bằng **dòng cuối non-empty**, không bằng `grep -c`.

**Baseline chuyển giao phiên sau:** corruption **26 hit / 13 file** (universe `.claude ∪ docs`, control-verified) · orphan **0/93** · role-dir **29** · read-limit **0/29 vượt** (đo ký-tự).

---

## 12. Containment (G-015 — khai đúng giới hạn, không overclaim)

- Tao **KHÔNG ghi** file nào trong repo ngoài **chính artifact này** (`runs/2026-08-10-S189-bookstart-open/sub-harvest-curator-open-S189.md`) — đúng vùng run-folder được giao.
- `git status --porcelain` giữa lượt: **1** dòng `M .claude/governance/.session-counter.json` — **KHÔNG phải tao**; đó là counter phiên tự tăng (62→63, khớp `run.md` S189). Tao chỉ chạy lệnh ĐỌC + ghi 1 file control **ngoài repo** (`/tmp/ctrl.md`).
- 🔴 Khai thật: run-folder git-**TRACKED** ⇒ mọi write của tao **hiện trong git-diff**. Nhưng TRACKED **≠** read-only-enforced — tao vẫn còn `Bash` = kênh ghi mở. Containment THẬT = **lead single-writer + git-diff**, không phải "vai này read-only".
- **0** `store_memory` · **0** APPEND vào `agent-memory/*` · **0** quyết định. Fidelity nghi-bịa: **không có** ⇒ **không** escalate `reviewer`.

== HẾT ==
