# 只朝一个方向看的闸

> 2026-08-07，INFRA-F104（render-gate 豁免判据字段化）。本篇只留**通用经验**；判据、数字、⛔ 清单在 [`specs/2026-08-07-infra-f104-render-gate-field-level-excuse-design.md`](../../superpowers/specs/2026-08-07-infra-f104-render-gate-field-level-excuse-design.md)，落地叙述在 tracker。

---

## 1. 收缩上了闸，放大只剩散文 —— 新机制自己带着同形态的假绿口

本条工作的全部目的，是消灭「看起来在守、其实守不住」的判据：旧机制对 entry 的散文警告做正则，命中即整条 entry 免疫。换成字段级豁免表后，我们给它配了 shrink-only 判据（S6：某行不再命中 → 红，要求删行），并把「表空着是终态不是待办」写进了闸的报错文案。

**做完之后，终审问了一个我和计划都没问的问题：那放大呢？**

把某行 `entryScope` 从 `*--theme-light` 放宽成 `*`：schema 校验通过（非空字符串）· 该行仍命中失败 check 所以算 `matched`· `excusedChecks` **只数当前失败的 check**，放大到今天 pass 的 entry 上 **一位不变** · S5/S6/S6b/S7 全绿 · 已提交的 report diff 里 `summary.excuse` 四个数**完全不动**。

于是那个字段从此被**预先免疫**，唯一证据是表里一行 JSON 的 diff。

这不是实现 bug，是**判据的方向性**：我们把「豁免面缩小」做成了受检事实，却把「豁免面扩大」留在散文要求里（spec §4b 写着「放大必须写出来」——写给人看的）。而 spec §2b 自己刚论证过同形态的东西：Rating 那 10 条今天 0 个 fail check 却同样免疫，**潜伏的免疫不产生任何当期信号**，正因如此才立了 S6。同一个洞在同一份 spec 里被识别了一次、又在相反方向上被漏掉一次。

**通用形态**：给一个「例外表」上闸时，收缩与放大是两个独立方向，只守一个等于没守。判断方法不是读判据条文，是问**「把这张表往松了改，哪个已提交的数字会变？」** —— 如果答案是「没有」，那条路就是敞开的。

**解法也有方向性**：这里刻意**不加闸**，只让 `summarize()` 多吐一个按行的 `scopedEntries`。因为 glob 命中数会随 manifest 正常扩容而增长，设阈值必然误报（正是被否掉的路线 C 的形态）；而只要它是一个**已提交进 git 的数字**，放大就会在 diff 里留下痕迹——**可见性和阻断性是两种不同的工具，选错会让闸被人关掉**。

---

## 2. 「作者已经识别过这个危险」不等于「防住了」

`classifyFailedCheck` 里有两条降级：一条 field-specific（border-collapse），一条 entry-level（六个短语）。field-specific 那条的注释逐字写着做成字段级的理由 ——

> so a real left-padding drift on the SAME Table entry still classifies as A

读到这句时的自然反应是「作者想过这个问题」。**但拿真分类器对同一条 Table entry 做阴阳对照，那条 padding 漂移实测判 B。** 根因：触发 field-specific 那条的警告句**自己含 `verifier resolution`**，于是 entry-level 那条照样兜住。把 warnings 清空才判 A；而那条 entry 上「不含短语的 border-collapse 句子」数量是 **0**。

⇒ **那句注释描述的保护，从落地那天起就没成立过。**

**通用形态**：注释、commit message、entry 描述里的「我们已经处理了 X」是**作者的意图**，不是**系统的行为**。两者的差距只有一种查法——构造那个 X，看系统怎么判。本仓库已有同源教训（memory `entry-restatement-is-secondhand`、`regression-pass-needs-fault-proof`），本轮是它在**代码注释**这个载体上的又一次复现；载体越像"技术事实"（带 file:line 的注释比散文 entry 更唬人），越需要实测。

---

## 3. 判别轴决定了你能看见什么 —— 「39 条」按构造看不见第二群

前一轮体检量出「39 条搭便车 fail、收紧后会打红」，判别轴是**警告有没有指名该字段**：指名了算正当，没指名算搭便车。

这个轴自洽、可机械算、结论也对。但它按构造看不见另一群：**警告指名了字段、同时自陈那是待修的真 code 债**。

| 组件 | 警告自陈（逐字） |
|---|---|
| Slider ×10 | `real width fix needs explicit width: 240px on .slider__input` |
| Message ×10 | `pending real fix in followup sprint（add dark-theme override block or split token names）` |

