Files
FreeCADWasmDev/tools/run_p6_core_shell_gate.mjs
wangdequan 9a7c4f0335 Save FreeCAD Web workspace sources and user validation evidence
IFC native binding remains incomplete; preserve accurate test results.
2026-09-15 22:01:58 +08:00

72 lines
3.5 KiB
JavaScript

#!/usr/bin/env node
import crypto from "node:crypto";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const docs = path.join(root, "docs");
const p6 = path.join(docs, "p6");
const read = (file) => JSON.parse(fs.readFileSync(path.join(p6, file), "utf8"));
const hash = (file) => crypto.createHash("sha256").update(fs.readFileSync(path.join(p6, file))).digest("hex");
const chrome = read("core-shell-chrome.json");
const cases = Object.fromEntries(chrome.cases.map((item) => [item.id, item]));
const required = ["core-ready", "core-action", "core-duplicate", "core-expected-error", "core-cancel", "core-reset", "core-repeat"];
const action = cases["core-action"]?.state;
const native = action?.response?.result?.native;
const contracts = Object.fromEntries(required.map((id) => [id, {
status: cases[id]?.status ?? "missing",
stage: cases[id]?.state?.stage ?? "missing",
responseKind: cases[id]?.state?.response?.kind ?? null,
error: cases[id]?.state?.response?.error?.code ?? null,
progressEvents: cases[id]?.state?.progress?.length ?? 0,
}]));
const result = chrome.result === "pass"
&& required.every((id) => cases[id]?.status === "pass")
&& action?.stage === "success"
&& action?.response?.kind === "result"
&& action?.progress?.length === 3
&& cases["core-duplicate"]?.state?.response?.error?.code === "duplicate_request"
&& cases["core-cancel"]?.state?.response?.error?.code === "cancelled"
&& native?.recomputeCount === 1
&& native?.transactionUndoVolume > 0
&& native?.transactionRedoVolume > native?.transactionUndoVolume;
const report = {
schema: "freecad-web-p6-core-shell-gate/v1",
taskId: "FW-P6-FPA-B",
result: result ? "pass" : "fail",
contracts,
native: {
document: action?.response?.result?.document ?? null,
values: native ?? null,
resourcesReleased: action?.response?.result?.resourcesReleased ?? false,
},
chrome: {
artifact: "docs/p6/core-shell-chrome.json",
sha256: hash("core-shell-chrome.json"),
screenshot: chrome.evidence?.screenshot ?? null,
screenshotSha256: chrome.evidence?.screenshotSha256 ?? null,
browser: chrome.chrome?.version ?? null,
externalRequests: chrome.cases.flatMap((item) => item.externalRequests ?? []).length,
exceptions: chrome.cases.flatMap((item) => item.exceptions ?? []).length,
},
architecture: {
schema: "freecad-web-core/v1",
worker: "web/src/core.worker.ts",
runtime: "web/src/core-runtime.ts",
shell: "web/src/core-shell.tsx",
nativeProbe: "FreeCADWebDocumentProbe",
queue: "one serial queue per Worker; duplicate and cancellation are typed terminal events",
},
boundaries: [
"B closes the reusable React/Worker/Document actor substrate and one native multi-step contract only.",
"403 object types, 236 format records, full FCStd graph coverage, and the 13,385 Python API dispositions remain later cards.",
"The page does not claim desktop GUI or arbitrary Python execution.",
],
};
fs.writeFileSync(path.join(p6, "core-shell-gate.json"), `${JSON.stringify(report, null, 2)}\n`);
fs.writeFileSync(path.join(docs, "freecad-p6-core-shell-gate.log"), `${JSON.stringify({ result: report.result, cases: required.length, externalRequests: report.chrome.externalRequests, exceptions: report.chrome.exceptions })}\n`);
console.log(JSON.stringify({ result: report.result, cases: required.length, externalRequests: report.chrome.externalRequests, exceptions: report.chrome.exceptions }));
if (!result) process.exitCode = 1;