# Q1 · 那 48 段 `unclassified` Acceptance 的**逐段裁定**（落盘版）

> 本文件存在的唯一理由：**上一轮声称做完的这份裁定没有落盘**，于是「已判」不可复核、必须重做。
> ⛔ 别再只把裁定留在对话里。每段都写出「**会让它判红的具体输入**」——
> 没有红输入的那一行不算裁定，只算印象。

---

## 0 先把债说清楚（⛔ 不是背景介绍，是这份文件的验收条件）

`docs/2026-09-07-q1-step2-batch1-preregistration.md` **第 26 行逐字**承诺交付
`docs/2026-09-07-q1-unclassified-51-classification.md`。**亲验：那个文件不存在。**

```
lab 仓 ls docs/2026-09-07-q1-unclassified-51-classification.md
  ⇒ No such file or directory（2026-09-08 现取）
```

⚠️ 判据刻意写成**点名那个具体文件名**，⛔ 不写 `ls docs/*.md | grep classification`
—— 后者在本文件建好之后就会命中本文件自己，于是这条读数**永远为真**、不可复核。
（同族：本仓已登记的「报警不能读自己写的值」。）

⇒ 上一轮承诺的落盘物**本身又没落盘**，只留下聚合数。这是同一个病的**第二次**发作
（第一次是队列 Q1 小节声称 51 段「每条都写出了会让它判红的具体输入」而清单两个仓都没有）。
⇒ 本文件的验收条件不是「有一份文件」，是**48 行里每一行都有一个可复核的红输入**。

⚠️ **文件名两处与交接字面不同，都是刻意的**：
1. 日期用 **09-08**（本文件的创建日）。仓内既有范式是「日期 = 创建日」
   （`2026-09-07-q5-…` / `2026-09-07-q7-…` 都是那天写的）。写 09-07 会造成
   「这份文件昨天就有了」的假象 —— 而昨天恰恰没有，那正是本轮要还的债。
2. 池子用 **48** 不是 51：51 是 Q1-a/Q1-b 落地前的数，现取已是 48。

---

## 1 现取分母（⛔ 非转述，本轮单跑）

```
node scripts/audit-acceptance-gate-coverage.mjs --json
  起手（本文件裁定的那 48 段）  ⇒ gated 35 · nmc 50 · unclassified 48   EXIT=0
  A0 落地后（DS 95112869）      ⇒ gated 37 · nmc 50 · unclassified 46   EXIT=0
```

⚠️ **本文件的 48 是「裁定的分母」，⛔ 不是「此刻的缺口」** —— 后者现取是 **46**。
两者不同是刻意的：这份裁定要能被拿去核对第 4/5/6 章的每一行，
而那 48 行里已有 2 行（`#C7` / `#Delivery`）落地了。⛔ 别把标题里的 48 读成现状。

| 文件 | 段数 |
|---|---:|
| `docs/internal/mockup-conventions.md` | 34 |
| `docs/internal/design-process.md` | 9 |
| `docs/internal/domain-tvu.md` | 5 |
| **合计** | **48** ✅ 与闸自印一致 |

清单由 **import 闸自己导出的 `collectSections` / `collectCovers` / `loadAllowlist` / `classify`** 导出，
⛔ 未重写分类算式（分类口径一动这份裁定就与闸对不上）。

---

## 2 判定面代码（⛔ 这一列比分支列更重要 —— 它决定牙在哪）

| 码 | 判定面 | DS 仓里的真实分母 | 牙在哪 |
|---|---|---|---|
| **P** | Figma live REST payload | fixture `figma-data/mockup/*.json`（4 份，其中 3 份 350–400MB） | 判据纯函数被**单测**守住（`pnpm test` ⇒ pre-commit L8–9 无条件）；真 payload 上跑在 `.claude/hooks/post-figma-write.sh`（L4）。⛔ 引擎不在 pre-commit 上 |
| **H** | handoff / design-record 文本 | DS 仓 **1 份**：`templates/consumer-product/docs/handoffs/_handoff.template.md` | DS 仓守**模板不回退**；⚠️ **但不止于此** —— `templates/consumer-product/.githooks/` 里带着这条闸的**自包含可执行镜像**（parity 测试断言两边判据逐字相同）⇒ **装了 `.githooks` 的消费仓会被真拦**。⛔ 别只说「只守模板」|
| **D** | DS 仓内文档 / 源码文本 | 仓内真实文件 | **牙最真的一类**（不依赖凭据、不依赖消费仓） |
| **X** | 不落盘 | — | 行为 / prompt / 目测 / 外部 API / 需要一个不存在的输入 |

---

## 3 成本档（⛔ 排序依据是这一列，不是「重要程度」）

| 档 | 含义 | 段数 |
|---|---|---:|
| **A0** | **判据已在跑，只差一行自陈** ⇒ 零新代码 | **2** |
| **B1** | 落既有闸的既有机制（`SECTIONS` 加一行 + 模板补段），照第一批范式 | **5** |
| **B2** | 要写新纯函数判据 + 规则模块 + 单测 | **37** |
| **B3** | 要**先量分母**才能定判据（⛔ 不许先写闸后量） | **4** |

⚠️ **这四个数被更正过两次，两次都是我手点错的** —— 第一次手写成 `B1 9 / B2 34`，
程序化计数后是 `8 / 35`；随后落 B1 批时**回活源逐条核判据串**，又发现 4 段的规则原文
根本没有引号圈定的段名（不符合那条闸的形态）、而 `#M36` 被我漏判 ⇒ 终值 **`2 / 5 / 37 / 4`**。
详见 [`2026-09-08-q1-b1-batch-preregistration.md`](2026-09-08-q1-b1-batch-preregistration.md) §0。
⇒ **「档」列是我读完原文后的归类，⛔ 不是活源** —— 拿它去动手之前必须回闸的头注释再核一次。
复核命令（判据 = 逐段表行的第 3、4 列都是纯数字，⛔ 别用「行首是数字」，那会把第 7 章那张表也算进来）：

