Files
wasm-simulator/docs/linuxcnc-source-policy.md
2026-06-02 08:20:17 +08:00

19 KiB

LinuxCNC Source Policy

The simulator must not grow independently designed functional behavior. Functional behavior must come from LinuxCNC source code.

Hard rules:

  • Port-first: prefer direct LinuxCNC source porting, trimming, wrapping, or platform adaptation over project-authored replacements.
  • Do not write project-owned functional CNC behavior.
  • Functional CNC behavior must be ported, trimmed, wrapped, or routed from LinuxCNC source code.
  • Any G/M-code interpretation, motion behavior, kinematics, coordinate handling, cutter compensation, canned cycle, parameter expression, modal state, tool data, remap behavior, or RTCP behavior must first be traced to LinuxCNC source before implementation.
  • Browser-side wasm filesystem behavior must use OPFS-backed storage. Do not add browser filesystem paths that bypass OPFS.
  • Browser app and wasm bridge code must not persist CNC programs, LinuxCNC parameter files, or mirrored workspace files through non-OPFS browser storage APIs such as Local Storage, IndexedDB, File Picker writes, WebKit filesystem APIs, or FileReader-backed import paths.

Allowed project code:

  • LinuxCNC source porting, trimming, wrappers, and platform adaptation.
  • Thin adapters between LinuxCNC source code and the simulator C API.
  • Platform shims needed to compile LinuxCNC code for native tests or wasm.
  • Event serialization, test fixtures, build scripts, and documentation.
  • Temporary smoke scaffolding only when it is explicitly marked as temporary.

Not allowed as final behavior:

  • Hand-written G-code interpretation semantics.
  • Hand-derived kinematics, RTCP, coordinate transform, cutter compensation, canned cycle, modal, parameter, or expression behavior.
  • Behavior copied from documentation, controller intuition, or examples without checking the LinuxCNC implementation.

Required workflow for every functional change:

  1. Identify the LinuxCNC source file and function that defines the behavior.
  2. Add or update a test that demonstrates the LinuxCNC behavior.
  3. Port, wrap, or route to that LinuxCNC implementation.
  4. Record the source file/function in code comments or nearby documentation when the mapping is not obvious.
  5. Keep the change inside one active workstream context unless a dependency is unavoidable and explicitly named in the final report.
  6. Run ./test-native.sh and ./test-linuxcnc-source-link.sh.
  7. For source-manifest, build, or build-policy changes, also run the aggregate and guardrail checks: ./test-all-native.sh, ./test-linuxcnc-source-syntax.sh, and ./test-linuxcnc-wasm-cmake-safe-probe.sh. When ./test-native.sh and ./test-linuxcnc-source-link.sh have already been run in the same pass, use CNC_SIM_ALL_NATIVE_GUARDRAILS_ONLY=1 ./test-all-native.sh for the aggregate guardrail pass instead of recompiling the same native/source-link targets again.
  8. Keep ./test-linuxcnc-wasm-cmake-safe-probe.sh focused on the actual CMake probe by default. Run CNC_SIM_WASM_CMAKE_SAFE_PROBE_SELF_CHECKS=1 ./test-linuxcnc-wasm-cmake-safe-probe.sh only when changing its meta-guardrails or the surrounding build-wasm policy.

