# 一份 plan 里最不可靠的部分，是它对「闸会不会红」的预判

> 2026-09-03（落地线第九十一轮）。执行 [`2026-08-12-ux-scenario-coverage-expansion`](../../superpowers/plans/2026-08-12-ux-scenario-coverage-expansion.md) 全部四个 Task 时的两条通用发现。
> 落地物与逐条读数在 [STATUS-CHANGELOG](../STATUS-CHANGELOG.md) 顶条，⛔ 本文不复述。
>
> 🔴 **同日第九十二轮追加 §4 —— 本文 §1 的结论当天就被证明「说窄了」。** 执行另一份 08-12 的 plan（`rule-inventory-mirror-gate-extension`）时预判又错 4 次，其中第 4 次**不属于 §1 描述的任何一种**。⇒ **先读 §1，再读 §4**；§1 的判据仍然对，只是它的适用面比原以为的窄。

---

## §1 主发现：plan 对闸的预判，四次错了三次

那份 plan 写于 2026-08-12，本轮（09-03）执行。它的**判据、文本、锚点纪律全部经得起考验**——每处行号都配了「以内容锚定位，不以行号定位」的兜底，撞到的漂移我都能自行吸收。

真正失手的是另一类句子：

| Task | plan 的原话 | 实测 |
|---|---|---|
| 1 | 「本 task 无新 H2、无新编号，**闸应零负担**」 | `audit:rule-inventory` **S4 红** —— 分工声明那一行同行堆了 3 个 `mockup-conventions` 裸 id，正是 S4 定义的「又枚举一份清单」 |
| 2 | 落地三处清单（与 `rule:next` 自印的三处一致） | **漏了第四处** = 目标文件头部的 `rule-inventory` 块 ⇒ **S3 红**；另撞 `acceptance-gate-coverage` **S2 棘轮** |
| 3 | 「三闸零触碰」 | `acceptance-gate-coverage` **S4 子项对位红** —— 给 M49 Acceptance 加一行 ⇒ 该段 9→10 项，而 `scripts/design-kickoff.mjs` 自陈 `[9]` |
| 4 | —— | S2 棘轮红（这次预判到了） |

**三次红，没有一次是 plan 的判据错，全是 plan 对「闸会怎么反应」的预测错。**

### 为什么这类句子特别不可靠

- **它是撰写时的一次推断，而且从不被复核。** entry 正文里的数字有整套纪律盯着（每条 entry 自带「现取判据命令」、满篇「⛔ 数别抄」、触发器 S 强制四行块）。而「闸应零负担」这句话**没有任何机制会在它过期时报警** —— 它甚至不像数字那样长得像一个待核项。
- **它的过期方式是单向的。** 三周里闸只会变多、判据只会变严（本轮撞的 `acceptance-gate-coverage` 就是 2026-08-27 才加文件级豁免粒度的）。所以这类预判**系统性偏乐观**。
- **它把「我这次改了什么」误当成了「闸看什么」。** plan 的推理是「无新 H2、无新编号 ⇒ 三闸不管我」，而 S4 管的是**行内 id 密度**、S2 管的是**Acceptance 段计数**、S4 子项对位管的是**段内核查项数**——三条都与「有没有新 H2/新编号」正交。

⇒ **判据**：plan / entry / 交接 prompt 里凡出现「闸应…… / 三闸零触碰 / 这个改动不触发 X」，一律当**待证伪的预测**，不当前提。它与被转述的数字同性质（memory `entry-restatement-is-secondhand`），**新形态 = 被转述的对象不是数字，而是「闸的反应」**。

### 三次红的处置都不是放宽闸（记下来防复现）

- Task 1：按 **S4 头注释自己写的口径**给 id 加 `§` 前缀（「§ 前缀的 id 不计数 —— 那是去读该节的**引用**，不是复述该文件有哪些内容的**清单**」）。⛔ 未拆行凑数 · ⛔ 未加豁免 · ⛔ 未放宽判据。
- Task 2 / 4：按闸自己定义的三态之一登记**段级**豁免（具名 + 带日期 + 带重开条件），⛔ **未改 BASELINE** —— S2 的失败信息逐字写着「⛔ 别改 BASELINE 放行」。
- Task 3：把自陈锚 `[9]` 改成 `[10]`。这**必须**做而不是放宽 —— 该闸头注释逐字说 S4 立项就是为了治「规则里加了第 5 个核查项而闸的声明没跟上」（F104 那个病）；同时它也警告 `N` 是**变更探测的锚**、不是覆盖度声明，⛔ 别把 `[10]` 读成这 10 项都有闸。

