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
text/typescript
/**
* 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) }],
};
}
}