test(criteria): runner 不再手写 --test(由内容推导)+ 自检 4「这条判据能不能红」;规范补两档
pi 提的三条,第一条落地前先按他的要求**贴真实样本实测**,结论与他的猜测不同(记在代码里)。 ## 1 runner 内部那个"配错 flag = 绿" —— 实测后换了个形状 pi 的猜测:给自定义 `check()` 的判据传 `--test`,runner 会报"0 个测试"并以 0 退出。 实测(node v22.22.2,两条真实样本): - `node --test <自定义 check() 判据>`:**退出码照样传出来**(文件 exit 1 → 命令行 exit 1), 没有被吞; - 但 `node --test <什么都不做的文件>` 报 `# tests 1 / # pass 1` —— **pass 计数不是"检查跑过"的证据**。 所以"解析 pass 计数、0 就判红"这条路两头不讨好:抓不到空判据(它报 1), 还会在 `narrow-layout` 上误报(它的汇总行是"窄屏布局:全部通过",里面没有数字)—— 正是 pi 提醒的"别照抄我的正则,先贴样本"。 换成两条**结构证据**: - **`--test` 不再手写**:由文件内容推导(源码里 `from 'node:test'` 就走 node:test), 清单里出现手写 `--test` 直接红 —— 配对错误不再靠记性维护; - **自检 4**:每条判据文件里必须存在"能红"的路径(`test(` / `check(` / `process.exit(1)`), 外加"跑完必须有输出"。一个都没有 = 它永远不会红,与"全通过"长得一模一样 (这是"判据自己不会跑"家族的第 6 个宿主,家族表和六种宿主都写进规范了)。 变异:清单手写 `--test` → 红;加一条"什么都不做、退出 0"的判据 → 红; 静默成功(有能红路径但一行不输出)→ 红。 ## 2 规范 §3 补一档:变异红了还要看**红在哪**(pi) "只报红了不算,要能指名红的是哪几条";**红在解析/加载失败上不算红**(先让变异 "语法正确、语义错");变异作用于被剥掉的注释也不算。 ## 3 `CRITERIA.md` 的可见性(pi 提的位置问题) 它管两个客户端的判据,却躺在 electron 的测试目录里。已在 `docs/HARMONY-ALIGN-PLAN.md` §四(验收纪律)加指针,并顺手把 pi 点名过的两条口径写死在那儿: **"未验"只能用于"步骤做过、结果没看",功能不存在必须写"没做"**; **"机制上确定不同"要判、不许记成"未验"**(深色档预设那次)。 ## 验证 `npm test` 退出码 0(12 个判据文件全绿 + vitest 258/258)。
This commit is contained in:
@ -60,6 +60,43 @@ const ALLOW = [ /* { name, replacement, why } */ ];
|
||||
顺带:变异后**不要用 `git checkout` 还原**(会连同未提交的改动一起抹掉)。
|
||||
先 `cp` 到备份,再从事先的备份还原。
|
||||
|
||||
### 变异红了,还要看**红在哪**(pi 2026-09-14 补的一档)
|
||||
|
||||
只报"红了"不算证据。反过来的那一半同样成立:**变异后红了,也可能是假红** ——
|
||||
比如变异把文件写坏了语法,判据红在"模块加载失败/解析不到源码",看起来像判据生效,
|
||||
实际那条断言根本没执行。所以:
|
||||
|
||||
- 报结果要能**指名红的是哪几条**(本仓的变异表就是按这个写的:
|
||||
"红 2 条(B + 裸色值)"、"红 3 条(含品牌色防线)");
|
||||
- **红在解析/加载失败上不算红** —— 先让变异"语法正确、语义错",再谈判据有没有生效;
|
||||
- 同理,变异**作用于注释**(被剥掉的那部分)也不算:判据读的是剥注释后的源码,
|
||||
文档里的"理由"断言才读原文(见 §4)。
|
||||
|
||||
### 判据自己不会跑:一个家族,六种宿主
|
||||
|
||||
这条家族在本仓已经露头六次,共同点都是"**看起来全绿**":
|
||||
|
||||
| # | 宿主 | 形态 |
|
||||
|---|---|---|
|
||||
| ① | `&&` 链 | 前面红一条,后面全部不跑("红"不可信) |
|
||||
| ② | 判据文件 | 没接进 `SUITE`(写好了但隐身) |
|
||||
| ③ | 清单名字 | 文件名写错 = 静默跳过一条判据 |
|
||||
| ④ | 文件末尾 | 判据写在 `process.exit()` **之后**(并发写入总往末尾追加) |
|
||||
| ⑤ | 验证手法 | 用 `node --test` 去验 runner,里面的 `process.exit(1)` 被吞(见 §6) |
|
||||
| ⑥ | runner 内部 | 清单 flag 与判据写法配错 |
|
||||
|
||||
`run-all.mjs` 现在对 ②③④⑥ 都有静态自检,⑥ 的落地方式见下(**不要**照抄"解析 pass 计数"):
|
||||
|
||||
⚠️ **实测过两条真实样本,结论与直觉不同**:
|
||||
- `node --test <自定义 check() 的判据>`:**退出码照样传出来**(文件 exit 1 → 命令行 exit 1),
|
||||
并没有被 runner 吞掉;
|
||||
- 但 `node --test <什么都不做的文件>` 会报 `# tests 1 / # pass 1` ——
|
||||
**计数不是"检查跑过"的证据**。所以"数 pass、0 就判红"既抓不到空判据(它报 1),
|
||||
又会在汇总行没有数字的判据上误报。
|
||||
|
||||
改用**结构证据**:每条判据文件里必须存在"能红"的路径(`test(` / `check(` / `process.exit(1)`),
|
||||
外加"跑完必须有输出"。**先看真实输出再写规则**——这一条本身就是 §1 的推论。
|
||||
|
||||
## 4. 读源码断言的两种模式,别混用
|
||||
|
||||
- 断**代码行为**:读**剥掉注释**的源码(注释里出现的调用不是调用);
|
||||
|
||||
Reference in New Issue
Block a user