fix(判据): 探针三值 + 发布候选标签 —— 顺带查出探针从写下那天起一次都没跑成过
pi 的两条"真实的洞",都落了,而且第一条当场抓到实证。 1. **探针三值**(可用 / 不可用 / 拿不准→红):`RESULT static=5 probe=ok|unknown` 把"欠账余额"和"探针是否健康"拆成两个数字。 **换完第一次运行就报 probe=unknown** —— 一查:探针调的是 `execFileSync`, 而这个文件 import 的是 `spawnSync`,**名字根本没定义**。也就是说 **探针从写下的那天起一次都没跑成过**,旧的两值设计把 `ReferenceError` 和"没有设备"一起吞掉、统一报成"设备不可用":机制在、闸门从没开过, 而它看起来完全健康。这正是 pi 描述的"恒不开闸",只是比预想更彻底。 现在:命令在但跑不成 → unknown → 红;所有候选都不存在(本机没装 hdc)→ 可判的 "没有设备工具" → false,避免没装 SDK 的机器天天假红。 附 `--probe-selftest`(只跑分类器,不跑套件)+ 变异验证(把 unknown 当"不成立"→ 红)。 2. **releaseCandidate = !gitDirty**(从展示升成标签):BUILD_INFO 现在自报 `releaseCandidate`,发布脚本在脏树时会打印"这个包不是发布候选"。 判据 `build-stamp` 断言"标签与 gitDirty 必须一致"。 **实证**:本轮我打的包正是这种情况 —— `gitDirty: true`(含着 gui-lab 未提交的 NarrowStack/index.css),`releaseCandidate: false`,日志里明确说了"不是发布候选"。 3. 附带:`criteria-hygiene` 加一条"用到 `code/prose/bytes` 就必须真的 import"。 理由是同一形状我这轮在三个文件里各犯过一次(最后一次是 `execFileSync`/`spawnSync`), 而它表现为"判据红了"(ReferenceError 抛在判据自己身上),看起来像判据失败、 不像判据写错。这条至少把最常写错的那几个名字变成明确的红。
This commit is contained in:
@ -89,3 +89,43 @@ test('★ 判据目录里不得出现裸 readFileSync(必须走 code/prose/byt
|
||||
" · bytes(path) —— 二进制(安装包等)。\n" +
|
||||
" 为什么不能裸用:读原文去判代码,会被解释性注释骗(同一个坑已经踩过两次)。");
|
||||
});
|
||||
|
||||
/**
|
||||
* ★ 用到 `lib/read.mjs` 的导出名就必须真的 import(我这轮在三个文件里各犯过一次)。
|
||||
*
|
||||
* 形状一模一样:`code(...)` / `prose(...)` 写下去,import 里却只有另一个 ——
|
||||
* 于是在**跑起来的那一刻**才炸 `ReferenceError`,而它抛在判据自己身上,
|
||||
* 看起来像"这条判据红了",不像"判据写错了"。dsh 桥那边也栽过同一形状
|
||||
* (`MODE_FULL` 没 import,而且被 `tsc | tail` 的退出码骗过)。
|
||||
*
|
||||
* 判据做法:把每个判据文件里出现的 `code(`/`prose(`/`bytes(` 收集起来,
|
||||
* 与它从 `lib/read.mjs` 实际 import 的名字比对;缺一个就红,并点名文件与名字。
|
||||
* **例外**:文件里自己定义了同名函数(本地实现)时不算缺 —— 但那种情况要显式声明。
|
||||
*/
|
||||
test('★ 用到 code/prose/bytes 就必须 import(不许靠运行时才发现)', () => {
|
||||
const EXPORTS = ['code', 'prose', 'bytes'];
|
||||
const problems = [];
|
||||
const SELF_PATH = fileURLToPath(import.meta.url);
|
||||
for (const f of criteriaFiles()) {
|
||||
// 它自己的源码里就写着 code/prose/bytes 这几个名字(EXPORTS 列表),跳过自己
|
||||
if (f === SELF_PATH) continue;
|
||||
const src = prose(f);
|
||||
if (src.includes("from './lib/read.mjs'") || src.includes("from '../lib/read.mjs'")) {
|
||||
const m = /import \{([^}]*)\} from '\.\.?\/lib\/read\.mjs'/.exec(src);
|
||||
const bound = new Set((m ? m[1] : '').split(',').map(x => x.trim().split(/\s+as\s+/).pop()).filter(Boolean));
|
||||
for (const name of EXPORTS) {
|
||||
if (new RegExp(`\\b${name}\\(`).test(src) && !bound.has(name)) {
|
||||
problems.push(`${relative(RELECTRON, f)} 用了 ${name}(…) 但没 import(已 import:${[...bound].join('、') || '无'})`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const name of EXPORTS) {
|
||||
if (new RegExp(`\\b${name}\\(`).test(src)) {
|
||||
problems.push(`${relative(RELECTRON, f)} 用了 ${name}(…) 但根本没从 lib/read.mjs import`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert.deepEqual(problems, [],
|
||||
`这些判据会以 ReferenceError 的形式红,看起来像"判据失败了",其实是"判据写错了":\n ${problems.join('\n ')}`);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user