Efficiency rules:

  • Each pass should advance one reasonable, reviewable context. Do not use a nearby failing smoke assertion, broad fixture, or convenient touched file as permission to expand the pass into another workstream.
  • Do not add a smoke-only behavior path when the LinuxCNC-backed route already exists; add coverage to the source-backed route instead.
  • Keep browser filesystem guardrails negative as well as positive: require the OPFS bridge and reject browser app/wasm storage APIs that could bypass it.
  • Smoke tests are verification guardrails. They must not be expanded with new functional CNC behavior unless that behavior is directly routed to, copied from, or checked against the relevant LinuxCNC source in the same narrow context.
  • Do not mix generator/table work, manifests, OPFS/browser work, and build policy cleanup in the same pass unless the files directly depend on each other.
  • Prefer tightening an existing probe or manifest over adding another broad end-to-end smoke case.
  • Do not run the full native aggregate after already running its expensive native/source-link children in the same pass; use the explicit guardrails-only aggregate mode for build-policy cleanup.
  • Keep meta-guardrails out of hot build paths. The wasm-safe CMake probe may run extended self-checks with CNC_SIM_WASM_CMAKE_SAFE_PROBE_SELF_CHECKS=1, and the source syntax probe may run extended self-checks with CNC_SIM_SOURCE_SYNTAX_SELF_CHECKS=1. The wasm blocker probe may run analyzer failure-path self-checks with CNC_SIM_WASM_BLOCKERS_SELF_CHECKS=1. The default actual CMake, syntax, and blocker probe paths remain fast.
  • Keep test-linuxcnc-wasm-source-syntax.sh on the same persistent incremental build pattern as the native syntax probe. It must use build/wasm-source-syntax-test by default, dependency files, a signature, make --output-sync=target, and CNC_SIM_BUILD_JOBS:-8.
  • Reuse source preflight results in persistent build directories through check-linuxcnc-inputs-cached.sh; its signature must include the LinuxCNC root, manifest content, source file size and nanosecond mtime stats, the check mode, the cached wrapper script hash, and the checker script hash. Cache updates must be serialized with a lock inside the cache directory and must write next signatures through unique temporary files. Root-only source, flag, and link helper scripts must also use this cached preflight, defaulting to build/linuxcnc-helper-preflight-cache when a caller has not supplied CNC_SIM_PREFLIGHT_CACHE_DIR. build-wasm.sh must pass its preflight cache into nested build probes such as test-linuxcnc-wasm-blockers.sh and test-linuxcnc-wasm-cmake-safe-probe.sh instead of forcing a second cache walk in the same pass.
  • Cache wasm blocker analyzer output in test-linuxcnc-wasm-blockers.sh. Its signature must include the blocker wrapper script, analyzer script, manifest content, LinuxCNC source size and nanosecond mtime stats, shim lister script, and shim source hashes. The cache must be locked and may be overridden with CNC_SIM_WASM_BLOCKERS_CACHE_DIR.
  • Reuse switchkins/remap table check results in the same persistent cache with check-linuxcnc-switchkins-remap-table-cached.sh; its signature must include the cached wrapper script, checker script, generator script, the kinematics manifest, referenced LinuxCNC source size and nanosecond mtime stats, tracked generated table/case outputs, and the thin API/web bridge files that pass switchkins config aliases.
  • Reuse wasm probe objects across the wasm source object probe, rs274ngc_pre blocker/link probes, and the runtime link probe through build-linuxcnc-wasm-probe-objects.sh. Its mode-specific object caches must be keyed by compiler, LinuxCNC root, manifest, flags, and source list, and must include make dependency files so repeated build-wasm passes and the paired rs274ngc_pre probes do not recompile unchanged LinuxCNC core files, shims, or kinematics adapters.
  • Reuse standalone wasm probe objects and binaries for the tooldata link, tooldata_common link, interp_base link, python_plugin link, and rs274ngc_pre object probes through build-linuxcnc-wasm-standalone-probe.sh. Its mode-specific caches must keep compiler, LinuxCNC root, flags, source list, dependency files, and a lock so repeated build-wasm passes do not rebuild unchanged probe inputs.
  • Reuse wasm final link probes for rs274ngc_pre and runtime link checks through build-linuxcnc-wasm-link-probe.sh. It must consume build-linuxcnc-wasm-probe-objects.sh, cache probe main objects and linked executables with dependency files and a lock, and keep runtime symbol checks in test-linuxcnc-wasm-runtime-link.sh.
  • Cache the runtime link probe symbol table in test-linuxcnc-wasm-runtime-link.sh using the probe binary size and mtime plus an explicit SYMBOL_RULE_VERSION, so repeated build-wasm passes do not rerun nm -C on an unchanged probe.
  • Cache the rs274ngc_pre pre-link undefined-symbol scan in test-linuxcnc-wasm-rs274ngc-pre-link-blockers.sh. Its signature must include the LinuxCNC root, manifest, object list, object size and mtime stats, and an explicit FILTER_RULE_VERSION, with a lock and CNC_SIM_WASM_RS274NGC_PRE_LINK_BLOCKERS_CACHE_DIR override.
  • Keep test-linuxcnc-wasm-python-c-api-symbols.sh persistent for repeated build-wasm passes. It must use build/wasm-python-c-api-symbols, dependency files, a build signature, cached source token and object symbol signatures, make --output-sync=target, and CNC_SIM_BUILD_JOBS:-8 while still deriving required Python C API symbols from LinuxCNC RS274 Python/remap sources.
  • Keep test-linuxcnc-wasm-interp-find-link.sh persistent for repeated build-wasm passes. It must use build/wasm-interp-find-link, dependency files, a signature, make --output-sync=target, and CNC_SIM_BUILD_JOBS:-8 while still linking LinuxCNC interp_find.cc with the wasm-safe tooldata and RTAPI shims.
  • Keep tooldata symbol probes persistent for repeated build-wasm passes. test-linuxcnc-wasm-tooldata-mmap-symbols.sh must use build/wasm-tooldata-mmap-symbols, and test-linuxcnc-wasm-tooldata-runtime-symbols.sh must use build/wasm-tooldata-runtime-symbols; both must use dependency files, build signatures, cached nm --defined-only symbol export signatures, make --output-sync=target, and CNC_SIM_BUILD_JOBS:-8 while comparing wasm shim exports against LinuxCNC tooldata sources.
  • Default native, source-link, build-wasm, and wasm-safe CMake probe parallelism to CNC_SIM_BUILD_JOBS:-8; raise it only by explicit positive-integer environment override.
  • Persistent object/stamp signatures must not include CNC_SIM_BUILD_JOBS. Parallelism affects scheduling only; changing it must not invalidate otherwise unchanged LinuxCNC source, shim, syntax, or CMake probe build outputs.
  • Persistent native, source-object, source-link, source-syntax, RS274 native, bridge native, API native, shared bridge-object, wasm source-syntax, wasm probe-object, wasm link-probe, wasm standalone-probe, wasm Python C API, wasm interp_find, and wasm tooldata symbol signatures must include an explicit BUILD_RULE_VERSION instead of hashing the whole probe script. Bump that version when generated compile or link rule semantics change; ordinary guardrail and smoke assertion edits must not invalidate unchanged LinuxCNC source, shim, or project objects.
  • The LinuxCNC canon bridge native smoke probe must use persistent build/bridge-native-test objects, dependency files, a build-rule signature, make --output-sync=target, and CNC_SIM_BUILD_JOBS:-8; it must not compile all bridge sources in a throwaway temporary directory on every aggregate pass. Its 41 LinuxCNC bridge/project objects must be built through the shared build-linuxcnc-native-bridge-objects.sh cache so the RS274 API native smoke probe can link the same objects instead of recompiling them.
  • The LinuxCNC RS274 API native smoke probe must use persistent build/api-native-test objects, dependency files, a build-rule signature, make --output-sync=target, and CNC_SIM_BUILD_JOBS:-8; it must keep resetting its RS274 parameter file from LinuxCNC tests/halui/jogging/sim.var before running the smoke executable. It must reuse the shared bridge object cache and compile only its extra API/backend sources locally. Its LinuxCNC RS274 backend compile define must be applied only to source files that use that define, currently core/src/gcode_backend.cpp, so unrelated bridge and kinematics adapter objects are not rebuilt by backend-specific rule changes.
  • When ccache is available and CXX is unset, native, source-link, source-syntax, and wasm build paths should enable compiler caching automatically rather than requiring a manual wrapper, including the wasm-safe CMake probe.
  • Persistent native, source-link, source-syntax, and wasm-safe CMake probe build directories, plus the wasm source-syntax, Python C API, and interp_find probe build directories, tooldata symbol probe build directories, and wasm standalone/link probe cache directories may be overridden for local workflows, but must not point at the filesystem root.
  • Build policy knobs are intentionally narrow: CNC_SIM_BUILD_JOBS, CNC_SIM_NATIVE_BUILD_DIR, CNC_SIM_SOURCE_LINK_BUILD_DIR, CNC_SIM_SOURCE_SYNTAX_BUILD_DIR, CNC_SIM_SOURCE_OBJECTS_BUILD_DIR, CNC_SIM_BRIDGE_NATIVE_BUILD_DIR, CNC_SIM_API_NATIVE_BUILD_DIR, CNC_SIM_NATIVE_BRIDGE_OBJECT_CACHE_DIR, and CNC_SIM_RS274_NATIVE_BUILD_DIR, and CNC_SIM_WASM_CMAKE_SAFE_PROBE_BUILD_DIR. The wasm source-syntax probe also accepts CNC_SIM_WASM_SOURCE_SYNTAX_BUILD_DIR because it owns a persistent incremental cache. The wasm Python C API probe accepts CNC_SIM_WASM_PYTHON_C_API_BUILD_DIR for the same reason, and the wasm interp_find probe accepts CNC_SIM_WASM_INTERP_FIND_BUILD_DIR. Tooldata symbol probes accept CNC_SIM_WASM_TOOLDATA_MMAP_SYMBOLS_BUILD_DIR and CNC_SIM_WASM_TOOLDATA_RUNTIME_SYMBOLS_BUILD_DIR. Standalone wasm probes accept CNC_SIM_WASM_STANDALONE_PROBE_CACHE_DIR. Final wasm link probes accept CNC_SIM_WASM_LINK_PROBE_CACHE_DIR. Build directory overrides must stay non-empty, whitespace-free, and outside the filesystem root.
  • build-wasm.sh keeps fixed artifact paths: CMake writes build/wasm, then the script copies and byte-compares cnc_sim.js and cnc_sim.wasm under web/public before running Node and browser smoke checks.

