# Chuẩn đặt tên — tầng BỘ MÁY (SOLUTION_ERP)

> **Văn bản này BỔ SUNG tầng bộ-máy. Nó KHÔNG thay `docs/rules.md`.**
> `docs/rules.md` phủ tầng **mã nguồn** (PascalCase `.cs`, kebab TS/TSX, bảng DB…). Văn bản này phủ tầng **vật quản trị**: tên vai, thư mục lượt chạy, tệp mốc phiên, nhật ký phiên, kịch bản, sổ, nhãn lớp kiểm, nhãn tác vụ, tên lệnh.
> Một khái niệm — một chỗ tra. Tên chạm **mã sản phẩm** → `docs/rules.md`. Tên chạm **bộ máy quản trị** → tệp này. Không có vùng chồng lấn.

- **Ngày ký:** 2026-08-07 (phiên S180, wave W1) · **Nguồn sàn:** `broadcasts/inbox/ai_infra/2026-08-04-Governance-upgrade-pack-phased-phu-luc-spec-pitfall.md` **§GĐ-1** (`:93-137`)
- **Kiểm kê máy nền:** `.claude/workflows/runs/2026-08-07-S180-adap-upgrade-pack-phased/sub-w1a-mayd-octen.md` — **14 đoạn máy đọc tên, 11 vỡ-câm**. Phụ lục A dưới đây là bản rút gọn BẮT BUỘC tra trước mọi lần đổi tên.
- **Máy soi:** `scripts/naming-scan.ps1` — INFORM-only, mã thoát 0, quét **231 tên vật-bộ-máy**.
- **Sổ đổi tên:** `docs/governance/rename-ledger.md` — chỉ-thêm-không-xoá.
- **Bổ sung SAU ngày ký:** **§12-bis** (masthead của chính tệp vừa sửa) — thêm 2026-08-09 / phiên S185, nguồn sàn `3-khoan:19-27`. *(Dòng này chính là §12-bis tự áp lên tệp của nó: thân đổi thì masthead phải nói ra.)*

---

## §0 — Năm luật nền (áp cho MỌI nhóm bên dưới)

### L0 — Luật NẤC: viết tới đâu thì phải ép máy tới đó, không sâu hơn MỘT nấc

> **Một nhóm tên sạch CHÍNH XÁC tới độ sâu mà máy của nó KIỂM — không sâu hơn một nấc.**

Đây là luật gốc, đo được, không phải khẩu hiệu. Bốn ca nền (đo 2026-08-07):

| Nhóm | Máy ép tới nấc | Kết quả ở nấc đó | Nấc SÂU HƠN |
|---|---|---|---|
| Tên vai | **thành viên** (danh sách 26, `throw`) | sạch 26/26/26 | — |
| Thư mục phiên | **hình dạng** `^session-\d+$` (chỉ INFORM) | sạch 12/12 | tệp BÊN TRONG: **7 họ** |
| Nhãn lớp kiểm | **tiền tố** `view-`/`gap-` | sạch 12/12 | nấc-2: **8 họ** |
| Nhật ký phiên | **KHÔNG CÓ MÁY** | **40,3%** (64/159) | — |

⇒ **Hệ quả bắt buộc:** mỗi mục dưới đây khai **NẤC muốn sạch** và **MÁY ép đúng nấc đó**. Nhóm nào không có máy thì ghi thẳng `CHƯA CÓ MÁY — mô tả, không cưỡng chế`, và **cấm ký luật hình dạng cho nó**. Ký sâu hơn máy = ký ra thứ tự nó sẽ trôi, rồi không ai biết.

⇒ **Hệ quả thứ hai:** máy **chỉ ĐỌC** hoặc máy **THA THỨ** thì tên vẫn trôi. Bằng chứng: `detectors:1109` đọc tên lạ rồi chỉ *liệt* (112/719 tệp ngoài mọi họ); `detectors:1660` chấp cả `_end` lẫn `closed.md` bằng `-or` (fork sống vô hạn). Máy phải **TỪ CHỐI**, không được liệt-rồi-thôi. Nhưng **không cần dừng-hẳn**: `detectors:1639` chỉ in một dòng INFORM và nhóm đó vẫn sạch tuyệt đối.

### L1 — Giữ nguyên tên cũ, tuyệt đối (sàn §GĐ-1(iv))

Đổi tên hồi tố thư mục/tệp mốc đã tồn tại = động vào mọi con trỏ trong nhật ký, mục lục, sổ tay, lịch sử phiên bản. **Rủi ro khổng lồ, lợi ích gần bằng không.**

Năm vùng **ĐÓNG BĂNG** — không viết lại tên, không đổi tên, vĩnh viễn. Danh sách này **KHÔNG chép lại ở đây**; nguồn duy nhất là `docs/governance/vocab-alias-map.md` (khối "Lưu ý nền tảng"). Tra ở đó.

Mọi luật hình dạng trong tệp này **chỉ áp VỀ PHÍA TRƯỚC** — cho vật sinh ra từ 2026-08-07. Vật cũ hợp lệ vĩnh viễn.

### L2 — Lane đơn trị: mỗi loại sổ đúng MỘT thư mục, bỏ chữ "hoặc"

Cho phép hai chỗ đặt là cho phép hai chỗ tìm, và tới lúc cần thì ai cũng tìm chỗ còn lại. Nếu một luật hiện hành đang chứa chữ "hoặc" cho vị trí, nó là **nợ**, ghi vào Phụ lục B chứ không được để im.

### L3 — 🔴 CẤM MỌI QUY ƯỚC DẠNG "GIỮ NGUYÊN SỐ DÒNG"