**⇒ 共同点：三次的正解都写在闸自己的头注释里。** 撞红时的第一个动作应该是读那条判据的头注释，而不是想怎么绕过。

---

## §2 副发现：同一个闸的同一个绿，换一份被扫文件就换一个信息量

Task 1 改完 `docs/internal/design-process.md`，`audit:stale-anchors` 报 `EXIT=0` 零孤儿。**但 `rule-ref 416` / `TOTAL 984` 与改前逐字相同** —— 我刚加了 7 个 `§Mxx` 引用，计数一动没动。

查活源坐实：

- `SCAN_FILES` 只有三份（`mockup-conventions` / `code-conventions` / `meta-rules`），它们走**全六类**判据；
- `design-process.md` 只出现在 **`DEF_FILES`** —— 那是 rule-ref 的**定义来源**注册表，不是被扫对象；
- 现行层 `LIVE_TREE_KINDS = ['path', 'code-span-path', 'fragment']`，**不含 rule-ref**。

⇒ 那 7 个引用**结构上不在任何 rule-ref 扫描面里**。它们指向的规则确实都存在，但那是我手工 grep 逐个核出来的，**不是闸给的绿**。

### 「读数有没有变」就是判据

这一轮同时拿到了正负两侧，且是自然出现的：

| 改哪份文件 | 在 `SCAN_FILES` 里？ | `stale-anchors` 读数 |
|---|---|---|
| `design-process.md`（Task 1） | ❌ 只在 `DEF_FILES` | rule-ref **416 → 416**（逐字不变）· TOTAL 984 → 984 |
| `mockup-conventions.md`（Task 2 / 4） | ✅ 走全六类 | rule-ref 416 → **422** → **440** · script 59 → **61** · TOTAL 984 → **998** → **1020** |

**被验过的那一半用故障注入钉住**（否则「path 臂到底看不看 design-process」也只是我的推断）：往 item 7 注入 `./zz-probe-nonexistent-9f3a.md`（探针名注入前已 grep 全仓确认零命中），闸 **EXIT=1** 并精确点名 `docs/internal/design-process.md:852 [live:path] — 目标文件不存在`；反向 Edit 复原（⛔ 未用 `git checkout --`，该文件当时有未提交改动），复原后读数逐字回到 `path 137 / TOTAL 984`。

⇒ **`EXIT=0` 加读数不变 ≈ 空过。** 报绿时要配一句「它这次看见了什么」，判据是**读数变化**而不是退出码。这是 memory `verification-criterion-must-be-terminal-state` 里「绿是真的、但对象不在扫描面里」那一形态的一个干净实例，也是 `regression-pass-needs-fault-proof`「全红先证量具活着」的**镜像面**：全绿且读数不动，同样要先证量具在看。

⚠️ **如实登记本轮留下的缺口**：`design-process.md` 是 mockup 任务 mandatory 全读的规则真源之一、25 个 H2，而往它写指向不存在规则的 `§Mxx` **没有任何闸会红**。本轮**没有顺手扩扫描面** —— 那是独立决定（`SCAN_FILES` 走全六类的代价、以及 rule-ref 类在现行层的真缺陷率 0/6 已被 2026-08-25 那轮实测过并据此决定「不扩」），按 root-cause 纪律不在修 bug 的同一轮里做。

---

## §3 两条小的

- **plan 的查重清单会漏**（触发器 J 现场补）：Task 4 撞上 plan §Placement 没列的 **§M-INTEGRITY 的 §I1**，它逐字管的正是候选文本必做 3 想管的那半（多个 Plan section 并存时 layout 互相 mirror）。⇒ 必做 3 收窄成「独立具名 + 并列 + 共用 Context」，mirror 那半显式指回 §I1，并在分工声明写明两条是配套的两半、⛔ 都不复写对方。**「plan 已经做过查重」不能替我做查重。**
- **异步通知又加了一层包装**：后台任务通知的 "exit code 0" 是 `bash -c '<cmd>; echo EXIT=$?'` **包装脚本**的退出码。Task 2 首次 commit 实为 `EXIT=1`（被 S2 拦下）、`git log` 仍停在上一条 —— 靠取终态事实（`git log` + `EXIT=` 行）抓到。⇒ 同族教训又一个落点：**判「commit 成不成」永远看 `git log`，不看任何一层转述的退出码。**

