import { isDeepStrictEqual } from 'node:util' import { 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 [report, semantics, progress, roundTrip, chrome] = await Promise.all([ load('config/freecad-property-fileincluded-promotion.json'), load('config/freecad-native-property-semantics.json'), load('config/freecad-follow-up-task-progress.json'), load('config/freecad-property-fileincluded-roundtrip.json'), load('config/chrome-property-fileincluded-verification.json'), ]) const fail = (message) => { throw new Error(`FreeCAD PropertyFileIncluded promotion check failed: ${message}`) } if (report.schemaVersion !== 1 || report.status !== 'pass' || report.taskId !== 'PROP-app-propertyfileincluded-I' || report.propertyType !== 'App::PropertyFileIncluded' || report.recordCount !== 20 || report.baseline?.freecadVersion !== '1.1.1' || report.baseline?.commit !== '0108fd4b4850cc46e625b60e53cea7a7bbe69f8d' || report.systemExact !== false) fail('promotion report boundary is invalid') const requiredPhases = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'] const completed = new Map(progress.completedTasks?.map((entry) => [entry.id, entry]) ?? []) for (const phase of requiredPhases) { const taskId = `PROP-app-propertyfileincluded-${phase}` if (!completed.has(taskId) || !Array.isArray(report.phaseEvidence?.[phase]) || report.phaseEvidence[phase].length === 0 || !isDeepStrictEqual(report.phaseEvidence[phase], completed.get(taskId).evidence)) fail(`phase ${phase} evidence is incomplete`) } const nativeTarget = '09f4e4853de4277e25871d26f2e953c6ea9c13a73c7a01bdfcb5209d17f9a583' const propertyType = semantics.types?.find(({ typeId }) => typeId === report.propertyType) if (report.promotion?.from !== 'opaque-fcstd-proxy' || report.promotion.to !== 'native-editable-codec' || propertyType?.support !== report.promotion.to || propertyType.recordCount !== 20 || propertyType.objectTypeCount !== 15 || propertyType.statusNames?.join(',') !== 'PropOutput,ReadOnly' || report.promotion.facadeValueModel !== 'project-resource-identity-and-authoritative-bytes-with-native-fileincluded-fcstd-resource' || report.promotion.writableRecords !== 11 || report.promotion.readOnlyRecords !== 8 || report.promotion.outputRecords !== 1 || report.promotion.objectTypeCount !== 15 || report.promotion.fcstdElement !== 'FileIncluded' || report.promotion.nativeArchiveName !== 'payload.bin' || report.promotion.nativeRoundTripSha256 !== nativeTarget || report.promotion.browserArchiveName !== 'chrome-resource.bin' || report.promotion.browserRoundTripBytes !== 16 || report.promotion.externalResourceBoundary !== 'embedded FCStd ZIP entry restored to a read-only document transient file' || report.promotion.zeroUnknownDrift !== true) fail('capability promotion is incomplete') const sync = report.exactBlockerSync if (sync?.nativeEditableTypes !== 34 || sync.nativeEditableRecords !== 4370 || sync.opaqueTypes !== 46 || sync.opaqueRecords !== 457 || sync.exactPromotionReady !== false || sync.exactBlocker !== '46 runtime property types and 457 records remain opaque-only; complete native document and property semantics') fail('exact blocker synchronization is stale') if (!isDeepStrictEqual(sync, { nativeEditableTypes: semantics.supportSummary['native-editable-codec'].typeCount, nativeEditableRecords: semantics.supportSummary['native-editable-codec'].recordCount, opaqueTypes: semantics.supportSummary['opaque-fcstd-proxy'].typeCount, opaqueRecords: semantics.supportSummary['opaque-fcstd-proxy'].recordCount, exactPromotionReady: semantics.exactPromotionReady, exactBlocker: semantics.exactBlocker })) fail('promotion report diverges from global property semantics') if (roundTrip.classification?.zeroUnknownDrift !== true || roundTrip.classification.resavedSha256 !== nativeTarget || roundTrip.classification.resavedResourceMatches !== true || roundTrip.classification.externalResourceBoundary !== 'embedded FCStd ZIP entry restored to a read-only document transient file' || chrome.status !== 'pass' || chrome.persistence?.fcstdElement !== 'FileIncluded' || chrome.persistence.fcstdResourcePath !== 'chrome-resource.bin' || chrome.persistence.fcstdResourceBytes !== 16 || chrome.persistence.fcstdResourceMatches !== true || chrome.resource?.documentRoundTrip !== true || chrome.resource.independentReleased !== true || chrome.resource.markerRemoved !== true || chrome.release?.workerTerminated !== true) fail('G/H closure evidence regressed') console.log(JSON.stringify({ status: 'freecad-property-fileincluded-promotion-pass', propertyType: report.propertyType, promotion: report.promotion, completedPhases: requiredPhases, exactBlockerSync: sync, systemExact: report.systemExact }, null, 2))