```bash
node -e "
const t=require('fs').readFileSync('docs/2026-09-08-q1-unclassified-48-classification.md','utf8');
const rows=t.split('\n').filter(l=>{const c=l.split('|').map(s=>s.trim());
  return /^\|\s*\d+\s*\|/.test(l) && /^\d+\$/.test(c[3]) && /^\d+\$/.test(c[4])});
const tally={}; for(const r of rows){const c=r.split('|').map(s=>s.trim());
  const k=(c[c.length-2].match(/A0|B1|B2|B3/)||['?'])[0]; tally[k]=(tally[k]||0)+1}
console.log(rows.length, JSON.stringify(tally))"
# ⇒ 48 {\"B2\":37,\"B3\":4,\"B1\":5,\"A0\":2}
```

⇒ **A0 那 2 条是本轮该先落的**：证据最硬（判据已在 L4 上跑）、成本为零、且各降 1 格棘轮。

### ⚠️ `L` 列是会漂的 —— 而**本轮自己就把 32 个顶漂了**

给 `#C7` 的 Acceptance 补那句指针（1 行正文 + 1 空行）之后，
`mockup-conventions.md` 里 **L ≥ 852 的每一段行号全部 +2**。
⇒ 表里的 `L` 只是**取数那一刻**的快照，⛔ 别拿它当稳定地址。
稳定地址是**段 id**（`#M23.12` 这种，闸的 `slugOfHeading` 保证它与「文件里别处插了什么」无关）。

本表落盘前已用活源逐段程序化对账过（48 行 L/Σ 全部与闸的 `classify()` 输出一致）。
以后要复核就重跑对账，⛔ 不要相信这一列的绝对值：

```bash
node scripts/audit-acceptance-gate-coverage.mjs --list   # report-only, exit 0
```

---

## 4 逐段裁定 · `design-process.md`（9 段）

| # | 段 id | L | Σ | 判定面 | **会让它判红的具体输入** | 分支 | 档 |
|---|---|---:|---:|---|---|---|---|
| 1 | `#参考物落地（Reference` | 181 | 5 | P+H | page 内有名为 `REFERENCE` 的 SECTION，其子树全部 TEXT 的 `characters` 都不含 `node-id` 形态串、且无一 range 带 `hyperlink` ⇒ 红 | `gate` | B2 |
| 2 | `#Step~2` | 718 | 7 | P（[3] 三小项之一）+X | PRD / 交付卡内 TEXT 出现字母后缀段号形态 `§\d+[a-z]`（如 `§4b`）⇒ 红。⛔ [1][4][5] 是行为 / prompt ⇒ 不落盘 | `gate`（窄） | B2 |
| 3 | `#Canonical` | 763 | 3 | P（[1]）+X | ~~存在名为 `Canonical Terms` 的表而行数 < 3 ⇒ 红。⛔ [2] 需要「同义词」这个输入，它不落盘~~ 🔴 **2026-09-08 两处更正**：① **前件够不着** —— 4 份 payload 里 `Canonical Terms` 字面 0、表头列名 0、`templates/` 0 ⇒ 上闸恒绿零信息 ② [2] 要的同义词清单**就是表的第 4 列 `不准用的同义词`**，⇒ 真正够不着的是**表本身**、不是同义词 ⇒ 分支改 `nmc`（登记属 C4 ⇒ **Q1-d**） | ~~`gate`~~ `nmc` | B3 ⇒ **⏳ Q1-d** |
| 4 | `#⚠️` | 891 | 3 | P+H | 枚举清单里出现 `🔴` 而同一交付里无 `priority gap` 串 ⇒ 红 | `gate`（窄） | B2 |
| 5 | `#User` | 971 | 9 | P | Journey 卡内出现一个 TEXT 恰为 `OUT`，或 `OUT` 后无 `—`/`:` 依据 ⇒ 红（[4] 逐字「没有裸 `OUT`」）| `gate` | B2 |
| 6 | `#M16.1` | 1223 | 6 | P | deliverable 内 frame 名形如 `M5` 而无 `·` + state 词后缀 ⇒ 红（[2] 逐字「不允许只标 frame 编号」）| `gate` | B2 |
| 7 | `#M21.1` | 1323 | 3 | H | 模板缺 `derive from` / `from-scratch` 段名 ⇒ 红。**与第一批 3 段判据形态完全相同**（引号圈一个必须落盘的段名）| `gate` | **B1** |
| 8 | `#Scope` | 1587 | 3 | P+H | 交付 Section 内有 `visible:false` 的 sibling 节点而 handoff 无对应 confirm 声明 ⇒ 红。⚠️「与 clone source 一致」需要 clone source id，它落在 handoff（M21.1 [1]）⇒ 真判据跨 P+H | `gate`（窄） | B2 |
| 9 | `#Delivery` | 1637 | 5 | **D**（[5]）+X | 交付物 md 正文命中 `TBD`/`待 confirm`/`待…拍板`/`TODO`/`(?)`/`Open questions`/`需进一步讨论` ⇒ 红 | `gate` | **A0** ✅ |

### 🔴 第 9 条是本轮实测出来的 A0 —— **闸早就在 L4 上跑，一条自陈都没有**

`scripts/audit-deliverable-open-questions.mjs` 头注释第 4 行逐字：
「未决占位（TBD / 待 confirm / 待…拍板 / TODO / (?) / "Open questions" / 需进一步讨论）」，
`docs/meta-rules.md:820` 逐字把它登记为 **L4（pre-commit gate）**。
而 `#Delivery` 段第 [5] 条逐字点名的黑名单**与它逐字同源**（`§ No Open Questions / 触发器 P`）。
⇒ **不是「要建闸」，是「已有闸没登记覆盖」** —— 与 Q9/S5 那条
「判据所需输入本闸早就在算，只是没被当判据用」是同族。

