推进 INI 面板 G-code 回退来源 guard

This commit is contained in:
2026-06-14 15:39:18 +08:00
parent f204b7f113
commit a158f66071
3 changed files with 85 additions and 1 deletions

View File

@@ -672,3 +672,63 @@ host_wasm_opfs_browser_smokes=ok
snapshot、只保存 machine files 并 `Load Machine Session` 后运行 G-code 的路径,验证
`Run G-code` 会回退默认 `linuxcnc/gcode/ui-session.ngc` 且保持 canonical-event flow。
仍只做 OPFS/session/UI 编排,不解析或改写 G-code 语义。
八、2026-06-14 继续执行记录INI panel G-code fallback source guard
本轮继续推进 browser/UI workflow 的可验证性,补齐 `Run G-code` 在未恢复 snapshot
时的默认 G-code fallback 覆盖。
完成内容:
- 在 `wasm-port/runtime/ui/ini-panel/app.js` 的 selected G-code program 中增加
`source` 标记:
- restored snapshot 提供 `linuxcnc/gcode/<filename>` 时为 `snapshot`
- 未恢复 snapshot 或 snapshot 无可用 G-code path 时为 `default`
- `Run G-code` 日志新增 `Program source: ...`,让 browser smoke 能明确区分 default
fallback 与 snapshot 文件清单路径;
- 在 browser INI panel smoke 中新增 fallback 流程:
- 只保存 machine files
- 通过既有 `Load Machine Session` 加载到 interpreter WASM FS
- 直接 `Run G-code`
- 验证程序来自默认 `linuxcnc/gcode/ui-session.ngc -> /work/ui-session.ngc`
- 验证 `Program source: default` 与 LinuxCNC canonical-event flow
- 原 restore-and-load 后的 snapshot G-code run 继续验证 `Program source: snapshot`
- 未改变 G-code 文本内容、interpreter run API、canonical-event 解析、OPFS path model
或 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 做小步实质推进。优先把
`linuxcnc/gcode/<filename>` 到 filename 的转换下沉为 OPFS G-code store 的可复用 helper
例如 `gcodeFilenameFromProgramPath(...)`,并在 Node OPFS smoke 与 browser smoke 中覆盖
合法 path、非 G-code path fallback 或 reject 行为。仍不解析或改写 G-code 语义。

View File

@@ -323,9 +323,11 @@ function gcodeFilenameFromSnapshotPath(path) {
async function loadSelectedGcodeProgram() {
const opfsPath = restoredSessionSnapshot?.payload?.files?.gcode;
const filename = gcodeFilenameFromSnapshotPath(opfsPath);
const hasSnapshotGcode = typeof opfsPath === "string" && opfsPath.startsWith("linuxcnc/gcode/");
return {
filename,
opfsPath: opfsPath ?? `linuxcnc/gcode/${filename}`,
source: hasSnapshotGcode ? "snapshot" : "default",
wasmPath: GCODE_WASM_FILE,
text: await loadGcodeProgram(filename),
};
@@ -593,6 +595,7 @@ document.getElementById("run-gcode").addEventListener("click", async () => {
[
"Ran G-code through LinuxCNC interpreter WASM.",
`Program: ${program.opfsPath} -> ${program.wasmPath}`,
`Program source: ${program.source}`,
`INI: ${loadedSession.ini.wasmPath}`,
result.trim(),
].join("\n"),

View File

@@ -379,6 +379,24 @@ TOOL_TABLE = browser-tool.tbl
() => uiDocument.getElementById("log")?.textContent.includes("Saved machine text files"),
"machine file save",
);
uiDocument.getElementById("load-session").click();
await waitFor(
() => uiDocument.getElementById("log")?.textContent.includes("Loaded machine session"),
"fallback machine session load",
);
uiDocument.getElementById("run-gcode").click();
await waitFor(
() => uiDocument.getElementById("log")?.textContent.includes("Ran G-code"),
"fallback G-code run",
);
const fallbackRunLog = uiDocument.getElementById("log").textContent;
if (
!fallbackRunLog.includes("Program: linuxcnc/gcode/ui-session.ngc -> /work/ui-session.ngc") ||
!fallbackRunLog.includes("Program source: default") ||
!fallbackRunLog.includes("canon_event=STRAIGHT_FEED")
) {
throw new Error(`UI fallback G-code run did not use default OPFS program path: ${fallbackRunLog}`);
}
uiDocument.getElementById("save-session-snapshot").click();
await waitFor(
() => uiDocument.getElementById("log")?.textContent.includes("Saved machine session snapshot"),
@@ -464,7 +482,10 @@ TOOL_TABLE = browser-tool.tbl
"UI G-code run status",
);
const runLog = uiDocument.getElementById("log").textContent;
if (!runLog.includes("Program: linuxcnc/gcode/ui-session.ngc -> /work/ui-session.ngc")) {
if (
!runLog.includes("Program: linuxcnc/gcode/ui-session.ngc -> /work/ui-session.ngc") ||
!runLog.includes("Program source: snapshot")
) {
throw new Error(`UI G-code run did not use snapshot OPFS program path: ${runLog}`);
}
if (