Files
cnc_wams/wasm-port/docs/drift-report.md
2026-07-08 09:20:47 -04:00

19 KiB

Drift Report

Current Status

As of the current upstream baseline, no byte-level drift is allowed between files listed in tools/source-manifest.txt and the matching files under ../linuxcnc/.

The project-level release handoff in docs/project-release-handoff.md includes this drift report in the final acceptance path alongside source reuse, OPFS/session, sim-config coverage, host/runtime boundary, SDK, and UI docs.

The enforced upstream baseline is:

60597ee0718873d2449058c824262a275e5e4bad

tools/verify_vendor_sync.sh enforces this by comparing every manifest file against upstream during native validation.

Allowed Standalone Boundaries

The following differences are intentional runtime boundaries, not LinuxCNC semantic rewrites:

Boundary Standalone treatment
RTAPI Minimal compatibility shim in runtime/core/shims/rtapi.h.
HAL lookup Standalone HAL adapter for _hal[...] named parameter reads; native, Node WASM, and browser interpreter smokes validate lookup through vendored Interp::find_named_param().
INI lookup Standalone INI adapter around vendored LinuxCNC INI parser behavior, including boolean conversion through LinuxCNC iniFindBool() and string lookup for INI-declared [RS274NGC]PARAMETER_FILE and [EMCIO]TOOL_TABLE machine file names; native, Node WASM, and browser interpreter smokes validate _ini[...] lookup through vendored Interp::find_named_param().
Canonical output Canonical calls are captured as test events instead of driving hardware.
Feed-rate state SET_FEED_RATE updates standalone canonical runtime state so vendored convert_length_units() can read it back through GET_EXTERNAL_FEED_RATE() during G20/G21 changes.
Tool-data reload LinuxCNC RELOAD_TOOLDATA is captured as a canonical test event; browser/native tool-table reload plumbing remains a future host/runtime adapter.
Tool table storage Vendored LinuxCNC tooldata_common.cc owns tool-table parsing and formatting; the standalone boundary only supplies the in-memory tooldata_get()/tooldata_put() callbacks, exposes load/save through the WASM C ABI, and forwards the host random-toolchanger flag to LinuxCNC tooldata_init().
Tool slot status Standalone tool adapter state supplies GET_EXTERNAL_TOOL_SLOT() and GET_EXTERNAL_SELECTED_TOOL_SLOT() for vendored Interp::synch(); linuxcnc_interp_init_harness plus Node WASM and browser interpreter smokes guard current/selected slot synchronization.
Interpreter state tags LinuxCNC UPDATE_TAG callbacks are captured from the state tags packed by vendored interpreter code; standalone code does not derive modal state.
Rotary indexer lock state LinuxCNC UNLOCK_ROTARY and LOCK_ROTARY callbacks are captured from the vendored single-axis indexer path; standalone code does not implement rotary-indexing semantics, and native, Node WASM, and browser interpreter smokes validate the same boundary events.
File flush LinuxCNC FINISH is captured as a canonical test event on the vendored %-delimited file-reading path.
WASM parameter-file backup LinuxCNC save_parameters() calls link() to create the .bak parameter-file backup; runtime/core/linuxcnc_wrap/linuxcnc_wasm_posix_stubs.cpp maps that WASM/MEMFS edge to a file copy so the vendored save path can run unchanged, while restore_parameters() behavior such as missing required numeric parameter defaulting remains vendored LinuxCNC behavior validated through native, Node WASM, and browser interpreter smokes.
Interpreter reset LinuxCNC ON_RESET is captured as a canonical test event on the vendored interpreter reset/file-open path.
Interpreter init LinuxCNC INIT_CANON and the canonical initialization sequence from vendored Interp::init() are captured as test events in native, Node WASM, and browser interpreter validation.
Comment logging LinuxCNC LOGOPEN, LOG, LOGAPPEND, and LOGCLOSE callbacks are captured as canonical test events instead of writing host log files.
EMC status machine units A narrow standalone emcStatus shim exposes the machine-units field used by vendored interpreter conversion and initialization code; linuxcnc_emc_status_probe, linuxcnc_interp_init_harness, and the interpreter WASM/browser init probe guard the inch/mm boundary.
Python/remap Python/remap hooks are stubbed at the runtime edge.
Dynamic interpreter path interp_base.cc probe uses standalone EMC2_HOME compile-time path boundary.
Realtime scheduler TP probes seed deterministic status/config data instead of running LinuxCNC realtime process topology.
Kinematics component lifecycle Kinematics modules are initialized through LinuxCNC module entry points where native runtime probes exist, while HAL component init/ready/exit, HAL pin allocation, and RTAPI module metadata are handled by standalone shims.
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.
INI-context SDK staging runtime/sdk/src/sim-config-staging.js exposes planIniFileContextStaging() as a generic host-boundary file planner and planSimConfigStaging() as the representative vendored configs/sim wrapper. The planner reads INI text plus tools/source-manifest.txt to collect [DISPLAY]OPEN_FILE, [EMCIO]TOOL_TABLE, [RS274NGC]PARAMETER_FILE, one or more [RS274NGC]SUBROUTINE_PATH entries, one or more [RS274NGC]USER_M_PATH entries, and remap-NGC files for staging without relying on browser directory enumeration. runtime/sdk/src/linuxcnc-interp.js exposes runSimConfigProgram() as the execution convenience only: it writes planned 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(); neither helper implements interpreter, axis, remap, tool, parameter, or user M-code semantics.
Task/motion/HAL WASM runtime runtime/core/linuxcnc_wrap/linuxcnc_task_hal_wasm.cpp, linuxcnc_motion_runtime.c, and the phase 2 HAL runtime form a deterministic Web simulation adapter. The current boundary has task-cycle motion snapshots, command buffering, plan/execute/motion-update/subordinate-sync/status-write stages, source-anchored emctask.cc/taskintf.cc/emccanon.cc subsets, a T-033 taskintf.cc motion bridge for emcMotionInit()/emcMotionUpdate()/emcMotionAbort() over lcmot_*, T-034 traj control mapping for enable/disable/abort/pause/step/resume/set-motion-id, T-035 linear move mapping from emcTrajLinearMove() to structured lcmot_write_linear_move(), T-036 jog/home/switchkins mapping from emcJogIncr()emcJointHome/Unhome() and emcMotionSetAout() to structured lcmot_write_* calls, T-037 abort/state/mode mapping from emcTaskAbort()emcTaskSetMode() and emcTaskSetState() to a structured emctask.cc command result, T-038 determine/update snapshot mapping from LcmotStatusSnapshot and the IO estop/error latch into determineMode()determineState() and emcTaskUpdate(), T-039 plan wait/open/synch/reset mapping from emcTaskPlanSetWait/IsWait/ClearWait/Synch/Open/Close/Reset() into source-anchored plan results over staged FS, T-040 plan read/execute/line/level/command mapping from emcTaskPlanRead/Execute/Line/Level/Command() into source-anchored plan IO results that can append staged program work to the interp_list path without host JSON motion plans, config/error read snapshots, motion ERROR and soft-limit injection coverage, and top/task/motion/io DONE/EXEC/ERROR aggregation aligned with emctaskmain.cc. It is still not a full native task/HAL promotion: nativeTaskReady=false, nativeHalSyncReady=false, fullLinuxCncProgramExecutionReady=false, and task_hal_runtime_promoted=0 remain required.
Task/motion/HAL WASM runtime T-007 StandaloneEmcStatus T-007 centralizes the required top/task/motion/io status fields into StandaloneEmcStatus, a phased EMC_STAT equivalent. write_status_snapshot() synchronizes task state/mode/interp/exec, motion snapshot fields, IO error/estop state, and RCS aggregation before status JSON is written; compatibility JSON fields task, motionStatus, rcsStatus, and taskTopLevelStatus are exported from the same container through statusSource=StandaloneEmcStatus and emcStatus. Full upstream emc_nml.hh and NML transport remain intentionally unpromoted.
Task/motion/HAL WASM runtime T-051-T-055 status JSON contract T-051 through T-055 extend the same StandaloneEmcStatus boundary rather than adding a JSON-owned state machine. emcStatus.motion.traj maps LcmotStatusSnapshot queue/inpos/id/pause/velocity/pose fields to LinuxCNC EMC_TRAJ_STAT names; emcStatus.task.currentLine/readLine/motionLine/callLevel come from staged plan and motion snapshot evidence; emcStatus.motion.axis[] and joint[] expose structured axis/joint arrays while legacy motionStatus.axis and joint0 remain compatibility views; emcStatus.io.aux/tool/coolant exposes only shim/unsupported IO boundaries. tools/verify_task_status_json_contract.sh fixes this schema and confirms lctask_read_status_json() does not call motion JSON or advance motion state.
Task/motion/HAL WASM runtime T-041 canon state T-041 canon init/finish/unit/endpoint mapping brings INIT_CANON()ON_RESET()FINISH()USE_LENGTH_UNITS() and external unit/position getters into the source-anchored emccanon.cc subset. Drift remains bounded to deterministic status evidence: counters, length/angle units, and endpoint snapshots are surfaced through task status JSON, while full interpreter/canon process ownership is still unpromoted.
Task/motion/HAL WASM runtime T-042 canon straight motion T-042 straight traverse/feed mapping brings generate_fast_move()generate_move()STRAIGHT_TRAVERSE() and STRAIGHT_FEED() into the source-anchored emccanon.cc subset. Drift remains bounded to EMC_TRAJ_LINEAR_MOVE / interp_list evidence and the existing structured taskintf.cc motion command boundary; full native canon offsets, tags, feed modes, and NML queue ownership remain unpromoted.
Task/motion/HAL WASM runtime T-043 canon dwell/path-control T-043 dwell/path-control mapping brings DWELL() and SET_MOTION_CONTROL_MODE() into the source-anchored emccanon.cc subset. Drift remains bounded to EMC_TRAJ_DELAY / EMC_TRAJ_SET_TERM_COND / interp_list evidence and task status counters; full native blend planning, queue ownership, and NML transport remain unpromoted.
Task/motion/HAL WASM runtime T-044 canon spindle/tool T-044 spindle/tool command mapping brings SET_SPINDLE_SPEED()START_SPINDLE_CLOCKWISE()START_SPINDLE_COUNTERCLOCKWISE()STOP_SPINDLE_TURNING()SELECT_TOOL()CHANGE_TOOL()CHANGE_TOOL_NUMBER() and RELOAD_TOOLDATA() into the source-anchored emccanon.cc subset. Drift remains bounded to EMC_SPINDLE_* / EMC_TOOL_* / interp_list evidence and task status counters; full native spindle control, IO, tool DB ownership, and NML transport remain unpromoted.
Task/motion/HAL WASM runtime T-045 canon motion output/switchkins T-045 motion output/switchkins mapping brings SET_MOTION_OUTPUT_BIT()CLEAR_MOTION_OUTPUT_BIT()SET_AUX_OUTPUT_BIT()CLEAR_AUX_OUTPUT_BIT()SET_MOTION_OUTPUT_VALUE()SET_AUX_OUTPUT_VALUE() and WAIT() into the source-anchored emccanon.cc subset. Drift remains bounded to EMC_MOTION_SET_DOUT / EMC_MOTION_SET_AOUT / EMC_AUX_INPUT_WAIT / interp_list evidence, with M428-M430 routed through canon SET_AUX_OUTPUT_VALUE() before the existing taskintf.cc AOUT boundary; full native IO wait, queue ownership, and NML transport remain unpromoted.
Task/motion/HAL WASM runtime T-046 no-JSON main RUN path T-046 makes staged program RUN the default validation path through emctask.cc plan read/command/execute, emccanon.cc command envelopes, and taskintf.cc motion issue. Drift remains bounded by keeping loadProgramMotionPlan() as an explicit timed-plan compatibility/debug entry only; the primary WASM smoke no longer calls lctask_load_program_motion_plan_json() before RUN.
emc_nml.hh status container Full upstream src/emc/nml_intf/emc_nml.hh is evaluated but not vendored or directly included. T-029 records that direct include would pull NML/CMS, RS274, canon/tool-table, and message serialization dependencies before the broader NML transport boundary exists. Current status aggregation therefore remains a phased StandaloneEmcStatus/typedef boundary with LinuxCNC field names and validation gates, not byte-level drift from a vendored emc_nml.hh.