**Cấm tuyệt đối.** Không luật nào trong kho này được yêu cầu một dòng mã ở lại đúng một số dòng.

**Vì sao — đo được, không phải lo xa:**
- `.claude/hooks/wal-flush.ps1:16-17` đang tự khai: *"GIU `$paths` O DUNG DONG 13: nhieu doc trich-dan `wal-flush.ps1:13`… Chen dong TREN day = lao-hoa het cac trich-dan do"*. Quy ước này **được canh bằng đúng một dòng chú thích** — không máy nào thi hành nó.
- Đo 2026-08-07: chuỗi `wal-flush.ps1:13` xuất hiện **21 lần** trong `*.md`, trong đó **2 neo SỐNG ngoài vùng đóng băng**: `.claude/commands/tiep.md:23` và `docs/governance/session-model-se-draft.md:4`.
- Cùng lớp lỗi (LỚP-6) đã **giết 3 neo trong `docs/STATUS.md` ngay trong phiên S180 này**.

**Thay bằng:** neo bằng **chuỗi tìm được** — một đoạn văn bản đủ đặc trưng để `grep` ra. Ví dụ đúng: neo `$paths = @(` thay vì neo `:13`. Số dòng **chỉ** được dùng cho tệp đã đóng băng (5 vùng ở L1), nơi không ai chèn dòng nữa.

Áp cho cả **con số chép tay** (LỚP-5): một đại lượng = một con số, và **neo LỆNH thay vì chép số**. Muốn nói "có bao nhiêu lớp cờ" thì trỏ khoá cấu hình, đừng viết số.

### L4 — Miễn trừ theo QUY ƯỚC NGÔN NGỮ (tường minh, không im lặng)

Một chuẩn "mọi tên kebab" sẽ **cờ 5 tệp đang đúng** = dương-giả ngay ngày đầu. Ba miễn trừ, liệt từng loại, **cấm mở rộng bằng suy diễn**:

| Miễn trừ | Phạm vi | Lý do | Đo 2026-08-07 |
|---|---|---|---|
| **snake_case cho `*.py`** | mọi tệp `.py` | **PEP-8** — quy ước bắt buộc của ngôn ngữ | 5/5 `.py` snake · 0 `.py` kebab · 0 `.ps1` snake ⇒ **kỷ luật 100%, 2 chiều** |
| **`README.md` chữ HOA** | mọi thư mục | quy ước phổ quát | 2 tệp (`.claude/agents/`, `docs/governance/`) |
| **vật sinh tự động** | `__pycache__` | công cụ sinh, không ai đặt | 1 |

🔴 Máy soi **in tên từng vật được miễn**, không được im lặng bỏ qua. Miễn trừ im lặng và lỗi im lặng trông giống hệt nhau.

---

## §1 — Tên vai

- **NẤC muốn sạch:** **THÀNH VIÊN** (tập đóng — không chỉ hình dạng)
- **Tập hợp lệ:** đúng 26 giá trị liệt trong `.claude/workflows/hmw.js` `VALID_ROLES` (`:22-51`). Đây là **nguồn**; không chép danh sách vào đây (L3).
- **Hình dạng:** kebab thuần `^[a-z0-9]+(-[a-z0-9]+)*$` — đo 26/26 đạt.
- **MÁY ép nấc này:** `hmw.js:171-186` — `badRoles` filter + `throw … DỪNG HẲN (STOP-HARD)`. **Đây là máy chặn DUY NHẤT trong cả kho thật sự dừng hẳn.**
- 🔴 **Giới hạn phải biết:** máy chặn theo **danh sách liệt kê**, KHÔNG theo hình dạng. Luật "tên vai phải theo dạng X" **sẽ không được máy này thi hành**. Và `hmw.js:180` (`x.raw != null && x.raw !== ''`) ⇒ **vai rỗng/null KHÔNG throw** (backward-compat role-less) ⇒ STOP-HARD bắt tên **SAI**, không bắt tên **THIẾU**.
- **Bất biến bắt buộc:** `.claude/agents/<role>.md` (BaseName) ≡ `.claude/agent-memory/<role>/` (tên thư mục) ≡ phần tử trong `VALID_ROLES`. **Ba chỗ, không nguồn chung.** Lệch ⇒ `scripts/mfe-eval.ps1:264-267` in `N/A (no persistent diary -> ephemeral/unspawned)` và **loại vai khỏi phép đo** — một lời giải thích có thiện chí nhưng sai sự thật; đồng thời `detectors:1109` xếp vào `$unmapped` (liệt, không cờ).
  ⇒ Trước W1 bất biến này có **0 máy kiểm**. Từ W1, `naming-scan.ps1` kiểm nó **hai chiều** (thiếu thư mục / thừa thư mục).

## §2 — Nhãn lớp kiểm

- **NẤC muốn sạch:** **TIỀN TỐ** (`view-` hoặc `gap-`). Nấc-2 **KHÔNG ép** — khai thẳng.
- **Tập hợp lệ:** đọc từ `.claude/agent-memory/memory-budget.json` → `lead_self_audit.flag_classes`. **Nguồn sống duy nhất.**
- **MÁY:** `governance-detectors.ps1:1761` `$flagTagRx` ép tiền tố · `scripts/h24-signal-write.ps1` từ chối nhãn lạ với mã thoát 2 (*"a monitor may NOT invent a class"*).
- **Nấc-2 đang có 8 họ** (`view-stale` 4 · `view-residual` 1 · `view-claim` 1 · `gap-carry` 2 · `gap-owner` 1 · `gap-decision` 1 · `gap-underfill` 1 · `gap-incident` 1). **Không có máy ép nấc-2 ⇒ tệp này KHÔNG ký luật nấc-2.**
- 🔴 **CẤM chép SỐ lớp vào văn xuôi** (L3/B1). Ca sống: `hmw.js:33` viết `(11 class: 5 view-* + 6 gap-*)` — **sai cả tổng lẫn thành phần** (thật: 12 = 6 view + 6 gap; lớp thứ 12 `view-claim-broader-than-sample` nằm cuối mảng, ngoài cụm `view-*`, nên đếm lướt ra 5). Vá đúng = **bỏ số, trỏ khoá cấu hình** — sửa 11→12 là để nó thối lại.

