Files
proffesor-for-testing__agen…/tests/integration/fleet-commander-integration.test.ts
Profa 5a2883a4a0 chore: Initial release v1.0.0
Agentic Quality Engineering Fleet - AI-driven quality management platform

Features:
- 16 specialized QE agents for comprehensive testing
- AI-powered test generation with 95% coverage targets
- O(log n) sublinear algorithms for massive scale
- Parallel test execution with intelligent orchestration
- Real-time coverage analysis and gap detection
- Smart quality gates with ML-driven decisions
- Security scanning (SAST, DAST, dependency analysis)
- Performance testing with load orchestration
- Flaky test detection with automatic stabilization
- API contract validation with breaking change detection
- Test data generation (10,000+ records/sec)
- Production intelligence (convert incidents to tests)
- Chaos engineering for resilience testing
- MCP integration with Claude Code
- Multi-framework support (Jest, Mocha, Cypress, Playwright)

Architecture:
- TypeScript implementation
- MCP (Model Context Protocol) integration
- Claude Code agent orchestration
- Event-driven agent coordination
- Distributed fleet management
- Cross-session memory persistence

Documentation:
- Complete API documentation (TypeDoc)
- User guides (Getting Started, MCP Integration, Test Generation, etc.)
- Architecture deep-dive
- CLI reference
- Contributing guidelines
- MIT License

Tech Stack:
- TypeScript 5.3+
- Node.js 18+
- @anthropic-ai/sdk ^0.64.0
- @modelcontextprotocol/sdk ^1.18.2
- Jest for testing
- Winston for logging
- SQLite for persistence

Project Structure:
- src/ - Source code (agents, core, MCP, CLI)
- tests/ - Comprehensive test suite
- docs/ - Complete documentation
- .claude/ - Agent definitions and commands
- config/ - Configuration files

🤖 Generated with Claude Code
https://claude.com/claude-code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-30 19:59:56 +00:00

654 lines
20 KiB
TypeScript

