# sub-implementer-backend-1 — T1 MÁY `mind-check` (extend `scripts/session_ctx.py`)

> GHI TRONG LÚC LÀM (chống #53). Thứ tự: design → diff-summary → acceptance-runs → END-line.
> Task: T1 spec `spec-ctx-adopt-26-07-2026.md` + `sub-fable-invest-S153.md` Mục 2 §T1 / Mục 3 / PHẦN B.
> Vết ủy quyền: OWNER-DELEGATED qua lệnh pipeline 26-07 (KHÔNG ghi "owner chốt" ở bất kỳ file nào).

## ⚠️ Lệch tên file (khai ngay, không tự ý chọn im lặng)

TASK-block nói ghi `sub-implementer-backend-1.md` + END-line `<!-- END sub-implementer-backend-1 · TOTAL=<n> acceptance -->`;
RUN-TRACE boilerplate (đoạn footer chung mọi vai) nói `sub-implementer-backend-0.md`.
⇒ Theo **chỉ-thị task-specific** (nêu 2 lần, kèm đúng END-line) ⇒ ghi `-1`. Em main đọc `-1`, KHÔNG có `-0`.

---

## PHẦN 1 — DESIGN (chốt trước khi code)

### 1.1 Ranh scope

- SỬA ĐÚNG 1 FILE: `scripts/session_ctx.py` (ADD-only: 1 hằng module-level + 1 khối `mind-check` + 1 parser CLI + 1 nhánh dispatch).
- KHÔNG tạo `.ps1` (spec T1 chốt: extend python, 1-nguồn `_SECRET_RES`/`_TS_KEY_RE`).
- KHÔNG đụng `machine_block` / `secrets_sweep` / `_SECRET_RES` / `SECRET_PATTERNS` / helper git — hành vi 2 subcommand cũ BẤT ĐỘNG (proof = insertion-only diff, xem §2).
- KHÔNG đụng `memory-budget.json` (T7 = lead-solo), KHÔNG đụng template (T2 = lane khác), KHÔNG đụng command .md (T6 = lead).

### 1.2 Quyết định thiết-kế + lý-do đo được

| # | Quyết định | Vì sao (chứng) |
|---|---|---|
| D1 | **Config đọc LAZY** — chỉ đọc `memory-budget.json` khi CÓ tệp để đo | 2 dòng acceptance Mục 3 chỉ đồng-thời đúng khi đúng thứ tự này: repo thật `--session 6` (chưa có `_mind`, chưa có khoá `mind_ctx_kb` vì T7 land SAU) ⇒ `bỏ-qua-có-khai` exit 0; cây tạm CÓ `_mind` mà THIẾU khoá ⇒ exit 3. Nguyên tắc phát biểu tường minh trong code: *"không có gì để đo thì không đọc trần; có thứ để đo thì TỪ CHỐI đoán trần"* (khuôn H24-2 cấm default) |
| D2 | Full-mode đòi `{mind_ctx_kb, session_ctx_kb}`; draft-mode chỉ đòi `{session_ctx_kb}` | draft-mode bỏ phép 6/7 (spec) ⇒ không tiêu thụ `mind_ctx_kb` ⇒ đòi nó = fail-loud oan; và cho `/pause` draft-gate (T6a) DÙNG ĐƯỢC NGAY trước khi T7 land. Thiếu khoá ⇒ in **TÊN KHOÁ** thiếu (tên-sai-phải-nêu-tên) |
| D3 | Vùng nội-dung = slice DƯỚI `<!-- MIND-RULES-END -->`; marker VẮNG ⇒ quét TRỌN tệp + **CỜ** | enclosure use⟂mention (`feedback_citation_trap_selfreference`): khối luật CHỨA chuỗi cấm để giải thích. Hướng hỏng chọn NGHIÊM (quét trọn + cờ) vì tệp thiếu marker = tệp sai khuôn, phải lộ chứ không được im |
| D4 | Rào-3 in **pattern-name + file:line, KHÔNG in snippet** | mind-check là gate chống rò; in snippet = tự tay rò ra log/transcript. (Khác `secrets-sweep` cũ có in snippet — KHÔNG sửa hành vi cũ, chỉ không lặp ở phép mới) |
| D5 | Nhãn che nhận **DUY NHẤT** dạng có dấu `[đã che <8-hex>]` (escape `đã`) | spec literal. CỐ Ý không nhận biến-thể ASCII "da che": gate bảo-mật thì lệch về phía QUÁ NGHIÊM (fail-safe), không nới bằng suy diễn |
| D6 | Mọi đoạn trích in ra đi qua `_ascii_safe()` (backslashreplace) | giữ ASCII-source ⟂ ASCII-output: console cp1252 gặp diacritic sẽ `UnicodeEncodeError` = máy chết giữa gate. Đây là bẫy THẬT trên Windows PS 5.1 (họ gotcha #30/#37) |
| D7 | Phép-9 nhận **họ hình-dạng** heading A-E (`### A —` · `**A.**` · `- **A** —` · `A)` · `#### A:`) | T2 (template) do lane KHÁC viết SONG SONG ⇒ code khớp **marker theo SPEC** (`MIND-RULES-*`/`MIND-TOP`/`^## MIND-<k>`), còn hình-dạng A-E spec KHÔNG chốt ⇒ nhận rộng + in ra đúng "họ dạng đã nhận" khi trượt để chẩn 1 nhát. Khai coupling: nếu T2 chọn dạng ngoài họ này ⇒ phép-9 trượt oan ⇒ T4/lead phải chạy lại trên template THẬT |
| D8 | p (phép-6) = **ĐẾM ĐĨA** `_pause-*.md` + `pause-*.md` (dual-accept); `markers:`/`mind-blocks:` trong `_end` CHỈ cross-check ⇒ **cờ-INFO** | spec + `tiep.md:102` (glob `pause-*` KHÔNG khớp `_pause-1.md` ⇒ cộng thẳng an-toàn, 0 đếm đôi). Tự-khai KHÔNG BAO GIỜ là nguồn đếm |
| D9 | exit {0 = 0 trượt · 1 = ≥1 trượt · 3 = config/state} ; argparse giữ 2 = usage | spec T1 + khuôn `session-scaffold.ps1` (exit 2 usage / 3 config) |

### 1.3 Bảng phép (7 chuẩn + 2 phụ) — nguồn dữ liệu + 4 mức

| Phép | Đo gì | đạt | trượt | cờ | bỏ-qua-có-khai |
|---|---|---|---|---|---|
| (1) rào-1 lời-anh | `^[ \t]*>[ \t]*anh[ \t]*:` trong vùng nội-dung | 0 hit | ≥1 hit + file:line | — | draft: vẫn chạy |
| (2) rào-2 ts-key | `_TS_KEY_RE` (module-level, canonical) | 0 hit | ≥1 hit + file:line | — | — |
| (3) rào-3 secret | `_SECRET_RES` per-line, trừ dòng có nhãn che | 0 hit | ≥1 hit (pattern+line, 0 snippet) | — | — |
| (4) con-trỏ E top | path trong backtick ở mục E block TRÊN CÙNG | mọi path tồn tại | broken (cha KHÔNG có) — mọi mode · pending khi **closed** | pending khi **open** · E có nội dung mà 0 con-trỏ | E = `(trống — khai)` · token placeholder `<>`/`*` |
| (5) số-hiệu | `^## MIND-(\d+)` | duy nhất ∧ top ≥ mọi số dưới | trùng số / top < số dưới | — | 0 block |
| (6) bất-biến | `|block| ∈ {p, p+1}` | trong tập | ngoài tập | lệch tự-khai (INFO) | draft-mode |
| (7) trần | `size(_mind)` vs `mind_ctx_kb`×1024 (LIVE) | ≤ trần | — (nợ hiển thị, KHÔNG trượt) | vượt trần (+hướng nén / "TỪ-CHỐI nén" khi <3 block) | draft-mode |
| [phụ-8] `_context` | `size(_context-s-N.md)` vs `session_ctx_kb`×1024 | ≤ trần | — | vượt | tệp vắng |
| [phụ-9] cấu-trúc | 5 mục A-E mọi block + nhãn D | đủ | thiếu mục / bullet-D thiếu nhãn | — | — |

- **Nhãn D nhận:** `mới-nêu` · `đang-cãi` · `gần-chốt` · `treo-chờ-anh` (escape `ớ ê đ ã ầ ố ờ`).
- **Mục trống:** `(trống …` → `\(\s*trống`.

### 1.4 Chế-độ + thứ tự thi hành (fail-order)

```
--session N (BẮT BUỘC, không default-latest)  --root PATH (seam fault-inject)  [--draft F] [--closed]
1. resolve root/sessions/session-N ; closed = --closed OR exists(_end)
2. DRAFT? -> đọc file nháp; đếm block trên đĩa (canonical, 0 nếu vắng); phép 1,2,3 + 5-draft(số==count) + 4 + phụ-8 + phụ-9 ; phép 6,7 = bỏ-qua-có-khai
3. FULL: canonical vắng -> glob '*mind*' NÊU ĐÚNG TÊN ứng viên
      open   -> bỏ-qua-có-khai, exit 0   (CHƯA đọc config = D1)
      closed -> TRƯỢT, exit 1
4. FULL có tệp: require keys -> thiếu = exit 3 (nêu tên khoá) ; rồi 7 phép + 2 phụ
```

### 1.5 Câu hỏi đã cân + BÁC

- *Có nên `--session` default "mới nhất"?* BÁC — spec §3 "input chỉ đích danh — 2 cửa sổ song song sẽ đua" (kẽ 2-cửa-sổ nêu ở PHẦN B #24(ii)).
- *Có nên máy tự canh bất-biến block cũ (immutability)?* BÁC — cần git-history diff, ngoài tầm $0; PHẦN B #17 đã khai lưới = luật + git + ctx-audit.
- *Có nên gộp `secrets-sweep` vào mind-check?* BÁC — 2 lưới ĐỘC LẬP (PHẦN B #7 đo đúng tính chất đó: sweep rglob vốn phủ `_mind`).

---

## PHẦN 2+3 — ACCEPTANCE-RUNS *(lead on-behalf @S153 — lane mất return [schema-fail #53-biến-thể], code ĐÃ LAND; lead chạy 4 acceptance độc lập, dán số thật)*

| # | Lệnh | Kỳ vọng | Đo được | Verdict |
|---|---|---|---|---|
| a | `python scripts/session_ctx.py mind-check --session 6` (repo thật) | bỏ-qua-có-khai + exit 0 + glob nêu ứng viên | `(0) ... bo-qua-co-khai · glob *mind* (0 ung vien) · chua doc memory-budget.json` · exit **0** | ĐẠT |
| b | `--root <cây thiếu mind_ctx_kb>` (có `_mind`) | exit 3 + nêu TÊN khoá | `CONFIG/STATE ERROR: missing key(s) mind_ctx_kb ... CAM default (khuon H24-2 fail-loud)` · exit **3** | ĐẠT |
| c | `python -c "...decode('ascii')"` | pass | `ascii OK` · exit 0 | ĐẠT |
| d | `--root <cây đủ khoá + fixture render từ template THẬT 8845B>` | exit 0 | **8 đạt / 0 TRƯỢT / 0 cờ / 2 bỏ-qua-có-khai** (E `(trống)` khai · `_context` vắng khai) · phép-7 đọc LIVE 32×1024 · phép-6 đếm-ĐĨA p=0 dual-accept · exit **0** | ĐẠT |

Chứng code trên đĩa: `_TS_KEY_RE` :59 (canonical, comment single-truth) · vùng mind-check :196+ · `mind_check()` :535 · CLI parser :698 + dispatch :729 · 55 hit `mind`. Diff = ADD-only (2 subcommand cũ bất động — machine-block/secrets-sweep giữ nguyên hành vi).

<!-- END sub-implementer-backend-1 · TOTAL=4 acceptance -->

