# Q1 · B2 批第 2 组预注册 —— `#M41` + `#M12` 共用的「反馈组件不自画」判据

> ⛔ **本文件写在动手之前**，判据形态、分母、造故障预测全部钉死在此。
> 落地后如实回填「预注册没预见到的」，⛔ 不许事后改预测。
>
> 上一轮（DS `9834b949`）量出的真共用分组是 **`#M41` + `#M12`**，
> ⛔ **不是**裁定表原写的 `#M12` + `#M13` —— `#M13` [2] 逐字只说「用对应谱系反馈组件」，
> **没有「不自画」三个字**，按仓规「判据串逐字取自活源」它不能靠这条判据算覆盖。

---

## 0 判据串逐字取自活源（⛔ 非转述，本轮回源逐字核过）

| 段 | 活源位置 | 逐字串 |
|---|---|---|
| `#M12` [2] | `docs/internal/domain-tvu.md:179`（段 Σ=3） | 「反馈按谱系取对应库 variant（设备 `Message` / web `Notification`），需操作则用带按钮组件，**不自画**」 |
| `#M41` [3] | `docs/internal/mockup-conventions.md:2782`（段 Σ=4） | 「Dialog 必是 TVU `Notification` instance，**非 detach 自建**」 |
| `#M12` 正文 | `domain-tvu.md:169` | 「反馈控件一律取库 variant **不自画**」 |
| `#M41` 禁止项 | `mockup-conventions.md`（M41 §禁止） | 「❌ Dialog detach 后自建（应保持 TVU library 连接，遵守 M32 library-first）」 |

⇒ 两段共用的可 falsify 断言只有一条：**名为反馈组件的节点必须是库 instance，不能是自画 / 已 detach 的容器。**

---

## 1 落地前必答的两件事（交接点名的前置，⛔ 两件都从活源答出，不需 owner）

### ① 判定对象从「名字像」收窄 ⇒ **name.trim() 逐字相等**，⛔ 不用 `includes`

本轮探针（4 份本机 payload 快照，遍历 **302,766** 节点，量具自证见 §2）：

| 形态 | 命中节点 | 其中 type ≠ `INSTANCE`（= 会被判违例） |
|---|---:|---:|
| **逐字相等** `name.trim() ∈ {Notification, Message}` | **76** | **3** |
| 放宽成 `name.includes(…)` | 817 | **76** ⇒ **假阳 73 处** |

那 73 处假阳的构成（现取）：`TEXT` 散文 **23** · `SLOT`（`Notification_content`）**30** ·
`FRAME`（`Notification_content` / `Notification_content row`）**7** · `VECTOR`（`Flow_text --> Notification` 等）**12** · `CANVAS` **1**。

🔴 **更正上一轮读数的污染源清单** —— 它逐字写的是「`Notification_content` 31 处 ·
`Notification Settings` 1 处 · `Notification --> Flow_text` 2 处」，只覆盖 `Notification` 词族。
实测最大污染源它**整片没提**：`Message` 词族里 `icon/Message/*` 图标实例约 **668 处**
（`icon/Message/Help 1` 单项 445 · `Success 2` 50 · `Success 1` 38 · `warning 1` 38 · …）。
⇒ 它们恰好都是 `INSTANCE`，所以在放宽形态下**不会**变违例 —— 但它们会把 `scanned` 分母从
76 灌到 817（**放大 10.7 倍**），而违例数只从 3 变 76 ⇒ **合规率会从 96% 假涨到 91%**，
两个数都不再是这条规则说的东西。⇒ 收窄不只是防假阳，也是防假分母。

### ② 「自画」与 `#M46` detach 豁免的边界 ⇒ **不冲突，理由在豁免表自己的原文里**

`figma-data/audit-allowlist/acceptance-not-machine-checkable.json` 里 `#M46` 那条 `reason` 逐字：

> 「某节点现在是 INSTANCE 还是已 detach 的 FRAME，在 payload 里**可读**（`scripts/mockup-rules/`
> 正在吃这份 payload），但『detach 范围是否最小必要』需要『必要范围』这个输入，而它不落盘
> ⇒ **可读的那一半不构成本条断言**」

⇒ 逐字读出来的边界：

