按规划持续工作

This commit is contained in:
2026-06-09 06:13:28 +08:00
parent 902c6ecaea
commit 2658ee3b72
255 changed files with 12487 additions and 150 deletions

View File

@@ -12,6 +12,12 @@ The primary native validation command is:
wasm-port/tests/native/verify_native_probes.sh
```
The native LinuxCNC `nc_files` basic/example validation command is:
```bash
wasm-port/tests/native/verify_nc_files.sh
```
The current WASM smoke validation command is:
```bash
@@ -24,6 +30,18 @@ The current WASM interpreter-core smoke validation command is:
wasm-port/tests/wasm/node/verify_interp_wasm.sh
```
The current WASM sim-config smoke validation command is:
```bash
wasm-port/tests/wasm/node/verify_sim_configs_wasm.sh
```
The current WASM `nc_files` smoke validation command is:
```bash
wasm-port/tests/wasm/node/verify_nc_files_wasm.sh
```
The current WASM trajectory-planner smoke validation command is:
```bash
@@ -74,10 +92,58 @@ The native validation script runs these checks in order:
5. `tools/build_native_probes.sh`
Builds native source probes and standalone harnesses from vendored
LinuxCNC source plus narrow runtime wrappers.
6. `tests/native/verify_native_probes.sh`
6. `tests/native/verify_sim_configs.sh`
Runs LinuxCNC `configs/sim` `.ngc` programs through the upstream
`../linuxcnc/bin/rs274` standalone entry point, using nearest or explicit
sim INI/tool-table mappings and classifying main programs, macro-load
checks, and remap subroutines separately.
7. `tests/native/verify_nc_files.sh`
Runs the basic/example subset of upstream `linuxcnc/nc_files` through
`../linuxcnc/bin/rs274`, with complete programs executed strictly and
macro/library files wrapped only for load/parse validation.
8. `tests/native/verify_native_probes.sh`
Checks probe exit codes, source-probe coverage, harness stdout, canonical
fixture events, and expected error behavior.
Current `nc_files` basic-suite baseline:
```text
total: 107
pass: 101
fail: 6
timeout: 0
expected_fail: 6
unexpected_fail: 0
```
The six expected failures are LinuxCNC-native entry-point/context edges:
`cone.ngc` needs a W-axis 5-axis machine context; `g76.ngc` and
`lathe-g76.ngc` need lathe cutter-compensation/tool context;
`lathe_g70_71_demo.ngc` needs lathe profile/tool context; `nestedcall.ngc`
uses an upstream O-word `callsub` syntax edge; and `tool-length-probe.ngc`
needs probe runtime context.
The same runner also supports exploratory full-directory inventory:
```bash
wasm-port/tests/native/verify_nc_files.sh --all
```
Current full-directory `nc_files` inventory:
```text
total: 247
pass: 219
fail: 28
timeout: 0
expected_fail: 28
unexpected_fail: 0
```
The additional expected failures are probe/plasmac runtime-context files and
one NURBS sample using `G2.2`, which the current upstream `bin/rs274`
standalone entry point reports as `Unknown g code used`.
The WASM INI smoke script builds `runtime/ui/ini-panel/linuxcnc_ini.js` and
`linuxcnc_ini.wasm` from vendored LinuxCNC `inifile.cc`, then loads that
module through `runtime/sdk/src/index.js` in Node and verifies INI string and
@@ -109,8 +175,10 @@ Emscripten filesystem through the SDK and runs them through LinuxCNC
`Interp::open()`, `Interp::read()`, and `Interp::execute()` to validate the
file execution path. It also writes the vendored LinuxCNC `xyzac-trt` and
`xyzbc-trt` table-rotary-tilting sample machine INI, `remap_subs/*.ngc`, and
`xyzac_switchkins.ngc`/`xyzbc_switchkins.ngc`, `boat-xyzac.ngc`,
`boat-xyzbc.ngc`, and `impeller-7bl-xyzac.ngc` demo files into the Emscripten
`xyzac_switchkins.ngc`/`xyzbc_switchkins.ngc`,
`xyzac_switchkins_test_1.ngc`, `xyzac_switchkins_test_2.ngc`,
`xyzac_switchkins_test_3.ngc`, `boat-xyzac.ngc`, `boat-xyzbc.ngc`, and
`impeller-7bl-xyzac.ngc` demo files into the Emscripten
filesystem. It also writes the vendored LinuxCNC `xyzab-tdr` table-dual-rotary
INI, tool table, `remap_subs/*.ngc`, and `xyzab-tdr-demo.ngc` into the
Emscripten filesystem. It also writes the vendored LinuxCNC bridge-mill
@@ -119,7 +187,52 @@ Emscripten filesystem. These checks validate the WASM C ABI/SDK path for
vendored LinuxCNC `REMAP` parsing, vendored LinuxCNC tool-table loading from
the machine INI, O-word remap execution, `M68`/`M66` HAL synchronization, and
file `open()`/`read()`/`execute()` completion without JavaScript M-code or
kinematics semantics. The same Node smoke writes
kinematics semantics. The same Node smoke writes the vendored LinuxCNC
`tests/remap/duplicate-o-word`, NGC-only `tests/remap/fail/args.0`,
`tests/remap/fail/args.1`, `tests/remap/fail/args.2`,
`tests/remap/fail/body-ngc`, `tests/remap/m30-interaction`,
`tests/remap/nested-remaps-oword`, `tests/remap/posargs.0`, and
`tests/remap/sequencing` INI, program, and remap subroutines into the
Emscripten filesystem and validates those
upstream NGC remap regressions through the generic `runRemapFile()` C ABI/SDK
path, which only reads LinuxCNC INI `SUBROUTINE_PATH`, `REMAP`, and
`OWORD_NARGS` entries and calls vendored `Interp::parse_remap()`, `open()`,
`read()`, and `execute()`. The NGC-only failure cases that match upstream
`rs274 -n 0` flow use the sibling `runRemapFileContinueOnError()` C ABI/SDK
path, which records LinuxCNC error text and continues the same vendored
`open()`/`read()`/`execute()` loop without implementing failure semantics in
JavaScript. The same Node smoke also writes the NGC-only LinuxCNC
`tests/remap/remap-io/test-ngc.ini` and `io_*.ngc` subroutines into the
Emscripten filesystem, then calls `runRemapIoMdiSequence()` to feed the
upstream test-driver MDI sequence into vendored `Interp::execute()`. The SDK
does not implement M62-M68, M66 input, or REMAP semantics; the standalone
boundary only pre-seeds deterministic external input values and captures
LinuxCNC canonical events. The same WASM interpreter smoke also writes minimal `M110` and
`M111` fixtures into the Emscripten filesystem, marks the `M1xx` files
executable, and validates that the standalone machine-config boundary mirrors
LinuxCNC task-layer `[DISPLAY]PROGRAM_PREFIX` plus `[RS274NGC]USER_M_PATH`
lookup by registering `USER_DEFINED_FUNCTION` entries and recording
deterministic `USER_M_COMMAND` events instead of spawning host processes. The
same Node smoke writes the vendored LinuxCNC
`tests/interp/do-while-break`, `tests/interp/oword-bug315`,
`tests/interp/oword-bug315-p2`, `tests/interp/exists`,
`tests/interp/return-value`, `tests/interp/subs-follow-main`,
`tests/interp/fractional-linenumbers`, `tests/interp/namedparam-bug424`,
selected `tests/interp/rotation` pure interpreter cases, `tests/interp/iniparam`,
`tests/interp/iniparam-failassign`,
`tests/interp/sub-call-from-sub`, `tests/interp/sequence-number`, and
`tests/interp/nested-sub-error`, `tests/interp/nested-sub-in-file-error`, and
`tests/interp/abort-hot-comment`
files into the Emscripten filesystem and validates those upstream interpreter
regressions through `runFile()` or
`runFileWithIni()`, which only reads LinuxCNC INI `SUBROUTINE_PATH` where
needed and calls vendored LinuxCNC `Interp::open()`, `read()`, and `execute()`.
The `iniparam` fixtures validate vendored LinuxCNC `_ini[...]` lookup, missing
INI-parameter error text, and read-only named-parameter assignment rejection
through the `INI_FILE_NAME` runtime edge. It checks LinuxCNC canonical messages,
canonical motion/events, and final interpreter state without JavaScript O-word,
subroutine lookup, INI-variable, or read-only-parameter semantics. The
same Node smoke writes
LinuxCNC-format parameter files into the Emscripten filesystem and validates
vendored `Interp::restore_parameters()` and `Interp::save_parameters()`,
including the saved parameter values, missing required numeric parameter
@@ -203,14 +316,59 @@ override INI-derived names before OPFS text is copied into the LinuxCNC-backed
WASM filesystem, and that absent INI file-name values use the default OPFS
parameter/tool-table paths in a real browser session. It also writes vendored
LinuxCNC `xyzac-trt`/`xyzbc-trt` INI, remap subroutines, and switchkins demo
files, including the larger `boat-xyzac.ngc`, `boat-xyzbc.ngc`, and
`impeller-7bl-xyzac.ngc` demos, into the browser WASM filesystem. It also
files, including `xyzac_switchkins_test_1.ngc`,
`xyzac_switchkins_test_2.ngc`, `xyzac_switchkins_test_3.ngc`, and the larger
`boat-xyzac.ngc`, `boat-xyzbc.ngc`, and `impeller-7bl-xyzac.ngc` demos, into
the browser WASM filesystem. It also
writes vendored LinuxCNC `xyzab-tdr` machine files and `xyzab-tdr-demo.ngc`
into the browser WASM filesystem. It also writes vendored LinuxCNC bridge-mill
machine files and `5axisgui.ngc` into the browser WASM filesystem. The browser
smoke verifies `runFiveAxisRemapFile()` for the table-rotary-tilting,
table-dual-rotary, and bridge-mill sample machines through the exported
LinuxCNC remap/tool-table/file execution path.
LinuxCNC remap/tool-table/file execution path. It also verifies the vendored
LinuxCNC `configs/sim/axis/foam/foam.ngc`, `axis/geometry/xyzc.ngc`, and
`axis/external_offsets/dyn_demo.ngc` programs through `runSimConfigProgram()`,
which writes the browser WASM filesystem files and forwards to
`runFileWithIni()`. It also verifies the bridge-mill
`axis/vismach/5axis/bridgemill/5axisgui.ngc` program through
`runSimConfigProgram()` with `executionMode: "fiveAxisRemap"`, which forwards
to `runFiveAxisRemapFile()`. These paths use the real vendored executable
`M110` and `M111` files for `USER_M_PATH` registration without spawning host
processes. It
also verifies the vendored
LinuxCNC `tests/remap/duplicate-o-word`, NGC-only `tests/remap/fail/args.0`,
`tests/remap/fail/args.1`, `tests/remap/fail/args.2`,
`tests/remap/fail/body-ngc`, `tests/remap/m30-interaction`,
`tests/remap/nested-remaps-oword`, `tests/remap/posargs.0`, and
`tests/remap/sequencing` regressions through `runRemapFile()` or
`runRemapFileContinueOnError()`, using the browser WASM filesystem and
vendored LinuxCNC REMAP/O-word/file execution path without JavaScript remap
semantics. It also writes the NGC-only vendored LinuxCNC
`tests/remap/remap-io/test-ngc.ini` and `io_*.ngc` subroutines into the
browser WASM filesystem and validates `runRemapIoMdiSequence()` through
vendored LinuxCNC REMAP parsing and MDI execution without JavaScript M-code or
I/O semantics. It also writes vendored LinuxCNC `tests/interp/do-while-break`,
`tests/interp/oword-bug315`, `tests/interp/oword-bug315-p2`,
`tests/interp/exists`, `tests/interp/return-value`,
`tests/interp/subs-follow-main`, `tests/interp/fractional-linenumbers`,
`tests/interp/namedparam-bug424`, and selected `tests/interp/rotation`
`.ngc` files plus
`tests/interp/sub-call-from-sub` `test.ini`, `test.ngc`, and `subs/*.ngc`
files and `tests/interp/sequence-number` `test.ini`, `test.ngc`, and
`rm400.ngc` plus `tests/interp/nested-sub-error` `test.ini`, `test.ngc`, and
`subs/nested.ngc` and `tests/interp/nested-sub-in-file-error` `test.ini`,
`test.ngc`, and `subs/sequential.ngc`, plus `tests/interp/abort-hot-comment`
`test.ini` and `test.ngc`, plus `tests/interp/m19` `test.ini` and `test.ngc`,
plus `tests/interp/magic_comments/param_format_printing` `test.ngc`,
plus selected pure-interpreter `tests/interp/m98m99` cases covering
Fanuc-style `M98/M99`, parameter scope, nested numbered subprograms,
subprograms after main program text, leading-zero O-word lookup, named and
numbered main programs, and expression-based O-sub/M98 calls,
into the browser WASM filesystem and
validates those upstream
interpreter regressions through `runFile()` or `runFileWithIni()`, without
JavaScript O-word, parameter, line-number, spindle-speed, spindle-orient,
magic-comment formatting, M98/M99, subroutine lookup, or branch semantics.
The aggregate host smoke script builds the INI, interpreter-core, and
trajectory-planner WASM artifacts once, then runs the Node WASM smokes, the
@@ -240,7 +398,8 @@ The validation fails if:
| `linuxcnc_interp_init_harness` | Validates vendored LinuxCNC `Interp::init()` emits canonical initialization boundaries, reads metric/inch machine units, and synchronizes current/selected tool slots through standalone status adapters. |
| `linuxcnc_indexer_harness` | Validates vendored LinuxCNC single-axis rotary indexer dispatch emits lock/unlock and motion boundaries through the standalone event sink. |
| `linuxcnc_remap_hal_sync_harness` | Validates vendored LinuxCNC `M68`/`M66` execution can drive the standalone HAL adapter boundary used by 5-axis switchkins remap files, including `_hal[motion.switchkins-type]` readback. |
| `linuxcnc_5axis_remap_execute_harness` | Validates vendored LinuxCNC `REMAP` parsing plus NGC remap execution for the 5-axis `M429 -> M428 -> M430 -> M429` switchkins path in the `xyzac-trt` and `xyzbc-trt` sample machines, the two-remap `M429 -> M428 -> M429` path in the `xyzab-tdr` sample machine, and the bridge-mill `M429 -> M428 -> M430 -> M429` path where M428 selects the default bridge-mill kinematics. It loads vendored machine tool tables through LinuxCNC `tooldata_load()`, then runs vendored `xyzac_switchkins.ngc`, `xyzbc_switchkins.ngc`, `xyzac_switchkins_test_1.ngc`, `xyzac_switchkins_test_3.ngc`, `boat-xyzac.ngc`, `boat-xyzbc.ngc`, `impeller-7bl-xyzac.ngc`, `xyzab-tdr-demo.ngc`, and `5axisgui.ngc` through the LinuxCNC file `open/read/execute` path. |
| `linuxcnc_5axis_remap_execute_harness` | Validates vendored LinuxCNC `REMAP` parsing plus NGC remap execution for the 5-axis `M429 -> M428 -> M430 -> M429` switchkins path in the `xyzac-trt` and `xyzbc-trt` sample machines, the two-remap `M429 -> M428 -> M429` path in the `xyzab-tdr` sample machine, and the bridge-mill `M429 -> M428 -> M430 -> M429` path where M428 selects the default bridge-mill kinematics. It loads vendored machine tool tables through LinuxCNC `tooldata_load()`, then runs vendored `xyzac_switchkins.ngc`, `xyzbc_switchkins.ngc`, `xyzac_switchkins_test_1.ngc`, `xyzac_switchkins_test_2.ngc`, `xyzac_switchkins_test_3.ngc`, `boat-xyzac.ngc`, `boat-xyzbc.ngc`, `impeller-7bl-xyzac.ngc`, `xyzab-tdr-demo.ngc`, and `5axisgui.ngc` through the LinuxCNC file `open/read/execute` path. |
| `linuxcnc_duplicate_oword_remap_harness` | Validates vendored LinuxCNC upstream `tests/remap/duplicate-o-word`, NGC-only `tests/remap/fail/args.0`, `tests/remap/fail/args.1`, `tests/remap/fail/args.2`, `tests/remap/fail/body-ngc`, `tests/remap/m30-interaction`, `tests/remap/nested-remaps-oword`, `tests/remap/posargs.0`, `tests/remap/sequencing`, and the NGC-only `tests/remap/remap-io/test-ngc.ini` branch through LinuxCNC `REMAP` parsing, O-word remap dispatch, `OWORD_NARGS`, error-text reporting, G/M remap sequencing, remapped M62-M68/M66 MDI execution, and file `open/read/execute`. The standalone harness only supplies INI/file path setup, deterministic external input values, and canonical-event capture; it can continue after LinuxCNC errors for upstream `rs274 -n 0` style tests and does not implement duplicate-label, O-word, M30, positional-argument, failure, sequencing, M62-M68, M66 input, or remap semantics. |
| `linuxcnc_tp_api_probe` | Validates vendored LinuxCNC trajectory planner calls for linear, arc, and queued motion paths. |
| `linuxcnc_kinematics_probe` | Validates vendored LinuxCNC `trivkins.c` plus `kins_util.c` initialize and perform identity forward/inverse mapping through the standalone HAL/RTAPI boundary. |
| `linuxcnc_5axis_kinematics_probe` | Validates vendored LinuxCNC `5axiskins.c` through `switchkins.c`, including 5-axis forward/inverse round-trip behavior and switching to identity kinematics. |
@@ -265,11 +424,13 @@ The validation fails if:
| Harness | Purpose |
| --- | --- |
| `tests/wasm/node/verify_ini_wasm.sh` | Validates the browser-facing INI WASM module can be built from vendored LinuxCNC `inifile.cc`, loaded through the JS SDK in Node, and queried through the exported C ABI, including LinuxCNC-backed boolean conversion and machine-session file-name string lookup. |
| `tests/wasm/node/verify_interp_wasm.sh` | Validates the interpreter-core WASM module can be built from vendored LinuxCNC interpreter/remap source, loaded through the interpreter JS SDK, run the first fixture group through `Interp::execute()` and selected file fixtures through `Interp::open()`/`read()`/`execute()`, match the native canonical event plus required state readback fixtures, run vendored `xyzac-trt`/`xyzbc-trt` switchkins remap demo files through the WASM C ABI/SDK path, and run parameter-file restore/save through vendored LinuxCNC `Interp::restore_parameters()` and `Interp::save_parameters()`. |
| `tests/wasm/node/verify_interp_wasm.sh` | Validates the interpreter-core WASM module can be built from vendored LinuxCNC interpreter/remap source, loaded through the interpreter JS SDK, run the first fixture group through `Interp::execute()` and selected file fixtures plus vendored upstream `tests/interp` regression files through `Interp::open()`/`read()`/`execute()`, match the native canonical event plus required state readback fixtures, run vendored `xyzac-trt`/`xyzbc-trt` switchkins remap demo files through the WASM C ABI/SDK path, and run parameter-file restore/save through vendored LinuxCNC `Interp::restore_parameters()` and `Interp::save_parameters()`. |
| `tests/wasm/node/verify_sim_configs_wasm.sh` | Validates representative vendored LinuxCNC `configs/sim` programs in Node WASM through `runSimConfigProgram()`, copying `axis/foam`, `axis/geometry`, and `axis/external_offsets` INI/G-code/user-M assets into the Emscripten filesystem before forwarding to `runFileWithIni()`, plus bridge-mill `5axis.ini`, tool table, `remap_subs/*.ngc`, and `5axisgui.ngc` before forwarding to `runFiveAxisRemapFile()`. This covers INI-driven `U/V/W` axis mask handling, real `USER_M_PATH` registration for executable `M110`/`M111`, and vendored LinuxCNC bridge-mill NGC remap execution without spawning host processes. |
| `tests/wasm/node/verify_nc_files_wasm.sh` | Validates representative vendored LinuxCNC `nc_files` examples in Node WASM by copying `arcspiral.ngc`, `hole-circle.ngc`, `factorial.ngc`, and `m6demo.ngc` into the Emscripten filesystem and forwarding to the LinuxCNC-backed `Interp::open()`/`read()`/`execute()` path. JavaScript only stages files and checks LinuxCNC output; it does not implement G-code, O-word, tool-change, or M-code behavior. |
| `tests/wasm/node/verify_tp_wasm.sh` | Validates a standalone trajectory-planner WASM module can be built from vendored LinuxCNC TP/TC/Ruckig support source, loaded in Node, and run the same linear, arc, and queued-line planner probe paths covered by the native TP harness. |
| `tests/opfs/node/verify_file_service.sh` | Validates the host-owned OPFS text-file adapter, path model, session snapshot store including custom filenames and envelope/path rejection paths, machine file store, G-code text store including filename rejection paths, OPFS-to-WASM parameter/tool-table bridges, and grouped machine-session loading without moving file persistence, parameter semantics, or tool-table semantics into the WASM core. |
| `tests/browser/verify_ini_panel_browser.sh` | Validates the INI SDK, INI/interpreter WASM module loading, LinuxCNC-backed INI machine-session file-name string lookup, OPFS text-file round trip, generic session snapshot round trip plus custom filename and envelope/path rejection paths, machine file text round trip, G-code text round trip plus filename rejection paths, and the INI panel UI's machine-session load with default OPFS parameter/tool-table file mapping, G-code run, canonical-event display paths, and 5-axis remap demo action in a real browser runtime. |
| `tests/browser/verify_interp_browser.sh` | Validates the interpreter-core WASM module loads through the interpreter JS SDK in a real browser runtime and runs selected positive and negative canonical fixtures through vendored LinuxCNC `Interp::execute()` plus `Interp::open()`/`read()`/`execute()` via the exported C ABI, including direct browser SDK and OPFS-backed parameter-file restore/save, non-random/random tool-table load/save through vendored LinuxCNC source, and vendored `xyzac-trt`/`xyzbc-trt` switchkins remap demo execution. |
| `tests/browser/verify_interp_browser.sh` | Validates the interpreter-core WASM module loads through the interpreter JS SDK in a real browser runtime and runs selected positive and negative canonical fixtures plus vendored upstream `tests/interp` regression files through vendored LinuxCNC `Interp::execute()` and `Interp::open()`/`read()`/`execute()` via the exported C ABI, including direct browser SDK and OPFS-backed parameter-file restore/save, non-random/random tool-table load/save through vendored LinuxCNC source, vendored `xyzac-trt`/`xyzbc-trt` switchkins remap demo execution, representative vendored `configs/sim` `foam`, `geometry`, `external_offsets`, and bridge-mill programs through `runSimConfigProgram()`, and representative vendored `nc_files` examples through `runFile()`. |
| `tests/host/verify_host_smokes.sh` | Runs the current host-side Node, WASM interpreter-core, WASM trajectory-planner, OPFS, and browser smoke validation with shared WASM builds. |
## Fixture Coverage
@@ -593,7 +754,15 @@ comparable canonical runtime edge and program-end cleanup calls. The
standalone vendored-source harness, Node WASM smoke, and browser smoke also
pin `coordinate_offsets` MDI/file-path, `feed_control_modes`, the
`position_params` MDI/file-path, `tool_semantics`, and `canon_runtime_edges`
post-program modal, override, spindle, mist, and flood `_setup` state. The same upstream baseline also
post-program modal, override, spindle, mist, and flood `_setup` state. Native
and WASM standalone checks also cover the user M-code registration boundary for
INI-declared `M110`/`M111` handlers while keeping process execution outside the
browser/WASM runtime. Node and browser WASM sim-config coverage now run the real
vendored `axis/geometry/xyzc.ngc` and
`axis/external_offsets/dyn_demo.ngc` programs with their executable
`M110`/`M111` files, `axis/foam/foam.ngc` with its `U/V` machine
configuration, and bridge-mill `5axisgui.ngc` with its `W` machine
coordinates. The same upstream baseline also
validates the current negative fixture error text and absent canonical-event
constraints. Fixtures that depend on standalone-only runtime
adapters, HAL state, upstream `rs274` output gaps such as
@@ -633,3 +802,38 @@ resulting `_setup.m_remapped` descriptors for each machine's LinuxCNC-defined
`M428`/`M429`/`M430` set. Python callbacks remain runtime boundaries. Native
and WASM validation now execute the NGC remap/file paths through vendored
LinuxCNC O-word dispatch and the standalone HAL adapter boundary.
`linuxcnc_duplicate_oword_remap_harness` vendors LinuxCNC's upstream
`tests/remap/duplicate-o-word` and `tests/remap/m30-interaction` files
unchanged and runs each `test.ngc` with its `test.ini` through vendored
`Interp::parse_remap()`, `open()`, `read()`, and `execute()`. Native, Node
WASM, and browser interpreter validation assert the same successful LinuxCNC
regression paths, including the remapped `M207`/`M208` messages and final
`FINISH()` event for duplicate O-word, and the `M400 M30` remap-level
interaction with `PROGRAM_END`.
`linuxcnc_interp_minimal_harness` now also runs selected vendored LinuxCNC
upstream `tests/interp/*/test.ngc` files through vendored `Interp::open()`,
`read()`, and `execute()`, using LinuxCNC INI `SUBROUTINE_PATH` for
`tests/interp/sub-call-from-sub`, `tests/interp/sequence-number`, and
`tests/interp/nested-sub-error`, `tests/interp/nested-sub-in-file-error`, and
`tests/interp/abort-hot-comment`, plus LinuxCNC `[RS274NGC]ORIENT_OFFSET` for
`tests/interp/m19`.
Native, Node WASM, and browser interpreter validation assert the LinuxCNC
canonical messages, canonical events, error texts, and interpreter state for
O-word loop/break/subroutine paths, dynamic O-word calls, `EXISTS[]`,
subroutine return values, subroutines after main programs, fractional line
numbers, named-parameter parsing, M19 spindle-orient offset and wait timeout
canonical events, magic-comment parameter formatting, valid external subroutine calls from another
external subroutine, external-subroutine `#<_line>` reporting,
nested-subroutine-definition rejection, and blocked forward seek to a later
numbered subroutine in the same external file, selected `tests/interp/rotation`
absolute-position `#<_abs_x>`, `#<_abs_y>`, and `#<_abs_z>` reporting under
G54, G92, XY rotation, and unit changes plus rotated-coordinate `G28` and
`G53` endpoint behavior, selected `tests/interp/m98m99`
Fanuc-style `M98/M99` subprogram calls, parameter-scope differences,
nested numbered subprograms, subprograms after main program text,
leading-zero O-word lookup, named/numbered main programs, and O-expression
calls, plus `(ABORT,...)` hot-comment numbered, named, and INI-parameter
expansion, with skipped branch/subroutine messages and post-abort program end
asserted absent where applicable.