## §3 — Thư mục lượt chạy

- **NẤC muốn sạch:** **HÌNH DẠNG**
- **Tập hợp lệ (vật MỚI):** `YYYY-MM-DD-S<n>-<slug-kebab>`
- **Tập hợp lệ (vật CŨ, giữ vĩnh viễn theo L1):** `YYYY-MM-DD-<slug-kebab>` — 18/88 thư mục hôm nay.
- **MÁY:** `closeout-sentinel.ps1:165` lọc thư mục lượt chạy theo **mã phiên trong tên** (`$sessRe`) · `:168` khớp tên thư mục H24 · `governance-detectors.ps1:1097-1102` quét đệ quy.
- 🔴 **Hệ quả đang sống, không phải giả thuyết:** **18/88 thư mục (20,5%) VÔ HÌNH với `closeout-sentinel` NGAY HÔM NAY**, không cần ai đổi tên gì. Đây là lý do luật hình dạng chỉ áp về sau **nhưng máy soi vẫn phải in con số 18** — im con số đó là để vùng mù nằm im.

## §4 — Tệp con trong lượt chạy

- **NẤC muốn sạch:** **HỌ** (tệp có ĐỊNH DANH VAI phải rơi vào một họ máy đọc được)
- **Tập hợp lệ cho tệp mang định danh vai:**
  - `sub-<role>-<i>.md` — nhiều lượt cùng vai
  - `sub-<role>.md` — một lượt
  - `<role>-return.md` — lượt trả
  - `run.md` — mô tả lượt chạy
  - `<stage>-synthesis.md` — tổng hợp
- **MÁY:** `governance-detectors.ps1:1102` + `:1771` (**cùng regex, HAI bản sao, không dùng chung hằng số**) + `scripts/memory-selfimprove-audit.ps1:298` (sau bản vá W1). ⇒ đổi họ = sửa **3 chỗ**, xem §12.
- 🔴 **Điểm mù CÓ CHỦ ĐÍCH, phải biết:** **112/719 tệp (15,6%) không thuộc bất kỳ họ nào** — ghi chú, bảng, tệp phụ trợ. Đó **không phải lỗi**: tệp phụ trợ không mang định danh vai thì máy không cần thấy. Nhưng hệ quả là: **đặt tệp-trả-lời-của-một-vai ra ngoài 5 họ trên = vai đó bị đọc thành CHƯA CHẠY, và chỗ lệch chỉ được LIỆT chứ không CỜ** (`detectors:1109`). Ca thật S159: 9 lượt chạy, bộ lọc thấy 6, **rơi đúng 3 lane đắt nhất**.

## §5 — Tệp mốc phiên

- **NẤC muốn sạch:** **TIỀN TỐ `_`** (tệp mốc) — thư mục chứa ép ở nấc **HÌNH DẠNG**
- **Thư mục:** `session-<N>` — `^session-\d+$`, đo **12/12 = 100%**. Máy: `governance-detectors.ps1:1639` (INFORM) + `session_ctx.py:133` + `session-scaffold.ps1:116` + `session_scaffold.py:105`.
- **Tệp bên trong — 8 họ tiền tố hợp lệ (+`_day-*` @S185 W-1 day-wake):** `_tiep-*` · `_pause-*` · `_snapshot-*` · `_day-*` · `_context-s-<N>.md` · `_mind-s-<N>.md` · `_end` · và **`pause-*` (chỉ vật cũ, xem dưới)**.
- **Luật vật MỚI:** tệp mốc phiên **bắt buộc mở đầu bằng `_`**. Lý do cơ học: `session_ctx.py:351-353` tự khai *"glob `pause-*` does NOT match `_pause-1.md` (leading underscore)"* — dấu `_` là thứ phân tách hai họ mà không đếm trùng.
- 🔴 **HAI cặp fork đang sống, cả hai đều sống VÌ MÁY THA:**

| Fork | Số | Máy | Cách máy tha | Hệ quả |
|---|---|---|---|---|
| `_pause-*` ⟂ `pause-*` | 22 ⟂ 1 | `session_ctx.py:349-358` | đọc **cả hai** glob | 🟢 an toàn, nhưng fork không bao giờ tự đóng |
| `_end` ⟂ `closed.md` | 10 ⟂ 1 | `detectors:1660` | chấp cả hai bằng `-or` | 🔴 đổi sang **tên thứ ba** ⇒ phiên đã đóng bị đọc là **đang mở**, cờ *"BƯỚC 0.8 bị bỏ"* **không bao giờ bắn** |

  ⇒ Máy tha là **đúng** cho vật cũ (L1) và **sai** như một trạng thái vĩnh viễn. Máy soi phải **gọi tên hai vật này mỗi lượt** — nếu không, chúng là hai cái tên mà **không văn bản nào và không cờ nào từng nhắc tới**.
- **Vật thứ ba, ngoài mọi họ:** `resume-S146-20260722T2334.md`. Vật cũ ⇒ giữ (L1) ⇒ nhưng phải được **liệt tên**.