| | `#M46` 豁免的 | 本判据判的 |
|---|---|---|
| 断言 | detach 的**范围是否最小必要** | 反馈组件**是不是** instance |
| 需要的输入 | 「必要范围」⇒ ⛔ 不落盘 | 节点 `type` ⇒ **payload 里可读** |
| 对象 | 既有库 instance **表 / row cell** 的结构性变更 | **反馈组件**（`Notification` / `Message`） |

⇒ M46 那句「可读的那一半不构成**本条**断言」的要害在「本条」：对 M41 [3] / M12 [2] 而言，
**可读的那一半恰好就是它们的断言全文**。⇒ ⛔ 不需要 owner，也 ⛔ 不动 M46 那条豁免一个字。

⚠️ **但如实登记一处真张力（附重开条件）**：M46 决策树留了一条「真的需要变更 layout 结构
⇒ 才考虑 detach（range narrow）」的路，而 **M41 [3] 对 dialog 这个对象逐字禁掉了它**
（「非 detach 自建」）。本判据依 M41 字面 ⇒ 一个「按 M46 决策树合法 detach 的 Notification」
会被判红。**重开条件**：若 owner 判定 dialog 也该走 M46 那条 detach 通道 ⇒ 那是扩豁免（C4）
⇒ 届时进队列，⛔ 本轮不替他开。

---

## 2 量具自证（⛔ 探针自己也要有分母 —— 本轮它坏了两次，都是自证抓到的）

| # | 自证项 | 读数 |
|---|---|---|
| **I1** | 遍历总节点数 ≥ 1000，否则 `exit 9` | **302,766** ✅ |
| **I2** | 已知锚点必须命中（上一轮读数逐字给出的自画 dialog 祖先 `… Remove Confirmation …`） | 命中 ✅ |

🔴 **两次自证失败的经过（⛔ 不隐去 —— 它们正是这条纪律要防的东西）**：

1. **第一遍 root 路径猜错** ⇒ 只遍历 **4** 个节点、`exit 9`。真结构是 `raw.file.document`，
   ⛔ 不是 `raw.document`。若没有 I1，这一遍会输出「逐字命中 0 · 违例 0」——
   **一个恒绿的零信息读数，且长得像「今日全合规」**。
2. **第二遍锚点写成了精确相等** ⇒ `exit 9`。真名字是**带后缀**的
   （`M9 · Remove Confirmation — M7 base + Notification dialog overlay`）⇒ 是我的锚点错、
   ⛔ 不是遍历面错。⚠️ 这一条本身也是教训：**自证锚点写太死会给出假的「量具坏了」**。

---

## 3 判据形态（⛔ 钉死，落地后逐字对照）

**判定对象**：payload 里 `name.trim()` 逐字 ∈ `{'Notification', 'Message'}` 的节点。

**probe**：

| probe | 判据 | 依据（逐字） |
|---|---|---|
| **M41/M12-A** | name 逐字 `Notification` 而 `type` ∉ 豁免集 ⇒ 违反 | M41 [3]「必是 TVU `Notification` instance，非 detach 自建」+ M12 [2]「不自画」 |
| **M41/M12-B** | name 逐字 `Message` 而 `type` ∉ 豁免集 ⇒ 违反 | M12 [2]「不自画」（⛔ 与 M41 无关 —— M41 只管 dialog） |

**豁免集** = `{'INSTANCE', 'COMPONENT', 'COMPONENT_SET'}`。

🔴 **`COMPONENT` / `COMPONENT_SET` 那一半是我自己想到的假阳风险，且它今日分母为 0** ——
库文件里 name=`Notification` 的 COMPONENT_SET **就是组件定义本身**，判它「不是 instance」
是把定义侧当使用侧。两段规则逐字管的都是**取用**（「必用 …instance」/「一律取库 variant」）。
⚠️ 现取 4 份 payload 里逐字命中的 type 只有 `FRAME`(3) 与 `INSTANCE`(73) ⇒
**`COMPONENT` 侧命中 0** ⇒ 这个豁免在真 payload 上是一条**恒真断言**。
⇒ 按上一轮新立的纪律「**豁免类断言必须钉住非豁免侧**」，单测必须**同时**给：
豁免侧一个 `COMPONENT`（不报）+ 非豁免侧一个 `FRAME`（报）⇒ 拆掉豁免时豁免侧那条会转红。

**分母 0 的处理**：`scanned === 0` ⇒ 报 `unverified`，⛔ 不报 findings、⛔ 不冒充一次通过
（照 `jira-hyperlink.mjs` 既有形态 —— 一次交付里完全没有反馈组件是**正常**的）。

