37 lines
2.4 KiB
JavaScript
37 lines
2.4 KiB
JavaScript
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 task = process.argv[2];
|
|
const output = path.resolve(process.argv[3] ?? "");
|
|
const contracts = {
|
|
"M15-02C": { mode: "LOCAL_EXACT", nextTask: "M15-02D", required: ["desktopFixture", "wasmFixture", "sameFixture"] },
|
|
"M15-02D": { mode: "LOCAL_EQUIVALENT", nextTask: "M15-02E", required: ["mainEvidence", "saveReopenEvidence"] },
|
|
"M15-02E": { mode: "SERVER_EXACT", nextTask: "M15-02F", required: ["jobEvidence", "cancelEvidence", "isolationEvidence", "resultBindingEvidence"] },
|
|
"M15-02F": { mode: "UNKNOWN_DATA_PRESERVATION", nextTask: "M15-03A", required: ["unknownDataFixture", "saveReloadEvidence", "bytePreservationEvidence"] },
|
|
};
|
|
if (!contracts[task] || !output) throw new Error("usage: node generate-blender-contract-audit.mjs M15-02C OUTPUT.json");
|
|
const contract = contracts[task];
|
|
const mapPath = path.join(root, "tests/golden/M15-02A/blender-parity-map.json");
|
|
const map = JSON.parse(fs.readFileSync(mapPath, "utf8"));
|
|
const claims = map.entries.filter((entry) => entry.implementationClass === contract.mode);
|
|
const blocked = claims.filter((entry) => contract.required.some((field) => !entry[field]));
|
|
const ready = claims.filter((entry) => !blocked.includes(entry));
|
|
const audit = {
|
|
schemaVersion: 1,
|
|
task,
|
|
operation: "BLENDER_PARITY_CONTRACT_AUDIT",
|
|
source: { path: "tests/golden/M15-02A/blender-parity-map.json", sha256: crypto.createHash("sha256").update(fs.readFileSync(mapPath)).digest("hex") },
|
|
contract: { mode: contract.mode, requiredEvidence: contract.required, failClosed: true },
|
|
summary: { inventoried: map.entries.length, applicable: claims.length, blocked: blocked.length, ready: ready.length, notApplicable: map.entries.length - claims.length },
|
|
blockedIds: blocked.map((entry) => entry.id).sort((a, b) => a < b ? -1 : a > b ? 1 : 0),
|
|
readyIds: ready.map((entry) => entry.id).sort((a, b) => a < b ? -1 : a > b ? 1 : 0),
|
|
interpretation: claims.length === 0 ? "NO_CLAIMS_DECLARED" : "MISSING_EVIDENCE_BLOCKS_CLAIM",
|
|
nextTask: contract.nextTask,
|
|
};
|
|
fs.mkdirSync(path.dirname(output), { recursive: true });
|
|
fs.writeFileSync(output, `${JSON.stringify(audit, null, 2)}\n`);
|
|
process.stdout.write(`blender-contract-audit-generated task=${task} mode=${contract.mode} applicable=${claims.length} blocked=${blocked.length} output=${output}\n`);
|