58 lines
3.9 KiB
JavaScript
58 lines
3.9 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("document-contract-chrome.json");
|
|
const cases = Object.fromEntries(chrome.cases.map((item) => [item.id, item]));
|
|
const required = ["document-ready", "document-action", "document-duplicate", "document-expected-error", "document-cancel", "document-reset", "document-repeat"];
|
|
const resultState = cases["document-action"]?.state?.response?.result;
|
|
const repeatState = cases["document-repeat"]?.state?.response?.result;
|
|
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")
|
|
&& cases["document-action"]?.state?.response?.kind === "result"
|
|
&& cases["document-action"]?.state?.progress?.length === 5
|
|
&& cases["document-duplicate"]?.state?.response?.error?.code === "duplicate_request"
|
|
&& cases["document-cancel"]?.state?.response?.error?.code === "cancelled"
|
|
&& resultState?.semanticRoundTrip === true
|
|
&& repeatState?.semanticRoundTrip === true
|
|
&& resultState?.recovery?.invalidError === "Length of box too small"
|
|
&& resultState?.recovery?.hasError === 0
|
|
&& resultState?.opened?.objectType === "Part::Box"
|
|
&& resultState?.opened?.dimensions?.join(",") === "2,3,4"
|
|
&& resultState?.transaction?.undoResult === 1
|
|
&& resultState?.transaction?.redoResult === 1
|
|
&& resultState?.resourcesReleased === true
|
|
&& chrome.cases.flatMap((item) => item.externalRequests ?? []).length === 0
|
|
&& chrome.cases.flatMap((item) => item.exceptions ?? []).length === 0;
|
|
const report = {
|
|
schema: "freecad-web-p6-document-contract-gate/v1",
|
|
taskId: "FW-P6-FPA-C",
|
|
result: result ? "pass" : "fail",
|
|
contracts,
|
|
semantic: { action: resultState ?? null, repeat: repeatState ?? null, compares: ["objectType", "dimensions", "volume", "recovery", "transaction"] },
|
|
chrome: { artifact: "docs/p6/document-contract-chrome.json", sha256: hash("document-contract-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 },
|
|
boundaries: [
|
|
"C proves one native Part::Box document semantic round-trip and transaction/recovery contract; it does not close the 403 object inventory.",
|
|
"FCStd acceptance compares semantic fields, not archive bytes.",
|
|
"Cross-module links and larger object graphs remain explicit D/C follow-up work.",
|
|
],
|
|
};
|
|
fs.writeFileSync(path.join(p6, "document-contract-gate.json"), `${JSON.stringify(report, null, 2)}\n`);
|
|
fs.writeFileSync(path.join(docs, "freecad-p6-document-contract-gate.log"), `${JSON.stringify({ result: report.result, cases: required.length, semanticRoundTrip: resultState?.semanticRoundTrip ?? false, externalRequests: report.chrome.externalRequests, exceptions: report.chrome.exceptions })}\n`);
|
|
console.log(JSON.stringify({ result: report.result, cases: required.length, semanticRoundTrip: resultState?.semanticRoundTrip ?? false, externalRequests: report.chrome.externalRequests, exceptions: report.chrome.exceptions }));
|
|
if (!result) process.exitCode = 1;
|