---

## 4 今日读数（⛔ 本机分母，非闸守 —— `figma-data/mockup/` 被 `.gitignore:29` 排掉，`git ls-files` 为空）

| 侧 | 数 | 明细 |
|---|---:|---|
| **红侧存量（M41/M12-A）** | **3** | 全在 `DtZcMkhNy6qh6jbQQnhreQ.json`，全 `hasComponentId: false`，children 逐字 `FRAME:"Notification_content"` + `FRAME:"comfirm"`；480×161 / 480×182 / 480×182 |
| **红侧存量（M41/M12-B）** | **0** | 逐字命中的 55 个 `Message` **全部**是 INSTANCE ⇒ B 侧今日零信息的绿（前向 fail-closed） |
| **阴性对照（合规）** | **73** | `Message/INSTANCE` 55 + `Notification/INSTANCE` 18 |

⚠️ **与上一轮 G3 读数的差异，如实解释，⛔ 不当矛盾**：上一轮报 `Notification/INSTANCE` **16**、
探针走过 **101,295** 节点；本轮报 **18**、走过 **302,766**。差异原因：上一轮只扫**一份**「丰
payload」，本轮扫全部 4 份 —— 多出的 2 个在 `0054ib0nLmt27bC3QlGDl7.json`
（祖先逐字 `< V4-1495 > CLONE - [Feature Request] …`）。⇒ 两个数都对，口径不同。

🔴 **更正上一轮的一处推断**：它逐字写那 3 个自画 FRAME 的「children 逐字 `Notification_content`
+ `comfirm` —— **拼写错误就是手打的痕迹**」。实测**不成立**：合规 INSTANCE 的 children 是
`content 1` + **`comfirm`** ⇒ **`comfirm` 这个拼写错来自库组件本身**，⛔ 不是手打痕迹。
真正区分自画与合规的 children 差异是 `Notification_content` vs `content 1`。
⚠️ 但判据 ⛔ 不用 children 名做判据（那是代理指标）—— 判据仍是 `type`。

⚠️ **3 处存量的位置要如实说**（读者会问，且它触到 M41 一条正文）：其中 **2 处**祖先逐字是
`variants-row` / `variant-V1 · OFF session` / `backdrop` ⇒ 在 **variants 区**，而 M41 §关键区分
逐字承认「Mockup artifact（design 工作区 / variants 区）可能 2-3 个 dialog variant 并排放 ——
**这是 design tool 用法**」。**但 M41 没有为 variants 区豁免 [3]** —— 它给 variants 区的义务
是 [4]「必标 `artifact / variants reference`，与 user-flow frame 分隔」，⛔ 不是「可以自画」。
⇒ 判据 ⛔ 不豁免 variants 区。第 3 处祖先逐字 `M9 · Remove Confirmation — M7 base +
Notification dialog overlay` ⇒ 在 UX 交付帧内。

---

## 5 为什么这不是重复既有闸（⛔ 亲核，非转述）

`scripts/mockup-rules/library-origin.mjs` **自己逐字登记了这个失明**：

- `:51` 逐字「本规则只看 INSTANCE；手搓按钮（FRAME+TEXT+VECTOR 拼的）**结构性地不在视野内**」
- `:65` 逐字「手搓 FRAME / 自画元素结构性不可见 —— 见 `scripts/lib/mockup-library-origin.mjs` §结构性失明」

⇒ 本判据补的是**既有闸已具名登记的盲区**，⛔ 不是加一层重复。另两个候选也亲核排除：
`library-binding.mjs` 判 M0/M1/M30 · `audit-mockup-html-conformance.mjs` 里那个 `Notification`
是**生成 HTML 产物**的 lint（现取 `:171` / `:202` 判 `form="dialog"` / `confirmText` 用法）。

---

## 6 预注册的落点与算术

| 项 | 值 |
|---|---|
| 判据真源（含 `covers-acceptance` 自陈） | `scripts/audit-mockup-feedback-not-selfdrawn.mjs`（纯函数 `classifyFeedbackSelfDrawn`） |
| 规则模块 | `scripts/mockup-rules/feedback-not-selfdrawn.mjs` |
| 注册表 | `scripts/mockup-rules/index.mjs` ⇒ RULES **14 → 15** |
| 单测 | `tests/audit-mockup-feedback-not-selfdrawn.test.ts`（合成节点树） |
| 棘轮 | `unclassified` **40 → 38** · `gated` **43 → 45** |

