# LinuxCNC Web/WASM 仿真项目执行与交付策略 **文档状态**:Draft v0.1 **适用范围**:本仓库的纯 Web/WASM 仿真移植、浏览器运行时、OPFS 工程存储、覆盖矩阵和发布物 **固定基线**:LinuxCNC `2.10.0~pre0`(以 `linuxcnc/VERSION` 和锁定的源码提交为准) **关联文档**:[技术路线](linuxcnc-web-wasm-technical-roadmap.md)、[仿真全功能覆盖矩阵](linuxcnc-web-wasm-simulation-coverage.md)、[功能与源程序关联目录](linuxcnc-web-wasm-source-map.md)、[前端与 LinuxCNC 通信详细设计](linuxcnc-web-wasm-frontend-communication-design.md)、[总控执行手册](linuxcnc-web-wasm-integration-playbook.md)、[上下文治理与最小任务目录](linuxcnc-web-wasm-context-governance.md) 本文件是项目执行的治理入口。技术路线回答“做什么以及采用什么架构”,覆盖矩阵回答“逐项覆盖什么以及如何验收”,本文件回答“谁在什么固定上下文中交付、如何在断网或失败后接续、什么证据才能过门禁”。三份文档必须以同一基线版本更新;若规则冲突,以本文件的交付门禁和覆盖矩阵的逐项验收要求为准。 ## 1. 治理缺口与补强决定 | 已有内容 | 缺口 | 本策略的控制措施 | 证据位置 | |---|---|---|---| | 技术路线已有 A-E 阶段 | 没有阶段退出条件、依赖关系和返工规则 | 为每个里程碑定义入口、出口、证据和阻断条件;未过门禁不得进入下一阶段 | 第 6、7 节 | | 覆盖矩阵要求 100% | `sim_status`、`web_status` 没有统一枚举,差异可能被静默接受 | 固定状态机和缺失项 CI 门禁;`REAL-EXCLUDED` 与未实现严格分离 | 第 3.4 节;覆盖矩阵第 1、13 节 | | OPFS 已有 journal 思路 | 没有断网、标签页挂起、Worker 崩溃和配额不足的接续协议 | 本地优先、事务提交、checkpoint、重放和幂等命令协议;恢复结果必须可验证 | 第 5 节 | | 固定 tick 和 golden 已提出 | 没有明确“同一上下文”的构成,难以复现差异 | 建立 context lock,提交和 golden 必须携带锁定摘要 | 第 3 节 | | 仿真与真实硬件边界已说明 | 任务容易跨越 WASM、Worker、UI 和存储责任边界 | 以工作流和接口为边界分工;跨边界改动必须有契约变更记录 | 第 4 节 | | 有原生/WASM 对照目标 | 没有统一的变更、回滚和发布证据包 | 采用小步、单主题提交;发布只消费完整证据包和签名的 manifest | 第 3.3、7 节 | 治理原则:基线可重建、仿真结果可重复、持久数据可恢复、差异可定位、排除项可识别。任何“先合并再补测试”或“离线时先静默丢弃”的做法都不满足本策略。 ## 2. 文档与决策层级 文档关系固定如下: ```text 执行与交付策略(本文件) ├─ 技术路线:架构、范围、阶段 A-E 和风险决策 ├─ 覆盖矩阵:功能来源、manifest 条目、测试和逐项验收 ├─ 源程序关联目录:功能到源文件、配置、符号和测试的反向索引 ├─ 前端与通信设计:UI 工作流、Worker 协议、状态契约、任务和 FE/COM 里程碑 └─ 总控执行手册:端到端依赖、统一任务目录、场景验收和当前实施状态 ``` 架构、范围或阶段发生变化时,先更新技术路线;功能条目、标记、测试或差异状态发生变化时,先更新覆盖矩阵;两者都需要同步更新本文件中的里程碑或门禁时,必须在同一变更包中完成。文档链接、基线版本和状态枚举由文档一致性检查自动校验。 ### 2.1 全功能移植闭环 “全部功能”按可观察的仿真能力定义,而不是按成功编译的源码行数定义。功能全集由以下来源的并集规范化得到: ```text F = docs capabilities ∪ exported/configurable behavior in src/emc, src/hal, classicladder, usr_intf and Python APIs ∪ configs/sim/** resources and workflows ∪ tests/** and unit_tests/** cases ∪ Web UI, VCP, visualization and persistence workflows ``` M0 必须冻结来源扫描和规范化规则;每个来源项至少映射到一个 manifest 条目,每个 manifest 条目必须反向列出来源、依赖、输入、输出、错误、仿真替代方案、测试和 oracle。来源项没有映射、manifest 条目没有测试、依赖没有递归闭包或新增源码未触发 manifest 变化时,CI 直接阻断。一个来源可以拆成多个功能条目,但不能把多个未验证功能合并成一个笼统的“全覆盖”。 每个功能条目都要通过六个覆盖维度:正常行为、边界/资源限制、错误和报警、暂停/恢复/急停、持久化/刷新/离线恢复、UI/API/脚本工作流;需要与其他域交互的条目还必须进入关键路径或 pairwise 交互测试。`REAL-EXCLUDED` 只允许用于真实硬件、硬实时和物理安全;任何 `configs/sim` 依赖都必须映射为可观测的 `SIM-CORE`、`SIM-ADAPTER`、`SIM-DEVICE`、`WEB-EQUIV` 或 `PY-WASM` 行,不能用排除项掩盖仿真缺口。 完整性证明按“来源扫描 → manifest 闭包 → 实现映射 → 多维测试 → 原生/WASM 差异 → 发布签署”顺序生成。[功能与源程序关联目录](linuxcnc-web-wasm-source-map.md)是来源扫描和反向索引的规范入口;发布报告必须同时给出已接受条目、排除条目、阻断条目、孤儿来源和未覆盖交互;只给出一个百分比不能作为全功能声明。 ## 3. 固定上下文与提交策略 ### 3.1 Context lock 每个可复现构建、golden 集和发布候选都绑定一个不可变的 context lock。锁至少包含以下字段,实际格式可为 `context-lock.json` 或 CI 产物: | 字段 | 要求 | |---|---| | `context_id` | 全局唯一,例如 `linuxcnc-2.10.0-pre0-wasm-c1` | | `linuxcnc_version`、`linuxcnc_source_sha` | 与 `linuxcnc/VERSION` 和源码提交一致 | | `roadmap_revision`、`coverage_revision` | 两份治理文档的提交摘要或版本号 | | `emscripten_version`、`compiler_flags` | 包括优化、浮点、异常、线程和文件系统选项 | | `python_runtime` | Pyodide/CPython-WASM 版本及包锁摘要 | | `schema_versions` | C ABI、命令、事件、快照和工程格式版本 | | `browser_matrix` | 浏览器、版本范围、操作系统和是否跨源隔离 | | `test_manifest_sha`、`golden_manifest_sha` | 输入清单及参考结果的内容摘要 | 锁定后,不能在同一 `context_id` 内悄悄升级编译器、Python、浏览器基线、schema 或 LinuxCNC 源码。升级必须创建新的 `context_id`,重新生成受影响的 golden,并在迁移说明中列出差异。 ### 3.2 固定大小的任务上下文包 “固定上下文”指每次任务交接和每次提交都重新装载一个固定格式、固定预算的上下文包,而不是把整个历史对话、全部日志或已完成阶段重新带入。上下文包是可丢弃的工作索引;完整源码、日志、golden 和差异报告留在仓库或 CI 产物中,只通过路径和摘要引用。 上下文包使用固定的八段结构,逻辑预算为 **8,192 tokens,UTF-8 序列化不超过 32 KiB**。实现上由 [`scripts/context_packet.py`](../scripts/context_packet.py) 在选择证据时执行预算;校验器不能成为第一次发现超限的地方。每段有上限,缺省内容用 `none`,不得追加自由历史段: | 段 | 固定内容 | 建议上限 | |---|---|---:| | `header` | `context_id`、`packet_id`、任务和里程碑 | 512 tokens | | `baseline` | 源码/工具链/schema/golden 摘要 | 1,024 tokens | | `scope` | 主工作流、目标、非目标、受影响 manifest ID | 1,024 tokens | | `contracts` | 仅列出本任务读写的 ABI、事件、文件和状态契约 | 1,536 tokens | | `evidence` | 已通过测试、失败测试和产物路径/哈希 | 1,536 tokens | | `risks` | 未解决风险、阻断原因和回滚点 | 1,024 tokens | | `next` | 下一步最多三项可执行动作 | 768 tokens | | `forbidden` | 本任务明确不得触碰的边界 | 768 tokens | 包的 `packet_id` 由 `context_id`、任务 ID 和修订号组成;修订只替换对应段,不复制旧包。超过任一段上限或总预算时,必须先拆分任务、生成摘要或把内容移到可寻址产物,不能扩大上下文预算。每次交接从最新包重建,旧包只保留哈希和归档链接,因此移植从阶段 A 深入阶段 E 时,上下文大小不变。 #### 生成阶段的预算算法 证据选择必须在写入输出文件前完成,按以下顺序执行: 1. 加载固定上下文骨架并计算 `skeleton_bytes`;骨架超过 `byte_limit` 立即失败。 2. 将候选证据规范化为 `path`、`bytes`、`sha256`、`kind`、`priority`、`required`,按必需、优先级、路径排序,保证选择确定性。 3. 逐项检查:单项证据字节预算、证据总字节预算、证据文件数,以及把该项加入 `selected` 后的完整上下文剩余空间;完整上下文按 `packet_bytes + selected_evidence_bytes` 计算,不能只计算 JSON 清单。 4. 可选项无法容纳时不写入包,记录稳定排除码;必需项无法容纳时直接失败,不生成部分成功包。 5. 生成最终预算元数据后再次序列化校验;若审计清单本身使包超限,从最低优先级可选项回退并以 `E5=context_remaining_bytes_insufficient` 记录。若只剩必需项仍超限,失败。 排除原因使用稳定机器码,避免长文本侵占上下文:`E1 duplicate_path`、`E2 evidence_item_bytes_exceed_budget`、`E3 evidence_file_count_exceed_budget`、`E4 evidence_bytes_exceed_budget`、`E5 context_remaining_bytes_insufficient`。输出必须包含选中证据字节数、选中/排除文件数、证据预算、总包预算、最终包字节数和排除码;CI 同时检查 `packet_bytes <= byte_limit` 和 `packet_bytes + selected_evidence_bytes <= byte_limit`,而不是先写超限包再报告错误。 上下文包的最小机器可读形状如下;CI 应检查字段齐全、段顺序、预算、`context_id` 一致性和引用产物存在: ```yaml context_id: linuxcnc-2.10.0-pre0-wasm-c1 packet_id: M2-WS1-interpreter-r07 task: "[WS-1][M2] ..." header: { milestone: M2, owner_role: runtime } baseline: { source_sha: "...", schema: { abi: 1, snapshot: 1 } } scope: { include: ["coverage/..."], exclude: ["WS-5"], manifest: ["..."] } contracts: ["sim_step", "snapshot.v1"] evidence: { passed: ["..."], failed: ["..."], artifacts: ["..."] } risks: ["..." ] next: ["...", "...", "..."] forbidden: ["real hardware", "host process", "unversioned schema"] budget: { token_limit: 8192, byte_limit: 32768 } ``` ### 3.3 提交和证据包 提交按一个可审查主题组织:运行时、持久化、组件、UI、测试或文档只能有一个主主题;跨主题改动拆成有依赖顺序的提交。每个提交或合并请求必须声明: ```text Context-ID: Context-Packet: Scope: / Contract-Change: none | Evidence: Offline-Impact: none | cached-start | mid-run | recovery Coverage: Context-Budget: 8192 tokens / 32768 bytes ``` 合并请求的证据包至少包括变更摘要、受影响 manifest 条目、测试日志、golden/difference 摘要、性能或配额影响、回滚方式和文档链接。提交正文只保存上下文包和产物摘要,不复制完整日志或历史讨论。没有 `Context-ID`、`Context-Packet`、预算声明、证据路径或覆盖条目的提交只能作为草稿,不能进入受保护分支。 ### 3.4 覆盖状态机 `sim_status` 和 `web_status` 使用同一组值: `planned` → `in_progress` → `implemented` → `verified` → `accepted`。 允许从任何非终态回到 `blocked`;`blocked` 必须填写阻断原因、责任工作流、下一步和复核日期。`REAL-EXCLUDED` 是终态,但只允许用于覆盖矩阵定义的真实硬件、硬实时和安全排除项。`accepted` 必须同时具备实现、自动测试、差异报告和 context lock;没有这些证据不得通过文字描述或 UI 状态伪装成已支持。 ### 3.5 变更分类和审查 * **C0 文档/注释**:不改变契约;文档链接和术语检查通过即可。 * **C1 行为实现**:必须更新 manifest、golden 或差异说明,并运行受影响功能域测试。 * **C2 契约/格式**:改变 ABI、消息、快照或工程格式;必须先提交迁移方案、双读/版本策略和兼容测试。 * **C3 基线/工具链**:改变 LinuxCNC、Emscripten、Python 或浏览器基线;必须新建 context lock,完整重跑基线回归。 C2/C3 变更需要运行时、测试/兼容性和存储(若受影响)三个责任角色共同审查。任何改动都不得把真实硬件能力从 `REAL-EXCLUDED` 改成普通覆盖项而不修改产品边界和安全说明。 ## 4. 工作流拆分与边界 工作流以可交付接口划分,避免按目录切割导致责任重叠。角色是责任类别,不预设具体人员。 | ID | 责任工作流 | 交付物 | 依赖 | 明确不负责 | |---|---|---|---|---| | WS-0 | 基线与清单 | context lock、来源扫描、`coverage/manifest.jsonl`、golden 索引 | 无 | 运行时实现 | | WS-1 | WASM 核心与 ABI | `sim_*` 生命周期、解释器/TP/kinematics 适配、版本化 ABI | WS-0 | UI、OPFS 事务 | | WS-2 | Worker 调度与虚拟设备 | 固定 tick、HAL、IO、故障模型、事件序列 | WS-1 | 浏览器布局和用户文件选择器 | | WS-3 | Workspace/OPFS | 虚拟 POSIX、journal、checkpoint、迁移、配额诊断 | WS-0;消费 WS-1 schema | 运动语义和 UI 状态管理 | | WS-4 | Python/插件兼容 | Pyodide 虚拟模块、remap/filter/VCP 权限和生命周期 | WS-1、WS-3 | 宿主进程、网络和设备访问 | | WS-5 | Web UI/可视化 | Worker 客户端、控制台、3D、工具和配置工作流 | WS-2、WS-3 | 改写核心算法和持久化协议 | | WS-6 | 参考运行器与测试 | 原生/WASM golden、浏览器 E2E、故障注入、差异报告 | WS-0;随各工作流增量接入 | 为失败测试降级或删除样本 | | WS-7 | 发布与文档 | 兼容报告、许可证清单、迁移说明、离线包和发布证据 | WS-0..6 | 绕过门禁发布 | 跨工作流接口只通过已版本化的 ABI、命令/事件 schema、快照 schema、工程格式和 manifest 交换;WS-2/WS-5 的具体接口、FE/COM 任务和 FE-M0..M5 退出条件见[前端与 LinuxCNC 通信详细设计](linuxcnc-web-wasm-frontend-communication-design.md)。若需要直接读取另一个工作流的内部结构,应先提出契约变更(C2),而不是复制内部状态。每个任务必须标注一个主工作流和一个里程碑;一个任务同时改动三个以上工作流时,默认拆分。 ## 5. 稳定性、断网与接续 ### 5.1 本地优先原则 已缓存的应用壳、WASM、Pyodide、样例和工程可以在无网络时启动;仿真核心、Worker、OPFS 和 UI 主流程不得把网络可用性当作前置条件。网络只用于可选更新、协作或远程调试。断网期间禁止自动覆盖已提交版本,禁止删除唯一可恢复的 checkpoint,禁止把失败写入标记为成功。 ### 5.2 故障分类与策略 | 故障 | 运行策略 | 接续依据 | 验收结果 | |---|---|---|---| | 启动时无网 | 从 Service Worker 缓存启动;缺少资源则显示明确缺件 | cache manifest、context lock | 已缓存版本可启动;未缓存依赖可诊断 | | 运行中断网 | 仿真继续按固定 tick 运行;本地命令和日志照常提交 | OPFS journal、`seq`、`simulation_tick` | 重载页面后恢复最近已提交状态 | | 标签页挂起/Worker 重启 | 在安全 checkpoint 重启并重放增量事件 | checkpoint 基线 + event log | 重放终点与连续运行一致 | | 写入中止/崩溃 | 只接受完整 commit;清理临时文件或回滚 | prepare/commit、哈希和版本索引 | 不出现半文件,不损坏旧版本 | | 配额不足 | 停止非关键 cache/日志写入,保留工程和最近 checkpoint | 配额诊断、版本保留策略 | 已提交工程可读;用户得到导出/清理动作 | | 重新联网 | 不自动重放重复命令;按摘要对账可选远程数据 | `context_id`、`seq`、`tick`、状态哈希 | 对账成功或明确冲突,不静默合并 | ### 5.3 命令、事件和快照接续协议 每条控制命令带单调递增 `seq`、`context_id`、客户端 `session_id` 和幂等键;每个事件和快照带 `seq`(最后应用的命令)、`simulation_tick`、`schema_version` 和状态哈希。恢复流程固定为: 1. Worker 读取并校验最新完整 checkpoint 和 journal;只接受哈希、版本和路径均匹配的记录。 2. 以 checkpoint 的 tick 为起点按序重放事件;遇到缺号、重复或未知 schema 时停止并报告,不猜测补齐。 3. 发布 `recovered` 事件,包含恢复到的 tick、最后提交序号、丢弃的未提交记录和差异摘要。 4. UI 只有在收到 `recovered` 后才允许继续发送依赖运行态的命令;重复提交使用幂等键返回原结果。 快照采用“完整基线 + 有界增量”策略:增量达到大小、数量或时间上限就合并为新基线。UI 偏好与仿真状态分离;恢复仿真不得依赖尚未提交的 UI 偏好。连续运行与恢复运行必须在相同 `context_id`、输入文件哈希和故障注入种子下得到相同终点。 自动接续使用以下状态机,不依赖用户手动刷新或重复点击: ```text online_ready └─ 网络/资源不可用 ─▶ offline_degraded └─ 本地资源完整 ─▶ local_continuation └─ online 事件 ─▶ reconnecting ├─ 摘要一致 ─▶ reconciled ─▶ online_ready └─ 摘要冲突 ─▶ conflict(暂停远程同步,保留本地版本) ``` `reconnecting` 使用指数退避和上限,不重复执行已确认的 `seq`;`local_continuation` 只把命令写入本地 journal,`reconciled` 后按序发送未确认摘要。出现 `conflict` 时不能自动覆盖任一版本,必须保留两个可导出的版本和差异报告。网络恢复不是仿真恢复的前提:即使永远不重新联网,已缓存资源和 OPFS 工程仍应按本地策略完成运行、暂停、快照和导出。 ### 5.4 稳定性指标 每个里程碑都记录以下指标,不以平均值掩盖长尾:Worker 周期 overrun、命令确认延迟、快照吞吐、checkpoint 写入耗时、恢复耗时、journal 未完成事务数、OPFS 错误率和 UI 主线程阻塞时间。指标必须按浏览器矩阵和场景分组;性能回归超过基线阈值时阻止发布,除非有带期限的书面例外。 ### 5.5 高效执行策略 效率优化不能改变固定 tick、事件顺序或恢复结果。执行和构建按以下规则收敛: * **按影响图测试**:提交前只运行受影响 manifest 的快速测试;里程碑运行整个功能域;M5 运行全量来源、golden、浏览器和故障矩阵。影响图由来源、契约和测试 ID 生成,不能由提交者手工缩小。 * **按 context 缓存**:构建、解析和轨迹缓存的键至少包含 `context_id`、源码摘要、工具链摘要和输入文件摘要;不同 context 不共享可能改变语义的缓存。 * **并行与串行分界**:独立 manifest、浏览器和 golden 任务可并行;同一仿真会话内的 tick、命令、HAL 和 OPFS 提交必须串行。并行只是缩短验证时间,不得引入非确定性。 * **冷热路径分离**:仿真周期只处理内存中的热点状态;OPFS、日志压缩、差异计算和完整快照在有界批次中运行。任何后台工作都必须有队列上限和取消点,不能拖慢周期或无限积压。 * **预算先测后优化**:M1 建立参考场景的周期耗时、P95/P99 Worker 延迟、内存、快照吞吐、恢复时间和 UI 帧时间基线;后续提交默认不得超过基线 20%,否则必须附 profiling、替代方案和期限明确的例外。 性能优化提交必须同时携带确定性回放结果和资源指标;只有速度变快但无法证明状态、错误和恢复一致的实现不得合并。 ### 5.6 问答、工具或执行失败后的接续 断网之外,还必须处理请求超时、回答传输中断、工具调用返回失败、工具已执行但确认消息丢失、结果校验失败和 Worker 崩溃。系统不能把“没有收到回答”当成“没有执行”,也不能把“回答失败”当成“任务失败且需要从头开始”。每个任务使用持久化任务账本记录可恢复边界: | 字段 | 含义 | |---|---| | `operation_id` | 一次任务或工具操作的稳定幂等键 | | `packet_id`、`context_id` | 恢复时必须重新装载的固定上下文 | | `phase`、`step_id` | 当前里程碑、工作流和步骤;步骤必须可重入 | | `intent_hash` | 输入、目标和契约的摘要,防止用新任务误恢复旧任务 | | `prepare_ref`、`commit_ref` | 操作前后 journal/产物引用 | | `last_verified_step` | 已验证完成的最后步骤,不以“已发送”代替“已完成” | | `status` | `running`、`retrying`、`recovering`、`awaiting_reconcile`、`completed` 或 `blocked` | 每个有副作用的步骤遵循 `prepare → execute → verify → commit`:先写入 prepare 记录,再以 `operation_id` 调用;收到结果后校验状态哈希、产物和契约,最后写 commit。重试前先查询 `operation_id` 是否已有 commit:已有则直接复用结果,只有明确没有 commit 才能再次执行。执行完成但确认丢失时进入 `awaiting_reconcile`,通过状态查询或产物哈希判定结果,禁止盲目重放。 恢复流程固定为: 1. 重新装载 context lock、最新固定大小上下文包和任务账本,检查 `intent_hash` 是否匹配。 2. 扫描 prepare/commit、工具产物、Worker 事件和 OPFS journal,建立每个 `step_id` 的 `unknown`、`verified` 或 `unfinished` 判定。 3. 已 `verified` 的步骤只引用原证据;`unfinished` 步骤从最近 checkpoint 继续;`unknown` 步骤先查询和对账,不能猜测。 4. 每完成一个步骤立即更新 `last_verified_step` 和上下文包的 `evidence/risks/next` 段;不追加历史对话,因此恢复前后仍受 8,192 tokens/32 KiB 预算约束。 5. 所有步骤完成后写入 `completed` commit,并生成可重跑的证据索引;无法安全判定时保留本地版本,进入 `blocked` 或 `awaiting_reconcile`,不得静默标记成功。 网络和回答通道都恢复后,自动接续只发送未确认的操作摘要,使用指数退避和有限重试;重复响应、重复事件和迟到响应按 `operation_id` 丢弃或关联到原结果。该机制保证在本地已提交边界内可继续执行;对外部服务不可查询、数据已发生不可逆变化或上下文摘要冲突的情况,只能保证不丢失本地证据并明确要求对账,不能伪造“恰好执行一次”的结论。 ## 6. 里程碑、依赖和退出条件 技术路线的阶段 A-E 映射到以下可审查里程碑。里程碑不是日期承诺,而是证据包边界。 | 里程碑 | 对应路线 | 关键交付 | 退出条件 | |---|---|---|---| | M0 基线锁定 | A | context lock、来源/测试清单、状态枚举、责任分工 | 清单可重建;缺项 CI 失败;文档链接和基线一致 | | M1 运行时骨架 | A | 单 Worker、固定 tick、ABI、最小 OPFS journal、Python 启动 | create/load/step/snapshot/recover ABI 测试通过;无网加载缓存样例 | | M2 核心行为 | B | G/M/O、TP、坐标、补偿、kinematics、原生 golden | 受影响核心 manifest 全部 `verified`;首个 divergent tick 可定位 | | M3 虚拟设备与持久化 | C | HAL/PLC/IO、数字孪生、事务恢复、断网接续 | 故障注入和恢复矩阵通过;配额不足不损坏已提交版本 | | M4 Web 工作流 | D | 控制台、3D、VCP/配置工具、导入导出、离线 PWA | 关键 UI 工作流在浏览器矩阵通过;键盘/触摸和刷新恢复有证据 | | M5 发布候选 | E | 全量覆盖、兼容/许可证报告、迁移工具、离线包 | 所有可计入条目 `accepted`,排除项可识别,发布门禁全绿 | 里程碑依赖单向推进:M2 不能绕过 M1,M3 不能把未版本化的核心状态写入 OPFS,M4 不能以 UI mock 替代 M2/M3 的真实状态,M5 不接受“后续补齐”的覆盖条目。发现契约或基线变化时,回退到受影响的最早里程碑并重新生成证据。 ## 7. CI、合并与发布门禁 ### 7.1 合并门禁 每个变更包至少通过:文档链接和术语检查、格式/静态检查、受影响单测、manifest 完整性检查、原生/WASM 差异测试(适用时)、离线影响场景(适用时)、`context_packet.py` 生成器测试、上下文包字段/大小检查和证据包字段检查。任何新增来源、配置、组件、G/M/O 功能或 UI 工作流没有 manifest 条目时 CI 失败。上下文包超过 8,192 tokens 或 32 KiB、出现未定义段、把旧包全文嵌入新包,均直接阻止合并。生成阶段不能产生超限包;验证阶段只能复核,不能负责裁剪。 ### 7.2 里程碑门禁 * **G0 基线门禁**:context lock 可重建,依赖和生成器版本锁定。 * **G1 行为门禁**:核心状态、canonical 输出、错误码和关键轨迹对照通过;容差写入报告。 * **G2 持久化门禁**:刷新、Worker 重启、半提交、损坏记录、迁移和配额不足场景通过。 * **G3 离线门禁**:断网启动、中途断网、标签页挂起、重新联网对账、请求超时、回答中断、工具结果丢失和 Worker 重启场景通过;没有静默丢命令、重复副作用或跳过步骤。 * **G4 覆盖门禁**:所有 `SIM-*`、`WEB-EQUIV`、`PY-WASM` 条目达到 `accepted`;`REAL-EXCLUDED` 均有明确错误和说明。 * **G5 发布门禁**:浏览器矩阵、性能预算、安全/权限审查、许可证清单、迁移和回滚演练全部有签名证据。 门禁失败时,发布候选保持原 context lock 不变;修复可以追加提交,但若改变契约或基线,必须创建新锁并重新跑受影响门禁。任何例外都必须记录范围、风险、补救责任人和失效日期,不能永久豁免。 ## 8. 任务编写与追踪规则 任务标题使用 `[WS-x][Mx]` 前缀,正文包含目标、非目标、输入契约、输出证据、依赖、风险、回滚和受影响 manifest。父任务必须按[上下文治理与最小任务目录](linuxcnc-web-wasm-context-governance.md)拆成单结果子任务;执行者只读取该子任务及其直接依赖,不把整份路线、覆盖矩阵或父任务历史装入上下文。任务启动时创建一个固定大小的上下文包;每次交接只更新 `evidence`、`risks` 和 `next` 等对应段,并递增 `packet_id`,不把历史对话或旧包拼接进来。证据候选必须交给 `scripts/context_packet.py` 预筛选,禁止手工把完整日志塞进包。任务完成不是“代码已写”,而是对应条目达到约定状态并附上可重跑命令。阻塞任务保留原上下文和失败日志的摘要及哈希;不得通过删除样本、降低容差或把 `in_progress` 改成 `REAL-EXCLUDED` 来清除阻塞。 最小任务拆分建议与技术路线第 11 节一致:先做 WS-0 的清单和 golden 格式,再做 WS-1/WS-2 的 `sim_step` 与快照,随后做 WS-3 的 WorkspaceRuntime 和恢复测试,最后接入 UI 和全量回归。每个垂直切片都必须同时包含一个正常路径、一个错误路径和一个恢复路径,避免只交付“能运行一次”的演示。 ## 9. 里程碑检查清单 里程碑评审前,负责人逐项确认: 1. context lock、源码/工具链版本和文档 revision 一致。 2. 每个任务上下文包均为固定八段结构,未超过 8,192 tokens/32 KiB,旧包只以哈希引用。 3. 新增或变更的 manifest 条目、测试 ID、golden 和差异报告互相可追溯。 4. 正常、边界、错误、暂停/恢复、断网和回答/工具失败场景均有自动化结果。 5. OPFS 已提交版本、临时文件、journal、任务账本和 checkpoint 状态可解释且可恢复。 6. 失败重试使用幂等键,已确认步骤不会重复执行,未确认步骤不会被跳过。 7. 真实硬件排除项未被误报为仿真支持,仿真数字孪生仍覆盖所需可观察行为。 8. 性能、配额、浏览器兼容和许可证风险已记录,未关闭的风险有责任人和期限。 9. 变更可按证据包中的步骤回滚,并且回滚后旧 context lock 仍可重建。 通过后,将评审记录、门禁结果和 context lock 摘要作为里程碑附件;未通过则保持里程碑开放,不发布“部分完成”的兼容声明。 ## 10. 与现有路线的落地关系 技术路线第 8 节的测试层级和第 9 节的阶段 A-E 由本文件第 6、7 节转化为可执行退出条件;覆盖矩阵第 1、2、13 节的状态、manifest、完整性和覆盖率要求由本文件第 2.1、3.4、7 节落实。OPFS 的目录、事务和快照设计以技术路线第 5 节为实现约束,并以本文件第 5 节的故障矩阵作为验收补充。浏览器 UI、Worker 通信、快照、背压、前端任务和 FE-M0..M5 以[前端与 LinuxCNC 通信详细设计](linuxcnc-web-wasm-frontend-communication-design.md)为实现约束。固定上下文包和提交字段由本文件第 3.2、3.3 节统一,任何后续文档若新增阶段、状态或门禁,必须在这里登记并同步关联文档。