Files
linuxcncWebWASM/doc-rtcp/xyzac-trt-web-wasm-source-parity-contract.md

18 KiB
Raw Blame History

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

下列行为一律视为实现失败:

  1. React 根据按钮点击直接把 task/mode/position/kinematics 写成目标状态。
  2. JS 根据 A/C 角度和 tool length 自行计算 X/Y/Z 补偿并展示为实际 pose。
  3. JS G-code preview、Three.js preview 或 canvas 轨迹被当作 canonical motion。
  4. UI 通过 setTimeout、墙钟、requestAnimationFrame 或点击次数推进仿真 tick。
  5. 浏览器直接访问 WASM 指针、导出内部内存、写 OPFS journal 或调用宿主 LinuxCNC。
  6. 前端绕过 Worker gateway 直接发送 HAL pin 写入、M428/M429 或模拟 IO 副作用。
  7. 收不到 COMMAND_RESULT 时把 pending 命令当作成功,或超时后无 ledger reconcile 直接重发。
  8. 把 native/AXIS 行为复制成新的 JS 状态机,再用 WASM 只做最终演示。
  9. 以截图、按钮存在、模块测试或“曲线看起来一样”宣称完整五轴 parity。
  10. 把 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 等价层级

  1. Protocol:信封、seq、operation id、command/result/error schema。
  2. Control:按钮 gate、模式转换、队列、取消、abort/reconcile。
  3. State:task/interp/motion/home/limit/tool/IO/kinematics snapshot。
  4. Canonical:canonical events、TP queue、pose/joints/toolpath。
  5. Recovery:checkpoint、replay、endpoint hash、无重复副作用。
  6. 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 或全功能完成。