**P-A0 · 自陈 ⛔ 不写 `[N]`**（这是**部分覆盖**）：`COVERS_RE` 逐字
`/^\s*\/\/\s*covers-acceptance:\s*(\S+)\s*(?:\[(\d+)\])?\s*$/` ⇒ `[N]` 可选、不写就不核 S4
（闸头注释 `:44` 逐字「不写 `[N]` 就不核（不强制，避免把没准备好的闸逼进假声明）」）。
⚠️ M12 Σ=3 / M41 Σ=4，本判据各只覆盖 **1 条** ⇒ 写 `[3]`/`[4]` 就是**假声明**。
⇒ 自陈里必须逐字列出**未覆盖的那几条**（M12 [1][3] · M41 [1][2][4]），
⛔ 否则这两段会以「gated」的面目掩盖 5 条没人看的核查项 —— 那正是本仓 Q8 那族
「**存在性 ≠ 声明为真**」的病。⚠️ 且 `#M41 [2]`（scrim 数值）⛔ **刻意不进闸** —— 它是 Q11 待拍。

**P-B0 · ⛔ 不许说的话**（落地后自查）：⛔ 不许说「M41 / M12 已守住」（各只覆盖 1/4 与 1/3）·
⛔ 不许说「今日 3 处违例是闸抓到的」（payload 未进 git ⇒ 那是**本机读数**）·
⛔ 不许说「`#M13` 也覆盖了」· ⛔ 不许把 `Message` 侧的 0 读成「B probe 已验证」。

---

## 7 造故障清单 + **预测**（⛔ 绿灯不算证据；预测写在造之前）

⚠️ 本仓纪律：**预测红侧条数时先问「谁的前置条件被这个故障挡住了」** ——
上一轮两批各偏低一次（3→6 · 2→4），都是因为漏算了「被挡住前置条件的**下游**用例」。

| # | 造什么 | **预测** | 「谁的前置条件被挡住」自问 |
|---|---|---|---|
| **F-N1** | 把「逐字相等」放宽成 `includes` | 真 payload 违例 **3 → 76**（假阳 +73）；单测侧转红的是**全部词族阴性对照** | 挡住的是「这个 name 不该进判定面」这个前提 ⇒ 只影响阴性对照类用例，⛔ 不影响正向违例用例（它们仍红）。⇒ 预测 = 词族阴性对照条数 |
| **F-N2** | 拆掉 `COMPONENT`/`COMPONENT_SET` 豁免 | **恰好 1 条**转红（豁免侧那条 COMPONENT 阴性对照）；非豁免侧那条 FRAME 仍红 ⇒ 证明豁免**双侧都有牙** | 挡住的只是「定义侧不算取用」这一个前提；`scanned` 计数类断言**也会变**（COMPONENT 那个节点从「命中但豁免」变「命中且违例」）⇒ ⚠️ 若有断言 `violations.length` 的用例，它也会红 ⇒ 预测**上调到 1–2 条**，落地时数清 |
| **F-N3** | 把自陈 target 改成不存在的段 id | `EXIT=1` · `[S3]` 逐字点出那一行并要求删行 | — |
| **F-N4** | 删掉一条 `covers-acceptance` 自陈 | `EXIT=1` · `[S2] unclassified 39 > BASELINE 38（+1）` + 闸自印「⛔ 别改 BASELINE 放行」 | — |

⛔ **造故障之前先验注入真落盘了**（上一轮 F-D 第一遍 perl 转义没生效、目标串原样未动，
那个 `EXIT=0` 是假绿）⇒ 一律用 **node 精确替换 + 「找不到目标串就 exit 9」的前置断言**。

**还原后必须**：逐字 `diff`（`cmp EXIT=0`）确认零残留。

---

## 8 必跑闸 + 回归基线

`acceptance-gate-coverage` · `stale-anchors` · `rule-inventory` · `doc-shape` ·
`gate-mount-declaration` · `rule-load-map` + 全量 `pnpm test`（基线 **3303 passed**）。

⚠️ Σ 纪律：改规则正文**只加缩进续行**，⛔ 不加顶层条、⛔ 不往顶层条里加 `·`，否则 S4 当场红。
⇒ **本批不改规则正文一个字**（判据串已在活源里）⇒ Σ 应**零变化**。

---

