592 lines
45 KiB
Markdown
592 lines
45 KiB
Markdown
# 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 <version> on <machine>`,无文件时显示 `(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 | 编辑/选行/运行到选中行/错误定位;不能使用静态 `<pre>` 冒充 |
|
||
| 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` 已形成测试矩阵:[`coverage/axis-test-matrix.report.json`](../coverage/axis-test-matrix.report.json) 中 DOM/accessibility、Chromium visual、operation replay、Worker case parity 和 Chromium repeat performance 已验证;Firefox/Safari minimum matrix、OPFS recovery 和 6 个案例资源/oracle blocker 仍明确 blocked。报告哈希 `9ba5de25bd8cfbfd61bd0a87bcb282170fa1de44b28a172b1c6ba649f580c357`。
|
||
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 中。
|