# LinuxCNC Web/WASM 完整仿真移植实施计划 **版本**:1.0 **状态**:implementation baseline **目标基线**:仓库 `context-lock.json` 锁定的 LinuxCNC 版本 **接续入口**:[`nextTask1.md`](../nextTask1.md) **已有专项资料**: - [`linuxcnc-web-wasm-full-port-implementation.md`](linuxcnc-web-wasm-full-port-implementation.md) - [`linuxcnc-web-wasm-simulation-coverage.md`](linuxcnc-web-wasm-simulation-coverage.md) - [`linuxcnc-web-wasm-source-map.md`](linuxcnc-web-wasm-source-map.md) - [`linuxcnc-web-wasm-frontend-communication-design.md`](linuxcnc-web-wasm-frontend-communication-design.md) - [`linuxcnc-web-wasm-kinematics-migration-plan.md`](linuxcnc-web-wasm-kinematics-migration-plan.md) 本文件是“完整仿真移植”实施轨道的唯一执行目录。仿真实现不依赖 release、owner、许可证审批或发布候选流程;这些内容不参与仿真任务的排队、执行和验收。 ## 1. 目标和边界 ### 1.1 目标 在浏览器 Dedicated Worker 中运行 LinuxCNC 的可观察仿真行为,使用 WASM 承载数值密集型核心,使用 Web API 承载工程、恢复、界面和可视化。用户应能: 1. 导入或创建一个 LinuxCNC 仿真工程。 2. 解析 INI/HAL/工具表/参数/程序/Python/VCP/ClassicLadder 等资源。 3. 启动仿真并看到确定性的 `READY`、`RUNNING`、`PAUSED`、`ESTOP`、`FAULT`、`STOPPED` 状态。 4. 执行 G-code、MDI、jog、home、pause、resume、single-step、abort、override 和模式切换。 5. 观察轴/关节/姿态/轨迹、HAL pin/signal、主轴、工具、探针、限位、冷却、报警和 Python/VCP 状态。 6. 注入故障、暂停、导出 checkpoint、刷新 Worker、从 OPFS 恢复并得到相同的确定性终点。 7. 对纳入范围的 `configs/sim` 入口给出 `READY` 或可定位的 `BLOCKED/ERROR`,不静默跳过资源。 ### 1.2 仿真范围 以下行为必须实现或有原生/WASM 对照证据: | 功能域 | 必须覆盖的行为 | 浏览器实现边界 | |---|---|---| | 工程与配置 | workspace、INI/include/变量、HAL、工具表、参数、程序、Python、VCP、ClassicLadder、资源错误 | `/workspace` 虚拟文件系统;禁止宿主绝对路径、`..`、符号链接逃逸 | | Task/命令 | mode、MDI、program load/run/pause/resume/step/abort、错误、状态、operation ledger | Worker 单写者;主线程只能发送版本化命令 | | 解释器 | G/M/O words、模态、单位、坐标、参数、子程序、循环、宏、过滤器和错误行号 | 运行在 WASM/Python Worker;能力拒绝必须稳定 | | TP/motion | canonical queue、直线/圆弧/同步运动、速度/加速度/jerk、blend、exact stop、暂停和恢复 | 逻辑 tick 取代硬实时墙钟,保持顺序和结果确定 | | 运动学 | trivkins、gantry/CoreXY、5/6 轴、TRT、机器人、Delta/Tripod/Hexapod/Pentapod、switchkins/userk | 静态链接、注册表选择;动态模块加载不进入浏览器 | | 轴/关节 | joint/axis 映射、home、软限位、following error、外部偏置、jog、override、estop | 由数字孪生提供输入和故障状态 | | HAL/组件 | pin、signal、parameter、thread、function、addf、setp、net、twopass、`.comp` 静态组件 | 组件不得访问宿主设备、进程、网络或动态库 | | PLC/IO | ClassicLadder scan、寄存器、定时器、计数器、数字/模拟 IO、采样、触发、背压 | 虚拟寄存器和逻辑设备;真实 transport 为 `REAL-EXCLUDED` | | 设备数字孪生 | 主轴、编码器、探针、限位、home、换刀、冷却/润滑、故障/延迟/抖动 | 故障注入必须可记录、回放、恢复,不使用未固定的随机数 | | Python/remap/VCP | 白名单模块、参数/工具/INI API、remap/filter 生命周期、VCP pin/回调/异常 | Pyodide Worker;`subprocess/socket/device files` 明确拒绝 | | 持久化/恢复 | journal、checkpoint、snapshot、event replay、Worker restart、OPFS quota、migration、rollback、offline | OPFS 只保存已提交数据,不参与运动计算 | | Web 工作流 | 编辑器、MDI、控制台、HAL/PLC 面板、报警、恢复向导、轨迹和机床可视化 | UI 只消费 authoritative snapshot/event,不反写核心状态 | ### 1.3 明确排除 以下是宿主能力排除,不是仿真行为排除: - 真实 PCI/USB/串口/GPIO/并口、真实伺服和真实安全回路。 - Linux PREEMPT_RT、内核线程、共享内存 NML/CMS 进程边界、`fork/exec` 和动态 `.so` 加载。 - 浏览器无法提供的设备文件、任意宿主路径、任意网络 socket 和真实硬件时钟。 被排除的宿主层必须返回稳定的 `REAL-EXCLUDED` 错误;对应的轴、主轴、编码器、探针、限位、换刀和 IO 仍必须由数字孪生覆盖。 ## 2. 架构和不变量 ```text Web UI / Editor / Three.js │ protocol.v1 Dedicated Worker CommandRouter → TaskLedger → SimScheduler ├─ SimTask / rs274 / canonical ├─ TP / posemath / kinematics ├─ SimMotion / home / limits ├─ SimHAL / components / ClassicLadder ├─ SimIO / digital twins └─ PythonRuntime / remap / VCP ├─ SnapshotPublisher / EventBus / TraceRecorder └─ WorkspaceRuntime → WasmFS/POSIX → OPFS journal/checkpoint │ └─ native oracle 使用同一输入和命令序列 ``` 必须保持以下不变量: 1. Worker 是唯一 authoritative state 写者;UI 不读取 WASM 指针,不直接写 HAL/OPFS。 2. `sim_step(cycles)` 是唯一改变仿真结果的入口;墙钟只负责调度和让出事件循环。 3. 命令按 `seq` 顺序提交,`operation_id` 幂等;确认丢失先对账,不重复执行副作用。 4. 固定宽度 ABI、明确的 protocol/snapshot/event/workspace schema 和稳定错误码优先于 UI 便利。 5. 状态、事件、轨迹、HAL、IO、Python 和恢复结果都能产生确定性 hash。 6. 缺少输入、未支持能力、配额不足、非法路径、非有限数和 schema mismatch 必须 fail closed。 7. 任何 native/WASM 差异都保留首个 divergent tick、字段路径、单位、容差和来源证据。 ### 2.1 固定 tick 顺序 每一个逻辑 tick 依次执行: 1. 对账并去重已确认命令。 2. 执行 Task/解释器预算,更新模态、参数、当前行和 canonical。 3. 执行 TP 前瞻、速度/加速度/jerk、blend/exact-stop。 4. 调用 kinematics inverse,检查奇异性、joint 数量、limits 和 NaN/Inf。 5. 更新 motion、home、jog、following error、外部偏置、estop/limit。 6. 按静态线程/function 顺序运行 HAL、组件、编码器、主轴、探针、换刀和 PLC scan。 7. 运行 IO 完成、超时、报警、Python/remap/VCP 回调;回调不能越过当前 tick。 8. 生成 snapshot/event/trace/state hash,再执行已提交 checkpoint/journal。 快速运行、1x、单步、暂停恢复、导出导入和 replay 在相同逻辑终点必须得到相同 hash。 ## 3. 功能实施顺序 ### F0:输入、来源和契约 - 以 `context-lock.json`、source index、manifest、config resource graph 和 protocol schema 为输入。 - 为每个 source/file/symbol/config/test 建立 `source_id → feature_id → task_id → test_id → oracle_id` 关系。 - 固定 `sim_task.v1`、`command-envelope.v1`、`snapshot.v1`、`event-log.v1`、`workspace-package.v1` 的字段、版本和错误策略。 - 缺少官方测试输入时保留 `blocked`,不得用近似目录伪装官方 oracle。 ### F1:运行时骨架 - 建立 `SimTask`、`SimScheduler`、`TaskLedger`、`SnapshotPublisher` 和 `EventBus`。 - 把现有 WASM lifecycle、fixed tick、event、snapshot、G-code runner 接入 authoritative task state。 - 增加容量、非有限值、取消、abort、pause/resume、operation replay 和 checkpoint 边界。 ### F2:工作区和配置启动 - 实现虚拟 POSIX 文件 API、规范化路径、大小/配额和事务写入。 - 解析 INI/include/变量,解析 HAL/工具表/参数/程序/Python/VCP/ClassicLadder 资源图。 - 统一 `NEW → MOUNTED → PARSED → RESOLVED → CORE_CREATED → HAL_READY → TASK_READY` 状态机。 - 每个 `configs/sim` 入口输出 `READY` 或带文件/行/字段/source_id 的诊断。 ### F3:解释器、Task、TP、motion、kinematics - 先让 native oracle 输出每个 block 的 modal/canonical/参数和错误,再接入 WASM。 - 接入 O-word/子程序/循环/参数/宏/remap/filter、MDI、program state machine。 - 将 canonical queue 连接 TP、motion 和 kinematics;实现暂停、单步、abort、jog、home、override、limits、following error。 - 按 kinematics registry 逐族接入并保留每个族的 forward/inverse、branch、singularity 和 limit 证据。 ### F4:HAL、PLC、IO 和数字孪生 - 解析并执行 pin/signal/parameter/thread/function、`loadrt/addf/setp/net/sets/link*` 和静态 `.comp`。 - 实现 ClassicLadder 工程、scan、寄存器、计数器、定时器、HAL 绑定和诊断。 - 接入 spindle/encoder/probe/limit/home/tool/coolant/IO,支持故障注入、延迟、抖动、恢复和回放。 ### F5:Python、remap、VCP - 固定 Pyodide 版本、manifest、模块白名单、内存/时间/源码限制。 - 实现 `linuxcnc/hal/gstat/INI/tool/parameter/workspace/virtual-clock` 兼容 API。 - 接入 remap/filter 生命周期、VCP descriptor、pin callback、异常隔离和权限拒绝。 ### F6:恢复、离线和迁移 - 将 Task、解释器、TP、motion、kinematics、HAL、IO、Python、workspace 和 ledger 纳入 checkpoint。 - 实现 journal prepare/commit、确认丢失对账、崩溃恢复、OPFS quota、离线包、版本迁移和 rollback。 - 恢复必须从最近有效 checkpoint 重放已提交 event,不得只重新加载配置。 ### F7:Web 工作流和可视化 - 完善工程导入、编辑器诊断、MDI、run/pause/step/abort、jog/home/override、HAL/PLC/IO/报警面板。 - 以 authoritative snapshot/event 驱动姿态、joint、toolpath、stock、坐标系、工具、主轴和故障渲染。 - 用 Worker 重启、离线、配额和错误场景覆盖 UI 恢复向导;不使用 mock 替代真实 Worker。 ### F8:全量兼容、性能和交付 - 对所有纳入范围的 `configs/sim`、相关 tests/unit_tests 和资源入口执行 native/WASM 差异矩阵。 - 固定至少三次重复、快速/1x/单步/恢复、浏览器矩阵、性能、内存和离线报告。 - 许可证、来源、下载、迁移、回滚和 REAL-EXCLUDED 边界全部有证据;只有所有 gate 满足时才讨论 release candidate。 ## 4. 任务分解 任务状态只能按 `queued → in_progress → verified` 或 `in_progress → blocked` 转移。每个任务只有一个主要结果,并必须提供输入 context、直接证据、专属测试、完整回归和回滚点。 | ID | 任务 | 依赖 | 主要产物 | 验收重点 | |---|---|---|---|---| | P0-01 | 冻结来源、工具链、schema 和 source hash | 无 | context/source baseline | baseline 可重建,缺输入 fail closed | | P0-02 | 建立 source→feature→task→test 图 | P0-01 | coverage graph/manifest | 无孤儿、重复、未知 ID | | P0-03 | 固定 ABI/protocol/snapshot/event/workspace 契约 | P0-01 | schema + compatibility tests | 版本 mismatch 和字段缺失拒绝 | | P1-01 | 建立 `sim_task.v1` authoritative 状态对象 | P0-03 | Task state/native/WASM tests | state hash、状态机、错误码一致 | | P1-02 | 固定 `sim_step` 调度顺序和 tick budget | P1-01 | scheduler + tick golden | 快速/1x/单步终点一致 | | P1-03 | 接入 command ledger、幂等和 abort | P1-01 | ledger/replay tests | operation replay 不重复副作用 | | P1-04 | 将现有 G-code/MDI runner 接入 Task snapshot | P1-01 | Worker/native/WASM report | 当前行、模态、程序状态可观察 | | P2-01 | 虚拟 POSIX/Workspace API | P1-01 | workspace runtime | 路径、编码、配额、事务错误稳定 | | P2-02 | INI/include/变量解析器 | P2-01 | parser/resource graph | 行号、循环、缺失资源可诊断 | | P2-03 | HAL/工具表/参数/程序/Python/VCP/CLP resolver | P2-01 | config resource graph | 所有依赖可定位、不静默替换 | | P2-04 | 统一配置启动状态机 | P2-02/P2-03/P1-02 | startup resolver/233-entry report | 入口只进入 READY 或 BLOCKED | | P3-01 | rs274 grammar/modal/parameter 完整闭环 | P1-04 | native/WASM interpreter oracle | block、错误列和 modal hash 一致 | | P3-02 | O-word、子程序、循环、宏和过滤器 | P3-01/P5-02 | interpreter golden | 深度、预算、异常边界完整 | | P3-03 | canonical queue、TP 前瞻、blend/exact-stop | P1-02/P3-01 | TP golden/diff report | segment 顺序、速度和首差 tick | | P3-04 | Task mode、MDI、program state machine | P1-03/P3-01 | command golden | run/pause/resume/step/abort 可恢复 | | P3-05 | motion、jog、override、home、limits、following error | P3-03 | motion state/故障矩阵 | 轴/关节、estop、limit、home 一致 | | P3-06 | kinematics registry 和 trivkins/gantry/CoreXY | P3-05 | registry + native/WASM tests | forward/inverse/branch/limits | | P3-07 | 5/6-axis、TRT、机器人、并联和 switch/user kins | P3-06 | 每族 report/golden | singularity、非有限、缺 oracle 明确 | | P4-01 | HAL graph/twopass/pin/signal/thread/function | P2-03/P1-02 | HAL graph/runtime | 顺序、类型、重复、未知组件 fail closed | | P4-02 | 静态 `.comp` 组件和能力 manifest | P4-01 | component manifest/tests | 不动态加载、不访问宿主 | | P4-03 | ClassicLadder/采样/触发/背压 | P4-01 | PLC runtime/report | scan 顺序、寄存器、故障可回放 | | P4-04 | spindle/encoder/probe/limit/home/tool/coolant twin | P4-01/P3-05 | device model/fault matrix | 延迟、故障、恢复、hash 一致 | | P4-05 | IO command/ack/timeout/estop/recover | P4-04/P1-03 | IO Worker/native tests | ack 丢失和恢复不重复副作用 | | P5-01 | Pyodide runtime、模块白名单和虚拟时钟 | P2-01 | runtime manifest/report | 资源和能力限制稳定 | | P5-02 | Python linuxcnc/hal/INI/tool/parameter API | P5-01/P3-04 | API compatibility tests | 正常、异常、禁止能力 | | P5-03 | remap/filter/VCP callback 和隔离 | P5-02/P4-01 | remap/VCP report | 异常不破坏 Worker 核心 | | P6-01 | snapshot/event/trace 全状态导出 | P1-02/P3-05/P4-05/P5-03 | schema/hash tests | 导入导出 round-trip | | P6-02 | journal/checkpoint/operation reconciliation | P6-01/P1-03 | recovery matrix | crash、半提交、确认丢失 | | P6-03 | OPFS/offline/migration/rollback | P6-02/P2-01 | browser recovery report | 离线、配额、版本迁移 | | P7-01 | Worker protocol/client、backpressure、cancel | P1-03/P6-01 | protocol E2E | seq、schema、timeout、cancel | | P7-02 | editor/diagnostic/MDI/run workflow | P3-04/P7-01 | browser E2E | 真实 Worker,不用 mock | | P7-03 | state/HAL/IO/Python/PLC/alarm panels | P4/P5/P7-01 | UI tests | snapshot/event 单向消费 | | P7-04 | Three.js pose/joint/toolpath/stock view | P3-05/P7-03 | WebGL/canvas tests | 非空、姿态和轨迹跟随 authoritative state | | P7-05 | recovery/offline/error/permission UX | P6-03/P7-02 | browser fault E2E | 恢复状态可操作、错误可定位 | | P8-01 | native oracle runner 和 golden schema | P0-03/P3/P4 | JSONL oracle | 同输入、同命令、首差 tick | | P8-02 | 全量 sim entrypoint matrix | P2-04/P8-01 | startup/diff matrix | 每入口 READY 或诊断 BLOCKED | | P8-03 | 三次重复和执行模式 determinism | P8-02/P6 | determinism report | 1x/fast/step/recover hash 一致 | | P8-04 | browser/performance/memory/offline matrix | P7/P8-03 | perf/compat report | P95/P99、配额、WebGL、离线 | | P8-05 | 来源/许可证/下载/迁移/回滚交付闭合 | P8-02/P8-04 | release evidence | 所有排除项和剩余 blocker 显式保留 | ## 5. 里程碑 | 里程碑 | 名称 | 包含任务 | 退出条件 | |---|---|---|---| | M0 | 输入和契约闭合 | P0-01..03 | context/source/schema hash 可重建;输入缺失不会被接受 | | M1 | Task/WASM/Worker 会话闭合 | P1-01..04 | create/load/MDI/program/tick/pause/abort/snapshot/replay 通过 native/WASM/Worker | | M2 | 解释器和运动主链 | P3-01..07 | G-code→canonical→TP→motion→kinematics→snapshot 闭合,首差可定位 | | M3 | 配置启动闭合 | P2-01..04 | 纳入范围的每个入口进入 READY 或带来源诊断的 BLOCKED | | M4 | HAL/IO/数字孪生闭合 | P4-01..05 | HAL/PLC/主轴/编码器/探针/限位/工具/冷却/estop 故障可执行、可回放 | | M5 | Python/remap/VCP 闭合 | P5-01..03 | 白名单 API、remap、VCP、异常、能力拒绝和资源限制通过 | | M6 | 恢复和离线闭合 | P6-01..03 | Worker 重启、OPFS checkpoint、journal、迁移、回滚、离线路径通过 | | M7 | Web 工作流和可视化闭合 | P7-01..05 | UI 真实消费 Worker authoritative state,Three.js/Canvas 非空并可恢复 | | M8 | 全量兼容和交付闭合 | P8-01..05 | 全量矩阵、三次 determinism、浏览器/性能和来源证据齐全;仿真结果独立可运行 | 每个里程碑完成时必须生成一份确定性 report,包含 `context_id`、任务 ID、输入/输出 hash、native/WASM/Worker 测试、已知 blocked 项和下一个依赖任务。里程碑不能从 `blocked` 自动跳回 `in_progress`。 ## 6. 验收证据和回归门禁 每个任务至少保留: - native test;适用时必须有 WASM/Worker 对照 test。 - 正常、边界、非有限值、容量、错误、abort、pause/resume、恢复和离线样本。 - 输入 context、source hash、ABI/protocol/schema 影响和直接 evidence 路径。 - 状态 hash、event hash、首个 divergent tick 或明确的 `REAL-EXCLUDED/BLOCKED` 原因。 - 可重跑命令和报告 self-hash。 技术任务的最小回归: ```bash python3 scripts/validate_baseline.py python3 scripts/validate_download_index.py python3 scripts/validate_task_pointer.py scripts/build-wasm.sh ctest --test-dir build-native --output-on-failure for f in web/worker/test_*.mjs; do node "$f" || exit 1; done for f in web/app/test_*.mjs; do node "$f" || exit 1; done ``` 修改配置、协议、恢复或发布证据时,再运行对应的生成器专项测试和完整 Python unittest;生成器产生的报告不能被手工改 hash 伪装为通过。 ## 7. 停止线 立即将当前任务标记为 `blocked` 并保留证据的情况: 1. LinuxCNC 来源、官方测试输入、配置资源或协议契约缺失。 2. 需要改变 ABI/protocol/schema/manifest 时,必须同步更新兼容性测试和迁移证据。 3. native/WASM 差异的首个 divergent tick 未定位。 4. 只能删除失败样本、降低检查、静默替换资源或把缺失能力改成 `REAL-EXCLUDED` 才能通过。 5. Python/组件/VCP 需要未经允许的宿主路径、设备、进程或网络能力。 6. checkpoint/journal 无法验证 hash、确认丢失无法对账或恢复会重复副作用。 7. 运行结果依赖未固定的墙钟、随机数、线程竞争或浏览器环境。 blocked 不是失败样本删除理由,也不是自动跳过前置任务的理由。修复后必须重新运行原任务的专属测试和完整回归,再认领下一个依赖满足的任务。 ## 8. 当前实现基线 截至本计划建立时,仓库已有: - WASM/native 核心构建、posemath、解释器、多个 kinematics、HAL、IO 和固定 tick 切片。 - Worker protocol/session、虚拟设备、Python bridge、workspace recovery 和前端基础面板。 - G-code `PROGRAM_LOAD/RUN/PAUSE/RESUME/ABORT/STEP/SEEK`、`MDI_EXECUTE` 的 Worker/WASM 垂直切片。 这些能力仍不能替代 M1-M8 的完整验收。下一项直接实现任务由 [`nextTask1.md`](../nextTask1.md) 指向 `P1-01`:把已有 runner、解释器、motion/kinematics、HAL、IO 和 snapshot 统一纳入 `sim_task.v1` authoritative state,并固定首个可对照的 tick 边界。