View File

@@ -45,6 +45,7 @@ semantic rewrites:
| Go math C/C++ linkage | `genserkins` runtime probing compiles vendored `gomath.c` through a narrow C++ wrapper so LinuxCNC `genserfuncs.c` can link to the upstream Go math symbols without editing vendored source. |
| Switchkins iterative forward | `genhexkins` runtime probing follows LinuxCNC switchkins iterative-forward behavior, including the first-call warmup path before asserting roundtrip convergence. |
| Browser storage | OPFS remains outside the native core; `runtime/opfs/file-service.js` owns browser text-file persistence, `runtime/opfs/path-model.js` owns host-side storage paths for INI, tool table, parameter, G-code, preview-cache, and session-snapshot content, `runtime/opfs/snapshot-store.js` owns generic JSON session snapshot persistence, `runtime/opfs/machine-file-store.js` owns pure-text machine-file and G-code persistence, `runtime/opfs/linuxcnc-parameter-bridge.js` only copies parameter files between OPFS text storage and the LinuxCNC-backed WASM parameter-file ABI, `runtime/opfs/linuxcnc-tool-table-bridge.js` only copies tool tables between OPFS text storage and the LinuxCNC-backed WASM tool-table ABI, and `runtime/opfs/linuxcnc-machine-session-bridge.js` groups INI, parameter, and tool-table loading while using the LinuxCNC-backed INI SDK for `[EMCIO]RANDOM_TOOLCHANGER`, `[RS274NGC]PARAMETER_FILE`, and `[EMCIO]TOOL_TABLE` when available; explicit host session file-name options take precedence over INI-derived file names, missing INI file-name values fall back to host default parameter/tool-table paths, and path validation remains owned by the OPFS path model, including rejection of traversal or nested path segments from INI-derived file names. |
| Sim-config SDK staging | `runtime/sdk/src/linuxcnc-interp.js` exposes `runSimConfigProgram()` as a host-boundary convenience only. It writes caller-provided text files into the Emscripten filesystem, applies executable bits for user M-code files, and forwards to existing LinuxCNC-backed C ABI entry points such as `runFileWithIni()` or `runFiveAxisRemapFile()`; it does not implement interpreter, axis, remap, or user M-code semantics. |
## Enforced Non-Drift Rules
@@ -78,7 +79,9 @@ semantic rewrites:
paths.
- Host-side smoke validation is aggregated by
`tests/host/verify_host_smokes.sh` so Node, WASM, OPFS, and browser checks
run from one command.
run from one command. The current aggregate run passes with
`host_wasm_opfs_browser_smokes=ok`, including the Node and browser
sim-config paths staged through `runSimConfigProgram()`.
- Identity/trivial, `5axiskins`, TRT `xyzac`/`xyzbc`, delta, SCARA, PUMA,
serial, hexapod, pentapod, and related kinematics sources now have native
source-probe coverage.