## §6 — Nhật ký phiên

> 🔴 **Mục có rủi ro BOM HẸN GIỜ cao nhất trong cả chuẩn. Đọc trọn trước khi sửa.**

- **NẤC muốn sạch:** **KHÔNG ÉP HÌNH DẠNG.** Nhóm này có **0 máy**. Theo L0, tệp này **cấm ký luật hình dạng cho nó**.
- **Tập giá trị hợp lệ = CẢ NĂM HỌ ĐANG SỐNG** (mẫu số **159 tệp**, đo 2026-08-07):

| Họ | Dạng | Số | % |
|---|---|---|---|
| (a) | `YYYY-MM-DD-HHMM-S<n>-<slug>` | 19 | 11,9% |
| (b) | `YYYY-MM-DD-S<n>-<slug>` | 78 | **49,1%** |
| (c) | `YYYY-MM-DD-s<n>-<slug>` (chữ `s` thường) | 13 | 8,2% |
| (d) | `YYYY-MM-DD-HHMM-<slug>` | 45 | 28,3% |
| (e) | `YYYY-MM-DD-<slug>` | 4 | 2,5% |

- 🔴 **VÌ SAO tập hợp lệ phải chứa cả 5 (bẫy-1 của sàn):** một bài kiểm khẳng định cứng *"kho sạch"* cộng với một quy ước chỉ có hiệu lực từ ngày D sẽ **xanh hôm nay và TỰ CHUYỂN ĐỎ vào ngày D** mà không ai chạm vào mã. Thu hẹp tập hợp lệ xuống 1 họ = cài đúng quả bom đó. **Cấm.**
- **Khuyến nghị đi tới (khuyến nghị, KHÔNG cưỡng chế — vì không có máy):** họ **(b)**. Lý do: đông nhất (78/159), có mã phiên nên `closeout-sentinel` đọc được, và không mang giờ-phút vốn hay bị đặt sai.
- 🔴 **XUNG ĐỘT ĐANG SỐNG — khai, không tự vá:** `CLAUDE.md:151` quy định `docs/changelog/sessions/YYYY-MM-DD-HHMM-{topic}.md`, tức **chỉ họ (a)+(d)**. Đĩa khớp `^\d{4}-\d{2}-\d{2}-\d{4}-` = **64/159 = 40,3%**. ⇒ **quy ước thành văn DUY NHẤT của kho đang sai với 59,7% đĩa, sống nhiều tháng, 0 máy, 0 ai biết.**
  **Tệp này KHÔNG sửa `CLAUDE.md`** (ngoài phạm vi W1 — xem Phụ lục B, nợ N-1). Cho tới khi nợ đó đóng, `CLAUDE.md:151` phải được đọc là **"khuôn khuyến nghị cho vật mới"**, KHÔNG phải "vị từ kiểm kho".

## §7 — Tên lệnh

- **NẤC muốn sạch:** **HÌNH DẠNG** kebab `^[a-z0-9]+(-[a-z0-9]+)*$` — đo **19/19 = 100%**.
- **MÁY:** **không có script nào.** Nhóm này sạch nhờ **vòng phản hồi NGƯỜI**: đổi tên lệnh = lệnh biến mất khỏi tay chủ dự án ngay lượt sau.
- ⇒ Ghi thẳng để không ai tưởng có máy canh (LỚP-9): **sạch KHÔNG phải nhờ cưỡng chế.** `naming-scan.ps1` là máy đầu tiên soi nhóm này.
- `tiep.md` là ngoại lệ **NGÔN NGỮ** (tiếng Việt không dấu), **không** phải ngoại lệ hình dạng ⇒ vẫn 1 họ.

## §8 — Kịch bản

- **NẤC muốn sạch:** **HÌNH DẠNG, THEO NGÔN NGỮ** (L4)
  - `.ps1` · `.sql` · `.md` → **kebab-case**
  - `.py` → **snake_case** (PEP-8)
- Đo (mẫu số **53 mục**): kebab 46 · snake 6 (= 5 `.py` + `__pycache__`) · đuôi: `.ps1` 32 · `.sql` 14 · `.py` 5 · `.md` 1 · thư mục 1. **Kỷ luật 2 chiều 100%** — 0 `.py` kebab, 0 `.ps1` snake.
- 🔴 **Trục tiền tố `s<n>-` / `plan-` là HỢP LỆ, KHÔNG phải lệch** (16/53 = 30,2%). Nghĩa: *"kịch bản MỘT LẦN thuộc phiên/kế hoạch N"*, phân biệt với máy thường trực nằm cùng thư mục. Đây là **thông tin tự mô tả có ích**, không phải trôi tên.
  ⇒ Máy soi **đếm riêng** cụm này thành nhóm `MOT-LAN` với mẫu số của nó — một tín hiệu tồn kho, **không phải cờ vi phạm**. Xếp chúng vào cột "lệch" là **dương-giả**, và dương-giả ngày đầu là cách nhanh nhất để người ta tắt máy soi.
- **Fork thật duy nhất:** `session-scaffold.ps1` ⟂ `session_scaffold.py` — **hợp lệ theo luật ngôn ngữ nhưng TRÙNG KHÁI NIỆM**. Hai bản hiện sinh ra tên đầu ra **giống hệt nhau** (`session-<N>` + `_context-s-<N>.md`), cả hai đều hard-pin, **0 nguồn chung**. Chưa vỡ; là nợ, xem §12.

## §9 — Tên sổ

