diff --git a/text11.txt b/text11.txt index 4deadc6..855ddf1 100644 --- a/text11.txt +++ b/text11.txt @@ -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 语义边界。 diff --git a/wasm-port/docs/ui-panel-state-summary.md b/wasm-port/docs/ui-panel-state-summary.md index 4a8ab21..0a2bf75 100644 --- a/wasm-port/docs/ui-panel-state-summary.md +++ b/wasm-port/docs/ui-panel-state-summary.md @@ -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. diff --git a/wasm-port/runtime/ui/ini-panel/app.js b/wasm-port/runtime/ui/ini-panel/app.js index 9c24a8e..ad897f7 100644 --- a/wasm-port/runtime/ui/ini-panel/app.js +++ b/wasm-port/runtime/ui/ini-panel/app.js @@ -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") { diff --git a/wasm-port/runtime/ui/ini-panel/panel-state-summary.js b/wasm-port/runtime/ui/ini-panel/panel-state-summary.js index 048838e..f62f0db 100644 --- a/wasm-port/runtime/ui/ini-panel/panel-state-summary.js +++ b/wasm-port/runtime/ui/ini-panel/panel-state-summary.js @@ -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, + }; +} diff --git a/wasm-port/tests/browser/ini_panel_smoke.html b/wasm-port/tests/browser/ini_panel_smoke.html index 0f3047e..8a1b61d 100644 --- a/wasm-port/tests/browser/ini_panel_smoke.html +++ b/wasm-port/tests/browser/ini_panel_smoke.html @@ -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, diff --git a/wasm-port/tests/ui/node/verify_ini_panel_state_summary.mjs b/wasm-port/tests/ui/node/verify_ini_panel_state_summary.mjs index 31b242b..2701248 100644 --- a/wasm-port/tests/ui/node/verify_ini_panel_state_summary.mjs +++ b/wasm-port/tests/ui/node/verify_ini_panel_state_summary.mjs @@ -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", }, );