推进 INI 面板 workflow status helper

This commit is contained in:
2026-06-14 22:28:44 +08:00
parent a1c34e454e
commit f537a8fa42
6 changed files with 194 additions and 2 deletions

View File

@@ -828,3 +828,71 @@ host_wasm_opfs_browser_smokes=ok
`getMachineSessionWorkflowStatus()`,把当前 last action、error、readiness、session/run
摘要合并为控制网页界面可直接轮询的状态对象;仍不新增按钮、不解析 G-code、不把 CNC
语义搬进 JS。
八、2026-06-14 继续执行记录INI panel workflow status helper
本轮继续推进 `window.linuxCncIniPanelApi` 的只读面,补一个更适合控制网页界面轮询的
workflow status helper把现有 report 派生为更轻量的状态对象。
完成内容:
- `wasm-port/runtime/ui/ini-panel/panel-state-summary.js` 新增
`createMachineSessionWorkflowStatus(state)`
- helper 只从 `createMachineSessionStateReport(state)` 派生,返回:
- `readiness`
- `lastAction`
- `error`
- `session`
- `run`
- `wasm-port/runtime/ui/ini-panel/app.js` 在
`window.linuxCncIniPanelApi`、`window.getMachineSessionWorkflowStatus()` 下暴露该 helper
- `wasm-port/tests/ui/node/verify_ini_panel_state_summary.mjs` 覆盖 workflow status 的字段;
- `wasm-port/tests/browser/ini_panel_smoke.html` 通过真实 save、restore-load、run 流程验证
workflow status并确认其与 report / export / legacy getter 一致;
- `wasm-port/docs/ui-panel-state-summary.md` 补充 workflow status helper 说明;
- 未新增按钮;
- 未解析 G-code
- 未改变 OPFS/session persistence、LinuxCNC interpreter、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
browser_ini_opfs_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
ini_panel_state_summary_node_smoke=ok
ui_node_smokes=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
```
下一步建议:
继续沿 `window.linuxCncIniPanelApi` 收敛控制面。下一批建议把当前散落的 report/export/
status getter 再包成一个明确的 `getMachineSessionStateBundle()` 或 `getMachineSessionView()`
只读入口,给控制网页界面一个单点轮询对象;仍保持只读,不加按钮,不扩大 CNC 语义边界。

View File

@@ -18,6 +18,10 @@ directly. The legacy `window.getMachineSessionStateReport()` and
`window.getMachineSessionStateReportExport()` globals remain as compatibility
shims.
For control-page polling, use
`window.linuxCncIniPanelApi.getMachineSessionWorkflowStatus()`. It returns a
smaller workflow-facing object derived from the same report data.
## `createIniPanelStateSummary(input)`
`input` may contain:
@@ -103,6 +107,23 @@ This helper wraps the report in a stable export payload:
It is a small export-layer helper for future copy/download/UI SDK wrappers.
## `createMachineSessionWorkflowStatus(state)`
This helper derives a lightweight status object for upper-level control pages:
```js
{
readiness: { ini: "...", interp: "...", opfs: "..." },
lastAction: "run-gcode",
error: null,
session: { snapshotLabel: "...", workflow: "...", gcode: "..." },
run: { status: "ok", canonicalEventCount: 2, motionSnapshotCount: 2, iniWasmPath: "..." }
}
```
It is intended for polling or status panels that need current UI workflow
state without parsing logs, DOM nodes, or transient window state.
## Boundary Rules
- Do not parse G-code text in this helper.

View File

@@ -49,6 +49,7 @@ import {
createMachineSessionStateSnapshot,
createMachineSessionStateReport,
createMachineSessionStateReportExport,
createMachineSessionWorkflowStatus,
} from "./panel-state-summary.js";
const SAMPLE_PATH =
@@ -161,6 +162,10 @@ function getMachineSessionStateReportExport() {
return createMachineSessionStateReportExport(window.linuxCncIniPanelMachineSessionState);
}
function getMachineSessionWorkflowStatus() {
return createMachineSessionWorkflowStatus(window.linuxCncIniPanelMachineSessionState);
}
function updatePanelMachineSessionState(patch = {}) {
panelMachineSessionState = createMachineSessionStateSnapshot({
...panelMachineSessionState,
@@ -177,9 +182,11 @@ function updatePanelMachineSessionState(patch = {}) {
window.linuxCncIniPanelApi = {
getMachineSessionStateReport,
getMachineSessionStateReportExport,
getMachineSessionWorkflowStatus,
};
window.getMachineSessionStateReport = getMachineSessionStateReport;
window.getMachineSessionStateReportExport = getMachineSessionStateReportExport;
window.getMachineSessionWorkflowStatus = getMachineSessionWorkflowStatus;
window.linuxCncIniPanelMachineSessionState = panelMachineSessionState;
function setBadge(node, text, className = "badge") {

View File

@@ -118,3 +118,14 @@ export function createMachineSessionStateReportExport(state = {}, options = {})
text: `${JSON.stringify(report, null, 2)}\n`,
};
}
export function createMachineSessionWorkflowStatus(state = {}) {
const report = createMachineSessionStateReport(state);
return {
readiness: report.readiness,
lastAction: report.status.lastAction,
error: report.status.error,
session: report.session,
run: report.run,
};
}

View File

@@ -368,8 +368,12 @@ TOOL_TABLE = browser-tool.tbl
"INI panel OPFS readiness",
);
const uiApi = uiDocument.defaultView.linuxCncIniPanelApi;
if (!uiApi?.getMachineSessionStateReport || !uiApi?.getMachineSessionStateReportExport) {
throw new Error("INI panel API namespace did not expose state report getters");
if (
!uiApi?.getMachineSessionStateReport ||
!uiApi?.getMachineSessionStateReportExport ||
!uiApi?.getMachineSessionWorkflowStatus
) {
throw new Error("INI panel API namespace did not expose state getters");
}
uiDocument.getElementById("ini-editor").value = iniText;
@@ -773,6 +777,37 @@ TOOL_TABLE = browser-tool.tbl
"snapshot",
"UI machine session state report export program source",
);
const machineSessionWorkflowStatus = uiApi.getMachineSessionWorkflowStatus();
assertEqual(
machineSessionWorkflowStatus.lastAction,
"run-gcode",
"UI machine session workflow status last action",
);
assertEqual(
machineSessionWorkflowStatus.error,
null,
"UI machine session workflow status error",
);
assertEqual(
machineSessionWorkflowStatus.readiness.opfs,
"OPFS: ready",
"UI machine session workflow status OPFS readiness",
);
assertEqual(
machineSessionWorkflowStatus.session.workflow,
"save-session-snapshot",
"UI machine session workflow status session workflow",
);
assertEqual(
machineSessionWorkflowStatus.run.status,
"ok",
"UI machine session workflow status run status",
);
assertEqual(
machineSessionWorkflowStatus.run.canonicalEventCount,
2,
"UI machine session workflow status canonical event count",
);
assertEqual(
uiDocument.defaultView.getMachineSessionStateReport().status.lastAction,
machineSessionStateReport.status.lastAction,

View File

@@ -5,6 +5,7 @@ import {
createMachineSessionStateSnapshot,
createMachineSessionStateReport,
createMachineSessionStateReportExport,
createMachineSessionWorkflowStatus,
} from "../../../runtime/ui/ini-panel/panel-state-summary.js";
const summary = createIniPanelStateSummary({
@@ -330,14 +331,63 @@ assert.deepEqual(
},
);
assert.deepEqual(
createMachineSessionWorkflowStatus({
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",
sessionGcode: "linuxcnc/gcode/ui-session.ngc",
runStatus: "ok",
runWorkflow: "save-session-snapshot",
},
run: {
runStatus: "ok",
canonicalEventCount: 2,
motionSnapshotCount: 2,
},
lastAction: "run-gcode",
error: null,
}),
{
readiness: {
ini: "INI WASM: ready",
interp: "Interpreter WASM: ready",
opfs: "OPFS: ready",
},
lastAction: "run-gcode",
error: null,
session: {
snapshotLabel: "ui-machine-session/ui-machine-session.json",
workflow: "save-session-snapshot",
ini: "/work/session-machine.ini",
parameters: null,
toolTable: null,
gcode: "linuxcnc/gcode/ui-session.ngc",
},
run: {
status: "ok",
canonicalEventCount: 2,
motionSnapshotCount: 2,
iniWasmPath: null,
},
},
);
assert.deepEqual(
{
getMachineSessionStateReport: typeof globalThis.window?.linuxCncIniPanelApi?.getMachineSessionStateReport,
getMachineSessionStateReportExport: typeof globalThis.window?.linuxCncIniPanelApi?.getMachineSessionStateReportExport,
getMachineSessionWorkflowStatus: typeof globalThis.window?.linuxCncIniPanelApi?.getMachineSessionWorkflowStatus,
},
{
getMachineSessionStateReport: "undefined",
getMachineSessionStateReportExport: "undefined",
getMachineSessionWorkflowStatus: "undefined",
},
);