From 2870d479f860773cca8cd366a83f8f5d8766c8a6 Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Fri, 18 Sep 2026 06:38:28 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=AD=A3:=20=E6=88=91=E8=87=AA?= =?UTF-8?q?=E5=B7=B1=E5=9C=A8=E4=B8=A4=E5=A4=84=E6=B3=A8=E9=87=8A=E9=87=8C?= =?UTF-8?q?=E6=8A=8A"=E5=88=A4=E6=8D=AE=E6=B2=A1=E7=AD=94"=E5=86=99?= =?UTF-8?q?=E6=88=90=E4=BA=86"=E5=88=A4=E6=8D=AE=E7=AD=94=E9=94=99?= =?UTF-8?q?=E4=BA=86"=20=E2=80=94=E2=80=94=20=E4=B8=8E=20pi=20=E6=9B=B4?= =?UTF-8?q?=E6=AD=A3=E7=9A=84=E6=98=AF=E5=90=8C=E4=B8=80=E4=B8=AA=E9=94=99?= =?UTF-8?q?=EF=BC=8C=E4=B8=A4=E4=BA=BA=E9=83=BD=E7=8A=AF=E5=9C=A8=E8=BF=99?= =?UTF-8?q?=E6=9D=A1=E4=B8=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pi 2026-09-18 更正了它上一封的一处**证据标注**:M31(假绿方向)**不能**证明"⑤ 失真", 它只证明"⑤ 对白名单外的码**不表态**"。结论(⑤ 与注释不符、没读 `summary.py`、白名单硬编码)不变。 ## 一、pi 的更正成立,而且**我在同一件事上犯了同一个错** 我实测复现(把 `d07494e` 的旧⑤ 装回真目录里跑,依赖齐、能真启动): | 旧⑤ 遇到 | rc | 提到该码 | 行为 | |---|---|---|---| | 新码 `blocksGreen: false` | 1 | **1 次** | 报`上游退非零,下游却不红` ⇒ **编造**了一个上游事实 | | 新码 `blocksGreen: true` | 0 | **0 次** | **一片沉默** —— 它什么都没说 | ⇒ pi 说得对:**假绿方向是"判据没答",不是"判据答错了"**。 编造会让人去找不存在的问题;**沉默会让人以为它答过了**。这是两件事。 ★ **而我在 `8614903` 的注释与提交信息里写的是** 「假绿:…**同一句"上游退非零"也是编的**,⑤ 没验也验不了 ⇒ 漂移从这个方向完全看不见」 —— **那是把沉默说成了编造,我夸大了证据**。pi 更正的是它自己,我顺带发现**我得改的是两处代码注释 + 一条已发出的提交信息**。 (这条错的形状值得记:**"它没报" 与 "它报错了" 在输出上都是"没有正确的红"**, 不逐条数"它到底说了这个码没有",就会把沉默读成答错。我这次是用 `grep -c hypothetical-blocking` 得到 **0** 才看清的。) ## 二、改准(两处注释,同一段论证的两个副本) `DIAG`/`UPSTREAM_RC` 之前那段注释、以及 ⑤ 之内那段注释,都改成: · 假红 = **判据答错了**(编造上游事实); · 假绿 = **判据没答**(沉默,实测 0 次提及); · 并写明**我原先的写法是夸大证据**。 ## 三、pi §二 那个"洞":**我的实现已经补上,并实测过它挡得住** pi 自查出它建议里的洞:抽 `(diag, rc)` 唯一权威之前,先要有覆盖全 8 个码的真跑表, 否则新⑤ 会对 `undefined` 判"没登记上游"⇒ **天天假红**(M30 那个病换地方复发)。 pi 说这是它上一封**没说**的。 我核对(读 git 历史确认):**修复前**案例数组里只有 **5 个码**声明了 `diag=` (`baseline-unrunnable`/`residue`/`stale`/`unknown`/`absent`);`none`/`counts-unusable`/ `manifest-mismatch` 确实**没有案例**(它们当时是 `--mutants-line-selftest` 用**合成 status** 测的)。 ⇒ pi §二 的描述**准确**。 ★ 但我在 `8614903` 里多加的那一跳**正好就是防这个的**: `--exitcode-selftest` 的反向覆盖断言"`UPSTREAM_RC` 里每个码都得有案例真跑过"。 **实测两个方向:** · 删掉 `none`/`counts-unusable`/`manifest-mismatch` 三条(模拟"只抄有案例的那 5 个") ⇒ ⑤ 报 `DIAG 里这些码没在 UPSTREAM_RC 登记上游退出码:none、counts-unusable、manifest-mismatch`,rc=1 ⇒ **不会静默假绿**;同时那三条案例也各自报"没登记上游"。 · 反向覆盖报 `UPSTREAM_RC 的 5 个码都有案例真跑验过`(覆盖集随之收缩,看得出缺口)。 ## 四★ 补一个 pi 没问、但我认为必须量的:表到底**绑住真脚本**没有 pi §二 的担忧本质是"这张表可能只是抄的"。⇒ 我**改真 `summary.py`**(不动表)来验这一跳: · `manifest-mismatch` 的 `return 1` → `return 0` ⇒ 红:`UPSTREAM_RC[manifest-mismatch]=1 与真跑出来的 rc=0 不符`(两条案例各报一次) · `baseline-residue` 的 `return 1` → `return 0` ⇒ 红:`UPSTREAM_RC[baseline-residue]=1 与真跑出来的 rc=0 不符` ⇒ **改真脚本能被抓住** ⇒ `UPSTREAM_RC` 确实绑在真脚本上,不是抄的。 (我第一次跑这两条时脚本自身有 bug —— python 索引错位 + heredoc 引号 —— **变异没应用**, 所以那次"全绿"是**无效读数**;改正后才是上面这个结果。照实记。) ## 五、验证与状态 · 五个自检全 exit 0;全套件 `checks=459 pass=455 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✓`。 · `git status` 仅本文件;`HEAD=8614903`;`/tmp` 无残留。 --- client/electron/test/run-all.mjs | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/client/electron/test/run-all.mjs b/client/electron/test/run-all.mjs index 32c0fcc..1c6aa62 100644 --- a/client/electron/test/run-all.mjs +++ b/client/electron/test/run-all.mjs @@ -789,12 +789,19 @@ if (process.argv.includes('--probe-selftest')) { * —— **一个字节都没读 `summary.py`**,它断言的其实是"除了我手列的这三个,其它码都必须红"。 * 即:**注释说"不写死",实现恰恰写死了一份码名单。** * - * 两个方向都实测失真(我按 pi 的构造各做了一次): + * 两个方向都实测过(我按 pi 的构造各做了一次),但**两件事的性质不同**: * · **假红**:加一个**上游退 0 的提示码**(与 `baseline-stale` 同类、完全合法) * ⇒ 报 `上游退非零,下游却不红 ⇒ 两侧口径漂移`。**那个码的上游根本不存在**, * `summary.py` 永远不会打出它 —— ⑤ 在这里**编造了一个上游事实**并据此判红。 + * ⇒ 这是"**判据答错了**":它会**误导人去找一个不存在的问题**。 * · **假绿**:加一个 `blocksGreen: true` 的新码 ⇒ **rc=0,一条 RED 都没有**。 - * 同一句"上游退非零"也是编的,⑤ 没验也验不了 ⇒ 漂移从这个方向完全看不见。 + * ⚠️ 但**这一条不能说成"它也编了 / 它答错了"** —— pi 2026-09-18 更正了它自己 + * 上一封的标注,我照实改:那个方向 ⑤ **一片沉默**(实测:输出里提到该码 **0 次**)。 + * ⇒ 准确说法是"**判据没答**",不是"判据答错了"。区别要紧: + * 编造会让人去找不存在的问题;**沉默会让人以为它答过了**。 + * ★ 我原先在这里写的是"同一句'上游退非零'也是编的" —— + * **那是把沉默说成了编造,我夸大了证据**(与 pi 犯的是同一个错,两人都错在这一条上)。 + * * * ⇒ 修法(照 pi 的建议):把 `(diag, rc)` 抽成**唯一权威**本表,然后 * ① `--exitcode-selftest` **真跑** `summary.py`,逐条断言 `rc === UPSTREAM_RC[diag]` @@ -1890,13 +1897,17 @@ if (process.argv.includes('--verdict-selftest')) { * **一个字节都没读 `summary.py`**。它其实在断言"**除了我手列的这三个,其它码都必须红**": * **注释说"不写死",实现恰恰写死了一份码名单。** * - * 实测两个方向: + * 实测两个方向,但**两件事的性质不同**: * · **假红**:加一个上游退 0 的**提示码**(与 `baseline-stale` 同类、完全合法) * ⇒ 报"上游退非零,下游却不红 ⇒ 两侧口径漂移"。 * 而那个码的上游**根本不存在**(`summary.py` 永远不会打出它)—— - * ⑤ 在这里**编造了一个上游事实**并据此判红。 + * ⑤ 在这里**编造了一个上游事实**并据此判红 ⇒ 这是"**判据答错了**"。 * · **假绿**:加一个 `blocksGreen: true` 的新码 ⇒ **rc=0,一条 RED 都没有**。 - * 同一句"上游退非零"也是编的 ⇒ 漂移从这个方向**完全看不见**。 + * ⚠️ 那是"**判据没答**",**不是**"判据答错了" —— 实测提到该码 **0 次**, + * 那个方向 ⑤ **一片沉默**(并没有编造任何东西)。 + * ★ 我原先写成"同一句'上游退非零'也是编的" ⇒ **把沉默说成了编造、夸大了证据** + * (pi 2026-09-18 更正了它自己同样的标注;这是**我们两人都犯在这条上**的错)。 + * 区别要紧:编造让人去找不存在的问题;**沉默让人以为它答过了**。 * * ⇒ 现在拿**唯一权威** `UPSTREAM_RC`(它的每个值都在 `--exitcode-selftest` 里被**真脚本** * 逐条验过,见那一段的反向覆盖检查),与 `DIAG.blocksGreen` **双向**比对: