chore: close wasm status contract work

This commit is contained in:
wangdequan
2026-07-08 09:20:47 -04:00
parent 97732ceb0b
commit e69333972c
69 changed files with 20435 additions and 495 deletions

View File

@@ -0,0 +1,242 @@
# 12-status JSON LinuxCNC对标方案
## 目标
本方案用于后续在 WASM 中完善 `status JSON`:对标 LinuxCNC 的 `EMC_STAT` / status buffer 模型,在 WASM/C++ 内维护结构化 status 事实源,再把最后一次 status write 序列化为 JSON 给 JS/SDK/UI 读取。
`status JSON` 不是 LinuxCNC 语义实现层。它是浏览器/Node host 无法直接读取 native NML/CMS status channel 时的外部通信格式。
## LinuxCNC对标基线
上游 LinuxCNC 的 status 模型来自:
- `/home/mes123456/cnc_wams/linuxcnc/src/emc/nml_intf/emc.hh`
- 定义 `EMC_TASK_MODE``EMC_TASK_STATE``EMC_TASK_EXEC``EMC_TASK_INTERP``EMC_TRAJ_MODE` 等枚举。
- 定义 `EMC_STAT_TYPE``EMC_TASK_STAT_TYPE``EMC_MOTION_STAT_TYPE``EMC_IO_STAT_TYPE` 等 NML 类型编号。
- `/home/mes123456/cnc_wams/linuxcnc/src/emc/nml_intf/emc_nml.hh`
- `EMC_STAT` 聚合 `EMC_TASK_STAT task``EMC_MOTION_STAT motion``EMC_IO_STAT io`
- `EMC_TASK_STAT` 保存 task mode/state、exec/interp state、program line、file、active G/M code、offset、program units、pause 等状态。
- `EMC_MOTION_STAT` 保存 `EMC_TRAJ_STAT traj`、joint、axis、spindle、synch IO、analog IO、soft limit、heartbeat 等状态。
- `EMC_TRAJ_STAT` 保存 enabled、inpos、queue、activeQueue、queueFull、id、paused、single_stepping、position、actualPosition、current_vel、probe、kinematics 等轨迹状态。
- `EMC_IO_STAT` 保存 tool、coolant、aux、fault/reason 等 IO 状态。
上游 GUI 读取的是 status channel 中的 `EMC_STAT` 快照,不是在 GUI 层重建 task/motion 状态机。WASM 中的 JSON 应只模拟“读 status channel 后得到可展示快照”的边界。
## WASM中的等价模型
当前 WASM 侧已建立:
- `StandaloneEmcStatus`
- `StandaloneEmcTaskStatus`
- `StandaloneEmcMotionStatus`
- `StandaloneEmcIoStatus`
- `write_status_snapshot()`
- `lctask_read_status_json()`
后续完善时采用以下固定链路:
```text
LinuxCNC source semantics
-> WASM/C++ task cycle
-> LcmotStatusSnapshot
-> StandaloneEmcStatus
-> write_status_snapshot()
-> lctask_read_status_json()
-> JS/SDK/UI
```
禁止以下链路:
```text
motion JSON -> parse -> task state
status JSON -> parse -> task/motion state
JS/SDK -> compute LinuxCNC task/motion semantics
lctask_read_status_json() -> step servo / read fresh motion / consume command
```
## status JSON职责
`status JSON` 只承担四类职责:
1. 把最后一次 `write_status_snapshot()` 中的状态导出给 JS/SDK/UI。
2. 给浏览器 UI 提供稳定、可版本化、可兼容的字段名。
3. 给 Node/WASM/browser 测试提供可断言的观察面。
4. 保留旧 SDK/UI 兼容字段,同时新增更接近 `EMC_STAT``emcStatus` 对象。
`status JSON` 不承担:
- task 状态机事实源。
- motion 状态机事实源。
- LinuxCNC planner/canon/interpreter 语义。
- queueFull、inpos、abort、estop、pause/resume/step 等语义判断。
## 推荐JSON结构
顶层保留 runtime/readiness 和兼容字段,同时以 `emcStatus` 作为 LinuxCNC 对标主对象:
```json
{
"statusSource": "StandaloneEmcStatus",
"schemaVersion": 1,
"taskTopLevelStatus": "DONE",
"rcsStatus": {
"top": "DONE",
"task": "DONE",
"motion": "DONE",
"io": "DONE"
},
"task": {},
"motionStatus": {},
"emcStatus": {
"source": "StandaloneEmcStatus",
"top": { "status": "DONE" },
"task": {},
"motion": {},
"io": {}
}
}
```
要求:
- `task``motionStatus` 是兼容视图,字段必须来自 `emcStatus` 或同一份 C/C++ status buffer。
- `emcStatus` 是后续新增 LinuxCNC 对标字段的默认入口。
- 新字段优先落在 `emcStatus.task``emcStatus.motion.traj``emcStatus.motion.joint[]``emcStatus.motion.axis[]``emcStatus.io` 中。
- 若必须保留旧字段名,应在测试中断言旧字段与 `emcStatus` 同源一致。
## 字段映射方案
| LinuxCNC字段 | WASM事实源 | JSON位置 | 状态 |
| --- | --- | --- | --- |
| `EMC_STAT.status` / top RCS status | `StandaloneEmcStatus.top_rcs_status` | `emcStatus.top.status``taskTopLevelStatus``rcsStatus.top` | 已有 |
| `EMC_STAT.task.status` | `StandaloneEmcTaskStatus.rcs_status` | `emcStatus.task.status``task.status``rcsStatus.task` | 已有 |
| `EMC_STAT.task.state` | `StandaloneEmcTaskStatus.state` | `emcStatus.task.state``task.state` | 已有 |
| `EMC_STAT.task.mode` | `StandaloneEmcTaskStatus.mode` | `emcStatus.task.mode``task.mode` | 已有 |
| `EMC_STAT.task.execState` | `StandaloneEmcTaskStatus.exec_state` | `emcStatus.task.execState``task.execState` | 已有 |
| `EMC_STAT.task.interpState` | `StandaloneEmcTaskStatus.interp_state` | `emcStatus.task.interpState``task.interpState` | 已有 |
| `EMC_STAT.task.task_paused` | `StandaloneEmcTaskStatus.task_paused` | `emcStatus.task.taskPaused``task.taskPaused` | 已有 |
| `EMC_STAT.task.file` | `StandaloneEmcTaskStatus.open_program` | `emcStatus.task.file``task.file` | 已有 |
| `EMC_STAT.task.currentLine/readLine/motionLine` | staged interpreter + motion snapshot | `emcStatus.task.currentLine/readLine/motionLine` | 已有 |
| `EMC_STAT.task.activeGCodes/activeMCodes/activeSettings` | vendored interpreter/canon state | `emcStatus.task.activeGCodes/activeMCodes/activeSettings` | 后续 |
| `EMC_STAT.task.g5x_offset/g92_offset/toolOffset` | vendored interpreter/canon state | `emcStatus.task.offsets` | 后续 |
| `EMC_STAT.motion.status` | `StandaloneEmcMotionStatus.rcs_status` | `emcStatus.motion.status``rcsStatus.motion` | 已有 |
| `EMC_STAT.motion.traj.enabled` | `LcmotStatusSnapshot.motion_enabled` | `emcStatus.motion.traj.enabled` | 已有 |
| `EMC_STAT.motion.traj.inpos` | `LcmotStatusSnapshot.in_position` | `emcStatus.motion.traj.inpos` | 已有 |
| `EMC_STAT.motion.traj.queue` | `LcmotStatusSnapshot.queue_count` | `emcStatus.motion.traj.queue` | 已有 |
| `EMC_STAT.motion.traj.activeQueue` | `LcmotStatusSnapshot.active_depth` | `emcStatus.motion.traj.activeQueue` | 已有 |
| `EMC_STAT.motion.traj.queueFull` | `LcmotStatusSnapshot.queue_full` | `emcStatus.motion.traj.queueFull` | 已有 |
| `EMC_STAT.motion.traj.id` | `LcmotStatusSnapshot.motion_id` | `emcStatus.motion.traj.id` | 已有 |
| `EMC_STAT.motion.traj.paused` | `LcmotStatusSnapshot.paused` | `emcStatus.motion.traj.paused` | 已有 |
| `EMC_STAT.motion.traj.single_stepping` | `LcmotStatusSnapshot.stepping` | `emcStatus.motion.traj.singleStepping` | 已有 |
| `EMC_STAT.motion.traj.position/actualPosition` | `LcmotStatusSnapshot.axis_cmd/axis_fb` | `emcStatus.motion.traj.position/actualPosition` | 已有 |
| `EMC_STAT.motion.traj.current_vel` | `LcmotStatusSnapshot.current_vel` | `emcStatus.motion.traj.currentVel` | 已有 |
| `EMC_STAT.motion.on_soft_limit` | `LcmotStatusSnapshot.on_soft_limit` | `emcStatus.motion.onSoftLimit` | 已有 |
| `EMC_STAT.motion.joint[]` | `LcmotStatusSnapshot.joint_cmd/joint_fb` | `emcStatus.motion.joint[]` | 已有 |
| `EMC_STAT.motion.axis[]` | `LcmotStatusSnapshot.axis_cmd/axis_fb` | `emcStatus.motion.axis[]` | 已有 |
| `EMC_STAT.io.status` | `StandaloneEmcIoStatus.rcs_status` | `emcStatus.io.status``rcsStatus.io` | 已有 |
| `EMC_STAT.io.aux.estop` | task/io shim | `emcStatus.io.aux.estop` | 已有 |
| `EMC_STAT.io.fault/reason` | `StandaloneEmcIoStatus.error/reason` | `emcStatus.io.fault/reason` | 已有 |
## 后续实施批次
### SJ-1规范 `emcStatus.motion.traj`
状态:已完成,对应 T-051。
目标:把当前 `motionStatus.motion.*` 中已有的 queue、inpos、id、paused、stepping、currentVel 等字段,以 LinuxCNC `EMC_TRAJ_STAT` 名称归入 `emcStatus.motion.traj`
验收:
- `emcStatus.motion.traj.queue` 等于兼容字段 `motionStatus.motion.queueDepth`
- `emcStatus.motion.traj.inpos` 等于兼容字段 `motionStatus.motion.inPosition`
- `emcStatus.motion.traj.id` 等于兼容字段 `motionStatus.motion.id`
- `lctask_read_status_json()` 不新增 motion read 或 servo step。
### SJ-2规范 task line 和 interpreter字段
状态:已完成,对应 T-052。active G/M code、active settings 和 offsets 仍按字段映射表保留为后续 source-anchored 扩展,不计入本 SJ-2 验收。
目标:对齐 `EMC_TASK_STAT.currentLine``readLine``motionLine``callLevel`,让 UI 和测试能分辨 interpreter 已读行、当前执行行和 motion 正在执行行。
验收:
- staged program RUN 后,`emcStatus.task.readLine/currentLine/motionLine` 与现有 plan read/execute/motion id evidence 一致。
- 兼容字段若存在,必须与 `emcStatus.task.*Line` 同源。
### SJ-3规范 `motion.axis[]` 和 `motion.joint[]`
状态:已完成,对应 T-053。`emcStatus.motion.axis``emcStatus.motion.joint` 为数组;按名字访问的兼容视图保留在 `motionStatus.axis``emcStatus.motion.axisByName` 仅辅助迁移。
目标:把当前 axis x/y/z/a/b/c 和 joint0 字段扩展成数组结构,对标 `EMC_MOTION_STAT.axis[]``joint[]`
验收:
- 至少导出存在的 5/6 轴位置和 joint0 command/feedback。
-`motionStatus.axis``motionStatus.joint0` 与新数组值一致。
### SJ-4规范 IO/aux/tool/coolant边界
状态:已完成,对应 T-054。tool/coolant 只暴露 shim/unsupported 边界,不提升 native IO readiness。
目标:将当前 IO shim 状态组织为 `emcStatus.io.aux``emcStatus.io.tool``emcStatus.io.coolant` 的窄对象,未实现字段显式标记为 shim/unsupported而不是省略成语义完成。
验收:
- `emcStatus.io.status``fault``reason``aux.estop` 可观测。
- readiness 仍保持 false不因 JSON 字段存在而宣称 native IO ready。
### SJ-5引入 schema gate
状态:已完成,对应 T-055。
目标:新增专用 gate例如 `tools/verify_task_status_json_contract.sh`,固定 status JSON 字段来自 `StandaloneEmcStatus`,并检查 `emcStatus` 与兼容字段的一致性。
验收:
- gate 检查 `statusSource=StandaloneEmcStatus`
- gate 检查 `lctask_read_status_json()` 不调用 `lcmot_read_status_json()`
- gate 检查 JS/SDK 没有实现 task/motion 语义。
- gate 纳入 `tools/verify_task_full_closure.sh`
## 兼容策略
短期保留:
- `taskTopLevelStatus`
- `rcsStatus`
- `task`
- `motionStatus`
新增字段默认进入:
- `emcStatus.top`
- `emcStatus.task`
- `emcStatus.motion`
- `emcStatus.motion.traj`
- `emcStatus.motion.axis`
- `emcStatus.motion.joint`
- `emcStatus.io`
旧字段只能作为兼容视图,不能作为后续实现的主字段。新增测试应优先断言 `emcStatus`,再断言兼容字段与其一致。
## 文档和测试要求
每完成一个 SJ 批次,需要同步更新:
- `04-任务矩阵.md`
- `03-推进台账.md`
- `05-验收证据.md`
- `06-决策记录.md`
- `07-emctaskmain周期对标蓝图.md`
- `11-WASM核心状态机边界与后续完善路线.md`
- `docs/source-reuse-map.md`
- `docs/compatibility-validation.md`
- 对应 `tools/verify_task_*` gate
默认最终验收命令:
```bash
cd /home/mes123456/cnc_wams/wasm-port
./tools/verify_task_full_closure.sh
git diff --check
```