Files
cnc_wams/wasm-port/docs/compatibility-validation.md
wangdequan 83f409c900 补充 INI WASM 文件名查询覆盖
结论:Node INI WASM smoke 现在通过 LinuxCNC-backed getString 路径验证 PARAMETER_FILE 和 TOOL_TABLE 文件名查询,支撑后续 OPFS 会话桥接输入。
2026-06-08 10:09:14 +08:00

463 lines
23 KiB
Markdown

# Compatibility Validation
## Purpose
This document records how the standalone LinuxCNC WASM port currently proves
that migrated behavior remains tied to LinuxCNC source code and fixture
semantics.
The primary native validation command is:
```bash
wasm-port/tests/native/verify_native_probes.sh
```
The current WASM smoke validation command is:
```bash
wasm-port/tests/wasm/node/verify_ini_wasm.sh
```
The current WASM interpreter-core smoke validation command is:
```bash
wasm-port/tests/wasm/node/verify_interp_wasm.sh
```
The current OPFS host-boundary validation command is:
```bash
wasm-port/tests/opfs/node/verify_file_service.sh
```
The current browser smoke validation command is:
```bash
wasm-port/tests/browser/verify_ini_panel_browser.sh
```
The current browser interpreter smoke validation command is:
```bash
wasm-port/tests/browser/verify_interp_browser.sh
```
The current aggregate host/WASM/browser smoke command is:
```bash
wasm-port/tests/host/verify_host_smokes.sh
```
## Validation Chain
The native validation script runs these checks in order:
1. `tools/verify_upstream_baseline.sh`
Confirms `../linuxcnc` is at the recorded upstream commit in
`tools/upstream-baseline.txt`.
2. `tools/verify_vendor_sync.sh`
Confirms every manifest file is present in `vendor/linuxcnc/`, no extra
vendored file exists, and every vendored file is byte-identical to upstream.
3. `tools/verify_no_standalone_cnc_semantics.sh`
Confirms standalone code has not introduced project-owned `Interp::...`
member definitions outside the documented Python/remap runtime-edge stubs.
4. `tools/verify_native_linuxcnc_fixture_baseline.sh`
Runs a side-by-side fixture baseline through upstream
`../linuxcnc/bin/rs274` and compares normalized canonical events for
fixtures that do not require standalone-only runtime adapters.
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`
Checks probe exit codes, source-probe coverage, harness stdout, canonical
fixture events, and expected error behavior.
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
boolean queries against a file written to the Emscripten filesystem. Boolean
conversion is validated through vendored LinuxCNC `iniFindBool()`, and
machine-session file-name lookup is validated through LinuxCNC string queries
for `[RS274NGC]PARAMETER_FILE` and `[EMCIO]TOOL_TABLE`.
The WASM interpreter-core smoke script builds
`build/wasm/core/linuxcnc_interp.js` and `linuxcnc_interp.wasm` from the same
vendored LinuxCNC interpreter source set used by the native minimal
interpreter harness. It loads the module in Node through
`runtime/sdk/src/index.js`, runs the first WASM interpreter fixture
group through `Interp::execute()`, and compares emitted canonical events plus
required LinuxCNC `_setup` state readback with the matching files in
`tests/fixtures/canon/`. It also writes selected G-code fixtures into the
Emscripten filesystem through the SDK and runs them through LinuxCNC
`Interp::open()`, `Interp::read()`, and `Interp::execute()` to validate the
file execution path. 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 and `.bak` backup file boundary.
The OPFS host-boundary script validates the JavaScript file-service adapter
with a Node mock of the browser File System Access handles. It covers nested
directory creation, text save/load, missing file behavior, invalid relative
paths, unavailable OPFS storage, and the host-side OPFS path model for INI,
tool table, parameter, G-code, preview-cache, and session-snapshot storage
targets. It also validates the host-side session snapshot JSON envelope and
round-trip store, including unsupported format/version, session-id mismatch,
non-object metadata/payload rejection, custom snapshot filenames, and invalid
snapshot filename rejection, plus pure-text machine file and G-code stores,
including G-code program filename rejection for traversal or nested paths,
without defining CNC machine-state or file-format semantics. It now also validates the
OPFS-to-WASM parameter-file bridge with a mock interpreter SDK to ensure the
host boundary copies text into and out of the WASM filesystem without defining
parameter semantics, and that INI-derived machine file names are still
rejected by the OPFS path model when they contain traversal or nested path
segments. The same Node smoke also validates that explicit session file-name
options take precedence over INI-derived parameter and tool-table file names,
and that missing INI file-name values fall back to the host path model defaults,
keeping host override policy outside CNC semantics.
The browser INI/OPFS smoke script serves `wasm-port/` over localhost and runs
Chromium headless against a test page that imports the JS SDK, loads the INI
WASM module, queries vendored LinuxCNC INI parsing through the SDK, and
performs an OPFS text-file, generic session snapshot, custom snapshot filename,
invalid snapshot filename/envelope, machine file, G-code text round trip, and
G-code filename path-model rejection. It also verifies that the INI panel UI
exposes the default OPFS parameter-file and tool-table mappings used when a
machine session is copied into the interpreter WASM filesystem.
The browser interpreter smoke script serves `wasm-port/` over localhost and
runs Chromium headless against a test page that loads the interpreter-core
WASM module through `runtime/sdk/src/index.js`, writes no CNC
behavior in JavaScript, and verifies existing canonical fixtures through the
exported C ABI backed by vendored LinuxCNC `Interp::execute()` and
`Interp::open()`/`read()`/`execute()` paths, including the INI-aware
named-parameter file path and negative interpreter fixtures with expected
error text plus absent canonical motion output. It also uses real browser OPFS
storage plus the interpreter SDK to restore and save a LinuxCNC parameter file
through vendored `Interp::restore_parameters()` and `Interp::save_parameters()`,
to load/save LinuxCNC tool tables through vendored `tooldata_common.cc`, and
to reject invalid INI-derived parameter/tool-table file names through the OPFS
path model after the names are parsed by the LinuxCNC-backed INI WASM SDK. It
also verifies that explicit session parameter/tool-table file-name options
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.
The aggregate host smoke script builds the INI and interpreter-core WASM
artifacts once, then runs the Node WASM smokes, the Node OPFS mock smoke, and
the Chromium browser smokes.
## Source Coverage
Every `.c` and `.cc` entry in `tools/source-manifest.txt` must have a
corresponding `*_source_probe` entry in `build/native/source-probes.tsv`.
The validation fails if:
- a manifest source file lacks a source probe;
- a source probe references a file not listed in the manifest;
- a manifest file is duplicated;
- vendored files drift byte-for-byte from upstream LinuxCNC.
## Current Native Harnesses
| Harness | Purpose |
| --- | --- |
| `linuxcnc_ini_probe` | Validates vendored LinuxCNC INI parsing can be used standalone. |
| `linuxcnc_interp_state_probe` | Validates interpreter state constants and structs compile under the standalone boundary. |
| `linuxcnc_emc_status_probe` | Validates the standalone `emcStatus` machine-units status boundary used by vendored interpreter conversion and initialization code. |
| `linuxcnc_namedparam_harness` | Validates LinuxCNC named parameter behavior, `_ini[...]`, and `_hal[...]` adapter resolution. |
| `linuxcnc_interp_minimal_harness` | Runs G-code fixtures through vendored LinuxCNC parser/execution/conversion code, captures canonical events, and validates feed-rate state readback across length-unit changes. |
| `linuxcnc_parameter_file_harness` | Validates LinuxCNC parameter file restore/save behavior and required/read-only parameter handling. |
| `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_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. |
| `linuxcnc_xyzac_trt_kinematics_probe` | Validates vendored LinuxCNC XYZAC TRT kinematics through `switchkins.c`, including forward/inverse round-trip behavior and switching to identity kinematics. |
| `linuxcnc_xyzbc_trt_kinematics_probe` | Validates vendored LinuxCNC XYZBC TRT kinematics through `switchkins.c`, including forward/inverse round-trip behavior and switching to identity kinematics. |
| `linuxcnc_corexy_kinematics_probe` | Validates vendored LinuxCNC CoreXY forward/inverse behavior through the standalone HAL/RTAPI boundary. |
| `linuxcnc_rotate_kinematics_probe` | Validates vendored LinuxCNC rotated-axis forward/inverse behavior. |
| `linuxcnc_rose_kinematics_probe` | Validates vendored LinuxCNC rose kinematics forward/inverse behavior. |
| `linuxcnc_max_kinematics_probe` | Validates vendored LinuxCNC max kinematics forward/inverse behavior. |
| `linuxcnc_lineardelta_kinematics_probe` | Validates vendored LinuxCNC linear-delta inverse/forward pose round-trip behavior. |
| `linuxcnc_rotarydelta_kinematics_probe` | Validates vendored LinuxCNC rotary-delta inverse/forward pose round-trip behavior. |
| `linuxcnc_scorbot_kinematics_probe` | Validates vendored LinuxCNC Scorbot forward/inverse behavior and pose round-trip behavior. |
| `linuxcnc_tripod_kinematics_probe` | Validates vendored LinuxCNC tripod inverse/forward behavior, including below-platform flag behavior. |
| `linuxcnc_scara_kinematics_probe` | Validates vendored LinuxCNC SCARA forward/inverse behavior and switching to identity kinematics. |
| `linuxcnc_puma_kinematics_probe` | Validates vendored LinuxCNC PUMA forward/inverse behavior, pose round-trip behavior, and switching to identity kinematics. |
| `linuxcnc_genser_kinematics_probe` | Validates vendored LinuxCNC generic serial kinematics forward/inverse behavior and switching to identity kinematics. |
| `linuxcnc_genhex_kinematics_probe` | Validates vendored LinuxCNC generic hexapod inverse/forward behavior, including the switchkins iterative-forward warmup path. |
| `linuxcnc_pentakins_kinematics_probe` | Validates vendored LinuxCNC pentapod inverse/forward pose round-trip behavior. |
## Current WASM Harnesses
| 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 initial interpreter-core WASM module can be built from vendored LinuxCNC interpreter 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, and run parameter-file restore/save through vendored LinuxCNC `Interp::restore_parameters()` and `Interp::save_parameters()`. |
| `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, 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, and canonical-event display paths 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 OPFS-backed parameter-file restore/save and tool-table load/save through vendored LinuxCNC source. |
| `tests/host/verify_host_smokes.sh` | Runs the current host-side Node, WASM interpreter-core, OPFS, and browser smoke validation with shared WASM builds. |
## Fixture Coverage
Positive G-code fixtures currently cover:
- linear traverse/feed
- arc semantics
- modal absolute/incremental motion
- position parameters
- canned cycles
- coordinate offsets
- G53 machine-coordinate motion
- feed and motion control modes
- probing
- threading and rigid tap
- NURBS G5/G6
- spindle orient
- tool semantics
- tool table setup
- tool-data reload boundary
- interpreter state-tag boundary
- percent-delimited file `FINISH` boundary
- file-open `ON_RESET` boundary
- comment logging canonical calls
- named and numbered parameters
- O-word subroutines
- program-end modal reset
- canonical runtime edge calls
Negative fixtures currently cover:
- zero-feed `G1`
- arc radius mismatch
- zero-radius arc
- G53 incremental-mode rejection
- read-only named parameter writes
- read-only numbered parameter writes
- missing tool
- missing tool length offset
## Validation Boundaries
Current full-core validation is native-only. WASM/SDK validation covers the
INI parser smoke harness and an initial interpreter-core canonical event smoke
for `minimal_linear`, `arc_semantics`, `length_units`, `modal_incremental`,
`plane_selection`, `coordinate_offsets`, `g53_machine_coordinates`,
`feed_control_modes`, `position_params`, `probe_semantics`, `spindle_orient`,
`comment_logging`, `numbered_params`, `tool_semantics`, `tool_table_setup`,
`tool_reload`, `canned_cycles`, `cutter_comp_motion`, `threading_sync`,
`nurbs_g5_semantics`, `nurbs_g6_semantics`, `state_tag_motion`,
`canon_runtime_edges`, `program_end_modal_reset`, and `namedparam_semantics`
through both Node WASM and browser INI-aware program ABI smoke coverage,
plus the `g1_zero_feed`, `arc_radius_mismatch`, `arc_zero_radius`,
`cutter_comp_plane_change`, `g53_incremental`, `namedparam_readonly`,
`numbered_param_readonly`, `tool_not_found`, and
`tool_length_offset_not_found` negative fixtures. The WASM interpreter file
path additionally covers the same canonical-event fixture group, plus
`namedparam_semantics` through the INI-aware file execution ABI,
`file_open_reset`, `percent_file_finish`, and `oword_subroutine`.
`position_params` uses a dedicated file-path expectation under
`tests/fixtures/canon_file/` because LinuxCNC file execution advances the
post-execute position parameters differently than the line-by-line MDI smoke.
The Node WASM interpreter smoke also covers LinuxCNC parameter-file
restore/save behavior through the exported C ABI, including out-of-order file
rejection, missing-file success, required numeric parameter writeback, removal
of named-parameter-only lines from saved output, and the `.bak` backup produced
by vendored `save_parameters()`. It also covers LinuxCNC tool-table
load/save behavior through vendored `tooldata_common.cc`, including the
non-random and random-toolchanger `tooldata_init()` branches, with the SDK
only copying text into the Emscripten filesystem and calling the exported C
ABI.
OPFS validation covers the JavaScript host-boundary adapter, the INI browser
smoke harness, the INI panel UI's machine-session load and G-code run buttons,
the raw canonical-event display fed directly by LinuxCNC interpreter WASM
output, the Node parameter/tool-table bridges that copy OPFS text through the
SDK into vendored LinuxCNC file APIs, the Node machine-session bridge that
groups INI, parameter, and tool-table loading, the random-toolchanger flag
derived from vendored LinuxCNC INI boolean parsing, INI-derived
`[RS274NGC]PARAMETER_FILE` and `[EMCIO]TOOL_TABLE` file names mapped to OPFS
machine files, OPFS path-model rejection of invalid INI-derived file names,
explicit host session file-name overrides taking precedence over INI-derived
names, default host path fallback when INI file-name values are absent,
session snapshot custom filename handling plus envelope/path rejection
for unsupported format/version, wrong session id, and invalid snapshot
filenames, and a browser interpreter smoke that uses the same session bridge
with real LinuxCNC INI WASM parsing before saving OPFS-backed parameter and
tool-table text through vendored LinuxCNC file APIs, including default OPFS
path fallback when INI file-name values are absent.
Full browser coverage, full SDK coverage, and richer machine-state validation
remain future work.
## WASM/Browser Fixture Matrix
The executable fixture lists for Node WASM and browser interpreter smoke tests
are centralized in `tests/fixtures/interp-fixture-matrix.mjs`. Additions to the
matrix must continue to route execution through the SDK and exported C ABI
backed by vendored LinuxCNC interpreter code; the matrix is only a test
coverage list, not a CNC behavior implementation.
Node WASM `Interp::execute()` coverage currently includes:
- `minimal_linear`
- `arc_semantics`
- `length_units`
- `modal_incremental`
- `plane_selection`
- `coordinate_offsets`
- `g53_machine_coordinates`
- `feed_control_modes`
- `position_params`
- `probe_semantics`
- `spindle_orient`
- `comment_logging`
- `numbered_params`
- `tool_semantics`
- `tool_table_setup`
- `tool_reload`
- `canned_cycles`
- `cutter_comp_motion`
- `threading_sync`
- `nurbs_g5_semantics`
- `nurbs_g6_semantics`
- `state_tag_motion`
- `canon_runtime_edges`
- `program_end_modal_reset`
- `namedparam_semantics` through the INI-aware program ABI
Node WASM file-path coverage currently includes:
- `minimal_linear`
- `arc_semantics`
- `length_units`
- `modal_incremental`
- `plane_selection`
- `coordinate_offsets`
- `g53_machine_coordinates`
- `feed_control_modes`
- `probe_semantics`
- `spindle_orient`
- `comment_logging`
- `numbered_params`
- `tool_semantics`
- `tool_table_setup`
- `tool_reload`
- `canned_cycles`
- `cutter_comp_motion`
- `threading_sync`
- `nurbs_g5_semantics`
- `nurbs_g6_semantics`
- `state_tag_motion`
- `canon_runtime_edges`
- `program_end_modal_reset`
- `file_open_reset`
- `percent_file_finish`
- `oword_subroutine`
- `position_params` through the dedicated `canon_file/` expectation
- `namedparam_semantics` through the INI-aware file ABI
Browser interpreter `Interp::execute()` coverage currently includes:
- `minimal_linear`
- `arc_semantics`
- `length_units`
- `modal_incremental`
- `plane_selection`
- `coordinate_offsets`
- `g53_machine_coordinates`
- `feed_control_modes`
- `canned_cycles`
- `numbered_params`
- `comment_logging`
- `tool_semantics`
- `tool_table_setup`
- `probe_semantics`
- `spindle_orient`
- `cutter_comp_motion`
- `threading_sync`
- `nurbs_g5_semantics`
- `nurbs_g6_semantics`
- `state_tag_motion`
- `canon_runtime_edges`
- `tool_reload`
- `program_end_modal_reset`
- `namedparam_semantics` through the INI-aware program ABI
Browser interpreter negative coverage currently includes every fixture under
`tests/fixtures/gcode_errors/`:
- `g1_zero_feed`
- `arc_radius_mismatch`
- `arc_zero_radius`
- `g53_incremental`
- `cutter_comp_plane_change`
- `namedparam_readonly`
- `numbered_param_readonly`
- `tool_length_offset_not_found`
- `tool_not_found`
Browser interpreter file-path coverage currently includes the same
`INTERP_FILE_FIXTURES` list as the Node WASM smoke:
- `minimal_linear`
- `arc_semantics`
- `length_units`
- `modal_incremental`
- `plane_selection`
- `coordinate_offsets`
- `g53_machine_coordinates`
- `feed_control_modes`
- `probe_semantics`
- `spindle_orient`
- `comment_logging`
- `numbered_params`
- `tool_semantics`
- `tool_table_setup`
- `tool_reload`
- `canned_cycles`
- `cutter_comp_motion`
- `threading_sync`
- `nurbs_g5_semantics`
- `nurbs_g6_semantics`
- `state_tag_motion`
- `canon_runtime_edges`
- `program_end_modal_reset`
- `file_open_reset`
- `percent_file_finish`
- `oword_subroutine`
- `position_params` through the dedicated `canon_file/` expectation
- `namedparam_semantics` through the INI-aware file ABI
All current positive G-code fixtures have browser interpreter smoke coverage
through either `Interp::execute()`, the file-path ABI, or the INI-aware
file-path ABI.
The current fixture expectations validate standalone behavior against both the
vendored LinuxCNC source path and an upstream `rs274` side-by-side baseline for
parser/conversion, arc geometry, offsets, feed-control and feed-state
readback, comment/logging,
numbered-parameter, probing, spindle-orient, file-open reset, file-finish,
tool-reload, tool select/change/length-offset, canned-cycle, state-tag motion,
tool-table setup, and O-word subroutine fixtures, plus threading/rigid tap,
NURBS dispatch boundaries, and the comparable canonical runtime edge and
program-end cleanup calls. Fixtures that depend on standalone-only runtime
adapters, HAL/INI/tool-change state, upstream `rs274` output gaps such as
`WAIT` or hidden NURBS control-point detail, or richer machine session state
still need dedicated native LinuxCNC baselines.
Remaining positive fixtures that are not in the upstream `rs274` side-by-side
baseline are intentionally held out until they get a dedicated native LinuxCNC
baseline: `namedparam_semantics` depends on standalone INI/HAL adapter
resolution. `state_tag_motion` now compares its motion events with upstream
`rs274`, while `UPDATE_TAG` events remain a standalone state-tag capture
boundary. `tool_semantics` now compares T/M6/G43/G49 canonical events with
upstream `rs274`; M61 current-pocket host-state behavior remains covered by the
standalone fixture expectation, and `Interp::synch()` current/selected tool
slot reads are covered by the native init harness.
The kinematics probes currently cover LinuxCNC identity/trivial kinematics, the
switchable `5axiskins` XYZBCW bridge-mill model, TRT `xyzac`/`xyzbc`
table-rotary models, CoreXY, rotated-axis, rose, max, linear-delta,
rotary-delta, Scorbot, tripod, SCARA, PUMA, generic serial, generic hexapod,
and pentapod models.