diff --git a/text10.txt b/text10.txt index bcd4ae1..396d661 100644 --- a/text10.txt +++ b/text10.txt @@ -1539,3 +1539,71 @@ browser_interp_smoke=ok “日志文本 / DOM 状态 / 机器可读状态”三份并行维护的 host-boundary 数据,如果有,继续 抽取为纯 helper 并接入 `verify_ui_node_smokes.sh`;保持 helper 只描述 host/runtime 边界, 不扩展 CNC 语义。 + +二十二、2026-06-14 继续执行记录:INI panel session load summary helper + +本轮继续沿 OPFS/session/UI boundary 推进,把 machine session load 的 OPFS/WASM 映射 +日志构造收敛为纯 helper,并与 session snapshot summary 一起纳入 UI Node smoke。 + +完成内容: + +- 新增 `wasm-port/runtime/ui/ini-panel/session-load-summary.js`; +- 导出: + - `createMachineSessionLoadSummary(session)`; + - `machineSessionLoadLogLines(summary)`; +- helper 只聚合 machine-session bridge 已返回的 host/runtime boundary facts: + - INI OPFS/WASM path; + - parameter OPFS/WASM path; + - parameter load result text; + - tool table OPFS/WASM path; + - tool table load result text; +- `wasm-port/runtime/ui/ini-panel/app.js` 的 `Load Machine Session` 和 + `Restore And Load Session` 日志改为复用该 helper; +- 新增 `wasm-port/docs/ui-session-summary-helpers.md`,记录 session snapshot 与 session + load helper 的输入/输出和语义边界; +- `wasm-port/tests/ui/node/verify_ini_panel_session_summary.mjs` 增加 session load summary + 和 log lines 覆盖; +- UI node smoke 继续通过 `verify_ini_panel_session_summary.sh` 覆盖该 helper; +- 未改变 UI runtime、OPFS bridge、interpreter run API、G-code 文本、canonical-event 输出 + 或 LinuxCNC-owned runtime semantics。 + +验证已通过: + +```bash +git diff --check +wasm-port/tests/ui/node/verify_ini_panel_session_summary.sh +wasm-port/tests/ui/node/verify_ui_node_smokes.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/opfs/node/verify_file_service.sh +SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_ini_panel_browser.sh +SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_interp_browser.sh +wasm-port/tests/host/verify_host_smokes.sh +``` + +关键输出: + +```text +ini_panel_session_summary_node_smoke=ok +ini_panel_run_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 +opfs_file_service_node_smoke=ok +browser_ini_opfs_smoke=ok +browser_interp_smoke=ok +host_wasm_opfs_browser_smokes=ok +``` + +下一步建议: + +继续沿 OPFS/session/UI boundary 推进。优先把 `ui-session-summary-helpers.md` 的验证入口 +同步到 `compatibility-validation.md` 或补充统一 UI helper docs 索引,确保新增 helper 和 +常规 gate 的关系可发现;仍只做 host/runtime boundary 文档和测试 glue,不扩展 CNC 语义。 diff --git a/wasm-port/docs/ui-session-summary-helpers.md b/wasm-port/docs/ui-session-summary-helpers.md new file mode 100644 index 0000000..d6e9edf --- /dev/null +++ b/wasm-port/docs/ui-session-summary-helpers.md @@ -0,0 +1,85 @@ +# UI Session Summary Helpers + +## Purpose + +`runtime/ui/ini-panel/session-summary.js` contains small host-boundary helpers +for summarizing machine session snapshot state. +`runtime/ui/ini-panel/session-load-summary.js` contains the matching helpers +for machine-session load state. These helpers are pure so browser UI panels, +SDK-facing wrappers, and Node smoke tests can share the same data shape without +parsing log text. + +The helpers do not implement CNC behavior. G-code execution, canonical events, +tool handling, parameters, kinematics, and planner behavior remain owned by the +vendored LinuxCNC runtime. + +## `createSessionSnapshotSummary(snapshot, fallbackLabel)` + +`snapshot` is the saved machine session snapshot loaded by the UI. +`fallbackLabel` is the UI-selected label to prefer when present. + +The returned summary has this shape: + +```js +{ + snapshotLabel: "ui-machine-session/ui-machine-session.json", + workflow: "save-session-snapshot", + defaultGcodeOpfsPath: "linuxcnc/gcode/ui-session.ngc", + iniOpfsPath: "linuxcnc/machines/xyzab-tdr/machine.ini", + parameterOpfsPath: "linuxcnc/machines/xyzab-tdr/linuxcnc.var", + toolTableOpfsPath: "linuxcnc/machines/xyzab-tdr/tool.tbl", + gcodeOpfsPath: "linuxcnc/gcode/ui-session.ngc" +} +``` + +## `createMachineSessionLoadSummary(session)` + +`session` is the loaded interpreter/session bridge result. The helper extracts +the OPFS and WASM path mapping plus the captured parameter/tool-table result +texts. + +The returned summary has this shape: + +```js +{ + 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" +} +``` + +## Log Helpers + +- `sessionSnapshotSummaryLogLines(summary)` renders snapshot label, workflow, + and default G-code path. +- `sessionSnapshotMetadataLogLines(summary)` renders the metadata subset used in + save/restore log summaries. +- `machineSessionLoadLogLines(summary)` renders the interpreter/session + OPFS-to-WASM mapping and captured result lines. + +## Boundary Rules + +- Do not parse G-code text in these helpers. +- Do not infer tool, parameter, kinematics, planner, or modal semantics. +- Do not derive new CNC behavior from the load result strings. +- Keep new fields limited to host/runtime boundary facts already produced by the + LinuxCNC-owned runtime or UI staging layer. + +## Validation + +Run the focused Node smoke after changing these helpers: + +```bash +wasm-port/tests/ui/node/verify_ini_panel_session_summary.sh +``` + +The aggregate UI Node smoke is: + +```bash +wasm-port/tests/ui/node/verify_ui_node_smokes.sh +``` diff --git a/wasm-port/runtime/ui/ini-panel/app.js b/wasm-port/runtime/ui/ini-panel/app.js index d51f8ad..5d74087 100644 --- a/wasm-port/runtime/ui/ini-panel/app.js +++ b/wasm-port/runtime/ui/ini-panel/app.js @@ -26,6 +26,10 @@ import { createRunSummary, summarizeRunResult, } from "./run-summary.js"; +import { + createMachineSessionLoadSummary, + machineSessionLoadLogLines, +} from "./session-load-summary.js"; import { createSessionSnapshotSummary, sessionSnapshotMetadataLogLines, @@ -616,14 +620,11 @@ document.getElementById("restore-session-snapshot").addEventListener("click", as document.getElementById("load-session").addEventListener("click", async () => { try { await loadMachineSessionIntoWasm(); + const loadSummary = createMachineSessionLoadSummary(loadedSession); setLog( [ "Loaded machine session into the interpreter WASM filesystem.", - `INI: ${loadedSession.ini.opfsPath} -> ${loadedSession.ini.wasmPath}`, - `Parameter file: ${loadedSession.parameters.opfsPath} -> ${loadedSession.parameters.wasmPath}`, - `Parameters: ${loadedSession.parameters.result.trim()}`, - `Tool table file: ${loadedSession.toolTable.opfsPath} -> ${loadedSession.toolTable.wasmPath}`, - `Tool table: ${loadedSession.toolTable.result.trim()}`, + ...machineSessionLoadLogLines(loadSummary), ].join("\n"), ); } catch (error) { @@ -637,15 +638,12 @@ document.getElementById("restore-load-session").addEventListener("click", async await loadMachineSessionIntoWasm(); setField("sessionGcode", snapshot.payload.files.gcode); const summary = createSessionSnapshotSummary(snapshot, sessionSnapshotLabel(snapshot.sessionId)); + const loadSummary = createMachineSessionLoadSummary(loadedSession); setLog( [ "Restored and loaded machine session snapshot.", ...sessionSnapshotSummaryLogLines(summary), - `INI: ${loadedSession.ini.opfsPath} -> ${loadedSession.ini.wasmPath}`, - `Parameter file: ${loadedSession.parameters.opfsPath} -> ${loadedSession.parameters.wasmPath}`, - `Parameters: ${loadedSession.parameters.result.trim()}`, - `Tool table file: ${loadedSession.toolTable.opfsPath} -> ${loadedSession.toolTable.wasmPath}`, - `Tool table: ${loadedSession.toolTable.result.trim()}`, + ...machineSessionLoadLogLines(loadSummary), `G-code: ${summary.gcodeOpfsPath ?? "-"}`, ].join("\n"), ); diff --git a/wasm-port/runtime/ui/ini-panel/session-load-summary.js b/wasm-port/runtime/ui/ini-panel/session-load-summary.js new file mode 100644 index 0000000..d1117bb --- /dev/null +++ b/wasm-port/runtime/ui/ini-panel/session-load-summary.js @@ -0,0 +1,22 @@ +export function createMachineSessionLoadSummary(session) { + return { + iniOpfsPath: session?.ini?.opfsPath ?? null, + iniWasmPath: session?.ini?.wasmPath ?? null, + parameterOpfsPath: session?.parameters?.opfsPath ?? null, + parameterWasmPath: session?.parameters?.wasmPath ?? null, + parameterResult: session?.parameters?.result ?? "", + toolTableOpfsPath: session?.toolTable?.opfsPath ?? null, + toolTableWasmPath: session?.toolTable?.wasmPath ?? null, + toolTableResult: session?.toolTable?.result ?? "", + }; +} + +export function machineSessionLoadLogLines(summary) { + return [ + `INI: ${summary.iniOpfsPath ?? "-"} -> ${summary.iniWasmPath ?? "-"}`, + `Parameter file: ${summary.parameterOpfsPath ?? "-"} -> ${summary.parameterWasmPath ?? "-"}`, + `Parameters: ${summary.parameterResult.trim()}`, + `Tool table file: ${summary.toolTableOpfsPath ?? "-"} -> ${summary.toolTableWasmPath ?? "-"}`, + `Tool table: ${summary.toolTableResult.trim()}`, + ]; +} diff --git a/wasm-port/tests/ui/node/verify_ini_panel_session_summary.mjs b/wasm-port/tests/ui/node/verify_ini_panel_session_summary.mjs index 09f2690..8782f66 100644 --- a/wasm-port/tests/ui/node/verify_ini_panel_session_summary.mjs +++ b/wasm-port/tests/ui/node/verify_ini_panel_session_summary.mjs @@ -1,5 +1,9 @@ import assert from "node:assert/strict"; +import { + createMachineSessionLoadSummary, + machineSessionLoadLogLines, +} from "../../../runtime/ui/ini-panel/session-load-summary.js"; import { createSessionSnapshotSummary, sessionSnapshotMetadataLogLines, @@ -71,4 +75,56 @@ assert.deepEqual( }, ); +const loadSummary = createMachineSessionLoadSummary({ + 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", + }, +}); +assert.deepEqual(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( + machineSessionLoadLogLines(loadSummary), + [ + "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", + ], +); + +assert.deepEqual( + createMachineSessionLoadSummary(null), + { + iniOpfsPath: null, + iniWasmPath: null, + parameterOpfsPath: null, + parameterWasmPath: null, + parameterResult: "", + toolTableOpfsPath: null, + toolTableWasmPath: null, + toolTableResult: "", + }, +); + console.log("ini_panel_session_summary_node_smoke=ok");