## 9 ✅ 落地回填（2026-09-08 · DS 提交见变更日志）

### 9.1 实测读数（⛔ 全部单跑、不带管道读 `$?`）

| 项 | 预注册预测 | 实测 |
|---|---|---|
| `unclassified` | 40 → 38 | **40 → 38** ✅ |
| `gated` | 43 → 45 | **43 → 45** ✅ |
| 引擎规则条数（`--list-rules` 现算） | 14 → 15 | **15 条**，`feedback-not-selfdrawn` 在列 ✅ |
| 真 payload `scanned` / `violations` | 76 / 3（A 3 · B 0） | **76 / 3**（A 3 · B 0），`byType` = INSTANCE 73 · FRAME 3 ✅ |
| 六条必跑闸 | 全 0 | 全 **EXIT=0** ✅ |
| 全量 `pnpm test` | 3303 + 24 = 3327 | **3327 passed** / 0 failed（14 skipped）✅ |
| Σ 变化 | 0（不改规则正文） | **0** —— `[S4]` 未触发 ✅ |

### 9.2 造故障四次（⛔ 绿灯不算证据；每次注入都先验落盘）

| # | 造什么 | 预注册预测 | **造前修正预测** | 实测 |
|---|---|---|---|---|
| **F-N1** | 逐字相等 ⇒ `includes` | 「词族阴性对照条数」≈6 | **13** | **恰好 13 条转红**，逐条与修正清单一致、零误伤；真 payload `scanned 76→817` · 违例 `3→76` |
| **F-N2** | 拆掉 `COMPONENT`/`COMPONENT_SET` 豁免 | 「1–2 条，落地时数清」 | **3** | **恰好 3 条**；其中「双侧」那条转红 ⇒ **豁免侧真有牙** |
| **F-N3** | 自陈 target 改成不存在的段 | `[S3]` 点名 | — | `EXIT=1` · `[S3]` 逐字点名文件 + `#M12-NOPE`「活源里没有这个 Acceptance 段」⚠️ **`[S2]` 也红**（见 9.3-③） |
| **F-N4** | 删掉 `#M41` 那行自陈 | `[S2]` 超基线 | — | `EXIT=1` · `[S2] unclassified 39 > BASELINE 38（+1）` + 闸自印「⛔ 别改 BASELINE 放行」；**`[S3]` 不红** ⇒ 两次故障各自点名不同 check |

四次还原后 `cmp` 均 **EXIT=0**，并逐字 `grep` 确认零残留
（`FEEDBACK_NAMES.has(name)` 1 处 · `includes(w)` 0 处 · `covers-acceptance:` 2 行）。

### 9.3 🔴 预注册没预见到的（⛔ 逐条如实登记）

**① 两条造故障的预测都偏低，根因是同一个：预注册那一栏里我没把 helper 自己算进去。**
`selfDrawnDialog()` 这个测试 helper 的 children 逐字含 `Notification_content` ——
放宽成 `includes` 后**子节点自己也进判定面** ⇒ 凡是用到这个 helper 的用例（7 条）全部转红，
而预注册只算了「纯词族阴性对照」那 6 条。⚠️ 修正是在造故障**之前**做的（推演出 13，实测 13），
但那不改变一件事：**预注册那一栏当时是错的**。
⇒ 一般性教训（第三次同型，前两批各一次 3→6 · 2→4）：
**「谁的前置条件被这个故障挡住了」这一问要连测试 helper 一起问** ——
故障注在判定面上时，凡是**构造判定对象的工具**都可能顺带被改变。

**② 那一问我只对 F-N1/F-N2 做了，F-N3/F-N4 漏做 ⇒ F-N3 实际多红一个 check。**
F-N3 改坏自陈 target ⇒ 不只 `[S3]` 点名，`#M12` 还会**退回 `unclassified`** ⇒ `[S2]` 一起红。
⛔ 不是缺陷（两个 check 各自说的是对的事），但它说明这一问该**逐条都问**，
⛔ 不是只对「像是会有连锁反应」的那几条问。

**③ 探针自己坏了两次，都是 I1/I2 自证抓到的。**
第一遍 root 路径猜错（真结构是 `raw.file.document`）⇒ 只遍历 **4** 个节点；
若没有 I1 那道 `exit 9`，它会输出「命中 0 · 违例 0」——
**一个恒绿的零信息读数，且长得像「今日全合规」**。
第二遍是**自证锚点自己写错**（写成精确相等，而真名字带后缀）⇒ 假报「量具坏了」。
⇒ 补一条纪律：**自证锚点写太死会给出假的「量具坏了」** —— 锚点要用最稳的那一段子串。

