diff --git a/text12.txt b/text12.txt index c2f3c91..847bad7 100644 --- a/text12.txt +++ b/text12.txt @@ -305,3 +305,68 @@ host_wasm_opfs_browser_smokes=ok 继续推进 OPFS/session persistence 的实质链路。下一批建议把 `load-session` 按钮路径抽成 `loadMachineSessionIntoWasmWorkflow()`,统一返回 loaded session、load summary、field state 和 log lines;仍保持由 LinuxCNC/OPFS bridge 执行实际语义,不在 JS 中解释 CNC 行为。 + +二、2026-06-15 继续执行记录:INI panel load-session workflow helper + +本轮按“第一原则:加快实质性推进”继续推进 OPFS/session persistence 主链路,抽出 +`load-session` 按钮路径的可复用 workflow helper,统一返回 loaded session、load summary、 +field state 和 log lines。 + +完成内容: + +- `wasm-port/runtime/ui/ini-panel/session-workflow.js` 新增 + `createMachineSessionLoadFieldState(summary)`; +- `session-workflow.js` 新增 `machineSessionLoadWorkflowLogLines(summary)`; +- `session-workflow.js` 新增 `loadMachineSessionIntoWasmWorkflow({ loadSession })`; +- workflow 只调用外部传入的 LinuxCNC/OPFS session loader,并基于现有 + `createMachineSessionLoadSummary()` 生成 UI 状态; +- `wasm-port/runtime/ui/ini-panel/app.js` 的 `load-session` handler 改为调用 + `loadMachineSessionIntoWasmWorkflow()`; +- `app.js` 仍由 `loadMachineSessionFromOpfs()` 通过 LinuxCNC/OPFS bridge 执行实际 session + staging; +- `wasm-port/tests/ui/node/verify_ini_panel_session_workflow.mjs` 覆盖 load workflow 的 + loader 调用、summary、field state、log lines 和缺失 loader 错误; +- 未新增控制按钮; +- 未解析 G-code; +- 未解释 canonical events; +- 未改变 OPFS/session persistence、LinuxCNC interpreter、tool、parameter、planner 或 + LinuxCNC-owned runtime semantics。 + +验证已通过: + +```bash +git diff --check +wasm-port/tests/ui/node/verify_ini_panel_session_workflow.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_session_workflow_node_smoke=ok +ui_node_smokes=ok +browser_ini_opfs_smoke=ok +browser_ini_control_page_smoke=ok +browser_ini_launch_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 +browser_interp_smoke=ok +host_wasm_opfs_browser_smokes=ok +``` + +下一步建议: + +继续推进 OPFS/session persistence 的实质链路。下一批建议将 `restore-load-session` 路径改为复用 +`loadMachineSessionIntoWasmWorkflow()`,避免 restore+load 与单独 load 的 field/log 状态模型 +分叉;仍保持由 LinuxCNC/OPFS bridge 执行实际语义,不在 JS 中解释 CNC 行为。 diff --git a/wasm-port/runtime/ui/ini-panel/app.js b/wasm-port/runtime/ui/ini-panel/app.js index 2ce957c..0ff5cfc 100644 --- a/wasm-port/runtime/ui/ini-panel/app.js +++ b/wasm-port/runtime/ui/ini-panel/app.js @@ -34,14 +34,11 @@ import { import { runGcodeSessionWorkflow, } from "./run-workflow.js"; -import { - createMachineSessionLoadSummary, - machineSessionLoadLogLines, -} from "./session-load-summary.js"; import { sessionSnapshotSummaryLogLines, } from "./session-summary.js"; import { + loadMachineSessionIntoWasmWorkflow, restoreMachineSessionSnapshotWorkflow, saveMachineSessionSnapshotWorkflow, } from "./session-workflow.js"; @@ -712,24 +709,17 @@ document.getElementById("restore-session-snapshot").addEventListener("click", as document.getElementById("load-session").addEventListener("click", async () => { try { - await loadMachineSessionIntoWasm(); - const loadSummary = createMachineSessionLoadSummary(loadedSession); + const workflow = await loadMachineSessionIntoWasmWorkflow({ + loadSession: () => loadMachineSessionIntoWasm(), + }); + loadedSession = workflow.loadedSession; updatePanelMachineSessionState({ - sessionLoad: loadSummary, - fields: { - sessionIni: loadSummary.iniWasmPath, - sessionParameters: loadSummary.parameterWasmPath, - sessionToolTable: loadSummary.toolTableWasmPath, - }, + sessionLoad: workflow.loadSummary, + fields: workflow.fields, lastAction: "load-session", error: null, }); - setLog( - [ - "Loaded machine session into the interpreter WASM filesystem.", - ...machineSessionLoadLogLines(loadSummary), - ].join("\n"), - ); + setLog(workflow.logLines.join("\n")); } catch (error) { updatePanelMachineSessionState({ lastAction: "load-session", diff --git a/wasm-port/runtime/ui/ini-panel/session-workflow.js b/wasm-port/runtime/ui/ini-panel/session-workflow.js index a851393..e8f6af8 100644 --- a/wasm-port/runtime/ui/ini-panel/session-workflow.js +++ b/wasm-port/runtime/ui/ini-panel/session-workflow.js @@ -37,6 +37,35 @@ export function sessionSnapshotRestoreLogLines(summary) { ]; } +export function createMachineSessionLoadFieldState(summary) { + return { + sessionIni: summary.iniWasmPath, + sessionParameters: summary.parameterWasmPath, + sessionToolTable: summary.toolTableWasmPath, + }; +} + +export function machineSessionLoadWorkflowLogLines(summary) { + return [ + "Loaded machine session into the interpreter WASM filesystem.", + ...machineSessionLoadLogLines(summary), + ]; +} + +export async function loadMachineSessionIntoWasmWorkflow({ loadSession }) { + if (typeof loadSession !== "function") { + throw new Error("A machine session loader is required."); + } + const loadedSession = await loadSession(); + const loadSummary = createMachineSessionLoadSummary(loadedSession); + return { + loadedSession, + loadSummary, + fields: createMachineSessionLoadFieldState(loadSummary), + logLines: machineSessionLoadWorkflowLogLines(loadSummary), + }; +} + export async function saveMachineSessionSnapshotWorkflow({ machineId, snapshotId, diff --git a/wasm-port/tests/ui/node/verify_ini_panel_session_workflow.mjs b/wasm-port/tests/ui/node/verify_ini_panel_session_workflow.mjs index 03a2700..7e1df4e 100644 --- a/wasm-port/tests/ui/node/verify_ini_panel_session_workflow.mjs +++ b/wasm-port/tests/ui/node/verify_ini_panel_session_workflow.mjs @@ -1,10 +1,68 @@ import assert from "node:assert/strict"; import { + createMachineSessionLoadFieldState, + loadMachineSessionIntoWasmWorkflow, + machineSessionLoadWorkflowLogLines, restoreMachineSessionSnapshotWorkflow, saveMachineSessionSnapshotWorkflow, } from "../../../runtime/ui/ini-panel/session-workflow.js"; +const loadedSessionFixture = { + ini: { + opfsPath: "linuxcnc/machines/xyzab-tdr/machine.ini", + wasmPath: "/work/session-machine.ini", + }, + parameters: { + opfsPath: "linuxcnc/machines/xyzab-tdr/linuxcnc.var", + wasmPath: "/work/session-linuxcnc.var", + result: "restore_parameters=0", + }, + toolTable: { + opfsPath: "linuxcnc/machines/xyzab-tdr/tool.tbl", + wasmPath: "/work/session-tool.tbl", + result: "tooldata_load=0", + }, +}; + +const loadWorkflowCalls = []; +const loadWorkflow = await loadMachineSessionIntoWasmWorkflow({ + loadSession: async () => { + loadWorkflowCalls.push(["loadSession"]); + return loadedSessionFixture; + }, +}); + +assert.deepEqual(loadWorkflowCalls, [["loadSession"]]); +assert.deepEqual(loadWorkflow.loadSummary, { + iniOpfsPath: "linuxcnc/machines/xyzab-tdr/machine.ini", + iniWasmPath: "/work/session-machine.ini", + parameterOpfsPath: "linuxcnc/machines/xyzab-tdr/linuxcnc.var", + parameterWasmPath: "/work/session-linuxcnc.var", + parameterResult: "restore_parameters=0", + toolTableOpfsPath: "linuxcnc/machines/xyzab-tdr/tool.tbl", + toolTableWasmPath: "/work/session-tool.tbl", + toolTableResult: "tooldata_load=0", +}); +assert.deepEqual(loadWorkflow.fields, { + sessionIni: "/work/session-machine.ini", + sessionParameters: "/work/session-linuxcnc.var", + sessionToolTable: "/work/session-tool.tbl", +}); +assert.deepEqual(createMachineSessionLoadFieldState(loadWorkflow.loadSummary), loadWorkflow.fields); +assert.deepEqual(machineSessionLoadWorkflowLogLines(loadWorkflow.loadSummary), [ + "Loaded machine session into the interpreter WASM filesystem.", + "INI: linuxcnc/machines/xyzab-tdr/machine.ini -> /work/session-machine.ini", + "Parameter file: linuxcnc/machines/xyzab-tdr/linuxcnc.var -> /work/session-linuxcnc.var", + "Parameters: restore_parameters=0", + "Tool table file: linuxcnc/machines/xyzab-tdr/tool.tbl -> /work/session-tool.tbl", + "Tool table: tooldata_load=0", +]); +await assert.rejects( + () => loadMachineSessionIntoWasmWorkflow({}), + /machine session loader/, +); + const calls = []; const saveWorkflow = await saveMachineSessionSnapshotWorkflow({ machineId: "xyzab-tdr", @@ -199,22 +257,7 @@ const restoreLoadWorkflow = await restoreMachineSessionSnapshotWorkflow({ }, loadSession: async () => { restoreLoadCalls.push(["loadSession"]); - return { - ini: { - opfsPath: "linuxcnc/machines/xyzab-tdr/machine.ini", - wasmPath: "/work/session-machine.ini", - }, - parameters: { - opfsPath: "linuxcnc/machines/xyzab-tdr/linuxcnc.var", - wasmPath: "/work/session-linuxcnc.var", - result: "restore_parameters=0", - }, - toolTable: { - opfsPath: "linuxcnc/machines/xyzab-tdr/tool.tbl", - wasmPath: "/work/session-tool.tbl", - result: "tooldata_load=0", - }, - }; + return loadedSessionFixture; }, });