---

## 5 逐段裁定 · `domain-tvu.md`（5 段）

| # | 段 id | L | Σ | 判定面 | **会让它判红的具体输入** | 分支 | 档 |
|---|---|---:|---:|---|---|---|---|
| 10 | `#M10` | 129 | 3 | P | 一个 list row 组件的 `state` 轴只有 `{Active, Inactive}` 两值（缺 `Inactive-Idle` / `Inactive-NeverStarted`）⇒ 红。近亲范式 = `mockup-rules/variant-axis.mjs` | `gate`（窄） | B2 |
| 11 | `#M11` | 154 | 3 | **D**（[1]）+P | `domain-tvu.md` 的 M11 段内没有三列（icon + 数值色 + token）映射表 ⇒ 红 | `gate`（窄） | B2 |
| 12 | `#M12` | 179 | 3 | P（[2]） | ~~设备谱系 frame 内出现 web 谱系的 `Notification` instance ⇒ 红~~ 🔴 **2026-09-08 推翻，见下方框**。更正后的红输入：**交付里出现名为 `Message`/`Notification` 但 type ∉ {`INSTANCE`,`COMPONENT`,`COMPONENT_SET`} 的节点（= 自画/已 detach）⇒ 红** | `gate`（窄） | **B2 ✅ 已落地**（与 `#M41` 共用一条判据；⚠️ **只覆盖 [2] 的「不自画」那一半**，Σ=3 ⇒ 自陈刻意不写 `[N]`） |
| 13 | `#M13` | 194 | 3 | P（[2]） | ~~同 #M12 ⇒ 与 #M12 共用一条判据~~ 🔴 **2026-09-08 更正：⛔ 不共用** —— `#M13` [2] 逐字只说「用对应谱系反馈组件」，**没有「不自画」三个字** ⇒ 按仓规「判据串逐字取自活源」，它不能靠那条判据算覆盖 | `gate`（窄） | B2 |
| 14 | `#M17.1` | 253 | 5 | P（[3][4]） | LCD 设置页底栏出现名为 `Back` 的按钮 ⇒ 红（[3] 逐字「底栏没有 `Back` 按钮」）| `gate` | B2 |

### 🔴 2026-09-08 · 第 12 / 13 条那条红输入**被活源推翻** —— ⛔ 别再照上面划掉的字面动手

| # | 读数（本轮单跑） | 它否掉了什么 |
|---|---|---|
| **G1** | `domain-tvu.md:170` 逐字「设备侧…走 `Message` set…web/SaaS 侧走 `Notification` set。**勿混用两套库**」—— **但紧接着 `:171` 逐字**「`Message` 无按钮…若前进路径需一键动作或用户决策…**须升级到带按钮的 `Notification`（alert / dialog / pop confirm）或 `Popup Box`**」 | ⇒ 「设备帧内有 `Notification` ⇒ 红」会**判红一个规则明确要求的做法**。⛔ 这条判据不能上 |
| **G2** | §M33 [1] 逐字只给了**设备** frame 的识别形态（「name 命中设备 mockup 模式如 `S<N>` / `M<N>` / 设备屏幕 frame」）——**没有 web frame 的形态** | ⇒ 反方向（web 帧里出现 `Message`，`:171` 对它没给豁免）**判定面缺一块** |
| **G3** | 实测（丰 payload，探针走过 **101,295** 节点）：`Message/INSTANCE` **55** · `Notification/INSTANCE` **16** ⇒ 共 71 个，其中**落在设备谱系帧内的 = 0** | ⇒ 谱系那个方向**今日分母 = 0 ⇒ 恒绿 ⇒ 零信息** |
| **G4** | 同一次实测另有 **3 个**名为 `Notification` 而 type 是 **`FRAME`** 的节点（children 逐字 `FRAME:"Notification_content"` + `FRAME:"comfirm"` —— 拼写错误就是手打的痕迹；480×161 / 480×182 / 480×182；`4598:4676` 的祖先逐字 `M9 · Remove Confirmation — M7 base + Notification dialog overlay`） | ⇒ 这是**自画 / 已 detach**，`:169` 逐字「反馈控件一律取库 variant **不自画**」+ [2] 逐字含「不自画」⇒ **这才是可 falsify 且分母非空的那一半** |

🔴 **⇒ 真正的「一条判据解掉多段」分组是 `#M41` + `#M12`，⛔ 不是 `#M12` + `#M13`**：
第 39 条（`#M41`）的红输入逐字就是「modal-overlay 帧里 dialog 不是 TVU `Notification`
instance（**已 detach**）⇒ 红」—— 与 G4 是**同一批节点**。

⚠️ **落地前还要先定两件事**（⛔ 所以那一轮没落它，理由是落点未定、不是难做）：
① 判定对象要从「名字像」收窄 —— 实测词族污染源：`Notification_content` **31 处** ·
`Notification Settings` **1 处（那是功能名，不是反馈组件）** · `Notification --> Flow_text` **2 处**；
② 「自画」与 **M46 已登记的 detach 豁免**的边界要先定（Q1-c 批的 6 条豁免里就有 M46）。

##### ✅ 2026-09-08 · 两件都已定完并落地 —— 读数与两侧证据在 [B2 批第 2 组预注册](2026-09-08-q1-b2-batch2-preregistration.md)

