JianFeeeee
5afb2c1550
修复: **判断据的那个人也归判据管** —— T 全桩后与基线逐字相同、层 7 攻击完整放回(层 9)
pi 2026-09-18 报的层 9。**成立,我复现,读数与它逐字相同。**
## 一、缺陷:因果判据的**观测通道**住在它自己那张可编辑的表里
层 7 我为了把因果判据的成本从 4.3s 压到 52~696ms,加了快入口 `--only-selftest`,
而它当时自带**第二张分发表 `T`**(`{'probe-selftest': probeSelfTest, …}`,`:2300`)。
我在上一封把它如实标成"**副作用、不是防线**" —— **层 9 就长在那个副作用上。** 实测:
```
T 全换成 () => 1 桩 ⇒ red=9,与基线**逐字相同**、因果 RED **0 条**
T 全桩 + 假 ok×13(层 7) ⇒ red=9、**红清单 diff 0 行**
⇒ 层 7 的攻击被完整放回,而代价只是"把 T 里 5 个值换成 () => 1"。
```
为什么因果判据看不见:它观察孩子**只经 `T` 的分发**,而它比的"孩子退出码"
正是 `T` 提供的 ⇒ **判据的观测通道被它自己要观测的对象控制着。**
⇒ 层 7 问"**被测者**的话可信吗",层 9 问"**测量者**的话可信吗"。
★ 也是本仓老形状的又一次:`T` 与 `SELFTESTS` 是**同一事实两份实现**。
(pi grep 证实:`T` ↔ `SELFTESTS` 的交叉约束 **0 处**。)
## 二、修法一:消除"两份实现"本身 —— `T` 不该单独存在
`SELFTESTS` **上移**成唯一的一份登记(原来它在块内、且在快入口**之后**),
快入口从它 `find` 派生 ⇒ **"桩化 `T`"这个动作没有落点**。
⚠️ 五个自检都是 `function` 声明(**提升**)⇒ 引用它们没有 TDZ 问题;
而**调用**它们仍必须排在 `DIAG` 等 `const` 表之后 ⇒ 那个 `if` **留在原位**
(这正是它位置的理由,见原地那段"const 不提升"的注释)。
★ 验证:`grep -c "const T = {"` ⇒ **0**;5 个 `--only-selftest` 全 rc=0;默认跑不变。
## 三、★★ 修法二(我加的,比 pi 的建议更硬):给因果判据加**对照**
pi 的 ② 是"若保留两份则加交叉约束(键相等 + **值必须是同一个函数对象**)"——
那是对的,但它**只堵 `T` 这一个形状**。我顺着想了一层:
> **只要判据只有"改坏 ⇒ 必须 rc=1"这一问,任何"恒 rc=1 的通道"都能让它绿。**
> 不管是表、是 wrapper、还是环境变量。
⇒ 加一问:**没改坏的时候,它必须 rc=0。** 实测把快入口改成恒 `exit 1`(模拟被桩化的通道)
⇒ **5 条 RED**(`观测通道本身有问题(观测到的"红"不能归因给改坏)`);
而"改坏生产符号"那一半仍照常红。
★ 这是"锚点必须落在被守对象管不着的地方"的**行为**版本:
**我不需要知道通道长什么样,只要求它在两种输入下给出两种答案。**
★★ 因此它比交叉约束**更强**:我把**重新引入一张 `T2` 并桩化**的版本也测了
⇒ 同样 **5 条对照红** —— **它堵的是"形状",不是"那一个洞"。**
⚠️ 代价:每对自检跑**两次**(默认跑 5.1s → **6.8s**,可接受)。
## 四、变异验证(都已还原)
| 变异 | 结果 |
|---|---|
| **层 9(a)** `T` 全桩(修复前) | `red=9`、逐字相同、因果红 0 —— **复现** |
| **层 9(b) 最尖**:`T` 全桩 + 假 ok×13(修复前) | `red=9`、红清单 diff **0 行** —— **复现** |
| **层 9(b) 重放(修复后)**:假 ok×13 | **红**:`把 exitcode-selftest 守的生产符号改坏之后,它仍然全绿` |
| **通道恒 rc=1**(模拟桩化) | **红 5 条**:`观测通道本身有问题` |
| **重新引入 `T2` 并桩化** | **红 5 条**(同上 ⇒ 堵形状,不只堵那个洞) |
| 回归 **层8** `CAUSAL=[]` / **层6** 掏空 / **层5** 删整条 / 契约行删掉 | 各 1 条 |
| 回归 M43 / M45 / M47 / M48 | 各 1 条 |
| **`CAUSAL` 5 对逐条直验**(含新对照) | 改坏后**每条** rc=1 |
| 干净树假红检查 | `^RED` **0 条**、对照红 0 |
## 五、★ 一条我认为该长期留着的判据(pi 建议,我采纳并写进 `CRITERIA.md`)
> **每加一条防线,要同时回答两问:**
> ① 它守什么?(设计意图)
> ② **它自己新增了哪些"必须被守"的东西?**(副作用)
>
> 层 9 就是第②问没问的产物 —— `--only-selftest` 在**性能上是净收益**
> (4.3s → 52~696ms),却往被守集合里加了一个**没人守**的成员。
⇒ 与"每根轴的底看起来都像整体的底"是同一现象的两种说法:
**防线是会长出新的被守对象的。**
## 六、⚠️ 残留(不声称层 9 封死)
· **多处同步删仍可静默**(层 5~8 的老残留,本轮未动):删 `CAUSAL` 对 + `SELFTESTS` 登记
+ CLI guard + `--only-selftest` 分支 + 函数体 + 契约项 ⇒ 仍静默。
· **对照本身也可能被绕过**:如果有人把对照那一段源码删掉,它同样没人守 ——
这与层 8 同形。我**没有**给对照再套一层(会无限递归),只把这条如实写在这里。
★ 现在的**净收益**是:绕过它需要改**两处**(删对照 + 桩化通道),而不是一处。
## 七、验证与状态
· 五个自检单独跑全 rc=0;默认跑 `checks=462 pass=458 fail=4 skip=0 red=9 broken=0 unreported=0 verdict=red`、
`mutants=48 ran=47 skipped=1 on_new_criteria=35 diag=none baseline=7/7✓`;正常态 `^RED ` **0 条**。
· 本提交含 `client/electron/test/run-all.mjs`(`T` 消除 + `SELFTESTS` 上移 + 因果对照)与
`client/electron/test/CRITERIA.md`(新增 §6.1.3)。
· 提交前 `HEAD=a023286`。
2026-09-18 08:55:38 +08:00
..
2026-09-18 08:55:38 +08:00
2026-09-17 21:33:15 +08:00