推进 INI 面板 session summary helper

This commit is contained in:
2026-06-14 18:22:57 +08:00
parent b2b8bd6b4f
commit aeb290b885
6 changed files with 198 additions and 19 deletions

View File

@@ -1471,3 +1471,71 @@ host_wasm_opfs_browser_smokes=ok
“日志文本/DOM 状态/机器可读状态”三份并行维护的 host-boundary 数据,如果有,选择一个 “日志文本/DOM 状态/机器可读状态”三份并行维护的 host-boundary 数据,如果有,选择一个
小型候选提取为纯 helper 并接入 `verify_ui_node_smokes.sh`;仍不触碰 interpreter、OPFS 小型候选提取为纯 helper 并接入 `verify_ui_node_smokes.sh`;仍不触碰 interpreter、OPFS
bridge 或 LinuxCNC-owned runtime semantics。 bridge 或 LinuxCNC-owned runtime semantics。
二十一、2026-06-14 继续执行记录INI panel session summary helper
本轮继续沿 OPFS/session/UI boundary 推进,把 INI panel 的 session snapshot 日志构造
收敛为纯 helper并把它纳入 UI Node smoke wrapper。
完成内容:
- 新增 `wasm-port/runtime/ui/ini-panel/session-summary.js`
- 导出:
- `createSessionSnapshotSummary(snapshot, fallbackLabel)`
- `sessionSnapshotSummaryLogLines(summary)`
- `sessionSnapshotMetadataLogLines(summary)`
- helper 只聚合 session snapshot boundary facts
- snapshot label
- workflow
- default G-code OPFS path
- ini/parameter/tool/gcode OPFS paths
- `wasm-port/runtime/ui/ini-panel/app.js` 的保存、恢复、restore-load 日志改为复用纯 helper
- `wasm-port/tests/ui/node/verify_ini_panel_session_summary.mjs` 覆盖:
- 正常 session snapshot summary
- runtime label override
- 空 snapshot 默认值;
- log lines 输出;
- `wasm-port/tests/ui/node/verify_ui_node_smokes.sh` 现在同时覆盖 run summary 与 session summary 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_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_run_summary_node_smoke=ok
ini_panel_session_summary_node_smoke=ok
ui_node_smokes=ok
host_wasm_opfs_browser_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
```
下一步建议:
继续沿 OPFS/session/UI boundary 推进。优先扫描 INI panel 中是否还有类似
“日志文本 / DOM 状态 / 机器可读状态”三份并行维护的 host-boundary 数据,如果有,继续
抽取为纯 helper 并接入 `verify_ui_node_smokes.sh`;保持 helper 只描述 host/runtime 边界,
不扩展 CNC 语义。

View File

@@ -26,6 +26,11 @@ import {
createRunSummary, createRunSummary,
summarizeRunResult, summarizeRunResult,
} from "./run-summary.js"; } from "./run-summary.js";
import {
createSessionSnapshotSummary,
sessionSnapshotMetadataLogLines,
sessionSnapshotSummaryLogLines,
} from "./session-summary.js";
const SAMPLE_PATH = const SAMPLE_PATH =
"../../../vendor/linuxcnc/configs/sim/axis/vismach/5axis/table-dual-rotary/xyzab-tdr.ini"; "../../../vendor/linuxcnc/configs/sim/axis/vismach/5axis/table-dual-rotary/xyzab-tdr.ini";
@@ -343,10 +348,7 @@ function sessionSnapshotMetadata() {
} }
function sessionMetadataLogLines(metadata = {}) { function sessionMetadataLogLines(metadata = {}) {
return [ return sessionSnapshotMetadataLogLines(createSessionSnapshotSummary({ metadata }));
`Workflow: ${metadata.workflow ?? "-"}`,
`Default G-code: ${metadata.defaultGcodeOpfsPath ?? "-"}`,
];
} }
function runSessionContextLogLines(program, snapshot = restoredSessionSnapshot) { function runSessionContextLogLines(program, snapshot = restoredSessionSnapshot) {
@@ -576,15 +578,15 @@ document.getElementById("save-session-snapshot").addEventListener("click", async
setField("sessionToolTable", snapshot.payload.files.toolTable); setField("sessionToolTable", snapshot.payload.files.toolTable);
setField("sessionGcode", snapshot.payload.files.gcode); setField("sessionGcode", snapshot.payload.files.gcode);
setField("sessionSnapshot", sessionSnapshotLabel(UI_SESSION)); setField("sessionSnapshot", sessionSnapshotLabel(UI_SESSION));
const summary = createSessionSnapshotSummary(snapshot, sessionSnapshotLabel(UI_SESSION));
setLog( setLog(
[ [
"Saved machine session snapshot to OPFS.", "Saved machine session snapshot to OPFS.",
`Snapshot: ${sessionSnapshotLabel(UI_SESSION)}`, ...sessionSnapshotSummaryLogLines(summary),
...sessionMetadataLogLines(snapshot.metadata), `INI: ${summary.iniOpfsPath}`,
`INI: ${snapshot.payload.files.ini}`, `Parameter file: ${summary.parameterOpfsPath}`,
`Parameter file: ${snapshot.payload.files.parameters}`, `Tool table file: ${summary.toolTableOpfsPath}`,
`Tool table file: ${snapshot.payload.files.toolTable}`, `G-code: ${summary.gcodeOpfsPath}`,
`G-code: ${snapshot.payload.files.gcode}`,
].join("\n"), ].join("\n"),
); );
} catch (error) { } catch (error) {
@@ -595,15 +597,15 @@ document.getElementById("save-session-snapshot").addEventListener("click", async
document.getElementById("restore-session-snapshot").addEventListener("click", async () => { document.getElementById("restore-session-snapshot").addEventListener("click", async () => {
try { try {
const snapshot = await restoreSessionSnapshotToEditor(); const snapshot = await restoreSessionSnapshotToEditor();
const summary = createSessionSnapshotSummary(snapshot, sessionSnapshotLabel(snapshot.sessionId));
setLog( setLog(
[ [
"Restored machine session snapshot from OPFS.", "Restored machine session snapshot from OPFS.",
`Snapshot: ${sessionSnapshotLabel(snapshot.sessionId)}`, ...sessionSnapshotSummaryLogLines(summary),
...sessionMetadataLogLines(snapshot.metadata), `INI: ${summary.iniOpfsPath}`,
`INI: ${snapshot.payload.files.ini}`, `Parameter file: ${summary.parameterOpfsPath}`,
`Parameter file: ${snapshot.payload.files.parameters}`, `Tool table file: ${summary.toolTableOpfsPath}`,
`Tool table file: ${snapshot.payload.files.toolTable}`, `G-code: ${summary.gcodeOpfsPath ?? "-"}`,
`G-code: ${snapshot.payload.files.gcode ?? "-"}`,
].join("\n"), ].join("\n"),
); );
} catch (error) { } catch (error) {
@@ -634,17 +636,17 @@ document.getElementById("restore-load-session").addEventListener("click", async
const snapshot = await restoreSessionSnapshotToEditor(); const snapshot = await restoreSessionSnapshotToEditor();
await loadMachineSessionIntoWasm(); await loadMachineSessionIntoWasm();
setField("sessionGcode", snapshot.payload.files.gcode); setField("sessionGcode", snapshot.payload.files.gcode);
const summary = createSessionSnapshotSummary(snapshot, sessionSnapshotLabel(snapshot.sessionId));
setLog( setLog(
[ [
"Restored and loaded machine session snapshot.", "Restored and loaded machine session snapshot.",
`Snapshot: ${sessionSnapshotLabel(snapshot.sessionId)}`, ...sessionSnapshotSummaryLogLines(summary),
...sessionMetadataLogLines(snapshot.metadata),
`INI: ${loadedSession.ini.opfsPath} -> ${loadedSession.ini.wasmPath}`, `INI: ${loadedSession.ini.opfsPath} -> ${loadedSession.ini.wasmPath}`,
`Parameter file: ${loadedSession.parameters.opfsPath} -> ${loadedSession.parameters.wasmPath}`, `Parameter file: ${loadedSession.parameters.opfsPath} -> ${loadedSession.parameters.wasmPath}`,
`Parameters: ${loadedSession.parameters.result.trim()}`, `Parameters: ${loadedSession.parameters.result.trim()}`,
`Tool table file: ${loadedSession.toolTable.opfsPath} -> ${loadedSession.toolTable.wasmPath}`, `Tool table file: ${loadedSession.toolTable.opfsPath} -> ${loadedSession.toolTable.wasmPath}`,
`Tool table: ${loadedSession.toolTable.result.trim()}`, `Tool table: ${loadedSession.toolTable.result.trim()}`,
`G-code: ${snapshot.payload.files.gcode ?? "-"}`, `G-code: ${summary.gcodeOpfsPath ?? "-"}`,
].join("\n"), ].join("\n"),
); );
} catch (error) { } catch (error) {

View File

@@ -0,0 +1,28 @@
export function createSessionSnapshotSummary(snapshot, fallbackLabel = null) {
const metadata = snapshot?.metadata ?? {};
const files = snapshot?.payload?.files ?? {};
return {
snapshotLabel: fallbackLabel ?? metadata.snapshotLabel ?? null,
workflow: metadata.workflow ?? null,
defaultGcodeOpfsPath: metadata.defaultGcodeOpfsPath ?? null,
iniOpfsPath: files.ini ?? null,
parameterOpfsPath: files.parameters ?? null,
toolTableOpfsPath: files.toolTable ?? null,
gcodeOpfsPath: files.gcode ?? null,
};
}
export function sessionSnapshotSummaryLogLines(summary) {
return [
`Snapshot: ${summary.snapshotLabel ?? "-"}`,
`Workflow: ${summary.workflow ?? "-"}`,
`Default G-code: ${summary.defaultGcodeOpfsPath ?? "-"}`,
];
}
export function sessionSnapshotMetadataLogLines(summary) {
return [
`Workflow: ${summary.workflow ?? "-"}`,
`Default G-code: ${summary.defaultGcodeOpfsPath ?? "-"}`,
];
}

View File

@@ -0,0 +1,74 @@
import assert from "node:assert/strict";
import {
createSessionSnapshotSummary,
sessionSnapshotMetadataLogLines,
sessionSnapshotSummaryLogLines,
} from "../../../runtime/ui/ini-panel/session-summary.js";
const snapshot = {
metadata: {
workflow: "save-session-snapshot",
snapshotLabel: "ui-machine-session/ui-machine-session.json",
defaultGcodeOpfsPath: "linuxcnc/gcode/ui-session.ngc",
},
payload: {
files: {
ini: "linuxcnc/machines/xyzab-tdr/machine.ini",
parameters: "linuxcnc/machines/xyzab-tdr/linuxcnc.var",
toolTable: "linuxcnc/machines/xyzab-tdr/tool.tbl",
gcode: "linuxcnc/gcode/ui-session.ngc",
},
},
};
const summary = createSessionSnapshotSummary(snapshot);
assert.deepEqual(summary, {
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",
});
assert.deepEqual(
createSessionSnapshotSummary(snapshot, "override-session/override.json"),
{
...summary,
snapshotLabel: "override-session/override.json",
},
);
assert.deepEqual(
sessionSnapshotSummaryLogLines(summary),
[
"Snapshot: ui-machine-session/ui-machine-session.json",
"Workflow: save-session-snapshot",
"Default G-code: linuxcnc/gcode/ui-session.ngc",
],
);
assert.deepEqual(
sessionSnapshotMetadataLogLines(summary),
[
"Workflow: save-session-snapshot",
"Default G-code: linuxcnc/gcode/ui-session.ngc",
],
);
assert.deepEqual(
createSessionSnapshotSummary(null),
{
snapshotLabel: null,
workflow: null,
defaultGcodeOpfsPath: null,
iniOpfsPath: null,
parameterOpfsPath: null,
toolTableOpfsPath: null,
gcodeOpfsPath: null,
},
);
console.log("ini_panel_session_summary_node_smoke=ok");

View File

@@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "$0")/../../.." && pwd)"
node "$ROOT_DIR/tests/ui/node/verify_ini_panel_session_summary.mjs"

View File

@@ -4,5 +4,6 @@ set -euo pipefail
ROOT_DIR="$(cd "$(dirname "$0")/../../.." && pwd)" ROOT_DIR="$(cd "$(dirname "$0")/../../.." && pwd)"
"$ROOT_DIR/tests/ui/node/verify_ini_panel_run_summary.sh" "$ROOT_DIR/tests/ui/node/verify_ini_panel_run_summary.sh"
"$ROOT_DIR/tests/ui/node/verify_ini_panel_session_summary.sh"
echo "ui_node_smokes=ok" echo "ui_node_smokes=ok"