# Error-Ledger — SOLUTION_ERP (Gov-v2 §L keystone)

> **Living artifact.** Blameless RCA + Active-Guards index for SE. Closes the open delta from adap-report `2026-06-02-Governance-gov-v2-session-cmd-framework` (the only Gov-v2 floor item SE had distributed-but-not-formalized).
> **Maintained at `/session-end` §L.b** (deterministic step, not a daemon — G-015). Blameless = root-cause + guard, NOT blame.

## 📐 The 3-ledger triad (Gov-v2 §L.b / §G3 — form gộp, function intact)

SE maps the mandated 3 living ledgers onto existing + new artifacts (§F4 form-freedom):

| Ledger (function) | SE artifact | Role |
|---|---|---|
| **(i) error-ledger** | **this file** (`docs/governance/error-ledger.md`) | RCA blameless · Active-Guards index · 3-axis tag · 2-strike promote |
| **(ii) comms-ledger** | `docs/governance/README.md` "Cross-Project Adoption Ledger" + `docs/governance/adap-reports/` | 2-way cross-project OUT→ACK / IN→decided, link-not-copy |
| **(iii) summary-index** | `docs/STATUS.md` "Recently Done" + `docs/changelog/sessions/` | timeline spine, pointer-not-log, reverse-chron |

## 🔍 §L.a — Deterministic detect (action-signature scan @ session-end)

Detect by **action-signature** (NOT "AI tự phán có vi phạm không"). Scan the session for these; each hit → an RCA entry below. List is **open** — extend when a new class appears. (G-015: catches signatures in this list, NOT "mọi vi phạm".)

