# LinuxCNC AXIS 完全对标规范与执行计划 **文档状态**:执行基线 v1.0(源程序已冻结;实现和验收按任务逐项关闭) **适用版本**:LinuxCNC `2.10.0~pre0` 239dcf4284762ad7e9c65d390bc5524d855c2f8e **项目上下文**:`linuxcnc-2.10.0-pre0-wasm-m1-py-c1` **主入口**:[`web/react`](../web/react) **原始 AXIS 入口**:[`linuxcnc/share/axis/tcl/axis.tcl`](../linuxcnc/share/axis/tcl/axis.tcl) **配套通信契约**:[前端与通信详细设计](linuxcnc-web-wasm-frontend-communication-design.md) **配套案例契约**:[案例对标计划](linuxcnc-web-wasm-case-parity-plan.md) 本文件是“Web 主界面完全对标 LinuxCNC 原始 AXIS”的唯一执行规范。它把原始 AXIS 的功能、界面结构、状态门控、快捷键、图标、绘图和外部集成拆成可追溯任务;没有来源、命令序列、状态结果和验收证据的功能,不得标记为完成。 ## 1. 目标、定义和边界 ### 1.1 对标目标 对标不是把网页做成相似的深色控制台,而是对同一配置、同一程序、同一输入序列满足以下四类等价: 1. **结构等价**:菜单、工具栏顺序、Notebook、程序区、DRO、状态栏、控制件和图标的角色与布局对应 AXIS。 2. **操作等价**:同一用户动作发出同一 LinuxCNC 语义命令,按相同状态条件启用、禁用、暂停、恢复或拒绝。 3. **状态等价**:任务态、解释器态、模式、轴/关节选择、位置显示、倍率、主轴、工具、冷却、报警和恢复结果来自同一权威状态,事件顺序和当前行一致。 4. **结果等价**:native AXIS oracle 与 WASM/Worker 的 command trace、tick、快照、事件、错误和 checkpoint 哈希一致;允许的浮点误差必须在功能条目中明确,不能事后放宽。 ### 1.2 规范性术语 | 词 | 含义 | |---|---| | MUST | 必须满足,否则该条目失败 | | MUST NOT | 严禁发生,否则停止验收 | | SHOULD | 默认要求;若不满足必须记录理由和影响 | | source oracle | 锁定 LinuxCNC 源码、原始 AXIS 运行或其确定性输出 | | Web-equivalent | 浏览器中实现相同工作流和状态语义的等价控件,不复制桌面窗口进程 | | host boundary | 原始程序依赖宿主进程、动态库、真实设备或外部窗口的边界;必须显式显示为 blocked/excluded | | verified | 代码、测试、native/WASM/Worker 证据、视觉证据和自哈希报告均通过 | | blocked | 输入、官方 oracle、浏览器能力或宿主边界不足;保留失败样本,不得伪造 verified | ### 1.3 明确边界 - LinuxCNC 原始 AXIS 是 Tk 前端;Web 采用 React/TypeScript/Worker/Three.js,实现的是 **Web-equivalent**,不是复制 Tk 窗口或在浏览器启动桌面进程。 - `exec classicladder`、`halshow`、`halmeter`、`halscope`、`linuxcnctop`、`debuglevel`、外部编辑器、真实硬件和原始 socket 不得伪装为浏览器已支持;用 Web 面板或 `HOST_BOUNDARY` 诊断替代。 - WASM、HAL、IO、Python、OPFS 和快照的权威状态在 Dedicated Worker;React 只能通过协议读写,不得访问 WASM 指针或直接写 OPFS。 - 原始图标必须使用锁定源码中的字节;重新绘制、emoji、通用 icon 库或不同来源的同名图标不算对标。 - 所有视觉结论必须在固定视口、固定字体/缩放和固定资源哈希下产生;动态 canvas 区域单独做像素/非空检查,不得用“截图看起来差不多”替代 DOM 和行为检查。 ## 2. 锁定的 AXIS 源程序和证据入口 ### 2.1 源文件分工 | 领域 | 原始来源 | 对标内容 | |---|---|---| | 主窗口、菜单、工具栏、Notebook、控件门控 | [`share/axis/tcl/axis.tcl`](../linuxcnc/share/axis/tcl/axis.tcl) | 全部主界面结构、动作、启用条件、快捷键和默认变量 | | 图标加载、动态帮助、控件辅助函数 | [`share/axis/tcl/support.tcl`](../linuxcnc/share/axis/tcl/support.tcl)、[`accel.tcl`](../linuxcnc/share/axis/tcl/accel.tcl) | 资源解析、tooltip、菜单/控件 accelerator | | 自定义下拉、滚动条、对话框 | [`share/axis/tcl/combobox.tcl`](../linuxcnc/share/axis/tcl/combobox.tcl)、[`sb.tcl`](../linuxcnc/share/axis/tcl/sb.tcl)、[`dialog.tcl`](../linuxcnc/share/axis/tcl/dialog.tcl) | Jog increment、MDI history、文件和错误对话框的交互语义 | | AXIS 设计说明 | [`src/emc/usr_intf/axis/README`](../linuxcnc/src/emc/usr_intf/axis/README) | AXIS 的定位是 file preview + live plot;自解释控件、tooltip 和 Quick Reference | | 3D/预览窗口 | [`lib/python/gremlin.py`](../linuxcnc/lib/python/gremlin.py)、[`gremlin_view.py`](../linuxcnc/lib/python/gremlin_view.py) | 视角、缩放、拖动/旋转、预览加载、live plot、当前行和绘图刷新 | | G-code 绘图和坐标叠加 | [`lib/python/rs274/glcanon.py`](../linuxcnc/lib/python/rs274/glcanon.py) | rapid、path、dwell、tool、origin、offset、extents、grid、limits、velocity、DTG | | 配置声明和 GUI 家族 | [`configs/sim/axis`](../linuxcnc/configs/sim/axis) | DISPLAY=axis、PYVCP/GLADEVCP/NGCGUI/VisMach/外部脚本及资源闭包 | | 原始 bitmap | [`share/axis/images`](../linuxcnc/share/axis/images) | AXIS logo、toolbar、spindle、标准报警图标、banner | 本文中的 `axis.tcl:N-M` 是 [`linuxcnc/share/axis/tcl/axis.tcl`](../linuxcnc/share/axis/tcl/axis.tcl) 的行号简写;`gremlin.py` 和 `glcanon.py` 同理分别指上表中的完整路径。 ### 2.2 源哈希和变更规则 基线文件的初始 SHA-256 记录如下;每次源更新必须重新生成 manifest 和本文件引用,不得沿用旧报告: ```text share/axis/tcl/axis.tcl c9f0b4dc686717b37565f85fb0ab8cc8ded9cfa0028cc0aaaccdbcf808c4c524 lib/python/gremlin.py 7559a52300de92ed156fe22267c8fbca975338321cf3afada141360a244756a3 lib/python/rs274/glcanon.py 0dfb20f1fdc05289894f3aa638357d98e1063fbd53329c723c777399ec7b33b7 src/emc/usr_intf/axis/README 2fe357ba28bb0aa66565f85fb0ab8cc8ded9cfa0028cc0aaaccdbcf808c4c524 ``` 若报告发现文件内容与上述哈希不一致,先修正文档/manifest,再开始实现。源码树中由运行时生成的 `tool.tbl`、`sim.var`、`linuxcnc.var` 必须标明是 `source-owned` 还是 `runtime-generated-fixture`,不可混用。 ## 3. AXIS 原始功能完整清单 功能 ID 是后续任务、协议、测试和验收报告的稳定主键。每个 ID 至少绑定一条源码路径、一个 Web 控件、一个命令/查询、一个状态字段和一份 evidence。 ### 3.1 应用壳、菜单和窗口 | ID | 原始功能 | 原始实现/行 | Web 对标要求 | |---|---|---|---| | AXIS-SHELL-01 | 窗口标题 `AXIS on `,无文件时显示 `(no file)`,有文件时显示文件名 | `axis.tcl:1755-1765` | 根据 Worker 的 machine/taskfile 快照更新标题;标题更新不能改变仿真状态 | | AXIS-SHELL-02 | 顶级菜单 File、Machine、View、Help | `axis.tcl:33-53,468-482` | 顺序、命名、子菜单、快捷键和 enabled 状态一致;菜单项必须有可测试的 `data-axis-command` | | AXIS-SHELL-03 | 最小窗口尺寸随 pane 请求尺寸更新 | `axis.tcl:2234-2240` | CSS 使用稳定最小尺寸和滚动策略;窄屏切换布局,不能让高风险按钮被裁掉 | | AXIS-SHELL-04 | About AXIS、Quick Reference 对话框 | `axis.tcl:453-464,1549-1632` | Web modal 保留版本、许可证、源码链接、快捷键和关闭/焦点语义;外部链接另标记 host/network boundary | | AXIS-SHELL-05 | 动态帮助 tooltip | `axis.tcl:2250-2270`、`accel.tcl:150-185` | 所有图标按钮的 tooltip 文案、快捷键和 disabled 原因可通过 DOM/辅助技术读取 | ### 3.2 File 菜单和工程入口 原始菜单定义位于 `axis.tcl:55-102`。Web 实现必须保留以下条目和顺序: | ID | 菜单项 | 语义 | |---|---|---| | AXIS-FILE-01 | Open… (`O`) | 选择 G-code,解析、预览并进入 `PROGRAM_LOAD`; 不允许 basename 替换 | | AXIS-FILE-02 | Recent Files | 最近文件列表、序号快捷键、清空列表;路径/哈希来自 Worker 工程存储 | | AXIS-FILE-03 | Edit… | 以配置声明的 editor 或 Web G-code editor 打开;宿主 editor 必须显示 `HOST_BOUNDARY` | | AXIS-FILE-04 | Reload (`Ctrl-R`) | 仅在解释器 idle 且有 taskfile 时启用;重新读取精确资源 | | AXIS-FILE-05 | Save G-code as… (`Ctrl-S`) | 保存当前内容/版本,写 journal,返回文件哈希 | | AXIS-FILE-06 | Properties… | 显示程序路径、大小、行数、解析诊断、单位和 source hash | | AXIS-FILE-07 | Edit tool data… | Web tool table editor;原始 `tooledit` 外部窗口标为 boundary | | AXIS-FILE-08 | Reload tool data | 重新加载工具表并显示 table hash、当前刀、prepared/pocket | | AXIS-FILE-09 | Ladder Editor… | Web ClassicLadder 面板;无法运行宿主 editor 时不得静默忽略 | | AXIS-FILE-10 | Quit | 浏览器不能关闭宿主窗口;显示“关闭标签页”提示并记录 `WEB_EQUIVALENT` | ### 3.3 Machine 菜单和任务控制 原始定义位于 `axis.tcl:105-264`。下列条目是 P0/P1,不得只保留 Run/Pause: | ID | 功能 | 关键语义 | |---|---|---| | AXIS-MACHINE-01 | Toggle Emergency Stop (`F1`) | `ESTOP` 状态机;急停时禁止运动/IO,界面进入 pressed/fault,恢复必须有独立 `IO_RECOVER`/reset 结果 | | AXIS-MACHINE-02 | Toggle Machine Power (`F2`) | task state OFF/ON;按钮 relief 与状态一致,不能把 recover 当作已上电 | | AXIS-MACHINE-03 | Run program (`R`) | 仅 task ON、程序有效、解释器 idle 时启用;返回当前行、interp state、tick | | AXIS-MACHINE-04 | Run from selected line | 以选中行建立确定性 seek/预读语义;没有选中行必须 disabled | | AXIS-MACHINE-05 | Step (`T`) | 只执行下一行/下一 canonical 单元;记录 line before/after 和状态 hash | | AXIS-MACHINE-06 | Pause (`P`) / Resume (`S`) | 只在对应 interp state 启用;pause 图标切换 `tool_pause`/`resume_inhibit` | | AXIS-MACHINE-07 | Stop (`Esc`) | 中止程序而不是销毁 session;queue、tool、spindle、IO 和恢复点结果必须明确 | | AXIS-MACHINE-08 | Stop at M1 | `optional_stop` checkbutton/toolbar relief 与 M1 行为一致 | | AXIS-MACHINE-09 | Skip lines with `/` | `block_delete` checkbutton/toolbar relief 与程序过滤语义一致 | | AXIS-MACHINE-10 | MDI history clear/copy/paste | `Ctrl-M`、`Ctrl-H`、`Ctrl-Shift-H`;历史只在 Worker committed state 中更新 | | AXIS-MACHINE-11 | Calibration | 原始 `emccalib.tcl` 是外部窗口;Web 提供能力诊断或 boundary,不得模拟完成 | | AXIS-MACHINE-12 | Show HAL Configuration / HAL Meter / HAL Scope | 分别映射 HAL graph、HAL sample/plot、scope;原始外部窗口路径保留诊断 | | AXIS-MACHINE-13 | Show LinuxCNC Status / Set Debug Level | 映射状态时间线、日志和 debug level 白名单;未经授权的 level 必须拒绝 | | AXIS-MACHINE-14 | Homing / Unhoming | 动态子菜单按轴/关节生成;顺序、homed、limit、门控和错误一致 | | AXIS-MACHINE-15 | Zero coordinate system | P1…P9/G54…G59.3/G92 全部入口;每次写入显示坐标系、旧值、新值和 hash | | AXIS-MACHINE-16 | Tool touch off to workpiece/fixture | `tto_g11` 两种模式;选择影响 G10/G11 语义并在快照中可见 | ### 3.4 View 菜单、DRO 和坐标显示 原始定义位于 `axis.tcl:266-449`。View 菜单必须拆成可验证状态,不得只做文字菜单: | ID | 功能 | 状态字段/输出 | |---|---|---| | AXIS-VIEW-01 | Top / Rotated Top / Side / Front / Perspective | `view_type`、camera pose、视角图标 relief;对应 `set_view_z/z2/x/y/p` | | AXIS-VIEW-02 | Display Inches / Display MM | `metric`;DRO、速度、倍率单位同步;切换不改机床内部单位 | | AXIS-VIEW-03 | Show program | program path overlay 开关 | | AXIS-VIEW-04 | Show program rapids | rapid segments 是否显示 | | AXIS-VIEW-05 | Alpha-blend program | program overlay alpha | | AXIS-VIEW-06 | Show live plot | 已运行轨迹与预览轨迹分层;clear 不得删除程序预览 | | AXIS-VIEW-07 | Show tool | tool cone/model、tool position、orientation | | AXIS-VIEW-08 | Show extents | program/machine extents bounding box | | AXIS-VIEW-09 | Grid Off/Custom | grid size、origin、spacing 和自定义参数 | | AXIS-VIEW-10 | Show offsets | G5x/G92/tool offset 可视化和数值 | | AXIS-VIEW-11 | Show machine limits | axis/joint limits overlay 和 limit fault | | AXIS-VIEW-12 | Show velocity | velocity vector/数值;来源为 snapshot,不使用墙钟推算 | | AXIS-VIEW-13 | Show distance to go | DTG 与 commanded/actual、machine/relative 模式联动 | | AXIS-VIEW-14 | Large coordinate font | DRO 字号开关,布局必须稳定 | | AXIS-VIEW-15 | Clear live plot (`Ctrl-K`) | 仅清 live layer,返回新 plot revision | | AXIS-VIEW-16 | Show PyVCP panel (`Ctrl-E`) | 配置声明 `PYVCP` 时显示 Web VCP;缺少 host plugin 时显示 boundary | | AXIS-VIEW-17 | Show commanded/actual position | `display_type`,DRO 与状态栏同源 | | AXIS-VIEW-18 | Show machine/relative position | `coord_type`,DRO 与触碰/坐标系同源 | | AXIS-VIEW-19 | Joint mode / World mode | `teleop_mode`;非平凡 kinematics 未全 homed 时禁止切换到 world | ### 3.5 AXIS 工具栏和图标对照表 原始工具栏从 `axis.tcl:484-787` 创建并按 `671-787` 顺序 pack。图标文件必须来自 [`linuxcnc/share/axis/images`](../linuxcnc/share/axis/images): | 序号 | 原始 widget | 图标 | 原始动作 | Web 对标 | |---:|---|---|---|---| | 1 | `machine_estop` | `tool_estop.gif` | `estop_clicked` | icon-only button,tooltip `Toggle Emergency Stop [F1]` | | 2 | `machine_power` | `tool_power.gif` | `onoff_clicked` | task power 状态,初始 disabled/relief 与 oracle 一致 | | 3 | `file_open` | `tool_open.gif` | `open_file` | 精确资源选择 + `PROGRAM_LOAD` | | 4 | `reload` | `tool_reload.gif` | `reload_file` | reload gate | | 5 | `program_run` | `tool_run.gif` | `task_run` | run gate | | 6 | `program_step` | `tool_step.gif` | `task_step` | step gate | | 7 | `program_pause` | `tool_pause.gif` / `resume_inhibit.gif` | `task_pauseresume` | pause/resume 图标切换 | | 8 | `program_stop` | `tool_stop.gif` | `task_stop` | stop/abort gate | | 9 | `program_blockdelete` | `tool_blockdelete.gif` | `toggle_block_delete` | pressed state + 程序语义 | | 10 | `program_optpause` | `tool_optpause.gif` | `toggle_optional_stop` | pressed state + M1 语义 | | 11 | `view_zoomin` | `tool_zoomin.gif` | `zoomin` | camera scale | | 12 | `view_zoomout` | `tool_zoomout.gif` | `zoomout` | camera scale | | 13 | `view_z` | `tool_axis_z.gif` | `set_view_z` | top camera | | 14 | `view_z2` | `tool_axis_z2.gif` | `set_view_z2` | rotated top camera | | 15 | `view_x` | `tool_axis_x.gif` | `set_view_x` | side camera | | 16 | `view_y` | `tool_axis_y.gif` | `set_view_y` | front camera | | 17 | `view_y2` | `tool_axis_y2.png` | `set_view_y2` | inverted front camera | | 18 | `view_p` | `tool_axis_p.gif` | `set_view_p` | perspective camera | | 19 | `rotate` | `tool_rotate.gif` | toggle drag/rotate | pressed state and pointer gesture | | 20 | `clear_plot` | `tool_clear.gif` | `clear_live_plot` | live layer only | 验收必须检查:文件名、字节 hash、实际加载 URL、`alt`/tooltip、按钮顺序、disabled/pressed relief 和点击后的命令。QtVCP 同名镜像只能用于历史兼容,不得作为 AXIS source oracle。 ### 3.6 Manual Control Notebook 原始布局在 `axis.tcl:803-1213`,默认页为 `Manual Control [F3]`: | ID | 控件 | 必须保留的行为 | |---|---|---| | AXIS-MANUAL-01 | 轴选择 X/Y/Z/A/B/C/U/V/W | 3×3 radio;`axis_activated`;非平凡运动学切换为动态 joint numbers | | AXIS-MANUAL-02 | Jog `-`/`+` | 增量模式 click 一次;Continuous 模式 pointer/key down 开始、release/leave 必须 `JOG_STOP` | | AXIS-MANUAL-03 | Jog increment | `Continuous`, `0.1000`, `0.0100`, `0.0010`, `0.0001`;选择变化进入命令 payload | | AXIS-MANUAL-04 | Home Axis | 当前轴/关节 home;Home 键快捷键;结果更新 homed/limit/position | | AXIS-MANUAL-05 | Touch Off | G54 当前轴;End 快捷键;保存坐标系结果 | | AXIS-MANUAL-06 | Tool Touch Off | Ctrl-End;只在有加载工具且模式允许时启用 | | AXIS-MANUAL-07 | Override Limits | 只在 `on_any_limit` 时启用;临时越限必须有 fault/recover trace | | AXIS-MANUAL-08 | Spindle CCW/Stop/CW | `spindledir` radio、16×16 原始图标、F10/F9;Stop 文案必须可读 | | AXIS-MANUAL-09 | Spindle -/+ | 按下加速/减速、释放进入 constant;F11/F12;主轴未运行时 disabled | | AXIS-MANUAL-10 | Brake | B/Shift-B;状态和互锁可见 | | AXIS-MANUAL-11 | Mist/Flood | F7/F8;冷却状态、故障和恢复来自 device IO | | AXIS-MANUAL-12 | Jog Speed/Max Velocity | 来源为 `jog_slider_val`/`maxvel_slider_val`,单位随 metric,显示值和内部速度转换一致 | ### 3.7 MDI Notebook 原始布局在 `axis.tcl:1215-1294`:History listbox、MDI Command entry、Go 按钮。Web 必须支持: - 历史最多/最少行为与 Worker 的 `mdi_history` 一致,初始有空元素,不把草稿历史当已执行。 - Enter 与 Go 相同,发送 `MDI_EXECUTE`,返回 command result、当前行、模式和错误行。 - `queued_mdi_commands >= max_queued_mdi_commands` 时整个 MDI group disabled(`axis.tcl:1851-1855`)。 - `Ctrl-M` 清历史,`Ctrl-H` history→clipboard,`Ctrl-Shift-H` clipboard→history;浏览器 clipboard 权限失败必须显式诊断。 ### 3.8 Preview、DRO、程序和状态栏 原始布局在 `axis.tcl:1296-1709`: | 区域 | 原始行为 | Web 必须实现 | |---|---|---| | Preview tab | Gremlin/GLCanon 预览、程序/rapid/live/tool/extents/offset/grid/limit/velocity overlays | Three.js/WebGL 只消费 Worker snapshot/trajectory;每层可独立开关,canvas 必须非空 | | DRO tab | 原始 AXIS DRO widget;显示 machine/relative、actual/commanded、DTG、单位、关节态 | 表格列和模式可切换;数值、单位、homed、limit、fault、tick/hash 同源 | | `.info.task_state` | ESTOP/OFF/ON,sunken relief | `task_state` 颜色/状态必须由快照驱动 | | `.info.tool` | 当前刀具/工具信息 | current/prepared/pocket/change state 和 tool table hash | | `.info.position` | Position + coordinate type + display type | `Machine/Relative` 与 `Actual/Commanded` 组合准确 | | G-code pane | 有滚动条、当前行/highlight、底部固定 pane | 编辑/选行/运行到选中行/错误定位;不能使用静态 `
` 冒充 |
| Active G-Codes | `gcodes` text,disabled、2 行起步 | modal codes、units、plane、feed/spindle/tool/coolant 同步 |
| Jog sliders | `jogspeed`、`ajogspeed`、`maxvel`,值通过 `setval/val2vel` 转换 | 显示值与内部单位、min/max、metric 切换、键盘增量一致 |
| Overrides | `spinoverride`、`feedoverride`、`rapidoverride`,0…120%、整数分辨率 | worker authoritative override;滑块 release/commit 和 pending/error 可见 |

### 3.9 状态门控、默认状态和快捷键

`axis.tcl:1715-1887` 是行为对标的核心,不得只按按钮标签实现。门控规则:

1. `ESTOP` 时 machine power、程序、jog、主轴、冷却等高风险动作禁用;estop relief 按下。
2. task 非 ON 时 manual group disabled;task ON 且 interpreter idle 时才 enable manual group。
3. 有 taskfile 且 idle 才能 reload、edit、properties、open、block-delete;有 taskfile 且 ON 才能 step。
4. interpreter reading/waiting 才能 Pause;paused 才能 Resume;非 idle 才能 Stop。
5. `on_any_limit` 才能启用 Override Limits;非自由运动学或 identity kinematics 且 idle 才能 Touch Off。
6. 有有效工具、task ON、idle、模式允许时才能 Tool Touch Off。
7. MDI queue 未满才启用 MDI group。
8. 非平凡 kinematics 的自由/joint 模式显示 joint numbers;没有全 homed 不能从 joint 切换到 world。

默认变量见 `axis.tcl:1941-1985`,至少包含 `rotate_mode`、`taskfile`、`task_state`、`task_mode`、`task_paused`、`optional_stop`、`block_delete`、`interp_pause`、`interp_state`、`running_line`、`highlight_line`、`coord_type`、`display_type`、`spindledir`、`motion_mode`、`kinematics_type`、`metric`、`queued_mdi_commands`。Web store 必须有等价字段或明确映射,不能删除门控原因。

快捷键基线:

| 键 | 功能 | 来源 |
|---|---|---|
| F1/F2 | 急停/电源 | `axis.tcl:105-113` |
| O/Ctrl-R/Ctrl-S | Open/Reload/Save | `axis.tcl:55-76` |
| R/T/P/S/Esc | Run/Step/Pause/Resume/Stop | `axis.tcl:117-144` |
| Ctrl-M/Ctrl-H/Ctrl-Shift-H | MDI history | `axis.tcl:158-169` |
| Ctrl-K/Ctrl-E | Clear live plot/Show PyVCP | `axis.tcl:378-387` |
| F3/F5 | Manual/MDI tab | `axis.tcl:820-825` |
| Home/End/Ctrl-End | Home/Touch Off/Tool Touch Off | `axis.tcl:2258-2260` |
| F7/F8/F9/F10/F11/F12 | Mist/Flood/Spindle/速度 | `axis.tcl:2250-2257` |
| X/Y/Z/A/4/5 | 轴激活 | `axis.tcl:2261-2266` |
| Ctrl-Tab | Manual/MDI 切换 | `axis.tcl:1989-1996` |

## 4. LinuxCNC 源功能到 Web 实现的映射

### 4.1 分层映射原则

| 原始层 | Web 层 | 强制规则 |
|---|---|---|
| Tk widget/variable | React component + domain store | 控件可以换实现,字段名、启用条件、事件顺序不能换 |
| AXIS command procedure | protocol command | 每个副作用动作有 `operation_id`、pending/ack/result/error、tick/hash |
| LinuxCNC status/NML | Worker snapshot/event | UI 不可读取指针、共享内存或宿主 NML |
| Gremlin/GLCanon | Three.js visual workflow | 只读 pose/joints/toolpath/stock/overlay;渲染失败不能改变仿真 |
| Tcl external exec | Web panel or host boundary | 不可静默成功;必须有 capability result 和 source path |
| Tk image | exact bitmap URL | 记录字节 hash,禁止同名替换 |
| `state`/`relief` | `disabled`/`aria-pressed`/visual state | 状态由 authoritative snapshot 派生,不能由点击乐观设置 |

### 4.2 推荐组件和协议字段

```text
AxisShell
  ├─ AxisMenuBar             File / Machine / View / Help
  ├─ AxisToolbar             exact source icons, order and tooltip
  ├─ AxisNotebook
  │   ├─ ManualControl       axis/joint, jog, home, touch-off, spindle, coolant
  │   └─ MDIControl          history, command, go, queue gate
  ├─ ViewNotebook
  │   ├─ Preview              Three.js/trajectory/overlays
  │   └─ DRO                  machine/relative × actual/commanded × DTG
  ├─ ProgramPane              source, line selection, current line, active G-codes
  ├─ OverridePane             feed/rapid/spindle/jog/max velocity
  └─ AxisInfoBar              task state, tool, position, alarm/recovery