View File

@@ -0,0 +1,165 @@
# LinuxCNC Test Porting Tracker
## Purpose
This file tracks the continuing work to validate this simulation port against
LinuxCNC behavior by using LinuxCNC's own source files and test assets.
Hard rule: CNC semantics must come directly from LinuxCNC source. Project-owned
code may provide build logic, runtime shims, filesystem adapters, C ABI, SDK,
browser UI, and test runners, but must not reimplement interpreter, remap, tool,
parameter, kinematics, planner, or machine-control behavior.
## Fixed Validation Gates
Run these checks as the baseline for every substantial porting step:
```bash
wasm-port/tools/verify_upstream_baseline.sh
wasm-port/tools/verify_vendor_sync.sh
wasm-port/tests/native/verify_native_probes.sh
wasm-port/tests/native/verify_nc_files.sh
wasm-port/tests/wasm/node/verify_ini_wasm.sh
wasm-port/tests/wasm/node/verify_interp_wasm.sh
wasm-port/tests/wasm/node/verify_sim_configs_wasm.sh
wasm-port/tests/wasm/node/verify_nc_files_wasm.sh
wasm-port/tests/wasm/node/verify_tp_wasm.sh
wasm-port/tests/opfs/node/verify_file_service.sh
wasm-port/tests/browser/verify_ini_panel_browser.sh
wasm-port/tests/browser/verify_interp_browser.sh
wasm-port/tests/host/verify_host_smokes.sh
```
## Status Legend
| Status | Meaning |
| --- | --- |
| Done | Native, WASM, browser, docs, and source-sync validation are complete for the current scope. |
| In progress | Test assets or runners are present, but coverage still needs extension or verification. |
| Planned | The item is selected for future work. |
| Blocked | The item needs missing LinuxCNC source, runtime boundary work, or upstream baseline clarification. |
## Continuing Steps
| Step | Status | Tracking notes |
| --- | --- | --- |
| Lock LinuxCNC upstream baseline | Done | Baseline commit is recorded in `wasm-port/tools/upstream-baseline.txt`; keep `docs/scope-and-baseline.md` synchronized when it changes. |
| Verify vendored source byte identity | Done | `tools/verify_vendor_sync.sh` must pass for every file in `tools/source-manifest.txt`. |
| Reject standalone CNC semantics | Done | `tools/verify_no_standalone_cnc_semantics.sh` guards project-owned `Interp::...` definitions outside documented runtime-edge stubs. |
| Maintain source reuse map | Done | Current sim-config, remap, interpreter, kinematics, TP, user-M, tool, named-parameter, and OPFS runtime boundaries are recorded in `docs/source-reuse-map.md`; keep updating it whenever LinuxCNC source, test assets, or runtime boundaries are added. |
| Maintain compatibility validation notes | Done | Current native, Node WASM, browser, OPFS, and host aggregate checks are recorded in `docs/compatibility-validation.md`; keep updating it whenever a validation command or fixture class is added. |
| Build LinuxCNC test inventory | In progress | `linuxcnc/tests/remap` has been inventoried by dependency class; the first broader `linuxcnc/tests` pass now records full-process, HAL/realtime, linuxcncrsh, Python-binding, and external-component families in the blocked table. |
| Prefer pure interpreter tests first | In progress | Continue with tests that can run through `Interp::open()`, `read()`, and `execute()` without realtime hardware or GUI. |
| Add upstream-output comparison | In progress | Use upstream `../linuxcnc/bin/rs274` or original `test.sh` output where practical, then compare against native/WASM/browser output. |
| Promote tests through three layers | In progress | Add each selected test first to native harnesses, then WASM Node, then browser smoke where meaningful. |
| Record blocked tests | In progress | First broader family-level blocked batch is recorded below; continue expanding it as each `linuxcnc/tests` family is inspected. |
| Add aggregate smoke coverage | Done | `tests/host/verify_host_smokes.sh` now runs stable Node WASM, sim-config WASM, `nc_files` WASM, OPFS, and browser smoke checks with shared builds. Current run passed with `host_wasm_opfs_browser_smokes=ok`. |
| Add `linuxcnc/nc_files` basic examples | Done | `tests/native/verify_nc_files.sh` now runs the basic/example subset of upstream `linuxcnc/nc_files` through LinuxCNC `bin/rs274`; current native baseline is 107 total, 101 pass, 6 expected context/entry-point edges, 0 unexpected failures. Exploratory `--all` inventory is 247 total, 219 pass, 28 expected context/entry-point edges, 0 unexpected failures. A representative vendored subset now passes Node WASM and browser execution through LinuxCNC-backed `Interp::open()`/`read()`/`execute()`. |
## LinuxCNC Test Asset Queue
| LinuxCNC test path | Status | Current target | Notes |
| --- | --- | --- | --- |
| `nc_files` basic/example programs | Done | Native, WASM Node, browser | Native coverage is tracked by `wasm-port/tests/native/verify_nc_files.sh`; complete programs execute strictly, macro/library files are wrapped with temporary `M2` for load/parse validation, and six known LinuxCNC-native context edges are classified explicitly. `--all` also inventories probe/plasmac/NURBS files and currently classifies all 28 non-passing files as expected runtime-context or entry-point edges. The representative vendored WASM/browser subset covers `arcspiral.ngc`, `hole-circle.ngc`, `factorial.ngc`, and `m6demo.ngc` through LinuxCNC-backed file execution only. |
| `tests/remap/duplicate-o-word` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/remap/duplicate-o-word`; validates duplicate O-word behavior through vendored LinuxCNC remap/O-word/file execution paths. |
| `tests/remap/fail/args.0` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/remap/fail/args.0`; validates required `P`/`Q` remap arguments when both are present through vendored LinuxCNC remap argument handling. |
| `tests/remap/fail/args.1` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/remap/fail/args.1`; validates LinuxCNC missing-`Q` remap error text and upstream-style continue-after-error flow. |
| `tests/remap/fail/args.2` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/remap/fail/args.2`; validates LinuxCNC missing-`P,Q` remap error text and upstream-style continue-after-error flow. |
| `tests/remap/fail/body-ngc` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/remap/fail/body-ngc`; validates LinuxCNC NGC remap body failure text and remap level restoration after continue-on-error execution. |
| `tests/remap/m30-interaction` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/remap/m30-interaction`; validates LinuxCNC remap/M30 interaction through vendored interpreter paths. |
| `tests/remap/nested-remaps-oword` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/remap/nested-remaps-oword`; validates nested NGC remaps through vendored LinuxCNC O-word dispatch. |
| `tests/remap/posargs.0` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/remap/posargs.0`; validates LinuxCNC positional remap arguments and `OWORD_NARGS` through vendored interpreter paths. |
| `tests/remap/sequencing` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/remap/sequencing`; validates LinuxCNC G/M remap execution ordering through vendored interpreter paths. |
| `tests/remap/remap-io` NGC-only branch | Done | Native, WASM Node, browser | Vendored `test-ngc.ini` plus `io_*.ngc` subroutines validate LinuxCNC NGC remaps for M62-M68 and M66 immediate input through vendored `Interp::parse_remap()` and `Interp::execute()`; the standalone boundary only stages inputs and captures canonical events. |
| `tests/interp/do-while-break` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/do-while-break`; validates LinuxCNC O-word do/while/break flow through vendored `Interp::open()`, `read()`, and `execute()` paths. |
| `tests/interp/oword-bug315` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/oword-bug315`; validates LinuxCNC O-word break-out-of-subroutine behavior through vendored file execution paths. |
| `tests/interp/oword-bug315-p2` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/oword-bug315-p2`; validates LinuxCNC dynamic O-word subroutine call selection through vendored file execution paths. |
| `tests/interp/exists` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/exists`; validates LinuxCNC `EXISTS[]` parameter handling through vendored file execution paths. |
| `tests/interp/return-value` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/return-value`; validates LinuxCNC O-word return-value and `#<_value>` behavior through vendored file execution paths. |
| `tests/interp/subs-follow-main` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/subs-follow-main`; validates LinuxCNC subroutines after main program text through vendored file execution paths. |
| `tests/interp/fractional-linenumbers` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/fractional-linenumbers`; validates LinuxCNC fractional line-number parsing through vendored file execution paths. |
| `tests/interp/namedparam-bug424` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/namedparam-bug424`; validates LinuxCNC named-parameter parsing regression behavior through vendored file execution paths. |
| `tests/interp/rotation` selected pure interpreter cases | Done | Native, WASM Node, browser | Vendored selected upstream cases under `wasm-port/vendor/linuxcnc/tests/interp/rotation`; validates LinuxCNC machine-coordinate `G53` absolute-position named parameters `#<_abs_x>`, `#<_abs_y>`, and `#<_abs_z>` across G54 offsets, G92 offsets, XY rotation, and inch/millimeter modes, plus rotated-coordinate `G28` and `G53` endpoint behavior through vendored file execution paths. |
| `tests/interp/iniparam` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/iniparam`; validates LinuxCNC `_ini[...]` lookup, missing INI-parameter error text, and continued file execution through vendored file execution paths and `INI_FILE_NAME`. |
| `tests/interp/iniparam-failassign` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/iniparam-failassign`; validates LinuxCNC `_ini[...]` read-only named-parameter assignment rejection through vendored file execution paths and `INI_FILE_NAME`. |
| `tests/interp/m19` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/m19`; validates LinuxCNC `M19` spindle orient canonical events, wait timeout, and `[RS274NGC]ORIENT_OFFSET` handling through vendored file execution paths. |
| `tests/interp/magic_comments/param_format_printing` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/magic_comments/param_format_printing`; validates LinuxCNC `(DEBUG,...)` magic-comment parameter formatting for integer, default float, and explicit precision formats through vendored file execution paths. |
| `tests/interp/m98m99` selected pure interpreter cases | Done | Native, WASM Node, browser | Vendored selected upstream cases under `wasm-port/vendor/linuxcnc/tests/interp/m98m99`; validates LinuxCNC Fanuc-style `M98/M99`, parameter scope, nested numbered subprograms, subprograms after main program text, leading-zero O-word lookup, named and numbered main programs, and expression-based O-sub/M98 calls through vendored file execution paths. |
| `tests/interp/sub-call-from-sub` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/sub-call-from-sub`; validates LinuxCNC external subroutine calls from another external subroutine through vendored file execution paths and LinuxCNC INI `SUBROUTINE_PATH`. |
| `tests/interp/sequence-number` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/sequence-number`; validates LinuxCNC `#<_line>` reporting in main files and external subroutines through vendored file execution paths and LinuxCNC INI `SUBROUTINE_PATH`. |
| `tests/interp/nested-sub-error` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/nested-sub-error`; validates LinuxCNC nested-subroutine-definition rejection through vendored file execution paths and LinuxCNC INI `SUBROUTINE_PATH`. |
| `tests/interp/nested-sub-in-file-error` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/nested-sub-in-file-error`; validates LinuxCNC rejection of forward seek to a later numbered subroutine in the same external subroutine file through vendored file execution paths and LinuxCNC INI `SUBROUTINE_PATH`. |
| `tests/interp/abort-hot-comment` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/tests/interp/abort-hot-comment`; validates LinuxCNC `(ABORT,...)` hot-comment parameter expansion for numbered, named, and INI named parameters through vendored file execution paths and `INI_FILE_NAME`. |
| `configs/sim/axis/foam/foam.ngc` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/configs/sim/axis/foam`; validates LinuxCNC INI-driven `U/V` axis mask handling through `axis_foam.ini` and vendored file execution paths. |
| `configs/sim/axis/geometry/xyzc.ngc` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/configs/sim/axis/geometry`; validates LinuxCNC `USER_M_PATH` registration with the real executable `M110` while process execution remains a deterministic standalone `USER_M_COMMAND` boundary. |
| `configs/sim/axis/external_offsets/dyn_demo.ngc` | Done | Native, WASM Node, browser | Vendored under `wasm-port/vendor/linuxcnc/configs/sim/axis/external_offsets`; validates LinuxCNC `USER_M_PATH` registration with the real executable `M111` against an upstream sim program while process execution remains a deterministic standalone boundary. |
| More `tests/remap/*` interpreter-only cases | Planned | Native first | Select cases that do not require Python behavior beyond documented runtime-edge stubs unless the required LinuxCNC source path is ported. |
| More `tests/interp/*` interpreter-only cases | Planned | Native first | Select upstream interpreter cases that can run through vendored file execution without Python, HAL, realtime motion, or GUI. |
| `tests/rs274ngc/*` candidates | Planned | Native first | Use upstream `rs274` as the baseline where output is comparable. |
| Tool-table regression assets | Planned | Native and WASM Node | Must call vendored `tooldata_common.cc`; project code may only provide storage callbacks and filesystem boundaries. |
| Kinematics tests | Planned | Native probes first | Add runtime probes only around LinuxCNC kinematics entry points; HAL lifecycle remains a shim boundary. |
| Trajectory-planner tests | Planned | Native then WASM Node | Must call vendored LinuxCNC TP APIs; project code may only seed deterministic status/config state. |
## Per-Test Intake Checklist
Use this checklist when adding each LinuxCNC upstream test:
- Record the upstream test path.
- Copy or extract the original LinuxCNC files into `wasm-port/vendor/linuxcnc/`.
- Add the copied files to the relevant manifest or vendor-sync rule.
- Keep `.ini`, `.ngc`, `expected`, and original support files unchanged.
- Identify the LinuxCNC source files that own the behavior being tested.
- Add native runner coverage that calls vendored LinuxCNC code.
- Add WASM Node coverage through the exported C ABI and SDK filesystem bridge.
- Add browser coverage if the behavior crosses SDK, OPFS, or UI boundaries.
- Compare against upstream LinuxCNC output where practical.
- Update `docs/source-reuse-map.md`.
- Update `docs/compatibility-validation.md`.
- Add any blocked dependency to the blocked-test table below.
## Blocked Test Table
| LinuxCNC test path | Status | Blocking dependency | Next action |
| --- | --- | --- | --- |
| `tests/remap/introspect` | Blocked | Python remap modules and Python interpreter introspection. | Port or expose the required LinuxCNC Python remap runtime boundary before executing. |
| `tests/remap/fail/body-py` | Blocked | Python remap body error path. | Port the LinuxCNC Python remap body boundary before executing. |
| `tests/remap/fail/canon_error` | Blocked | Python prolog plus `emccanon.CANON_ERROR`. | Port LinuxCNC Python prolog and canonical-error boundary before executing. |
| `tests/remap/fail/epilog` | Blocked | Python epilog failure path. | Port LinuxCNC Python epilog boundary before executing. |
| `tests/remap/fail/prolog` | Blocked | Python prolog failure path. | Port LinuxCNC Python prolog boundary before executing. |
| `tests/remap/oword-pycall` | Blocked | Python O-word callable modules plus tool-change path. | Port the LinuxCNC Python O-word call boundary and required tool-change runtime edges. |
| `tests/remap/predefined-named-params` | Blocked | Python predefined named parameters. | Port the LinuxCNC Python named-parameter registration boundary. |
| `tests/remap/remap-io` full process/UI branch | Blocked | Full LinuxCNC process, HAL pins, motion I/O status propagation, and Python UI/test driver. | Keep the full process test upstream-only until those runtime boundaries exist; the NGC-only `test-ngc.ini` subpath is covered separately above. |
| `tests/remap/remap-reentry` | Blocked | Python generator remaps, HAL/motion runtime, and remap reentry. | Port LinuxCNC Python generator remap boundary and motion/HAL synchronization first. |
| `tests/remap/spindle` | Blocked | Python remap body and spindle runtime state. | Port the LinuxCNC Python remap boundary and spindle status adapter. |
| `tests/remap/variable-injection` | Blocked | Python prolog/epilog variable injection. | Port LinuxCNC Python prolog/epilog boundary before executing. |
| `tests/abort/*` | Blocked | Full LinuxCNC task/motion process, abort/stop handling, HAL files, and machine state after interruption. | Keep as upstream process reference until task/motion abort boundaries are available; do not reduce to standalone interpreter execution. |
| `tests/ccomp/early-exit` | Blocked | Full LinuxCNC process and motion-position validation after cutter-compensation early exit. | Use interpreter-only `tests/ccomp/*` cases first; revisit after motion state comparison is available. |
| `tests/classicladder/estop` | Blocked | ClassicLadder component, full LinuxCNC process, HAL files, and UI driver. | Keep as upstream-only reference until ClassicLadder/HAL process boundaries are represented. |
| `tests/halui/*` | Blocked | Full LinuxCNC process with `halui`, postgui HAL files, and UI/test driver interaction. | Establish HALUI/task runtime boundaries before porting. |
| `tests/hard-limits` | Blocked | Full LinuxCNC machine process, HAL limit wiring, and motion limit behavior. | Keep as upstream process reference until motion/HAL limit boundaries exist. |
| `tests/inifile/python_bindings` | Blocked | LinuxCNC Python INI bindings, not just vendored C++ `inifile.cc`. | Add only after a Python binding boundary is intentionally exposed, or keep covered by upstream. |
| `tests/io-startup/*` | Blocked | Full LinuxCNC `io` startup, task process, HAL files, and postgui setup. | Revisit after IO/task startup runtime boundaries are represented. |
| `tests/linuxcncrsh` | Blocked | Full LinuxCNC process plus `linuxcncrsh` socket protocol server. | Keep as upstream integration reference until linuxcncrsh/server boundaries are intentionally ported. |
| `tests/linuxcncrsh-tcp` | Blocked | Full LinuxCNC process plus TCP socket service and network timing. | Keep as upstream integration reference until linuxcncrsh/server boundaries are intentionally ported. |
| `tests/mdi-queue/*` | Blocked | Full LinuxCNC task/MDI queue behavior through linuxcncrsh, tool changes, and queued command synchronization. | Port only after task queue and linuxcncrsh boundaries are available. |
| `tests/motion/*` | Blocked | Full LinuxCNC sim process, HAL pins, linuxcncrsh, halsampler, and realtime motion behavior. | Keep as upstream motion integration reference; prefer standalone TP/kinematics probes for now. |
| `tests/motion-logger/*` | Blocked | Full LinuxCNC process plus motion-logger userspace program and mock-motion HAL setup. | Revisit after motion logging/runtime process boundaries are represented. |
| `tests/halcompile/*` | Blocked | LinuxCNC HAL component build/install flow, often including userspace or realtime component loading. | Keep as build-system/HAL integration reference; do not treat as interpreter semantics. |
| `tests/module-loading/*` | Blocked | HAL realtime module loading and RTAPI lifecycle through `halrun`/`loadrt`. | Covered only by narrow source/native probes today; full HAL module loading remains out of scope. |
| `tests/mb2hal/*` | Blocked | External `mb2hal` userspace component, Modbus I/O behavior, and HAL process wiring. | Keep as external-component integration reference until a host I/O boundary exists. |
| `tests/t0/*` | Blocked | Full LinuxCNC process, linuxcncrsh display, tool table startup, random/nonrandom toolchanger behavior, and HAL files. | Continue validating tool tables through vendored `tooldata_common.cc`; revisit full T0 startup through task/IO boundaries later. |
| `tests/tool-info/*` | Blocked | Full LinuxCNC task/IO startup with HALUI, startup tool state, and random/nonrandom toolchanger process behavior. | Keep tool parsing/formatting in standalone probes; revisit process startup behavior later. |
| `tests/toolchanger/*` | Blocked | Full LinuxCNC tool-change process, MDI/task behavior, IO state, and subroutine/user-M paths. | Continue standalone interpreter/tooldata coverage first; revisit after task/IO tool-change boundaries exist. |
| `tests/trajectory-planner/circular-arcs` | Blocked | Full LinuxCNC sim configs with task, HAL/Tcl files, GUI/display settings, and motion execution logs. | Keep using standalone TP API probes for planner code; full circular-arc machine tests require task/HAL/motion boundaries. |
| `tests/lowlevel/emcmot-error-mpsc` | Blocked | RIP-only build against LinuxCNC motion sources and low-level motion error driver. | Revisit only if low-level motion process test drivers are intentionally ported. |
| `tests/uspace/spawnv-root` | Blocked | Sudo-installed userspace HAL component and `spawnv` root behavior. | Keep upstream-only unless HAL component install/runtime support is added. |
## Next Work Batch
1. Continue inventorying `linuxcnc/tests/interp/*` for additional pure
interpreter cases that can run through vendored file execution without full
task/HAL/motion process state.
2. Keep adding skipped upstream families to the blocked-test table with a
concrete dependency reason before attempting implementation.
3. Run `wasm-port/tests/browser/verify_interp_browser.sh` and then
`wasm-port/tests/host/verify_host_smokes.sh` after each stable batch.

View File

@@ -809,24 +809,33 @@ Current five-axis switchkins status:
bridge-mill kinematics, loads vendored machine tool tables through
LinuxCNC `tooldata_load()`, and runs vendored `xyzac_switchkins.ngc`,
`xyzbc_switchkins.ngc`,
`xyzac_switchkins_test_1.ngc`, `xyzac_switchkins_test_3.ngc`,
`boat-xyzac.ngc`, `boat-xyzbc.ngc`, `impeller-7bl-xyzac.ngc`, and
`xyzab-tdr-demo.ngc`, plus bridge-mill `5axisgui.ngc` through LinuxCNC
remap/file execution paths.
`xyzac_switchkins_test_1.ngc`, `xyzac_switchkins_test_2.ngc`,
`xyzac_switchkins_test_3.ngc`, `boat-xyzac.ngc`, `boat-xyzbc.ngc`,
`impeller-7bl-xyzac.ngc`, and `xyzab-tdr-demo.ngc`, plus bridge-mill
`5axisgui.ngc` through LinuxCNC remap/file execution paths.
7. The WASM interpreter core now links vendored `interp_remap.cc` plus the
Python-only runtime edge stub, and the Node WASM smoke runs vendored
`xyzac_switchkins.ngc`, `xyzbc_switchkins.ngc`, `boat-xyzac.ngc`, and
`boat-xyzbc.ngc`, `impeller-7bl-xyzac.ngc`, `xyzab-tdr-demo.ngc`, and
`5axisgui.ngc` through the SDK C ABI without JavaScript M-code or
kinematics semantics.
`xyzac_switchkins.ngc`, `xyzbc_switchkins.ngc`,
`xyzac_switchkins_test_1.ngc`, `xyzac_switchkins_test_2.ngc`,
`xyzac_switchkins_test_3.ngc`, `boat-xyzac.ngc`, `boat-xyzbc.ngc`,
`impeller-7bl-xyzac.ngc`, `xyzab-tdr-demo.ngc`, and `5axisgui.ngc`
through the SDK C ABI without JavaScript M-code or kinematics semantics.
8. Browser smoke and the INI panel UI now expose the same validated 5-axis
remap execution path by copying vendored LinuxCNC sample-machine files into
the interpreter WASM filesystem and calling the SDK C ABI.
9. LinuxCNC upstream `tests/remap/duplicate-o-word` and
`tests/remap/m30-interaction` are now vendored unchanged and validated
through the generic remap file execution path. Native, Node WASM, and
browser interpreter smokes load the vendored INI, program, and remap
subroutines, then call vendored `Interp::parse_remap()`, `open()`,
`read()`, and `execute()`; standalone code only supplies the INI/file path
boundary.
Next work:
1. Continue broadening five-axis fixture coverage through the same
source-backed execution boundary.
1. Continue broadening source-backed remap coverage through LinuxCNC upstream
tests that can run through NGC REMAP/O-word/file execution without Python
semantics.
2. Evaluate additional vendored LinuxCNC five-axis sample machines and demos
after the TRT boat/impeller, TDR demo, and bridge-mill demo paths are
stable in native, Node WASM, browser, and UI remap paths.

View File

@@ -0,0 +1,486 @@
# LinuxCNC Sim Config Completion Plan
This plan tracks the work needed to run the LinuxCNC programs under
`linuxcnc/configs/sim` through the standalone native/WASM simulation runtime.
LinuxCNC source remains the semantic source of truth. Port code must live under
`wasm-port/`; do not edit `linuxcnc/` in place.
## Current Baseline
The latest strict harness run used `linuxcnc/configs/sim` as the program source,
selected the nearest INI/tool table for each `.ngc` unless an explicit sim
mapping is required, and ran `rs274` from the INI directory so relative
`SUBROUTINE_PATH` and `REMAP` entries resolve like a real sim config.
Result file:
```text
wasm-port/build/native/sim-configs/summary.tsv
```
Baseline:
```text
total: 159
pass: 151
fail: 8
timeout: 0
expected_fail: 8
unexpected_fail: 0
main: PASS 40, FAIL 8
macro_load: PASS 46, FAIL 0
remap_subroutine: PASS 65, FAIL 0
```
Remaining failures are explicit LinuxCNC-native baseline edges:
- `axis/external_offsets/*`: 4 failures from sim-only user M-codes `M111`.
- `axis/geometry/xyzc.ngc`: 1 failure from sim-only user M-code `M110`.
- `axis/foam/foam.ngc`: 1 failure from missing `U/V` axis support in the
LinuxCNC `bin/rs274` entry point.
- `axis/vismach/5axis/bridgemill/5axisgui.ngc`: 1 failure from missing `W`
axis support in the LinuxCNC `bin/rs274` entry point.
- `axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/incremental_repetition_g533.ngc`:
1 failure from an upstream demo line that uses bare `X/Y/Z` words after
`G53.6` without an explicit motion G-code.
## Target
The first target is not a browser UI feature. It is a repeatable native and
WASM simulation harness that can load and execute all `linuxcnc/configs/sim`
programs that are meaningful in a standalone non-hardware simulation context.
Acceptance criteria:
- The native sim-config harness reports all executable sim programs as `PASS`.
- Macro/remap files are validated by the correct entry point: direct execution
only for real programs, load/parse or remap-call validation for subroutines.
- WASM tests cover the same representative classes after the native harness is
green.
- Any remaining unsupported files are explicitly classified as native GUI or
hardware-only and excluded by rule, not by accident.
## Phase 1: Make The Harness A First-Class Test
Status: complete. The tracked script exists and is wired into the native
validation entry point.
1. Add a tracked script:
```text
wasm-port/tests/native/verify_sim_configs.sh
```
2. Move the ad hoc test logic into the script:
- scan only `linuxcnc/configs/sim`;
- identify `.ngc`, nearest `.ini`, nearest `.tbl`;
- run from the INI directory;
- write `summary.tsv`, stdout, stderr, and interpreter output under
`wasm-port/build/native/sim-configs/`;
- classify programs as `main`, `macro_load`, `remap_subroutine`, or
`unsupported_runtime_edge`;
- fail the script only on unexpected failures.
3. Add deterministic classification rules:
- files under `remap_subs/` and `nc_subroutines/` are not standalone main
programs;
- files with no `M2`, `M30`, or `%` are load/parse fixtures unless the INI
references them through `REMAP`;
- user M-code files are tested through `USER_M_PATH` resolution, not by
pretending LinuxCNC native process services exist.
4. Wire the script into existing validation:
```text
wasm-port/tests/native/verify_native_probes.sh
```
5. Completion check:
```bash
wasm-port/tests/native/verify_sim_configs.sh
```
Latest result:
```text
total: 159
pass: 151
fail: 8
timeout: 0
expected_fail: 8
unexpected_fail: 0
skipped: 0
```
## Phase 2: Load Machine Axes From INI
Status: partially complete for the port runtime. The standalone native/WASM
runtime now parses `[TRAJ] COORDINATES`, updates the standalone external axis
mask used by LinuxCNC `GET_EXTERNAL_AXIS_MASK()`, and applies the same
`Interp::_readers` filtering that upstream `rs274ngc_pre.cc` uses. Native
regression coverage verifies that `axis_foam.ini` enables `U/V` readers and
`bridgemill/5axis.ini` enables the `W` reader.
The `verify_sim_configs.sh` baseline still records the LinuxCNC `bin/rs274`
entry-point failures as expected failures. That harness is intentionally kept
as a LinuxCNC-native baseline while the port runtime coverage tracks this
phase's standalone behavior.
Current failures:
- `axis/foam/foam.ngc`: `Bad character 'u' used`
- `axis/vismach/5axis/bridgemill/5axisgui.ngc`: `Bad character 'w' used`
Root cause:
The current standalone interpreter initialization does not configure the active
axis mask from `[TRAJ] COORDINATES` / `[KINS] KINEMATICS`. Native LinuxCNC
accepts `U/V/W` only when the machine config declares those axes.
Implementation steps:
1. Add a machine-config loader in `runtime/core/linuxcnc_wrap/`, for example:
```text
linuxcnc_machine_config.hh
linuxcnc_machine_config.cpp
```
2. Reuse vendored `inifile.cc` to parse:
- `[TRAJ] COORDINATES`
- `[KINS] KINEMATICS`
- `[DISPLAY] GEOMETRY`
- `[RS274NGC] PARAMETER_FILE`
- `[RS274NGC] SUBROUTINE_PATH`
- `[RS274NGC] USER_M_PATH`
- `[EMCIO] TOOL_TABLE`
3. Extend `initialize_minimal_interp()` / the runtime equivalent to set the
interpreter setup fields from the parsed machine config instead of hardcoded
`XYZ`.
4. Add focused native fixtures:
- `axis_foam.ini` + `foam.ngc` accepts `U/V`.
- `bridgemill/5axis.ini` + `5axisgui.ngc` accepts `W`.
5. Add the same coverage to the WASM SDK once native is green.
Completion check:
```bash
wasm-port/tests/native/verify_sim_configs.sh --only axis/foam/foam.ngc
wasm-port/tests/native/verify_sim_configs.sh --only axis/vismach/5axis/bridgemill/5axisgui.ngc
```
## Phase 3: Implement Standalone User M-Code Dispatch
Status: complete for the standalone native/WASM runtime boundary. The port now
reads `[DISPLAY] PROGRAM_PREFIX` and `[RS274NGC] USER_M_PATH`, searches
executable `M100` through `M199` files using the same order as LinuxCNC task
initialization, registers them in LinuxCNC's `USER_DEFINED_FUNCTION` table, and
records `USER_M_COMMAND` canonical boundary events instead of spawning host
processes. Native probes cover `axis/geometry` `M110` and
`axis/external_offsets` `M111`; Node WASM covers minimal `M110` and `M111`
fixtures through the Emscripten filesystem.
The `verify_sim_configs.sh` baseline still records these files as expected
failures because it intentionally runs LinuxCNC `bin/rs274`, not the standalone
task/runtime adapter.
Current failures:
- `axis/external_offsets/*.ngc`: unknown `M111`
- `axis/geometry/xyzc.ngc`: unknown `M110`
Root cause:
Native LinuxCNC resolves user M-codes through `[DISPLAY] PROGRAM_PREFIX` and
`[RS274NGC] USER_M_PATH` during task initialization, registers matching
executable `M100..M199` handlers with the interpreter, and later runs external
scripts through the task process boundary. The standalone runtime must register
the same interpreter boundary without running host processes in WASM/browser.
Implementation steps:
1. Locate the upstream M-code dispatch path in LinuxCNC and vendor the minimum
source needed to preserve semantics, or add a narrow runtime-edge adapter if
the upstream path is process-bound. Done: the adapter mirrors
`src/emc/task/emctask.cc` search/registration behavior and keeps process
execution outside CNC semantics.
2. Add `USER_M_PATH` parsing to the machine-config loader. Done.
3. For native standalone tests. Done:
- resolve `M100` through `M199` against configured search paths;
- register only executable files;
- emit deterministic `USER_M_COMMAND` boundary events.
4. For WASM/browser. Done for Node WASM:
- do not spawn host processes;
- use a host-boundary user-M adapter that registers deterministic
message-emitting handlers for sim-only notification M-codes;
- document this as a runtime edge, not CNC semantics.
5. Add tests. Done:
- `M110` from `axis/geometry`;
- `M111` from `axis/external_offsets`;
- minimal WASM `M110` and `M111` fixtures.
Completion check:
```bash
wasm-port/tests/native/verify_sim_configs.sh --only axis/external_offsets
wasm-port/tests/native/verify_sim_configs.sh --only axis/geometry/xyzc.ngc
```
Standalone runtime checks:
```bash
wasm-port/tests/native/verify_native_probes.sh
wasm-port/tests/wasm/node/verify_interp_wasm.sh
```
## Phase 4: Bring Up Python Remap Runtime Edges
Status: complete for the native sim-config harness. Current checks:
```text
gmoccapy: total 38, pass 38, fail 0
axis/laser: total 3, pass 3, fail 0
```
Root cause:
The configs use LinuxCNC Python remap modules. Earlier harness runs failed while
initializing `python/toplevel.py`; current native runs now resolve and execute
these configs under the LinuxCNC `rs274` baseline.
Implementation steps:
1. Preserve upstream behavior where possible:
- inspect vendored LinuxCNC Python plugin interfaces;
- identify exact APIs used by:
- `configs/sim/gmoccapy/python/toplevel.py`
- `configs/sim/gmoccapy/python/remap.py`
- `configs/sim/gmoccapy/python/stdglue.py`
- `configs/sim/axis/laser/python/toplevel.py`
- `configs/sim/axis/laser/python/remap.py`
2. Split the implementation into two layers:
- native harness support using the host Python runtime, if available;
- WASM support using a documented adapter boundary or a Python-free
equivalent only for runtime edges, not G-code semantics.
3. Add runtime state adapters required by Python remap:
- selected tool and pocket;
- tool table access;
- interpreter status object fields used by stdglue;
- message/error reporting;
- canonical tool-change side effects needed by `M6`, `M61`, and laser
remaps.
4. Make Python module path resolution match LinuxCNC:
- INI directory is the base directory;
- `PYTHONPATH` includes config `python/` directories;
- remap modules load relative to the sim config.
5. Add narrowly-scoped tests before running all 38 gmoccapy programs. Done:
- one gmoccapy tool-change macro;
- one gmoccapy lathe macro;
- one gmoccapy 5-axis example;
- one laser raster/vector program.
Completion check:
```bash
wasm-port/tests/native/verify_sim_configs.sh --only gmoccapy
wasm-port/tests/native/verify_sim_configs.sh --only axis/laser
```
## Phase 5: Support TWP Remaps Including G69
Status: mapping complete. The harness now maps
`axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/*` through the
explicit `xyzacb-trsrn_twp/xyzacb-trsrn.ini` machine config instead of falling
back to `axis/axis.ini`. That loads the TWP `G69` remap declarations correctly,
and 14 of the 15 TWP demo/remap programs now pass.
Current failures:
- `axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/incremental_repetition_g533.ngc`
fails in the LinuxCNC `rs274` baseline because line 10 uses bare
`x50y50z150` after `G53.6`; same-directory demos use explicit `G0` motion
words at this point.
Root cause:
The demo programs rely on table/spindle rotary TWP remaps. The original test
mapping fell back to `axis/axis.ini` for these demo files because the actual
INI is in a child directory:
```text
axis/vismach/5axis/table-rotary_spindle-rotary-nutating/
xyzacb-trsrn_twp/xyzacb-trsrn.ini
xyzbca-trsrn_twp/xyzbca-trsrn.ini
```
Implementation steps:
1. Improve sim-config mapping. Done:
- if a `.ngc` is under a `demos/` sibling of machine-specific INI
directories, map it to the appropriate TWP INI instead of walking upward
to `axis/axis.ini`;
- encode this as explicit metadata in the harness, not a fragile heuristic.
2. Ensure `SUBROUTINE_PATH` includes `../remap_subs:../demos` as declared by
the TWP INIs.
3. Verify remap subroutines:
- `g69remap.ngc`
- `g531remap.ngc`
- `g533remap.ngc`
- `g536remap.ngc`
4. Add a native test for each failing demo.
Latest result:
```text
total: 15
pass: 14
fail: 1
timeout: 0
expected_fail: 1
unexpected_fail: 0
skipped: 0
```
Completion check:
```bash
wasm-port/tests/native/verify_sim_configs.sh --only table-rotary_spindle-rotary-nutating
```
## Phase 6: Promote Native Coverage To WASM
Status: complete for representative Node and browser WASM coverage. Dedicated
Node and browser smokes now pass a representative vendored `configs/sim` subset
through the SDK `runSimConfigProgram()` host boundary, which copies files into
the Emscripten filesystem and forwards execution to existing LinuxCNC-backed C
ABI paths. They cover:
- `axis/foam/foam.ngc` with `axis_foam.ini`, verifying INI-driven `U/V` axis
mask handling in WASM.
- `axis/vismach/5axis/bridgemill/5axisgui.ngc` with `5axis.ini`, verifying
INI-driven `W` axis mask handling and bridge-mill NGC remap execution in
WASM.
- `axis/geometry/xyzc.ngc` with `xyzc.ini` and real executable `M110`, verifying
`USER_M_PATH` registration in WASM.
- `axis/external_offsets/dyn_demo.ngc` with `dynamic_offsets.ini` and real
executable `M111`, verifying the same user-M boundary against an upstream sim
program.
Completion checks:
```bash
wasm-port/tests/wasm/node/verify_sim_configs_wasm.sh
wasm-port/tests/browser/verify_interp_browser.sh
```
Remaining work:
1. Extend `runtime/core/linuxcnc_wrap/linuxcnc_interp_wasm.cpp` with the same
machine-config entry point used by native tests. Done for the existing
`runFileWithIni()` file-execution path.
2. Extend `runtime/sdk/src/linuxcnc-interp.js` with a host-boundary method such
as:
```js
runSimConfigProgram({ iniPath, programPath, files })
```
Done. The method only writes caller-provided text files into the
Emscripten filesystem, applies executable bits for user M-code files, and
forwards execution to the existing LinuxCNC-backed C ABI path. It does not
implement CNC semantics in JavaScript.
3. Copy required sim config files into the Emscripten FS:
- INI;
- tool table;
- parameter file;
- `.ngc` program;
- `SUBROUTINE_PATH` files;
- `USER_M_PATH` handler files or registered adapter handlers.
Done for the representative Node and browser subsets.
4. Add Node WASM coverage. Done:
```text
wasm-port/tests/wasm/node/verify_sim_configs_wasm.mjs
wasm-port/tests/wasm/node/verify_sim_configs_wasm.sh
```
5. Add representative browser coverage. Done in
`wasm-port/tests/browser/interp_smoke.html` through the existing browser
interpreter smoke and the same `runSimConfigProgram()` SDK boundary as Node.
## Phase 7: Documentation And Drift Control
Status: complete for the current representative sim-config WASM/browser
coverage. The documentation and manifest now record the native, Node WASM,
browser, source reuse, and vendor-sync state for the selected sim-config
programs.
1. Update `docs/compatibility-validation.md` with the sim-config matrix. Done.
2. Update `docs/source-reuse-map.md` for newly vendored source files. Done.
3. Update `tools/source-manifest.txt` and `tools/verify_vendor_sync.sh` if new
LinuxCNC files are copied into `wasm-port/vendor/linuxcnc`. Done for the
representative `axis/foam`, `axis/geometry`, and `axis/external_offsets`
sim-config files; no `verify_vendor_sync.sh` logic change was needed.
4. Preserve the latest result summary as a machine-readable artifact, but do
not commit generated logs unless they are intentionally used as fixtures.
Done: generated logs remain under build/test output directories, while the
tracked documentation records only the current summary values and validation
commands.
## Recommended Work Order
1. Harness first: make `verify_sim_configs.sh` reproducible.
2. Axis config next: unblock `U/V/W` failures.
3. TWP mapping: complete; remaining TWP demo failures are Python/HAL remap
runtime edges.
4. User M-code dispatch: small runtime-edge feature, unblocks five files.
5. Python remap runtime: largest block; do it after the harness and smaller
runtime edges are stable.
6. WASM promotion after native parity.
## Non-Goals
- Do not implement a new JavaScript or project-authored G-code interpreter.
- Do not edit `linuxcnc/configs/sim` or any upstream `linuxcnc/` file to make
tests pass.
- Do not fake path, modal, kinematic, tool, or parameter semantics in the SDK.
- Do not treat gmoccapy native GUI code as browser UI implementation. Only its
simulation/remap behavior is relevant to this runtime.

View File

@@ -40,13 +40,18 @@ Current validation is intentionally mechanical:
| Identity/trivial kinematics | `src/emc/kinematics/kinematics.h`, `cubic.h`, `kins_util.c`, `trivkins.c` | Copy unchanged | HAL component lifecycle and RTAPI module metadata are replaced by standalone shims; forward/inverse mapping behavior remains LinuxCNC source | Vendor byte sync, per-file source probes, `linuxcnc_kinematics_probe` |
| Switchable 5-axis bridge kinematics | `src/emc/kinematics/5axiskins.c`, `switchkins.c`, `switchkins.h`, `userkfuncs.c`, plus `src/rtapi/rtapi_ctype.h` | Copy unchanged | HAL pin allocation, HAL component lifecycle, and RTAPI module metadata are standalone runtime edges; switchable 5-axis forward/inverse behavior remains LinuxCNC source | Vendor byte sync, per-file source probes, `linuxcnc_5axis_kinematics_probe` |
| TRT table-rotary kinematics | `src/emc/kinematics/trtfuncs.c`, `xyzac-trt-kins.c`, `xyzbc-trt-kins.c` | Copy unchanged | HAL pin allocation and switchkins lifecycle stay runtime boundaries; XYZAC/XYZBC TRT forward/inverse behavior remains LinuxCNC source | Vendor byte sync, per-file source probes, `linuxcnc_xyzac_trt_kinematics_probe`, `linuxcnc_xyzbc_trt_kinematics_probe` |
| Five-axis switchkins machine configs and M428/M429/M430 remaps | `configs/sim/axis/vismach/5axis/bridgemill/*`, `table-dual-rotary/*`, and `table-rotary-tilting/*` selected INI, HAL, tool-table, XML, demo, and `remap_subs/*.ngc` files plus `src/emc/rs274ngc/interp_remap.cc` | Copy unchanged | `M428`, `M429`, and `M430` remain LinuxCNC `REMAP` entries that call LinuxCNC NGC subroutines using `M68`, `M66`, `_hal[motion.switchkins-type]`, and the INI/HAL `motion.analog-out-03 => motion.switchkins-type` link; standalone remap descriptor parsing routes through vendored `Interp::parse_remap()` and `find_ngc_file()`, and NGC remap/file execution routes through vendored LinuxCNC O-word and `open()`/`read()`/`execute()` paths while HAL synchronization stays a runtime adapter boundary | Vendor byte sync, `linuxcnc_5axis_remap_asset_probe`, `linuxcnc_remap_parse_harness`, `linuxcnc_remap_hal_sync_harness`, `linuxcnc_5axis_remap_execute_harness`, `tests/wasm/node/verify_interp_wasm.sh`, `tests/browser/verify_interp_browser.sh`, `tests/browser/verify_ini_panel_browser.sh` |
| Five-axis switchkins machine configs and M428/M429/M430 remaps | `configs/sim/axis/vismach/5axis/bridgemill/*`, `table-dual-rotary/*`, and `table-rotary-tilting/*` selected INI, HAL, tool-table, XML, demo, and `remap_subs/*.ngc` files plus `src/emc/rs274ngc/interp_remap.cc` | Copy unchanged | `M428`, `M429`, and `M430` remain LinuxCNC `REMAP` entries that call LinuxCNC NGC subroutines using `M68`, `M66`, `_hal[motion.switchkins-type]`, and the INI/HAL `motion.analog-out-03 => motion.switchkins-type` link; standalone remap descriptor parsing routes through vendored `Interp::parse_remap()` and `find_ngc_file()`, and NGC remap/file execution routes through vendored LinuxCNC O-word and `open()`/`read()`/`execute()` paths while HAL synchronization stays a runtime adapter boundary | Vendor byte sync, `linuxcnc_5axis_remap_asset_probe`, `linuxcnc_remap_parse_harness`, `linuxcnc_remap_hal_sync_harness`, `linuxcnc_5axis_remap_execute_harness`, `tests/wasm/node/verify_interp_wasm.sh`, `tests/wasm/node/verify_sim_configs_wasm.sh`, `tests/browser/verify_interp_browser.sh`, `tests/browser/verify_ini_panel_browser.sh` |
| Representative sim-config machine programs | `configs/sim/axis/foam/*`, `configs/sim/axis/geometry/M110`, `xyzc.ini`, `xyzc.ngc`, `configs/sim/axis/external_offsets/M111`, `dyn_demo.ngc`, `dynamic_offsets.ini`, `eoffset.tbl`, and `configs/sim/axis/sim.tbl` | Copy unchanged | The `foam`, `xyzc`, and dynamic external-offset sample programs remain LinuxCNC sim-config assets. The standalone boundary only copies INI, tool table, G-code, and executable user-M files into the native or WASM filesystem, then calls vendored LinuxCNC INI parsing and `Interp::open()`/`read()`/`execute()` through the existing machine-config adapter. The JS SDK `runSimConfigProgram()` is only the host file-staging helper for this boundary: it writes caller-provided text files to the Emscripten filesystem, applies executable bits, and forwards to LinuxCNC-backed C ABI entry points. `M110`/`M111` process execution stays a runtime boundary represented by deterministic `USER_M_COMMAND` canonical events | Vendor byte sync, `tests/native/verify_sim_configs.sh`, `tests/wasm/node/verify_sim_configs_wasm.sh`, `tests/browser/verify_interp_browser.sh` |
| Representative `nc_files` examples | `nc_files/arcspiral.ngc`, `nc_files/factorial.ngc`, `nc_files/hole-circle.ngc`, `nc_files/m6demo.ngc` | Copy unchanged | These upstream `linuxcnc/nc_files` examples are copied byte-for-byte into the WASM vendor tree after the native `nc_files` harness classifies the broader directory. Node and browser tests only stage the original `.ngc` text in the Emscripten filesystem and call the LinuxCNC-backed `Interp::open()`, `read()`, and `execute()` path through the existing SDK; no G-code, O-word, tool-change, or M-code behavior is implemented in JavaScript | Vendor byte sync, `tests/native/verify_nc_files.sh`, `tests/wasm/node/verify_nc_files_wasm.sh`, `tests/browser/verify_interp_browser.sh`, `tests/host/verify_host_smokes.sh` |
| LinuxCNC remap regression fixtures | `tests/remap/duplicate-o-word/*`, `tests/remap/fail/args.0/*`, `tests/remap/fail/args.1/*`, `tests/remap/fail/args.2/*`, `tests/remap/fail/body-ngc/*`, `tests/remap/m30-interaction/*`, `tests/remap/nested-remaps-oword/*`, `tests/remap/posargs.0/*`, `tests/remap/sequencing/*`, selected NGC-only `tests/remap/remap-io/test-ngc.ini` plus `io_*.ngc`, and `src/emc/rs274ngc/interp_remap.cc` plus `interp_o_word.cc` | Copy unchanged | The upstream duplicate O-word, NGC-only remap failure, M30/remap-level interaction, nested O-word remap, positional-argument remap, G/M remap sequencing, and remap-IO NGC subroutine regressions remain LinuxCNC REMAP/O-word/file or MDI execution tests. The standalone boundary only copies the upstream test files into native or WASM filesystems, reads LinuxCNC INI `SUBROUTINE_PATH`, `REMAP`, and `OWORD_NARGS` entries, and calls vendored `Interp::parse_remap()`, `open()`, `read()`, and `execute()` or feeds the upstream remap-IO MDI sequence into vendored `Interp::execute()`; the continue-on-error runner path only mirrors LinuxCNC `rs274 -n 0` test execution and does not implement duplicate-label, O-word, nested remap, M30, positional-argument, failure, sequencing, M62-M68, M66 input, or remap semantics | Vendor byte sync, `linuxcnc_duplicate_oword_remap_harness`, `tests/wasm/node/verify_interp_wasm.sh`, `tests/browser/verify_interp_browser.sh` |
| LinuxCNC interpreter regression fixtures | `tests/interp/do-while-break/*`, `tests/interp/oword-bug315/*`, `tests/interp/oword-bug315-p2/*`, `tests/interp/exists/*`, `tests/interp/return-value/*`, `tests/interp/subs-follow-main/*`, `tests/interp/fractional-linenumbers/*`, `tests/interp/namedparam-bug424/*`, selected `tests/interp/rotation/*` pure interpreter cases, `tests/interp/iniparam/*`, `tests/interp/iniparam-failassign/*`, `tests/interp/m19/*`, `tests/interp/magic_comments/param_format_printing/*`, selected `tests/interp/m98m99/*` pure interpreter cases, `tests/interp/sub-call-from-sub/*`, `tests/interp/sequence-number/*`, `tests/interp/nested-sub-error/*`, `tests/interp/nested-sub-in-file-error/*`, `tests/interp/abort-hot-comment/*`, plus vendored interpreter/O-word sources including `interp_o_word.cc`, `interp_read.cc`, `interp_execute.cc`, `interp_find.cc`, `interp_namedparams.cc`, and `rs274ngc_pre.cc` | Copy unchanged | The upstream do/while/break, O-word bug315, `EXISTS[]`, subroutine return-value, subs-after-main, fractional line-number, named-parameter, selected rotation/G53/G28 absolute-position and endpoint, INI named-parameter lookup/read-only protection, M19 spindle-orient offset/timeout handling, magic-comment parameter formatting, selected Fanuc `M98/M99` and O-expression call regressions, external-subroutine-call, external-subroutine line-number, nested-subroutine-definition rejection, blocked forward-seek-to-later-numbered-sub, and `(ABORT,...)` hot-comment parameter-expansion regressions remain LinuxCNC interpreter file-execution tests. The standalone boundary only vendors the original upstream assets, copies `*.ngc`, `test.ini`, `test.tbl`, `subs/*.ngc`, and referenced external subroutine `.ngc` files into native or WASM filesystems where applicable, sets the LinuxCNC `INI_FILE_NAME` runtime edge for `_ini[...]`, applies LinuxCNC INI machine settings such as `[RS274NGC]ORIENT_OFFSET`, reads LinuxCNC INI `SUBROUTINE_PATH`, captures LinuxCNC `(PRINT,...)` output through the existing stdout/Emscripten `print` boundary, and calls vendored `Interp::open()`, `read()`, and `execute()`; it does not implement O-word loop, break, subroutine, dynamic call, `M98/M99`, `EXISTS[]`, named-parameter, absolute-position named-parameter, G28/G53 endpoint, INI-variable, read-only parameter, line-number, spindle-speed, spindle-orient, magic-comment formatting, subroutine lookup, ABORT hot-comment, error, or branch semantics | Vendor byte sync, `linuxcnc_interp_minimal_harness`, `tests/wasm/node/verify_interp_wasm.sh`, `tests/browser/verify_interp_browser.sh` |
| Additional non-switchable kinematics | `src/emc/kinematics/corexykins.c`, `rotatekins.c`, `rosekins.c`, `maxkins.c`, `lineardeltakins.c`, `lineardeltakins-common.h`, `rotarydeltakins.c`, `rotarydeltakins-common.h`, `scorbot-kins.c`, `tripodkins.c`, `scarakins.c`, `pumakins.c`, `pumakins.h`, `genhexkins.c`, `genhexkins.h`, `genserfuncs.c`, `genserkins.c`, `genserkins.h`, `ugenserkins.c`, `pentakins.c`, `pentakins.h`, `cubic.c` | Copy unchanged | HAL pin allocation, HAL parameter allocation, HAL component lifecycle, RTAPI module metadata, Go math C/C++ linkage, switchkins iterative-forward warmup, and userspace test-program process entry remain standalone runtime edges; forward/inverse behavior remains LinuxCNC source where the module exposes it | Vendor byte sync, per-file source probes, `linuxcnc_corexy_kinematics_probe`, `linuxcnc_rotate_kinematics_probe`, `linuxcnc_rose_kinematics_probe`, `linuxcnc_max_kinematics_probe`, `linuxcnc_lineardelta_kinematics_probe`, `linuxcnc_rotarydelta_kinematics_probe`, `linuxcnc_scorbot_kinematics_probe`, `linuxcnc_tripod_kinematics_probe`, `linuxcnc_scara_kinematics_probe`, `linuxcnc_puma_kinematics_probe`, `linuxcnc_genser_kinematics_probe`, `linuxcnc_genhex_kinematics_probe`, `linuxcnc_pentakins_kinematics_probe` |
| Trajectory planner | `src/emc/tp/tp.c`, `tc.c`, `tcq.c`, `spherical_arc.c`, `blendmath.c`, `sp_scurve.c`, `ruckig_wrapper.c`, plus matching `*.h` files | Copy unchanged | Native realtime scheduling and motion process state are replaced by standalone probe setup; the WASM TP probe uses the same deterministic status/config boundary and calls vendored TP APIs through a narrow C ABI | Vendor byte sync, per-file source probes, `linuxcnc_tp_api_probe`, `tests/wasm/node/verify_tp_wasm.sh` |
| Ruckig C planner support | Selected `src/emc/tp/cruckig/*.c` and `*.h` files in the manifest | Copy unchanged | Used as LinuxCNC planner support code through vendored TP sources | Vendor byte sync, per-file source probes, `tests/wasm/node/verify_tp_wasm.sh` |
| Posemath | `src/libnml/posemath/posemath.cc`, `_posemath.c`, `gomath.c`, `sincos.c`, and matching headers | Copy unchanged | `gomath.c` is compiled as C; `rtapi.h` shim is C/C++ compatible for this boundary | Vendor byte sync, per-file source probes, TP native and WASM probes |
| RS274 interpreter state and parser | `src/emc/rs274ngc/modal_state.*`, `interp_internal.*`, `interp_read.cc`, `interp_check.cc`, `interp_execute.cc`, `interp_find.cc`, `interp_array.cc`, `interp_queue.*`, `rs274ngc*`, `units.h` | Copy unchanged | Python/remap/runtime edges are isolated in standalone wrappers and shims; parser and execution logic remain LinuxCNC source | Vendor byte sync, per-file source probes, interpreter harness fixtures |
| RS274 conversion semantics | `src/emc/rs274ngc/interp_convert.cc`, `interp_arc.cc`, `interp_inverse.cc`, `interp_cycles.cc`, `interp_g7x.cc`, `interp_o_word.cc`, `interp_write.cc` | Copy unchanged | Canonical calls are captured by standalone event sink functions; conversion behavior stays in vendored LinuxCNC files; feed-rate state is read back through the canonical runtime boundary during length-unit conversion; single-axis rotary indexer lock/unlock dispatch remains vendored LinuxCNC `issue_straight_index()` behavior | Vendor byte sync, per-file source probes, canonical fixture suite, no standalone `Interp::convert_g()` guard, `linuxcnc_indexer_harness`, `tests/wasm/node/verify_interp_wasm.sh` and `tests/browser/verify_interp_browser.sh` rotary-indexer assertions |
| User M-code registration boundary | `src/emc/task/emctask.cc`, `src/emc/rs274ngc/interp_convert.cc`, `src/emc/rs274ngc/interp_queue.cc` | Runtime-edge adapter | Vendored interpreter conversion still checks LinuxCNC `USER_DEFINED_FUNCTION` before accepting `M100..M199` and queues through vendored `enqueue_M_USER_COMMAND()`. The standalone machine-config adapter mirrors LinuxCNC task search order for `[DISPLAY]PROGRAM_PREFIX` and `[RS274NGC]USER_M_PATH`, registers executable M-code files in `USER_DEFINED_FUNCTION`, calls the canonical `FINISH()` boundary, and records deterministic `USER_M_COMMAND` events instead of spawning host processes in WASM/browser. | `linuxcnc_interp_minimal_harness` sim `M110`/`M111` probes, `tests/wasm/node/verify_interp_wasm.sh` minimal `M110`/`M111` fixtures |
| Named parameters and tool slot status | `src/emc/rs274ngc/interp_namedparams.cc`, related interpreter headers | Copy unchanged | `_ini[...]` and `_hal[...]` resolve through standalone INI/HAL adapters while lookup order stays LinuxCNC-derived; current/selected tool slot reads for vendored `Interp::synch()` come from the standalone tool adapter | Vendor byte sync, source probe, `linuxcnc_namedparam_harness`, `linuxcnc_interp_init_harness`, `tests/wasm/node/verify_interp_wasm.sh` and `tests/browser/verify_interp_browser.sh` `Interp::synch()` tool-slot assertions plus `Interp::init_named_parameters()`/`find_named_param()` named-parameter lookup assertions |
| Tool table parsing and formatting | `src/emc/tooldata/tooldata_common.cc` | Copy unchanged plus standalone storage callbacks | Native file parsing/formatting stays in vendored LinuxCNC source; the standalone tool adapter supplies `tooldata_get()`/`tooldata_put()` storage and index lookup, the WASM boundary only selects the LinuxCNC non-random or random-toolchanger branch via `tooldata_init()`, and OPFS remains a host-side persistence boundary | Vendor byte sync, `linuxcnc_tooldata_common_source_probe`, `tests/wasm/node/verify_interp_wasm.sh` non-random/random load/save tool-table assertions |
| Dynamic interpreter base | `src/emc/rs274ngc/interp_base.*` | Copy unchanged | `interp_base.cc` source probe uses standalone `EMC2_HOME` compile-time path boundary for LinuxCNC dynamic interpreter lookup | Vendor byte sync, `linuxcnc_interp_base_source_probe` |
@@ -59,8 +64,9 @@ Current validation is intentionally mechanical:
| RTAPI | `rtapi_*.h`, TP, posemath, motion headers | Minimal standalone shim in `runtime/core/shims/rtapi.h` |
| NML transport | `emc.hh`, motion/NML type headers | Transport is not ported; only the status/type edges needed by vendored compute code are exposed through standalone shims and probes |
| HAL runtime | named parameter lookup, kinematics component lifecycle, and runtime status edges | Standalone HAL adapter under `runtime/core/linuxcnc_wrap/` |
| Python/remap | `rs274ngc_pre.cc`, `interp_o_word.cc`, `interp_remap.cc`, remap hooks, selected LinuxCNC `configs/sim/axis/vismach/5axis/*/remap_subs/*.ngc` files | Python calls remain stubbed at the runtime boundary today; five-axis M428/M429/M430 source assets are vendored unchanged, the NGC remap descriptor path parses through vendored LinuxCNC code, and native validation now executes the switchkins NGC remap files plus selected demo programs through vendored LinuxCNC O-word and file execution paths while `_hal[...]` synchronization is supplied by the standalone HAL adapter |
| Canonical machine actions | `interp_convert.cc`, `interp_execute.cc`, `interp_queue.cc` | Captured by standalone canonical event sink functions for regression fixtures |
| User M-code process execution | `emctask.cc`, `interp_convert.cc`, `interp_queue.cc` | Search and registration are mirrored at the standalone machine-config boundary; native/WASM tests record deterministic `USER_M_COMMAND` events and do not spawn host processes |
| Python/remap | `rs274ngc_pre.cc`, `interp_o_word.cc`, `interp_remap.cc`, remap hooks, selected LinuxCNC `configs/sim/axis/vismach/5axis/*/remap_subs/*.ngc` files, `tests/remap/duplicate-o-word/*`, `tests/remap/fail/args.0/*`, `tests/remap/fail/args.1/*`, `tests/remap/fail/args.2/*`, `tests/remap/fail/body-ngc/*`, `tests/remap/m30-interaction/*`, `tests/remap/nested-remaps-oword/*`, `tests/remap/posargs.0/*`, `tests/remap/sequencing/*`, and NGC-only `tests/remap/remap-io/test-ngc.ini` plus `io_*.ngc` | Python calls remain stubbed at the runtime boundary today; five-axis M428/M429/M430 source assets and the upstream NGC remap regression files are vendored unchanged. NGC remap descriptor paths parse through vendored LinuxCNC code, native/WASM/browser validation executes the NGC remap files through vendored LinuxCNC O-word and file execution paths, and the remap-IO NGC-only branch feeds the upstream MDI sequence into vendored LinuxCNC `Interp::execute()` while external M66 input values and `_hal[...]` synchronization remain standalone runtime adapter boundaries |
| Canonical machine actions | `interp_convert.cc`, `interp_execute.cc`, `interp_queue.cc`, selected `tests/interp/*` regression assets | Captured by standalone canonical event sink functions for regression fixtures; vendored upstream interpreter test assets remain unchanged and are executed through LinuxCNC file execution |
| Realtime scheduling | TP and motion headers | Not ported; native TP probes seed deterministic status/config state |
| GUI | None used as implementation | Native LinuxCNC GUI remains reference-only |