28 lines
6.1 KiB
JavaScript
28 lines
6.1 KiB
JavaScript
import fs from 'node:fs'; import path from 'node:path'; import os from 'node:os'; import crypto from 'node:crypto'; import { pathToFileURL } from 'node:url'; import { createRequire } from 'node:module';
|
|
const root='/home/mes123456/FreeCADWasmDev/working/FreeCAD'; const build=path.join(root,'freecad-source/build-web/configure/bin');
|
|
const b=JSON.parse(fs.readFileSync(path.join(root,'docs/current/module-batch-manifest.json'),'utf8')); const rows=b.records.map(([apiId,name,disposition,sourcePath,sourceLine])=>({apiId,name,family:b.selected.family,kind:'object',sourcePath,sourceLine,disposition}));
|
|
const evidencePath=path.join(root,`docs/p6/robot-generic-document-object-module-batch-${b.batchId}-runtime.json`);
|
|
// A native probe failure is durable boundary evidence. Re-running the same
|
|
// pthread/runtime startup only burns the gate timeout until build inputs change.
|
|
try {
|
|
const previous=JSON.parse(fs.readFileSync(evidencePath,'utf8'));
|
|
const previousIds=new Set((previous.records??[]).map(r=>r?.apiId||r?.id).filter(Boolean));
|
|
const currentIds=new Set(rows.map(r=>r.apiId));
|
|
const state=previous.status||previous.result;
|
|
const currentWasmSha=crypto.createHash('sha256').update(fs.readFileSync(path.join(build,'FreeCADWebRobotRuntimeProbe.wasm'))).digest('hex');
|
|
const previousWasmSha=previous.artifacts?.wasmSha256||previous.artifactHashes?.wasmSha256||previous.build?.wasmSha256;
|
|
if (state==='blocked_native_probe' && previousWasmSha===currentWasmSha && currentIds.size===previousIds.size && [...currentIds].every(id=>previousIds.has(id))) {
|
|
console.log(JSON.stringify({status:'blocked_native_probe',batchId:b.batchId,reusedEvidence:true,evidence:`docs/p6/robot-generic-document-object-module-batch-${b.batchId}-runtime.json`}));
|
|
process.exit(78);
|
|
}
|
|
} catch (_) { /* no prior evidence; run the probe */ }
|
|
const temporary=fs.mkdtempSync(path.join(os.tmpdir(),'freecad-robot-object-gate-')); const runtimeName='FreeCADWebRobotRuntimeProbe.js'; const workerName='FreeCADWebRobotRuntimeProbe.worker.js';
|
|
fs.writeFileSync(path.join(temporary,'package.json'),'{"type":"module"}\n'); fs.writeFileSync(path.join(temporary,runtimeName),fs.readFileSync(path.join(build,runtimeName),'utf8').replaceAll(workerName,'FreeCADWebRobotRuntimeProbe.worker.cjs')); fs.copyFileSync(path.join(build,workerName),path.join(temporary,'FreeCADWebRobotRuntimeProbe.worker.cjs'));
|
|
globalThis.__dirname=`${temporary}${path.sep}`; globalThis.require=createRequire(import.meta.url); let k; try { const mod=await import(pathToFileURL(path.join(temporary,runtimeName))); k=await mod.default({wasmBinary:fs.readFileSync(path.join(build,'FreeCADWebRobotRuntimeProbe.wasm')),print:()=>{},printErr:()=>{}}); } catch (e) { const err=String(e?.message||e); const records=rows.map(r=>({...r,status:'blocked_native_probe',native:false,resourcesReleased:false,error:err})); const sha=p=>crypto.createHash('sha256').update(fs.readFileSync(path.join(build,p))).digest('hex'); const report={schema:'freecad-web-robot-generic-document-object-module-batch-runtime/v1',taskId:'FW-P6-FPA-Y',batchId:b.batchId,module:'Robot',tier:'object-contract',family:'generic-document-object',status:'blocked_native_probe',dispatcher:'fc_web_dispatch_json',route:{command:'robot.pythonFamilyBatch',facade:'web/src/robot-python-family-facade.ts',worker:'web/src/robot-python.worker.ts'},probeError:err,artifacts:{runtimeUrl:'freecad-source/build-web/configure/bin/FreeCADWebRobotRuntimeProbe.js',wasmUrl:'freecad-source/build-web/configure/bin/FreeCADWebRobotRuntimeProbe.wasm',runtimeSha256:sha('FreeCADWebRobotRuntimeProbe.js'),wasmSha256:sha('FreeCADWebRobotRuntimeProbe.wasm')},records}; const evidence=`docs/p6/robot-generic-document-object-module-batch-${b.batchId}-runtime.json`; fs.writeFileSync(path.join(root,evidence),JSON.stringify(report,null,2)+'\n'); fs.rmSync(temporary,{recursive:true,force:true}); console.log(JSON.stringify({status:report.status,batchId:b.batchId,probeError:err})); process.exit(1); }
|
|
const result=JSON.parse(String(k.ccall('fc_web_dispatch_json','string',['string'],[JSON.stringify({cmd:'robot.pythonFamilyBatch',args:{tier:'object-contract',records:rows}})])));
|
|
const ok=result.ok===true&&result.count===rows.length&&result.resourcesReleased===true&&result.records.every(r=>r.status==='exposed'&&r.native===true&&r.resourcesReleased===true);
|
|
const hash=v=>crypto.createHash('sha256').update(JSON.stringify(v)).digest('hex'); const evidence=`docs/p6/robot-generic-document-object-module-batch-${b.batchId}-runtime.json`;
|
|
const manifest=JSON.parse(fs.readFileSync(path.join(root,'web/public/modules/manifest.json'),'utf8')); const artifact=manifest.modules?.Robot??{};
|
|
const report={schema:'freecad-web-robot-generic-document-object-module-batch-runtime/v1',taskId:'FW-P6-FPA-Y',batchId:b.batchId,module:'Robot',tier:'object-contract',family:'generic-document-object',status:ok?'pass':'fail',dispatcher:'fc_web_dispatch_json',route:{command:'robot.pythonFamilyBatch',native:'freecad-source/src/WebAssembly/FreeCADCoreProbe/RobotInventoryApi.cpp:fc_web_dispatch_json',facade:'web/src/robot-python-family-facade.ts',worker:'web/src/robot-python.worker.ts',loader:'web/src/module-loader.ts',routerApi:['WebModuleRouter.setArtifact','WebModuleRouter.loadManifest','WebModuleRouter.preload']},artifact:{revision:artifact.revision,runtimeUrl:artifact.runtimeUrl,wasmUrl:artifact.wasmUrl,dataUrl:artifact.dataUrl,assetBaseUrl:artifact.assetBaseUrl,buildProfile:artifact.buildProfile,workers:artifact.workers},input:{cmd:'robot.pythonFamilyBatch',args:{tier:'object-contract',records:rows}},result,resultSha256:hash(result),dispositionCounts:{exposed:result.records.filter(r=>r.status==='exposed').length,restricted:0,nonportable:0,not_implemented:result.records.filter(r=>r.status!=='exposed').length},records:result.records,boundaries:['Native Robot document-object registration and recompute are covered through one shared dispatcher and dynamically routed Worker.']};
|
|
fs.writeFileSync(path.join(root,evidence),JSON.stringify(report,null,2)+'\n'); fs.rmSync(temporary,{recursive:true,force:true}); console.log(JSON.stringify({status:report.status,batchId:b.batchId,resultSha256:report.resultSha256})); process.exit(ok?0:1);
|