```

最低命令集合:`PROGRAM_LOAD`, `PROGRAM_RUN`, `PROGRAM_SEEK`, `PROGRAM_STEP`, `PROGRAM_PAUSE`, `PROGRAM_RESUME`, `PROGRAM_ABORT`, `MDI_EXECUTE`, `JOG_START`, `JOG_STOP`, `HOME`, `SET_MODE`, `SET_OVERRIDE`, `SPINDLE_COMMAND`, `COOLANT_COMMAND`, `TOOL_PREPARE`, `TOOL_CHANGE`, `PROBE_CONFIG`, `ESTOP`, `IO_RECOVER`, `HAL_COMMAND`, `SNAPSHOT_REQUEST`, `CHECKPOINT`, `RECOVER`。新增命令必须先更新 protocol capability、source map、replay fixture 和本规范任务表。

## 5. 严格对标流程

每个 AXIS 功能 ID 都必须独立走完以下流程;不允许把多个功能合并成一张“整体通过”截图。

### R0:冻结基线

1. 读取 `context-lock.json`、`linuxcnc/VERSION` 和 source commit。
2. 计算源文件、图标、配置入口、HAL、TBL/VAR、程序和生成资源 hash。
3. 记录 OS、浏览器、DPR、viewport、字体、语言、单位和启动参数。
4. 若输入有未提交 runtime fixture,先分类 `source-owned`/`runtime-generated`/`user-approved-fixture`。

**退出条件**:source manifest、asset manifest、case manifest、运行环境 JSON 均 self-hashed;否则 STOP。

### R1:提取原始功能

1. 从 `axis.tcl` 的 menu/widget/proc/bind/state 定义生成 `axis-source-inventory.jsonl`。
2. 从 `support.tcl`、`accel.tcl`、`gremlin.py`、`glcanon.py` 提取依赖动作、tooltip、视觉层和状态字段。
3. 每个条目填写 `feature_id`, `source_path`, `source_lines`, `source_hash`, `ui_role`, `command`, `state_fields`, `external_boundary`。
4. 把源代码中实际未实现/历史 wishlist 与当前功能分开,不把 wishlist 当现状。

**退出条件**:功能 ID 覆盖菜单、工具栏、Notebook、DRO、程序、状态、快捷键、图形和外部集成;任何未归属文件进入 audit 缺口。

### R2:建立协议和状态契约

1. 为每个命令定义输入 schema、能力条件、幂等键、成功结果、错误码和恢复语义。
2. 为每个 UI 状态定义 authoritative snapshot 字段、派生选择器和 enabled predicate。
3. 固定 `pending → ack → result/error`;ACK 不得被渲染为 verified。
4. 录制最小 native trace:启动、加载、动作、step、快照、错误、恢复。

**退出条件**:同一操作可在 Worker replay 中重放;未定义的门控或错误不得进入 UI 实现。

### R3:实现结构和图标

1. 先实现 AXIS shell 和稳定布局,再接入动作;禁止用临时卡片替代原始区域。
2. 按原始 pack 顺序加载 20 个 toolbar 图标,记录每个文件 byte hash、尺寸和 URL。
3. 实现 File/Machine/View/Help 菜单和 Notebook;所有菜单 item 带稳定测试 ID。
4. 对 canonical 1440×900、1280×800、390×844 截图并做 DOM geometry 检查。

**退出条件**:结构 diff 只剩有记录的字体/平台边界;工具栏顺序和 icon hash 100% 一致。

### R4:实现控制和门控

1. 先实现 ESTOP/OFF/ON/idle/reading/waiting/paused/limit/not-homed 状态转换。
2. 再接 program/MDI/jog/home/touch-off/spindle/coolant/override。
3. 每个 pointer/key 事件测试按下、移动、离开、释放、重复触发和 Worker 重启。
4. 每个 disabled 状态测试“为什么 disabled”:UI 显示 source state、predicate 和 capability。

**退出条件**:状态矩阵的每一格都有 command trace 或明确 blocked 证据;没有基于本地 `useState` 的假成功。

### R5:实现预览、DRO 和编辑器

1. G-code load 后先产生解析/预览结果,再允许 run;程序预览、rapid、live plot、tool、offset、limits、grid 分层。
2. DRO 实现 machine/relative、actual/commanded、DTG、unit、joint/world、large font。
3. G-code editor 支持行号、当前行、高亮、选中行运行、错误列、滚动和程序 hash。
4. 3D canvas 检查非空像素、有限坐标、视角、缩放、旋转和 resize;绘图线程不得改仿真 tick。

**退出条件**:同一 native/WASM trace 的当前行、DRO、path layer、tool pose、状态 hash 相同。

### R6:案例和外部边界

1. `minimal_xyz.ini`:关闭 Cartesian P0 核心闭环。
2. `corexy_by_kins.ini` 与 `corexy_by_hal.ini`:分别验证 kinematics/HAL 路径。
3. lathe、9-axis、gantry、nontrivial kinematics、iocontrolv2、vismach、PYVCP/GLADEVCP/NGCGUI 代表案例按 family 扩展。
4. 每个 DISPLAY/插件声明都输出 Web capability、host boundary 和缺失资源;不能把外部 Python/Tk/动态 loader 当作浏览器已完成。

**退出条件**:每个案例有 exact resource graph、native startup、Worker startup、frontend mapping、差异和 self-hashed report。

### R7:视觉、交互和故障验收

1. DOM:区域、顺序、role、label、tooltip、快捷键、禁用/pressed、焦点顺序。
2. Screenshot:canonical viewport 的结构区域、工具栏顺序、icon byte/尺寸、颜色/边框、文字和间距。
3. Interaction:每个 command 的操作序列、pending/ack/result、错误和恢复。
4. Fault:ESTOP、limit、following error、invalid G-code、HAL blocked、tool busy、OPFS quota、Worker crash/restart。
5. Performance:首屏、Worker ready、snapshot latency、3D frame、stream backpressure、内存和长程序编辑器。

**退出条件**:报告包含失败截图/DOM/trace,而不是只有通过计数;任何 STOP 条件未关闭则 milestone 保持 blocked。

### R8:发布门禁

- `source_hash`, `asset_hash`, `case_hash`, `command_trace_hash`, `endpoint_hash`, `screenshot_hash` 全部可复现。
- native、WASM、Worker、React、浏览器矩阵版本和运行参数明确。
- host boundary、REAL-EXCLUDED、缺资源、官方 oracle 缺失和浏览器不支持分开统计。
- 不以“实现存在”“构建通过”替代行为或视觉验收。
- 报告自哈希失败、首个 divergent tick 未定位、恢复重复副作用、真实硬件误报或降低检查才能通过时立即 `STOP_RELEASE`。

## 6. 任务分解

任务状态初始为 `planned`。每个任务完成时必须提交代码、专属测试和 self-hashed evidence;依赖未完成不得跳过。

| 任务 ID | 任务 | 具体输出 | 依赖 | 专属验收 |
|---|---|---|---|---|
| AXIS-INV-01 | 冻结 AXIS 源 | source/version/environment manifest | 无 | R0 manifest hash |
| AXIS-INV-02 | 生成 Tcl UI inventory | menu/widget/proc/bind/state JSONL | INV-01 | 每行 source path/line/hash |
| AXIS-INV-03 | 生成 bitmap inventory | 20 toolbar + logo/spindle/std icon hash/size | INV-01 | byte hash、URL、尺寸一致 |
| AXIS-INV-04 | 生成 AXIS case inventory | `configs/sim/axis` exact graph + DISPLAY family | INV-01 | 无 basename substitution |
| AXIS-CON-01 | 状态枚举契约 | task/interp/motion/mode/coordinate/override/device schema | INV-02 | reducer/state contract tests |
| AXIS-CON-02 | 命令和 ledger 契约 | command schema、idempotency、ack/result/error | CON-01 | duplicate/replay/cancel tests |
| AXIS-CON-03 | 门控谓词契约 | `state()`/`relief()` 的 Web selector | CON-01 | 全状态矩阵覆盖 |
| AXIS-CON-04 | 诊断和 boundary 契约 | host/Python/loader/real hardware 分类 | CON-02 | blocked 不得伪造成功 |
| AXIS-UI-01 | AXIS shell | title、menu、main panes、responsive root | INV-02 | DOM geometry + screenshot |
| AXIS-UI-02 | File menu | Open/Recent/Edit/Reload/Save/Properties/tool/ladder/Quit | UI-01, CON-02 | menu order + command trace |
| AXIS-UI-03 | Machine menu | task controls、history、diagnostics、homing、offset、touch-off | UI-01, CON-03 | state-gated menu matrix |
| AXIS-UI-04 | View menu | views、units、overlays、DRO、grid、teleop | UI-01, CON-01 | setting round-trip + screenshot |
| AXIS-UI-05 | Exact toolbar | 20 icons、顺序、tooltip、pressed/disabled | INV-03, UI-01 | asset and DOM hash |
| AXIS-UI-06 | Notebook shell | Manual/MDI、Preview/DRO tabs,焦点/快捷键 | UI-01 | tab switching/no reinit |
| AXIS-UI-07 | Info/program panes | task/tool/position、G-code、active G-codes、scroll | UI-06, CON-01 | current-line/scroll tests |
| AXIS-CTRL-01 | ESTOP/power/recover | task/IO 状态机和视觉 relief | CON-02, CON-03 | ESTOP fault/recover trace |
| AXIS-CTRL-02 | Program controls | load/run/line-run/step/pause/resume/stop/restart | CTRL-01 | native vs Worker endpoint |
| AXIS-CTRL-03 | MDI | command、history、Go、clipboard、queue gate | CTRL-01 | queue-full/history tests |
| AXIS-CTRL-04 | Jog | axis/joint、continuous/increment、press/release/stop | CTRL-01 | release safety and replay |
| AXIS-CTRL-05 | Home/touch-off | home、G54、tool offset、override limits | CTRL-04 | homing/limit/offset oracle |
| AXIS-CTRL-06 | Spindle/coolant | direction、rpm delta、brake、mist/flood | CTRL-01 | IO/device result and fault |
| AXIS-CTRL-07 | Overrides | jog/axis/max velocity/feed/rapid/spindle、metric | CTRL-01 | conversion and range tests |
| AXIS-CTRL-08 | Keyboard map | F1/F2/F3/F5/R/T/P/S/Esc/O/Ctrl keys/F7-F12 | UI-06, CTRL-* | keyboard replay matrix |
| AXIS-VIEW-01 | Preview parser | G-code path、rapid、dwell、current line | CTRL-02 | preview hash/line mapping |
| AXIS-VIEW-02 | Camera | z/z2/x/y/y2/p、zoom、drag/rotate | UI-05, VIEW-01 | canvas nonblank + camera state |
| AXIS-VIEW-03 | Overlays | live/tool/extents/grid/offset/limits/velocity/DTG | VIEW-01 | per-layer toggle screenshots |
| AXIS-VIEW-04 | DRO | machine/relative × actual/commanded × DTG/units/font | CON-01, VIEW-01 | numeric endpoint parity |
| AXIS-EDIT-01 | G-code editor | line numbers、highlight、selection、error column | CTRL-02 | selected-line/run/error tests |
| AXIS-EDIT-02 | Tool table | edit/reload/current/prepared/pocket/hash | CTRL-06 | tool IO/native trace |
| AXIS-EDIT-03 | Config/resource UI | INI/HAL/TBL/VAR/include graph and diagnostics | INV-04 | exact-path report |
| AXIS-EXT-01 | HAL/PLC diagnostics | graph、pin、scope、ClassicLadder Web panels | CON-04 | virtual HAL/PLC replay |
| AXIS-EXT-02 | PyVCP/GLADEVCP/NGCGUI | descriptor→Web component、Python boundary | AXIS-EDIT-03 | capability and blocked cases |
| AXIS-CASE-01 | Minimal XYZ | native/WASM/Worker/frontend full controls | CTRL-*, VIEW-* | `minimal-xyz` report |
| AXIS-CASE-02 | CoreXY dual path | kins vs HAL path | CASE-01 | two independent reports |
| AXIS-CASE-03 | Lathe/9-axis/gantry | axis/joint/lathe variations | CASE-01 | case family matrix |
| AXIS-CASE-04 | VisMach/5-axis | pose/joint/tool orientation/model/stock | VIEW-02, CASE-01 | visual + kinematics report |
| AXIS-TEST-01 | DOM/accessibility | roles、labels、focus、tooltip、shortcut | UI-* | browser DOM report |
| AXIS-TEST-02 | Canonical visual | 1440×900、1280×800、390×844 screenshots | UI-05, VIEW-* | pixel/geometry report |
| AXIS-TEST-03 | Interaction replay | command/event/ack/error/recovery sequence | CTRL-*, EDIT-* | trace hash |
| AXIS-TEST-04 | Native/WASM parity | endpoint/tick/state/error/plot hash | CASE-* | differential report |
| AXIS-TEST-05 | Fault matrix | estop/limit/invalid/blocked/busy/quota/restart | CTRL-01, CON-04 | all failure samples retained |
| AXIS-TEST-06 | Browser/performance | Chromium/Firefox/Safari、WebGL、OPFS、worker | TEST-01..05 | matrix report; blocked explicit |
| AXIS-REL-01 | Evidence index | 每功能、任务、报告、hash、owner、date | TEST-* | self-hash + link audit |
| AXIS-REL-02 | Release gate | license/NOTICE、boundary、STOP_RELEASE 决策 | REL-01 | no unresolved P0/P1 |

## 7. 验收里程碑

里程碑是累积门槛;后一个里程碑不能覆盖前一个未关闭的失败。

### M0:源基线冻结

**目标**:AXIS source/UI/asset/case inventory 可重复生成。
**必须通过**:AXIS-INV-01…04;全部源引用、行号、hash 有效;不存在未分类的外部依赖。
**证据**:`coverage/axis-source-inventory.report.json`(同一 self-hashed 报告包含 source/UI/asset/case inventory)。
**失败即停止**:源码提交、资源字节、案例资源或 fixture 变化未重新生成报告。

### M1:像素和结构对标

**目标**:首屏结构与原始 AXIS 一致。
**必须通过**:AXIS-UI-01…07、AXIS-TEST-01/02。
**硬门槛**:菜单四项顺序;toolbar 20 个图标顺序/byte hash/tooltip;Manual/MDI 与 Preview/DRO tab;程序区、Active G-Codes、info bar;canonical 桌面和窄屏无重叠、无裁切。
当前 Chromium 结构证据:`coverage/gui-browser-visual-fe-m4.report.json`,报告哈希 `0df7a7c9c663292bbf1f764946032fb4ba1b882b23532863569470c723401ae1`;Firefox/Safari/OPFS 不随该授权切片关闭。
**不计入通过**:只截图而没有 DOM geometry、asset URL、aria/tooltip 检查。

### M2:控制和状态门控对标

**目标**:每个按钮在与原始 AXIS 相同的状态下启用/禁用/pressed,并产生相同语义命令。
**必须通过**:AXIS-CON-01…04、AXIS-CTRL-01…08、AXIS-TEST-03/05。
**硬门槛**:ESTOP、OFF、ON、idle、reading、waiting、paused、limit、not-homed、queue-full 全矩阵;jog release safety;重复 operation 不产生副作用。
**失败分类**:首个 divergent command/tick、错误码、门控谓词和恢复状态必须定位。

### M3:程序、MDI、DRO、预览对标

**目标**:G-code、MDI、程序预览、live plot、DRO、坐标/单位/模式全部对齐。
**必须通过**:AXIS-VIEW-01…04、AXIS-EDIT-01、AXIS-CASE-01、AXIS-TEST-04。
**硬门槛**:native/Worker 当前行、active G-codes、machine/relative、actual/commanded、DTG、metric、path layer、tool pose、state hash 一致;canvas 非空且切换视角不改变仿真结果。

### M4:工具、HAL、插件和外部边界

**目标**:工具表、主轴/IO、HAL/PLC、PYVCP/GLADEVCP/NGCGUI/VisMach 入口可用或明确 blocked。
**必须通过**:AXIS-EDIT-02/03、AXIS-EXT-01/02、AXIS-CASE-02…04。
**硬门槛**:所有 host-only 能力有 capability/boundary 记录;不允许用 mock 让外部菜单显示 verified;HAL pin 类型、线程顺序和工具 IO 事件可回放。

### M5:案例级 native/WASM/Worker/frontend parity

**目标**:代表案例及全量 AXIS 案例矩阵有 exact resource、startup、control、visual、recovery 证据。
**必须通过**:AXIS-TEST-04、案例对标计划 S8-03…S8-10。
**硬门槛**:每案例 endpoint/checkpoint/event hash 可重放;资源 blocker、host blocker、oracle blocker、error 分开;不能把 `STATIC READY` 当 `TASK_READY`。

### M6:浏览器、性能和恢复

**目标**:支持矩阵下 UI/Worker/OPFS/3D/恢复可复现。
**必须通过**:AXIS-TEST-01…06。
**硬门槛**:Chromium canonical visual/performance/recovery verified;Firefox/Safari/OPFS 若环境不支持则保留 blocked 证据;Worker crash/restart、offline、quota、half-commit 不丢 journal、不重复副作用。

### M7:发布关闭

**目标**:AXIS 对标交付有可审计证据和边界声明。
**必须通过**:AXIS-REL-01/02、所有 P0/P1 条目、所有 release gate。
**禁止发布**:视觉只验了 React 静态 DOM;native oracle 缺失未标记;浏览器矩阵未跑却宣称全平台;真实硬件/宿主能力被算作 Web 等价;报告无法自哈希。

## 8. 证据格式和差异判定

### 8.1 单功能 evidence schema

每个 `feature_id` 的报告至少包含:

```json
{
  "schema": "axis-feature-evidence.v1",
  "feature_id": "AXIS-MANUAL-02",
  "status": "verified",
  "source": {
    "path": "linuxcnc/share/axis/tcl/axis.tcl",
    "lines": "893-924",
    "sha256": "..."
  },
  "web": {
    "paths": ["web/react/src/App.tsx", "web/react/src/worker-client.ts"],
    "selectors": ["[data-axis-feature=AXIS-MANUAL-02]"],
    "asset_urls": []
  },
  "protocol": {
    "commands": ["JOG_START", "JOG_STOP"],
    "operation_ids": ["..."],
    "capability_predicate": "task=ON && interp=IDLE && !ESTOP"
  },
  "oracle": {
    "native_trace_hash": "...",
    "worker_trace_hash": "...",
    "endpoint_hash": "...",
    "first_divergent_tick": null
  },
  "visual": {
    "viewport": "1440x900@1x",
    "dom_hash": "...",
    "screenshot_hash": "...",
    "asset_hashes": []
  },
  "failure_policy": "blocked|host_boundary|missing_oracle|resource|error",
  "report_sha256": "..."
}
```

### 8.2 差异判定顺序

出现差异时按以下顺序停止和定位:

1. source/config/resource hash 是否相同;
2. 启动 phase 和 capability 是否相同;
3. command kind、payload、seq、operation_id 是否相同;
4. 第一个不同的 `simulation_tick`、task/interp/motion state;
5. 事件顺序、错误码、alarm/recovery、checkpoint/event hash;
6. 最后才比较 DOM geometry、样式和 canvas 像素。

不能先调 CSS 掩盖状态差异,也不能先放宽数值容差。数值容差应按来源类型登记:整数/枚举必须完全相等;位置/速度按固定浮点策略;哈希、事件序号、行号和命令序列不允许容差。

### 8.3 视觉判定

- **强等价**:布局区域、菜单顺序、工具栏顺序、原始 icon byte、控件 role/label、状态颜色和 disabled/pressed 必须精确。
- **规范化等价**:浏览器字体抗锯齿、滚动条、系统 checkbox 外观可在 report 中 mask,但区域尺寸、文本内容、边界和可访问名称不能 mask。
- **动态图层**:Three.js canvas 进行 nonblank/finite/pixel sample/相机状态检查;预览 path、tool、origin、grid、limit、live plot 分层截图。
- **固定视口**:`1440×900@1x`、`1280×800@1x`、`390×844@1x`;另测 DPR 2,但不能以 DPR 2 代替 canonical。

## 9. 当前实现状态和下一步执行顺序

当前 React 已具备 AXIS 风格 shell、原始 bitmap toolbar、Manual/MDI 与 Preview/DRO 结构、Worker-backed program/MDI/jog/home/override/spindle/coolant/ESTOP/recover 入口和 Three.js 视角交互;这只证明实现切片,不等于本规范的 M1…M7 已验收。

M0 的 `AXIS-INV-01…04` 已执行:[`coverage/axis-source-inventory.report.json`](../coverage/axis-source-inventory.report.json) 由 [`scripts/generate_axis_source_inventory.py`](../scripts/generate_axis_source_inventory.py) 生成,专属契约测试为 [`scripts/test_axis_source_inventory.py`](../scripts/test_axis_source_inventory.py),当前冻结 10 个源码入口、31 个 bitmap 资源和 115 个精确 AXIS INI 案例,报告自哈希为 `0ec92a467ca13700bd12a7f2889ada8aa11588ca50858dbe25f84a5c946b8176`。该报告只冻结来源,不代表任何 Web 功能已通过行为或视觉验收。

接续执行顺序固定为:

1. `AXIS-INV-01…04` 已完成;报告保留 exact path、source hash、asset hash 和 DISPLAY 声明。
2. `AXIS-CON-01…04` 已完成:[`coverage/axis-contract.report.json`](../coverage/axis-contract.report.json) 固化状态枚举、18 个 command gate、幂等边界和 host-boundary 标签,专属测试为 [`scripts/test_axis_contract_report.py`](../scripts/test_axis_contract_report.py)。
3. `AXIS-UI-01…07` 已完成 Chromium 结构证据:[`coverage/gui-browser-visual-fe-m4.report.json`](../coverage/gui-browser-visual-fe-m4.report.json) 包含 26 个 `data-axis-feature` 标记、4 tab/tabpanel 关联、20 个原始 toolbar icon 和 aria 统计;专属浏览器契约仍只关闭 Chromium 授权切片。
4. `AXIS-CTRL-01…08` 已完成:[`coverage/axis-control.report.json`](../coverage/axis-control.report.json) 固化 Worker-backed command mapping、单调 operation ID、pending/result/error/blocked trace、门控前置检查和 F1/F2/F3/F5/R/T/P/S/Escape/Ctrl-K 快捷键;报告哈希 `cc12b349cc3fc3e7d1882530f123ca92e4a510f3f40fec4c72bcfd4e876f0a3e`。
5. `AXIS-VIEW-01…04` 和 `AXIS-EDIT-01` 已完成:[`coverage/axis-view-edit.report.json`](../coverage/axis-view-edit.report.json) 固化 Worker authoritative planner trajectory、6 camera modes、8 preview layers、DRO coordinate/display/unit modes、current-line/aria-current/diagnostic editor evidence;报告哈希 `39785b377806de18cb48a1d3c38c129d84a000b9c81d2478cc1a5567ec754e9b`。
6. `AXIS-CASE-01…04` 已形成案例矩阵:[`coverage/axis-case-parity.report.json`](../coverage/axis-case-parity.report.json) 中 Minimal XYZ、CoreXY kins/HAL、Linear/Rotary Delta representative verified;lathe/gantry/VisMach-5-axis 仍按 exact resource/startup 与 official kinematics oracle 保持 blocked。报告哈希 `a6fcc5eec964a02b821f9a52f30b8e0d3303b8c94507b6d44d6cc75b7a7089e4`。
7. `AXIS-TEST-01…06`:Chromium visual/interaction/performance/recovery,外加明确的 Firefox/Safari/OPFS blocker。
8. `AXIS-REL-01/02`:只有所有 P0/P1 和报告自哈希通过,才更新 release gate。

第一批可执行命令:

```bash
python3 scripts/validate_baseline.py
python3 scripts/validate_task_pointer.py
sha256sum linuxcnc/share/axis/tcl/axis.tcl linuxcnc/lib/python/gremlin.py linuxcnc/lib/python/rs274/glcanon.py
find linuxcnc/share/axis/images -maxdepth 1 -type f -printf '%f\n' | sort
npm --prefix web/react run typecheck
npm --prefix web/react run build
for f in web/app/test_*.mjs; do node "$f" || exit 1; done
```

执行者每完成一个任务,必须在对应报告中记录:源文件行号、Web 文件、命令/状态字段、测试命令、native/WASM/Worker 哈希、视觉视口、失败分类和下一依赖。没有这些字段的“完成”只算 `implementation_present`,不算 `verified`。

## 10. STOP_RELEASE 条件

出现以下任一项,立即停止扩大范围并将当前里程碑标为 `blocked`:

- AXIS 源、图标或案例输入变化但未重新生成 hash;
- 首个 divergent command/tick 未定位;
- UI 使用本地乐观状态伪造 task/position/IO 已执行;
- jog release、急停、恢复或 checkpoint 可能重复副作用;
- 缺少 native oracle 却宣称结果一致;
- host-only、真实硬件、动态 loader、外部窗口被统计为 Web 已支持;
- 视觉测试只比较截图,没有 DOM/交互/状态证据;
- 浏览器或 OPFS 不支持被静默降级;
- 任何报告无法用固定输入重新生成或 self-hash 不一致。

本规范关闭的是“AXIS 对标工程”而不是“LinuxCNC 全功能发布”声明。所有未实现、缺资源、无官方 oracle、浏览器边界和真实硬件排除项都必须保留在最终 evidence index 中。