Files
linuxcncWebWASM/docs/linuxcnc-web-wasm-execution-strategy.md

32 KiB
Raw Blame History

LinuxCNC Web/WASM 仿真项目执行与交付策略

文档状态:Draft v0.1 适用范围:本仓库的纯 Web/WASM 仿真移植、浏览器运行时、OPFS 工程存储、覆盖矩阵和发布物 固定基线:LinuxCNC 2.10.0~pre0(以 linuxcnc/VERSION 和锁定的源码提交为准) 关联文档:技术路线、完整仿真机床实施蓝图、运动学完整移植计划、仿真全功能覆盖矩阵、功能与源程序关联目录、前端与 LinuxCNC 通信详细设计、总控执行手册、上下文治理与最小任务目录

本文件是项目执行的治理入口。技术路线回答“做什么以及采用什么架构”,覆盖矩阵回答“逐项覆盖什么以及如何验收”,本文件回答“谁在什么固定上下文中交付、如何在断网或失败后接续、什么证据才能过门禁”。三份文档必须以同一基线版本更新;若规则冲突,以本文件的交付门禁和覆盖矩阵的逐项验收要求为准。

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. 文档与决策层级

文档关系固定如下:

执行与交付策略(本文件)
  ├─ 技术路线:架构、范围、阶段 A-E 和风险决策
  ├─ 覆盖矩阵:功能来源、manifest 条目、测试和逐项验收
  ├─ 源程序关联目录:功能到源文件、配置、符号和测试的反向索引
  ├─ 前端与通信设计:UI 工作流、Worker 协议、状态契约、任务和 FE/COM 里程碑
  └─ 总控执行手册:端到端依赖、统一任务目录、场景验收和当前实施状态

架构、范围或阶段发生变化时,先更新技术路线;功能条目、标记、测试或差异状态发生变化时,先更新覆盖矩阵;两者都需要同步更新本文件中的里程碑或门禁时,必须在同一变更包中完成。文档链接、基线版本和状态枚举由文档一致性检查自动校验。

2.1 全功能移植闭环

“全部功能”按可观察的仿真能力定义,而不是按成功编译的源码行数定义。功能全集由以下来源的并集规范化得到:

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 差异 → 发布签署”顺序生成。功能与源程序关联目录是来源扫描和反向索引的规范入口;发布报告必须同时给出已接受条目、排除条目、阻断条目、孤儿来源和未覆盖交互;只给出一个百分比不能作为全功能声明。

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 产物中,只通过路径和摘要引用。

启动顺序同样受预算约束:先只读取 nextTask.md 指针(不超过 8 KiB),再按当前子任务读取 context-lock.json 摘要和直接输入。docs/task-history.md、完整路线图、覆盖矩阵、coverage/*.jsonl 和完整 stdout/stderr 均为按需 L3 资料,不能在启动时批量加载。

上下文包使用固定的八段结构,逻辑预算为 8,192 tokens,UTF-8 序列化不超过 32 KiB。实现上由 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 时,上下文大小不变。

模型调用还必须显式保留输出空间:

request_input_tokens = packet_input_tokens + fixed_overhead_tokens
model_context_window >= request_input_tokens + max_output_tokens + safety_margin

请求前由 validate_model_budget.py 阻断超限;请求后还必须由 validate_provider_response 校验 provider 返回的 usage,确认 output_tokens <= max_output_tokens。若 finish_reason 为 length/max_tokens/max_output_tokens,只保存 metadata-only checkpoint 并从最新 packet 发起更小的新请求,不能把截断响应追加回下一轮。

fixed_overhead_tokens 必须由调用方按当前请求重新计数,不能把上一次请求的历史累加进去。max_output_tokens 应按任务类型固定(文档 768、feature 1,024、contract 1,536、milestone 2,048 的默认上限),而不是使用模型的最大值;调用参数只能缩小 profile 的输入/输出预算,不能放大。context_packet.py 的字节、证据文件数和令牌覆盖值同样只能缩小 profile。没有 provider tokenizer 时按 UTF-8 字节作硬上界,拿到精确令牌数后可用 --input-tokens 替换估算。输入包达到预算 80% 或模型返回 context_length_exceeded 时,先移除最低优先级证据、缩短摘要或拆分子任务;不得把旧对话和失败响应再次拼回请求。

流式调用必须由 scripts/model_stream.py 的有界 SSE 解码器消费。只有 response.completed 且 usage.input_tokens/output_tokens/total_tokens 一致、输出未超 max_output_tokens 时才标记可复用;中途断流、解码失败、response.failed、上下文超限或 response.incomplete 只生成 metadata-only checkpoint。恢复动作固定为丢弃可选证据并从新 packet 重建,禁止续接半截文本或重试同一个超大请求。

生成阶段的预算算法

证据选择必须在写入输出文件前完成,按以下顺序执行:

  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 或 E6=token_budget_exceeded 记录。若只剩必需项仍超限,失败。

排除原因使用稳定机器码,避免长文本侵占上下文: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、E6 token_budget_exceeded。输出必须包含选中证据字节数、选中/排除文件数、证据预算、总包预算、最终包字节数和排除码;CI 同时检查 packet_bytes <= byte_limit、packet_bytes + selected_evidence_bytes <= byte_limit 和 token 上限,而不是先写超限包再报告错误。

上下文包的最小机器可读形状如下;CI 应检查字段齐全、段顺序、预算、context_id 一致性和引用产物存在:

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、测试或文档只能有一个主主题;跨主题改动拆成有依赖顺序的提交。每个提交或合并请求必须声明:

Context-ID: <context_id>
Context-Packet: <packet_id>
Scope: <workstream>/<milestone>
Contract-Change: none | <ABI/schema/format/compatibility id>
Evidence: <test command or artifact paths>
Offline-Impact: none | cached-start | mid-run | recovery
Coverage: <manifest ids or paths>
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 通信详细设计。若需要直接读取另一个工作流的内部结构,应先提出契约变更(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、输入文件哈希和故障注入种子下得到相同终点。

自动接续使用以下状态机,不依赖用户手动刷新或重复点击:

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、坐标、补偿、K0-K5 运动学主线、原生 golden 受影响核心 manifest 全部 verified;每个运动学族的首个 divergent tick 可定位
M3 虚拟设备与持久化 C HAL/PLC/IO、K6 运动集成、数字孪生、事务恢复、断网接续 故障注入和恢复矩阵通过;配额不足不损坏已提交版本
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 生成器测试、validate_task_pointer.py 启动指针检查、validate_model_budget.py 请求预算检查、上下文包字段/大小检查和证据包字段检查。任何新增来源、配置、组件、G/M/O 功能或 UI 工作流没有 manifest 条目时 CI 失败。上下文包超过 8,192 tokens 或 32 KiB、启动指针超过 8 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。父任务必须按上下文治理与最小任务目录拆成单结果子任务;执行者只读取该子任务及其直接依赖,不把整份路线、覆盖矩阵或父任务历史装入上下文。任务启动时创建一个固定大小的上下文包;每次交接只更新 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 通信详细设计为实现约束。固定上下文包和提交字段由本文件第 3.2、3.3 节统一,任何后续文档若新增阶段、状态或门禁,必须在这里登记并同步关联文档。