# 项目运行时基线与“引擎版本警告”解决方案

## 1. 问题结论

本项目的 `package.json` 声明 Node.js `>=22`，而原开发环境实际使用系统 `/usr/bin/node v20.19.2` 与 `/usr/bin/npm 9.2.0`。npm 的 `EBADENGINE` 是运行 npm 的解释器版本不满足依赖声明所产生的警告；仅修改 `engines`、PATH 文档或 Vite 配置都不会改变当前解释器。

项目现在锁定 Node.js `22.23.2` 与 npm `10.9.8`，并把官方归档恢复或下载到被 Git 忽略的 `.runtime/`。启动器优先读取本机统一资源库，在线模式仅在资源库缺失时访问官方发行目录。`./npmw`、`./nodew` 和 `scripts/bootstrap-node.sh` 是项目运行时的唯一启动路径，系统 Node 不会被替换或修改。

版本与校验值来源：

- [Node.js v22.23.2 官方发行目录](https://nodejs.org/dist/v22.23.2/)
- [Node.js 官方 SHA-256 清单](https://nodejs.org/dist/v22.23.2/SHASUMS256.txt)
- [Node.js 官方发行索引](https://nodejs.org/dist/index.json)

## 2. 固定契约

| 项目 | 固定值 | 记录位置 | 目的 |
|---|---|---|---|
| Node | `22.23.2` | `.node-version`、`.nvmrc`、`config/node-runtime.env` | 规避同一大版本内的隐式差异 |
| npm | `10.9.8` | `package.json` 的 `packageManager`、`config/node-runtime.env` | 固定 lockfile 生成器 |
| Node 来源 | `nodejs.org` 官方归档 | `scripts/bootstrap-node.sh` | 下载来源可审计 |
| 完整性 | 四平台 SHA-256 | `config/node-runtime.env` | 防止缓存或代理返回错误二进制 |
| 安装目录 | `.runtime/` | `.gitignore` | 不把二进制提交到仓库 |
| 包引擎策略 | `engine-strict=true` | `.npmrc` | 误用旧 Node 时立即失败，不再静默产生警告 |
| 应用入口 | `BitBybitWebCadFacade` | `config/runtime-baseline.json` | React、Three、SQLite、OCCT 均不能绕过 Facade |

## 3. 日常操作

首次安装或依赖变化：

```bash
./npmw install
```

启动开发服务器：

```bash
./npmw run dev
```

全量校验：

```bash
./npmw run verify
```

直接查看项目解释器：

```bash
./nodew --version
./npmw --version
```

期望输出分别为 `v22.23.2` 和 `10.9.8`。第一次运行会优先从 `~/resource-library/web-freecad-bitbybit` 恢复约 30 MB 的 Node Linux x64 归档；在线且资源库缺失时才下载，后续运行复用校验通过的缓存。

## 4. 启动器的安全行为

1. 脚本按 `uname` 映射 Linux x64/arm64、macOS x64/arm64，平台不在清单内时明确失败。
2. 下载先写入 `.part` 文件，下载完成后计算 SHA-256，校验通过才原子改名为归档文件。
3. 已有缓存每次启动仍检查 SHA-256；错误缓存只删除确定的单个归档路径，不触碰仓库或用户目录。
4. 解压到 `.runtime/extract.*` 临时目录，确认 `bin/node` 存在且 `node --version` 精确等于 `v22.23.2` 后才移动到目标目录。
5. 运行时二进制和下载缓存不进入 Git；升级必须同时更新版本、四个平台校验值、lockfile 和验证记录。

## 5. CI 与发布规则

- CI 不直接调用系统 `npm`，统一使用 `./npmw ci`、`./npmw run verify`。
- CI 缓存键必须包含 Node 版本、操作系统、架构和 `package-lock.json` 哈希。
- 合并门禁先执行 `./nodew scripts/check-runtime.mjs`，再执行 Facade 边界检查、单元测试、构建和浏览器黄金测试。
- 发布产物必须记录 Node/npm、Vite、Three.js、Bitbybit OCCT、SQLite WASM 版本及 SHA-256；禁止使用 `npm install` 生成未审计 lockfile。
- Node 升级是独立变更：先在 P0-RT-01 建立双版本矩阵，再更新 `.node-version` 与校验值，最后重新生成 lockfile 和 SBOM。

## 6. 故障处理

**仍出现 `EBADENGINE`**：检查命令是否以 `./npmw` 开头；检查 `./nodew --version`。直接执行系统 `npm` 在 `.npmrc` 的 `engine-strict=true` 下应失败，这是故意的防误用信号。

**归档不可用**：先执行 `./npmw run offline:check` 检查统一资源库。在线模式可确认能访问 `https://nodejs.org`，删除确定的 `.runtime/downloads/node-v22.23.2-*` 缓存后重新执行 `./npmw install`。不要手工替换归档或跳过校验。

**架构不支持**：在当前开发机使用 Linux x64；新增平台时必须先把官方归档和 SHA-256 加入 `config/node-runtime.env`，并增加对应 CI job。

**依赖损坏**：执行 `./npmw ci` 重建 `node_modules`，不要用系统 Node 生成或修改 lockfile。

## 7. 验收证据

运行时修复的完成条件是：

- `./nodew --version` 与 `./npmw --version` 精确匹配固定值；
- `./npmw install` 无 `EBADENGINE`；
- `./npmw run verify` 中的 `check:runtime`、Facade 边界、测试和生产构建全部通过；
- Vite/tsx 子进程的 `/proc/<pid>/exe`（Linux）指向 `.runtime/node-v22.23.2-*`；
- 旧 `/usr/bin/node` 不被替换，且仓库工作区无 `.runtime` 未跟踪文件。
