# Engine Manifest Schema v2 `M6-04A` 冻结双 variant 的数据合同和纯校验器。`M6-04B` 已将生产 `web/app/public/engine-manifest.json` 切换到 schema v2,并从两个独立构建目录把资产安装到 `/vendor/blender/single/` 与 `/vendor/blender/pthread/`。纯策略选择和双环境实机加载已由 `M6-04C-G` 完成;旧 single Worker 入口继续作为 `M6-05` fallback 接线前的完整 Main 兼容路径。 ## 顶层合同 - `schemaVersion` 固定为 `2`,`protocolVersion` 固定为 `1`,`engine` 固定为 `blender-wasm`。 - `releaseId` 是整个 manifest 的原子发布身份;single/pthread 及其 JS、WASM、worker 摘要 必须作为同一份 manifest 一起切换,调用方不得从另一 release 补资源。 - `variants` 必须恰好包含一个 `single` 和一个 `pthread`,不能有第三种或重复 variant。 - single 与 pthread 的 JS URL 必须不同,WASM URL 也必须不同,避免通过通用路径隐含构建类型。 ## 资源合同 每项资源都必须声明 `fileName`、同源根路径 `url` 和小写 64 位十六进制 SHA-256: | variant | 必需资源 | 禁止资源 | | --- | --- | --- | | `single` | `resources.js`、`resources.wasm` | `resources.pthreadWorker` | | `pthread` | `resources.js`、`resources.wasm`、`resources.pthreadWorker` | 无 | JS 与 pthread worker 文件名必须以 `.js` 结尾,WASM 文件名必须以 `.wasm` 结尾;URL 的最后一段 必须与 `fileName` 完全一致。资源 URL 不允许远程 origin、query、fragment、反斜线或路径穿越。 `pthreadWorker` 表示 worker 加载角色,不强制是第四个物理文件:当前 Emscripten pthread 输出会 让 worker 重新加载同一个 pthread ES module,因此该角色可以与 `resources.js` 使用相同的 `fileName`、`url` 和 SHA-256;同一 URL 不允许声明不同摘要。worker 不得引用 single 的 JS。 若后续工具链产生独立 worker 文件,则三个字段必须描述该文件。 ## 内存合同 WASM page 固定为 65,536 bytes。每个 variant 都独立声明 `initialPages`、`maximumPages` 和 `shared`: - `initialPages` 范围为 256 至 32,768 pages,即 16 MiB 至 2 GiB。 - `maximumPages` 不得小于 `initialPages`,且不得超过 32,768 pages(2 GiB)。 - single 必须为 `shared=false`;pthread 必须为 `shared=true`。 权威 TypeScript 类型和无 I/O 校验器位于 `web/protocol/manifest.ts`;结构化正例位于 `tests/golden/M6-04A/engine-manifest-v2.json`。校验器只接收输入并返回深层新对象或抛出带稳定 `code`/`path` 的 `WebEngineManifestValidationError`,不读取文件、不请求网络,也不选择运行时 variant。 安装命令为 `bash tools/web/install-web-engine-assets.sh`。默认读取 `build_web-single` 和 `build_web-pthread`,先在临时目录生成并复核 manifest,再安装四个物理文件。专项命令 `npm --prefix web run test:engine-variant-install` 同时覆盖正常复制、同一构建目录拒绝、缺失资产 拒绝和失败不改写目标 manifest。 纯选择器位于 `web/protocol/engine-variant.ts`,策略为 `AUTO`、`SINGLE_REQUIRED` 和 `PTHREAD_REQUIRED`。它不读取 DOM、网络、存储或 Worker;调用方必须显式传入已校验 manifest 和三项线程能力。`PTHREAD_REQUIRED` 被阻断时不返回 variant。专项命令为 `npm --prefix web run test:engine-variant-selection`、`npm --prefix web run test:pthread-engine` 和 `npm --prefix web run test:single-thread-unisolated`。 升级入口为 `bootstrapWebEngineRelease`。旧 HTML 绑定的 expected release 与重新验证后的 manifest 不一致时只返回 `REFRESH_REQUIRED`,不会选择或初始化 variant,也不会打开待处理项目。资源 SHA-256 不一致统一返回 `ENGINE_VARIANT_INTEGRITY_FAILED`;该错误不可进入 pthread -> single fallback。`npm --prefix web run test:engine-upgrade-safety` 同时覆盖纯策略和真实 Chromium 篡改响应。