import assert from "node:assert/strict"; import crypto from "node:crypto"; import fs from "node:fs"; import os from "node:os"; import path from "node:path"; import { createRequire } from "node:module"; import { fileURLToPath } from "node:url"; import ts from "../../web/node_modules/typescript/lib/typescript.js"; const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); const temporary = fs.mkdtempSync(path.join(os.tmpdir(), "release-evidence-")); const require = createRequire(import.meta.url); try { for (const name of ["capability-gates", "release-gate"]) { const source = fs.readFileSync(path.join(root, `web/protocol/${name}.ts`), "utf8"); const result = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022 }, fileName: `${name}.ts` }); fs.writeFileSync(path.join(temporary, `${name}.cjs`), result.outputText.replace('require("./capability-gates")', 'require("./capability-gates.cjs")')); } const module = require(path.join(temporary, "release-gate.cjs")); const reportPath = path.join(root, "docs/status/release-evidence.json"); const ledgerPath = path.join(root, "docs/status/parity-ledger.json"); const report = JSON.parse(fs.readFileSync(reportPath, "utf8")); assert.equal(report.sourceSha256, crypto.createHash("sha256").update(fs.readFileSync(ledgerPath)).digest("hex"), "release report is stale relative to parity ledger"); const parsed = module.parseReleaseManifest(report); const evaluation = module.evaluateReleaseManifest(parsed); assert.equal(evaluation.status, "READY"); assert.deepEqual(evaluation.missing, []); assert.equal(evaluation.missing.includes("faults.deviceLoss"), false); assert.equal(evaluation.missing.includes("performance.simulationCache"), false); assert.equal(evaluation.missing.includes("faults.networkInterrupt"), false); assert.equal(evaluation.missing.includes("performance.texture4K"), false); assert.equal(evaluation.missing.includes("performance.texture8K"), false); assert.equal(evaluation.missing.includes("browser.chromium"), false); assert.ok(parsed.evidence.records.length >= 7); assert.equal(parsed.evidence.records.some((record) => record.fields.includes("faults.zipBomb")), true); assert.equal(parsed.evidence.records.some((record) => record.fields.includes("performance.simulationCache")), true); assert.equal(parsed.evidence.records.some((record) => record.fields.includes("faults.networkInterrupt")), true); assert.equal(parsed.evidence.records.some((record) => record.fields.includes("faults.deviceLoss")), true); assert.equal(parsed.evidence.records.some((record) => record.fields.includes("performance.texture4K")), true); assert.equal(parsed.evidence.records.some((record) => record.fields.includes("performance.texture8K")), true); assert.equal(parsed.evidence.records.some((record) => record.fields.includes("performance.geometry10M")), true); assert.equal(parsed.evidence.records.some((record) => record.fields.includes("performance.longMedia")), true); assert.equal(parsed.evidence.records.some((record) => record.fields.includes("faults.oom")), true); process.stdout.write(`release-evidence-check-ok records=${parsed.evidence.records.length} missing=${evaluation.missing.length} status=${evaluation.status}\n`); } finally { fs.rmSync(temporary, { recursive: true, force: true }); }