#!/usr/bin/env npx tsx /** * Agentic QE v3 - Benchmark Runner * * Run this to verify O(log n) claims and measure performance. * * Usage: npx tsx src/benchmarks/run-benchmarks.ts * * @module benchmarks/run-benchmarks */ import { runFullBenchmarkSuite, formatBenchmarkReport, verifyLogNComplexity, BenchmarkSuite, } from './performance-benchmarks.js'; // ============================================================================ // Additional O(log n) Verification Tests // ============================================================================ async function verifyGapDetectorComplexity(): Promise { console.log('\nšŸ“Š Verifying Gap Detector O(log n) complexity...'); try { const { GapDetectorService } = await import( '../domains/coverage-analysis/services/gap-detector.js' ); // Create minimal memory backend const store = new Map(); const mockMemory = { set: async (key: string, value: unknown) => { store.set(key, value); }, get: async (key: string): Promise => (store.get(key) as T) || null, delete: async (key: string) => store.delete(key), has: async (key: string) => store.has(key), keys: async () => Array.from(store.keys()), clear: async () => store.clear(), close: async () => {}, vectorSearch: async () => [], storeVector: async () => {}, getStats: async () => ({ keyCount: store.size }), search: async () => [], }; const result = await verifyLogNComplexity( 'Gap Detector', async (size) => { const service = new GapDetectorService(mockMemory as any); // Generate coverage data with specified size const files = Array.from({ length: size }, (_, i) => ({ path: `src/file${i}.ts`, lines: { covered: 70, total: 100 }, branches: { covered: 50, total: 80 }, functions: { covered: 8, total: 10 }, statements: { covered: 75, total: 100 }, uncoveredLines: [10, 20, 30, 40, 50], uncoveredBranches: [5, 15, 25], })); return { runFn: async () => { await service.detectGaps({ coverageData: { files, summary: { line: Math.round(files.reduce((s, f) => s + f.lines.covered / f.lines.total, 0) * 100 / files.length), branch: Math.round(files.reduce((s, f) => s + f.branches.covered / f.branches.total, 0) * 100 / files.length), function: Math.round(files.reduce((s, f) => s + f.functions.covered / f.functions.total, 0) * 100 / files.length), statement: Math.round(files.reduce((s, f) => s + f.statements.covered / f.statements.total, 0) * 100 / files.length), files: files.length, }, }, minCoverage: 80, prioritize: 'risk', }); }, }; }, [100, 500, 1000] ); console.log(` Result: ${result.verified ? 'āœ… VERIFIED' : 'āŒ NOT VERIFIED'}`); console.log(` Details: ${result.details}`); } catch (error) { console.error(` Failed: ${error instanceof Error ? error.message : String(error)}`); } } async function verifyCoverageAnalyzerComplexity(): Promise { console.log('\nšŸ“Š Verifying Coverage Analyzer O(log n) complexity...'); try { const { CoverageAnalyzerService } = await import( '../domains/coverage-analysis/services/coverage-analyzer.js' ); // Create minimal memory backend with vector support const store = new Map(); const vectors = new Map(); const mockMemory = { set: async (key: string, value: unknown) => { store.set(key, value); }, get: async (key: string): Promise => (store.get(key) as T) || null, delete: async (key: string) => store.delete(key), has: async (key: string) => store.has(key), keys: async () => Array.from(store.keys()), clear: async () => { store.clear(); vectors.clear(); }, close: async () => {}, vectorSearch: async (embedding: number[], k: number) => { // Simple brute force for testing const results = Array.from(vectors.entries()) .map(([key, data]) => ({ key, score: cosineSimilarity(embedding, data.embedding), metadata: data.metadata, })) .sort((a, b) => b.score - a.score) .slice(0, k); return results; }, storeVector: async (key: string, embedding: number[], metadata?: unknown) => { vectors.set(key, { embedding, metadata }); }, getStats: async () => ({ keyCount: store.size }), search: async () => [], }; const result = await verifyLogNComplexity( 'Coverage Analyzer', async (size) => { const service = new CoverageAnalyzerService(mockMemory as any); // Generate coverage data with specified size const files = Array.from({ length: size }, (_, i) => ({ path: `src/file${i}.ts`, lines: { covered: 70 + Math.floor(Math.random() * 30), total: 100 }, branches: { covered: 50 + Math.floor(Math.random() * 30), total: 80 }, functions: { covered: 8 + Math.floor(Math.random() * 2), total: 10 }, statements: { covered: 75 + Math.floor(Math.random() * 25), total: 100 }, uncoveredLines: Array.from({ length: 10 }, (_, j) => j * 10 + Math.floor(Math.random() * 10)), uncoveredBranches: Array.from({ length: 5 }, (_, j) => j * 15 + Math.floor(Math.random() * 10)), })); return { runFn: async () => { await service.findGaps({ files, summary: { line: Math.round(files.reduce((s, f) => s + f.lines.covered / f.lines.total, 0) * 100 / files.length), branch: Math.round(files.reduce((s, f) => s + f.branches.covered / f.branches.total, 0) * 100 / files.length), function: Math.round(files.reduce((s, f) => s + f.functions.covered / f.functions.total, 0) * 100 / files.length), statement: Math.round(files.reduce((s, f) => s + f.statements.covered / f.statements.total, 0) * 100 / files.length), files: files.length, }, }, 80); }, }; }, [100, 500, 1000] ); console.log(` Result: ${result.verified ? 'āœ… VERIFIED' : 'āŒ NOT VERIFIED'}`); console.log(` Details: ${result.details}`); } catch (error) { console.error(` Failed: ${error instanceof Error ? error.message : String(error)}`); } } async function verifyDefectPredictorComplexity(): Promise { console.log('\nšŸ“Š Verifying Defect Predictor complexity...'); try { const { DefectPredictorService } = await import( '../domains/defect-intelligence/services/defect-predictor.js' ); const store = new Map(); const mockMemory = { set: async (key: string, value: unknown) => { store.set(key, value); }, get: async (key: string): Promise => (store.get(key) as T) || null, delete: async (key: string) => store.delete(key), has: async (key: string) => store.has(key), keys: async () => Array.from(store.keys()), clear: async () => store.clear(), close: async () => {}, vectorSearch: async () => [], storeVector: async () => {}, getStats: async () => ({ keyCount: store.size }), search: async () => [], }; const service = new DefectPredictorService(mockMemory as any); // Generate test files for different sizes const result = await verifyLogNComplexity( 'Defect Predictor', async (size) => { const files = Array.from({ length: size }, (_, i) => `src/file${i}.ts`); return { runFn: async () => { await service.predictDefects({ files: files.slice(0, Math.min(10, size)), // Limit to 10 files per call features: [ { name: 'codeComplexity', weight: 0.25 }, { name: 'changeFrequency', weight: 0.20 }, ], threshold: 0.5, }); }, }; }, [10, 50, 100] ); console.log(` Result: ${result.verified ? 'āœ… VERIFIED' : 'āŒ NOT VERIFIED'}`); console.log(` Details: ${result.details}`); } catch (error) { console.error(` Failed: ${error instanceof Error ? error.message : String(error)}`); } } // ============================================================================ // Utility Functions // ============================================================================ function cosineSimilarity(a: number[], b: number[]): number { if (a.length !== b.length) return 0; let dotProduct = 0; let normA = 0; let normB = 0; for (let i = 0; i < a.length; i++) { dotProduct += a[i] * b[i]; normA += a[i] * a[i]; normB += b[i] * b[i]; } return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB) || 1); } function printBanner(): void { console.log(` ╔═══════════════════════════════════════════════════════════════════╗ ā•‘ AGENTIC QE v3 BENCHMARKS ā•‘ ā•‘ ā•‘ ā•‘ Verifying O(log n) claims and measuring real performance ā•‘ ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā• `); } function printDivider(): void { console.log('\n' + '═'.repeat(70) + '\n'); } // ============================================================================ // Main Runner // ============================================================================ async function main(): Promise { printBanner(); const startTime = Date.now(); // Run full benchmark suite console.log('šŸš€ Running full benchmark suite...\n'); const suite = await runFullBenchmarkSuite(); printDivider(); // Run additional O(log n) verification tests console.log('šŸ” Running additional O(log n) verification tests...'); await verifyGapDetectorComplexity(); await verifyCoverageAnalyzerComplexity(); await verifyDefectPredictorComplexity(); printDivider(); // Print summary const elapsed = ((Date.now() - startTime) / 1000).toFixed(2); console.log(`\nā±ļø Total benchmark time: ${elapsed}s\n`); console.log(suite.summary); // Print detailed report printDivider(); console.log('šŸ“‹ DETAILED RESULTS:\n'); console.log(formatBenchmarkReport(suite)); // Final verdict printDivider(); const hnswVerified = suite.results.find( (r) => r.name === 'HNSW Search Complexity' && r.verified ); console.log('šŸŽÆ FINAL VERDICT:\n'); if (hnswVerified) { console.log(' āœ… HNSW Search: O(log n) VERIFIED'); } else { console.log(' āŒ HNSW Search: O(log n) NOT VERIFIED or test failed'); } const failedBenchmarks = suite.results.filter( (r) => r.complexity === 'FAILED' ); if (failedBenchmarks.length > 0) { console.log(`\n āš ļø ${failedBenchmarks.length} benchmark(s) failed:`); for (const f of failedBenchmarks) { console.log(` - ${f.name}: ${f.details}`); } } // Exit with error if critical benchmarks failed if (!hnswVerified && failedBenchmarks.length > 0) { process.exit(1); } } // Run if executed directly main().catch((error) => { console.error('Benchmark runner failed:', error); process.exit(1); });