import { access, readFile } from 'node:fs/promises' import { resolve } from 'node:path' const root = resolve(new URL('..', import.meta.url).pathname) const load = (path) => readFile(resolve(root, path), 'utf8').then(JSON.parse) const [plan, compatibility, platformCoverage, sourceInventory, reportSchema] = await Promise.all([ load('config/freecad-web-exact-parity-plan.json'), load('config/compatibility-matrix.json'), load('config/platform-module-coverage.json'), load('config/freecad-source-inventory.json'), load('config/freecad-web-exact-promotion-report.schema.json'), ]) const fail = (message) => { throw new Error(`FreeCAD Web exact promotion: ${message}`) } const tasks = plan.programs.flatMap((program) => program.tasks) const finalTask = tasks.find((task) => task.id === plan.promotionGate.finalTask) const requiredMetrics = plan.promotionGate.requiredZeroMetrics const requiredEvidence = plan.promotionGate.requiredEvidenceClasses if (reportSchema.$schema !== 'https://json-schema.org/draft/2020-12/schema' || reportSchema.properties?.completedTasks?.const !== 52 || reportSchema.properties?.exactModules?.const !== 34) fail('promotion report schema is missing the locked 52/52 and 34/34 contract.') if (plan.claim?.exact !== true) { if (!finalTask) fail('EX-REL-01 is missing from the exact-parity plan.') if (finalTask?.status === 'completed') fail('EX-REL-01 cannot be completed while claim.exact is false.') if (compatibility.systemExactEvaluation?.exact !== false) fail('compatibility matrix must remain exact=false while promotion is incomplete.') console.log(JSON.stringify({ status: 'freecad-web-exact-promotion-fail-closed', systemExact: false, finalTask: finalTask?.status ?? 'missing', completedTasks: tasks.filter((task) => task.status === 'completed').length, requiredTasks: tasks.length, exactModules: platformCoverage.modules.filter((module) => module.level === 'exact').length, requiredExactModules: plan.promotionGate.requiredExactModules, report: 'not-required-until-EX-REL-01-is-requested', }, null, 2)) process.exit(0) } if (!finalTask || finalTask.id !== 'EX-REL-01' || finalTask.status !== 'completed' || finalTask.exactBlockedBy.length !== 0) fail('EX-REL-01 must be completed without blockers before exact can be claimed.') if (tasks.some((task) => task.status !== 'completed')) fail('all exact-parity tasks must be completed before promotion.') if (compatibility.systemExactEvaluation?.exact !== true || compatibility.systemExactEvaluation.featureExactCount !== plan.promotionGate.requiredExactModules) fail('compatibility matrix exact evaluation is not fully promoted.') const exactModules = platformCoverage.modules.filter((module) => module.level === 'exact').map((module) => module.name).sort() const expectedModules = sourceInventory.modules.map((module) => module.name).sort() if (JSON.stringify(exactModules) !== JSON.stringify(expectedModules)) fail(`exact module set is incomplete: ${exactModules.length}/${expectedModules.length}.`) if (compatibility.systemExactEvaluation.blockers?.length !== 0) fail('system exact blockers must be empty at promotion time.') const reportPath = 'config/freecad-web-exact-promotion-report.json' await access(resolve(root, reportPath)).catch(() => fail(`${reportPath} is required for EX-REL-01.`)) const report = await load(reportPath) if (report.schemaVersion !== 1 || report.taskId !== 'EX-REL-01') fail('promotion report schema or task ID is invalid.') if (report.completedTasks !== tasks.length || report.exactModules !== expectedModules.length) fail('promotion report does not confirm 52/52 tasks and 34/34 exact modules.') for (const metric of requiredMetrics) if (report.metrics?.[metric] !== 0) fail(`promotion metric ${metric} must be zero.`) for (const evidence of requiredEvidence) if (!report.evidenceClasses?.includes(evidence)) fail(`promotion report is missing evidence class ${evidence}.`) console.log(JSON.stringify({ status: 'freecad-web-exact-promotion-pass', systemExact: true, completedTasks: report.completedTasks, exactModules: report.exactModules, zeroMetrics: requiredMetrics, evidenceClasses: requiredEvidence, }, null, 2))