Files
solution-erp/.claude/governance/reinject-ledger.md

8.9 KiB

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. 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ếuKHÔ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 reinjectedresolved (đ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.