- **NẤC muốn sạch:** **HÌNH DẠNG** kebab — cho **sổ ĐANG BẢO TRÌ**.
- Đo (mẫu số **15 mục** `docs/governance/`): kebab thường 10/15 · chữ HOA-GẠCH 5/15.
- **Phân loại 5 vật HOA** — phân biệt này là bắt buộc, gộp lại sẽ đọc sai:
  - `README.md` → **miễn theo L4** (quy ước phổ quát).
  - `BROADCAST-OUT-SOLUTION-ERP-2026-05-29-INFRA-RETRO.md` · `BROADCAST-OUT-…-2026-05-29.md` · `BROADCAST-OUT-…-2026-06-01.md` · `RAG-AUDIT-RESPONSE-2026-05-29.md` → **vật lịch sử** (thư đã gửi, mang ngày). Giữ nguyên theo L1, **nhưng vẫn bị LIỆT TÊN** mỗi lượt quét: chúng là **chứng nhân** rằng nhóm này có 2 họ. Giấu chúng đi thì con số "sạch" của nhóm là con số bịa.
- **Luật vật MỚI:** sổ mới trong `docs/governance/` **bắt buộc kebab thường**. Thư đã gửi thuộc `broadcasts/`, không thuộc `docs/governance/` (L2).

## §10 — Nhãn tác vụ

- **NẤC muốn sạch:** **KHÔNG ÉP HÌNH DẠNG.**
- **Vật là gì:** `taskList[].label` truyền vào `.claude/workflows/hmw.js` lúc phát lệnh (`:18`), dùng ở `:292` `nameOf`.
- **Vì sao không ép:** nhãn này **phù du** — sống trong tham số một lượt gọi, không hạ cánh thành tên tệp (trừ khi được chép vào ảnh chụp `taskList` trong `run.md`). **0 máy kiểm hình dạng.** Theo L0, cấm ký luật hình dạng.
- **Luật duy nhất ký được:** nhãn phải **mô tả VIỆC**, không lặp lại **VAI** (vai đã có trường riêng). Đây là luật **mô tả, không cưỡng chế** — khai đúng như vậy.
- **Nợ đã biết:** `hmw.js:292` khi thiếu nhãn thì rơi về `role`, rồi rơi tiếp về `'(no-label)'` — **suy giảm im lặng**, đúng lớp lối câm ở L0. Không vá trong W1 (ngoài phạm vi); ghi Phụ lục B nợ N-3.

---

## §11 — Tên bị neo NGOÀI kho mã 🔴

**Đây là lớp nguy hiểm nhất, vì không ai `grep` tệp cấu hình khi đổi tên một kịch bản.**

| # | Vật bị neo | Neo ở đâu | Đổi tên ⇒ chuyện gì |
|---|---|---|---|
| 1 | `.claude/hooks/wal-flush.ps1` | `.claude/settings.json:9` — `-File .claude/hooks/wal-flush.ps1` | PowerShell không tìm thấy tệp ⇒ **việc tự-commit WAL DỪNG HẲN**. Hook tự khai *"fail-open moi nhanh: exit 0 ke ca loi"* — nhưng `exit 0` đó **nằm TRONG tệp**; tệp không chạy thì không ai `exit 0` hộ. **Mã thoát thật của nhánh này: KHÔNG ĐO ĐƯỢC** (cần đổi tên trên cây tạm rồi chạy hook thật). |
| 2 | thư mục `.claude/auto-memory` **và vị trí gốc của cả kho** | `.claude/settings.json:2` — `"autoMemoryDirectory": "D:/Dropbox/…/SOLUTION_ERP/.claude/auto-memory"` (**đường dẫn TUYỆT ĐỐI**) | Đổi tên thư mục **hoặc dời/đổi tên thư mục gốc của kho** ⇒ ký-ức-tự-động trỏ hụt, im lặng. *(Vật này lane a chưa liệt — bổ sung @W1.)* |
| 3 | 4 đường dẫn trong thân hook | `wal-flush.ps1:13` — `.claude/WAL.md` · `.claude/agent-memory/` · `.claude/workflows/runs/` · `.claude/sessions/` | `git add` trượt im lặng (`2>$null`) ⇒ **thư mục đó thôi được commit tự động, 0 báo**. |

**Luật:** đổi tên bất kỳ vật nào ở cột 2 ⇒ **bắt buộc mở `.claude/settings.json` và đọc TOÀN TỆP**, không chỉ grep khối `hooks`. Tệp này 15 dòng, đọc trọn mất 5 giây; hai neo nằm ở hai khối khác nhau (`:2` và `:9`) nên grep một khối sẽ bỏ sót khối kia.

## §12 — Số chỗ phải sửa ĐỒNG THỜI 🔴

Đổi một trong các tên dưới đây mà không mở đủ số chỗ = vỡ câm. Con số này là **cận dưới đã đo**, không phải ước lượng.

| Tên | Số chỗ | Từng chỗ (liệt đủ, cấm nén thành khoảng) |
|---|---|---|
| `session-<N>` (hình dạng thư mục phiên) | **4** | `governance-detectors.ps1:1639` · `scripts/session_ctx.py:133` · `scripts/session-scaffold.ps1:116` · `scripts/session_scaffold.py:105` |
| `sub-*` (họ tệp con lượt chạy) | **3** | `governance-detectors.ps1:1102` · `governance-detectors.ps1:1771` · `scripts/memory-selfimprove-audit.ps1:298` |
| tên vai | **3** | `.claude/workflows/hmw.js` `VALID_ROLES` · `.claude/agents/<role>.md` · `.claude/agent-memory/<role>/` |
| `.claude/agent-memory` (đường dẫn) | **5** | `closeout-sentinel.ps1:119` · `mfe-eval.ps1:44` · `mfe-eval.ps1:264` · `memory-selfimprove-audit.ps1:122-124` · `crystallized-backfill.ps1:54-55` (+ `wal-flush.ps1:13`) |

