From 8691940505c641295dc9344e513082b2b51b3da1 Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Fri, 18 Sep 2026 07:23:31 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D:=20=E5=8F=8D=E9=9D=A2?= =?UTF-8?q?=E5=AF=B9=E7=85=A7=E7=9A=84**=E6=A0=B7=E6=9C=AC=E8=A1=A8?= =?UTF-8?q?=E8=87=AA=E5=B7=B1=E6=B2=A1=E4=BA=BA=E5=AE=88**=20=E2=80=94?= =?UTF-8?q?=E2=80=94=20=E5=88=A0=E6=8E=89=205=20=E4=B8=AA=E6=A0=B7?= =?UTF-8?q?=E6=9C=AC=E9=87=8C=E7=9A=84=203=20=E4=B8=AA=EF=BC=8C=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E8=B7=91=200=20=E6=9D=A1=20RED=E3=80=81=E9=9D=99?= =?UTF-8?q?=E9=BB=98=E7=BC=A9=E6=B0=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 我自己变异出来的(M45)。这是 `957ec5e` 新加那道防线**内部**的缺口, 而且缺口长在"**覆盖**"这件事本身上。 ## 一、缺陷:`发现规则在 N 种写法上都有对照` 当时是**散文**,不是判据 实测:把 `FORM_SAMPLES` 的 5 个样本**删掉 3 个**(只留 `function 声明` 与 `const = async`) ⇒ 默认跑 **0 条 RED**、`red` 仍是 9(与干净树逐字相同), 只是成功报文里那半句从"在 **5** 种写法上都有对照"变成"在 **2** 种写法上…"。 ⇒ 它把 N 打出来,而 **N 变小没有任何东西拦**。 而"样本齐不齐"正是这条防线**唯一的防线** —— 样本可以被悄悄删光, 防线的覆盖就静默退回到"只验我恰好留下的那一种"。 **这是"判据存在 vs 判据在路径上"的又一个变体:样本在,但"样本够不够"没有判据。** ★ 与我上一轮那条同源、但换了一层:`957ec5e` 修的是"**发现规则看不见某种写法**", 这次是"**样本表可以静默缩水**" —— 修掉前者之后,后者的存在才显出来。 **每修一层,缺口换一层**,这与 `baseline` 那条线"接缝会移动"是同一个观察。 ## 二、修法:要求清单**具名**,两个方向都判 · 列出 `REQUIRED_FORMS`(要覆盖哪些写法,**具名**); · ① 每种要求的写法都必须有样本(⇒ **删样本 = 红,并指名删的是哪一种**); · ② 每个样本都必须能被认出来(原有方向); · ③ 多出来的样本未登记进 `REQUIRED_FORMS` ⇒ 也红(加了样本却没说守哪种写法)。 ★ 为什么不用 `assert length >= 5`:那个数**自己**就是可以随手改小的常量, 改小它不会留下任何痕迹。具名清单让"我要放弃支持箭头函数写法"变成一次**看得见的声明**。 成功报文也随之带上"(要求 5 种,缺一即红)",让**要求**和**实际**同时可见。 ## 三、变异验证(都已还原) | 变异 | 结果 | |---|---| | **M45** 删掉 3 个样本 | **红**:`这些写法要求覆盖、却没有样本:箭头函数、async function、名与括号间有空格`,`red=9→10`(**修复前 0 条 RED**) | | **M46** 加一个未登记的多余样本 | **红** 2 条:`不在要求清单里` + `发现规则认不出这些写法` | | 回归:**M40/M41/M42** 箭头/async/带空格三种未接线写法 | 各 **1 条报警**(`957ec5e` 的修复未被破坏) | | 回归:**M43** 发现规则退化回窄正则 | **红**:`认不出…` | ## 四、验证与状态 · 五个自检单独跑仍全 rc=0;默认跑 `checks=459 pass=455 fail=4 skip=0 red=9 … verdict=red`、 `mutants=48 ran=47 skipped=1 on_new_criteria=35 diag=none baseline=7/7✓`; 自检段现为 `…发现规则在 5 种写法上都有对照(要求 5 种,缺一即红)`。 · 残留全清;`git status` 仅本文件;`HEAD=957ec5e`。 · 同期 pi 已把我在它插件里报的那例修好并提交 `cc8beb7`(`--self-check` 改进程内 + 默认路径先跑 + 量纲分三档)。我**复核过**它:干净树 rc=0 且自检真出现在默认路径上,变异 `findDuplicates → []` ⇒ `npm test` **rc=3** 并打出"工具坏了,不是被测代码坏了"。它的目录我一行未动。 --- client/electron/test/run-all.mjs | 36 +++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/client/electron/test/run-all.mjs b/client/electron/test/run-all.mjs index 6ab3d69..0ea5c3e 100644 --- a/client/electron/test/run-all.mjs +++ b/client/electron/test/run-all.mjs @@ -2370,6 +2370,40 @@ let selfCheckRuns = 0; ['名与括号间有空格', 'function fooSelfTest (a) {}\n'], ['const = async (…', 'const fooSelfTest = async (a) => {};\n'], ]; + /* + * ★★ **样本表本身也必须被钉住**(我自己变异出来的 M45)。 + * + * 实测:把 5 个样本**删掉 3 个**(只留 `function` 声明与 `const = async`) + * ⇒ 默认跑 **0 条 RED**、`red` 仍是 9,只是成功报文里那半句从 + * "在 **5** 种写法上都有对照" 变成 "在 **2** 种写法上…"。 + * ⇒ 也就是说 **"发现规则在 N 种写法上都有对照" 当时是散文,不是判据**: + * 它把 N 打出来,而 N 变小**没有任何东西拦**。 + * 而"样本齐不齐"正是这条防线**唯一的防线** —— 样本可以被悄悄删光, + * 防线的覆盖就静默地退回到"只验我恰好留下的那一种"。 + * **这是"判据存在 vs 判据在路径上"的又一个变体**:样本在,但"样本够不够"没判据。 + * + * ⇒ 修法:把**要求覆盖的写法**列成一份**具名的**清单(`REQUIRED_FORMS`), + * 然后两个方向都判: + * ① 每种**要求**的写法都必须有样本(⇒ 删样本 = 红,不再是静默); + * ② 每个样本都必须能被认出来(原有方向)。 + * ⇒ 删样本现在会红,而且**指名**删的是哪一种。 + * (为什么不是"断言 `length >= 5`":那个数**自己**就是可以随手改小的常量; + * 具名清单至少让"我要放弃支持箭头函数写法"变成一次**看得见的声明**。) + */ + const REQUIRED_FORMS = ['function 声明', '箭头函数', 'async function', '名与括号间有空格', 'const = async (…']; + const sampleNames = FORM_SAMPLES.map(([w]) => w); + const noSample = REQUIRED_FORMS.filter(w => !sampleNames.includes(w)); + if (noSample.length) { + console.log(`RED 这些写法**要求覆盖、却没有样本**:${noSample.join('、')}` + + ' ⇒ 覆盖静默缩水(发现规则对那种写法可能就是瞎的)'); + reds.push(`(自检)\`FORM_SAMPLES\` 缺了要求的样本:${noSample.join('、')}` + + ' —— 覆盖缩水必须看得见,不能只改一个数字'); + } + const stray = sampleNames.filter(w => !REQUIRED_FORMS.includes(w)); + if (stray.length) { + console.log(`RED 这些样本不在要求清单里(加了样本却没说是为了守哪种写法):${stray.join('、')}`); + reds.push(`(自检)\`FORM_SAMPLES\` 有多余样本未登记进 \`REQUIRED_FORMS\`:${stray.join('、')}`); + } const missed = FORM_SAMPLES.filter(([, src]) => !declaredSelfTests(src).includes('fooSelfTest')); if (missed.length) { console.log(`RED 发现规则认不出这些写法(⇒ 那种写法写了自检也不会被接线防线看见):` @@ -2404,7 +2438,7 @@ let selfCheckRuns = 0; console.log(`自检段:${SELFTESTS.length} 个自检已在**默认路径**内跑过` + `(${SELFTESTS.map(([n]) => `--${n}`).join('、')});` + `源码里 ${declared.length} 个 \`*SelfTest\` 函数**全部**在册(无"写了没接线");` - + `发现规则在 ${FORM_SAMPLES.length} 种写法上都有对照`); + + `发现规则在 ${FORM_SAMPLES.length} 种写法上都有对照(要求 ${REQUIRED_FORMS.length} 种,缺一即红)`); } }