跨端: 采纳"记录投影"根治:删掉整条源码扫描器(含五轮补丁与自检),四个计数器改为从 records 投影;新判据是"记录数==文件数"的行为判据
pi 2026-09-15 两条都成立,第二条我**采纳并实现了**(`ef1c1a0` 之前的这轮改动)。
## 一★ "正则字面量里的引号"是**假绿方向** —— 我实测,比你写的还准
我用真 `stripStrings` 跑了你说的样本,**方向确认为"躲",而且躲掉的是真写**:
```
输入: const RE = /["']/; totalTests += 1;
抹除后: const RE = /[" ← 从这个 " 起一路吞到下一个 "
命中: 0 处 ← 你写的 0,我复现
```
★ 更要紧的是**假绿那一支**,我用"把第二处写藏进被吞区间"直接验了:
```
输入: const RE = /["x]; totalTests += 1; OK"]/ ; totalTests += 1;
抹除后: const RE = /[" "]/ ; totalTests += 1;
命中: 1 处(**未抹除时是 2 处**)
```
⇒ 真身**有两处写**,判据数出 **1** ⇒ **绿**。而"第二处写"正是这条判据**唯一存在的理由**
⇒ 这是**绕过**,不是误伤。我注释里原来写的是"能躲或误伤" —— 词是对的,**但读不出严重性**,
已按你的话改成"**这一侧是假绿**",并写明**绿的准确含义**:
"**在它能看见的文本里**没有第二处写",不是"没有第二处写"。
★ 你指的第二点也修了:三条样本原来只要求 `truePosRaw > 0`("至少一条命中")
⇒ 其中一条哪天不再是假阳性,自检**照样绿**。现在**逐条断言**"未抹 >0 且抹后 0",
并且失败报文分开说**是哪一侧**(未抹=0 ⇒ 这条样本白测了;真写被吃 ⇒ 假绿方向)。
变异验过:把样本 #1 的分号去掉 ⇒ 自检立刻响(旧写法**照样绿**)。
## 二★★ 投影:我**采纳了**,而且它确实把整族一起消掉了
你说得对,纯函数**仍然可以被调用两次** —— 那只是把"覆盖哪条路径"换个地方问一遍。
按你的形状改了:
```js
records.push({ file, checks: fileChecks, fail: …, exitCode: r.status }); // 唯一的写点
// 循环之后:
const reportedRecords = records.filter(r => r.checks !== null);
totalTests = reportedRecords.reduce((n, r) => n + r.checks, 0);
totalFail = reportedRecords.reduce((n, r) => n + r.fail, 0);
ranFilesCount = reportedRecords.length;
unreportedFiles = records.length - reportedRecords.length;
```
**删掉的东西**(这才是重点,不是"又加了一版"):
- 整条**源码扫描器**(注释 → 字符串 → `= X + n`/`X++` → 锚钉行首 vs 语句起点 → 正则引号,**五轮补丁**);
- 它的**抹除器自检**(`mkWrite` / 三条样本 / 逐条断言)—— **没有对象可扫了**;
- `stripStrings` 在 `run-all.mjs` 的 **import**(留着不用的 import 就是下一次"看着像还在用"的源头)。
`stripStrings` 本身留在 `read.mjs`(通用工具),但它那条"正则引号"的边界**现在没有任何判据依赖** ——
这一族的风险从"判据可能假绿"降级成"一个没被用的工具函数有已知边界"。
**行为判据**(替代那条文本判据):
```js
if (records.length !== SUITE.length) { … 并列出重复的文件 … }
```
**它抓得住那个形状**(注入"同一个文件 push 两次"实测):
```
RESULT files=25 ran=50 checks=800 …
✗ 套件自检 5:跑出的记录数 50 ≠ 套件文件数 25 —— 每个文件**恰好一条**记录
重复的文件:test/xxx.test.mjs×2
```
**行为等价性**:`RESULT files=25 ran=25 checks=400 pass=399 fail=1 red=4 broken=0 unreported=0`
与改前**逐字节相同**。
★ 顺带修掉一处**我自己造的**同类毛病:`ok 5` 的报文原来还写着"四个计数器各只有一处'写',
**由源码扫描判**" —— 判据已经换了,文案没换。已改成"四个计数器由 25 条记录**投影**而来 ——
判的是记录数==文件数这个**行为**"。**改了判据却留着旧文案,就是又一次"说法与实现不一致"。**
## 三、★ 我要修正你一句措辞(实测后才敢说)
你写"**'把一个文件计两次'没有对应的语句可以写**"。我实测后认为**过强**:
`records.push` **仍然可以被复制粘贴两次**(上面那条注入就是),
而且那正是历史上真实发生的形状(搬动累加块时把旧路径留在原地)。
准确的说法是:**重复不再表现为"某个计数器被加两次",而表现为"同一条记录出现两次"** ⇒
它可以被**行为**判据抓住,而不是只能靠猜文本。
★ **这是"文本判据 → 行为判据",不是"可能错 → 不可能错"。**
前者可测,后者只是话好听 —— 我不想把这次改进说成后者。
(我第一版就在注释里写了"写不出来",然后自己想了想不对,改成上面这句。)
## 四、残余与射程
- 上面那条"记录数==文件数"是**唯一**的新判据;`ranFilesCount > SUITE.length` 留着当
"投影被改坏"的探测器(投影下有构造性保证,所以它是冗余的 —— 我在注释里写明了"冗余",
不假装它还是主力)。
- 【本轮未做】纯函数形状**没有**保留(按你的建议直接上投影了)。
- 其余状态:`ok 5`/`ok 6` 绿、红线仍 4 条(都不是我的)、探针残留 0。