import { spawnSync } from 'node:child_process'; import { readFile, stat } from 'node:fs/promises'; import path from 'node:path'; import { fail, pass, repositoryRoot, sha256 } from './lib.mjs'; const contractRoot = path.join(repositoryRoot, 'contracts', 'phase9'); const manifestPath = path.join(contractRoot, 'PACKAGE_MANIFEST_v1.0.json'); const manifest = JSON.parse(await readFile(manifestPath, 'utf8')); const errors = []; if (manifest.file_count !== manifest.files.length) { errors.push( `Manifest count ${manifest.file_count} differs from ${manifest.files.length} entries.`, ); } for (const entry of manifest.files) { const filePath = path.join(contractRoot, entry.path); try { const details = await stat(filePath); if (details.size !== entry.bytes) errors.push(`${entry.path}: byte count changed.`); if ((await sha256(filePath)) !== entry.sha256) errors.push(`${entry.path}: checksum changed.`); } catch { errors.push(`${entry.path}: missing.`); } } const validator = spawnSync( process.execPath, [path.join(contractRoot, 'qa', 'validate-phase9-package_v1.0.mjs'), contractRoot], { encoding: 'utf8' }, ); if (validator.status !== 0) { errors.push(`Phase 9 validator failed: ${validator.stderr || validator.stdout}`); } if (errors.length > 0) fail(errors); else pass( `Phase 9 contract package is immutable and ${manifest.files.length} payload checksums match.`, );