Build and source-link guardrails:

  • CNC_SIM_BUILD_JOBS must be a positive integer and defaults to 8.
  • test-native.sh uses persistent build/native-test objects, dependency files, and native-build.signature.
  • test-linuxcnc-source-link.sh uses persistent build/source-link-test objects, dependency files, and source-link-build.signature.
  • test-linuxcnc-source-syntax.sh uses persistent build/source-syntax-test stamps, dependency files, and source-syntax.signature.
  • test-linuxcnc-source-objects.sh uses persistent build/source-objects-test objects, dependency files, and source-objects.signature.
  • test-linuxcnc-rs274-native.sh uses persistent build/rs274-native-test objects, dependency files, and rs274-native.signature.
  • test-linuxcnc-wasm-cmake-safe-probe.sh uses persistent build/wasm-cmake-safe-probe and wasm-cmake-safe-probe.signature; signature changes must reconfigure in place, its signature must include an explicit CONFIGURE_RULE_VERSION, and its two probe executables must be built with one combined cmake --build invocation.
  • test-linuxcnc-wasm-source-syntax.sh uses persistent build/wasm-source-syntax-test stamps, dependency files, and wasm-source-syntax.signature.
  • test-linuxcnc-wasm-python-c-api-symbols.sh uses persistent build/wasm-python-c-api-symbols objects, dependency files, and python-c-api.signature.
  • test-linuxcnc-wasm-interp-find-link.sh uses persistent build/wasm-interp-find-link objects, dependency files, and interp-find.signature.
  • test-linuxcnc-wasm-tooldata-mmap-symbols.sh uses persistent build/wasm-tooldata-mmap-symbols objects, dependency files, and tooldata-mmap-symbols.signature.
  • test-linuxcnc-wasm-tooldata-runtime-symbols.sh uses persistent build/wasm-tooldata-runtime-symbols objects, dependency files, and tooldata-runtime-symbols.signature.
  • Native, source-link, source-syntax, wasm-safe CMake probe, and build-wasm paths must reject empty, whitespace-containing, or filesystem-root build directory overrides before doing destructive cleanup.
  • Native, source-link, source-syntax, and build-wasm entry points must serialize shared non-concurrency-safe paths with lock files before writing fixed outputs.
  • CNC_SIM_ALL_NATIVE_GUARDRAILS_ONLY=1 ./test-all-native.sh must run the aggregate guardrail and failure-path assertions without invoking the expensive child native/source-link compile and smoke scripts.
  • Native, source-object, source-link, RS274 native, and syntax probes must build from generated makefiles with -MMD -MP dependency tracking and make --output-sync=target.
  • build-wasm.sh must run blocker, syntax, object, CMake, tooldata, interp_*, Python, rs274ngc_pre, and runtime link probes before copying browser artifacts.
  • Independent tooldata, interp_*, Python, and rs274ngc_pre object probes in build-wasm.sh may run in parallel, but their logs must be replayed in a deterministic order and the script must wait for all of them before rs274ngc_pre link checks.
  • build-wasm.sh must check cmake, emcmake, emcc, and node before the Emscripten configure step.
  • build-wasm.sh must reuse a persistent build/wasm configure signature keyed by manifest, core/CMakeLists.txt, an explicit CONFIGURE_RULE_VERSION, LinuxCNC root, and compiler launcher. The signature must not include CNC_SIM_BUILD_JOBS, and signature changes must reconfigure the existing build tree in place instead of deleting compiled objects.
  • build-wasm.sh must build cnc_sim_wasm_runtime_probe before cnc_sim_wasm, using one combined cmake --build invocation for both targets.
  • build-wasm.sh must copy build/wasm/cnc_sim.js and build/wasm/cnc_sim.wasm exactly once each.
  • build-wasm.sh must compare copied artifacts with cmp -s before running Node or browser smoke tests.
  • build-wasm.sh must run test-web-wasm-node-smoke.sh before the browser smoke so the Node prerequisite, syntax, and minimum-step checks are enforced.
  • The default wasm manifest partition must remain explicitly checked for 26 wasm-safe core sources and 9 blocked sources.
  • Manifest source listers must reject malformed lines, absolute source paths, unknown groups, unknown filters, and duplicate source entries.
  • Native link flags must include the built LinuxCNC lib path and rpath.
  • Common CXX flag helpers must surface helper failures instead of hiding them behind process substitution or read.
  • Temporary probe reports must be cleaned on failure and preserved only after a successful report path explicitly opts in.
  • Documentation-only build policy edits should still update the guardrail checks that enforce the relevant script and artifact ordering.

Current temporary exceptions:

  • The smoke parser exists only to exercise the public API and UI around remaining fallback paths; native, source-linked, and wasm smoke coverage now route LinuxCNC RS274 behavior through the LinuxCNC-backed interpreter.
  • RTCP pivot behavior is limited to LinuxCNC source-backed switchkins paths; unsupported switchkins types must not fall back to hand-derived geometry.

Both exceptions should shrink over time. New functional behavior should not be added to them unless it is directly copied from, or routed to, LinuxCNC source code.