UNPKG

claude-flow

Version:

Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration

1,332 lines (1,231 loc) 39.8 kB
/** * Agentic-QE Plugin Implementation * Main plugin class implementing PluginInterface with lifecycle methods * * @module v3/plugins/agentic-qe/plugin * @version 3.2.3 */ // Bridge interfaces are available but not directly used in this scaffold // They will be used by the full implementation import type { QEPluginContext } from './interfaces.js'; import type { AQEPluginConfig, BoundedContext, ContextMapping, ModelTier, QEMemoryNamespace, SecurityLevel, V3Domain, } from './types.js'; import { PluginConfigSchema, parseWithDefaults, } from './schemas.js'; // ============================================================================= // Local Interface Definitions (for plugin system integration) // ============================================================================= /** * Plugin interface for V3 plugin system */ interface IPlugin { readonly name: string; readonly version: string; readonly description: string; readonly author: string; readonly capabilities: readonly string[]; register(registry: IPluginRegistry): Promise<void>; initialize(context: IPluginContext): Promise<void>; shutdown(): Promise<void>; getHealth(): Promise<PluginHealthStatus>; } /** * Plugin registry for tool/hook/worker registration */ interface IPluginRegistry { registerTool?(tool: IMCPTool): void; registerHook?(hook: QEHookDefinition): void; registerWorker?(worker: QEWorkerDefinition): void; registerAgent?(agent: QEAgentDefinition): void; registerTools?(tools: IMCPTool[]): void; registerHooks?(hooks: QEHookDefinition[]): void; registerWorkers?(workers: QEWorkerDefinition[]): void; registerAgents?(agents: QEAgentDefinition[]): void; } /** * Plugin context with V3 services */ interface IPluginContext { services: { memory?: unknown; security?: unknown; embeddings?: unknown; modelRouter?: unknown; hiveMind?: unknown; ui?: unknown; }; config: Record<string, unknown>; logger: { debug(message: string, ...args: unknown[]): void; info(message: string, ...args: unknown[]): void; warn(message: string, ...args: unknown[]): void; error(message: string, ...args: unknown[]): void; }; getConfig?(): Record<string, unknown>; set?(key: string, value: unknown): void; getMemoryService?(): { clearNamespace(ns: string): Promise<void>; createNamespace?(config: unknown): Promise<void>; } | null; getSecurityModule?(): { pathValidator: { validate(path: string): Promise<{ valid: boolean; error?: string }> } } | null; getUIService?(): { confirm(message: string): Promise<boolean> } | null; } /** * MCP tool interface */ interface IMCPTool { name: string; description: string; inputSchema: Record<string, unknown>; category?: string; version?: string; handler?: (input: unknown, context: IPluginContext) => Promise<MCPToolResult>; execute?: (input: unknown, context: IPluginContext) => Promise<MCPToolResult>; } /** * MCP tool result */ interface MCPToolResult { content?: Array<{ type: string; text: string }>; success?: boolean; data?: unknown; error?: string; isError?: boolean; } /** * Plugin health status */ interface PluginHealthStatus { healthy: boolean; status?: 'healthy' | 'degraded' | 'unhealthy'; components: Record<string, ComponentHealth>; lastCheck: number; uptime: number; } /** * Component health */ interface ComponentHealth { name: string; healthy: boolean; status?: 'healthy' | 'degraded' | 'unhealthy'; message?: string; lastCheck: number; lastSuccess?: number; } /** * Hook definition */ interface QEHookDefinition { name: string; event: string; priority: 'low' | 'normal' | 'high' | 'critical'; description?: string; handler: string | ((context: IPluginContext, data: unknown) => Promise<void>); } /** * Worker definition */ interface QEWorkerDefinition { name: string; type: string; capabilities?: string[]; maxConcurrent?: number; handler?: (context: IPluginContext, input: unknown) => Promise<unknown>; } /** * Agent definition */ interface QEAgentDefinition { id: string; name?: string; type?: string; context: string | BoundedContext; capabilities: string[]; modelTier?: ModelTier; description?: string; } /** * Context mapper interface */ interface IContextMapper { mapToV3Domain(context: BoundedContext): V3Domain[]; getAgentsForContext(context: BoundedContext): string[]; getMemoryNamespace(context: BoundedContext): string; getSecurityLevel(context: BoundedContext): SecurityLevel; } /** * Security sandbox interface */ interface ISecuritySandbox { execute<T>(fn: () => Promise<T>, options?: SandboxExecutionOptions): Promise<T>; validatePath(path: string): boolean; getResourceUsage(): ResourceUsage; } interface SandboxExecutionOptions { timeout?: number; maxMemory?: number; allowNetwork?: boolean; allowFileSystem?: boolean; allowFileWrite?: boolean; workingDirectory?: string; securityLevel?: SecurityLevel; } interface ResourceUsage { memoryBytes?: number; memoryUsed?: number; cpuMs?: number; cpuTime?: number; networkRequests?: number; fileOperations?: number; activeOperations?: number; } // ============================================================================= // Constants // ============================================================================= const PLUGIN_NAME = 'agentic-qe'; const PLUGIN_VERSION = '3.2.3'; const PLUGIN_DESCRIPTION = 'Quality Engineering plugin with 51 specialized agents across 12 DDD bounded contexts'; const PLUGIN_AUTHOR = 'rUv'; const PLUGIN_CAPABILITIES = [ 'test-generation', 'test-execution', 'coverage-analysis', 'quality-assessment', 'defect-intelligence', 'requirements-validation', 'code-intelligence', 'security-compliance', 'contract-testing', 'visual-accessibility', 'chaos-resilience', 'learning-optimization', ] as const; // ============================================================================= // Context Mapper Implementation // ============================================================================= /** * Maps QE bounded contexts to V3 domains */ class ContextMapper implements IContextMapper { private mappings: Map<BoundedContext, ContextMapping> = new Map(); constructor() { this.initializeMappings(); } private initializeMappings(): void { const mappingData: ContextMapping[] = [ { qeContext: 'test-generation', v3Domains: ['Core', 'Integration'], agents: [ 'unit-test-generator', 'integration-test-generator', 'e2e-test-generator', 'property-test-generator', 'mutation-test-generator', 'fuzz-test-generator', 'api-test-generator', 'performance-test-generator', 'security-test-generator', 'accessibility-test-generator', 'contract-test-generator', 'bdd-test-generator', ], memoryNamespace: 'aqe/v3/test-patterns', securityLevel: 'medium', }, { qeContext: 'test-execution', v3Domains: ['Core', 'Coordination'], agents: [ 'test-runner', 'parallel-executor', 'retry-manager', 'result-aggregator', 'flaky-test-detector', 'timeout-manager', 'resource-allocator', 'test-reporter', ], memoryNamespace: 'aqe/v3/test-execution', securityLevel: 'high', }, { qeContext: 'coverage-analysis', v3Domains: ['Core', 'Memory'], agents: [ 'coverage-collector', 'gap-detector', 'priority-ranker', 'hotspot-analyzer', 'trend-tracker', 'impact-assessor', ], memoryNamespace: 'aqe/v3/coverage-data', securityLevel: 'low', }, { qeContext: 'quality-assessment', v3Domains: ['Core'], agents: [ 'quality-gate-evaluator', 'readiness-assessor', 'risk-calculator', 'metric-aggregator', 'decision-maker', ], memoryNamespace: 'aqe/v3/quality', securityLevel: 'low', }, { qeContext: 'defect-intelligence', v3Domains: ['Core', 'Memory'], agents: [ 'defect-predictor', 'root-cause-analyzer', 'pattern-detector', 'regression-tracker', ], memoryNamespace: 'aqe/v3/defect-patterns', securityLevel: 'low', }, { qeContext: 'requirements-validation', v3Domains: ['Core'], agents: [ 'bdd-validator', 'testability-analyzer', 'requirement-tracer', ], memoryNamespace: 'aqe/v3/requirements', securityLevel: 'low', }, { qeContext: 'code-intelligence', v3Domains: ['Core', 'Memory', 'Integration'], agents: [ 'knowledge-graph-builder', 'semantic-searcher', 'dependency-analyzer', 'complexity-assessor', 'pattern-miner', ], memoryNamespace: 'aqe/v3/code-knowledge', securityLevel: 'medium', }, { qeContext: 'security-compliance', v3Domains: ['Security'], agents: [ 'sast-scanner', 'dast-scanner', 'audit-trail-manager', 'compliance-checker', ], memoryNamespace: 'aqe/v3/security-findings', securityLevel: 'critical', }, { qeContext: 'contract-testing', v3Domains: ['Integration'], agents: [ 'openapi-validator', 'graphql-validator', 'grpc-validator', ], memoryNamespace: 'aqe/v3/contracts', securityLevel: 'medium', }, { qeContext: 'visual-accessibility', v3Domains: ['Integration'], agents: [ 'visual-regression-detector', 'wcag-checker', 'screenshot-differ', ], memoryNamespace: 'aqe/v3/visual-baselines', securityLevel: 'medium', }, { qeContext: 'chaos-resilience', v3Domains: ['Core', 'Coordination'], agents: [ 'chaos-injector', 'load-generator', 'resilience-assessor', 'recovery-validator', ], memoryNamespace: 'aqe/v3/chaos-experiments', securityLevel: 'critical', }, { qeContext: 'learning-optimization', v3Domains: ['Memory', 'Integration'], agents: [ 'cross-domain-learner', 'pattern-optimizer', ], memoryNamespace: 'aqe/v3/learning-trajectories', securityLevel: 'low', }, ]; for (const mapping of mappingData) { this.mappings.set(mapping.qeContext, mapping); } } getMapping(context: BoundedContext): ContextMapping | undefined { return this.mappings.get(context); } mapToV3Domain(context: BoundedContext): V3Domain[] { return this.mappings.get(context)?.v3Domains ?? []; } getV3DomainsForContext(context: BoundedContext): V3Domain[] { return this.mappings.get(context)?.v3Domains ?? []; } getAgentsForContext(context: BoundedContext): string[] { return this.mappings.get(context)?.agents ?? []; } getAllAgents(): string[] { return Array.from(this.mappings.values()).flatMap((m) => m.agents); } getSecurityLevel(context: BoundedContext): SecurityLevel { return this.mappings.get(context)?.securityLevel ?? 'medium'; } getMemoryNamespace(context: BoundedContext): string { return this.mappings.get(context)?.memoryNamespace ?? 'aqe/v3/default'; } } // ============================================================================= // Security Sandbox Implementation // ============================================================================= /** * Security sandbox for executing test code safely */ class SecuritySandbox implements ISecuritySandbox { private config: AQEPluginConfig['sandbox']; private activeOperations = 0; constructor(config: AQEPluginConfig['sandbox']) { this.config = config; } async execute<T>( fn: () => Promise<T>, options: { securityLevel?: SecurityLevel; allowNetwork?: boolean; allowFileWrite?: boolean; timeout?: number; } = {} ): Promise<T> { const timeout = options.timeout ?? this.config?.maxExecutionTime ?? 30000; const level = options.securityLevel ?? 'medium'; // Validate execution is allowed if (!this.checkPolicy('execute', level)) { throw new Error(`Execution not allowed at security level: ${level}`); } this.activeOperations++; try { // Create timeout promise const timeoutPromise = new Promise<never>((_, reject) => { setTimeout( () => reject(new Error(`Execution timeout after ${timeout}ms`)), timeout ); }); // Race execution against timeout return await Promise.race([fn(), timeoutPromise]); } finally { this.activeOperations--; } } checkPolicy(operation: string, level: SecurityLevel): boolean { const levelPriority: Record<SecurityLevel, number> = { low: 1, medium: 2, high: 3, critical: 4, }; // Critical operations require explicit approval if (levelPriority[level] >= 4 && operation === 'execute') { return this.config?.networkPolicy !== 'blocked'; } return true; } validatePath(path: string): boolean { // Check against blocked paths const blockedPaths = this.config?.blockedPaths ?? ['/etc', '/proc', '/sys']; for (const blocked of blockedPaths) { if (path.startsWith(blocked)) { return false; } } return true; } getResourceUsage(): ResourceUsage { return { memoryUsed: process.memoryUsage().heapUsed, memoryBytes: process.memoryUsage().heapUsed, cpuTime: process.cpuUsage().user, cpuMs: process.cpuUsage().user / 1000, activeOperations: this.activeOperations, networkRequests: 0, fileOperations: 0, }; } } // ============================================================================= // Memory Namespace Definitions // ============================================================================= /** * Get all QE memory namespace definitions */ function getMemoryNamespaces(): QEMemoryNamespace[] { return [ { name: 'aqe/v3/test-patterns', description: 'Learned test generation patterns', vectorDimension: 384, hnswConfig: { m: 16, efConstruction: 200, efSearch: 100 }, schema: { patternType: { type: 'string', index: true }, language: { type: 'string', index: true }, framework: { type: 'string', index: true }, effectiveness: { type: 'number' }, usageCount: { type: 'number' }, }, ttl: null, }, { name: 'aqe/v3/coverage-data', description: 'Coverage analysis results and gaps', vectorDimension: 384, hnswConfig: { m: 12, efConstruction: 150, efSearch: 50 }, schema: { filePath: { type: 'string', index: true }, linesCovered: { type: 'number' }, linesTotal: { type: 'number' }, branchCoverage: { type: 'number' }, gapType: { type: 'string', index: true }, priority: { type: 'number' }, }, ttl: 86400000, // 24h }, { name: 'aqe/v3/defect-patterns', description: 'Defect intelligence and predictions', vectorDimension: 384, hnswConfig: { m: 16, efConstruction: 200, efSearch: 100 }, schema: { defectType: { type: 'string', index: true }, severity: { type: 'string', index: true }, rootCause: { type: 'string' }, resolution: { type: 'string' }, recurrence: { type: 'number' }, }, ttl: null, }, { name: 'aqe/v3/code-knowledge', description: 'Code intelligence knowledge graph', vectorDimension: 384, hnswConfig: { m: 24, efConstruction: 300, efSearch: 150 }, schema: { nodeType: { type: 'string', index: true }, nodeName: { type: 'string', index: true }, filePath: { type: 'string', index: true }, complexity: { type: 'number' }, dependencies: { type: 'string' }, }, ttl: null, }, { name: 'aqe/v3/security-findings', description: 'Security scan findings and compliance', vectorDimension: 384, hnswConfig: { m: 16, efConstruction: 200, efSearch: 100 }, schema: { findingType: { type: 'string', index: true }, severity: { type: 'string', index: true }, cweId: { type: 'string', index: true }, filePath: { type: 'string' }, lineNumber: { type: 'number' }, remediation: { type: 'string' }, }, ttl: null, }, { name: 'aqe/v3/contracts', description: 'API contract definitions and validations', vectorDimension: 384, hnswConfig: { m: 12, efConstruction: 150, efSearch: 50 }, schema: { contractType: { type: 'string', index: true }, serviceName: { type: 'string', index: true }, version: { type: 'string' }, endpoint: { type: 'string' }, validationStatus: { type: 'string', index: true }, }, ttl: null, }, { name: 'aqe/v3/visual-baselines', description: 'Visual regression baselines and diffs', vectorDimension: 768, // Higher dim for image embeddings hnswConfig: { m: 32, efConstruction: 400, efSearch: 200 }, schema: { componentId: { type: 'string', index: true }, viewport: { type: 'string', index: true }, baselineHash: { type: 'string' }, lastUpdated: { type: 'number' }, }, ttl: null, }, { name: 'aqe/v3/chaos-experiments', description: 'Chaos engineering experiments and results', vectorDimension: 384, hnswConfig: { m: 12, efConstruction: 150, efSearch: 50 }, schema: { experimentType: { type: 'string', index: true }, targetService: { type: 'string', index: true }, failureMode: { type: 'string' }, impactLevel: { type: 'string' }, recoveryTime: { type: 'number' }, }, ttl: 604800000, // 7 days }, { name: 'aqe/v3/learning-trajectories', description: 'ReasoningBank learning trajectories for QE', vectorDimension: 384, hnswConfig: { m: 16, efConstruction: 200, efSearch: 100 }, schema: { taskType: { type: 'string', index: true }, agentId: { type: 'string', index: true }, success: { type: 'boolean', index: true }, reward: { type: 'number' }, trajectory: { type: 'string' }, }, ttl: null, }, ]; } // ============================================================================= // AQE Plugin Class // ============================================================================= /** * Main Agentic-QE Plugin class * Implements IPlugin interface for claude-flow integration */ export class AQEPlugin implements IPlugin { readonly name = PLUGIN_NAME; readonly version = PLUGIN_VERSION; readonly description = PLUGIN_DESCRIPTION; readonly author = PLUGIN_AUTHOR; readonly capabilities = [...PLUGIN_CAPABILITIES]; private config: AQEPluginConfig | null = null; private context: IPluginContext | null = null; private contextMapper: ContextMapper | null = null; private sandbox: SecuritySandbox | null = null; private initialized = false; private componentHealth: Map<string, ComponentHealth> = new Map(); /** * Register the plugin with the plugin system */ async register(registry: IPluginRegistry): Promise<void> { // Register MCP tools - use batch or individual registration const tools = this.getMCPTools(); if (registry.registerTools) { registry.registerTools(tools); } else if (registry.registerTool) { for (const tool of tools) { registry.registerTool(tool); } } // Register hooks const hooks = this.getHooks(); if (registry.registerHooks) { registry.registerHooks(hooks); } else if (registry.registerHook) { for (const hook of hooks) { registry.registerHook(hook); } } // Register workers const workers = this.getWorkers(); if (registry.registerWorkers) { registry.registerWorkers(workers); } else if (registry.registerWorker) { for (const worker of workers) { registry.registerWorker(worker); } } // Register agents const agents = this.getAgents(); if (registry.registerAgents) { registry.registerAgents(agents); } else if (registry.registerAgent) { for (const agent of agents) { registry.registerAgent(agent); } } this.updateHealth('registry', 'healthy', 'Plugin registered successfully'); } /** * Initialize the plugin with context */ async initialize(context: IPluginContext): Promise<void> { if (this.initialized) { throw new Error('Plugin already initialized'); } this.context = context; const configData = context.getConfig?.() ?? context.config ?? {}; this.config = parseWithDefaults(PluginConfigSchema, configData) as AQEPluginConfig; // Initialize context mapper this.contextMapper = new ContextMapper(); context.set?.('aqe.contextMapper', this.contextMapper); this.updateHealth('contextMapper', 'healthy', 'Context mapper initialized'); // Initialize security sandbox this.sandbox = new SecuritySandbox(this.config.sandbox ?? undefined); context.set?.('aqe.sandbox', this.sandbox); this.updateHealth('sandbox', 'healthy', 'Security sandbox initialized'); // Initialize memory namespaces try { await this.initializeMemoryNamespaces(); this.updateHealth('memory', 'healthy', 'Memory namespaces initialized'); } catch (error) { this.updateHealth( 'memory', 'degraded', `Memory initialization failed: ${(error as Error).message}` ); } this.initialized = true; this.updateHealth('plugin', 'healthy', 'Plugin fully initialized'); } /** * Shutdown the plugin cleanly */ async shutdown(): Promise<void> { if (!this.initialized) { return; } // Cleanup temporary memory data try { const memoryService = this.context?.getMemoryService?.(); if (memoryService) { // Only clear temporary namespaces const tempNamespaces = ['aqe/v3/coverage-data']; for (const ns of tempNamespaces) { await memoryService.clearNamespace(ns).catch(() => { // Ignore cleanup errors }); } } } catch { // Ignore cleanup errors during shutdown } this.initialized = false; this.context = null; this.config = null; this.contextMapper = null; this.sandbox = null; this.componentHealth.clear(); } /** * Get plugin health status */ async getHealth(): Promise<PluginHealthStatus> { const components: Record<string, ComponentHealth> = {}; let overallStatus: 'healthy' | 'degraded' | 'unhealthy' = 'healthy'; for (const [name, health] of this.componentHealth) { components[name] = health; if (health.status === 'unhealthy') { overallStatus = 'unhealthy'; } else if (health.status === 'degraded' && overallStatus === 'healthy') { overallStatus = 'degraded'; } } return { healthy: overallStatus === 'healthy', status: overallStatus, components, lastCheck: Date.now(), uptime: Date.now() - (this.initialized ? 0 : Date.now()), }; } // ========================================================================== // Private Methods // ========================================================================== private updateHealth( component: string, status: 'healthy' | 'degraded' | 'unhealthy', message: string ): void { this.componentHealth.set(component, { name: component, healthy: status === 'healthy', status, message, lastCheck: Date.now(), lastSuccess: status === 'healthy' ? Date.now() : undefined, }); } private async initializeMemoryNamespaces(): Promise<void> { const memoryService = this.context?.getMemoryService?.(); if (!memoryService?.createNamespace) { // Memory service not available or doesn't support namespace creation return; } const namespaces = getMemoryNamespaces(); for (const ns of namespaces) { await memoryService.createNamespace({ name: ns.name, vectorDimension: ns.vectorDimension, hnswConfig: ns.hnswConfig, schema: ns.schema as Record<string, unknown>, }); } } private getMCPTools(): IMCPTool[] { return [ { name: 'aqe/generate-tests', description: 'Generate tests for code using AI-powered test generation', category: 'test-generation', version: this.version, inputSchema: { type: 'object', properties: { targetPath: { type: 'string', description: 'Path to file/directory to test' }, testType: { type: 'string', enum: ['unit', 'integration', 'e2e', 'property', 'mutation', 'fuzz'], default: 'unit', }, framework: { type: 'string', enum: ['vitest', 'jest', 'mocha', 'pytest', 'junit'], }, coverage: { type: 'object', properties: { target: { type: 'number', default: 80 }, focusGaps: { type: 'boolean', default: true }, }, }, style: { type: 'string', enum: ['tdd-london', 'tdd-chicago', 'bdd', 'example-based'], default: 'tdd-london', }, }, required: ['targetPath'], }, handler: this.handleGenerateTests.bind(this), }, { name: 'aqe/analyze-coverage', description: 'Analyze code coverage with O(log n) gap detection', category: 'coverage-analysis', version: this.version, inputSchema: { type: 'object', properties: { coverageReport: { type: 'string' }, targetPath: { type: 'string' }, algorithm: { type: 'string', enum: ['johnson-lindenstrauss', 'full-scan'], default: 'johnson-lindenstrauss', }, prioritize: { type: 'boolean', default: true }, }, required: ['targetPath'], }, handler: this.handleAnalyzeCoverage.bind(this), }, { name: 'aqe/security-scan', description: 'Run SAST/DAST security scans with compliance checking', category: 'security-compliance', version: this.version, inputSchema: { type: 'object', properties: { targetPath: { type: 'string' }, scanType: { type: 'string', enum: ['sast', 'dast', 'both'], default: 'sast' }, compliance: { type: 'array', items: { type: 'string' }, default: ['owasp-top-10'], }, severity: { type: 'string', default: 'all' }, }, required: ['targetPath'], }, handler: this.handleSecurityScan.bind(this), }, { name: 'aqe/evaluate-quality-gate', description: 'Evaluate quality gates for release readiness', category: 'quality-assessment', version: this.version, inputSchema: { type: 'object', properties: { gates: { type: 'array' }, defaults: { type: 'string', enum: ['strict', 'standard', 'minimal'], default: 'standard' }, }, }, handler: this.handleEvaluateQualityGate.bind(this), }, { name: 'aqe/predict-defects', description: 'Predict potential defects using ML-based analysis', category: 'defect-intelligence', version: this.version, inputSchema: { type: 'object', properties: { targetPath: { type: 'string' }, depth: { type: 'string', enum: ['shallow', 'medium', 'deep'], default: 'medium' }, includeRootCause: { type: 'boolean', default: true }, }, required: ['targetPath'], }, handler: this.handlePredictDefects.bind(this), }, { name: 'aqe/validate-contract', description: 'Validate API contracts (OpenAPI, GraphQL, gRPC)', category: 'contract-testing', version: this.version, inputSchema: { type: 'object', properties: { contractPath: { type: 'string' }, contractType: { type: 'string', enum: ['openapi', 'graphql', 'grpc', 'asyncapi'] }, targetUrl: { type: 'string' }, strict: { type: 'boolean', default: true }, }, required: ['contractPath', 'contractType'], }, handler: this.handleValidateContract.bind(this), }, { name: 'aqe/chaos-inject', description: 'Inject chaos failures for resilience testing', category: 'chaos-resilience', version: this.version, inputSchema: { type: 'object', properties: { target: { type: 'string' }, failureType: { type: 'string', enum: ['network-latency', 'network-partition', 'cpu-stress', 'memory-pressure', 'disk-failure', 'process-kill'], }, duration: { type: 'number', default: 30 }, intensity: { type: 'number', default: 0.5 }, dryRun: { type: 'boolean', default: true }, }, required: ['target', 'failureType'], }, handler: this.handleChaosInject.bind(this), }, { name: 'aqe/tdd-cycle', description: 'Execute TDD red-green-refactor cycle with 7 specialized subagents', category: 'test-generation', version: this.version, inputSchema: { type: 'object', properties: { requirement: { type: 'string' }, targetPath: { type: 'string' }, style: { type: 'string', enum: ['london', 'chicago'], default: 'london' }, maxCycles: { type: 'number', default: 10 }, }, required: ['requirement', 'targetPath'], }, handler: this.handleTDDCycle.bind(this), }, ]; } private getHooks(): QEHookDefinition[] { return [ { name: 'pre-test-execution', event: 'pre-test-execution', description: 'Validate test environment before execution', priority: 'high', handler: 'handlePreTestExecution', }, { name: 'pre-security-scan', event: 'pre-security-scan', description: 'Validate scan targets and permissions', priority: 'critical', handler: 'handlePreSecurityScan', }, { name: 'post-test-execution', event: 'post-test-execution', description: 'Store test results and learn patterns', priority: 'normal', handler: 'handlePostTestExecution', }, { name: 'post-coverage-analysis', event: 'post-coverage-analysis', description: 'Store coverage data and update trends', priority: 'normal', handler: 'handlePostCoverageAnalysis', }, { name: 'post-security-scan', event: 'post-security-scan', description: 'Store findings and update compliance status', priority: 'high', handler: 'handlePostSecurityScan', }, ]; } private getWorkers(): QEWorkerDefinition[] { return [ { name: 'test-executor', type: 'test-executor', capabilities: ['test-execution', 'parallel-processing'], maxConcurrent: 10, }, { name: 'coverage-analyzer', type: 'coverage-analyzer', capabilities: ['coverage-collection', 'gap-detection'], maxConcurrent: 5, }, { name: 'security-scanner', type: 'security-scanner', capabilities: ['sast', 'dast'], maxConcurrent: 3, }, ]; } private getAgents(): QEAgentDefinition[] { const agents: QEAgentDefinition[] = []; // Get all agents from context mapper if (this.contextMapper) { for (const context of PLUGIN_CAPABILITIES) { const contextAgents = this.contextMapper.getAgentsForContext(context as BoundedContext); const securityLevel = this.contextMapper.getSecurityLevel(context as BoundedContext); for (const agentName of contextAgents) { agents.push({ id: agentName, name: agentName.replace(/-/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase()), context: context as BoundedContext, capabilities: [context], modelTier: this.getModelTierForSecurityLevel(securityLevel), description: `Agent for ${context} context`, }); } } } return agents; } private getModelTierForSecurityLevel(level: SecurityLevel): ModelTier { switch (level) { case 'critical': return 'opus'; case 'high': return 'sonnet'; case 'medium': return 'sonnet'; case 'low': return 'haiku'; default: return 'sonnet'; } } // ========================================================================== // MCP Tool Handlers // ========================================================================== private async handleGenerateTests( input: unknown, _context: IPluginContext ): Promise<MCPToolResult> { const result = { status: 'success', message: 'Test generation completed', data: { targetPath: (input as { targetPath: string }).targetPath, testType: (input as { testType?: string }).testType ?? 'unit', testsGenerated: 0, note: 'Full implementation requires agentic-qe package', }, }; return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], }; } private async handleAnalyzeCoverage( input: unknown, _context: IPluginContext ): Promise<MCPToolResult> { const result = { status: 'success', message: 'Coverage analysis completed', data: { targetPath: (input as { targetPath: string }).targetPath, algorithm: (input as { algorithm?: string }).algorithm ?? 'johnson-lindenstrauss', coverage: { lines: 0, branches: 0, functions: 0 }, gaps: [], note: 'Full implementation requires agentic-qe package', }, }; return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], }; } private async handleSecurityScan( input: unknown, context: IPluginContext ): Promise<MCPToolResult> { // Validate path first const securityModule = context.getSecurityModule?.(); if (securityModule) { const pathResult = await securityModule.pathValidator.validate( (input as { targetPath: string }).targetPath ); if (!pathResult.valid) { return { content: [{ type: 'text', text: JSON.stringify({ error: pathResult.error }) }], isError: true, }; } } const result = { status: 'success', message: 'Security scan completed', data: { targetPath: (input as { targetPath: string }).targetPath, scanType: (input as { scanType?: string }).scanType ?? 'sast', findings: [], complianceStatus: [], note: 'Full implementation requires agentic-qe package', }, }; return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], }; } private async handleEvaluateQualityGate( _input: unknown, _context: IPluginContext ): Promise<MCPToolResult> { const result = { status: 'success', message: 'Quality gate evaluation completed', data: { passed: true, qualityScore: 85, gateResults: [], readiness: { ready: true, confidence: 0.85, blockers: [], warnings: [], }, note: 'Full implementation requires agentic-qe package', }, }; return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], }; } private async handlePredictDefects( input: unknown, _context: IPluginContext ): Promise<MCPToolResult> { const result = { status: 'success', message: 'Defect prediction completed', data: { targetPath: (input as { targetPath: string }).targetPath, predictions: [], hotspots: [], overallRisk: 0.2, confidence: 0.75, note: 'Full implementation requires agentic-qe package', }, }; return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], }; } private async handleValidateContract( input: unknown, _context: IPluginContext ): Promise<MCPToolResult> { const result = { status: 'success', message: 'Contract validation completed', data: { contractPath: (input as { contractPath: string }).contractPath, contractType: (input as { contractType: string }).contractType, valid: true, errors: [], warnings: [], note: 'Full implementation requires agentic-qe package', }, }; return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], }; } private async handleChaosInject( input: unknown, context: IPluginContext ): Promise<MCPToolResult> { const typedInput = input as { target: string; failureType: string; dryRun?: boolean; }; // Check if dry run if (!typedInput.dryRun) { const uiService = context.getUIService?.(); if (uiService) { const confirmed = await uiService.confirm( `WARNING: This will inject ${typedInput.failureType} into ${typedInput.target}. Continue?` ); if (!confirmed) { return { content: [{ type: 'text', text: 'Chaos injection cancelled by user' }], }; } } } const result = { status: 'success', message: 'Chaos injection completed', data: { target: typedInput.target, failureType: typedInput.failureType, dryRun: typedInput.dryRun ?? true, experimentId: `chaos-${Date.now()}`, observations: [], note: 'Full implementation requires agentic-qe package', }, }; return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], }; } private async handleTDDCycle( input: unknown, _context: IPluginContext ): Promise<MCPToolResult> { const result = { status: 'success', message: 'TDD cycle completed', data: { requirement: (input as { requirement: string }).requirement, targetPath: (input as { targetPath: string }).targetPath, style: (input as { style?: string }).style ?? 'london', cyclesCompleted: 0, testResults: { total: 0, passed: 0, failed: 0, skipped: 0 }, agents: [ 'requirement-analyzer', 'test-designer', 'red-phase-executor', 'green-phase-implementer', 'refactor-advisor', 'coverage-verifier', 'cycle-coordinator', ], note: 'Full implementation requires agentic-qe package', }, }; return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], }; } }