/* Recompute perturbations and predictions; no dependencies or API access. */ const fs=require('fs'),crypto=require('crypto'),path=require('path'); const source=require('./source_modelops_engine.js');const robust=require('./robustness_engine.js'); const read=(name)=>JSON.parse(fs.readFileSync(path.join(__dirname,name),'utf8')); const train=read('train.json'),iid=read('iid_test.json'),challenge=read('challenge.json'); const bundle=source.train(train);const all=[]; for(const [split,items] of [['iid',iid],['challenge',challenge]])for(const method of robust.METHODS){ for(let i=0;iNumber(v.toFixed(9)))}); } } } const manifest={project:'RobustnessLab AI',schemaVersion:'1.0.0',sourceDataset:'Academic Rhetorical Intent Mini v1.1',sourceType:'synthetic-curated',sourceProject:'ModelOps Research Lab 2.0',generatedWith:'node generate_artifacts.js',modelMethods:robust.METHODS,attackIds:robust.ATTACKS.map(a=>a.id),trainingCount:train.length,iidCount:iid.length,challengeCount:challenge.length,evaluationRecords:all.length,license:'code MIT; original curated synthetic dataset CC BY 4.0',warning:'This is synthetic offline research. Labels may not be invariant under all perturbations. No external/production validation.',files:{}}; for(const name of ['train.json','iid_test.json','challenge.json','source_modelops_engine.js','robustness_engine.js'])manifest.files[name]=crypto.createHash('sha256').update(fs.readFileSync(name)).digest('hex'); const payload={metadata:manifest,rows:all}; fs.writeFileSync('robustness_snapshots.json',JSON.stringify(payload)); manifest.files['robustness_snapshots.json']=crypto.createHash('sha256').update(fs.readFileSync('robustness_snapshots.json')).digest('hex'); fs.writeFileSync('benchmark_manifest.json',JSON.stringify(manifest,null,2)); console.log('TRAIN',train.length,'IID',iid.length,'CHALLENGE',challenge.length,'RECORDS',all.length); console.log('AUDIT',JSON.stringify(robust.audit(all))); for(const method of robust.METHODS){const items=robust.ATTACKS.map(a=>robust.summarize(all,method,'challenge',a.id));console.log('MODEL',method,items.map(x=>`${x.attack}:n${x.changed}/${x.n},flip${(x.flipRate*100).toFixed(1)}%,acc${x.accuracy===null?'NA':(x.accuracy*100).toFixed(1)+'%'}`).join(' | '));}