**① 收窄成 `name.trim()` 逐字相等**（⛔ 不用 `includes`）。造故障 F-N1 实测的硬数：
逐字命中 **76** 个节点（违例 **3**）· 放宽成 `includes` 命中 **817** 个（违例 **76** ⇒ 假阳 **+73**）。
🔴 **同时更正上面那份污染源清单** —— 它只覆盖 `Notification` 词族，**最大污染源整片没提**：
`Message` 词族的 `icon/Message/*` 图标实例约 **668 处**（`icon/Message/Help 1` 单项就 445）。
⚠️ 它们咬人的方式**不是假阳**（那些都是 INSTANCE ⇒ 不变违例），而是**假分母** ——
`scanned` 放大 10.7 倍 ⇒ 「合规率」会从 96% 假涨到 91%。⇒ 收窄不只防假阳，也防假分母。

**② 边界从活源直接读出来了，⛔ 不需 owner** —— 豁免表 `#M46` 那条 `reason` 自己逐字写着
「某节点现在是 INSTANCE 还是已 detach 的 FRAME，在 payload 里**可读**…但『detach 范围是否
最小必要』需要『必要范围』这个输入，而它不落盘 ⇒ **可读的那一半不构成本条断言**」。
要害在「**本条**」：M46 断言的是**范围**，M41 [3] / M12 [2] 断言的是**是不是 instance**
⇒ 对后两者而言，可读的那一半恰好就是断言全文。⇒ M46 那条豁免**一个字未动**。
🔴 如实登记一处真张力 + 重开条件：M46 决策树留了「真需变更 layout 结构 ⇒ 才考虑 detach」
这条路，而 M41 [3] 对 dialog 逐字禁掉了它 ⇒ 一个「按 M46 合法 detach 的 Notification」
会被判红。判据依 M41 字面；若 owner 判定 dialog 也该走那条通道 ⇒ 那是扩豁免（C4）⇒ 进队列。

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

⚠️ **G3 那个 16 与本轮的 18 不矛盾**：G3 只扫一份「丰 payload」（101,295 节点），
本轮扫全部 4 份（302,766 节点）⇒ 多出的 2 个在 `0054ib0nLmt27bC3QlGDl7.json`。两个数口径不同。
已实测**未被既有闸覆盖**（`library-origin` 判的是已存在 INSTANCE 的**来源库** ·
`library-binding` 判 M0/M1/M30 · `audit-mockup-html-conformance` 里那个 `Notification`
是**生成 HTML 产物**的 lint）⇒ 是真缺口。

⚠️ **#M17.1 [2] 的阈值不在 DS 仓** —— 逐字「行高等取值以**项目 spec §1 登记值**为准」
⇒ 那一条的判定面在消费仓，DS 侧只能判 [3][4][5]。⛔ 别把它读成「M17.1 全覆盖」。
父段 `#M17` 已 gated 于 `audit-mockup-geometry-consistency.mjs [7]`。

---

## 6 逐段裁定 · `mockup-conventions.md`（34 段）

