Files
cnc_wams/textbak/text16.txt
wangdequan 626bcfe8e3 继续完成 web-rtcp-5axis-sim-plan
结论:完成 LinuxCNC kinematics WASM ABI 覆盖,并将 web-rtcp-5axis-sim-plan 的 RTCP frame/boundary adapter 接到 xyzac-trt kinematics SDK;Node、build、browser smoke 验证通过。
2026-06-21 16:44:29 +08:00

1436 lines
45 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# text16.txt - LinuxCNC WASM/browser port continuation
Created: 2026-06-16 CST
This file continues from `text15.txt`. Use it for the next execution batches.
## Current Repository State
- Branch: `master`
- Remote sync state at creation: `master...origin/master`
- Latest commit at creation:
```text
69ccf93 支持真实G代码程序执行
```
- Working tree at creation: clean
- Active project tracker still exists at `PROJECT_COMPLETION_TRACKER.md`
- Previous continuation file: `text15.txt`
## Current Priority
The first priority remains the real browser CNC simulation page:
```text
wasm-port/runtime/ui/simulation/index.html
```
Primary supporting docs:
```text
wasm-port/docs/real-browser-simulation-priority.md
wasm-port/docs/axis-style-simulation-implementation.md
PROJECT_COMPLETION_TRACKER.md
```
Do not switch back to dashboard-only metadata work unless it directly creates a
gate or unblocks the browser simulation page.
## Completed Since text15 Start
The browser simulation page now has:
- AXIS-style browser shell:
- titlebar;
- File / Machine / View / Help menubar;
- toolbar;
- Manual Control / MDI tabs;
- Preview / DRO tabs;
- G-code pane;
- machine-state pane;
- bottom status bar.
- LinuxCNC-backed WASM execution through `createLinuxCncInterpSdk()`.
- Built-in test program selector.
- Built-in program directory:
```text
wasm-port/runtime/ui/simulation/programs/
```
- Current built-in program modules:
- `square-linear.js`;
- `pocket-z.js`;
- `incremental-loop.js`;
- `arc-g2-g3.js`;
- `drill-g81.js`.
- Program inventory export:
```text
wasm-port/runtime/ui/simulation/programs/index.js
```
- Reset / Step Back / Play / Step Forward / Finish playback over LinuxCNC
canonical motion events.
- Active G-code line highlighting.
- Active and executed motion row highlighting.
- Live XYZ/ABC readout.
- Full toolpath and executed-path SVG rendering.
- Moving toolhead marker.
- Real operator-provided G-code execution:
- `linuxCncRealSimulationApi.runProgramText(programText, metadata)`;
- `linuxCncRealSimulationApi.loadProgramFile(file)`;
- toolbar `Open` file input for `.ngc/.nc/.tap/.gcode/.txt`.
- Editable AXIS-style G-code pane:
- loaded file/custom/built-in program text is visible in a textarea;
- editor text can be changed before execution;
- toolbar `Run Editor Text` executes the current editor contents;
- `getProgramText()`, `setProgramText()`, and `runEditorProgramText()` are
exposed on the browser API.
- Program source metadata:
- `program.source`;
- `program.sourceLabel`;
- `program.filename`;
- `document.body.dataset.simulationProgramSource`.
## Current Browser API
Available on the simulation page:
```js
window.linuxCncRealSimulationApi
```
Current methods:
- `getState()`
- `getPrograms()`
- `runProgramById(programId)`
- `runProgramText(programText, metadata)`
- `loadProgramFile(file)`
- `getProgramText()`
- `setProgramText(text, metadata)`
- `runEditorProgramText()`
- `getPlaybackFrame()`
- `resetPlayback()`
- `stepPlayback(delta)`
- `play()`
- `pause()`
- `finishPlayback()`
All G-code execution must continue to go through LinuxCNC-backed WASM. Browser
JS must not interpret G-code or implement planner/machine semantics.
## Validation Baseline
The latest full validation completed successfully:
```text
real_simulation_programs_node_smoke=ok
ui_node_smokes=ok
browser_real_simulation_page_smoke=ok
axis_style_simulation_docs_node_smoke=ok
real_browser_simulation_priority_docs_node_smoke=ok
project_release_gate=ok
```
Useful focused commands:
```bash
wasm-port/tests/ui/node/verify_real_simulation_programs.sh
wasm-port/tests/ui/node/verify_ui_node_smokes.sh
SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_real_simulation_browser.sh
wasm-port/tests/docs/node/verify_axis_style_simulation_docs.sh
wasm-port/tests/docs/node/verify_real_browser_simulation_priority_docs.sh
```
Full gate:
```bash
wasm-port/tests/host/verify_project_release_gate.sh
```
## Semantic Boundary
LinuxCNC remains the only CNC semantic source.
Browser code may:
- render UI layout and interaction state;
- read user-selected G-code files/text;
- call the SDK/WASM boundary;
- render LinuxCNC-produced canonical output;
- animate playback over LinuxCNC-produced canonical motion events;
- stage future OPFS/session files when that integration is added.
Browser code must not implement:
- G-code interpretation;
- modal semantics;
- tool/cutter compensation semantics;
- parameter semantics;
- kinematics;
- remap behavior;
- planner behavior;
- machine-control behavior not backed by LinuxCNC/WASM or validated session APIs.
## Next Recommended Batches
### 1. Real G-code Editor Pane
Status: complete.
Implemented:
- show loaded file/custom text in an editor area;
- allow editing before run;
- add `Run Editor Text`;
- preserve line numbers and active-line highlighting;
- expose `linuxCncRealSimulationApi.getProgramText()`;
- expose `linuxCncRealSimulationApi.setProgramText(text, metadata)`.
- expose `linuxCncRealSimulationApi.runEditorProgramText()`.
Validation:
- browser smoke sets editor text, runs it, and verifies changed LinuxCNC
canonical output.
### 2. OPFS Program Persistence
Connect real G-code programs to OPFS:
- save current program text to OPFS;
- load program text from OPFS;
- show OPFS path in status/readiness;
- keep browser file loading as an import path, not the only path.
Validation:
- browser smoke load file -> save OPFS -> reload OPFS -> run -> playback.
### 3. AXIS DRO/Modal State Expansion
Improve the DRO panel without inventing unsupported data:
- derive any available fields from LinuxCNC output or validated summaries;
- show unavailable fields as `n/a`;
- add tests that prevent silently fabricated G54/G92/TLO/DTG values.
Validation:
- browser smoke verifies no `undefined` and no fabricated unavailable values.
### 4. Preview Controls
Add AXIS-like preview controls:
- zoom fit;
- reset view;
- optional pan/viewport scale state;
- keep SVG nonblank and stable.
Validation:
- browser smoke verifies viewBox changes/reset and toolhead/path remain visible.
### 5. Machine/Session Integration
Use the existing OPFS/session workflow:
- load machine session;
- show machine file readiness;
- stage INI/parameter/tool-table/program into WASM;
- block run with explicit reasons when readiness is missing.
Validation:
- OPFS/session browser smoke covers load -> run -> playback.
## Adding More Built-In Test Programs
To add a built-in test:
1. Add a module under:
```text
wasm-port/runtime/ui/simulation/programs/
```
2. Export an object with:
```js
{
id,
label,
category,
text,
expectedMotionTypes,
}
```
3. Import it in:
```text
wasm-port/runtime/ui/simulation/programs/index.js
```
4. Add it to `SIMULATION_TEST_PROGRAMS`.
5. Run:
```bash
wasm-port/tests/ui/node/verify_real_simulation_programs.sh
SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_real_simulation_browser.sh
```
## Commit / Upload Rule
After each completed implementation batch:
1. Run focused smoke(s).
2. Run `wasm-port/tests/host/verify_project_release_gate.sh` when feasible.
3. Commit with a Chinese title and conclusion body.
4. Push to:
```text
http://154.8.160.151:3000/wangdequan/cnc_wams.git
```
## Immediate Suggested Start
Start with "OPFS Program Persistence" because the page can now load, edit, and
run real G-code text/files, but programs are not yet saved to or restored from
OPFS from within the AXIS shell.
Updated after batch 9: compact run summary is implemented. The next recommended
batch is adding machine/session run summaries to saved OPFS/session artifacts or
making the preview controls more AXIS-like with fit-state persistence.
## Execution Record
### 一、2026-06-16 Real G-code Editor Pane
按 `text16.txt` 的 Immediate Suggested Start 推进,完成 AXIS shell 内真实 G-code 编辑区。
本批新增实质能力:
- `runtime/ui/simulation/index.html` 新增 editable G-code pane
- `data-axis-shell="program-editor"`
- `textarea[data-program-editor]`
- `data-program-editor-status`
- 工具栏新增:
- `Run Editor Text`
- 页面状态新增 `programEditorState`
- 内置程序加载、真实文本执行、真实文件加载都会同步到 editor textarea
- editor textarea 修改后可直接运行;
- `window.linuxCncRealSimulationApi` 新增:
- `getProgramText()`
- `setProgramText(text, metadata)`
- `runEditorProgramText()`
- browser smoke 新增验证:
- 初始内置程序会同步到 editor
- `runProgramText()` 后 editor 同步自定义文本;
- `loadProgramFile()` 后 editor 同步文件文本和 filename metadata
- `setProgramText()` 修改 editor 内容;
- `runEditorProgramText()` 通过 LinuxCNC WASM 执行修改后的 G-code并验证 canonical output
出现修改后的坐标。
关键验证:
```text
browser_real_simulation_page_smoke=ok
real_simulation_programs_node_smoke=ok
```
语义边界:
- editor 只保存和显示 G-code 文本;
- G-code 执行仍通过 LinuxCNC-backed WASM
- JS 不解释 G-code、不规划刀路、不推导 modal/machine semantics。
### 二、2026-06-16 AXIS DRO/Modal State and Preview Controls
继续按 AXIS 实现文档推进,完成 Phase 3/4 的可落地部分。
本批新增实质能力:
- `runtime/ui/simulation/simulation-app.js` 新增:
- `createModalState(resultText)`
- `createDroState(frame)`
- `zoomToolpathViewBox(viewBox, zoom)`
- modal display 不再使用硬编码 active G-code 文本,改为显示 LinuxCNC
`canon_event=UPDATE_TAG` 字段;
- DRO 显示:
- actual X/Y/Z/A/B/C 来自 LinuxCNC canonical motion playback frame
- DTG/G54/G92/TLO/velocity 在当前 canonical 输出不可用时明确显示 `n/a`
- `window.linuxCncRealSimulationApi` 新增:
- `getDroState()`
- `getModalState()`
- `fitPreview()`
- `zoomPreview(factor)`
- `resetPreview()`
- preview toolbar 新增 Fit / Zoom In / Zoom Out / Reset
- SVG preview 保留 full path、executed path、toolhead并支持 viewBox 缩放/恢复。
测试覆盖:
- Node smoke 验证:
- modal state 来自 `UPDATE_TAG`
- unavailable DRO 字段保持显式 `n/a`
- viewBox zoom 会收窄;
- browser smoke 验证:
- API 暴露;
- modal DOM 显示 LinuxCNC 字段;
- DRO 不伪造 DTG/G54/G92/TLO/velocity
- preview zoom 改变 viewBoxreset 恢复 fit viewBox
- 现有 built-in/custom/file/editor G-code 执行继续走 LinuxCNC WASM。
关键验证:
```text
real_simulation_programs_node_smoke=ok
axis_style_simulation_docs_node_smoke=ok
browser_real_simulation_page_smoke=ok
```
语义边界:
- JS 只解析 LinuxCNC canonical text 中已经输出的 `UPDATE_TAG` 字段用于显示;
- JS 不解释 G-code不推导 modal 语义,不计算 DTG/G54/G92/TLO/velocity
- preview zoom/reset 只改变 SVG viewBox不改变 LinuxCNC 生成的 motion events。
### 三、2026-06-16 AXIS OPFS Program Persistence
继续按 AXIS 实现文档推进,完成 Phase 2 的 OPFS program persistence 闭环。
本批新增实质能力:
- AXIS editable G-code pane 新增:
- OPFS G-code filename 输入;
- `Save OPFS`
- `Load OPFS`
- 页面复用既有 OPFS helpers
- `saveGcodeProgram()`
- `loadGcodeProgram()`
- `gcodeProgramPath()`
- `window.linuxCncRealSimulationApi` 新增:
- `getOpfsProgramState()`
- `saveProgramToOpfs(filename)`
- `loadProgramFromOpfs(filename)`
- OPFS load 会调用现有 `runProgramText()`,因此 reloaded program 仍通过
LinuxCNC-backed WASM 执行;
- OPFS metadata 写入 program state
- `program.source = "opfs"`
- `program.opfsPath = "linuxcnc/gcode/<filename>"`
- statusbar 显示 `Loaded OPFS: ...`。
browser smoke 新增验证:
- 设置 editor G-code
- 保存到 `linuxcnc/gcode/axis-opfs-roundtrip.ngc`
- 修改 editor 为不同内容;
- 从 OPFS 重新加载保存的程序;
- 验证 reloaded canonical output 出现保存内容的坐标;
- 验证 editor、body dataset、statusbar 和 OPFS state metadata 同步。
关键验证:
```text
browser_real_simulation_page_smoke=ok
real_simulation_programs_node_smoke=ok
```
语义边界:
- OPFS 只持久化 G-code 文本;
- OPFS load 后仍走 LinuxCNC-backed WASM interpreter
- JS 不解释 G-code不推导机床状态不绕过 canonical output。
### 四、2026-06-16 AXIS Machine/Session Readiness
继续按 AXIS 实现文档推进,完成 Phase 5 的 readiness 前半段。
本批新增实质能力:
- Manual Control panel 新增 `data-axis-shell="machine-session"` 区域:
- machine id
- session id
- G-code filename
- `Check Session`
- readiness phase/missing/path readout
- 页面复用既有 OPFS/session helper
- `readMachineSessionReadiness()`
- `window.linuxCncRealSimulationApi` 新增:
- `getMachineReadiness()`
- `checkMachineSessionReadiness(options)`
- readiness DOM 同步:
- `document.body.dataset.machineSessionReady`
- `data-machine-readiness-phase`
- `data-machine-readiness-missing`
- `data-machine-readiness-path="ini"`
- `data-machine-readiness-path="gcode"`。
browser smoke 新增验证:
- 检查不存在的 machine/session确认 readiness 为 blocked并报告 missing
`ini` 和 `gcode`
- 通过既有 OPFS helpers 写入:
- machine INI
- parameter file
- tool table
- G-code
- machine session snapshot
- 再次调用 AXIS API 检查 readiness确认 phase 为 `ready`missing 为空;
- 验证 readiness paths 与 OPFS path model 一致,并同步到 API/body/DOM。
关键验证:
```text
browser_real_simulation_page_smoke=ok
```
语义边界:
- readiness 只检查 OPFS 文件存在和 snapshot envelope
- JS 不合成 INI/tool/parameter/G-code 语义;
- 本批不加载或执行完整 machine session只把可运行前置条件暴露给 AXIS shell。
### 五、2026-06-16 AXIS Machine/Session WASM Staging
继续按 AXIS 实现文档推进,完成 Phase 5 的 ready session load/stage 能力。
本批新增实质能力:
- Manual Control panel 的 machine-session 区域新增:
- `Load Session`
- loaded INI WASM path
- loaded parameter WASM path
- loaded tool-table WASM path
- 页面复用既有 LinuxCNC-backed helpers
- `createLinuxCncInterpSdk()`
- `createLinuxCncIniSdk()`
- `loadMachineSessionFromOpfs()`
- `window.linuxCncRealSimulationApi` 新增:
- `getMachineSessionLoadState()`
- `loadReadyMachineSession(options)`
- `loadReadyMachineSession()` 先调用 readiness checkblocked 时返回 blocked
load state不 stage
- ready 时创建 LinuxCNC interp/INI SDK调用 `loadMachineSessionFromOpfs()`
把 OPFS INI/parameter/tool-table staged 到 WASM filesystem
- DOM 同步:
- `document.body.dataset.machineSessionLoaded`
- `data-machine-session-loaded-path="ini"`
- `data-machine-session-loaded-path="parameters"`
- `data-machine-session-loaded-path="toolTable"`。
browser smoke 新增验证:
- 在 ready machine/session 基础上调用 `loadReadyMachineSession()`
- 使用显式 WASM paths
- `/work/axis-smoke/machine.ini`
- `/work/axis-smoke/linuxcnc.var`
- `/work/axis-smoke/tool.tbl`
- 验证 API 返回 loaded state
- 验证 API/body/DOM 中 loaded paths 同步。
关键验证:
```text
browser_real_simulation_page_smoke=ok
```
语义边界:
- session load/stage 完全通过既有 LinuxCNC-backed SDK 和 OPFS bridge
- JS 不解释 INI/tool-table/parameter/G-code
- 本批只 stage machine session不改变 program execution semantics。
### 六、2026-06-16 AXIS Loaded-Session Program Execution
继续按 AXIS 实现文档推进,让 loaded machine session 真正参与程序执行。
本批新增实质能力:
- `simulation-app.js` 新增:
- `runLinuxCncProgram(interp, programText, options)`
- `runRealBrowserSimulation({ interp, iniPath })`
- state.execution
- `mode: "linuxcnc-wasm"`
- `mode: "linuxcnc-wasm-with-ini"`
- `iniPath`
- AXIS page 在 `loadReadyMachineSession()` 成功后保留 staged interpreter
- 后续 built-in/custom/editor/OPFS text execution 自动使用:
- staged interpreter
- loaded session INI WASM path
- LinuxCNC-backed `runProgramWithIni()`
- program source label 会显示 `Session INI: <wasm path>`。
browser smoke 新增验证:
- 在 ready session staged 后设置 editor G-code
- 调用 `runEditorProgramText()`
- 验证 returned state
- `execution.mode === "linuxcnc-wasm-with-ini"`
- `execution.iniPath === "/work/axis-smoke/machine.ini"`
- canonical output 包含修改后的 G-code 坐标;
- source label 包含 loaded session INI path。
Node smoke 新增验证:
- `runLinuxCncProgram()` 无 INI 时调用 `runProgram()`
- 有 INI 时调用 `runProgramWithIni()`
- `runRealBrowserSimulation({ interp, iniPath })` 返回
`linuxcnc-wasm-with-ini` execution metadata。
关键验证:
```text
real_simulation_programs_node_smoke=ok
browser_real_simulation_page_smoke=ok
```
语义边界:
- JS 只选择 LinuxCNC-backed interpreter SDK 方法;
- G-code 解释仍由 LinuxCNC WASM 执行;
- INI/tool/parameter state 仍由 existing OPFS bridge 和 LinuxCNC SDK staged/loaded。
### 七、2026-06-16 AXIS Run Mode Status and OPFS Session-Backed Execution
继续按 AXIS 实现文档推进,补齐 visible run-mode 状态,并扩展 OPFS program
在 loaded session 下的执行覆盖。
本批新增实质能力:
- toolbar status strip 新增:
- `Run mode Standalone`
- loaded session 执行后显示 `Session-backed: <iniPath>`
- statusbar 同步显示 run mode
- body dataset 新增:
- `data-run-mode="standalone"`
- `data-run-mode="session-backed"`
- `window.linuxCncRealSimulationApi` 新增:
- `getRunMode()`
- 每次 program render 后同步 run-mode UI/API 状态。
browser smoke 新增验证:
- 初始页面 run mode 为 standalone
- loaded session editor run 后 run mode 切换为 session-backed
- OPFS-loaded G-code 在 session-backed 模式下执行:
- 保存 `axis-session-opfs.ngc` 到 OPFS
- 修改 editor 为不同内容;
- 从 OPFS load/run
- 验证 `execution.mode === "linuxcnc-wasm-with-ini"`
- 验证 canonical output 来自 OPFS 保存内容;
- 验证 source label 同时包含 OPFS path 和 Session INI path。
关键验证:
```text
real_simulation_programs_node_smoke=ok
browser_real_simulation_page_smoke=ok
```
语义边界:
- run mode 只反映当前 LinuxCNC-backed execution path
- OPFS program load/run 仍通过 LinuxCNC-backed `runProgramWithIni()`
- JS 不解释 G-code也不实现 session semantics。
### 八、2026-06-16 AXIS Run Mode Session Toggle
继续按 AXIS 实现文档推进,补齐 standalone/session-backed 显式切换。
本批新增实质能力:
- Manual Control machine-session actions 新增:
- `Use Session` checkbox
- run mode 逻辑新增:
- loaded session 存在且 Use Session 开启时,程序执行走 loaded session INI
- Use Session 关闭时,即使 session staged也回到 standalone execution
- `window.linuxCncRealSimulationApi` 新增:
- `setUseLoadedSession(value)`
- `getRunMode()` 返回:
- `mode`
- `label`
- `iniPath`
- `useLoadedSession`
- `sessionLoaded`。
browser smoke 新增验证:
- loaded session editor run 后为 session-backed
- 调用 `setUseLoadedSession(false)` 后 checkbox 同步关闭;
- 再次运行 editor G-code确认
- `execution.mode === "linuxcnc-wasm"`
- `execution.iniPath === null`
- body run mode 维持 standalone
- 调用 `setUseLoadedSession(true)` 后 checkbox 同步开启;
- 后续 OPFS program load/run 再次使用 loaded session INI。
关键验证:
```text
real_simulation_programs_node_smoke=ok
browser_real_simulation_page_smoke=ok
```
语义边界:
- Use Session 只选择 LinuxCNC-backed execution method
- 不修改 staged machine session 内容;
- JS 不解释 G-code/INI/tool/parameter semantics。
### 九、2026-06-16 AXIS Run Summary
继续按 AXIS 实现文档推进,增加 compact run summary方便操作时判断当前运行上下文。
本批新增实质能力:
- Machine State readout 新增:
- Execution Mode
- Session INI
- OPFS Program
- Session State
- `window.linuxCncRealSimulationApi` 新增:
- `getRunSummary()`
- run summary 字段:
- `apiName: "real-browser-simulation-run-summary"`
- `executionMode`
- `runMode`
- `sessionIniPath`
- `opfsProgramPath`
- `readinessPhase`
- `sessionLoadPhase`
- `programSource`
- readiness/load/run/toggle 后都会同步 run summary DOM。
browser smoke 新增验证:
- 初始 summary 为 standalone `linuxcnc-wasm`
- session ready/load 后 summary 显示 `ready / loaded`
- session-backed editor run 后 summary 显示:
- `linuxcnc-wasm-with-ini`
- `/work/axis-smoke/machine.ini`
- Use Session 关闭后 standalone run summary 回到:
- `linuxcnc-wasm`
- Session INI `n/a`
- session-backed OPFS run 后 summary 显示:
- OPFS program path `linuxcnc/gcode/axis-session-opfs.ngc`。
关键验证:
```text
real_simulation_programs_node_smoke=ok
browser_real_simulation_page_smoke=ok
```
语义边界:
- run summary 只汇总已有 LinuxCNC-backed execution/session/readiness state
- 不推导 CNC semantics
- 不改变 execution path。
### 十、2026-06-17 AXIS MDI Text and Preview Pan
继续按 AXIS 实现文档推进,补齐 MDI scratch 文本路径和 preview pan 控制。
本批新增实质能力:
- AXIS MDI panel 新增:
- `data-mdi-program-text` scratch G-code textarea
- `Load MDI Text`
- `Run MDI Text`
- `data-mdi-status`
- `window.linuxCncRealSimulationApi` 新增:
- `loadProgramText(text, metadata)`
- `runMdiProgramText(text)`
- `loadProgramText()` 只把 operator text staging 到 AXIS G-code pane
不执行、不解释 G-code
- `runMdiProgramText()` 复用既有 `runProgramText()`,继续走 LinuxCNC-backed
WASM execution
- preview controls 新增 pan left/right/up/down
- `simulation-app.js` 新增纯显示 helper
- `panToolpathViewBox(viewBox, offset)`
- browser API 新增:
- `panPreview(dx, dy)`
- `fitPreview()` / `resetPreview()` 清除 pan offsetzoom/pan 不改变 canonical
motion state。
browser smoke 新增验证:
- MDI 控件存在;
- `loadProgramText()` 可以 staging 文本到 editor/statusbar
- MDI scratch 文本执行后 canonical output 包含 LinuxCNC-produced
`STRAIGHT_FEED`
- `panPreview()` 会移动已填充 toolpath viewBox
- `fitPreview()` 会清除 pan offset 并恢复 fit viewBox。
Node smoke 新增验证:
- `panToolpathViewBox()` 只平移 viewBox不改变 width/height
- existing zoom helper 仍围绕 fit viewBox 缩放。
文档同步:
- `wasm-port/docs/axis-style-simulation-implementation.md` 将
`loadProgramText()` 从 future API 移入 required API
- Phase 2 增补 MDI text execution
- Phase 4 增补 preview pan
- Immediate Next Batch 更新为当前后续方向run-control blocked/ready
messaging 和 preview state readback。
关键验证:
```text
real_simulation_programs_node_smoke=ok
axis_style_simulation_docs_node_smoke=ok
browser_real_simulation_page_smoke=ok
git diff --check ok
```
语义边界:
- MDI text 只是 operator-provided program text仍由 LinuxCNC WASM 解释;
- preview pan/zoom 只改变 SVG viewBox
- JS 不实现 G-code、modal、planner、kinematics 或 machine runtime semantics。
### 十一、2026-06-17 AXIS Run-Control State and Preview State Readback
继续按“页面样式和功能对标 LinuxCNC AXIS”的方向推进补齐 operator-facing
状态反馈,避免 session-backed/standalone 执行路径不透明。
本批新增实质能力:
- toolbar status strip 新增 run-control 状态行:
- `data-run-control-state`
- `document.body.dataset.runControlPhase`
- 初始显示 `fallback`,说明 Use Session 开启但尚无 loaded machine session
- Machine State readout 新增:
- Run Control
- Preview
- browser API 新增:
- `getRunControlState()`
- `getPreviewState()`
- run-control state 字段:
- `apiName: "real-browser-simulation-run-control-state"`
- `phase`
- `requestedMode`
- `executionMode`
- `reason`
- `canUseSession`
- `loadedIniPath`
- preview state 字段:
- `apiName: "real-browser-simulation-preview-state"`
- `zoom`
- `pan`
- `fitViewBox`
- `viewBox`
- preview controls 的 pan/zoom 状态同步到:
- `data-preview-zoom`
- `data-preview-pan`
- Machine State Preview
- Manual Control 新增 explicit blocked LED
- `data-axis-machine-control-state`
- 明确 jog/spindle/coolant 未绑定真实 machine runtime。
AXIS visual polish
- preview pan controls 从长文字改为更接近工具按钮的 `< > ^ v`
- 保留 `aria-label` 和原有 `data-preview-pan-*` selectors
- 控件仍保持密集、灰色、边框式 AXIS 风格。
browser smoke 新增验证:
- 初始 run-control 为 fallback
- run-control DOM 解释 standalone fallback 原因;
- preview pan 后 API/DOM 同步;
- fit 后 pan offset 清零;
- session load 后 run-control 显示 loaded INI 可用;
- session-backed run 后 run-control 为 ready
- Use Session 关闭后 run-control 说明 loaded session 被 bypass
- real-machine controls 必须显示 `not bound` blocked 状态。
文档同步:
- `wasm-port/docs/axis-style-simulation-implementation.md` 增补:
- `getRunControlState()`
- `getPreviewState()`
- real jog/spindle/coolant unbound blocked state
- run-control ready/fallback 状态。
关键验证:
```text
real_simulation_programs_node_smoke=ok
axis_style_simulation_docs_node_smoke=ok
browser_real_simulation_page_smoke=ok
git diff --check ok
```
语义边界:
- run-control 只反映当前 LinuxCNC-backed execution path
- preview state 只反映 SVG viewBox
- unbound machine-control 状态不伪造真实 jog/spindle/coolant 行为。
### 十二、2026-06-17 AXIS Canonical Machine Status Panel
继续推进 AXIS 对标,把左侧和 Machine State 中的 spindle/coolant/tool/override
状态从静态 UI 升级为 LinuxCNC canonical output 派生状态。
本批新增实质能力:
- `simulation-app.js` 新增:
- `createMachineStatusState(resultText)`
- simulation state 新增:
- `machineStatus`
- browser API 新增:
- `getMachineStatusState()`
- machine status 字段:
- `apiName: "real-browser-simulation-machine-status-state"`
- `source: "linuxcnc-canonical-events"`
- `spindle.state` / `spindle.direction` / `spindle.speed`
- `coolant.mist` / `coolant.flood`
- `tool.selected` / `tool.current` / `tool.pocket` / `tool.lengthOffset`
- `overrides.feed` / `overrides.speed` / `overrides.adaptiveFeed` /
`overrides.feedHold`
- AXIS UI 新增/同步:
- Manual Control Spindle status LED
- Manual Control Coolant status LED
- Machine State Spindle row
- Machine State Coolant row
- Machine State Tool row
- Machine State Overrides row
- 没有 LinuxCNC canonical event 的字段保持 `n/a`。
canonical event mapping
- `SET_SPINDLE_SPEED` -> spindle speed
- `START_SPINDLE_CLOCKWISE` / `START_SPINDLE_COUNTERCLOCKWISE` -> spindle
direction/state
- `STOP_SPINDLE_TURNING` -> spindle off
- `MIST_ON/OFF`、`FLOOD_ON/OFF` -> coolant state
- `SELECT_TOOL`、`CHANGE_TOOL_NUMBER`、`USE_TOOL_LENGTH_OFFSET` -> tool/TLO
- `ENABLE/DISABLE_*_OVERRIDE`、`ENABLE/DISABLE_FEED_HOLD` -> override rows。
browser smoke 新增验证:
- 初始 built-in program 未产生 machine-status events 时spindle/coolant
明确显示 `n/a`
- 执行包含 `S1200 M3/M5/M7/M8/M9/M48/M50/T2/M6/G43/G49/M61` 的 program
- 验证 API 和 DOM 中 spindle/coolant/tool/override 状态均来自 LinuxCNC
canonical output。
Node smoke 新增验证:
- `createMachineStatusState()` 对 unavailable canonical output 返回 `n/a`
- spindle/coolant/override canonical events 可正确折叠为最终状态;
- tool/TLO canonical events 可正确折叠为当前 tool/pocket/TLO。
文档同步:
- `wasm-port/docs/axis-style-simulation-implementation.md` 增补:
- machine status canonical event display
- `getMachineStatusState()` required API。
关键验证:
```text
real_simulation_programs_node_smoke=ok
browser_real_simulation_page_smoke=ok
git diff --check ok
```
语义边界:
- machine status 只显示 LinuxCNC canonical output 已产生的事件;
- 前端不推断真实 spindle/coolant/tool runtime
- 缺失字段继续显示 `n/a`。
### 十三、2026-06-17 AXIS Preview Extents, Origin, and Legend
继续推进 AXIS preview 对标,补齐更接近 LinuxCNC AXIS 的预览覆盖层。
本批新增实质能力:
- SVG preview 新增:
- `data-preview-extents` extents rectangle
- `data-preview-origin-x` / `data-preview-origin-y` origin axes
- `data-preview-origin` origin marker
- `data-axis-shell="preview-legend"` legend
- `data-preview-extents-label` extents text
- `renderToolpath()` 现在基于 LinuxCNC canonical motion 生成的
`createToolpathViewBox(motion)` 同步:
- extents rectangle
- origin axes
- origin marker size
- extents label
- preview legend 显示:
- Extents
- Full path
- Executed path
- Origin。
browser smoke 新增验证:
- AXIS shell 必须存在 preview legend
- SVG extents rectangle width/height > 0
- origin marker 位于 `0,0`
- extents label 同时包含 X/Y 范围;
- zoom/pan/fit 仍保持原有行为。
文档同步:
- `wasm-port/docs/axis-style-simulation-implementation.md` Phase 4 记录:
- motion-derived extents rectangle
- origin axes/marker
- preview legend。
关键验证:
```text
real_simulation_programs_node_smoke=ok
axis_style_simulation_docs_node_smoke=ok
browser_real_simulation_page_smoke=ok
git diff --check ok
```
语义边界:
- extents 只来自 LinuxCNC canonical motion path
- origin marker/axes 只是 preview display overlay
- 不新增浏览器端 CNC 几何、planner 或 kinematics 语义。
### 十四、2026-06-17 AXIS Three.js Toolpath Preview
按用户要求,刀具轨迹预览区改用 Three.js版本要求为
```json
"three": "^0.183.2"
```
本批新增实质能力:
- 新增 `wasm-port/runtime/ui/simulation/package.json`
- `dependencies.three = "^0.183.2"`
- 新增 `package-lock.json` 记录 resolved dependency
- 新增 vendored runtime build
- `runtime/ui/simulation/vendor/three/three.module.js`
- `runtime/ui/simulation/vendor/three/three.core.js`
- `runtime/ui/simulation/vendor/three/LICENSE`
- `simulation-app.js` 直接 import
- `./vendor/three/three.module.js`
- preview 主视图新增:
- `<canvas data-toolpath-three>`
- 原 SVG preview 改为 hidden fallback/state surface
- 保留 `data-toolpath-svg`
- 保留 polyline/head/extents selectors兼容既有 tests/API。
Three.js 渲染内容:
- orthographic camera
- dark AXIS-like background
- motion-derived extents outline
- origin X/Y axes
- full canonical path
- executed canonical path
- origin marker
- active tool marker
- camera fit/zoom/pan 与现有 `fitPreview()` / `zoomPreview()` /
`panPreview()` 同步。
browser smoke 新增验证:
- `data-toolpath-three.dataset.threeReady === "true"`
- Three.js revision 为 `183`
- Three path point count 等于 LinuxCNC canonical motion count
- playback step 后 Three executed point count 前进;
- SVG fallback viewBox/polyline 继续保持兼容。
docs smoke 新增验证:
- AXIS implementation docs 记录 Three.js `^0.183.2`
- simulation package 声明 `three: ^0.183.2`
- vendored `three.core.js` revision 为 `183`
- real-browser priority docs smoke 确认页面包含 `data-toolpath-three`。
关键验证:
```text
real_simulation_programs_node_smoke=ok
axis_style_simulation_docs_node_smoke=ok
real_browser_simulation_priority_docs_node_smoke=ok
browser_real_simulation_page_smoke=ok
git diff --check ok
```
语义边界:
- Three.js 只负责显示 LinuxCNC canonical motion
- 不在 Three.js/浏览器端实现 G-code、planner、kinematics 或 compensation
- SVG fallback 仅作为 state/compatibility surface 保留。
### 十五、2026-06-17 AXIS Three.js Preview View Modes
继续按用户“预览区使用 threejs、对标 LinuxCNC AXIS”的要求推进补齐 AXIS
常见预览视图模式。
本批新增实质能力:
- Preview toolbar 新增:
- `Top`
- `Front`
- `Side`
- `Iso`
- `window.linuxCncRealSimulationApi` 新增:
- `setPreviewViewMode(mode)`
- `getPreviewState()` 新增:
- `viewMode`
- Three.js preview canvas 新增/同步:
- `data-three-view-mode`
- UI 新增:
- `data-preview-view-label`
- active view-mode button state。
Three.js camera behavior
- `top`:正交 top view
- `front`:正交 front-style view
- `side`:正交 side-style view
- `iso`isometric-like angled view
- zoom/pan/fit 继续复用现有 viewBox 状态;
- Three.js 仅显示 LinuxCNC canonical motion不改变 motion semantics。
browser smoke 新增验证:
- API 必须存在 `setPreviewViewMode()`
- 切换 `iso` 后:
- `getPreviewState().viewMode === "iso"`
- Three canvas `data-three-view-mode === "iso"`
- UI label 显示 `Iso`
- 切换 `side` 后:
- active button state 为 true
- 切回 `top` 后继续执行 fit/zoom/pan smoke。
文档同步:
- `wasm-port/docs/axis-style-simulation-implementation.md` Phase 4 增补
Top/Front/Side/Iso view modes
- Required APIs 增补 `setPreviewViewMode(mode)`。
关键验证:
```text
real_simulation_programs_node_smoke=ok
axis_style_simulation_docs_node_smoke=ok
browser_real_simulation_page_smoke=ok
git diff --check ok
```
语义边界:
- view modes 只改变 Three.js camera
- 不改变 LinuxCNC canonical motion path
- 不实现浏览器端 kinematics 或 G-code 几何语义。
### 十六、2026-06-17 AXIS Three.js Grid, Axis Labels, and Pixel Smoke
继续按“预览区使用 threejs、对标 LinuxCNC AXIS”推进补齐 Three.js 预览的
网格、轴标签和 canvas 非空验证。
本批新增实质能力:
- Three.js preview 新增动态 grid
- `chooseGridStep(span)` 按 viewBox 尺寸选择 1/2/5/10 系列步距;
- `addThreeGrid(scene, viewBox)` 生成 viewBox 覆盖范围内的 grid lines
- canvas dataset
- `data-three-grid-step`
- `data-three-grid-lines`
- Three.js preview 新增 X/Y/Z axis labels
- `createTextSprite(text, color)`
- `addThreeAxisLabels(scene, viewBox)`
- canvas dataset
- `data-three-axis-labels="3"`
- Three.js preview smoke 新增 WebGL pixel readback
- 获取 `webgl2` / `webgl` context
- `readPixels()` 检查 canvas 中心像素非透明空白;
- 继续验证 Three.js revision/path points/executed points。
文档同步:
- `wasm-port/docs/axis-style-simulation-implementation.md` Phase 4 增补:
- dynamic grid lines
- X/Y/Z axis labels
- browser smoke canvas pixel check。
关键验证:
```text
real_simulation_programs_node_smoke=ok
axis_style_simulation_docs_node_smoke=ok
browser_real_simulation_page_smoke=ok
git diff --check ok
```
语义边界:
- grid 和 labels 只使用当前 preview viewBox
- Three.js 仍只显示 LinuxCNC canonical motion
- pixel smoke 只验证渲染非空,不推导 CNC 语义。
### 十七、2026-06-17 Browser Virtual HAL for AXIS Manual Controls
接续“虚拟 HAL 业务”,本批把 AXIS 手动控制从静态未绑定状态推进为浏览器
虚拟 HAL 状态模型,并接入 UI、SDK 和 WASM bridge。
本批新增实质能力:
- 新增 `wasm-port/runtime/sdk/src/linuxcnc-hal.js`
- `VIRTUAL_HAL_AXISUI_PINS` 对齐 `linuxcnc/bin/axis` 中的 axisui pins
`jog.x/y/z/a/b/c/u/v/w`、`jog.increment`、notification pins、
`error`、`abort`
- `createVirtualHalState()` / `applyVirtualHalAction()` 管理 ESTOP、Power、
Home、Jog、Touch Off、Spindle、Coolant、Limit Override、Brake 等状态;
- `createVirtualHalDroState()` 输出 AXIS DRO 默认/实际位置;
- `createVirtualHalLimitsHomeState()` 输出 home/limit/fault rows
- `createVirtualHalMachineStatusState()` 输出 spindle/coolant/tool/override state
- `createVirtualHalWasmBridgeSnapshot()` 生成可写入 standalone HAL adapter 的
pin/value snapshot。
- SDK 入口新增 re-export
- virtual HAL 状态、action、DRO、limits/home、machine status、runtime、
bridge snapshot、jog increment parser。
- Interpreter SDK 新增 HAL bridge API
- `hasWasmFunction(name)`
- `resetHal()`
- `setHalValue({ kind, name, type, value, connected })`
- `applyVirtualHalSnapshot(snapshot, options)`
- `applyVirtualHalState(halState, options)`
- `probeHalNamed(name)`。
- WASM wrapper 新增导出:
- `lcinterp_hal_reset()`
- `lcinterp_hal_set_value()`
- `lcinterp_probe_hal_named()`
- `build_wasm_core.sh` 已把这些函数加入 `EXPORTED_FUNCTIONS`。
- Browser simulation UI 接入:
- F1/F2 快捷键驱动 ESTOP/Power
- Ctrl-Home 驱动 Home All
- Manual jog 更新 `jog.*` pins 和 DRO
- spindle/coolant/brake/limit override 写入 virtual HAL state
- diagnostics artifact 新增 `virtualHal`
- machine control state 从“not bound”变为
`browser virtual HAL active for jog/spindle/coolant/home simulation`。
- Bridge snapshot 同时输出:
- AXIS Python component 内部 pin 名,例如 `jog.x`
- HAL 全名,例如 `axisui.jog.x`
- machine/task pins例如 `halui.machine.is-on`
- spindle/coolant pins例如 `spindle.0.speed-out`、
`iocontrol.0.coolant-flood`。
新增/扩展验证:
- `verify_real_simulation_programs.mjs` 覆盖 virtual HAL SDK、runtime snapshot、
`axisui.*` HAL 全名、DRO、home、spindle、coolant
- `real_simulation_page_smoke.html` 覆盖 F1/F2/Ctrl-Home/jog/spindle/coolant 的
浏览器交互;
- `verify_interp_wasm.mjs` 在新 WASM 导出存在时验证:
`applyVirtualHalState()` 写入 HAL adapter 后,`probeHalNamed()` 能读到
`_hal[jog.x]`、`_hal[axisui.jog.x]`、`_hal[halui.machine.is-on]`、
`_hal[spindle.0.speed-out]`、`_hal[iocontrol.0.coolant-flood]`。
关键验证:
```text
real_simulation_programs_node_smoke=ok
interp_wasm_node_smoke=ok (SKIP_INTERP_BUILD=1)
browser_real_simulation_page_smoke=ok (SKIP_INTERP_BUILD=1)
sdk_surface_node_smoke=ok
ui_node_smokes=ok
git diff --check ok
```
当前构建备注:
- 当前 Codex shell 的 `PATH` 未解析到 `emcc`,完整 `build_wasm_core.sh` 会停在
`emcc: command not found`
- 这不是代码侧缺少 Emscripten 的结论,只是本 shell 未加载用户已有的
Emscripten 环境;
- 快速 smoke 已用现有 WASM 产物验证旧路径不回归,新导出的 HAL bridge smoke 会在
重建后的 WASM 存在对应函数时自动执行。
语义边界:
- virtual HAL 只模拟 AXIS/manual UI 与 standalone HAL adapter 的状态桥;
- 不在浏览器端实现 LinuxCNC realtime HAL、motion controller、planner、
kinematics 或 G-code 语义;
- G-code execution 和 canonical motion 仍来自 LinuxCNC interpreter WASM。
### 十八、2026-06-17 Project-level Virtual HAL SDK Boundary
按用户要求“虚拟 HAL 适合整个项目”,本批把上一节的 simulation/UI 虚拟 HAL
提升为项目级 SDK host-boundary 能力,供 simulation、INI panel、Node/browser
smoke、外部 dashboard 和 interpreter bridge 共用。
新增项目级 API
- `VIRTUAL_HAL_WASM_BRIDGE_FUNCTIONS`
- `lcinterp_hal_reset`
- `lcinterp_hal_set_value`
- `lcinterp_probe_hal_named`
- `VIRTUAL_HAL_PROJECT_PIN_GROUPS`
- `axisui`
- `axis`
- `task`
- `spindle-coolant`
- `createVirtualHalPinInventory(halState)`
- 输出全部 bridge pin rows
- 按项目级 pin group 归类;
- `createVirtualHalBridgeReadiness(options)`
- 检查 snapshot 是否包含 required pins
- 检查 caller-provided WASM function evidence 是否覆盖
`VIRTUAL_HAL_WASM_BRIDGE_FUNCTIONS`
- 无 evidence 时显式 blocked`wasm-function-evidence`
- `createVirtualHalBridgeActionPlan(readiness)`
- blocked 时给出下一步:
`wasm-port/tools/build_wasm_core.sh`
`SKIP_INTERP_BUILD=1 wasm-port/tests/wasm/node/verify_interp_wasm.sh`
- ready 时返回空 command
- `createVirtualHalProjectReport(options)`
- 汇总 state、DRO、limits/home、machine status、pin inventory、
WASM bridge snapshot、bridge readiness、bridge action plan
- `applyVirtualHalToInterpSdk(interpSdk, halState, options)`
- 对有 `applyVirtualHalState()` 或 `applyVirtualHalSnapshot()` 的 interpreter
SDK 做统一适配;
- `createLinuxCncVirtualHalRuntime()` 新增:
- `getPinInventory()`
- `getProjectReport(options)`
- `applyToInterpSdk(interpSdk, options)`。
文档同步:
- `runtime/sdk/README.md` 新增 `Project-level virtual HAL boundary` 小节;
- `docs/project-release-handoff.md` 把 project-level virtual HAL 纳入当前支持
workflow
- `PROJECT_COMPLETION_TRACKER.md` 的 SDK/API surface 行记录 pin inventory、
bridge readiness/action-plan、project report、interpreter apply adapter
- `verify_project_release_handoff_docs.mjs` 增加文档 gate防止后续退回页面私有
virtual HAL。
新增/扩展验证:
- `verify_sdk_surface.mjs` 覆盖:
- SDK re-export
- constants discovery
- virtual HAL snapshot
- pin inventory
- blocked/ready bridge readiness
- bridge action plan
- project report
- runtime project report
- fake interpreter SDK apply wrapper
- `verify_project_release_handoff_docs.mjs` 覆盖 handoff/README 中的项目级
virtual HAL API 和 realtime HAL runtime 边界声明。
关键验证:
```text
sdk_surface_node_smoke=ok
project_release_handoff_docs_node_smoke=ok
real_simulation_programs_node_smoke=ok
git diff --check ok
```
语义边界:
- project-level virtual HAL 仍是 host-boundary adapter
- 它可服务 UI/session/diagnostics/dashboard 和 `_hal[...]` interpreter probe
- 它不是 LinuxCNC realtime HAL runtime
- 不提升 task、motion、HAL module loading、HALUI process、Tcl/Python process、
external device semantics。
### 十九、2026-06-17 Simulation-grade LinuxCNC Realtime HAL / halcmd / Motion Replacement
按用户要求“在满足仿真方面,实现 LinuxCNC realtime HAL / halcmd / motion controller
的完整替代,以虚拟 HAL 方式实现”,本批把上一节项目级 virtual HAL 从 bridge/readiness
推进为仿真级 runtime replacement。
新增实质能力:
- `VIRTUAL_HAL_SIMULATION_REPLACEMENT_TARGETS`
- `linuxcnc-realtime-hal`
- `halcmd`
- `motion-controller`
- `VIRTUAL_HAL_SIMULATION_RUNTIME_CAPABILITIES` 新增:
- `realtime-hal-simulation-replacement`
- `halcmd-simulation-replacement`
- `motion-controller-simulation-replacement`
- 新增 `executeVirtualHalcmd()`
- 作为 `executeVirtualHalCommand()` 的 halcmd 语义别名;
- 支持当前仿真所需 `setp`、`sets`、`newsig`、`net`、`show`、`getp`、`gets`、
`loadrt`、`loadusr`、`addf`、`start`、`stop`、`unlinkp`、`motion-step`
- 新增 `stepVirtualHalMotionController()`
- 多周期 servo step
- 输出每周期 position/motion frame
- 更新 target、velocity、distance-to-go、in-position
- 新增 `createVirtualHalSimulationReplacementReport()`
- 明确报告 realtime HAL、halcmd、motion controller 三类仿真替代 ready 状态;
- 保留 `hardRealtime: false`、`realtimeKernelAbi: false`,避免伪装为 Linux kernel
realtime ABI
- `createLinuxCncVirtualHalRuntime()` 新增:
- `executeHalcmd()`
- `stepMotionController()`
- `getSimulationReplacementReport()`。
Browser simulation API 新增:
- `executeVirtualHalcmd()`
- `executeVirtualHalCommand()`
- `stepVirtualHalMotionController()`
- `getVirtualHalSimulationRuntimeReport()`
- `getVirtualHalSimulationReplacementReport()`
- `getVirtualRealtimeHalRuntimeReport()`
- diagnostics artifact 新增 `virtualHalSimulationReplacement`。
新增/扩展验证:
- `verify_sdk_surface.mjs` 覆盖:
- replacement target constants
- runtime capability constants
- `executeVirtualHalcmd()`
- `stepVirtualHalMotionController()`
- `createVirtualHalSimulationReplacementReport()`
- runtime wrapper 的 `executeHalcmd()` / `stepMotionController()` /
`getSimulationReplacementReport()`
- `real_simulation_page_smoke.html` 覆盖:
- 页面 API 暴露 halcmd/motion/replacement report
- browser 中执行 `loadrt`、`addf`、`setp`、`show pin`
- browser 中执行 motion controller 多周期 step
- diagnostics artifact 携带 replacement report。
关键验证:
```text
sdk_surface_node_smoke=ok
project_release_gate_manifest_node_smoke=ok
project_release_artifact_url_workflow_node_smoke=ok
project_batch_acceptance_workflow_node_smoke=ok
project_batch_acceptance_artifact_node_smoke=ok
real_simulation_programs_node_smoke=ok
browser_real_simulation_page_smoke=ok
git diff --check ok
```
语义边界:
- 本批实现的是 simulation-grade replacement
- Browser/SDK 仿真不再依赖 host `halcmd`、host realtime HAL process 或 host motion
process 来完成页面/Node 仿真闭环;
- 仍不声称提供 Linux kernel hard-realtime ABI、外部硬件驱动 ABI、native HAL module ABI
- G-code 执行、canonical event、planner/interpreter 语义仍来自 LinuxCNC-backed WASM。