推进 INI 面板运行摘要状态
This commit is contained in:
67
text10.txt
67
text10.txt
@@ -1028,3 +1028,70 @@ host_wasm_opfs_browser_smokes=ok
|
|||||||
`programSource`、`snapshotLabel`、`workflow`、`programOpfsPath`、`programWasmPath`,
|
`programSource`、`snapshotLabel`、`workflow`、`programOpfsPath`、`programWasmPath`,
|
||||||
供后续 SDK/API 或 UI panel 读取;先只做 UI/测试边界,不改变 interpreter、OPFS bridge
|
供后续 SDK/API 或 UI panel 读取;先只做 UI/测试边界,不改变 interpreter、OPFS bridge
|
||||||
或 LinuxCNC-owned runtime semantics。
|
或 LinuxCNC-owned runtime semantics。
|
||||||
|
|
||||||
|
十四、2026-06-14 继续执行记录:INI panel run summary state
|
||||||
|
|
||||||
|
本轮继续沿 OPFS/session/UI boundary 推进,把最近一次 `Run G-code` 的 session context
|
||||||
|
同步到可见 UI 状态字段和机器可读 run summary,避免后续 UI/API 从日志文本反解析。
|
||||||
|
|
||||||
|
完成内容:
|
||||||
|
|
||||||
|
- 在 `wasm-port/runtime/ui/ini-panel/index.html` 增加最近一次 run 的可见状态字段:
|
||||||
|
- `Run Source`;
|
||||||
|
- `Run Snapshot`;
|
||||||
|
- `Run Workflow`;
|
||||||
|
- `Run OPFS Path`;
|
||||||
|
- `Run WASM Path`;
|
||||||
|
- 在 `wasm-port/runtime/ui/ini-panel/app.js` 新增:
|
||||||
|
- `clearLastRunSummary()`;
|
||||||
|
- `setLastRunSummary(program, snapshot)`;
|
||||||
|
- 成功运行 G-code 后,UI 写入 `window.linuxCncIniPanelLastRunSummary`,字段包括:
|
||||||
|
- `programSource`;
|
||||||
|
- `snapshotLabel`;
|
||||||
|
- `workflow`;
|
||||||
|
- `programOpfsPath`;
|
||||||
|
- `programWasmPath`;
|
||||||
|
- fallback run 的 summary 明确为 `programSource: "default"`,snapshot/workflow 为 `null`;
|
||||||
|
- snapshot run 的 summary 明确为 `programSource: "snapshot"`,并包含
|
||||||
|
`ui-machine-session/ui-machine-session.json` 与 `save-session-snapshot`;
|
||||||
|
- browser INI panel smoke 同时验证可见字段与 `window.linuxCncIniPanelLastRunSummary`;
|
||||||
|
- 未改变日志格式以外的 runtime 行为、snapshot envelope、OPFS path model、G-code 文本、
|
||||||
|
interpreter run API、canonical-event 输出或 LinuxCNC-owned runtime semantics。
|
||||||
|
|
||||||
|
验证已通过:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git diff --check
|
||||||
|
SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_ini_panel_browser.sh
|
||||||
|
wasm-port/tests/opfs/node/verify_file_service.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
|
||||||
|
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
|
||||||
|
browser_ini_opfs_smoke=ok
|
||||||
|
opfs_file_service_node_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/UI boundary 推进。优先把 `Run G-code` 的机器可读 summary 扩展为
|
||||||
|
包含轻量 runtime result 摘要,例如 `canonicalEventCount`、`motionSnapshotCount`、
|
||||||
|
`runStatus` 和 `iniWasmPath`,方便 UI/API 判断运行是否真的产生 LinuxCNC canonical output;
|
||||||
|
仍只统计 LinuxCNC-owned runtime 输出,不解析或改写 G-code、tool、parameter、planner 等
|
||||||
|
CNC 语义。
|
||||||
|
|||||||
@@ -109,6 +109,11 @@ const fields = {
|
|||||||
sessionGcode: document.getElementById("field-session-gcode"),
|
sessionGcode: document.getElementById("field-session-gcode"),
|
||||||
sessionSnapshot: document.getElementById("field-session-snapshot"),
|
sessionSnapshot: document.getElementById("field-session-snapshot"),
|
||||||
runStatus: document.getElementById("field-run-status"),
|
runStatus: document.getElementById("field-run-status"),
|
||||||
|
runSource: document.getElementById("field-run-source"),
|
||||||
|
runSnapshot: document.getElementById("field-run-snapshot"),
|
||||||
|
runWorkflow: document.getElementById("field-run-workflow"),
|
||||||
|
runOpfsPath: document.getElementById("field-run-opfs-path"),
|
||||||
|
runWasmPath: document.getElementById("field-run-wasm-path"),
|
||||||
fiveaxisRemap: document.getElementById("field-fiveaxis-remap"),
|
fiveaxisRemap: document.getElementById("field-fiveaxis-remap"),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -350,6 +355,34 @@ function runSessionContextLogLines(program, snapshot = restoredSessionSnapshot)
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clearLastRunSummary() {
|
||||||
|
window.linuxCncIniPanelLastRunSummary = null;
|
||||||
|
setField("runSource", "-");
|
||||||
|
setField("runSnapshot", "-");
|
||||||
|
setField("runWorkflow", "-");
|
||||||
|
setField("runOpfsPath", "-");
|
||||||
|
setField("runWasmPath", "-");
|
||||||
|
}
|
||||||
|
|
||||||
|
function setLastRunSummary(program, snapshot = restoredSessionSnapshot) {
|
||||||
|
const snapshotLabel = snapshot ? sessionSnapshotLabel(snapshot.sessionId) : null;
|
||||||
|
const metadata = snapshot?.metadata ?? {};
|
||||||
|
const summary = {
|
||||||
|
programSource: program.source,
|
||||||
|
snapshotLabel,
|
||||||
|
workflow: metadata.workflow ?? null,
|
||||||
|
programOpfsPath: program.opfsPath,
|
||||||
|
programWasmPath: program.wasmPath,
|
||||||
|
};
|
||||||
|
window.linuxCncIniPanelLastRunSummary = summary;
|
||||||
|
setField("runSource", summary.programSource);
|
||||||
|
setField("runSnapshot", summary.snapshotLabel ?? "-");
|
||||||
|
setField("runWorkflow", summary.workflow ?? "-");
|
||||||
|
setField("runOpfsPath", summary.programOpfsPath);
|
||||||
|
setField("runWasmPath", summary.programWasmPath);
|
||||||
|
return summary;
|
||||||
|
}
|
||||||
|
|
||||||
async function loadSelectedGcodeProgram() {
|
async function loadSelectedGcodeProgram() {
|
||||||
const opfsPath = restoredSessionSnapshot?.payload?.files?.gcode;
|
const opfsPath = restoredSessionSnapshot?.payload?.files?.gcode;
|
||||||
let filename = UI_SESSION.defaultGcodeFilename;
|
let filename = UI_SESSION.defaultGcodeFilename;
|
||||||
@@ -627,11 +660,13 @@ document.getElementById("run-gcode").addEventListener("click", async () => {
|
|||||||
interp.writeTextFile(program.wasmPath, program.text);
|
interp.writeTextFile(program.wasmPath, program.text);
|
||||||
clearRunPlayback();
|
clearRunPlayback();
|
||||||
setField("runStatus", "running");
|
setField("runStatus", "running");
|
||||||
|
clearLastRunSummary();
|
||||||
setRunMonitor(5, "running", {}, "running");
|
setRunMonitor(5, "running", {}, "running");
|
||||||
await nextFrame();
|
await nextFrame();
|
||||||
const result = interp.runFileWithIni(program.wasmPath, loadedSession.ini.wasmPath);
|
const result = interp.runFileWithIni(program.wasmPath, loadedSession.ini.wasmPath);
|
||||||
setField("sessionGcode", program.opfsPath);
|
setField("sessionGcode", program.opfsPath);
|
||||||
setField("runStatus", "ok");
|
setField("runStatus", "ok");
|
||||||
|
setLastRunSummary(program);
|
||||||
setCanonicalEvents(result.trim());
|
setCanonicalEvents(result.trim());
|
||||||
playRunMotion(result.trim(), program.text);
|
playRunMotion(result.trim(), program.text);
|
||||||
setLog(
|
setLog(
|
||||||
@@ -646,6 +681,7 @@ document.getElementById("run-gcode").addEventListener("click", async () => {
|
|||||||
setField("runStatus", "failed");
|
setField("runStatus", "failed");
|
||||||
setCanonicalEvents("");
|
setCanonicalEvents("");
|
||||||
clearRunPlayback();
|
clearRunPlayback();
|
||||||
|
clearLastRunSummary();
|
||||||
setRunMonitor(0, "failed", {}, "failed");
|
setRunMonitor(0, "failed", {}, "failed");
|
||||||
setLog(`G-code run failed: ${error.message}`, true);
|
setLog(`G-code run failed: ${error.message}`, true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -279,6 +279,16 @@
|
|||||||
<dd id="field-session-snapshot">-</dd>
|
<dd id="field-session-snapshot">-</dd>
|
||||||
<dt>Run Status</dt>
|
<dt>Run Status</dt>
|
||||||
<dd id="field-run-status">-</dd>
|
<dd id="field-run-status">-</dd>
|
||||||
|
<dt>Run Source</dt>
|
||||||
|
<dd id="field-run-source">-</dd>
|
||||||
|
<dt>Run Snapshot</dt>
|
||||||
|
<dd id="field-run-snapshot">-</dd>
|
||||||
|
<dt>Run Workflow</dt>
|
||||||
|
<dd id="field-run-workflow">-</dd>
|
||||||
|
<dt>Run OPFS Path</dt>
|
||||||
|
<dd id="field-run-opfs-path">-</dd>
|
||||||
|
<dt>Run WASM Path</dt>
|
||||||
|
<dd id="field-run-wasm-path">-</dd>
|
||||||
<dt>5-Axis Remap</dt>
|
<dt>5-Axis Remap</dt>
|
||||||
<dd id="field-fiveaxis-remap">-</dd>
|
<dd id="field-fiveaxis-remap">-</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|||||||
@@ -411,6 +411,45 @@ TOOL_TABLE = browser-tool.tbl
|
|||||||
) {
|
) {
|
||||||
throw new Error(`UI fallback G-code run did not use default OPFS program path: ${fallbackRunLog}`);
|
throw new Error(`UI fallback G-code run did not use default OPFS program path: ${fallbackRunLog}`);
|
||||||
}
|
}
|
||||||
|
assertEqual(
|
||||||
|
uiDocument.getElementById("field-run-source").textContent,
|
||||||
|
"default",
|
||||||
|
"UI fallback run source field",
|
||||||
|
);
|
||||||
|
assertEqual(
|
||||||
|
uiDocument.getElementById("field-run-snapshot").textContent,
|
||||||
|
"-",
|
||||||
|
"UI fallback run snapshot field",
|
||||||
|
);
|
||||||
|
assertEqual(
|
||||||
|
uiDocument.getElementById("field-run-workflow").textContent,
|
||||||
|
"-",
|
||||||
|
"UI fallback run workflow field",
|
||||||
|
);
|
||||||
|
assertEqual(
|
||||||
|
uiDocument.getElementById("field-run-opfs-path").textContent,
|
||||||
|
"linuxcnc/gcode/ui-session.ngc",
|
||||||
|
"UI fallback run OPFS field",
|
||||||
|
);
|
||||||
|
assertEqual(
|
||||||
|
uiDocument.getElementById("field-run-wasm-path").textContent,
|
||||||
|
"/work/ui-session.ngc",
|
||||||
|
"UI fallback run WASM field",
|
||||||
|
);
|
||||||
|
const fallbackRunSummary = uiDocument.defaultView.linuxCncIniPanelLastRunSummary;
|
||||||
|
assertEqual(fallbackRunSummary.programSource, "default", "UI fallback run summary source");
|
||||||
|
assertEqual(fallbackRunSummary.snapshotLabel, null, "UI fallback run summary snapshot");
|
||||||
|
assertEqual(fallbackRunSummary.workflow, null, "UI fallback run summary workflow");
|
||||||
|
assertEqual(
|
||||||
|
fallbackRunSummary.programOpfsPath,
|
||||||
|
"linuxcnc/gcode/ui-session.ngc",
|
||||||
|
"UI fallback run summary OPFS path",
|
||||||
|
);
|
||||||
|
assertEqual(
|
||||||
|
fallbackRunSummary.programWasmPath,
|
||||||
|
"/work/ui-session.ngc",
|
||||||
|
"UI fallback run summary WASM path",
|
||||||
|
);
|
||||||
uiDocument.getElementById("save-session-snapshot").click();
|
uiDocument.getElementById("save-session-snapshot").click();
|
||||||
await waitFor(
|
await waitFor(
|
||||||
() => uiDocument.getElementById("log")?.textContent.includes("Saved machine session snapshot"),
|
() => uiDocument.getElementById("log")?.textContent.includes("Saved machine session snapshot"),
|
||||||
@@ -542,6 +581,53 @@ TOOL_TABLE = browser-tool.tbl
|
|||||||
) {
|
) {
|
||||||
throw new Error(`UI G-code run missing snapshot session context: ${runLog}`);
|
throw new Error(`UI G-code run missing snapshot session context: ${runLog}`);
|
||||||
}
|
}
|
||||||
|
assertEqual(
|
||||||
|
uiDocument.getElementById("field-run-source").textContent,
|
||||||
|
"snapshot",
|
||||||
|
"UI snapshot run source field",
|
||||||
|
);
|
||||||
|
assertEqual(
|
||||||
|
uiDocument.getElementById("field-run-snapshot").textContent,
|
||||||
|
"ui-machine-session/ui-machine-session.json",
|
||||||
|
"UI snapshot run snapshot field",
|
||||||
|
);
|
||||||
|
assertEqual(
|
||||||
|
uiDocument.getElementById("field-run-workflow").textContent,
|
||||||
|
"save-session-snapshot",
|
||||||
|
"UI snapshot run workflow field",
|
||||||
|
);
|
||||||
|
assertEqual(
|
||||||
|
uiDocument.getElementById("field-run-opfs-path").textContent,
|
||||||
|
"linuxcnc/gcode/ui-session.ngc",
|
||||||
|
"UI snapshot run OPFS field",
|
||||||
|
);
|
||||||
|
assertEqual(
|
||||||
|
uiDocument.getElementById("field-run-wasm-path").textContent,
|
||||||
|
"/work/ui-session.ngc",
|
||||||
|
"UI snapshot run WASM field",
|
||||||
|
);
|
||||||
|
const snapshotRunSummary = uiDocument.defaultView.linuxCncIniPanelLastRunSummary;
|
||||||
|
assertEqual(snapshotRunSummary.programSource, "snapshot", "UI snapshot run summary source");
|
||||||
|
assertEqual(
|
||||||
|
snapshotRunSummary.snapshotLabel,
|
||||||
|
"ui-machine-session/ui-machine-session.json",
|
||||||
|
"UI snapshot run summary snapshot",
|
||||||
|
);
|
||||||
|
assertEqual(
|
||||||
|
snapshotRunSummary.workflow,
|
||||||
|
"save-session-snapshot",
|
||||||
|
"UI snapshot run summary workflow",
|
||||||
|
);
|
||||||
|
assertEqual(
|
||||||
|
snapshotRunSummary.programOpfsPath,
|
||||||
|
"linuxcnc/gcode/ui-session.ngc",
|
||||||
|
"UI snapshot run summary OPFS path",
|
||||||
|
);
|
||||||
|
assertEqual(
|
||||||
|
snapshotRunSummary.programWasmPath,
|
||||||
|
"/work/ui-session.ngc",
|
||||||
|
"UI snapshot run summary WASM path",
|
||||||
|
);
|
||||||
if (
|
if (
|
||||||
!runLog.includes("canon_event=STRAIGHT_TRAVERSE") ||
|
!runLog.includes("canon_event=STRAIGHT_TRAVERSE") ||
|
||||||
!runLog.includes("canon_event=STRAIGHT_FEED")
|
!runLog.includes("canon_event=STRAIGHT_FEED")
|
||||||
|
|||||||
Reference in New Issue
Block a user