# `tools/checks/` — 验收套件 跑一遍就相当于"这次改动没把东西弄坏"的全部证据。它原来是散在 `.scratch/` 里的, 而 `.scratch/` 按 `AGENTS.md` 是**问题与规格**的存放处——这些脚本不是某条 issue 的产物, issue 关掉之后还要一直跑,所以搬到了这里。 --- ## 怎么跑 它们的前置条件不一样,**不能一条命令全跑完**。按下面三组来: ### ① 不需要服务器 ```bash pnpm check # 类型 + 构建 + 语法 + 路径 + 产物自包含 + 游戏合集文案归属 pnpm build sim # 下面几项要 sim 产物 node tools/checks/test-sim-gate.mts # 门禁真的会拦(往页面注入四种外部依赖) node tools/checks/test-inline-guard.mts # 内联 # 自包含包 file:// 可用(含"零 http 请求") node tools/checks/verify-static-preview.mts <分发名> # 静态托管子路径可用(自带服务器) node tools/checks/read-audio-tags.mts # 读音频文件自带标签(核对歌名用) node tools/checks/check-sim-scripts.mts [页面] # 抽出自包含页的每个内联 script 单独语法检查 node tools/checks/check-downloader.mts # 抓取器:能编译 + 夹具绿 + 四处破坏必红(不联网) node tools/checks/verify-scene-player.mts # 场景播放器:多骨架+平面合成、画面非空、atlas 指错必红 ``` `verify-scene-player` 自己跑 `tsc -p tsconfig.runtime.json` 并自造夹具(用抓取器 staged 的 `kv45/scene_main` 与 `nico-tea/scene_main`——staging 是"一个场景一个壁纸目录"), **不碰 `wallpapers/`、不需要 `pnpm build`**;前置只有 `python -m tools.downloader fetch --page kv45`。 `verify-static-preview` 需要 `pnpm build --with-sim`(面板要随产物走)。 ### ② 需要 `serve.mjs`(对拍驱动 `window.__test` 只有它注入) > ⚠ **跑 `test-inline-guard` 之前必须先停掉 `pnpm dev`。** 它会故意把 `src/vendor/spine-player.js` > 改坏来验证守卫,而调试服的热更新正在监听 `src/`——两者会抢构建,结果随机失败。 > 同理,任何会写 `dist/` 的构建都别和 watcher 同时跑(`pnpm build sim` 与 watcher 也会抢 `dist/`)。 ```bash node tools/serve.mjs 8190 --root dist/releases/collection-all # 另开一个终端 node tools/checks/test-props.mjs # bgm 选择/回落 + fps 限流 node tools/checks/test-resize.mjs # 改窗口尺寸不泄漏、不跑偏 node tools/checks/test-acceptance.mjs # 体积/文案/音源/构图总验收 node tools/checks/verify-fitter.mjs # viewport-fitter 的纯函数 ``` ### ③ 需要 `pnpm dev`(模拟器面板) ```bash node tools/dev.ts --port 5173 --no-build # 另开一个终端 node tools/checks/smoke-dev.mts 5173 # 路由、注入、越界 404 node tools/checks/smoke-sim.mts http://127.0.0.1:5173 # 面板真的挂上、属性真的下发 node tools/checks/verify-panel.mts http://127.0.0.1:5173 # 面板还原度(12 组) node tools/checks/verify-hot-reload.mts http://127.0.0.1:5173 # 改 CSS 只换样式表、改 runtime 整页刷新 node tools/checks/check-single-bgm.mts http://127.0.0.1:5173 # 单档分发里切歌真的换音源 node tools/checks/shot-panel.mts http://127.0.0.1:5173 [输出目录] # 给面板出图(不是断言) ``` `verify-dev-flags.mts` 要**另一个模式**:先 `node tools/build.ts --with-sim`, 再 `node tools/dev.ts --port 5173 --no-build --with-sim`,然后 `node tools/checks/verify-dev-flags.mts`。它验的是"热更新重建后 `--with-sim` 还在"。 `verify-visual-equivalence.mts` 要两步:先用 `tools/capture.mjs` 拍到 `tools/shots/visual-current/`,再跑它。基线在 `tools/shots/baseline-pre-refactor/`, **不能重新生成**。 --- ## 两层,以及为什么 | 后缀 | 是否被 `pnpm typecheck` 检查 | 说明 | | --- | --- | --- | | `.mts` | ✅ 走 `tsconfig.checks.json` | 后来写的验收脚本 | | `.mjs` | ❌ | 四个早期的运行时测试:`test-acceptance` / `test-props` / `test-resize` / `verify-fitter` | `tsconfig.checks.json` 只关掉 `noImplicitAny` 一项,其余严格模式照旧—— 正是严格模式翻出了 28 处真问题(可能 undefined、`[]` 推成 `never[]`、`catch` 里 `error` 是 unknown、 参数个数不符),其中一条是"文件头声明了 ⑤ 但从未实现的断言"。 **往 `.mjs` 里写类型注解会让它运行时崩。** `.mjs` 是纯 JS,`(x: string) => …` 是 SyntaxError, 而 `tsc` 不管 `.mjs`,所以这个错在类型检查里完全看不见——踩过一次。 要写类型就先改成 `.mts`。 > 把那四个 `.mjs` 也并进受检层是一件独立的、该单独做的事:实测会立刻多出约 80 处既有问题。 > 别在别的改动的尾巴上顺手做。 --- ## 约定 - **一个从不失败的检查等于没有检查。** 门禁类的脚本(`test-sim-gate` / `test-inline-guard`) 都要"先证明它会红"——注入一个坏东西,确认它报错,再还原。 - **验证要先检查前置条件。** `verify-dev-flags.mts` 第一件事是 `fetch("/")` 断言服务活着; 否则"服务没起来"会被当成"验证通过"——这是真实发生过的一次空验证。 - **区分"选项在"和"能生效"。** `verify-panel.mts` 断言面板上有那个下拉; `check-single-bgm.mts` 断言选了之后 `