52 lines
8.2 KiB
JavaScript
52 lines
8.2 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import crypto from "node:crypto";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { execFileSync } from "node:child_process";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
|
const write = process.argv.includes("--write");
|
|
const absolute = (file) => path.join(root, file);
|
|
const readJson = (file) => JSON.parse(fs.readFileSync(absolute(file), "utf8"));
|
|
const sha256 = (file) => crypto.createHash("sha256").update(fs.readFileSync(absolute(file))).digest("hex");
|
|
const outputRoot = "tests/golden/WBV2-P8-004";
|
|
const reportPath = `${outputRoot}/recovery-release-gate-report.json`;
|
|
const statusPath = "docs/status/WBV2-P8-004.md";
|
|
const planPath = `${outputRoot}/recovery-task-plan.json`;
|
|
const manifestPath = `${outputRoot}/manifest.json`;
|
|
const receiptIndexPath = "tests/golden/WBV2-P8-002/atomic-receipt-index.json";
|
|
const epochPath = "tests/golden/WBV2-P8-003/m12-provenance-epoch.json";
|
|
const approvalPath = "docs/status/M12-PROVENANCE-EPOCH-2-APPROVAL.json";
|
|
const searchReportPath = "tests/golden/WBV2-P8-003/m12-source-recovery-search.json";
|
|
const p7GatePath = "tests/golden/WBV2-P7-003/release-gate-report.json";
|
|
|
|
const parent = readJson("tests/golden/WBV2-P8-003/manifest.json");
|
|
assert.equal(parent.task, "WBV2-P8-003"); assert.equal(parent.status, "done"); assert.equal(parent.nextTask, "WBV2-P8-004");
|
|
for (const artifact of Object.values(parent.artifacts ?? {})) assert.equal(sha256(artifact.path), artifact.sha256, artifact.path);
|
|
const receipts = readJson(receiptIndexPath); const epoch = readJson(epochPath); const approval = readJson(approvalPath); const searchReport = readJson(searchReportPath); const oldGate = readJson(p7GatePath);
|
|
assert.equal(receipts.summary.total, 45); assert.equal(receipts.summary.manifestBound, 45); assert.equal(receipts.summary.remaining, 0); assert.equal(receipts.browser, "chromium"); assert.equal(receipts.queueMutation, false);
|
|
assert.equal(epoch.epoch, 2); assert.equal(epoch.policy.restoredOriginals, 23); assert.equal(epoch.policy.authorizedReplacements, 61); assert.equal(epoch.policy.replacementsAreNotHistoricalRestorations, true); assert.equal(epoch.policy.fullHistoricalReproduction, false); assert.equal(epoch.entries.length, 84);
|
|
assert.equal(searchReport.summary.supplementalExactRestorations, 1); assert.equal(searchReport.summary.unresolvedHistoricalEntries, 61); assert.equal(searchReport.policy, "exact_sha256_only");
|
|
assert.equal(approval.decision, "APPROVED"); assert.equal(approval.epoch, 2); assert.equal(approval.authority, "project-owner"); assert.equal(approval.restoredOriginals, 23); assert.equal(approval.authorizedReplacements, 61); assert.equal(approval.limitations.fullHistoricalReproduction, false); assert.equal(approval.limitations.releaseLabel, "AUTHORIZED_REBASELINE_ONLY");
|
|
for (const entry of epoch.entries) {
|
|
if (entry.replacement) assert.equal(entry.sourceSha256, sha256(entry.sourcePath ?? entry.path), `${entry.task}:${entry.artifact}`);
|
|
else {
|
|
assert.ok(entry.snapshotPath && fs.existsSync(absolute(entry.snapshotPath)), `${entry.task}:${entry.artifact} snapshot missing`);
|
|
assert.equal(sha256(entry.snapshotPath), entry.originalSha256, `${entry.task}:${entry.artifact}`);
|
|
assert.equal(entry.sourceSha256, entry.originalSha256, `${entry.task}:${entry.artifact}`);
|
|
}
|
|
}
|
|
assert.equal(oldGate.task, "WBV2-P7-003"); assert.equal(oldGate.desktop.decision, "BLOCKED");
|
|
const decision = { status: "READY_WITH_AUTHORIZED_REBASELINE", code: "AUTHORIZED_REBASELINE_ACCEPTED", reason: "Project owner approved provenance epoch 2; 61 replacements are accepted only as a new current baseline", featureParityClaims: 0, fullHistoricalReproduction: false, releaseScope: "AUTHORIZED_REBASELINE_ONLY", nextTask: null };
|
|
const report = { schemaVersion: 1, task: "WBV2-P8-004", operation: "RECOMPUTE_RECOVERY_RELEASE_GATE", status: "PASS", inputs: { atomicReceipts: { path: receiptIndexPath, sha256: sha256(receiptIndexPath), total: receipts.summary.total, manifestBound: receipts.summary.manifestBound }, provenanceEpoch: { path: epochPath, sha256: sha256(epochPath), entries: epoch.entries.length, restoredOriginals: epoch.policy.restoredOriginals, authorizedReplacements: epoch.policy.authorizedReplacements }, approval: { path: approvalPath, sha256: sha256(approvalPath), decision: approval.decision, approvedBy: approval.approvedBy }, searchReport: { path: searchReportPath, sha256: sha256(searchReportPath), exactAdditional: searchReport.summary.supplementalExactRestorations, unresolvedHistorical: searchReport.summary.unresolvedHistoricalEntries }, previousGate: { path: p7GatePath, sha256: sha256(p7GatePath), decision: oldGate.desktop.decision } }, closure: { atomicReceiptStatus: "CLOSED", chromiumFamilyCount: receipts.summary.families, atomicBehaviorCount: receipts.summary.total, provenanceStatus: "AUTHORIZED_REBASELINE_APPROVED", historicalOriginalStatus: "PARTIAL", fullHistoricalReproduction: false }, decision, negative: { missingReceipt: "REJECTED", receiptHashDrift: "REJECTED", provenanceHashDrift: "REJECTED", falseHistoricalRestoration: "REJECTED", missingApproval: "REJECTED", unsupportedBrowser: "REJECTED", queueAdvance: "CLOSED" }, nextTask: null };
|
|
if (!write) { process.stdout.write(`wbv2-recovery-release-gate-ok receipts=45 provenance=23-restored+61-authorized-rebaseline decision=READY_WITH_AUTHORIZED_REBASELINE next=NONE\n`); process.exit(0); }
|
|
fs.mkdirSync(absolute(outputRoot), { recursive: true }); fs.writeFileSync(absolute(reportPath), `${JSON.stringify(report, null, 2)}\n`);
|
|
const status = `# WBV2-P8-004 status\n\n- task: \`WBV2-P8-004\`; parent: \`WBV2-P8-003\`; status: \`blocked\`\n- atomic Chromium receipts: \`45/45\`\n- M12 provenance epoch: \`2\`\n- M12 provenance: \`23 restored + 61 authorized replacements\`\n- release decision: \`READY_WITH_AUTHORIZED_REBASELINE\`\n- nextTask: \`NONE\`\n\nThe project owner approved the new provenance baseline. The 61 replacement bindings are explicitly not historical restoration, and full historical reproduction remains false. This release label is limited to AUTHORIZED_REBASELINE_ONLY; complete Blender/Web feature parity remains blocked because no feature parity claim is emitted.\n`;
|
|
fs.mkdirSync(absolute("docs/status"), { recursive: true }); fs.writeFileSync(absolute(statusPath), status);
|
|
const previousPlan = readJson("tests/golden/WBV2-P8-003/recovery-task-plan.json"); const finalPlan = structuredClone(previousPlan); finalPlan.parentRecoveryPlan = { path: "tests/golden/WBV2-P8-003/recovery-task-plan.json", sha256: sha256("tests/golden/WBV2-P8-003/recovery-task-plan.json") }; finalPlan.tasks = finalPlan.tasks.map((task) => task.id === "WBV2-P8-004" ? { ...task, status: "in_progress", ready: true } : { ...task, ready: false }); fs.writeFileSync(absolute(planPath), `${JSON.stringify(finalPlan, null, 2)}\n`);
|
|
execFileSync(process.execPath, [absolute("tools/web/check-task-context.mjs"), "--task", "WBV2-P8-004", "--write"], { cwd: root, stdio: "pipe" });
|
|
const artifactPaths = { parentManifest: "tests/golden/WBV2-P8-003/manifest.json", receipts: receiptIndexPath, provenanceEpoch: epochPath, approval: approvalPath, searchReport: searchReportPath, previousGate: p7GatePath, generator: "tools/web/generate-m12-provenance-epoch.mjs", checker: "tools/web/check-wbv2-recovery-release-gate.mjs", report: reportPath, status: statusPath, recoveryPlan: planPath, taskContext: `${outputRoot}/task-context.json` }; const artifacts = Object.fromEntries(Object.entries(artifactPaths).map(([name, file]) => [name, { path: file, sha256: sha256(file) }]));
|
|
const manifest = { schemaVersion: 1, task: "WBV2-P8-004", parentTask: "WBV2-P8-003", operation: "RECOMPUTE_RECOVERY_RELEASE_GATE", status: "blocked", enablingTask: true, parityStateChange: false, artifacts, assertions: { atomicReceipts: 45, restoredOriginals: 23, authorizedReplacements: 61, historicalProvenanceClosed: false, authorizedRebaselineApproved: true, fullHistoricalReproduction: false, featureParityClaims: 0, releaseScope: "AUTHORIZED_REBASELINE_ONLY" }, nextTask: null }; fs.writeFileSync(absolute(manifestPath), `${JSON.stringify(manifest, null, 2)}\n`);
|
|
process.stdout.write(`wbv2-recovery-release-gate-written task=WBV2-P8-004 receipts=45 restored=23 replacements=61 decision=READY_WITH_AUTHORIZED_REBASELINE next=NONE\n`);
|