UNPKG

mcp-ai-agent-guidelines

Version:

A comprehensive Model Context Protocol server providing professional tools, resources, and prompts for implementing AI agent best practices

391 lines (372 loc) 15.7 kB
// Iterative Coverage Enhancement & Dead Code Elimination Tool // Provides comprehensive analysis and actionable steps for improving code coverage // while identifying and suggesting removal of dead code import { z } from "zod"; import { buildReferencesSection } from "./shared/prompt-utils.js"; const IterativeCoverageEnhancerSchema = z.object({ // Analysis Configuration projectPath: z.string().optional().default("."), language: z.string().default("typescript"), framework: z.string().optional(), // Coverage Analysis Options analyzeCoverageGaps: z.boolean().optional().default(true), detectDeadCode: z.boolean().optional().default(true), generateTestSuggestions: z.boolean().optional().default(true), adaptThresholds: z.boolean().optional().default(true), // Current Coverage Data (from tools like vitest, jest, etc.) currentCoverage: z .object({ statements: z.number().min(0).max(100), functions: z.number().min(0).max(100), lines: z.number().min(0).max(100), branches: z.number().min(0).max(100), }) .optional(), // Target Coverage Goals targetCoverage: z .object({ statements: z.number().min(0).max(100).optional(), functions: z.number().min(0).max(100).optional(), lines: z.number().min(0).max(100).optional(), branches: z.number().min(0).max(100).optional(), }) .optional(), // Output Configuration outputFormat: z .enum(["markdown", "json", "text"]) .optional() .default("markdown"), includeReferences: z.boolean().optional().default(true), includeCodeExamples: z.boolean().optional().default(true), generateCIActions: z.boolean().optional().default(true), }); export async function iterativeCoverageEnhancer(args) { const input = IterativeCoverageEnhancerSchema.parse(args); // Simulate coverage analysis (in real implementation, this would analyze actual code) const analysis = await performCoverageAnalysis(input); const sections = [ generateExecutiveSummary(analysis), ...(input.analyzeCoverageGaps ? [generateCoverageGapsSection(analysis.coverageGaps)] : []), ...(input.detectDeadCode ? [generateDeadCodeSection(analysis.deadCode)] : []), ...(input.generateTestSuggestions ? [generateTestSuggestionsSection(analysis.coverageGaps)] : []), ...(input.adaptThresholds ? [ generateThresholdRecommendationsSection(analysis.thresholdRecommendations), ] : []), generateIterationPlanSection(analysis.iterationPlan), ...(input.generateCIActions ? [generateCIActionsSection()] : []), ]; const references = input.includeReferences ? buildReferencesSection([ "Coverage-driven development best practices: https://martinfowler.com/bliki/TestCoverage.html", "Dead code elimination techniques: https://refactoring.guru/smells/dead-code", "Test-driven development guide: https://testdriven.io/", "The benefits of consistent testing: https://abseil.io/resources/swe-book/html/ch11.html#benefits_of_testing_code", "GitHub’s Engineering System Success Playbook: https://resources.github.com/engineering-system-success-playbook/", "Automated testing strategies: https://testing.googleblog.com/", "Code coverage analysis: https://docs.github.com/en/actions/automating-builds-and-tests/about-continuous-integration", ]) : ""; const content = sections.join("\n\n") + (references ? `\n\n${references}` : ""); return { content: [ { type: "text", text: content, }, ], }; } async function performCoverageAnalysis(input) { // In a real implementation, this would: // 1. Parse coverage reports (lcov, json, etc.) // 2. Analyze source code for dead code // 3. Generate test suggestions based on AST analysis // 4. Calculate optimal threshold adjustments const currentCov = input.currentCoverage || { statements: 42.41, functions: 26.98, lines: 42.41, branches: 88.29, }; const targetCov = input.targetCoverage || { statements: Math.min(currentCov.statements + 10, 95), functions: Math.min(currentCov.functions + 15, 90), lines: Math.min(currentCov.lines + 10, 95), branches: Math.min(currentCov.branches + 5, 95), }; // Mock coverage gaps analysis const coverageGaps = [ { file: "src/tools/example-tool.ts", uncoveredLines: [45, 46, 67, 89, 92], uncoveredFunctions: ["handleErrorCase", "validateInput"], priority: "high", effort: "medium", testSuggestions: [ "Add test for error handling in handleErrorCase()", "Test input validation edge cases", "Add integration test for complete workflow", ], }, { file: "src/utils/helper-functions.ts", uncoveredLines: [12, 13, 24], uncoveredFunctions: ["formatOutput"], priority: "medium", effort: "low", testSuggestions: [ "Test output formatting with different input types", "Verify edge cases for empty/null inputs", ], }, ]; // Mock dead code detection const deadCode = [ { file: "src/utils/deprecated-helpers.ts", type: "function", name: "oldFormatFunction", line: 15, confidence: "high", reason: "No references found, deprecated since v0.5.0", }, { file: "src/tools/legacy-tool.ts", type: "import", name: "unusedLibrary", line: 3, confidence: "medium", reason: "Imported but never used in file", }, ]; // Mock threshold recommendations const thresholdRecommendations = [ { metric: "functions", current: currentCov.functions, recommended: Math.min(currentCov.functions + 5, 35), rationale: "Gradual improvement targeting frequently used modules first", }, { metric: "statements", current: currentCov.statements, recommended: Math.min(currentCov.statements + 3, 50), rationale: "Conservative increase to avoid coverage regression during development", }, ]; // Mock iteration plan const iterationPlan = [ { phase: 1, description: "Dead Code Cleanup & High-Priority Gaps", actions: [ "Remove identified dead code (2-3 hours)", "Add tests for high-priority uncovered functions", "Update coverage thresholds incrementally", ], expectedImpact: { coverageIncrease: 4.5, deadCodeReduction: 80, }, timeEstimate: "1-2 days", }, { phase: 2, description: "Medium Priority Coverage Expansion", actions: [ "Add tests for remaining uncovered utility functions", "Implement integration tests for key workflows", "Review and adjust coverage thresholds", ], expectedImpact: { coverageIncrease: 6.2, deadCodeReduction: 20, }, timeEstimate: "2-3 days", }, ]; return { currentCoverage: currentCov, targetCoverage: targetCov, coverageGaps, deadCode, thresholdRecommendations, iterationPlan, }; } function generateExecutiveSummary(analysis) { const { currentCoverage, targetCoverage, coverageGaps, deadCode } = analysis; return `# 🎯 Iterative Coverage Enhancement Report ## Executive Summary | Metric | Current | Target | Gap | |--------|---------|--------|-----| | **Statements** | ${currentCoverage.statements.toFixed(1)}% | ${targetCoverage.statements?.toFixed(1) || "N/A"}% | ${targetCoverage.statements ? (targetCoverage.statements - currentCoverage.statements).toFixed(1) : "N/A"}% | | **Functions** | ${currentCoverage.functions.toFixed(1)}% | ${targetCoverage.functions?.toFixed(1) || "N/A"}% | ${targetCoverage.functions ? (targetCoverage.functions - currentCoverage.functions).toFixed(1) : "N/A"}% | | **Lines** | ${currentCoverage.lines.toFixed(1)}% | ${targetCoverage.lines?.toFixed(1) || "N/A"}% | ${targetCoverage.lines ? (targetCoverage.lines - currentCoverage.lines).toFixed(1) : "N/A"}% | | **Branches** | ${currentCoverage.branches.toFixed(1)}% | ${targetCoverage.branches?.toFixed(1) || "N/A"}% | ${targetCoverage.branches ? (targetCoverage.branches - currentCoverage.branches).toFixed(1) : "N/A"}% | ### 📊 Analysis Results - **Coverage Gaps Identified**: ${coverageGaps.length} files with uncovered code - **Dead Code Detected**: ${deadCode.length} items ready for removal - **Priority Actions**: ${coverageGaps.filter((g) => g.priority === "high").length} high-priority improvements - **Estimated Cleanup Impact**: ${deadCode.filter((d) => d.confidence === "high").length} high-confidence removals`; } function generateCoverageGapsSection(gaps) { const highPriority = gaps.filter((g) => g.priority === "high"); const mediumPriority = gaps.filter((g) => g.priority === "medium"); const lowPriority = gaps.filter((g) => g.priority === "low"); let section = `## 🔍 Coverage Gaps Analysis ### High Priority Gaps (${highPriority.length})`; for (const gap of highPriority) { section += ` #### ${gap.file} - **Uncovered Lines**: ${gap.uncoveredLines.join(", ")} - **Uncovered Functions**: ${gap.uncoveredFunctions.join(", ")} - **Effort**: ${gap.effort} - **Test Suggestions**: ${gap.testSuggestions.map((s) => ` - ${s}`).join("\n")}`; } if (mediumPriority.length > 0) { section += `\n\n### Medium Priority Gaps (${mediumPriority.length})`; for (const gap of mediumPriority) { section += `\n- **${gap.file}**: ${gap.uncoveredFunctions.length} functions, ${gap.uncoveredLines.length} lines`; } } if (lowPriority.length > 0) { section += `\n\n### Low Priority Gaps (${lowPriority.length})`; section += `\n*These can be addressed in future iterations.*`; } return section; } function generateDeadCodeSection(deadCode) { const highConfidence = deadCode.filter((d) => d.confidence === "high"); const mediumConfidence = deadCode.filter((d) => d.confidence === "medium"); let section = `## 🗑️ Dead Code Detection ### High Confidence Removals (${highConfidence.length})`; for (const item of highConfidence) { section += ` #### ${item.file}:${item.line} - **Type**: ${item.type} - **Name**: \`${item.name}\` - **Reason**: ${item.reason}`; } if (mediumConfidence.length > 0) { section += `\n\n### Medium Confidence Removals (${mediumConfidence.length})`; section += `\n*Review these manually before removal:*`; for (const item of mediumConfidence) { section += `\n- **${item.file}:${item.line}** - \`${item.name}\` (${item.reason})`; } } return section; } function generateTestSuggestionsSection(gaps) { let section = `## 🧪 Test Generation Suggestions ### Prioritized Test Development`; const allSuggestions = gaps.flatMap((g) => g.testSuggestions.map((s) => ({ file: g.file, suggestion: s, priority: g.priority, effort: g.effort, }))); const byPriority = { high: allSuggestions.filter((s) => s.priority === "high"), medium: allSuggestions.filter((s) => s.priority === "medium"), low: allSuggestions.filter((s) => s.priority === "low"), }; for (const [priority, suggestions] of Object.entries(byPriority)) { if (suggestions.length > 0) { section += `\n\n#### ${priority.charAt(0).toUpperCase() + priority.slice(1)} Priority`; for (const { file, suggestion } of suggestions) { section += `\n- **${file}**: ${suggestion}`; } } } return section; } function generateThresholdRecommendationsSection(recommendations) { let section = `## ⚙️ Adaptive Threshold Recommendations ### Proposed Coverage Threshold Updates`; for (const rec of recommendations) { section += ` #### ${rec.metric.charAt(0).toUpperCase() + rec.metric.slice(1)} - **Current**: ${rec.current.toFixed(1)}% - **Recommended**: ${rec.recommended.toFixed(1)}% - **Rationale**: ${rec.rationale}`; } section += `\n\n### Configuration Update \`\`\`typescript // vitest.config.ts or similar thresholds: { ${recommendations.map((r) => ` ${r.metric}: ${Math.floor(r.recommended)}, // ${r.rationale}`).join("\n")} } \`\`\``; return section; } function generateIterationPlanSection(plan) { let section = `## 📋 Iterative Enhancement Plan`; for (const phase of plan) { section += ` ### Phase ${phase.phase}: ${phase.description} **Timeline**: ${phase.timeEstimate} **Actions**: ${phase.actions.map((a) => `- ${a}`).join("\n")} **Expected Impact**: - Coverage increase: +${phase.expectedImpact.coverageIncrease.toFixed(1)}% - Dead code reduction: ${phase.expectedImpact.deadCodeReduction}%`; } return section; } function generateCIActionsSection() { return `## 🔄 CI/CD Integration Actions ### GitHub Actions Workflow Example \`\`\`yaml name: Iterative Coverage Enhancement on: schedule: - cron: '0 2 * * 1' # Weekly on Monday workflow_dispatch: jobs: coverage-analysis: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' - name: Install dependencies run: npm ci - name: Run coverage analysis run: npm run test:coverage:vitest - name: Generate coverage enhancement report run: | npx mcp-ai-agent-guidelines iterative-coverage-enhancer \\ --current-coverage-from-file coverage/coverage-summary.json \\ --generate-ci-actions true - name: Create PR if improvements found # Add logic to create PR with suggested improvements \`\`\` ### Automated Threshold Updates The system can automatically adjust coverage thresholds based on: - Current project velocity - Historical coverage trends - Dead code removal impact - Team capacity and priorities ### Integration with Existing Tools - **Coverage Reports**: Integrates with vitest, jest, nyc, c8, pytest-cov, coverage - **Dead Code Detection**: AST analysis, dependency graph analysis - **Test Generation**: Template-based test stub creation - **Threshold Management**: Dynamic adjustment based on project metrics ### Further Information ℹ️ - [GitHub’s Engineering System Success Playbook](https://resources.github.com/engineering-system-success-playbook/) - [GitHub Workflow Syntax](https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax?search-overlay-input=coverage&search-overlay-ask-ai=true) - [GitHub Copilot for Coverage](https://docs.github.com/en/copilot/tutorials/roll-out-at-scale/drive-downstream-impact/increase-test-coverage)`; } //# sourceMappingURL=iterative-coverage-enhancer.js.map