🔸 Hai bảng sao **cùng một regex** ở `detectors:1102` và `:1771` là **nợ kỹ thuật: 1 luật / 2 bản sao**. S159 đã phải vá **cả hai**; chú thích `:1769-1770` tự khai *"mirror of the C11(b) filter fix above"*. Hợp nhất thành một hằng số là việc nên làm — **không làm trong W1** (đụng máy đang sống, thuộc W2 theo `Q5`).

## §12-bis — MASTHEAD của CHÍNH tệp vừa sửa 🔴

**Nguồn sàn:** `broadcasts/inbox/ai_infra/2026-07-20-Governance-3-khoan-title-tier-posture-home-distill-params.md` **Khoản 1** (`:19-27` — vùng đóng băng L1 nên neo số dòng ở đây hợp lệ). Hub đo: **ba ca cùng một hình trong ba phiên liền**; ca nặng nhất — một doc chính sách mang tiêu đề khai một tên model **đã bị thay hai đời trước** — **sống sót qua hai lượt quét**.

**Vì sao luật này nằm ở tệp này, ngay sau §12:** §12 liệt "số chỗ phải sửa ĐỒNG THỜI" theo **danh mục nơi TRỎ TỚI** một cái tên. Nhưng cách một tệp **tự mô tả chính nó** — dòng `#` đầu, khối masthead, dòng trạng thái ngay dưới tiêu đề — **không nằm trong danh mục của ai cả**. Nó là chỗ duy nhất không ai trỏ tới, nên là tầng sống lâu nhất sau mỗi lượt quét. Đây là chỗ ghi nó.

**Luật (một bước, vài giây):** sửa THÂN một tệp trong một lượt quét/vá ⇒ **đọc lại dòng `#` đầu + khối masthead của CHÍNH tệp đó** trước khi tuyên lượt quét xong. Tuyên "xong" mà chưa đọc lại = **chưa xong**.

**Phạm vi:** mọi tệp có masthead **mang trạng thái** — nhãn DRAFT/RATIFIED, mã phiên, ngày, tên chế độ, con số, tên model. Masthead thuần mô tả (chỉ nói tệp này là cái gì) thì miễn; miễn thì **nói ra**, đừng im (L4).

**Phép thử (tái lập được, không cần máy):**

```bash
for f in docs/governance/*.md docs/rules.md docs/STATUS.md docs/HANDOFF.md CLAUDE.md; do
  printf "%-52s | %s\n" "$f" "$(grep -m1 '^#' "$f")"; done
```

Đối chiếu từng dòng in ra với trạng thái hiện hành **trong thân chính tệp đó** — không đối chiếu với trí nhớ.

**Lượt chạy đầu (2026-08-09, phiên S185 — 21 tệp): một ca dương THẬT.** `docs/governance/ctx-soft-memory-se-draft.md` còn chữ `DRAFT` ở dòng `#` đầu trong khi khối trạng thái của **chính nó** đã tuyên `✅ RATIFIED + ĐÃ WIRE @S153 (OWNER-VETO)` — thân đã vá, masthead sống sót. Đã đồng bộ ngay trong lượt đó, giữ vết 🧊. **KHÔNG tính là ca:** `session-model-se-draft.md` — masthead ở đó **khớp** thân (`0 nghi-thức chuyển per-L`); thân có cũ hay không là câu của khoản đối chiếu thư trả lời hub 07-22, **không phải** lỗi masthead. Phân biệt hai loại này quan trọng: gộp lại sẽ đẻ ra dương giả và làm phép thử mất uy.

**CHƯA CÓ MÁY** — khai theo **L0**: luật này sống bằng kỷ luật một bước, chưa đoạn máy nào ép. Ai muốn cắm máy thì cắm ở **lớp INFORM** (`naming-scan.ps1`, họ tệp `.md` có masthead mang trạng thái) và ghi vào **Phụ lục B**; **cấm** ký hình dạng sâu hơn nấc máy ép.

## §13 — Giao thức di trú sáu bước (cho ca BUỘC phải đổi tên đã có người trỏ)

1. **Ký chuẩn** (tệp này).
2. **Kiểm kê mọi chỗ máy đang đọc tên** — tra **Phụ lục A**, và quét lại thật: biểu thức tìm kiếm trong `scripts/`, trong bài kiểm, trong `.claude/commands/*.md`.
3. **Cho bộ phân tích đọc được CẢ tên cũ lẫn tên mới TRƯỚC ĐÃ.** Hai tiền lệ đúng sách có sẵn trong kho, dùng lại khuôn của chúng: `session_ctx.py:349-358` (hai glob, chú thích giải thích vì sao không đếm trùng) và `governance-detectors.ps1:1648-1649`.
4. **Tên mới chỉ áp TỪ NAY VỀ SAU** (L1).
5. **Đối chứng HAI CHIỀU + phản chứng.** Gài một tên cũ giả và một tên mới giả trên **cây tạm** → máy phải đọc được **cả hai**. Rồi gài thêm một tên **sai cả hai chuẩn** → máy **phải báo**. Chạy trọn bộ máy trước/sau, so mã thoát.
6. **Bật chế độ nghiêm sau `3` phiên sạch liên tiếp.** *(Con số 3 do nhà mình đặt; đây là chỗ ghi nó. Đổi số thì đổi ở đây, không chép đi chỗ khác.)* — Bật nghiêm là việc của **W3b**, sau khi chủ dự án chốt câu **P1**; W1 **không** lái mã thoát.

