UNPKG

@versatil/sdlc-framework

Version:

🚀 AI-Native SDLC framework with 11-MCP ecosystem, RAG memory, OPERA orchestration, and 6 specialized agents achieving ZERO CONTEXT LOSS. Features complete CI/CD pipeline with 7 GitHub workflows (MCP testing, security scanning, performance benchmarking),

305 lines 13.5 kB
/** * OPERA Testing Orchestrator - Agent-Driven UI/UX Testing Workflow * * Coordinates Enhanced Maria-QA and Enhanced James for comprehensive * UI/UX testing with real-time quality feedback and agent handoffs. */ import { EnhancedMaria } from '../agents/enhanced-maria.js'; import { EnhancedJames } from '../agents/enhanced-james.js'; import { VERSATILLogger } from '../utils/logger.js'; export class OPERATestingOrchestrator { constructor() { this.activeWorkflows = new Map(); this.logger = VERSATILLogger.getInstance(); this.mariaQA = new EnhancedMaria(); this.jamesFrontend = new EnhancedJames(); } /** * Trigger agent-driven testing workflow based on file changes */ async triggerAgentWorkflow(context) { const workflowId = `workflow-${Date.now()}`; this.activeWorkflows.set(workflowId, context); this.logger.info('🚀 Starting OPERA Agent-Driven Testing Workflow', { workflowId, changeType: context.changeType, testingSuite: context.testingSuite }, 'opera-orchestrator'); try { // Phase 1: Frontend Analysis (Enhanced James) let workflowResult = await this.executeJamesAnalysis(context); // Phase 2: Quality Validation (Enhanced Maria) if (workflowResult.qualityScore >= 70) { workflowResult = await this.executeMariaValidation(context, workflowResult); } // Phase 3: Agent Handoff Decision workflowResult.nextSteps = this.determineNextSteps(workflowResult); // Phase 4: Execute Quality Gates if (context.qualityGates.performance || context.qualityGates.accessibility) { workflowResult = await this.executeQualityGates(context, workflowResult); } this.activeWorkflows.delete(workflowId); return workflowResult; } catch (error) { this.logger.error('❌ OPERA Testing Workflow Failed', error, 'opera-orchestrator'); this.activeWorkflows.delete(workflowId); return { success: false, qualityScore: 0, agent: 'opera-orchestrator', issues: [{ type: 'critical', description: `Workflow execution failed: ${error instanceof Error ? error.message : 'Unknown error'}`, recommendation: 'Review workflow configuration and agent availability', agent: 'opera-orchestrator' }], recommendations: ['Fix workflow execution issues', 'Check agent system status'], nextSteps: ['Debug workflow failure', 'Restart agent system if needed'] }; } } /** * Execute Enhanced James frontend analysis */ async executeJamesAnalysis(context) { this.logger.info('🎨 Enhanced James: Frontend Analysis Phase', { changeType: context.changeType, components: context.affectedComponents }, 'enhanced-james'); const jamesContext = { trigger: 'opera-workflow', filePath: context.filePath || '', userRequest: `Analyze ${context.changeType} changes for UI/UX quality`, contextClarity: 'clear', urgency: 'high', testing: true }; const jamesResponse = await this.jamesFrontend.activate(jamesContext); return { success: true, qualityScore: this.calculateQualityScore(jamesResponse), agent: 'enhanced-james', issues: this.convertToWorkflowIssues(jamesResponse), recommendations: jamesResponse.suggestions.map(s => s.message), nextSteps: ['Proceed to Enhanced Maria QA validation'], handoffTo: jamesResponse.handoffTo }; } /** * Execute Enhanced Maria quality validation */ async executeMariaValidation(context, previousResult) { this.logger.info('🔍 Enhanced Maria: Quality Validation Phase', { previousScore: previousResult.qualityScore, qualityGates: context.qualityGates }, 'enhanced-maria'); const mariaContext = { trigger: 'opera-handoff', filePath: context.filePath || '', userRequest: 'Validate UI/UX changes against quality standards', contextClarity: 'clear', urgency: 'high', testing: true }; const mariaResponse = await this.mariaQA.activate(mariaContext); // Combine results from both agents const combinedScore = Math.round((previousResult.qualityScore + this.calculateQualityScore(mariaResponse)) / 2); return { success: combinedScore >= 70, qualityScore: combinedScore, agent: 'enhanced-maria', issues: [ ...previousResult.issues, ...this.convertToWorkflowIssues(mariaResponse) ], recommendations: [ ...previousResult.recommendations, ...mariaResponse.suggestions.map(s => s.message) ], nextSteps: this.determineNextSteps({ ...previousResult, qualityScore: combinedScore }), handoffTo: mariaResponse.handoffTo }; } /** * Execute quality gates based on configuration */ async executeQualityGates(context, workflowResult) { this.logger.info('🚨 Executing Quality Gates', context.qualityGates, 'opera-quality-gates'); const qualityGateResults = []; // Performance Gate if (context.qualityGates.performance) { const performanceScore = await this.executePerformanceGate(context); qualityGateResults.push({ gate: 'performance', passed: performanceScore >= 90, score: performanceScore }); } // Accessibility Gate if (context.qualityGates.accessibility) { const accessibilityScore = await this.executeAccessibilityGate(context); qualityGateResults.push({ gate: 'accessibility', passed: accessibilityScore >= 95, score: accessibilityScore }); } // Visual Regression Gate if (context.qualityGates.visualRegression) { const visualScore = await this.executeVisualRegressionGate(context); qualityGateResults.push({ gate: 'visual', passed: visualScore >= 95, score: visualScore }); } // Security Gate if (context.qualityGates.security) { const securityScore = await this.executeSecurityGate(context); qualityGateResults.push({ gate: 'security', passed: securityScore >= 90, score: securityScore }); } // Calculate overall gate score const gateScore = Math.round(qualityGateResults.reduce((sum, result) => sum + result.score, 0) / qualityGateResults.length); const allGatesPassed = qualityGateResults.every(result => result.passed); // Add quality gate issues const gateIssues = qualityGateResults .filter(result => !result.passed) .map(result => ({ type: 'high', description: `Quality gate failed: ${result.gate} (Score: ${result.score})`, recommendation: `Improve ${result.gate} to meet quality standards`, agent: 'opera-quality-gates' })); return { ...workflowResult, success: workflowResult.success && allGatesPassed, qualityScore: Math.round((workflowResult.qualityScore + gateScore) / 2), issues: [...workflowResult.issues, ...gateIssues], recommendations: [ ...workflowResult.recommendations, ...qualityGateResults.map(result => `${result.gate} gate: ${result.passed ? '✅ PASSED' : '❌ FAILED'} (${result.score}/100)`) ] }; } /** * Execute performance quality gate */ async executePerformanceGate(context) { // Mock performance testing - in real implementation, this would: // - Run Lighthouse audits // - Measure Core Web Vitals // - Check performance budgets // - Analyze bundle sizes this.logger.info('⚡ Performance Quality Gate Executing', { context }, 'performance-gate'); // Simulate performance analysis const performanceFactors = { bundleSize: context.changeType === 'component' ? 85 : 95, renderTime: context.testingSuite === 'performance' ? 90 : 85, networkOptimization: 90, coreWebVitals: 88 }; const score = Math.round(Object.values(performanceFactors).reduce((sum, score) => sum + score, 0) / 4); this.logger.info('📊 Performance Gate Result', { score, factors: performanceFactors }, 'performance-gate'); return score; } /** * Execute accessibility quality gate */ async executeAccessibilityGate(context) { this.logger.info('♿ Accessibility Quality Gate Executing', { context }, 'accessibility-gate'); // Mock accessibility testing - in real implementation, this would: // - Run axe-core audits // - Check WCAG compliance // - Validate keyboard navigation // - Test screen reader compatibility const accessibilityFactors = { wcagCompliance: 95, keyboardNavigation: 92, screenReaderCompatibility: 94, colorContrast: 96 }; const score = Math.round(Object.values(accessibilityFactors).reduce((sum, score) => sum + score, 0) / 4); this.logger.info('📊 Accessibility Gate Result', { score, factors: accessibilityFactors }, 'accessibility-gate'); return score; } /** * Execute visual regression quality gate */ async executeVisualRegressionGate(context) { this.logger.info('👁️ Visual Regression Quality Gate Executing', { context }, 'visual-gate'); // Mock visual testing - in real implementation, this would: // - Compare screenshots with baselines // - Detect pixel differences // - Analyze layout shifts // - Check responsive design const visualFactors = { pixelAccuracy: context.changeType === 'style' ? 85 : 98, layoutStability: 95, responsiveDesign: 92, crossBrowserConsistency: 90 }; const score = Math.round(Object.values(visualFactors).reduce((sum, score) => sum + score, 0) / 4); this.logger.info('📊 Visual Regression Gate Result', { score, factors: visualFactors }, 'visual-gate'); return score; } /** * Execute security quality gate */ async executeSecurityGate(context) { this.logger.info('🔒 Security Quality Gate Executing', { context }, 'security-gate'); // Mock security testing - in real implementation, this would: // - Scan for XSS vulnerabilities // - Check CSP headers // - Validate authentication // - Test authorization const securityFactors = { xssProtection: 95, cspHeaders: 90, authenticationSecurity: 92, dataValidation: 88 }; const score = Math.round(Object.values(securityFactors).reduce((sum, score) => sum + score, 0) / 4); this.logger.info('📊 Security Gate Result', { score, factors: securityFactors }, 'security-gate'); return score; } /** * Helper methods */ calculateQualityScore(agentResponse) { // Convert agent response to quality score const priorityWeights = { critical: 0, high: 20, medium: 50, low: 80 }; const baseScore = 100; const deductions = agentResponse.suggestions.reduce((total, suggestion) => { const weight = priorityWeights[suggestion.priority] ?? 50; return total + (100 - weight); }, 0); return Math.max(0, Math.round(baseScore - deductions)); } convertToWorkflowIssues(agentResponse) { return agentResponse.suggestions.map(suggestion => ({ type: suggestion.priority, description: suggestion.message, recommendation: suggestion.message, agent: agentResponse.agentId })); } determineNextSteps(result) { const steps = []; if (result.qualityScore < 70) { steps.push('🚨 CRITICAL: Address quality issues before proceeding'); steps.push('Fix critical and high priority issues'); } if (result.qualityScore >= 70 && result.qualityScore < 90) { steps.push('⚠️ Address medium priority issues for production readiness'); steps.push('Run additional quality gates'); } if (result.qualityScore >= 90) { steps.push('✅ Quality standards met - ready for deployment'); steps.push('Execute final integration tests'); } return steps; } /** * Get active workflow status */ getActiveWorkflows() { return Array.from(this.activeWorkflows.entries()).map(([id, context]) => ({ id, context })); } /** * Cancel workflow */ cancelWorkflow(workflowId) { return this.activeWorkflows.delete(workflowId); } } export default OPERATestingOrchestrator; //# sourceMappingURL=bmad-testing-orchestrator.js.map