Files
Shuery 3f11426964 feat: TS 构建管线、Spine 抓取器与 wallpapers/ 唯一真相来源
把项目从「手写 dist/」改成「wallpapers/ 是唯一真相来源,dist/ 由 pnpm build 生成」,
并补上配套的类型、门禁与抓取器。一次提交落地整条管线,因为拆开会留下不能构建的中间态。

- src/:运行时与模拟器源码(TS,strict),编译到 build/ 再拷进各分发
- tools/:build / dev / check-{syntax,paths,dist},以及抓取器与回归门禁 tools/checks/
  (.scratch/ 下那批一次性脚本移入 tools/checks/ 并入库为长期门禁)
- wallpapers/:七档壁纸的源数据 + README.md(id/音频/预设的完整规范)
- docs/adr/0005-0008:构建管线与分发拓扑、模拟器契约、自包含 sim、每骨架资源布局
- .gitignore:排除 .scratch/ 的参考资料副本(上游 spine 整仓克隆 ~1.2 GB、
  抓取侦查数据 ~680 MB)与调试转储;这些是本地调查材料,补偿会让仓库无法克隆
- 归一化 .gitignore/CONTEXT.md 行尾(工作区 CRLF、索引 LF 造成的整文件假 diff)

同时修掉三档卡住构建的未完工壁纸:
- kv45 的 meta.json 里 id 还是抓取期场景名 scene_main,经 downloader promote 正名为 kv45
- shajin / zhigengniao_juheye 的 meta.json 误用了骨架描述文件(name/spine/animations/pages)、
  且都缺 preset.template.json;现按规范重建:骨架沉到 spines/<名>/(spine-ts 按 atlas 所在
  目录解析贴图页)、补上元数据与单骨架预设,并清掉 zhigengniao 骨架里指向作者机的绝对路径
- 顺带 promote 已在 sources.yml 里的 kv46(月升之前,与兽共舞)

pnpm check 五道门全绿:10 个分发 / 7 档壁纸 / 141 处引用自包含。
2026-10-02 01:27:02 +08:00

43 lines
2.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 自包含模拟包(`pnpm build sim`)
## 问题
`pnpm dev` 需要本地 HTTP 服务才能看壁纸效果。要给别人看一版效果、要在没装依赖的机器上确认某档壁纸的样子、要归档某一版画面,都得先把服务起起来。需要一种**双击就能打开**的产物:不依赖 `pnpm dev`,不依赖任何服务器,也不依赖网络。
同时,构建入口本身也需要整理:`pnpm build name` / `single` / `collect` 在 ADR 0005 里已经写进文档,但 CLI 只认 `--single` / `--collect`;`package.json` 的 `build:all` 还引用了一个不存在的 `--all`。
## 目标
1. `pnpm build sim` 产出自包含包,`file://` 双击可开,四档分发(两个单档、两个合集)都可用。
2. `pnpm build` / `pnpm build <壁纸id>` / `pnpm build single` / `pnpm build collect` 四种范围选择都能用,且各自语义明确。
3. 自包含包的"无外部依赖"是**门禁**,不是口头承诺。
4. 已发布的 `collection-all` 产物逐字段、逐键序不变(workshopid 3604974793 / version 3)。
## 非目标
- 不做"打包成 exe / 单文件应用"——一个 HTML 文件就是交付形态。
- 不改运行时行为、不改已发布产物的资源落点。
- 不做 Service Worker / 本地代理绕过 `file://` 限制。
## 约束
- `file://` 下 `origin` 为 `null`:ES module、`fetch`、`XHR` 全部被 CORS 拒绝;只有内联 `<script>` 与 `data:` URL 可靠。
- 发布产物仍须是 ES module(它走 HTTP),自包含包是**同一批源码的另一种装载形态**,不是另一套代码。
- 音频默认内联(`xilian-src.flac` 37.7 MB → base64 50.3 MB),可用 `--no-embed-audio` 关闭。
## 验收
- `tools/checks/verify-sim-page.mts <分发目录名>`:CDP 以 `file://` 打开,断言画布有实际像素、0 异常、0 控制台报错、音频是 `data:` 且可解码、无 `http(s)` 请求、模拟器面板在。
- `tools/checks/test-sim-gate.mts`:向页面注入四种外部依赖,确认 `check:dist` 每种都拦得住。
- `tools/checks/diff-project.mts`:`collection-all/project.json` 与已发布基线(`.scratch/published-project.json`)逐字段比对、键序比对。
- ~~`.scratch/compare-presets.mts`~~:所有资源引用解析到同一份内容(SHA-1)。
它是**重构等价性**的一次性对拍,基线是整份旧 dist 拷贝(96.9 MB)。重构结束后基线已按
`.gitignore` 的约定删除,脚本一并移除。引用完整性现在由 `check:paths` + `check:dist` 常态覆盖
(每处引用都能解析、音源声明无孤儿文件),不再依赖旧基线。
## 相关 ADR
- ADR 0005:分发拓扑与构建入口(本工作把文档里的 `pnpm build name` 真正实现)
- ADR 0006:模拟器契约(自包含包复用同一份模拟器与驱动生成器)
- ADR 0007:自包含包本身(两个根、表的两族键、门禁的剥除细节)