---

## §4 追加（同日第九十二轮）：§1 说窄了 —— 还有一种过期，是「plan 写完之后仓库长出了新的闸面」

§1 把病因归到「plan 的那句预判是撰写时的推断、且系统性偏乐观」。当天下午执行另一份同日期的 plan（[`2026-08-12-rule-inventory-mirror-gate-extension`](../../superpowers/plans/2026-08-12-rule-inventory-mirror-gate-extension.md)）时**又错 4 次**，前三次都落在 §1 里，**第 4 次不在**：

| # | 形态 | 本轮实例 | §1 覆盖到了吗 |
|---|---|---|---|
| 1 | plan 把「哪些行会红」列窄了 | §现状实测只点了 OVERVIEW 的 §3.1/§3.2/§3.3/§6，漏掉 §8 第 3 条那行 3 个裸 id | ✅ |
| 2 | 锚点漂移 | 两处 `old_string` 对不上活源；且其中一处**活源后来长出的内容更好**（照 plan 的 `new` 整行覆盖会删掉有用的东西）| ✅（§1 说「撞到的漂移我都能自行吸收」）|
| 3 | plan 的用例集有系统性盲区 | `SKILL.md` 一行 6 个裸 id 靠 `I\d+` 命中，而 plan 的 15 条用例**一个 I 系列都没有** | ✅ |
| 4 | 🔴 **plan 撰写日之后，仓库长出了一个新的回归面，plan 全文零提及** | `tests/audit-rule-inventory-cli.test.ts`（本闸的整脚本 fixture-root harness，[[INFRA-F138]]，**2026-08-27 加、晚于 plan 15 天**）。S7 的 fail-closed 让它每个 fixture 多 4 条红 ⇒ **首次提交 14/16 红被拦** | ❌ |

### 为什么第 4 种更难防

§1 里那三种都有**文本痕迹**可供警觉：一句「闸应零负担」、一个对不上的锚点、一组明显偏窄的用例。**第 4 种没有痕迹** —— plan 从头到尾自洽，它只是**不知道有那个东西**。读 plan 读不出来，跑 plan 列的验证也跑不出来（plan 列的验证不含那份文件）。

⇒ **判据（可机械执行，已写进 STATUS 顶条 ①）**：**起工任何隔了周的 plan，动某个闸之前先跑一次 `grep -rln <闸脚本名> tests/`**，拿到的清单才是今天真正盯着它的面；plan 列的那些只是撰写日的快照。同理适用于 `.husky/pre-commit` 与 `package.json` 的 gate-chain。

⚠️ 这条与 [触发器 S](../../meta-rules.md) 的分工：触发器 S 核的是**这件事还该不该做**（决策前提），本条核的是**做它会撞到什么**（执行环境）。四行块全绿也拦不住第 4 种。

### 处置同样不是放宽闸（第 4 次的诱惑最大）

14 条红有一个一行的便宜修法：让 S7 对读不到的受管文件 `skip` 而不是 fail closed。那会**把本轮刚建的判据当场挖空** —— 注册表 stale（文件被移/改名）恰恰是最需要它说话的时刻。正解是**给 fixture 树补齐那 4 份**，并顺手把 S7 补进整脚本回归面（读不到 ⇒ 红且分子 `4/4→3/4` · inline 且 must-not-hit `[S4]` · table 且 must-not-hit「单行枚举」）。

⇒ 与 §1「三次红的处置都不是放宽闸」合并成一条通则：**闸红时，「改判据让它别红」这个选项要先假定是错的。** 本轮四次，四次的正解都在判据之外（改文档 / 改 fixture / 补用例），没有一次该动判据。

### 顺带订正本文自己 §3 之外的一处外推

§1 那张表下面写「三次红，没有一次是 plan 的判据错」——**这句仍然成立**，但当天我在 tracker 里由「这四次 commit 是 50 块」外推出「纯 docs 49 已漂」，收尾时自己抓到并订正（`b5a5bc57`）。本轮实测 **47 / 49 / 50 三个值都出现过**（47 那次逐条核过 distinct 47、零重复）⇒ **`▶ pre-commit` 块数随 staged 文件集变，任何单值都不是常量**，唯一可靠的判据是「**0 别当绿**」。⛔ 别再从任何一次观察里推出「某某档是 N」。