**Ngoại lệ đáng học (từ sàn):** có những tệp mà **máy neo đường dẫn cố định** — đổi tên chúng mỗi lần cập nhật là phá form, đúng cái mà chuẩn sinh ra để chống. Với loại này: **giữ tên cố định, để thời điểm sống trong tiêu đề khối BÊN TRONG tệp.** Ca sống ở kho ta: `docs/STATUS.md`, `docs/HANDOFF.md`, `.claude/WAL.md`.

## §14 — Hai xung đột: KHAI, KHÔNG vá âm thầm 🔴

### XĐ-1 — Luật S122 *"đo NỘI DUNG, đừng đoán TÊN"* ⟂ đòi hỏi *"tên lệch phải kêu"*

`governance-detectors.ps1:1104-1109` **cố ý** không đoán tên: tên lạ rơi vào `$unmapped` và chỉ được **liệt**, không **cờ**. Đó là thi hành luật S122 — và luật đó **đúng**.

Nhưng hệ quả là **lệch tên = im lặng theo thiết kế**. Muốn "tên lệch phải kêu" thì **phải sửa chính chỗ đó**, tức đi ngược một luật đang sống.

**Cách W1 đi qua mà không phạm luật nào:** `naming-scan.ps1` là **máy MỚI, tách riêng**, soi **tên vật-bộ-máy** (agents / commands / scripts / sessions / sổ / hook) — **không** đụng `$unmapped` của detectors, **không** đổi hành vi máy cũ. S122 nói *đừng suy vai từ tên*; nó **không** cấm một máy chuyên trách soi hình dạng tên. Hai việc khác nhau.
⇒ **Chưa cần chủ dự án phán.** Nếu về sau ai muốn cho `detectors:1109` kêu thật, **lúc đó** mới là xung đột cần phán.

### XĐ-2 — Doctrine exit-0-advisory ⟂ lái mã thoát

Chủ dự án **đã chốt P1 = PA-2** (hai mã thoát mỗi máy, phân loại lại 70 cờ). Việc đó thuộc **W3b**, có điều kiện vào riêng (rider-jump phải soak INFORM ≥1 phiên trước).

⇒ **W1 KHÔNG lái mã thoát.** `naming-scan.ps1` **luôn `exit 0`**, kể cả khi có cờ. Lý do đo được (lane F): bật gate mà chưa soak ⇒ **8-12 lớp nợ tồn kêu cùng lúc**, người đọc tưởng máy hỏng rồi tắt máy. Khoản `G1-B7` (siết máy soi sang mã thoát) nằm **NGOÀI scope W1** đúng theo `adap-upgrade-pack-fitmap.md` dòng GĐ-1.

---

## PHỤ LỤC A — 14 đoạn máy ĐANG ĐỌC TÊN (tra TRƯỚC mọi lần đổi tên)

> Nguồn đầy đủ: `runs/2026-08-07-S180-adap-upgrade-pack-phased/sub-w1a-mayd-octen.md` §1.
> 🔴 **0/14 đoạn tự thích nghi được với tên mới.** Ba nhánh 🟢 tồn tại đều là **xử lý tay cho một cặp cụ thể**, không phải cơ chế tổng quát. **Không được giả định có máy nào sẽ tự nuốt tên mới.**
> Mức: 🔴 vỡ-câm (vẫn chạy, vẫn in, kết quả sai/mù) · 🟡 vỡ-ồn (throw/cờ/dừng — đau nhưng thấy được).