/**
* FleetCommanderAgent Integration Tests
* Tests memory coordination, agent lifecycle, resource allocation, and topology management
*/
import { EventEmitter } from 'events';
import { MemoryManager } from '../../src/core/MemoryManager';
import { EventBus } from '../../src/core/EventBus';
import { Database } from '../../src/utils/Database';
import { Logger } from '../../src/utils/Logger';
// Mock external dependencies
jest.mock('../../src/utils/Database');
jest.mock('../../src/utils/Logger');
describe('FleetCommanderAgent Integration', () => {
let eventBus: EventBus;
let memoryManager: MemoryManager;
let mockDatabase: jest.Mocked<Database>;
let mockLogger: jest.Mocked<Logger>;
const fleetConfig = {
topology: 'hierarchical',
maxAgents: 50,
agentPools: {
'test-generator': { min: 2, max: 10, priority: 'high' },
'test-executor': { min: 3, max: 15, priority: 'critical' },
'coverage-analyzer': { min: 1, max: 5, priority: 'high' },
'quality-gate': { min: 1, max: 3, priority: 'medium' }
},
resourceLimits: {
cpuPerAgent: 0.5,
memoryPerAgent: '512MB',
maxConcurrent: 20
}
};
beforeEach(async () => {
jest.clearAllMocks();
// Mock Database
mockDatabase = {
initialize: jest.fn().mockResolvedValue(undefined),
close: jest.fn().mockResolvedValue(undefined),
run: jest.fn().mockResolvedValue({ lastID: 1, changes: 1 }),
get: jest.fn().mockResolvedValue(null),
all: jest.fn().mockResolvedValue([])
} as any;
// Mock Logger
mockLogger = {
info: jest.fn(),
warn: jest.fn(),
error: jest.fn(),
debug: jest.fn(),
getInstance: jest.fn().mockReturnValue(mockLogger)
} as any;
(Database as jest.Mock).mockImplementation(() => mockDatabase);
(Logger.getInstance as jest.Mock).mockReturnValue(mockLogger);
// Create real EventBus and MemoryManager
eventBus = new EventBus();
await eventBus.initialize();
memoryManager = new MemoryManager(mockDatabase);
await memoryManager.initialize();
});
afterEach(async () => {
if (eventBus) {
eventBus.removeAllListeners();
}
jest.restoreAllMocks();
jest.clearAllMocks();
if (global.gc) {
global.gc();
}
});
describe('Memory Coordination (aqe/fleet/*)', () => {
it('should store fleet topology in aqe/fleet/topology namespace', async () => {
const topology = {
type: fleetConfig.topology,
maxAgents: fleetConfig.maxAgents,
currentAgents: 8,
structure: {
commander: 'fleet-commander-1',
coordinators: ['coordinator-1', 'coordinator-2'],
workers: ['agent-1', 'agent-2', 'agent-3', 'agent-4', 'agent-5']
},
timestamp: Date.now()
};
await memoryManager.store('current', topology, {
namespace: 'aqe/fleet/topology',
persist: true
});
const retrieved = await memoryManager.retrieve('current', {
namespace: 'aqe/fleet/topology'
});
expect(retrieved).toBeDefined();
expect(retrieved.value.type).toBe('hierarchical');
expect(retrieved.value.currentAgents).toBe(8);
expect(retrieved.value.structure.workers).toHaveLength(5);
});
it('should store active agents in aqe/fleet/agents/active namespace', async () => {
const activeAgents = [
{
id: 'agent-1',
type: 'test-generator',
status: 'active',
resources: { cpu: 0.3, memory: '256MB' },
tasksCompleted: 45,
uptime: 3600000
},
{
id: 'agent-2',
type: 'test-executor',
status: 'active',
resources: { cpu: 0.5, memory: '512MB' },
tasksCompleted: 123,
uptime: 3600000
},
{
id: 'agent-3',
type: 'coverage-analyzer',
status: 'active',
resources: { cpu: 0.2, memory: '128MB' },
tasksCompleted: 23,
uptime: 1800000
}
];
await memoryManager.store('list', activeAgents, {
namespace: 'aqe/fleet/agents/active'
});
const retrieved = await memoryManager.retrieve('list', {
namespace: 'aqe/fleet/agents/active'
});
expect(retrieved).toBeDefined();
expect(retrieved.value).toHaveLength(3);
expect(retrieved.value[0].type).toBe('test-generator');
expect(retrieved.value[1].tasksCompleted).toBe(123);
});
it('should store coordination results in aqe/fleet/coordination/results namespace', async () => {
const coordinationResults = {
taskId: 'coord-task-001',
coordinator: 'fleet-commander-1',
agents: ['agent-1', 'agent-2', 'agent-3'],
action: 'load-balancing',
result: 'success',
metrics: {
duration: 234,
agentsRebalanced: 3,
tasksRedistributed: 12,
cpuUtilization: 0.65,
memoryUtilization: 0.72
},
timestamp: Date.now()
};
await memoryManager.store('coord-task-001', coordinationResults, {
namespace: 'aqe/fleet/coordination/results'
});
const retrieved = await memoryManager.retrieve('coord-task-001', {
namespace: 'aqe/fleet/coordination/results'
});
expect(retrieved).toBeDefined();
expect(retrieved.value.result).toBe('success');
expect(retrieved.value.metrics.agentsRebalanced).toBe(3);
});
it('should store fleet performance metrics in aqe/fleet/metrics/performance namespace', async () => {
const performanceMetrics = {
period: '2025-09-29T14:00:00Z',
fleet: {
totalAgents: 12,
activeAgents: 10,
idleAgents: 2,
erroredAgents: 0
},
resources: {
totalCpu: 0.65,
totalMemory: 4.2,
peakCpu: 0.87,
peakMemory: 5.6
},
throughput: {
tasksCompleted: 456,
tasksPerMinute: 7.6,
avgTaskDuration: 2340
},
efficiency: {
resourceUtilization: 0.72,
taskDistributionBalance: 0.89,
agentIdleTime: 0.15
},
timestamp: Date.now()
};
await memoryManager.store('current', performanceMetrics, {
namespace: 'aqe/fleet/metrics/performance',
ttl: 3600000
});
const retrieved = await memoryManager.retrieve('current', {
namespace: 'aqe/fleet/metrics/performance'
});
expect(retrieved).toBeDefined();
expect(retrieved.value.fleet.activeAgents).toBe(10);
expect(retrieved.value.efficiency.resourceUtilization).toBe(0.72);
});
});
describe('Hook Execution', () => {
it('should execute pre-task hook and retrieve fleet topology', async () => {
// Setup: Store current topology
const topology = {
type: 'hierarchical',
agents: ['agent-1', 'agent-2']
};
await memoryManager.store('topology', topology, {
namespace: 'aqe/fleet'
});
// Pre-task: Retrieve topology
const retrieved = await memoryManager.retrieve('topology', {
namespace: 'aqe/fleet'
});
expect(retrieved).toBeDefined();
expect(retrieved.value.type).toBe('hierarchical');
expect(retrieved.value.agents).toHaveLength(2);
});
it('should execute post-task hook and store coordination results', async () => {
const taskId = 'task-spawn-agents';
const results = {
agentsSpawned: 5,
agentTypes: ['test-generator', 'test-executor'],
duration: 1234
};
await memoryManager.store('coordination-results', results, {
namespace: 'aqe/fleet',
metadata: { taskId, completedAt: new Date().toISOString() }
});
const stored = await memoryManager.retrieve('coordination-results', {
namespace: 'aqe/fleet'
});
expect(stored).toBeDefined();
expect(stored.value.agentsSpawned).toBe(5);
expect(stored.metadata?.taskId).toBe(taskId);
});
it('should execute post-edit hook when fleet config is updated', async () => {
const filePath = '/config/fleet.yml';
const updatedConfig = {
...fleetConfig,
maxAgents: 75, // Increased
lastModified: new Date().toISOString()
};
await memoryManager.store('fleet-config', updatedConfig, {
namespace: 'aqe/fleet/config',
metadata: { filePath, action: 'edit' }
});
const updated = await memoryManager.retrieve('fleet-config', {
namespace: 'aqe/fleet/config'
});
expect(updated).toBeDefined();
expect(updated.value.maxAgents).toBe(75);
expect(updated.metadata?.filePath).toBe(filePath);
});
});
describe('Agent Spawning and Lifecycle', () => {
it('should spawn agents dynamically based on workload', async () => {
const workload = {
testSuiteSize: 1500,
frameworks: ['jest', 'cypress'],
estimatedDuration: 3600000
};
// Calculate optimal agent distribution
const allocation = {
'test-generator': 5,
'test-executor': 8,
'coverage-analyzer': 2
};
// Simulate spawning agents
const spawnedAgents = Object.entries(allocation).flatMap(([type, count]) =>
Array.from({ length: count }, (_, i) => ({
id: `${type}-${i}`,
type,
status: 'spawning',
spawnedAt: Date.now()
}))
);
await memoryManager.store('spawned', spawnedAgents, {
namespace: 'aqe/fleet/agents'
});
const retrieved = await memoryManager.retrieve('spawned', {
namespace: 'aqe/fleet/agents'
});
expect(retrieved).toBeDefined();
expect(retrieved.value).toHaveLength(15); // 5 + 8 + 2
expect(retrieved.value.filter((a: any) => a.type === 'test-executor')).toHaveLength(8);
});
it('should despawn idle agents to optimize resources', async () => {
const agents = [
{ id: 'agent-1', type: 'test-generator', status: 'active', idleTime: 60000 },
{ id: 'agent-2', type: 'test-generator', status: 'active', idleTime: 600000 }, // 10 min idle
{ id: 'agent-3', type: 'test-executor', status: 'active', idleTime: 30000 }
];
// Identify idle agents (idle > 5 minutes)
const idleThreshold = 300000;
const agentsToDespawn = agents.filter(a => a.idleTime > idleThreshold);
await memoryManager.store('despawn-queue', agentsToDespawn, {
namespace: 'aqe/fleet/agents'
});
const retrieved = await memoryManager.retrieve('despawn-queue', {
namespace: 'aqe/fleet/agents'
});
expect(retrieved).toBeDefined();
expect(retrieved.value).toHaveLength(1);
expect(retrieved.value[0].id).toBe('agent-2');
});
it('should monitor agent health and trigger recovery', async () => {
const healthChecks = [
{ id: 'agent-1', status: 'healthy', responseTime: 45 },
{ id: 'agent-2', status: 'unhealthy', responseTime: 5000, error: 'timeout' },
{ id: 'agent-3', status: 'healthy', responseTime: 67 }
];
const unhealthyAgents = healthChecks.filter(h => h.status === 'unhealthy');
await memoryManager.store('health-report', {
healthy: healthChecks.filter(h => h.status === 'healthy').length,
unhealthy: unhealthyAgents.length,
unhealthyAgents,
timestamp: Date.now()
}, {
namespace: 'aqe/fleet/health'
});
const retrieved = await memoryManager.retrieve('health-report', {
namespace: 'aqe/fleet/health'
});
expect(retrieved).toBeDefined();
expect(retrieved.value.unhealthy).toBe(1);
expect(retrieved.value.unhealthyAgents[0].id).toBe('agent-2');
});
});
describe('Resource Allocation', () => {
it('should allocate CPU and memory resources optimally', async () => {
const totalResources = {
cpu: 8.0, // 8 cores
memory: 16384 // 16GB in MB
};
const agents = [
{ id: 'agent-1', type: 'test-executor', priority: 'critical', cpuRequest: 1.0, memoryRequest: 1024 },
{ id: 'agent-2', type: 'test-generator', priority: 'high', cpuRequest: 0.5, memoryRequest: 512 },
{ id: 'agent-3', type: 'coverage-analyzer', priority: 'medium', cpuRequest: 0.3, memoryRequest: 256 }
];
// Calculate allocation
const allocation = agents.map(agent => ({
...agent,
cpuAllocated: agent.cpuRequest,
memoryAllocated: agent.memoryRequest,
status: 'allocated'
}));
const utilization = {
cpu: allocation.reduce((sum, a) => sum + a.cpuAllocated, 0) / totalResources.cpu,
memory: allocation.reduce((sum, a) => sum + a.memoryAllocated, 0) / totalResources.memory
};
await memoryManager.store('resource-allocation', {
allocation,
utilization,
timestamp: Date.now()
}, {
namespace: 'aqe/fleet/resources'
});
const retrieved = await memoryManager.retrieve('resource-allocation', {
namespace: 'aqe/fleet/resources'
});
expect(retrieved).toBeDefined();
expect(retrieved.value.allocation).toHaveLength(3);
expect(retrieved.value.utilization.cpu).toBeLessThan(1.0);
expect(retrieved.value.utilization.memory).toBeLessThan(1.0);
});
it('should handle resource conflicts and prioritize critical agents', async () => {
const resourceRequest = {
agentId: 'agent-critical-1',
type: 'test-executor',
priority: 'critical',
cpuRequest: 2.0,
memoryRequest: 2048
};
const availableResources = {
cpu: 1.5, // Not enough!
memory: 3000
};
// Conflict resolution: Can we free resources?
const lowPriorityAgents = [
{ id: 'agent-low-1', priority: 'low', cpu: 0.5, memory: 512 },
{ id: 'agent-low-2', priority: 'low', cpu: 0.3, memory: 256 }
];
const canFreeResources = lowPriorityAgents.reduce((sum, a) => sum + a.cpu, 0) >= (resourceRequest.cpuRequest - availableResources.cpu);
await memoryManager.store('resource-conflict', {
request: resourceRequest,
available: availableResources,
conflict: true,
resolution: canFreeResources ? 'despawn-low-priority' : 'queue-request',
agentsToDespawn: canFreeResources ? lowPriorityAgents : [],
timestamp: Date.now()
}, {
namespace: 'aqe/fleet/resources'
});
const retrieved = await memoryManager.retrieve('resource-conflict', {
namespace: 'aqe/fleet/resources'
});
expect(retrieved).toBeDefined();
expect(retrieved.value.conflict).toBe(true);
expect(retrieved.value.resolution).toBe('despawn-low-priority');
});
});
describe('Topology Switching', () => {
it('should switch from hierarchical to mesh topology', async () => {
const currentTopology = 'hierarchical';
const newTopology = 'mesh';
const topologySwitch = {
from: currentTopology,
to: newTopology,
reason: 'High inter-agent communication detected',
steps: [
'Pause new task assignment',
'Complete running tasks',
'Reconfigure event bus for mesh',
'Update agent connections',
'Resume task assignment'
],
estimatedDowntime: 30000, // 30 seconds
timestamp: Date.now()
};
await memoryManager.store('topology-switch', topologySwitch, {
namespace: 'aqe/fleet/topology'
});
const retrieved = await memoryManager.retrieve('topology-switch', {
namespace: 'aqe/fleet/topology'
});
expect(retrieved).toBeDefined();
expect(retrieved.value.from).toBe('hierarchical');
expect(retrieved.value.to).toBe('mesh');
expect(retrieved.value.steps).toHaveLength(5);
});
it('should use adaptive topology based on workload patterns', async () => {
const workloadAnalysis = {
taskTypes: {
'unit-test': 45,
'integration-test': 30,
'e2e-test': 15,
'coverage-analysis': 10
},
communicationPattern: 'high-interdependency', // Many agents need to coordinate
optimalTopology: 'mesh', // Better for high communication
confidence: 0.87,
timestamp: Date.now()
};
await memoryManager.store('workload-analysis', workloadAnalysis, {
namespace: 'aqe/fleet/topology'
});
const retrieved = await memoryManager.retrieve('workload-analysis', {
namespace: 'aqe/fleet/topology'
});
expect(retrieved).toBeDefined();
expect(retrieved.value.optimalTopology).toBe('mesh');
expect(retrieved.value.communicationPattern).toBe('high-interdependency');
});
});
describe('Event Bus Communication', () => {
it('should emit fleet.agent.spawned event', async () => {
let eventReceived = false;
const eventPromise = new Promise<void>((resolve) => {
eventBus.once('fleet.agent.spawned', (event) => {
eventReceived = true;
expect(event.data.agentId).toBe('agent-new-1');
expect(event.data.type).toBe('test-generator');
resolve();
});
});
await eventBus.emitFleetEvent(
'fleet.agent.spawned',
'fleet-commander',
{
agentId: 'agent-new-1',
type: 'test-generator',
resources: { cpu: 0.5, memory: '512MB' }
}
);
await Promise.race([
eventPromise,
new Promise((_, reject) => setTimeout(() => reject(new Error('Event timeout')), 500))
]);
expect(eventReceived).toBe(true);
});
it('should emit fleet.topology.changed event', async () => {
let eventReceived = false;
const eventPromise = new Promise<void>((resolve) => {
eventBus.once('fleet.topology.changed', (event) => {
eventReceived = true;
expect(event.data.from).toBe('hierarchical');
expect(event.data.to).toBe('mesh');
resolve();
});
});
await eventBus.emitFleetEvent(
'fleet.topology.changed',
'fleet-commander',
{
from: 'hierarchical',
to: 'mesh',
reason: 'workload-optimization'
}
);
await Promise.race([
eventPromise,
new Promise((_, reject) => setTimeout(() => reject(new Error('Event timeout')), 500))
]);
expect(eventReceived).toBe(true);
});
it('should emit fleet.resource.conflict event', async () => {
let eventReceived = false;
const eventPromise = new Promise<void>((resolve) => {
eventBus.once('fleet.resource.conflict', (event) => {
eventReceived = true;
expect(event.data.conflict).toBe('cpu-exhausted');
expect(event.data.resolution).toBe('despawn-idle-agents');
resolve();
});
});
await eventBus.emitFleetEvent(
'fleet.resource.conflict',
'fleet-commander',
{
conflict: 'cpu-exhausted',
requested: 2.0,
available: 0.5,
resolution: 'despawn-idle-agents'
}
);
await Promise.race([
eventPromise,
new Promise((_, reject) => setTimeout(() => reject(new Error('Event timeout')), 500))
]);
expect(eventReceived).toBe(true);
});
it('should coordinate with other agents via events', async () => {
const coordination: string[] = [];
eventBus.on('fleet.coordination', (event) => {
coordination.push(event.data.action);
});
// Spawn agents
await eventBus.emitFleetEvent('fleet.coordination', 'fleet-commander', {
action: 'spawn-agents',
count: 5
});
// Allocate resources
await eventBus.emitFleetEvent('fleet.coordination', 'fleet-commander', {
action: 'allocate-resources'
});
// Start tasks
await eventBus.emitFleetEvent('fleet.coordination', 'fleet-commander', {
action: 'distribute-tasks'
});
await new Promise(resolve => setTimeout(resolve, 100));
expect(coordination).toContain('spawn-agents');
expect(coordination).toContain('allocate-resources');
expect(coordination).toContain('distribute-tasks');
});
});
});