All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 10m0s
Owner chốt: "(b) Chặn HẾT 7 loại — mọi HĐ đều phải từ KHKK -> Tao nghĩ nên như vậy trước đã."
BE: ContractCreationGate (1 chỗ, AllowedDirectTypes rỗng — nới = thêm loại, không sửa handler)
chặn 409 ở 2/3 write-site: POST /contracts (tạo tự do) + POST /purchase-evaluations/{id}/
create-contract (PE→HĐ 1-click nhảy cóc KHKK, di tích Phase 6). Bridge KHKK giữ nguyên
(write-site duy nhất). Gate đứng TRƯỚC mọi load — không lộ tồn tại dữ liệu. Seeder demo
là write-site miễn-trừ có khai (flag-gated).
FE ×2 app (8 lối): menu Create per-loại ẩn (Layout, policy Ct_*_Create giữ DB) · nút
"Tạo HĐ mới"/"Thêm mới" → "Tạo từ KHKK" trỏ /khkk/list (MyContracts + Dashboard +
ContractCreatePage) · ?mode=new → EmptyState chỉ đường KHKK · nút PE→HĐ ẩn (PeDetailTabs).
ContractCreatePage + PeDetailTabs giữ SHA-mirror 2 app.
Tests 697 pass + 6 skip / 0 fail (total 703): +4 gate mới (quét-trọn-enum fail-closed +
chặn-trước-NotFound + đổi message ApplicableType); 6 test multi-winner PE→HĐ chuyển
Skip-có-khai (spec di sản Mig 58, mở lại khi owner nới gate). Reviewer PASS_WITH_FIXES,
6/6 issue vá trong lượt (kể cả 3 chuỗi EmptyState/ListPanel còn mời tạo trực tiếp).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
149 lines
18 KiB
Markdown
149 lines
18 KiB
Markdown
# 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 |
|
||
|---|---|---|---|---|---|---|
|
||
| CG-1 `front-end-reviewer-style` (floor-rot sub-class **clobber-rot** — mất H1 + LUẬT LÕI owner) | `.claude/agent-memory/front-end-reviewer-style/MEMORY.md` | S195 | S195 (UNION `e470bddf^`, commit `24566a50`) | 1 | **S197** (lead đo TƯƠI cùng lượt: `wc -c` = **5.913 B ≥ ngưỡng 5.800** + H1 dòng-1 còn; khớp `harness-eval` I1 bản PIN) | **resolved** |
|
||
|
||
> 🧊 *Dòng trên = dòng THẬT đầu tiên của bảng (@S197, thi hành `harness-refine` A1). Placeholder cũ "(chưa có floor-rot nào được reinject — ledger khởi-tạo trống S95)" đứng ở đây S95→S197 và từ @S195 đã TỰ MÂU THUẪN với prose `:100` (attempt=1) — `harness-audit` N2 @S197 bắt; lật trong CÙNG lượt ghi để lượt đóng nợ không đẻ neo thối mới. CHỐT-DỪNG giữ nguyên: tick sau nếu file <5.800 B hoặc mất H1 ⇒ ESCALATE, CẤM attempt-2.*
|
||
|
||
---
|
||
|
||
> **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.
|
||
|
||
---
|
||
|
||
## CG-1 attempt #1 — `front-end-reviewer-style` · REINJECT THI HÀNH (2026-08-14, S195)
|
||
|
||
**Phân loại B3 = FLOOR-ROT**, sub-class MỚI: **`clobber-rot`** (rơi do bị ĐÈ, không do drain). Đây là **lần đầu tiêu quota CG-1** — sổ trước đó 0 dòng reinject.
|
||
|
||
**Trigger:** `harness-eval` §3 trục #14 + `harness-refine` A1 — `.claude/agent-memory/front-end-reviewer-style/MEMORY.md` **4.721 B → 1.192 B = −3.529 B (−74,8%)** tại commit `e470bddf`.
|
||
|
||
**4 bằng chứng độc lập chốt là CLOBBER, không phải curate:**
|
||
1. Cùng commit `e470bddf` chạm **9 diary — 8/9 là APPEND THUẦN** (`+7 −0`, `+10 −0`; +1.154…+1.690 B). Riêng 1/9 là **`+5 −17`**. Cùng một thao tác seed, 8 con làm đúng ⇒ **ý định là append**.
|
||
2. Commit đó **KHÔNG tạo file archive nào** (`--name-status`: 2 file `A` đều thuộc `.claude/sessions/`) ⇒ 3.529 B **không đi đâu cả**.
|
||
3. **Mất luôn dòng H1.** Quét 29 diary: **đúng 1/29** có dòng đầu không phải H1 — chính con này. **28/29 sạch = control dương**, thước có phân giải.
|
||
4. **Blob còn nguyên** tại `e470bddf^` = 4.721 B ⇒ **hồi phục được, KHÔNG mất trắng**.
|
||
|
||
**Cái mất là loại đắt nhất, không phải log:** LUẬT LÕI nguyên văn của owner (*"tính năng đã deploy production là chuẩn, trừ khi tao chỉnh lại"*) · toàn bộ **địa phận/ranh vai** (`fe-admin/src/**` + `fe-user/src/**`; soi style không soi logic) · bản vá thước dispatch **SỬA-1** (thứ quyết định vai **có được gọi hay không**) · 2 bài citation-trap. Vai vẫn sống (`.claude/agents/front-end-reviewer-style.md` 12.960 B) ⇒ lần spawn tới nó vào việc **không còn định nghĩa địa phận lẫn luật owner**, mà diary chỉ còn *một ghi chú rằng nó đã chết*.
|
||
|
||
**Thi hành:** **UNION trên đúng 1 path** — `git show 'e470bddf^:<path>'` + append nội dung hiện có.
|
||
🔴 **BÁC `git revert e470bddf`** (`harness-refine` BÁC-14): revert sẽ **xoá entry S194** (ghi nhận một lần vai chết = dữ liệu thật), **lật ngược 8 file anh em đã append ĐÚNG**, và đụng 2 file `.claude/sessions/`.
|
||
|
||
**Verify sau thi hành (4 phép, đo tươi):** `wc -c` = **5.913 B** — 🔴 **khớp BYTE-EXACT dự đoán 5.913 B của `harness-refine`** · H1 `# front-end-reviewer-style Agent — Persistent Memory` đã về · `grep -c '^## S194'` = **1** (không nhân đôi, không mất) · `grep -c 'SINH SỔ … SỬA-5a'` = **1** (nội dung cũ không lặp) · 3 hit các mục load-bearing kể trên.
|
||
Bản cũ chứa **0 hit `S194`** ⇒ UNION an toàn by-construction, không đếm đôi.
|
||
|
||
**CHỐT-DỪNG (theo `harness-refine`):** attempt = **1**, lần đầu trên vật này. Tick sau nếu file **< 5.800 B** HOẶC vẫn thiếu H1 ⇒ **ESCALATE lead, CẤM attempt-2**.
|
||
|
||
**Nợ KÈM — thuộc lead, KHÔNG phải corpus (ES-3):** **đường ghi** đẻ ra clobber này (Write đè thay vì append) lọt qua nghi thức vì thước hiện tại là *"byte > 0"* mà **1.192 > 0** ⇒ **guard có, nhưng mù đúng sub-class mới**. Luật phân biệt đã ghi: *L1 co lại mà **0 file L2 sinh trong cùng commit** + **mất H1** = clobber, KHÔNG phải curate*.
|
||
|
||
---
|
||
|
||
## 🔴 ĐÍNH CHÍNH TIỀN-ĐỀ SAI của dòng `:70` — phán bởi `harness-audit` @S195, lead nhận
|
||
|
||
**Dòng `:70` (mục MFE @S185) khai:** *"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**"* ⇒ phân loại **BUILD-GAP** cho CẢ HAI vai. **Tiền-đề này SAI cho CẢ HAI**, mỗi vai sai một kiểu.
|
||
|
||
### (a) `implementer-backend` — SAI vì mục ĐÃ BỊ CHÍNH LANE REFINE DỜI ĐI
|
||
|
||
`implementer-backend/archive/2026-07.md:18` nguyên văn:
|
||
```
|
||
## @S152 R1 retention-note [moved-not-cut @S185 refine-A1, verbatim]
|
||
```
|
||
`:19` = mục `Integration testing multiple components` — **chính mục MFE báo MISS**. Chuỗi nhân quả đóng kín: **@S152** vai ghi vào L1 → **@S185 `refine-A1`** (hành động của chính lane refine) dời L1→L2 → **@S185 ledger** phán build-gap bằng grep **chỉ quét L1, và L1 rỗng VÌ A1 vừa dọn** → **@S192** MFE 18/18→17/18.
|
||
Control-dương đóng vòng: L1 = **0** · `archive/2026-07.md` = **1** · 14 file archive khác = **0**.
|
||
⇒ Phân loại đúng = **FLOOR-ROT**. `mfe-eval.ps1:243` (nguồn mục = role-file) + **`:264`** (diary = **CHỈ** `MEMORY.md`) ⇒ **archive tàng hình với MFE by construction**.
|
||
|
||
### (b) `implementer-frontend` — SAI vì MATCHER MÙ, không phải vì mục không tồn tại
|
||
|
||
🔴 **`harness-refine` ES-4 định GIỮ NGUYÊN phán quyết build-gap cho vai này. `harness-audit` bác bằng đĩa:**
|
||
```
|
||
.claude/agents/implementer-frontend.md:31 6. ❌ < 30 min trivial <- mục denominator
|
||
implementer-frontend/MEMORY.md:54 "2 ranh auto-refuse: việc <30min/trivial = em-main solo"
|
||
implementer-frontend/archive/2026-H2.md:80 "(a) Việc < 30 min / trivial: … REFUSE nhận đúng
|
||
role-file; nhận việc trivial = đốt spawn vô ích."
|
||
```
|
||
Mục này **ĐANG SỐNG Ở L1 HÔM NAY**, còn có bản đầy đủ ở L2. *"Chưa từng sống"* **SAI**. Và cơ-chế biện minh kèm theo (*"lead tự làm chứ không spawn sub ⇒ vai chưa từng gặp ca để từ chối"*) cũng đổ: `2026-H2.md:80` là **đúng một ca từ chối có lý do**.
|
||
|
||
**Vì sao máy vẫn báo MISS — cơ-chế, không phải bí ẩn:** matcher `mfe-eval.ps1:281-287` đòi **≥2 content-word là alnum-run RỜI** (`(?<![a-z0-9])…(?![a-z0-9])`). L1 viết **DÍNH**: `<30min/trivial` ⇒ `30min` là **MỘT** run ⇒ `30` và `min` **đều trượt lookaround** ⇒ chỉ còn `trivial` = 1 từ < `minWords 2` ⇒ **MISS**. Đây đúng cơ-chế **DÍNH-vs-TÁCH** đã ghi @S173 — **tái phát nguyên vẹn**, và lần này bị đọc nhầm thành *"chưa từng tồn tại"*.
|
||
|
||
### 🔴 Hệ quả — HÀNH ĐỘNG giữ nguyên, LÝ DO phải đổi
|
||
|
||
**KHÔNG reinject cho cả hai** — nhưng nền lý lẽ đổi hẳn:
|
||
- ~~"chưa từng sống ⇒ build-gap"~~ **SAI**.
|
||
- **Nền đúng:** nội dung **ĐÃ được mang rồi** (backend ở L2 sau A1 copy-về; frontend ở cả L1 lẫn L2) ⇒ nhồi thêm là **Goodhart thuần**: đẩy 92%→100% với **0 thông tin mới**. Đúng cảnh báo `harness-audit` đã ghi @S173: *"cách RẺ NHẤT đẩy 92%→100% là viết chuỗi `30` đứng riêng vào diary"*.
|
||
- ⇒ Đây là hình dạng **quen thuộc S189/S192: ĐÚNG KẾT LUẬN, SAI LÝ DO**. Nếu ES-4 thi hành y văn thì sổ governance sẽ mang **một mệnh đề sự thật SAI, tồn tại lâu dài**.
|
||
|
||
### Vai tự nghi trước khi kết tội (giữ vì đây là chuẩn)
|
||
`harness-audit` chạy **F16** (*"probe `30 min` của tao có lỏng, bắt oan refine không?"*) và **F17** (*"`<30min/trivial` có khác nghĩa mục 6 không?"*) — dùng control-dương trên backend (1 hit đúng file, 0 chỗ khác) **và đọc NGUYÊN VĂN** cả 2 dòng thay vì tin số đếm. **Cả 2 HELD.**
|
||
|
||
### Khuyết tật thước KÈM (chưa vá, thuộc owner/tooling)
|
||
1. **`git ls-tree`/`git archive` KHÔNG dùng được cho trục byte trên kho này** — `measure-agent-memory.ps1:14` dùng `(Get-Item).Length` = **ĐĨA**, git normalize CRLF→LF nên blob **luôn hụt đúng số dòng**. Đo: `reviewer` disk **28.804** ⟂ blob **28.673**, delta **131** = **CRLF pairs 131**, khớp tuyệt đối. **8/29 diary là `w/crlf`.** Công thức đúng: `disk = blob + LF_count nếu w/crlf`.
|
||
2. **`mfe-eval.ps1` KHÔNG IN dòng tổng nào** — `grep 'roles_scored\|numerator\|denominator'` trong script = **0 hit**; `163/165 = 98,79%` là số **gộp tay**, **chưa bao giờ là output máy**. ⇒ signal #7 của con-ĐO (*"MFE dòng tổng vắng khỏi bề mặt"*) sẽ đẩy lane refine đi đòi lead dán **một dòng không bao giờ tồn tại**. Verdict *"không tự kiểm được dưới C1"* ĐÚNG, **nguyên nhân SAI**.
|
||
3. **`-Tier sub` là đường READ-ONLY** của `mfe-eval.ps1` (dispatch `:329` `Measure-Lead` chứa write ⟂ `:330` `Measure-Sub`) — chứng bằng **md5 trước = sau** (`58ebfd05…`, mtime bất biến), không bằng đọc code. Mở lại đường chạy mà @S192 vai từng **từ chối**.
|