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
302 lines • 11.8 kB
JavaScript
/**
* Test Orchestrator - Testing and validation workflows
*
* Coordinates test generation, execution, coverage analysis, and regression detection
*/
export class TestOrchestrator {
subAgents = {
generation: 'test_generation_agent',
execution: 'test_execution_agent',
coverage: 'coverage_analysis_agent',
regression: 'regression_detection_agent',
validation: 'test_validation_agent'
};
async orchestrate(task) {
console.error('🧪 Test Orchestrator: Analyzing testing task...');
const analysis = this.analyzeTask(task);
const plan = this.createExecutionPlan(analysis);
const results = await this.executePlan(plan);
return this.synthesizeResults(results);
}
analyzeTask(task) {
const keywords = (task.task || task.description || '').toLowerCase();
const analysis = {
action: 'general',
scope: task.scope || 'all',
hasTarget: !!task.target,
suggestedAgents: []
};
// Determine primary action
if (keywords.includes('generate') || keywords.includes('create') || keywords.includes('write')) {
analysis.action = 'generate';
analysis.suggestedAgents.push(this.subAgents.generation);
}
else if (keywords.includes('run') || keywords.includes('execute')) {
analysis.action = 'execute';
analysis.suggestedAgents.push(this.subAgents.execution);
}
else if (keywords.includes('coverage') || keywords.includes('uncovered')) {
analysis.action = 'coverage';
analysis.suggestedAgents.push(this.subAgents.coverage);
}
else if (keywords.includes('regression') || keywords.includes('broken')) {
analysis.action = 'regression';
analysis.suggestedAgents.push(this.subAgents.regression);
}
else {
// Default: full testing workflow
analysis.action = 'full';
analysis.suggestedAgents.push(this.subAgents.execution, this.subAgents.coverage, this.subAgents.validation);
}
return analysis;
}
createExecutionPlan(analysis) {
const plan = {
steps: [],
parallel: false,
estimatedDuration: 0
};
switch (analysis.action) {
case 'generate':
// Generate tests workflow
plan.steps.push({
agent: this.subAgents.generation,
action: 'generate_tests',
params: {
scope: analysis.scope,
target: analysis.hasTarget ? 'specific' : 'general',
style: 'behavior-driven'
}
});
plan.steps.push({
agent: this.subAgents.validation,
action: 'validate_generated_tests',
params: { runSample: true }
});
break;
case 'execute':
// Run tests workflow
plan.steps.push({
agent: this.subAgents.execution,
action: 'run_tests',
params: {
scope: analysis.scope,
parallel: true,
bail: false
}
});
plan.steps.push({
agent: this.subAgents.coverage,
action: 'analyze_results',
params: { generateReport: true }
});
break;
case 'coverage':
// Coverage analysis workflow
plan.steps.push({
agent: this.subAgents.coverage,
action: 'collect_coverage',
params: {
includeUntested: true,
showGaps: true
}
});
plan.steps.push({
agent: this.subAgents.generation,
action: 'suggest_missing_tests',
params: { prioritizeByRisk: true }
});
break;
case 'regression':
// Regression detection workflow
plan.steps.push({
agent: this.subAgents.regression,
action: 'detect_regressions',
params: {
compareToBaseline: true,
includePerformance: true
}
});
break;
default:
// Full testing workflow
plan.steps.push({
agent: this.subAgents.execution,
action: 'run_all_tests',
params: { scope: 'all' }
}, {
agent: this.subAgents.coverage,
action: 'generate_coverage_report',
params: { detailed: true }
}, {
agent: this.subAgents.validation,
action: 'validate_test_quality',
params: { checkFlaky: true }
});
}
plan.estimatedDuration = plan.steps.length * 10; // 10 seconds per step
return plan;
}
async executePlan(plan) {
const results = [];
for (const step of plan.steps) {
console.log(` → Delegating to ${step.agent} for ${step.action}...`);
// Mock implementation
const result = {
agent: step.agent,
action: step.action,
success: true,
summary: `Completed ${step.action}`,
data: this.getMockDataForAction(step.action),
duration: Math.random() * 8000 + 2000
};
results.push(result);
}
return results;
}
getMockDataForAction(action) {
switch (action) {
case 'generate_tests':
return {
generated: 15,
types: { unit: 10, integration: 5 },
files: ['user.test.js', 'api.test.js']
};
case 'run_tests':
case 'run_all_tests':
return {
total: 45,
passed: 42,
failed: 2,
skipped: 1,
duration: 12.5
};
case 'collect_coverage':
case 'generate_coverage_report':
return {
lines: 85.5,
branches: 78.2,
functions: 92.1,
statements: 86.3,
uncoveredFiles: ['utils/helper.js', 'services/cache.js']
};
case 'detect_regressions':
return {
regressions: [
{
test: 'user login flow',
type: 'functional',
confidence: 0.95
}
]
};
default:
return { status: 'completed' };
}
}
synthesizeResults(results) {
const testResults = results.find(r => r.action === 'run_tests' || r.action === 'run_all_tests');
const coverageResults = results.find(r => r.action.includes('coverage'));
const findings = {
critical: [],
warnings: [],
info: []
};
// Process test failures
if (testResults?.data?.failed && testResults.data.failed > 0) {
findings.critical.push({
type: 'test_failure',
severity: 'critical',
title: `${testResults.data.failed} tests failing`,
description: 'Tests are failing and need immediate attention'
});
}
// Process coverage
if (coverageResults?.data?.lines !== undefined && coverageResults.data.lines < 80) {
findings.warnings.push({
type: 'low_coverage',
severity: 'warning',
title: `Test coverage at ${coverageResults.data.lines}%`,
description: 'Coverage is below recommended 80% threshold'
});
}
// Process regressions
const regressionResult = results.find(r => r.action === 'detect_regressions');
if (regressionResult?.data?.regressions && regressionResult.data.regressions.length > 0) {
regressionResult.data.regressions.forEach((reg) => {
findings.critical.push({
type: 'regression',
severity: 'critical',
title: `Regression in ${reg.test}`,
description: `${reg.type} regression detected with ${reg.confidence * 100}% confidence`
});
});
}
const summary = this.createSummary(testResults?.data, coverageResults?.data, findings);
return {
success: !findings.critical.length,
summary,
findings,
suggestions: this.generateSuggestions(results),
nextSteps: this.determineNextSteps(findings),
metadata: {
duration: results.reduce((sum, r) => sum + r.duration, 0),
agentsUsed: [...new Set(results.map(r => r.agent))],
confidence: 0.9
}
};
}
createSummary(testData, coverageData, findings) {
const parts = [];
if (testData) {
const passRate = ((testData.passed / testData.total) * 100).toFixed(1);
parts.push(`Tests: ${testData.passed}/${testData.total} (${passRate}%)`);
}
if (coverageData) {
parts.push(`Coverage: ${coverageData.lines}%`);
}
if (findings.critical.length > 0) {
parts.push(`⚠️ ${findings.critical.length} critical issues`);
}
return parts.join(' | ') || 'Test analysis complete';
}
generateSuggestions(results) {
const suggestions = [];
const coverageResult = results.find(r => r.action.includes('coverage'));
if (coverageResult?.data?.uncoveredFiles) {
suggestions.push({
title: 'Add tests for uncovered files',
description: `Files need coverage: ${coverageResult.data.uncoveredFiles.join(', ')}`,
priority: 'high',
effort: 'medium'
});
}
const testResult = results.find(r => r.action.includes('run_tests'));
if (testResult?.data?.skipped && testResult.data.skipped > 0) {
suggestions.push({
title: 'Enable skipped tests',
description: `${testResult.data.skipped} tests are currently skipped`,
priority: 'medium',
effort: 'low'
});
}
return suggestions;
}
determineNextSteps(findings) {
const steps = [];
if (findings.critical.length > 0) {
steps.push('Fix failing tests immediately');
steps.push('Run regression tests after fixes');
}
else if (findings.warnings.length > 0) {
steps.push('Improve test coverage to 80%+');
steps.push('Add integration tests for critical paths');
}
else {
steps.push('Set up continuous test monitoring');
steps.push('Consider property-based testing for edge cases');
}
return steps;
}
}
//# sourceMappingURL=test-orchestrator.js.map