Files
FreeCADWasmDev/tools/run_p6_cam_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

77 lines
3.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
import assert from "node:assert/strict";
import crypto from "node:crypto";
import fs from "node:fs";
import path from "node:path";
const root = path.resolve(path.dirname(new URL(import.meta.url).pathname), "..");
const docsRoot = path.join(root, "docs");
const read = (relativePath) => JSON.parse(fs.readFileSync(path.join(docsRoot, relativePath), "utf8"));
const sha256 = (relativePath) => crypto.createHash("sha256").update(fs.readFileSync(path.join(docsRoot, relativePath))).digest("hex");
const contractFiles = {
A: "p6/cam-source-boundary.json",
B: "p6/cam-runtime.json",
C: "p6/cam-kernel.json",
D: "p6/cam-recovery.json",
E: "p6/cam-facade.json",
F: "p6/cam-chrome.json",
G: "p6/cam-persistence.json",
};
const reports = Object.fromEntries(Object.entries(contractFiles).map(([key, file]) => [key, read(file)]));
const sourceRevision = reports.A.sourceRevision;
assert.equal(reports.A.result, "pass_probe_only");
assert.equal(reports.B.status, "pass");
assert.equal(reports.C.status, "pass");
assert.equal(reports.D.status, "pass");
assert.equal(reports.E.status, "pass");
assert.equal(reports.F.result, "pass");
assert.equal(reports.G.result, "pass");
assert.equal(reports.F.network.externalRequestCount, 0);
assert.equal(reports.F.exceptions.length, 0);
assert.equal(reports.G.applicable, false);
for (const key of ["B", "C", "D", "G"]) assert.equal(reports[key].source_revision ?? reports[key].sourceRevision, sourceRevision);
const contracts = Object.fromEntries(Object.entries(contractFiles).map(([key, file]) => {
const report = reports[key];
return [key, {
artifact: `docs/${file}`,
artifactSha256: sha256(file),
result: report.status === "pass" || report.result === "pass" || report.result === "pass_probe_only" ? "pass" : "fail",
sourceRevision: report.sourceRevision ?? report.source_revision ?? sourceRevision,
}];
}));
const report = {
schema: "freecad-web-p6-cam-gate/v1",
task_id: "FW-P6-CAM-X",
module: "CAM",
result: "pass",
closedAction: "create/recompute",
sourceRevision,
contracts,
chrome: {
browser: reports.F.chrome.version,
mode: reports.F.mode,
viewport: reports.F.viewport,
externalRequests: reports.F.network.externalRequestCount,
runtimeExceptions: reports.F.exceptions.length,
},
coverage: {
createRecompute: "pass",
importExport: "pending",
inspectSourceInventory: "pending",
pythonApi: "pending",
saveReopen: "pending",
},
moduleStatus: "pending",
boundaries: [
"Only the create/recompute action has a complete A-G contract chain.",
"The persistence contract records save/reopen as not applicable for the current ephemeral facade action.",
"Other CAM actions remain pending until their own C-G chains and the Y gate are complete.",
],
};
fs.writeFileSync(path.join(docsRoot, "p6/cam-gate.json"), `${JSON.stringify(report, null, 2)}\n`);
fs.writeFileSync(path.join(docsRoot, "p6/cam-gate.md"), `# CAM 首切片 Gate\n\n- 状态:\`pass\`\n- 关闭动作:\`create/recompute\`\n- 源码 revision:\`${sourceRevision}\`\n\nA-G 七个原子合同均有独立产物、hash 和结论。${reports.F.chrome.version} ${reports.F.mode} 回放 viewport ${reports.F.viewport.width}x${reports.F.viewport.height},外部请求 ${reports.F.network.externalRequestCount}、运行时异常 ${reports.F.exceptions.length}。\n\nCAM 模块仍保持 \`pending\`:\`import/export\`、\`inspect/source-inventory\`、\`python-api\` 和 \`save/reopen\` 尚未完成各自动作级 C-G 子链;本 gate 不把首切片通过推断为完整模块。\n`);
console.log(JSON.stringify({ result: report.result, closedAction: report.closedAction, moduleStatus: report.moduleStatus, contracts: Object.keys(contracts).length }));