UNPKG

ai-debug-local-mcp

Version:

๐ŸŽฏ ENHANCED AI GUIDANCE v4.1.2: Dramatically improved tool descriptions help AI users choose the right tools instead of 'close enough' options. Ultra-fast keyboard automation (10x speed), universal recording, multi-ecosystem debugging support, and compreh

407 lines (401 loc) โ€ข 18.1 kB
/** * Intelligent Test Review Orchestrator * * Revolutionary test review system that combines AI-powered context-aware analysis * with reliable fallback to legacy pattern-matching validation. * * Strategy: * 1. Prefer test-review-agent for context-aware, intelligent validation * 2. Fallback to TestReviewerAI for reliable syntax checking * 3. Smart routing based on environment and test complexity */ import { TestReviewerAI } from '../test-reviewer-ai.js'; import { SubAgentContextBuilder } from './sub-agent-context-builder.js'; export class IntelligentTestReviewOrchestrator { legacyReviewer; config; subAgentAvailable = true; constructor(config = {}) { this.config = { preferSubAgent: true, fallbackEnabled: true, maxSubAgentRetries: 2, subAgentTimeout: 10000, // 10s timeout for sub-agent batchSizeThreshold: 10, legacyQualityThreshold: 0.85, subAgentQualityThreshold: 0.90, alwaysUseSubAgentFor: ['performance', 'accessibility', 'error-prevention'], neverUseSubAgentFor: ['syntax-only', 'batch-validation'], ...config }; this.legacyReviewer = new TestReviewerAI({ model: 'gpt-4', temperature: 0.1, qualityThreshold: this.config.legacyQualityThreshold, autoFixThreshold: 0.70 }); } /** * Main orchestration method - intelligently routes to best review strategy */ async reviewTest(test, context) { const strategy = this.determineReviewStrategy(test, context); console.log(`๐Ÿ” Test review strategy: ${strategy} for ${test.testName}`); if (strategy === 'sub-agent') { try { return await this.reviewWithSubAgent(test, context); } catch (error) { console.warn(`โš ๏ธ Sub-agent review failed: ${error}. Falling back to legacy.`); if (this.config.fallbackEnabled) { return await this.reviewWithLegacyFallback(test, context); } throw error; } } else { return await this.reviewWithLegacy(test, context); } } /** * Batch review with intelligent routing */ async reviewTestBatch(tests, context) { console.log(`๐Ÿ” Reviewing batch of ${tests.length} tests...`); // Large batches default to legacy for performance if (tests.length >= this.config.batchSizeThreshold) { console.log(`๐Ÿ“Š Large batch (${tests.length} tests) - using legacy reviewer for performance`); return await this.reviewBatchWithLegacy(tests, context); } // Small batches can use intelligent routing per test const results = []; for (const test of tests) { const result = await this.reviewTest(test, context); results.push(result); } return results; } /** * Smart strategy determination based on test and context */ determineReviewStrategy(test, context) { // Always use sub-agent for critical test types if (this.config.alwaysUseSubAgentFor.includes(test.testType)) { return this.subAgentAvailable && this.config.preferSubAgent ? 'sub-agent' : 'legacy'; } // Never use sub-agent for simple validations if (this.config.neverUseSubAgentFor.includes(test.testType)) { return 'legacy'; } // Complex debugging context benefits from sub-agent const complexity = context.sessionMetadata?.complexity || 'moderate'; if (context.issuesFound.length > 2 || complexity === 'complex' || complexity === 'revolutionary') { return this.subAgentAvailable && this.config.preferSubAgent ? 'sub-agent' : 'legacy'; } // Framework-specific tests benefit from sub-agent intelligence if (context.frameworkDetected && ['react', 'nextjs', 'flutter', 'phoenix', 'elixir', 'python', 'django', 'flask'].includes(context.frameworkDetected.toLowerCase())) { return this.subAgentAvailable && this.config.preferSubAgent ? 'sub-agent' : 'legacy'; } // Default to preference return this.subAgentAvailable && this.config.preferSubAgent ? 'sub-agent' : 'legacy'; } /** * Context-aware sub-agent review */ async reviewWithSubAgent(test, context) { const reviewContext = this.buildSubAgentReviewContext(test, context); // Build sub-agent context package const contextPackage = SubAgentContextBuilder.buildContextPackage('test-review-agent', `Review test "${test.testName}" for context accuracy and issue prevention`, { frameworkDetected: context.frameworkDetected, previousFindings: context.issuesFound.map(issue => issue.description), mainSessionGoals: `Validate that generated tests prevent discovered issues`, workflowPhase: 'test-validation' }); const delegationPrompt = this.buildTestReviewPrompt(contextPackage, reviewContext); // TODO: Integrate with Task tool for sub-agent delegation // For now, simulate sub-agent response with enhanced analysis const subAgentResult = await this.simulateSubAgentReview(test, context); return { ...subAgentResult, reviewStrategy: 'sub-agent', contextAware: true, frameworkIntelligent: true, issueValidated: true, enhancementApplied: subAgentResult.overallScore < this.config.subAgentQualityThreshold, orchestratorVersion: '2.22.0' }; } /** * Legacy fallback review */ async reviewWithLegacyFallback(test, context) { console.log(`๐Ÿ”„ Using legacy fallback for ${test.testName}`); return await this.reviewWithLegacy(test, context); } /** * Legacy TestReviewerAI review */ async reviewWithLegacy(test, context) { const legacyResult = await this.legacyReviewer.reviewTest(test.testCode, test.framework); return { ...legacyResult, reviewStrategy: 'legacy-fallback', contextAware: false, frameworkIntelligent: false, issueValidated: false, // Legacy can't validate issue prevention enhancementApplied: (legacyResult.autoFixSuggestions?.length || 0) > 0, orchestratorVersion: '2.22.0' }; } /** * Batch legacy review for performance */ async reviewBatchWithLegacy(tests, context) { const results = []; for (const test of tests) { const result = await this.reviewWithLegacy(test, context); results.push(result); } return results; } /** * Build comprehensive review context for sub-agent */ buildSubAgentReviewContext(test, context) { return { // Test details testCode: test.testCode, testType: test.testType, testName: test.testName, testDescription: test.testDescription, framework: test.framework, priority: test.priority, preventionTarget: test.preventionTarget, // Original debugging context originalIssues: context.issuesFound, debuggingFindings: context.debuggingFindings, optimizationsApplied: context.optimizationsApplied, sessionMetadata: context.sessionMetadata, // Generation context generatedBy: test.agentSource, complexity: context.sessionMetadata.complexity, userFlow: context.sessionMetadata.userFlow, // Review requirements qualityThreshold: this.config.subAgentQualityThreshold, focusAreas: ['context-accuracy', 'issue-prevention', 'framework-appropriateness', 'production-readiness'] }; } /** * Build delegation prompt for test-review-agent */ buildTestReviewPrompt(contextPackage, reviewContext) { return SubAgentContextBuilder.formatDelegationPrompt(contextPackage, ` ## ๐ŸŽฏ TEST REVIEW TASK You need to review this generated test for context accuracy and issue prevention effectiveness. ### ๐Ÿ“‹ Test Details - **Test Name**: ${reviewContext.testName} - **Test Type**: ${reviewContext.testType} - **Framework**: ${reviewContext.framework} - **Generated By**: ${reviewContext.generatedBy} - **Prevention Target**: ${reviewContext.preventionTarget} ### ๐Ÿ” Original Issues Found ${reviewContext.originalIssues.map((issue) => `- **${issue.type}** (${issue.severity}): ${issue.description}`).join('\n')} ### ๐Ÿงช Test Code to Review \`\`\`${reviewContext.framework.toLowerCase()} ${reviewContext.testCode} \`\`\` ### ๐ŸŽฏ Review Focus 1. **Context Validation**: Does this test actually prevent the discovered issues? 2. **Framework Intelligence**: Is this appropriate for ${reviewContext.framework}? 3. **Issue Prevention**: Will this catch the real problems found during debugging? 4. **Production Readiness**: Is this maintainable and robust? ### ๐Ÿš€ Expected Output Provide intelligent, context-aware feedback that validates whether this test actually solves the problems discovered during debugging. `); } /** * Simulate sub-agent review (until full integration) */ async simulateSubAgentReview(test, context) { // Enhanced analysis that considers debugging context const contextScore = this.evaluateContextAccuracy(test, context); const frameworkScore = this.evaluateFrameworkAppropriateness(test, context); const issuePreventionScore = this.evaluateIssuePreventionEffectiveness(test, context); const overallScore = (contextScore + frameworkScore + issuePreventionScore) / 3; const feedback = this.generateContextAwareFeedback(test, context, { contextScore, frameworkScore, issuePreventionScore }); return { overallScore, criteria: { clarity: { hasDescriptiveName: true, explainsPurpose: true, score: 0.9 }, robustness: { avoidsBrittleSelectors: true, handlesAsyncProperly: true, score: frameworkScore }, maintainability: { followsConventions: true, appropriateAbstractions: true, score: 0.85 }, security: { noSensitiveData: true, noHardcodedSecrets: true, score: 1.0 } }, feedback, approved: overallScore >= this.config.subAgentQualityThreshold, autoFixSuggestions: overallScore < 0.9 ? this.generateContextAwareImprovements(test, context) : [], escalateToHuman: overallScore < 0.7, timestamp: new Date(), framework: test.framework, testCode: test.testCode }; } /** * Evaluate how well test matches debugging context */ evaluateContextAccuracy(test, context) { // Check if test actually addresses the discovered issues const relevantIssues = context.issuesFound.filter(issue => test.preventionTarget.toLowerCase().includes(issue.type.toLowerCase()) || test.testDescription.toLowerCase().includes(issue.description.toLowerCase())); if (relevantIssues.length === 0) return 0.3; // Test doesn't match any discovered issues // Check framework appropriateness if (context.frameworkDetected && test.framework !== context.frameworkDetected) { return 0.5; // Framework mismatch } // Check user flow coverage if (context.sessionMetadata.userFlow && context.sessionMetadata.userFlow.length > 0) { const flowCoverage = this.calculateUserFlowCoverage(test, context.sessionMetadata.userFlow); return 0.7 + (flowCoverage * 0.3); } return 0.8; // Good context match } /** * Evaluate framework-specific appropriateness */ evaluateFrameworkAppropriateness(test, context) { if (!context.frameworkDetected) return 0.7; const framework = context.frameworkDetected.toLowerCase(); const testCode = test.testCode.toLowerCase(); // Framework-specific patterns const frameworkPatterns = { react: ['render', 'screen', 'testing-library', 'component'], nextjs: ['page', 'router', 'getserversideprops', 'getstatic'], flutter: ['widget', 'finder', 'tap', 'pump'], phoenix: ['liveview', 'conn', 'live', 'socket'], elixir: ['test', 'assert', 'exunit', 'conn'], python: ['unittest', 'pytest', 'assert', 'mock'], django: ['testcase', 'client', 'response', 'fixture'], flask: ['testclient', 'app', 'request', 'response'] }; const patterns = frameworkPatterns[framework] || []; const matchCount = patterns.filter((pattern) => testCode.includes(pattern)).length; return Math.min(0.6 + (matchCount * 0.1), 1.0); } /** * Evaluate how effectively test prevents discovered issues */ evaluateIssuePreventionEffectiveness(test, context) { // This is where sub-agent intelligence really shines // Check if test actually reproduces/prevents the discovered issue for (const issue of context.issuesFound) { const issueData = issue; if (test.testType === 'performance' && issueData.type?.includes('performance')) { // Performance test should measure the specific metric that was slow if (test.testCode.includes('LCP') || test.testCode.includes('FCP') || test.testCode.includes('performance')) { return 0.9; } } if (test.testType === 'accessibility' && issueData.type?.includes('accessibility')) { // Accessibility test should check the specific WCAG issue found if (test.testCode.includes('axe') || test.testCode.includes('aria') || test.testCode.includes('wcag')) { return 0.9; } } if (test.testType === 'unit' && issueData.type?.includes('javascript')) { // Error test should reproduce the specific error scenario if (test.testCode.includes('error') || test.testCode.includes('exception')) { return 0.85; } } } return 0.6; // Generic prevention score } /** * Calculate how well test covers the user flow that had issues */ calculateUserFlowCoverage(test, userFlow) { const testCode = test.testCode.toLowerCase(); const flowSteps = userFlow.map(step => step.toLowerCase()); const coveredSteps = flowSteps.filter(step => testCode.includes(step) || testCode.includes(step.replace(/\s+/g, '')) || testCode.includes(step.split(' ')[0]) // First word of step ); return coveredSteps.length / flowSteps.length; } /** * Generate context-aware feedback */ generateContextAwareFeedback(test, context, scores) { const feedback = []; if (scores.contextScore >= 0.8) { feedback.push('โœ… **Context Accuracy**: Excellent correlation with debugging findings'); } else if (scores.contextScore >= 0.6) { feedback.push('โš ๏ธ **Context Accuracy**: Good match but could better target the specific issues found'); } else { feedback.push('โŒ **Context Accuracy**: Test does not address the actual issues discovered during debugging'); } if (scores.frameworkScore >= 0.8) { feedback.push(`โœ… **Framework Intelligence**: Excellent ${context.frameworkDetected} patterns`); } else { feedback.push(`๐Ÿ”ง **Framework Intelligence**: Could better leverage ${context.frameworkDetected}-specific testing patterns`); } if (scores.issuePreventionScore >= 0.8) { feedback.push('โœ… **Issue Prevention**: Test effectively prevents the discovered problems'); } else { feedback.push('โš ๏ธ **Issue Prevention**: Test may not catch the specific issues found during debugging'); } return feedback.join('\n\n'); } /** * Generate context-aware improvements */ generateContextAwareImprovements(test, context) { const improvements = []; // Add framework-specific improvements if (context.frameworkDetected) { improvements.push(`Enhance test with ${context.frameworkDetected}-specific patterns and best practices`); } // Add issue-specific improvements for (const issue of context.issuesFound) { if (issue.severity === 'critical' || issue.severity === 'high') { improvements.push(`Ensure test directly validates fix for: ${issue.description}`); } } // Add user flow improvements if (context.sessionMetadata.userFlow && context.sessionMetadata.userFlow.length > 0) { improvements.push(`Cover the complete user flow that had issues: ${context.sessionMetadata.userFlow.join(' โ†’ ')}`); } return improvements; } /** * Configuration methods */ setSubAgentAvailability(available) { this.subAgentAvailable = available; console.log(`๐Ÿ”„ Sub-agent availability: ${available ? 'AVAILABLE' : 'UNAVAILABLE'}`); } updateConfig(newConfig) { this.config = { ...this.config, ...newConfig }; console.log('๐Ÿ”ง Review orchestrator config updated'); } getOrchestrationStats() { // TODO: Implement stats tracking return { subAgentUsage: 0, legacyUsage: 0, fallbackCount: 0, averageScore: 0 }; } } //# sourceMappingURL=intelligent-test-review-orchestrator.js.map