# 02-程序开发步骤

## 阶段 1：确认语义来源

1. 阅读 workspace 规则和 LinuxCNC WASM port 规则。
2. 确认本轮不能新增独立 CNC 语义，必须以 LinuxCNC 源码为语义依据。
3. 查阅 LinuxCNC task 源码：
   - `linuxcnc/src/emc/task/emctaskmain.cc`
   - `linuxcnc/src/emc/nml_intf/emc_nml.hh`
   - `linuxcnc/src/emc/nml_intf/emc.hh`
4. 确认按钮对应的 LinuxCNC command：
   - Run -> `EMC_TASK_PLAN_RUN`
   - Stop -> `EMC_TASK_ABORT`
   - Pause -> `EMC_TASK_PLAN_PAUSE`
   - Resume -> `EMC_TASK_PLAN_RESUME`
   - Step -> `EMC_TASK_PLAN_STEP`
   - Home -> `EMC_JOINT_HOME`

## 阶段 2：前端按钮状态调整

文件：

- `web-rtcp-5axis-sim-plan/app/src/ui/gmoccapy-shell.js`

步骤：

1. 找到 bottom controls 渲染逻辑。
2. 增加 promptable action 列表：
   - `RUN`
   - `STOP`
   - `PAUSE`
   - `RESUME`
   - `STEP`
   - `HOME`
3. 这些按钮在 blocked 时不再设置 HTML `disabled`。
4. blocked 状态通过以下属性体现：
   - `data-command-ready="false"`
   - `aria-disabled="true"`
   - `title="... blocked reason ..."`
5. 点击后仍 dispatch 原 action，由 store gate 返回真实阻塞原因。

## 阶段 3：Web store 命令行为调整

文件：

- `web-rtcp-5axis-sim-plan/app/src/state/store.js`

步骤：

1. Resume
   - 发送 `EMC_TASK_PLAN_RESUME`。
   - 根据返回 status 调用 `shouldContinueTaskHalStatusLoop()`。
   - 只有仍处于 reading/mdi 等应继续状态时才重启 status loop。

2. Step
   - 从空 command sequence 改为发送 `EMC_TASK_PLAN_STEP`。
   - 保留单步后 paused 状态。

3. Home
   - 在 task/HAL runtime 存在时，先在 Web 状态中标记：
     - `mode="manual"`
     - `allHomed=true`
     - `interpState="idle"`
     - `taskPaused=false`
   - 再异步发送 `EMC_JOINT_HOME`。
   - 修复快速 `HOME -> SET_MODE` 导致 Home 状态丢失的问题。

4. Session reset
   - `initializeTaskHalSession()` 开始时停止旧 `taskHalStatusLoop`。
   - 避免旧运行循环覆盖新 session 或 MDI/Step 状态。

5. Status patch
   - `applyTaskHalStatusPatch()` 保留 `allHomed`。
   - 同时保留 `noForceHoming`，避免 gate 状态回退。

## 阶段 4：WASM task/HAL runtime 补齐

文件：

- `wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_task_hal_wasm.cpp`

步骤：

1. 在 `TaskRuntime` 中增加：
   - `task_paused`
   - `single_stepping`
2. 在 `status_json()` 输出：
   - `task.taskPaused`
   - `task.singleStepping`
3. 在 command handler 中补齐：
   - `EMC_TASK_PLAN_STEP`
   - RUN/RESUME/ABORT/HOME/completion 时清理 pause/step 状态。
4. Step 行为：
   - 设置 `single_stepping=true`
   - 设置 `task_paused=true`
   - 发送 `EMC_TRAJ_STEP`
   - cycle 后回到 paused。

## 阶段 5：WASM motion runtime 补齐

文件：

- `wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_motion_runtime.c`

步骤：

1. 增加 `LCMOT_CMD_STEP`。
2. 解析：
   - `EMC_TRAJ_STEP`
   - `EMCMOT_STEP`
3. paused 状态下允许 STEP 命令通过 queue gate。
4. apply step 时短暂解除 paused，使单步命令可以推进。

## 阶段 6：测试覆盖

修改测试：

- `web-rtcp-5axis-sim-plan/tests/node/verify_linuxcnc_task_hal_runtime.mjs`
- `web-rtcp-5axis-sim-plan/tests/browser/gmoccapy_shell_smoke.html`

新增/强化验证：

1. blocked Run 按钮不能被 HTML disabled，应可点击并提示原因。
2. Pause 后 `runState=paused`。
3. Resume 后恢复 running/reading 状态。
4. Step 后：
   - `machine.interpState="paused"`
   - `machine.taskPaused=true`
   - `taskHalStatus.task.singleStepping=true`
5. Stop 后：
   - `runState="stopped"`
   - `machine.interpState="idle"`
   - `motion.aborted=true`

## 阶段 7：构建与验证

执行：

