fix(判据): 自指豁免改成"按次数"登记;标签缩回"已登记词表"并把它自己的盲区登记成欠账

pi 2026-09-14 两点,本质是同一件事:**判据自己的盲区,又成了新的"只写在某处"**。

1. **自指豁免从"整文件放行"改成"登记一个次数"**:整文件放行的后果很具体 ——
   `debt-visibility.test.mjs` 成了唯一一个"可以在里面声明边界而不被抓"的文件,
   而它恰好是定义词表的那个(将来有人在这里写一句真实的「这里没判/已知缺口」,① 不会红)。
   现在把 N=9 当普通登记值:N 处是**词表定义与报错文案**,第 N+1 处就是新边界声明 ⇒ 红。
   变异确认:在本文件里再加一处 ⇒ 红;撤回 ⇒ 绿。
   pi 那句话我照抄进注释:"用自己定义的词表数自己无意义"推出的是"**这 N 处**无意义",
   不是"**这个文件**无意义"。

2. **标签缩回断言范围**(§17 的收法一):判据名从"有边界声明就必须登记"改成
   "用**已登记词表**声明边界的文件,必须在余额里有对应的一笔(词表外的说法不在范围内)"。
   并且**词表键控这个盲区本身按我自己的新规则进了余额**:
   `boundary-vocabulary-incomplete`(已知未覆盖:`TODO`/「这里没判」/「跳过」等同义说法抓不到),
   到期前提是"发现词表外说法时扩词表并登记那一处"。
   —— 这条是被**本判据自己的分支 ③** 逼出来的:它先报"debt-visibility.test.mjs 有边界声明,
   但没有任何一笔余额的 where 指向它"。判据咬到了判据自己身上,正合其意。

余额:`debts=13 (static-only=5==登记 ✓ / other=8 by go-test)`。
This commit is contained in:
2026-09-14 17:39:47 +08:00
parent d34342b49b
commit 9fd89308ab
2 changed files with 23 additions and 8 deletions

View File

@ -31,23 +31,32 @@ const MARKERS = ['未覆盖', '未验', '已知缺口'];
const REGISTERED = new Map([
['background.test.mjs', 3], // 两条反向断言的未覆盖路(route B / route C)+ 说明
['harmony-appearance.test.mjs', 4], // bgBlur 消费侧/映射、运行期形态类边界
['harmony-logic.test.mjs', 1] // `.ets` 状态机要跑起来才算数
['harmony-logic.test.mjs', 1], // `.ets` 状态机要跑起来才算数
['debt-visibility.test.mjs', 9] // 本文件:N 处是词表定义 + 报错文案(第 N+1 处即红)
]);
const HERE = dirname(fileURLToPath(import.meta.url));
test('★ 判据目录里的“未覆盖/未验/已知缺口”声明,必须在余额里有对应的一笔', () => {
test('★ 用**已登记词表**声明边界的文件,必须在余额里有对应的一笔(词表外的说法不在本判据范围内)', () => {
const ledger = JSON.parse(prose(join(HERE, '..', '..', '..', 'docs', 'DEBTS.json')));
const wheres = ledger.debts.map(d => `${d.where || ''}`);
/*
* 自指豁免(**按文件 + 理由**):本文件**定义**了这套措辞(MARKERS 里那三个词),
* 所以它自己必然包含它们 —— 用自己定义的词表来数自己是无意义的(数出来的只会是"我提到了几次")。
* 这是"定义词表者不被该词表计数",不是"凡是判据目录都放行"。
* 自检:本条判据**第一次跑就把自己抓出来了**(11 处未登记),说明计数机制是活的。
* 本文件**也**在受判之列 —— 而且**按次数**登记,不整文件放行(pi 2026-09-14)。
*
* 我第一版给它的是"整文件豁免",理由是"用自己定义的词表数自己无意义"。这句话是对的,
* 但它推出的是"**这 N 处**无意义",不是"**这个文件**无意义":整文件放行的后果很具体 ——
* 将来有人在这个文件里写一句真实的「这里没判 / 已知缺口」,①不会红。
* 那就是 `migrate.go` 那个形状换了个落点,这次落在判据自己身上。
*
* 所以现在把 N 当成普通登记值:N 处是**词表定义与报错文案**(它们必须提到这些词),
* 第 N+1 处就是新的边界声明 ⇒ 红。
*
* **词表是采样、不是完备**(同一个词表键控的盲区):换 `TODO` / 「这里没判」/「跳过」
* 等同义说法声明同一个边界,本判据**抓不到** —— 这条盲区已登记在 `docs/DEBTS.json`
* 的 `boundary-vocabulary-incomplete`,所以在默认路径的余额里看得见,不靠记得。
*/
const SELF = 'debt-visibility.test.mjs';
const files = readdirSync(HERE).filter(f => (f.endsWith('.test.mjs') || f.endsWith('.mjs')) && f !== SELF);
const files = readdirSync(HERE).filter(f => f.endsWith('.test.mjs') || f.endsWith('.mjs'));
const findings = [];
for (const f of files) {
const src = prose(join(HERE, f));

View File

@ -54,6 +54,12 @@
"count": 1,
"due": "**第一次给导航元素加工具类模糊(Tailwind `backdrop-blur-*`)时**堵",
"where": "同上文件 —— **已知未覆盖的回滚路径**:元素级 `backdrop-blur-lg` 不在那条选择器下,变异确认过逃得掉"
},
{
"id": "boundary-vocabulary-incomplete",
"count": 1,
"due": "有人用**词表外**的说法声明边界时(`TODO`、「这里没判」、「跳过」…)——发现即扩词表,并把那一处登记;在此之前它抓不到",
"where": "client/electron/test/debt-visibility.test.mjs(词表键控的盲区:**已知未覆盖**——词表是采样、不是完备)"
}
]
}