Add reviewed fleet domain proposals

This commit is contained in:
thePR0M3TH3AN committed 2026-09-27 15:44:56 -04:00
1 parent cce059fc3a
commit b609ae44ce
9 files changed
+499 -17

No files matched your search

+24 -1
View File
@@ -1,6 +1,6 @@
import assert from 'node:assert/strict';
import { execFileSync, spawnSync } from 'node:child_process';
import { existsSync, mkdtempSync, writeFileSync } from 'node:fs';
import { existsSync, mkdtempSync, readFileSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import test from 'node:test';
@@ -43,3 +43,26 @@ test('SCN-cli-install-approval: install requires an explicit reviewed approval f
assert.equal(JSON.parse(result.stdout).error, 'APPROVAL_REQUIRED');
assert.equal(existsSync(join(root, '.torch')), false);
});
test('SCN-cli-domain-review: a generated proposal must be approved before install', () => {
const root = repo();
const proposalPath = join(root, 'fleet-proposal.json');
const generated = run(root, ['domains', '--output', proposalPath, '--json']);
assert.equal(generated.status, 0, generated.stderr || generated.stdout);
const proposal = JSON.parse(readFileSync(proposalPath, 'utf8'));
assert.equal(proposal.review.status, 'pending');
assert.equal(proposal.domains.length > 0, true);
const rejected = run(root, ['install', '--proposal', proposalPath, '--yes', '--json']);
assert.equal(rejected.status, 2);
assert.equal(JSON.parse(rejected.stdout).error, 'PROPOSAL_NOT_APPROVED');
assert.equal(existsSync(join(root, '.torch')), false);
proposal.review = {
status: 'approved', reviewedAt: '2026-09-27T00:00:00Z', reviewedBy: 'fixture-owner', notes: [],
};
writeFileSync(proposalPath, `${JSON.stringify(proposal, null, 2)}\n`);
const installed = run(root, ['install', '--proposal', proposalPath, '--yes', '--json']);
assert.equal(installed.status, 0, installed.stderr || installed.stdout);
assert.equal(existsSync(join(root, '.torch', 'domain-proposal.approved.json')), true);
});
+50
View File
@@ -0,0 +1,50 @@
import assert from 'node:assert/strict';
import { execFileSync } from 'node:child_process';
import { mkdirSync, mkdtempSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import test from 'node:test';
import { analyzeRepository } from '../../src/kernel/analyze.mjs';
import { proposeDomains } from '../../src/kernel/domains.mjs';
import { inspectRepository } from '../../src/kernel/git.mjs';
function architectureFixture() {
const root = mkdtempSync(join(tmpdir(), 'torch-domains-'));
for (const dir of ['src/client', 'src/server', 'src/shared', 'test']) mkdirSync(join(root, dir), { recursive: true });
writeFileSync(join(root, 'src/shared/types.js'), 'export const protocol = 1;\n');
writeFileSync(join(root, 'src/client/app.js'), "import { protocol } from '../shared/types.js';\nexport const client = protocol;\n");
writeFileSync(join(root, 'src/client/view.js'), 'export const view = true;\n');
writeFileSync(join(root, 'src/server/api.js'), "import { protocol } from '../shared/types.js';\nexport const api = protocol;\n");
writeFileSync(join(root, 'src/server/store.js'), 'export const store = true;\n');
writeFileSync(join(root, 'test/system.test.js'), 'export const scenario = true;\n');
writeFileSync(join(root, 'test/contracts.test.js'), 'export const contracts = true;\n');
writeFileSync(join(root, 'package.json'), JSON.stringify({ name: 'split-app', scripts: { test: 'node --test' } }));
execFileSync('git', ['init', '-b', 'main', root]);
execFileSync('git', ['-C', root, 'config', 'user.email', '[email protected]']);
execFileSync('git', ['-C', root, 'config', 'user.name', 'TORCH Test']);
execFileSync('git', ['-C', root, 'add', '.']);
execFileSync('git', ['-C', root, 'commit', '-m', 'architecture fixture']);
return root;
}
test('SCN-domain-collision: shared contracts create evidence-linked neighboring domains', () => {
const repository = inspectRepository(architectureFixture());
const analysis = analyzeRepository(repository);
const proposal = proposeDomains({ repository, analysis });
const ids = proposal.domains.map((domain) => domain.id);
assert.deepEqual(ids, ['src-client', 'src-server', 'qa']);
assert.equal(analysis.architecture.dependencies.some((edge) =>
edge.from === 'src/client' && edge.to === 'src/shared' && edge.evidence === 'src/client/app.js'), true);
assert.equal(analysis.architecture.dependencies.some((edge) =>
edge.from === 'src/server' && edge.to === 'src/shared' && edge.evidence === 'src/server/api.js'), true);
assert.equal(analysis.architecture.sharedSurfaces.includes('src/shared/types.js'), true);
const frontend = proposal.domains.find((domain) => domain.id === 'src-client');
assert.deepEqual(frontend.neighbours, ['qa', 'src-server']);
const collision = proposal.collisions.find((item) => item.domains.join(':') === 'src-client:src-server');
assert.equal(collision.score >= 1, true);
assert.equal(collision.reasons.some((reason) => reason.type === 'shared-dependency'), true);
assert.equal(collision.resolution.strategy, 'session-manager-coordination');
assert.equal(proposal.review.status, 'pending');
});
+31 -3
View File
@@ -8,6 +8,7 @@ import { analyzeRepository } from '../../src/kernel/analyze.mjs';
import { diagnoseProject } from '../../src/kernel/doctor.mjs';
import { inspectRepository } from '../../src/kernel/git.mjs';
import { installProject, planInstall, uninstallProject } from '../../src/kernel/install.mjs';
import { proposeDomains, validateApprovedProposal } from '../../src/kernel/domains.mjs';
function fixture() {
const root = mkdtempSync(join(tmpdir(), 'torch-kernel-'));
@@ -24,12 +25,20 @@ function fixture() {
return { root, env: { ...process.env, XDG_DATA_HOME: stateHome } };
}
function approvedProposal(repository) {
const proposal = proposeDomains({ repository, analysis: analyzeRepository(repository) });
proposal.review = {
status: 'approved', reviewedAt: '2026-09-27T00:00:00Z', reviewedBy: 'fixture-owner', notes: [],
};
return proposal;
}
test('SCN-init-read-only: inspection and analysis do not mutate the project', () => {
const { root, env } = fixture();
const before = execFileSync('git', ['-C', root, 'status', '--porcelain'], { encoding: 'utf8' });
const repository = inspectRepository(root);
const analysis = analyzeRepository(repository);
const plan = planInstall({ repository, env });
const plan = planInstall({ repository, proposal: approvedProposal(repository), env });
const after = execFileSync('git', ['-C', root, 'status', '--porcelain'], { encoding: 'utf8' });
assert.equal(analysis.mutationPerformed, false);
@@ -43,8 +52,9 @@ test('SCN-init-read-only: inspection and analysis do not mutate the project', ()
test('SCN-install-doctor-purge: a fresh install is healthy and exactly reversible', () => {
const { root, env } = fixture();
const repository = inspectRepository(root);
const proposal = approvedProposal(repository);
const installed = installProject({
repository, env, projectId: 'fixture-project', now: () => new Date('2026-09-27T00:00:00Z'),
repository, proposal, env, projectId: 'fixture-project', now: () => new Date('2026-09-27T00:00:00Z'),
});
assert.equal(existsSync(join(root, '.torch', 'torch.yaml')), true);
@@ -66,7 +76,7 @@ test('SCN-install-doctor-purge: a fresh install is healthy and exactly reversibl
test('SCN-purge-protects-user-change: uninstall refuses to delete modified managed files', () => {
const { root, env } = fixture();
const repository = inspectRepository(root);
installProject({ repository, env, projectId: 'modified-project' });
installProject({ repository, proposal: approvedProposal(repository), env, projectId: 'modified-project' });
const configPath = join(root, '.torch', 'torch.yaml');
writeFileSync(configPath, `${readFileSync(configPath, 'utf8')}\n# owner change\n`);
@@ -77,3 +87,21 @@ test('SCN-purge-protects-user-change: uninstall refuses to delete modified manag
);
assert.equal(existsSync(configPath), true);
});
test('SCN-domain-approval: installation rejects stale or unapproved organizational proposals', () => {
const { root, env } = fixture();
const repository = inspectRepository(root);
const pending = proposeDomains({ repository, analysis: analyzeRepository(repository) });
assert.throws(
() => installProject({ repository, proposal: pending, env }),
(error) => error.code === 'PROPOSAL_NOT_APPROVED'
&& error.details.includes('proposal review status is not approved'),
);
pending.review.status = 'approved';
pending.repository.head = '0000000000000000000000000000000000000000';
assert.throws(
() => validateApprovedProposal({ proposal: pending, repository }),
(error) => error.details.includes('proposal is stale because HEAD changed'),
);
assert.equal(existsSync(join(root, '.torch')), false);
});