'use strict'; const assert = require('node:assert/strict'); const crypto = require('node:crypto'); const fs = require('node:fs'); const os = require('node:os'); const path = require('node:path'); const test = require('node:test'); const REMOTE_DIR = '/data/ps5_autoloader'; const digest = value => crypto.createHash('sha256').update(value).digest('hex'); function elf(marker, size = 64) { const value = Buffer.alloc(size, marker); Buffer.from('7f454c46020101', 'hex').copy(value); value.writeUInt16LE(0x3e, 18); return value; } class FakeFtp { constructor(files, corrupt = false) { this.files = new Map(Object.entries(files).map(([name, bytes]) => [`${REMOTE_DIR}/${name}`, Buffer.from(bytes)])); this.writes = 0; this.corrupt = corrupt; } async list() { return [...this.files].map(([name, bytes]) => ({ name: path.posix.basename(name), size: bytes.length, isDir: false })); } async download(source, target) { let bytes = this.files.get(source); if (!bytes) throw new Error('missing'); if (this.corrupt && source.endsWith('/autoload.txt') && this.writes >= 7) bytes = Buffer.from('corrupt\n'); fs.mkdirSync(path.dirname(target), { recursive: true }); fs.writeFileSync(target, bytes); } async upload(source, target) { this.writes += 1; this.files.set(target, fs.readFileSync(source)); } async rename(source, target) { this.writes += 1; const bytes = this.files.get(source); if (!bytes) throw new Error('missing'); this.files.delete(source); this.files.set(target, bytes); } async delete(target) { this.writes += 1; if (!this.files.delete(target)) throw new Error('missing'); } } async function fixture(t) { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-a8-completion-stage-')); t.after(() => fs.rmSync(root, { recursive: true, force: true })); const local = path.join(root, 'local'); const temporary = path.join(root, 'temp'); const backup = path.join(root, 'backup'); fs.mkdirSync(local); const oldLoader = elf(1, 80); const oldReader = elf(2, 72); const newLoader = elf(3, 96); const newReader = elf(4, 76); const currentLines = ['', '', 'manager.elf', 'a7-loader.elf', '!30000', 'a7-reader.elf', '!5000', 'service.elf']; const manifest = Buffer.from(`${currentLines.join('\n')}\n`); fs.writeFileSync(path.join(local, 'new-loader.elf'), newLoader); fs.writeFileSync(path.join(local, 'new-reader.elf'), newReader); const contract = { schema: 'test.a8.stage.v1', identity: 'a8-stage-test', current: { manifestSha256: digest(manifest), loaderName: 'a7-loader.elf', loaderSize: oldLoader.length, loaderSha256: digest(oldLoader), readerName: 'a7-reader.elf', readerSize: oldReader.length, readerSha256: digest(oldReader), }, next: { loaderLocalName: 'new-loader.elf', loaderRemoteName: 'a8-loader.elf', loaderSize: newLoader.length, loaderSha256: digest(newLoader), readerLocalName: 'new-reader.elf', readerRemoteName: 'a8-reader.elf', readerSize: newReader.length, readerSha256: digest(newReader), }, currentManifest: currentLines, }; const files = { 'autoload.txt': manifest, 'a7-loader.elf': oldLoader, 'a7-reader.elf': oldReader, 'manager.elf': elf(5), 'service.elf': elf(6), }; return { local, temporary, backup, oldLoader, oldReader, newLoader, newReader, manifest, contract, files }; } test('A8 plan is read-only and binds the exact call-bound runtime pair', async t => { const f = await fixture(t); const ftp = new FakeFtp(f.files); const { createPlan, CONFIRMATION } = await import('../../scripts/autonomous/p15-a8-stage-completion.mjs'); const plan = await createPlan({ ftp, localRoot: f.local, temporaryRoot: f.temporary, contract: f.contract }); assert.equal(CONFIRMATION, 'STAGE CHIMERA P15 A8 COMPLETION RUNTIME'); assert.equal(ftp.writes, 0); assert.match(plan.proposed.manifest, /a8-loader\.elf/); assert.match(plan.proposed.manifest, /a8-reader\.elf/); assert.doesNotMatch(plan.proposed.manifest, /a7-loader\.elf|a7-reader\.elf/); assert.equal(plan.consoleMutationPerformed, false); assert.equal(plan.payloadLoadPerformed, false); assert.equal(plan.launchPerformed, false); }); test('A8 default contract advances only the qualified A7 runtime and exact reproducible artifacts', async () => { const { DEFAULT_CONTRACT } = await import('../../scripts/autonomous/p15-a8-stage-completion.mjs'); const currentManifest = Buffer.from(`${DEFAULT_CONTRACT.currentManifest.join('\n')}\n`); assert.equal(digest(currentManifest), DEFAULT_CONTRACT.current.manifestSha256); assert.equal(DEFAULT_CONTRACT.current.loaderName, 'kstuff-p15-a7-route-selection.elf'); assert.equal(DEFAULT_CONTRACT.current.readerName, 'kstuff-p15-a7-route-reader.elf'); assert.equal(DEFAULT_CONTRACT.next.loaderSha256, '9c1640cd61fdaa99f510f7eea78fe14ed526fc2ced8a78bef80c8bc03fed692f'); assert.equal(DEFAULT_CONTRACT.next.readerSha256, 'a2aedb429d2beb3e8bdb273329013db767c674c19d52854e5114dffa78f21699'); assert.equal(DEFAULT_CONTRACT.recoverySchema, 'chimera.p15-a8-completion-recovery.v1'); }); test('A8 apply snapshots the full autoload directory and preserves A7 rollback bytes', async t => { const f = await fixture(t); const ftp = new FakeFtp(f.files); const { createPlan, applyPlan, CONFIRMATION } = await import('../../scripts/autonomous/p15-a8-stage-completion.mjs'); const plan = await createPlan({ ftp, localRoot: f.local, temporaryRoot: f.temporary, contract: f.contract }); const receipt = await applyPlan({ ftp, localRoot: f.local, temporaryRoot: f.temporary, backupRoot: f.backup, contract: f.contract, confirmation: CONFIRMATION, planDigest: plan.planDigest, now: () => 1234567890123, nonce: () => 'a8stage1', }); assert.equal(receipt.status, 'staged_verified'); assert.equal(receipt.consoleMutationPerformed, true); assert.equal(receipt.automaticRebootPerformed, false); assert.equal(receipt.payloadLoadPerformed, false); assert.equal(receipt.launchPerformed, false); assert.deepEqual(ftp.files.get(`${REMOTE_DIR}/a7-loader.elf`), f.oldLoader); assert.deepEqual(ftp.files.get(`${REMOTE_DIR}/a7-reader.elf`), f.oldReader); assert.deepEqual(ftp.files.get(`${REMOTE_DIR}/a8-loader.elf`), f.newLoader); assert.deepEqual(ftp.files.get(`${REMOTE_DIR}/a8-reader.elf`), f.newReader); assert.equal(JSON.parse(fs.readFileSync(path.join(f.backup, receipt.snapshotId, 'meta.json'))).files.length, 5); }); test('A8 independent readback is read-only and verifies new plus preserved runtime bytes', async t => { const f = await fixture(t); const ftp = new FakeFtp(f.files); const { createPlan, applyPlan, verifyStaged, CONFIRMATION } = await import('../../scripts/autonomous/p15-a8-stage-completion.mjs'); const plan = await createPlan({ ftp, localRoot: f.local, temporaryRoot: f.temporary, contract: f.contract }); await applyPlan({ ftp, localRoot: f.local, temporaryRoot: f.temporary, backupRoot: f.backup, contract: f.contract, confirmation: CONFIRMATION, planDigest: plan.planDigest, now: () => 1234567890123, nonce: () => 'readback', }); const writesBefore = ftp.writes; const result = await verifyStaged({ ftp, temporaryRoot: f.temporary, contract: f.contract }); assert.equal(result.status, 'verified'); assert.equal(result.oldRuntimeArtifactsPreserved, true); assert.equal(result.consoleMutationPerformed, false); assert.equal(ftp.writes, writesBefore); }); test('A8 refuses confirmation or plan drift before any write', async t => { const f = await fixture(t); const ftp = new FakeFtp(f.files); const { createPlan, applyPlan, CONFIRMATION } = await import('../../scripts/autonomous/p15-a8-stage-completion.mjs'); const plan = await createPlan({ ftp, localRoot: f.local, temporaryRoot: f.temporary, contract: f.contract }); await assert.rejects(applyPlan({ ftp, localRoot: f.local, temporaryRoot: f.temporary, backupRoot: f.backup, contract: f.contract, confirmation: 'wrong', planDigest: plan.planDigest, }), { code: 'P15_A8_STAGE_CONFIRMATION' }); await assert.rejects(applyPlan({ ftp, localRoot: f.local, temporaryRoot: f.temporary, backupRoot: f.backup, contract: f.contract, confirmation: CONFIRMATION, planDigest: '0'.repeat(64), }), { code: 'P15_A8_STAGE_PLAN_DRIFT' }); assert.equal(ftp.writes, 0); }); test('A8 post-publication drift restores A7 manifest and removes A8 targets', async t => { const f = await fixture(t); const ftp = new FakeFtp(f.files, true); const { createPlan, applyPlan, CONFIRMATION } = await import('../../scripts/autonomous/p15-a8-stage-completion.mjs'); const plan = await createPlan({ ftp, localRoot: f.local, temporaryRoot: f.temporary, contract: f.contract }); await assert.rejects(applyPlan({ ftp, localRoot: f.local, temporaryRoot: f.temporary, backupRoot: f.backup, contract: f.contract, confirmation: CONFIRMATION, planDigest: plan.planDigest, now: () => 1234567890123, nonce: () => 'rollback', }), error => error.code === 'P15_A8_STAGE_POST_VERIFY' && error.details.rolledBack === true); assert.deepEqual(ftp.files.get(`${REMOTE_DIR}/autoload.txt`), f.manifest); assert.equal(ftp.files.has(`${REMOTE_DIR}/a8-loader.elf`), false); assert.equal(ftp.files.has(`${REMOTE_DIR}/a8-reader.elf`), false); });