建立ToolDbProcessPort合约层

结论:已新增ToolDbProcessPort合约、OPFS tool DB flat-file/transcript store和Node/WASM gates,baseline保持28/28/131/0且promotion继续锁定。
This commit is contained in:
2026-06-19 06:36:26 +08:00
parent d9ac3770a7
commit d8e0196c61
13 changed files with 711 additions and 0 deletions

View File

@@ -13,6 +13,9 @@ import {
parameterFilePath,
previewCachePath,
sessionSnapshotPath,
toolDbFilePath,
toolDbRootPath,
toolDbTranscriptPath,
toolTablePath,
} from "../../../runtime/opfs/path-model.js";
import {
@@ -205,6 +208,12 @@ assert.equal(await getOpfsRoot(storage), root);
assert.equal(normalizeOpfsPath("linuxcnc/machines/xyzab.ini"), "linuxcnc/machines/xyzab.ini");
assert.equal(machineIniPath("xyzab-tdr"), "linuxcnc/machines/xyzab-tdr/machine.ini");
assert.equal(toolTablePath("xyzab-tdr"), "linuxcnc/machines/xyzab-tdr/tool.tbl");
assert.equal(toolDbRootPath("xyzab-tdr"), "linuxcnc/machines/xyzab-tdr/tool-db");
assert.equal(toolDbFilePath("xyzab-tdr"), "linuxcnc/machines/xyzab-tdr/tool-db/db_nonran_file");
assert.equal(
toolDbTranscriptPath("xyzab-tdr", "run-1"),
"linuxcnc/machines/xyzab-tdr/tool-db/transcripts/run-1/transcript.json",
);
assert.equal(parameterFilePath("xyzab-tdr"), "linuxcnc/machines/xyzab-tdr/linuxcnc.var");
assertGcodeProgramStoragePath("fixture.ngc", gcodeProgramPath("fixture.ngc"));
assertGcodeProgramStoragePath(

View File

@@ -0,0 +1,110 @@
import assert from "node:assert/strict";
import {
createToolDbStorePaths,
loadToolDbFile,
loadToolDbTranscript,
saveToolDbFile,
saveToolDbTranscript,
} from "../../../runtime/opfs/tool-db-store.js";
import {
toolDbFilePath,
toolDbRootPath,
toolDbTranscriptPath,
} from "../../../runtime/opfs/path-model.js";
class MockFileHandle {
constructor(name) {
this.name = name;
this.textValue = "";
}
async createWritable() {
return {
write: async (text) => {
this.textValue = String(text);
},
close: async () => {},
};
}
async getFile() {
return {
text: async () => this.textValue,
};
}
}
class MockDirectoryHandle {
constructor(name = "") {
this.name = name;
this.dirs = new Map();
this.files = new Map();
}
async getDirectoryHandle(name, options = {}) {
if (!this.dirs.has(name)) {
if (!options.create) {
throw new Error(`missing directory: ${name}`);
}
this.dirs.set(name, new MockDirectoryHandle(name));
}
return this.dirs.get(name);
}
async getFileHandle(name, options = {}) {
if (!this.files.has(name)) {
if (!options.create) {
throw new Error(`missing file: ${name}`);
}
this.files.set(name, new MockFileHandle(name));
}
return this.files.get(name);
}
}
const root = new MockDirectoryHandle();
const storage = {
getDirectory: async () => root,
};
assert.equal(toolDbRootPath("db-demo"), "linuxcnc/machines/db-demo/tool-db");
assert.equal(toolDbFilePath("db-demo"), "linuxcnc/machines/db-demo/tool-db/db_nonran_file");
assert.equal(
toolDbTranscriptPath("db-demo", "run-42"),
"linuxcnc/machines/db-demo/tool-db/transcripts/run-42/transcript.json",
);
assert.deepEqual(createToolDbStorePaths("db-demo", { runId: "run-42" }), {
dbFile: "linuxcnc/machines/db-demo/tool-db/db_nonran_file",
transcript: "linuxcnc/machines/db-demo/tool-db/transcripts/run-42/transcript.json",
});
const dbText = "T11 P111 D0.33 Z0.11\nT14 P114 D0.14 Z0.14\n";
const savedDb = await saveToolDbFile("db-demo", dbText, { storage });
assert.equal(savedDb.opfsPath, "linuxcnc/machines/db-demo/tool-db/db_nonran_file");
assert.equal(savedDb.displayPath, "/machines/db-demo/tool-db/db_nonran_file");
assert.match(savedDb.dbFileHash, /^[0-9a-f]{8}$/);
const loadedDb = await loadToolDbFile("db-demo", { storage });
assert.equal(loadedDb.text, dbText);
assert.equal(loadedDb.dbFileHash, savedDb.dbFileHash);
const transcript = [
{ direction: "read", line: "v2.1" },
{ direction: "write", line: "g" },
{ direction: "read", line: "FINI (get_cmd)" },
];
const savedTranscript = await saveToolDbTranscript("db-demo", "run-42", transcript, { storage });
assert.equal(
savedTranscript.opfsPath,
"linuxcnc/machines/db-demo/tool-db/transcripts/run-42/transcript.json",
);
assert.equal(savedTranscript.displayPath, "/machines/db-demo/tool-db/transcripts/run-42/transcript.json");
assert.match(savedTranscript.transcriptHash, /^[0-9a-f]{8}$/);
const loadedTranscript = await loadToolDbTranscript("db-demo", "run-42", { storage });
assert.equal(loadedTranscript.payload.schema, "linuxcnc.toolDbProcessTranscript.v1");
assert.deepEqual(loadedTranscript.payload.transcript, transcript);
assert.equal(loadedTranscript.transcriptHash, savedTranscript.transcriptHash);
console.log("tool_db_store_opfs=ok");

View File

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