推进 INI 面板 machine session state report helper

This commit is contained in:
2026-06-14 21:53:36 +08:00
parent 7d57bce5de
commit e80ecd4b7a
4 changed files with 209 additions and 0 deletions

View File

@@ -523,3 +523,66 @@ host_wasm_opfs_browser_smokes=ok
整理成更明确的 API/文档使用方式,或者在 `run-gcode`/restore/load/save 之外再补一层
更高阶的 UI consumer helper用于读取状态并生成上层展示/导出结果;只围绕已有
host/runtime boundary facts 组合,不回到 path guard。
四、2026-06-14 继续执行记录INI panel machine session state report helper
本轮继续按 `text11.txt` 第一原则推进上层 UI/API 可消费能力,把 machine session state
snapshot 转成稳定的 consumer report 结构,方便外部 UI、导出路径或测试直接读取状态。
完成内容:
- 扩展 `wasm-port/runtime/ui/ini-panel/panel-state-summary.js`
- 新增导出 `createMachineSessionStateReport(state)`
- report helper 输出稳定分组:
- readiness
- session
- loaded
- program
- run
- status
- `wasm-port/tests/ui/node/verify_ini_panel_state_summary.mjs` 覆盖 report 输出结构;
- `wasm-port/docs/ui-panel-state-summary.md` 增加 report API、用途和边界说明
- 未改变 INI panel UI workflow、OPFS bridge、snapshot-store、machine-file-store、
LinuxCNC interpreter、G-code 文本、canonical-event 语义、tool、parameter、planner 或
LinuxCNC-owned runtime semantics。
验证已通过:
```bash
git diff --check
wasm-port/tests/ui/node/verify_ini_panel_state_summary.sh
wasm-port/tests/ui/node/verify_ui_node_smokes.sh
SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_ini_panel_browser.sh
wasm-port/tools/verify_vendor_sync.sh
wasm-port/tools/verify_no_standalone_cnc_semantics.sh
SKIP_INTERP_BUILD=1 wasm-port/tests/wasm/node/verify_interp_wasm.sh
SKIP_INTERP_BUILD=1 wasm-port/tests/wasm/node/verify_sim_configs_inventory_wasm.sh
wasm-port/tests/host/verify_host_smokes.sh
```
关键输出:
```text
ini_panel_state_summary_node_smoke=ok
ini_panel_run_summary_node_smoke=ok
ini_panel_run_workflow_node_smoke=ok
ini_panel_session_summary_node_smoke=ok
ini_panel_session_workflow_node_smoke=ok
ini_panel_machine_file_summary_node_smoke=ok
ui_node_smokes=ok
browser_ini_opfs_smoke=ok
vendor sync up to date
standalone CNC semantics guard complete
interp_wasm_node_smoke=ok
sim_configs_wasm_node_inventory_executed=28
sim_configs_wasm_node_inventory_passed=28
sim_configs_wasm_node_inventory_skipped=131
sim_configs_wasm_node_inventory_unexpected_fail=0
host_wasm_opfs_browser_smokes=ok
```
下一步建议:
继续按“实质性能力优先”推进。优先把该 state report 接入浏览器 UI 的真实可用流程,例如
新增一个导出/复制 report 的 UI action 或一个明确的 SDK-facing getter使上层消费者不必
直接读取 `window` 内部对象;仍只导出 host/runtime boundary facts不解析或实现 CNC 语义。

View File

@@ -62,6 +62,25 @@ The INI panel updates this state after save, restore, load, run, and error
paths so browser tests and future API consumers can read one machine-readable
state object instead of collecting DOM fields and log text.
## `createMachineSessionStateReport(state)`
This helper converts the richer state snapshot into a stable consumer report
with four sections:
```js
{
readiness: { ini: "...", interp: "...", opfs: "..." },
session: { snapshotLabel: "...", workflow: "...", ini: "...", parameters: "...", toolTable: "...", gcode: "..." },
loaded: { iniWasmPath: "...", parameterWasmPath: "...", toolTableWasmPath: "..." },
program: { source: "snapshot", opfsPath: "...", wasmPath: "..." },
run: { status: "ok", canonicalEventCount: 2, motionSnapshotCount: 2, iniWasmPath: "..." },
status: { lastAction: "run-gcode", error: null, fiveaxisRemap: "ok" }
}
```
The report is intended for upper-level UI consumers or export paths that want a
stable summary shape without touching DOM nodes.
## Boundary Rules
- Do not parse G-code text in this helper.

View File

