import { createHash } from 'node:crypto' import { readFile, stat } from 'node:fs/promises' import { resolve } from 'node:path' import { FREECAD_NAMING_CALLBACKS, FREECAD_NAMING_OPERATIONS } from './freecad-naming-production-matrix.mjs' const root = resolve(new URL('..', import.meta.url).pathname) const fail = (message) => { throw new Error(`FreeCAD production naming verification failed: ${message}`) } const checkReport = async (reportName, runtime, artifactRoot) => { const report = JSON.parse(await readFile(resolve(root, 'config', reportName), 'utf8')) if (report.status !== 'pass' || report.runtime !== runtime || report.implementation !== 'freecad-linked' || report.productionWorkerLinked !== true || report.systemExact !== false) fail(`${reportName} has an invalid production boundary.`) if (JSON.stringify(report.callbacks) !== JSON.stringify(FREECAD_NAMING_CALLBACKS)) fail(`${reportName} callback list is incomplete.`) if (JSON.stringify(report.operations) !== JSON.stringify(FREECAD_NAMING_OPERATIONS) || report.cases?.length !== FREECAD_NAMING_OPERATIONS.length) fail(`${reportName} operation matrix is incomplete.`) if (report.cases.some((entry, index) => { const native = entry.selectedRecords > 0 return entry.operation !== FREECAD_NAMING_OPERATIONS[index] || entry.status !== 'pass' || entry.provenanceResults < 1 || entry.provenanceResults !== entry.selectedRecords + entry.ambiguousResults || entry.externallySourcedRecords < 1 || entry.internalRecordsExcluded < 0 || entry.externallySourcedRecords + entry.internalRecordsExcluded !== entry.historyRecords || entry.duplicateRecordsCollapsed < 0 || entry.modifiedRelationPrecedence < 0 || entry.callbackExecuted !== native || entry.mappedNames !== entry.selectedRecords || (native && (entry.stringHasherEntries < 0 || entry.elementMaps < 1 || !['native-evidence', 'mixed-native-and-ambiguous'].includes(entry.namingStatus))) || (!native && (entry.ambiguousResults < 1 || entry.stringHasherEntries !== 0 || entry.elementMaps !== 0 || entry.namingStatus !== 'ambiguous')) })) fail(`${reportName} contains an invalid operation result.`) const callbackCases = report.cases.filter(({ callbackExecuted }) => callbackExecuted).length const ambiguityOnlyCases = report.cases.filter(({ namingStatus }) => namingStatus === 'ambiguous').length if (report.callbackExecutedCases !== callbackCases || report.ambiguityOnlyCases !== ambiguityOnlyCases || callbackCases < 1 || callbackCases + ambiguityOnlyCases !== FREECAD_NAMING_OPERATIONS.length) fail(`${reportName} has invalid callback/ambiguity partitioning.`) if (report.isomorphicCorpus?.status !== 'pass' || report.isomorphicCorpus.fixture !== 'coincident-equal-boxes' || report.isomorphicCorpus.uniqueResults !== 0 || report.isomorphicCorpus.ambiguousResults < 1 || report.isomorphicCorpus.arrayOrderFallbackUsed !== false || report.isomorphicCorpus.candidateSets?.some(({ candidates }) => candidates.length < 2)) fail(`${reportName} is missing its symmetric native-provenance corpus.`) if (report.invalidHistoryRejected !== true || report.chainedStage?.mappedNames < 1 || report.chainedStage?.stringHasherEntries < 2) fail(`${reportName} is missing chained or fail-closed evidence.`) for (const artifact of report.artifacts ?? []) { const path = resolve(root, artifactRoot, artifact.name) const [content, bytes] = await Promise.all([readFile(path), stat(path).then(({ size }) => size)]) if (bytes !== artifact.bytes || createHash('sha256').update(content).digest('hex') !== artifact.sha256) fail(`${reportName} is stale for ${artifact.name}.`) } if (report.artifacts?.length !== 3) fail(`${reportName} must lock JS, WASM and DATA.`) const harnessPath = resolve(root, report.harness?.path ?? '') const [harnessContent, harnessBytes] = await Promise.all([readFile(harnessPath), stat(harnessPath).then(({ size }) => size)]) if (report.harness?.path !== 'scripts/freecad-naming-production-matrix.mjs' || harnessBytes !== report.harness.bytes || createHash('sha256').update(harnessContent).digest('hex') !== report.harness.sha256) fail(`${reportName} is stale for the shared production harness.`) return { runtime, cases: report.cases.length, generatedAt: report.generatedAt } } const requestedRuntime = process.argv.find((argument) => argument.startsWith('--runtime='))?.slice('--runtime='.length) ?? 'all' if (!['all', 'node', 'chrome'].includes(requestedRuntime)) fail(`unsupported runtime ${requestedRuntime}.`) const specs = [ ['freecad-naming-production-verification.json', 'node', 'native/occt-history/dist'], ['chrome-freecad-naming-production-verification.json', 'chrome', 'public/native/occt-history'], ].filter(([, runtime]) => requestedRuntime === 'all' || runtime === requestedRuntime) const reports = [] for (const [reportName, runtime, artifactRoot] of specs) reports.push(await checkReport(reportName, runtime, artifactRoot)) console.log(JSON.stringify({ status: 'freecad-production-naming-pass', implementation: 'freecad-linked', callbacks: FREECAD_NAMING_CALLBACKS, operations: FREECAD_NAMING_OPERATIONS.length, reports, systemExact: false }, null, 2))