按那个轴，这 20 条稳稳落在「正当」一侧。**而它们恰恰是最该有闹钟的那种。**

这给了否掉「把正则收成 field 级」那条路线的**第二个独立理由**：不只是「一句 `across all checks` 就能重开免疫」，更是**同一句措辞可以既指名字段、又承认自己是 bug** —— 措辞根本承载不了这个区分。

**通用形态**：接手一个带判别轴的既有测量，除了核它的数字，还要问**「这个轴按构造看不见什么」**。数字全对 ≠ 分类面完整。（与 memory `test-purpose-claim-before-numbers` 同族，但那条讲的是"目的"，这条讲的是"分类器的盲区"。）

---

## 4. 三条过程性的坑

**① 我自己写的文件里混进了 6 个 NUL 字节。** 后果比看上去严重：`file(1)` 把那份 `.md` 判成 `data`、`grep` 因此当二进制处理并**静默不匹配**（我一度确信计划里整段代码不存在）、`task-brief` 抽取时在 NUL 处截断，让 implementer 拿到两段坏代码。它自己用 `::` 重建了并主动申报，才暴露出来。
⇒ **grep 返回空要先排除「文件不是文本」这一种可能**，`file -b` 一次就能分辨。

**② 「命名类比生成」是一种不像编造的编造。** subagent 往 divergence 条目写了 `GEOMETRY_BY_SIZE.M.paddingSquare`，全仓命中 1 处、就是那条 JSON 自己（真名 `SIZE_GEOMETRY`）。成因链值得记：grep 词里没有 `const`/`Record` → 没命中声明行、只看到属性值 → 又看到兄弟表 `FIXED_WIDTH_BUCKETS_BY_SIZE` 的命名模式 → **按规律补出一个名字**。数值 16 是对的，名字是编的；报告里还写着「grep 确认三处都命中」。
⇒ 凡要写进交付物的**标识符 / 路径 / 行号**，必须在真实工具输出里出现过。**「我见过这个值」≠「我见过这个名字」。** 审查侧的对策：要 reviewer 抽查「符号 → 实际命中的 file:line」表——一处编造往往连着一句假的验证声明。

**③ skill 的菜单架空了仓库的标准动作。** 收尾走 `finishing-a-development-branch`，照搬它的三选一（merge / 建 PR / 保留分支）请 owner 拍板。owner 反问「我自己提交的直接提交到 Master，这是个规则，记录到 Memory 了，为什么还没记住」。
⇒ 这条规则的失效形态**变了**：从「我主动把已落 master 的改动补救成 branch」变成「我把一个标准动作降级成一道选择题」。skill 自己写着「用户/仓库规则优先于 skill」，但菜单类 skill 的形态天然诱导「呈现选项 + 等待」。
**判据**：需要 owner 拍的是**内容层决策**（走哪条技术路线、数值定多少、要不要登记 divergence），不是「这活要不要合进 master」。用 worktree ≠ 走 PR 流程——worktree 只是并行隔离手段，终点仍是 master。

---

## 5. 验到有效的做法

- **开工前对计划做一次冲突扫描**，当场抓到 S6b 那个假绿口（`summarize` 的默认空表会让 S5+S6 双双放行）。**在写第一行代码前发现的判据洞，比在终审发现便宜一个数量级。**
- **每个 subagent 的完成声明都自己重跑取证**：Task 2 报的三个数字、Task 6 的 8 条探针复原、Task 7 的删档与计数，都由 controller 独立复算过；Task 6 那条「A=294 而非 300」的偏差正是这样确认为**计划预期不精确**（6 条 Tooltips `rootWidth` 偏差 2.3% 落进既有 ≤5% 容差）而非实现问题。
- **给 reviewer 点名具体风险，而不是让它泛泛审**。「新机制自己会不会变成同一种假绿」「cache 的键覆盖了全部输入维度吗」这类具名问题，抓到了 fix round 1 自己引入的 `filePath` 维度缺口——那是通用 review 很难命中的。
- **终审用最强模型、且必须真做**。本轮三条最重要的 finding（`reviewBy` 无上界 / 生产表无便宜校验点 / 放大不可见）全部来自终审，全部是**逐 task review 按定义看不见**的跨任务组合缺陷。这与 [[2026-08-06]] F98 那轮的结论一致：final whole-branch review 不是走过场。
