feat: expand oracle and topology evidence gates
This commit is contained in:
@@ -8,7 +8,8 @@ const profile = process.env.FREECAD_ORACLE_PROFILE || 'headless'
|
||||
if (!['headless', 'desktop'].includes(profile)) throw new Error(`Unknown FreeCAD oracle profile: ${profile}`)
|
||||
const localOracle = resolve(root, profile === 'desktop' ? '.cache/freecad/install-desktop/bin/FreeCAD' : '.cache/freecad/install-native/bin/FreeCADCmd')
|
||||
const fallbackOracle = profile === 'desktop' ? ['FreeCAD', 'freecad'] : ['FreeCADCmd', 'freecadcmd']
|
||||
const candidates = process.env.FREECAD_CMD ? [process.env.FREECAD_CMD] : [localOracle, ...fallbackOracle]
|
||||
const referenceCommand = process.env.FREECAD_REFERENCE_CMD || process.env.FREECAD_CMD
|
||||
const candidates = referenceCommand ? [referenceCommand] : [localOracle, ...fallbackOracle]
|
||||
let command = null
|
||||
for (const candidate of candidates) {
|
||||
const probe = spawnSync(candidate, profile === 'desktop' ? ['--console', '--version'] : ['--version'], { encoding: 'utf8', timeout: 15000 })
|
||||
@@ -32,7 +33,10 @@ const runtimeEnv = profile === 'desktop'
|
||||
MPLBACKEND: 'Agg',
|
||||
}
|
||||
: process.env
|
||||
const execution = spawnSync(command, commandArgs, {
|
||||
const desktopNeedsVirtualDisplay = profile === 'desktop' && !process.env.DISPLAY && !process.env.WAYLAND_DISPLAY
|
||||
const launchCommand = desktopNeedsVirtualDisplay ? 'xvfb-run' : command
|
||||
const launchArgs = desktopNeedsVirtualDisplay ? ['-a', command, ...commandArgs] : commandArgs
|
||||
const execution = spawnSync(launchCommand, launchArgs, {
|
||||
cwd: root,
|
||||
encoding: 'utf8',
|
||||
timeout: 120000,
|
||||
@@ -53,5 +57,44 @@ for (const module of result.modules) {
|
||||
throw new Error(`Reference probe returned an invalid module status for ${module.name || '<unknown>'}.`)
|
||||
}
|
||||
}
|
||||
const runtimeObjects = result.runtimeObjects
|
||||
if (!runtimeObjects?.available || runtimeObjects.candidateSource !== 'Document.supportedTypes' || !Array.isArray(runtimeObjects.types)) {
|
||||
throw new Error('Reference probe must include the complete Document.supportedTypes runtime inventory.')
|
||||
}
|
||||
if (runtimeObjects.candidateCount !== runtimeObjects.types.length || runtimeObjects.availableCount + runtimeObjects.unavailableCount !== runtimeObjects.candidateCount) {
|
||||
throw new Error('Reference probe returned inconsistent runtime object counts.')
|
||||
}
|
||||
const runtimeTypeIds = new Set()
|
||||
for (const candidate of runtimeObjects.types) {
|
||||
if (typeof candidate.typeId !== 'string' || !candidate.typeId || runtimeTypeIds.has(candidate.typeId) || !['available', 'unavailable'].includes(candidate.probeStatus)) {
|
||||
throw new Error(`Reference probe returned an invalid runtime object candidate: ${candidate.typeId || '<unknown>'}.`)
|
||||
}
|
||||
runtimeTypeIds.add(candidate.typeId)
|
||||
if (candidate.available) {
|
||||
if (candidate.probeStatus !== 'available' || typeof candidate.runtimeTypeId !== 'string' || !candidate.runtimeTypeId || !Array.isArray(candidate.properties)) {
|
||||
throw new Error(`Reference probe returned incomplete metadata for ${candidate.typeId}.`)
|
||||
}
|
||||
for (const property of candidate.properties) {
|
||||
if (typeof property.name !== 'string' || typeof property.typeId !== 'string' || !Array.isArray(property.status) || !Object.hasOwn(property, 'default')) {
|
||||
throw new Error(`Reference probe returned invalid property metadata for ${candidate.typeId}.`)
|
||||
}
|
||||
}
|
||||
} else if (candidate.probeStatus !== 'unavailable' || typeof candidate.error !== 'string' || !candidate.error) {
|
||||
throw new Error(`Reference probe did not explain why ${candidate.typeId} is unavailable.`)
|
||||
}
|
||||
}
|
||||
await writeFile(resolve(root, `.cache/freecad/reference-${profile}.json`), `${JSON.stringify(result, null, 2)}\n`)
|
||||
console.log(JSON.stringify({ command, result }, null, 2))
|
||||
console.log(JSON.stringify({
|
||||
command: launchCommand === command ? command : `${launchCommand} ${command}`,
|
||||
profile,
|
||||
freecadVersion: result.freecadVersion,
|
||||
moduleStatusSummary: result.moduleStatusSummary,
|
||||
guiCommandCount: result.guiCommands?.commands?.length ?? 0,
|
||||
runtimeObjectSummary: {
|
||||
candidateCount: runtimeObjects.candidateCount,
|
||||
availableCount: runtimeObjects.availableCount,
|
||||
unavailableCount: runtimeObjects.unavailableCount,
|
||||
propertyCount: runtimeObjects.types.reduce((total, candidate) => total + (candidate.properties?.length ?? 0), 0),
|
||||
},
|
||||
report: `.cache/freecad/reference-${profile}.json`,
|
||||
}, null, 2))
|
||||
|
||||
Reference in New Issue
Block a user