| # | Đoạn máy | Đọc tên gì | Mức | Đổi tên ⇒ |
|---|---|---|---|---|
| M-01 | `hmw.js:22-51` + chặn `:171-186` | 26 tên vai | 🟡 | throw DỪNG HẲN, fan-out chết (chỉ bắt tên SAI, không bắt tên THIẾU) |
| M-02 | `governance-detectors.ps1:1102` | họ `^(sub-.+\|.+-return)\.md$` | 🔴 | tệp biến mất khỏi tầm quét, vai bị coi là chưa chạy |
| M-03 | `governance-detectors.ps1:1104-1107` | suy VAI từ tên tệp, 3 nấc tham lam | 🔴 | rơi `$unmapped` — **liệt, không cờ** |
| M-04 | `governance-detectors.ps1:1762` (dùng `:1774`) | `lead-stale\|lead-gap\|ring2-audit` trong tên tệp | 🔴 | luật FLAG-khuôn ngừng áp; in *"đã đo, 0 cờ"* trong khi **chưa đo gì** |
| M-05 | `governance-detectors.ps1:1771` | **bản sao thứ 2** của M-02 | 🔴 | vá một chỗ quên chỗ kia (S159 đã phải vá cả hai) |
| M-07 | `governance-detectors.ps1:1044`+`:1050` (+`:1882`) | đường dẫn `docs/changelog/sessions/` | 🔴 | cờ MED **bắn sai mỗi phiên** — máy ồn nhưng **tố người dùng thay vì tố chính nó**; `:1882` là nhánh `[skip]` im lặng |
| M-08 | `governance-detectors.ps1:1624`·`1639`·`1648`·`1649`·`1660` | 5 tên trong một khối | 🔴+🟡 | `:1622` **skip trọn khối** nếu đổi tên thư mục gốc; `:1660` chấp 2 tên bằng `-or` |
| M-09 | `scripts/session_ctx.py` (7 vùng) | `_snapshot-*` `:110` · `WAL.md` `:116` · `session-{n}` `:133` · `_pause`/`pause` `:349-358` · `_context-s`/`_mind-s`/`_end` `:530-549` | 🔴 rìa / 🟢 lõi | `:110` `:116` hỏng **câm**; `:349-358` + `:594` là **hai mẫu tốt** nên nhân rộng |
| M-10 | `session-scaffold.ps1` ⟂ `session_scaffold.py` | cùng sinh `session-<N>` + `_context-s-<N>.md` | 🟡 | lệch nhau ⇒ COLLISION exit 4 (thấy được); nhưng **hard-pin 2 bản, 0 nguồn chung** |
| M-11 | `.claude/hooks/wal-flush.ps1` | tên chính nó (`settings.json:9`) + 4 đường dẫn (`:13`) | 🔴 ×2 | hook không chạy (mã thoát **KHÔNG ĐO ĐƯỢC**) · `git add` trượt im lặng |
| M-12 | `scripts/closeout-sentinel.ps1:118`·`119`·`160`·`163`·`165`·`168` | tên sổ đếm · `agent-memory` · `runs` · khuôn tên H24 · **mã phiên trong tên thư mục** | 🔴 | phiên chuyển **SKIP chứ không FLAG** — SKIP đọc y hệt *"phiên này không cần kiểm"* |
| M-13 | `scripts/mfe-eval.ps1:44`·`52-54`·`243`·`264` | `memory-budget.json` · 3 tên sổ · roster suy từ tên tệp · **ghép tên vai vào đường dẫn** | 🔴 | vai bị **LOẠI khỏi phép đo**, kèm lời giải thích sai sự thật |
| M-14 | `scripts/memory-selfimprove-audit.ps1:122-124`·`189`·`211`·`230-231`·`252-258`·**`:298`**·`:299` | 3 neo thư mục · tên vai→tệp · **tên script khác** · 2 sổ · 3 artefact bộ nhớ · **`-Filter 'sub-*.md'`** | 🔴 | `:298` = **chính bộ lọc đã vá ở tệp A mà chưa nhân sang tệp B** → vá tại W1 |
| M-15 | `scripts/crystallized-backfill.ps1:54-55`·`73-78`·`106-114` | `agent-memory` · 4 tên sổ mặc định | 🟡 hiển thị / 🔴 số dẫn xuất | in `MISSING` từng dòng, **nhưng** `$totalBytes` không cộng ⇒ kết luận *"còn nhiều chỗ trống"* **sai câm** |

**Hai vật KHÔNG phải máy đọc tên — đừng bảo tồn nhầm:** `governance-detectors.ps1:1716` (dòng **chú thích**, mô tả một điểm mù đã biết) · `scripts/applied-eval-nokey.ps1` (**0 thao tác tệp**; control cùng thước trên `mfe-eval.ps1` = 14 hit ⇒ 0 là 0 thật). Đưa chúng vào danh sách sẽ khiến người sau đi bảo tồn một cái tên **không máy nào đọc**, đồng thời làm phồng mẫu số.

## PHỤ LỤC B — NỢ và CHƯA ĐO (ghi tên, không để im)

| # | Nợ | Vì sao chưa đóng ở W1 | Đóng ở đâu |
|---|---|---|---|
| N-1 | `CLAUDE.md:151` khuôn nhật ký phiên sai với **59,7%** đĩa | W1 **bị cấm sửa** `CLAUDE.md`; đây là bề mặt nạp mỗi lượt, sửa phải gom restart | Cần chủ dự án gật; gom vào lớp **C** của W3/W4 |
| N-2 | `detectors:1102` ⟂ `:1771` — 1 luật / 2 bản sao | Đụng máy `/session-end` đang sống ⇒ đòi fault-inject cây tạm (`Q5`) | W2 |
| N-3 | `hmw.js:292` thiếu nhãn ⇒ rơi `'(no-label)'` im lặng | Ngoài phạm vi W1 (W1 chỉ vá con số `:33`) | W2/W5 |
| N-4 | **CHƯA ĐO:** mã thoát thật khi `wal-flush.ps1` bị đổi tên | Cần đổi tên trên **cây tạm** rồi chạy hook thật + đọc `$LASTEXITCODE` | W2 |
| N-5 | **CHƯA ĐO:** `.claude/commands/*.md` (19) + `.claude/agents/*.md` (27) neo những tên gì | Đó là **kiểm kê máy** = phần việc lane a; nhận thêm ở W1 là ăn lẹm | W2 |
| N-6 | `session-scaffold.ps1` ⟂ `session_scaffold.py` trùng khái niệm, 0 nguồn chung | Hợp lệ theo L4; hợp nhất là đổi mã, không phải đổi tên | W2 |
| N-7 | **Vai giữ chuẩn** (`G1-B2`) chưa tồn tại | **NGOÀI scope GĐ-1 theo fit-map** — chờ chủ dự án phán câu **P4** | W4b |
| N-8 | Con số "18/88 thư mục lượt chạy vô hình với sentinel" | Là **hệ quả**, không phải tên sai. Vá nó = sửa `closeout-sentinel.ps1:165` | W2 |

**Ba ô nghiệm thu của sàn §GĐ-1 mà W1 CỐ Ý chưa đạt, khai thẳng thay vì để trống:**
- ☐ *"Vai giữ chuẩn tồn tại"* → **N-7**, ngoài scope theo fit-map, chờ **P4**.
- ☐ *"Máy soi tên đặt ở cổng"* → W1 chạy **tay + INFORM-only**; cắm vào cổng `session-end` thuộc **W3** (gom restart), lái mã thoát thuộc **W3b** (P1 = PA-2).
- ☑ Sáu ô còn lại: xem `rename-ledger.md` và báo cáo wave.