| # | 段 id | L | Σ | 判定面 | **会让它判红的具体输入** | 分支 | 档 |
|---|---|---:|---:|---|---|---|---|
| 15 | `#C6` | 497 | 3 | P（[3]）+X | 新建的带色节点既无 `boundVariables` 也无 `fillStyleId`、且填了字面 hex ⇒ 红。⛔ [1]（已跑 `get_libraries`）、[2]（选了哪个 API）是行为，产物里只看得到结果 | `gate`（窄） | B2 |
| 16 | `#C7` | 516 | 3 | P（[1][2]） | 手建 TEXT 的 `styles.text` 缺失（裸 `fontSize`）或 fill 未绑 Color Variable ⇒ 红 | `gate` | **A0** ✅ |
| 17 | `#M23.12` | 854 | 3 | P | UX / PRD 卡 frame 的 `primaryAxisSizingMode !== 'AUTO'`（手设固定高）⇒ 红（[2] 逐字给了字段）| `gate` | B2 |
| 18 | `#M23.12~2` | 866 | 2 | P | 同一 feature Section 内 PRD 卡宽 ≠ UX Delivery 卡宽 ≠ User Journey 卡宽 ⇒ 红（[2] 逐字「同一数值」）| `gate` | B2 |
| 19 | `#M23.14~2` | 938 | 3 | P | PRD / 交付卡 title 下方无 `YYYY-MM-DD` 形态的 cyan meta 行 ⇒ 红（[3]，2026-07-13 owner 纠正回流）| `gate` | B2 |
| 20 | `#M23.18` | 987 | 0 | ~~H~~ **X** | ~~M48 self-check 清单里缺「画布主题探测结果」那一行 ⇒ 红~~ 🔴 **2026-09-08 更正：判定面是 X 不落盘，⛔ 我原写的 H 是错的** —— `backlog.md:203` 逐字「M48 …产物**落 Figma 侧或对话侧**」+ `:204`「零存在性闸」；亲跑其判据 EXIT=1（阳性对照 EXIT=0）；`画布主题探测结果` 全仓只命中规则自己那一行。⚠️ 可探的那一半：`detectFrameTheme` 的 luma 算法在 payload 侧**可算**，够不着的是「那句声明有没有写进起手清单」 ⇒ 分支改 `nmc`（登记属 C4 ⇒ **Q1-d**） | ~~`gate`~~ `nmc` | B3 ⇒ **⏳ Q1-d** |
| 21 | `` #`Jira `` | 1143 | 0 | P | `Jira requirement` 实例内 issue-key TEXT 的 range 无 `hyperlink` ⇒ 红（Acceptance 逐字 `getRangeHyperlink(0,len)` 非 null）· ⚠️ **判据必须读 `node.style.hyperlink`，⛔ 不是只读 `styleOverrideTable`**，见下方框 | `gate` | **B2 ✅ 已落地 DS `9834b949`** |
| 22 | `#M23.8.1` | 1166 | 0 | P+X | ~~交付物 TEXT 内出现 `FB-\d+`/`V4-\d+`/`SEC-\d+` 形态而该 range 无 `hyperlink` ⇒ 红~~ 🔴 **2026-09-08 两处更正**：① 闭集前缀会让**分母静默变小**（造故障实测 `scanned` 109 → 78，缩 28% 而违例仍 0）⇒ 改通用 project-key 形态 ② ~~现取有 **55 处存量**（「来源/出处」段 17 · 散文 38）⇒ **要棘轮设计**~~ 🔴 **2026-09-08 再更正：那两句都不对** —— 宽形态实测 **71** 处，而**可落那一支只有 7 处**（3 无链 + 4 链错）⇒ **⛔ 不需要棘轮**。射程靠**上下文收窄**（闭集逐字取自规则第 5 款「来源/出处/Source/讨论结论」），⛔ 不靠 ticket 形态 —— 射程外那 82 个 range 里有形态上排不掉的假阳（`Q2-1` 是设计探索的问题编号 · `PID-1001` 是 UI 文案里的进程 ID），而真 project key 里 `V4`（74 处）与 `TM3` 自己就含数字。⛔「列全需求链」需 Jira API ⇒ 仍不落盘 | `gate` | **B2 ✅ 已落地 DS `495212dd`**（⚠️ 只覆盖 Acceptance 第 2 句在第 5 款射程内那一段 ⇒ 自陈不写 `[N]`） |
| 23 | `#I2` | 1324 | 4 | H | handoff 机检块只出现一个笼统 `overlap`、未同时出现 `sectionInternalOverlap` 与 `sectionToSectionOverlap` 两个具名数 ⇒ 红 | `gate` | **B1** |
| 24 | `#M23.6` | 1645 | 3 | P | 连线标签的可见字形外框距其目标段 > 60px ⇒ 红（[1] 逐字「**判据**：≤ 60px」）| `gate` | B2 |
| 25 | `#M23.9` | 1734 | 5 | P | state-preview 元素 `absoluteBoundingBox` 与产品 frame `absoluteBoundingBox` 重叠 ⇒ 红（[1]）| `gate` | B2 |
| 26 | `#(B)` | 1822 | 3 | P | UX 卡内 TEXT 含 `this round` / `shipped MM-DD` / `(YYYY-MM-DD)` 充当章节骨架，或含「取代此前…」「此前只有…」「原为…」⇒ 红（黑名单逐字在原文）| `gate` | B2 |
| 27 | `#M23.11` | 1835 | 2 | P | 交付 Section 内 UX 卡 > 6 张，或出现名为 `Persona` / `Out-of-scope` / `Future plans` 的卡 ⇒ 红（[2] 逐字给了 6 个具名卡 + 3 个禁入）| `gate` | B2 |
| 28 | `#M23.7` | 1865 | 3 | P | state-label 有 `Invariants` 段但段内无 `M-?\d+` 形态规则号 ⇒ 红（[3] 逐字「不允许只口语描述」）| `gate` | B2 |
| 29 | `#M31` | 1898 | 3 | P | product frame 内存在 `layoutMode === 'NONE'` 的 FRAME 且不属三类排除（顶层 viewport / overlay-annotation / library instance 内部）⇒ 红 | `gate` | B2 |
| 30 | `#M32` | 1948 | 3 | H+P | 模板缺 `Buttons used:` 段 ⇒ 红（[1] 逐字给了整行形态）| `gate` | **B1** |
| 31 | `#M32.3` | 2008 | 4 | H+P | 模板缺 `includeLibraryKeys` 样例段，或 handoff 出现「改用 X 库」字样 ⇒ 红（[2] 逐字「**不得**出现」）| `gate` | B2 |
| 32 | `#M32.4` | 2051 | 4 | P | INSTANCE 已切 `Status=Disabled` 变体而其容器 `opacity < 1` ⇒ 红（[2] 逐字「双重处理 = FAIL」）| `gate` | B2 |
| 33 | `#M33` | 2130 | 3 | P | product frame（name 命中 `S<N>`/`M<N>`）内的 TEXT `fontName.family === 'Noto Sans SC'` ⇒ 红（[1] 逐字给了字段与值）| `gate` | B2 |
| 34 | `#M36` | 2249 | 3 | P+H | file-local component 名不匹配 `MicroApp <Product> <Module>` ⇒ 红（[2] 逐字给了 pattern 与 3 个正例）| `gate` | **B1** |
| 35 | `#M36.1` | 2294 | 4 | H+P | 模板缺 `reused file-local components` 段 ⇒ 红（[4] 逐字点名该段，M36 [3] 亦要求）| `gate` | **B1** |
| 36 | `#M38` | 2463 | 5 | P | selected 列表项 `strokeLeftWeight` ∉ {4} —— 逐字点名 3 / 5 / 6 为违规 ⇒ 红 | `gate` | B2 |
| 37 | `#M-FONT` | 2481 | 3 | P | TEXT 的 `fontSize` ∈ {10,11,13,15,17,19,21} ⇒ 红（[1] 逐字给了算法与闭集）| `gate` | B2 |
| 38 | `#M39` | 2662 | 4 | P（[4] 结果面） | instance 的 TEXT 子节点 `characters` 与主组件不同却无对应 componentProperty（= `findOne + characters` 直改的残迹）⇒ 红 | `gate`（窄） | B2 |
| 39 | `#M41` | 2771 | 4 | P | destructive confirm flow 的 modal-overlay 帧里 dialog 不是 TVU `Notification` instance（已 detach）⇒ 红（[3]）| `gate` ⛔ **[2] 刻意排除** | **B2 ✅ 已落地**（与 `#M12` 共用一条判据；⚠️ 只覆盖 **[3]**，Σ=4 ⇒ 自陈刻意不写 `[N]`；[2] scrim 数值仍是 Q11 待拍） |
| 40 | `#M45` | 2821 | 3 | P（[1][3]）+X | page name 不满足三段式 ⇒ 红。⛔ [2]「FB-id 真实有效（gh / jira API 可查）」判定面是**外部 API** ⇒ 不落仓 | `gate`（窄） | B2 |
| 41 | `#M45~2` | 2859 | 3 | P（[2][3]） | 新 page 不在 `To be confirmed` 分隔符正下方，或无 Jira 时命名不匹配 `<Title EN> YYYYMMDD` ⇒ 红 | `gate` | B2 |
| 42 | `#M44` | 2893 | 3 | P（[2]）+X | PRD「关键元素 Key Elements」段缺某个新 label 的 EN/ZH + 后端字段声明 ⇒ 红。⛔ [3]「后端服务名」需要一份内部代号清单，它**不存在** | `gate`（窄） | B2 |
| 43 | `#M43` | 2974 | 6 | P+D | mockup 缺「截断态」帧 / tooltip 不是 library `tooltip/default` ⇒ 红。⛔ [5][6] 是 code 镜像 ⇒ 与 Q5 同处境（DS `src/` 恒绿）| `gate` | B2 |
| 44 | `#M43.2` | 3027 | 4 | H | 模板缺「哪些列做了 audit + audit 结果」声明段 ⇒ 红（[1] 那个「**或**」的后半支是可机检的那一支）| `gate`（窄） | B2 |
| 45 | `#M42.2` | 3140 | 4 | H+P | 模板缺 `direct children enumeration` 结果段 ⇒ 红（[1]）。⚠️ [4]「无沿用源语义的图层名」只能用词族冲突当**代理** | `gate` | B2 |
| 46 | `#M47.2~2` | 3320 | 3 | P（[2] 结果面） | TEXT 有非默认 `fontName` 却 `textStyleId` 为空（改完没绑回）⇒ 红。⛔ [1] 是时序、[3] 是目测 | `gate`（窄） | B2 |
| 47 | `#M-DISCIPLINE.SOURCE` | 3385 | 3 | **D** | 正文出现裸 node id / file key / 像素取值表 / 人名，而所在段无「为什么跨产品通用」说明、也无指向项目 repo 的指针 ⇒ 红（[2]）。🔴 **2026-09-08 两处更正**：① `\d+:\d+` 这个形态**假阳率 ≈ 37%**（30 处里 11 处是 `1:1`/`2:1`/`1:2` 比例习语与截断 URL 示例）⇒ 去污后真存量 ≈ **19**，形态必须先收窄 ② `\d+px` 那 **104** 处 ⛔ **不能整片算违例** —— 规则 ② 逐字把「做法、判据、核查项类别、反模式 ⇒ 真源」划在射程外，而本仓大量 px 在判据本体里 ⇒ 假分母 | `gate`（窄） | B3 ⇒ **✅ 2026-09-08 已落地 DS `af89f008`**（形态四候选实测比过；假阳靠具名豁免不靠正则；⚠️ 只覆盖 [2] 的「不许新增」那一半 ⇒ 自陈不写 `[N]`；⛔ `\d+px` 与人名两支明确不做） |
| 48 | `#M-DISCIPLINE.SCOPE` | 3421 | 7 | **D**（[1]）+X | ~~审计报告 md 的标题或首行无显式 scope 声明 ⇒ 红~~ 🔴 **2026-09-08：前件不存在** —— 仓里没有「哪些算清单/审计报告」的定义（`grep '算审计报告\|清单类产出物\|哪些算清单'` **零命中**）。文件名启发式给 34 个/只 4 个合规，**但启发式自己不成立**（收进了安装指南 `CONSUMER_AUDIT_SETUP.md`、`superpowers/plans/*`、设计 spec）⇒ 违例数完全取决于对象集怎么定 ⇒ **与 Q1-b（`#M40`）逐字同型**，需 owner 先定真源措辞。⛔ [2]–[7] 六条仍是方法论纪律、不落盘 | `gate`（窄） | B3 ⇒ **⏳ Q1-e** |

