mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-10-27 16:01:54 +00:00
114 lines
6.2 KiB
JavaScript
114 lines
6.2 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import { execFileSync } from 'node:child_process';
|
|
import { createHash } from 'node:crypto';
|
|
import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from 'node:fs';
|
|
import { tmpdir } from 'node:os';
|
|
import { basename, join } from 'node:path';
|
|
import test from 'node:test';
|
|
import { CheckService } from '../../src/checks/service.mjs';
|
|
import { openControlPlane } from '../../src/control-plane/service.mjs';
|
|
import { analyzeRepository } from '../../src/kernel/analyze.mjs';
|
|
import { proposeDomains } from '../../src/kernel/domains.mjs';
|
|
import { inspectRepository } from '../../src/kernel/git.mjs';
|
|
import { installProject } from '../../src/kernel/install.mjs';
|
|
import { createWorktrees } from '../../src/kernel/worktrees.mjs';
|
|
|
|
function fixture() {
|
|
const root = mkdtempSync(join(tmpdir(), 'torch-generated-artifacts-'));
|
|
execFileSync('git', ['init', '-b', 'main', root]);
|
|
execFileSync('git', ['-C', root, 'config', 'user.email', '[email protected]']);
|
|
execFileSync('git', ['-C', root, 'config', 'user.name', 'TORCH Test']);
|
|
writeFileSync(join(root, 'package.json'), `${JSON.stringify({
|
|
name: 'generated-artifacts-fixture', scripts: { 'verify:pass': 'node -e "process.exit(0)"' },
|
|
}, null, 2)}\n`);
|
|
writeFileSync(join(root, 'app.js'), 'export const app = true;\n');
|
|
mkdirSync(join(root, 'test'));
|
|
writeFileSync(join(root, 'test', 'scenario.js'), 'export const scenario = true;\n');
|
|
execFileSync('git', ['-C', root, 'add', '.']);
|
|
execFileSync('git', ['-C', root, 'commit', '-m', 'fixture']);
|
|
let repository = inspectRepository(root);
|
|
const proposal = proposeDomains({ repository, analysis: analyzeRepository(repository) });
|
|
proposal.review = { status: 'approved', reviewedAt: '2026-09-30T00:00:00Z', reviewedBy: 'fixture-owner', notes: [] };
|
|
const env = { ...process.env, XDG_DATA_HOME: join(tmpdir(), `${basename(root)}-state`) };
|
|
installProject({ repository, proposal, env, projectId: 'generated-artifacts-fixture' });
|
|
execFileSync('git', ['-C', root, 'add', '.torch']);
|
|
execFileSync('git', ['-C', root, 'commit', '-m', 'install torch']);
|
|
repository = inspectRepository(root);
|
|
createWorktrees({ repository, parentOverride: join(tmpdir(), `${basename(root)}-worktrees`) });
|
|
return { root, env, worker: proposal.domains.find((domain) => domain.id !== 'qa').id };
|
|
}
|
|
|
|
function addCheck(context, definition) {
|
|
const path = join(context.root, '.torch', 'torch.yaml');
|
|
const config = JSON.parse(readFileSync(path, 'utf8'));
|
|
config.checks.push(definition);
|
|
writeFileSync(path, `${JSON.stringify(config, null, 2)}\n`);
|
|
}
|
|
|
|
function treeStatus(path) {
|
|
return execFileSync('git', ['-C', path, 'status', '--porcelain'], { encoding: 'utf8' });
|
|
}
|
|
|
|
test('SCN-generated-check-artifacts: sequential exact checks retain external hashed evidence without changing tracked inputs', () => {
|
|
const context = fixture();
|
|
addCheck(context, {
|
|
id: 'emit-proof', command: process.execPath,
|
|
args: ['-e', `const fs=require('node:fs');const path=require('node:path');
|
|
const output=process.env.TORCH_CHECK_ARTIFACT_DIR;if(!output)process.exit(44);
|
|
fs.mkdirSync(path.join(output,'screenshots'),{recursive:true});
|
|
fs.writeFileSync(path.join(output,'screenshots','proof.txt'),'captured boundary evidence');`],
|
|
});
|
|
const control = openControlPlane({ repositoryRoot: context.root, env: context.env });
|
|
let id = 0;
|
|
const checks = new CheckService({ repositoryRoot: context.root, controlPlane: control,
|
|
idFactory: () => `artifact-run-${++id}` });
|
|
const expectedHash = createHash('sha256').update('captured boundary evidence').digest('hex');
|
|
try {
|
|
const receipts = [
|
|
checks.run({ checkId: 'emit-proof', areaId: context.worker }),
|
|
checks.run({ checkId: 'emit-proof', areaId: context.worker }),
|
|
];
|
|
for (const receipt of receipts) {
|
|
assert.equal(receipt.result, 'pass');
|
|
assert.equal(treeStatus(receipt.worktree), '', 'a passing check must leave its tested tree unchanged');
|
|
const retained = JSON.parse(readFileSync(receipt.artifactPath, 'utf8')).generatedArtifacts;
|
|
assert.deepEqual(retained.candidate, { commit: receipt.commit });
|
|
assert.deepEqual(retained.check, { id: 'emit-proof',
|
|
definitionHash: createHash('sha256').update(JSON.stringify(receipt.definition)).digest('hex') });
|
|
assert.deepEqual(retained.run, { id: receipt.id });
|
|
assert.deepEqual(retained.files, [{ path: 'screenshots/proof.txt', bytes: 26, sha256: expectedHash }]);
|
|
assert.equal(readFileSync(join(retained.directory, 'screenshots', 'proof.txt'), 'utf8'), 'captured boundary evidence');
|
|
}
|
|
assert.notEqual(receipts[0].generatedArtifacts.directory, receipts[1].generatedArtifacts.directory,
|
|
'each run retains its own recoverable evidence directory');
|
|
assert.equal(checks.exactPasses({ commit: receipts[0].commit, requiredChecks: ['emit-proof'] }), true);
|
|
} finally {
|
|
control.close();
|
|
}
|
|
});
|
|
|
|
test('SCN-generated-check-mutation: exit zero plus a tested-tree mutation is incomplete even when external evidence was retained', () => {
|
|
const context = fixture();
|
|
addCheck(context, {
|
|
id: 'emit-and-mutate', command: process.execPath,
|
|
args: ['-e', `const fs=require('node:fs');const path=require('node:path');
|
|
fs.writeFileSync(path.join(process.env.TORCH_CHECK_ARTIFACT_DIR,'proof.txt'),'retained despite mutation');
|
|
fs.writeFileSync('app.js','source mutation');`],
|
|
});
|
|
const control = openControlPlane({ repositoryRoot: context.root, env: context.env });
|
|
const checks = new CheckService({ repositoryRoot: context.root, controlPlane: control,
|
|
idFactory: () => 'mutation-run' });
|
|
try {
|
|
const receipt = checks.run({ checkId: 'emit-and-mutate', areaId: context.worker });
|
|
assert.equal(receipt.exitStatus, 0);
|
|
assert.equal(receipt.result, 'incomplete');
|
|
assert.equal(receipt.invalidReason, 'worktree-changed-during-check');
|
|
const retained = JSON.parse(readFileSync(receipt.artifactPath, 'utf8')).generatedArtifacts;
|
|
assert.equal(existsSync(join(retained.directory, 'proof.txt')), true);
|
|
assert.notEqual(treeStatus(receipt.worktree), '');
|
|
assert.equal(checks.exactPasses({ commit: receipt.commit, requiredChecks: ['emit-and-mutate'] }), false);
|
|
} finally {
|
|
control.close();
|
|
}
|
|
});
|