From a829984300016e7a9cca4183e17911cb42e4a1cc Mon Sep 17 00:00:00 2001 From: wangdequan Date: Sun, 14 Jun 2026 15:03:33 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8E=A8=E8=BF=9B=20OPFS=20=E6=9C=BA=E5=99=A8?= =?UTF-8?q?=E4=BC=9A=E8=AF=9D=E5=BF=AB=E7=85=A7=E4=BF=9D=E5=AD=98=E5=85=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- text10.txt | 79 +++++++++++++++++++ wasm-port/runtime/opfs/snapshot-store.js | 6 ++ wasm-port/tests/browser/ini_panel_smoke.html | 37 +++++++++ .../tests/opfs/node/verify_file_service.mjs | 25 ++++++ 4 files changed, 147 insertions(+) diff --git a/text10.txt b/text10.txt index 4a8d7aa..4b03c0d 100644 --- a/text10.txt +++ b/text10.txt @@ -70,6 +70,22 @@ remap 等语义必须来自 LinuxCNC upstream 或 vendored LinuxCNC C/C++/配置 native、Node、browser gate 都按顺序通过; - browser 不能依赖目录枚举。 +4. 加快实质性推进铁律。 + +核心移植已稳定后,暂停性能测试和纯 test glue 微整理,后续默认优先推进能被用户或 +上层 API 直接使用的实质性能力: + +- 优先级从高到低为:OPFS/session persistence、SDK/API surface、browser/UI workflow、 + sim config coverage promotion、host/runtime boundary proof、文档化可执行工作流; +- 每批应尽量产出一个可调用 helper、可复用 API、可验证用户流程、可执行 gate、 + 可提升覆盖面的 runtime boundary proof,或者一份直接指导下一步实现的设计/清单; +- 允许继续做测试胶水,但只能作为支撑实质能力的验证,不再把“局部常量化/断言整理” + 作为主要目标; +- 禁止启动性能测试,除非已有明确功能路径和用户流程需要性能基线; +- 禁止为了“推进”而扩大 CNC 语义边界;G-code、tool、parameter、planner 等语义仍必须 + 由 LinuxCNC-owned runtime 提供; +- 每批仍必须小步、可验证、可回滚,并按 `text10.txt` 记录结论和下一步建议。 + 三、当前完成情况摘要 1. 当前工作树状态。 @@ -336,3 +352,66 @@ host_wasm_opfs_browser_smokes=ok 继续小批量 browser test glue guard。优先扫描 machine text store path assertion groups 或剩余 OPFS readback path groups 是否还能进一步局部常量化或复用 existing helpers; 只改测试胶水,不改变输入、OPFS path、WASM path 字符串或保存/读取行为。 + +三、2026-06-14 继续执行记录:OPFS machine session snapshot save helper + +本轮先将“加快实质性推进”规则写入 `text10.txt` 的当前项目纪律铁律中,并按该规则 +继续推进 OPFS/session persistence 的实际 API 入口,而不是继续纯 test glue 微整理。 + +完成内容: + +- 在“当前项目纪律”中新增“加快实质性推进铁律”; +- 在 `wasm-port/runtime/opfs/snapshot-store.js` 新增 + `saveMachineSessionSnapshot(sessionId, machineId, options)`; +- 该 helper 组合既有 `createMachineSessionSnapshotPayload(...)` 与 + `saveSessionSnapshot(...)`,让上层能用一个入口生成并保存机器会话快照; +- 支持沿用既有 `storage`、snapshot `filename`、`createdAt`、`metadata` 以及 + `iniFilename`、`parameterFilename`、`toolTableFilename`、`gcodeFilename`、 + `iniOpfsPath`、`parameterOpfsPath`、`toolTableOpfsPath`、`gcodeOpfsPath` + 选项; +- 在 Node OPFS smoke 中验证组合 helper 的自定义 snapshot 文件名、G-code path、 + metadata 与 load round trip; +- 在 browser INI panel smoke 中验证浏览器运行时可直接调用组合 helper,并能加载回 + parameter/tool-table/G-code path 与 metadata; +- 未改变 session snapshot envelope 格式、版本、path model、file-service 行为或既有 + save/load API; +- 未改变 OPFS bridge behavior、SDK planner、interpreter、INI、tool、parameter 或 + LinuxCNC-owned runtime semantics。 + +验证已通过: + +```bash +git diff --check +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 +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 +opfs_file_service_node_smoke=ok +browser_ini_opfs_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 的实质能力推进。优先新增 +`loadMachineSessionSnapshot(sessionId, machineId, options)`,在读取 generic snapshot +后校验 `payload.machineId` 与机器文件 path 结构,并补 Node/browser smoke;如果该入口 +已足够清晰,再把 save/load machine session snapshot 接到 INI panel 的实际会话保存/恢复 +workflow。仍只处理 OPFS/filesystem/browser boundary,不引入或重写任何 CNC 语义。 diff --git a/wasm-port/runtime/opfs/snapshot-store.js b/wasm-port/runtime/opfs/snapshot-store.js index f1f7246..0b5b120 100644 --- a/wasm-port/runtime/opfs/snapshot-store.js +++ b/wasm-port/runtime/opfs/snapshot-store.js @@ -89,6 +89,12 @@ export async function saveSessionSnapshot(sessionId, payload, options = {}) { return snapshot; } +export async function saveMachineSessionSnapshot(sessionId, machineId, options = {}) { + assertPlainObject(options, "machine session snapshot save options"); + const payload = createMachineSessionSnapshotPayload(machineId, options); + return saveSessionSnapshot(sessionId, payload, options); +} + export async function loadSessionSnapshot(sessionId, options = {}) { const path = sessionSnapshotPath(sessionId, options.filename); const text = await loadTextFile(path, options.storage); diff --git a/wasm-port/tests/browser/ini_panel_smoke.html b/wasm-port/tests/browser/ini_panel_smoke.html index aa300e0..b9c4adc 100644 --- a/wasm-port/tests/browser/ini_panel_smoke.html +++ b/wasm-port/tests/browser/ini_panel_smoke.html @@ -17,6 +17,7 @@ import { createMachineSessionSnapshotPayload, loadSessionSnapshot, + saveMachineSessionSnapshot, saveSessionSnapshot, } from "../../runtime/opfs/snapshot-store.js"; import { @@ -204,6 +205,42 @@ TOOL_TABLE = browser-tool.tbl customSnapshot.metadata.source, "custom snapshot metadata", ); + const machineSessionSnapshot = await saveMachineSessionSnapshot( + "browser-machine-session", + "browser-smoke", + { + filename: "browser-machine-snapshot.json", + parameterFilename: "browser-linuxcnc.var", + toolTableFilename: "browser-tool.tbl", + gcodeFilename: "browser-smoke.ngc", + createdAt: "2026-06-08T00:00:00.000Z", + metadata: { source: "browser-machine-session" }, + }, + ); + const loadedMachineSessionSnapshot = await loadSessionSnapshot( + "browser-machine-session", + { filename: "browser-machine-snapshot.json" }, + ); + assertEqual( + machineSessionSnapshot.payload.files.parameters, + "linuxcnc/machines/browser-smoke/browser-linuxcnc.var", + "machine session snapshot parameter file", + ); + assertEqual( + machineSessionSnapshot.payload.files.toolTable, + "linuxcnc/machines/browser-smoke/browser-tool.tbl", + "machine session snapshot tool table", + ); + assertEqual( + loadedMachineSessionSnapshot.payload.files.gcode, + "linuxcnc/gcode/browser-smoke.ngc", + "machine session snapshot G-code", + ); + assertEqual( + loadedMachineSessionSnapshot.metadata.source, + "browser-machine-session", + "machine session snapshot metadata", + ); await assertRejects( "browser snapshot invalid filename save", () => saveSessionSnapshot("browser-session", {}, { diff --git a/wasm-port/tests/opfs/node/verify_file_service.mjs b/wasm-port/tests/opfs/node/verify_file_service.mjs index 0db1784..fc83558 100644 --- a/wasm-port/tests/opfs/node/verify_file_service.mjs +++ b/wasm-port/tests/opfs/node/verify_file_service.mjs @@ -19,6 +19,7 @@ import { createMachineSessionSnapshotPayload, createSessionSnapshot, loadSessionSnapshot, + saveMachineSessionSnapshot, saveSessionSnapshot, validateSessionSnapshot, } from "../../../runtime/opfs/snapshot-store.js"; @@ -325,6 +326,30 @@ assert.deepEqual( }), customSnapshot, ); +const machineSessionSnapshot = await saveMachineSessionSnapshot( + "machine-session-1", + "xyzab-tdr", + { + storage, + filename: "machine-session-snapshot.json", + gcodeFilename: "fixture.ngc", + createdAt: "2026-06-08T00:00:00.000Z", + metadata: { source: "node-machine-session" }, + }, +); +assertSessionSnapshotStoragePath( + "machine-session-1", + sessionSnapshotPath("machine-session-1", "machine-session-snapshot.json"), + "machine-session-snapshot.json", +); +assert.deepEqual(machineSessionSnapshot.payload, snapshotPayload); +assert.deepEqual( + await loadSessionSnapshot("machine-session-1", { + storage, + filename: "machine-session-snapshot.json", + }), + machineSessionSnapshot, +); await saveMachineTextFiles("xyzab-tdr", { ini: "[EMC]\nMACHINE = xyzab-tdr\n",