Files
ycode/scripts/rea/algorithm-expert-recover.mjs

28 lines
5.0 KiB
JavaScript

/** Reproduce target recovery only through public formal REA directory CLI. */
import fs from 'node:fs'
import path from 'node:path'
import crypto from 'node:crypto'
import {spawnSync} from 'node:child_process'
const input=process.argv[2]
if(!input)throw Error('Provide retained narrow package analysis or formal directory inventory')
const analysis=JSON.parse(fs.readFileSync(input,'utf8')),source=analysis.normalized_result
const root=source?.input_path??source?.root_identity?.path,pin=source?.root_artifact_sha256??source?.root_sha256,recovered='.tmp/rea-algorithm-recovered-20261016'
if(!root||!pin)throw Error('Pinned narrow REA analysis or formal inventory required')
function cli(command,args){const r=spawnSync(process.execPath,['.tmp/rea-css-runtime/scripts/rea.mjs',command,...args],{encoding:'utf8',maxBuffer:40*1024*1024});if(r.status!==0)throw Error(r.stderr||r.stdout);return JSON.parse(r.stdout)}
const inventory=cli('inspect-selected-directory-text-root',[root]);if(inventory.normalized_result.root_sha256!==pin)throw Error('Package changed since narrow REA analysis')
fs.writeFileSync(`.tmp/rea-algorithm-inventory-${inventory.evidence_id}.json`,JSON.stringify(inventory))
if(inventory.normalized_result.coverage.status!=='complete')throw Error('Target package inventory is incomplete')
const members=inventory.normalized_result.members.filter(m=>m.kind==='file'),meta=members.find(m=>/^\.(codebuddy|workbuddy)-plugin\/plugin\.json$/.test(m.path))
if(!meta)throw Error('No exact source plugin manifest')
function exportBatch(list,binary=false){return cli(binary?'export-selected-directory-binary':'export-selected-directory-text',[root,pin,JSON.stringify(binary?list.map(m=>({path:m.path,sha256:m.sha256})):list.map(m=>m.path))])}
const identityEvidence=exportBatch([meta]),p=JSON.parse(identityEvidence.normalized_result.files[0].text)
if(!/高级算法|小算|algorithm.?engineer/i.test(JSON.stringify([p.name,p.displayName,p.profession,p.agentName])))throw Error('Source metadata does not establish the requested algorithm expert')
const manifest={sourceExpert:'高级算法工程师 | 小算',sourceRoot:root,rootSha256:pin,inputEvidenceId:analysis.evidence_id,inputEvidenceKind:source.input_path?'javascript-application-analysis':'selected-directory-inventory',...(source.input_path?{analysisEvidenceId:analysis.evidence_id}:{}),inventoryEvidenceId:inventory.evidence_id,inventoryCoverage:inventory.normalized_result.coverage,identity:{name:p.name,agentName:p.agentName,expertType:p.expertType,displayName:p.displayName,profession:p.profession,version:p.version,agents:p.agents,skills:p.skills,dependencies:p.dependencies,mcpServers:p.mcpServers},files:[],omittedMarkers:[],unknown:[]}
const text=[],binary=[]
for(const m of members){if(/^\.(downloaded_at|created-by-session|pending-preview-session)$/.test(m.path)){manifest.omittedMarkers.push(m.path);continue}if(/\.png$/i.test(m.path))binary.push(m);else if(/\.(md|txt|json|yaml|yml|py|js|css|html|mjs|cjs|ps1)$/i.test(m.path)||/(^|\/)(LICENSE|NOTICE)$/i.test(m.path))text.push(m);else manifest.unknown.push({path:m.path,reason:'Required extension not yet supported by this recovery script'})}
function restore(evidence){if(evidence.normalized_result.root_sha256!==pin)throw Error('Root mismatch');const exportPath=`.tmp/rea-algorithm-export-${evidence.evidence_id}.json`;fs.writeFileSync(exportPath,JSON.stringify(evidence));for(const f of evidence.normalized_result.files){const original=members.find(m=>m.path===f.path),bytes=f.encoding==='base64'?Buffer.from(f.data_base64,'base64'):Buffer.from(f.text,'utf8'),sha=crypto.createHash('sha256').update(bytes).digest('hex');if(sha!==f.sha256||sha!==original.sha256||bytes.length!==f.size_bytes||bytes.length!==original.size_bytes)throw Error('Source byte/SHA mismatch');if(f.path.split('/').some(p=>!p||p==='.'||p==='..')||f.path.includes('\\'))throw Error('Noncanonical relative path');const destination=path.join(recovered,...f.path.split('/'));fs.mkdirSync(path.dirname(destination),{recursive:true});fs.writeFileSync(destination,bytes);if(crypto.createHash('sha256').update(fs.readFileSync(destination)).digest('hex')!==sha)throw Error('Recovery disk SHA mismatch');manifest.files.push({path:f.path,bytes:f.size_bytes,sha256:sha,evidenceId:evidence.evidence_id,retainedExport:exportPath,...(f.encoding?{encoding:f.encoding,mediaType:f.media_type}:{})})}}
restore(identityEvidence)
for(const [list,isBinary]of [[text.filter(m=>m.path!==meta.path),false],[binary,true]]){let batch=[],bytes=0;for(const m of list){if(batch.length&&(batch.length>=12||bytes+m.size_bytes>8*1024*1024)){restore(exportBatch(batch,isBinary));batch=[];bytes=0}batch.push(m);bytes+=m.size_bytes}if(batch.length)restore(exportBatch(batch,isBinary))}
fs.writeFileSync(path.join(recovered,'evidence-manifest.json'),JSON.stringify(manifest,null,2)+'\n')
console.log(JSON.stringify({result:manifest.unknown.length?'PARTIAL':'PASS',recovered,identity:manifest.identity,files:manifest.files.length,bytes:manifest.files.reduce((n,f)=>n+f.bytes,0),unknown:manifest.unknown,omittedMarkers:manifest.omittedMarkers},null,2))