Files
Dragan Spiridonov 20b098697e fix: add regression tests for march-fixes branch and fix 4 flaky tests
Move @ruvector/tiny-dancer-linux-arm64-gnu from dependencies to
optionalDependencies to prevent npm install failures on non-ARM64.

Add 26 regression tests across 5 files covering untested new paths:
- task-executor coherence gate & reasoning QEC advisory paths
- aqe-learning-engine witness chain & domain transfer wiring
- experience-capture witnessHash & setWitnessChain integration
- pattern-store filter-adapter module resolution & search compat
- metrics-tracker getDashboardDataWithRegret method

Fix 4 flaky tests failing under full-suite contention by resetting
shared singletons (queenGovernanceAdapter, sharedMinCutGraph,
UnifiedPersistence) in beforeEach/afterEach to prevent cross-test
state contamination.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 17:35:41 +00:00

355 lines
11 KiB
TypeScript

/**
* Agentic QE v3 - CLI Tests
* Tests for the command line interface
*/
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { QEKernelImpl } from '../../../src/kernel/kernel';
import { QueenCoordinator, createQueenCoordinator } from '../../../src/coordination/queen-coordinator';
import { CrossDomainEventRouter } from '../../../src/coordination/cross-domain-router';
import { DefaultProtocolExecutor } from '../../../src/coordination/protocol-executor';
import { WorkflowOrchestrator } from '../../../src/coordination/workflow-orchestrator';
import { DomainName, ALL_DOMAINS } from '../../../src/shared/types';
import { resetUnifiedPersistence } from '../../../src/kernel/unified-persistence';
import { queenGovernanceAdapter } from '../../../src/governance/queen-governance-adapter';
import { resetSharedMinCutState } from '../../../src/coordination/mincut/shared-singleton';
describe('CLI Components', () => {
let kernel: QEKernelImpl;
let router: CrossDomainEventRouter;
let queen: QueenCoordinator;
beforeEach(async () => {
// Reset shared singletons to prevent cross-test contamination
resetUnifiedPersistence();
queenGovernanceAdapter.reset();
resetSharedMinCutState();
kernel = new QEKernelImpl({
maxConcurrentAgents: 5,
memoryBackend: 'hybrid',
hnswEnabled: false,
lazyLoading: true,
enabledDomains: [...ALL_DOMAINS],
});
await kernel.initialize();
router = new CrossDomainEventRouter(kernel.eventBus);
await router.initialize();
const getDomainAPI = <T>(domain: DomainName): T | undefined => {
return kernel.getDomainAPI<T>(domain);
};
const protocolExecutor = new DefaultProtocolExecutor(
kernel.eventBus,
kernel.memory,
getDomainAPI
);
queen = createQueenCoordinator(
kernel,
router,
protocolExecutor,
undefined
);
await queen.initialize();
});
afterEach(async () => {
await queen.dispose();
await router.dispose();
await kernel.dispose();
// Clean up singletons
resetUnifiedPersistence();
queenGovernanceAdapter.reset();
resetSharedMinCutState();
});
describe('Kernel Initialization', () => {
it('should initialize kernel with configuration', () => {
const health = kernel.getHealth();
expect(health.status).toBeDefined();
expect(health.agents.maxAllowed).toBe(5);
});
it('should provide domain API access', () => {
// Lazy loading means API might not be available immediately
// This tests the mechanism exists
const api = kernel.getDomainAPI('test-generation');
// May be undefined due to lazy loading
expect(api === undefined || api !== null).toBe(true);
});
});
describe('Router Initialization', () => {
it('should initialize cross-domain router', async () => {
// Router is initialized if we reach this point without error
// The router exposes event handling methods
const history = router.getHistory({ limit: 1 });
expect(Array.isArray(history)).toBe(true);
});
});
describe('Queen Coordinator Integration', () => {
it('should initialize queen coordinator', async () => {
const health = queen.getHealth();
expect(['healthy', 'degraded']).toContain(health.status);
expect(health.totalAgents).toBeGreaterThanOrEqual(0);
});
it('should accept task submission', async () => {
const result = await queen.submitTask({
type: 'generate-tests',
priority: 'p1',
targetDomains: [],
payload: { source: 'test.ts' },
timeout: 30000,
});
expect(result.success).toBe(true);
if (result.success) {
expect(result.value).toBeDefined();
}
});
it('should list tasks', () => {
const tasks = queen.listTasks({});
expect(Array.isArray(tasks)).toBe(true);
});
it('should provide domain health', () => {
const health = queen.getDomainHealth('test-generation');
expect(health).toBeDefined();
expect(health?.status).toBeDefined();
});
it('should provide domain load', () => {
const load = queen.getDomainLoad('test-generation');
expect(typeof load).toBe('number');
expect(load).toBeGreaterThanOrEqual(0);
});
it('should provide metrics', () => {
const metrics = queen.getMetrics();
expect(metrics.tasksReceived).toBeGreaterThanOrEqual(0);
expect(metrics.uptime).toBeGreaterThanOrEqual(0);
});
});
describe('Task Types', () => {
const taskTypes = [
'generate-tests',
'execute-tests',
'analyze-coverage',
'assess-quality',
'predict-defects',
'validate-requirements',
'index-code',
'scan-security',
'validate-contracts',
'test-accessibility',
'run-chaos',
'optimize-learning',
] as const;
it.each(taskTypes)('should accept %s task type', async (taskType) => {
const result = await queen.submitTask({
type: taskType,
priority: 'p2',
targetDomains: [],
payload: {},
timeout: 10000,
});
expect(result.success).toBe(true);
});
});
describe('Priority Handling', () => {
it('should accept all priority levels', async () => {
const priorities = ['p0', 'p1', 'p2', 'p3'] as const;
for (const priority of priorities) {
const result = await queen.submitTask({
type: 'generate-tests',
priority,
targetDomains: [],
payload: {},
timeout: 10000,
});
expect(result.success).toBe(true);
}
});
});
describe('Agent Management', () => {
it('should list all agents', () => {
const agents = queen.listAllAgents();
expect(Array.isArray(agents)).toBe(true);
});
it('should get agents by domain', () => {
const agents = queen.getAgentsByDomain('test-generation');
expect(Array.isArray(agents)).toBe(true);
});
it('should request agent spawn', async () => {
const result = await queen.requestAgentSpawn(
'test-generation',
'worker',
['unit-test']
);
expect(result.success).toBe(true);
});
});
describe('Protocol Execution', () => {
it('should attempt protocol execution', async () => {
// Protocol may not exist, but mechanism should work
const result = await queen.executeProtocol('non-existent-protocol', {});
// Expected to fail as protocol doesn't exist
expect(result.success).toBe(false);
});
});
describe('Cleanup', () => {
it('should dispose cleanly', async () => {
// Create fresh instances for disposal test
const testKernel = new QEKernelImpl({
maxConcurrentAgents: 3,
lazyLoading: true,
});
await testKernel.initialize();
const testRouter = new CrossDomainEventRouter(testKernel.eventBus);
await testRouter.initialize();
const getDomainAPI = <T>(domain: DomainName): T | undefined => {
return testKernel.getDomainAPI<T>(domain);
};
const testProtocolExecutor = new DefaultProtocolExecutor(
testKernel.eventBus,
testKernel.memory,
getDomainAPI
);
const testQueen = createQueenCoordinator(
testKernel,
testRouter,
testProtocolExecutor,
undefined
);
await testQueen.initialize();
// Dispose in order
await testQueen.dispose();
await testRouter.dispose();
await testKernel.dispose();
// Verify clean state after disposal
expect(true).toBe(true);
});
});
});
describe('CLI Command Patterns', () => {
describe('Command Structure', () => {
it('should have init command requirements', () => {
// Test validates that init command accepts expected options
const initOptions = {
domains: 'all',
maxAgents: '15',
memory: 'hybrid',
lazy: false,
};
expect(initOptions.domains).toBe('all');
expect(parseInt(initOptions.maxAgents, 10)).toBe(15);
expect(initOptions.memory).toBe('hybrid');
expect(initOptions.lazy).toBe(false);
});
it('should have task command structure', () => {
// Test validates task command structure
const taskOptions = {
type: 'generate-tests',
priority: 'p1',
domain: 'test-generation',
timeout: '300000',
payload: '{}',
};
expect(taskOptions.type).toBeDefined();
expect(['p0', 'p1', 'p2', 'p3']).toContain(taskOptions.priority);
expect(parseInt(taskOptions.timeout, 10)).toBeGreaterThan(0);
expect(JSON.parse(taskOptions.payload)).toEqual({});
});
it('should have agent command structure', () => {
const agentOptions = {
domain: 'test-generation',
type: 'worker',
capabilities: 'unit-test,integration-test',
};
expect(ALL_DOMAINS).toContain(agentOptions.domain);
expect(agentOptions.type).toBe('worker');
expect(agentOptions.capabilities.split(',')).toHaveLength(2);
});
});
describe('Output Formatting', () => {
it('should format status correctly', () => {
const formatStatus = (status: string): string => {
switch (status) {
case 'healthy':
case 'completed':
return 'green';
case 'degraded':
case 'running':
return 'yellow';
case 'unhealthy':
case 'failed':
return 'red';
default:
return 'gray';
}
};
expect(formatStatus('healthy')).toBe('green');
expect(formatStatus('degraded')).toBe('yellow');
expect(formatStatus('unhealthy')).toBe('red');
expect(formatStatus('unknown')).toBe('gray');
});
it('should format duration correctly', () => {
const formatDuration = (ms: number): string => {
if (ms < 1000) return `${ms}ms`;
if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;
if (ms < 3600000) return `${(ms / 60000).toFixed(1)}m`;
return `${(ms / 3600000).toFixed(1)}h`;
};
expect(formatDuration(500)).toBe('500ms');
expect(formatDuration(5000)).toBe('5.0s');
expect(formatDuration(120000)).toBe('2.0m');
expect(formatDuration(7200000)).toBe('2.0h');
});
it('should format uptime correctly', () => {
const formatUptime = (ms: number): string => {
const hours = Math.floor(ms / 3600000);
const minutes = Math.floor((ms % 3600000) / 60000);
const seconds = Math.floor((ms % 60000) / 1000);
return `${hours}h ${minutes}m ${seconds}s`;
};
expect(formatUptime(3661000)).toBe('1h 1m 1s');
expect(formatUptime(0)).toBe('0h 0m 0s');
});
});
});