**④ 注入器的落盘断言在「新串包含旧串」时会假报失败。**
F-N3 把 `#M12` 换成 `#M12-NOPE`，而「旧串必须不在文件里」这个检查因子串关系永远不满足
⇒ `exit 9`，但注入**其实已经落盘**（`grep` 确认 `:10` 已是 `#M12-NOPE`）。
⚠️ 这是量具**过严**，方向偏保守（假报失败，⛔ 不会给出假绿）⇒ 本轮照实继续，登记不改。
⛔ 但别把它读成「注入器可靠」—— 它这一次恰好错在安全的一侧。

**⑤ F-N1 顺带暴露一个原设计里看不见的耦合**：放宽后那 73 处假阳**全部落进 probe B**
（`byProbe` 实测 `M41/M12-B: 73` · `A: 3`），因为 probe 分派用的是 `name === 'Notification'`
这个**精确**判断 ⇒ `Notification_content` 这类本该归 A 族的假阳被错分成 B（`Message` 族）。
⇒ 这说明「判定面收窄」与「probe 分派」共用同一个精确匹配假设：**收窄那一处被放宽，
分派也会跟着错**。⛔ 不改（逐字相等是判据本体），但登记这个耦合。

**⑥ 单测有一条期望是我写错的（⛔ 不是实现错）**：祖先链嵌套顺序 —— `i=0` 是最内层，
所以最近 3 层是 `L2/L1/L0`，我原写 `L3/L2/L1`。跑出来才发现，改的是**测试期望**。
⇒ 与「先把缺陷跑出来再改」的反向提醒配套：**红了先问「是判据错还是断言错」**。

### 9.4 🔴 更正上一轮（DS `9834b949`）留下的三处读数（⛔ 不是矛盾，逐条给口径）

| # | 上一轮逐字写的 | 本轮实测 | 差异原因 |
|---|---|---|---|
| 1 | `Notification/INSTANCE` **16**，探针走过 **101,295** 节点 | **18**，走过 **302,766** | 上一轮只扫**一份**「丰 payload」，本轮扫全部 4 份 ⇒ 多出的 2 个在 `0054ib0nLmt27bC3QlGDl7.json`（祖先逐字 `< V4-1495 > CLONE - [Feature Request] …`）。**两个数都对，口径不同** |
| 2 | 3 个自画 FRAME 的 children 里「**拼写错误（`comfirm`）就是手打的痕迹**」 | **不成立** —— 合规 INSTANCE 的 children 也是 `content 1` + **`comfirm`** ⇒ `comfirm` 来自**库组件本身** | 真正区分自画与合规的 children 差异是 `Notification_content` vs `content 1`。⚠️ 但判据 ⛔ 不用 children 名（那是代理指标），判据是 `type` |
| 3 | 污染源清单「`Notification_content` 31 · `Notification Settings` 1 · `Notification --> Flow_text` 2」 | 只覆盖 `Notification` 词族；**最大污染源整片没提** —— `Message` 词族的 `icon/Message/*` 图标实例约 **668 处** | 上一轮没量 `Message` 那一半。⇒ 它咬人的方式不是假阳（它们是 INSTANCE）而是**假分母**（`scanned` 放大 10.7 倍 ⇒ 合规率 96% 假涨到 91%） |

### 9.5 ⛔ 本批不能说的话（自查已过）

- ⛔ 不许说「`#M41` / `#M12` 已守住」—— 各只覆盖 **1/4** 与 **1/3**，未覆盖的 5 条逐条列在判据头注释里
- ⛔ 不许说「今日 3 处违例是闸抓到的」—— `figma-data/mockup/` 被 `.gitignore:29` 排掉、
  `git ls-files` 为空 ⇒ 那是**一次本机读数**，牙只在合成节点树的 24 条单测上
- ⛔ 不许说「`Message` 侧（probe B）已验证」—— 它现取违例 **0**，是**零信息的绿**（前向 fail-closed）
- ⛔ 不许说「`#M13` 也覆盖了」—— 它 [2] 没有「不自画」三个字
- ⛔ 不许说「B2 批做完了」—— B2 是 **37** 段，本批 2 段，累计 **3** 段
