38 lines
3.6 KiB
JavaScript
38 lines
3.6 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 readJson = file => JSON.parse(fs.readFileSync(path.join(docs, file), "utf8"));
|
|
const readCard = file => fs.readFileSync(path.join(root, "docs/tasks/p6/robot", file), "utf8");
|
|
const firstSlice = fs.readFileSync(path.join(root, "docs/p6/robot-gate.md"), "utf8");
|
|
const action02 = readJson("robot-action-02-persistence.json");
|
|
const action04 = readJson("robot-action-04-save-reopen.json");
|
|
const action03Card = readCard("FW-P6-ROB-ACT-03-G.md");
|
|
const action04Card = readCard("FW-P6-ROB-ACT-04-G.md");
|
|
const revision = execFileSync("git", ["-C", path.join(root, "freecad-source"), "rev-parse", "HEAD"], { encoding: "utf8" }).trim();
|
|
const actions = [
|
|
{ id: "FW-P6-ROB-ACT-01", action: "create/recompute", result: /Result:\s*`pass`/.test(firstSlice) ? "pass" : "fail", evidence: ["docs/p6/robot-gate.md", "docs/p6/robot-kernel.json"] },
|
|
{ id: "FW-P6-ROB-ACT-02", action: "inspect/source-inventory", result: action02.result, applicable: action02.applicable, evidence: ["docs/p6/robot-action-02-persistence.json"] },
|
|
{ id: "FW-P6-ROB-ACT-03", action: "python-api", result: /结论:`pass_boundary`/.test(action03Card) ? "pass_boundary" : "fail", applicable: false, evidence: ["docs/tasks/p6/robot/FW-P6-ROB-ACT-03-G.md", "docs/p6/robot-action-03-persistence.json"] },
|
|
{ id: "FW-P6-ROB-ACT-04", action: "save/reopen", result: action04.result, applicable: action04.applicable, evidence: ["docs/p6/robot-action-04-save-reopen.json"] },
|
|
];
|
|
const result = actions.every(action => action.result === "pass" || action.result === "pass_boundary");
|
|
const summary = { module: "Robot", result: result ? "completed" : "pending", actions: actions.map(({ id, action, result: status, applicable }) => ({ id, action, result: status, ...(applicable === undefined ? {} : { applicable }) })), revision, sourceChanges: ["src/Mod/Robot/App/RobotObject.cpp::RobotObject::Save", "src/Mod/Robot/App/RobotObject.cpp::RobotObject::Restore", "src/WebAssembly/FreeCADCoreProbe/RobotRuntimeProbeFixed.cpp"], boundaries: ["inspect/source-inventory and python-api are read-only and explicitly pass_boundary for persistence.", "save/reopen is limited to the fixed local FCStd fixture; RobotGui and cross-version migration remain out of scope."], evidenceSha256: crypto.createHash("sha256").update(JSON.stringify({ actions, revision })).digest("hex") };
|
|
fs.writeFileSync(path.join(docs, "robot-module-gate.json"), `${JSON.stringify({ schema: "freecad-web-p6-robot-module-gate/v1", taskId: "FW-P6-ROB-Y", ...summary }, null, 2)}\n`);
|
|
const markdown = [
|
|
"# Robot module gate",
|
|
"",
|
|
`- Result: ${summary.result}`,
|
|
`- Revision: ${revision}`,
|
|
`- Actions: create/recompute ${actions[0].result}; inspect/source-inventory ${actions[1].result}; python-api ${actions[2].result}; save/reopen ${actions[3].result}.`,
|
|
"- Evidence: docs/p6/robot-module-gate.json, docs/p6/robot-action-02-persistence.json, docs/p6/robot-action-04-save-reopen.json.",
|
|
"- Boundaries: inspect/source-inventory and python-api remain read-only pass-boundary actions; fixed local FCStd only for persistence; RobotGui, arbitrary external paths and cross-version migration are excluded.",
|
|
"",
|
|
].join("\n");
|
|
fs.writeFileSync(path.join(docs, "robot-module-gate.md"), markdown);
|
|
console.log(JSON.stringify({ result: summary.result, actionCount: actions.length, evidenceSha256: summary.evidenceSha256 }));
|
|
if (!result) process.exitCode = 1;
|