@@ -63,3 +63,48 @@ export function createMachineSessionStateSnapshot({
error: error ?? null,
};
}
export function createMachineSessionStateReport(state = {}) {
const badges = state.badges ?? {};
const fields = state.fields ?? {};
const sessionSnapshot = state.sessionSnapshot ?? {};
const sessionLoad = state.sessionLoad ?? {};
const selectedProgram = state.selectedProgram ?? {};
const run = state.run ?? {};
return {
readiness: {
ini: badges.ini ?? null,
interp: badges.interp ?? null,
opfs: badges.opfs ?? null,
},
session: {
snapshotLabel: sessionSnapshot.snapshotLabel ?? fields.sessionSnapshot ?? null,
workflow: sessionSnapshot.workflow ?? fields.runWorkflow ?? null,
ini: fields.sessionIni ?? sessionSnapshot.iniOpfsPath ?? sessionLoad.iniWasmPath ?? null,
parameters: fields.sessionParameters ?? sessionSnapshot.parameterOpfsPath ?? sessionLoad.parameterWasmPath ?? null,
toolTable: fields.sessionToolTable ?? sessionSnapshot.toolTableOpfsPath ?? sessionLoad.toolTableWasmPath ?? null,
gcode: fields.sessionGcode ?? sessionSnapshot.gcodeOpfsPath ?? null,
},
loaded: {
iniWasmPath: sessionLoad.iniWasmPath ?? null,
parameterWasmPath: sessionLoad.parameterWasmPath ?? null,
toolTableWasmPath: sessionLoad.toolTableWasmPath ?? null,
},
program: {
source: selectedProgram.source ?? run.programSource ?? fields.runSource ?? null,
opfsPath: selectedProgram.opfsPath ?? run.programOpfsPath ?? fields.runOpfsPath ?? null,
wasmPath: selectedProgram.wasmPath ?? run.programWasmPath ?? fields.runWasmPath ?? null,
},
run: {
status: run.runStatus ?? fields.runStatus ?? null,
canonicalEventCount: run.canonicalEventCount ?? 0,
motionSnapshotCount: run.motionSnapshotCount ?? 0,
iniWasmPath: run.iniWasmPath ?? null,
},
status: {
lastAction: state.lastAction ?? null,
error: state.error ?? null,
fiveaxisRemap: state.fiveaxisRemap ?? null,
},
};
}

View File

@@ -3,6 +3,7 @@ import assert from "node:assert/strict";
import {
createIniPanelStateSummary,
createMachineSessionStateSnapshot,
createMachineSessionStateReport,
} from "../../../runtime/ui/ini-panel/panel-state-summary.js";
const summary = createIniPanelStateSummary({
@@ -186,4 +187,85 @@ assert.deepEqual(
},
);
assert.deepEqual(
createMachineSessionStateReport({
badges: {
ini: "INI WASM: ready",
interp: "Interpreter WASM: ready",
opfs: "OPFS: ready",
},
fields: {
sessionSnapshot: "ui-machine-session/ui-machine-session.json",
sessionIni: "/work/session-machine.ini",
sessionParameters: "/work/session-linuxcnc.var",
sessionToolTable: "/work/session-tool.tbl",
sessionGcode: "linuxcnc/gcode/ui-session.ngc",
runStatus: "ok",
runSource: "snapshot",
runSnapshot: "ui-machine-session/ui-machine-session.json",
runWorkflow: "save-session-snapshot",
runOpfsPath: "linuxcnc/gcode/ui-session.ngc",
runWasmPath: "/work/ui-session.ngc",
},
sessionLoad: {
iniWasmPath: "/work/session-machine.ini",
parameterWasmPath: "/work/session-linuxcnc.var",
toolTableWasmPath: "/work/session-tool.tbl",
},
selectedProgram: {
source: "snapshot",
opfsPath: "linuxcnc/gcode/ui-session.ngc",
wasmPath: "/work/ui-session.ngc",
},
run: {
runStatus: "ok",
programSource: "snapshot",
programOpfsPath: "linuxcnc/gcode/ui-session.ngc",
programWasmPath: "/work/ui-session.ngc",
iniWasmPath: "/work/session-machine.ini",
canonicalEventCount: 2,
motionSnapshotCount: 2,
},
lastAction: "run-gcode",
error: null,
fiveaxisRemap: "ok",
}),
{
readiness: {
ini: "INI WASM: ready",
interp: "Interpreter WASM: ready",
opfs: "OPFS: ready",
},
session: {
snapshotLabel: "ui-machine-session/ui-machine-session.json",
workflow: "save-session-snapshot",
ini: "/work/session-machine.ini",
parameters: "/work/session-linuxcnc.var",
toolTable: "/work/session-tool.tbl",
gcode: "linuxcnc/gcode/ui-session.ngc",
},
loaded: {
iniWasmPath: "/work/session-machine.ini",
parameterWasmPath: "/work/session-linuxcnc.var",
toolTableWasmPath: "/work/session-tool.tbl",
},
program: {
source: "snapshot",
opfsPath: "linuxcnc/gcode/ui-session.ngc",
wasmPath: "/work/ui-session.ngc",
},
run: {
status: "ok",
canonicalEventCount: 2,
motionSnapshotCount: 2,
iniWasmPath: "/work/session-machine.ini",
},
status: {
lastAction: "run-gcode",
error: null,
fiveaxisRemap: "ok",
},
},
);
console.log("ini_panel_state_summary_node_smoke=ok");