Enforced Non-Drift Rules

  • Do not edit ../linuxcnc/.
  • Do not patch vendored files without adding a patch under patches/ and documenting the reason.
  • Do not add standalone Interp::... member definitions outside the documented Python/remap runtime-edge stubs.
  • Do not add .c or .cc manifest files without a source compile probe.
  • Do not sync from a different upstream commit without updating tools/upstream-baseline.txt and docs/scope-and-baseline.md.

Known Gaps

  • No browser/full-core WASM parity tests yet. The INI parser now has Node and Chromium smoke harnesses against vendored LinuxCNC inifile.cc.
  • JS SDK validation now covers the INI WASM wrapper around vendored LinuxCNC inifile.cc, including LinuxCNC boolean conversion and INI-declared parameter/tool-table file-name lookup, and the interpreter-core SDK wrapper around the existing exported C ABI. The interpreter SDK only manages strings, Emscripten file writes, and calls into vendored LinuxCNC execution paths, including parameter-file restore/save and tool-table load/save.
  • OPFS validation covers a Node mock of the file-service adapter, the host-side path model, generic session snapshot storage, pure-text machine file and G-code storage, parameter/tool-table bridge copying into the interpreter SDK filesystem, grouped machine-session loading, explicit session file-name overrides, default host path fallback when INI file names are absent, invalid INI-derived machine file names, generic session snapshot custom filenames plus envelope/path rejection paths, G-code program filename rejection paths, and a Chromium localhost round trip for those persistence 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. 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.
  • Full machine baselines beyond the current identity/trivial, 5axiskins, TRT, delta, SCARA, PUMA, serial genserkins, hexapod genhexkins, pentapod pentakins, and other existing runtime probes are not established.
  • Positive cutter-compensated motion and cutter compensation rejection paths now have standalone interpreter fixture coverage through vendored LinuxCNC source.
  • Fixture expectations are checked against the standalone vendored source path. The upstream rs274 side-by-side baseline now covers simple motion, arc geometry, offsets, feed-control, comment/logging, numbered-parameter, local named-parameter plus _ini[...] lookup through rs274 -i, probing, spindle-orient, file-open reset, file-finish, tool-reload, and tool select/change/length-offset plus M61 current-tool-number update, canned-cycle, state-tag motion, tool-table setup, and O-word subroutine fixtures; it also covers threading/rigid tap, NURBS dispatch boundaries, and comparable canonical runtime edge and program-end cleanup calls. The vendored-source native harness plus Node WASM and browser smokes 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. It now also checks the negative fixture set against upstream rs274 -g for expected error text and absent canonical event constraints. HAL-backed adapter-heavy fixtures, standalone modal-state assertions, and upstream rs274 output gaps such as WAIT or hidden NURBS control-point detail still need dedicated native LinuxCNC baselines.
  • canned_cycles is now in the upstream rs274 side-by-side baseline after the minimal interpreter harness was aligned with LinuxCNC Interp::init() default G73/G83 peck-clearance values for millimeter units.
  • tool_table_setup is now in the upstream rs274 side-by-side baseline using a dedicated rs274 -t tool table and -i millimeter-unit INI boundary.
  • tool_semantics now compares T/M6/G43/G49 plus M61 CHANGE_TOOL_NUMBER and current-pocket readback with upstream rs274 -t -i.
  • namedparam_ini_semantics now compares local named-parameter behavior and _ini[...] lookup with upstream rs274 -i; the broader namedparam_semantics fixture still keeps _hal[...] lookup on the documented standalone HAL adapter boundary.
  • Task/motion/HAL runtime validation now covers task-cycle motion snapshots, wait-for-motion queue behavior, motion abort/error/soft-limit subordinate sync, top/task/motion/io RCS DONE/EXEC/ERROR aggregation, source-anchored emctask.cc/taskintf.cc/emccanon.cc subsets, and the T-029 emc_nml.hh reuse decision. These are runtime-edge validations only and do not promote native task/HAL readiness.

Current Drift Conclusion

Within the native extracted-core scope, the port currently has no permitted byte-level drift from vendored LinuxCNC source files. All current behavior coverage is guarded by upstream baseline validation, vendor sync validation, source compile probes, native harnesses, and fixture checks.