### 🔴 2026-09-08 · 第 21 / 22 条那条 hyperlink 判据的**三个形态差异**（⛔ 照 Acceptance 字面写会整片错）

| # | 差异 | 照字面写会怎样 |
|---|---|---|
| **F1** | `setRangeHyperlink(0, len)` 是**整串**加链 ⇒ REST payload 里落在 `node.style.hyperlink`，**根本不进** `styleOverrideTable`。现取 **109 个** issue-key 节点的链**全部**走 `style`、override 表里 **0 个** | 只读 override 表的判据把 **109 条合规判成违例**。⚠️ **本轮真踩过**：读出「82/82 无链」，差点得出「§M23.8 自 2026-05-27 立规起合规率 0%」—— 靠「这个数太整齐」才回头重测 |
| **F2** | Acceptance 逐字 `{ type: 'URL', **value**: '<jira url>' }` —— 那是 **Plugin API** 的键名；REST payload 里是 **`url`** | 照 Acceptance 抄字段名 ⇒ 取到 `undefined` ⇒ 判据恒真或恒假 |
| **F3** | 第 22 条原提的闭集前缀 `FB\|V4\|SEC` | 造故障实测：分母 `scanned` **109 → 78**（缩 31 / 28%）而**违例仍是 0** ⇒ **分母静默变小、闸照样绿** |

⚠️ **F1/F2 与本文件 §7 第 1 条那个「hyperlink **在** REST payload 里」的读数不矛盾** ——
那一条量的是「**有没有**」（4 份 fixture 命中 258/85/33/8 处），本轮量的是「**从哪个字段取、
键名叫什么**」。⇒ ⛔ 「取得到」不足以写判据。

