61 lines
4.1 KiB
JavaScript
61 lines
4.1 KiB
JavaScript
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))
|