mirror of
https://github.com/affaan-m/ECC.git
synced 2026-09-17 23:28:04 +02:00
* feat: add read-only coordination inventory and overlap evaluation * test: make coordination process fixtures platform explicit * test: report bounded Stop wrapper failure diagnostics * test: clean up failed memory MCP sessions deterministically * fix: update js-yaml to patched 4.3.2 * feat(coordination): distinguish declared goals from open sessions
156 lines
11 KiB
JavaScript
156 lines
11 KiB
JavaScript
'use strict';
|
|
const { test } = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const os = require('node:os');
|
|
const path = require('node:path');
|
|
const { spawnSync } = require('node:child_process');
|
|
const { normalizeManifest, buildInventory, collectResources, collectTaskFiles, readJson } = require('../../scripts/lib/coordination-inventory');
|
|
const now = '2026-09-08T06:30:00.000Z';
|
|
const task = (id, paths, extra = {}) => ({ id, repoId: 'repo', paths, ...extra });
|
|
const fixture = () => ({ version: 1, repositories: [{ id: 'repo', sources: { 'src/a.js': "require('../lib/b')", 'lib/b.js': '' } }], tasks: [task('a', ['src/a.js']), task('b', ['lib/b.js'])], leases: [] });
|
|
const run = value => buildInventory(value, { now });
|
|
|
|
test('direct import warns when exact-path baseline would miss it; deterministic JSON', () => {
|
|
const f = fixture(); const before = JSON.stringify(f); const r = run(f);
|
|
assert.equal(r.warnings.length, 1); assert.deepEqual(r.warnings[0].reasons, ['import_dependency']);
|
|
assert.equal(r.warnings[0].channels.dependency, 1);
|
|
assert.equal(JSON.stringify(run(f)), JSON.stringify(r)); assert.equal(JSON.stringify(f), before);
|
|
});
|
|
test('normalized exact paths warn, tree-only neighbors and cross-repo pairs do not', () => {
|
|
const f = fixture(); f.tasks[1].paths = ['./src/a.js'];
|
|
assert.deepEqual(run(f).warnings[0].reasons, ['path_overlap']);
|
|
f.tasks[1].paths = ['src/c.js']; assert.equal(run(f).warnings.length, 0);
|
|
f.repositories.push({ id: 'other', sources: {} }); f.tasks[1] = task('b', ['src/a.js'], { repoId: 'other' });
|
|
assert.equal(run(f).warnings.length, 0);
|
|
});
|
|
test('leases show owner, expiry, conflicts and do not grant authority', () => {
|
|
const f = fixture(); f.leases = [
|
|
{ resource: 'browser:chrome', owner: 'root', expiresAt: '2026-09-08T07:00:00Z' },
|
|
{ resource: 'browser:chrome', owner: 'worker', expiresAt: '2026-09-08T07:00:00Z' },
|
|
{ resource: 'browser:chrome', owner: 'old', expiresAt: now }
|
|
]; const r = run(f);
|
|
assert.equal(r.leases[2].state, 'expired');
|
|
assert.deepEqual(r.leaseConflicts, [{ resource: 'browser:chrome', owners: ['root', 'worker'] }]);
|
|
assert.equal(r.mode, 'read-only'); assert.equal(r.leases[0].authority, 'declared-only');
|
|
});
|
|
test('stale heartbeat is not a proven stuck process; absent/future telemetry stays unknown', () => {
|
|
const f = fixture(); f.tasks = [task('a', [], { heartbeatAt: '2026-09-08T06:00:00Z', pid: 12 }), task('b', [], { heartbeatAt: '2026-09-08T07:00:00Z' }), task('c', [])];
|
|
const r = run(f); assert.equal(r.tasks[0].heartbeat.state, 'stale'); assert.equal(r.tasks[0].process.state, 'unknown');
|
|
assert.equal(r.tasks[1].heartbeat.state, 'clock-skew'); assert.equal(r.tasks[2].heartbeat.state, 'unknown');
|
|
});
|
|
test('task parents, status and bounded observations survive without source payload', () => {
|
|
const f = fixture(); f.tasks[1].parentId = 'a'; f.tasks[0].status = 'running'; f.tasks[0].unexpectedSecret = 'CANARY_SECRET';
|
|
f.repositories[0].sources['lib/b.js'] = 'CANARY_SOURCE';
|
|
const r = run(f); assert.equal(r.tasks[1].parentId, 'a'); assert.equal(r.tasks[0].status, 'running');
|
|
assert.ok(!JSON.stringify(r).includes('CANARY')); assert.equal(r.coverage.workingSets, 'declared-paths-only');
|
|
});
|
|
test('invalid shapes, IDs, paths, dates and missing repos fail closed', () => {
|
|
for (const mutate of [
|
|
f => { f.version = 2; }, f => { f.tasks = null; }, f => { f.tasks.push(f.tasks[0]); },
|
|
f => { f.tasks[0].paths = ['../escape']; }, f => { f.tasks[0].paths = ['/absolute']; },
|
|
f => { f.tasks[0].paths = ['C:\\secret']; }, f => { f.tasks[0].paths = ['a/../b']; },
|
|
f => { f.tasks[0].paths = ['__proto__']; }, f => { f.tasks[0].pid = '-1'; },
|
|
f => { f.tasks[0].heartbeatAt = 'yesterday'; }, f => { f.tasks[0].repoId = 'absent'; },
|
|
f => { f.repositories[0].sources = []; }, f => { f.tasks[0].id = '\n'; },
|
|
f => { f.tasks[0].parentId = 'a'; }, f => { f.tasks = Array(65).fill(f.tasks[0]); },
|
|
f => { f.leases = [{resource:'chrome',owner:'root',expiresAt:'bad'}]; }
|
|
]) { const f = fixture(); mutate(f); assert.throws(() => normalizeManifest(f), /Invalid/); }
|
|
});
|
|
test('process collection uses metadata-only argv, bounded timeout and no shell', () => {
|
|
let call; const r = collectResources([task('a', [], { pid: 12 })], { platform: 'darwin', totalmem: () => 1024, freemem: () => 512, execFileSync: (...args) => { call = args; return '12 1 32 01:30 S\n'; } });
|
|
assert.equal(call[0], 'ps'); assert.deepEqual(call[1], ['-p','12','-o','pid=,ppid=,rss=,etime=,stat=']);
|
|
assert.equal(call[2].timeout, 2000); assert.equal(call[2].shell, false);
|
|
assert.equal(r.processes[0].rssBytes, 32768); assert.equal(r.memory.freeBytes, 512);
|
|
});
|
|
test('unavailable, empty, malformed and unsupported process snapshots remain explicit', () => {
|
|
const tasks = [task('a', [], { pid: 12 })];
|
|
let runnerCalls = 0;
|
|
const unsupportedDeps = { platform: 'win32', execFileSync: () => { runnerCalls += 1; return ''; } };
|
|
const unsupported = collectResources(tasks, unsupportedDeps);
|
|
assert.equal(unsupported.processStatus, 'unsupported');
|
|
assert.equal(buildInventory({ ...fixture(), tasks }, { now, resources: unsupported }).tasks[0].process.state, 'unknown');
|
|
// Runner fixtures must select a supported platform independently of the host.
|
|
assert.equal(collectResources(tasks, { platform: 'darwin', execFileSync: () => { throw new Error('SECRET'); } }).processStatus, 'unavailable');
|
|
assert.equal(collectResources(tasks, { platform: 'darwin', execFileSync: () => '' }).processStatus, 'ok');
|
|
assert.equal(collectResources(tasks, { platform: 'darwin', execFileSync: () => 'bad row' }).processStatus, 'unavailable');
|
|
assert.equal(collectResources([], unsupportedDeps).processStatus, 'not-requested');
|
|
assert.equal(runnerCalls, 0);
|
|
});
|
|
test('live process snapshot enriches matching tasks and marks missing PID as unobserved', () => {
|
|
const f = fixture(); f.tasks[0].pid = 12; f.tasks[1].pid = 13;
|
|
const resources = collectResources(f.tasks, { platform: 'linux', execFileSync: () => '12 1 32 01:30 S\n' });
|
|
const r = buildInventory(f, { now, resources });
|
|
assert.equal(r.tasks[0].process.state, 'observed'); assert.equal(r.tasks[1].process.state, 'not-observed');
|
|
});
|
|
test('task file adapter reads structured status, labels mtime, skips symlinks and rejects oversized JSON', () => {
|
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'coordination-test-'));
|
|
try {
|
|
fs.mkdirSync(path.join(dir, 'worker')); fs.writeFileSync(path.join(dir, 'worker', 'STATUS.md'), '- State: running\n- Updated: 2026-09-08T06:29:00Z\n');
|
|
fs.symlinkSync(path.join(dir, 'worker'), path.join(dir, 'linked'));
|
|
const r = collectTaskFiles(dir); assert.equal(r.tasks.length, 1); assert.equal(r.tasks[0].status, 'running');
|
|
assert.ok(r.tasks[0].statusFileModifiedAt); assert.equal(r.tasks[0].heartbeatAt, '2026-09-08T06:29:00Z');
|
|
fs.writeFileSync(path.join(dir, 'large.json'), ' '.repeat(1024 * 1024 + 1));
|
|
assert.throws(() => readJson(path.join(dir, 'large.json')), /limit/);
|
|
assert.equal(collectTaskFiles(path.join(dir, 'missing')).status, 'unavailable');
|
|
} finally { fs.rmSync(dir, { recursive: true, force: true }); }
|
|
});
|
|
test('CLI JSON end to end, no output file changes and safe errors', () => {
|
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'coordination-cli-'));
|
|
const cli = path.resolve(__dirname, '../../scripts/coordination-inventory.js');
|
|
try {
|
|
const file = path.join(dir,'input.json'); fs.writeFileSync(file, JSON.stringify(fixture()));
|
|
const r = spawnSync(process.execPath, [cli, '--manifest', file, '--now', now], { encoding:'utf8' });
|
|
assert.equal(r.status,0,r.stderr); assert.equal(JSON.parse(r.stdout).warnings.length,1);
|
|
assert.deepEqual(fs.readdirSync(dir),['input.json']);
|
|
const bad = spawnSync(process.execPath,[cli,'--unknown','CANARY_SECRET'],{encoding:'utf8'});
|
|
assert.equal(bad.status,1); assert.ok(!bad.stderr.includes('CANARY_SECRET'));
|
|
const help = spawnSync(process.execPath,[cli,'--help'],{encoding:'utf8'}); assert.equal(help.status,0);
|
|
} finally { fs.rmSync(dir,{recursive:true,force:true}); }
|
|
});
|
|
|
|
test('prototype-named paths and strict calendar dates are safe', () => {
|
|
const f = fixture(); f.repositories[0].sources = {}; f.tasks[0].paths = ['toString']; f.tasks[1].paths = ['valueOf'];
|
|
assert.equal(run(f).warnings.length, 0);
|
|
for (const invalid of ['2026-02-30T00:00:00Z', '2026-09-08T24:00:00Z']) {
|
|
f.tasks[0].heartbeatAt = invalid; assert.throws(() => run(f), /Invalid/);
|
|
}
|
|
f.tasks[0].heartbeatAt = '2026-09-08T06:00:00.1Z'; assert.equal(run(f).tasks[0].heartbeat.state, 'stale');
|
|
});
|
|
test('aggregate comparison budget rejects compact but computationally excessive input', () => {
|
|
const f = fixture(); f.repositories[0].sources = {};
|
|
f.tasks = Array.from({length:64}, (_,i) => task(`task${i}`, Array.from({length:128}, (_,j) => `src/${i}/${j}.js`)));
|
|
assert.throws(() => run(f), /budget/);
|
|
});
|
|
test('CLI discovery composes normalized tasks and reports missing telemetry honestly', () => {
|
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'coordination-discovery-'));
|
|
try {
|
|
fs.mkdirSync(path.join(dir,'worker')); fs.writeFileSync(path.join(dir,'worker','STATUS.md'),'Freeform progress.\n');
|
|
const r = spawnSync(process.execPath,[path.resolve(__dirname,'../../scripts/coordination-inventory.js'),'--coordination',dir,'--now',now],{encoding:'utf8'});
|
|
assert.equal(r.status,0,r.stderr); const report=JSON.parse(r.stdout);
|
|
assert.equal(report.tasks[0].status,'unknown'); assert.equal(report.tasks[0].heartbeat.state,'unknown');
|
|
assert.ok(report.tasks[0].statusFileModifiedAt); assert.equal(report.tasks[0].process.state,'unknown');
|
|
} finally { fs.rmSync(dir,{recursive:true,force:true}); }
|
|
});
|
|
test('source snippets are bounded before invoking inherited regex extractor', () => {
|
|
const f = fixture(); f.repositories[0].sources = { 'a.js': `import ${' '.repeat(32000)}x` }; f.tasks=[];
|
|
assert.throws(() => run(f), /Invalid/);
|
|
f.repositories[0].sources = Object.fromEntries(Array.from({length:33},(_,i) => [`${i}.js`, ' '.repeat(1024)]));
|
|
assert.throws(() => run(f), /Invalid/);
|
|
});
|
|
test('maximum accepted whitespace snippets complete within bounded subprocess timeout', () => {
|
|
const code = `const {buildInventory}=require('./scripts/lib/coordination-inventory');
|
|
const source='import '+' '.repeat(1016)+'x';
|
|
const sources=Object.fromEntries(Array.from({length:32},(_,i)=>[i+'.js',source]));
|
|
const r=buildInventory({version:1,repositories:[{id:'r',sources}],tasks:[{id:'a',repoId:'r',paths:['0.js']},{id:'b',repoId:'r',paths:['1.js']}]});
|
|
if(r.warnings.length) process.exitCode=1;`;
|
|
const r=spawnSync(process.execPath,['-e',code],{cwd:path.resolve(__dirname,'../..'),encoding:'utf8',timeout:2000});
|
|
assert.equal(r.status,0,r.error?.message || r.stderr);
|
|
});
|
|
test('bounded import parsing preserves supported JS and TS import forms', () => {
|
|
const { buildDependencyGraphFromSources } = require('../../scripts/lib/agent-proximity/graph');
|
|
for (const source of ["import './b'", "import b from './b'", "import { b as c } from './b'", "import * as b from './b'", "import b, { c } from './b'", "import type { B } from './b'", "import {\n b\n} from './b'", "import('./b')"]) {
|
|
assert.deepEqual(buildDependencyGraphFromSources({'a.js':source,'b.js':''}).adjacency['a.js'],['b.js']);
|
|
}
|
|
});
|