⚠️ 另一条落地时才发现的：`.gitignore:29` 排掉 `figma-data/mockup/`、`git ls-files` **为空**
⇒ 本文件第 2 章那行「fixture `figma-data/mockup/*.json`（4 份…）」指的是**未进 git 的本机快照**
（`audit-plan-lifecycle.test.ts:504` 逐字称 **1.1 GB**）⇒ **任何单测都不能断言它们**。
⇒ P 类判定面的分母是**本机读数**，牙只能落在合成节点树的单测上。⛔ 别再写「真 fixture 上断言 X」。

### ⛔ 第 39 条（`#M41`）的排除是硬约束，不是偷懒

`#M41` [2] 逐字「该帧 scrim 数值精确（**20% black** + blur 8）」——
**那正是 Q11 待拍的那个值**（M41 说 0.2 / 活源 `--mask-overlay` 是 0.6 / Figma 变量名逐字
`Mask blur8 #000-60%`）。⇒ 给 `#M41` 上闸时**数值判据刻意不进闸**，与 Q5 的 R21
落法逐字一致（R21 只落两个真源都同意的那一半）。⛔ agent 不自裁 C3。

---

## 7 本轮实测推翻的 4 个印象（⛔ 都不是转述，逐条单跑）

| # | 印象 | 实测 | 后果 |
|---|---|---|---|
| 1 | `getStyledTextSegments(['hyperlink'])` 是 **Plugin API** ⇒ hyperlink 在 REST payload 里取不到 ⇒ 相关段判 NMC | **payload 里有** `hyperlink`：4 份 fixture 全部命中（258 / 85 / 33 / 8 处）| `` #`Jira `` 与 `#M23.8.1` 从「不可机检」变 **`gate`**，且**共用一条判据** ⇒ 一条判据解掉 2 段 |
| 2 | `connector.mjs` 已判 §M23.6 ⇒ `#M23.6` 只需补自陈 | 1645 | `#M23.6` 是 **B2**（真要建判据），⛔ 不是零代码 |
| 3 | `typography-icon.mjs` 判 FONT ⇒ 已覆盖 `#M33` 与 `#M-FONT` | 2130 | 两段都是 **B2** |
| 4 | `colors.mjs` 的 C1 判「裸 hex」⇒ 已覆盖 `#M38` [3] / `#M11` [3] | 2463 | 两段的「颜色必绑变量」**未被覆盖** ⇒ A0 候选从 7 条缩到 **2 条** |

⚠️ **第 4 条是本轮最该记住的一次**：我原本要把 5 段标成「零代码补自陈」，
读了活源才发现对象集不同。**「名字像」不等于「覆盖」** ——
`audit-canonical-compliance`（Vue canonical 层 CC-R1..R4）与 `#Canonical`（Canonical Terms 表）、
`audit-claude-design-reference-numbers`（`reference/NN-<slug>.md` 编号）与 `#参考物落地`
也各是**同名不同事**，都实测排除了。

---

## 8 算术对账（⛔ 落地后必须与闸自印一致）

| 步 | 动作 | `unclassified` | `gated` |
|---|---|---:|---:|
| 起手 | — | 48 | 35 |
| ✅ **A0** | `#C7` + `#Delivery` 补自陈（零新代码）· **2026-09-08 已落地 DS `95112869`** | 46 | 37 |
| ✅ **B1** | **5** 段走 `audit-handoff-deliverable-sections.mjs` + 模板补段（4 条判据覆盖 5 段）· **2026-09-08 已落地 DS `70344ccc`** | 41 | 42 |
| ✅ **B2 第 1 段** | `` #`Jira ``（§M23.8）落 `audit-mockup-jira-hyperlink.mjs` · **2026-09-08 已落地 DS `9834b949`** | **40 ← 现状** | **43** |
| B2 余 36 段 | 建纯函数判据 + 模块 + 单测 | 4 | 79 |
| B3 | 4 段先量分母再定判据 | **0** | 83 |

⛔ **上表原先写的 `B1 8 / B2 35 / B3 3` 是错的**（2026-09-08 更正）：那组数是第 3 章
被程序化对账更正**之前**写的。终值是 `A0 2 · B1 5 · B2 37 · B3 4`，
⇒ 正确算术是 `48 − 2 − 5 − 37 − 4 = 0`。⛔ 别再照那三个旧数对账。

**A0 的两侧读数（⛔ 绿灯不算证据）**：

| # | 造什么 | 红侧读数 |
|---|---|---|
| **F1** | 删掉 `#C7` 那行自陈 | `EXIT=1` · `[S2] unclassified 47 > BASELINE 46（+1）` · 闸逐字印「⛔ 别改 BASELINE 放行」 |
| **F2** | 把 `#Delivery [5]` 写成 `[6]` | `EXIT=1` · `[S4]` 逐字「逐字有 **5** 个核查项，而 `scripts/audit-deliverable-open-questions.mjs` 自陈覆盖 **6** 个」 |

两次还原后 `cmp EXIT=0`，闸输出与绿侧基线**逐字一致**（仅 `checkedAt` 差）。
4 条必跑闸全绿；全量 `pnpm test` **3241 passed / 0 failed**（与基线一致）。

**Σ 对账**：48 段 Σ 总和 = **171**；A0 落地后剩 46 段 Σ 总和 = **163**
⇒ 差 **8** = `#C7` 的 3 + `#Delivery` 的 5 ✅

⛔ **`BASELINE_UNCLASSIFIED` 只许收到现取值**，不许为放行而抬（S2 失败信息逐字禁止）。
⛔ **`[N]` 必须等于段内核查项总和 Σ**（本文件每行的 Σ 列即闸自己算出的值），否则 S4 当场红。
⛔ 一段**不能**同时有 `covers-acceptance` 和豁免行（S3b 判矛盾）⇒ 这 48 段别顺手塞进豁免表占位。

