# REINJECT-LEDGER — Harness-17 CG-1 termination ledger (SOLUTION_ERP)

> **Sổ-ghi chốt-dừng (termination) cho vòng tự-cải-thiện bộ-nhớ (Harness-17 §I).** Ghi mỗi lần một **mục-sàn floor-rot** (đã-từng-ở-hot-mem nay RỚT) được **reinject verbatim** trở lại L1 — để **CG-1** chặn reinject-loop vô-hạn.
>
> 🔴 **Vì sao file RIÊNG (không nhét vào `memory-budget.json`):** `memory-budget.json` = **quyền cấp-ngân-sách của anh (project-owner)** — MFE + audit chỉ **đọc** `token_governor`, KHÔNG ghi (ranh-giới §G.4(4), mark `RC-…21-06…01-58-01`). Trộn reinject-state vào đó = AI lấn quyền cấp-ngân-sách. Ledger này = **git-tracked · append-only · single-writer em-main (D9)** — mirror provenance-model của [`ACTIVE-MARKS.md`](ACTIVE-MARKS.md). NEVER overwrite dòng cũ.

## CG-1 rule (chốt-dừng — H17 mục B2)

- Mỗi `item-id` được **reinject TỐI-ĐA 1 lần trong N phiên** (SE solo-dev: **N = 3**). N nhỏ hơn multi-dev vì solo = 1 người-điều-phối, feedback-loop nhanh (đủ 3 phiên để work-state block bơm lại "ngấm").
- Sau reinject, phiên MFE kế **đo-lại**: nếu mục ĐÃ hiện diện lại trong L1 → `status=resolved`, **đóng chu-kỳ** (KHÔNG reinject nữa).
- Nếu đo-lại **VẪN thiếu** → **KHÔNG** tự-reinject lần-2 (KHÔNG ghi `attempt=2`). Thay vào → `status=escalated` + **báo anh (project-owner)**: có thể **build-gap** (cơ-chế bơm chưa đủ — cần extend) HOẶC cần anh quyết **tăng-budget / đổi-placement** (mirror MFE H3 2-ca: thiếu-CHỖ→tăng-budget-anh-quyết vs rot→sắp-xếp-lại). AI **KHÔNG** tự-loop.
- **Chỉ floor-rot mới vào ledger này** (phân-loại qua phép-thử B3 §I): item **ĐÃ-từng-tồn-tại ∩ CÒN-giá-trị ∩ RỚT-khỏi-L1**. Item chưa-từng-dựng = **build-gap** (đi dựng cơ-chế, KHÔNG reinject). Item hết-giá-trị = để **cold-archive** (rớt đúng-đắn).

## Schema (mỗi dòng = 1 chu-kỳ reinject; append newest xuống cuối)

| Cột | Nghĩa |
|---|---|
| `item-id` | id ổn-định mục-sàn rớt (RC-sig · `AS-N` · `gotcha #N` · guard-name) |
| `source` | file canonical chứa verbatim (`ACTIVE-MARKS.md` · `error-ledger.md` · `gotchas.md`) |
| `detected` | phiên MFE/audit phát-hiện floor-rot (`S<NN>`) |
| `reinjected` | phiên em-main reinject verbatim (`S<NN>`) |
| `attempt` | lần thứ mấy (rule ≤1 trong N=3; nếu cần lần-2 → **escalate**, KHÔNG reinject) |
| `remeasured` | phiên MFE đo-lại sau reinject (`S<NN>`) |
| `status` | `reinjected` → `resolved` (đo-lại đủ) HOẶC `escalated` (đo-lại vẫn thiếu → anh quyết) |

> **Cách đọc (ví-dụ minh-hoạ — KHÔNG phải dòng thật):**
> `| gotcha #57 | docs/gotchas.md | S96 | S96 | 1 | S97 | resolved |` = chu-kỳ đóng đúng: S96 audit FLAG gotcha #57 rớt khỏi L1 → em-main APPEND verbatim từ `gotchas.md` → S97 đo-lại thấy lại → `resolved`, dừng.
> Chu-kỳ **escalate**: reinject `attempt=1` @S96 → S97 đo-lại VẪN thiếu → `status=escalated`, báo anh (build-gap? tăng-budget? đổi-placement?) — KHÔNG ghi `attempt=2`.

## Ledger (append-only — single-writer em-main)

| item-id | source | detected | reinjected | attempt | remeasured | status |
|---|---|---|---|---|---|---|
| _(chưa có floor-rot nào được reinject — ledger khởi-tạo trống S95, 2026-07-01)_ | | | | | | |

---

> **Nấc honest:** ledger = **convention** (em-main append tay, git-tracked audit-trail — KHÔNG OS-hook auto-write, nhất-quán CAVEAT engine "no-OS-hook"). Tín-hiệu floor-rot feed = **mechanized** (`mfe-eval.ps1` age-band + `memory-selfimprove-audit.ps1`). Detection per-item-L1-presence hiện **partial** (MFE age-band chỉ đo marks-có-date; AS/guard/gotcha mang session-ref chưa có pass so-từng-item-trong-L1 — xem §I honest nấc + CAVEAT C4 self-blind-spot).

---

## Re-verify: presence-not-age selector (broadcast `ab6c387e`, adopt S115 · 2026-07-13)

> AI_INFRA broadcast `ab6c387e` (type=**update**) — re-verify the memory refine-step **selector** decides by PRESENCE/COVERAGE, not AGE. Verdict per floor:

