Lock AXIS panel contract to source behavior
This commit is contained in:
@@ -11,7 +11,7 @@ digraph LinuxCncAxisWebControlLogic {
|
||||
newrank=true,
|
||||
fontname="Noto Sans CJK SC",
|
||||
fontsize=22,
|
||||
label="LinuxCNC AXIS Web/WASM 控制面板完整逻辑关系图\n基线 239dcf4284762ad7e9c65d390bc5524d855c2f8e · 文档是 Web 面板唯一实现契约",
|
||||
label="LinuxCNC AXIS Web/WASM 控制面板源程序对标关系图\n源码锁 239dcf4284762ad7e9c65d390bc5524d855c2f8e · 源程序冲突时源程序优先",
|
||||
labelloc=t,
|
||||
labeljust=l
|
||||
];
|
||||
@@ -44,7 +44,7 @@ digraph LinuxCncAxisWebControlLogic {
|
||||
penwidth=1.5;
|
||||
|
||||
source [label="LinuxCNC 源程序\naxis.py · axis.tcl\nemctaskmain.cc · HAL/INI", fillcolor="#f7f1df", color="#b08a2e"];
|
||||
contract [label="源程序对标文档\nlinuxcnc-axis-web-control-panel-\nsource-logic.md", fillcolor="#fff5c9", color="#b08a2e", penwidth=2.2];
|
||||
contract [label="源程序锁定契约\nSOURCE_EXACT · SOURCE_ADAPTER\nSOURCE_BLOCKED · WEB_EXTENSION", fillcolor="#fff5c9", color="#b08a2e", penwidth=2.2];
|
||||
gesture [label="浏览器控件手势\ndata-axis-control\n82 个文档控制 ID", fillcolor="#edf6f8", color="#3c8091"];
|
||||
react [label="React handler\n只发意图,不是状态权威", fillcolor="#edf6f8", color="#3c8091"];
|
||||
operation [label="AxisOperationController\n串行操作 · operation_id · ledger", fillcolor="#eef2fb", color="#526da8"];
|
||||
@@ -94,12 +94,12 @@ digraph LinuxCncAxisWebControlLogic {
|
||||
fillcolor="#ffffff";
|
||||
|
||||
estop [label="ESTOP\n仅允许解除急停/安全诊断", fillcolor="#f8e7e5", color="#b94f45", penwidth=2.1];
|
||||
off [label="ESTOP_RESET / OFF\n急停已解除,机器未上电", fillcolor="#f7f1df", color="#b08a2e"];
|
||||
on_unhomed [label="ON · NOT HOMED\n可加载文件,可 HOME\n禁止 AUTO 运行", fillcolor="#fff5c9", color="#b08a2e"];
|
||||
off [label="ESTOP_RESET\n急停已解除,机器未上电\nSTATE_OFF 是命令值,不是稳定状态", fillcolor="#f7f1df", color="#b08a2e"];
|
||||
on_unhomed [label="ON · NOT HOMED\nOpen / Home / joint-mode manual\nAUTO/MDI 由 task homing 策略拒绝", fillcolor="#fff5c9", color="#b08a2e"];
|
||||
idle [label="ON · HOMED · IDLE\nRun / Step / Manual / MDI\n按各自源门控启用", fillcolor="#e9f5e8", color="#43844b", penwidth=2.1];
|
||||
running [label="AUTO · RUNNING\n解释器读取 + TP 执行\nPause / Stop / Power Off / ESTOP", fillcolor="#e5effa", color="#526da8", penwidth=2.1];
|
||||
paused [label="AUTO · PAUSED\n轨迹冻结但保留\nResume / Stop / Power Off / ESTOP", fillcolor="#fcebdc", color="#bd6a28", penwidth=2.1];
|
||||
ended [label="IDLE · completed / aborted\n保留当前 taskfile\n直接 Run 从第 0 行重新打开", fillcolor="#e9f5e8", color="#43844b"];
|
||||
ended [label="INTERP_IDLE · completed / aborted\nWeb 状态标签不是 LinuxCNC 枚举\n保留 taskfile;Run 重新打开第 0 行", fillcolor="#e9f5e8", color="#43844b"];
|
||||
|
||||
{ rank=same; estop; off; on_unhomed; idle; }
|
||||
{ rank=same; running; paused; ended; }
|
||||
@@ -149,7 +149,7 @@ digraph LinuxCncAxisWebControlLogic {
|
||||
];
|
||||
|
||||
secondary_controls [
|
||||
label="覆盖率 / 图层 / 菜单 / 边界\n\noverride-jog-speed (SET_JOG_SCALE)\noverride-feed (SET_OVERRIDE)\noverride-spindle (SET_SPINDLE_OVERRIDE)\noverride-max-velocity (SET_MAX_VELOCITY)\noverride-rapid (blocked_by_abi_rapidrate)\npreview-layer-path / live / limits / velocity / offsets / extents\nworkspace-case-select (本地配置选择)\nworkspace-load-3d-chips (PROGRAM_LOAD)\nmenu-file / menu-help (本地菜单)\nmenu-help-about / about-close (本地对话框)\nmenu-file-edit-tool-data (host_boundary disabled)\nmenu-file-quit (host_boundary disabled)\nTool / Probe:只读;无额外主面板命令按钮",
|
||||
label="覆盖率 / 图层 / 菜单 / 边界\n\noverride-jog-speed (SOURCE_ADAPTER)\noverride-feed / spindle / max-velocity\n (SOURCE_ADAPTER;原生无上电 UI gate)\noverride-rapid (SOURCE_BLOCKED)\npreview-layer-path / live / limits / velocity / offsets / extents\nworkspace-case-select / load-3d-chips (WEB_EXTENSION)\nmenu-file / menu-help (本地菜单)\nmenu-help-about / about-close (SOURCE_ADAPTER)\nmenu-file-edit-tool-data / quit (SOURCE_BLOCKED)\nTool / Probe:只读;无额外主面板命令按钮",
|
||||
fontname="Noto Sans Mono CJK SC",
|
||||
fillcolor="#f7f1df",
|
||||
color="#b08a2e"
|
||||
@@ -177,7 +177,7 @@ digraph LinuxCncAxisWebControlLogic {
|
||||
color="#b08a2e"
|
||||
];
|
||||
load_tx [
|
||||
label="文件替换事务\n1 仅 IDLE 且 TP/MDI queue=0\n2 save mode -> ensure MANUAL\n3 清旧 preview 与待处理边\n4 恢复 saved mode\n5 捕获当前 canonical TP pose\n6 PROGRAM_LOAD + task_plan_synch\n7 subroutine + preview\n8 重算 gates 并发布单一快照",
|
||||
label="文件替换事务\n1 原生 UI gate:INTERP_IDLE\n2 Web 安全适配:TP/MDI queue=0\n3 save mode -> ensure MANUAL\n4 可选 FILTER -> restore saved mode\n5 first line 0 -> task_plan_synch\n6 program_open / PROGRAM_LOAD\n7 新 AxisCanon + 状态派生 preview init\n8 set_mode_from_tab;Live Plot 不清除",
|
||||
fillcolor="#eef2fb",
|
||||
color="#526da8"
|
||||
];
|
||||
@@ -187,7 +187,7 @@ digraph LinuxCncAxisWebControlLogic {
|
||||
color="#43844b"
|
||||
];
|
||||
run_tx [
|
||||
label="程序执行事务\nRun: run_warn -> ensure AUTO -> AUTO_RUN line 0\nPause: 仅 READING/WAITING\nResume: 仅 PAUSED\nStop: abort -> wait -> TP queue clear\nCompleted/Aborted: taskfile 保留\n再次 Run: reopen 当前文件 line 0",
|
||||
label="程序执行事务\nRun UI gate:ON + INTERP_IDLE\nrun_warn -> ensure AUTO -> AUTO_RUN line 0\nStep UI gate:ON + taskfile\nPause:READING/WAITING;Resume:PAUSED\nStop:ON + 非 IDLE -> abort/wait/plan close\nCompleted/Aborted:taskfile 保留;Run reopen line 0",
|
||||
fillcolor="#fcebdc",
|
||||
color="#bd6a28"
|
||||
];
|
||||
@@ -206,12 +206,12 @@ digraph LinuxCncAxisWebControlLogic {
|
||||
style="rounded,filled";
|
||||
fillcolor="#ffffff";
|
||||
|
||||
static_preview [label="静态程序 Preview\n来源:open_file_guts / AxisCanon / WASM preview\nRun · Pause · Resume · Stop · Completed · Clear Plot 均保留\n仅新 PROGRAM_LOAD 隐藏旧图并原子替换", fillcolor="#eef2fb", color="#526da8"];
|
||||
live_empty [label="Live Plot 新 epoch\n轨迹点 = 0", fillcolor="#edf6f8", color="#3c8091"];
|
||||
static_preview [label="静态程序 Preview\n来源:open_file_guts / AxisCanon / WASM preview\nRun · Pause · Resume · Stop · Completed · Clear Plot 均保留\nOpen/Reload 分配新 canon;解析错误不回滚旧 canon", fillcolor="#eef2fb", color="#526da8"];
|
||||
live_empty [label="显式清除后的 Live Plot\n轨迹点 = 0", fillcolor="#edf6f8", color="#3c8091"];
|
||||
live_running [label="RUNNING\npositionlogger / motion_trace 累积", fillcolor="#e9f5e8", color="#43844b"];
|
||||
live_paused [label="PAUSED\n冻结且保留同一轨迹", fillcolor="#fcebdc", color="#bd6a28"];
|
||||
live_retained [label="STOPPED / COMPLETED\n保留完整加工轨迹", fillcolor="#e9f5e8", color="#43844b"];
|
||||
live_clear [label="清除边界\nPROGRAM_LOAD · 新 PROGRAM_RUN\nPROGRAM_RESTART · VISUAL_CLEAR\nWorker: live_path_epoch + 1", fillcolor="#f8e7e5", color="#b94f45", penwidth=2.1];
|
||||
live_clear [label="唯一源程序清除边界\nCtrl-K / Clear Live Plot\nVISUAL_CLEAR -> live_path_epoch + 1\nRun · Reload · Open 均不得清除", fillcolor="#f8e7e5", color="#b94f45", penwidth=2.1];
|
||||
|
||||
f_anchor [shape=point, width=0, height=0, label="", style=invis];
|
||||
{ rank=same; static_preview; f_anchor; live_clear; }
|
||||
@@ -222,7 +222,8 @@ digraph LinuxCncAxisWebControlLogic {
|
||||
live_paused -> live_running [label="Resume"];
|
||||
live_running -> live_retained [label="Stop / Complete"];
|
||||
live_clear -> live_empty [label="epoch change"];
|
||||
live_retained -> live_clear [label="重新加工 / 换程序 / Clear", color="#b94f45"];
|
||||
live_retained -> live_running [label="Run / 重跑 / 换程序后继续累积", color="#43844b"];
|
||||
live_retained -> live_clear [label="仅 Clear Live Plot", color="#b94f45"];
|
||||
static_preview -> live_running [label="相互独立", style=dashed, dir=both, arrowtail=none, color="#526da8"];
|
||||
}
|
||||
|
||||
@@ -233,17 +234,17 @@ digraph LinuxCncAxisWebControlLogic {
|
||||
fillcolor="#e9ecea";
|
||||
|
||||
invariants [
|
||||
label="实现不变量\n• React 不是状态权威\n• 每条命令必须经过 Worker gate\n• 每个控件必须有文档 ID\n• 拒绝必须返回稳定 reason\n• 不可用 ABI 不得用本地布尔/G92/固定 G43 模拟\n• 重复入口删除,不改变保留命令语义\n• 新控件必须先更新本文档与测试",
|
||||
label="实现不变量\n• 源程序冲突时源程序优先\n• React 不是状态权威\n• exact update_state 公式是 UI gate 基线\n• 每条命令必须经过 Worker gate\n• 不可用 ABI 不得用本地布尔/G92/固定 G43 模拟\n• WEB_EXTENSION 不计入 AXIS 对标\n• 新控件必须先更新本文档、图和测试",
|
||||
fillcolor="#ffffff",
|
||||
color="#667078"
|
||||
];
|
||||
verification [
|
||||
label="自动验收\n82 个文档控制 ID\n80 个静态 DOM 控件 + 2 个动态控制族\n51 个实际按钮 / 18 组浏览器流程\nWorker: 98 verified / 8 rejected / 6 ABI boundaries\nNative: 22 / 22\n多程序 A -> B -> C -> A\n桌面/移动 WebGL 像素检查",
|
||||
label="自动验收\n源码锁:axis.py + axis.tcl SHA-256\n7 条 exact update_state 公式\n5 条 handler 流程\n7 个非清除 Live Plot 生命周期函数\n82 个文档控制 ID\nSOURCE_EXACT / ADAPTER / BLOCKED / EXTENSION 分层\nWorker 与浏览器回归另行验证",
|
||||
fillcolor="#e9f5e8",
|
||||
color="#43844b"
|
||||
];
|
||||
legend [
|
||||
label="颜色图例\n绿色:WASM 规范状态/已验证操作\n蓝色:Task/程序控制\n青色:本地视图投影\n黄色:INI/文件/启动事务\n橙色:模式转换/暂停\n红色:急停/清除边界/明确禁用",
|
||||
label="对标图例\nSOURCE_EXACT:源代码公式/顺序原样\nSOURCE_ADAPTER:传输不同,语义相同\nSOURCE_BLOCKED:能力不足,禁用/缺席\nWEB_EXTENSION:非 AXIS 功能,不计入对标\n红色:急停/唯一清除边界/明确禁用",
|
||||
fillcolor="#ffffff",
|
||||
color="#667078"
|
||||
];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# LinuxCNC AXIS Web Control Panel Source Logic
|
||||
|
||||
Status: active implementation contract
|
||||
Status: source-locked implementation contract
|
||||
Scope: the selected `XYZAC TRT` Web/WASM panel and its LinuxCNC-compatible
|
||||
Worker command path
|
||||
Source baseline: LinuxCNC submodule `239dcf4284762ad7e9c65d390bc5524d855c2f8e`
|
||||
@@ -26,15 +26,32 @@ The React state is never an authority. A rejected Worker command must remain
|
||||
rejected in the UI, with the source gate reason visible as the disabled-button
|
||||
title and in Diagnostics.
|
||||
|
||||
"Source parity" has a strict meaning in this document:
|
||||
|
||||
| Mark | Meaning |
|
||||
| --- | --- |
|
||||
| `SOURCE_EXACT` | Same user action, source handler, UI enable formula, command ordering and observable result as AXIS. |
|
||||
| `SOURCE_ADAPTER` | Browser/WASM transport differs, but the accepted action and observable machine semantics are the same. Any stronger Web safety gate is stated explicitly. |
|
||||
| `SOURCE_BLOCKED` | AXIS has the action, but the selected WASM or browser boundary cannot represent its canonical state. It stays disabled or absent and is never emulated with local state. |
|
||||
| `WEB_EXTENSION` | No AXIS control exists. The control must be visibly and textually separated from source parity and must not alter the meaning or gate of an AXIS action. |
|
||||
|
||||
Only `SOURCE_EXACT` and `SOURCE_ADAPTER` count as implemented AXIS parity.
|
||||
`SOURCE_BLOCKED` is an honest capability boundary. `WEB_EXTENSION` is never
|
||||
evidence of parity. If this document and the pinned source disagree, the pinned
|
||||
source wins and this document, its graph and the Web implementation must be
|
||||
updated together.
|
||||
|
||||
The panel does not add a startup/run alias. The source-defined machine sequence
|
||||
is explicit: release E-stop when needed, power on, home, then press the single
|
||||
toolbar Run control (or the source `R` shortcut).
|
||||
|
||||
On browser startup, the selected INI is the only program-selection authority.
|
||||
For `xyzac-trt.ini`, `[DISPLAY] OPEN_FILE` selects
|
||||
`./demos/xyzac_switchkins.ngc`, matching `axis.py` startup around
|
||||
`initialfile`/`open_file_guts`. Browser UI persistence must not restore a
|
||||
different G-code source or path and must never schedule a hidden second
|
||||
Native AXIS selects its startup program in this exact priority order:
|
||||
positional command-line argument, `AXIS_OPEN_FILE`, `[DISPLAY] OPEN_FILE`, then
|
||||
the built-in lathe/mill sample. The browser has no AXIS process argument or
|
||||
process environment override, so the selected INI's `[DISPLAY] OPEN_FILE` is
|
||||
the first applicable source authority. For `xyzac-trt.ini` it selects
|
||||
`./demos/xyzac_switchkins.ngc`. Browser UI persistence must not insert a new
|
||||
higher-priority executable source and must never schedule a hidden second
|
||||
`PROGRAM_LOAD` after the configured file appears.
|
||||
|
||||
AXIS has both Machine/View menu bindings and toolbar/notebook bindings. The Web
|
||||
@@ -51,6 +68,24 @@ post-completion/abort behavior are also checked against
|
||||
Python button handler when the LinuxCNC task layer defines an additional
|
||||
transition.
|
||||
|
||||
### Source-lock manifest
|
||||
|
||||
The source baseline is the submodule commit above, not a LinuxCNC version name
|
||||
or an approximate UI description. The two primary GUI files are additionally
|
||||
fingerprinted so the audit fails on an unreviewed source drift:
|
||||
|
||||
| Source | Baseline SHA-256 | Normative responsibility |
|
||||
| --- | --- | --- |
|
||||
| `src/emc/usr_intf/axis/scripts/axis.py` | `328c038a1e8fefd952e53c8e398e3fa98b04602351c44318edd1b044e8f63ffa` | Handlers, mode transitions, keyboard bindings, preview and live-plot ownership |
|
||||
| `share/axis/tcl/axis.tcl` | `c9f0b4dc686717b37565f85fb0ab8cc8ded9cfa0028cc0aaaccdbcf808c4c524` | Widgets, menu/toolbar wiring and exact dynamic enable formulas |
|
||||
| `src/emc/task/emctask.cc` | pinned by submodule commit | Machine state edges and observed `ESTOP`/`ESTOP_RESET`/`ON` state |
|
||||
| `src/emc/task/emctaskmain.cc` | pinned by submodule commit | Task command acceptance, homing enforcement, run/pause/resume/abort and task-plan reopen/close |
|
||||
| `configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini` plus `remap_subs/{428,429,430}remap.ngc` | pinned by submodule commit | Selected axes, limits, speeds, startup file and switchkins remaps |
|
||||
|
||||
The current local LinuxCNC tree contains unrelated heartbeat instrumentation
|
||||
and an `INTRO_GRAPHIC` substitution. Neither changes the AXIS control flow
|
||||
specified here; they are not used to redefine parity.
|
||||
|
||||
| AXIS source symbol | Role |
|
||||
| --- | --- |
|
||||
| `manual_ok`, `ensure_mode` | Polling, task-state and mode preconditions |
|
||||
@@ -63,10 +98,12 @@ transition.
|
||||
| `spindle`, `spindle_forward_toggle`, `spindle_backward_toggle`, `spindle_increase`, `spindle_decrease`, `spindle_constant` | Spindle direction, speed and brake controls |
|
||||
| `mist_toggle`, `flood_toggle`, `brake_on`, `brake_off` | Auxiliary IO controls |
|
||||
| `toggle_override_limits`, `cycle_view` | Limit override and preview view selection |
|
||||
| `update_state`, `set_mode_from_tab` in `axis.tcl` | Exact widget enable/disable rules and idle mode restoration |
|
||||
|
||||
The widget wiring is in `linuxcnc/share/axis/tcl/axis.tcl`: machine menu and
|
||||
toolbar bindings are around lines 105-170 and 490-669; manual jog, home,
|
||||
touch-off, spindle and coolant bindings are around lines 893-1087.
|
||||
The widget wiring is in `linuxcnc/share/axis/tcl/axis.tcl`: File/Machine/View/
|
||||
Help menus are at lines 55-464, toolbar bindings at 490-669, manual and MDI
|
||||
controls at 839-1288, sliders at 1396-1538, control groups at 1715-1726 and the
|
||||
normative `update_state` formulas at 1767-1888.
|
||||
|
||||
## Source Surface Inventory
|
||||
|
||||
@@ -76,95 +113,183 @@ replaced by a different action.
|
||||
|
||||
| Source surface | Source entries | Web treatment |
|
||||
| --- | --- | --- |
|
||||
| File menu | Open, Recent Files, Edit, Reload, Save As, Properties, Edit Tool Data, Reload Tool Data, Ladder Editor, Quit | Open and Reload have one visible toolbar entry each. Edit Tool Data and Quit remain visible but disabled with a host-boundary reason. Other desktop-only entries are not rendered. |
|
||||
| Machine menu | E-stop, Power, Run, Run from selected line, Step, Pause, Resume, Stop, Optional Stop, Block Delete, MDI history, Calibration/HAL tools, Homing, Unhoming, Zero coordinate system, Tool touch-off target | E-stop/Power/Run/Step/Pause/Resume/Stop/Home/Touch Off are represented by documented commands; Run-from-line, MDI clipboard/file actions, calibration/HAL desktop tools and Unhoming are not exposed; Optional Stop, Block Delete, Override Limits and Tool Touch Off remain ABI-blocked. |
|
||||
| View menu | Six preset views, inches/mm, show program/rapids/live plot/tool/extents/offsets/limits/velocity/DTG, grid, DRO font, PyVCP, commanded/actual, machine/relative, joint/world, clear plot | Preset view/zoom/rotate, units, commanded/actual, machine/relative and supported visual layers are Web projections; unsupported teleop, grid/DTG/font/PyVCP settings are not aliased to motion state. |
|
||||
| File menu | Open, Recent Files, Edit, Reload, Save As, Properties, Edit Tool Data, Reload Tool Data, Ladder Editor, Quit | Open and Reload are `SOURCE_ADAPTER` toolbar entries. Edit Tool Data and Quit are visible `SOURCE_BLOCKED` entries. The remaining host/file actions are recorded below and are not silently aliased. |
|
||||
| Machine menu | E-stop, Power, Run, Run from selected line, Step, Pause, Resume, Stop, Optional Stop, Block Delete, MDI history actions, six desktop tools, Homing, Unhoming, ten zero-coordinate actions and two tool-touch modes | E-stop/Power/Run/Step/Pause/Resume/Stop/Home/Touch Off are represented; every omitted or ABI-blocked source action is recorded below. |
|
||||
| View menu | Five preset views, inches/mm, program/rapid/alpha/live/tool/extents/offset/limit/velocity/DTG layers, grid, large DRO font, PyVCP, commanded/actual, machine/relative, joint/world and Clear Live Plot | The menu has five views; the toolbar additionally has inverted-front `Y2`, for six toolbar presets. Supported projections are `SOURCE_ADAPTER`; every omitted view action is recorded below. |
|
||||
| Toolbar | E-stop, Power, Open, Reload, Run, Step, Pause/Resume, Stop, Block Delete, Optional Stop, zoom, six views, rotate, Clear Plot | Same source order and icon assets are retained for supported controls; unsupported controls are disabled with a source/ABI reason. |
|
||||
| Manual notebook | Axis/joint selector, continuous/increment jog, Home Axis, Touch Off, Tool Touch Off, Override Limits, spindle direction/stop/speed/brake and coolant | XYZAC axis selector, jog, Home Axis, Touch Off, spindle and coolant are represented. Joint selection, Tool Touch Off and Override Limits are explicitly bounded by the selected configuration/ABI. Tool and probe state is read-only; Prepare/Change/Arm/Disarm are IO/HAL operations, not AXIS main-panel controls. |
|
||||
| Web case strip | no AXIS equivalent | `Load exact XYZAC TRT case` is a Web workspace/bootstrap control, not an AXIS source button. It may only call the same documented `LOAD_WORKSPACE` + `PROGRAM_LOAD` transaction and must not introduce a second Run/Power/Home flow. |
|
||||
| MDI notebook | MDI entry, Go, history selection/double-click, Up/Down history, Ctrl-M/H/Shift-H clipboard operations | Entry, Go and local history are represented; clipboard/file history operations are host/UI-only and are not sent as machine commands. |
|
||||
| Help menu/dialogs | About AXIS, Quick Reference, dialog close buttons and website link | About is `SOURCE_ADAPTER`. Quick Reference and the external website link are not rendered; neither is mapped to a machine action. |
|
||||
| Bottom controls | Linear jog speed, angular jog speed, max velocity, spindle override, feed override and rapid override | Linear jog, max velocity, spindle and feed are adapters. Angular jog and rapid override are `SOURCE_BLOCKED`; one must never stand in for the other. |
|
||||
| Browser UI persistence | AXIS preferences do not override `[DISPLAY] OPEN_FILE` with executable source text | OPFS may persist presentation preferences such as view, zoom, tabs, units and selected axis. It must not persist or automatically load G-code source/path. |
|
||||
|
||||
The Web surface may remove duplicate menu entries, but it may not change the
|
||||
meaning of a retained command. This is why Machine/View menus are not rendered
|
||||
when the same source action already has a toolbar or notebook entry.
|
||||
|
||||
### Exhaustive native-action ledger
|
||||
|
||||
This ledger accounts for every interactive family constructed by `axis.tcl` or
|
||||
bound by `axis.py`. Separators, labels, scrollbars and read-only status text are
|
||||
not actions. Dynamically generated joint and grid entries are counted as
|
||||
families because their cardinality comes from the selected INI.
|
||||
|
||||
| Native action family | Source symbols | Parity disposition |
|
||||
| --- | --- | --- |
|
||||
| File Open/Recent/Edit/Reload/Save/Properties | `open_file`, `open_file_name`, `edit_program`, `reload_file`, `save_gcode`, `gcode_properties` | Open/Reload: `SOURCE_ADAPTER`; Recent/Edit/Save/Properties: browser file/host boundary, not rendered |
|
||||
| Tool table edit/reload, Ladder Editor, Quit | `edit_tooltable`, `reload_tool_table`, `classicladder`, `destroy` | Tool editor/Quit: visible `SOURCE_BLOCKED`; reload/Ladder: host boundary, not rendered |
|
||||
| E-stop and Power | `estop_clicked`, `onoff_clicked` | `SOURCE_ADAPTER`; exact edge selection and source widget gates apply |
|
||||
| Run, Run from line, Step, Pause, Resume, Stop | `task_run`, `task_run_line`, `task_step`, `task_pause`, `task_resume`, `task_pauseresume`, `task_stop` | Run/Step/toggle Pause-Resume/Stop: `SOURCE_ADAPTER`; Run from line is `SOURCE_BLOCKED` until source-line selection is canonical |
|
||||
| Optional Stop and Block Delete | `toggle_optional_stop`, `toggle_block_delete` | Visible `SOURCE_BLOCKED`; block delete's source wait, MANUAL switch and preview reload must not be approximated by a local checkbox |
|
||||
| MDI history clear/copy/paste/select/double-click/Up/Down | `clear_mdi_history`, `mdi_history_hist2clip`, `mdi_history_clip2hist`, `mdi_history_butt_1`, `mdi_history_double_butt_1`, `mdi_up_cmd`, `mdi_down_cmd` | Select/Up/Down/local history: `SOURCE_ADAPTER`; clipboard/file persistence variants are browser/host boundaries |
|
||||
| Calibration, HAL Configuration, HAL Meter, HAL Scope, LinuxCNC Status, Debug Level | external `exec` commands in Machine menu | Desktop-process boundary; not rendered and never mapped to Diagnostics as though it were the same action |
|
||||
| Home all/joint and Unhome all/joint | `home_all_joints`, `home_joint_number`, `unhome_all_joints`, `unhome_joint_number` | Home all/selected axis: `SOURCE_ADAPTER`; Unhome and joint-mode selector: `SOURCE_BLOCKED` |
|
||||
| Zero P1..P9 and G92 coordinate systems | `clear_offset` | `SOURCE_BLOCKED`; Touch Off is not an alias for clearing a coordinate system |
|
||||
| Tool touch-off target workpiece/fixture | `toggle_tto_g11` selecting `G10 L10`/`G10 L11` | `SOURCE_BLOCKED` with Tool Touch Off; no local target state is exposed |
|
||||
| Top/Z2/Side/Front/Y2/Perspective, zoom and rotate | `set_view_*`, `zoomin`, `zoomout`, rotate Tcl command | `SOURCE_ADAPTER`; Y2 is toolbar-only in the native layout |
|
||||
| Inches/MM, commanded/actual, machine/relative | `metric`, `display_type`, `coord_type` | `SOURCE_ADAPTER`; display projection only |
|
||||
| Show program, rapids, alpha, live plot, tool, extents, offsets, limits, velocity, DTG | `toggle_show_*`, `toggle_program_alpha` | Program/live/extents/offsets/limits/velocity have adapters; rapids, alpha, tool toggle and DTG are not rendered |
|
||||
| Grid Off/custom/INI increments, large DRO font, PyVCP, Joint/World | `set_grid_size`, `set_grid_size_custom`, `toggle_dro_large_font`, `toggle_show_pyvcppanel`, `set_teleop_mode` | Not rendered; Joint/World is `SOURCE_BLOCKED`, presentation-only settings are not aliased |
|
||||
| Clear Live Plot | `clear_live_plot` -> `LivePlotter.clear` -> `positionlogger.clear` | `SOURCE_ADAPTER`; this is the only native live-trace deletion action |
|
||||
| Axis/joint selection and jog increment | `ja_rbutton`, `jogincrement`, `activate_ja_widget` | XYZAC axis and increment selection: `SOURCE_ADAPTER`; native joint selection is `SOURCE_BLOCKED` |
|
||||
| Jog negative/positive and key jog | `jog_minus`, `jog_plus`, `jog_on`, `jog_off` | `SOURCE_ADAPTER`; press/release semantics and Manual-tab guard apply |
|
||||
| Home Axis, Touch Off, Tool Touch Off, Override Limits | corresponding `zerohome`/`override` widgets | Home/Touch Off: `SOURCE_ADAPTER`; Tool Touch Off/Override Limits: visible `SOURCE_BLOCKED` |
|
||||
| Spindle CCW/Stop/CW, slower/faster, brake | `spindle`, `spindle_decrease`, `spindle_increase`, `spindle_constant`, `brake` | `SOURCE_ADAPTER`; button-state formulas and press/release ordering apply |
|
||||
| Mist and Flood | `mist`, `flood`, `mist_toggle`, `flood_toggle` | `SOURCE_ADAPTER`; independent canonical IO bits |
|
||||
| MDI entry, Go, Enter, history activation | `send_mdi`, `send_mdi_command` | `SOURCE_ADAPTER`; source trim, mode and adjacent-history de-duplication apply |
|
||||
| Linear/angular jog speed, max velocity, spindle/feed/rapid override | `update_*slider_vel`, `set_maxvel`, `set_spindlerate`, `set_feedrate`, `set_rapidrate` | Linear jog/max velocity/spindle/feed: `SOURCE_ADAPTER`; angular jog/rapid: `SOURCE_BLOCKED` |
|
||||
| About, Quick Reference, clear notifications | About/keys dialogs and `Ctrl-Space` binding | About: local adapter; Quick Reference and notification-clear are not rendered |
|
||||
| Case selector/load, packaged 3D Chips, Diagnostics, pan/reset buttons, source editor | no AXIS widget equivalent | `WEB_EXTENSION`; may not be counted as AXIS parity |
|
||||
|
||||
## Source Keyboard Contract
|
||||
|
||||
The following bindings are copied from `axis.py` lines 3109-3171. Keys that
|
||||
would require an unavailable command are listed as blocked instead of being
|
||||
silently mapped to another operation.
|
||||
The following bindings are copied from `axis.py` lines 3109-3186 and
|
||||
`3194-3327`. The source binds lowercase Tk event sequences even though Quick
|
||||
Reference displays several letters in uppercase. Keys requiring an unavailable
|
||||
command are blocked instead of being silently mapped to another operation.
|
||||
|
||||
| Key | Source handler | Web treatment |
|
||||
| --- | --- | --- |
|
||||
| `F1`, `F2`, lowercase `r`, `T`, `P`, `S`, `Esc`, `Ctrl-R`, `O`, `F7`-`F12` | E-stop, power, run, step, pause, resume, stop, reload, open, coolant and spindle handlers | Worker-backed commands with the same gate and ordering rules. |
|
||||
| `F1`, `F2`, lowercase `o`, `r`, `t`, `p`, `s`, `Escape`, `Ctrl-r`, `F7`-`F12` | E-stop, power, open, run, step, pause, resume, stop, reload, coolant and spindle handlers | Worker-backed commands where the corresponding control is supported. Display labels remain `O/R/T/P/S`. |
|
||||
| uppercase `R`, `F` | `task_reverse`, `task_forward` | Source controls are recorded as blocked because the selected WASM program ABI has no reverse/forward command; they are never mapped to Run. |
|
||||
| `Home`, `Ctrl-Home`, `End`, `Ctrl-End` | `home_joint`, `home_all_joints`, `touch_off_system`, `touch_off_tool` | Home and system Touch Off are implemented; Tool Touch Off reports the documented ABI blocker. |
|
||||
| `x`, `y`, `z`, `a`, `c`, `-`, `=`, Shift jog keys | Axis selection and `jog_on`/`jog_off` | Axis selection and pointer jog are implemented; browser key-jog remains limited to the visible selected axes. |
|
||||
| `c`, `i`, `I` | Continuous/incremental jog mode | Represented by the jog increment selector; no second local mode state is created. |
|
||||
| `Home`, `Ctrl-Home`, `Shift-Home`, `End`, `Ctrl-End` | selected joint home, home all, zero selected G54 axis, system touch off, tool touch off | Home and system Touch Off have adapters; zero-G54 and Tool Touch Off are blocked. |
|
||||
| lowercase `x`, `y`, `z`, `a` | Select the first four source axes | Axis selection adapter. Native AXIS does **not** bind lowercase `c` to C-axis selection; `c` selects continuous jog. C remains selectable only through its radio control. |
|
||||
| `-`, `=`, arrows/Page keys/`[`/`]` and their Shift variants | `jog_on_map`/`jog_off_map` or selected-axis `jog_minus`/`jog_plus` | Jog key semantics require keydown start and keyup stop. Pointer controls are supported; unavailable key bindings are not reassigned. |
|
||||
| lowercase `c`, lowercase `i`, uppercase `I` | Continuous, next incremental and previous incremental jog modes | Represented by the jog increment selector; no second machine-mode state is created. |
|
||||
| `` ` ``, digits `0`-`9` | Select joints in joint mode; otherwise set feed override from 0% to 100% | Joint-mode selection is blocked. Feed changes, if bound, must use the same mode-dependent meaning. |
|
||||
| `,`/`.`; `<`/`>`; `;`/`'` | Linear jog speed; angular jog speed; maximum velocity | Linear jog/max velocity have adapters; angular jog speed is blocked and must not alias linear speed. |
|
||||
| `v`, `d`, `!`, `@`, `#`, `$` | Cycle view, rotate, units, display type, coordinate type, teleop mode | View/rotate/units/display/coordinate actions are projected; teleop mode is explicitly unavailable. |
|
||||
| uppercase `B`, lowercase `b` | `brake_on`, `brake_off` | Must preserve the distinct source edges; Quick Reference describes them as Shift-B/B. |
|
||||
| `Ctrl-K` | `clear_live_plot` | Worker visual-only `VISUAL_CLEAR`. |
|
||||
| `Ctrl-S`, Ctrl-M/H/Shift-H, `F4` | Save G-code, MDI clipboard/history, next tab | Save/clipboard operations are host/UI-boundary; `F4` notebook cycling is a Web navigation action and does not alter machine state. |
|
||||
| `Ctrl-S`, `Ctrl-M/H/Shift-H`, `F3`, `F4`, `F5`, `Ctrl-Space` | Save G-code, MDI history, notebook selection and notification clear | Save/clipboard actions are host boundaries; tabs are local navigation plus their documented mode callback; notification clear has no machine effect. |
|
||||
|
||||
## State Gates
|
||||
|
||||
Every motion or interpreter operation is evaluated against the canonical task,
|
||||
IO and trajectory state before the handler runs.
|
||||
AXIS does not have one combined `RUNNING/STOPPED/READY` enum. Source parity is
|
||||
derived from independent LinuxCNC status dimensions; Web-friendly labels may be
|
||||
displayed, but they may not replace these dimensions as gate authority.
|
||||
|
||||
| State | Meaning in the panel |
|
||||
| Source dimension | Exact values used by AXIS | Meaning |
|
||||
| --- | --- | --- |
|
||||
| `task_state` | `STATE_ESTOP`, `STATE_ESTOP_RESET`, `STATE_OFF`, `STATE_ON` | Machine E-stop/power state. `emctask.cc::determineState()` publishes only ESTOP, ESTOP_RESET or ON; `STATE_OFF` is an accepted command value and is documented by `emcmodule.cc` as not used as a stable status value. |
|
||||
| `task_mode` | `MODE_MANUAL`, `MODE_AUTO`, `MODE_MDI` | Current task command domain. |
|
||||
| `interp_state` | `INTERP_IDLE`, `INTERP_READING`, `INTERP_PAUSED`, `INTERP_WAITING` | Interpreter lifecycle used by `axis.tcl::update_state`. |
|
||||
| `task_paused` / `paused` | Boolean pause projection | Used by `task_resume` and toolbar relief/icon projection. |
|
||||
| `exec_state` | `DONE`, `ERROR`, motion/IO/delay/system-command wait states | Task executor progress; it is not interchangeable with `interp_state`. |
|
||||
| `motion_mode` | `TRAJ_MODE_FREE`, `TRAJ_MODE_COORD`, `TRAJ_MODE_TELEOP` | Joint/world motion selection and touch-off availability. |
|
||||
| `taskfile`, `homed[]`, `on_any_limit`, `queued_mdi_commands`, `spindle[].direction` | Independent status fields | Additional source gates; none may be inferred from a React label. |
|
||||
|
||||
The source helper definitions are exact:
|
||||
|
||||
```text
|
||||
running = task_mode in {AUTO, MDI} and interp_state != IDLE
|
||||
|
||||
manual_ok = task_state == ON
|
||||
and not running
|
||||
and (interp_state == IDLE
|
||||
or (task_mode == MDI
|
||||
and queued_mdi_commands < max_queued_mdi_commands))
|
||||
```
|
||||
|
||||
`ensure_mode(m, *p)` polls, returns if the current task mode is an accepted
|
||||
mode, otherwise sends `c.mode(m)`, waits for completion and polls again. It is a
|
||||
command transaction, not a React state assignment and not a success check that
|
||||
may be skipped.
|
||||
|
||||
### Source-exact widget enable formulas
|
||||
|
||||
These expressions are copied from `axis.tcl::update_state`; handler and task
|
||||
checks still apply after a widget is enabled.
|
||||
|
||||
| Native widget/family | Exact AXIS UI enable condition |
|
||||
| --- | --- |
|
||||
| `ESTOP` | E-stop input asserted. Only the reset edge and diagnostic-safe actions are available. |
|
||||
| `ESTOP_RESET` | E-stop released but power is not on. `POWER(active=true)` is the next machine edge. |
|
||||
| `OFF` | Machine power is off. File inspection/loading is allowed by LinuxCNC, but motion and MDI are not. |
|
||||
| `ON` | IO is ready. Manual operations still require an idle interpreter and the correct task mode. |
|
||||
| `RUNNING`/`PAUSED` | AUTO execution owns the interpreter. Manual, MDI, home, spindle and tool operations are blocked. |
|
||||
| `STOPPED` | A stopped taskfile remains recoverable; the next source-defined transition is `IO_RECOVER`, power or restart as applicable. |
|
||||
| E-stop | Always enabled |
|
||||
| Power | `task_state != STATE_ESTOP` |
|
||||
| Open | `interp_state == INTERP_IDLE` |
|
||||
| Reload | `interp_state == INTERP_IDLE && taskfile != ""` |
|
||||
| Run | `task_state == STATE_ON && interp_state == INTERP_IDLE` |
|
||||
| Step | `task_state == STATE_ON && taskfile != ""` |
|
||||
| Pause menu | `task_state == STATE_ON && interp_state in {INTERP_READING, INTERP_WAITING}` |
|
||||
| Resume menu | `task_state == STATE_ON && interp_state == INTERP_PAUSED` |
|
||||
| Pause/Resume toolbar | `task_state == STATE_ON && interp_state != INTERP_IDLE` |
|
||||
| Stop | `task_state == STATE_ON && interp_state != INTERP_IDLE` |
|
||||
| Run from selected line | `task_state == STATE_ON && interp_state == INTERP_IDLE && highlight_line != -1` |
|
||||
| Homing/Unhoming/Zero-coordinate menus | `task_state == STATE_ON && interp_state == INTERP_IDLE` |
|
||||
| Manual group | `task_state == STATE_ON && interp_state == INTERP_IDLE` |
|
||||
| MDI group | `task_state == STATE_ON && queued_mdi_commands < max_queued_mdi_commands` |
|
||||
| Touch Off | `task_state == STATE_ON && interp_state == INTERP_IDLE && (motion_mode != TRAJ_MODE_FREE || kinematics_type == KINEMATICS_IDENTITY)` |
|
||||
| Tool Touch Off | Touch Off condition plus a loaded tool |
|
||||
| Override Limits | `on_any_limit` |
|
||||
| Spindle slower/faster | `task_state == STATE_ON && interp_state == INTERP_IDLE && spindle.direction != 0` |
|
||||
| Feed/spindle/rapid override and max-velocity sliders | No `update_state` disable formula; setters send their command directly. INI and command-layer range/enable rules still apply. |
|
||||
| View controls and Clear Live Plot | No machine-state gate |
|
||||
|
||||
`manual_ok()` is equivalent to: poll, task state ON, not running, and either
|
||||
an idle interpreter or an MDI queue below its limit. `ensure_mode()` is a
|
||||
command transaction, not a React state assignment.
|
||||
The Web may disable an action while a browser-only asynchronous load is in
|
||||
flight. Any other gate stronger than this table must be identified as a Web
|
||||
safety adaptation, not attributed to AXIS.
|
||||
|
||||
## Control Matrix
|
||||
|
||||
| Panel control | React command | Source flow and required result |
|
||||
| --- | --- | --- |
|
||||
| Emergency Stop / Cancel | `ESTOP {active}` | `estop_clicked` toggles `STATE_ESTOP` and `STATE_ESTOP_RESET`; active E-stop aborts the interpreter and TP, then keeps the loaded taskfile. |
|
||||
| Power on / off | `POWER {active}` | `onoff_clicked` toggles `STATE_ON` and `STATE_OFF`; power-off aborts motion but preserves the loaded file. |
|
||||
| Open G-code file | browser file + `PROGRAM_LOAD` | `open_file_guts`: poll, save mode, enter MANUAL, restore the saved tab mode before `PLAN_OPEN/program_open`, set first line, synchronize, parse/preview, then `set_mode_from_tab` after refresh. |
|
||||
| Load case / packaged program / edited source | `LOAD_WORKSPACE` and/or `PROGRAM_LOAD` | The Web case bootstrap and packaged-program selector use the same replacement transaction as `open_file_guts`. Edited text is submitted only through the single toolbar Reload command; the program pane has no duplicate Load/Run/Step buttons. Old preview is cleared before parsing and never reused after a failed replacement. |
|
||||
| Switchkins Identity / TCP: XYZAC / User K | `KINEMATICS_SELECT {type}` | Selected-case remap equivalent for `M429`/`M428`/`M430` from `xyzac-trt.ini`; requires homed, idle, empty TP queue and canonical HAL switchkins state. |
|
||||
| Emergency Stop / Cancel | `ESTOP {active}` | `SOURCE_ADAPTER`: `estop_clicked` sends `STATE_ESTOP_RESET` only when status is `STATE_ESTOP`; every other status sends `STATE_ESTOP`. `emcTaskSetState(ESTOP)` aborts motion, spindle, task and IO, disables trajectory, applies volatile unhome and synchronizes the task plan. |
|
||||
| Power on / off | `POWER {active}` | `SOURCE_ADAPTER`: `onoff_clicked` sends `STATE_ON` only from `STATE_ESTOP_RESET`; otherwise it sends `STATE_OFF`. Power off aborts motion/task/IO and volatile homes; the subsequently observed source state is normally `STATE_ESTOP_RESET`, not stable `STATE_OFF`. The selected taskfile path remains status data. |
|
||||
| Open G-code file | browser file + `PROGRAM_LOAD` | `SOURCE_ADAPTER`: native UI gate is interpreter IDLE. `open_file_guts` polls, saves mode, ensures MANUAL, processes an optional filter, restores saved mode, resets start line/highlight, `task_plan_synch` + wait, `program_open`, replaces the text/canon, constructs status-derived preview init codes, parses, redraws, then calls `set_mode_from_tab`. A parse error is reported against the newly selected file; AXIS does not roll back to the previous canon. |
|
||||
| Load case / packaged program / edited source | `LOAD_WORKSPACE` and/or `PROGRAM_LOAD` | `WEB_EXTENSION` entry points. Once a file is selected they must use the Open/Reload adapter and may add a browser-load/queue exclusion while asynchronous parsing is active. Edited text is committed only through Reload; these controls are not native AXIS buttons. |
|
||||
| Switchkins Identity / TCP: XYZAC / User K | `KINEMATICS_SELECT {type}` | `SOURCE_ADAPTER` for the selected INI's HALUI MDI commands: `M429 -> type 0`, `M428 -> type 1`, `M430 -> type 2`; each remap executes `M68 E3 Q<type>` then `M66 E0 L0` and verifies `motion.switchkins-type` in task context. The Web's homed/idle/empty-TP gate is a stated safety strengthening around the source MDI/task gate. |
|
||||
| Run | `PROGRAM_RUN` | `run_warn`, `ensure_mode(AUTO)`, `AUTO_RUN` from the selected start line, then periodic task/TP ticks. Normal AXIS Run uses line 0. In `emctaskmain.cc`, an ended or aborted task plan is closed; the next `EMC_TASK_PLAN_RUN` reopens the current taskfile and runs from line 0. Therefore Run after `completed` or `aborted` must work directly and must not require a separate Reload/Restart click. |
|
||||
| Run from selected line | not exposed | AXIS `task_run_line` requires an editor highlight and source `AUTO_RUN` start line. The Web editor has no source-line selection command yet, so no partial/fake button is rendered. |
|
||||
| Reverse / Forward | not exposed | AXIS `task_reverse`/`task_forward` are keyboard-only source actions; the selected WASM program ABI has no corresponding command and Web preserves the distinction from Run. |
|
||||
| Step | `PROGRAM_STEP` | `ensure_mode(AUTO)` when needed, issue `AUTO_STEP`, and keep the interpreter at the source line boundary. |
|
||||
| Pause / Resume | `PROGRAM_PAUSE` / `PROGRAM_RESUME` | Pause only while AUTO is reading/waiting; resume only from the paused state. Polling ticks stop around the edge so a servo sample cannot race it. |
|
||||
| Step | `PROGRAM_STEP` | `SOURCE_ADAPTER`: source toolbar gate is ON plus taskfile, not interpreter IDLE. `task_step` clears highlight/runs warning unless already AUTO+IDLE, ensures AUTO and sends `AUTO_STEP`. Task-layer homing remains authoritative. |
|
||||
| Pause / Resume | `PROGRAM_PAUSE` / `PROGRAM_RESUME` | `SOURCE_ADAPTER`: `task_pause` accepts AUTO plus READING/WAITING. `task_resume` requires `paused` plus mode AUTO or MDI. The combined toolbar calls `task_pauseresume`, accepts AUTO or MDI, blocks resume when `resume_inhibit`, and otherwise pauses any non-IDLE interpreter. Web scheduling must serialize the edge but cannot change these state conditions. |
|
||||
| Stop | `PROGRAM_ABORT` | AXIS enables Stop only while the interpreter is non-idle; then it highlights the active line, issues `c.abort()`, waits for completion, and clears the abort edge. The Worker may accept an internal abort edge in more states, but the Web button follows the AXIS UI gate. |
|
||||
| Block delete / optional pause | disabled | LinuxCNC source has these controls, but the selected WASM ABI does not expose their canonical state. They are visible as disabled, with `blocked_by_abi`, and never emulate a local toggle. |
|
||||
| Preview view, zoom, rotate, clear plot | local view or `VISUAL_CLEAR` | Visual-only operations do not change task, interpreter, TP or IO state. `Ctrl-K` maps AXIS `clear_live_plot()` and clears only the accumulated execution Live Plot; it must not delete the loaded program's static preview. |
|
||||
| Preview view, zoom, rotate, clear plot | local view or `VISUAL_CLEAR` | `SOURCE_ADAPTER`: view operations do not change task/interpreter/TP/IO. `Ctrl-K` maps `clear_live_plot()` -> `live_plotter.clear()` -> `positionlogger.clear()` and clears only Live Plot; it never deletes the loaded `AxisCanon` preview. Native Run, Stop, completion and Open/Reload do not call this clear path. |
|
||||
| DRO coordinate/display/units | local projection | Maps AXIS `coord_type`, `display_type` and `metric` variables; values remain Worker snapshot projections. |
|
||||
| Preview layers | local projection | Maps source `show_live_plot`, `show_machine_limits`, `show_machine_speed`, `show_offsets` and `show_extents` where the selected visual adapter has data; toggling a layer never changes motion. |
|
||||
| Manual / MDI tabs | `SET_MODE` | The tab gesture sends an explicit Worker mode command. No background effect may change MANUAL after AUTO has started. |
|
||||
| Preview layers | local projection | `SOURCE_ADAPTER` only where the source variable exists: path=`show_program`, live=`show_live_plot`, limits=`show_machine_limits`, velocity=`show_machine_speed`, offsets=`show_offsets`, extents=`show_extents`. AXIS also has rapids, alpha, tool and DTG controls that the Web does not expose. Toggling visibility never deletes layer data. |
|
||||
| Manual / MDI tabs | `SET_MODE` | `SOURCE_ADAPTER`: native tab callbacks are `ensure_manual` and `ensure_mdi`, including `set_motion_teleop` transitions. `axis.tcl::update_state` calls `set_mode_from_tab` only when returning to ON+IDLE from a non-idle/task-state transition while task mode is AUTO. No unrelated React effect may force a mode. |
|
||||
| Joint/World (teleop) mode | not exposed | AXIS View menu calls `set_teleop_mode`/`c.teleop_enable`; the selected WASM motion ABI has no canonical teleop setter, so Web does not pretend its coordinate mode is a joint/world toggle. |
|
||||
| Jog `-` / `+` | `JOG_START`, repeated `SIM_STEP`, `JOG_STOP` | `jog_on`/`jog_off` semantics. Incremental mode submits one TP segment; Continuous mode samples the source TP jog velocity until pointer release. |
|
||||
| Jog `-` / `+` | `JOG_START`, `SIM_STEP`, `JOG_STOP` | `SOURCE_ADAPTER`: source requires `manual_ok` and the visible Manual tab. Incremental sends one `JOG_INCREMENT`; Continuous sends one `JOG_CONTINUOUS` and motion continues until the deferred release issues `JOG_STOP`. Web servo sampling is transport/runtime work, not repeated user jog commands. |
|
||||
| Home Axis | `HOME {axis}` | `manual_ok`, `ensure_mode(MANUAL)`, then source joint-home command. Individual axis home is rejected outside identity kinematics, matching `home_joint`. |
|
||||
| Home All / Re-home All | `HOME {all:true}` | `manual_ok`, `ensure_mode(MANUAL)`, then home all joints. Once the canonical homed mask is complete, the Web label changes to `RE-HOME ALL` so loading another program is not mistaken for a requirement to home again. Activating Re-home retains the source `home_all_joints` confirmation. `PROGRAM_LOAD` never clears the homed mask and never invokes HOME. |
|
||||
| Touch Off | `TOUCH_OFF {axis,value,system,units}` | Prompt for value and one of AXIS's `all_systems` entries (`P0 Current`, `P1 G54` ... `P9 G59.3`), enter MDI, issue `G10 L20 <P-token>`, wait/synchronize, reload the active interpreter state and restore the saved mode. |
|
||||
| Home All / Re-home All | `HOME {all:true}` | `SOURCE_ADAPTER`: `manual_ok`, ensure MANUAL, if `all_homed()` ask the native re-home confirmation, then `set_motion_teleop(0)`, `c.home(-1)`, wait. Native text remains Home All; the Web `RE-HOME ALL` label is presentation-only and cannot trigger a hidden home during load. |
|
||||
| Touch Off | `TOUCH_OFF {axis,value,system,units}` | `SOURCE_ADAPTER`: source UI condition is the Touch Off formula above; task-layer MDI additionally enforces homing unless `NO_FORCE_HOMING`. Prompt for `P0 Current` through `P9 G59.3`, save mode, ensure MDI, scale linear units, issue `G10 L20 <P-token> <axis>[value*scale]`, wait, redraw/reload, restore saved mode and TELEOP. |
|
||||
| Tool Touch Off | `TOOL_TOUCH_OFF {axis,value,system,units}` | LinuxCNC source requires `G10 L10/L11` plus `G43`, but the selected WASM interpreter does not expose canonical tool-offset storage. The control is therefore disabled with `blocked_by_abi_tool_offsets`; it never sends a fake fixed `G43`. |
|
||||
| Override limits | disabled | Source requires an active limit and an idle interpreter; the selected WASM limit override ABI is unavailable, so no unsafe local emulation is provided. |
|
||||
| Spindle CCW / stop / CW | `SPINDLE_COMMAND` | `manual_ok`, `ensure_mode(MANUAL)`, then source direction/stop command. The displayed pressed state is derived from canonical signed RPM. |
|
||||
| Override limits | disabled | `SOURCE_BLOCKED`: widget enable requires `on_any_limit`; handler separately requires interpreter IDLE. If already overridden it ensures AUTO; otherwise it ensures MANUAL and calls `c.override_limits()`. The selected WASM ABI cannot represent this canonical path. |
|
||||
| Spindle CCW / stop / CW | `SPINDLE_COMMAND` | `SOURCE_ADAPTER`: `manual_ok`, ensure MANUAL, then `c.spindle(0)` or `c.spindle(direction, default_spindle_speed)`. Pressed state comes from canonical `spindle[0].direction`, not an RPM-sign inference. |
|
||||
| Spindle - / + | `SPINDLE_COMMAND {delta}` → `SPINDLE_CONSTANT` on release | AXIS binds Button-1 to `spindle_decrease`/`spindle_increase` and ButtonRelease to `spindle_constant`; Web preserves this press/release sequence. |
|
||||
| Brake | `SPINDLE_BRAKE` | Source brake command, gated by `manual_ok`. |
|
||||
| Mist / Flood | `COOLANT_COMMAND` | Independent source coolant toggles; canonical device IO is returned after every edge. |
|
||||
| Mist / Flood | `COOLANT_COMMAND` | `SOURCE_ADAPTER`: manual checkboxes belong to the ON+IDLE manual group and call `c.mist(value)`/`c.flood(value)` directly. F7/F8 poll status and send the inverse canonical bit. |
|
||||
| Tool / probe status | read-only | AXIS does not put Prepare/Change/Arm/Disarm buttons in this manual notebook. Tool changes remain interpreter/MDI and IO/HAL operations. Web displays canonical tool/probe state but exposes no extra main-panel command buttons. |
|
||||
| Jog Speed | `SET_JOG_SCALE` | `update_jog_slider_vel` writes the source linear jog scale. |
|
||||
| Jog Speed | `SET_JOG_SCALE` | `SOURCE_ADAPTER`: the slider changes AXIS's linear jog-speed value used by subsequent jog commands; it is not itself a motion command and has no `update_state` power gate. |
|
||||
| Angular Jog Speed | not exposed | AXIS has a separate `ajogspeed` control for rotary joints; the selected WASM TP exposes one shared jog scale only, so the Web panel does not alias linear Jog Speed to this control. |
|
||||
| Feed Override | `SET_OVERRIDE` | `set_feedrate` writes the source feed override; updates are debounced but ordered in the Worker queue. |
|
||||
| Spindle Override | `SET_SPINDLE_OVERRIDE` | `set_spindlerate` writes canonical spindle override. |
|
||||
| Max Velocity | `SET_MAX_VELOCITY` | AXIS `set_maxvel` calls `c.maxvel` and changes the trajectory velocity limit. The selected WASM TP exposes this as its velocity scale. |
|
||||
| Feed Override | `SET_OVERRIDE` | `SOURCE_ADAPTER`: `set_feedrate` sends `c.feedrate(percent/100)` without a machine-state UI gate. Selected INI `MAX_FEED_OVERRIDE=2` makes the range 0-200%. Web debouncing may coalesce pointer events but must preserve the last ordered value. |
|
||||
| Spindle Override | `SET_SPINDLE_OVERRIDE` | `SOURCE_ADAPTER`: `set_spindlerate` sends `c.spindleoverride(percent/100)` without an `update_state` power gate. Its maximum defaults to MAX_FEED_OVERRIDE when `MAX_SPINDLE_OVERRIDE` is absent. |
|
||||
| Max Velocity | `SET_MAX_VELOCITY` | `SOURCE_ADAPTER`: `set_maxvel` converts display units and sends `c.maxvel(value/60)` without an `update_state` power gate. The selected WASM TP exposes this as its velocity limit/scale. |
|
||||
| Rapid Override | disabled | AXIS `set_rapidrate` calls `c.rapidrate` and is distinct from Max Velocity. The selected WASM TP has no rapid-scale setter, so the Web control is disabled with `blocked_by_abi_rapidrate`. |
|
||||
| MDI command/history | `MDI_EXECUTE` | `send_mdi` validates `manual_ok`, enters MDI, de-duplicates adjacent history entries and submits `c.mdi`. |
|
||||
| MDI command/history | `MDI_EXECUTE` | `SOURCE_ADAPTER`: `send_mdi` validates `manual_ok`; nonempty text is trimmed, the entry cleared, MDI mode ensured, and the command is inserted unless it equals the immediately preceding history entry, then `c.mdi(command)` is sent. A single click selects history; native double-click executes it. |
|
||||
| File tool-data editor / Quit | disabled | AXIS launches a host editor or terminates the desktop process. Browser controls remain visibly disabled with `host_boundary_tool_editor` / `host_boundary_process_quit`; clicking them cannot report a false success. |
|
||||
| About AXIS | local dialog | Mirrors the source `.about` dialog and its OK/close action. It changes no Worker, task, TP or IO state. |
|
||||
| About AXIS | local dialog | `SOURCE_ADAPTER`: mirrors the source `.about` open/OK-close action and changes no Worker/task/TP/IO state. The native website link is a separate external-host action. |
|
||||
|
||||
## Complete Web Control Inventory
|
||||
|
||||
@@ -179,14 +304,14 @@ history rows intentionally share the family ID `mdi-history-select`.
|
||||
| `menu-file-edit-tool-data`, `menu-file-quit` | `edit_tooltable`, `quit` host process operations | Permanently disabled in a browser | `host_boundary_tool_editor` / `host_boundary_process_quit`; no fake status success |
|
||||
| `menu-help-about`, `about-close` | `.menu.help` About entry and `.about.ok` | Local modal open/close | About visibility changes only |
|
||||
| `toolbar-estop` | `.toolbar.machine_estop` -> `estop_clicked` | `ESTOP {active}`; accepted from every task state | Toggle source E-stop edge; active edge aborts interpreter/TP |
|
||||
| `toolbar-power` | `.toolbar.machine_power` -> `onoff_clicked` | `POWER {active}`; reset E-stop before power-on | Canonical `STATE_ON`/`STATE_OFF`; power-off aborts motion |
|
||||
| `toolbar-power` | `.toolbar.machine_power` -> `onoff_clicked` | `POWER {active}`; source widget enabled whenever status is not ESTOP | Send ON only from ESTOP_RESET, otherwise OFF; stable post-off status normally projects ESTOP_RESET |
|
||||
| `toolbar-open`, `program-file-input` | `.toolbar.file_open` -> `open_file`/`open_file_guts` | File picker then `PROGRAM_LOAD`; interpreter must be IDLE | One replacement transaction; input itself is hidden and only the toolbar button opens it |
|
||||
| `toolbar-load-case` | Web workspace boundary; uses INI `DISPLAY`, `HAL`, `KINS` and `OPEN_FILE` inputs | `LOAD_WORKSPACE` then the documented `PROGRAM_LOAD`; IDLE only | Reloads the selected exact case; never adds Power/Home/Run aliases |
|
||||
| `toolbar-load-case` | `WEB_EXTENSION`; uses INI `DISPLAY`, `HAL`, `KINS` and `OPEN_FILE` inputs | `LOAD_WORKSPACE` then Open adapter; IDLE plus browser async/queue exclusion | Reloads the selected exact case; never counts as an AXIS control or adds Power/Home/Run aliases |
|
||||
| `toolbar-reload` | `.toolbar.reload` -> `reload_file` | `PROGRAM_LOAD` of current editor source/path; IDLE taskfile required | Replaces preview/interpreter at line 0; this is the only visible commit action for edited source |
|
||||
| `toolbar-run` | `.toolbar.program_run` -> `task_run` | `PROGRAM_RUN`; ON, taskfile, IDLE and task-layer homing gate | AUTO/RUNNING from line 0; completed/aborted taskfile reopens directly |
|
||||
| `toolbar-step` | `.toolbar.program_step` -> `task_step` | `PROGRAM_STEP`; ON, taskfile and homing gate | AUTO_STEP then PAUSED at the next source boundary |
|
||||
| `toolbar-pause-resume` | `.toolbar.program_pause` -> `task_pauseresume` | Pause while READING/WAITING; Resume while PAUSED | One source toggle whose icon/label and command follow canonical pause state |
|
||||
| `toolbar-stop` | `.toolbar.program_stop` -> `task_stop` | `PROGRAM_ABORT`; visible button enabled only for non-IDLE interpreter | Abort, drain/clear TP and retain selected taskfile |
|
||||
| `toolbar-run` | `.toolbar.program_run` -> `task_run` | `PROGRAM_RUN`; native widget ON+IDLE; task layer additionally requires a taskfile and homing unless `NO_FORCE_HOMING=1` | AUTO/READING from line 0; completed/aborted taskfile reopens directly |
|
||||
| `toolbar-step` | `.toolbar.program_step` -> `task_step` | `PROGRAM_STEP`; native widget ON+taskfile, then handler/task gates | AUTO_STEP at the next source boundary; do not add an IDLE-only UI gate |
|
||||
| `toolbar-pause-resume` | `.toolbar.program_pause` -> `task_pauseresume` | Native widget ON+non-IDLE; handler distinguishes `paused` and accepts AUTO/MDI | One source toggle whose icon/label and command follow canonical pause state and resume-inhibit |
|
||||
| `toolbar-stop` | `.toolbar.program_stop` -> `task_stop` | `PROGRAM_ABORT`; native widget ON+non-IDLE | Highlight AUTO running line when nonzero, abort, wait, retain selected taskfile |
|
||||
| `toolbar-block-delete`, `toolbar-optional-pause` | Source toolbar toggles | Permanently disabled for selected ABI | `blocked_by_abi`; no React-only toggle |
|
||||
| `toolbar-zoom-in`, `toolbar-zoom-out` | `zoomin`, `zoomout` | Local preview camera only | Bounded camera zoom; task/TP unchanged |
|
||||
| `toolbar-view-z`, `toolbar-view-z2`, `toolbar-view-x`, `toolbar-view-y`, `toolbar-view-y2`, `toolbar-view-p` | `set_view_z/z2/x/y/y2/p` | Local source view selection | Exactly one pressed view; opens Preview tab; machine state unchanged |
|
||||
@@ -194,33 +319,33 @@ history rows intentionally share the family ID `mdi-history-select`.
|
||||
| `toolbar-clear-live-plot` | `clear_live_plot` -> `positionlogger.clear()` | Worker `VISUAL_CLEAR`; always visual-only | Advances `live_path_epoch`, clears Live Plot only and retains static preview |
|
||||
| `workspace-case-select` | Web selection of the INI/configuration input | Local selection; selected catalog is restricted to supported XYZAC case | Does not load or change machine state until `toolbar-load-case` |
|
||||
| `workspace-load-3d-chips` | Web packaged-file equivalent of `open_file_guts` | Fetch published `3D_Chips.ngc`, then `PROGRAM_LOAD`; IDLE only | Same canonical file replacement path as Open; no automatic Run/Home |
|
||||
| `manual-home-all` | Machine Homing menu -> `home_all_joints` | `HOME {all:true}`; `manual_ok`, then MANUAL | First Home homes all; canonical homed mask changes label to Re-home; repeat asks source confirmation |
|
||||
| `manual-home-all` | Machine Homing menu -> `home_all_joints` | `HOME {all:true}`; `manual_ok`, then MANUAL | Repeat asks source confirmation; Web Re-home label is non-authoritative presentation only |
|
||||
| `switchkins-0`, `switchkins-1`, `switchkins-2` | `M429`, `M428`, `M430` remaps and `motion.switchkins-type` | `KINEMATICS_SELECT`; ON, homed, IDLE, empty TP | Identity/XYZAC/User K canonical type, or stable gate reason |
|
||||
| `tab-manual`, `tab-mdi` | AXIS notebook F3/F5 `ensure_manual`/`ensure_mdi` | `SET_MODE`; no active AUTO motion | Tab selection plus acknowledged MANUAL/MDI mode change |
|
||||
| `tab-manual`, `tab-mdi` | AXIS notebook F3/F5 `ensure_manual`/`ensure_mdi` | `SET_MODE` adapter; source `manual_ok` plus joint/teleop transitions apply | Tab selection plus acknowledged source-equivalent MANUAL/MDI and motion-mode transition |
|
||||
| `tab-diagnostics` | Web diagnostics boundary | Local tab only | Reads Worker state/gates; sends no command |
|
||||
| `tab-preview`, `tab-dro` | AXIS preview/DRO presentation | Local tab only | Changes visible projection; machine state unchanged |
|
||||
| `manual-axis-x`, `manual-axis-y`, `manual-axis-z`, `manual-axis-a`, `manual-axis-c` | AXIS axis radio group / `ja_rbutton` | Local axis selection | Supplies the selected axis to Jog/Home/Touch Off; sends no motion by itself |
|
||||
| `manual-jog-increment` | `jogincrement` combobox | Local choice: Continuous or configured increment | Determines `JOG_CONTINUOUS` versus `JOG_INCREMENT` payload only |
|
||||
| `manual-jog-negative`, `manual-jog-positive` | `jogminus`, `jogplus` -> `jog_on` | `JOG_START`; visible Manual tab, ON, IDLE, homed | Incremental submits once; Continuous repeats source-rate segments while held |
|
||||
| `manual-jog-negative`, `manual-jog-positive` | `jogminus`, `jogplus` -> `jog_on` | `JOG_START`; visible Manual tab and `manual_ok`; source chooses joint/teleop mode from kinematics+homing | Incremental submits once; Continuous remains active until one release/cancel `JOG_STOP` |
|
||||
| `manual-home-axis` | `home_joint` | `HOME {axis}`; `manual_ok`, MANUAL, identity kinematics for coordinate-axis home | Canonical joint home; repeated home asks confirmation |
|
||||
| `manual-touch-off` | `touch_off_system` | `TOUCH_OFF`; ON, homed, IDLE, MANUAL and valid value/system | MDI `G10 L20`, synchronize, reload and restore saved mode |
|
||||
| `manual-touch-off` | `touch_off_system` | `TOUCH_OFF`; exact Touch Off UI formula, `manual_ok`, valid axis/value/system, plus task-layer homing policy | MDI `G10 L20`, wait, reload and restore saved task/motion mode |
|
||||
| `manual-tool-touch-off` | `touch_off_tool` | Permanently disabled for selected ABI | `blocked_by_abi_tool_offsets`; never approximated with `G92`/fixed `G43` |
|
||||
| `manual-override-limits` | `toggle_override_limits` | Permanently disabled for selected ABI | No state mutation; explanatory ABI title |
|
||||
| `manual-spindle-ccw`, `manual-spindle-stop`, `manual-spindle-cw` | spindle radio group -> `spindle` | `SPINDLE_COMMAND`; `manual_ok`, MANUAL | Canonical signed RPM/direction determines pressed state |
|
||||
| `manual-spindle-decrease`, `manual-spindle-increase` | `spindle_decrease/increase`; ButtonRelease -> `spindle_constant` | Enabled only while spindle direction is nonzero, matching `axis.tcl update_state` | Press sends speed edge without crossing through zero into the opposite direction; release/cancel sends `SPINDLE_CONSTANT` |
|
||||
| `manual-spindle-brake` | `brake` | `SPINDLE_BRAKE`; same manual source gate | Canonical brake state controls checkbox |
|
||||
| `manual-coolant-mist`, `manual-coolant-flood` | manual-group `mist`/`flood` controls | `COOLANT_COMMAND`; visible checkboxes require ON and IDLE | Independent canonical coolant bits; disabled during AUTO activity |
|
||||
| `manual-coolant-mist`, `manual-coolant-flood` | manual-group `mist`/`flood` controls | `COOLANT_COMMAND`; checkboxes use the source ON+IDLE manual-group gate | Independent canonical coolant bits; F7/F8 inverse the polled source value |
|
||||
| `mdi-command`, `mdi-submit` | MDI entry and `send_mdi` | Local text; submit/Enter sends `MDI_EXECUTE` under `manual_ok`/queue gate | Trimmed nonempty block, MDI mode, canonical interpreter result |
|
||||
| `mdi-history-select` | AXIS MDI history row selection | Local history selection | Copies selected prior command into entry; does not execute until Submit/Enter |
|
||||
| `preview-panLeft`, `preview-panRight`, `preview-panUp`, `preview-panDown`, `preview-reset` | Web accessible equivalent of Gremlin mouse pan/reset | Local camera only | Moves/resets camera; no Worker command |
|
||||
| `dro-coordinate`, `dro-display`, `dro-units` | `coord_type`, `display_type`, `metric` | Local snapshot projection | Machine/Relative, Actual/Commanded and mm/inch display only |
|
||||
| `override-jog-speed` | `update_jog_slider_vel` | `SET_JOG_SCALE`; source jog gate | Canonical linear jog scale |
|
||||
| `override-feed` | `set_feedrate` | Debounced `SET_OVERRIDE`; ON | Canonical feed override, including while AUTO where task layer permits |
|
||||
| `override-spindle` | `set_spindlerate` | `SET_SPINDLE_OVERRIDE`; ON | Canonical spindle override |
|
||||
| `override-max-velocity` | `set_maxvel` | `SET_MAX_VELOCITY`; ON | Canonical TP velocity limit/scale |
|
||||
| `override-jog-speed` | `update_jog_slider_vel` | `SET_JOG_SCALE`; no native machine-state UI gate | Canonical linear jog value used by later jogs |
|
||||
| `override-feed` | `set_feedrate` | Debounced `SET_OVERRIDE`; no native `update_state` power gate; selected INI range 0-200% | Canonical feed override, including while AUTO where command layer permits |
|
||||
| `override-spindle` | `set_spindlerate` | `SET_SPINDLE_OVERRIDE`; no native `update_state` power gate | Canonical spindle override |
|
||||
| `override-max-velocity` | `set_maxvel` | `SET_MAX_VELOCITY`; no native `update_state` power gate | Canonical TP velocity limit/scale |
|
||||
| `override-rapid` | `set_rapidrate` | Permanently disabled for selected ABI | `blocked_by_abi_rapidrate`; never aliases Max Velocity |
|
||||
| `preview-layer-path`, `preview-layer-live`, `preview-layer-limits`, `preview-layer-velocity`, `preview-layer-offsets`, `preview-layer-extents` | AXIS View visibility variables | Local visibility only | Shows/hides existing snapshot data without deleting or mutating it |
|
||||
| `program-editor` | Browser replacement for AXIS external Edit boundary | Edits pending source text locally | Does not change loaded interpreter until `toolbar-reload` |
|
||||
| `preview-layer-path`, `preview-layer-live`, `preview-layer-limits`, `preview-layer-velocity`, `preview-layer-offsets`, `preview-layer-extents` | AXIS View visibility variables | Local visibility only; path maps `show_program` | Shows/hides existing snapshot data without deleting or mutating it |
|
||||
| `program-editor` | `WEB_EXTENSION`, not AXIS external Edit | Edits pending source text locally | Does not change loaded interpreter until the Reload adapter is accepted |
|
||||
|
||||
Tool/probe IO operations (`TOOL_PREPARE`, `TOOL_PREPARED`, `TOOL_CHANGE`,
|
||||
`TOOL_CHANGED`, `PROBE_CONFIG`) remain Worker capabilities for interpreter,
|
||||
@@ -236,24 +361,25 @@ React must derive its button gates from that state on the next snapshot.
|
||||
| Action | Must be true before the click | State change after acceptance | Controls affected next |
|
||||
| --- | --- | --- | --- |
|
||||
| `ESTOP(active=true)` | Always accepted by the task state machine | IO `estop=1`, `ready=0`; interpreter and TP aborted; task `ESTOP`; loaded source retained | Disable power-on, home, jog, MDI, spindle, tool, probe and all program controls except E-stop reset/recovery-safe actions |
|
||||
| `ESTOP(active=false)` | E-stop input is asserted | IO estop clears; task becomes `STOPPED`/`ESTOP_RESET`; power remains off | Enable Power On; keep all motion/interpreter operations disabled |
|
||||
| `POWER(active=true)` | E-stop clear, interpreter idle, task not running | IO `ready=1`; task `READY`/machine `ON` | Enable Home and source-gated manual/program controls; Run still requires homed and a taskfile |
|
||||
| `POWER(active=false)` | Machine on (source accepts the immediate off edge) | Abort motion/interpreter, IO `ready=0`, loaded taskfile retained | Disable motion, MDI, home and Run; allow Power On after the off edge |
|
||||
| `HOME(all/axis)` | Machine on, interpreter idle, homing gate true | Home-limit authority sets homed mask; individual non-identity home is rejected | Enables Run/MDI/jog only after the canonical homed result is published |
|
||||
| `PROGRAM_LOAD` | Interpreter idle, TP/MDI motion queue empty, source file/path valid | Enters MANUAL for replacement setup, captures the current canonical TP pose, restores the saved mode before PLAN_OPEN-equivalent parsing, replaces the interpreter source, applies the `task_plan_synch` pose before preview/subroutine processing, then reapplies the selected tab mode | Run/Step/Restart gates are recalculated from the new taskfile; old preview/trace is unavailable during parse and incremental coordinates start from the synchronized machine pose |
|
||||
| `ESTOP(active=false)` | Source toggle requires current status ESTOP | IO E-stop clears; observed source task state becomes `ESTOP_RESET`; Web may display `STOPPED` only as an adapter label | Power is enabled; motion/manual/MDI remain disabled until ON |
|
||||
| `POWER(active=true)` | Source ON edge is valid only from `ESTOP_RESET`; it does not require interpreter IDLE | Trajectory enables and observed task state becomes ON | Manual group requires ON+IDLE; program Run still meets UI/taskfile adapter and task-layer homing rules |
|
||||
| `POWER(active=false)` | Source toolbar allows the toggle whenever status is not ESTOP, including active execution | Motion/task/IO abort, trajectory disables, volatile-home joints unhome, task plan synchronizes; taskfile retained | Observed state returns to ESTOP_RESET; nonvolatile homing is not falsely cleared by the UI |
|
||||
| `HOME(all/axis)` | AXIS homing UI: ON+IDLE; handler `manual_ok`, then MANUAL | Home authority updates `homed[]`; individual coordinate-axis home is rejected for non-identity/duplicate coordinates | AUTO's task layer may run only when all required joints are homed unless `NO_FORCE_HOMING=1` |
|
||||
| `PROGRAM_LOAD` | Native Open/Reload requires interpreter IDLE; Web additionally excludes active TP/MDI queue and concurrent parse | Save mode, ensure MANUAL, restore mode, set line 0, synchronize, open/replace taskfile and canon, parse status-derived preview, then apply tab mode | New taskfile/preview replace the old selection. Static preview replacement is independent of Live Plot data. |
|
||||
| `KINEMATICS_SELECT` | Machine on, homed, idle, TP queue empty, valid type 0/1/2 | M429/M428/M430 selection updates canonical kinematics and the HAL switchkins type | Identity is required for individual coordinate-axis homing; a non-empty queue blocks selection |
|
||||
| `SET_MODE(MANUAL)` | Machine on, no active AUTO/MDI motion | Task mode becomes `MANUAL` | Enables manual jog/home/spindle/tool gates when idle; disables AUTO-only pause/resume |
|
||||
| `SET_MODE(MDI)` | Machine on, interpreter idle or MDI queue below limit | Task mode becomes `MDI` | Enables MDI submission; manual controls follow `manual_ok` and queue policy |
|
||||
| `PROGRAM_RUN` | AXIS toolbar projection: machine ON and interpreter IDLE. Task acceptance additionally requires a current taskfile and, unless `NO_FORCE_HOMING` is configured, all required joints homed. `completed` and `aborted` are valid idle starting states. | If the previous task plan ended or was aborted, reopen/rewind the current taskfile at line 0; set mode `AUTO`, program `RUNNING`, and begin TP samples. A short program may pass through RUNNING and reach `completed` before the next UI paint; that is successful execution, not a blocked Run. | Disable Load, MDI, Home, Jog, spindle and tool operations while active; enable Pause and Stop. On completion, Run becomes available again for another line-0 execution. |
|
||||
| `PROGRAM_PAUSE` | AUTO program is reading/waiting | Program/task `PAUSED`; run polling is stopped around the edge | Disable Pause and Stop-as-new-run; enable Resume; keep E-stop and Power Off available |
|
||||
| `PROGRAM_RESUME` | Program/task is paused | Program/task `RUNNING`; TP polling resumes | Re-enable Pause and Stop; keep manual/MDI/home disabled |
|
||||
| `SET_MODE(MANUAL)` | Source task rejects leaving active AUTO; tab handler also requires `manual_ok` | Task mode MANUAL plus source joint/teleop selection | Manual widgets are still controlled by ON+IDLE, not mode alone |
|
||||
| `SET_MODE(MDI)` | Tab handler requires `manual_ok`; task mode transition follows source motion-mode calls | Task mode MDI | MDI widgets use ON+queue-capacity; submission still calls `manual_ok` |
|
||||
| `PROGRAM_RUN` | Native toolbar formula is ON+IDLE and does not test taskfile. Web adds current-taskfile validation; task acceptance adds all-homed unless `NO_FORCE_HOMING=1`. Completed/aborted are valid idle starts. | `task_run`: warning, ensure AUTO, `AUTO_RUN(start_line)`, reset next start line to 0. Task layer reopens the retained file when plan is closed. | During non-IDLE, native Run relief is pressed and Open/Reload/Run/manual controls disable; on IDLE, direct Run is available again. |
|
||||
| `PROGRAM_PAUSE` | Source handler: AUTO plus READING/WAITING; combined toolbar: AUTO/MDI plus non-IDLE and not currently paused | Trajectory pauses, previous interpreter state is saved, interpreter becomes PAUSED | Combined toolbar remains enabled and becomes Resume; Stop, E-stop and Power remain enabled by their own formulas |
|
||||
| `PROGRAM_RESUME` | `paused` true, mode AUTO or MDI, and for combined toolbar `resume_inhibit` false | Trajectory resumes and interpreter restores `interpResumeState` | Combined toolbar returns to Pause; manual controls remain disabled until interpreter IDLE |
|
||||
| `PROGRAM_ABORT` | AXIS exposes Stop while machine ON and interpreter non-IDLE; the task abort command itself is immediate | Interpreter aborts, TP queue is cleared, current taskfile/path remains selected, and the open task plan is closed | Stop periodic run polling; direct Run is enabled again when the task is idle and reopens the same taskfile from line 0. Reload is not a prerequisite. |
|
||||
| `JOG_START` | Machine on, idle/manual gate, homed | One incremental segment or repeated continuous TP segments are queued | While held, another jog direction is not started; release/cancel must issue `JOG_STOP` |
|
||||
| `JOG_START` | `manual_ok`, Manual tab visible and a valid selected joint/axis. Homing selects coordinate TELEOP versus joint FREE behavior; it is not an unconditional GUI prerequisite. | One incremental command or one continuous command is sent | Continuous stays active until release/cancel sends `JOG_STOP`; incremental has no stop edge |
|
||||
| `JOG_STOP` | An active jog gesture exists | Active jog is aborted/stopped; TP remains runnable | Allows a subsequent jog, MDI or source-gated manual command |
|
||||
| `TOUCH_OFF` | Machine on, homed, idle/manual gate and valid dialog value | MDI `G10 L20` updates the selected coordinate system, then the saved mode is restored | Position/DRO and offsets refresh; program run state is unchanged |
|
||||
| `SET_MAX_VELOCITY` | Machine powered and the override gate permits the update | Source TP velocity limit is changed | Motion duration/velocity changes; jog and feed overrides remain independent |
|
||||
| `TOUCH_OFF` | Source widget/handler formula plus valid value; task MDI homing enforcement applies unless configured off | MDI `G10 L20` updates the selected coordinate system, reloads preview, then restores saved task/motion mode | Position/DRO/offsets refresh; program execution state remains idle |
|
||||
| `SET_MAX_VELOCITY` | No native machine-state UI gate; numeric value follows source unit conversion/range | Source TP maximum velocity changes | Motion duration/velocity changes; jog/feed/rapid controls remain independent |
|
||||
| Rapid Override control | Not available in the selected WASM TP | No state change | Rapid Override remains disabled; Max Velocity must not be used as a substitute |
|
||||
| Spindle/Coolant | Visible manual controls require machine ON and interpreter IDLE; spindle also requires MANUAL mode | Canonical device IO changes only after Worker verification | Pressed/checked states update from device IO; spindle speed +/- additionally requires a running spindle, matching `axis.tcl update_state` |
|
||||
| Spindle/Coolant | Native manual widgets require ON+IDLE; spindle direction/brake handlers additionally use `manual_ok` and ensure MANUAL where source does; coolant checkbox handlers do not switch mode | Canonical device IO changes only after Worker verification | Direction/checked states update from canonical status; spindle speed +/- also requires nonzero source direction |
|
||||
| Feed/Spindle override | No native machine-state UI gate; values follow INI ranges | Send `c.feedrate`/`c.spindleoverride` equivalents | Canonical override changes without inventing an ON-only restriction |
|
||||
|
||||
### Dependency Flow
|
||||
|
||||
@@ -270,18 +396,19 @@ ESTOP ──release──> ESTOP_RESET ──POWER ON──> ON
|
||||
└──PROGRAM LOAD──> loaded taskfile (idle only)
|
||||
```
|
||||
|
||||
Any E-stop or power-off edge invalidates the downstream branch immediately.
|
||||
The UI must not leave a stale enabled button visible while it waits for the
|
||||
next canonical snapshot; the Worker gate remains the final authority even if a
|
||||
click races a state transition.
|
||||
Any E-stop or power-off edge invalidates active motion immediately. It does not
|
||||
delete the selected taskfile, static preview or Live Plot, and only joints
|
||||
configured with volatile home are unhomed by the native source. The UI must not
|
||||
leave stale enabled controls while waiting for the next canonical snapshot;
|
||||
the Worker gate remains final authority if a click races a status transition.
|
||||
|
||||
## Required Transactions
|
||||
|
||||
### Startup program selection
|
||||
|
||||
```text
|
||||
read selected INI
|
||||
-> resolve [DISPLAY] OPEN_FILE
|
||||
native priority: argv[0] -> AXIS_OPEN_FILE -> [DISPLAY] OPEN_FILE
|
||||
browser applicable priority: selected INI [DISPLAY] OPEN_FILE
|
||||
-> keep preview/program controls in loading state
|
||||
-> LOAD_WORKSPACE
|
||||
-> exactly one PROGRAM_LOAD for the configured OPEN_FILE
|
||||
@@ -297,40 +424,45 @@ save. No default-preview-then-cached-preview transition is permitted.
|
||||
|
||||
```text
|
||||
poll
|
||||
-> reject if AUTO is running/paused
|
||||
-> native Open/Reload gate: interpreter IDLE
|
||||
-> Web safety adapter also requires TP/MDI queue empty and no active parse
|
||||
-> save task mode
|
||||
-> ensure MANUAL
|
||||
-> clear previous preview and pending TP/interpreter edges
|
||||
-> optional source FILTER; on failure report and stop
|
||||
-> restore saved task mode before PLAN_OPEN-equivalent parsing
|
||||
-> capture current canonical TP pose
|
||||
-> set first line / PROGRAM_LOAD
|
||||
-> task_plan_synch equivalent: initialize the new interpreter from that TP pose
|
||||
-> subroutine load + preview from the same synchronized pose
|
||||
-> set first line 0 and clear previous highlight
|
||||
-> task_plan_synch + wait_complete
|
||||
-> program_open / PROGRAM_LOAD
|
||||
-> replace editor text and AxisCanon/static preview owner
|
||||
-> construct preview init codes from canonical status and parse
|
||||
-> reapply selected tab mode after the UI refresh
|
||||
-> publish one canonical replacement snapshot
|
||||
```
|
||||
|
||||
The replacement is rejected while the TP or an MDI move still has a queued or
|
||||
active segment. Loading program B after program A has moved the machine must
|
||||
never reset the interpreter to the origin. For example, if A ends at `X10`, a
|
||||
new B program beginning with `G91 G1 X5` previews and executes from `X10` to
|
||||
`X15`, not from `X0` to `X5`.
|
||||
active segment by the Web safety adapter. Native `open_file_guts` builds
|
||||
preview initialization from polled machine position, units, tool, modal G/M
|
||||
codes and tool offsets. Therefore loading B after A moved the machine must not
|
||||
silently initialize relative preview at the origin. A failed filter does not
|
||||
open a new taskfile. A G-code preview parse error is reported for the newly
|
||||
selected file; native AXIS does not promise rollback to the old static preview.
|
||||
|
||||
### E-stop recovery and startup
|
||||
|
||||
```text
|
||||
ESTOP(active=true)
|
||||
-> abort interpreter and TP
|
||||
-> task ESTOP, IO estop=1, ready=0
|
||||
-> emcMotionAbort + spindle/task/IO abort + trajectory disable
|
||||
-> volatile-home joints may unhome; task-plan synch
|
||||
-> observed task_state ESTOP
|
||||
ESTOP(active=false)
|
||||
-> IO estop=0, task STOPPED (ESTOP_RESET)
|
||||
-> send STATE_ESTOP_RESET; abort/synch; observed task_state ESTOP_RESET
|
||||
POWER(active=true)
|
||||
-> IO ready=1, task READY/ON
|
||||
-> valid from ESTOP_RESET; trajectory enable; observed task_state ON
|
||||
HOME(all=true)
|
||||
-> MANUAL mode, all joints homed
|
||||
-> manual_ok -> MANUAL -> joint mode -> c.home(-1) -> wait
|
||||
PROGRAM_RUN
|
||||
-> if the previous plan is completed/aborted: reopen current taskfile at line 0
|
||||
-> AUTO mode, RUNNING, periodic SIM_STEP until completion
|
||||
-> AUTO mode, interpreter READING; browser scheduler drives WASM samples
|
||||
```
|
||||
|
||||
### Run after completion or Stop
|
||||
@@ -369,10 +501,11 @@ auditable without changing the UI behavior.
|
||||
### Continuous jog
|
||||
|
||||
AXIS binds Button-1 to continuous jog and ButtonRelease to `jog_stop`.
|
||||
The Web equivalent keeps a single active `{axis,direction}` gesture, issues
|
||||
one source-TP jog segment per 50 ms sample using the canonical jog velocity,
|
||||
advances one servo sample, and sends `JOG_STOP` exactly once on release,
|
||||
cancel, leave or E-stop.
|
||||
The source sends one `JOG_CONTINUOUS` command and motion continues until a
|
||||
deferred `JOG_STOP`; it does not submit a fresh user command every GUI sample.
|
||||
The Web equivalent keeps one active `{axis,direction}` gesture, sends one
|
||||
`JOG_START`, advances its WASM servo simulation internally and sends
|
||||
`JOG_STOP` exactly once on release, cancel, leave, focus loss or E-stop.
|
||||
|
||||
### Toolpath display lifecycle
|
||||
|
||||
@@ -381,37 +514,36 @@ clear condition:
|
||||
|
||||
| Layer | Source owner | Visible/retained | Cleared or replaced |
|
||||
| --- | --- | --- | --- |
|
||||
| Static program preview | `open_file_guts` creates `AxisCanon`; Gremlin renders the parsed canon | Remains visible during Run, Pause, Resume, Stop and normal completion | A new `PROGRAM_LOAD` hides the old preview while parsing, then replaces it atomically with the newly parsed program. A failed replacement must not relabel the old path as the new program. |
|
||||
| Machining Live Plot | `LivePlotter`/`linuxcnc.positionlogger`; `show_live_plot` controls visibility | Accumulates during motion. Pause freezes and retains it. Resume continues the same trace. Stop and normal completion retain the accumulated trace. Hiding the Live layer changes visibility only and does not delete data. | AXIS `clear_live_plot()` explicitly calls `logger.clear()`. The Web panel additionally starts a documented new machining epoch for an accepted `PROGRAM_RUN`, `PROGRAM_RESTART`, or `PROGRAM_LOAD`, as required for this panel: the previous machining trace is cleared without changing the static preview or any task/TP state. |
|
||||
| Static program preview | `open_file_guts` assigns a new `AxisCanon`; Gremlin renders that canon | Remains visible during Run, Pause, Resume, Stop and normal completion | Open/Reload replaces the previous canon with the newly selected program's canon and parses into it. A preview error is reported for the new file; native AXIS does not roll back to the old canon. Clear Live Plot does not affect it. |
|
||||
| Machining Live Plot | `LivePlotter` owns `linuxcnc.positionlogger`; `show_live_plot` controls visibility | Accumulates independently of the selected static program. Pause freezes and retains it; Resume continues; Stop and normal completion retain it. Opening, reloading, running or rerunning a program also retains the existing trace. Hiding changes visibility only. | Only `clear_live_plot()` calls `LivePlotter.clear()`, whose `clear()` calls `positionlogger.clear()`. No call exists in `open_file_guts`, `reload_file`, `task_run`, `task_step`, `task_pause`, `task_resume` or `task_stop`. |
|
||||
|
||||
The Worker publishes a monotonic `visual.live_path_epoch`. React may clear the
|
||||
machining Live Plot only when this value changes. Array identity, a full versus
|
||||
delta snapshot, Pause, Resume, Stop, task mode, queue depth and completion are
|
||||
not clear signals.
|
||||
not clear signals. To match the source, the epoch changes only for the explicit
|
||||
`VISUAL_CLEAR` adapter (or restoration of a previously persisted epoch); it
|
||||
must not change on a program lifecycle command.
|
||||
|
||||
```text
|
||||
PROGRAM_LOAD accepted -> increment live_path_epoch -> clear old live trace
|
||||
-> hide old static preview while parsing
|
||||
-> publish new static preview
|
||||
|
||||
PROGRAM_RUN accepted -> increment live_path_epoch -> begin a new live trace
|
||||
PROGRAM_LOAD accepted -> live epoch unchanged -> replace static preview only
|
||||
PROGRAM_RUN accepted -> live epoch unchanged -> continue accumulating live trace
|
||||
PROGRAM_PAUSE -> epoch unchanged -> retain/freeze live trace
|
||||
PROGRAM_RESUME -> epoch unchanged -> continue live trace
|
||||
PROGRAM_ABORT/STOP -> epoch unchanged -> retain live trace
|
||||
program completed -> epoch unchanged -> retain live trace
|
||||
VISUAL_CLEAR -> increment live_path_epoch -> clear live trace only
|
||||
PROGRAM_RESTART -> increment live_path_epoch -> clear live trace
|
||||
PROGRAM_RESTART -> epoch unchanged -> source has no visible Restart action
|
||||
```
|
||||
|
||||
If Clear Plot is used while motion is still active, history before the clear
|
||||
edge is removed and `positionlogger` semantics immediately begin accumulating
|
||||
the subsequent motion in the new epoch. At IDLE, the cleared trace stays empty.
|
||||
|
||||
The additional Web epoch at a new Run/load boundary is a presentation
|
||||
lifecycle rule requested for this panel. It does not pretend that AXIS calls
|
||||
`positionlogger.clear()` from `task_run` or `open_file_guts`: the native source
|
||||
does not. Pause/completion retention and explicit Clear Plot behavior remain
|
||||
direct source matches.
|
||||
This source-exact rule supersedes the earlier Web extension that cleared the
|
||||
trace on Run, Restart or Load. That extension contradicted native AXIS and is no
|
||||
longer part of this contract. A product variant that wants per-job traces must
|
||||
provide a separately named export/archive action; it may not change the AXIS
|
||||
Clear Live Plot lifecycle while claiming source parity.
|
||||
|
||||
## Implementation Invariants
|
||||
|
||||
@@ -431,7 +563,14 @@ direct source matches.
|
||||
7. Executable program source/path is never part of UI preference persistence;
|
||||
refresh performs one INI-authorized startup load.
|
||||
8. Live Plot clearing is controlled only by the Worker `live_path_epoch`;
|
||||
React object/array replacement is never a lifecycle signal.
|
||||
React object/array replacement is never a lifecycle signal, and only the
|
||||
explicit `VISUAL_CLEAR` source adapter advances the epoch.
|
||||
9. Every contract row carries or inherits one of `SOURCE_EXACT`,
|
||||
`SOURCE_ADAPTER`, `SOURCE_BLOCKED` or `WEB_EXTENSION`; extensions and blocked
|
||||
capabilities are never counted as source parity.
|
||||
10. Exact `axis.tcl::update_state` formulas remain the reference UI gates.
|
||||
A browser asynchronous-load exclusion must be documented separately; no
|
||||
other stronger React gate may be attributed to AXIS.
|
||||
|
||||
## Change Procedure
|
||||
|
||||
@@ -451,10 +590,12 @@ rendered actionable element without a documented ID or with a duplicate ID.
|
||||
When LinuxCNC source behavior or the selected machine configuration changes:
|
||||
|
||||
1. Update the source baseline and the affected matrix row/transaction above.
|
||||
2. Update the Worker gate/authority path.
|
||||
3. Update the React handler only after the Worker contract is verified.
|
||||
4. Add normal, blocked and recovery assertions to the focused test.
|
||||
5. Run the panel browser test, build the React bundle, and publish a new
|
||||
2. Recompute the source-lock hashes and review every changed source symbol.
|
||||
3. Update the Worker gate/authority path.
|
||||
4. Update the React handler only after the Worker contract is verified.
|
||||
5. Add normal, blocked and recovery assertions to the focused test.
|
||||
6. Regenerate the relationship graph from its DOT source.
|
||||
7. Run the panel browser test, build the React bundle, and publish a new
|
||||
release directory without replacing the previous rollback target.
|
||||
|
||||
The document deliberately records ABI blockers and source boundaries. A
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.3 MiB After Width: | Height: | Size: 2.4 MiB |
Reference in New Issue
Block a user