#!/usr/bin/env node import { createHash } from "node:crypto"; import { readFileSync, writeFileSync } from "node:fs"; import path from "node:path"; import { fileURLToPath, pathToFileURL } from "node:url"; import { verifyFullLocalDiscovery } from "./verify-full-local-discovery.mjs"; import { sourceSnapshot } from "./full-local-diagnostic.mjs"; const hash = value => createHash("sha256").update(value).digest("hex"); export const caseKey = entry => JSON.stringify([entry.file, entry.id, entry.title, entry.projectName ?? "", entry.repeatEachIndex ?? 0]); const sameCandidate = (a, b) => Boolean(a && b && /^[a-f0-9]{40}$/.test(a.commit ?? "") && /^[a-f0-9]{64}$/.test(a.digest ?? "") && a.commit === b.commit && a.digest === b.digest); export const localSpecArgs = plan => plan.localSpecs.map(file => `${file.slice(7).replace(/[.*+?^${}()|[\]\\]/gu, "\\$&")}$`); export function coveragePlan(root, discovery, contract, candidate) { const full = verifyFullLocalDiscovery(root, discovery); const issues = [...full.issues]; const exceptions = contract?.exceptions ?? []; if (contract?.schemaVersion !== 1 || !Array.isArray(contract?.exceptions) || !contract.approvalReference) issues.push("invalid_coverage_contract"); if (!sameCandidate(candidate, candidate)) issues.push("invalid_candidate"); const keys = full.cases.map(caseKey); if (new Set(keys).size !== keys.length) issues.push("duplicate_discovery_case"); const registered = new Map(); for (const entry of exceptions) { const key = caseKey(entry); if (registered.has(key)) issues.push("duplicate_exception"); registered.set(key, entry); if (!keys.includes(key)) issues.push("exception_identity_drift"); if (!["post-deploy", "frozen"].includes(entry.kind) || !entry.reason || !entry.entry || !entry.responsibilityRole || !entry.requiredEvidence) issues.push("invalid_exception_obligation"); if (!full.expectedSpecs.includes(entry.file)) issues.push("exception_source_unknown"); else if (hash(readFileSync(path.join(root, entry.file))) !== entry.sourceSha256) issues.push("exception_source_changed"); if (entry.kind === "frozen" && !full.cases.some(row => row.file === entry.replacementFile && row.title === entry.replacementTitle && !exceptions.some(other => caseKey(other) === caseKey(row)))) issues.push("frozen_protection_missing"); } const exceptionFiles = new Set(exceptions.map(entry => entry.file)); const localCases = full.cases.filter(entry => !registered.has(caseKey(entry))); if (localCases.some(entry => exceptionFiles.has(entry.file))) issues.push("unregistered_case_in_exception_file"); if (!localCases.length) issues.push("empty_local_coverage"); const localSpecs = [...new Set(localCases.map(entry => entry.file))].sort(); return { schemaVersion: 1, kind: "LAYERED_LOCAL_COVERAGE_PLAN", status: issues.length ? "FAIL" : "PASS", candidate: { commit: candidate?.commit, digest: candidate?.digest }, contractSha256: hash(JSON.stringify(contract)), discoverySha256: hash(JSON.stringify(discovery)), localSpecs, localCases, obligations: exceptions.map(entry => ({ ...entry, status: entry.kind === "post-deploy" ? "NOT_RUN_LOCAL" : "FROZEN_PROTECTION_REQUIRED" })), totalCases: full.cases.length, issues: [...new Set(issues)], normalReleaseEligible: false, }; } function reportCases(report) { const cases = []; function visit(suites, inherited = "") { for (const suite of suites ?? []) { for (const spec of suite.specs ?? []) { let file = (spec.file ?? suite.file ?? inherited).replaceAll("\\", "/"); if (!file.startsWith("client/tests/e2e/")) file = `client/tests/e2e/${file.replace(/^tests\/e2e\//u, "")}`; for (const test of spec.tests ?? []) cases.push({ file, id: spec.id, title: spec.title, projectName: test.projectName ?? "", repeatEachIndex: test.repeatEachIndex ?? 0, ...test }); } visit(suite.suites, suite.file ?? inherited); } } visit(report?.suites); return cases; } export function verifyCaseExecution(expected, report) { const issues = []; if (!Array.isArray(report?.suites) || !Array.isArray(report?.errors)) issues.push("invalid_execution_report"); if (report?.errors?.length) issues.push("execution_errors"); const actual = reportCases(report); const byKey = new Map(); for (const entry of actual) { const key = caseKey(entry); if (byKey.has(key)) issues.push("duplicate_execution_case"); byKey.set(key, entry); } const cases = expected.map(entry => { const observed = byKey.get(caseKey(entry)); byKey.delete(caseKey(entry)); const passed = observed?.expectedStatus === "passed" && observed?.status === "expected" && observed?.results?.length === 1 && observed.results[0].status === "passed" && observed.results[0].retry === 0; if (!passed) issues.push(observed ? "case_not_clean_pass" : "missing_execution_case"); return { ...entry, status: passed ? "PASS" : "FAIL", observedStatus: observed?.results?.at(-1)?.status ?? "NOT_RUN" }; }); if (byKey.size) issues.push("unexpected_execution_case"); return { status: issues.length ? "FAIL" : "PASS", cases, issues: [...new Set(issues)] }; } export function verifyLocalCoverage(plan, report, candidate) { const result = verifyCaseExecution(plan.localCases, report); if (plan.status !== "PASS") result.issues.push("coverage_plan_invalid"); if (!sameCandidate(plan.candidate, candidate)) result.issues.push("candidate_changed"); result.status = result.issues.length ? "FAIL" : "PASS"; return { ...result, kind: "LOCAL_BROWSER_COVERAGE_ONLY", candidate: plan.candidate, obligations: plan.obligations.map(entry => ({ ...entry, status: entry.kind === "post-deploy" ? "NOT_RUN_LOCAL" : result.cases.some(row => row.file === entry.replacementFile && row.title === entry.replacementTitle && row.status === "PASS") ? "FROZEN_PROTECTION_PASS" : "FROZEN_PROTECTION_FAIL" })), deliveryStatus: "INCOMPLETE", normalReleaseEligible: false }; } // Pure offline verifier. This does not run public tests or authorize deployment. export function verifyPostDeployCoverage(plan, evidence) { const expected = plan.obligations.filter(entry => entry.kind === "post-deploy"); const result = verifyCaseExecution(expected, evidence?.report); if (plan.status !== "PASS" || !expected.length) result.issues.push("coverage_plan_invalid"); if (evidence?.profile !== "post-deploy-live" || evidence?.mode !== "live") result.issues.push("live_profile_required"); if (!sameCandidate(plan.candidate, evidence?.candidate) || !sameCandidate(plan.candidate, evidence?.deployedCandidate)) result.issues.push("deployed_candidate_mismatch"); result.status = result.issues.length ? "FAIL" : "PASS"; return { ...result, normalReleaseEligible: false }; } if (process.argv[1] && import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href) { try { const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); const [mode, directory] = process.argv.slice(2); const read = file => JSON.parse(readFileSync(path.join(directory, file), "utf8")); const contract = JSON.parse(readFileSync(path.join(root, "scripts/qa/full-local-coverage-contract.json"), "utf8")); const current = coveragePlan(root, read("discovery.json"), contract, sourceSnapshot(root)); if (mode === "plan") { console.log(JSON.stringify(current, null, 2)); if (current.status === "PASS") writeFileSync(path.join(directory, "local-spec-args.txt"), localSpecArgs(current).join("\n") + "\n", { flag: "wx" }); process.exitCode = current.status === "PASS" ? 0 : 1; } else if (mode === "verify-local") { const saved = read("coverage-plan.json"); const result = verifyLocalCoverage(saved, read("playwright-results.json"), current.candidate); if (JSON.stringify(saved) !== JSON.stringify(current)) result.issues.push("coverage_plan_changed"); result.status = result.issues.length ? "FAIL" : "PASS"; console.log(JSON.stringify(result, null, 2)); process.exitCode = result.status === "PASS" ? 0 : 1; } else throw new Error("unknown_mode"); } catch { console.log(JSON.stringify({ status: "FAIL", issues: ["coverage_input_invalid"], normalReleaseEligible: false })); process.exitCode = 1; } }