Files
jobtrackingapp/automation/prepare_assessment.mjs
T

62 lines
4.2 KiB
JavaScript

// Trusted operator preparation. Validates published native evidence; runs no product suite.
import fs from 'node:fs';
import path from 'node:path';
import crypto from 'node:crypto';
import zlib from 'node:zlib';
import { pathToFileURL } from 'node:url';
import { execFileSync } from 'node:child_process';
const [repository, destination] = process.argv.slice(2);
if (!repository || !destination) throw new Error('Usage: node prepare_assessment.mjs <published-handoff-checkout> <new-output-directory>');
const root = fs.realpathSync(repository), output = path.resolve(destination);
if (fs.existsSync(output)) throw new Error('Use a new receipt directory; preserve previous qualification');
const git = (...args) => execFileSync('rtk', ['proxy','git','-C',root,...args], {encoding:'utf8'}).trim();
const handoff = '5cb903b989742b7a96cb22ddf4c0e24993b18980';
const baseline = 'fc5b9d377199ce51f480a920a3772108094929e3';
if (git('rev-parse','HEAD') !== handoff || git('status','--porcelain')) throw new Error('Require the exact clean published handoff checkout');
const remote = git('ls-remote','--exit-code','origin','refs/heads/test/pre-phase10-ux-acceptance');
if (remote.split(/\s/)[0] !== handoff) throw new Error('Handoff publication differs');
if (git('rev-parse',handoff+'^') !== baseline) throw new Error('Baseline relationship differs');
const relative = 'docs/automation/handoffs/pre-phase10';
const directory = path.join(root,relative);
const {validatePackage, measureNative} = await import(pathToFileURL(path.join(directory,'verify.mjs')).href);
const verified = validatePackage();
if (verified.integrity !== 'PASS' || !verified.observedWorkingTreeClean) throw new Error('Handoff integrity failed');
const evidence = JSON.parse(fs.readFileSync(path.join(directory,'TEST_EVIDENCE.json')));
const artifact = id => {
const row=evidence.artifacts.find(item=>item.id===id);
if (!row) throw new Error('Missing native artifact');
const raw=fs.readFileSync(path.join(directory,row.path));
return row.path.endsWith('.gz') ? zlib.gunzipSync(raw) : raw;
};
const hash = raw => crypto.createHash('sha256').update(raw).digest('hex');
const files = {};
// Freeze all tracked non-envelope sources, including tests/config/security/preservation documentation.
for (const name of git('ls-files','-z').split('\0').filter(Boolean)) {
if (!name.startsWith(relative+'/')) files[name]=hash(fs.readFileSync(path.join(root,name)));
}
const nativeReports = evidence.reports.map(report=>{
let observation=JSON.parse(artifact(report.processArtifactId));
const parts=report.processPointer.slice(1).split('/').map(value=>value.replaceAll('~1','/').replaceAll('~0','~'));
for (const key of parts.slice(0,-1)) observation=observation[key];
return {...report, measured:report.nativeFormat ? measureNative(report.nativeFormat,artifact(report.artifactId).toString('utf8')) : null,
nativeProcess:observation};
});
fs.mkdirSync(output,{recursive:true});
const evidenceFiles={};
for (const name of git('ls-files',relative).split(/\r?\n/).filter(Boolean)) {
const local=path.relative(directory,path.join(root,name));
const target=path.join(output,'handoff',local);
fs.mkdirSync(path.dirname(target),{recursive:true});
fs.copyFileSync(path.join(root,name),target);
evidenceFiles['handoff/'+local.split(path.sep).join('/')]=hash(fs.readFileSync(target));
}
const receipt={schemaVersion:1,scope:'P10-00-ASSESSMENT-ONLY',integrity:'PASS',
generatedUtc:new Date().toISOString(),baselineCommit:baseline,handoffCommit:handoff,
testedCommit:evidence.testedCommit,files,evidenceFiles,nativeReports,
retainedDecisions:JSON.parse(fs.readFileSync(path.join(directory,'ACCEPTANCE.json'))).verdicts,
revisedS01:verified.revisedS01,verifierObservation:verified,
limits:'Source-bound reuse for unchanged read-only assessment. Original failures and conditional/blocked decisions retained. No fresh product, security, model, human or production acceptance.'};
fs.writeFileSync(path.join(output,'receipt.json'),JSON.stringify(receipt,null,2)+'\n');
console.log(JSON.stringify({integrity:'PASS',receipt:path.join(output,'receipt.json'),sha256:hash(fs.readFileSync(path.join(output,'receipt.json'))),frozenSources:Object.keys(files).length,nativeReports:nativeReports.length,productSuitesExecuted:0},null,2));