mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-10-27 07:51:52 +00:00
133 lines
7.8 KiB
JavaScript
133 lines
7.8 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import { execFileSync, spawnSync } from 'node:child_process';
|
|
import { mkdirSync, mkdtempSync, readFileSync, writeFileSync } from 'node:fs';
|
|
import { tmpdir } from 'node:os';
|
|
import { dirname, join } from 'node:path';
|
|
import test from 'node:test';
|
|
import { analyzeCombatrigFleet } from '../../src/importers/combatrig.mjs';
|
|
import { validateApprovedProposal } from '../../src/kernel/domains.mjs';
|
|
import { inspectRepository } from '../../src/kernel/git.mjs';
|
|
import { installProject } from '../../src/kernel/install.mjs';
|
|
import { planWorktrees } from '../../src/kernel/worktrees.mjs';
|
|
|
|
const CLI = new URL('../../bin/torch.mjs', import.meta.url).pathname;
|
|
|
|
function fixture() {
|
|
const root = mkdtempSync(join(tmpdir(), 'torch-combatrig-import-'));
|
|
execFileSync('git', ['init', '-b', 'main', root]);
|
|
execFileSync('git', ['-C', root, 'config', 'user.email', '[email protected]']);
|
|
execFileSync('git', ['-C', root, 'config', 'user.name', 'TORCH Test']);
|
|
mkdirSync(join(root, 'docs', 'agents', 'prompts'), { recursive: true });
|
|
mkdirSync(join(root, 'docs', 'agents', 'backlog'), { recursive: true });
|
|
mkdirSync(join(root, 'tools', 'test'), { recursive: true });
|
|
const roster = { areas: [
|
|
{
|
|
id: 'ai-sessions', title: 'AI session management', worktree: 'FIXTURE-ai-sessions',
|
|
branch: 'feat/ai-session-management', scope: 'dispatch and fleet health', neighbours: ['all'],
|
|
},
|
|
{
|
|
id: 'terrain', title: 'Terrain', worktree: 'FIXTURE-terrain', branch: 'feat/terrain',
|
|
scope: 'terrain compiler and world', neighbours: ['animation'],
|
|
},
|
|
{
|
|
id: 'animation', title: 'Animation', worktree: 'FIXTURE-animation', branch: 'feat/animation',
|
|
scope: 'animation systems', notScope: ['terrain generation'], ownedPaths: ['src/animation/**'],
|
|
neighbours: ['terrain'],
|
|
},
|
|
] };
|
|
writeFileSync(join(root, 'docs', 'agents', 'roster.json'), `${JSON.stringify(roster, null, 2)}\n`);
|
|
writeFileSync(join(root, 'docs', 'agents', 'prompts', 'COMMON.md'), '# Legacy common rules\n');
|
|
for (const area of roster.areas) {
|
|
writeFileSync(join(root, 'docs', 'agents', 'prompts', `${area.id}.md`), `# Legacy ${area.title}\n`);
|
|
}
|
|
writeFileSync(join(root, 'docs', 'agents', 'backlog', 'terr-1.json'), JSON.stringify({
|
|
id: 'terr-1', area: 'terrain', status: 'assigned', title: 'Terrain task',
|
|
}));
|
|
writeFileSync(join(root, 'docs', 'agents', 'backlog', 'anim-1.json'), JSON.stringify({
|
|
id: 'anim-1', area: 'animation', status: 'done', title: 'Animation task',
|
|
}));
|
|
writeFileSync(join(root, 'docs', 'agents', 'backlog', 'mgr-1.json'), JSON.stringify({
|
|
id: 'mgr-1', area: 'ai-sessions', status: 'assigned', assignedTo: 'Legacy dispatcher', title: 'Manager task',
|
|
}));
|
|
writeFileSync(join(root, 'docs', 'agents', 'backlog', 'retired-1.json'), JSON.stringify({
|
|
id: 'retired-1', area: 'retired-domain', status: 'open', title: 'Retired area task',
|
|
}));
|
|
writeFileSync(join(root, 'package.json'), `${JSON.stringify({
|
|
name: 'combatrig-fixture', scripts: {
|
|
'test:sessions': 'node sessions.mjs', build: 'node build.mjs', test: 'node all.mjs', 'test:terrain': 'node terrain.mjs',
|
|
},
|
|
}, null, 2)}\n`);
|
|
writeFileSync(join(root, 'tools', 'test', 'serve.mjs'), 'export const GATE_SLOTS = Math.max(1, Number(process.env.CR_GATE_SLOTS) || 2);\n');
|
|
writeFileSync(join(root, 'docs', 'agents', 'OPERATIONS.md'), 'Session-local schedules\n0 8,16 * * * tools/dev/release.sh\n');
|
|
execFileSync('git', ['-C', root, 'add', '.']);
|
|
execFileSync('git', ['-C', root, 'commit', '-m', 'legacy fleet fixture']);
|
|
return root;
|
|
}
|
|
|
|
test('SCN-combatrig-import: legacy fleet evidence converts without mutation and blocks invented ownership', () => {
|
|
const root = fixture();
|
|
const repository = inspectRepository(root);
|
|
const before = execFileSync('git', ['-C', root, 'status', '--porcelain'], { encoding: 'utf8' });
|
|
const proposal = analyzeCombatrigFleet({ repository });
|
|
const after = execFileSync('git', ['-C', root, 'status', '--porcelain'], { encoding: 'utf8' });
|
|
assert.equal(after, before);
|
|
assert.equal(proposal.review.status, 'pending');
|
|
assert.equal(proposal.session_manager.legacy_id, 'ai-sessions');
|
|
assert.deepEqual(proposal.domains.map((domain) => domain.id), ['terrain', 'animation']);
|
|
assert.equal(proposal.resources[0].capacity, 2);
|
|
assert.deepEqual(proposal.compatibility.backlog.byStatus, { done: 1, assigned: 2, open: 1 });
|
|
assert.equal(proposal.compatibility.backlog.migration.mode, 'assessment-only');
|
|
assert.deepEqual(proposal.compatibility.backlog.migration.unmappedAreas, [{ area: 'retired-domain', count: 1 }]);
|
|
assert.equal(proposal.compatibility.backlog.migration.sessionManagerAreaItems, 1);
|
|
assert.equal(proposal.compatibility.backlog.migration.freeformAssigneeLabels, 1);
|
|
assert.equal(proposal.compatibility.backlog.migration.legacyDoneItems, 1);
|
|
assert.equal(proposal.compatibility.backlog.migration.canImportAutomatically, false);
|
|
assert.match(proposal.compatibility.backlog.migration.note, /does not create Torch backlog tasks/);
|
|
assert.deepEqual(proposal.compatibility.backlog.byArea, {
|
|
terrain: 1, animation: 1, 'ai-sessions': 1, 'retired-domain': 1,
|
|
});
|
|
assert.equal(proposal.compatibility.schedules.every((schedule) => schedule.detected), true);
|
|
assert.equal(proposal.compatibility.readyForApproval, false);
|
|
assert.equal(proposal.compatibility.migrationGaps.some((gap) =>
|
|
gap.areaId === 'terrain' && gap.field === 'owned_paths'), true);
|
|
|
|
proposal.review = {
|
|
status: 'approved', reviewedAt: '2026-09-27T00:00:00Z', reviewedBy: 'fixture-owner', notes: [],
|
|
};
|
|
assert.throws(
|
|
() => validateApprovedProposal({ proposal, repository }),
|
|
(error) => error.code === 'PROPOSAL_NOT_APPROVED' && error.details.includes('domain terrain has no owned paths'),
|
|
);
|
|
proposal.domains.find((domain) => domain.id === 'terrain').owned_paths = ['src/terrain/**'];
|
|
proposal.domains.find((domain) => domain.id === 'terrain').not_scope = ['animation systems'];
|
|
validateApprovedProposal({ proposal, repository });
|
|
const stateRoot = mkdtempSync(join(tmpdir(), 'torch-combatrig-state-'));
|
|
const installed = installProject({ repository, proposal, env: {
|
|
...process.env, XDG_DATA_HOME: stateRoot,
|
|
}, projectId: 'combatrig-import-fixture' });
|
|
const config = JSON.parse(readFileSync(join(root, '.torch', 'torch.yaml'), 'utf8'));
|
|
assert.equal(config.paths.worktree_parent, '..');
|
|
assert.equal(config.domains.find((domain) => domain.id === 'terrain').branch, 'feat/terrain');
|
|
assert.equal(config.domains.find((domain) => domain.id === 'terrain').worktree_name, 'FIXTURE-terrain');
|
|
assert.equal(readFileSync(join(root, '.torch', 'prompts', 'terrain.md'), 'utf8'), '# Legacy Terrain\n');
|
|
const worktrees = planWorktrees({ repository: inspectRepository(root) });
|
|
assert.equal(worktrees.actions.find((action) => action.area === 'terrain').path,
|
|
join(dirname(root), 'FIXTURE-terrain'));
|
|
assert.equal(installed.mutationPerformed, true);
|
|
});
|
|
|
|
test('SCN-cli-combatrig-import: public import command writes a review artifact and returns the blocking status', () => {
|
|
const root = fixture();
|
|
const output = join(mkdtempSync(join(tmpdir(), 'torch-combatrig-report-')), 'proposal.json');
|
|
const before = execFileSync('git', ['-C', root, 'status', '--porcelain'], { encoding: 'utf8' });
|
|
const result = spawnSync(process.execPath, [CLI, 'import', 'combatrig', '--source', root, '--output', output, '--json'], {
|
|
cwd: dirname(root), encoding: 'utf8',
|
|
});
|
|
assert.equal(result.status, 1, result.stderr || result.stdout);
|
|
const response = JSON.parse(result.stdout);
|
|
assert.equal(response.output, output);
|
|
assert.equal(response.proposal.compatibility.readyForApproval, false);
|
|
assert.equal(readFileSync(output, 'utf8').includes('combatrig-portable-fleet'), true);
|
|
assert.equal(execFileSync('git', ['-C', root, 'status', '--porcelain'], { encoding: 'utf8' }), before);
|
|
});
|