18 KiB
XYZAC TRT Web/WASM 源码对标与唯一权威合同
文档状态:强制实施合同 v1.0
本合同是 xyzac-trt-web-wasm-implementation-plan.md 的约束性补充。它回答一个更严格的问题:Web 控制面板如何证明自己是 LinuxCNC 源码行为的 Web/WASM 等价实现,并且所有控制功能唯一来自 LinuxCNC WASM,而不是来自 React、浏览器状态或第二套 JavaScript 运动模型。
适用案例:
linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini
1. 强制结论
1.1 唯一权威
以下数据只能由 LinuxCNC WASM runtime 产生;React、TypeScript、Three.js、Worker UI adapter 和浏览器不能自行生成“看起来合理”的替代值:
- task state、task mode、interpreter state、current line、queued MDI。
- program parse state、canonical events、trajectory queue、active segment。
- Cartesian pose、X/Y/Z/A/C 轴位置、五个 joint 位置、速度、加速度和 limits。
- XYZAC forward/inverse kinematics、switchkins type、TCP/RTCP tool compensation。
- tool table、tool offset、G43/G49/G43.1、spindle、coolant、probe、home、limit、following error。
- HAL pin/signal/parameter 读值、PyVCP state、IO ack、报警、错误和恢复结果。
- checkpoint、journal、replay、recovery endpoint 和 state hash。
前端可以拥有以下本地状态,但必须明确标记为非权威:
- 编辑器 draft、搜索词、文件选择、当前 tab、camera、图层显示、窗口尺寸、pending operation。
- 尚未提交的配置表单、UI 偏好和输入法状态。
1.2 严禁的替代 authority
下列行为一律视为实现失败:
- React 根据按钮点击直接把 task/mode/position/kinematics 写成目标状态。
- JS 根据 A/C 角度和 tool length 自行计算 X/Y/Z 补偿并展示为实际 pose。
- JS G-code preview、Three.js preview 或 canvas 轨迹被当作 canonical motion。
- UI 通过
setTimeout、墙钟、requestAnimationFrame或点击次数推进仿真 tick。 - 浏览器直接访问 WASM 指针、导出内部内存、写 OPFS journal 或调用宿主 LinuxCNC。
- 前端绕过 Worker gateway 直接发送 HAL pin 写入、M428/M429 或模拟 IO 副作用。
- 收不到
COMMAND_RESULT时把 pending 命令当作成功,或超时后无 ledger reconcile 直接重发。 - 把 native/AXIS 行为复制成新的 JS 状态机,再用 WASM 只做最终演示。
- 以截图、按钮存在、模块测试或“曲线看起来一样”宣称完整五轴 parity。
- 把 HOST_BOUNDARY、REAL-EXCLUDED、SOURCE_BLOCKED 或缺少官方 oracle 的结果改写为 verified。
2. 对标单位:source behavior slice
对标的最小单位不是“页面”或“组件”,而是 source behavior slice:
source symbol/control
→ input/event/command
→ native state gate
→ LinuxCNC canonical result
→ status/event/visual output
→ error/abort/recovery behavior
每个 slice 必须有唯一 slice_id。示例:
AXIS-XYZAC-AUTO-RUN
AXIS-XYZAC-M428-TCP
AXIS-XYZAC-JOG-C
AXIS-XYZAC-HOME-JOINT-3
AXIS-XYZAC-LOAD-PROGRAM
AXIS-XYZAC-VISMACH-POSE
2.1 Slice manifest 必填字段
{
"slice_id": "AXIS-XYZAC-M428-TCP",
"source": {
"path": "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/428remap.ngc",
"symbols": ["428remap"],
"lines": "1-24",
"sha256": "..."
},
"inputs": ["MDI_EXECUTE:M428", "task_state", "motion.switchkins-type"],
"native_commands": ["M68 E3 Q1", "M66 E0 L0"],
"wasm_commands": ["MDI_EXECUTE", "KINEMATICS_SELECT"],
"authoritative_outputs": ["kinematics.active_type", "state_hash"],
"ui_controls": ["AXIS-RTCP-TCP-XYZAC"],
"gates": ["interp_idle", "hal_pin_present", "switchkins_net_present"],
"normal_cases": [],
"boundary_cases": [],
"error_cases": [],
"recovery_cases": [],
"status": "queued"
}
没有 source path、symbol、输入、native command、WASM command、输出、gate 和测试的功能,不得进入“实现完成”统计。
3. 源码到 WASM 的闭合分层
3.1 Source inventory 层
必须锁定并哈希以下来源:
| 层 | 来源 |
|---|---|
| AXIS controls | linuxcnc/share/axis/tcl/axis.tcl、support.tcl、accel.tcl、dialog.tcl、combobox.tcl、sb.tcl |
| AXIS Python | linuxcnc/src/emc/usr_intf/axis/scripts/axis.py |
| Preview/canon | linuxcnc/lib/python/rs274/glcanon.py、gremlin.py、vismach.py |
| Case config | xyzac-trt.ini、xyzac-trt.xml、switchkins_postgui.hal、xyzac-trt.tbl、xyzac.var |
| Program/remap | demos/*.ngc、remap_subs/*.ngc |
| Kinematics | xyzac-trt-kins.c、xyzbc-trt-kins.c、trtfuncs.c、switchkins.c/h、kins_util.c |
| Motion/TP | motion/command.c、motion/control.c、motion/homing.c、motion/motion.c、tp/tp.c、tp/tcq.c、tp/blendmath.c |
| Interpreter | rs274ngc/interp_read.cc、interp_execute.cc、interp_queue.cc、interp_convert.cc、modal_state.cc |
| HAL/IO | task/emctaskmain.cc、iotask/ioControl.cc、HAL component source and basic_sim.tcl |
Inventory 不能只记录目录;必须展开到具体文件、source hash、引用关系和运行时 fixture。生成的 sim.var、position、journal 和临时 tool table 必须单独标为 runtime-generated-fixture。
3.2 Compat API 层
WASM 不直接向 React 暴露 C 内部函数。应建立有限、版本化的 LinuxCncCompat:
LinuxCncCompat
├── task: state/mode/interpreter/queue
├── program: load/parse/run/pause/resume/step/abort/seek
├── mdi: execute/cancel/result
├── motion: jog/home/limit/override/spindle
├── kinematics: forward/inverse/select/diagnostics
├── hal: read/write/subscribe/type-check
├── io: tool/coolant/probe/spindle ack
├── snapshot: full/delta/hash
└── recovery: checkpoint/replay/reconcile
每个方法必须映射到 source symbol 和固定 tick 位置;不允许添加“为了 UI 方便”的隐式状态改变。
3.3 Worker protocol 层
Worker gateway 负责 schema、capability、gate、ledger、seq、operation id 和错误包装;不负责猜测 motion 结果。协议命令必须能够回到 compat API,并最终回到 WASM canonical state。
UI event
→ WorkerClient
→ protocol validator
→ capability/gate validator
→ CommandLedger.prepare
→ LinuxCncCompat
→ fixed-tick WASM runtime
→ snapshot/event/hash
→ CommandLedger.commit
→ UI projection
3.4 Projection 层
React reducer 只做:
- 校验消息。
- 保存 authoritative snapshot/event/result。
- 派生按钮 gate、标签、错误和可视化 props。
- 保留 pending/draft/ack/reconcile 状态。
Reducer 不得:
- 生成新的 motion/joint/pose。
- 依据 UI 点击顺序补齐缺少的状态。
- 在没有 Worker 快照时把按钮变为成功。
- 把 preview segment 当成 active motion segment。
4. 完整功能对标登记
4.1 控制面板域
以下域必须全部有 source slice;每项还要登记 menu/toolbar/button/keyboard/HAL 入口:
| 域 | 最低条目 |
|---|---|
| Shell | title、machine name、version、about、quick reference、window/min-size、focus、tooltip |
| File | open、recent、reload、save-as、properties、tool data、quit、exact path |
| Machine | ESTOP、power、reset、home all、home joint、unhome、override limits、touch-off |
| Mode | manual、mdi、auto、joint/world/teleop、mode denial |
| Program | run、pause、resume、step、abort、restart、run-from-line、optional stop、block delete |
| MDI | input、history、queue、clear、calculator、error/ack |
| Jog | axis/joint selection、continuous/incremental、linear/angular speed、press/release/stop |
| DRO | actual/commanded/relative/machine、G5x/G92/tool offsets、DTG、rotation |
| Preview | perspective/X/Y/Z、zoom、pan/rotate、grid、rapids、tool、limits、extents、live plot、clear |
| Tool | tool table、reload、tool change、tool offset、G43/G49/G43.1、manual toolchange |
| Spindle/IO | direction、speed、override、brake、coolant、lube、probe、digital/analog |
| HAL/PLC | HAL graph/scope/command、PyVCP、ClassicLadder/PLC state、capability denial |
| Diagnostics | alarm、error、event log、command trace、snapshot diff、runtime overrun、recovery |
| Case-specific | XYZAC/XYZBC type buttons、M428/M429/M430、A/C limits、RTCP offsets、Vismach clear |
4.2 对标登记状态
每项只能处于:
UNREGISTERED → SOURCE_MAPPED → WASM_IMPLEMENTED → WORKER_VERIFIED → UI_VERIFIED → PARITY_VERIFIED
任意阶段失败都必须停留在对应状态并保存原因。UI_VERIFIED 不能越过 WASM_IMPLEMENTED;PARITY_VERIFIED 不能只用浏览器截图证明。
5. 状态和 gate 的唯一实现
5.1 Native gate 取证
对于每个按钮,必须从原始 AXIS/LinuxCNC 源码提取:
- handler 名和绑定位置。
- 读取的
stat、HAL pin、INI 值和局部变量。 - 允许状态/拒绝状态。
- 发送的 command 和参数。
- command 后检查的 state。
- 错误对话框/状态栏/恢复行为。
5.2 WASM gate 复现
WASM gate 只允许读取 WASM snapshot:
gate(action, authoritative_snapshot, capability, configuration)
→ { enabled, reason, required_state, source_slice_id }
React 可以显示 gate,但不能覆盖 gate。若 native 与 WASM gate 不同,先生成差异报告;不能在 React 中添加特殊分支“修正”显示。
5.3 XYZAC 特殊 gate
M428/TCP = interpreter_idle && HAL_PIN_VARS && switchkins_net && finite_offsets
M429/identity = interpreter_idle && HAL_PIN_VARS && switchkins_net
M430/userk = interpreter_idle && userk_capability
A/C jog = manual_ok && axis_enabled && angular_limits && no_fault
RTCP motion = active_type == 1 && pose/joint transform verified
Vismach clear = visual-only,不改变 task/motion/program/hash
6. Native/WASM 等价证明
6.1 输入冻结
每次 parity run 固定:
- context id、case source hashes、browser/runtime build hash。
- INI/HAL/NGC/TBL/VAR/Python/XML exact resources。
- 程序文本、MDI 文本、按钮动作序列、固定 logical tick 数量。
- 初始 task/mode/home/tool/offset/kinematics state。
6.2 Trace 规范
{
"slice_id": "AXIS-XYZAC-M428-TCP",
"step": 7,
"input": {"kind": "MDI_EXECUTE", "line": "M428"},
"native": {
"task_mode": "MDI",
"motion_switchkins_type": 1,
"state_hash": "..."
},
"wasm": {
"task_mode": "MDI",
"motion_switchkins_type": 1,
"state_hash": "..."
},
"equal": true,
"first_divergent_tick": null
}
6.3 等价层级
- Protocol:信封、seq、operation id、command/result/error schema。
- Control:按钮 gate、模式转换、队列、取消、abort/reconcile。
- State:task/interp/motion/home/limit/tool/IO/kinematics snapshot。
- Canonical:canonical events、TP queue、pose/joints/toolpath。
- Recovery:checkpoint、replay、endpoint hash、无重复副作用。
- Visual:DRO、当前行、轨迹、A/C pose、Vismach 非空和布局。
低层级通过不能替代高层级缺口;visual 通过尤其不能替代 canonical/control 失败。
7. WASM-only 前端实施拆分
7.1 Runtime 完整性
WASM bundle 必须包含或明确拒绝:
- RS274NGC parser/interpreter、modal state、canonical events。
- TP queue/blend/arc/helix、fixed tick。
- XYZAC/XYZBC TRT forward/inverse、tool offset、rotation points、limits。
- task/motion/home/limit/IO/tool/probe/spindle/coolant。
- remap/Python capability model(无能力时稳定拒绝)。
- snapshot/event/hash/checkpoint/recovery。
REAL-EXCLUDED 能力不能通过宿主 LinuxCNC fallback 伪装成 WASM 支持。
7.2 Worker 完整性
Worker 必须是:
- WASM runtime 的唯一调度者。
- protocol schema 和 capability 的唯一入口。
- OPFS journal/checkpoint 的唯一写者。
- command ledger 和 reconcile 的唯一实现者。
- snapshot/event/trajectory 的发布者。
Worker 不得把某些命令转给主线程 JS authority;若能力未实现,返回 capability_unavailable/source_blocked。
7.3 Web 控制台完整性
React 页面必须从 PanelSnapshotV1/扩展快照显示:
- case/configuration/source hash。
- task/mode/interpreter/kinematics state。
- gates 和 reason。
- program/line/preview/active segment。
- Cartesian pose、XYZAC joints、tool offset、A/C limits。
- HAL/IO/tool/spindle/coolant/probe/alarms。
- pending/ack/result/reconcile/recovery。
所有 button handler 只能调用 WorkerClient/AxisOperationController;禁止 setState 直接表示 command 已完成。
8. 里程碑增强版
在原 M0-M7 上增加“源码唯一权威”退出条件:
M0-SOURCE:完整 source manifest
- AXIS、G-code、motion、TP、kinematics、HAL、IO、Vismach 所有功能已登记 slice。
- source hash、symbol、resource graph 和 version lock 可复现。
- unregistered count = 0;blocked count 单独报告。
M1-WASM-AUTHORITY:无 JS authority
- 所有 task/motion/kinematics/program state 均由 WASM snapshot 产生。
- JS authority call count = 0;可以使用的 JS 只剩 projection/ledger/UI。
- 损坏/篡改 snapshot fail closed。
M2-CONTROL-PARITY:按钮和命令对标
- 每个 source slice 有 native/WASM button gate trace。
- 正常、拒绝、ESTOP、limit、pause、abort、reconcile 全部通过。
- gate mismatch count = 0。
M3-CANONICAL-PARITY:解释器、TP、运动学
- program/canonical/TP/XYZAC pose/joint/toolpath trace 一致。
- M428/M429/M430、helix、A/C 姿态和 tool offset 一致。
- first divergent tick 可定位且 verified 样本无差异。
M4-FRONTEND-PARITY:React/Three.js
- 所有 UI controls 只消费 WASM state。
- Three.js 不重算姿态;canvas 与 snapshot hash 对账。
- DOM、keyboard/touch、错误、pending、recovery UI 通过。
M5-RECOVERY-PARITY:恢复和离线
- command ledger、checkpoint、journal、Worker restart endpoint 一致。
- 无重复 M-code、tool/IO side effect、trajectory segment。
- offline/OPFS quota/schema mismatch 证据完整。
M6-RELEASE-PARITY:严格发布门
- source slice coverage = 100%(verified + explicit blocked 分开统计)。
- native/WASM/Worker trace、hash、错误、恢复和 browser matrix 报告齐全。
- 任何外部 oracle/browser/hardware/license/owner blocker 都保持
STOP_RELEASE。
9. 任务新增与调整
在 xyzac-trt-web-wasm-implementation-plan.md 的 RTCP-00..12 之前增加以下治理任务:
SRC-00:AXIS/XYZAC Source Slice Inventory
输出:coverage/xyzac-trt-source-slice-inventory.report.json、web/workspace/xyzac-trt-source-slices.mjs。
门禁:所有 source controls、handlers、commands、state fields、visual outputs 和 errors 有唯一 slice id;unregistered=0。
WASM-00:唯一权威审计
输出:coverage/xyzac-trt-wasm-authority-audit.report.json。
门禁:扫描 JS/TS/React/WASM bridge,证明没有 JS task/motion/kinematics authority、JS G-code execution 或 OPFS direct writer。
PARITY-00:Native/WASM Trace Comparator
输出:scripts/compare_xyzac_native_wasm_trace.py、web/worker/test_xyzac_trace_parity.mjs、parity report。
门禁:协议、control、state、canonical、recovery 五级比较器能报告 first divergent tick,而不是只比较最终位置。
UI-00:Source Control Binding Audit
输出:React control manifest、每个 control 的 source slice/gate/command/result 映射。
门禁:每个 button/menu/keyboard/gesture 都能追溯到 source id;每个 UI action 都通过 WorkerClient。
RELEASE-00:WASM-only Release Gate
输出:coverage/xyzac-trt-wasm-only-release-gate.report.json。
门禁:WASM-only capability、source coverage、trace parity、browser matrix、recovery、错误和 blocker identity 全部审计;任何缺口都输出 STOP_RELEASE。
10. 测试和证据规则
每个 source slice 最少包含:
native normal
native boundary
native error
WASM normal
WASM boundary
WASM error
Worker command/result
UI gate projection
pause/resume/abort
checkpoint/recovery(适用时)
deterministic state hash
测试不能只调用纯 JS helper;必须运行真实 WASM module、Dedicated Worker/session、固定 logical tick 和实际 snapshot publisher。mock 只能用于协议单元测试,不能用于功能通过。
报告必须记录:source hash、input hash、output hash、command sequence、tick sequence、state hash、first divergent tick、error code、failure sample、environment and exclusion reason。
11. 停止条件
下列任一条件出现,停止当前“完全对标”声明:
- 任意功能没有 source slice 或 source hash。
- 任意程序/运动/RTCP 结果来自 JS/React/Three.js 推算。
- 任意 button gate 与 native 不一致且没有明确 source/version 差异。
M428/M429/M430没有通过 WASM remap/kinematics 状态确认。- canonical trace 只比较最终坐标,未比较首个 divergent tick。
- recovery 可能重复 segment、M-code、tool/IO side effect。
- browser 截图通过但 Worker/WASM authority 或 state hash 未验证。
- 缺少官方 oracle、浏览器、实时硬件、OPFS crash 或 owner 输入时试图 promote release。
12. 对当前项目状态的诚实结论
当前仓库已有通用 AXIS gate、Worker protocol、React reducer、Three.js workflow 和选定案例证据,但这些不能直接等同于 xyzac-trt.ini 的完整 WASM-only parity。按照本合同,下一步应先执行 SRC-00 和 WASM-00,再实现 RTCP-01..12 中的缺口;在 source slice coverage、WASM authority audit、RTCP trace parity 和 recovery 完成前,状态必须保持 in_progress 或 blocked,不能写成 verified 或全功能完成。