Files
cnc_wams/wasm-port/working/06-决策记录.md
2026-07-10 03:22:55 -04:00

1184 lines
63 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 06-决策记录
## D-046task status JSON 不再保留旧顶层字段兼容视图
日期2026-07-08
状态:已采纳
### 决策
`lctask_read_status_json()` 只通过 `emcStatus` 导出 task/motion/io/top 状态,不再输出 `taskTopLevelStatus``rcsStatus`、顶层 `task``servoCycle`、顶层 `motionStatus`
本决策取代 D-044 中“既有旧字段保留为兼容视图”的部分D-044 中“status JSON 对标 LinuxCNC status buffer、JSON 不能成为事实源、read status 只读”的部分继续有效。
### 理由
上层项目已经迁移到 `emcStatus` 契约。继续在源头输出旧字段会扩大状态表面,导致 SDK/UI 继续依赖旧字段,并让后续 LinuxCNC `EMC_STAT` 对标和契约测试同时维护两套入口。
### 影响
- `status_json()` 移除旧顶层字段输出。
- `emcStatus.task``emcStatus.motion` 补齐旧视图中仍需要的字段。
- WASM、SDK、state matrix 和 status contract 测试均对旧顶层字段做负向断言。
- 后续新增字段只能进入 `emcStatus` 或底层 C/C++ status buffer不新增旧字段兼容视图。
## D-045SJ-1 到 SJ-5 必须进入任务矩阵并由 contract gate 固定
日期2026-07-08
状态:已采纳
### 决策
`11-WASM核心状态机边界与后续完善路线.md``12-status-json-LinuxCNC对标方案.md` 中的 SJ-1 到 SJ-5 是实际后续实现任务,不再只作为“未来路线”保留。将 SJ-1 到 SJ-5 分别补入 `04-任务矩阵.md` 的 T-051 到 T-055并以 `tools/verify_task_status_json_contract.sh` 固定 status JSON schema。
### 理由
上一轮只检查任务矩阵,导致 `11``12` 中已经写明目标和验收标准的任务没有被发现。后续只要文档中出现可执行实现项,就必须同步进入任务矩阵、验收证据和 gate否则“矩阵闭合”没有实际意义。
### 影响
- T-051 到 T-055 已闭合,覆盖 `emcStatus.motion.traj`、task line 字段、axis/joint 数组、IO aux/tool/coolant 和 status JSON contract gate。
- `tools/verify_task_full_closure.sh` 纳入 `tools/verify_task_status_json_contract.sh`
- source reuse、drift、compatibility 和 working closure gate 均检查 T-051 到 T-055。
- readiness 仍保持 `nativeTaskReady=false``nativeHalSyncReady=false``fullLinuxCncProgramExecutionReady=false`
## D-044status JSON 对标 LinuxCNC status buffer而不是替代状态机
日期2026-07-08
状态:已采纳
### 决策
后续在 WASM 中解决 `status JSON` 时,对标 LinuxCNC 的 `EMC_STAT` / status buffer 模型C/C++ 侧维护 `StandaloneEmcStatus` 或后续 `EMC_STAT` 等价容器,`write_status_snapshot()` 写入最后一次 status buffer`lctask_read_status_json()` 只把该 buffer 序列化为 JSON。
新增 LinuxCNC 对标字段默认进入 `emcStatus` JSON 对象。既有 `task``motionStatus``rcsStatus``taskTopLevelStatus` 等字段保留为兼容视图,但必须从同一 C/C++ status buffer 导出。
### 理由
上游 LinuxCNC GUI 读取的是 status channel 中的 `EMC_STAT` 快照,而不是在 GUI 中重建 task/motion 状态机。WASM/browser 环境不能直接暴露 native NML/CMS channel因此用 JSON 作为外部传输格式是合理的;但 JSON 不能成为语义事实源,否则会重新引入 JS/JSON 状态机并偏离 LinuxCNC 对标目标。
### 影响
- 新增 `12-status-json-LinuxCNC对标方案.md`
- 后续 status 字段扩展按 SJ-1 到 SJ-5 分批推进。
- `lctask_read_status_json()` 必须保持只读,不推进 cycle、不重新读取 motion、不消费 command。
- 后续应新增 `tools/verify_task_status_json_contract.sh` 并纳入 full closure gate。
- 当前 readiness 仍保持 `nativeTaskReady=false``nativeHalSyncReady=false``fullLinuxCncProgramExecutionReady=false`
## D-043后续 WASM 程序定位为核心状态机实现载体
日期2026-07-08
状态:已采纳
### 决策
后续完善 `wasm-port` 程序时WASM/C++ 侧作为核心状态机实现的运行载体,承载 LinuxCNC 语义复用、task/motion 状态机、周期调度、motion snapshot、状态聚合、command read/plan/execute 和 `StandaloneEmcStatus`
JS/SDK 只承担加载 WASM、传命令、读状态、Emscripten FS/OPFS 和浏览器/Node 边界。JSON 只作为外部通信格式,例如 command JSON 和 status JSON不作为核心状态机事实源。
### 理由
JSON 适合跨 host/browser 边界传输数据,但不适合保存和推进 task/motion 状态机。核心状态应由 C/C++ 结构体、枚举、队列和周期函数维护,并尽量复用 vendored LinuxCNC source。这样可以避免 JS/JSON 重新实现 CNC 语义,也符合 `wasm-port/AGENTS.md` 中“核心 CNC 逻辑编译到 WASM、前端只做 web 技术实现”的方向。
### 影响
- 新增 `11-WASM核心状态机边界与后续完善路线.md` 作为后续任务入口。
- 后续新增状态字段应先进入 `StandaloneEmcStatus` 或后续 `EMC_STAT` 等价容器,再导出到 status JSON。
- 后续新增 command 应先通过 JSON/C ABI 入队,再由 `lctask_run_cycles()` 的 command read/plan/execute 阶段消费。
- 当前 T-001 到 T-049 闭合状态不变;后续代码任务必须先补入 `04-任务矩阵.md`
- readiness 仍保持 `nativeTaskReady=false``nativeHalSyncReady=false``fullLinuxCncProgramExecutionReady=false`
## D-042T-049 建立 task-HAL 全量闭合验证入口
日期2026-07-08
状态:已采纳
### 决策
新增 `tools/verify_task_full_closure.sh` 作为 task-HAL 对标工作的统一闭合入口。该脚本负责构建 task-HAL WASM并串行运行核心 runtime smoke、SDK smoke、state matrix、motion/HAL sync、T-007 `StandaloneEmcStatus`、T-046 no-JSON 主路径、T-047/T-048 working closure、source reuse/drift docs 和 readiness contract gates。
### 理由
T-048 已将 working closure 纳入全局文档一致性验证,但最终验收仍需要人工记住多条命令。建立 full closure gate 可以把当前闭合状态固化成单一入口,降低后续遗漏某个关键 smoke 或文档 gate 的风险。
### 影响
- T-049 可闭合,当前任务矩阵继续保持全部完成。
- 后续 task-HAL 对标回归可优先运行 `./tools/verify_task_full_closure.sh`
- 不改变 runtime、WASM ABI、SDK 或 readiness。
- readiness 仍保持 `nativeTaskReady=false``nativeHalSyncReady=false``fullLinuxCncProgramExecutionReady=false`
## D-041T-048 将 working closure gate 纳入全局文档一致性 gate
日期2026-07-08
状态:已采纳
### 决策
T-048 将 `tools/verify_task_working_closure.sh` 记录到 `docs/source-reuse-map.md``docs/compatibility-validation.md`,并让 `tools/verify_task_source_reuse_drift_docs.sh` 检查该 gate、对应 compatibility 文案和 T-048 矩阵状态。
### 理由
T-047 已经建立 working closure gate但如果该 gate 只存在于 working 文档中,总文档一致性检查无法发现后续 source reuse / compatibility 文档漏记闭合 gate 的漂移。T-048 将 closure gate 纳入全局文档验证链,使“矩阵闭合、后续先补任务”的规则不只靠人工记忆维护。
### 影响
- T-048 可闭合,当前任务矩阵继续保持全部完成。
- `verify_task_source_reuse_drift_docs.sh` 新增 working closure gate 检查。
- 不改变 runtime、WASM ABI、SDK 或 readiness。
- readiness 仍保持 `nativeTaskReady=false``nativeHalSyncReady=false``fullLinuxCncProgramExecutionReady=false`
## D-040T-047 将 working 索引收口为“矩阵闭合、后续先补任务”
日期2026-07-08
状态:已采纳
### 决策
T-047 不新增 runtime 行为,只收口 working 文档索引和闭合 gate。`working/README.md``01-项目功能内容.md``09-emc_nml复用评估.md` 的当前状态描述更新为 T-007/T-046 后的事实:`StandaloneEmcStatus` 已建立task status 来自周期 snapshot/status writeRUN 主路径不依赖 host JSON motion plan。
新增 `tools/verify_task_working_closure.sh`,固定当前矩阵所有任务完成、下一条优先任务为“无”、无 `待办`/`进行中`/`阻塞` 任务,以及 working 索引文档包含当前闭合口径。
### 理由
T-007 完成后,原工作目录中的索引文档仍保留“当前缺少 EMC_STAT 容器”“motion 状态只在 status JSON 拼接”等历史描述。继续对标前必须避免 working 文档把已完成的任务重新描述成现状缺口。后续扩展应先新增矩阵任务、验收标准和 gate再实施变更。
### 影响
- T-047 可闭合,当前任务矩阵继续保持全部完成。
- `verify_task_working_closure.sh` 成为 working 索引闭合 gate。
- 不改变 `linuxcnc_task_hal_wasm.cpp`、WASM ABI、SDK 或 runtime readiness。
- readiness 仍保持 `nativeTaskReady=false``nativeHalSyncReady=false``fullLinuxCncProgramExecutionReady=false`
## D-039T-007 采用 `StandaloneEmcStatus` 作为当前阶段 `EMC_STAT` 等价容器
日期2026-07-08
状态:已采纳
### 决策
T-007 在 `linuxcnc_task_hal_wasm.cpp` 内建立 `StandaloneEmcStatus`,包含 `StandaloneEmcTaskStatus``StandaloneEmcMotionStatus``StandaloneEmcIoStatus`。该容器集中保存当前 WASM task/motion/io/top 所需的 `EMC_STAT` 等价字段。
`write_status_snapshot()` 在写入 `status_buffer` 前调用 `sync_standalone_emc_status()`,把 task 执行状态、motion snapshot、IO error/estop latch 和 RCS 聚合状态同步到容器。`status_json()` 从该容器导出新增 `emcStatus`,并让兼容字段 `taskTopLevelStatus``rcsStatus``task``motionStatus` 读取同一份容器状态。
### 理由
直接引入完整上游 `emc_nml.hh` 仍会拉入 NML/CMS、消息序列化、RS274/canon/tool-table 等依赖,超出当前 runtime-edge adapter 的边界。T-029 已记录分阶段 `StandaloneEmcStatus` / typedef 路线,因此 T-007 先把必需字段集中到明确容器,减少 JSON status 拼接时直接读取分散 runtime 字段的漂移。
### 影响
- T-007 可闭合,当前任务矩阵全部完成。
- status JSON 新增 `statusSource=StandaloneEmcStatus``emcStatus`
- `verify_task_hal_wasm.sh` 新增 `standalone_emc_status_container=ok`
- `verify_task_hal_sdk.sh` 新增 `task_hal_sdk_standalone_emc_status=ok`
- `verify_task_state_matrix.mjs` 新增 `standalone_emc_status_matrix=ok`
- 新增 `tools/verify_task_standalone_emc_status.sh` 固定 T-007 结构、测试、文档和矩阵状态。
- readiness 仍保持 `nativeTaskReady=false``nativeHalSyncReady=false``fullLinuxCncProgramExecutionReady=false`
## D-038T-046 主 RUN 路径移除 JSON motion plan 依赖,保留 timed-plan 兼容入口
日期2026-07-08
状态:已采纳
### 决策
T-046 将默认 RUN 文件验证路径切换为 staged program 驱动:`emcTaskPlanRead()` 读取已打开程序行,`emcTaskPlanCommand()` 生成 command evidence`emcTaskPlanExecute()` 进入 `emccanon.cc` command envelope并通过 `taskintf.cc` issue 到 motion runtime。主 smoke 和默认 SDK/status 场景不再预调用 `lctask_load_program_motion_plan_json()`
`loadProgramMotionPlan()` 与 wrapper 内的 `lctask_load_program_motion_plan_json()` 暂不删除,降级为 timed motion plan 兼容/调试入口。该入口只在显式 compatibility 场景中验证,不作为主 RUN 路径的验收基础。
### 理由
T-040 已引入 `emctask.cc` plan read/execute 子集T-041 到 T-045 已逐步把 canon init、straight motion、dwell/path-control、spindle/tool 和 motion output 收敛到 `emccanon.cc` evidence。继续让主 smoke 依赖 host JSON motion plan 会掩盖这些 native-like staged-program 边界;因此 T-046 要把默认路径改为程序文本读取和 command execute。
同时timed motion plan 对现有 SDK 用户和调试场景仍有价值,直接删除会扩大兼容风险。保留显式兼容 gate 可以让后续 T-007/T-008 在建立 `EMC_STAT` 和 interpreter 状态机时继续观察两条路径差异。
### 影响
- T-046 可闭合,任务矩阵下一条推进到 T-007。
- `verify_task_hal_wasm.sh` 新增 `task_hal_no_json_main_path_status=ok`,且主测试文件不再包含 `lctask_load_program_motion_plan_json()`
- `verify_task_hal_sdk.sh` 将 timed plan 输出改为 `task_hal_timed_motion_plan_compat=ok`
- `verify_task_state_matrix.mjs` 默认 `loadPlan=false`,新增显式 JSON timed-plan 兼容场景。
- 新增 `tools/verify_task_no_json_motion_plan_main_path.sh` 固定 T-046 主路径、兼容入口和矩阵状态。
- readiness 仍保持 `nativeTaskReady=false``nativeHalSyncReady=false``fullLinuxCncProgramExecutionReady=false`
## D-037T-045 motion output/switchkins 采用 canon output evidence 到 taskintf AOUT 边界
日期2026-07-08
状态:已采纳
### 决策
T-045 将 `SET_MOTION_OUTPUT_BIT()``CLEAR_MOTION_OUTPUT_BIT()``SET_AUX_OUTPUT_BIT()``CLEAR_AUX_OUTPUT_BIT()``SET_MOTION_OUTPUT_VALUE()``SET_AUX_OUTPUT_VALUE()``WAIT()` 纳入 `emccanon_wasm_subset`。subset 返回 `LcEmcCanonSubsetOutputCommand`wrapper 将这些 command 记录为 `EMC_MOTION_SET_DOUT` / `EMC_MOTION_SET_AOUT` / `EMC_AUX_INPUT_WAIT` / `interp_list` evidence。
`linuxcnc_task_hal_wasm.cpp` 删除 MDI 中旧的 `mdi.find("M428/M429/M430")` 字符串 special-case。M428、M429、M430 现在先进入 canon `SET_AUX_OUTPUT_VALUE()` evidence再桥接到既有 `taskintf.cc` `emcMotionSetAout()` / `lcmot_write_aout()` 路径,维持当前 switchkins HAL 同步行为。
### 理由
上游 `emccanon.cc` 的 output/wait callbacks 负责生成 `EMC_MOTION_SET_DOUT``EMC_MOTION_SET_AOUT``EMC_AUX_INPUT_WAIT` 并 append 到 `interp_list`。当前 WASM runtime 已有 `emcMotionSetAout()``lcmot_write_aout()` 的结构化 switchkins 路径,因此 T-045 只将 M428-M430 入口迁移到 canon output evidence不扩展或伪造完整数字 IO、模拟 IO wait、motion queue ownership 或 NML transport。
### 影响
- T-045 可闭合,任务矩阵下一条推进到 T-046。
- `verify_task_hal_wasm.sh` 新增 `emccanon_motion_output_status=ok`
- 新增 `tools/verify_task_emccanon_motion_output.sh` 固定 T-045 上游锚点、subset API、wrapper status、旧 special-case 移除和矩阵状态。
- `verify_task_hal_sdk.mjs` 改为断言新的 canon output 事件。
- readiness 仍保持 `nativeTaskReady=false``nativeHalSyncReady=false``fullLinuxCncProgramExecutionReady=false`
## D-036T-044 spindle/tool 采用 `emccanon.cc` 窄 command envelope evidence
日期2026-07-08
状态:已采纳
### 决策
T-044 将 `SET_SPINDLE_SPEED()``START_SPINDLE_CLOCKWISE()``START_SPINDLE_COUNTERCLOCKWISE()``STOP_SPINDLE_TURNING()``SELECT_TOOL()``CHANGE_TOOL()``CHANGE_TOOL_NUMBER()``RELOAD_TOOLDATA()` 纳入 `emccanon_wasm_subset`。subset 返回 spindle/tool command envelopewrapper 将这些 command 记录为 `EMC_SPINDLE_*` / `EMC_TOOL_*` / `interp_list` evidence。
`linuxcnc_task_hal_wasm.cpp` 在 MDI 和 staged program line 进入 dwell/path-control 与 straight motion 前识别 `S...`、精确 `M3/M4/M5``T...`、精确 `M6``M61 Q...`。精确 M-code 解析用于避免 `M428/M429/M430` 这类 switchkins special-case 被误判为 `M4`。status JSON 新增 `spindleCommandCount``spindleAppendCount``lastSpindleCommand``lastSpindle``lastSpindleSpeed``lastSpindleWait``toolCommandCount``toolAppendCount``lastToolCommand``lastTool``spindleToolAnchors`
### 理由
上游 spindle/tool canonical callbacks 构造 `EMC_SPINDLE_SPEED``EMC_SPINDLE_ON``EMC_SPINDLE_OFF``EMC_TOOL_PREPARE``EMC_TOOL_LOAD``EMC_TOOL_SET_NUMBER``EMC_TOOL_LOAD_TOOL_TABLE` 并 append 到 `interp_list`。T-044 先迁移可观测 command envelope 和 anchor evidence避免把 full native spindle control、tool DB process、IO side effects、queue ownership 和 NML transport 混入当前 WASM runtime-edge adapter。
### 影响
- T-044 可闭合,任务矩阵下一条推进到 T-045。
- `verify_task_hal_wasm.sh` 新增 `emccanon_spindle_tool_status=ok`
- 新增 `tools/verify_task_emccanon_spindle_tool.sh` 固定 T-044 上游锚点、subset API、wrapper status 和矩阵状态。
- `docs/source-reuse-map.md``docs/drift-report.md``docs/compatibility-validation.md``tools/verify_task_source_reuse_drift_docs.sh` 记录 T-044 spindle/tool 映射。
- readiness 仍保持 `nativeTaskReady=false``nativeHalSyncReady=false``fullLinuxCncProgramExecutionReady=false`
## D-035T-043 dwell/path-control 采用 `emccanon.cc` 窄 interp-list evidence
日期2026-07-08
状态:已采纳
### 决策
T-043 将 `DWELL()``SET_MOTION_CONTROL_MODE()` 纳入 `emccanon_wasm_subset``lc_emccanon_subset_dwell()` 返回 `LcEmcCanonSubsetDelay`,用于记录 `EMC_TRAJ_DELAY` / `interp_list` evidence`lc_emccanon_subset_set_motion_control_mode()` 返回 `LcEmcCanonSubsetTermCond`,用于记录 `EMC_TRAJ_SET_TERM_COND` / `interp_list` evidence。
`linuxcnc_task_hal_wasm.cpp` 在 MDI 和 staged program line 进入 straight motion 前识别 `G4``G61``G61.1``G64`,将 dwell 和 path-control 作为 canon non-motion command 记录到 `emccanonSourceReuse`,不发 motion command。status JSON 新增 `dwellCount``delayAppendCount``lastDwellSeconds``pathControlCount``termCondAppendCount``lastPathMode``lastTermCondition``lastPathTolerance``dwellPathControlAnchors`
### 理由
上游 `DWELL()` 生成 `EMC_TRAJ_DELAY` 并 append 到 `interp_list``SET_MOTION_CONTROL_MODE()` 生成 `EMC_TRAJ_SET_TERM_COND` 并 append 到 `interp_list`。T-043 先迁移可观测的 command envelope 和状态证据,避免把 full native blend planner、canon tag、queue ownership 和 NML transport 一次性引入。
### 影响
- T-043 可闭合,任务矩阵下一条推进到 T-044。
- `verify_task_hal_wasm.sh` 新增 `emccanon_dwell_path_control_status=ok`
- 新增 `tools/verify_task_emccanon_dwell_path_control.sh` 固定 T-043 上游锚点、subset API、wrapper status 和矩阵状态。
- `docs/source-reuse-map.md``docs/drift-report.md``docs/compatibility-validation.md``tools/verify_task_source_reuse_drift_docs.sh` 记录 T-043 dwell/path-control 映射。
- readiness 仍保持 `nativeTaskReady=false``nativeHalSyncReady=false``fullLinuxCncProgramExecutionReady=false`
## D-034T-042 straight traverse/feed 采用 `emccanon.cc` 窄 linear-move envelope
日期2026-07-08
状态:已采纳
### 决策
T-042 将 `generate_fast_move()``generate_move()``STRAIGHT_TRAVERSE()``STRAIGHT_FEED()``EMC_TRAJ_LINEAR_MOVE` / `interp_list` 的关系固定在 `emccanon_wasm_subset` 和 task-HAL status evidence 中。`lc_emccanon_subset_straight_traverse()``lc_emccanon_subset_straight_feed()` 继续返回 `LcEmcCanonSubsetLinearMove`wrapper 在 `taskintf_command_from_canon()` 处统一记录 straight traverse/feed 计数、linear move append 计数、最后 line、最后 canonical motion type、最后 interp_list command 和 `straightMotionAnchors`
该边界仍不实现完整 LinuxCNC canon offsets、tag、feed mode、acc/jerk、NURBS 或 NML queue ownership生成的 linear move envelope 随后通过既有 `taskintf.cc` `emcTrajLinearMove()` / `lcmot_write_linear_move()` 结构化 motion 边界进入 motion runtime。
### 理由
T-041 已迁入 canon 初始化、finish、reset、单位和 endpoint getter但 straight traverse/feed 的 `interp_list` evidence 仍只通过泛化 issueCount 间接体现。T-042 把 `EMC_TRAJ_LINEAR_MOVE``interp_list` append 作为可观测 status 字段固定下来,使后续 T-043/T-044/T-045 可以继续迁移 dwell、path-control、spindle/tool 和 motion output而不混淆 full native canon promotion。
### 影响
- T-042 可闭合,任务矩阵下一条推进到 T-043。
- `verify_task_hal_wasm.sh` 新增 `emccanon_straight_motion_status=ok`
- 新增 `tools/verify_task_emccanon_straight_motion.sh` 固定 T-042 上游锚点、subset API、wrapper status 和矩阵状态。
- `emccanonSourceReuse` 新增 `straightTraverseCount``straightFeedCount``linearMoveAppendCount``lastLinearMoveLine``lastLinearMoveType``lastInterpListCommand``straightMotionAnchors`
- readiness 仍保持 `nativeTaskReady=false``nativeHalSyncReady=false``fullLinuxCncProgramExecutionReady=false`
## D-033T-041 canon init/finish/unit/endpoint 采用 `emccanon.cc` 窄状态子集
日期2026-07-08
状态:已采纳
### 决策
T-041 将 `INIT_CANON()``ON_RESET()``FINISH()``USE_LENGTH_UNITS()``GET_EXTERNAL_LENGTH_UNITS()``GET_EXTERNAL_ANGLE_UNITS()``GET_EXTERNAL_POSITION*()` 纳入 `emccanon_wasm_subset`,通过 `LcEmcCanonSubsetState` 保存 initialized、finish/reset 计数、长度/角度单位和 external endpoint。
`linuxcnc_task_hal_wasm.cpp` 在 session init、motion update、plan reset、canon move issue 路径调用该 subset并将 `emccanonSourceReuse` status JSON 扩展为 `initCount``finishCount``resetCount``unitSetCount``positionGetCount``endpointUpdateCount``lengthUnits``externalLengthUnits``externalAngleUnits``endpoint``initFinishUnitAnchors`。该状态只作为 deterministic Web simulation evidence不提升 full native interpreter/canon ownership。
### 理由
T-040 已让 staged program line 进入 `interp_list`/taskintf issue 等价路径,但 canon 初始化、finish、reset、单位和 endpoint getter 仍由 wrapper 自有字段表达。上游 `emccanon.cc` 中这些函数是 interpreter/canon 状态与 `EMC_STAT` 可观测位置/单位之间的基础边界,先迁入窄 subset 可以为 T-042 的 `STRAIGHT_TRAVERSE()`/`STRAIGHT_FEED()` motion command 继续收敛状态来源。
### 影响
- T-041 可闭合,任务矩阵下一条推进到 T-042。
- `verify_task_hal_wasm.sh` 新增 `emccanon_init_finish_unit_status=ok`
- 新增 `tools/verify_task_emccanon_init_finish_unit.sh` 固定 T-041 上游锚点、subset API、wrapper status 和矩阵状态。
- `docs/source-reuse-map.md``docs/drift-report.md``docs/compatibility-validation.md``tools/verify_task_source_reuse_drift_docs.sh` 记录 T-041 canon init/finish/unit/endpoint 映射。
- readiness 仍保持 `nativeTaskReady=false``nativeHalSyncReady=false``fullLinuxCncProgramExecutionReady=false`
## D-032T-040 plan read/execute 接管 staged program 主路径
日期2026-07-08
状态:已采纳
### 决策
T-040 将 `emcTaskPlanRead()``emcTaskPlanExecute()``emcTaskPlanLine()``emcTaskPlanLevel()``emcTaskPlanCommand()` 纳入 `emctask_wasm_subset`,并通过 `LcEmcTaskSubsetPlanIoResult` 返回 read/execute/line/level/command 与 `interp_list` append 证据。
`EMC_TASK_PLAN_RUN` 不再要求 host 预先调用 `lctask_load_program_motion_plan_json()`;只要 staged FS 中已有 open programtask cycle 可通过 PlanRead/Command/Execute 读取 staged program lines再映射到现有 `emccanon` straight motion 和 `taskintf` structured motion issue 路径。为了避免 T-039 的 wait flag 阻塞 T-040 readRUN 起点不再立即 set-waitwait flag 改为在 staged program 行读完后记录并清理,表达上游 execute-finish 后等待 outstanding work 的窄语义。
完整 LinuxCNC interpreter、subroutine call stack、完整 `interp_list` 命令类型和 canon unit/endpoint 状态仍留给 T-041 之后继续迁移;`lctask_load_program_motion_plan_json()` 暂保留为 timed-plan 兼容入口,后续 T-046 再降级或移除。
### 理由
T-039 已把 plan open/wait/synch/reset 状态迁入 subset但 RUN 主路径仍依赖 host JSON motion plan。上游 `emctaskmain.cc` 的 readahead loop 是 `PlanRead -> PlanLine/Command -> PlanExecute -> interp_list`T-040 先建立这个窄边界,使 staged program 可直接驱动 motion issuing不再把 JSON motion plan 作为 RUN 的必要条件。
### 影响
- T-040 可闭合。
- status JSON 的 `emctaskSourceReuse` 新增 `planReadCount``planExecuteCount``planLineCount``planLevelCount``planCommandCount``interpListAppendCount``planReadExecuteAnchors` 等证据字段。
- `verify_task_hal_wasm.sh` 新增 no-json staged program RUN smoke输出 `emctask_plan_read_execute_status=ok`
- `verify_task_state_matrix.mjs` 将旧的 `INTERPRETER_PLAN_REQUIRED` JSON-plan gate 调整为 staged program 可执行。
- 新增 `tools/verify_task_emctask_plan_read_execute.sh` 固定该边界。
- readiness 仍保持 `nativeTaskReady=false``nativeHalSyncReady=false``fullLinuxCncProgramExecutionReady=false`
## D-031T-039 plan wait/open/synch/reset 采用 `emctask.cc` 窄 plan-result 子集
日期2026-07-08
状态:已采纳
### 决策
T-039 将 `emcTaskPlanSetWait()``emcTaskPlanIsWait()``emcTaskPlanClearWait()``emcTaskPlanSynch()``emcTaskPlanOpen()``emcTaskPlanClose()``emcTaskPlanReset()` 纳入 `emctask_wasm_subset`,并通过 `LcEmcTaskSubsetPlanState` / `LcEmcTaskSubsetPlanResult` 表达 plan wait flag、taskplanopen、行号清零、synch、close、reset 等窄语义。
staged FS 和 program text 仍由 WASM wrapper 管理subset 只接收“文件是否已 staged”的布尔边界并返回与上游 `interp.open()` 成功后类似的状态变化。完整 LinuxCNC interpreter read/execute、call level、command text、`interp_list` 驱动留给 T-040。
### 理由
上游 `emctask.cc` 的 plan wait/open/close/reset 是 `emcTaskPlan()` 与 interpreter 之间的关键边界。当前 WASM runtime 已有 staged FS 和简单 program state但这些状态此前直接由 wrapper 修改。T-039 先把 wait flag、taskplanopen、synch/open/close/reset 决策迁到 source-anchored subset可以在不提升 full native interpreter readiness 的前提下收敛 wrapper 自有 plan 语义。
### 影响
- T-039 可闭合。
- status JSON 的 `emctaskSourceReuse` 新增 `planIssueCount``planWaitSetCount``planWaitClearCount``planSynchCount``planOpenCount``planCloseCount``planResetCount``planWaitFlag``planOpenFlag``planAnchors`
- `verify_task_hal_wasm.sh` 新增 plan open/wait/synch evidence 断言。
- 新增 `tools/verify_task_emctask_plan_open_wait.sh` 固定该边界。
- readiness 仍保持 `nativeTaskReady=false``nativeHalSyncReady=false``fullLinuxCncProgramExecutionReady=false`
## D-030T-038 determine/update 输入改由 motion/io snapshot 提供
日期2026-07-08
状态:已采纳
### 决策
T-038 将 `wasm_emcTaskUpdate()` 传给 `lc_emctask_subset_update()` 的输入从 task wrapper 自有的 `state/mode` 字符串推导,改为优先来自 task cycle 已读取的 runtime snapshot
- `determineMode()` 的 traj mode 输入来自 `LcmotStatusSnapshot.coord_mode``teleop_mode`
- `determineState()` 的 traj enabled 输入来自 `LcmotStatusSnapshot.motion_enabled`
- IO estop 输入来自 task state 的 ESTOP latch 与 IO error latch 聚合。
- motion id 继续来自 `LcmotStatusSnapshot.motion_id`
当 motion snapshot 尚未有效时,保留 `taskStateFallback,ioSnapshot` 的降级路径;正常 task cycle 证据应记录为 `motionSnapshot,ioSnapshot`。本阶段只收敛 update 输入来源和证据字段,不提升 full native task/status container readiness。
### 理由
上游 `emctask.cc``determineMode()``determineState()``emcTaskUpdate()` 读取的是 motion/io 侧状态,而不是由 task wrapper 自行按字符串猜测。T-038 使用当前 task cycle 内的 `LcmotStatusSnapshot` 固定这个边界,可以让 update 语义更接近上游,同时保持 T-022/T-023 已建立的 command buffer、cycle 阶段和 status write 语义。
### 影响
- T-038 可闭合。
- status JSON 的 `emctaskSourceReuse` 新增 `snapshotUpdateCount``updateInputSource`
- `verify_task_hal_wasm.sh` 新增 snapshot-fed update 断言。
- 新增 `tools/verify_task_emctask_update_snapshot.sh` 固定 `determineMode()``determineState()``emcTaskUpdate()` 的 motion/io snapshot 输入边界。
- readiness 仍保持 `nativeTaskReady=false``nativeHalSyncReady=false``fullLinuxCncProgramExecutionReady=false`
## D-029T-037 abort/state/mode 采用 `emctask.cc` 窄 command-result 子集
日期2026-07-08
状态:已采纳
### 决策
T-037 将 `emcTaskAbort()``emcTaskSetMode()``emcTaskSetState()` 纳入 `emctask_wasm_subset`,并通过 `LcEmcTaskSubsetCommandResult` 返回 task wrapper 要执行的清理/下发决策:
- 清理 interpreter / exec / pause / stepping 状态。
- state ON 时触发 traj enable。
- state OFF/ESTOP 时触发 traj disable、motion abort、home reset 和 volatile unhome。
- explicit abort 时触发 motion abort。
- mode MANUAL/AUTO/MDI 时由 subset 返回目标 mode 和 traj mode同步清理 task 执行态。
为了保持当前 standalone `lcmot` 的语义稳定,`emcTaskSetMode(AUTO/MDI)` 的窄子集只执行 task/interpreter 清理和 plan synch 标记,不向 `lcmot` 下发 motion abort。完整上游 `emcTaskAbort()` 包含 motion abort但当前 `lcmot` 的 abort 是终止状态;若 set-mode 直接下发 motion abort会破坏已有 run smoke。该差异保留为 runtime-edge 降级,后续 native motion abort/reset 语义完善后再收紧。
### 理由
T-037 的目标是把 abort/state/mode 的决策来源迁入 source-anchored `emctask.cc` 子集,同时不改变 T-022/T-023 已建立的 command buffer 和 task cycle 触发语义。使用 command-result 可以让 wrapper 继续拥有 standalone runtime 状态容器,但不再在分支里直接手写每个上游函数族的决策。
### 影响
- T-037 可闭合。
- status JSON 的 `emctaskSourceReuse` 新增 `stateModeIssueCount``abortIssueCount``stateModeAnchors`
- `verify_task_hal_wasm.sh` 继续覆盖 `emctaskSourceReuse`state matrix 继续证明 send command 不直接改变状态。
- 新增 `tools/verify_task_emctask_state_mode.sh` 固定该边界。
- readiness 仍保持 `nativeTaskReady=false``nativeHalSyncReady=false``fullLinuxCncProgramExecutionReady=false`
## D-028T-036 jog/home/switchkins 通过结构化 `lcmot_write_*` 下发
日期2026-07-08
状态:已采纳
### 决策
T-036 将 `taskintf.cc` 的 jog/home/switchkins 子集继续从 task wrapper JSON 兼容路径收拢到结构化 ABI
- `emcJogIncr()` -> `lcmot_write_jog_incr()`
- `emcJointHome()` -> `lcmot_write_joint_home()`
- `emcJointUnhome()` -> `lcmot_write_joint_unhome()`
- `emcMotionSetAout()` -> `lcmot_write_aout()`
`taskintf_wasm_subset` 新增 `lc_taskintf_subset_jog_incr_ex()``lc_taskintf_subset_joint_unhome()`,保留 jog 的 axis/joint mode、distance、velocity、motion id以及 home/unhome/switchkins 的 command envelope。非本批次的完整 home 状态机、joint active/deactive、limit override、absolute/continuous jog 仍留待后续任务。
### 理由
上游 `taskintf.cc` 对这些函数同样是填充 `emcmotCommand` 并通过 `usrmotWriteEmcmotCommand()` 发送给 motion。T-035 已把 linear move 的主路径改为结构化 ABIT-036 继续把 Home/Jog/M428-M430 的现有 smoke 从 JSON 拼接下发迁到结构化 bridge减少 task wrapper 自有 motion command 语义。
### 影响
- T-036 可闭合。
- `lcmot` 新增 `lcmot_write_jog_incr()``lcmot_write_joint_home()``lcmot_write_joint_unhome()``lcmot_write_aout()`
- status JSON 的 `taskintfSourceReuse` 新增 `jogHomeSwitchkinsIssueCount``jogHomeSwitchkinsStructuredIssueCount``jogHomeSwitchkinsAnchors`
- `verify_task_hal_wasm.sh` 新增 `taskintf_jog_home_switchkins_status=ok`
- 新增 `tools/verify_task_taskintf_jog_home_switchkins.sh` 固定该边界。
- readiness 仍保持 `nativeTaskReady=false``nativeHalSyncReady=false``fullLinuxCncProgramExecutionReady=false`
## D-027T-035 linear move 通过结构化 `lcmot_write_linear_move()` 下发
日期2026-07-08
状态:已采纳
### 决策
T-035 不再让 task wrapper 为 `emcTrajLinearMove()` 主路径拼接 motion JSON。`taskintf_wasm_subset` 新增 `lc_taskintf_subset_linear_move_ex()`,保留 line、motion type、motion id、vel、ini maxvel、acceleration、ini maxjerk 和目标 posetask runtime 对 linear move 调用结构化 `lcmot_write_linear_move()`pending execute 队列也携带 `LcTaskIntfSubsetMotionCommand`flush 时继续走结构化 ABI。
非 linear 的 jog/home/switchkins/traj control 暂时保留现有 JSON 兼容路径,留给 T-036 继续收拢。
### 理由
上游 `emcTrajLinearMove()` 直接填充 `emcmotCommand`,设置 `EMCMOT_SET_LINE`、目标 pose、motion id、tag、motion type、速度/加速度/jerk 等字段,然后通过 `usrmotWriteEmcmotCommand()` 写给 motion。T-035 的结构化 ABI 比 task wrapper JSON 拼接更接近这个边界,也能让 G0/G1 smoke 同时覆盖 `STRAIGHT_TRAVERSE``STRAIGHT_FEED`
### 影响
- T-035 可闭合。
- `lcmot` 新增 `lcmot_write_linear_move()`
- status JSON 的 `taskintfSourceReuse` 新增 `linearMoveIssueCount``linearMoveStructuredIssueCount``linearMoveAnchors`
- `verify_task_hal_wasm.sh` 新增 `taskintf_linear_move_status=ok`
- 新增 `tools/verify_task_taskintf_linear_move.sh` 固定该边界。
- readiness 仍保持 `nativeTaskReady=false``nativeHalSyncReady=false``fullLinuxCncProgramExecutionReady=false`
## D-026T-034 traj control 先接入 `lcmot` 状态和 command envelope
日期2026-07-08
状态:已采纳
### 决策
T-034 将 `taskintf.cc` 的 traj control 子集纳入 `taskintf_wasm_subset`
- `emcTrajSetMotionId()`
- `emcTrajEnable()`
- `emcTrajDisable()`
- `emcTrajAbort()`
- `emcTrajPause()`
- `emcTrajStep()`
- `emcTrajResume()`
`lcmot` 增加 `motion_enabled``next_motion_id` 状态。SetMotionId 影响后续 linear/jog motion idEnable/Disable 更新 motion enabled 状态。为了不破坏既有 low-level motion smoke当前 runtime 仍允许初始化后直接发送 low-level motion command。
### 理由
上游 `taskintf.cc` 通过 `usrmotWriteEmcmotCommand()` 将这些 traj control 命令发送给 motion。T-033 已建立 motion init/update/abort bridgeT-034 继续把 pause/step/resume/abort 以及 enable/disable/set-motion-id 收拢到同一个 source-anchored traj control 子集,减少 task wrapper 自行拼接 motion control 语义。
### 影响
- T-034 可闭合。
- status JSON 的 `taskintfSourceReuse` 新增 `trajControlIssueCount``trajControlAnchors`
- motion status 新增 `enabled``nextMotionId`
- `verify_task_hal_wasm.sh` 新增 `taskintf_traj_control_status=ok`
- 新增 `tools/verify_task_taskintf_traj_control.sh` 固定该边界。
- readiness 仍保持 `nativeTaskReady=false``nativeHalSyncReady=false``fullLinuxCncProgramExecutionReady=false`
## D-025T-033 先实现 `taskintf.cc` motion bridge 的窄 init/update/abort 子集
日期2026-07-08
状态:已采纳
### 决策
T-033 不直接编译完整 `taskintf.cc``usrmotintf.cc`,而是在 `taskintf_wasm_subset` 中新增 motion bridge 子集:
- `lc_taskintf_subset_motion_init()`
- `lc_taskintf_subset_motion_update()`
- `lc_taskintf_subset_motion_abort()`
底层 `lcmot` 同步新增:
- `LcmotConfigSnapshot`
- `lcmot_read_config_snapshot()`
- `lcmot_read_error_message()`
task runtime 的 `lctask_init_session()`、周期 motion update 和 task abort path 必须通过这个 bridge。
### 理由
上游 `emcMotionInit()``emcMotionUpdate()``emcMotionAbort()` 是 task 到 motion 的关键边界,但完整上游实现仍依赖 native usrmot shared memory、RTAPI、NML 和完整 motion config/error ring。当前阶段先实现窄 bridge可以让 task 周期更接近 `taskintf.cc` 结构,同时不把未完成 native topology 提前标为 ready。
### 影响
- T-033 可闭合。
- status JSON 新增 `taskintfMotionBridge` 验证面。
- `verify_task_hal_wasm.sh` 新增 `taskintf_motion_bridge_status=ok`
- 新增 `tools/verify_task_taskintf_motion_bridge.sh` 固定该边界。
- readiness 仍保持 `nativeTaskReady=false``nativeHalSyncReady=false``fullLinuxCncProgramExecutionReady=false`
## D-024`taskintf.cc` usrmot shim 采用窄 `lcmot_*` bridge不直接编译完整 `usrmotintf.cc`
日期2026-07-08
状态:已采纳
### 决策
T-032 采用窄 usrmot shim
```text
taskintf.cc-compatible calls
-> wasm usrmot shim
-> lcmot_* C ABI
-> standalone motion runtime
```
command write 映射到 `lcmot_write_command_json()`status read 映射到 `lcmot_read_status_snapshot()`。config read 和 error read 不假装已实现,分别要求后续新增 `lcmot_read_config_snapshot()``lcmot_read_error_message()` 或等价 ABI。
### 理由
完整上游 `usrmotintf.cc` 依赖 native shared memory、mutex、command ack 轮询、split read、RTAPI init/exit、motion error ring 和 compensation file loading。WASM 当前是同进程 standalone motion runtime没有 native emcmot process 和 shared memory ack 通道。
窄 shim 可以让 T-033 先实现 `emcMotionInit()``emcMotionUpdate()``emcMotionAbort()` 的必要路径,同时保持 readiness 口径保守。
### 影响
- T-032 可闭合。
- 新增 `working/10-taskintf-usrmot-shim设计.md`
- 新增 `tools/verify_task_usrmot_shim_design.sh`
- 后续 T-033 实现时必须先补齐或显式处理 config/error read 缺口。
- 不得把该设计解释为 `nativeTaskReady=true``nativeHalSyncReady=true`
## D-023source reuse / drift 文档必须固定 task-HAL 未提升口径
日期2026-07-08
状态:已采纳
### 决策
T-030 后,`docs/source-reuse-map.md``docs/drift-report.md``docs/compatibility-validation.md` 必须同步记录当前 task/motion/HAL runtime 阶段:
- task-cycle motion snapshot、command buffer、plan/execute/motion-update/subordinate-sync/status-write 阶段已存在。
- motion ERROR、soft-limit、top/task/motion/io RCS DONE/EXEC/ERROR 聚合已验证。
- `emctask.cc``taskintf.cc``emccanon.cc` 只有窄 source-anchored subsets。
- 完整 `emc_nml.hh` 只评估,不 vendored、不直接 include。
- readiness 仍为 `task_hal_runtime_promoted=0``nativeTaskReady=false``nativeHalSyncReady=false``fullLinuxCncProgramExecutionReady=false`
### 理由
T-027/T-028/T-029 已经增加了明显更接近 LinuxCNC task 主循环的行为。如果 source reuse 和 drift 文档不及时更新,后续容易把 Web simulation adapter 误读为 full native task/HAL promotion或把 `emc_nml.hh` 误读为已经可直接 include。
### 影响
- T-030 可闭合。
- 新增 `tools/verify_task_source_reuse_drift_docs.sh` 作为文档一致性 gate。
- 后续 T-032+ 继续推进 usrmot/NML shim 时,必须同步更新这些文档和验证脚本。
## D-022`emc_nml.hh` 暂不直接 include先走分阶段 typedef / 窄 status 容器
日期2026-07-08
状态:已采纳
### 决策
T-029 不直接 include 完整上游 `emc_nml.hh`。当前阶段先采用分阶段 typedef / 窄 `StandaloneEmcStatus` 路线。
### 理由
`emc_nml.hh` 当前未 vendored 到 `wasm-port/vendor/linuxcnc/src/emc/nml_intf/`。完整上游头文件会拉入 `libnml`、CMS、command/status message 基类、RS274 modal state、canon/tool table 和 active G/M/settings arrays。直接 include 会把 NML transport、CMS serialization、RS274/canon 状态和完整 IO/tool/spindle object graph 提前混入 task main loop 迁移。
当前阶段刚闭合 T-028 的 DONE/EXEC/ERROR 聚合,还未完成 T-007 的集中 `EMC_STAT` 等价容器,也未完成 T-032+ 的 usrmot/NML shim。直接 include 风险高于收益。
### 影响
- T-029 可闭合。
- 新增 `working/09-emc_nml复用评估.md` 作为复用路线记录。
- 新增 `tools/verify_task_emc_nml_reuse_plan.sh` 固定该决策。
- 后续 T-007 建立 `StandaloneEmcStatus` 时,字段命名必须继续对齐 `EMC_STAT` 家族。
- 后续 T-032+ 补齐 usrmot/NML shim 后,再评估是否 vendor 完整 `emc_nml.hh` 或抽取 status subset header。
## D-021top-level RCS_STATUS 聚合先采用明确 DONE/EXEC/ERROR 字符串
日期2026-07-08
状态:已采纳
### 决策
T-028 先在 standalone task runtime 中维护字符串形式的 RCS 聚合状态:
- `top_level_rcs_status`
- `task_rcs_status`
- `motion_rcs_status`
- `io_rcs_status`
status JSON 导出 `taskTopLevelStatus``rcsStatus.top/task/motion/io``task.status`。聚合顺序按上游 `emctaskmain.cc` 顶层 status write 口径ERROR 优先,其次 DONE最后 EXEC。
### 理由
当前阶段尚未直接复用 `emc_nml.hh` 的完整 `EMC_STAT` 类型T-029 会单独评估直接 include 或窄 shim。为了先闭合 T-028 的行为验收,用字符串形式记录 DONE/EXEC/ERROR 可以避免提前拉入未评估的 NML 依赖,同时让 JSON surface 明确反映 task/motion/io 三方状态。
### 影响
- T-028 可闭合。
- `write_status_snapshot()` 每次写 status buffer 前刷新 top-level 聚合。
- 现有 `taskTopLevelStatus` 继续保留,但现在来自显式 `top_level_rcs_status`
- 后续 T-029/T-030 可以再决定是否把这些字符串替换或映射为 vendored `RCS_STATUS` enum。
## D-020motion ERROR 和 soft-limit 先以测试注入命令覆盖 subordinate sync
日期2026-07-08
状态:已采纳
### 决策
T-027 先在 standalone motion runtime 中加入两个测试注入命令:
- `EMCMOT_INJECT_ERROR`
- `EMCMOT_INJECT_SOFT_LIMIT`
它们只用于验证 task 周期内 subordinate sync 对 motion ERROR 和 soft-limit snapshot 字段的处理,不代表完整 LinuxCNC motion controller 错误模型已迁移完成。
### 理由
当前 motion runtime 仍是 deterministic Web simulation adapter。要对齐 `emctaskmain.cc` 的 subordinate sync 行为,需要先有可重复、低成本的 motion error/soft-limit 输入,而不是等待完整 native motion controller 或硬件 limit switch 边界完成。
### 影响
- T-027 可闭合。
- `LcmotStatusSnapshot` 尾部追加 `motion_error``on_soft_limit`,保留已有 C ABI struct 字段 offset。
- task status JSON 新增 `motion.status``motion.motionError``motion.onSoftLimit`
- task status JSON 新增最小 `taskTopLevelStatus`,用于 T-027 覆盖 ERROR/DONE/EXEC 表面;完整 `RCS_STATUS` 聚合仍由 T-028 推进。
- `sync_subordinate_states()` 能把 soft-limit 映射为 `MOTION_SOFT_LIMIT`,把 motion ERROR 映射为 `MOTION_ERROR`
- 后续 T-028 可以基于这些字段继续做 top-level `RCS_STATUS` 聚合。
## D-019readiness 字段保持 false直到 full native task/HAL promotion 真实闭合
日期2026-07-08
状态:已采纳
### 决策
当前 task/motion/HAL simulation runtime 继续标记为 runtime-edge adapter不标记为 full native task/HAL promotion。
当前 readiness contract 固定为:
- `task_hal_runtime_promoted=0`
- `nativeTaskReady=false`
- `nativeHalSyncReady=false`
- `fullLinuxCncProgramExecutionReady=false`
`docs/source-reuse-map.md` 必须使用上述口径,不得声称 full boundary gates 已将 `nativeTaskReady``nativeHalSyncReady` 置为 true。
### 理由
当前 WASM runtime 已有 phase 0 source/probe gates、phase 2 HAL registry、phase 3 motion/HAL servo-cycle C ABI、phase 4 task shim、SDK wrapper以及 `emctask.cc``taskintf.cc``emccanon.cc` 的窄 source-anchored subsets。但完整 `emctaskmain.cc` 主循环、NML/native process topology、native HAL sync、full LinuxCNC program execution、硬件 IO、external user-M process 和完整 tool DB process 仍未迁移完成。
如果此阶段把 readiness 置 true会误导后续验收和发布口径。
### 影响
- T-015 可闭合。
- 新增 `tools/verify_task_hal_readiness_contract.sh` 作为 readiness 文档/实现一致性 gate。
- `verify_task_hal_wasm.mjs` 明确断言 `fullLinuxCncProgramExecutionReady=false`
- 后续只有在 full native task cycle、native HAL sync、完整 program execution 分别完成并有独立验收证据时,才能改变对应 readiness 字段。
## D-018先引入 `emccanon.cc` canonical linear motion 子集
日期2026-07-07
状态:已采纳
### 决策
T-014 先引入 `emccanon.cc` 的 canonical linear motion 子集,而不是直接编译完整 `emccanon.cc`
新增 vendored 文件:
- `runtime/core/linuxcnc_task_subset/emccanon_wasm_subset.hh`
- `runtime/core/linuxcnc_task_subset/emccanon_wasm_subset.cc`
该子集锚定上游 `src/emc/task/emccanon.cc`
- `generate_fast_move()`
- `generate_move()`
- `STRAIGHT_TRAVERSE()`
- `STRAIGHT_FEED()`
task-HAL WASM build 编译该子集task runtime 调用它生成 canonical linear move envelope然后交给 `taskintf_wasm_subset` 生成 task-to-motion command envelope。
### 理由
完整 `emccanon.cc` 直接依赖 canon 全局状态、offset/unit conversion、`interp_list`、state tags、NURBS、spindle/tool/coolant 等大量 canonical callback 边界。当前阶段先迁入 linear motion envelope可以让 motion command 生成路径形成 `emccanon -> taskintf -> lcmot` 的分层,而不把未完成的 interpreter/canon 全量状态边界混入 T-014。
### 影响
- T-014 可闭合。
- `emccanonSourceReuse` status 字段记录 source path、anchors 和 issue count。
- `nativeTaskReady``nativeHalSyncReady``fullLinuxCncProgramExecutionReady` 仍保持 false。
- 后续 T-041/T-042/T-043/T-044/T-045 可以继续把 canon init、straight motion、dwell/path-control、spindle/tool、motion output/switchkins 子集迁入。
- `tools/verify_task_emccanon_subset.sh` 成为该子集的 source reuse gate。
## D-017先引入 `taskintf.cc` motion command envelope 子集
日期2026-07-07
状态:已采纳
### 决策
T-013 先引入 `taskintf.cc` 的 motion command issuing 子集,而不是直接编译完整 `taskintf.cc`
新增 vendored 文件:
- `runtime/core/linuxcnc_task_subset/taskintf_wasm_subset.hh`
- `runtime/core/linuxcnc_task_subset/taskintf_wasm_subset.cc`
该子集锚定上游 `src/emc/task/taskintf.cc`
- `emcTrajAbort()`
- `emcTrajPause()`
- `emcTrajStep()`
- `emcTrajResume()`
- `emcTrajLinearMove()`
- `emcJogIncr()`
- `emcJointHome()`
- `emcMotionSetAout()`
task-HAL WASM build 编译该子集task runtime 调用它生成 `LcTaskIntfSubsetMotionCommand`,再由 standalone bridge 序列化给现有 `lcmot_*` runtime edge。
### 理由
完整 `taskintf.cc` 直接依赖 `usrmot`、NML、INI config 和 native motion process。当前阶段的目标是把 task-to-motion issuing 语义先向 LinuxCNC 源码锚点靠拢,而不是一次性恢复 native motion process topology。
### 影响
- T-013 可闭合。
- `taskintfSourceReuse` status 字段记录 source path、anchors 和 issue count。
- `nativeTaskReady``nativeHalSyncReady``fullLinuxCncProgramExecutionReady` 仍保持 false。
- 后续 T-033/T-034/T-035/T-036 可以继续把 motion init/update、traj control、linear move、jog/home/switchkins 子集替换为更完整的 `taskintf.cc` bridge。
- `tools/verify_task_taskintf_subset.sh` 成为该子集的 source reuse gate。
## D-016先引入 `emctask.cc` 状态推导可编译子集
日期2026-07-07
状态:已采纳
### 决策
T-012 先引入 `emctask.cc` 的最小可编译状态推导子集,而不是直接编译完整 `emctask.cc`
新增 vendored 文件:
- `runtime/core/linuxcnc_task_subset/emctask_wasm_subset.hh`
- `runtime/core/linuxcnc_task_subset/emctask_wasm_subset.cc`
该子集锚定上游 `src/emc/task/emctask.cc`
- `determineMode()`
- `determineState()`
- `emcTaskUpdate()`
task-HAL WASM build 编译该子集,`wasm_emcTaskUpdate()` 调用 `lc_emctask_subset_update()`status JSON 暴露 `emctaskSourceReuse` 证据。
### 理由
完整 `emctask.cc` 直接依赖 interpreter、NML、dynamic loading、IO 和 native process 边界。当前阶段若强行编译完整文件,会把多个尚未设计的 runtime edge 混入 T-012风险和任务边界都过大。
先引入状态推导子集可以让 task update 阶段开始使用上游 `emctask.cc` 的明确语义锚点,同时保留 readiness false避免误报完整 native task runtime 已迁移。
### 影响
- T-012 可闭合。
- `nativeTaskReady``nativeHalSyncReady``fullLinuxCncProgramExecutionReady` 仍保持 false。
- 后续 T-013/T-014/T-037/T-038 可继续把 `taskintf.cc``emccanon.cc``emctask.cc` 的命令和 update 函数族迁入。
- `tools/verify_task_emctask_subset.sh` 成为该子集的 source reuse gate。
## D-015host JSON command 只在 C ABI 边界解析为内部 TaskCommand
日期2026-07-07
状态:已采纳
### 决策
`lctask_send_command_json()` 只承担 host boundary 职责:校验 JSON command envelope、解析为内部 `TaskCommand`、入队 command buffer、写 status buffer。task 语义不再通过该函数执行。
`wasm_emcTaskPlan()` 从 command buffer 读取 `TaskCommand`,调用内部 `apply_task_command()` 处理 state/mode/run/pause/resume/step/abort/MDI/JOG/HOME/IO shim 语义。
### 理由
此前 plan 阶段通过设置 processing 标志并递归调用 `lctask_send_command_json()` 来复用语义分支,导致 C ABI host 边界和 task plan 语义混在一起。T-011 要求 JSON 只作为 C ABI host 边界;内部 task 周期应处理结构化 command envelope后续才能逐步替换为 `emctask.cc``taskintf.cc``emccanon.cc` 的源码子集。
### 影响
- T-011 可闭合。
- 未知 host JSON command 在 send 边界直接返回 `-1`,不进入 pending command queue。
- run gate/home gate 等语义拒绝保持为 task 状态错误:写 `errorText`,但 `lctask_run_cycles()` 不因此失败。
- 后续 T-012/T-013/T-014 可把 `apply_task_command()` 内部 command 家族逐步替换为 vendored LinuxCNC 源码 bridge。
## D-014pause/resume/step motion issue 进入 execute 阶段
日期2026-07-07
状态:已采纳
### 决策
`EMC_TASK_PLAN_PAUSE``EMC_TASK_PLAN_STEP``EMC_TASK_PLAN_RESUME` 在 plan command handler 中只更新 task/interpreter 状态并排入 `pending_execute_motion_commands`,实际 `EMC_TRAJ_PAUSE``EMC_TRAJ_STEP``EMC_TRAJ_RESUME``wasm_emcTaskExecute()` 统一发给 motion runtime。
### 理由
上游 task 主循环中,外部 command 先进入 task 周期,再通过 plan/execute 阶段影响 motion。若 pause/resume/step 在 `lctask_send_command_json()` 时直接 forward motion会绕过 command buffer 和周期 snapshot和 T-022/T-023/T-025 建立的边界不一致。
### 影响
- T-010 可闭合。
- pause/resume/step 测试需要先断言 send 后 `pendingCommandDepth` 增加、motion snapshot 不变,再断言 run cycle 后 motion 状态变化。
- 后续 T-034 可把这组 traj control 命令继续替换为 `taskintf.cc``emcTrajPause/Step/Resume()` bridge。
## D-013native TRT phase0 probe 使用运行目录机器配置 overlay
日期2026-07-07
状态:已采纳
### 决策
`probe_trt_task_hal_runtime.sh` 不直接修改 `../linuxcnc`。脚本在 `build/native/trt-task-hal-runtime/machine` 生成机器配置 overlay
- 优先 symlink 只读上游 `../linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/` 的顶层条目。
- 对上游缺失的顶层条目,从 `wasm-port/vendor/linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/` 补 symlink。
- 输出 `trt_task_hal_vendor_overlay_*` 证据,保留 fallback 来源。
### 理由
`verify_task_hal_phase0.sh` 失败的直接原因是上游工作树缺失 `xyzac-trt_cmds.hal`,但 `wasm-port/AGENTS.md` 明确 `../linuxcnc` 是只读输入。运行目录 overlay 可以稳定 native probe 的机器配置输入,同时不污染上游树,也能保留 vendor 来源证据。
### 影响
- T-016 可闭合。
- phase0 gate 当前通过,输出 `task_hal_phase0_native_probe_gate=ok`
- nativeTaskReady/readiness 仍保持保守 falseoverlay 只修复 probe 输入完整性,不代表完整 LinuxCNC task/HAL runtime 已迁移完成。
## D-012区分 task 发起 abort cleanup 与外部 motion/io error
日期2026-07-07
状态:已采纳
### 决策
subordinate sync 阶段区分两类 abort/error
- task 自己发起的 abort 通过 `task_abort_requested` 标记为预期 cleanupmotion aborted 后 task `exec_state` 保持 `DONE`
- 外部 motion abort/error 没有 `task_abort_requested` 标记motion snapshot 显示 aborted 后 task 进入 `ERROR``error_text=MOTION_ABORTED`
- standalone IO runtime edge 暂用 `EMC_IO_INJECT_ERROR` 作为窄测试 shim进入周期后由 subordinate sync 置 `ERROR``error_text=IO_ERROR`
### 理由
LinuxCNC task 主循环需要区分主动 abort 清理和 subordinate 进程错误。如果二者都映射为 `DONE`motion/io error 不会暴露;如果二者都映射为 `ERROR`,用户主动 abort 会被误报。
### 影响
- T-009 可闭合。
- IO shim 只是 standalone 测试边界,不代表真实 LinuxCNC IO 进程已迁移。
- T-027 仍需补 soft-limit 等更细的 motion error 注入。
## D-011wait-for-motion 和 queueFull 以周期 motion snapshot 为准
日期2026-07-07
状态:已采纳
### 决策
`WAITING_FOR_MOTION``WAITING_FOR_MOTION_QUEUE` 的切换必须由 task 周期内的 `LcmotStatusSnapshot` 驱动:
- execute 阶段看到上一周期 `motion_snapshot.queue_full` 时,不继续向 motion runtime issue 新 motion command。
- subordinate sync 阶段看到本周期 queueFull 解除后,把 `WAITING_FOR_MOTION_QUEUE` 切回 `WAITING_FOR_MOTION`
- subordinate sync 阶段看到 motion queue/active depth 清空且 in-position 后,把 `WAITING_FOR_MOTION` 收敛到 `DONE`
### 理由
LinuxCNC 上游 `emcTaskExecute()` 的 wait 状态依赖 motion status而 motion status 由每周期 `emcMotionUpdate()` 刷新。如果 task 在发送 command 时直接假设 motion 可用,就会绕过 `emctaskmain.cc` 的周期状态机。
### 影响
- T-008 可闭合。
- 后续 T-009/T-027 可以在同一个 subordinate sync 阶段接入 motion error、soft-limit 和 abort cleanup。
- 后续 T-028 可以基于这些 task/motion 状态继续做 top-level `RCS_STATUS` 聚合。
## D-010形成周期阶段骨架并将 MDI/JOG/HOME issue 放入 execute 阶段
日期2026-07-07
状态:已采纳
### 决策
本轮把 `lctask_run_cycles()` 拆成 `task_cycle_begin()``task_read_commands()``wasm_emcTaskPlan()``wasm_emcTaskExecute()``wasm_emcMotionUpdate()``sync_subordinate_states()``wasm_emcTaskUpdate()``update_top_level_status()``write_status_snapshot()` 等阶段函数。
当前 command handler 仍作为 Phase 4 adapter 被 `wasm_emcTaskPlan()` 调用,保证 state/mode/home/run gate 由 task cycle 触发。MDI/JOG/HOME 的 motion issue 通过 `pending_execute_motion_commands` 排队,并由 `wasm_emcTaskExecute()` 统一发给 motion runtime。
### 理由
T-023 的主要风险是让 `lctask_run_cycles()` 继续成为混合大函数,后续无法逐段替换 `emctask.cc``taskintf.cc``emccanon.cc`。先建立清晰阶段边界,可以让后续把命令族迁入对应 plan/execute 函数时保持测试稳定。
### 影响
- T-006、T-023、T-024、T-025 可闭合。
- T-008 是下一优先任务,需要把 wait-for-motion 和 queueFull 语义迁到周期 motion snapshot。
- `sync_subordinate_states()``wasm_emcTaskUpdate()``update_top_level_status()` 当前是窄占位,后续 T-027/T-028/T-038 继续扩展。
## D-008先闭合 motion snapshot/status buffer再推进 command queue
日期2026-07-07
状态:已采纳
### 决策
本轮先完成 `LcmotStatusSnapshot``lcmot_read_status_snapshot()``wasm_emcMotionUpdate()` 和 task status buffer。`lctask_read_status_json()` 只导出最后一次 task status write不再在读取时同步 motion runtime。
完成 motion snapshot/status buffer 后,本轮继续推进 `lctask_send_command_json()` 的 command slot/queue 改造,将 T-022 纳入同一批验收。T-023 的周期函数拆分仍单独推进。
### 理由
motion snapshot/status buffer 是 `emctaskmain.cc` 周期对标的前置基础。如果同时迁移 command queue、plan、execute会扩大改动面并让 status 读取边界和 command side effect 边界难以分别验收。
本轮先用测试固定low-level motion runtime 单独变化不会被 task status read 捕获,只有下一次 `lctask_run_cycles()` 才会写入 task status snapshot。随后把 task command send 改为入队,状态变化也必须等待 `lctask_run_cycles()` 消费 command。
### 影响
- T-002、T-003、T-004、T-005、T-018、T-019、T-020、T-021、T-022、T-026 可闭合。
- T-023 仍为下一优先任务,必须把 command queue 消费逻辑继续拆成 command read / plan / execute。
- 后续 T-023 拆周期函数时,应把当前 `wasm_emcMotionUpdate()``write_status_snapshot()` 保留下来,并补齐 command read、plan、execute、subordinate sync、task update 的阶段函数。
## D-009task command send 入队,语义变化由 task cycle 消费
日期2026-07-07
状态:已采纳
### 决策
`lctask_send_command_json()` 默认只验证 command 类型并写入 `TaskRuntime.pending_commands``lctask_run_cycles()` 在每个 task cycle 开始消费 pending command并在该周期内触发 state/mode/run/pause/resume/MDI/JOG/HOME/abort 等现有语义。
### 理由
LinuxCNC 上游 task 主循环通过 command buffer 在周期内读取命令,而不是让外部 send API 直接改变 task 状态。先建立 command buffer/slot可以让后续 T-023 把 command read、plan、execute 拆成明确阶段。
### 影响
- task status 新增 `pendingCommandDepth`
- 发送 command 后,如果不调用 `lctask_run_cycles()`task `state/mode/interpState/execState` 不应变化。
- 现有 command 处理逻辑仍集中在一个消费分支中T-023 需要继续拆成独立周期函数。
## D-001以 LinuxCNC `emctaskmain.cc` 周期结构作为对标主线
日期2026-07-07
状态:已采纳
### 决策
后续 task/motion/HAL runtime 推进以 LinuxCNC `emctaskmain.cc` 的主循环结构为主线,而不是继续扩展当前 `TaskRuntime` 自有状态机。
### 理由
上游 task 主循环的关键语义来自固定周期:
1. 读取 command。
2. `emcTaskPlan()`
3. `emcTaskExecute()`
4. `emcMotionUpdate(&emcStatus->motion)`
5. subordinate sync。
6. `emcTaskUpdate()`
7. status write。
当前 WASM minimal adapter 已能 smoke但 motion 状态没有成为 task 周期内的控制输入。若继续扩展自有状态机,会偏离 `wasm-port/AGENTS.md` 中“复用 LinuxCNC 源码、不要新增项目自有 CNC 语义”的原则。
### 影响
- 新开发优先补 task 周期结构。
- JSON command/status 只能作为 host boundary不作为 CNC/task 语义来源。
- 后续任务需要逐步引入 vendored/upstream task 源码或窄 shim。
## D-002motion snapshot 先结构化读取,不在 task 周期解析 JSON
日期2026-07-07
状态:已采纳
### 决策
task 周期内读取 motion 状态时,应新增结构化 C/C++ snapshot 边界,不在 `lctask_run_cycles()` 内解析 `lcmot_read_status_json()` 输出。
### 理由
- LinuxCNC 原生路径是 `emcMotionUpdate(&emcStatus->motion)` 写结构化状态。
- JSON 是 Web/SDK 输出格式,不应成为内部控制语义。
- 结构化 snapshot 更容易映射到 `EMC_STAT.motion`
### 影响
- `linuxcnc_motion_runtime.c` 需要新增内部 snapshot 读取函数或共享 header。
- `status_json()` 后续应导出 task 已持有的 snapshot。
## D-003readiness 字段必须保守
日期2026-07-07
状态:已采纳
### 决策
`nativeTaskReady``nativeHalSyncReady``fullLinuxCncProgramExecutionReady` 只能在对应能力真实完成并有验收证据后置为 true。
### 理由
当前代码和测试输出仍为 false而部分文档文字曾出现 true 的表述容易造成推进误判。readiness 是边界契约,必须保守。
### 影响
- `docs/source-reuse-map.md` 需要在后续任务中修正。
- 测试应断言 readiness 与真实能力一致。
## D-004native process/realtime 拓扑不是本阶段目标
日期2026-07-07
状态:已采纳
### 决策
本阶段只对标 task 主循环语义和状态流,不尝试恢复 LinuxCNC 原生多进程、NML transport、realtime kernel 或真实硬件控制。
### 理由
`wasm-port` 目标是 standalone WASM simulation。运行时边界可以替换 file IO、IPC、HAL runtime、process model 和 browser integration但 CNC/task 语义应来自 LinuxCNC。
### 影响
- process spawning、external user-M、native GUI、真实 realtime driver 继续作为 runtime-edge 或 blocked 项处理。
- 任何 standalone 差异必须写入决策或设计文档。
## D-005status read 不同步 motion不产生语义副作用
日期2026-07-07
状态:已采纳
### 决策
`lctask_read_status_json()` 只能导出最后一次 task cycle 写出的 status snapshot不允许在读取 status 时调用 motion runtime 来刷新 task 语义状态。
### 理由
LinuxCNC 上游是在 task 主循环中调用 `emcMotionUpdate(&emcStatus->motion)`,随后 `emcStatusBuffer->write(emcStatus)`。GUI/客户端读取 status buffer 不应改变 task/motion 语义。如果 WASM status read 同步 motion就会掩盖“task 周期没有读取 motion”的缺陷。
### 影响
- 需要建立 task status buffer 等价物。
- 需要新增测试证明 status read 不推进、不同步、不改变 task 状态。
- motion JSON 可以作为 low-level debug API 保留,但不能作为 task status 事实源。
## D-006command send 只入队,语义变化由 task cycle 产生
日期2026-07-07
状态:已采纳
### 决策
`lctask_send_command_json()` 后续应只解析并入队 command envelope不直接修改 task `state/mode/interpState/execState`,也不直接 forward motion command。LinuxCNC 语义变化必须发生在 `lctask_run_cycles()` 的 command read、plan、execute 阶段。
### 理由
上游 `emctaskmain.cc` 每周期通过 `emcCommandBuffer->read()` 获取命令,再运行 `emcTaskPlan()``emcTaskExecute()`。当前 send API 直接改状态,是 host convenience不是 LinuxCNC task 主循环语义。
### 影响
- 现有测试需要调整send command 后必须 run cycle 才断言状态变化。
- 当前 immediate MDI/JOG/HOME forward motion 逻辑要迁到 execute 阶段。
- C ABI 仍可保持简单,但语义边界必须改为 command buffer。
## D-007先迁 `taskintf.cc` minimal bridge再迁 `emctask.cc` 和 `emccanon.cc`
日期2026-07-07
状态:已采纳
### 决策
上游 task 源码替换顺序采用:
1. `taskintf.cc` minimal motion bridge。
2. `emctask.cc` abort/state/mode/update。
3. `emctask.cc` plan wrapper。
4. `emccanon.cc` straight motion 子集。
5. `emctaskmain.cc` execute 分支接 `interp_list`
6. `emccanon.cc` spindle/tool/io 子集。
### 理由
`emctask.cc``emccanon.cc` 都依赖 task 到 motion 的接口。若没有先建立 `taskintf.cc``lcmot` 的 bridge`emctask.cc` 的 state/mode/abort 和 `emccanon.cc``EMC_TRAJ_*` command 只能继续落回 JSON 自有逻辑。先迁 `taskintf.cc` minimal bridge可以让后续上游函数真正通过 LinuxCNC task/motion 接口工作。
### 影响
- T-032 到 T-036 优先级高于 T-037 之后的源码替换。
- `emccanon.cc` 迁移不得绕过 `interp_list` 直接输出 JSON。
- `taskintf.cc` 中无法连接真实硬件/RT 的部分必须显式 shim 到 `lcmot/lchal` runtime。