23 lines
2.9 KiB
JavaScript
23 lines
2.9 KiB
JavaScript
import crypto from "node:crypto";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { execFileSync } from "node:child_process";
|
|
const root = path.resolve(path.dirname(new URL(import.meta.url).pathname), "..");
|
|
const docs = path.join(root, "docs/p6");
|
|
const files = {
|
|
X: "sketcher-gate.json",
|
|
inspectSourceInventory: "sketcher-action-02-inspect-source-inventory.json",
|
|
pythonApi: "sketcher-action-03-python-api.json",
|
|
saveReopen: "sketcher-action-04-persistence.json",
|
|
};
|
|
const read = file => { const bytes = fs.readFileSync(path.join(docs, file)); return { value: JSON.parse(bytes), sha256: crypto.createHash("sha256").update(bytes).digest("hex"), artifact: `docs/p6/${file}` }; };
|
|
const evidence = Object.fromEntries(Object.entries(files).map(([name, file]) => [name, read(file)]));
|
|
const contracts = Object.fromEntries(Object.entries(evidence).map(([name, item]) => [name, { result: item.value.result, artifact: item.artifact, sha256: item.sha256 }]));
|
|
const result = contracts.X.result === "pass" && contracts.inspectSourceInventory.result === "pass" && contracts.pythonApi.result === "pass" && contracts.saveReopen.result === "pass" ? "pass" : "fail";
|
|
const report = { schema: "freecad-web-p6-sketcher-module-gate/v1", taskId: "FW-P6-SKT-Y", module: "Sketcher", result, sourceRevision: execFileSync("git", ["-C", "freecad-source", "rev-parse", "HEAD"], { encoding: "utf8" }).trim(), closedActions: ["create/recompute", "inspect/source-inventory", "python-api", "save/reopen"], contracts, moduleStatusAfterGate: result === "pass" ? "completed" : "pending", coverage: { createRecompute: "pass", inspectSourceInventory: "pass_boundary", pythonApi: "pass_boundary", saveReopen: "pass" }, boundaries: ["Inspect/source-inventory and python-api are read-only pass_boundary actions with no FCStd state.", "Save/reopen covers one Sketcher::SketchObject with one line, one horizontal constraint, and ShapeMaterial UUID fallback in GUI-free Web.", "No release, legal, performance, cross-version migration, or arbitrary Sketcher graph claim is made."] };
|
|
fs.writeFileSync(path.join(docs, "sketcher-module-gate.json"), `${JSON.stringify(report, null, 2)}\n`);
|
|
fs.writeFileSync(path.join(docs, "sketcher-module-gate.md"), `# Sketcher module gate\n\n- Result: \`${result}\`\n- Source revision: \`${report.sourceRevision}\`\n- Closed actions: create/recompute, inspect/source-inventory, python-api, save/reopen\n- Sketcher status after gate: \`${report.moduleStatusAfterGate}\`\n\nAll four declared Sketcher actions have independent evidence. Read-only actions remain explicit pass boundaries; save/reopen includes ShapeMaterial UUID fallback.\n`);
|
|
fs.writeFileSync(path.join(root, "docs/freecad-p6-sketcher-y-gate.log"), `${JSON.stringify({ result, actions: report.closedActions.length, moduleStatus: report.moduleStatusAfterGate })}\n`);
|
|
console.log(JSON.stringify({ result, actions: report.closedActions.length, moduleStatus: report.moduleStatusAfterGate }));
|
|
if (result !== "pass") process.exitCode = 1;
|