---

## 9 ⚠️ 顺带登记 3 个**段 id 本身**的脆弱点（不改文件，只登记）

闸的 `slugOfHeading` 取 heading 的稳定前缀 `^([A-Za-z0-9][\w.\-]*)`，落到这 3 段上很难看：

| 段 id | 成因 | 是哑的还是响的 |
|---|---|---|
| `` #`Jira `` | heading 以反引号开头 ⇒ 正则第一分支不匹配，退到 `split(/\s+/)[0]` ⇒ slug 含反引号 | **响的** —— heading 改名 S3 当场报「活源里没有这个段」 |
| `#⚠️` | heading 以 emoji 开头 ⇒ 同上 | **响的** |
| `#(B)` | heading 以 `(` 开头 ⇒ 同上 | **响的** |

⚠️ 三个都是**响的**失效（S3 会报），所以 ⛔ 不急着改 heading ——
改 heading 会同时改变段 id，而那正是 Q1-b 教训 2 登记的「无人看守的段 id 重命名通道」。
**要改就得连自陈一起改，且改前后对比段集合零差异。** 本轮不动。

---

## 10 A0 那 2 段的**预注册判据**（⛔ 写死在动手之前）

零新代码 ≠ 零声明：这一批把 2 段从 `unclassified` 移到 `gated` 并把 BASELINE 从 48 降到 46
⇒ 那是一个可被读错的真声明，判据必须先钉死。

### A0-P1 · 自陈落在**头 60 行内**
`parseCoversDeclarations` 亲验 `scripts/audit-acceptance-gate-coverage.mjs:292` 逐字
`.slice(0, 60)` ⇒ 埋到 60 行之后 = 静默不生效（段数不变 ⇒ S2 也不红）。
两行自陈都必须落在各自文件头 60 行内，落地后用现取读数反证生效。

### A0-P2 · `[N]` 必须等于 Σ，写错当场红
- `#C7 [3]` · `#Delivery [5]`（Σ 取自本文件第 4/6 章，由闸自己算出）
- **造故障**：任一行改成 `Σ+1` ⇒ `[S4]` 必须**逐字**印出「逐字有 N 个、自陈 N+1 个」

### A0-P3 · 棘轮 48 → 46，BASELINE **只许收到现取值**
- `unclassified` **48 → 46** · `gated` **35 → 37** · `BASELINE_UNCLASSIFIED` **48 → 46**
- **造故障**：删掉两行自陈之一 ⇒ `EXIT=1` 且 `[S2]` 报 `unclassified 47 > BASELINE 46（+1）`，
  并逐字印「⛔ 别改 BASELINE 放行」
- ⛔ 不许把 BASELINE 留在 48（那样这批兑现量没被锁住，别人删回自陈闸照样绿）

### A0-P4 · ⚠️ 自陈**不许**写成「全覆盖」
两行都必须附一句如实的覆盖边界，照既有形态（`audit-mockup-binding-fidelity.mjs` 头注释逐字
「⛔ 别把 `[2]` 读成「这 2 项都有闸」」·`audit-mockup-overlap.mjs` 逐字「都是 handoff 文本要求，
本闸够不着，照样计入 6」）：
- `#C7`：本闸覆盖 [1][2]（B-TYPO 裸 fontSize + B-SEM fill 绑变量），**[3]**（handoff fix log
  记 `text styles bound: [N nodes]`）够不着
- `#Delivery`：本闸覆盖 **[5]**（wording 黑名单），[1]–[4]（cleanup checklist / 「必要」的判断 /
  「重复讲同一规则」/ 「被 supersede」）都是判断或 handoff 文本，够不着

### A0-P5 · 两端都有声明可比
既有自陈范式要求「两端都有声明可比」。⇒ 除闸头注释外，规则真源侧也要有指针：
- `#C7` 的 Acceptance 后加一句指向 D16 verifier（照 §C5 已有的「机检见 D16 verifier
  （`audit-mockup-binding-fidelity`）」形态，⛔ 不发明格式）
- `#Delivery` 第 [5] 条已逐字写着「§ No Open Questions / 触发器 P」，而
  `docs/meta-rules.md:820` 逐字点名 `audit:deliverable-open-questions` ⇒ **这一端本来就有**，不必加

### A0-P6 · 零回归 + 零残留
- 两条闸各自的既有测试全绿；全量 `pnpm test` 零新增失败（基线 3241 passed）
- 新建/改判据后必跑：`acceptance-gate-coverage` · `stale-anchors` · `rule-inventory` ·
  `doc-shape` · `gate-mount-declaration`（`rule-load-map` 只在 staged 时触发）
- 每次造故障后 `git diff` 逐字比对 ⇒ 零残留

---

## 11 ⛔ 这份文件不能说的话

- ⛔ 不许说「48 段已分类完」—— 本文件给的是**裁定**，`unclassified` 现取仍是 **48**。
  段真正离开 `unclassified` 要等自陈落进闸的头注释。
- ⛔ 不许说「48 段都能上闸」—— 每段只覆盖被点名的那**几条**，
  `[N]` 是变更探测的锚、**不是覆盖度声明**（`audit-mockup-binding-fidelity.mjs` 头注释逐字）。
- ⛔ 不许说「B2 那 34 段是机械的」—— 上一轮实测每段判据各不相同，本文件第 6 章的红输入列
  就是那个差异的证据。
- ⛔ 不许把 `#M41` 的上闸读成「scrim 已守住」—— 数值那一半是 **Q11，待 owner 拍**。
- ⛔ 不许说「A0 那 2 段是我建的闸」—— 那两条闸早就在跑，本轮补的是**登记**。
