Files
proffesor-for-testing__agen…/tests/benchmarks/agentic-flow-performance.bench.ts
Profa 2253d05618 feat: flatten project structure — archive v2, promote v3 to root
Remove the nested v3/ subdirectory by moving all active source code,
tests, configs, and assets directly to the project root. Archive v2/
(dead code, 847MB) to v2-archive.tar.gz.

Key changes:
- Move v3/src/ → src/, v3/tests/ → tests/, v3/packages/ → packages/
- Move v3/tsconfig.json, v3/vitest.config.ts to root
- Merge v3/package.json into root package.json (ESM, scripts, deps, exports)
- Merge v3/scripts/ into scripts/, v3/implementation/ into docs/implementation/
- Update all CI workflows to remove "cd v3 &&" and v3/ path prefixes
- Fix all init installer path resolution (3-level-up → 2-level-up)
- Fix hooks to use "node ./dist/cli/bundle.js" instead of bare "aqe"
- Update settings.json ADR/DDD directories to docs/implementation/
- Fix helper scripts (statusline, adr-compliance, ddd-tracker, guidance-hooks)
- Update 58 agent definitions: aqe/v3/ → aqe/ memory namespaces
- Update 15 guidance shards: v3/src/ → src/ path references
- Fix sync interfaces: remove v3/ and v2/ path references
- Fix test path calculations (process.cwd() + '..' no longer needed)
- Fix flaky perf test threshold (500ms → 1000ms for CI environments)
- Fix complexity-analyzer test to match ADR-051 keyword-based eligibility

Build passes, 17,901 tests pass, CLI and MCP bundles verified.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 11:35:41 +00:00

668 lines
21 KiB
TypeScript

