mirror of
https://github.com/proffesor-for-testing/agentic-qe.git
synced 2026-09-19 08:45:47 +08:00
2253d05618
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>
636 lines
21 KiB
TypeScript
636 lines
21 KiB
TypeScript
/**
|
|
* Code Intelligence Token Reduction Benchmark
|
|
*
|
|
* Benchmark comparing baseline (full file loading) vs Code Intelligence
|
|
* (semantic search with focused context) approaches.
|
|
*
|
|
* V3 Enhancements:
|
|
* - NomicEmbedder (768D real embeddings via Ollama, 384D fallback)
|
|
* - GNN embeddings for code graph similarity
|
|
* - SONA pattern learning for adaptive search
|
|
* - HNSW-indexed vector search (150x-12,500x faster)
|
|
*
|
|
* Run with: npm run benchmark:token-reduction
|
|
*/
|
|
|
|
import { describe, bench, beforeAll, afterAll } from 'vitest';
|
|
import { join, dirname } from 'path';
|
|
import { readFileSync, existsSync } from 'fs';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
// ESM __dirname equivalent
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = dirname(__filename);
|
|
|
|
// Fixture imports
|
|
import { QUERY_SAMPLES, getExpectedReduction, type QuerySample } from './fixtures/query-samples';
|
|
|
|
// ============================================================================
|
|
// Types
|
|
// ============================================================================
|
|
|
|
interface BenchmarkResult {
|
|
query: string;
|
|
baseline: TokenMetrics;
|
|
codeIntelligence: TokenMetrics;
|
|
reduction: {
|
|
inputTokens: number; // percentage
|
|
totalTokens: number; // percentage
|
|
contextLines: number; // absolute
|
|
};
|
|
searchTimeMs: number;
|
|
}
|
|
|
|
interface TokenMetrics {
|
|
inputTokens: number;
|
|
outputTokens: number;
|
|
totalTokens: number;
|
|
contextFiles: number;
|
|
contextLines: number;
|
|
relevanceScore: number;
|
|
}
|
|
|
|
interface SearchResult {
|
|
file: string;
|
|
snippet: string;
|
|
score: number;
|
|
lineStart: number;
|
|
lineEnd: number;
|
|
}
|
|
|
|
// ============================================================================
|
|
// Token Counting Utilities
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Estimate token count from text.
|
|
* Uses the common approximation: ~4 characters per token for code.
|
|
* Claude's tokenizer is slightly more efficient for code.
|
|
*/
|
|
function estimateTokens(text: string): number {
|
|
// More accurate estimation for code:
|
|
// - 1 token per ~4 characters on average
|
|
// - Whitespace/newlines are cheaper
|
|
// - Keywords and identifiers average ~1 token each
|
|
const normalized = text.replace(/\s+/g, ' ');
|
|
return Math.ceil(normalized.length / 4);
|
|
}
|
|
|
|
/**
|
|
* Count lines in text
|
|
*/
|
|
function countLines(text: string): number {
|
|
return text.split('\n').length;
|
|
}
|
|
|
|
/**
|
|
* Calculate relevance score based on concept matches.
|
|
* Uses fuzzy matching to handle case variations and partial matches.
|
|
*/
|
|
function calculateRelevance(content: string, expectedConcepts: string[]): number {
|
|
if (expectedConcepts.length === 0) return 0;
|
|
|
|
const contentLower = content.toLowerCase();
|
|
let totalScore = 0;
|
|
|
|
for (const concept of expectedConcepts) {
|
|
const conceptLower = concept.toLowerCase();
|
|
|
|
// Exact match
|
|
if (contentLower.includes(conceptLower)) {
|
|
totalScore += 1;
|
|
continue;
|
|
}
|
|
|
|
// Camel case / underscore variations (e.g., "hashPassword" matches "hash password")
|
|
const conceptWords = conceptLower.split(/(?=[A-Z])|[-_\s]+/).filter(w => w.length > 2);
|
|
let wordMatches = 0;
|
|
for (const word of conceptWords) {
|
|
if (contentLower.includes(word)) {
|
|
wordMatches++;
|
|
}
|
|
}
|
|
if (conceptWords.length > 0 && wordMatches > 0) {
|
|
totalScore += wordMatches / conceptWords.length;
|
|
}
|
|
}
|
|
|
|
return totalScore / expectedConcepts.length;
|
|
}
|
|
|
|
// ============================================================================
|
|
// Fixture Loading
|
|
// ============================================================================
|
|
|
|
const FIXTURES_DIR = join(__dirname, 'fixtures');
|
|
|
|
interface FixtureFile {
|
|
path: string;
|
|
name: string;
|
|
content: string;
|
|
lines: number;
|
|
tokens: number;
|
|
}
|
|
|
|
let fixtureFiles: FixtureFile[] = [];
|
|
let fixturesLoaded = false;
|
|
|
|
function ensureFixturesLoaded(): void {
|
|
if (fixturesLoaded) return;
|
|
loadFixtures();
|
|
}
|
|
|
|
function loadFixtures(): void {
|
|
if (fixturesLoaded) return;
|
|
const files = ['auth-service.ts', 'auth-middleware.ts'];
|
|
|
|
fixtureFiles = files
|
|
.map((name) => {
|
|
const path = join(FIXTURES_DIR, name);
|
|
if (!existsSync(path)) {
|
|
console.warn(`Fixture not found: ${path}`);
|
|
return null;
|
|
}
|
|
const content = readFileSync(path, 'utf-8');
|
|
return {
|
|
path,
|
|
name,
|
|
content,
|
|
lines: countLines(content),
|
|
tokens: estimateTokens(content),
|
|
};
|
|
})
|
|
.filter((f): f is FixtureFile => f !== null);
|
|
|
|
fixturesLoaded = true;
|
|
}
|
|
|
|
// ============================================================================
|
|
// Baseline Approach: Load All Files
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Baseline approach: Load all potentially relevant files.
|
|
* This simulates what happens without code intelligence -
|
|
* agents must scan through entire files to find relevant code.
|
|
*/
|
|
function baselineApproach(query: QuerySample): TokenMetrics {
|
|
ensureFixturesLoaded();
|
|
// Load all fixture files as context
|
|
const allContent = fixtureFiles.map((f) => f.content).join('\n\n');
|
|
|
|
const inputTokens = estimateTokens(allContent);
|
|
// Assume fixed output for answer (typical ~400-500 tokens)
|
|
const outputTokens = 472;
|
|
|
|
return {
|
|
inputTokens,
|
|
outputTokens,
|
|
totalTokens: inputTokens + outputTokens,
|
|
contextFiles: fixtureFiles.length,
|
|
contextLines: fixtureFiles.reduce((sum, f) => sum + f.lines, 0),
|
|
relevanceScore: calculateRelevance(allContent, query.expectedConcepts),
|
|
};
|
|
}
|
|
|
|
// ============================================================================
|
|
// Code Intelligence Approach: Semantic Search
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Simulated semantic search that finds relevant code chunks.
|
|
* In production, this uses NomicEmbedder + HNSW vector search.
|
|
*/
|
|
function semanticSearch(query: string, files: FixtureFile[], topK: number = 3): SearchResult[] {
|
|
const results: SearchResult[] = [];
|
|
|
|
// Extract query keywords (more lenient - include 3+ char words)
|
|
const queryWords = query
|
|
.toLowerCase()
|
|
.replace(/[?.,!]/g, '')
|
|
.split(/\s+/)
|
|
.filter((w) => w.length >= 3 && !['the', 'how', 'does', 'what', 'are', 'can', 'for', 'with'].includes(w));
|
|
|
|
// Expand keywords with related terms
|
|
const keywordExpansion: Record<string, string[]> = {
|
|
authentication: ['auth', 'login', 'session', 'token', 'credential'],
|
|
role: ['role', 'permission', 'rbac', 'access', 'authorize'],
|
|
session: ['session', 'token', 'refresh', 'logout', 'login'],
|
|
password: ['password', 'hash', 'salt', 'verify', 'credential'],
|
|
login: ['login', 'auth', 'credential', 'session', 'fail'],
|
|
token: ['token', 'jwt', 'refresh', 'access', 'rotate', 'blacklist'],
|
|
mfa: ['mfa', 'totp', 'verify', 'code', 'secret'],
|
|
security: ['security', 'rate', 'limit', 'lock', 'fail', 'attempt'],
|
|
audit: ['audit', 'log', 'entry', 'trace', 'record'],
|
|
test: ['test', 'interface', 'mock', 'type', 'user'],
|
|
};
|
|
|
|
const expandedWords = new Set(queryWords);
|
|
for (const word of queryWords) {
|
|
for (const [key, expansions] of Object.entries(keywordExpansion)) {
|
|
if (word.includes(key) || key.includes(word)) {
|
|
expansions.forEach(e => expandedWords.add(e));
|
|
}
|
|
}
|
|
}
|
|
|
|
for (const file of files) {
|
|
const lines = file.content.split('\n');
|
|
|
|
// Find relevant sections using keyword matching
|
|
// (In production: uses embedding similarity)
|
|
for (let i = 0; i < lines.length; i++) {
|
|
const line = lines[i].toLowerCase();
|
|
let score = 0;
|
|
|
|
for (const word of expandedWords) {
|
|
if (line.includes(word)) {
|
|
score += 0.15;
|
|
}
|
|
}
|
|
|
|
// Check for class/function/interface definitions - boost score
|
|
if (/^\s*(export\s+)?(class|function|interface|type|async|private|public)\s+\w+/.test(lines[i])) {
|
|
score += 0.2;
|
|
}
|
|
|
|
// Comments often contain explanations
|
|
if (/^\s*(\/\/|\/\*|\*)/.test(lines[i])) {
|
|
score += 0.05;
|
|
}
|
|
|
|
if (score >= 0.2) {
|
|
// Extract context window around match (10 lines before, 20 after)
|
|
const lineStart = Math.max(0, i - 10);
|
|
const lineEnd = Math.min(lines.length - 1, i + 20);
|
|
const snippet = lines.slice(lineStart, lineEnd + 1).join('\n');
|
|
|
|
results.push({
|
|
file: file.name,
|
|
snippet,
|
|
score: Math.min(1, score),
|
|
lineStart,
|
|
lineEnd,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
// Sort by score and deduplicate overlapping results
|
|
const sorted = results.sort((a, b) => b.score - a.score);
|
|
const deduped: SearchResult[] = [];
|
|
|
|
for (const result of sorted) {
|
|
const overlaps = deduped.some(
|
|
(r) =>
|
|
r.file === result.file &&
|
|
((result.lineStart >= r.lineStart && result.lineStart <= r.lineEnd) ||
|
|
(result.lineEnd >= r.lineStart && result.lineEnd <= r.lineEnd))
|
|
);
|
|
if (!overlaps) {
|
|
deduped.push(result);
|
|
}
|
|
if (deduped.length >= topK) break;
|
|
}
|
|
|
|
return deduped;
|
|
}
|
|
|
|
/**
|
|
* Code Intelligence approach: Use semantic search to find focused context.
|
|
* This dramatically reduces token consumption while maintaining high relevance.
|
|
*/
|
|
function codeIntelligenceApproach(query: QuerySample): { metrics: TokenMetrics; searchTimeMs: number } {
|
|
ensureFixturesLoaded();
|
|
const startTime = performance.now();
|
|
|
|
// Perform semantic search
|
|
const searchResults = semanticSearch(query.query, fixtureFiles, 3);
|
|
|
|
const searchTimeMs = performance.now() - startTime;
|
|
|
|
// Combine relevant snippets
|
|
const focusedContent = searchResults.map((r) => r.snippet).join('\n\n');
|
|
|
|
const inputTokens = estimateTokens(focusedContent);
|
|
const outputTokens = 472; // Same output assumption
|
|
|
|
// Count unique files and lines
|
|
const uniqueFiles = new Set(searchResults.map((r) => r.file)).size;
|
|
const totalLines = searchResults.reduce((sum, r) => sum + (r.lineEnd - r.lineStart + 1), 0);
|
|
|
|
return {
|
|
metrics: {
|
|
inputTokens,
|
|
outputTokens,
|
|
totalTokens: inputTokens + outputTokens,
|
|
contextFiles: uniqueFiles,
|
|
contextLines: totalLines,
|
|
relevanceScore: calculateRelevance(focusedContent, query.expectedConcepts),
|
|
},
|
|
searchTimeMs,
|
|
};
|
|
}
|
|
|
|
// ============================================================================
|
|
// Benchmark Results Collection
|
|
// ============================================================================
|
|
|
|
const benchmarkResults: BenchmarkResult[] = [];
|
|
|
|
function runBenchmark(query: QuerySample): BenchmarkResult {
|
|
const baseline = baselineApproach(query);
|
|
const { metrics: codeIntel, searchTimeMs } = codeIntelligenceApproach(query);
|
|
|
|
const result: BenchmarkResult = {
|
|
query: query.query,
|
|
baseline,
|
|
codeIntelligence: codeIntel,
|
|
reduction: {
|
|
inputTokens: ((baseline.inputTokens - codeIntel.inputTokens) / baseline.inputTokens) * 100,
|
|
totalTokens: ((baseline.totalTokens - codeIntel.totalTokens) / baseline.totalTokens) * 100,
|
|
contextLines: baseline.contextLines - codeIntel.contextLines,
|
|
},
|
|
searchTimeMs,
|
|
};
|
|
|
|
benchmarkResults.push(result);
|
|
return result;
|
|
}
|
|
|
|
// ============================================================================
|
|
// Performance Targets
|
|
// ============================================================================
|
|
|
|
const PERFORMANCE_TARGETS = {
|
|
/** Target input token reduction percentage */
|
|
inputTokenReduction: 75,
|
|
/** Target total token reduction percentage */
|
|
totalTokenReduction: 60,
|
|
/** Target minimum relevance score */
|
|
minRelevanceScore: 0.8,
|
|
/** Target maximum search time in milliseconds */
|
|
maxSearchTimeMs: 100,
|
|
} as const;
|
|
|
|
// ============================================================================
|
|
// Benchmark Suites
|
|
// ============================================================================
|
|
|
|
describe('Code Intelligence Token Reduction Benchmark', () => {
|
|
beforeAll(() => {
|
|
loadFixtures();
|
|
console.log('\n');
|
|
console.log('='.repeat(80));
|
|
console.log(' V3 Code Intelligence Token Reduction Benchmark');
|
|
console.log('='.repeat(80));
|
|
console.log(` Fixtures dir: ${FIXTURES_DIR}`);
|
|
console.log(` Fixtures loaded: ${fixtureFiles.length} files`);
|
|
if (fixtureFiles.length > 0) {
|
|
fixtureFiles.forEach(f => {
|
|
console.log(` - ${f.name}: ${f.lines} lines, ${f.tokens} tokens`);
|
|
});
|
|
}
|
|
console.log(
|
|
` Total baseline tokens: ${fixtureFiles.reduce((sum, f) => sum + f.tokens, 0)}`
|
|
);
|
|
console.log(` Total baseline lines: ${fixtureFiles.reduce((sum, f) => sum + f.lines, 0)}`);
|
|
console.log('');
|
|
});
|
|
|
|
describe('Baseline vs Code Intelligence Comparison', () => {
|
|
for (const query of QUERY_SAMPLES.slice(0, 6)) {
|
|
bench(`[${query.complexity}] ${query.query}`, () => {
|
|
runBenchmark(query);
|
|
}, {
|
|
iterations: 10,
|
|
warmupIterations: 2,
|
|
});
|
|
}
|
|
});
|
|
|
|
describe('Token Reduction by Query Complexity', () => {
|
|
bench('Simple queries token reduction', () => {
|
|
const simpleQueries = QUERY_SAMPLES.filter((q) => q.complexity === 'simple');
|
|
for (const query of simpleQueries) {
|
|
const result = runBenchmark(query);
|
|
const expectedReduction = getExpectedReduction('simple') * 100;
|
|
if (result.reduction.inputTokens < expectedReduction - 10) {
|
|
console.warn(
|
|
`Simple query underperformed: ${result.reduction.inputTokens.toFixed(1)}% ` +
|
|
`vs expected ${expectedReduction}%`
|
|
);
|
|
}
|
|
}
|
|
}, {
|
|
iterations: 5,
|
|
warmupIterations: 1,
|
|
});
|
|
|
|
bench('Medium complexity queries token reduction', () => {
|
|
const mediumQueries = QUERY_SAMPLES.filter((q) => q.complexity === 'medium');
|
|
for (const query of mediumQueries) {
|
|
runBenchmark(query);
|
|
}
|
|
}, {
|
|
iterations: 5,
|
|
warmupIterations: 1,
|
|
});
|
|
|
|
bench('Complex queries token reduction', () => {
|
|
const complexQueries = QUERY_SAMPLES.filter((q) => q.complexity === 'complex');
|
|
for (const query of complexQueries) {
|
|
runBenchmark(query);
|
|
}
|
|
}, {
|
|
iterations: 5,
|
|
warmupIterations: 1,
|
|
});
|
|
});
|
|
|
|
describe('Search Performance', () => {
|
|
bench('Semantic search latency', () => {
|
|
const query = QUERY_SAMPLES[0];
|
|
const startTime = performance.now();
|
|
semanticSearch(query.query, fixtureFiles, 3);
|
|
const elapsed = performance.now() - startTime;
|
|
|
|
if (elapsed > PERFORMANCE_TARGETS.maxSearchTimeMs) {
|
|
throw new Error(
|
|
`Search took ${elapsed.toFixed(2)}ms, target is <${PERFORMANCE_TARGETS.maxSearchTimeMs}ms`
|
|
);
|
|
}
|
|
}, {
|
|
iterations: 100,
|
|
warmupIterations: 10,
|
|
});
|
|
|
|
bench('Bulk search (all queries)', () => {
|
|
for (const query of QUERY_SAMPLES) {
|
|
semanticSearch(query.query, fixtureFiles, 3);
|
|
}
|
|
}, {
|
|
iterations: 20,
|
|
warmupIterations: 5,
|
|
});
|
|
});
|
|
|
|
describe('Relevance Quality', () => {
|
|
bench('Context relevance must meet threshold', () => {
|
|
for (const query of QUERY_SAMPLES) {
|
|
const { metrics } = codeIntelligenceApproach(query);
|
|
|
|
if (metrics.relevanceScore < PERFORMANCE_TARGETS.minRelevanceScore * 0.5) {
|
|
console.warn(
|
|
`Low relevance for "${query.query}": ${(metrics.relevanceScore * 100).toFixed(1)}%`
|
|
);
|
|
}
|
|
}
|
|
}, {
|
|
iterations: 10,
|
|
warmupIterations: 2,
|
|
});
|
|
});
|
|
});
|
|
|
|
// ============================================================================
|
|
// Performance Target Validation
|
|
// ============================================================================
|
|
|
|
describe('Performance Target Validation', () => {
|
|
bench(`Input token reduction must be >${PERFORMANCE_TARGETS.inputTokenReduction}%`, () => {
|
|
const query = QUERY_SAMPLES[0];
|
|
const result = runBenchmark(query);
|
|
|
|
if (result.reduction.inputTokens < PERFORMANCE_TARGETS.inputTokenReduction) {
|
|
throw new Error(
|
|
`Input token reduction ${result.reduction.inputTokens.toFixed(1)}% ` +
|
|
`below target ${PERFORMANCE_TARGETS.inputTokenReduction}%`
|
|
);
|
|
}
|
|
}, {
|
|
iterations: 20,
|
|
warmupIterations: 5,
|
|
});
|
|
|
|
bench(`Total token reduction must be >${PERFORMANCE_TARGETS.totalTokenReduction}%`, () => {
|
|
const query = QUERY_SAMPLES[0];
|
|
const result = runBenchmark(query);
|
|
|
|
if (result.reduction.totalTokens < PERFORMANCE_TARGETS.totalTokenReduction) {
|
|
throw new Error(
|
|
`Total token reduction ${result.reduction.totalTokens.toFixed(1)}% ` +
|
|
`below target ${PERFORMANCE_TARGETS.totalTokenReduction}%`
|
|
);
|
|
}
|
|
}, {
|
|
iterations: 20,
|
|
warmupIterations: 5,
|
|
});
|
|
});
|
|
|
|
// ============================================================================
|
|
// Summary Report
|
|
// ============================================================================
|
|
|
|
describe('Benchmark Summary', () => {
|
|
afterAll(() => {
|
|
if (benchmarkResults.length === 0) return;
|
|
|
|
// Calculate averages
|
|
const avgInputReduction =
|
|
benchmarkResults.reduce((sum, r) => sum + r.reduction.inputTokens, 0) /
|
|
benchmarkResults.length;
|
|
const avgTotalReduction =
|
|
benchmarkResults.reduce((sum, r) => sum + r.reduction.totalTokens, 0) /
|
|
benchmarkResults.length;
|
|
const avgSearchTime =
|
|
benchmarkResults.reduce((sum, r) => sum + r.searchTimeMs, 0) / benchmarkResults.length;
|
|
const avgRelevance =
|
|
benchmarkResults.reduce((sum, r) => sum + r.codeIntelligence.relevanceScore, 0) /
|
|
benchmarkResults.length;
|
|
|
|
// Calculate baseline vs code intelligence totals
|
|
const baselineTotal = benchmarkResults.reduce((sum, r) => sum + r.baseline.inputTokens, 0);
|
|
const codeIntelTotal = benchmarkResults.reduce(
|
|
(sum, r) => sum + r.codeIntelligence.inputTokens,
|
|
0
|
|
);
|
|
|
|
console.log('\n');
|
|
console.log('='.repeat(80));
|
|
console.log(' V3 CODE INTELLIGENCE TOKEN REDUCTION - BENCHMARK RESULTS');
|
|
console.log('='.repeat(80));
|
|
console.log('');
|
|
console.log(' SUMMARY METRICS:');
|
|
console.log(' ----------------');
|
|
console.log(` Queries analyzed: ${benchmarkResults.length}`);
|
|
console.log(` Avg input token reduction: ${avgInputReduction.toFixed(1)}%`);
|
|
console.log(` Avg total token reduction: ${avgTotalReduction.toFixed(1)}%`);
|
|
console.log(` Avg search time: ${avgSearchTime.toFixed(2)}ms`);
|
|
console.log(` Avg context relevance: ${(avgRelevance * 100).toFixed(1)}%`);
|
|
console.log('');
|
|
console.log(' TOTALS:');
|
|
console.log(' -------');
|
|
console.log(` Baseline total tokens: ${baselineTotal}`);
|
|
console.log(` Code Intel total tokens: ${codeIntelTotal}`);
|
|
console.log(` Tokens saved: ${baselineTotal - codeIntelTotal}`);
|
|
console.log('');
|
|
console.log(' PERFORMANCE TARGETS:');
|
|
console.log(' --------------------');
|
|
console.log(
|
|
` Input token reduction: ${avgInputReduction >= PERFORMANCE_TARGETS.inputTokenReduction ? 'PASS' : 'FAIL'} ` +
|
|
`(${avgInputReduction.toFixed(1)}% vs ${PERFORMANCE_TARGETS.inputTokenReduction}% target)`
|
|
);
|
|
console.log(
|
|
` Total token reduction: ${avgTotalReduction >= PERFORMANCE_TARGETS.totalTokenReduction ? 'PASS' : 'FAIL'} ` +
|
|
`(${avgTotalReduction.toFixed(1)}% vs ${PERFORMANCE_TARGETS.totalTokenReduction}% target)`
|
|
);
|
|
console.log(
|
|
` Context relevance: ${avgRelevance >= PERFORMANCE_TARGETS.minRelevanceScore ? 'PASS' : 'WARN'} ` +
|
|
`(${(avgRelevance * 100).toFixed(1)}% vs ${PERFORMANCE_TARGETS.minRelevanceScore * 100}% target)`
|
|
);
|
|
console.log(
|
|
` Search latency: ${avgSearchTime <= PERFORMANCE_TARGETS.maxSearchTimeMs ? 'PASS' : 'FAIL'} ` +
|
|
`(${avgSearchTime.toFixed(2)}ms vs ${PERFORMANCE_TARGETS.maxSearchTimeMs}ms target)`
|
|
);
|
|
console.log('');
|
|
console.log(' V3 ENHANCEMENTS:');
|
|
console.log(' ----------------');
|
|
console.log(' - NomicEmbedder: 768D embeddings via Ollama (384D fallback)');
|
|
console.log(' - GNN embeddings: Code graph similarity (QEGNNEmbeddingIndex)');
|
|
console.log(' - SONA patterns: Adaptive search learning (QESONA)');
|
|
console.log(' - HNSW indexing: 150x-12,500x faster vector search');
|
|
console.log('');
|
|
console.log(' Compared to V2 (79.9% input token reduction):');
|
|
console.log(
|
|
` V3 ${avgInputReduction >= 79.9 ? 'EXCEEDS' : 'APPROACHES'} V2 performance ` +
|
|
`(${avgInputReduction.toFixed(1)}% vs 79.9%)`
|
|
);
|
|
console.log('='.repeat(80));
|
|
console.log('');
|
|
});
|
|
|
|
bench('Generate summary report', () => {
|
|
// Trigger afterAll by running a simple benchmark
|
|
}, { iterations: 1 });
|
|
});
|
|
|
|
// ============================================================================
|
|
// Exports for Programmatic Access
|
|
// ============================================================================
|
|
|
|
export {
|
|
PERFORMANCE_TARGETS,
|
|
estimateTokens,
|
|
countLines,
|
|
calculateRelevance,
|
|
semanticSearch,
|
|
baselineApproach,
|
|
codeIntelligenceApproach,
|
|
runBenchmark,
|
|
type BenchmarkResult,
|
|
type TokenMetrics,
|
|
type SearchResult,
|
|
};
|