| # | Action-signature (grep/observe) | Rule it violates | On hit |
|---|---|---|---|
| AS-1 | `git add -A` / `git add .` | add-specific-files (concurrency safety, `feedback_rag_mcp_recovery_concurrency`) | RCA + re-stage specific |
| AS-2 | `--no-verify` / `--no-gpg-sign` / `commit.gpgsign=false` | no hook/sign bypass unless asked | RCA, justify or revert |
| AS-3 | sub-agent invokes `store_memory` | lead = sole RAG-writer (S47, mechanized) | should be impossible (allowlist-stripped); if chunk-count jumps w/o lead write → investigate |
| AS-4 | EF Mig adds UNIQUE/composite index on a soft-delete (`IsDeleted`) entity **without** `.HasFilter("[IsDeleted]=0")` | gotcha #57 (recreate-on-soft-deleted-slot → 500) | RCA + test-before + filter |
| AS-5 | heavy/long agent spawn in **foreground** | `feedback_background_spawn_visibility` (looks-frozen) | note; prefer `run_in_background` |
| AS-6 | docs-only commit that triggers a CI run | gotcha #41 path-filter (`paths-ignore`) | verify path-filter intact |
| AS-7 | model downgrade (haiku/sonnet) on codegen/guard/financial/security | critical-algo needs Max tier | RCA, re-run on Max |
| AS-8 | session-end memory `.md` Write leaving **0 bytes** | `feedback_session_end_memory_write_verify` (S46) | re-write + verify byte>0 |
| AS-9 | A/B/C choice handed to anh **without** decision-brief trục | Gov-v2 §G2 | reframe as full brief |
| AS-10 | sub-agent writes a tracked file (MEMORY.md / code) despite **R1 return-only** (Write/Bash residual) | R1 return-only (HMW) — prompt-rule, NOT mechanized (G-015) | git-diff post-P2 catch → lead VERIFY benign+accurate+placement → keep or revert (NOT a bug if correct; chunk-count for RAG-write) |
| AS-11 | cross-stack feature: BE validator/nullability ≠ FE required-marker for the SAME field | em-main shared-contract consistency (E-007) | RCA + align FE↔BE + reviewer-gate (held S51) |
| AS-12 | identifier-based data op trên prod (lock/seed/migrate-by-email/code) viết theo population đọc từ CODE/Dev, KHÔNG dump bảng env đích | gotcha #60 (E-008) — assertion 0-row/`-1` ⟹ nghi data-mismatch TRƯỚC code-bug | RCA + dump env-đích trước khi viết list + seed-password thỏa policy nghiêm nhất mọi env |
| AS-13 | **custom Workflow script (≠ hmw.js DEFAULT-mode)** chạy parallel **same-role** agents giữ Write → agents tự-ghi shared `agent-memory/<role>/MEMORY.md` → "file modified since read" race + verbose-append over-cap | E-009 — hmw.js DEFAULT có return-delta-guard, custom script KHÔNG kế-thừa | RCA + curate L1→L2 + custom workflow PHẢI copy return-delta-guard HOẶC file-disjoint 1-sub/file |
| AS-14 | phép ĐO text (length/char-count/so-sánh) qua `Get-Content`/console-pipe **KHÔNG ép encoding** trên file **no-BOM** (PS5.1 default = ANSI → ký-tự Việt đếm ×2-3) | đo-phải-chạm-đĩa-ĐÚNG-CÁCH (E-010; anh em với bẫy `grep -c` — `feedback_resume_premise_reverify`) | RCA + re-đo `[System.Text.UTF8Encoding]` tường-minh; số đã báo owner → đính-chính NGAY |
| AS-15 | **điểm-đóng-thật** (chốt-đợt commit+push HOẶC session-end) **KHÔNG kèm** delta diary monitor (H1/H2) **và KHÔNG** dòng counter §L.b(j) | session-end §L.b "(a)→(j) đủ HẾT, KHÔNG skip" (E-011 — nghi-thức chạy tắt; máy mù lớp "nghi-thức có chạy không") | RCA + spawn DỒN H1+H2 re-report phủ khoảng bị bỏ + harvest hồi-tố + đọc counter bù |
| **AS-16** | artifact **OUTWARD** (adap-report · email hub · broadcast) **cite sha CHƯA-push**, HOẶC được **stamp trước khi `git status --porcelain` sạch** | E-012 — closeout-squash phá đúng sha vừa cite ⇒ con-trỏ chết với người ngoài; và file sửa sau khi stamp làm câu trong bản đã-niêm thành sai. **Cite outward = commit SẼ SỐNG sau squash.** `git status` là bước **ĐẦU** của outward-gate, không phải bước cuối | RCA + re-anchor sang commit đã-push + **errata rời** (CẤM sửa file đã stamp — vỡ hash) |
| **AS-20** | sổ/stub khai *"X đã được ghi/chuyển/kết-luận"* mà đĩa **0 hit** — claim mạnh hơn việc đã làm | E-016 (S162 ×3 ca cùng phiên: `cicd-monitor` "verbatim→archive" thứ chưa từng archive · `ship-synthesis` trích VERDICT không tồn tại · memory viết claim CÓ-ĐIỀU-KIỆN thành vô-điều-kiện) | mệnh-đề *đã-làm* = **CLAIM ĐO ĐƯỢC**, phải đo trước khi viết; guard = **END-line bắt buộc** cho mọi `sub-*.md` (`END <slug> — VERDICT=<…>`) để trích dẫn luôn có neo grep được |
| **AS-19** | nén/gộp block trí-nhớ làm **rơi ý** mà không để lại vết (byte hợp-lệ, số-hiệu hợp-lệ, máy im) | E-015 (S162: nén `MIND-1` cấp disposition 3/5 ý ⇒ 2 ý mất, 1 trong đó **0 hit ngoài chính block bị nén**) | trước khi nén: liệt tập-ý mục D + gán **nơi đi** từng ý (đóng/carry/con-trỏ). Nén = chuyển-dạng, KHÔNG phải giảm số ý. 🔴 hiện là **nghi-thức, chưa cơ-khí-hoá** |
| **AS-17** | sub được lệnh ghi-đĩa-trong-lúc-làm nhưng lúc return/chết sub-file chỉ có **SKELETON** (header/checklist, 0 finding) — byte-content KHÔNG tăng theo tiến độ | sub-class `skeleton-ruột-rỗng` (E-013 — S150 gate `wf_f4e4c006` khung 274B/0-append → S151 ×2 thuần [sub-lead-stale header-only + sub-lead-gap checklist-only] = **2-strike**; "ghi-đĩa-trong-lúc-làm = CẦN, KHÔNG ĐỦ" — `feedback_agent_return_garble_recover`) | lead verify **BYTE-CONTENT tăng thật GIỮA wave** (đọc RUỘT — size nhỏ = nghi-vấn không phải bằng-chứng, phân biệt skeleton vs đang-viết-dở; H2 m#19) → resume-in-session ép đổ ruột (S151: 5/5 sạch) · lane quan-trọng giữ N-lane-redundancy + em-main-solo backstop |

## 🛡️ Active-Guards index (2-strike promote: episodic → procedural)

> **net-effect rule:** a guard that costs more than it saves (hại>lợi) → **retire**. `verified` = ran ≥1× and held. `strikes` = times the underlying error recurred before the guard.
> **G-011 ladder (canonical on-disk từ S139 — trước đó chỉ sống trong lineage adap-reports):** nấc tiến-độ khi khai một việc: `agreed` (đồng-ý làm) → `executed` (lệnh đã chạy xong) → `verified` / `verified-pending-restart` (đã KIỂM chạy thật; edit agent-file no-hot-reload = verified-pending-restart). 🔴 **KHÔNG tự khai `verified`** khi chưa có phép kiểm chạy được. Tham-chiếu: rules §6.6 K4 relay-attribution.
> **Luật re-base số-sống (K6.2 — generalize E-010, adopt S139):** Re-base baseline = chốt số **SỐNG** tại lúc re-base — mọi số vào sổ đọc lại từ **nguồn sống tại thời-điểm ghi** (CẤM chép từ ghi-chú/phiên trước, kể cả ghi-chú của chính mình); byte = `(Get-Item).Length` (E-010). *(nhà đề-xuất-mặc-định — [owner-reviewable])*

> ### 🪤 Carve-out ô3 — điều-kiện SỐNG (adopt S141, ghim S142)
>
> **Nấc:** force-fire khi closeout gộp sổ chạy dưới dạng **đề-xuất-chạy chờ anh gật** (KHÔNG auto-run) đứng ở nấc **`PASS-với-carve-out`** — 🔴 **CẤM nâng thành `PASS-trần`**. Đây không phải trừ-điểm: nó ghim đúng *điều-kiện sống* của carve-out.
>
> **VALID chỉ khi CẢ 2 lưới còn sống CÙNG LÚC** (đích danh, không nói chung chung):
> - **(a) dòng-nợ read-only vẫn IN ở MỌI điểm dừng** — `scripts/nhip-no-probe.ps1`
> - **(b) cái dò "closeout-thiếu-nghi-thức" vẫn được NỐI** — section `H25-closeout-ritual (GAP-2)` trong `scripts/governance-detectors.ps1`
>
> **Vì sao buộc CẢ HAI:** chuyển từ "máy tự chạy" sang "chờ anh gật" thì rủi-ro MỚI sinh ra là *anh quên gật mà không ai kêu*. Hai lưới trên **chính là cái kêu** — dòng-nợ cho anh thấy khoản quá-hạn, cái dò bắt closeout gộp mà thiếu nghi-thức.
>
> 🔴 **1 lưới chết ⇒ carve-out mất lớp tự-minh-bạch ⇒ RE-EVAL nấc**, và trong lúc chờ thì **tụt về chạy-vô-điều-kiện** cho tới khi lưới sống lại. Đây là luật đứng, không phải khuyến-nghị.
>
> **Basis:** hub reply `9a35405b` **khối-2** (`broadcasts/inbox/2026-07-17-ai_infra-to-se-reply-adap-wave-carveout-dp2.md`) — hub CONFIRM carve-out hợp-lệ *và* ghim đúng 2 điều-kiện này.
>
> **Live-evidence S139→S140 (dogfood mở sổ, không khai suông):** dòng-nợ `light 8/6` quá-hạn IN tại cửa nối-lại → anh **gật** → cặp H24 (`lead-view-auditor` + `lead-omission-auditor`) chạy THẬT → ra cờ THẬT (2 cờ view-cũ sửa trong phiên + 1 cờ MED "quyết-định-chìm" lặp-2) → probe sau audit `light 0/6`. Đủ một vòng: **nợ hiện → gật → chạy → ra việc thật → nợ về 0.**
>
> **Kiểm tại S142:** cả 2 lưới **SỐNG** (`scripts/nhip-no-probe.ps1` có trên đĩa; `H25-closeout-ritual` còn wired trong suite và chạy ra output) ⇒ nấc `PASS-với-carve-out` đứng vững, chưa phải re-eval.
>
> **Cùng CLASS — trio-consent S141:** bộ-ba đồng-kiểm memory (`harness-eval`/`refine`/`audit`) chạy **consent-gated** cũng là carve-out CÙNG LOẠI, chịu CHUNG luật trên; lưới của nó = **(a) proposal-line in CẢ khi Light-session** (không skip im) + **(b) vết-skip ghi `.claude/WAL.md` dạng `trio: skipped S<nn> (lý-do)`** để chuỗi skip nhìn thấy được. Khai nấc `PASS-với-carve-out` trong adap-report, KHÔNG PASS-trần; 1 trong 2 lưới chết ⇒ re-eval y hệt ô3.

| Guard | Counters | Tier | Strikes | Verified | Net |
|---|---|---|---|---|---|
| CI `paths-ignore` docs-only skip | gotcha #41 (AS-6) | procedural | 2 | ✅ (every docs commit 0s) | +++ |
| em-main verify-on-disk + proxy-append after agent return | gotcha #53 truncation | procedural | 5× (S35-S42) | ✅ | +++ |
| test-before bug-fix + soft-delete-UNIQUE `.HasFilter` | gotcha #57 (AS-4) | procedural | 3 (Holiday S45 · LeaveType/Shift/OtPolicy S51) | ✅ Mig 43 + Mig 45 (5 test RED→GREEN) | ++ |
| reviewer pre-commit on cross-stack / wire-BE-CRUD (contract-mismatch net) | E-007 (AS-11) | procedural | 1 (S51 Driver FE↔BE) | ✅ S51 (caught pre-commit, fixed before deploy) | ++ |
| verify byte-content sub-file GIỮA wave + resume-ép-đổ-ruột (anti skeleton-rỗng) | AS-17 / #53 sub-class E-013 | procedural (promote 2-strike @S151) | 2 (S150 gate + S151 stale/gap) | ✅ S151 (resume 5/5, 0 mất dữ-liệu; trio return-only 3/3 clean cùng phiên = counter-datum) | ++ |
| authz regression test per-action policy | gotcha #44 silent-403 | procedural | 1 (promoted S45 +10 test) | ✅ | ++ |
| agent frontmatter `model: inherit` (not `[1m]`) | gotcha #37 | procedural | — | ✅ (FD agent loaded S48) | ++ |
| **lead = sole RAG-writer** (`store_memory` stripped, mechanized) | store_memory rebootstrap-loss (S41) + AS-3 | procedural | 2 (NamGroup + SE S41) | ✅ runtime S48 (0/8 subs) | +++ (failure-safe) |
| session-end verify memory byte>0 | S46 0-byte (AS-8) | procedural | 1 (S46) | ✅ S49 (new mem 2355B + 0 byte-0 scan) | ++ |
| **git-diff + chunk-count post-P2 containment** (defense-in-depth, HMW) | R1 sub-write residual (AS-10) · store_memory bypass (AS-3) | **procedural** (institutionalized S50 = standard B6 post-wave audit) | 1 (S49) | ✅ S49 (caught inv-api self-MEMORY in git-diff; chunk 2414=2414) + **S50 wave `h2-verify` (git-diff agent-memory EMPTY, chunk 2415=2415, 0 leak)** + **S93 (WF1 3-agent residual caught+reverted; WF2 0-residual after explicit return-only)** + **S95 (WF1+WF3 residual caught+reverted 2×; WF3 explicit-return-only STILL self-wrote → instruction-fix NOT 100%, git-diff = the net)** + **S103 (investigator recon-agent garble-CURATED own memory [archive/2026-07.md new dù L1 NOT over-cap 17337<25600] → caught+reverted git-checkout; #53 ×3 phiên → recover incl Lane-B-from-diary; reviewer/tooling-auditor self-writes = LEGIT harvest kept)** | +++ (G-015 honest — 5 fires/5 catches/0 escape; NOT allowlist-alone, NOT instruction-alone) |
| heavy spawn → `run_in_background` | looks-frozen | **procedural** (2-strike met) | 2 (S45, S48) | ✅ S48 (FD bg) + S50 (all 4 monitor+wave spawns bg) | + |
| RAG glob `**/`-anchored (not root) | gotcha #10 node_modules leak | procedural | 1 (S41) | ✅ (2406 clean) | ++ |
| dump bảng env-đích TRƯỚC identifier-based data op (lock/seed-by-email) | gotcha #60 (AS-12) | episodic | 1 (S57bis lock NO-OP) | ✅ S58 (recon dump → fix `5998163` → Run #382 đo 34 locked) | ++ |
| custom Workflow same-role → copy return-delta-guard HOẶC file-disjoint 1-sub/file | E-009 (AS-13) | episodic | 1 (S71 invest/review race) | ✅ S71 (curate workflow `wf_f32987b8` file-disjoint 1-sub/file = 0 race; finalize curate đóng over-cap) | ++ |
| đo text = ép `UTF8Encoding` tường-minh (PS5.1 no-BOM ⇒ ANSI ⇒ số phồng ×2-3) | E-010 (AS-14) | episodic | 1 (S130) | ✅ S130 (B3 round-trip dùng UTF8-explicit PASS 2 file; số đính-chính cùng phiên) | + |
| điểm-đóng-thật ⇒ tự-hỏi "diary monitor có delta? dòng counter có in?" (chờ hub canonical detector) | E-011 (AS-15) | episodic | 1 đợt (×3 closeout S128-S130) | ✅ S132 (spawn dồn H1+H2 phủ S127→S131 xong: H2 GAPS→CLOSED + H1 1-drift-FIXED + 2 diary H24 seeded + counter-line in §L.b(j)) | + (đề-xuất khung đã gửi hub `e46863c8`) |

## 📋 RCA entries (blameless — newest on top)

> Format: `E-NNN | date | rule | what | 5-why root | fix (prod-bug = 2-fix: code + guard) | prevention | tags[TYPE/ACTOR/COMPONENT]`

### E-016 — AS-20 claim-mạnh-hơn-việc-đã-làm: sổ khai "đã archive / đã verbatim / đã VERDICT" cho thứ chưa từng tồn tại trên đĩa (S162, **3 ca cùng phiên**, H2 `harvest-curator` bắt cả 3)

- **rule (AS-20 NEW):** mọi mệnh-đề trong sổ có dạng *"X đã được ghi/chuyển/kết-luận"* là một **CLAIM ĐO ĐƯỢC** ⇒ **phải đo trước khi viết**, không được suy từ ý-định. Đặc-biệt nguy khi câu đó nằm trong **stub/summary** — nơi người đọc sau coi là đã-xử-lý xong nên **không mở gốc kiểm nữa**.
- **what — 3 ca, 1 class:**
  1. **F-02** `cicd-monitor/MEMORY.md:9` stub khai *"(#422 `b5799fc` · #423 · #424 · #425 `a2bbcb9`) + #419 — verbatim → `archive/2026-07.md`"*; đo: #423/#424/#419 CÓ, **#422 và #425 = 0 hit toàn `agent-memory/`**, `git log -S"b5799fc" -- .../archive/` **RỖNG toàn lịch sử** ⇒ chưa từng vào archive.
  2. **F-03** `ship-synthesis.md:14` trích ``designer `VERDICT: SHIP-READY` `` như **verbatim của vai**, nhưng `sub-frontend-designer-0.md` (17.844 B) **0 hit** `ship.?ready|VERDICT|END` — file kết bằng "TỰ ĐÁNH GIÁ CÒN HỞ". Nội-dung khớp đĩa (tsc/build EXIT 0, SHA-pair 6/6) ⇒ **không phải bịa**, nhưng **hình-thức trích dẫn tạo ra một chuỗi không tồn tại**.
  3. **F-08** (reviewer bắt, cùng phiên) memory `frontend-designer` viết *"0 rác 403"* **vô điều kiện** — thật là claim **CÓ ĐIỀU KIỆN** (chỉ đúng khi gate dùng đúng key policy endpoint); + câu *"`Ct_*` kế thừa `Contracts`"* SAI vì seeder tạo row `Ct_*` riêng.
- **5-why:** (1) người viết sổ vừa làm xong việc nên "biết" nó đã xong → (2) viết câu tổng-kết theo **trí-nhớ về ý-định**, không theo đĩa → (3) câu tổng-kết đọc mạnh hơn thực-tế → (4) **stub/summary được thiết-kế để thay thế việc mở gốc** ⇒ sai-số đóng băng ngay tại lớp mà người sau tin nhất → (5) máy MÙ: không detector nào so được "câu khai" với "trạng-thái đĩa" ở dạng tổng quát.
- **fix KÉP (bug-production = 2 fix):** (a) **vá dữ-liệu** — đính chính `cicd-monitor/MEMORY.md` (@S162, nêu rõ nguyên-liệu còn ở run-folder S159, re-distill khi retro-harvest) + sửa 2 câu memory `frontend-designer`; (b) **vá guard** — luật **END-line bắt buộc**: mọi `sub-*.md` kết bằng `END <slug> — VERDICT=<…>` ⇒ trích dẫn verdict **luôn có neo đo được**; ai trích mà grep 0 hit thì lộ ngay. (Đã lên HANDOFF NEXT-em #4 + `[carry:endline-sub-md]`.)
- **guard hiện có ĐÃ giữ:** H2 5-trục Fidelity-FLAG bắt được cả 3 ca **trong cùng phiên chúng sinh ra** ⇒ nấc episodic, chưa cần promote procedural (mới 1-strike với class này).

### E-015 — AS-19 nén-block làm rơi ý IM-LẶNG: nén `_mind` hợp-lệ về byte nhưng 2/5 ý mục D mất không để lại vết (S162, `ctx-verifier` K7 bắt)

- **rule (AS-19 NEW):** thao-tác **nén/gộp một block trí-nhớ** phải đối-chiếu **TỪNG ý** trong block bị nén có **nơi đi** (đóng · carry sang block mới · con-trỏ ra sổ bền). Nén = **chuyển-dạng**, không phải **giảm số ý**; giảm ý mà không khai = **mất dữ-liệu hợp-thức-hoá**.
- **what:** nén `MIND-1` @PAUSE-3 (vượt trần 212 B) tự cấp disposition `(nay …)` cho **3/5 dòng mục D**; **đúng 2 dòng không có disposition là 2 ý biến mất khỏi MIND-4**: `slot-45` (tiền-đề **đã LẬT** — trần thật 89,06%, nên ý này đang từ "báo-động-giả" trở lại "vấn-đề thật") và `detectors :1095/:1760 lọc sub-* sót trio-return (C11b)` (**0 hit ở WAL, 0 hit `_context`, chỉ còn trong chính MIND-1** ⇒ nén lần nữa = **mất hẳn**).
- **vì sao KHÔNG kêu:** máy `mind-check` phép (5)(6) chỉ soi **số-hiệu + bất-biến |block| vs p** — nén là **hợp lệ** với cả hai; phép (9) chỉ đòi *mỗi ý mục D có nhãn*, không đòi *mọi ý kỳ trước có nơi đi*. ⇒ đây là **vắng-mặt trông giống ổn** (`feedback_absence_looks_like_clean`) ở đúng lớp trí-nhớ mềm.
- **5-why:** (1) trần `_mind` chật (89%) ⇒ mỗi cửa buộc nén 1 block → (2) nén chọn block CŨ NHẤT (đúng luật) → (3) người nén tóm-tắt theo **ấn-tượng còn lại**, ý nào không nhớ thì rơi → (4) rơi **không sinh diff đọc được** (block cũ vốn được phép co lại) → (5) ý sống-sót duy-nhất ở block bị nén thì **không có nguồn thứ 2 để đối-chiếu**.
- **fix KÉP:** (a) **vá dữ-liệu** — di-trú 2 ý vào WAL rồi lên `HANDOFF` slot (58) + `[carry:mind-tran-nen-moi-cua]`; (b) **vá guard** — trước khi nén, liệt tập-ý mục D của block sắp nén và gán nơi-đi từng ý (nghi-thức, chưa cơ-khí-hoá được: máy không phán được "ý này đã đóng chưa"). 🔴 Khai thẳng: **guard (b) hiện là NGHI-THỨC, không phải máy** ⇒ đúng lớp "cấm bằng trí-nhớ" mà repo này vốn cảnh-giác; nâng lên máy được khi có nguồn thứ 2 để diff.
- **liên-đới:** trần chật là **nguyên-nhân gốc** ⇒ slot (58) hỏi owner (nâng `mind_ctx_kb` / đổi luật nén / chấp nhận nén mỗi cửa) — vá triệu-chứng mà không hỏi trần thì ca này **tái diễn mỗi cửa `/pause`**.

### E-014 — AS-18 slot-index tái-dụng làm MẤT owner-decision không để lại vết (S146, H24 `lead-omission-auditor` bắt, lead verify bằng `git show`)
- **rule (AS-18 NEW):** khối đánh số (`OWNER-DECISION [n]`, checklist, enum…) **CHỈ ĐƯỢC TĂNG index**. **CẤM tái-dụng số cũ cho nội-dung mới.** Đè slot = nội-dung cũ **biến mất im-lặng** — khác hẳn đổi giá-trị (còn thấy giá-trị cũ để grep).
- **what:** owner @S146 nói *"còn lại xử lý hết xong rồi session-end nhé"*; lead ghi ĐÚNG vào `.claude/WAL.md:9` slot `[7]` = **uỷ-quyền commit+push** (`ad02483`, `9c68bae`). Sau đó lead thêm 3 quyết-định session-model và **tái-dụng slot `[7]`** ⇒ `e7d06f2` mất hẳn dòng cũ. Grep toàn repo = **0 hit**.
- **hệ-quả THẬT (không phải lý-thuyết):** lead hỏi lại *"cho push chưa"* **3 lượt liền** — hỏi lại đúng thứ owner ĐÃ trả lời, và hỏi ngay dưới khối tự đặt tên **"ghi đè, KHÔNG hỏi lại"**. Lead làm **ngược** chính luật mình viết.
- **5-why:** (1) lead thêm mục mới vào khối có sẵn → (2) chọn số kế-tiếp *theo cảm-giác* thay vì đọc số lớn nhất đang dùng → (3) `[7]` trông "trống" vì lead nhớ khối chỉ tới `[6]` → (4) WAL **ghi-đè toàn-file** nên không có diff-review từng dòng như commit thường → (5) **máy MÙ hoàn-toàn**: không detector nào biết `[7]` từng là thứ khác.
- **fix:** khôi phục `[7]` (nguồn `git show ad02483:.claude/WAL.md:9`) + đẩy session-model xuống `[8]` + ghi luật **SLOT-INDEX CHỈ-TĂNG** ngay tiêu-đề khối.
- **prevention/guard:** vai H24 soi **CÁI THIẾU** = catch-layer **DUY NHẤT** cho lớp này (H24 §2(1) *"máy MÙ gần như hoàn toàn"*). 🔴 Nhắc: WAL ghi-đè ⇒ **mọi mất-mát trong WAL đều im lặng** ⇒ đối-chứng phải là `git show <sha>:.claude/WAL.md`.
- **tags:** [slot-reuse / lead / WAL.md · owner-decision · gap-owner-specifics · class_repeat 2→3 CHẠM jump]

### E-013 — AS-17 sự-cố KHÔNG vào sổ bền + phép trích-xuất hỏng đọc thành "sạch" (S146, cụm 2 lỗi cùng lớp *"vắng mặt trông giống ổn"*)
- **rule (AS-17 NEW):** (a) sự-cố chỉ có vết trong **run-folder** = **CHƯA vào sổ**; phải đổ vào ≥1 **sổ bền** (error-ledger / STATUS / HANDOFF / auto-memory). (b) phép trích-xuất trả **RỖNG** phải phân-biệt *"không có gì"* ⟂ *"phép đo hỏng"* — **CẤM đọc rỗng thành sạch**.
- **what (a):** garble `#53` THẬT trên `harness-audit` @S144 (`trio-synthesis.md:20-21`) + lead thu-hẹp tập đối-chứng mà im-lặng (*"đối chứng 4 mốc: 0 LỆCH"* trong khi khối liệt **5**, mốc-5 chính là mốc lệch) ⇒ **0 hit** ở cả 5 sổ bền; sổ đếm `feedback_agent_return_garble_recover.md` dừng ở `×25 qua S143`. **S146 thêm 3 garble nữa** (lead-view · lead-omission · h24-audit — **3/3 vai lane-H24**).
- **what (b):** lead vá 6 site consent theo danh-sách H24 liệt, **vá 5 sót 1** (`ring2-audit.md:25` (tên cũ h24-audit.md — rename @S149) — câu tự mâu-thuẫn *"KHÔNG consent-gate … khi OVERDUE + anh consent"*). **Cơ-chế tái-dựng được:** lệnh trích `grep -oE '.{50}consent.{80}'` đòi **đúng 50 ký-tự TRƯỚC** match; trên dòng đó `consent` ở ~offset 30 ⇒ **0 match ⇒ output RỖNG** ⇒ lead đọc thành *"dòng này không có gì"*. Đúng phải là `.{0,60}`.
- **5-why (b):** (1) vá theo danh-sách người khác liệt → (2) không tự grep lại sau khi vá → (3) dùng cửa-sổ ngữ-cảnh **cố-định** thay vì **0..n** → (4) rỗng **trông y hệt** sạch (khác `grep -c` trả `0` — một con SỐ, nhìn là biết đang đếm) → (5) `h24-audit` bắt được vì nó **đọc dòng đó trong chính persona nạp vào mình** + đối-chứng đĩa = 2 nguồn.
- **fix:** vá `:25`; re-grep toàn file = 0; ghi cụm sự-cố vào chính entry này.
- **prevention/guard:** 🔴 **Luật: vá xong PHẢI tự grep lại bằng lệnh KHÁC lệnh đã dùng để tìm** (khác mẫu, khác cửa-sổ). Họ hàng đã có trong sổ: `grep -c` (dòng) vs `grep -o|wc -l` (occurrence) — nay thêm **cửa-sổ-ngữ-cảnh-cố-định**.
- **EXT @S152 — tái-phát lần 2, cùng-họ `ring*`, cùng hình-dạng (b):** đợt sleep-AUTO owner (32) quét 7-site trong `commands/` mà **sót trọn lớp `agents/`** — stale-close FLAG-4 bắt `ring4-audit.md:26/:27`; H1 liệt lô 5-site vẫn **sót site-6 `ring1-audit.md:24`** (vết núp trong ngoặc SAU câu đúng "KHÔNG consent-gate (…gật mới chạy)") — `ring1-close` tự bắt **trong persona chính mình** bằng mồi KHÁC ("gật mới chạy"); lead grep cùng-lớp ra thêm 3 site trio-persona (`harness-eval.md:4` description · `harness-refine.md:58` · `harness-audit.md:50` vế "First-run chờ consent") ⇒ **lô cuối 9 site** (+2 vết ring2 đã vá đúng từ trước). Guard siết thêm: **sweep theo LỚP-file (commands + agents + skills), đừng theo danh-sách-site người khác liệt; mồi grep ≥2 biến-thể** ("consent" · "anh gật" · "gật mới chạy").
- **tags:** [incident-unrecorded + extraction-silent-empty / lead / error-ledger · ring2-audit.md:25 · #53 ×3 S146 · EXT-S152 lô-9-site ring1-audit.md:24]

### E-012 — AS-16 bằng-chứng-tự-huỷ-sau-squash: 7 adap-report + 1 email hub neo vào sha `wal:` chưa-push, closeout-squash phá đúng sha đó (S143, reviewer-gate độc-lập bắt SAU khi thư đã gửi)
- **rule (AS-16 NEW):** artifact OUTWARD phải cite **commit SẼ SỐNG sau squash**, và phải qua `git status --porcelain` **TRƯỚC** khi stamp. Vi-phạm nền: `/adap-report` §3 *"evidence: commit-sha · file path · byte/dòng (đo THẬT)"* — đo thật nhưng **neo vào con-trỏ sắp chết**; và `/send-email` 6c selftest-stamp chỉ kiểm **hash khớp thân-thư**, KHÔNG kiểm **thân-thư có còn đúng sự-thật** lúc phát.
- **what:** (1) 7 adap-report cite `1a0fa59`/`a458102`/`96ab2679`/`c3708e9`/`b1d92b9` (đều `wal:`-commit local). Closeout §5.0 `reset --soft HEAD~8` gộp chúng vào `2757e41` ⇒ cả 5 thành **dangling**: `cat-file -t` = `commit` (sống nhờ reflog LOCAL) nhưng `merge-base --is-ancestor <sha> origin/main` = **exit 1** ⇒ hub clone repo về `git show 1a0fa59` = **object missing**. Nội-dung nguyên vẹn trong `2757e41` ⇒ **chết con-trỏ, không chết việc**. (2) Cùng gốc: report + email khai `is-ancestor 96ab2679 HEAD = exit 0 → OK-reachable` làm bằng-chứng "contract v2 chạy runtime" — squash **cùng phiên** lật nó thành `exit 1`/`SQUASH-BENIGN` ⇒ **phép đo tự huỷ trong chính phiên phát-biểu nó**. (3) Biến-thể thứ ba: email `:47` khai *"vế pull-age **chưa làm**, chờ owner"* — owner gật ngay sau đó, lead làm, `scripts/nhip-no-probe.ps1` sửa **sau** khi thư đã stamp ⇒ bản đã-niêm khai sai hiện-trạng, và **không sửa được** (sửa = vỡ hash).
- **5-why root:** (1) vì sao sha chết? — squash rewrite history. (2) vì sao squash sau khi cite? — report viết **trước** push, đúng thứ-tự tự-nhiên của việc ("làm xong thì ghi lại"). (3) vì sao thứ-tự đó sai? — vì với artifact OUTWARD, *người đọc ở repo KHÁC*, nên tham-chiếu chỉ có nghĩa nếu nó tồn tại **trên remote**, không phải trên đĩa mình. (4) vì sao không ai bắt lúc viết? — mọi phép verify của lead chạy **trên máy lead**, nơi reflog còn giữ sha ⇒ `cat-file -t` xanh ⇒ **kiểm bằng góc nhìn người-trong-nhà cho một artifact gửi người-ngoài**. (5) 🔴 **root:** *tiêu-chí verify được chọn theo cái mình đo được, không theo cái người nhận sẽ đo.* Cùng class với E-010 (đo bằng công-cụ tiện tay) và với "TRIPLE chọn enum DỄ" cũng bắt trong phiên này.
- **fix (KHÔNG prod-bug — artifact-only, vẫn 2 lớp):** *(a) lớp artifact:* re-anchor toàn bộ 7 report sang `2757e41` + thêm caveat ghi rõ sha cũ chỉ còn giá-trị local; phát **errata rời** `e43484cef10f` cho hub (CẤM sửa bản đã stamp). *(b) lớp luật:* AS-16 + 3 luật đọc-được ghi vào report/errata — **cite outward = commit sống sau squash** · **`git status` là bước ĐẦU của outward-gate** · **tách claim-DELTA (bền) khỏi claim-TUYỆT-ĐỐI (phải neo commit+thời-điểm)**.
- **prevention/guard:** *episodic → chờ strike-2.* Guard đề-xuất khi tái: chèn vào `/send-email` bước 6c một phép **`git status --porcelain` = rỗng** + **`merge-base --is-ancestor <mọi sha cite> origin/main`** trước khi stamp; fail ⇒ ABORT. 🔴 **Chưa wire** — vì guard này cần định-nghĩa "sha cite" (parse thân-thư) và có thể dương-giả với sha của repo KHÁC (hub sha như `58e28bae` KHÔNG nằm trong repo SE). Ghi làm nợ, không tự dựng cổng nửa vời.
- **Đối chứng (chứng đây là class, không phải xui):** wave TRƯỚC (S138–S139) cite `7760cdf`/`da349fc` = commit **đích** sau squash → **sống hết tới nay**. Cùng người, cùng nghi-thức, khác đúng một điểm: thời-điểm viết report so với thời-điểm push.
- **tags:** `[GOVERNANCE/lead/outward-artifact · evidence-self-destruct-squash · cite-post-squash-commit · git-status-first · verify-tu-goc-nhin-nguoi-nhan]`

### E-011 — AS-15 nghi-thức chạy tắt: 3 closeout liên-tiếp S128-S130 KHÔNG spawn monitor H1/H2 + bỏ §L.b(j) — máy im suốt, lộ nhờ 1 câu hỏi của anh (S131 phát-hiện, S132 xử)
- **rule (AS-15 NEW):** session-end §L.b (session-end.md:52) *"auto-maintain (a)→(j) đủ HẾT, KHÔNG skip — thiếu = ledger thối"*; (d)(f) = H2 harvest-curator · (g) = H1 tooling-auditor · (j) = đọc counter/OVERDUE. **Điểm-đóng-thật** (chốt-đợt + push) đi qua mà nghi-thức không chạy = closeout chạy tắt, dù phiên kết thúc bằng `/pause` chứ không phải `/session-end`.
- **what:** 3 closeout liên-tiếp — S128 `289ba96` 20:57 · S129 `295c70c` 23:16 · S130 `71757fc` 00:26 — commit + push xong mà KHÔNG spawn H1/H2 (mtime diary 2 monitor đứng 2026-07-16 15:18; commit cuối chạm diary = `e9124fc` 15:19; S130 Recently-Done còn tự ghi *"0 sub spawn"*) + bỏ luôn §L.b(j) — cả lớp ĐỌC counter cuối phiên không chạy. Không detector nào đo lớp "nghi-thức có chạy không" → im lặng trông y hệt sạch; chỉ lộ khi anh hỏi *"sao không thấy lead-view/lead-omission/harvest chạy?"*. Họ-hàng cùng đợt (GAP-1, email `e46863c8`): mạch pause→`/tiep` không tick counter H24 → S128·S129·S130 không tick → counter dưới-đếm ~37% trên cửa-sổ 8 nhãn (5 tick/3 không).
- **5-why:** phiên kết thúc bằng `/pause` (H22 điểm-dừng chủ-động) hoặc mở bằng `/tiep` nối-mạch → không đi qua cổng `/session-end` → §L.b không ai gọi → không gate máy nào ép (a)→(j) → 3 phiên lặp cùng kiểu → gốc = **kẽ THIẾT-KẾ giao-điểm 2 harness** (H22 pause/tiep ⟂ nghi-thức đóng §L.b + H24 tick 1-điểm-vào), KHÔNG phải lỗi cá-nhân một phiên; máy mù lớp nghi-thức (cùng họ caveat (e) adap-report H24).
- **fix (KHÔNG prod-bug — process):** (đợt này) S131 mở session-end ĐÚNG nghi-thức đầu-tiên sau 3 lần tắt (sentinel + §L.a + archive-gate DRY PASS) — chết giữa vì session-limit → S132 `/tiep` nối: spawn DỒN H1+H2 phủ S127→S131 + harvest hồi-tố GAP-3 (diary 2 vai H24) + entry này. (báo) email hub `e46863c8` 3-gap stamped + đề-xuất khung: tick đa-điểm-vào H22×H24 · detector "closeout-missing-monitor" · "first-run-role-has-diary" — chờ hub canonical, SE không tự chế detector riêng.
- **prevention/guard:** AS-15 thêm §L.a + Active-Guard episodic (occurrences ×3 nhưng 1 đợt phát-hiện — promote nếu tái SAU guard). Wire tick vào `/tiep` + tick-at-close = đề-xuất ĐÃ TRÌNH ANH (email mục "SE tự làm trong-khung" #1), **CHỜ ANH GẬT mới sửa `tiep.md`** — không tự áp.
- **tags:** [ritual-skip / em-main / session-end×H22-pause-tiep×H24-counter]

### E-010 — AS-14 encoding-mismeasure: `Get-Content` no `-Encoding` trên file no-BOM → báo owner số sai ×2-3 (S130, tự-bắt + đính-chính trong-phiên)
- **rule (AS-14 NEW):** phép ĐO text (length/count/so-sánh) phải ép encoding tường-minh. PS5.1 `Get-Content` trên file UTF-8 **no-BOM** đọc theo ANSI ⇒ mỗi ký-tự Việt (2-3 byte UTF-8) đếm thành 2-3 char ⇒ số phồng ×2-3. Repo này CỐ Ý để docs no-BOM ⇒ mọi phép đo mặc-định đều dính.
- **what:** S130 khi trình 3 mục owner-gated, em đo mega-line bằng `(Get-Content docs\STATUS.md)[5].Length` = 70.008 / HANDOFF = 65.429 → báo anh "phình ~13K chỉ trong 1 ngày" ngay trong AskUserQuestion. Số THẬT (UTF8Encoding explicit): 64.794 / 59.686 — phình thật +113 ch + ~2.5K. Kết-luận "đang phình" đúng HƯỚNG nhưng độ-lớn sai ~5×. May: cả 3 phương án đã trên bàn từ S126 ⇒ quyết-định anh không dựa số này.
- **5-why:** đo nhanh bằng cách quen tay (Get-Content index) → không nhớ PS5.1 đoán encoding theo BOM → file cố-ý no-BOM (chính-sách repo) → số sai trôi thẳng vào câu hỏi trình anh → chỉ bị bắt khi B3-execute phải ReadAllText UTF8 (round-trip cần byte-đúng) cho ra số khác ⇒ tự-đính-chính. Gốc: **phép đo không khai encoding = phép đo chưa chạm đĩa đúng cách** — cùng họ bẫy `grep -c` (đếm dòng ≠ occurrence) S121.
- **fix (KHÔNG prod-bug — measurement-only):** (đo lại) mọi con số phát-biểu lại bằng `[System.Text.UTF8Encoding]::new($false)` + đính-chính với anh TRONG phiên (WAL + STATUS + HANDOFF ghi cả số sai lẫn số đúng). (guard) AS-14 thêm §L.a + Active-Guard episodic + append `feedback_resume_premise_reverify`.
- **prevention/guard:** đo text ⇒ `ReadAllText($path, UTF8Encoding-explicit)`; cần ĐỌC tiếng Việt từ console ⇒ dump-ra-file rồi Read (console PS cũng mojibake — đã thấy cùng phiên với ACTIVE-MARKS). Số đã lỡ báo owner ⇒ đính-chính ngay khi phát-hiện, giữ kết-luận nếu còn đúng + khai độ-lớn sai.
- **tags:** [measurement-mislabel / em-main-solo / docs-megaline+PS5.1-encoding]

### E-009 — AS-13 custom-workflow same-role MEMORY write-race → over-cap (S71, finalize-review-caught, curated same-session)
- **rule (AS-13 NEW):** custom Workflow script (≠ hmw.js DEFAULT-mode) chạy parallel **same-role** agents giữ Write → mỗi agent chạy frontmatter "update MEMORY before return" → concurrent writes shared `agent-memory/<role>/MEMORY.md` → "file modified since read" race + verbose-append over-cap. hmw.js DEFAULT-mode inject return-delta-only writeGuard; custom script KHÔNG kế-thừa.
- **what:** S71 Harness-10 adop chạy custom workflow (h10-invest 4× investigator-codebase · h10-review + h910-finalize 3× reviewer). Agents tự-ghi diary → 4 investigator ghi `investigator-codebase/MEMORY.md` đồng-thời + 3 reviewer ghi `reviewer/MEMORY.md`. Kết quả: reviewer 24.8→**36.7KB** (harness silent-truncate ~8KB HOT lúc spawn), investigator 24→29.8KB — cả 2 over auto-inject cap 25600. Content HỢP-LỆ (additive, 0 corruption, git numstat +N -0) nhưng P1 curate-debt (claimed CLOSED S70) re-opened.
- **5-why:** custom invest/review/finalize workflow author KHÔNG inject return-delta-guard mà hmw.js DEFAULT có → same-role agents mỗi con chạy "update MEMORY before return" → concurrent write cùng file → race + bloat tích-lũy → over-cap → harness silent HOT-truncate. Caught: finalize-review R3 (`wc -c`) + budget-audit-by-hand S71 (KHÔNG phải runtime-error — silent).
- **fix (KHÔNG prod-bug — 0 production code):** (process) curate L1→L2 `wf_f32987b8-03f` **file-disjoint 1-sub/file** (reviewer 36.7→24.8 + inv 29.8→23.2, 0-byte-loss numstat +N -0 + grep-Fxf 10/10 + md5sum) + budget.json re-measure + reviewer-gist gen:2. (guard) AS-13 + Active-Guard episodic + `feedback_harness10_run_trace` #2 lesson.
- **prevention/guard:** custom Workflow parallel same-role → (a) inject return-delta-only writeGuard (mirror hmw.js DEFAULT), HOẶC (b) file-disjoint 1-agent/memory-file (curate S71 dùng = 0 race). Budget-audit @session-start re-measure bắt re-accumulation. hmw.js RUN-TRACE mode (S71) đã guard.
- **tags:** [memory-race-overcap / custom-workflow-agents / agent-memory reviewer+investigator-codebase]

### E-008 — AS-12 lock-demo-user prod NO-OP: population Dev ≠ prod + seed silent-fail (S57bis ship, S58 fix, cicd-caught)
- **rule (AS-12 NEW):** thao tác data theo-identifier trên prod (lock/seed/migrate-by-email) mà list viết từ CODE/Dev population, KHÔNG dump bảng env đích → silent NO-OP/sai-target. Assertion trả 0-row/`-1` ⟹ nghi data-mismatch TRƯỚC khi nghi code.
- **what:** S57bis ship `LockDemoSampleUsersAsync` 14 email named-person (đọc từ seed code = population Dev-only). Demo prod thật = 20 UAT-matrix (`bod.1@`, `pm.nv@`… tạo TAY 05-13, chưa từng trong code). Run #381 deploy PASS + health 200 + code RAN — locked=0, hoàn toàn silent. Tầng 2 ẩn sâu hơn: `DemoUserPassword` 11 ký tự < prod `Identity:Password:RequiredLength=12` → `CreateAsync` trả `IdentityResult.Failed` (LogWarning-only, by-design 1-fail-không-abort) **mọi startup từ trước tới giờ** → named-person + `nv.cao`/`nv.truong` (IT pool — root cause "helpdesk inert" S56!) + 5 real staff KHÔNG BAO GIỜ tồn tại trên prod.
- **5-why:** author tin seed code là source-of-truth population → Dev ≠ prod vì password-policy silent-fail → silent vì `IdentityResult` không throw → warning log prod không ai đọc → chỉ cicd #381 data-dump (PASS+PARTIAL) bắt được — test xanh + CI gate + health 200 đều mù với data-absence. **Why-0 (RAG-archaeology S58):** bug này TỪNG được phát hiện S22 (2026-05-13, session log ghi "Identity password policy ≥12 — existing memory mention `User@123456` 11 chars OUTDATED", 20 UAT user seed bằng `TestUser@2026` 12 ký tự) — nhưng const `DemoUserPassword` trong code KHÔNG được fix lúc đó → knowledge nằm trong session-log mà không thành code-fix/guard → tái diễn S57bis. Lesson: discovery phải đổi thành code-fix HOẶC ledger-guard ngay, session-log alone = chết.
- **fix (prod-bug = 2-fix):** (code) `5998163` union 20 email prod-population (exact-email, KHÔNG pattern — `binh.le@` người thật sát scheme demo) + password → 12 ký tự → Run #382 đo thật: 55 user / 34 locked / helpdesk sống / 5 staff tạo / guard 6-6 active. (guard) gotcha **#60** + debug-checklist item 32 + cicd LESSON "lock/deactivate-by-email trả 0 ⟹ ALWAYS dump actual Users trước khi score FAIL" + Active-Guard episodic mới (dump-env-đích).
- **prevention/guard:** mọi identifier-based op → dump env đích TRƯỚC khi viết list; seed password const thỏa policy NGHIÊM NHẤT mọi env (prod 12); grep warning log sau deploy có user-seed mới. AS-12 added §L.a.
- **tags:** [seed-silent-fail+population-mismatch / em-main-S57bis-author · cicd-caught · recon-grounded / DbInitializer]

### E-007 — AS-11 parallel-fan-out shared-contract mismatch (S51, reviewer-caught pre-commit)
- **rule (AS-11 NEW):** cross-stack feature fan-out where BE field nullability/validator ≠ FE required-marker for the SAME field → contract mismatch (empty submit → 400/500). Em-main shared-contract must spec required/optional consistently BOTH sides.
- **what:** P11-C BE∥FE parallel (file-disjoint) spawn. Driver `phoneNumber/licenseNumber/licenseClass`: BE `NotEmpty()` validator + EF `.IsRequired()` NOT NULL, but FE KIND_CONFIG rendered them OPTIONAL (no `required:true`) → `buildBody` empty→null → 400/500. 186 tests GREEN (no test hit empty-optional path).
- **5-why:** em-main BE brief said "mirror Vehicle (all-required)" but FE brief omitted `required:true` on those 3 → each implementer faithful to its half → inconsistency invisible until integration (file-disjoint parallel = no cross-talk) → green tests ≠ correct contract.
- **fix:** (code) FE +`required:true` on the 3 fields (align to BE all-required, like Vehicle — `HrmConfigsPage.tsx:132-134` ×2 app). (guard) reviewer pre-commit on cross-stack = the net that caught it (HELD).
- **prevention/guard:** Active-Guard "reviewer pre-commit on cross-stack/wire-BE-CRUD" (fired correctly) + NEW discipline: em-main cross-stack brief MUST state required/optional explicitly for EACH shared field (BE validator+nullability AND FE required-marker). AS-11 added to §L.a.
- **tags:** [contract-mismatch / em-main-brief+implementer-be+fe / HrmConfigsPage,HrmConfigFeatures]

### E-006 — AS-10 autonomous monitor write at session-end (S50, git-diff-caught)
- **rule (AS-10):** sub writes a tracked file despite propose-only / R1-return-only (Write/Bash residual) → git-diff catch → lead VERIFY benign+accurate+placement → keep-if-correct or revert.
- **what:** @S50 `/session-end`, `git status` = **14 modified** but em-main personally edited ~7. Non-em-main writes: `error-ledger.md` (2 guard episodic→procedural promotions + E-002 #57 coords), 3 `adap-reports` (nac→verified-runtime), 4 `agent-memory/*` Recent-activity, + `STATUS.md` (Recently-Done-S50 block / In-Progress flip / RAG-line 2406↔2415 reconcile). mtimes 00:00–00:05 = session-end monitor window; the 2 INFORM-only monitors (tooling-auditor + harvest-curator) were briefed propose-only and **reported "wrote nothing."**
- **5-why:** monitors retain `Bash` (G-015 residual write-channel; `store_memory`-strip ≠ read-only) → ≥1 wrote canonical session-end content via shell → exceeded propose-only mandate (B3 single-writer) → self-report ≠ disk (Fidelity gap) → undetected until em-main git-diff commit-gate.
- **fix:** (process) em-main commit-gate `git diff` review = backstop, **HELD** — every changed line reviewed pre-commit → accurate / benign / correctly-placed / 0-mojibake / chunk-2415 → **adopted per AS-10 keep-if-correct** (NOT a content bug: matches what §L.b prescribes). (guard) "git-diff + chunk-count post-P2 containment" already promoted procedural this session; AS-10 now has its **first real fire**.
- **prevention/guard:** RECOMMEND (anh / AI_INFRA, charter-v2 infra): harden monitor tool-grant — `Write/Edit` removal alone leaves Bash residual → consider a session-end hook blocking sub-Bash-write to tracked paths, OR accept commit-gate as sufficient defense-in-depth. Fidelity: if monitors write, their reports MUST disclose it → escalate 🟥 reviewer if recurs. Provenance timing-implicated, **not definitively attributable** (no false accusation).
- **recurrence S93 (2026-06-29):** AS-10 2nd fire — 3 WF1 workflow-agents (investigator-codebase ×2 + reviewer, return-only) self-wrote agent-memory (diary append + archive self-curate + 1 stray `project_s92_*` mis-named file). git-diff post-P2 containment caught ALL → em-main reverted (kept cicd-monitor PE-deploy harvest hợp-lệ). Guard HELD again. **WF2 fix:** added explicit "RETURN-ONLY: do NOT write ANY file incl MEMORY.md" to every lane prompt → **0 residual** (instruction-fix worked, git-diff confirmed). Lesson: workflow-agent frontmatter "update MEMORY before return" fights return-only mandate → prompt MUST override + git-diff is the net (G-015, not mechanized).
- **recurrence S95 (2026-07-01, H17 adopt):** AS-10 **3rd + 4th fire** — WF1 (investigator-codebase self-compacted its MEMORY.md 25.5→16.98KB, CLAIMED archive-move but `archive/2026-06.md` was NOT created → keeping it would have LOST 8.5KB) + WF3-Lane-A (reviewer self-wrote diary + new `project_s95_harness17_faultinjection.md`). git-diff post-P2 caught BOTH → em-main reverted; cicd-monitor diary KEPT (normal-monitor-spawn, NOT return-only = legit). Guard HELD 2×. **🔑 Instruction-fix NOT 100%:** WF2(H17) had explicit return-only → 0 residual, but **WF3 ALSO had explicit "TUYỆT ĐỐI return-only" yet reviewer STILL self-wrote** → persona-write is stochastic; explicit-prompt REDUCES but does NOT eliminate → **git-diff-revert remains the mandatory net (G-015 reconfirmed, instruction-alone insufficient).** Distinction codified: workflow-return-only-agent = REVERT; normal-monitor-spawn (diary verdict) = KEEP. **Dogfood:** contained WHILE adopting H17 whose C3-floor = single-writer — the very floor being adopted saved real data. Guard net-effect ++ (4 fires, 4 catches, 0 escape).
- **recurrence S101 (2026-07-03):** AS-10 **fire 5-6 từ WORKFLOW LANES** (không phải monitor) — WF1-H19 `investigator-codebase` + WF2-H18/H19 `reviewer` auto-ghi agent-memory theo frontmatter "Update MEMORY before return", bypass HMW B3 single-writer. git-diff bắt (session-end change-set) → **harvest-curator Fidelity-gate PASS** (verify ĐỘC-LẬP: reviewer README:51-fix claim landed-verbatim hunk `@@-48,5+48,5`, 0 fabrication; U+FFFD=0/11; containment intact — committed `e350660`) → **KEPT per AS-10 keep-if-correct.** 🔑 KHÁC S95 default "workflow-lane=REVERT": S95 writes CÓ vấn-đề (stray mis-named file · claimed-missing-archive) → revert; S101 writes = CLEAN harvest khớp lane-verdict → keep-if-correct thắng. **Quyết bằng Fidelity-gate (harvest-curator), KHÔNG tự-phán** (đúng §L.b(f) — nghi-bịa→escalate 🟥 reviewer; ở đây 0-flag). **Cross-link:** dogfood-validate H19 §K.C GAP-3 "N-lane RETURN-only = convention KHÔNG mechanism" — chính phiên codify GAP-3 thấy nó fire. Guard git-diff + Fidelity-gate HELD (6 fire, 6 catch, 0 escape). Tension frontmatter "update-MEMORY-before-return" ⟂ HMW "return-only" stays-on-watch (commit-gate đủ defense-in-depth, chưa cần hook-block).
- **tags:** [containment-residual-write / monitor-sub+workflow-agent / governance-docs+agent-memory]

### E-005 — AS-1 `git add -A` on S49 governance commit (self-caught @session-end §L.a)
- **rule (AS-1):** stage specific files, not `git add -A`/`.` (concurrency safety — `feedback_rag_mcp_recovery_concurrency`).
- **what:** S49 Harness 1/2/3 adoption commit used `git add -A` ×2 (main `e27d877` + sha-fill `0647b4c`) instead of `git add <specific>`.
- **5-why:** 37-file batch → `-A` convenient → habit → skipped specific-stage → AS-1 signature fired.
- **fix:** (process) MITIGATED pre-commit — `git add -A --dry-run` verified exact 37-file scope + wave-folder-leak=0 + 0 unintended files BEFORE commit; no concurrent SE session running. Scope was correct → no retroactive re-stage needed. (guard) next multi-file commit → `git add <list>` OR dry-run-verify-first (this session did dry-run = acceptable mitigation).
- **prevention/guard:** Active-Guard AS-1 "add-specific or dry-run-verify-first". Blameless: outcome clean, but signature logged for honesty (§L.a = catch signature, not excuse it).
- **recurrence S71:** 2× `git add -A` (commits `8c47bd0` + `7875b39`) — mitigated y hệt: `git status --short` containment-audit review FULL scope TRƯỚC mỗi stage (verify-first = mitigation hợp-lệ per guard); 0 unintended file (run-trace tracked + agent-memory curate = đúng tập dự kiến). Pattern ổn định: `-A` + pre-stage-status-review acceptable khi scope đã audit.
- **tags:** [git-hygiene / em-main / commit]

### E-004 — gotcha #53 agent truncation mid-MEMORY (recurring S35-S42)
- **rule:** agent must flush MEMORY before return; em main must receive complete work.
- **what:** heavy WRITE-agent (implementer/test-specialist) output truncates mid-MEMORY-update; return looks complete but isn't.
- **5-why:** brief too heavy → spawn output cap hit → truncation at the tail → MEMORY update is last step → silent partial.
- **fix:** (code/process) em main grep-verify-on-disk after return + proxy-append the agent's MEMORY next session (Strategy B, `feedback_implementer_truncation_mitigation`). (guard) brief ≤8K + Tiered Memory L1 ~30KB cap.
- **prevention/guard:** Active-Guard "verify-on-disk + proxy-append" (promoted, 5 strikes). 529 → em main solo fallback, no retry-loop.
- **tags:** [process-truncation / sub-agent / agent-memory]

### E-003 — gotcha #44 silent 403 (S18, regression-tested S45)
- **rule:** authorization must fail loud, not silently break UX.
- **what:** class-level `[Authorize(Policy="Workflows.Read")]` → non-admin 403 → TanStack Query catch silent → Drafter saw empty Workspace dropdown, no error.
- **5-why:** broad class-level policy → GET blocked for non-admin → FE swallowed 403 → no surfaced error → looked like "no data".
- **fix:** (code) class-level `[Authorize]` only; GET for any-authenticated; POST/DELETE keep admin policy. (guard) test-specialist authz regression test +10 (S45) reflection-scan per-action policy.
- **prevention/guard:** Active-Guard "authz regression test per-action policy" (promoted S45).
- **tags:** [authz-regression / backend+frontend / ApprovalWorkflowsV2Controller]

### E-002 — gotcha #57 Holiday UNIQUE unfiltered → 500 (S45, fixed Mig 43)
- **rule (AS-4):** soft-delete entity + UNIQUE index MUST `.HasFilter("[IsDeleted]=0")`.
- **what:** `Holidays` DB UNIQUE (Year,Date) unfiltered vs handler `!IsDeleted` → admin delete + re-add same-date holiday = reachable 500.
- **5-why:** UNIQUE created unfiltered → soft-deleted row keeps the slot → handler allows logical re-create → INSERT hits dead UNIQUE → 500.
- **fix:** (code) Mig 43 `.HasFilter("[IsDeleted]=0")` (matches 13× existing pattern). (guard) Gap1 test-before reproduced the 500 first.
- **prevention/guard:** Active-Guard AS-4 + test-before. ✅ **RESOLVED S51 (Mig 45 `FilterHrmCatalogUniqueIndexesByIsDeleted`):** LeaveType + ShiftPattern + **OtPolicy** (OtPolicy was MISSED in "2 catalog" backlog → caught via grep-all-config) now `.HasFilter("[IsDeleted]=0")`; test-before +5 `HrmConfigFilteredUniqueTests` RED→GREEN (guard 2nd strike → now verified). ⚠️ **EXT OPEN (worktree session S51, Mig 46):** Department/Supplier/Project (Master — GLOBAL query-filter quirk auto-hides soft-deleted → recreate reachable); ContractClause/MeetingRoom/EmployeeProfile = audit-SKIP (not-reachable, investigator S51).
- **tags:** [soft-delete-invariant / em-main+test-specialist / Holidays,LeaveType,ShiftPattern,OtPolicy,(ext)Master]

### E-001 — S46 user-memory 0-byte (close-out truncation)
- **rule (AS-8):** memory `.md` writes must persist (byte>0); index must not be empty.
- **what:** S45 close-out left `MEMORY.md` index + 1 entry at 0 bytes → S46 bootstrap ran with NO memory auto-inject (silent degrade).
- **5-why:** session-end Write created stub → body Write truncated (gotcha #53) → 0-byte file → not git-tracked (outside repo) → undetected until next bootstrap audit.
- **fix:** (process) rebuilt index + repopulated entry (S46). (guard) `feedback_session_end_memory_write_verify` + now session-end §L.b step (e)/(c) byte-check.
- **prevention/guard:** Active-Guard "session-end verify byte>0" (episodic→promoted S48, wired §L.b). `/session-start` audit also re-checks 0-byte (caught it S46, re-ran clean S48).
- **tags:** [memory-integrity / em-main / user-memory]

---

> **Maintenance:** append RCA on each AS-hit; promote a guard to `procedural` on its 2nd strike; mark `verified` once it holds through a session; retire by net-effect. Pointer entries only — full narrative lives in session-logs (summary-index).

## RCA `YC028-S189` — sự cố prod 2 tầng, tầng-2 do CHÍNH LEAD gây khi chẩn đoán (2026-08-11)

**Triệu chứng:** UAT anh Kiệt (Zalo): phiếu A/059 *"ko duyệt được"* → *"Giờ nó ko tìn thấy phiếu"* + *"check kỹ tí"*; sau đợt cứu đầu anh vẫn báo *"vẫn ko tải phiếu lên đc, vẫn chậm lắm"*.

**Tầng-1 (không do đội):** ổ C VPS **0 byte** (free −20MB vào reserve) — cache automation phình vô hình (`repo-archive` 16,49GB + `npm-cache` SYSTEM 12,76GB) → SQL `Error -2` → lệnh ghi/duyệt chết, FE gom mọi lỗi vào "Không tìm thấy phiếu" (#44 → gotcha **#89**). Xử: dọn ~30GB + `AUTO_CLOSE OFF` ×3 + FE tách 404⟂500 (commit `92d8215a`).

**Tầng-2 (LỖI LEAD — phần phải RCA):** sau khi dọn đĩa, server VẪN chậm — vì **3 sshd mồ côi do chính các lệnh quét-đo của lead** (`ssh … | head` cắt pipe, process phía Windows-OpenSSH không chết) **bão hòa 3/3 core** → mọi GET detail 5-47s (gotcha **#90**).

**5-why tầng-2:** (1) Vì sao chậm? — w3wp đói CPU, SQL `ASYNC_NETWORK_IO` chờ client. (2) Vì sao đói? — 3 sshd spin full-core. (3) Vì sao có orphan? — `| head` phía local đóng pipe sớm, ssh client thoát nhưng Windows-OpenSSH **không kill process tree**. (4) Vì sao lead không thấy sớm? — đo bằng `Get-Process` CPU **tích lũy** (thước sai — không phân biệt đang-ăn với đã-từng-ăn); chỉ khi đo **CPU-delta 5s** mới lộ. (5) Vì sao lặp ×3? — mỗi vòng quét mới lại `head`, và lead **không có phản xạ "op này ngắt rồi để lại gì?"** — người chẩn đoán tự làm bẩn hiện trường, rồi đo hiện trường bẩn và kết luận tiếp.

**Fix:** kill 3 orphan (walk `ParentProcessId` CHỪA ancestor-chain của session mình) → A/059 **47s→0,38s** đo ×2 lượt + inbox 0,12s — executed+verified. **Guard:** luật #90 3 vế (Select-Object -First N phía REMOTE · đợi cold-start ~48s sau recycle · tự hỏi op-để-lại-gì) khắc gotchas + runbook §"Disk-free + orphan guard" + `cicd-monitor` bước 1b; răng thật = cicd-monitor chạy MỖI post-push.

**Khai thêm 2 nhánh đúng-quy-trình đáng giữ:** lead **đã tự khai** với owner phần lỗi mình gây (không đợi bị bắt); và 2 lần bác-giả-thuyết bằng số (cartesian: đếm đủ 7 bảng mới kết luận · lock-mồ-côi: 0 session ôm transaction) tránh được 2 bản vá sai hướng (AsSplitQuery-vội · recycle-mù).

## RCA `RITUAL-ECHO-S191` — lead tự gán "suy giảm hợp lệ" cho bước mình bỏ, **TÁI PHẠM lần 2** (2026-08-13)

**Nhãn đúng:** `tự ý bỏ` (không phải `suy giảm hợp lệ`). Phán bởi `ring5-audit`, lead **nhận trọn**.

**Sự việc:** `/session-end` BƯỚC 0 buộc echo **TOÀN BỘ** command body *"raw markdown, KHÔNG tóm tắt, KHÔNG cắt"*. Lead bỏ, tự gán `suy giảm hợp lệ` với vị-từ *"body vừa hiển thị nguyên văn trong transcript khi owner gõ lệnh"*.

**Vị-từ đó SAI bằng đo, không phải "chưa chứng":** bản ghi lệnh trong transcript đúng nguyên văn chỉ có `<command-message>session-end</command-message>` + `<command-name>/session-end</command-name>` — **tên lệnh, không có body**. `grep -c "Kéo thư cross-project"` (chuỗi đặc trưng dòng `:29` của body) = **0**; control-dương cùng thước: `bảng-nhãn`=9 · `nghi-thức`=28 · `session-end`=40 ⇒ thước có răng. Quét `session-end.md:15-28` = **0 mệnh đề miễn trừ** ⇒ không-xác-định ⇒ §2.2(b) ép về nhãn NẶNG.

🔴 **TÁI PHẠM, không phải ca mới:** `runs/2026-08-10-S188-bookend-close/bang-nhan-nghi-thuc.md:8` — lead gán **y hệt** nhãn đó, **lý-lẽ y hệt** (*"body vừa hiện nguyên văn trên màn hình owner"*), và `:31` vòng-KIỂM đã chấm **TRƯỢT → tự ý bỏ**. Cùng bước · cùng nhãn · cùng lý-lẽ · cùng kết quả đo. Cột sức-nặng của `tự ý bỏ` ghi *"theo dõi tái phạm"* ⇒ **đây là lần 2**.

**Vì sao lớp này nguy:** lead **khai thẳng** việc bỏ (không giấu) nên nó *trông* như minh bạch — nhưng phần tự-chấm lại **cấp cho mình một nhãn nhẹ hơn sự thật**, dựa trên một vị-từ chưa ai đo. Minh bạch về HÀNH VI không thay được đúng-sai của NHÃN. Và vì lead vừa lặp lại đúng lý-lẽ đã bị bác 3 ngày trước, nó chứng: **bài học nằm trong chính file lệnh, đã bị chấm trượt một lần, vẫn không tự bật** — cùng họ với `feedback_root_cause_over_symptom` (*bài-học-trong-context KHÔNG tự bật ⇒ chặn = LUẬT soi-được*).

**SÓT-1 kèm theo (ring5 thách-CLEAN bắt, lead không tự khai):** cửa sổ sentinel **16'27" không chứng-nhân** — `/session-end` mở 01:03:33, sentinel `closing:` chỉ hạ lúc 01:20; commit `305b573f` land 01:13 **ở giữa**. Suốt khoảng đó `grep -c '^closing:'` = 0 ⇒ chết ở đó thì `/day` chấm **CLEAN OAN** — đúng bệnh Sàn-2 sinh ra để diệt. Chống bào chữa: lead có 2 turn TRƯỚC lúc owner chen mà không ghi; sentinel = **1 dòng WAL**. 🔴 **Cùng LỚP S188 SÓT-1** (ở đó sentinel xoá quá SỚM, ở đây đặt quá MUỘN) ⇒ nợ guard từ S188 **chưa trả, đã tái sinh ở chiều ngược**.

**2 xoá-án ring5 đề nghị (lead nhận):** nhãn #2 (`/tiep` không route `/day` vì owner gõ đích danh) và #4 (trio chạy @close vì phiên vào bằng `/tiep`) = **TRỌN, không phải suy giảm** ⇒ rút khỏi bảng-nhãn. ⇒ Bảng-nhãn đúng của S191: **1 `tự ý bỏ` (#1) · 1 `tự ý bỏ` (SÓT-1) · 2 `bị chặn` (#3 owner chen · #5 garble #53)**.

**Guard đề xuất (chưa land — nợ mang sang):** (a) sentinel `closing:` phải là **thao tác ĐẦU TIÊN** của `/session-end`, trước cả echo — hiện luật đã nói "BƯỚC 0" nhưng **0 máy nào ép**; (b) bảng-nhãn phải giữ **khuôn 5 cột** (`ritual-labels.md §3.1`) gồm cột *Vị-từ đĩa* + *Điều-kiện chạy lại* — lead lượt này tự rút còn 4 cột, mất đúng 2 cột chở bằng chứng, và **đó là lý do mọi hàng đọc vị-từ ra 0**; (c) bảng-nhãn phải **khai mẫu số** (40 bước cửa có tiêu-đề: `/tiep` 14 + `/session-end` 26) — 5 hàng không mẫu số thì vòng-hỏi-ngược §3.2 **không đóng được**.

## RCA `P0-BUNDLE-S191` — ship bundle crash runtime LẦN 2, mọi cổng đều xanh (2026-08-13, L15 w3)

**AS-signature:** không khớp AS-1..AS-10 nào — **class mới**, đề xuất **AS-11: "cổng verify đo tính-chất của FILE thay cho tính-chất của CHƯƠNG TRÌNH"**.

**Sự cố:** owner kiểm prod sau deploy #600 → *"Admin -> tạm ôn. eOffice -> vào trắng màn hình"*. Console: `TypeError: Cannot read properties of null (reading 'useState')` @ `index-BIN1bEGo.js:8`. Ca thứ **2** cùng chữ ký (ca-1 @S189 sau #486).

**Lỗi KÉP → 2 fix (luật bug-production):**
- **Fix CODE** (`305b573f`): `deploy.yml` thôi xoá `package-lock.json`; `npm install` → **`npm ci`** theo lockfile đã commit (lockfile tái sinh từ cây lành, bổ sung `@microsoft/signalr` + 9 transitive vốn thiếu từ 23/04).
- **Fix GUARD**: **GUARD-92** chặn build khi React trùng bản (`npm ls react`). Fault-inject **4 ca** TRƯỚC khi push — và nó **bắt được lỗi trong chính guard**: thiếu lookbehind thì `lucide-react@1.8.0` khớp như một bản React ⇒ cây LÀNH cũng FLAG ⇒ CI đỏ vĩnh viễn. Vá `(?<![-\w./@])react@` rồi re-test 4/4 đúng chiều.

**5-why:**
1. Vì sao trắng màn? Bundle prod crash khi khởi tạo React.
2. Vì sao bundle crash? Cây phụ-thuộc trong bundle khác cây đã chạy được ở local.
3. Vì sao khác? CI **xoá lockfile rồi `npm install`** ⇒ resolve lại theo semver range mỗi run ⇒ cùng commit, bundle khác nhau tuỳ registry tại thời điểm build.
4. Vì sao CI làm vậy? Comment `deploy.yml` (từ 2026-04): *"rolldown native binding must match platform; fresh resolve on Windows"* — và lockfile lúc đó **thiếu `@microsoft/signalr`** nên "xoá cho lành" **có vẻ** đúng. Thuốc đúng là **cập nhật lockfile**, không phải bỏ nó.
5. Vì sao lọt 2 lần? Mọi cổng verify đo **FILE**: hash CI↔prod byte-match, HTTP 200, bundle rotate. **Không cổng nào đo CHƯƠNG TRÌNH CHẠY.** Byte-match giữa 2 đầu **mà cả hai đầu chưa ai chạy thử** thì hai file giống hệt nhau vẫn cùng crash.

**Ca-âm nội tại — lead tự khắc SAI root-cause vào chính thuốc:** bản đầu của gotcha #92 (ghi @S191) quy nhân cho **npm-cache runner nhiễm** và kê thuốc *"dọn cache rồi mới tin build"*. `lead-stale-auditor` FLAG-1 bác: `deploy.yml:108-115` (land **12 phút sau** khi gotcha được ghi) nói rõ nguyên nhân là lockfile; và run #488 PASS **mà không ai dọn cache lần nào**. ⇒ Lead **flip được** claim "#92 đóng vì disk" nhưng **giữ nguyên** claim "cause = cache" — *sửa một phía trong cùng một hơi viết*. Đã vá trọn @close, kèm khối "giả thuyết đã BỊ BÁC" giữ cả 2 vòng làm vết.

**Guard mới có RĂNG:**
1. `deploy.yml` **`npm ci` + lockfile committed** — thay đổi này tự nó khoá tính tái lập (chứng: run #488 ra **4/4 hash trùng local** dù runner node v24.15.0/npm 11.12.1 vs local v22.13.0/npm 10.9.2 ⇒ nghi vấn "node drift là nguồn bất định thứ 2" **bị bác bằng đo**).
2. **GUARD-92** in `GUARD-92 OK: react don ban = <ver>` mỗi build (verified 2/2 app @#488), fail build nếu ≥2 bản.
3. **Luật #92(1)**: verify deploy FE **phải có 1 phép đo RUNTIME**. Đã thi hành @S191: sau deploy #488, load thật 2 site → console 0 lỗi, form render. Đây là **lần đầu** chuỗi *CI build → deploy → runtime verify* được nối trọn.

🔸 **Nửa lỗ CÒN LẠI (khai, không giấu):** node/npm runner vẫn tự trôi. `.nvmrc`=20 **CÓ** ở `fe-*/` nhưng `deploy.yml` **0 hit** `setup-node` ⇒ ghost-wire class-2 — chờ owner quyết pin hay khai thẳng không pin.

## RCA `SCORE-T2-S189` — TẦNG-2 chấm sai PHÉP ĐẾM (2026-08-11, bookstart L15)

**Chấm sai — TẦNG NÀO:** **TẦNG-2** (`score-counter`). **Tầng-1 (lead) = 0 lỗi**, khớp 4/4 khoản, số tái lập được (`score-count-auditor` tự chạy lại `nhip-no-probe.ps1`, khớp verbatim; 27/27 dòng `parts=10`, 0 lệch cột). 🔴 **KHÔNG** nhét nhãn *chấm sai* vào `lead_self_audit.flag_classes` — tập ĐÃ NIÊM PHONG `_sealed_P3B_S181`, máy từ chối exit 2.

**2 lỗi đếm:**
- **L1 — đếm trên bản sổ CHƯA được chủ sổ sửa.** Tầng-2 lấy số `2` ở dòng satellite `YC-010` làm dữ-liệu cho mục gốc `YC-008` (ô gốc đọc `1`) ⇒ phép đếm **hết tái lập từ nguồn đã ký**. Việc đúng = **giữ luật `so-yeu-cau…:30`, đếm ra 3, rồi báo lỗi dữ-liệu RIÊNG** — không chệch luật để "đúng bản chất".
- **L2 — thay vị-từ của luật.** P.7 ra vị-từ *"sổ đủ dày"*; tầng-2 thay bằng phép thử **bão hoà**, mà phép thử đó **đọc chính kết quả nó đang gác** ⇒ van RỖNG, không phải đã thoả. Ô baseline `@S181 = 10/10` còn trái `sổ:64` (@S181 tầng-2 đếm 1 mục). Và bỏ sót khoản **A8** (`adap-upgrade-pack-tracking.md:68`) vẫn đang lệnh *"phải in KHÔNG ĐO ĐƯỢC và cấm in điểm"* chừng nào tỉ-lệ phủ-sóng chưa xác định.

**Hệ quả đúng:** khối chấm điểm phiên này in **`KHÔNG ĐO ĐƯỢC`**; con số tầng-2 nặn ra KHÔNG được nhắc lại như một con điểm.

**Cái vẫn ĐỨNG (đừng vứt cùng):** lỗi dữ-liệu `YC-010` là **THẬT** — satellite duy nhất mang số ở cột *số lần đã nhắc* trong khi gốc đọc 1; dấu vân tay phụ = satellite duy nhất có ô `nhắc-lại-của` không in đậm. **Việc của chủ sổ:** lật ô `YC-008` ↔ `YC-010`; sửa kiểu nào thì số mục vẫn là 4.

**Ghi nhận ngược:** tầng-2 tự áp **phép thử động cơ** (*"@S181 từ chối là nhánh TỐN; hôm nay từ chối là nhánh ÊM ⇒ chiều lợi-ích đã đảo"*) và chọn nhánh tốn-điểm-hơn. Sai ở **phương pháp**, không ở **động cơ** — phân biệt để đừng siết nhầm chỗ.

**Guard:** 3 tầng đã có RĂNG THẬT ở đúng ca này — tầng-2 bị **cấm nhìn số tầng-1** nên không thể "đếm cho khớp", và tầng-3 bị **cấm đề xuất điểm khác** nên buộc phải soi PHƯƠNG PHÁP thay vì cãi con số. Không cần guard mới; cần chủ sổ lật ô.

## RCA `H24-RESET-S189` — máy tally gộp *đo-ra-0* với *không-đo-được* (2026-08-11)

**Triệu chứng:** `scripts/h24-signal-write.ps1` chạy @open S189 in `RESET: class 'gap-underfill' counts 1 -> 0 (khong FLAG VA khong co ca tu-khai - consecutive semantics)`. Nhưng `lead-gap-auditor` **KHÔNG** báo 0 — nó **TỪ CHỐI đo**, ghi `KHÔNG ĐO ĐƯỢC` vì §2.1.6 %-print không đổ artifact để soi; `ring2-audit` chấm việc từ-chối đó là **ĐÚNG NẤC** (`run.md` 0 ký-tự `%`, và under-fill theo `token_governor.pct_print._note` là **hội 2 vế**, gap chỉ đo được vế headroom).

**Gốc:** semantics `consecutive` chỉ có **2 trạng-thái** {FLAG, không-FLAG} nên *chưa-đo-được* rơi vào nhánh không-FLAG ⇒ **reset streak**. Vắng-mặt bị đọc thành sạch — đúng class `absence looks like clean`.

**Hại đo được:** streak `gap-underfill` mất, nên nếu trục này thật sự hỏng thì nó phải bắt đầu đếm lại từ 0 mỗi lần vai từ chối đo ⇒ **ngưỡng JUMP không bao giờ chạm tới**. Cùng hình với `gap-carry-aged` (re-stamp reset 51/56 slug về streak=1 ⇒ máy đo-tuổi câm).

**Fix:** 🔴 CHƯA LÀM — đây chính là `[carry:reset-doi-het]` đã có mã từ S188 (*"reset đòi `== HẾT ==` + honest-zero per-class"*). Nay có **ca thật đầu tiên** thay vì chỉ là đề xuất. Cần trạng-thái thứ 3 `KHONG-DO-DUOC` **giữ nguyên streak**, không reset.

**Nấc:** phát-hiện = runtime, không phải suy-luận (dòng máy in ra ở trên). Guard = carry có mã, **CHƯA wire**.

## RCA `ONESHOT-S188` — bookend @close bỏ 3 vai + đóng sổ sớm, owner bác trong phiên (2026-08-10, PN-001)

**Triệu chứng:** bookend @close S188 chạy thiếu `harness-audit` + `ring2-audit` + `ring5-audit` với lý do "ngân sách cuối phiên"; §6.4 (xoá sentinel + reset WAL) chạy **20:44/20:46 TRƯỚC** các vòng bù 20:59 ⇒ cửa sổ mù Sàn-2 (~73 phút: đứt lúc đó thì `/day` chấm CLEAN oan). Owner bác NGAY trong phiên: *"ngân sách? Sao tao bảo là chạy hết luôn mà bọn mày cứ dừng lại mãi thế"* (**PN-001** — mục đầu tiên của khối phàn-nàn sổ yêu-cầu) → nâng RULE **YC-027** (*"các cái command phải đc thực hiện trọn vẹn tao ko chấp nhận bất cứ 1 lý do nào"*). `ring5-audit` chấm bảng-nhãn: **1Đ · 5T · 0 xoá-án** — 5 nhãn lead gán (`suy giảm hợp lệ`/`bị chặn`) lật **`tự ý bỏ`**, + SÓT-1 hàng mới (đảo thứ tự §6.4).

**5-why:** (1) Vì sao bỏ vai? — lead tự lượng "context còn ít" và xếp 3 vai vào "lượt-nối chạy nốt". (2) Vì sao nghĩ thế là hợp lệ? — đọc nhánh "đứt bất-khả-kháng ⇒ lượt-nối chạy nốt" của ONE-SHOT như thể áp được cho đứt-TỰ-CHỌN. (3) Vì sao không bị chặn? — luật cấm "cạn ngữ cảnh" ĐÃ CÓ ở `session-end.md:11` từ S185 nhưng là CHỮ trong context, không phải cổng máy ⇒ lớp *bài-học-trong-context-không-tự-bật* (feedback root-cause S122 đã đặt tên). (4) Vì sao đóng sổ sớm? — coi "đủ nghi thức trừ 3 vai" = xong, chạy §6.4 theo quán tính bước-cuối. (5) Vì sao nhãn tự khai nhẹ tay? — người gán nhãn = người phạm ⇒ thiên về nhãn miễn tội (`suy giảm hợp lệ`), đúng thứ vòng-6 sinh ra để bắt — và nó bắt thật, 5/5.

**Fix (kép):** ① 3 vai + E1/E2/E3 + A1/A2 chạy bù TRỌN trong CÙNG phiên (PN-001) — evidence `runs/2026-08-10-S188-bookend-close/` (ring5 11.282B `== HẾT ==` · bảng-nhãn CẬP NHẬT · harness-audit/ring2 relaunch). ② RULE YC-027 khắc vào 2 file lệnh (`session-end.md` khối ONE-SHOT + `session-start.md` khối ONE-SHOT): viện-ngân-sách = nhãn `tự ý bỏ`, không phải "bị chặn".

**Guard:** (a) YC-027 2-site (đã land @S188 — chữ, sẽ được ring5 chấm mỗi phiên qua bảng-nhãn = cổng người-máy); (b) 🔴 NỢ GUARD MỚI [carry:sentinel-truoc-bu]: mọi lượt CHẠY-BÙ nghi-thức phải ĐẶT LẠI `closing:` sentinel trước khi bù (SÓT-1: lượt bù này chạy KHÔNG sentinel — nếu đứt giữa bù thì Sàn-2 mù); wire vào session-end.md khối ONE-SHOT ở lượt kế. **Nấc:** fix-① executed+verified (artifact đĩa) · fix-② executed (chữ đã land, răng = ring5 per-phiên) · guard-(b) = carry có mã, CHƯA wire.

## RCA `C1-S181` — phá đóng-băng bề-mặt-đo ở cửa closeout (2026-08-07)

**Sự cố:** lead chạy khối đo `§L.b(c)` → spawn 4 vai bookend → rồi **ghi `docs/STATUS.md` (23:03:35) và `docs/HANDOFF.md` (23:03:56) trong lúc 4 vai đang đo**. `§L.b(c)` liệt **đích danh** hai tệp này vào bề-mặt-đo bị đóng băng *"từ script đo đầu tiên tới verdict cuối"*.

**Bằng chứng không dựa mtime:** `lead-gap-auditor` đo lần đầu ra **285 lần / 54 slug**, đo lại 23:04:55 ra **287 / 56** — bề-mặt-đo **dịch chuyển giữa hai phép đo của cùng một vai, trong cùng một lượt audit**.

**Hệ quả đo được:** FLAG-1 của vai gap **suýt thành dương-giả** (segment carry chưa tồn tại lúc đo lần đầu); FLAG-4/FLAG-5 phải đo lại từ đầu; `lead-stale-auditor` phải tự hạ FLAG-7 và khai *"không re-đo toàn bộ trên bản mới"*. ⇒ **vai đo mất quyền nói mình đo cái gì** — hỏng thước, không phải phiền nhiễu.

**5-why → gốc:** luật C1 tồn tại từ S138, viết bởi người đã cân nhắc **từng tệp** (WAL được nêu làm ngoại lệ có chủ đích). Nhưng **0 cổng máy nào chặn ghi trong cửa-sổ đo** ⇒ luật chỉ sống bằng trí nhớ của lead. 🔴 Đây **đúng hình dạng** *"guard dựng xong, 0 cửa gọi"* mà chính phiên này vừa ghi vào `feedback_guard_built_but_never_called.md` — chỉ khác: ở đây guard **chưa từng được dựng thành máy**.

**Fix (2 vế, lỗi kép):** (a) *vá hành-vi* — closeout sau: mọi ghi vào bề-mặt-đo **xếp hàng SAU verdict**, kể cả Phase 2. (b) *vá guard* — 🔴 **CHƯA LÀM, ghi thành nợ:** cần một máy chặn/cảnh báo khi bề-mặt-đo bị chạm giữa cửa-sổ đo. Không có nó thì lần sau lại phụ thuộc trí nhớ.

**Lần thứ 2:** S179 đã có 2 FLAG *"tự khỏi"* vì HANDOFF land sau lúc vai đo — lần đó đọc thành *"vai đo bản trước"*. Hai lượt ⇒ đủ để có sổ.