```bash
bash wasm-port/tools/build_task_hal_wasm.sh
node wasm-port/tests/wasm/node/verify_task_hal_wasm.mjs
node web-rtcp-5axis-sim-plan/tests/node/verify_linuxcnc_task_hal_runtime.mjs
node web-rtcp-5axis-sim-plan/tests/node/verify_run_preconditions.mjs
node web-rtcp-5axis-sim-plan/tests/node/verify_rtcp_store.mjs
bash web-rtcp-5axis-sim-plan/tests/browser/verify_gmoccapy_shell_browser.sh
```

结果：全部通过。

## 阶段 8：浏览器按钮截图取证

新增文件：

- `qa/web-rtcp-5axis-site-test/capture-button-control-evidence.mjs`

步骤：

1. 启动本地静态 HTTP server，打开 `web-rtcp-5axis-sim-plan/app/index.html`。
2. 等待 kinematics、interpreter、task/HAL runtime ready。
3. 加载短 G-code 程序 `button-control-evidence.ngc`。
4. 按顺序采集：
   - 初始界面
   - 程序加载后
   - Home 前后
   - Run 前后
   - Pause 前后
   - Resume 前后
   - Step 前后
   - Stop 前后
5. 每个步骤记录：
   - PNG 截图
   - `RUN/STOP/PAUSE/RESUME/STEP/HOME` 按钮 DOM readiness 属性
   - Web store machine/run/taskHalStatus 状态
   - Three.js canvas dataset
   - PNG 非黑像素统计
6. 输出 JSON 报告：

```text
/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/output/button-control-evidence-report.json
```

验证命令：

```bash
node --check qa/web-rtcp-5axis-site-test/capture-button-control-evidence.mjs
node qa/web-rtcp-5axis-site-test/capture-button-control-evidence.mjs
```

结果：

```text
button_control_evidence_status=PASS
```

## 阶段 9：云端部署与按钮验收

步骤：

1. 重建当前静态站点：

```bash
bash wasm-port/tools/build_task_hal_wasm.sh
npm --prefix web-rtcp-5axis-sim-plan/app run build
```

2. 打包 `web-rtcp-5axis-sim-plan/app/dist`：

```bash
tar -C web-rtcp-5axis-sim-plan/app/dist -czf /tmp/web-rtcp-5axis-sim-8092-working1.tar.gz .
```

3. 通过 SSH/paramiko 发布到云端 nginx root：

```text
host=82.156.24.101
user=ubuntu
root=/var/www/web-rtcp-5axis-sim
```

4. 云端执行：

```bash
sudo nginx -t
sudo systemctl reload nginx
curl -k -I https://127.0.0.1:8092/
```

5. 对公网 URL 运行按钮流程取证：

```bash
TARGET_URL='https://82.156.24.101:8092/' \
EVIDENCE_SCOPE='cloud-button-control-evidence' \
node qa/web-rtcp-5axis-site-test/capture-button-control-evidence.mjs
```

结果：

```text
button_control_evidence_status=PASS
button_control_evidence_job_id=btn-20260623091811-c291e49b
button_control_evidence_report_id=report-btn-20260623091811-c291e49b
button_control_evidence_json=/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/output/cloud-button-control-evidence-report.json
button_control_evidence_pdf=/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/output/cloud-button-control-evidence-report.pdf
button_control_evidence_screenshots=/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/screenshots/cloud-button-control-evidence
```

## 阶段 10：LinuxCNC native 对照报告

新增文件：

- `qa/web-rtcp-5axis-site-test/capture-native-task-hal-comparison.mjs`

步骤：

1. 运行 phase0 native source/probe gate。
2. 运行 Web native task/HAL readiness audit。
3. 尝试运行 opt-in TRT native runtime probe。
4. 尝试运行 upstream `rs274` fixture baseline。
5. 记录 `halcmd`、`rs274`、`linuxcncsvr` 动态库依赖。
6. 输出 native 对照 JSON/Markdown 报告。

命令：

```bash
node --check qa/web-rtcp-5axis-site-test/capture-native-task-hal-comparison.mjs
node qa/web-rtcp-5axis-site-test/capture-native-task-hal-comparison.mjs
```

结果：

```text
native_task_hal_comparison_status=PASS_WITH_HOST_NATIVE_RUNTIME_BLOCKER
native_task_hal_comparison_json=/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/output/native-task-hal-comparison-report.json
native_task_hal_comparison_markdown=/home/meswork/cnc_wams/qa/web-rtcp-5axis-site-test/output/native-task-hal-comparison-report.md
native_task_hal_transition_log_available=0
native_task_hal_host_blocker_count=15
```

说明：当前主机不能启动 LinuxCNC native TRT task/HAL runtime，原因包括 RIP 脚本硬编码旧绝对路径 `/home/cnc/桌面/cnc_wams/linuxcnc`，以及二进制依赖当前主机缺失的 `GLIBC_2.38`、`GLIBCXX_3.4.31`、`libpython3.13.so.1.0` 等 runtime 条件。因此 BTN-013 的完成形态是 native/source 对照审计和 host blocker 证据，不声明真实 host-native 状态转换日志已生成。
