test(criteria): 规范补两条 + 还原纪律改写成"先固化基线再破坏"
pi 三条增量的第三条(纠正我的写法)与配套文档: ## 1 还原纪律:禁令 → 操作顺序(pi 纠正) 我原来写的是"变异后不要用 `git checkout` 还原"——**治症不治因**。真因是 **被还原到的那个状态还没提交**(我丢的是一个刚加、尚未提交的 marker)。 可执行的形状: > **任何破坏性还原,都要求"将被还原到的那个状态已经在某个提交里"。** 所以:**变异前先把基线提交掉**;更稳就 `git worktree add` 一个干净副本去变异。 `cp` 备份仍然可用,但它依赖"人记得备份",顺序改对了则不依赖记性 —— 与"记得打 marker"改成"计数写在 `check()` 内部"是同一招。 本提交自身就是这条纪律的示范:先提交 `ec90cba`(helper + 移植 + 错误信息)作为基线, 再在已提交的基线上做 marker 变异验证。 ## 2 共享 helper 与"失败信息自带修法"写进 §6.6 - `test/lib/checks.mjs` 的存在理由与用法(计数只可能在该模块内发生 → 漏 marker / 计数写错位置在新判据上不可能发生); - **失败信息要自带修法**:red 是那个人一定会看到的东西,文档不一定被打开。 验证方式也记了:真删掉一条判据的 marker 行跑一遍,确认错误信息能照抄执行 (已验:输出里给了 helper 用法与样板文件路径,且 `node:test` 的判据不用管)。 ## 3 规范自检关键词 7 → 9 新增 '已经在某个提交里'、'自带修法',防止这两条被删掉还不报错。 ## 验证 `npm test` 退出码 0(12 个判据文件全绿 + vitest 258/258)。
This commit is contained in:
@ -57,8 +57,19 @@ const ALLOW = [ /* { name, replacement, why } */ ];
|
|||||||
变异没红有两种可能,都要查清:一是判据没覆盖,二是**变异没真的生效**
|
变异没红有两种可能,都要查清:一是判据没覆盖,二是**变异没真的生效**
|
||||||
(本仓真发生过:变异脚本的锚点不匹配、缩进不对,于是"变异后依然全绿"被当成判据有效)。
|
(本仓真发生过:变异脚本的锚点不匹配、缩进不对,于是"变异后依然全绿"被当成判据有效)。
|
||||||
|
|
||||||
顺带:变异后**不要用 `git checkout` 还原**(会连同未提交的改动一起抹掉)。
|
**还原纪律(pi 2026-09-14 纠正了我的写法,这条更好用)**:
|
||||||
先 `cp` 到备份,再从事先的备份还原。
|
我原来写的是"变异后不要用 `git checkout` 还原"——**那是治症不治因**。
|
||||||
|
真因是:**被还原到的那个状态还没提交**,于是 `checkout` 把未提交的改动一起抹掉了
|
||||||
|
(我丢的是一个刚加、尚未提交的 marker)。
|
||||||
|
可执行的形状是改**操作顺序**,而不是记一条禁令:
|
||||||
|
|
||||||
|
> **任何破坏性还原,都要求"将被还原到的那个状态已经在某个提交里"。**
|
||||||
|
|
||||||
|
- 所以:**变异前先把基线提交掉**(哪怕是个很小的提交)。之后 `git checkout -- <文件>`
|
||||||
|
只可能还原到已提交状态,不会连带抹掉未提交的东西;
|
||||||
|
- 要更稳就 `git worktree add` 一个干净副本,在副本里变异,主工作区完全不碰;
|
||||||
|
- 备份(`cp` 到 `/tmp/*.bak`)仍然可以,但它靠的是"人记得备份"——顺序改对了则不依赖记性。
|
||||||
|
这跟"记得打 marker"改成"计数写在 `check()` 内部"是同一招。
|
||||||
|
|
||||||
### 变异红了,还要看**红在哪**(pi 2026-09-14 补的一档)
|
### 变异红了,还要看**红在哪**(pi 2026-09-14 补的一档)
|
||||||
|
|
||||||
@ -160,8 +171,33 @@ console.log('主题:通过'); // 有输出
|
|||||||
—— 上面那个反例的 `pass` 会是 0,正是靠这一条才有分辨力。
|
—— 上面那个反例的 `pass` 会是 0,正是靠这一条才有分辨力。
|
||||||
|
|
||||||
> ⚠️ 本节的作者在写完之后**又踩了一次 §3 那条**:变异验证时用 `git checkout -- <文件>`
|
> ⚠️ 本节的作者在写完之后**又踩了一次 §3 那条**:变异验证时用 `git checkout -- <文件>`
|
||||||
> 还原,把尚未提交的改动(刚加的 marker)一起抹掉了。**规矩写下来不等于会遵守**;
|
> 还原,把尚未提交的改动(刚加的 marker)一起抹掉了。**规矩写下来不等于会遵守** ——
|
||||||
> 变异前先 `cp` 备份,从备份还原。
|
> 所以 §3 已经把那条禁令改写成"**先固化基线、再破坏**"的操作顺序(pi 指出真因是
|
||||||
|
> "被还原到的状态还没提交",不是 `checkout` 这个命令有罪)。
|
||||||
|
|
||||||
|
### 共享 helper:`test/lib/checks.mjs`(新判据请用它)
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { check, finish } from './lib/checks.mjs';
|
||||||
|
|
||||||
|
check('这条判据的名字', 条件, '失败时给人看的细节');
|
||||||
|
finish('标签'); // 打汇总 + `RESULT pass=N fail=M`,有失败则退出码 1
|
||||||
|
```
|
||||||
|
|
||||||
|
计数只可能发生在这个模块内部,所以用它以后:
|
||||||
|
**漏打 marker** 与 **计数写错位置**(导致 `check` 实现被改空也看不见)这两类
|
||||||
|
在新判据文件上**不可能发生** —— 不用再靠记性。
|
||||||
|
`markdown-xss` / `narrow-layout` 已改用它;其余 10 条保持原写法(`run-all` 的 marker 检查已覆盖)。
|
||||||
|
|
||||||
|
### 失败信息要**自带修法**(pi 2026-09-14)
|
||||||
|
|
||||||
|
受众不只是读过这份规范的人:并发写 WebUI 的 agent 新加判据时**不会打开这份文件**,
|
||||||
|
看到套件红的第一反应很可能是"套件坏了" → 删自检或往清单里塞豁免。
|
||||||
|
所以 `run-all.mjs` 现在在"没找到自报条数""条数掉了"这两条错误里直接写出
|
||||||
|
**可照抄的修法**与样板文件路径。
|
||||||
|
|
||||||
|
> 原则:**red 是那个人一定会看到的东西,文档不一定被打开** —— 错误信息是最省成本的交接面。
|
||||||
|
> (验证方式:真删掉一条判据的 marker 行跑一遍,确认错误信息能照抄执行。)
|
||||||
|
|
||||||
## 7. 判据要钉用户真正会点的那一层
|
## 7. 判据要钉用户真正会点的那一层
|
||||||
|
|
||||||
|
|||||||
@ -49,7 +49,7 @@ if (!existsSync(CRITERIA_DOC)) {
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
const criteriaDoc = readFileSync(CRITERIA_DOC, 'utf8');
|
const criteriaDoc = readFileSync(CRITERIA_DOC, 'utf8');
|
||||||
for (const must of ['配对/解析', 'allow-list', '变异验证', '剥掉注释', '按行', '自报条数', '只支撑你看到的那一层']) {
|
for (const must of ['配对/解析', 'allow-list', '变异验证', '剥掉注释', '按行', '自报条数', '只支撑你看到的那一层', '已经在某个提交里', '自带修法']) {
|
||||||
if (!criteriaDoc.includes(must)) {
|
if (!criteriaDoc.includes(must)) {
|
||||||
console.error(`✗ 判据规范里少了「${must}」这条 —— 规则被删掉了还是搬走了?`);
|
console.error(`✗ 判据规范里少了「${must}」这条 —— 规则被删掉了还是搬走了?`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
|||||||
Reference in New Issue
Block a user