/**
* Agentic QE v3 - ADR-051 Agentic-Flow Integration Performance Benchmarks
*
* Validates success metrics defined in ADR-051:
* - Agent Booster: <5ms mechanical edit latency (vs 352ms LLM)
* - ReasoningBank: 50% cross-session pattern hit rate
* - Model Router: >90% routing accuracy
* - ONNX Embeddings: <50ms for 384-dim embedding generation
* - Pattern Retention: 100% retention rate across sessions
*
* Run with: npm run test:perf tests/benchmarks/agentic-flow-performance.bench.ts
* Or: vitest bench tests/benchmarks/agentic-flow-performance.bench.ts
*/
import { bench, describe } from 'vitest';
import { v4 as uuidv4 } from 'uuid';
// ============================================================================
// Mock Implementations (Minimal for Performance Testing)
// ============================================================================
/**
* Agent Booster - Mechanical code transforms
*/
class AgentBoosterBenchmark {
/**
* var to const transform (simplest mechanical edit)
*/
varToConst(code: string): string {
return code.replace(/\bvar\s+(\w+)/g, 'const $1');
}
/**
* Remove console statements
*/
removeConsole(code: string): string {
return code.replace(/^\s*console\.\w+\([^)]*\);?\s*$/gm, '');
}
/**
* Add TypeScript types to string constants
*/
addTypes(code: string): string {
return code.replace(/const\s+(\w+)\s*=\s*(['"`][^'"` ]*['"`]);/g, 'const $1: string = $2;');
}
/**
* Promise .then() to async/await
*/
promiseToAsync(code: string): string {
return code.replace(/(\w+)\s*\.\s*then\s*\(\s*(\w+)\s*=>\s*\{([^}]*)\}\s*\)/g, 'const $2 = await $1;\n$3');
}
/**
* CommonJS to ESM
*/
cjsToEsm(code: string): string {
return code
.replace(/const\s+(\w+)\s*=\s*require\(['"]([^'"]+)['"]\);?/g, "import $1 from '$2';")
.replace(/module\.exports\s*=\s*(\w+);?/g, 'export default $1;');
}
/**
* Function to arrow function
*/
funcToArrow(code: string): string {
return code.replace(/\bfunction\s+(\w+)\s*\(([^)]*)\)\s*\{/g, 'const $1 = ($2) => {');
}
}
/**
* Model Router - Complexity analysis for tier routing
*/
class ModelRouterBenchmark {
analyzeComplexity(description: string, filesAffected: number, linesOfCode: number): {
tier: 'booster' | 'haiku' | 'sonnet' | 'opus';
score: number;
confidence: number;
} {
// Check for mechanical transforms (Tier 0)
const mechanicalKeywords = ['var to const', 'add types', 'remove console'];
if (mechanicalKeywords.some(k => description.toLowerCase().includes(k)) && linesOfCode < 100) {
return { tier: 'booster', score: 5, confidence: 0.95 };
}
// Calculate complexity score
let score = 0;
score += description.length < 100 ? 10 : description.length < 500 ? 25 : 40;
score += filesAffected <= 1 ? 5 : filesAffected <= 5 ? 20 : 35;
score += linesOfCode <= 50 ? 5 : linesOfCode <= 200 ? 20 : linesOfCode <= 1000 ? 35 : 50;
// Semantic complexity
const complexKeywords = ['security', 'architecture', 'refactor', 'performance'];
score += complexKeywords.filter(k => description.toLowerCase().includes(k)).length * 15;
// Determine tier
if (score < 30) return { tier: 'haiku', score, confidence: 0.9 };
if (score < 60) return { tier: 'sonnet', score, confidence: 0.85 };
return { tier: 'opus', score, confidence: 0.8 };
}
}
/**
* ONNX Embeddings - Vector generation for semantic search
*/
class ONNXEmbeddingsBenchmark {
private cache: Map<string, number[]> = new Map();
/**
* Generate deterministic 384-dimensional embedding
*/
generate(text: string): number[] {
// Check cache
const cached = this.cache.get(text);
if (cached) return cached;
// Generate embedding (deterministic hash-based)
const hash = this.hashString(text);
const embedding: number[] = [];
for (let i = 0; i < 384; i++) {
embedding.push(Math.sin(hash + i) * 0.5 + 0.5);
}
// Normalize
const norm = Math.sqrt(embedding.reduce((sum, v) => sum + v * v, 0));
const normalized = embedding.map(v => v / norm);
this.cache.set(text, normalized);
return normalized;
}
/**
* Batch generate embeddings
*/
generateBatch(texts: string[]): number[][] {
return texts.map(t => this.generate(t));
}
/**
* Cosine similarity
*/
cosineSimilarity(vec1: number[], vec2: number[]): number {
let dot = 0;
for (let i = 0; i < vec1.length; i++) {
dot += vec1[i] * vec2[i];
}
return dot;
}
/**
* Search top-K similar vectors
*/
search(query: number[], vectors: number[][], topK: number): number[] {
const scores = vectors.map((v, i) => ({ index: i, score: this.cosineSimilarity(query, v) }));
scores.sort((a, b) => b.score - a.score);
return scores.slice(0, topK).map(s => s.index);
}
private hashString(str: string): number {
let hash = 0;
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i);
hash = (hash << 5) - hash + char;
hash = hash & hash;
}
return Math.abs(hash);
}
}
/**
* ReasoningBank - Pattern storage and retrieval
*/
class ReasoningBankBenchmark {
private patterns: Map<string, { content: string; confidence: number; successRate: number; usageCount: number }> = new Map();
/**
* Store pattern
*/
storePattern(id: string, content: string, confidence: number, successRate: number): void {
this.patterns.set(id, { content, confidence, successRate, usageCount: 0 });
}
/**
* Search patterns by content similarity
*/
searchPatterns(query: string, limit: number): Array<{ id: string; score: number }> {
const results: Array<{ id: string; score: number }> = [];
for (const [id, pattern] of this.patterns.entries()) {
const score = this.calculateSimilarity(query, pattern.content);
results.push({ id, score });
}
results.sort((a, b) => b.score - a.score);
return results.slice(0, limit);
}
/**
* Track pattern usage
*/
trackUsage(id: string): void {
const pattern = this.patterns.get(id);
if (pattern) {
pattern.usageCount++;
}
}
/**
* Calculate pattern retention rate
*/
getRetentionRate(): number {
const stored = this.patterns.size;
if (stored === 0) return 1.0;
// All patterns are retained in memory
return 1.0;
}
private calculateSimilarity(query: string, content: string): number {
const queryWords = new Set(query.toLowerCase().split(/\s+/));
const contentWords = new Set(content.toLowerCase().split(/\s+/));
const intersection = [...queryWords].filter(w => contentWords.has(w)).length;
return intersection / Math.max(queryWords.size, 1);
}
}
// ============================================================================
// Test Data Generation
// ============================================================================
/**
* Generate realistic test code samples
*/
function generateTestCode(lines: number, hasVar: boolean = false, hasConsole: boolean = false): string {
const code: string[] = [];
for (let i = 0; i < lines; i++) {
if (hasVar && i % 3 === 0) {
code.push(`var x${i} = ${i};`);
} else if (hasConsole && i % 4 === 0) {
code.push(`console.log('debug ${i}');`);
} else {
code.push(`const y${i} = ${i * 2};`);
}
}
return code.join('\n');
}
/**
* Generate task descriptions for routing
*/
function generateTaskDescription(complexity: 'simple' | 'moderate' | 'complex'): string {
const templates = {
simple: [
'fix null pointer check in utility function',
'update error message in validation module',
'add missing type annotation',
],
moderate: [
'refactor and improve multiple authentication modules',
'add pagination feature to API endpoint with proper error handling',
'implement caching layer for database queries',
],
complex: [
'redesign authentication architecture for microservices',
'implement end-to-end encryption with security audit',
'refactor entire backend system for performance optimization and scalability',
],
};
return templates[complexity][Math.floor(Math.random() * templates[complexity].length)];
}
/**
* Generate realistic text for embeddings
*/
function generateText(words: number): string {
const vocabulary = [
'authentication', 'authorization', 'security', 'encryption', 'jwt', 'oauth',
'database', 'query', 'optimization', 'performance', 'cache', 'index',
'testing', 'validation', 'error', 'handling', 'logging', 'monitoring',
'api', 'rest', 'graphql', 'endpoint', 'request', 'response',
];
return Array.from({ length: words }, () =>
vocabulary[Math.floor(Math.random() * vocabulary.length)]
).join(' ');
}
// ============================================================================
// Agent Booster Benchmarks (Target: <5ms per transform)
// ============================================================================
describe('Agent Booster Performance - ADR-051 Target: <5ms', () => {
const booster = new AgentBoosterBenchmark();
// Test with various code sizes
const smallCode = generateTestCode(10, true, true);
const mediumCode = generateTestCode(50, true, true);
const largeCode = generateTestCode(200, true, true);
bench('var-to-const: 10 lines', () => {
booster.varToConst(smallCode);
});
bench('var-to-const: 50 lines', () => {
booster.varToConst(mediumCode);
});
bench('var-to-const: 200 lines', () => {
booster.varToConst(largeCode);
});
bench('remove-console: 10 lines', () => {
booster.removeConsole(smallCode);
});
bench('remove-console: 50 lines', () => {
booster.removeConsole(mediumCode);
});
bench('add-types: 10 lines', () => {
booster.addTypes(smallCode);
});
bench('promise-to-async: 10 lines', () => {
booster.promiseToAsync(smallCode);
});
bench('cjs-to-esm: 10 lines', () => {
booster.cjsToEsm(smallCode);
});
bench('func-to-arrow: 10 lines', () => {
booster.funcToArrow(smallCode);
});
bench('ALL transforms combined: 50 lines', () => {
let code = mediumCode;
code = booster.varToConst(code);
code = booster.removeConsole(code);
code = booster.addTypes(code);
code = booster.promiseToAsync(code);
code = booster.cjsToEsm(code);
code = booster.funcToArrow(code);
});
});
// ============================================================================
// Model Router Benchmarks (Target: <10ms routing decision)
// ============================================================================
describe('Model Router Performance - ADR-051 Target: <10ms', () => {
const router = new ModelRouterBenchmark();
bench('analyze simple task', () => {
router.analyzeComplexity('fix null pointer check', 1, 15);
});
bench('analyze moderate task', () => {
router.analyzeComplexity('refactor authentication module', 3, 250);
});
bench('analyze complex task', () => {
router.analyzeComplexity('architecture redesign with security audit', 15, 2000);
});
bench('analyze mechanical transform', () => {
router.analyzeComplexity('var to const transform', 1, 30);
});
bench('batch routing: 100 tasks', () => {
for (let i = 0; i < 100; i++) {
const complexity = i % 3 === 0 ? 'simple' : i % 3 === 1 ? 'moderate' : 'complex';
const desc = generateTaskDescription(complexity);
const files = complexity === 'simple' ? 1 : complexity === 'moderate' ? 3 : 15;
const loc = complexity === 'simple' ? 20 : complexity === 'moderate' ? 250 : 2000;
router.analyzeComplexity(desc, files, loc);
}
});
});
// ============================================================================
// ONNX Embeddings Benchmarks (Target: <50ms for 384-dim embedding)
// ============================================================================
describe('ONNX Embeddings Performance - ADR-051 Target: <50ms', () => {
const embeddings = new ONNXEmbeddingsBenchmark();
bench('generate single embedding (10 words)', () => {
embeddings.generate(generateText(10));
});
bench('generate single embedding (50 words)', () => {
embeddings.generate(generateText(50));
});
bench('generate single embedding (100 words)', () => {
embeddings.generate(generateText(100));
});
bench('generate batch: 10 texts', () => {
const texts = Array.from({ length: 10 }, () => generateText(20));
embeddings.generateBatch(texts);
});
bench('generate batch: 50 texts', () => {
const texts = Array.from({ length: 50 }, () => generateText(20));
embeddings.generateBatch(texts);
});
bench('cosine similarity calculation', () => {
const vec1 = embeddings.generate('authentication with JWT tokens');
const vec2 = embeddings.generate('OAuth 2.0 authorization flow');
embeddings.cosineSimilarity(vec1, vec2);
});
bench('similarity search: top-5 from 100 vectors', () => {
const query = embeddings.generate('authentication security');
const vectors = Array.from({ length: 100 }, () => embeddings.generate(generateText(20)));
embeddings.search(query, vectors, 5);
});
bench('similarity search: top-10 from 1000 vectors', () => {
const query = embeddings.generate('database optimization');
const vectors = Array.from({ length: 1000 }, () => embeddings.generate(generateText(20)));
embeddings.search(query, vectors, 10);
});
bench('cache hit performance', () => {
const text = 'cached authentication pattern';
embeddings.generate(text); // Prime cache
embeddings.generate(text); // Should be instant
});
});
// ============================================================================
// ReasoningBank Benchmarks (Target: <20ms pattern retrieval)
// ============================================================================
describe('ReasoningBank Performance - ADR-051 Target: <20ms', () => {
const reasoningBank = new ReasoningBankBenchmark();
// Pre-populate with patterns
for (let i = 0; i < 1000; i++) {
reasoningBank.storePattern(
`pattern-${i}`,
generateText(30),
Math.random(),
Math.random()
);
}
bench('store single pattern', () => {
reasoningBank.storePattern(uuidv4(), generateText(30), 0.85, 0.9);
});
bench('search patterns: top-5 from 1000', () => {
reasoningBank.searchPatterns('authentication security pattern', 5);
});
bench('search patterns: top-10 from 1000', () => {
reasoningBank.searchPatterns('database query optimization', 10);
});
bench('track pattern usage', () => {
reasoningBank.trackUsage('pattern-0');
});
bench('calculate retention rate', () => {
reasoningBank.getRetentionRate();
});
bench('batch pattern storage: 100 patterns', () => {
for (let i = 0; i < 100; i++) {
reasoningBank.storePattern(
uuidv4(),
generateText(30),
Math.random(),
Math.random()
);
}
});
});
// ============================================================================
// Cross-Session Pattern Hit Rate Benchmark
// ============================================================================
describe('Cross-Session Pattern Hit Rate - ADR-051 Target: 50%', () => {
bench('simulate 100 pattern lookups with 50% hit rate', () => {
const reasoningBank = new ReasoningBankBenchmark();
// Store 50 patterns (session 1)
const patterns = Array.from({ length: 50 }, (_, i) => ({
id: `pattern-${i}`,
content: generateText(20),
}));
patterns.forEach(p => {
reasoningBank.storePattern(p.id, p.content, 0.8, 0.9);
});
// Simulate 100 lookups (session 2)
// 50 should hit existing patterns, 50 should be new
let hits = 0;
for (let i = 0; i < 100; i++) {
if (i < 50) {
// Hit existing pattern
const results = reasoningBank.searchPatterns(patterns[i].content, 1);
if (results.length > 0 && results[0].score > 0.5) {
hits++;
}
} else {
// New pattern
reasoningBank.searchPatterns(generateText(20), 1);
}
}
// Calculate hit rate
const hitRate = hits / 100;
// This should be close to 50% (0.5)
// In benchmark, we just want to ensure the calculation is fast
});
});
// ============================================================================
// Pattern Retention Rate Benchmark (Target: 100%)
// ============================================================================
describe('Pattern Retention Rate - ADR-051 Target: 100%', () => {
bench('verify 100% retention across 10000 patterns', () => {
const reasoningBank = new ReasoningBankBenchmark();
// Store 10000 patterns
for (let i = 0; i < 10000; i++) {
reasoningBank.storePattern(
`pattern-${i}`,
generateText(30),
Math.random(),
Math.random()
);
}
// Verify retention
const retentionRate = reasoningBank.getRetentionRate();
// Should be 1.0 (100%)
});
bench('retention rate calculation with pattern usage tracking', () => {
const reasoningBank = new ReasoningBankBenchmark();
// Store 1000 patterns
for (let i = 0; i < 1000; i++) {
reasoningBank.storePattern(`p-${i}`, generateText(20), 0.8, 0.9);
}
// Track usage for 500 patterns
for (let i = 0; i < 500; i++) {
reasoningBank.trackUsage(`p-${i}`);
}
// Calculate retention
reasoningBank.getRetentionRate();
});
});
// ============================================================================
// End-to-End Integration Benchmarks
// ============================================================================
describe('End-to-End Integration Performance', () => {
bench('complete agentic-flow pipeline', () => {
const booster = new AgentBoosterBenchmark();
const router = new ModelRouterBenchmark();
const embeddings = new ONNXEmbeddingsBenchmark();
const reasoningBank = new ReasoningBankBenchmark();
// 1. Analyze task with router
const taskDesc = 'var to const transform in authentication module';
const decision = router.analyzeComplexity(taskDesc, 1, 30);
// 2. If mechanical, use Agent Booster
if (decision.tier === 'booster') {
const code = generateTestCode(30, true, false);
const transformed = booster.varToConst(code);
// 3. Generate embedding for pattern storage
const embedding = embeddings.generate(taskDesc);
// 4. Store pattern in ReasoningBank
reasoningBank.storePattern(
uuidv4(),
taskDesc,
decision.confidence,
1.0 // Successful
);
}
});
bench('parallel processing: 10 tasks', () => {
const booster = new AgentBoosterBenchmark();
const router = new ModelRouterBenchmark();
const reasoningBank = new ReasoningBankBenchmark();
// Process 10 tasks in parallel
const tasks = Array.from({ length: 10 }, () => ({
desc: generateTaskDescription('simple'),
code: generateTestCode(20, true, true),
}));
tasks.forEach((task, i) => {
const decision = router.analyzeComplexity(task.desc, 1, 20);
if (decision.tier === 'booster') {
const transformed = booster.varToConst(task.code);
reasoningBank.storePattern(`task-${i}`, task.desc, decision.confidence, 1.0);
}
});
});
bench('memory efficiency: large pattern store', () => {
const reasoningBank = new ReasoningBankBenchmark();
const embeddings = new ONNXEmbeddingsBenchmark();
// Store 5000 patterns with embeddings
for (let i = 0; i < 5000; i++) {
const text = generateText(30);
const embedding = embeddings.generate(text);
reasoningBank.storePattern(`large-${i}`, text, 0.8, 0.9);
}
// Search should still be fast
reasoningBank.searchPatterns('authentication pattern', 10);
});
});
// ============================================================================
// Comparative Benchmarks (ADR-051 vs Manual LLM)
// ============================================================================
describe('ADR-051 vs Manual LLM API Calls', () => {
bench('Agent Booster: mechanical transform', () => {
const booster = new AgentBoosterBenchmark();
const code = generateTestCode(50, true, true);
booster.varToConst(code);
// Target: <5ms (vs 352ms LLM API call = 70x faster)
});
bench('Model Router: routing decision', () => {
const router = new ModelRouterBenchmark();
router.analyzeComplexity('var to const transform', 1, 30);
// Target: <10ms (vs manual selection)
});
bench('ReasoningBank: pattern retrieval', () => {
const reasoningBank = new ReasoningBankBenchmark();
for (let i = 0; i < 100; i++) {
reasoningBank.storePattern(`p-${i}`, generateText(20), 0.8, 0.9);
}
reasoningBank.searchPatterns('authentication', 5);
// Target: <20ms (vs no cross-session learning)
});
});