- **(i) Reinject = MET (presence-based).** Trigger = **floor-rot** `"ĐÃ-từng-ở-L1 ∩ CÒN-giá-trị ∩ RỚT-khỏi-L1"` (coverage-gap, this file `:12`) = the broadcast (i) condition "should be present but is missing." Age plays no part in *what-to-reinject*. The CG-1 `reinjected` session column is a **reinject-event rate-limiter / loop-breaker (≤1 per N=3 sessions), NOT an age-rank** → OK per broadcast (iii) carve-out ("date used only for last-seen/loop-breaking = OK"). Drop-date test: dropping the column changes only the rate-limit/termination count, never the selection.
- **(iii) MFE age-band = FLAG-only (COMPLIANT).** `mfe-eval.ps1` `$oldN` is computed then `Write-Host`-printed ("KEPT status-driven age-blind") with **no downstream consumer**; the denominator is gated by STATUS, not date. Drop-date test: changes one diagnostic count, not the denominator / FIT / Goodhart / any selection.
- **(ii)+(iii) Archive-gate = RED-FLAG surfaced → HARDENED (D3, S115).** The planner's oldest-by-position base ordering tripped the (iii) self-check; fixed in `scripts/memory-archive-gate.ps1` by promoting `value_protect` from an advisory post-hoc flag to a **pre-selection HARD-SKIP** (value-primary; position = within-low-value tiebreak) + a value-floor WARN. Fault-injection-verified (protected-not-drained + permutation-invariant + value-floor). See `memory-budget.json:value_protect._note`.

**BUILD-GAP (honest, disclosed):** mechanized **per-item-L1-presence** detection is still PARTIAL — the MFE age-band counts *present* marks (by date), not per-item *drops*; AS/guard/gotcha carrying session-refs have no per-item-in-L1 pass yet. So reinject-detection stays **convention + em-main judgement**, not full mechanization (do NOT overclaim). Consistent with §I honest nấc + CAVEAT C4.

**3 honest-notes (broadcast §5 — MANDATORY):**
1. Basis = **ONE** occurrence already fixed elsewhere → **proactive-prevention**, NOT a spreading SE incident.
2. **SPECIFIC-APPLICATION**, not a new rule — SE reinject + MFE age-band were already presence/flag-based (quick re-verify, no change); only the archive-gate needed hardening.
3. Floor = **FUNCTION not FORM** — implemented in SE's own script shape; no hub structure/filenames copied.

> **Provenance:** `/fable-clone reviewer` 5-lane ensemble (`wf_b621aac4-f0b`) → spec `runs/2026-07-13-presence-not-age-adopt/spec-presence-not-age-adopt-13-07-2026.md` → `/fable-real reviewer` deep-pass (PASS-WITH-FIXES; M1+M2 applied) → HMW execute D1/D2/D3. Applies existing mark `RC-…10-29-11` (age=false-proxy) to the selector layer; codify-only (no new mark).

---

## S185 (2026-08-10) — 2 mục MFE MISS lần đầu CÓ TÊN ⇒ phân loại B3 = **BUILD-GAP, KHÔNG reinject**

**Bối cảnh:** `-Detail` được cắm vào `session-end §L.b(c)` @YC-019(6) (switch tồn tại từ đầu, **0 call-site suốt 12 phiên**). Lần chạy đầu tiên có cờ này, 2 mục MISS thoát khỏi trạng thái vô danh:

| Vai | Điểm | Mục MISS (nguyên văn máy in) | Nhà trong role-file |
|---|---|---|---|
| `implementer-backend` | 17/18 = 94% | `❌ Integration testing multiple components` | `.claude/agents/implementer-backend.md:34` (auto-refuse #5) |
| `implementer-frontend` | 12/13 = 92% | `❌ < 30 min trivial` | `.claude/agents/implementer-frontend.md:31` (auto-refuse #6) |

**Phân loại B3 (bắt buộc TRƯỚC reinject) = BUILD-GAP, không phải floor-rot.** Bằng chứng đo: `grep -ci` trên diary 2 vai = **0/0** — 2 mục này **chưa bao giờ xuất hiện rồi rơi**; chúng chưa bao giờ được **kích hoạt**. Lý do cơ chế: "integration test nhiều component" ở SE luôn về `test-specialist` (ranh vai), còn "< 30 min trivial" thì lead tự làm chứ không spawn sub ⇒ 2 vai **chưa từng gặp ca để từ chối**.

🔴 **Quyết định: KHÔNG reinject-verbatim.** Nhồi 2 dòng này vào diary sẽ đẩy 94%→100% / 92%→100% mà **không thêm một giá trị nào** — đúng hình dạng Goodhart mà `feedback_goodhart_leave_measurement_set` mô tả: đổi hình-dạng thứ đang bị đo thay vì đổi thực-chất. CG-1 (≤1/N=3) **không tiêu quota** vì không có sự kiện reinject nào.

**Hệ quả phải khai khi đọc số MFE về sau:** trần thực tế của 2 vai này **< 100% cho tới khi có ca thật** — 94%/92% ở đây đọc là *"chưa gặp ca"*, KHÔNG phải *"trí nhớ rot"*. Ai thấy số này rồi "vá" cho tròn 100% là đang xoá **chứng nhân**, không phải xoá lỗi.

**Điều-kiện lật (làm cho phán quyết này falsifiable):** nếu về sau một trong 2 vai **thực sự từ chối** một task bằng đúng tiêu chí đó mà diary vẫn 0-hit ⇒ lúc ấy mới là **floor-rot thật** ⇒ reinject theo CG-1.
