cto-ai-cli 3.0.2 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/engine/analyzer.ts","../../src/types/engine.ts","../../src/types/config.ts","../../src/engine/tokenizer.ts","../../src/engine/graph.ts","../../src/engine/risk.ts","../../src/engine/graph-utils.ts","../../src/engine/config.ts","../../src/engine/cache.ts","../../src/engine/watcher.ts","../../src/engine/pr-context.ts","../../src/engine/selector.ts","../../src/govern/secrets.ts","../../src/engine/pruner.ts","../../src/engine/coverage.ts","../../src/engine/budget.ts","../../src/engine/score.ts","../../src/engine/benchmark.ts","../../src/engine/quality-benchmark.ts","../../src/interact/router.ts","../../src/interact/prompt.ts","../../src/engine/predictor.ts","../../src/engine/cross-repo.ts","../../src/engine/feedback.ts","../../src/engine/semantic.ts","../../src/engine/compilability.ts","../../src/engine/compile-proof.ts","../../src/engine/multi-model.ts"],"sourcesContent":["import { readFile, readdir, stat } from 'node:fs/promises';\nimport { join, extname, relative, resolve, basename } from 'node:path';\nimport { createHash } from 'node:crypto';\nimport type {\n AnalyzedFile,\n FileKind,\n ProjectAnalysis,\n WalkEntry,\n WalkOptions,\n} from '../types/engine.js';\nimport { DEFAULT_RISK_WEIGHTS } from '../types/engine.js';\nimport type { CTOConfig } from '../types/config.js';\nimport { DEFAULT_CONFIG } from '../types/config.js';\nimport { estimateTokens, countTokensChars4 } from './tokenizer.js';\nimport { buildProjectGraph } from './graph.js';\nimport { scoreAllFiles } from './risk.js';\n\n// ===== FILE WALKING =====\n\nfunction matchesPattern(filename: string, patterns: string[]): boolean {\n for (const pattern of patterns) {\n if (pattern.startsWith('*.')) {\n const ext = pattern.slice(1);\n if (filename.endsWith(ext)) return true;\n } else if (filename === pattern) {\n return true;\n }\n }\n return false;\n}\n\nexport async function walkProject(\n rootPath: string,\n options: WalkOptions,\n): Promise<WalkEntry[]> {\n const results: WalkEntry[] = [];\n const { ignoreDirs, ignorePatterns, extensions, maxDepth = 20 } = options;\n const ignoreDirSet = new Set(ignoreDirs);\n\n async function walk(dir: string, depth: number): Promise<void> {\n if (depth > maxDepth) return;\n\n let entries;\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n const promises: Promise<void>[] = [];\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n\n if (entry.isDirectory()) {\n if (!ignoreDirSet.has(entry.name) && !entry.name.startsWith('.')) {\n promises.push(walk(fullPath, depth + 1));\n }\n } else if (entry.isFile()) {\n const ext = extname(entry.name).slice(1).toLowerCase();\n if (ext && extensions.includes(ext) && !matchesPattern(entry.name, ignorePatterns)) {\n promises.push(\n (async () => {\n const fileStat = await stat(fullPath).catch(() => null);\n if (!fileStat) return;\n\n let lines = 0;\n try {\n const content = await readFile(fullPath, 'utf-8');\n lines = content.split('\\n').length;\n } catch {\n lines = 0;\n }\n\n results.push({\n path: fullPath,\n relativePath: relative(rootPath, fullPath),\n extension: ext,\n size: fileStat.size,\n lastModified: fileStat.mtime,\n lines,\n });\n })(),\n );\n }\n }\n }\n\n await Promise.all(promises);\n }\n\n await walk(rootPath, 0);\n return results;\n}\n\n// ===== FILE KIND DETECTION =====\n\nconst TYPE_PATTERNS = [/types?\\//i, /\\.d\\.ts$/, /interfaces?\\//i];\nconst TEST_PATTERNS = [/\\.test\\.[jt]sx?$/, /\\.spec\\.[jt]sx?$/, /\\/__tests__\\//, /\\/tests?\\//];\nconst CONFIG_PATTERNS = [/\\.config\\.[jt]s$/, /rc\\.[jt]s$/, /\\.env/, /tsconfig/, /package\\.json$/, /\\.yml$/, /\\.yaml$/, /\\.toml$/];\nconst ENTRY_PATTERNS = [/^index\\.[jt]sx?$/, /^main\\.[jt]sx?$/, /^app\\.[jt]sx?$/, /^server\\.[jt]sx?$/];\n\nexport function classifyFileKind(relativePath: string): FileKind {\n const filename = basename(relativePath);\n\n if (TYPE_PATTERNS.some((p) => p.test(relativePath))) return 'type';\n if (TEST_PATTERNS.some((p) => p.test(relativePath))) return 'test';\n if (CONFIG_PATTERNS.some((p) => p.test(relativePath) || p.test(filename))) return 'config';\n if (ENTRY_PATTERNS.some((p) => p.test(filename))) return 'entry';\n return 'source';\n}\n\n// ===== STACK DETECTION =====\n\nexport function detectStack(files: WalkEntry[]): string[] {\n const stack: string[] = [];\n const extensions = new Set(files.map((f) => f.extension));\n const paths = files.map((f) => f.relativePath.toLowerCase());\n\n if (extensions.has('ts') || extensions.has('tsx')) stack.push('TypeScript');\n else if (extensions.has('js') || extensions.has('jsx')) stack.push('JavaScript');\n if (extensions.has('py')) stack.push('Python');\n if (extensions.has('go')) stack.push('Go');\n if (extensions.has('rs')) stack.push('Rust');\n if (extensions.has('java')) stack.push('Java');\n if (extensions.has('kt')) stack.push('Kotlin');\n if (extensions.has('rb')) stack.push('Ruby');\n if (extensions.has('php')) stack.push('PHP');\n if (extensions.has('cs')) stack.push('C#');\n if (extensions.has('c') || extensions.has('cpp')) stack.push('C/C++');\n\n if (paths.some((p) => p.includes('next.config'))) stack.push('Next.js');\n if (paths.some((p) => p.includes('nuxt.config'))) stack.push('Nuxt');\n if (paths.some((p) => p.includes('angular.json'))) stack.push('Angular');\n\n return stack;\n}\n\n// ===== MAIN ANALYSIS PIPELINE =====\n\nexport async function analyzeProject(\n projectPath: string,\n config?: Partial<CTOConfig>,\n): Promise<ProjectAnalysis> {\n const absPath = resolve(projectPath);\n const projectName = basename(absPath);\n const mergedConfig = mergeConfig(DEFAULT_CONFIG, config);\n\n // 1. Walk project files\n const allExtensions = [\n ...mergedConfig.analysis.extensions.code,\n ...mergedConfig.analysis.extensions.config,\n ...mergedConfig.analysis.extensions.docs,\n ];\n\n const walkEntries = await walkProject(absPath, {\n ignoreDirs: mergedConfig.analysis.ignore.dirs,\n ignorePatterns: mergedConfig.analysis.ignore.patterns,\n extensions: allExtensions,\n maxDepth: mergedConfig.analysis.maxDepth,\n });\n\n // 2. Estimate tokens and build initial AnalyzedFile[]\n const tokenMethod = mergedConfig.tokens.method;\n const files: AnalyzedFile[] = [];\n\n for (const entry of walkEntries) {\n let tokens: number;\n if (tokenMethod === 'tiktoken') {\n try {\n const content = await readFile(entry.path, 'utf-8');\n tokens = estimateTokens(content, entry.size, 'tiktoken');\n } catch {\n tokens = countTokensChars4(entry.size);\n }\n } else {\n tokens = countTokensChars4(entry.size);\n }\n\n files.push({\n path: entry.path,\n relativePath: entry.relativePath,\n extension: entry.extension,\n size: entry.size,\n tokens,\n lines: entry.lines,\n lastModified: entry.lastModified,\n kind: classifyFileKind(entry.relativePath),\n\n // Graph data — populated by graph analysis\n imports: [],\n importedBy: [],\n isHub: false,\n complexity: 0,\n\n // Risk data — populated by risk analysis\n riskScore: 0,\n riskFactors: [],\n exclusionImpact: 'none',\n });\n }\n\n // 3. Build dependency graph (AST-based, best-effort)\n const graph = buildProjectGraph(absPath, files);\n\n // 4. Enrich files with graph data\n for (const file of files) {\n const nodeImports: string[] = [];\n const nodeImportedBy: string[] = [];\n\n for (const edge of graph.edges) {\n if (edge.from === file.relativePath) nodeImports.push(edge.to);\n if (edge.to === file.relativePath) nodeImportedBy.push(edge.from);\n }\n\n file.imports = nodeImports;\n file.importedBy = nodeImportedBy;\n file.isHub = graph.hubs.some((h) => h.relativePath === file.relativePath);\n }\n\n // 5. Score risk for all files\n const riskWeights = mergedConfig.risk.weights;\n scoreAllFiles(files, graph, riskWeights);\n\n // 6. Build risk profile\n const riskProfile = {\n distribution: {\n critical: files.filter((f) => f.riskScore >= 80).length,\n high: files.filter((f) => f.riskScore >= 60 && f.riskScore < 80).length,\n medium: files.filter((f) => f.riskScore >= 30 && f.riskScore < 60).length,\n low: files.filter((f) => f.riskScore < 30).length,\n },\n topRiskFiles: [...files].sort((a, b) => b.riskScore - a.riskScore).slice(0, 10),\n overallComplexity: files.length > 0\n ? files.reduce((s, f) => s + f.complexity, 0) / files.length\n : 0,\n };\n\n // 7. Build analysis hash for determinism\n const totalTokens = files.reduce((s, f) => s + f.tokens, 0);\n const hashInput = files\n .map((f) => `${f.relativePath}:${f.tokens}:${f.riskScore}`)\n .sort()\n .join('|');\n const hash = createHash('sha256').update(hashInput).digest('hex').substring(0, 16);\n\n const stack = detectStack(walkEntries);\n\n return {\n projectPath: absPath,\n projectName,\n analyzedAt: new Date(),\n hash,\n files,\n totalFiles: files.length,\n totalTokens,\n graph,\n riskProfile,\n stack,\n tokenMethod,\n };\n}\n\n// ===== CONFIG MERGE =====\n\nfunction mergeConfig(base: CTOConfig, overrides?: Partial<CTOConfig>): CTOConfig {\n if (!overrides) return base;\n\n return {\n ...base,\n ...overrides,\n analysis: {\n ...base.analysis,\n ...overrides.analysis,\n extensions: {\n ...base.analysis.extensions,\n ...overrides.analysis?.extensions,\n },\n ignore: {\n ...base.analysis.ignore,\n ...overrides.analysis?.ignore,\n },\n },\n risk: {\n ...base.risk,\n ...overrides.risk,\n weights: {\n ...base.risk.weights,\n ...overrides.risk?.weights,\n },\n },\n interaction: {\n ...base.interaction,\n ...overrides.interaction,\n },\n tokens: {\n ...base.tokens,\n ...overrides.tokens,\n },\n governance: {\n ...base.governance,\n ...overrides.governance,\n },\n };\n}\n","// ===== Layer 1: Context Intelligence Engine Types =====\n\n// ===== FILE ANALYSIS =====\n\nexport interface AnalyzedFile {\n path: string;\n relativePath: string;\n extension: string;\n size: number;\n tokens: number;\n lines: number;\n lastModified: Date;\n kind: FileKind;\n\n // Graph data (populated after graph analysis)\n imports: string[];\n importedBy: string[];\n isHub: boolean;\n complexity: number;\n\n // Risk data (populated after risk analysis)\n riskScore: number;\n riskFactors: RiskFactor[];\n exclusionImpact: ExclusionImpact;\n}\n\nexport type FileKind = 'source' | 'type' | 'test' | 'config' | 'entry' | 'asset';\nexport type ExclusionImpact = 'critical' | 'high' | 'medium' | 'low' | 'none';\n\n// ===== PROJECT ANALYSIS =====\n\nexport interface ProjectAnalysis {\n projectPath: string;\n projectName: string;\n analyzedAt: Date;\n hash: string;\n\n files: AnalyzedFile[];\n totalFiles: number;\n totalTokens: number;\n\n graph: ProjectGraph;\n riskProfile: RiskProfile;\n stack: string[];\n tokenMethod: 'chars4' | 'tiktoken';\n}\n\n// ===== DEPENDENCY GRAPH =====\n\nexport interface ProjectGraph {\n nodes: string[];\n edges: GraphEdge[];\n hubs: HubNode[];\n leaves: string[];\n orphans: string[];\n clusters: FileCluster[];\n}\n\nexport interface GraphEdge {\n from: string;\n to: string;\n type: 'import' | 'export' | 're-export';\n}\n\nexport interface HubNode {\n relativePath: string;\n dependents: number;\n dependencies: number;\n score: number;\n}\n\nexport interface FileCluster {\n id: string;\n name: string;\n files: string[];\n totalTokens: number;\n internalEdges: number;\n externalEdges: number;\n cohesion: number;\n}\n\n// ===== RISK MODEL =====\n\nexport interface RiskProfile {\n distribution: {\n critical: number;\n high: number;\n medium: number;\n low: number;\n };\n topRiskFiles: AnalyzedFile[];\n overallComplexity: number;\n}\n\nexport interface RiskFactor {\n type: RiskFactorType;\n score: number;\n weight: number;\n detail: string;\n}\n\nexport type RiskFactorType =\n | 'hub'\n | 'type-provider'\n | 'complexity'\n | 'recency'\n | 'config'\n | 'churn';\n\nexport interface RiskWeights {\n hub: number;\n typeProvider: number;\n complexity: number;\n recency: number;\n config: number;\n churn: number;\n}\n\nexport const DEFAULT_RISK_WEIGHTS: RiskWeights = {\n hub: 30,\n typeProvider: 25,\n complexity: 15,\n recency: 15,\n config: 10,\n churn: 5,\n};\n\n// ===== CONTEXT COVERAGE =====\n\nexport interface CoverageResult {\n score: number;\n relevantFiles: string[];\n includedRelevant: string[];\n missingRelevant: string[];\n missingCritical: string[];\n explanation: string;\n}\n\n// ===== CONTEXT SELECTION =====\n\nexport interface ContextSelection {\n files: SelectedFile[];\n totalTokens: number;\n budget: number;\n usedPercent: number;\n\n coverage: CoverageResult;\n riskScore: number;\n deterministic: boolean;\n hash: string;\n\n decisions: SelectionDecision[];\n}\n\nexport interface SelectedFile {\n relativePath: string;\n tokens: number;\n originalTokens: number;\n pruneLevel: PruneLevel;\n riskScore: number;\n reason: string;\n}\n\nexport type PruneLevel = 'full' | 'signatures' | 'skeleton' | 'excluded';\n\nexport interface SelectionDecision {\n file: string;\n action: 'include-full' | 'include-signatures' | 'include-skeleton' | 'exclude';\n reason: string;\n alternatives?: string;\n}\n\n// ===== BUDGET =====\n\nexport interface BudgetPlan {\n budget: number;\n used: number;\n remaining: number;\n fillPercent: number;\n files: BudgetEntry[];\n}\n\nexport interface BudgetEntry {\n relativePath: string;\n originalTokens: number;\n allocatedTokens: number;\n pruneLevel: PruneLevel;\n included: boolean;\n reason: string;\n}\n\n// ===== PRUNING =====\n\nexport interface PrunedContent {\n relativePath: string;\n originalTokens: number;\n prunedTokens: number;\n pruneLevel: PruneLevel;\n content: string;\n savingsPercent: number;\n}\n\n// ===== WALKER =====\n\nexport interface WalkEntry {\n path: string;\n relativePath: string;\n extension: string;\n size: number;\n lastModified: Date;\n lines: number;\n}\n\nexport interface WalkOptions {\n ignoreDirs: string[];\n ignorePatterns: string[];\n extensions: string[];\n maxDepth?: number;\n}\n","// ===== Configuration Types =====\n\nimport type { RiskWeights } from './engine.js';\n\nexport interface CTOConfig {\n version: string;\n\n analysis: {\n extensions: {\n code: string[];\n config: string[];\n docs: string[];\n };\n ignore: {\n dirs: string[];\n patterns: string[];\n };\n maxDepth: number;\n };\n\n risk: {\n weights: RiskWeights;\n };\n\n interaction: {\n defaultBudget: number;\n defaultModel: string;\n };\n\n tokens: {\n method: 'chars4' | 'tiktoken';\n };\n\n governance: {\n auditEnabled: boolean;\n secretDetection: boolean;\n retentionDays: number;\n };\n}\n\nexport const DEFAULT_CONFIG: CTOConfig = {\n version: '2.0',\n\n analysis: {\n extensions: {\n code: ['ts', 'tsx', 'js', 'jsx', 'py', 'go', 'rs', 'java', 'kt', 'rb', 'php', 'c', 'cpp', 'h', 'hpp', 'cs'],\n config: ['json', 'yml', 'yaml', 'toml'],\n docs: ['md', 'txt', 'rst'],\n },\n ignore: {\n dirs: ['node_modules', 'dist', 'build', '.git', 'coverage', '__pycache__', '.next', 'vendor', '.cto'],\n patterns: ['*.min.js', '*.map', '*.lock', '*.generated.*'],\n },\n maxDepth: 20,\n },\n\n risk: {\n weights: {\n hub: 30,\n typeProvider: 25,\n complexity: 15,\n recency: 15,\n config: 10,\n churn: 5,\n },\n },\n\n interaction: {\n defaultBudget: 50_000,\n defaultModel: 'claude-sonnet-4',\n },\n\n tokens: {\n method: 'chars4',\n },\n\n governance: {\n auditEnabled: true,\n secretDetection: true,\n retentionDays: 90,\n },\n};\n","import { encodingForModel } from 'js-tiktoken';\nimport { readFile, stat } from 'node:fs/promises';\n\nconst CHARS_PER_TOKEN = 4;\n\nlet encoder: ReturnType<typeof encodingForModel> | null = null;\n\nfunction getEncoder() {\n if (!encoder) {\n encoder = encodingForModel('claude-3-5-sonnet-20241022' as Parameters<typeof encodingForModel>[0]);\n }\n return encoder;\n}\n\nexport function countTokensTiktoken(text: string): number {\n try {\n const enc = getEncoder();\n const tokens = enc.encode(text);\n return tokens.length;\n } catch {\n return Math.ceil(text.length / CHARS_PER_TOKEN);\n }\n}\n\nexport function countTokensChars4(sizeInBytes: number): number {\n return Math.ceil(sizeInBytes / CHARS_PER_TOKEN);\n}\n\nexport function estimateTokens(\n content: string,\n sizeInBytes: number,\n method: 'chars4' | 'tiktoken' = 'chars4',\n): number {\n if (method === 'tiktoken') {\n return countTokensTiktoken(content);\n }\n return countTokensChars4(sizeInBytes);\n}\n\nexport async function estimateFileTokens(\n filePath: string,\n method: 'chars4' | 'tiktoken' = 'chars4',\n): Promise<number> {\n if (method === 'chars4') {\n const s = await stat(filePath);\n return countTokensChars4(s.size);\n }\n\n try {\n const content = await readFile(filePath, 'utf-8');\n return countTokensTiktoken(content);\n } catch {\n const s = await stat(filePath);\n return countTokensChars4(s.size);\n }\n}\n\nexport function freeEncoder(): void {\n encoder = null;\n}\n","import { Project, SyntaxKind, type SourceFile, type Node } from 'ts-morph';\nimport { resolve, relative, dirname, join, basename } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport type {\n AnalyzedFile,\n ProjectGraph,\n GraphEdge,\n HubNode,\n FileCluster,\n} from '../types/engine.js';\n\nconst TS_EXTENSIONS = new Set(['ts', 'tsx', 'js', 'jsx', 'mts', 'mjs', 'cts', 'cjs']);\n\n// ===== PROJECT CREATION =====\n\nexport function createProject(projectPath: string, filePaths: string[]): Project {\n const tsConfigPath = join(projectPath, 'tsconfig.json');\n const hasTsConfig = existsSync(tsConfigPath);\n\n const project = new Project({\n tsConfigFilePath: hasTsConfig ? tsConfigPath : undefined,\n skipAddingFilesFromTsConfig: true,\n compilerOptions: hasTsConfig\n ? undefined\n : {\n allowJs: true,\n jsx: 4 as any, // JsxEmit.ReactJSX\n esModuleInterop: true,\n moduleResolution: 100 as any, // Bundler\n },\n });\n\n const tsFiles = filePaths.filter((f) => {\n const ext = f.split('.').pop()?.toLowerCase() ?? '';\n return TS_EXTENSIONS.has(ext);\n });\n\n for (const filePath of tsFiles) {\n try {\n project.addSourceFileAtPath(filePath);\n } catch {\n // skip files that can't be parsed\n }\n }\n\n return project;\n}\n\n// ===== DEPENDENCY GRAPH =====\n\nexport function buildProjectGraph(\n projectPath: string,\n files: AnalyzedFile[],\n): ProjectGraph {\n const absPath = resolve(projectPath);\n\n const tsFiles = files\n .filter((f) => TS_EXTENSIONS.has(f.extension))\n .map((f) => f.path);\n\n if (tsFiles.length === 0) {\n return emptyGraph(files);\n }\n\n let project: Project;\n try {\n project = createProject(projectPath, tsFiles);\n } catch {\n return emptyGraph(files);\n }\n\n const edges: GraphEdge[] = [];\n const nodeSet = new Set<string>();\n\n for (const sourceFile of project.getSourceFiles()) {\n const fromRel = relative(absPath, sourceFile.getFilePath());\n if (fromRel.startsWith('..') || fromRel.includes('node_modules')) continue;\n nodeSet.add(fromRel);\n\n // Imports\n for (const imp of sourceFile.getImportDeclarations()) {\n const moduleSpecifier = imp.getModuleSpecifierValue();\n const resolved = resolveImport(sourceFile, moduleSpecifier, absPath);\n if (resolved) {\n nodeSet.add(resolved);\n edges.push({ from: fromRel, to: resolved, type: 'import' });\n }\n }\n\n // Re-exports\n for (const exp of sourceFile.getExportDeclarations()) {\n const moduleSpecifier = exp.getModuleSpecifierValue();\n if (moduleSpecifier) {\n const resolved = resolveImport(sourceFile, moduleSpecifier, absPath);\n if (resolved) {\n nodeSet.add(resolved);\n edges.push({ from: fromRel, to: resolved, type: 're-export' });\n }\n }\n }\n }\n\n const nodes = Array.from(nodeSet);\n\n // Calculate import counts\n const importedByCount = new Map<string, number>();\n const importCount = new Map<string, number>();\n\n for (const edge of edges) {\n importedByCount.set(edge.to, (importedByCount.get(edge.to) ?? 0) + 1);\n importCount.set(edge.from, (importCount.get(edge.from) ?? 0) + 1);\n }\n\n // Identify hubs using normalized in-degree centrality (Freeman, 1978).\n // centrality = in-degree / (N - 1), then combined with out-degree for a\n // \"betweenness-lite\" score: score = (in-degree × 2 + out-degree) / (N - 1 + 1)\n // This normalizes by graph size so hub detection is consistent across projects.\n const N = Math.max(nodes.length, 1);\n const hubs: HubNode[] = nodes\n .map((node) => {\n const inDeg = importedByCount.get(node) ?? 0;\n const outDeg = importCount.get(node) ?? 0;\n // Normalized centrality score (0-100 scale)\n const centrality = N > 1 ? (inDeg / (N - 1)) * 100 : 0;\n const score = Math.round(centrality + outDeg * (100 / (2 * N)));\n return {\n relativePath: node,\n dependents: inDeg,\n dependencies: outDeg,\n score: Math.min(100, score),\n };\n })\n .filter((h) => h.dependents >= 3 || h.score >= 15)\n .sort((a, b) => b.score - a.score);\n\n // Identify leaves (files that import but are not imported by anyone)\n const leaves = nodes.filter(\n (node) => (importedByCount.get(node) ?? 0) === 0 && (importCount.get(node) ?? 0) > 0,\n );\n\n // Identify orphans (files with no connections at all)\n const connectedNodes = new Set<string>();\n for (const edge of edges) {\n connectedNodes.add(edge.from);\n connectedNodes.add(edge.to);\n }\n const allFileNodes = new Set(files.map((f) => f.relativePath));\n const orphans = Array.from(allFileNodes).filter((n) => !connectedNodes.has(n));\n\n // Detect clusters using Union-Find for true connected components,\n // then refine with directory grouping for naming.\n const clusters = detectClusters(nodes, edges, files);\n\n // Enrich files with complexity (AST-based)\n enrichComplexity(project, absPath, files);\n\n return { nodes, edges, hubs, leaves, orphans, clusters };\n}\n\n// ===== CLUSTER DETECTION (Union-Find + directory naming) =====\n\nclass UnionFind {\n parent: Map<string, string>;\n rank: Map<string, number>;\n\n constructor(nodes: string[]) {\n this.parent = new Map();\n this.rank = new Map();\n for (const n of nodes) {\n this.parent.set(n, n);\n this.rank.set(n, 0);\n }\n }\n\n find(x: string): string {\n const p = this.parent.get(x);\n if (p === undefined) return x;\n if (p !== x) {\n this.parent.set(x, this.find(p)); // path compression\n }\n return this.parent.get(x)!;\n }\n\n union(a: string, b: string): void {\n const ra = this.find(a);\n const rb = this.find(b);\n if (ra === rb) return;\n const rankA = this.rank.get(ra) ?? 0;\n const rankB = this.rank.get(rb) ?? 0;\n if (rankA < rankB) {\n this.parent.set(ra, rb);\n } else if (rankA > rankB) {\n this.parent.set(rb, ra);\n } else {\n this.parent.set(rb, ra);\n this.rank.set(ra, rankA + 1);\n }\n }\n}\n\nfunction detectClusters(\n nodes: string[],\n edges: GraphEdge[],\n files: AnalyzedFile[],\n): FileCluster[] {\n // 1. Build connected components using Union-Find (O(E × α(V)))\n const uf = new UnionFind(nodes);\n for (const edge of edges) {\n uf.union(edge.from, edge.to);\n }\n\n // 2. Group by component root\n const components = new Map<string, string[]>();\n for (const node of nodes) {\n const root = uf.find(node);\n if (!components.has(root)) components.set(root, []);\n components.get(root)!.push(node);\n }\n\n // 3. For each component, derive a human-readable name from common directory prefix\n const tokenMap = new Map(files.map((f) => [f.relativePath, f.tokens]));\n const clusters: FileCluster[] = [];\n\n for (const [, groupFiles] of components) {\n if (groupFiles.length < 2) continue;\n\n // Find common directory prefix for naming\n const name = commonPrefix(groupFiles);\n const fileSet = new Set(groupFiles);\n let internalEdges = 0;\n let externalEdges = 0;\n\n for (const edge of edges) {\n const fromIn = fileSet.has(edge.from);\n const toIn = fileSet.has(edge.to);\n if (fromIn && toIn) internalEdges++;\n else if (fromIn || toIn) externalEdges++;\n }\n\n const totalEdges = internalEdges + externalEdges;\n const cohesion = totalEdges > 0 ? internalEdges / totalEdges : 0;\n const totalTokens = groupFiles.reduce((s, f) => s + (tokenMap.get(f) ?? 0), 0);\n\n clusters.push({\n id: name.replace(/[^a-zA-Z0-9]/g, '-') || `cluster-${clusters.length}`,\n name: name || `cluster-${clusters.length}`,\n files: groupFiles,\n totalTokens,\n internalEdges,\n externalEdges,\n cohesion: Math.round(cohesion * 100) / 100,\n });\n }\n\n return clusters.sort((a, b) => b.files.length - a.files.length);\n}\n\nfunction commonPrefix(paths: string[]): string {\n if (paths.length === 0) return '';\n const parts = paths.map((p) => p.split('/'));\n const prefix: string[] = [];\n for (let i = 0; i < parts[0].length - 1; i++) {\n const segment = parts[0][i];\n if (parts.every((p) => p[i] === segment)) {\n prefix.push(segment);\n } else break;\n }\n return prefix.join('/') || parts[0][0];\n}\n\n// ===== COMPLEXITY ANALYSIS =====\n\nfunction enrichComplexity(\n project: Project,\n absPath: string,\n files: AnalyzedFile[],\n): void {\n const fileMap = new Map(files.map((f) => [f.relativePath, f]));\n\n for (const sourceFile of project.getSourceFiles()) {\n const relPath = relative(absPath, sourceFile.getFilePath());\n if (relPath.startsWith('..') || relPath.includes('node_modules')) continue;\n\n const file = fileMap.get(relPath);\n if (!file) continue;\n\n let totalComplexity = 0;\n\n // Function declarations\n for (const func of sourceFile.getFunctions()) {\n totalComplexity += calculateCyclomaticComplexity(func);\n }\n\n // Class methods\n for (const cls of sourceFile.getClasses()) {\n for (const method of cls.getMethods()) {\n totalComplexity += calculateCyclomaticComplexity(method);\n }\n }\n\n // Arrow functions assigned to variables\n for (const varDecl of sourceFile.getVariableDeclarations()) {\n const init = varDecl.getInitializer();\n if (init && (init.getKind() === SyntaxKind.ArrowFunction || init.getKind() === SyntaxKind.FunctionExpression)) {\n totalComplexity += calculateCyclomaticComplexity(init);\n }\n }\n\n file.complexity = Math.max(1, totalComplexity);\n }\n}\n\nfunction calculateCyclomaticComplexity(node: Node): number {\n let complexity = 1;\n\n node.forEachDescendant((descendant) => {\n switch (descendant.getKind()) {\n case SyntaxKind.IfStatement:\n case SyntaxKind.ConditionalExpression:\n case SyntaxKind.ForStatement:\n case SyntaxKind.ForInStatement:\n case SyntaxKind.ForOfStatement:\n case SyntaxKind.WhileStatement:\n case SyntaxKind.DoStatement:\n case SyntaxKind.CaseClause:\n case SyntaxKind.CatchClause:\n complexity++;\n break;\n case SyntaxKind.BinaryExpression: {\n // FIX: Check the operator token kind directly instead of getText()\n // to avoid double-counting nested logical expressions.\n // getText() on `a && (b || c)` returns the full text including\n // the inner `||`, which would match both operators from the outer node.\n const opToken = (descendant as any).getOperatorToken?.();\n if (opToken) {\n const kind = opToken.getKind();\n if (\n kind === SyntaxKind.AmpersandAmpersandToken ||\n kind === SyntaxKind.BarBarToken ||\n kind === SyntaxKind.QuestionQuestionToken\n ) {\n complexity++;\n }\n }\n break;\n }\n }\n });\n\n return complexity;\n}\n\n// ===== IMPORT RESOLUTION =====\n\nfunction resolveImport(\n sourceFile: SourceFile,\n moduleSpecifier: string,\n projectRoot: string,\n): string | null {\n if (!moduleSpecifier.startsWith('.')) return null;\n\n const sourceDir = dirname(sourceFile.getFilePath());\n const basePath = resolve(sourceDir, moduleSpecifier);\n\n const extensions = ['.ts', '.tsx', '.js', '.jsx', '/index.ts', '/index.tsx', '/index.js', '/index.jsx'];\n\n for (const ext of extensions) {\n const candidate = basePath.endsWith(ext) ? basePath : basePath + ext;\n if (existsSync(candidate)) {\n const rel = relative(projectRoot, candidate);\n if (!rel.startsWith('..')) return rel;\n }\n }\n\n // .js → .ts resolution\n if (moduleSpecifier.endsWith('.js')) {\n const tsPath = basePath.replace(/\\.js$/, '.ts');\n if (existsSync(tsPath)) {\n const rel = relative(projectRoot, tsPath);\n if (!rel.startsWith('..')) return rel;\n }\n }\n\n return null;\n}\n\n// ===== HELPERS =====\n\nfunction emptyGraph(files: AnalyzedFile[]): ProjectGraph {\n return {\n nodes: files.map((f) => f.relativePath),\n edges: [],\n hubs: [],\n leaves: [],\n orphans: files.map((f) => f.relativePath),\n clusters: [],\n };\n}\n","import type {\n AnalyzedFile,\n RiskFactor,\n RiskFactorType,\n RiskWeights,\n ExclusionImpact,\n ProjectGraph,\n} from '../types/engine.js';\nimport { DEFAULT_RISK_WEIGHTS } from '../types/engine.js';\n\n// ===== RISK SCORING ENGINE =====\n//\n// Each file gets a riskScore ∈ [0, 100] representing the risk of EXCLUDING it\n// from AI context. Higher score = more dangerous to exclude.\n//\n// riskScore(file) = Σ(factor.score × factor.weight) / Σ(factor.weight)\n\nexport function scoreAllFiles(\n files: AnalyzedFile[],\n graph: ProjectGraph,\n weights: RiskWeights = DEFAULT_RISK_WEIGHTS,\n): void {\n // Pre-compute type provider map: files that export types used by others\n const typeProviderUsage = computeTypeProviderUsage(files, graph);\n\n for (const file of files) {\n const factors = computeRiskFactors(file, graph, typeProviderUsage, weights);\n file.riskFactors = factors;\n file.riskScore = computeWeightedScore(factors);\n file.exclusionImpact = scoreToImpact(file.riskScore);\n }\n}\n\nexport function scoreFile(\n file: AnalyzedFile,\n graph: ProjectGraph,\n weights: RiskWeights = DEFAULT_RISK_WEIGHTS,\n): number {\n const typeProviderUsage = computeTypeProviderUsage([file], graph);\n const factors = computeRiskFactors(file, graph, typeProviderUsage, weights);\n file.riskFactors = factors;\n file.riskScore = computeWeightedScore(factors);\n file.exclusionImpact = scoreToImpact(file.riskScore);\n return file.riskScore;\n}\n\n// ===== FACTOR COMPUTATION =====\n\nfunction computeRiskFactors(\n file: AnalyzedFile,\n graph: ProjectGraph,\n typeProviderUsage: Map<string, number>,\n weights: RiskWeights,\n): RiskFactor[] {\n const factors: RiskFactor[] = [];\n\n // 1. Hub factor — how many files depend on this file\n factors.push(computeHubFactor(file, weights.hub));\n\n // 2. Type provider factor — exports types used by other files\n factors.push(computeTypeProviderFactor(file, typeProviderUsage, weights.typeProvider));\n\n // 3. Complexity factor — cyclomatic complexity\n factors.push(computeComplexityFactor(file, weights.complexity));\n\n // 4. Recency factor — how recently modified\n factors.push(computeRecencyFactor(file, weights.recency));\n\n // 5. Config factor — is it a config or entry point\n factors.push(computeConfigFactor(file, weights.config));\n\n // 6. Churn factor — based on complexity as proxy (git integration deferred)\n factors.push(computeChurnFactor(file, weights.churn));\n\n return factors;\n}\n\nfunction computeHubFactor(file: AnalyzedFile, weight: number): RiskFactor {\n const dependents = file.importedBy.length;\n\n // Logarithmic scaling: score = min(100, 100 × log₂(1 + dependents) / log₂(1 + K))\n // K=12 means 12 dependents → score 100. Based on information theory:\n // each doubling of dependents adds equal marginal risk.\n const K = 12;\n const score = dependents === 0\n ? 0\n : Math.min(100, Math.round(100 * Math.log2(1 + dependents) / Math.log2(1 + K)));\n\n const detail = dependents === 0\n ? 'No dependents'\n : `Hub: ${dependents} file(s) depend on this (score ${score}/100)`;\n\n return { type: 'hub', score, weight, detail };\n}\n\nfunction computeTypeProviderFactor(\n file: AnalyzedFile,\n usage: Map<string, number>,\n weight: number,\n): RiskFactor {\n const isTypeFile = file.kind === 'type';\n const consumers = usage.get(file.relativePath) ?? 0;\n\n let score: number;\n let detail: string;\n\n if (isTypeFile && consumers >= 4) {\n score = 100;\n detail = `Type provider: used by ${consumers} files (critical type source)`;\n } else if (isTypeFile && consumers >= 1) {\n score = 50;\n detail = `Type provider: used by ${consumers} files`;\n } else if (isTypeFile) {\n score = 30;\n detail = 'Type file (no detected consumers)';\n } else {\n score = 0;\n detail = 'Not a type provider';\n }\n\n return { type: 'type-provider', score, weight, detail };\n}\n\nfunction computeComplexityFactor(file: AnalyzedFile, weight: number): RiskFactor {\n const c = file.complexity;\n\n // Logarithmic scaling: score = min(100, 100 × ln(1 + c) / ln(1 + K))\n // K=30 means complexity 30 → score 100. ln provides diminishing returns\n // for very complex files (consistent with McCabe 1976 thresholds).\n const K = 30;\n const score = Math.min(100, Math.round(100 * Math.log(1 + c) / Math.log(1 + K)));\n\n const detail = c >= 30\n ? `Very high complexity: ${c} (AI needs full context)`\n : c >= 10\n ? `High complexity: ${c}`\n : `Complexity: ${c}`;\n\n return { type: 'complexity', score, weight, detail };\n}\n\nfunction computeRecencyFactor(file: AnalyzedFile, weight: number): RiskFactor {\n const now = Date.now();\n const modified = new Date(file.lastModified).getTime();\n const daysAgo = (now - modified) / (1000 * 60 * 60 * 24);\n\n // Exponential decay with half-life of 7 days.\n // score = 100 × 2^(-daysAgo / halfLife)\n // This is the standard temporal decay model used in information retrieval\n // (Lv & Zhai, 2011 — \"Adaptive Relevance Feedback\").\n const HALF_LIFE = 7;\n const score = Math.round(100 * Math.pow(2, -daysAgo / HALF_LIFE));\n\n const detail = daysAgo <= 1\n ? 'Modified today'\n : `Modified ${Math.round(daysAgo)} days ago (decay score ${score})`;\n\n return { type: 'recency', score, weight, detail };\n}\n\nfunction computeConfigFactor(file: AnalyzedFile, weight: number): RiskFactor {\n let score: number;\n let detail: string;\n\n if (file.kind === 'entry') {\n score = 90;\n detail = 'Entry point — critical for understanding app structure';\n } else if (file.kind === 'config') {\n score = 80;\n detail = 'Configuration file — affects runtime behavior';\n } else {\n score = 0;\n detail = 'Regular source file';\n }\n\n return { type: 'config', score, weight, detail };\n}\n\nfunction computeChurnFactor(file: AnalyzedFile, weight: number): RiskFactor {\n // PROXY: Without git integration, approximate churn as geometric mean of\n // complexity signal and recency signal. This avoids double-weighting\n // (since complexity and recency have their own factors) by using the\n // *interaction* term only — high churn requires BOTH high complexity AND\n // recent modification simultaneously.\n //\n // TODO: Replace with real git churn (commit count in last 30 days) when\n // git integration is added. Proxy weight is intentionally low (5%).\n const complexitySignal = Math.min(file.complexity / 20, 1);\n const now = Date.now();\n const daysAgo = (now - new Date(file.lastModified).getTime()) / (1000 * 60 * 60 * 24);\n const recencySignal = Math.pow(2, -daysAgo / 7); // same half-life as recency factor\n\n // Geometric mean ensures both signals must be high for a high score\n const score = Math.round(Math.sqrt(complexitySignal * recencySignal) * 100);\n const detail = score >= 50\n ? 'Likely under active development (complex + recent)'\n : score >= 20\n ? 'Some recent activity'\n : 'Stable — low churn (proxy estimate)';\n\n return { type: 'churn', score, weight, detail };\n}\n\n// ===== HELPERS =====\n\nfunction computeWeightedScore(factors: RiskFactor[]): number {\n let totalWeightedScore = 0;\n let totalWeight = 0;\n\n for (const factor of factors) {\n totalWeightedScore += factor.score * factor.weight;\n totalWeight += factor.weight;\n }\n\n if (totalWeight === 0) return 0;\n return Math.round(totalWeightedScore / totalWeight);\n}\n\nfunction scoreToImpact(score: number): ExclusionImpact {\n if (score >= 80) return 'critical';\n if (score >= 60) return 'high';\n if (score >= 30) return 'medium';\n if (score > 0) return 'low';\n return 'none';\n}\n\nfunction computeTypeProviderUsage(\n files: AnalyzedFile[],\n graph: ProjectGraph,\n): Map<string, number> {\n const usage = new Map<string, number>();\n\n // Count how many files import each type file\n const typeFiles = new Set(\n files.filter((f) => f.kind === 'type').map((f) => f.relativePath),\n );\n\n for (const edge of graph.edges) {\n if (typeFiles.has(edge.to)) {\n usage.set(edge.to, (usage.get(edge.to) ?? 0) + 1);\n }\n }\n\n return usage;\n}\n","import type { GraphEdge } from '../types/engine.js';\n\n// ===== SHARED GRAPH UTILITIES =====\n\nexport interface AdjacencyList {\n forward: Map<string, string[]>; // file → files it imports\n reverse: Map<string, string[]>; // file → files that import it\n}\n\nexport function buildAdjacencyList(edges: GraphEdge[]): AdjacencyList {\n const forward = new Map<string, string[]>();\n const reverse = new Map<string, string[]>();\n\n for (const edge of edges) {\n if (!forward.has(edge.from)) forward.set(edge.from, []);\n forward.get(edge.from)!.push(edge.to);\n\n if (!reverse.has(edge.to)) reverse.set(edge.to, []);\n reverse.get(edge.to)!.push(edge.from);\n }\n\n return { forward, reverse };\n}\n\nexport function bfsBidirectional(\n seeds: string[],\n adj: AdjacencyList,\n depth: number,\n): Set<string> {\n const result = new Set(seeds);\n let frontier = [...seeds];\n const visited = new Set<string>();\n\n for (let d = 0; d < depth; d++) {\n const nextFrontier: string[] = [];\n\n for (const node of frontier) {\n if (visited.has(node)) continue;\n visited.add(node);\n\n // Forward neighbors (imports)\n const fwd = adj.forward.get(node);\n if (fwd) {\n for (const neighbor of fwd) {\n if (!visited.has(neighbor)) {\n result.add(neighbor);\n nextFrontier.push(neighbor);\n }\n }\n }\n\n // Reverse neighbors (imported by)\n const rev = adj.reverse.get(node);\n if (rev) {\n for (const neighbor of rev) {\n if (!visited.has(neighbor)) {\n result.add(neighbor);\n nextFrontier.push(neighbor);\n }\n }\n }\n }\n\n frontier = nextFrontier;\n }\n\n return result;\n}\n\nexport function matchGlob(path: string, pattern: string): boolean {\n const regexStr = pattern\n .replace(/\\./g, '\\\\.')\n .replace(/\\*\\*/g, '§§')\n .replace(/\\*/g, '[^/]*')\n .replace(/§§/g, '.*')\n .replace(/\\?/g, '.');\n\n try {\n return new RegExp(`^${regexStr}$`).test(path);\n } catch {\n return false;\n }\n}\n","import { readFile, writeFile, mkdir } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { parse as parseYAML, stringify as stringifyYAML } from 'yaml';\nimport type { CTOConfig } from '../types/config.js';\nimport { DEFAULT_CONFIG } from '../types/config.js';\n\n// ===== CONFIG FILE SUPPORT =====\n//\n// Loads and saves .cto/config.yml per the ARCHITECTURE.md spec.\n// Deep-merges user config on top of DEFAULT_CONFIG so partial\n// configs work correctly.\n\nconst CONFIG_DIR = '.cto';\nconst CONFIG_FILE = 'config.yml';\nconst POLICY_FILE = 'policy.yml';\n\nexport function getConfigPath(projectPath: string): string {\n return join(projectPath, CONFIG_DIR, CONFIG_FILE);\n}\n\nexport function getPolicyPath(projectPath: string): string {\n return join(projectPath, CONFIG_DIR, POLICY_FILE);\n}\n\nexport function getCTODir(projectPath: string): string {\n return join(projectPath, CONFIG_DIR);\n}\n\nexport async function loadConfig(projectPath: string): Promise<CTOConfig> {\n const configPath = getConfigPath(projectPath);\n\n if (!existsSync(configPath)) {\n return { ...DEFAULT_CONFIG };\n }\n\n try {\n const raw = await readFile(configPath, 'utf-8');\n const userConfig = parseYAML(raw) as Partial<CTOConfig>;\n return deepMerge(DEFAULT_CONFIG, userConfig) as CTOConfig;\n } catch {\n return { ...DEFAULT_CONFIG };\n }\n}\n\nexport async function saveConfig(\n projectPath: string,\n config: CTOConfig,\n): Promise<string> {\n const ctoDir = getCTODir(projectPath);\n await mkdir(ctoDir, { recursive: true });\n\n const configPath = getConfigPath(projectPath);\n const yamlContent = stringifyYAML(config, { indent: 2 });\n await writeFile(configPath, yamlContent, 'utf-8');\n return configPath;\n}\n\nexport async function initProjectConfig(projectPath: string): Promise<{\n configPath: string;\n policyPath: string;\n created: string[];\n}> {\n const ctoDir = getCTODir(projectPath);\n await mkdir(join(ctoDir, 'snapshots'), { recursive: true });\n\n const created: string[] = [];\n\n // Create config.yml if it doesn't exist\n const configPath = getConfigPath(projectPath);\n if (!existsSync(configPath)) {\n await saveConfig(projectPath, DEFAULT_CONFIG);\n created.push(configPath);\n }\n\n // Create policy.yml if it doesn't exist\n const policyPath = getPolicyPath(projectPath);\n if (!existsSync(policyPath)) {\n const defaultPolicy = {\n version: '1.0',\n name: 'default',\n rules: [\n {\n id: 'types-always',\n type: 'include-always',\n pattern: '**/types/**',\n reason: 'Type definitions provide essential context',\n enabled: true,\n },\n {\n id: 'no-env',\n type: 'exclude-always',\n pattern: '**/*.env*',\n reason: 'Environment files must never be sent to AI',\n enabled: true,\n },\n {\n id: 'no-secrets',\n type: 'secret-block',\n reason: 'Files with detected secrets are blocked',\n enabled: true,\n },\n {\n id: 'test-budget',\n type: 'budget-limit',\n category: 'test',\n threshold: 20,\n reason: 'Test files should not exceed 20% of budget',\n enabled: true,\n },\n {\n id: 'min-coverage',\n type: 'coverage-minimum',\n threshold: 70,\n reason: 'Warn if context coverage drops below 70%',\n enabled: true,\n },\n ],\n };\n const yamlContent = stringifyYAML(defaultPolicy, { indent: 2 });\n await writeFile(policyPath, yamlContent, 'utf-8');\n created.push(policyPath);\n }\n\n return { configPath, policyPath, created };\n}\n\nexport async function loadPolicyFromYAML(projectPath: string): Promise<import('../types/govern.js').PolicySet | null> {\n const policyPath = getPolicyPath(projectPath);\n if (!existsSync(policyPath)) return null;\n\n try {\n const raw = await readFile(policyPath, 'utf-8');\n return parseYAML(raw) as import('../types/govern.js').PolicySet;\n } catch {\n return null;\n }\n}\n\n// ===== HELPERS =====\n\nfunction deepMerge(target: Record<string, any>, source: Record<string, any>): Record<string, any> {\n const result = { ...target };\n\n for (const key of Object.keys(source)) {\n if (\n source[key] !== null &&\n typeof source[key] === 'object' &&\n !Array.isArray(source[key]) &&\n typeof target[key] === 'object' &&\n !Array.isArray(target[key])\n ) {\n result[key] = deepMerge(target[key], source[key]);\n } else if (source[key] !== undefined) {\n result[key] = source[key];\n }\n }\n\n return result;\n}\n","import { createHash } from 'node:crypto';\nimport { readdir, stat } from 'node:fs/promises';\nimport { join, extname, relative, resolve } from 'node:path';\nimport type { ProjectAnalysis } from '../types/engine.js';\nimport type { CTOConfig } from '../types/config.js';\nimport { DEFAULT_CONFIG } from '../types/config.js';\nimport { analyzeProject } from './analyzer.js';\n\n// ===== Analysis Cache =====\n//\n// Problem: analyzeProject() is expensive (file walk + AST parse + token count + graph build).\n// MCP tools and CLI commands call it on every invocation.\n//\n// Solution: Two-level cache with lightweight fingerprint invalidation.\n// 1. Compute a fast fingerprint: hash of (sorted file paths + mtimes)\n// Cost: O(n) readdir + stat, no file reads, no AST, no token counting\n// 2. If fingerprint matches cached entry → return cached analysis (instant)\n// 3. If fingerprint differs → full re-analysis, update cache\n//\n// TTL: Safety net. Even if fingerprint matches, expire after maxAgeMs.\n//\n// Reference: Content-addressable caching (Git object model principle)\n\ninterface CacheEntry {\n analysis: ProjectAnalysis;\n fingerprint: string;\n createdAt: number;\n hits: number;\n}\n\ninterface CacheOptions {\n maxAgeMs: number;\n maxEntries: number;\n enabled: boolean;\n}\n\nconst DEFAULT_CACHE_OPTIONS: CacheOptions = {\n maxAgeMs: 5 * 60 * 1000, // 5 minutes\n maxEntries: 10,\n enabled: true,\n};\n\n// In-memory LRU-ish cache\nconst cache = new Map<string, CacheEntry>();\nlet cacheOptions: CacheOptions = { ...DEFAULT_CACHE_OPTIONS };\n\n// ===== FINGERPRINT =====\n\n// Fast fingerprint: walk directory, collect paths + mtimes, hash them.\n// ~10-100x faster than full analysis (no file reads, no AST, no tokenization).\nasync function computeFingerprint(\n rootPath: string,\n config: CTOConfig = DEFAULT_CONFIG,\n): Promise<string> {\n const entries: string[] = [];\n const allExtensions = new Set([\n ...config.analysis.extensions.code,\n ...config.analysis.extensions.config,\n ...config.analysis.extensions.docs,\n ]);\n const ignoreDirSet = new Set(config.analysis.ignore.dirs);\n\n async function walk(dir: string, depth: number): Promise<void> {\n if (depth > config.analysis.maxDepth) return;\n\n let dirEntries;\n try {\n dirEntries = await readdir(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n const promises: Promise<void>[] = [];\n\n for (const entry of dirEntries) {\n const fullPath = join(dir, entry.name);\n\n if (entry.isDirectory()) {\n if (!ignoreDirSet.has(entry.name) && !entry.name.startsWith('.')) {\n promises.push(walk(fullPath, depth + 1));\n }\n } else if (entry.isFile()) {\n const ext = extname(entry.name).slice(1).toLowerCase();\n if (ext && allExtensions.has(ext)) {\n promises.push(\n (async () => {\n try {\n const s = await stat(fullPath);\n const rel = relative(rootPath, fullPath);\n // Include path + mtime + size for change detection\n entries.push(`${rel}:${s.mtimeMs.toFixed(0)}:${s.size}`);\n } catch {\n // skip inaccessible files\n }\n })(),\n );\n }\n }\n }\n\n await Promise.all(promises);\n }\n\n await walk(rootPath, 0);\n\n // Sort for determinism\n entries.sort();\n return createHash('sha256').update(entries.join('|')).digest('hex').substring(0, 16);\n}\n\n// ===== PUBLIC API =====\n\n/**\n * Get a project analysis, using cache when possible.\n *\n * Cache hit: ~1-5ms (fingerprint check only)\n * Cache miss: full analyzeProject() + cache update\n */\nexport async function getCachedAnalysis(\n projectPath: string,\n config?: Partial<CTOConfig>,\n): Promise<ProjectAnalysis> {\n const absPath = resolve(projectPath);\n\n if (!cacheOptions.enabled) {\n return analyzeProject(absPath, config);\n }\n\n const existing = cache.get(absPath);\n\n // Check TTL first (cheap)\n if (existing) {\n const age = Date.now() - existing.createdAt;\n if (age > cacheOptions.maxAgeMs) {\n cache.delete(absPath);\n }\n }\n\n // Compute fingerprint\n const mergedConfig = config\n ? { ...DEFAULT_CONFIG, ...config } as CTOConfig\n : DEFAULT_CONFIG;\n const fingerprint = await computeFingerprint(absPath, mergedConfig);\n\n // Cache hit: fingerprint matches\n const cached = cache.get(absPath);\n if (cached && cached.fingerprint === fingerprint) {\n cached.hits++;\n return cached.analysis;\n }\n\n // Cache miss: full analysis\n const analysis = await analyzeProject(absPath, config);\n\n // Evict oldest entry if at capacity\n if (cache.size >= cacheOptions.maxEntries) {\n const oldest = [...cache.entries()].sort(\n (a, b) => a[1].createdAt - b[1].createdAt,\n )[0];\n if (oldest) cache.delete(oldest[0]);\n }\n\n cache.set(absPath, {\n analysis,\n fingerprint,\n createdAt: Date.now(),\n hits: 0,\n });\n\n return analysis;\n}\n\n/**\n * Invalidate cache for a specific project (e.g., after a known file change).\n */\nexport function invalidateCache(projectPath?: string): void {\n if (projectPath) {\n cache.delete(resolve(projectPath));\n } else {\n cache.clear();\n }\n}\n\n/**\n * Get cache statistics for debugging/monitoring.\n */\nexport function getCacheStats(): {\n entries: number;\n totalHits: number;\n projects: { path: string; hits: number; ageMs: number }[];\n} {\n const now = Date.now();\n const projects = [...cache.entries()].map(([path, entry]) => ({\n path,\n hits: entry.hits,\n ageMs: now - entry.createdAt,\n }));\n\n return {\n entries: cache.size,\n totalHits: projects.reduce((s, p) => s + p.hits, 0),\n projects,\n };\n}\n\n/**\n * Configure cache behavior.\n */\nexport function configureCache(options: Partial<CacheOptions>): void {\n cacheOptions = { ...cacheOptions, ...options };\n if (!cacheOptions.enabled) {\n cache.clear();\n }\n}\n","import chokidar from 'chokidar';\nimport { resolve } from 'node:path';\nimport { EventEmitter } from 'node:events';\nimport type { CTOConfig } from '../types/config.js';\nimport { DEFAULT_CONFIG } from '../types/config.js';\nimport { invalidateCache } from './cache.js';\n\n// ===== Project Watcher =====\n//\n// Watches a project directory for file changes and invalidates the analysis cache.\n// Designed for long-running processes (MCP server, CLI watch mode).\n//\n// Key properties:\n// - Debounced: coalesces rapid changes into one cache invalidation\n// - Lightweight: no re-analysis on change, just cache invalidation\n// - Auto-managed: watchProject() returns a handle to stop watching\n// - Observable: emits events for logging/UI\n\nexport interface WatcherOptions {\n debounceMs?: number;\n config?: Partial<CTOConfig>;\n}\n\nexport interface FileChangeEvent {\n type: 'add' | 'change' | 'unlink';\n path: string;\n timestamp: Date;\n}\n\nexport class ProjectWatcher extends EventEmitter {\n private watcher: chokidar.FSWatcher | null = null;\n private projectPath: string;\n private debounceMs: number;\n private config: CTOConfig;\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private pendingChanges: FileChangeEvent[] = [];\n private running = false;\n\n constructor(projectPath: string, options: WatcherOptions = {}) {\n super();\n this.projectPath = resolve(projectPath);\n this.debounceMs = options.debounceMs ?? 500;\n this.config = { ...DEFAULT_CONFIG, ...options.config } as CTOConfig;\n }\n\n async start(): Promise<void> {\n if (this.running) return;\n\n const allExtensions = [\n ...this.config.analysis.extensions.code,\n ...this.config.analysis.extensions.config,\n ...this.config.analysis.extensions.docs,\n ];\n\n const globs = allExtensions.map((ext) => `**/*.${ext}`);\n\n this.watcher = chokidar.watch(globs, {\n cwd: this.projectPath,\n ignored: [\n ...this.config.analysis.ignore.dirs.map((d) => `**/${d}/**`),\n ...this.config.analysis.ignore.patterns,\n ],\n persistent: true,\n ignoreInitial: true,\n awaitWriteFinish: {\n stabilityThreshold: 200,\n pollInterval: 50,\n },\n });\n\n this.watcher.on('add', (path) => this.handleEvent('add', path));\n this.watcher.on('change', (path) => this.handleEvent('change', path));\n this.watcher.on('unlink', (path) => this.handleEvent('unlink', path));\n this.watcher.on('error', (error) => this.emit('error', error));\n\n this.running = true;\n this.emit('started', { projectPath: this.projectPath });\n }\n\n async stop(): Promise<void> {\n if (!this.running) return;\n\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n\n // Flush any pending changes\n if (this.pendingChanges.length > 0) {\n this.flush();\n }\n\n if (this.watcher) {\n await this.watcher.close();\n this.watcher = null;\n }\n\n this.running = false;\n this.emit('stopped', { projectPath: this.projectPath });\n }\n\n isRunning(): boolean {\n return this.running;\n }\n\n getProjectPath(): string {\n return this.projectPath;\n }\n\n private handleEvent(type: FileChangeEvent['type'], filePath: string): void {\n const event: FileChangeEvent = {\n type,\n path: filePath,\n timestamp: new Date(),\n };\n\n this.pendingChanges.push(event);\n this.emit('fileChange', event);\n\n // Debounce: coalesce rapid changes into one cache invalidation\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n }\n\n this.debounceTimer = setTimeout(() => {\n this.flush();\n }, this.debounceMs);\n }\n\n private flush(): void {\n const changes = [...this.pendingChanges];\n this.pendingChanges = [];\n\n if (changes.length === 0) return;\n\n // Invalidate the cache for this project\n invalidateCache(this.projectPath);\n\n this.emit('cacheInvalidated', {\n projectPath: this.projectPath,\n changedFiles: changes.length,\n changes,\n });\n }\n}\n\n// ===== Managed Watchers =====\n//\n// For long-running processes (MCP server): auto-watch projects,\n// one watcher per project, with cleanup on shutdown.\n\nconst activeWatchers = new Map<string, ProjectWatcher>();\n\n/**\n * Start watching a project. Returns the watcher instance.\n * If already watching, returns the existing watcher.\n */\nexport async function watchProject(\n projectPath: string,\n options?: WatcherOptions,\n): Promise<ProjectWatcher> {\n const absPath = resolve(projectPath);\n\n const existing = activeWatchers.get(absPath);\n if (existing && existing.isRunning()) {\n return existing;\n }\n\n const watcher = new ProjectWatcher(absPath, options);\n await watcher.start();\n activeWatchers.set(absPath, watcher);\n\n return watcher;\n}\n\n/**\n * Stop watching a specific project.\n */\nexport async function unwatchProject(projectPath: string): Promise<void> {\n const absPath = resolve(projectPath);\n const watcher = activeWatchers.get(absPath);\n if (watcher) {\n await watcher.stop();\n activeWatchers.delete(absPath);\n }\n}\n\n/**\n * Stop all active watchers. Call on process shutdown.\n */\nexport async function unwatchAll(): Promise<void> {\n const stopPromises = [...activeWatchers.values()].map((w) => w.stop());\n await Promise.all(stopPromises);\n activeWatchers.clear();\n}\n\n/**\n * Get all actively watched projects.\n */\nexport function getActiveWatchers(): { path: string; running: boolean }[] {\n return [...activeWatchers.entries()].map(([path, w]) => ({\n path,\n running: w.isRunning(),\n }));\n}\n","import { resolve } from 'node:path';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport type { ProjectAnalysis, AnalyzedFile } from '../types/engine.js';\nimport { buildAdjacencyList, bfsBidirectional } from './graph-utils.js';\n\n// ===== PR Context — Git-diff Aware Context Selection =====\n//\n// When the task is \"review this PR\", sending the entire project is wasteful.\n// This module:\n// 1. Extracts changed files from git diff (branch comparison or working dir)\n// 2. Expands to transitive dependencies using BFS on the adjacency list\n// 3. Prioritizes by risk score (high-risk changed files first)\n// 4. Returns a structured PR context with change categorization\n//\n// Complexity: O(|changed| × depth) for BFS expansion\n\nconst exec = promisify(execFile);\n\nasync function git(args: string[], cwd: string): Promise<string> {\n try {\n const { stdout } = await exec('git', args, { cwd, maxBuffer: 10 * 1024 * 1024 });\n return stdout.trim();\n } catch {\n return '';\n }\n}\n\n// ===== TYPES =====\n\nexport type ChangeType = 'added' | 'modified' | 'deleted' | 'renamed';\n\nexport interface ChangedFile {\n relativePath: string;\n changeType: ChangeType;\n linesAdded: number;\n linesRemoved: number;\n}\n\nexport interface PRContextResult {\n baseBranch: string;\n currentBranch: string;\n isGitRepo: boolean;\n\n changedFiles: ChangedFile[];\n dependencyFiles: string[];\n allRelevantFiles: AnalyzedFile[];\n\n totalChangedTokens: number;\n totalContextTokens: number;\n\n riskSummary: {\n critical: number;\n high: number;\n medium: number;\n low: number;\n maxRiskFile: string;\n maxRiskScore: number;\n };\n\n renderedSummary: string;\n}\n\nexport interface PRContextOptions {\n baseBranch?: string;\n depth?: number;\n includeTests?: boolean;\n}\n\n// ===== GIT OPERATIONS =====\n\nasync function isGitRepo(projectPath: string): Promise<boolean> {\n const result = await git(['rev-parse', '--is-inside-work-tree'], projectPath);\n return result === 'true';\n}\n\nasync function getCurrentBranch(projectPath: string): Promise<string> {\n return git(['rev-parse', '--abbrev-ref', 'HEAD'], projectPath);\n}\n\nasync function getChangedFilesFromDiff(\n projectPath: string,\n baseBranch?: string,\n): Promise<ChangedFile[]> {\n const results = new Map<string, ChangedFile>();\n\n // Working directory changes (unstaged)\n const workingDiff = await git(['diff', '--numstat', 'HEAD'], projectPath);\n parseDiffNumstat(workingDiff, results, 'modified');\n\n // Staged changes\n const stagedDiff = await git(['diff', '--numstat', '--cached'], projectPath);\n parseDiffNumstat(stagedDiff, results, 'modified');\n\n // Untracked files\n const untracked = await git(['ls-files', '--others', '--exclude-standard'], projectPath);\n for (const line of untracked.split('\\n')) {\n const f = line.trim();\n if (f && !results.has(f)) {\n results.set(f, { relativePath: f, changeType: 'added', linesAdded: 0, linesRemoved: 0 });\n }\n }\n\n // Branch comparison (if baseBranch provided)\n if (baseBranch) {\n // Check if base branch exists\n const branchExists = await git(['rev-parse', '--verify', baseBranch], projectPath);\n if (branchExists) {\n const branchDiff = await git(['diff', '--numstat', `${baseBranch}...HEAD`], projectPath);\n parseDiffNumstat(branchDiff, results, 'modified');\n\n // Detect newly added files (in HEAD but not in base)\n const nameStatus = await git(['diff', '--name-status', `${baseBranch}...HEAD`], projectPath);\n for (const line of nameStatus.split('\\n')) {\n const parts = line.trim().split('\\t');\n if (parts.length >= 2) {\n const status = parts[0];\n const filePath = parts[parts.length - 1];\n if (results.has(filePath)) {\n const existing = results.get(filePath)!;\n if (status === 'A') existing.changeType = 'added';\n else if (status === 'D') existing.changeType = 'deleted';\n else if (status.startsWith('R')) existing.changeType = 'renamed';\n }\n }\n }\n }\n }\n\n return [...results.values()];\n}\n\nfunction parseDiffNumstat(\n output: string,\n results: Map<string, ChangedFile>,\n defaultType: ChangeType,\n): void {\n for (const line of output.split('\\n')) {\n const parts = line.trim().split('\\t');\n if (parts.length < 3) continue;\n\n const added = parts[0] === '-' ? 0 : parseInt(parts[0], 10) || 0;\n const removed = parts[1] === '-' ? 0 : parseInt(parts[1], 10) || 0;\n const filePath = parts[2];\n\n if (!filePath) continue;\n\n const existing = results.get(filePath);\n if (existing) {\n existing.linesAdded = Math.max(existing.linesAdded, added);\n existing.linesRemoved = Math.max(existing.linesRemoved, removed);\n } else {\n results.set(filePath, {\n relativePath: filePath,\n changeType: defaultType,\n linesAdded: added,\n linesRemoved: removed,\n });\n }\n }\n}\n\n// ===== MAIN API =====\n\n/**\n * Generate PR-focused context by analyzing git changes and expanding dependencies.\n *\n * @param analysis - Project analysis (from analyzeProject or getCachedAnalysis)\n * @param options - PR context options (baseBranch, depth, includeTests)\n * @returns Structured PR context with changed files, dependencies, risk summary\n */\nexport async function generatePRContext(\n analysis: ProjectAnalysis,\n options: PRContextOptions = {},\n): Promise<PRContextResult> {\n const projectPath = resolve(analysis.projectPath);\n const baseBranch = options.baseBranch ?? 'main';\n const depth = options.depth ?? 2;\n const includeTests = options.includeTests ?? false;\n\n // Check git repo\n const gitRepo = await isGitRepo(projectPath);\n if (!gitRepo) {\n return emptyResult(baseBranch);\n }\n\n const currentBranch = await getCurrentBranch(projectPath);\n\n // 1. Get changed files from git\n const changedFiles = await getChangedFilesFromDiff(projectPath, baseBranch);\n\n if (changedFiles.length === 0) {\n return {\n ...emptyResult(baseBranch),\n currentBranch,\n isGitRepo: true,\n renderedSummary: '# PR Context\\n\\nNo changed files detected.',\n };\n }\n\n // 2. Filter to files that exist in our analysis\n const analysisFileSet = new Set(analysis.files.map((f) => f.relativePath));\n const validChangedPaths = changedFiles\n .filter((c) => c.changeType !== 'deleted' && analysisFileSet.has(c.relativePath))\n .map((c) => c.relativePath);\n\n // 3. Expand dependencies using BFS on adjacency list\n const adj = buildAdjacencyList(analysis.graph.edges);\n const expanded = bfsBidirectional(validChangedPaths, adj, depth);\n\n // Separate changed files from dependency-only files\n const changedSet = new Set(validChangedPaths);\n const dependencyFiles = [...expanded].filter((f) => !changedSet.has(f));\n\n // 4. Filter tests if not included\n const allRelevantPaths = new Set(expanded);\n if (!includeTests) {\n for (const path of allRelevantPaths) {\n const file = analysis.files.find((f) => f.relativePath === path);\n if (file && file.kind === 'test') {\n // Keep if it was directly changed, remove if it's a dependency\n if (!changedSet.has(path)) {\n allRelevantPaths.delete(path);\n }\n }\n }\n }\n\n // 5. Collect AnalyzedFile objects, sorted by risk score (descending)\n const allRelevantFiles = analysis.files\n .filter((f) => allRelevantPaths.has(f.relativePath))\n .sort((a, b) => b.riskScore - a.riskScore);\n\n // 6. Compute token totals\n const changedAnalyzed = allRelevantFiles.filter((f) => changedSet.has(f.relativePath));\n const totalChangedTokens = changedAnalyzed.reduce((s, f) => s + f.tokens, 0);\n const totalContextTokens = allRelevantFiles.reduce((s, f) => s + f.tokens, 0);\n\n // 7. Risk summary\n const riskSummary = {\n critical: allRelevantFiles.filter((f) => f.riskScore >= 80).length,\n high: allRelevantFiles.filter((f) => f.riskScore >= 60 && f.riskScore < 80).length,\n medium: allRelevantFiles.filter((f) => f.riskScore >= 30 && f.riskScore < 60).length,\n low: allRelevantFiles.filter((f) => f.riskScore < 30).length,\n maxRiskFile: allRelevantFiles[0]?.relativePath ?? '',\n maxRiskScore: allRelevantFiles[0]?.riskScore ?? 0,\n };\n\n // 8. Render summary\n const renderedSummary = renderSummary(\n analysis,\n currentBranch,\n baseBranch,\n changedFiles,\n dependencyFiles,\n allRelevantFiles,\n changedSet,\n riskSummary,\n totalChangedTokens,\n totalContextTokens,\n );\n\n return {\n baseBranch,\n currentBranch,\n isGitRepo: true,\n changedFiles,\n dependencyFiles: dependencyFiles.filter((f) => allRelevantPaths.has(f)),\n allRelevantFiles,\n totalChangedTokens,\n totalContextTokens,\n riskSummary,\n renderedSummary,\n };\n}\n\n// ===== RENDERING =====\n\nfunction renderSummary(\n analysis: ProjectAnalysis,\n currentBranch: string,\n baseBranch: string,\n changedFiles: ChangedFile[],\n dependencyFiles: string[],\n allRelevant: AnalyzedFile[],\n changedSet: Set<string>,\n risk: PRContextResult['riskSummary'],\n changedTokens: number,\n totalTokens: number,\n): string {\n const lines: string[] = [];\n\n lines.push(`## PR Context — ${analysis.projectName}`);\n lines.push('');\n lines.push(`**Branch:** ${currentBranch} ← ${baseBranch}`);\n lines.push(`**Changed:** ${changedFiles.length} files | **Dependencies:** ${dependencyFiles.length} files`);\n lines.push(`**Tokens:** ~${Math.round(changedTokens / 1000)}K changed + ~${Math.round((totalTokens - changedTokens) / 1000)}K context = ~${Math.round(totalTokens / 1000)}K total`);\n lines.push('');\n\n // Risk banner\n if (risk.critical > 0 || risk.high > 0) {\n lines.push(`⚠️ **Risk:** ${risk.critical} critical + ${risk.high} high-risk files affected`);\n lines.push(`**Highest risk:** ${risk.maxRiskFile} (score: ${risk.maxRiskScore})`);\n lines.push('');\n }\n\n // Changed files\n lines.push('### Changed Files');\n lines.push('');\n\n const sortedChanged = changedFiles\n .filter((c) => c.changeType !== 'deleted')\n .sort((a, b) => {\n const fa = allRelevant.find((f) => f.relativePath === a.relativePath);\n const fb = allRelevant.find((f) => f.relativePath === b.relativePath);\n return (fb?.riskScore ?? 0) - (fa?.riskScore ?? 0);\n });\n\n for (const c of sortedChanged) {\n const file = allRelevant.find((f) => f.relativePath === c.relativePath);\n const risk = file ? ` risk:${file.riskScore}` : '';\n const delta = c.linesAdded || c.linesRemoved\n ? ` (+${c.linesAdded}/-${c.linesRemoved})`\n : '';\n const badge = c.changeType === 'added' ? ' 🆕' : c.changeType === 'renamed' ? ' 📝' : '';\n lines.push(`- \\`${c.relativePath}\\`${delta}${risk}${badge}`);\n }\n\n // Deleted files\n const deleted = changedFiles.filter((c) => c.changeType === 'deleted');\n if (deleted.length > 0) {\n lines.push('');\n lines.push(`**Deleted:** ${deleted.map((d) => `\\`${d.relativePath}\\``).join(', ')}`);\n }\n\n // Dependencies\n if (dependencyFiles.length > 0) {\n lines.push('');\n lines.push('### Dependencies (included for context)');\n lines.push('');\n\n const depWithInfo = dependencyFiles\n .map((d) => {\n const file = allRelevant.find((f) => f.relativePath === d);\n return { path: d, riskScore: file?.riskScore ?? 0, tokens: file?.tokens ?? 0 };\n })\n .sort((a, b) => b.riskScore - a.riskScore);\n\n for (const d of depWithInfo) {\n lines.push(`- \\`${d.path}\\` risk:${d.riskScore} ~${Math.round(d.tokens / 1000)}K tokens`);\n }\n }\n\n lines.push('');\n lines.push('### Review Focus');\n lines.push('');\n lines.push('- Review changed files for correctness, especially high-risk files');\n lines.push('- Dependencies are included for type/interface context — not for review');\n lines.push(`- ${analysis.totalFiles - allRelevant.length} files excluded (not affected by this change)`);\n\n return lines.join('\\n');\n}\n\n// ===== HELPERS =====\n\nfunction emptyResult(baseBranch: string): PRContextResult {\n return {\n baseBranch,\n currentBranch: '',\n isGitRepo: false,\n changedFiles: [],\n dependencyFiles: [],\n allRelevantFiles: [],\n totalChangedTokens: 0,\n totalContextTokens: 0,\n riskSummary: { critical: 0, high: 0, medium: 0, low: 0, maxRiskFile: '', maxRiskScore: 0 },\n renderedSummary: '# PR Context\\n\\nNot a git repository.',\n };\n}\n","import { createHash } from 'node:crypto';\nimport type {\n AnalyzedFile,\n ProjectAnalysis,\n ContextSelection,\n SelectedFile,\n SelectionDecision,\n PruneLevel,\n CoverageResult,\n} from '../types/engine.js';\nimport type { PolicySet, PolicyRule } from '../types/govern.js';\nimport { scanFileForSecrets } from '../govern/secrets.js';\nimport { pruneFile } from './pruner.js';\nimport { calculateCoverage } from './coverage.js';\nimport { getPruneLevelForRisk } from './budget.js';\nimport { buildAdjacencyList, bfsBidirectional, matchGlob } from './graph-utils.js';\n\n// ===== DETERMINISTIC CONTEXT SELECTION =====\n//\n// Given a task, analysis, budget, and policies → always returns the same file set.\n// No randomness, no heuristics that change over time.\n//\n// Algorithm:\n// 1. Identify target files from task description\n// 2. Expand via dependency graph (BFS, depth=2)\n// 3. Apply policies (include-always, exclude-always)\n// 4. Score & rank by riskScore\n// 5. Greedy allocation with cascading prune levels\n// 6. Validate policies\n// 7. Calculate coverage score\n// 8. Hash for reproducibility\n\nexport interface SelectionInput {\n task: string;\n analysis: ProjectAnalysis;\n budget: number;\n policies?: PolicySet;\n depth?: number;\n}\n\nexport async function selectContext(input: SelectionInput): Promise<ContextSelection> {\n const { task, analysis, budget, policies, depth = 2 } = input;\n const decisions: SelectionDecision[] = [];\n\n // 1. Identify target files from task description\n const targetPaths = identifyTargetFiles(task, analysis.files);\n if (targetPaths.length > 0) {\n decisions.push({\n file: targetPaths.join(', '),\n action: 'include-full',\n reason: `Target file(s) identified from task description`,\n });\n }\n\n // 2. Expand via dependency graph (O(V+E) using adjacency list)\n const adj = buildAdjacencyList(analysis.graph.edges);\n const expandedPaths = targetPaths.length > 0\n ? Array.from(bfsBidirectional(targetPaths, adj, depth))\n : [];\n const expansionCount = expandedPaths.length - targetPaths.length;\n if (expansionCount > 0) {\n decisions.push({\n file: `${expansionCount} dependencies`,\n action: 'include-full',\n reason: `Expanded ${targetPaths.length} target(s) to ${expandedPaths.length} files via dependency graph (depth ${depth})`,\n });\n }\n\n // 2b. Add type providers of expanded files as candidates.\n // This aligns with coverage.ts which counts type providers as \"relevant\".\n // Without this, coverage would flag missing critical type files that the\n // selector never considered as candidates — a consistency bug.\n const allFileMap = new Map(analysis.files.map((f) => [f.relativePath, f]));\n if (targetPaths.length > 0) {\n for (const path of expandedPaths) {\n const file = allFileMap.get(path);\n if (!file) continue;\n for (const imp of file.imports) {\n const impFile = allFileMap.get(imp);\n if (impFile && impFile.kind === 'type') {\n expandedPaths.push(imp);\n }\n }\n }\n }\n\n // 3. Apply policies\n const { mustInclude, mustExclude } = applyPolicies(analysis.files, policies);\n\n // Merge: targets + expanded + must-include → candidate set\n const candidateSet = new Set([...expandedPaths, ...mustInclude]);\n\n // If no targets identified, use all files (filtered by exclude)\n if (targetPaths.length === 0) {\n for (const f of analysis.files) {\n candidateSet.add(f.relativePath);\n }\n }\n\n // Remove must-exclude\n for (const ex of mustExclude) {\n candidateSet.delete(ex);\n decisions.push({\n file: ex,\n action: 'exclude',\n reason: 'Excluded by policy',\n });\n }\n\n // 3b. secret-block: scan candidate files for secrets and exclude them\n const hasSecretBlock = policies?.rules.some(\n (r) => r.type === 'secret-block' && r.enabled,\n );\n if (hasSecretBlock) {\n for (const path of Array.from(candidateSet)) {\n const file = allFileMap.get(path);\n if (!file) continue;\n const findings = await scanFileForSecrets(\n file.path,\n analysis.projectPath,\n );\n if (findings.length > 0) {\n candidateSet.delete(path);\n decisions.push({\n file: path,\n action: 'exclude',\n reason: `Blocked: ${findings.length} secret(s) detected (${findings.map((f) => f.type).join(', ')})`,\n });\n }\n }\n }\n\n // 4. Sort candidates by riskScore descending\n const candidates = Array.from(candidateSet)\n .map((p) => allFileMap.get(p))\n .filter((f): f is AnalyzedFile => f !== undefined)\n .sort((a, b) => {\n // Targets always first\n const aIsTarget = targetPaths.includes(a.relativePath) ? 0 : 1;\n const bIsTarget = targetPaths.includes(b.relativePath) ? 0 : 1;\n if (aIsTarget !== bIsTarget) return aIsTarget - bIsTarget;\n\n // Then must-include\n const aIsMust = mustInclude.has(a.relativePath) ? 0 : 1;\n const bIsMust = mustInclude.has(b.relativePath) ? 0 : 1;\n if (aIsMust !== bIsMust) return aIsMust - bIsMust;\n\n // Then by riskScore\n return b.riskScore - a.riskScore;\n });\n\n // 5. Greedy allocation with cascading prune levels\n const selectedFiles: SelectedFile[] = [];\n let usedTokens = 0;\n\n for (const file of candidates) {\n const isTarget = targetPaths.includes(file.relativePath);\n const isMustInclude = mustInclude.has(file.relativePath);\n const defaultLevel = isTarget ? 'full' : getPruneLevelForRisk(file.riskScore);\n const levels = getCascadeLevels(defaultLevel);\n\n let included = false;\n\n for (const level of levels) {\n if (level === 'excluded') break;\n\n let tokens: number;\n if (level === 'full') {\n tokens = file.tokens;\n } else {\n const pruned = await pruneFile(file, level);\n tokens = pruned.prunedTokens;\n }\n\n if (usedTokens + tokens <= budget) {\n usedTokens += tokens;\n selectedFiles.push({\n relativePath: file.relativePath,\n tokens,\n originalTokens: file.tokens,\n pruneLevel: level,\n riskScore: file.riskScore,\n reason: buildReason(file, level, isTarget, isMustInclude),\n });\n\n if (level !== defaultLevel) {\n decisions.push({\n file: file.relativePath,\n action: `include-${level}` as SelectionDecision['action'],\n reason: `Downgraded from ${defaultLevel} to ${level} due to budget constraint`,\n alternatives: `Would need ${file.tokens - tokens} more tokens for ${defaultLevel}`,\n });\n }\n\n included = true;\n break;\n }\n }\n\n if (!included) {\n decisions.push({\n file: file.relativePath,\n action: 'exclude',\n reason: `Budget exhausted (risk: ${file.riskScore}, needs ${file.tokens} tokens)`,\n });\n }\n }\n\n // 6. Calculate coverage\n const includedPaths = selectedFiles.map((f) => f.relativePath);\n const coverage = calculateCoverage(\n targetPaths,\n includedPaths,\n analysis.files,\n analysis.graph,\n depth,\n );\n\n // 7. Calculate overall risk of the selection (lower = better)\n const includedSet = new Set(includedPaths);\n const excludedFiles = analysis.files.filter(\n (f) => !includedSet.has(f.relativePath),\n );\n const excludedRisk = excludedFiles.length > 0\n ? Math.round(excludedFiles.reduce((s, f) => s + f.riskScore, 0) / excludedFiles.length)\n : 0;\n\n // 8. Hash for determinism\n const hashInput = selectedFiles\n .map((f) => `${f.relativePath}:${f.pruneLevel}`)\n .sort()\n .join('|') + `|budget:${budget}`;\n const hash = createHash('sha256').update(hashInput).digest('hex').substring(0, 16);\n\n return {\n files: selectedFiles,\n totalTokens: usedTokens,\n budget,\n usedPercent: budget > 0 ? Math.round((usedTokens / budget) * 100 * 10) / 10 : 0,\n coverage,\n riskScore: excludedRisk,\n deterministic: true,\n hash,\n decisions,\n };\n}\n\n// ===== TARGET IDENTIFICATION =====\n\nfunction identifyTargetFiles(task: string, files: AnalyzedFile[]): string[] {\n const targets: string[] = [];\n\n // Extract file paths mentioned in the task\n // Matches patterns like: src/foo/bar.ts, ./utils.js, components/Header.tsx\n const pathPattern = /(?:^|\\s|[\"'`])([.\\w/-]+\\.[a-zA-Z]{1,4})(?:\\s|$|[\"'`]|,|:)/g;\n let match: RegExpExecArray | null;\n\n while ((match = pathPattern.exec(task)) !== null) {\n const candidate = match[1];\n // Find matching file\n const found = files.find(\n (f) => f.relativePath === candidate || f.relativePath.endsWith(candidate),\n );\n if (found && !targets.includes(found.relativePath)) {\n targets.push(found.relativePath);\n }\n }\n\n return targets;\n}\n\n// ===== POLICY APPLICATION =====\n\nfunction applyPolicies(\n files: AnalyzedFile[],\n policies?: PolicySet,\n): { mustInclude: Set<string>; mustExclude: Set<string> } {\n const mustInclude = new Set<string>();\n const mustExclude = new Set<string>();\n\n if (!policies) return { mustInclude, mustExclude };\n\n for (const rule of policies.rules) {\n if (!rule.enabled) continue;\n\n if (rule.type === 'include-always' && rule.pattern) {\n for (const file of files) {\n if (matchGlob(file.relativePath, rule.pattern)) {\n mustInclude.add(file.relativePath);\n }\n }\n }\n\n if (rule.type === 'exclude-always' && rule.pattern) {\n for (const file of files) {\n if (matchGlob(file.relativePath, rule.pattern)) {\n mustExclude.add(file.relativePath);\n }\n }\n }\n\n // secret-block is handled separately in applyPoliciesAsync\n // because it requires file I/O (scanning file contents)\n }\n\n return { mustInclude, mustExclude };\n}\n\n// ===== HELPERS =====\n\nfunction getCascadeLevels(startLevel: PruneLevel): PruneLevel[] {\n const all: PruneLevel[] = ['full', 'signatures', 'skeleton', 'excluded'];\n const startIdx = all.indexOf(startLevel);\n return all.slice(startIdx);\n}\n\nfunction buildReason(\n file: AnalyzedFile,\n level: PruneLevel,\n isTarget: boolean,\n isMustInclude: boolean,\n): string {\n if (isTarget) return 'Target file';\n if (isMustInclude) return 'Required by policy';\n\n const impact = file.exclusionImpact;\n const levelStr = level === 'full' ? 'full content' : level;\n\n if (impact === 'critical') return `Critical dependency (risk ${file.riskScore}) — ${levelStr}`;\n if (impact === 'high') return `High-risk dependency (risk ${file.riskScore}) — ${levelStr}`;\n if (impact === 'medium') return `Medium relevance (risk ${file.riskScore}) — ${levelStr}`;\n return `Low relevance (risk ${file.riskScore}) — ${levelStr}`;\n}\n","import { readFile } from 'node:fs/promises';\nimport { resolve, relative } from 'node:path';\nimport type { SecretFinding, SecretType } from '../types/govern.js';\n\n// ===== SECRET DETECTION ENGINE =====\n\ninterface SecretPattern {\n type: SecretType;\n pattern: RegExp;\n severity: SecretFinding['severity'];\n description: string;\n}\n\nconst BUILTIN_PATTERNS: { type: SecretType; source: string; flags: string; severity: SecretFinding['severity']; description: string }[] = [\n // API Keys\n { type: 'api-key', source: '(?:api[_-]?key|apikey)\\\\s*[:=]\\\\s*[\\'\"]?([a-zA-Z0-9_\\\\-]{20,})[\\'\"]?', flags: 'gi', severity: 'critical', description: 'API Key' },\n { type: 'api-key', source: 'sk-[a-zA-Z0-9]{20,}', flags: 'g', severity: 'critical', description: 'OpenAI/Anthropic API Key' },\n { type: 'api-key', source: 'sk-ant-[a-zA-Z0-9\\\\-]{20,}', flags: 'g', severity: 'critical', description: 'Anthropic API Key' },\n\n // AWS\n { type: 'aws-key', source: 'AKIA[0-9A-Z]{16}', flags: 'g', severity: 'critical', description: 'AWS Access Key ID' },\n { type: 'aws-key', source: '(?:aws_secret_access_key|aws_secret)\\\\s*[:=]\\\\s*[\\'\"]?([a-zA-Z0-9/+=]{40})[\\'\"]?', flags: 'gi', severity: 'critical', description: 'AWS Secret Key' },\n\n // Private Keys\n { type: 'private-key', source: '-----BEGIN (?:RSA |EC |DSA )?PRIVATE KEY-----', flags: 'g', severity: 'critical', description: 'Private Key' },\n { type: 'private-key', source: '-----BEGIN OPENSSH PRIVATE KEY-----', flags: 'g', severity: 'critical', description: 'SSH Private Key' },\n\n // Passwords\n { type: 'password', source: '(?:password|passwd|pwd)\\\\s*[:=]\\\\s*[\\'\"]([^\\'\"]{8,})[\\'\"](?!\\\\s*\\\\{)', flags: 'gi', severity: 'high', description: 'Hardcoded Password' },\n { type: 'password', source: '(?:DB_PASSWORD|DATABASE_PASSWORD|MYSQL_PASSWORD|POSTGRES_PASSWORD)\\\\s*[:=]\\\\s*[\\'\"]?([^\\'\"{}\\\\s]{4,})[\\'\"]?', flags: 'gi', severity: 'high', description: 'Database Password' },\n\n // Tokens\n { type: 'token', source: '(?:bearer|token|auth_token|access_token|refresh_token)\\\\s*[:=]\\\\s*[\\'\"]([a-zA-Z0-9_\\\\-.]{20,})[\\'\"](?!\\\\s*\\\\{)', flags: 'gi', severity: 'high', description: 'Auth Token' },\n { type: 'token', source: 'ghp_[a-zA-Z0-9]{36}', flags: 'g', severity: 'critical', description: 'GitHub Personal Access Token' },\n { type: 'token', source: 'gho_[a-zA-Z0-9]{36}', flags: 'g', severity: 'critical', description: 'GitHub OAuth Token' },\n { type: 'token', source: 'glpat-[a-zA-Z0-9\\\\-]{20,}', flags: 'g', severity: 'critical', description: 'GitLab Personal Access Token' },\n { type: 'token', source: 'npm_[a-zA-Z0-9]{36}', flags: 'g', severity: 'high', description: 'npm Token' },\n\n // Connection strings\n { type: 'connection-string', source: '(?:mongodb(?:\\\\+srv)?|postgres(?:ql)?|mysql|redis|amqp):\\\\/\\\\/[^\\\\s\\'\"]+:[^\\\\s\\'\"]+@[^\\\\s\\'\"]+', flags: 'gi', severity: 'critical', description: 'Database Connection String' },\n { type: 'connection-string', source: '(?:DATABASE_URL|REDIS_URL|MONGODB_URI)\\\\s*[:=]\\\\s*[\\'\"]?([^\\\\s\\'\"]{10,})[\\'\"]?', flags: 'gi', severity: 'high', description: 'Database URL' },\n\n // Environment variables with secrets\n { type: 'env-variable', source: '(?:SECRET|PRIVATE|ENCRYPTION)[_-]?(?:KEY|TOKEN|PASS)\\\\s*[:=]\\\\s*[\\'\"]?([^\\\\s\\'\"]{8,})[\\'\"]?', flags: 'gi', severity: 'high', description: 'Secret Environment Variable' },\n];\n\nfunction buildPatterns(customPatterns: string[] = []): SecretPattern[] {\n const patterns: SecretPattern[] = BUILTIN_PATTERNS.map((def) => ({\n type: def.type,\n pattern: new RegExp(def.source, def.flags),\n severity: def.severity,\n description: def.description,\n }));\n\n for (const custom of customPatterns) {\n try {\n patterns.push({\n type: 'custom',\n pattern: new RegExp(custom, 'gi'),\n severity: 'medium',\n description: `Custom pattern: ${custom}`,\n });\n } catch { /* skip invalid regex */ }\n }\n\n return patterns;\n}\n\nexport function scanContentForSecrets(\n content: string,\n filePath: string,\n customPatterns: string[] = [],\n): SecretFinding[] {\n const findings: SecretFinding[] = [];\n const lines = content.split('\\n');\n const allPatterns = buildPatterns(customPatterns);\n\n for (const secretPattern of allPatterns) {\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n secretPattern.pattern.lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = secretPattern.pattern.exec(line)) !== null) {\n const matchText = match[0];\n if (isTemplateOrPlaceholder(matchText)) continue;\n\n findings.push({\n type: secretPattern.type,\n file: filePath,\n line: i + 1,\n match: matchText,\n redacted: redactSecret(matchText),\n severity: secretPattern.severity,\n });\n }\n }\n }\n\n return deduplicateFindings(findings);\n}\n\nexport async function scanFileForSecrets(\n filePath: string,\n projectPath: string,\n customPatterns: string[] = [],\n): Promise<SecretFinding[]> {\n try {\n const content = await readFile(filePath, 'utf-8');\n const relPath = relative(resolve(projectPath), resolve(filePath));\n return scanContentForSecrets(content, relPath, customPatterns);\n } catch {\n return [];\n }\n}\n\nexport async function scanProjectForSecrets(\n projectPath: string,\n filePaths: string[],\n customPatterns: string[] = [],\n): Promise<SecretFinding[]> {\n const allFindings: SecretFinding[] = [];\n\n for (const fp of filePaths) {\n const findings = await scanFileForSecrets(fp, projectPath, customPatterns);\n allFindings.push(...findings);\n }\n\n return allFindings.sort((a, b) => {\n const severityOrder = { critical: 0, high: 1, medium: 2, low: 3 };\n return severityOrder[a.severity] - severityOrder[b.severity];\n });\n}\n\nexport function sanitizeContent(content: string, customPatterns: string[] = []): string {\n let sanitized = content;\n const allPatterns = buildPatterns(customPatterns);\n\n for (const secretPattern of allPatterns) {\n sanitized = sanitized.replace(secretPattern.pattern, (match) => {\n if (isTemplateOrPlaceholder(match)) return match;\n return redactSecret(match);\n });\n }\n\n return sanitized;\n}\n\nfunction redactSecret(value: string): string {\n if (value.length <= 8) return '***REDACTED***';\n const prefix = value.substring(0, 4);\n const suffix = value.substring(value.length - 2);\n return `${prefix}${'*'.repeat(Math.min(value.length - 6, 20))}${suffix}`;\n}\n\nfunction isTemplateOrPlaceholder(value: string): boolean {\n const placeholders = [\n /\\$\\{.*\\}/, /\\{\\{.*\\}\\}/, /%[sd]/, /<[A-Z_]+>/, /YOUR_.*_HERE/i,\n /\\bCHANGE_ME\\b/i, /\\bPLACEHOLDER\\b/i, /\\bexample\\b/i, /\\bTODO\\b/i, /xxx+/i,\n /\\breplace.?me\\b/i, /\\bdummy\\b/i, /\\btest_?key\\b/i, /\\bsample\\b/i,\n ];\n return placeholders.some((p) => p.test(value));\n}\n\nfunction deduplicateFindings(findings: SecretFinding[]): SecretFinding[] {\n const seen = new Set<string>();\n return findings.filter((f) => {\n const key = `${f.file}:${f.line}:${f.type}:${f.match}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n","import { Project, SyntaxKind, type SourceFile } from 'ts-morph';\nimport { readFile } from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { AnalyzedFile, PruneLevel, PrunedContent } from '../types/engine.js';\nimport { countTokensChars4 } from './tokenizer.js';\n\nconst TS_EXTENSIONS = new Set(['ts', 'tsx', 'js', 'jsx', 'mts', 'mjs']);\n\n// ===== PUBLIC API =====\n\nexport async function pruneFile(\n file: AnalyzedFile,\n level: PruneLevel,\n): Promise<PrunedContent> {\n if (level === 'excluded') {\n return emptyResult(file, 'excluded');\n }\n\n if (level === 'full') {\n return fullContent(file);\n }\n\n const ext = file.extension.toLowerCase();\n const isTS = TS_EXTENSIONS.has(ext);\n\n if (isTS) {\n return pruneTypeScript(file, level);\n }\n\n return pruneGeneric(file, level);\n}\n\nexport async function pruneFiles(\n files: AnalyzedFile[],\n levelFn: (file: AnalyzedFile) => PruneLevel,\n): Promise<PrunedContent[]> {\n const results: PrunedContent[] = [];\n\n for (const file of files) {\n const level = levelFn(file);\n const pruned = await pruneFile(file, level);\n results.push(pruned);\n }\n\n return results;\n}\n\n// ===== TYPESCRIPT AST-BASED PRUNING =====\n\nasync function pruneTypeScript(\n file: AnalyzedFile,\n level: PruneLevel,\n): Promise<PrunedContent> {\n let content: string;\n try {\n content = await readFile(file.path, 'utf-8');\n } catch {\n return emptyResult(file, level);\n }\n\n let project: Project;\n try {\n const tsConfigPath = findTsConfig(file.path);\n project = new Project({\n tsConfigFilePath: tsConfigPath,\n skipAddingFilesFromTsConfig: true,\n compilerOptions: tsConfigPath\n ? undefined\n : { allowJs: true, esModuleInterop: true },\n });\n project.createSourceFile(file.path, content, { overwrite: true });\n } catch {\n // Fallback to generic pruning if AST fails\n return pruneGenericFromContent(file, content, level);\n }\n\n const sourceFile = project.getSourceFiles()[0];\n if (!sourceFile) {\n return pruneGenericFromContent(file, content, level);\n }\n\n const prunedContent = level === 'signatures'\n ? extractSignaturesAST(sourceFile)\n : extractSkeletonAST(sourceFile);\n\n const prunedTokens = countTokensChars4(Buffer.byteLength(prunedContent, 'utf-8'));\n const savingsPercent = file.tokens > 0 ? ((file.tokens - prunedTokens) / file.tokens) * 100 : 0;\n\n return {\n relativePath: file.relativePath,\n originalTokens: file.tokens,\n prunedTokens,\n pruneLevel: level,\n content: prunedContent,\n savingsPercent: Math.max(0, savingsPercent),\n };\n}\n\n// ===== SIGNATURES: Keep imports, type defs, function signatures, class outlines =====\n\nfunction extractSignaturesAST(sf: SourceFile): string {\n const parts: string[] = [];\n\n // Imports\n for (const imp of sf.getImportDeclarations()) {\n parts.push(imp.getText());\n }\n\n if (parts.length > 0) parts.push('');\n\n // Type aliases\n for (const ta of sf.getTypeAliases()) {\n addJSDoc(ta, parts);\n parts.push(ta.getText());\n }\n\n // Interfaces\n for (const iface of sf.getInterfaces()) {\n addJSDoc(iface, parts);\n parts.push(iface.getText());\n }\n\n // Enums\n for (const en of sf.getEnums()) {\n addJSDoc(en, parts);\n parts.push(en.getText());\n }\n\n // Function declarations — signature only\n for (const fn of sf.getFunctions()) {\n addJSDoc(fn, parts);\n const isExported = fn.isExported();\n const isAsync = fn.isAsync();\n const name = fn.getName() ?? '<anonymous>';\n const params = fn.getParameters().map((p) => p.getText()).join(', ');\n const returnType = fn.getReturnTypeNode()?.getText();\n const returnStr = returnType ? `: ${returnType}` : '';\n\n const prefix = isExported ? 'export ' : '';\n const asyncStr = isAsync ? 'async ' : '';\n parts.push(`${prefix}${asyncStr}function ${name}(${params})${returnStr} { /* ... */ }`);\n }\n\n // Variable declarations (const/let with arrow functions)\n for (const stmt of sf.getVariableStatements()) {\n for (const decl of stmt.getDeclarations()) {\n const init = decl.getInitializer();\n if (init && (init.getKind() === SyntaxKind.ArrowFunction || init.getKind() === SyntaxKind.FunctionExpression)) {\n addJSDoc(stmt, parts);\n const isExported = stmt.isExported();\n const prefix = isExported ? 'export ' : '';\n const kind = stmt.getDeclarationKind();\n const name = decl.getName();\n const typeNode = decl.getTypeNode()?.getText();\n const typeStr = typeNode ? `: ${typeNode}` : '';\n parts.push(`${prefix}${kind} ${name}${typeStr} = /* ... */;`);\n } else {\n // Non-function variables: keep full declaration\n addJSDoc(stmt, parts);\n parts.push(stmt.getText());\n }\n }\n }\n\n // Classes — outline with method signatures\n for (const cls of sf.getClasses()) {\n addJSDoc(cls, parts);\n const isExported = cls.isExported();\n const prefix = isExported ? 'export ' : '';\n const name = cls.getName() ?? '<anonymous>';\n const ext = cls.getExtends()?.getText();\n const impl = cls.getImplements().map((i) => i.getText()).join(', ');\n let header = `${prefix}class ${name}`;\n if (ext) header += ` extends ${ext}`;\n if (impl) header += ` implements ${impl}`;\n header += ' {';\n parts.push(header);\n\n // Properties\n for (const prop of cls.getProperties()) {\n parts.push(` ${prop.getText()}`);\n }\n\n // Constructor\n const ctor = cls.getConstructors()[0];\n if (ctor) {\n const ctorParams = ctor.getParameters().map((p) => p.getText()).join(', ');\n parts.push(` constructor(${ctorParams}) { /* ... */ }`);\n }\n\n // Methods — signature only\n for (const method of cls.getMethods()) {\n const isStatic = method.isStatic();\n const isAsync = method.isAsync();\n const methodName = method.getName();\n const methodParams = method.getParameters().map((p) => p.getText()).join(', ');\n const returnType = method.getReturnTypeNode()?.getText();\n const returnStr = returnType ? `: ${returnType}` : '';\n const staticStr = isStatic ? 'static ' : '';\n const asyncStr = isAsync ? 'async ' : '';\n parts.push(` ${staticStr}${asyncStr}${methodName}(${methodParams})${returnStr} { /* ... */ }`);\n }\n\n parts.push('}');\n }\n\n // Re-exports\n for (const exp of sf.getExportDeclarations()) {\n parts.push(exp.getText());\n }\n\n // Export assignments\n for (const exp of sf.getExportAssignments()) {\n parts.push(exp.getText());\n }\n\n return parts.join('\\n');\n}\n\n// ===== SKELETON: Keep only declarations, no bodies at all =====\n\nfunction extractSkeletonAST(sf: SourceFile): string {\n const parts: string[] = [];\n\n // Imports\n for (const imp of sf.getImportDeclarations()) {\n parts.push(imp.getText());\n }\n\n if (parts.length > 0) parts.push('');\n\n // Type aliases — full\n for (const ta of sf.getTypeAliases()) {\n if (ta.isExported()) parts.push(ta.getText());\n }\n\n // Interfaces — name + extends only\n for (const iface of sf.getInterfaces()) {\n if (!iface.isExported()) continue;\n const ext = iface.getExtends().map((e) => e.getText());\n const extStr = ext.length > 0 ? ` extends ${ext.join(', ')}` : '';\n parts.push(`export interface ${iface.getName()}${extStr} { /* ${iface.getProperties().length} props */ }`);\n }\n\n // Enums — name only\n for (const en of sf.getEnums()) {\n if (!en.isExported()) continue;\n const members = en.getMembers().map((m) => m.getName());\n parts.push(`export enum ${en.getName()} { ${members.join(', ')} }`);\n }\n\n // Functions — name + params only\n for (const fn of sf.getFunctions()) {\n if (!fn.isExported()) continue;\n const name = fn.getName() ?? '<anonymous>';\n const params = fn.getParameters().map((p) => p.getText()).join(', ');\n parts.push(`export function ${name}(${params});`);\n }\n\n // Classes — name + method names only\n for (const cls of sf.getClasses()) {\n if (!cls.isExported()) continue;\n const methods = cls.getMethods().map((m) => m.getName());\n parts.push(`export class ${cls.getName()} { /* methods: ${methods.join(', ')} */ }`);\n }\n\n // Re-exports\n for (const exp of sf.getExportDeclarations()) {\n parts.push(exp.getText());\n }\n\n return parts.join('\\n');\n}\n\n// ===== GENERIC PRUNING (non-TS files) =====\n\nasync function pruneGeneric(\n file: AnalyzedFile,\n level: PruneLevel,\n): Promise<PrunedContent> {\n let content: string;\n try {\n content = await readFile(file.path, 'utf-8');\n } catch {\n return emptyResult(file, level);\n }\n\n return pruneGenericFromContent(file, content, level);\n}\n\nfunction pruneGenericFromContent(\n file: AnalyzedFile,\n content: string,\n level: PruneLevel,\n): PrunedContent {\n const lines = content.split('\\n');\n let result: string[];\n\n if (level === 'signatures') {\n result = lines.filter((line) => {\n const t = line.trim();\n return (\n t === '' ||\n t.startsWith('#') ||\n t.startsWith('//') ||\n t.startsWith('import ') ||\n t.startsWith('from ') ||\n t.startsWith('export ') ||\n t.startsWith('def ') ||\n t.startsWith('async def ') ||\n t.startsWith('class ') ||\n t.startsWith('function ') ||\n t.startsWith('const ') ||\n t.startsWith('let ') ||\n t.startsWith('var ') ||\n /^(pub |fn |struct |enum |impl |mod |use )/.test(t)\n );\n });\n } else {\n // skeleton: even more aggressive — only declarations\n result = lines.filter((line) => {\n const t = line.trim();\n return (\n t.startsWith('import ') ||\n t.startsWith('from ') ||\n t.startsWith('export ') ||\n t.startsWith('def ') ||\n t.startsWith('class ') ||\n t.startsWith('function ') ||\n /^(pub |fn |struct |enum |mod |use )/.test(t)\n );\n });\n }\n\n const prunedContent = result.join('\\n');\n const prunedTokens = countTokensChars4(Buffer.byteLength(prunedContent, 'utf-8'));\n const savingsPercent = file.tokens > 0 ? ((file.tokens - prunedTokens) / file.tokens) * 100 : 0;\n\n return {\n relativePath: file.relativePath,\n originalTokens: file.tokens,\n prunedTokens,\n pruneLevel: level,\n content: prunedContent,\n savingsPercent: Math.max(0, savingsPercent),\n };\n}\n\n// ===== HELPERS =====\n\nasync function fullContent(file: AnalyzedFile): Promise<PrunedContent> {\n let content = '';\n try {\n content = await readFile(file.path, 'utf-8');\n } catch { /* empty */ }\n\n return {\n relativePath: file.relativePath,\n originalTokens: file.tokens,\n prunedTokens: file.tokens,\n pruneLevel: 'full',\n content,\n savingsPercent: 0,\n };\n}\n\nfunction emptyResult(file: AnalyzedFile, level: PruneLevel): PrunedContent {\n return {\n relativePath: file.relativePath,\n originalTokens: file.tokens,\n prunedTokens: 0,\n pruneLevel: level,\n content: '',\n savingsPercent: 100,\n };\n}\n\nfunction addJSDoc(node: { getJsDocs?: () => { getText(): string }[] }, parts: string[]): void {\n if (!node.getJsDocs) return;\n const docs = node.getJsDocs();\n if (docs.length > 0) {\n parts.push(docs[0].getText());\n }\n}\n\nfunction findTsConfig(filePath: string): string | undefined {\n let dir = filePath;\n for (let i = 0; i < 10; i++) {\n dir = join(dir, '..');\n const candidate = join(dir, 'tsconfig.json');\n if (existsSync(candidate)) return candidate;\n }\n return undefined;\n}\n","import type {\n AnalyzedFile,\n ProjectGraph,\n CoverageResult,\n} from '../types/engine.js';\nimport { buildAdjacencyList, bfsBidirectional } from './graph-utils.js';\n\n// ===== CONTEXT COVERAGE SCORING =====\n//\n// Given a set of included files and a task's target files, calculate\n// how much of the \"relevant universe\" is covered.\n//\n// coverageScore = |includedRelevant| / |relevantFiles| × 100\n//\n// \"Relevant\" = target files + their dependencies (up to `depth` levels)\n// + type providers used by included files.\n\nexport function calculateCoverage(\n targetPaths: string[],\n includedPaths: string[],\n allFiles: AnalyzedFile[],\n graph: ProjectGraph,\n depth: number = 2,\n): CoverageResult {\n // 1. Find all relevant files: targets + their dependency cone\n // Uses adjacency list for O(V+E) BFS instead of scanning all edges per node.\n const adj = buildAdjacencyList(graph.edges);\n const relevantSet = targetPaths.length > 0\n ? bfsBidirectional(targetPaths, adj, depth)\n : new Set<string>();\n const includedSet = new Set(includedPaths);\n\n // Also add type providers used by included files\n const tempFileMap = new Map(allFiles.map((f) => [f.relativePath, f]));\n for (const path of includedPaths) {\n const file = tempFileMap.get(path);\n if (!file) continue;\n\n for (const imp of file.imports) {\n const impFile = tempFileMap.get(imp);\n if (impFile && impFile.kind === 'type') {\n relevantSet.add(imp);\n }\n }\n }\n\n // 2. Calculate coverage\n const relevantFiles = Array.from(relevantSet);\n const includedRelevant = relevantFiles.filter((f) => includedSet.has(f));\n const missingRelevant = relevantFiles.filter((f) => !includedSet.has(f));\n\n // Missing critical = missing files with critical/high exclusion impact\n const missingCritical = missingRelevant.filter((f) => {\n const file = tempFileMap.get(f);\n return file && (file.exclusionImpact === 'critical' || file.exclusionImpact === 'high');\n });\n\n // Risk-weighted coverage: missing a high-risk file hurts more than missing a low-risk one.\n // score = Σ(riskScore of included relevant) / Σ(riskScore of all relevant) × 100\n // Falls back to count-based if no risk data is available.\n const fileMap = new Map(allFiles.map((f) => [f.relativePath, f]));\n let totalRelevantRisk = 0;\n let includedRelevantRisk = 0;\n\n for (const f of relevantFiles) {\n const risk = fileMap.get(f)?.riskScore ?? 1;\n totalRelevantRisk += risk;\n if (includedSet.has(f)) {\n includedRelevantRisk += risk;\n }\n }\n\n const score = totalRelevantRisk > 0\n ? Math.round((includedRelevantRisk / totalRelevantRisk) * 100)\n : relevantFiles.length > 0\n ? Math.round((includedRelevant.length / relevantFiles.length) * 100)\n : 100;\n\n // Build explanation\n let explanation: string;\n if (score >= 90) {\n explanation = `Excellent coverage (${score}%): AI has nearly all relevant context.`;\n } else if (score >= 70) {\n explanation = `Good coverage (${score}%): Most relevant files included.`;\n if (missingCritical.length > 0) {\n explanation += ` Warning: ${missingCritical.length} critical file(s) missing.`;\n }\n } else if (score >= 50) {\n explanation = `Partial coverage (${score}%): Significant context is missing.`;\n if (missingCritical.length > 0) {\n explanation += ` ${missingCritical.length} critical file(s) not included — AI quality will degrade.`;\n }\n } else {\n explanation = `Low coverage (${score}%): Most relevant files are excluded. AI response quality will be poor.`;\n }\n\n return {\n score,\n relevantFiles,\n includedRelevant,\n missingRelevant,\n missingCritical,\n explanation,\n };\n}\n","import type { AnalyzedFile, BudgetPlan, BudgetEntry, PruneLevel } from '../types/engine.js';\nimport { pruneFile } from './pruner.js';\n\n// ===== BUDGET OPTIMIZER =====\n//\n// Greedy knapsack with cascading prune levels.\n// Files are sorted by riskScore (descending) — highest risk first.\n// Each file is tried at progressively smaller prune levels until it fits.\n\nexport function getPruneLevelForRisk(riskScore: number): PruneLevel {\n if (riskScore >= 80) return 'full'; // critical — include everything, no cascading\n if (riskScore >= 60) return 'full'; // high — try full first, can cascade\n if (riskScore >= 30) return 'signatures'; // medium — signatures by default\n return 'skeleton'; // low — skeleton\n}\n\nexport function isCriticalRisk(riskScore: number): boolean {\n return riskScore >= 80;\n}\n\nexport async function optimizeBudget(\n files: AnalyzedFile[],\n budget: number,\n): Promise<BudgetPlan> {\n const entries: BudgetEntry[] = [];\n let used = 0;\n\n // Sort by riskScore descending — most important files first\n const sorted = [...files].sort((a, b) => b.riskScore - a.riskScore);\n\n for (const file of sorted) {\n const defaultLevel = getPruneLevelForRisk(file.riskScore);\n\n // Try cascading prune levels: full → signatures → skeleton → excluded\n const levelsToTry = getCascadeLevels(defaultLevel);\n\n let included = false;\n\n for (const level of levelsToTry) {\n if (level === 'excluded') break;\n\n if (level === 'full') {\n if (used + file.tokens <= budget) {\n used += file.tokens;\n entries.push({\n relativePath: file.relativePath,\n originalTokens: file.tokens,\n allocatedTokens: file.tokens,\n pruneLevel: 'full',\n included: true,\n reason: `Risk ${file.riskScore} — included in full`,\n });\n included = true;\n break;\n }\n } else {\n const pruned = await pruneFile(file, level);\n if (pruned.prunedTokens > 0 && used + pruned.prunedTokens <= budget) {\n used += pruned.prunedTokens;\n entries.push({\n relativePath: file.relativePath,\n originalTokens: file.tokens,\n allocatedTokens: pruned.prunedTokens,\n pruneLevel: level,\n included: true,\n reason: `Risk ${file.riskScore} — pruned to ${level} (budget constraint)`,\n });\n included = true;\n break;\n }\n }\n }\n\n if (!included) {\n entries.push({\n relativePath: file.relativePath,\n originalTokens: file.tokens,\n allocatedTokens: 0,\n pruneLevel: 'excluded',\n included: false,\n reason: `Risk ${file.riskScore} — excluded (budget exhausted, ${file.tokens} tokens)`,\n });\n }\n }\n\n return {\n budget,\n used,\n remaining: budget - used,\n fillPercent: budget > 0 ? Math.round((used / budget) * 100 * 10) / 10 : 0,\n files: entries,\n };\n}\n\n// ===== HELPERS =====\n\nfunction getCascadeLevels(startLevel: PruneLevel): PruneLevel[] {\n const all: PruneLevel[] = ['full', 'signatures', 'skeleton', 'excluded'];\n const startIdx = all.indexOf(startLevel);\n return all.slice(startIdx);\n}\n","import type { ProjectAnalysis, AnalyzedFile } from '../types/engine.js';\nimport type { ContextSelection } from '../types/engine.js';\nimport { selectContext } from './selector.js';\nimport { calculateCoverage } from './coverage.js';\nimport { buildAdjacencyList } from './graph-utils.js';\n\n// ===== Context Score™ =====\n//\n// A single 0-100 metric that quantifies how well a project's context\n// can be optimized for AI consumption.\n//\n// The score answers: \"If I send this project to an AI with CTO,\n// how much value am I getting per token?\"\n//\n// Dimensions:\n// 1. Efficiency (30%) — How much can we compress without losing value?\n// 2. Coverage (25%) — How much of the relevant universe do we capture?\n// 3. Risk Control (20%) — Are high-risk files properly prioritized?\n// 4. Structure (15%) — How well-organized is the codebase for AI consumption?\n// 5. Governance (10%) — Is the project set up for safe, auditable AI use?\n//\n// Grade scale:\n// A+ (95-100) | A (90-94) | A- (85-89)\n// B+ (80-84) | B (75-79) | B- (70-74)\n// C+ (65-69) | C (60-64) | C- (55-59)\n// D (40-54) | F (0-39)\n\nexport type Grade = 'A+' | 'A' | 'A-' | 'B+' | 'B' | 'B-' | 'C+' | 'C' | 'C-' | 'D' | 'F';\n\nexport interface ContextScore {\n overall: number;\n grade: Grade;\n\n dimensions: {\n efficiency: DimensionScore;\n coverage: DimensionScore;\n riskControl: DimensionScore;\n structure: DimensionScore;\n governance: DimensionScore;\n };\n\n insights: ScoreInsight[];\n\n comparison: {\n naiveTokens: number;\n optimizedTokens: number;\n savedTokens: number;\n savedPercent: number;\n monthlySavingsUSD: number;\n };\n\n meta: {\n projectName: string;\n totalFiles: number;\n totalTokens: number;\n analyzedAt: Date;\n };\n}\n\nexport interface DimensionScore {\n score: number;\n weight: number;\n weighted: number;\n detail: string;\n}\n\nexport interface ScoreInsight {\n type: 'strength' | 'weakness' | 'opportunity';\n title: string;\n detail: string;\n impact: 'high' | 'medium' | 'low';\n}\n\n// ===== MAIN API =====\n\n/**\n * Compute the Context Score™ for a project.\n *\n * @param analysis - Project analysis (from analyzeProject or getCachedAnalysis)\n * @param task - Representative task (default: \"general code review\")\n * @param budget - Token budget (default: 50000)\n */\nexport async function computeContextScore(\n analysis: ProjectAnalysis,\n task: string = 'general code review and refactoring',\n budget: number = 50_000,\n): Promise<ContextScore> {\n // Run context selection to get real numbers\n const selection = await selectContext({ task, analysis, budget });\n\n const insights: ScoreInsight[] = [];\n\n // 1. EFFICIENCY (30%) — compression ratio + pruning effectiveness\n const efficiency = scoreEfficiency(analysis, selection, insights);\n\n // 2. COVERAGE (25%) — how much of the relevant universe is captured\n const coverage = scoreCoverage(analysis, selection, insights);\n\n // 3. RISK CONTROL (20%) — high-risk file prioritization\n const riskControl = scoreRiskControl(analysis, selection, insights);\n\n // 4. STRUCTURE (15%) — codebase organization for AI\n const structure = scoreStructure(analysis, insights);\n\n // 5. GOVERNANCE (10%) — project setup for safe AI use\n const governance = scoreGovernance(analysis, insights);\n\n // Overall\n const overall = Math.round(\n efficiency.weighted + coverage.weighted + riskControl.weighted +\n structure.weighted + governance.weighted\n );\n\n const grade = scoreToGrade(overall);\n\n // Comparison: CTO vs naive (send everything)\n const naiveTokens = analysis.totalTokens;\n const optimizedTokens = selection.totalTokens;\n const savedTokens = naiveTokens - optimizedTokens;\n const savedPercent = naiveTokens > 0 ? Math.round((savedTokens / naiveTokens) * 100) : 0;\n\n // Monthly savings estimate: assume 40 interactions/day, 20 working days\n // Claude Sonnet: $3/M input tokens\n const interactionsPerMonth = 40 * 20;\n const costPerMToken = 3; // $/M tokens (Sonnet)\n const naiveMonthlyCost = (naiveTokens / 1_000_000) * costPerMToken * interactionsPerMonth;\n const optimizedMonthlyCost = (optimizedTokens / 1_000_000) * costPerMToken * interactionsPerMonth;\n const monthlySavingsUSD = Math.round((naiveMonthlyCost - optimizedMonthlyCost) * 100) / 100;\n\n return {\n overall,\n grade,\n dimensions: {\n efficiency,\n coverage,\n riskControl,\n structure,\n governance,\n },\n insights: insights.sort((a, b) => {\n const order = { high: 0, medium: 1, low: 2 };\n return order[a.impact] - order[b.impact];\n }),\n comparison: {\n naiveTokens,\n optimizedTokens,\n savedTokens,\n savedPercent,\n monthlySavingsUSD,\n },\n meta: {\n projectName: analysis.projectName,\n totalFiles: analysis.totalFiles,\n totalTokens: analysis.totalTokens,\n analyzedAt: analysis.analyzedAt,\n },\n };\n}\n\n// ===== DIMENSION SCORERS =====\n\nfunction scoreEfficiency(\n analysis: ProjectAnalysis,\n selection: ContextSelection,\n insights: ScoreInsight[],\n): DimensionScore {\n const weight = 30;\n\n // Compression ratio: how much we reduced tokens\n const ratio = analysis.totalTokens > 0\n ? 1 - (selection.totalTokens / analysis.totalTokens)\n : 0;\n\n // File selectivity: what % of files were excluded\n const selectivity = analysis.totalFiles > 0\n ? 1 - (selection.files.length / analysis.totalFiles)\n : 0;\n\n // Pruning effectiveness: how many files got pruned (signatures/skeleton)\n const prunedFiles = selection.files.filter(\n (f) => f.pruneLevel === 'signatures' || f.pruneLevel === 'skeleton'\n ).length;\n const pruneRatio = selection.files.length > 0\n ? prunedFiles / selection.files.length\n : 0;\n\n // Weighted combination\n const raw = (ratio * 0.5 + selectivity * 0.3 + pruneRatio * 0.2) * 100;\n const score = Math.min(100, Math.max(0, Math.round(raw)));\n const weighted = (score / 100) * weight;\n\n if (ratio > 0.7) {\n insights.push({\n type: 'strength',\n title: 'Excellent compression',\n detail: `${Math.round(ratio * 100)}% token reduction while maintaining context quality`,\n impact: 'high',\n });\n }\n\n if (ratio < 0.3 && analysis.totalTokens > 20_000) {\n insights.push({\n type: 'weakness',\n title: 'Low compression opportunity',\n detail: 'Most files are needed. Consider splitting the project into smaller modules.',\n impact: 'medium',\n });\n }\n\n return {\n score,\n weight,\n weighted,\n detail: `${Math.round(ratio * 100)}% compression, ${prunedFiles}/${selection.files.length} files pruned`,\n };\n}\n\nfunction scoreCoverage(\n analysis: ProjectAnalysis,\n selection: ContextSelection,\n insights: ScoreInsight[],\n): DimensionScore {\n const weight = 25;\n\n const coverageScore = selection.coverage.score;\n const missingCritical = selection.coverage.missingCritical.length;\n\n // Penalize missing critical files heavily\n let penalty = 0;\n if (missingCritical > 0) {\n penalty = Math.min(30, missingCritical * 10);\n insights.push({\n type: 'weakness',\n title: `${missingCritical} critical file(s) missing from context`,\n detail: `Missing: ${selection.coverage.missingCritical.slice(0, 3).join(', ')}${missingCritical > 3 ? ` +${missingCritical - 3} more` : ''}`,\n impact: 'high',\n });\n }\n\n const score = Math.min(100, Math.max(0, Math.round(coverageScore - penalty)));\n const weighted = (score / 100) * weight;\n\n if (coverageScore >= 90 && missingCritical === 0) {\n insights.push({\n type: 'strength',\n title: 'Excellent context coverage',\n detail: `${coverageScore}% of the relevant universe captured with zero critical gaps`,\n impact: 'high',\n });\n }\n\n return {\n score,\n weight,\n weighted,\n detail: `${coverageScore}% coverage, ${missingCritical} critical gaps`,\n };\n}\n\nfunction scoreRiskControl(\n analysis: ProjectAnalysis,\n selection: ContextSelection,\n insights: ScoreInsight[],\n): DimensionScore {\n const weight = 20;\n\n const dist = analysis.riskProfile.distribution;\n const totalFiles = analysis.totalFiles;\n\n // What % of critical+high risk files are included in the selection?\n const criticalFiles = analysis.files.filter((f) => f.riskScore >= 80);\n const highFiles = analysis.files.filter((f) => f.riskScore >= 60 && f.riskScore < 80);\n const selectedPaths = new Set(selection.files.map((f) => f.relativePath));\n\n const criticalIncluded = criticalFiles.filter((f) => selectedPaths.has(f.relativePath)).length;\n const highIncluded = highFiles.filter((f) => selectedPaths.has(f.relativePath)).length;\n\n const criticalCoverage = criticalFiles.length > 0\n ? criticalIncluded / criticalFiles.length\n : 1;\n const highCoverage = highFiles.length > 0\n ? highIncluded / highFiles.length\n : 1;\n\n // Risk distribution health: fewer critical files = healthier\n const criticalRatio = totalFiles > 0 ? dist.critical / totalFiles : 0;\n const healthScore = Math.max(0, 1 - criticalRatio * 5); // penalize heavy critical\n\n const raw = (criticalCoverage * 0.5 + highCoverage * 0.3 + healthScore * 0.2) * 100;\n const score = Math.min(100, Math.max(0, Math.round(raw)));\n const weighted = (score / 100) * weight;\n\n if (criticalCoverage === 1 && criticalFiles.length > 0) {\n insights.push({\n type: 'strength',\n title: 'All critical files included',\n detail: `${criticalFiles.length} critical-risk files are captured in context`,\n impact: 'high',\n });\n }\n\n if (criticalRatio > 0.2) {\n insights.push({\n type: 'opportunity',\n title: 'High concentration of critical files',\n detail: `${dist.critical} files (${Math.round(criticalRatio * 100)}%) are critical risk. Consider refactoring complex modules.`,\n impact: 'medium',\n });\n }\n\n return {\n score,\n weight,\n weighted,\n detail: `${criticalIncluded}/${criticalFiles.length} critical + ${highIncluded}/${highFiles.length} high-risk files included`,\n };\n}\n\nfunction scoreStructure(\n analysis: ProjectAnalysis,\n insights: ScoreInsight[],\n): DimensionScore {\n const weight = 15;\n\n const graph = analysis.graph;\n const totalFiles = analysis.totalFiles;\n\n // Cluster cohesion: well-organized projects have clear clusters\n const avgCohesion = graph.clusters.length > 0\n ? graph.clusters.reduce((s, c) => s + c.cohesion, 0) / graph.clusters.length\n : 0;\n\n // Orphan penalty: too many orphans = poor structure\n const orphanRatio = totalFiles > 0 ? graph.orphans.length / totalFiles : 0;\n\n // Hub concentration: too few hubs = flat, too many = coupled\n const hubRatio = totalFiles > 0 ? graph.hubs.length / totalFiles : 0;\n const hubHealth = hubRatio > 0.02 && hubRatio < 0.15 ? 1 : Math.max(0, 1 - Math.abs(hubRatio - 0.08) * 10);\n\n // Type coverage: having type files is good for AI\n const typeFiles = analysis.files.filter((f) => f.kind === 'type').length;\n const typeRatio = totalFiles > 0 ? typeFiles / totalFiles : 0;\n const typeScore = Math.min(1, typeRatio * 10); // reward up to 10% types\n\n const raw = (avgCohesion * 0.3 + (1 - orphanRatio) * 0.3 + hubHealth * 0.2 + typeScore * 0.2) * 100;\n const score = Math.min(100, Math.max(0, Math.round(raw)));\n const weighted = (score / 100) * weight;\n\n if (orphanRatio > 0.5) {\n insights.push({\n type: 'weakness',\n title: 'Many orphan files',\n detail: `${graph.orphans.length} files (${Math.round(orphanRatio * 100)}%) have no imports/exports. AI gets less context from the dependency graph.`,\n impact: 'medium',\n });\n }\n\n if (graph.clusters.length > 0 && avgCohesion > 0.7) {\n insights.push({\n type: 'strength',\n title: 'Well-organized module structure',\n detail: `${graph.clusters.length} cohesive clusters (avg cohesion: ${(avgCohesion * 100).toFixed(0)}%). CTO can efficiently select relevant modules.`,\n impact: 'medium',\n });\n }\n\n return {\n score,\n weight,\n weighted,\n detail: `${graph.clusters.length} clusters, ${graph.orphans.length} orphans, ${graph.hubs.length} hubs`,\n };\n}\n\nfunction scoreGovernance(\n analysis: ProjectAnalysis,\n insights: ScoreInsight[],\n): DimensionScore {\n const weight = 10;\n\n // Check for config/policy/type organization\n const hasTypes = analysis.files.some((f) => f.kind === 'type');\n const hasConfig = analysis.files.some((f) => f.kind === 'config');\n const hasTests = analysis.files.some((f) => f.kind === 'test');\n\n let score = 50; // baseline\n\n if (hasTypes) { score += 15; }\n if (hasConfig) { score += 10; }\n if (hasTests) { score += 15; }\n\n // Stack detection: known stacks get better AI support\n if (analysis.stack.length > 0) { score += 10; }\n\n score = Math.min(100, score);\n const weighted = (score / 100) * weight;\n\n if (!hasTests) {\n insights.push({\n type: 'opportunity',\n title: 'No test files detected',\n detail: 'Adding tests helps CTO understand code intent and provides better context boundaries.',\n impact: 'low',\n });\n }\n\n if (!hasTypes) {\n insights.push({\n type: 'opportunity',\n title: 'No type definition files',\n detail: 'Type files dramatically improve AI code generation accuracy. Consider adding interfaces/types.',\n impact: 'medium',\n });\n }\n\n return {\n score,\n weight,\n weighted,\n detail: `types:${hasTypes ? '✓' : '✗'} tests:${hasTests ? '✓' : '✗'} config:${hasConfig ? '✓' : '✗'} stack:${analysis.stack.join(',') || 'unknown'}`,\n };\n}\n\n// ===== HELPERS =====\n\nfunction scoreToGrade(score: number): Grade {\n if (score >= 95) return 'A+';\n if (score >= 90) return 'A';\n if (score >= 85) return 'A-';\n if (score >= 80) return 'B+';\n if (score >= 75) return 'B';\n if (score >= 70) return 'B-';\n if (score >= 65) return 'C+';\n if (score >= 60) return 'C';\n if (score >= 55) return 'C-';\n if (score >= 40) return 'D';\n return 'F';\n}\n\n// ===== RENDERING =====\n\n/**\n * Render the Context Score as a beautiful terminal-friendly string.\n */\nexport function renderContextScore(score: ContextScore): string {\n const lines: string[] = [];\n\n const gradeColor = score.grade.startsWith('A') ? '🟢'\n : score.grade.startsWith('B') ? '🔵'\n : score.grade.startsWith('C') ? '🟡'\n : '🔴';\n\n lines.push('');\n lines.push(` ╔══════════════════════════════════════════════════╗`);\n lines.push(` ║ ║`);\n lines.push(` ║ ${gradeColor} Context Score™ ${padCenter(score.overall.toString(), 3)} / 100 Grade: ${padCenter(score.grade, 2)} ║`);\n lines.push(` ║ ║`);\n lines.push(` ║ ${score.meta.projectName.padEnd(20).substring(0, 20)} ║`);\n lines.push(` ║ ${score.meta.totalFiles} files · ${Math.round(score.meta.totalTokens / 1000)}K tokens ║`);\n lines.push(` ║ ║`);\n lines.push(` ╠══════════════════════════════════════════════════╣`);\n\n // Dimensions\n const dims = [\n { label: 'Efficiency', dim: score.dimensions.efficiency },\n { label: 'Coverage', dim: score.dimensions.coverage },\n { label: 'Risk Control', dim: score.dimensions.riskControl },\n { label: 'Structure', dim: score.dimensions.structure },\n { label: 'Governance', dim: score.dimensions.governance },\n ];\n\n lines.push(` ║ ║`);\n\n for (const { label, dim } of dims) {\n const bar = renderBar(dim.score, 20);\n const pct = dim.score.toString().padStart(3);\n lines.push(` ║ ${label.padEnd(14)} ${bar} ${pct}% (×${dim.weight}%) ║`);\n }\n\n lines.push(` ║ ║`);\n lines.push(` ╠══════════════════════════════════════════════════╣`);\n\n // Comparison\n lines.push(` ║ ║`);\n lines.push(` ║ 💰 vs. Sending Everything: ║`);\n lines.push(` ║ Tokens saved: ${formatNumber(score.comparison.savedTokens).padEnd(12)} (${score.comparison.savedPercent}%) ║`);\n lines.push(` ║ Monthly savings: $${score.comparison.monthlySavingsUSD.toFixed(2).padEnd(10)} ║`);\n lines.push(` ║ (${score.comparison.optimizedTokens.toLocaleString()} vs ${score.comparison.naiveTokens.toLocaleString()} tokens) ║`);\n lines.push(` ║ ║`);\n\n // Insights\n if (score.insights.length > 0) {\n lines.push(` ╠══════════════════════════════════════════════════╣`);\n lines.push(` ║ ║`);\n\n const top = score.insights.slice(0, 5);\n for (const insight of top) {\n const icon = insight.type === 'strength' ? '✅'\n : insight.type === 'weakness' ? '⚠️'\n : '💡';\n const title = insight.title.substring(0, 44).padEnd(44);\n lines.push(` ║ ${icon} ${title} ║`);\n }\n\n lines.push(` ║ ║`);\n }\n\n lines.push(` ╚══════════════════════════════════════════════════╝`);\n lines.push('');\n\n return lines.join('\\n');\n}\n\nfunction renderBar(pct: number, width: number): string {\n const filled = Math.round((pct / 100) * width);\n const empty = width - filled;\n return '█'.repeat(filled) + '░'.repeat(empty);\n}\n\nfunction padCenter(str: string, width: number): string {\n const pad = Math.max(0, width - str.length);\n const left = Math.floor(pad / 2);\n return ' '.repeat(left) + str + ' '.repeat(pad - left);\n}\n\nfunction formatNumber(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`;\n return n.toString();\n}\n","import type { ProjectAnalysis } from '../types/engine.js';\nimport { selectContext } from './selector.js';\n\n// ===== Benchmark Engine =====\n//\n// Proves CTO works with real numbers. Compares three strategies:\n// 1. CTO (risk-aware, deterministic selection)\n// 2. Naive (send everything — what most people do)\n// 3. Random (randomly pick files up to budget — baseline)\n//\n// Measures: tokens, coverage, cost, time\n\nexport interface BenchmarkResult {\n project: string;\n totalFiles: number;\n totalTokens: number;\n budget: number;\n task: string;\n\n strategies: {\n cto: StrategyResult;\n naive: StrategyResult;\n random: StrategyResult;\n };\n\n winner: 'cto' | 'naive' | 'random';\n ctoAdvantage: {\n vsNaiveTokensSaved: number;\n vsNaiveTokensSavedPercent: number;\n vsRandomCoverageGain: number;\n vsNaiveCostSavedMonthlyUSD: number;\n };\n}\n\nexport interface StrategyResult {\n filesSelected: number;\n tokensUsed: number;\n coverageScore: number;\n criticalFilesCovered: number;\n criticalFilesTotal: number;\n highRiskCovered: number;\n highRiskTotal: number;\n costPerInteractionUSD: number;\n timeMs: number;\n}\n\n/**\n * Run a full benchmark comparing CTO vs naive vs random selection.\n */\nexport async function runBenchmark(\n analysis: ProjectAnalysis,\n task: string = 'general code review and refactoring',\n budget: number = 50_000,\n): Promise<BenchmarkResult> {\n const criticalFiles = analysis.files.filter((f) => f.riskScore >= 80);\n const highRiskFiles = analysis.files.filter((f) => f.riskScore >= 60 && f.riskScore < 80);\n\n // ===== STRATEGY 1: CTO (risk-aware selection) =====\n const ctoStart = performance.now();\n const ctoSelection = await selectContext({ task, analysis, budget });\n const ctoTime = performance.now() - ctoStart;\n\n const ctoSelectedPaths = new Set(ctoSelection.files.map((f) => f.relativePath));\n const ctoCritical = criticalFiles.filter((f) => ctoSelectedPaths.has(f.relativePath)).length;\n const ctoHigh = highRiskFiles.filter((f) => ctoSelectedPaths.has(f.relativePath)).length;\n\n const cto: StrategyResult = {\n filesSelected: ctoSelection.files.length,\n tokensUsed: ctoSelection.totalTokens,\n coverageScore: ctoSelection.coverage.score,\n criticalFilesCovered: ctoCritical,\n criticalFilesTotal: criticalFiles.length,\n highRiskCovered: ctoHigh,\n highRiskTotal: highRiskFiles.length,\n costPerInteractionUSD: (ctoSelection.totalTokens / 1_000_000) * 3, // Sonnet pricing\n timeMs: Math.round(ctoTime),\n };\n\n // ===== STRATEGY 2: NAIVE (send everything up to budget) =====\n const naiveStart = performance.now();\n const naiveFiles = [...analysis.files].sort((a, b) => a.relativePath.localeCompare(b.relativePath));\n let naiveTokens = 0;\n let naiveCount = 0;\n const naiveSelectedPaths = new Set<string>();\n\n for (const f of naiveFiles) {\n if (naiveTokens + f.tokens <= budget) {\n naiveTokens += f.tokens;\n naiveCount++;\n naiveSelectedPaths.add(f.relativePath);\n }\n }\n // If budget exceeds total, include everything\n if (naiveTokens === 0 && analysis.totalTokens <= budget) {\n naiveTokens = analysis.totalTokens;\n naiveCount = analysis.totalFiles;\n for (const f of analysis.files) naiveSelectedPaths.add(f.relativePath);\n }\n const naiveTime = performance.now() - naiveStart;\n\n const naiveCritical = criticalFiles.filter((f) => naiveSelectedPaths.has(f.relativePath)).length;\n const naiveHigh = highRiskFiles.filter((f) => naiveSelectedPaths.has(f.relativePath)).length;\n\n // Naive coverage: just count how many of the relevant files are included\n const naiveCoverage = analysis.totalFiles > 0\n ? Math.round((naiveCount / analysis.totalFiles) * 100)\n : 0;\n\n const naive: StrategyResult = {\n filesSelected: naiveCount,\n tokensUsed: naiveTokens > 0 ? naiveTokens : analysis.totalTokens,\n coverageScore: naiveTokens > 0 ? naiveCoverage : 100,\n criticalFilesCovered: naiveCritical,\n criticalFilesTotal: criticalFiles.length,\n highRiskCovered: naiveHigh,\n highRiskTotal: highRiskFiles.length,\n costPerInteractionUSD: ((naiveTokens > 0 ? naiveTokens : analysis.totalTokens) / 1_000_000) * 3,\n timeMs: Math.round(naiveTime),\n };\n\n // ===== STRATEGY 3: RANDOM (randomly pick files up to budget) =====\n const randomStart = performance.now();\n const shuffled = [...analysis.files].sort(() => Math.random() - 0.5);\n let randomTokens = 0;\n let randomCount = 0;\n const randomSelectedPaths = new Set<string>();\n\n for (const f of shuffled) {\n if (randomTokens + f.tokens <= budget) {\n randomTokens += f.tokens;\n randomCount++;\n randomSelectedPaths.add(f.relativePath);\n }\n }\n const randomTime = performance.now() - randomStart;\n\n const randomCritical = criticalFiles.filter((f) => randomSelectedPaths.has(f.relativePath)).length;\n const randomHigh = highRiskFiles.filter((f) => randomSelectedPaths.has(f.relativePath)).length;\n const randomCoverage = analysis.totalFiles > 0\n ? Math.round((randomCount / analysis.totalFiles) * 100)\n : 0;\n\n const random: StrategyResult = {\n filesSelected: randomCount,\n tokensUsed: randomTokens,\n coverageScore: randomCoverage,\n criticalFilesCovered: randomCritical,\n criticalFilesTotal: criticalFiles.length,\n highRiskCovered: randomHigh,\n highRiskTotal: highRiskFiles.length,\n costPerInteractionUSD: (randomTokens / 1_000_000) * 3,\n timeMs: Math.round(randomTime),\n };\n\n // ===== DETERMINE WINNER =====\n // Score: coverage * 0.5 + criticalCoverage * 0.3 + tokenEfficiency * 0.2\n const ctoScore = computeStrategyScore(cto, budget);\n const naiveScore = computeStrategyScore(naive, budget);\n const randomScore = computeStrategyScore(random, budget);\n\n const winner = ctoScore >= naiveScore && ctoScore >= randomScore ? 'cto'\n : naiveScore >= randomScore ? 'naive' : 'random';\n\n // Monthly savings: 40 interactions/day × 20 days\n const interactionsPerMonth = 800;\n const vsNaiveCostSaved = (naive.costPerInteractionUSD - cto.costPerInteractionUSD) * interactionsPerMonth;\n\n return {\n project: analysis.projectName,\n totalFiles: analysis.totalFiles,\n totalTokens: analysis.totalTokens,\n budget,\n task,\n strategies: { cto, naive, random },\n winner,\n ctoAdvantage: {\n vsNaiveTokensSaved: naive.tokensUsed - cto.tokensUsed,\n vsNaiveTokensSavedPercent: naive.tokensUsed > 0\n ? Math.round(((naive.tokensUsed - cto.tokensUsed) / naive.tokensUsed) * 100)\n : 0,\n vsRandomCoverageGain: cto.coverageScore - random.coverageScore,\n vsNaiveCostSavedMonthlyUSD: Math.round(vsNaiveCostSaved * 100) / 100,\n },\n };\n}\n\nfunction computeStrategyScore(strategy: StrategyResult, budget: number): number {\n const coverageWeight = strategy.coverageScore / 100;\n const criticalWeight = strategy.criticalFilesTotal > 0\n ? strategy.criticalFilesCovered / strategy.criticalFilesTotal\n : 1;\n const efficiency = budget > 0 ? 1 - (strategy.tokensUsed / budget) : 0;\n\n return coverageWeight * 0.5 + criticalWeight * 0.3 + Math.max(0, efficiency) * 0.2;\n}\n\n/**\n * Render benchmark results as a formatted comparison table.\n */\nexport function renderBenchmark(result: BenchmarkResult): string {\n const lines: string[] = [];\n const { cto, naive, random } = result.strategies;\n\n lines.push('');\n lines.push(` ╔══════════════════════════════════════════════════════════════╗`);\n lines.push(` ║ ⚡ CTO Benchmark — ${result.project.substring(0, 20).padEnd(20)} ║`);\n lines.push(` ╠══════════════════════════════════════════════════════════════╣`);\n lines.push(` ║ ║`);\n lines.push(` ║ ${pad('Metric', 20)} ${pad('CTO', 12)} ${pad('Naive', 12)} ${pad('Random', 12)} ║`);\n lines.push(` ║ ${'─'.repeat(56)} ║`);\n lines.push(` ║ ${pad('Files selected', 20)} ${pad(cto.filesSelected.toString(), 12)} ${pad(naive.filesSelected.toString(), 12)} ${pad(random.filesSelected.toString(), 12)} ║`);\n lines.push(` ║ ${pad('Tokens used', 20)} ${pad(fmt(cto.tokensUsed), 12)} ${pad(fmt(naive.tokensUsed), 12)} ${pad(fmt(random.tokensUsed), 12)} ║`);\n lines.push(` ║ ${pad('Coverage', 20)} ${pad(cto.coverageScore + '%', 12)} ${pad(naive.coverageScore + '%', 12)} ${pad(random.coverageScore + '%', 12)} ║`);\n lines.push(` ║ ${pad('Critical files', 20)} ${pad(`${cto.criticalFilesCovered}/${cto.criticalFilesTotal}`, 12)} ${pad(`${naive.criticalFilesCovered}/${naive.criticalFilesTotal}`, 12)} ${pad(`${random.criticalFilesCovered}/${random.criticalFilesTotal}`, 12)} ║`);\n lines.push(` ║ ${pad('High-risk files', 20)} ${pad(`${cto.highRiskCovered}/${cto.highRiskTotal}`, 12)} ${pad(`${naive.highRiskCovered}/${naive.highRiskTotal}`, 12)} ${pad(`${random.highRiskCovered}/${random.highRiskTotal}`, 12)} ║`);\n lines.push(` ║ ${pad('Cost/interaction', 20)} ${pad('$' + cto.costPerInteractionUSD.toFixed(4), 12)} ${pad('$' + naive.costPerInteractionUSD.toFixed(4), 12)} ${pad('$' + random.costPerInteractionUSD.toFixed(4), 12)} ║`);\n lines.push(` ║ ${pad('Time', 20)} ${pad(cto.timeMs + 'ms', 12)} ${pad(naive.timeMs + 'ms', 12)} ${pad(random.timeMs + 'ms', 12)} ║`);\n lines.push(` ║ ║`);\n lines.push(` ╠══════════════════════════════════════════════════════════════╣`);\n lines.push(` ║ ║`);\n lines.push(` ║ 🏆 Winner: ${result.winner.toUpperCase().padEnd(48)} ║`);\n\n if (result.ctoAdvantage.vsNaiveTokensSavedPercent > 0) {\n lines.push(` ║ 📉 ${result.ctoAdvantage.vsNaiveTokensSavedPercent}% fewer tokens than naive ║`);\n }\n if (result.ctoAdvantage.vsRandomCoverageGain > 0) {\n lines.push(` ║ 📈 +${result.ctoAdvantage.vsRandomCoverageGain}% better coverage than random ║`);\n }\n if (result.ctoAdvantage.vsNaiveCostSavedMonthlyUSD > 0) {\n lines.push(` ║ 💰 $${result.ctoAdvantage.vsNaiveCostSavedMonthlyUSD.toFixed(2)}/mo saved vs naive (800 interactions) ║`);\n }\n\n lines.push(` ║ ║`);\n lines.push(` ╚══════════════════════════════════════════════════════════════╝`);\n lines.push('');\n\n return lines.join('\\n');\n}\n\nfunction pad(s: string, w: number): string { return s.padEnd(w).substring(0, w); }\nfunction fmt(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`;\n return n.toString();\n}\n","import { resolve } from 'node:path';\nimport { readFile } from 'node:fs/promises';\nimport type { ProjectAnalysis, AnalyzedFile, ContextSelection } from '../types/engine.js';\nimport type { TaskType } from '../types/interact.js';\nimport { selectContext } from './selector.js';\nimport { buildAdjacencyList, bfsBidirectional } from './graph-utils.js';\nimport { classifyTask } from '../interact/router.js';\nimport { buildPrompt } from '../interact/prompt.js';\nimport { countTokensChars4 } from './tokenizer.js';\n\n// ===== Quality Benchmark =====\n//\n// Proves that CTO context → better AI output by comparing prompt quality\n// across three strategies: CTO (risk-aware), Naive (alphabetical), Random.\n//\n// Metrics:\n// 1. Relevance Score — What % of included files are actually relevant to the task?\n// 2. Completeness Score — What % of task-critical files are included?\n// 3. Noise Ratio — What % of tokens are wasted on irrelevant files?\n// 4. Type Coverage — Are type definitions included for the selected files?\n// 5. Dependency Closure — Are transitive deps of relevant files included?\n//\n// These are PROXY metrics for output quality. The claim:\n// Higher relevance + completeness → fewer hallucinations + more correct code.\n\nexport interface QualityBenchmarkResult {\n project: string;\n task: string;\n taskType: TaskType;\n budget: number;\n\n strategies: {\n cto: QualityMetrics;\n naive: QualityMetrics;\n random: QualityMetrics;\n };\n\n comparison: {\n ctoVsNaiveRelevance: number;\n ctoVsRandomRelevance: number;\n ctoVsNaiveCompleteness: number;\n ctoVsRandomCompleteness: number;\n ctoNoiseReduction: number;\n };\n\n prompts: {\n cto: { rendered: string; tokens: number };\n naive: { rendered: string; tokens: number };\n };\n\n verdict: string;\n}\n\nexport interface QualityMetrics {\n filesSelected: number;\n tokensUsed: number;\n\n relevanceScore: number;\n completenessScore: number;\n noiseRatio: number;\n typeCoverage: number;\n dependencyClosure: number;\n\n relevantFilesIncluded: number;\n relevantFilesTotal: number;\n typeFilesIncluded: number;\n typeFilesNeeded: number;\n depsIncluded: number;\n depsNeeded: number;\n}\n\n// ===== MAIN API =====\n\n/**\n * Run a quality benchmark comparing CTO vs naive vs random context selection.\n * Measures relevance, completeness, noise, and dependency closure.\n */\nexport async function runQualityBenchmark(\n analysis: ProjectAnalysis,\n task: string,\n budget: number = 50_000,\n): Promise<QualityBenchmarkResult> {\n const taskType = classifyTask(task);\n\n // 1. Identify task-relevant files using keyword matching + graph expansion\n const relevantFiles = identifyRelevantFiles(analysis, task, taskType);\n const relevantPaths = new Set(relevantFiles.map((f) => f.relativePath));\n\n // 2. Identify type files needed by relevant files\n const typeFilesNeeded = findTypeFiles(analysis, relevantFiles);\n const typePaths = new Set(typeFilesNeeded.map((f) => f.relativePath));\n\n // 3. Identify transitive deps of relevant files\n const adj = buildAdjacencyList(analysis.graph.edges);\n const depsNeeded = bfsBidirectional(\n relevantFiles.map((f) => f.relativePath),\n adj,\n 2,\n );\n\n // 4. Run CTO selection\n const ctoSelection = await selectContext({ task, analysis, budget });\n const ctoMetrics = computeMetrics(\n ctoSelection.files.map((f) => f.relativePath),\n ctoSelection.totalTokens,\n analysis,\n relevantPaths,\n typePaths,\n depsNeeded,\n );\n\n // 5. Run Naive selection (alphabetical, up to budget)\n const naiveFiles = [...analysis.files]\n .sort((a, b) => a.relativePath.localeCompare(b.relativePath));\n const naiveSelected: string[] = [];\n let naiveTokens = 0;\n for (const f of naiveFiles) {\n if (naiveTokens + f.tokens <= budget) {\n naiveSelected.push(f.relativePath);\n naiveTokens += f.tokens;\n }\n }\n if (naiveSelected.length === 0 && analysis.totalTokens <= budget) {\n for (const f of analysis.files) naiveSelected.push(f.relativePath);\n naiveTokens = analysis.totalTokens;\n }\n const naiveMetrics = computeMetrics(\n naiveSelected, naiveTokens, analysis, relevantPaths, typePaths, depsNeeded,\n );\n\n // 6. Run Random selection\n const shuffled = [...analysis.files].sort(() => Math.random() - 0.5);\n const randomSelected: string[] = [];\n let randomTokens = 0;\n for (const f of shuffled) {\n if (randomTokens + f.tokens <= budget) {\n randomSelected.push(f.relativePath);\n randomTokens += f.tokens;\n }\n }\n const randomMetrics = computeMetrics(\n randomSelected, randomTokens, analysis, relevantPaths, typePaths, depsNeeded,\n );\n\n // 7. Generate actual prompts for CTO vs Naive\n const ctoPrompt = buildPrompt({\n task,\n taskType,\n analysis,\n selection: ctoSelection,\n enableCoT: true,\n });\n\n // Build a fake selection for naive to generate its prompt\n const naiveSelectionFiles = naiveSelected.map((p) => {\n const f = analysis.files.find((af) => af.relativePath === p);\n return {\n relativePath: p,\n tokens: f?.tokens ?? 0,\n originalTokens: f?.tokens ?? 0,\n pruneLevel: 'full' as const,\n riskScore: f?.riskScore ?? 0,\n reason: 'alphabetical inclusion',\n };\n });\n const naiveFakeSelection: ContextSelection = {\n files: naiveSelectionFiles,\n totalTokens: naiveTokens,\n budget,\n usedPercent: budget > 0 ? (naiveTokens / budget) * 100 : 0,\n coverage: { score: naiveMetrics.completenessScore, missingCritical: [], missingRelevant: [], relevantFiles: [], includedRelevant: [], explanation: 'naive selection' },\n riskScore: 0,\n deterministic: false,\n hash: '',\n decisions: [],\n };\n const naivePrompt = buildPrompt({\n task,\n taskType,\n analysis,\n selection: naiveFakeSelection,\n enableCoT: true,\n });\n\n // 8. Comparison\n const comparison = {\n ctoVsNaiveRelevance: ctoMetrics.relevanceScore - naiveMetrics.relevanceScore,\n ctoVsRandomRelevance: ctoMetrics.relevanceScore - randomMetrics.relevanceScore,\n ctoVsNaiveCompleteness: ctoMetrics.completenessScore - naiveMetrics.completenessScore,\n ctoVsRandomCompleteness: ctoMetrics.completenessScore - randomMetrics.completenessScore,\n ctoNoiseReduction: naiveMetrics.noiseRatio - ctoMetrics.noiseRatio,\n };\n\n // 9. Verdict\n const verdict = generateVerdict(ctoMetrics, naiveMetrics, randomMetrics, comparison);\n\n return {\n project: analysis.projectName,\n task,\n taskType,\n budget,\n strategies: {\n cto: ctoMetrics,\n naive: naiveMetrics,\n random: randomMetrics,\n },\n comparison,\n prompts: {\n cto: { rendered: ctoPrompt.rendered, tokens: ctoPrompt.totalTokens },\n naive: { rendered: naivePrompt.rendered, tokens: naivePrompt.totalTokens },\n },\n verdict,\n };\n}\n\n// ===== RELEVANCE IDENTIFICATION =====\n\nfunction identifyRelevantFiles(\n analysis: ProjectAnalysis,\n task: string,\n taskType: TaskType,\n): AnalyzedFile[] {\n const keywords = extractKeywords(task);\n const scored = new Map<string, number>();\n\n for (const file of analysis.files) {\n let relevance = 0;\n\n // Keyword match in path\n for (const kw of keywords) {\n if (file.relativePath.toLowerCase().includes(kw)) {\n relevance += 10;\n }\n }\n\n // High risk = likely important\n if (file.riskScore >= 60) relevance += 5;\n\n // Hub files are often relevant\n if (file.isHub) relevance += 3;\n\n // Entry points\n if (file.kind === 'entry') relevance += 3;\n\n // Type files that define interfaces used across the project\n if (file.kind === 'type') relevance += 2;\n\n // Task-type specific boosts\n if (taskType === 'test' && file.kind === 'test') relevance += 8;\n if (taskType === 'refactor' && file.complexity > 10) relevance += 4;\n if (taskType === 'debug' && file.riskScore >= 40) relevance += 4;\n\n if (relevance > 0) {\n scored.set(file.relativePath, relevance);\n }\n }\n\n // Expand via dependencies\n const adj = buildAdjacencyList(analysis.graph.edges);\n const seeds = [...scored.keys()];\n const expanded = bfsBidirectional(seeds, adj, 1);\n\n // Add expanded files with lower score\n for (const path of expanded) {\n if (!scored.has(path)) {\n scored.set(path, 1);\n }\n }\n\n // Return files sorted by relevance\n return analysis.files\n .filter((f) => scored.has(f.relativePath))\n .sort((a, b) => (scored.get(b.relativePath) ?? 0) - (scored.get(a.relativePath) ?? 0));\n}\n\nfunction extractKeywords(task: string): string[] {\n const stopWords = new Set([\n 'the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been', 'being',\n 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could',\n 'should', 'may', 'might', 'can', 'shall', 'to', 'of', 'in', 'for',\n 'on', 'with', 'at', 'by', 'from', 'as', 'into', 'through', 'and',\n 'but', 'or', 'nor', 'not', 'so', 'yet', 'both', 'either', 'neither',\n 'this', 'that', 'these', 'those', 'it', 'its', 'my', 'your', 'our',\n 'their', 'his', 'her', 'fix', 'add', 'remove', 'update', 'change',\n 'refactor', 'implement', 'create', 'build', 'make', 'code', 'file',\n ]);\n\n return task\n .toLowerCase()\n .replace(/[^a-z0-9\\s]/g, '')\n .split(/\\s+/)\n .filter((w) => w.length > 2 && !stopWords.has(w));\n}\n\nfunction findTypeFiles(\n analysis: ProjectAnalysis,\n relevantFiles: AnalyzedFile[],\n): AnalyzedFile[] {\n const adj = buildAdjacencyList(analysis.graph.edges);\n const typeFiles = new Set<string>();\n\n for (const file of relevantFiles) {\n // Find forward deps that are type files\n const deps = adj.forward.get(file.relativePath) ?? [];\n for (const dep of deps) {\n const depFile = analysis.files.find((f) => f.relativePath === dep);\n if (depFile && depFile.kind === 'type') {\n typeFiles.add(dep);\n }\n }\n }\n\n return analysis.files.filter((f) => typeFiles.has(f.relativePath));\n}\n\n// ===== METRICS COMPUTATION =====\n\nfunction computeMetrics(\n selectedPaths: string[],\n tokensUsed: number,\n analysis: ProjectAnalysis,\n relevantPaths: Set<string>,\n typePaths: Set<string>,\n depsNeeded: Set<string>,\n): QualityMetrics {\n const selected = new Set(selectedPaths);\n\n // Relevance: what % of selected files are actually relevant?\n const relevantIncluded = selectedPaths.filter((p) => relevantPaths.has(p)).length;\n const relevanceScore = selectedPaths.length > 0\n ? Math.round((relevantIncluded / selectedPaths.length) * 100)\n : 0;\n\n // Completeness: what % of relevant files are included?\n const completenessHits = [...relevantPaths].filter((p) => selected.has(p)).length;\n const completenessScore = relevantPaths.size > 0\n ? Math.round((completenessHits / relevantPaths.size) * 100)\n : 100;\n\n // Noise: what % of tokens are spent on irrelevant files?\n let irrelevantTokens = 0;\n for (const path of selectedPaths) {\n if (!relevantPaths.has(path)) {\n const f = analysis.files.find((af) => af.relativePath === path);\n irrelevantTokens += f?.tokens ?? 0;\n }\n }\n const noiseRatio = tokensUsed > 0\n ? Math.min(100, Math.round((irrelevantTokens / tokensUsed) * 100))\n : 0;\n\n // Type coverage: are needed type files included?\n const typeIncluded = [...typePaths].filter((p) => selected.has(p)).length;\n const typeCoverage = typePaths.size > 0\n ? Math.round((typeIncluded / typePaths.size) * 100)\n : 100;\n\n // Dependency closure: are transitive deps included?\n const depsIncluded = [...depsNeeded].filter((p) => selected.has(p)).length;\n const dependencyClosure = depsNeeded.size > 0\n ? Math.round((depsIncluded / depsNeeded.size) * 100)\n : 100;\n\n return {\n filesSelected: selectedPaths.length,\n tokensUsed,\n relevanceScore,\n completenessScore,\n noiseRatio,\n typeCoverage,\n dependencyClosure,\n relevantFilesIncluded: relevantIncluded,\n relevantFilesTotal: relevantPaths.size,\n typeFilesIncluded: typeIncluded,\n typeFilesNeeded: typePaths.size,\n depsIncluded,\n depsNeeded: depsNeeded.size,\n };\n}\n\n// ===== VERDICT =====\n\nfunction generateVerdict(\n cto: QualityMetrics,\n naive: QualityMetrics,\n random: QualityMetrics,\n comp: QualityBenchmarkResult['comparison'],\n): string {\n const lines: string[] = [];\n\n lines.push('## Quality Verdict');\n lines.push('');\n\n // Headline\n if (comp.ctoVsNaiveRelevance > 0 && comp.ctoVsNaiveCompleteness > 0) {\n lines.push(`**CTO produces higher-quality context than both naive and random selection.**`);\n } else if (comp.ctoVsRandomRelevance > 0) {\n lines.push(`**CTO produces higher-quality context than random selection.**`);\n } else {\n lines.push(`**All strategies perform similarly for this task.**`);\n }\n lines.push('');\n\n // Relevance\n lines.push(`### Relevance (higher = less hallucination risk)`);\n lines.push(`- CTO: ${cto.relevanceScore}% of included files are relevant`);\n lines.push(`- Naive: ${naive.relevanceScore}% relevant`);\n lines.push(`- Random: ${random.relevanceScore}% relevant`);\n if (comp.ctoVsNaiveRelevance > 0) {\n lines.push(`- **CTO includes ${comp.ctoVsNaiveRelevance}% more relevant files than naive**`);\n }\n lines.push('');\n\n // Completeness\n lines.push(`### Completeness (higher = more correct code generation)`);\n lines.push(`- CTO: ${cto.completenessScore}% of required files included`);\n lines.push(`- Naive: ${naive.completenessScore}% complete`);\n lines.push(`- Random: ${random.completenessScore}% complete`);\n if (comp.ctoVsNaiveCompleteness > 0) {\n lines.push(`- **CTO captures ${comp.ctoVsNaiveCompleteness}% more required files**`);\n }\n lines.push('');\n\n // Noise\n lines.push(`### Noise (lower = less distraction for the AI)`);\n lines.push(`- CTO: ${cto.noiseRatio}% noise`);\n lines.push(`- Naive: ${naive.noiseRatio}% noise`);\n lines.push(`- Random: ${random.noiseRatio}% noise`);\n if (comp.ctoNoiseReduction > 0) {\n lines.push(`- **CTO reduces noise by ${comp.ctoNoiseReduction} percentage points**`);\n }\n lines.push('');\n\n // Type coverage\n lines.push(`### Type Coverage (higher = fewer type errors in generated code)`);\n lines.push(`- CTO: ${cto.typeCoverage}% | Naive: ${naive.typeCoverage}% | Random: ${random.typeCoverage}%`);\n lines.push('');\n\n // Dependency closure\n lines.push(`### Dependency Closure (higher = AI understands import chain)`);\n lines.push(`- CTO: ${cto.dependencyClosure}% | Naive: ${naive.dependencyClosure}% | Random: ${random.dependencyClosure}%`);\n\n return lines.join('\\n');\n}\n\n// ===== RENDERING =====\n\nexport function renderQualityBenchmark(result: QualityBenchmarkResult): string {\n const { cto, naive, random } = result.strategies;\n const lines: string[] = [];\n\n lines.push('');\n lines.push(` ╔══════════════════════════════════════════════════════════════════╗`);\n lines.push(` ║ 🔬 Quality Benchmark — ${pad(result.project, 20)} ║`);\n lines.push(` ║ Task: ${pad(result.task.substring(0, 45), 45)} ║`);\n lines.push(` ╠══════════════════════════════════════════════════════════════════╣`);\n lines.push(` ║ ║`);\n lines.push(` ║ ${pad('Metric', 22)} ${pad('CTO', 12)} ${pad('Naive', 12)} ${pad('Random', 12)} ║`);\n lines.push(` ║ ${'─'.repeat(58)} ║`);\n lines.push(` ║ ${pad('Relevance', 22)} ${pad(cto.relevanceScore + '%', 12)} ${pad(naive.relevanceScore + '%', 12)} ${pad(random.relevanceScore + '%', 12)} ║`);\n lines.push(` ║ ${pad('Completeness', 22)} ${pad(cto.completenessScore + '%', 12)} ${pad(naive.completenessScore + '%', 12)} ${pad(random.completenessScore + '%', 12)} ║`);\n lines.push(` ║ ${pad('Noise ratio', 22)} ${pad(cto.noiseRatio + '%', 12)} ${pad(naive.noiseRatio + '%', 12)} ${pad(random.noiseRatio + '%', 12)} ║`);\n lines.push(` ║ ${pad('Type coverage', 22)} ${pad(cto.typeCoverage + '%', 12)} ${pad(naive.typeCoverage + '%', 12)} ${pad(random.typeCoverage + '%', 12)} ║`);\n lines.push(` ║ ${pad('Dependency closure', 22)} ${pad(cto.dependencyClosure + '%', 12)} ${pad(naive.dependencyClosure + '%', 12)} ${pad(random.dependencyClosure + '%', 12)} ║`);\n lines.push(` ║ ${'─'.repeat(58)} ║`);\n lines.push(` ║ ${pad('Relevant files', 22)} ${pad(`${cto.relevantFilesIncluded}/${cto.relevantFilesTotal}`, 12)} ${pad(`${naive.relevantFilesIncluded}/${naive.relevantFilesTotal}`, 12)} ${pad(`${random.relevantFilesIncluded}/${random.relevantFilesTotal}`, 12)} ║`);\n lines.push(` ║ ${pad('Type files', 22)} ${pad(`${cto.typeFilesIncluded}/${cto.typeFilesNeeded}`, 12)} ${pad(`${naive.typeFilesIncluded}/${naive.typeFilesNeeded}`, 12)} ${pad(`${random.typeFilesIncluded}/${random.typeFilesNeeded}`, 12)} ║`);\n lines.push(` ║ ${pad('Tokens used', 22)} ${pad(fmt(cto.tokensUsed), 12)} ${pad(fmt(naive.tokensUsed), 12)} ${pad(fmt(random.tokensUsed), 12)} ║`);\n lines.push(` ║ ║`);\n\n // Comparison highlights\n const c = result.comparison;\n if (c.ctoVsNaiveRelevance > 0) {\n lines.push(` ║ 📈 +${c.ctoVsNaiveRelevance}% more relevant files than naive ║`);\n }\n if (c.ctoVsNaiveCompleteness > 0) {\n lines.push(` ║ ✅ +${c.ctoVsNaiveCompleteness}% more complete context than naive ║`);\n }\n if (c.ctoNoiseReduction > 0) {\n lines.push(` ║ 🔇 ${c.ctoNoiseReduction}% less noise than naive ║`);\n }\n\n lines.push(` ║ ║`);\n lines.push(` ╚══════════════════════════════════════════════════════════════════╝`);\n lines.push('');\n\n return lines.join('\\n');\n}\n\nfunction pad(s: string, w: number): string { return s.padEnd(w).substring(0, w); }\nfunction fmt(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`;\n return n.toString();\n}\n","import type { TaskType, ModelChoice, ModelSpec, ModelId } from '../types/interact.js';\nimport type { ProjectAnalysis } from '../types/engine.js';\n\n// ===== MODEL REGISTRY =====\n\nexport const MODEL_REGISTRY: ModelSpec[] = [\n {\n id: 'claude-haiku-3.5',\n name: 'Claude 3.5 Haiku',\n tier: 'fast',\n pricing: { inputPerMillion: 0.80, outputPerMillion: 4.00, cacheReadPerMillion: 0.08 },\n contextWindow: 200_000,\n strengths: ['speed', 'simple-tasks', 'low-cost'],\n },\n {\n id: 'claude-sonnet-4',\n name: 'Claude Sonnet 4',\n tier: 'balanced',\n pricing: { inputPerMillion: 3.00, outputPerMillion: 15.00, cacheReadPerMillion: 0.30 },\n contextWindow: 200_000,\n strengths: ['code-generation', 'refactoring', 'balanced-reasoning'],\n },\n {\n id: 'claude-opus-4',\n name: 'Claude Opus 4',\n tier: 'reasoning',\n pricing: { inputPerMillion: 15.00, outputPerMillion: 75.00, cacheReadPerMillion: 1.50 },\n contextWindow: 200_000,\n strengths: ['deep-reasoning', 'architecture', 'complex-debugging'],\n },\n];\n\n// ===== ROUTING RULES =====\n\ninterface RoutingRule {\n task: TaskType;\n defaultModel: ModelId;\n upgradeIf: (analysis: ProjectAnalysis) => boolean;\n upgradeTo: ModelId;\n reason: string;\n upgradeReason: string;\n}\n\nconst ROUTING_RULES: RoutingRule[] = [\n {\n task: 'simple-edit',\n defaultModel: 'claude-haiku-3.5',\n upgradeIf: () => false,\n upgradeTo: 'claude-haiku-3.5',\n reason: 'Simple edits are best handled by fast models',\n upgradeReason: '',\n },\n {\n task: 'docs',\n defaultModel: 'claude-haiku-3.5',\n upgradeIf: (a) => a.totalTokens > 100_000,\n upgradeTo: 'claude-sonnet-4',\n reason: 'Documentation tasks are straightforward',\n upgradeReason: 'Large codebase — Sonnet provides better understanding',\n },\n {\n task: 'test',\n defaultModel: 'claude-sonnet-4',\n upgradeIf: (a) => a.riskProfile.overallComplexity > 15,\n upgradeTo: 'claude-opus-4',\n reason: 'Test generation requires good code understanding',\n upgradeReason: 'High complexity codebase — Opus for better test coverage',\n },\n {\n task: 'debug',\n defaultModel: 'claude-sonnet-4',\n upgradeIf: (a) => a.riskProfile.distribution.critical > 5,\n upgradeTo: 'claude-opus-4',\n reason: 'Debugging requires solid reasoning about code flow',\n upgradeReason: 'Many critical files involved — Opus for deeper analysis',\n },\n {\n task: 'refactor',\n defaultModel: 'claude-sonnet-4',\n upgradeIf: (a) => a.totalFiles > 50 && a.riskProfile.overallComplexity > 10,\n upgradeTo: 'claude-opus-4',\n reason: 'Refactoring needs good structural understanding',\n upgradeReason: 'Large + complex project — Opus for safer refactoring',\n },\n {\n task: 'review',\n defaultModel: 'claude-sonnet-4',\n upgradeIf: (a) => a.riskProfile.distribution.critical > 3,\n upgradeTo: 'claude-opus-4',\n reason: 'Code review benefits from balanced reasoning',\n upgradeReason: 'Critical code under review — Opus for thorough analysis',\n },\n {\n task: 'feature',\n defaultModel: 'claude-sonnet-4',\n upgradeIf: (a) => a.totalFiles > 100,\n upgradeTo: 'claude-opus-4',\n reason: 'Feature development needs code generation + understanding',\n upgradeReason: 'Large codebase — Opus for better integration',\n },\n {\n task: 'architecture',\n defaultModel: 'claude-opus-4',\n upgradeIf: () => false,\n upgradeTo: 'claude-opus-4',\n reason: 'Architecture decisions require deep reasoning',\n upgradeReason: '',\n },\n];\n\n// ===== TASK CLASSIFICATION =====\n\nconst TASK_KEYWORDS: Record<TaskType, string[]> = {\n debug: ['debug', 'fix', 'bug', 'error', 'issue', 'broken', 'crash', 'failing', 'wrong'],\n review: ['review', 'check', 'assess', 'evaluate', 'audit', 'inspect', 'critique'],\n refactor: ['refactor', 'restructure', 'reorganize', 'clean up', 'simplify', 'extract', 'move'],\n test: ['test', 'spec', 'coverage', 'unit test', 'integration test', 'e2e'],\n docs: ['document', 'docs', 'readme', 'jsdoc', 'comment', 'explain'],\n feature: ['add', 'implement', 'create', 'build', 'new', 'feature', 'endpoint'],\n architecture: ['architecture', 'design', 'system', 'structure', 'migrate', 'pattern'],\n 'simple-edit': ['rename', 'typo', 'update', 'change', 'modify', 'tweak', 'adjust'],\n};\n\nexport function classifyTask(taskDescription: string): TaskType {\n const lower = taskDescription.toLowerCase();\n\n // Score each task type by keyword matches\n let bestType: TaskType = 'simple-edit';\n let bestScore = 0;\n\n for (const [type, keywords] of Object.entries(TASK_KEYWORDS) as [TaskType, string[]][]) {\n let score = 0;\n for (const kw of keywords) {\n if (lower.includes(kw)) score++;\n }\n if (score > bestScore) {\n bestScore = score;\n bestType = type;\n }\n }\n\n return bestType;\n}\n\n// ===== MODEL ROUTING =====\n\nexport function routeModel(\n taskType: TaskType,\n analysis: ProjectAnalysis,\n preferredModel?: ModelId,\n): ModelChoice {\n // If user explicitly chose a model, respect it\n if (preferredModel) {\n const spec = MODEL_REGISTRY.find((m) => m.id === preferredModel);\n if (spec) {\n return {\n model: preferredModel,\n reason: 'User-specified model',\n confidence: 1.0,\n alternatives: buildAlternatives(preferredModel, taskType),\n };\n }\n }\n\n // Find routing rule for this task\n const rule = ROUTING_RULES.find((r) => r.task === taskType);\n if (!rule) {\n return {\n model: 'claude-sonnet-4',\n reason: 'Default model for unrecognized task type',\n confidence: 0.5,\n alternatives: buildAlternatives('claude-sonnet-4', taskType),\n };\n }\n\n // Check if upgrade is warranted\n const shouldUpgrade = rule.upgradeIf(analysis);\n const model = shouldUpgrade ? rule.upgradeTo : rule.defaultModel;\n const reason = shouldUpgrade ? rule.upgradeReason : rule.reason;\n\n return {\n model,\n reason,\n confidence: shouldUpgrade ? 0.8 : 0.9,\n alternatives: buildAlternatives(model, taskType),\n };\n}\n\n// ===== HELPERS =====\n\nfunction buildAlternatives(chosenModel: ModelId, taskType: TaskType) {\n return MODEL_REGISTRY\n .filter((m) => m.id !== chosenModel)\n .map((m) => {\n const chosen = MODEL_REGISTRY.find((r) => r.id === chosenModel)!;\n const costDelta = m.pricing.inputPerMillion - chosen.pricing.inputPerMillion;\n const tradeoff = costDelta > 0\n ? `More capable but ${(costDelta / chosen.pricing.inputPerMillion * 100).toFixed(0)}% more expensive`\n : `${Math.abs(costDelta / chosen.pricing.inputPerMillion * 100).toFixed(0)}% cheaper but less capable`;\n\n return { model: m.id, costDelta, tradeoff };\n });\n}\n\nexport function getModelSpec(modelId: ModelId): ModelSpec | undefined {\n return MODEL_REGISTRY.find((m) => m.id === modelId);\n}\n","import type { StructuredPrompt, PromptSection, TaskType } from '../types/interact.js';\nimport type { ContextSelection, ProjectAnalysis } from '../types/engine.js';\nimport { countTokensChars4 } from '../engine/tokenizer.js';\n\n// ===== STRUCTURED PROMPT BUILDER =====\n//\n// Not templates. Not libraries.\n// Task-aware prompt construction with sections that can be measured and optimized.\n\nexport interface PromptOptions {\n task: string;\n taskType: TaskType;\n analysis: ProjectAnalysis;\n selection: ContextSelection;\n enableCoT?: boolean;\n enableConstraints?: boolean;\n enableAntiHallucination?: boolean;\n}\n\nexport function buildPrompt(options: PromptOptions): StructuredPrompt {\n const {\n task,\n taskType,\n analysis,\n selection,\n enableCoT = true,\n enableConstraints = true,\n enableAntiHallucination = true,\n } = options;\n\n const sections: PromptSection[] = [];\n\n // 1. System section — role priming\n sections.push(buildSystemSection(analysis.stack, taskType));\n\n // 2. Context section — project info + selected files\n sections.push(buildContextSection(analysis, selection));\n\n // 3. Task section — what the user wants\n sections.push(buildTaskSection(task, taskType));\n\n // 4. Constraints section — safety rails\n if (enableConstraints) {\n sections.push(buildConstraintsSection(analysis.stack, taskType));\n }\n\n // 5. Chain-of-thought section\n if (enableCoT) {\n sections.push(buildCoTSection(taskType));\n }\n\n // 6. Anti-hallucination section\n if (enableAntiHallucination) {\n sections.push(buildAntiHallucinationSection());\n }\n\n // 7. Output format section\n sections.push(buildFormatSection(taskType));\n\n const rendered = sections.map((s) => s.content).join('\\n\\n---\\n\\n');\n const totalTokens = sections.reduce((s, sec) => s + sec.tokens, 0);\n\n return { sections, totalTokens, rendered };\n}\n\n// ===== SECTION BUILDERS =====\n\nfunction buildSystemSection(stack: string[], taskType: TaskType): PromptSection {\n const stackStr = stack.length > 0 ? stack.join(', ') : 'software';\n const taskRole = TASK_ROLES[taskType] ?? 'engineer';\n\n const content = [\n `You are a senior ${stackStr} ${taskRole} with deep expertise in clean architecture, testing, and production-quality code.`,\n 'You prioritize correctness, readability, and maintainability.',\n 'You never make assumptions without evidence from the code.',\n ].join(' ');\n\n return makeSection('system', 'system', content);\n}\n\nfunction buildContextSection(\n analysis: ProjectAnalysis,\n selection: ContextSelection,\n): PromptSection {\n const lines: string[] = [];\n\n lines.push(`## Project: ${analysis.projectName}`);\n lines.push(`Stack: ${analysis.stack.join(', ') || 'Unknown'}`);\n lines.push(`Files analyzed: ${analysis.totalFiles} | Tokens: ~${Math.round(analysis.totalTokens / 1000)}K`);\n lines.push(`Context coverage: ${selection.coverage.score}% | Risk score: ${selection.riskScore}/100`);\n lines.push('');\n\n // List included files with their prune levels\n lines.push('### Included Files');\n lines.push('');\n\n const fullFiles = selection.files.filter((f) => f.pruneLevel === 'full');\n const sigFiles = selection.files.filter((f) => f.pruneLevel === 'signatures');\n const skelFiles = selection.files.filter((f) => f.pruneLevel === 'skeleton');\n\n if (fullFiles.length > 0) {\n lines.push('**Full content (read these first):**');\n for (const f of fullFiles) {\n lines.push(`- \\`${f.relativePath}\\` (~${Math.round(f.tokens / 1000)}K tokens) — ${f.reason}`);\n }\n lines.push('');\n }\n\n if (sigFiles.length > 0) {\n lines.push('**Signatures only (reference as needed):**');\n for (const f of sigFiles) {\n lines.push(`- \\`${f.relativePath}\\` (~${Math.round(f.tokens / 1000)}K tokens)`);\n }\n lines.push('');\n }\n\n if (skelFiles.length > 0) {\n lines.push('**Skeleton (structure overview):**');\n for (const f of skelFiles) {\n lines.push(`- \\`${f.relativePath}\\``);\n }\n lines.push('');\n }\n\n if (selection.coverage.missingCritical.length > 0) {\n lines.push('⚠️ **Missing critical files** (not included due to budget):');\n for (const f of selection.coverage.missingCritical) {\n lines.push(`- \\`${f}\\``);\n }\n lines.push('');\n }\n\n const content = lines.join('\\n');\n return makeSection('context', 'context', content);\n}\n\nfunction buildTaskSection(task: string, taskType: TaskType): PromptSection {\n const content = [\n '## Task',\n '',\n task,\n '',\n `Task type: **${taskType}**`,\n ].join('\\n');\n\n return makeSection('task', 'task', content);\n}\n\nfunction buildConstraintsSection(stack: string[], taskType: TaskType): PromptSection {\n const lines: string[] = ['## Constraints', ''];\n\n lines.push('- **Do NOT** delete or modify existing tests unless explicitly asked');\n lines.push('- **Do NOT** change function signatures that are part of the public API');\n lines.push('- **Do NOT** introduce new dependencies without mentioning it');\n lines.push('- **Always** handle errors explicitly (no silent catches)');\n lines.push('- **Always** preserve existing code style and conventions');\n lines.push('- **Prefer** minimal changes — smallest diff that solves the problem');\n\n if (stack.includes('TypeScript')) {\n lines.push('- **Always** use strict TypeScript types (no `any` unless unavoidable)');\n lines.push('- **Always** add explicit return types to exported functions');\n }\n\n if (taskType === 'refactor') {\n lines.push('- **Do NOT** change behavior — refactoring must be behavior-preserving');\n lines.push('- **Verify** all existing tests still pass after changes');\n }\n\n if (taskType === 'test') {\n lines.push('- Use AAA pattern: Arrange, Act, Assert');\n lines.push('- Test boundaries, null/undefined, async errors, type edges');\n lines.push('- Use descriptive test names: \"should [expected] when [condition]\"');\n }\n\n return makeSection('constraints', 'constraints', lines.join('\\n'));\n}\n\nfunction buildCoTSection(taskType: TaskType): PromptSection {\n const steps = COT_STEPS[taskType] ?? COT_STEPS['simple-edit'];\n\n const lines: string[] = ['## Thinking Process', '', 'Before writing any code:'];\n steps.forEach((step, i) => {\n lines.push(`${i + 1}. ${step}`);\n });\n\n return makeSection('cot', 'constraints', lines.join('\\n'));\n}\n\nfunction buildAntiHallucinationSection(): PromptSection {\n const content = [\n '## Important',\n '',\n '- Only reference files, functions, and APIs that exist in the provided context',\n '- If you are unsure about something, say so explicitly',\n '- Do NOT invent function signatures, types, or module paths',\n '- If the context is insufficient to complete the task, explain what is missing',\n ].join('\\n');\n\n return makeSection('anti-hallucination', 'constraints', content);\n}\n\nfunction buildFormatSection(taskType: TaskType): PromptSection {\n const lines: string[] = ['## Output Format', ''];\n\n if (taskType === 'review') {\n lines.push('Provide findings in priority order: Critical > Major > Minor > Nitpick');\n lines.push('For each finding: file, line, issue, and concrete suggestion with code');\n } else if (taskType === 'architecture') {\n lines.push('Present 2-3 options with trade-offs, then recommend one with justification');\n } else if (taskType === 'debug') {\n lines.push('1. Root cause analysis');\n lines.push('2. Minimal fix');\n lines.push('3. Explanation of why the fix works');\n lines.push('4. Edge cases to consider');\n } else {\n lines.push('Provide clean, production-ready code with brief explanations of key decisions');\n }\n\n return makeSection('format', 'format', lines.join('\\n'));\n}\n\n// ===== CONSTANTS =====\n\nconst TASK_ROLES: Record<TaskType, string> = {\n debug: 'debugger',\n review: 'code reviewer',\n refactor: 'architect',\n test: 'test engineer',\n docs: 'technical writer',\n feature: 'engineer',\n architecture: 'systems architect',\n 'simple-edit': 'engineer',\n};\n\nconst COT_STEPS: Record<TaskType, string[]> = {\n debug: [\n '**Reproduce** — Understand the exact symptom and when it occurs',\n '**Hypothesize** — List the most likely root causes (max 3)',\n '**Verify** — Check each hypothesis against the code',\n '**Fix** — Apply the minimal fix that addresses the root cause',\n '**Validate** — Explain why the fix works and what edge cases it covers',\n ],\n review: [\n '**Understand** — Read the code and understand its purpose',\n '**Assess** — Evaluate correctness, readability, performance, security',\n '**Prioritize** — Rank issues by severity (critical > major > minor)',\n '**Suggest** — Provide concrete, actionable improvements with code',\n ],\n refactor: [\n '**Analyze** — Identify code smells and structural issues',\n '**Plan** — Define the target structure before changing anything',\n '**Preserve** — Ensure behavior doesn\\'t change',\n '**Refactor** — Apply changes incrementally',\n '**Verify** — Confirm all existing tests still pass',\n ],\n test: [\n '**Identify** — What needs testing? (happy path, edge cases, errors)',\n '**Structure** — Use AAA pattern: Arrange, Act, Assert',\n '**Cover** — Test boundaries, null/undefined, async errors',\n '**Isolate** — Mock external dependencies, test units independently',\n ],\n docs: [\n '**Read** — Understand the code before documenting',\n '**Structure** — Organize by audience (API users, contributors, operators)',\n '**Write** — Clear, concise, with examples',\n ],\n feature: [\n '**Clarify** — Restate the requirement in your own words',\n '**Design** — Plan the approach (types, interfaces, flow)',\n '**Implement** — Build incrementally, starting with types',\n '**Test** — Write tests alongside implementation',\n '**Integrate** — Ensure no regressions',\n ],\n architecture: [\n '**Context** — Understand current architecture and constraints',\n '**Options** — Present 2-3 viable approaches with trade-offs',\n '**Recommend** — Choose the best and explain why',\n '**Plan** — Define migration steps',\n '**Risks** — Identify risks and mitigation strategies',\n ],\n 'simple-edit': [\n '**Understand** — Read the relevant code',\n '**Plan** — Think before writing',\n '**Implement** — Write clean, well-typed code',\n '**Verify** — Check for edge cases',\n ],\n};\n\n// ===== HELPERS =====\n\nfunction makeSection(\n id: string,\n role: PromptSection['role'],\n content: string,\n): PromptSection {\n const tokens = countTokensChars4(Buffer.byteLength(content, 'utf-8'));\n return { id, role, content, tokens };\n}\n","import { resolve, join } from 'node:path';\nimport { readFile, writeFile, mkdir } from 'node:fs/promises';\nimport type { ProjectAnalysis, AnalyzedFile } from '../types/engine.js';\nimport type { TaskType } from '../types/interact.js';\nimport { classifyTask } from '../interact/router.js';\nimport { buildAdjacencyList, bfsBidirectional } from './graph-utils.js';\n\n// ===== ML-based Context Predictor =====\n//\n// Learns from past context selections to improve future ones.\n//\n// How it works:\n// 1. Every time context is selected, record: (taskType, keywords) → selectedFiles\n// 2. Build a frequency model: for each (taskType, keyword) pair, track which files\n// were selected and how often\n// 3. On future selections, boost files that were historically useful for similar tasks\n//\n// Storage: .cto/predictor.json (per-project)\n//\n// This is a simple frequency-based approach (not a neural net), but it:\n// - Learns from YOUR usage patterns\n// - Gets better over time\n// - Is fully transparent (you can inspect the model)\n// - Works offline, no API calls\n\nexport interface PredictorModel {\n version: number;\n trainedAt: string;\n totalObservations: number;\n\n // taskType → { filePath → selectionCount }\n taskTypeFrequency: Record<string, Record<string, number>>;\n\n // keyword → { filePath → selectionCount }\n keywordFrequency: Record<string, Record<string, number>>;\n\n // filePath → { totalSelections, avgRiskScore, avgTokens }\n fileStats: Record<string, {\n totalSelections: number;\n avgRiskScore: number;\n avgTokens: number;\n lastSelected: string;\n }>;\n\n // Co-occurrence: when file A is selected, file B is also selected\n coSelection: Record<string, Record<string, number>>;\n}\n\nexport interface PredictionResult {\n filePath: string;\n predictedScore: number;\n reasons: string[];\n}\n\nexport interface PredictorConfig {\n maxCoSelectionPairs: number;\n decayFactor: number;\n minObservations: number;\n}\n\nconst DEFAULT_PREDICTOR_CONFIG: PredictorConfig = {\n maxCoSelectionPairs: 500,\n decayFactor: 0.95, // slight decay to favor recent patterns\n minObservations: 2, // need at least 2 observations before predicting\n};\n\n// ===== LOAD / SAVE =====\n\nasync function getModelPath(projectPath: string): Promise<string> {\n const ctoDir = join(resolve(projectPath), '.cto');\n await mkdir(ctoDir, { recursive: true });\n return join(ctoDir, 'predictor.json');\n}\n\nexport async function loadModel(projectPath: string): Promise<PredictorModel> {\n try {\n const path = await getModelPath(projectPath);\n const raw = await readFile(path, 'utf-8');\n return JSON.parse(raw);\n } catch {\n return createEmptyModel();\n }\n}\n\nexport async function saveModel(projectPath: string, model: PredictorModel): Promise<void> {\n const path = await getModelPath(projectPath);\n await writeFile(path, JSON.stringify(model, null, 2));\n}\n\nfunction createEmptyModel(): PredictorModel {\n return {\n version: 1,\n trainedAt: new Date().toISOString(),\n totalObservations: 0,\n taskTypeFrequency: {},\n keywordFrequency: {},\n fileStats: {},\n coSelection: {},\n };\n}\n\n// ===== TRAINING (record an observation) =====\n\nexport async function recordSelection(\n projectPath: string,\n task: string,\n selectedFiles: { relativePath: string; riskScore: number; tokens: number }[],\n): Promise<PredictorModel> {\n const model = await loadModel(projectPath);\n const taskType = classifyTask(task);\n const keywords = extractKeywords(task);\n\n model.totalObservations++;\n model.trainedAt = new Date().toISOString();\n\n const selectedPaths = selectedFiles.map((f) => f.relativePath);\n\n // 1. Update taskType → file frequency\n if (!model.taskTypeFrequency[taskType]) {\n model.taskTypeFrequency[taskType] = {};\n }\n for (const path of selectedPaths) {\n model.taskTypeFrequency[taskType][path] = (model.taskTypeFrequency[taskType][path] ?? 0) + 1;\n }\n\n // 2. Update keyword → file frequency\n for (const kw of keywords) {\n if (!model.keywordFrequency[kw]) {\n model.keywordFrequency[kw] = {};\n }\n for (const path of selectedPaths) {\n model.keywordFrequency[kw][path] = (model.keywordFrequency[kw][path] ?? 0) + 1;\n }\n }\n\n // 3. Update file stats\n for (const file of selectedFiles) {\n const existing = model.fileStats[file.relativePath];\n if (existing) {\n const n = existing.totalSelections;\n existing.totalSelections = n + 1;\n existing.avgRiskScore = (existing.avgRiskScore * n + file.riskScore) / (n + 1);\n existing.avgTokens = (existing.avgTokens * n + file.tokens) / (n + 1);\n existing.lastSelected = new Date().toISOString();\n } else {\n model.fileStats[file.relativePath] = {\n totalSelections: 1,\n avgRiskScore: file.riskScore,\n avgTokens: file.tokens,\n lastSelected: new Date().toISOString(),\n };\n }\n }\n\n // 4. Update co-selection (top pairs only to limit model size)\n const topFiles = selectedPaths.slice(0, 20); // only track top 20 per observation\n for (let i = 0; i < topFiles.length; i++) {\n const a = topFiles[i];\n if (!model.coSelection[a]) model.coSelection[a] = {};\n for (let j = i + 1; j < topFiles.length; j++) {\n const b = topFiles[j];\n model.coSelection[a][b] = (model.coSelection[a][b] ?? 0) + 1;\n if (!model.coSelection[b]) model.coSelection[b] = {};\n model.coSelection[b][a] = (model.coSelection[b][a] ?? 0) + 1;\n }\n }\n\n // Prune co-selection if too large\n pruneCoSelection(model, DEFAULT_PREDICTOR_CONFIG.maxCoSelectionPairs);\n\n await saveModel(projectPath, model);\n return model;\n}\n\n// ===== PREDICTION =====\n\nexport async function predictRelevantFiles(\n projectPath: string,\n task: string,\n analysis: ProjectAnalysis,\n config: Partial<PredictorConfig> = {},\n): Promise<PredictionResult[]> {\n const cfg = { ...DEFAULT_PREDICTOR_CONFIG, ...config };\n const model = await loadModel(projectPath);\n\n if (model.totalObservations < cfg.minObservations) {\n return []; // not enough data to predict\n }\n\n const taskType = classifyTask(task);\n const keywords = extractKeywords(task);\n const scores = new Map<string, { score: number; reasons: string[] }>();\n\n // Helper to add score\n const boost = (path: string, amount: number, reason: string) => {\n const existing = scores.get(path) ?? { score: 0, reasons: [] };\n existing.score += amount;\n existing.reasons.push(reason);\n scores.set(path, existing);\n };\n\n // 1. TaskType frequency boost (weight: 3x)\n const taskFreqs = model.taskTypeFrequency[taskType];\n if (taskFreqs) {\n const maxFreq = Math.max(...Object.values(taskFreqs));\n for (const [path, freq] of Object.entries(taskFreqs)) {\n const normalized = maxFreq > 0 ? freq / maxFreq : 0;\n boost(path, normalized * 30, `${taskType} task history (${freq}× selected)`);\n }\n }\n\n // 2. Keyword frequency boost (weight: 2x per keyword)\n for (const kw of keywords) {\n const kwFreqs = model.keywordFrequency[kw];\n if (kwFreqs) {\n const maxFreq = Math.max(...Object.values(kwFreqs));\n for (const [path, freq] of Object.entries(kwFreqs)) {\n const normalized = maxFreq > 0 ? freq / maxFreq : 0;\n boost(path, normalized * 20, `keyword \"${kw}\" (${freq}× selected)`);\n }\n }\n }\n\n // 3. General selection frequency boost (weight: 1x)\n for (const [path, stats] of Object.entries(model.fileStats)) {\n const freqRatio = model.totalObservations > 0\n ? stats.totalSelections / model.totalObservations\n : 0;\n if (freqRatio > 0.3) { // selected in >30% of all observations\n boost(path, freqRatio * 10, `frequently selected (${stats.totalSelections}/${model.totalObservations})`);\n }\n }\n\n // 4. Co-selection boost — if high-score files have co-selected partners, boost them\n const topPredicted = [...scores.entries()]\n .sort((a, b) => b[1].score - a[1].score)\n .slice(0, 10)\n .map(([path]) => path);\n\n for (const topPath of topPredicted) {\n const coFiles = model.coSelection[topPath];\n if (coFiles) {\n for (const [coPath, count] of Object.entries(coFiles)) {\n if (count >= 2) {\n boost(coPath, count * 2, `co-selected with ${topPath} (${count}×)`);\n }\n }\n }\n }\n\n // Filter to files that exist in the current analysis\n const existingPaths = new Set(analysis.files.map((f) => f.relativePath));\n const results: PredictionResult[] = [];\n\n for (const [path, data] of scores) {\n if (existingPaths.has(path)) {\n results.push({\n filePath: path,\n predictedScore: Math.round(data.score * 10) / 10,\n reasons: data.reasons.slice(0, 5),\n });\n }\n }\n\n return results\n .sort((a, b) => b.predictedScore - a.predictedScore)\n .slice(0, 50); // top 50 predictions\n}\n\n// ===== INTEGRATION: boost selector scores =====\n\nexport async function getPredictorBoosts(\n projectPath: string,\n task: string,\n analysis: ProjectAnalysis,\n): Promise<Map<string, number>> {\n const predictions = await predictRelevantFiles(projectPath, task, analysis);\n const boosts = new Map<string, number>();\n\n if (predictions.length === 0) return boosts;\n\n // Normalize to 0-10 boost range\n const maxScore = predictions[0]?.predictedScore ?? 1;\n for (const p of predictions) {\n const normalized = maxScore > 0 ? (p.predictedScore / maxScore) * 10 : 0;\n boosts.set(p.filePath, normalized);\n }\n\n return boosts;\n}\n\n// ===== MODEL STATS =====\n\nexport function getModelStats(model: PredictorModel): {\n observations: number;\n taskTypes: number;\n keywords: number;\n trackedFiles: number;\n coSelectionPairs: number;\n trainedAt: string;\n} {\n const coSelectionPairs = Object.values(model.coSelection)\n .reduce((s, pairs) => s + Object.keys(pairs).length, 0) / 2;\n\n return {\n observations: model.totalObservations,\n taskTypes: Object.keys(model.taskTypeFrequency).length,\n keywords: Object.keys(model.keywordFrequency).length,\n trackedFiles: Object.keys(model.fileStats).length,\n coSelectionPairs: Math.round(coSelectionPairs),\n trainedAt: model.trainedAt,\n };\n}\n\n// ===== HELPERS =====\n\nfunction extractKeywords(task: string): string[] {\n const stopWords = new Set([\n 'the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been', 'being',\n 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could',\n 'should', 'may', 'might', 'can', 'shall', 'to', 'of', 'in', 'for',\n 'on', 'with', 'at', 'by', 'from', 'as', 'into', 'through', 'and',\n 'but', 'or', 'not', 'this', 'that', 'it', 'its',\n 'fix', 'add', 'remove', 'update', 'change', 'refactor', 'implement',\n 'create', 'build', 'make', 'code', 'file', 'module', 'function',\n ]);\n\n return task\n .toLowerCase()\n .replace(/[^a-z0-9\\s]/g, '')\n .split(/\\s+/)\n .filter((w) => w.length > 2 && !stopWords.has(w));\n}\n\nfunction pruneCoSelection(model: PredictorModel, maxPairs: number): void {\n const totalPairs = Object.values(model.coSelection)\n .reduce((s, pairs) => s + Object.keys(pairs).length, 0) / 2;\n\n if (totalPairs <= maxPairs) return;\n\n // Collect all pairs with their counts\n const allPairs: { a: string; b: string; count: number }[] = [];\n for (const [a, pairs] of Object.entries(model.coSelection)) {\n for (const [b, count] of Object.entries(pairs)) {\n if (a < b) allPairs.push({ a, b, count });\n }\n }\n\n // Sort by count descending, keep top maxPairs\n allPairs.sort((x, y) => y.count - x.count);\n const keep = new Set(allPairs.slice(0, maxPairs).map((p) => `${p.a}|${p.b}`));\n\n // Rebuild\n model.coSelection = {};\n for (const pair of allPairs) {\n if (keep.has(`${pair.a}|${pair.b}`)) {\n if (!model.coSelection[pair.a]) model.coSelection[pair.a] = {};\n if (!model.coSelection[pair.b]) model.coSelection[pair.b] = {};\n model.coSelection[pair.a][pair.b] = pair.count;\n model.coSelection[pair.b][pair.a] = pair.count;\n }\n }\n}\n","import { resolve, join, basename } from 'node:path';\nimport { readFile, writeFile, mkdir } from 'node:fs/promises';\nimport type { ProjectAnalysis, AnalyzedFile } from '../types/engine.js';\nimport type { TaskType } from '../types/interact.js';\nimport { classifyTask } from '../interact/router.js';\n\n// ===== Cross-Repo Intelligence =====\n//\n// Learns patterns ACROSS repositories:\n// - \"When working on auth in Express-like projects, these file patterns matter\"\n// - \"TypeScript projects with >200 files always need types/*.ts for refactoring\"\n// - \"Test tasks in monorepos need the shared fixtures directory\"\n//\n// This is the MOAT. Cursor/Copilot optimize per-file.\n// We optimize per-project-archetype × task-type.\n//\n// How it works:\n// 1. Every project gets a \"fingerprint\": { stack, size-class, structure-pattern }\n// 2. Every selection is recorded with: fingerprint × taskType × file-patterns\n// 3. On new projects, match fingerprint → predict useful patterns\n//\n// Storage: ~/.cto/global-intelligence.json (cross-project, user-level)\n\nexport interface ProjectFingerprint {\n stack: string[];\n sizeClass: 'tiny' | 'small' | 'medium' | 'large' | 'huge';\n hasTypes: boolean;\n hasTests: boolean;\n isMonorepo: boolean;\n entryPointPatterns: string[];\n dominantLanguage: string;\n}\n\nexport interface CrossRepoModel {\n version: number;\n updatedAt: string;\n totalProjects: number;\n totalObservations: number;\n\n // fingerprint-hash → archetype name\n archetypes: Record<string, ArchetypeProfile>;\n\n // Patterns that work across ALL archetypes\n universalPatterns: PatternStats[];\n}\n\nexport interface ArchetypeProfile {\n name: string;\n fingerprint: ProjectFingerprint;\n projectCount: number;\n observationCount: number;\n\n // taskType → file pattern → { hitRate, avgRelevanceBoost }\n taskPatterns: Record<string, Record<string, PatternStats>>;\n\n // File kinds that are always important for this archetype\n criticalKinds: { kind: string; importance: number }[];\n\n // Directory patterns that matter\n criticalDirs: { pattern: string; importance: number }[];\n}\n\nexport interface PatternStats {\n pattern: string;\n hitCount: number;\n totalSelections: number;\n hitRate: number;\n avgRelevanceBoost: number;\n}\n\nexport interface CrossRepoPrediction {\n filePath: string;\n boost: number;\n reason: string;\n confidence: number; // 0-1, based on how many observations back this\n}\n\n// ===== FINGERPRINTING =====\n\nexport function computeFingerprint(analysis: ProjectAnalysis): ProjectFingerprint {\n const totalFiles = analysis.totalFiles;\n\n const sizeClass: ProjectFingerprint['sizeClass'] =\n totalFiles < 20 ? 'tiny'\n : totalFiles < 100 ? 'small'\n : totalFiles < 500 ? 'medium'\n : totalFiles < 2000 ? 'large'\n : 'huge';\n\n const hasTypes = analysis.files.some((f) => f.kind === 'type');\n const hasTests = analysis.files.some((f) => f.kind === 'test');\n\n // Detect monorepo: has packages/ or apps/ with multiple package.json\n const isMonorepo = analysis.files.some((f) =>\n f.relativePath.startsWith('packages/') || f.relativePath.startsWith('apps/')\n );\n\n const entryPointPatterns = analysis.files\n .filter((f) => f.kind === 'entry')\n .map((f) => extractPattern(f.relativePath))\n .filter((p, i, arr) => arr.indexOf(p) === i)\n .slice(0, 5);\n\n // Dominant language from stack\n const dominantLanguage = analysis.stack[0] ?? 'unknown';\n\n return {\n stack: analysis.stack.slice(0, 5),\n sizeClass,\n hasTypes,\n hasTests,\n isMonorepo,\n entryPointPatterns,\n dominantLanguage,\n };\n}\n\nfunction extractPattern(filePath: string): string {\n // Convert specific path to pattern: src/engine/analyzer.ts → src/*/analyzer.*\n const parts = filePath.split('/');\n if (parts.length <= 1) return filePath;\n if (parts.length === 2) return `${parts[0]}/*`;\n return `${parts[0]}/*/${basename(filePath).replace(/\\.[^.]+$/, '.*')}`;\n}\n\nfunction fingerprintHash(fp: ProjectFingerprint): string {\n return `${fp.dominantLanguage}_${fp.sizeClass}_${fp.hasTypes ? 'T' : 'F'}${fp.hasTests ? 'T' : 'F'}${fp.isMonorepo ? 'M' : 'S'}`;\n}\n\n// ===== MODEL STORAGE =====\n\nfunction getGlobalModelPath(): string {\n const home = process.env.HOME ?? process.env.USERPROFILE ?? '/tmp';\n return join(home, '.cto', 'global-intelligence.json');\n}\n\nexport async function loadGlobalModel(): Promise<CrossRepoModel> {\n try {\n const raw = await readFile(getGlobalModelPath(), 'utf-8');\n return JSON.parse(raw);\n } catch {\n return createEmptyModel();\n }\n}\n\nexport async function saveGlobalModel(model: CrossRepoModel): Promise<void> {\n const dir = join(getGlobalModelPath(), '..');\n await mkdir(dir, { recursive: true });\n await writeFile(getGlobalModelPath(), JSON.stringify(model, null, 2));\n}\n\nfunction createEmptyModel(): CrossRepoModel {\n return {\n version: 1,\n updatedAt: new Date().toISOString(),\n totalProjects: 0,\n totalObservations: 0,\n archetypes: {},\n universalPatterns: [],\n };\n}\n\n// ===== TRAINING =====\n\nexport async function recordCrossRepoSelection(\n analysis: ProjectAnalysis,\n task: string,\n selectedFiles: { relativePath: string; riskScore: number; tokens: number }[],\n): Promise<CrossRepoModel> {\n const model = await loadGlobalModel();\n const fp = computeFingerprint(analysis);\n const hash = fingerprintHash(fp);\n const taskType = classifyTask(task);\n\n model.totalObservations++;\n model.updatedAt = new Date().toISOString();\n\n // Get or create archetype\n if (!model.archetypes[hash]) {\n model.totalProjects++;\n model.archetypes[hash] = {\n name: `${fp.dominantLanguage}-${fp.sizeClass}${fp.isMonorepo ? '-monorepo' : ''}`,\n fingerprint: fp,\n projectCount: 1,\n observationCount: 0,\n taskPatterns: {},\n criticalKinds: [],\n criticalDirs: [],\n };\n }\n\n const archetype = model.archetypes[hash];\n archetype.observationCount++;\n\n // Record file patterns for this task type\n if (!archetype.taskPatterns[taskType]) {\n archetype.taskPatterns[taskType] = {};\n }\n\n const patterns = archetype.taskPatterns[taskType];\n\n for (const file of selectedFiles) {\n const pattern = extractPattern(file.relativePath);\n if (!patterns[pattern]) {\n patterns[pattern] = {\n pattern,\n hitCount: 0,\n totalSelections: 0,\n hitRate: 0,\n avgRelevanceBoost: 0,\n };\n }\n const p = patterns[pattern];\n p.hitCount++;\n p.totalSelections = archetype.observationCount;\n p.hitRate = p.hitCount / p.totalSelections;\n // Boost proportional to risk score (higher risk = more important)\n p.avgRelevanceBoost = (p.avgRelevanceBoost * (p.hitCount - 1) + file.riskScore) / p.hitCount;\n }\n\n // Update critical kinds\n const kindCounts = new Map<string, number>();\n for (const file of selectedFiles) {\n const af = analysis.files.find((f) => f.relativePath === file.relativePath);\n if (af) {\n kindCounts.set(af.kind, (kindCounts.get(af.kind) ?? 0) + 1);\n }\n }\n archetype.criticalKinds = [...kindCounts.entries()]\n .map(([kind, count]) => ({ kind, importance: count / selectedFiles.length }))\n .sort((a, b) => b.importance - a.importance)\n .slice(0, 10);\n\n // Update critical dirs\n const dirCounts = new Map<string, number>();\n for (const file of selectedFiles) {\n const dir = file.relativePath.split('/').slice(0, -1).join('/');\n if (dir) dirCounts.set(dir, (dirCounts.get(dir) ?? 0) + 1);\n }\n archetype.criticalDirs = [...dirCounts.entries()]\n .map(([pattern, count]) => ({ pattern, importance: count / selectedFiles.length }))\n .sort((a, b) => b.importance - a.importance)\n .slice(0, 10);\n\n // Update universal patterns (patterns that appear in >50% of archetypes)\n updateUniversalPatterns(model);\n\n await saveGlobalModel(model);\n return model;\n}\n\nfunction updateUniversalPatterns(model: CrossRepoModel): void {\n const patternCounts = new Map<string, { count: number; totalBoost: number }>();\n const archetypeCount = Object.keys(model.archetypes).length;\n\n for (const archetype of Object.values(model.archetypes)) {\n const seenPatterns = new Set<string>();\n for (const taskPatterns of Object.values(archetype.taskPatterns)) {\n for (const [pattern, stats] of Object.entries(taskPatterns)) {\n if (!seenPatterns.has(pattern)) {\n seenPatterns.add(pattern);\n const entry = patternCounts.get(pattern) ?? { count: 0, totalBoost: 0 };\n entry.count++;\n entry.totalBoost += stats.avgRelevanceBoost;\n patternCounts.set(pattern, entry);\n }\n }\n }\n }\n\n model.universalPatterns = [...patternCounts.entries()]\n .filter(([_, data]) => data.count / archetypeCount > 0.5) // >50% of archetypes\n .map(([pattern, data]) => ({\n pattern,\n hitCount: data.count,\n totalSelections: archetypeCount,\n hitRate: data.count / archetypeCount,\n avgRelevanceBoost: data.totalBoost / data.count,\n }))\n .sort((a, b) => b.hitRate - a.hitRate)\n .slice(0, 20);\n}\n\n// ===== PREDICTION =====\n\nexport async function predictFromCrossRepo(\n analysis: ProjectAnalysis,\n task: string,\n): Promise<CrossRepoPrediction[]> {\n const model = await loadGlobalModel();\n const fp = computeFingerprint(analysis);\n const hash = fingerprintHash(fp);\n const taskType = classifyTask(task);\n\n const predictions: CrossRepoPrediction[] = [];\n\n // 1. Match exact archetype\n const archetype = model.archetypes[hash];\n if (archetype && archetype.observationCount >= 2) {\n const taskPatterns = archetype.taskPatterns[taskType] ?? {};\n\n for (const file of analysis.files) {\n const pattern = extractPattern(file.relativePath);\n const stats = taskPatterns[pattern];\n\n if (stats && stats.hitRate > 0.3) {\n predictions.push({\n filePath: file.relativePath,\n boost: stats.hitRate * stats.avgRelevanceBoost / 10,\n reason: `pattern \"${pattern}\" selected ${Math.round(stats.hitRate * 100)}% of the time for ${taskType} tasks in ${archetype.name} projects`,\n confidence: Math.min(1, archetype.observationCount / 10),\n });\n }\n }\n\n // Critical kind boost\n for (const file of analysis.files) {\n const af = analysis.files.find((f) => f.relativePath === file.relativePath);\n if (!af) continue;\n const critKind = archetype.criticalKinds.find((k) => k.kind === af.kind);\n if (critKind && critKind.importance > 0.2) {\n const existing = predictions.find((p) => p.filePath === file.relativePath);\n if (existing) {\n existing.boost += critKind.importance * 3;\n existing.reason += ` + ${af.kind} files are critical (${Math.round(critKind.importance * 100)}%)`;\n } else {\n predictions.push({\n filePath: file.relativePath,\n boost: critKind.importance * 3,\n reason: `${af.kind} files are critical in ${archetype.name} projects (${Math.round(critKind.importance * 100)}%)`,\n confidence: Math.min(1, archetype.observationCount / 10),\n });\n }\n }\n }\n }\n\n // 2. Similar archetype matching (fuzzy)\n for (const [otherHash, otherArchetype] of Object.entries(model.archetypes)) {\n if (otherHash === hash) continue;\n const similarity = computeSimilarity(fp, otherArchetype.fingerprint);\n if (similarity < 0.5) continue;\n\n const taskPatterns = otherArchetype.taskPatterns[taskType] ?? {};\n for (const file of analysis.files) {\n const pattern = extractPattern(file.relativePath);\n const stats = taskPatterns[pattern];\n\n if (stats && stats.hitRate > 0.5) {\n const existing = predictions.find((p) => p.filePath === file.relativePath);\n const boost = stats.hitRate * similarity * stats.avgRelevanceBoost / 20;\n if (existing) {\n existing.boost += boost;\n } else {\n predictions.push({\n filePath: file.relativePath,\n boost,\n reason: `similar project pattern (${otherArchetype.name}, ${Math.round(similarity * 100)}% match)`,\n confidence: similarity * Math.min(1, otherArchetype.observationCount / 10),\n });\n }\n }\n }\n }\n\n // 3. Universal patterns boost\n for (const universalPattern of model.universalPatterns) {\n for (const file of analysis.files) {\n const pattern = extractPattern(file.relativePath);\n if (pattern === universalPattern.pattern) {\n const existing = predictions.find((p) => p.filePath === file.relativePath);\n if (existing) {\n existing.boost += universalPattern.hitRate * 2;\n } else {\n predictions.push({\n filePath: file.relativePath,\n boost: universalPattern.hitRate * 2,\n reason: `universal pattern across ${universalPattern.hitCount} project types`,\n confidence: universalPattern.hitRate,\n });\n }\n }\n }\n }\n\n return predictions\n .sort((a, b) => b.boost - a.boost)\n .slice(0, 50);\n}\n\nfunction computeSimilarity(a: ProjectFingerprint, b: ProjectFingerprint): number {\n let score = 0;\n let maxScore = 0;\n\n // Language match (most important)\n maxScore += 3;\n if (a.dominantLanguage === b.dominantLanguage) score += 3;\n\n // Size class proximity\n maxScore += 2;\n const sizes = ['tiny', 'small', 'medium', 'large', 'huge'];\n const aDist = sizes.indexOf(a.sizeClass);\n const bDist = sizes.indexOf(b.sizeClass);\n const sizeDiff = Math.abs(aDist - bDist);\n score += Math.max(0, 2 - sizeDiff);\n\n // Structural matches\n maxScore += 1; if (a.hasTypes === b.hasTypes) score += 1;\n maxScore += 1; if (a.hasTests === b.hasTests) score += 1;\n maxScore += 1; if (a.isMonorepo === b.isMonorepo) score += 1;\n\n // Stack overlap\n maxScore += 2;\n const stackOverlap = a.stack.filter((s) => b.stack.includes(s)).length;\n const maxStack = Math.max(a.stack.length, b.stack.length, 1);\n score += (stackOverlap / maxStack) * 2;\n\n return score / maxScore;\n}\n\n// ===== STATS =====\n\nexport function getCrossRepoStats(model: CrossRepoModel): {\n totalProjects: number;\n totalObservations: number;\n archetypes: { name: string; projects: number; observations: number }[];\n universalPatterns: number;\n} {\n return {\n totalProjects: model.totalProjects,\n totalObservations: model.totalObservations,\n archetypes: Object.values(model.archetypes).map((a) => ({\n name: a.name,\n projects: a.projectCount,\n observations: a.observationCount,\n })),\n universalPatterns: model.universalPatterns.length,\n };\n}\n","import { resolve, join } from 'node:path';\nimport { readFile, writeFile, mkdir } from 'node:fs/promises';\nimport type { ProjectAnalysis } from '../types/engine.js';\nimport type { TaskType } from '../types/interact.js';\nimport { classifyTask } from '../interact/router.js';\n\n// ===== Output Feedback Loop =====\n//\n// The flywheel that makes CTO impossible to replicate:\n//\n// 1. User asks AI to do a task with CTO context\n// 2. AI generates code\n// 3. User ACCEPTS or REJECTS the output\n// 4. CTO records: { task, context, outcome }\n// 5. Over time: learn which context selections lead to ACCEPTED outputs\n//\n// This creates a feedback loop:\n// More users → more feedback → better selections → more users\n//\n// Metrics tracked per context selection:\n// - accepted: boolean (user kept the code)\n// - compilable: boolean (code passed type check)\n// - testsPassed: number (how many tests passed)\n// - linesAccepted: number (lines of generated code kept)\n// - timeToAccept: number (seconds from generation to accept — faster = better context)\n//\n// Storage: .cto/feedback.json (per-project)\n\nexport interface FeedbackEntry {\n id: string;\n timestamp: string;\n task: string;\n taskType: TaskType;\n\n // What context was used\n contextHash: string;\n filesIncluded: string[];\n tokensUsed: number;\n budget: number;\n\n // Outcome\n outcome: FeedbackOutcome;\n\n // Optional metadata\n model?: string;\n promptTokens?: number;\n}\n\nexport interface FeedbackOutcome {\n accepted: boolean;\n compilable?: boolean;\n testsPassed?: number;\n testsTotal?: number;\n linesGenerated?: number;\n linesAccepted?: number;\n timeToAcceptMs?: number;\n userRating?: 1 | 2 | 3 | 4 | 5;\n notes?: string;\n}\n\nexport interface FeedbackModel {\n version: number;\n updatedAt: string;\n totalFeedback: number;\n acceptRate: number;\n\n // file → acceptance stats\n fileAcceptance: Record<string, {\n includedCount: number;\n acceptedCount: number;\n acceptRate: number;\n avgTimeToAccept: number;\n }>;\n\n // taskType → acceptance stats\n taskTypeAcceptance: Record<string, {\n totalCount: number;\n acceptedCount: number;\n acceptRate: number;\n avgCompilable: number;\n }>;\n\n // file pair → when both included, acceptance rate\n pairAcceptance: Record<string, {\n count: number;\n acceptedCount: number;\n acceptRate: number;\n }>;\n\n // Insights derived from feedback\n insights: FeedbackInsight[];\n}\n\nexport interface FeedbackInsight {\n type: 'positive' | 'negative' | 'opportunity';\n title: string;\n detail: string;\n impact: number; // 0-100\n}\n\n// ===== STORAGE =====\n\nasync function getFeedbackPath(projectPath: string): Promise<string> {\n const ctoDir = join(resolve(projectPath), '.cto');\n await mkdir(ctoDir, { recursive: true });\n return join(ctoDir, 'feedback.json');\n}\n\nasync function getModelPath(projectPath: string): Promise<string> {\n const ctoDir = join(resolve(projectPath), '.cto');\n await mkdir(ctoDir, { recursive: true });\n return join(ctoDir, 'feedback-model.json');\n}\n\nexport async function loadFeedback(projectPath: string): Promise<FeedbackEntry[]> {\n try {\n const raw = await readFile(await getFeedbackPath(projectPath), 'utf-8');\n return JSON.parse(raw);\n } catch {\n return [];\n }\n}\n\nasync function saveFeedback(projectPath: string, entries: FeedbackEntry[]): Promise<void> {\n await writeFile(await getFeedbackPath(projectPath), JSON.stringify(entries, null, 2));\n}\n\nexport async function loadFeedbackModel(projectPath: string): Promise<FeedbackModel> {\n try {\n const raw = await readFile(await getModelPath(projectPath), 'utf-8');\n return JSON.parse(raw);\n } catch {\n return createEmptyModel();\n }\n}\n\nasync function saveFeedbackModel(projectPath: string, model: FeedbackModel): Promise<void> {\n await writeFile(await getModelPath(projectPath), JSON.stringify(model, null, 2));\n}\n\nfunction createEmptyModel(): FeedbackModel {\n return {\n version: 1,\n updatedAt: new Date().toISOString(),\n totalFeedback: 0,\n acceptRate: 0,\n fileAcceptance: {},\n taskTypeAcceptance: {},\n pairAcceptance: {},\n insights: [],\n };\n}\n\n// ===== RECORD FEEDBACK =====\n\nexport async function recordFeedback(\n projectPath: string,\n entry: Omit<FeedbackEntry, 'id' | 'timestamp' | 'taskType'>,\n): Promise<FeedbackModel> {\n const entries = await loadFeedback(projectPath);\n\n const fullEntry: FeedbackEntry = {\n ...entry,\n id: `fb_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,\n timestamp: new Date().toISOString(),\n taskType: classifyTask(entry.task),\n };\n\n entries.push(fullEntry);\n\n // Keep last 1000 entries\n const trimmed = entries.slice(-1000);\n await saveFeedback(projectPath, trimmed);\n\n // Rebuild model\n const model = rebuildModel(trimmed);\n await saveFeedbackModel(projectPath, model);\n\n return model;\n}\n\n// ===== MODEL BUILDING =====\n\nfunction rebuildModel(entries: FeedbackEntry[]): FeedbackModel {\n const model = createEmptyModel();\n model.totalFeedback = entries.length;\n\n let acceptedTotal = 0;\n\n for (const entry of entries) {\n const accepted = entry.outcome.accepted;\n if (accepted) acceptedTotal++;\n\n // File acceptance\n for (const file of entry.filesIncluded) {\n if (!model.fileAcceptance[file]) {\n model.fileAcceptance[file] = {\n includedCount: 0,\n acceptedCount: 0,\n acceptRate: 0,\n avgTimeToAccept: 0,\n };\n }\n const fa = model.fileAcceptance[file];\n fa.includedCount++;\n if (accepted) fa.acceptedCount++;\n fa.acceptRate = fa.acceptedCount / fa.includedCount;\n if (entry.outcome.timeToAcceptMs) {\n fa.avgTimeToAccept = (fa.avgTimeToAccept * (fa.includedCount - 1) + entry.outcome.timeToAcceptMs) / fa.includedCount;\n }\n }\n\n // Task type acceptance\n const tt = entry.taskType;\n if (!model.taskTypeAcceptance[tt]) {\n model.taskTypeAcceptance[tt] = {\n totalCount: 0,\n acceptedCount: 0,\n acceptRate: 0,\n avgCompilable: 0,\n };\n }\n const tta = model.taskTypeAcceptance[tt];\n tta.totalCount++;\n if (accepted) tta.acceptedCount++;\n tta.acceptRate = tta.acceptedCount / tta.totalCount;\n if (entry.outcome.compilable !== undefined) {\n tta.avgCompilable = (tta.avgCompilable * (tta.totalCount - 1) + (entry.outcome.compilable ? 1 : 0)) / tta.totalCount;\n }\n\n // Pair acceptance (top 10 files per entry to limit combinatorics)\n const topFiles = entry.filesIncluded.slice(0, 10);\n for (let i = 0; i < topFiles.length; i++) {\n for (let j = i + 1; j < topFiles.length; j++) {\n const key = [topFiles[i], topFiles[j]].sort().join('|');\n if (!model.pairAcceptance[key]) {\n model.pairAcceptance[key] = { count: 0, acceptedCount: 0, acceptRate: 0 };\n }\n const pa = model.pairAcceptance[key];\n pa.count++;\n if (accepted) pa.acceptedCount++;\n pa.acceptRate = pa.acceptedCount / pa.count;\n }\n }\n }\n\n model.acceptRate = entries.length > 0 ? acceptedTotal / entries.length : 0;\n\n // Generate insights\n model.insights = generateInsights(model);\n\n return model;\n}\n\nfunction generateInsights(model: FeedbackModel): FeedbackInsight[] {\n const insights: FeedbackInsight[] = [];\n\n // High acceptance files\n const highAccept = Object.entries(model.fileAcceptance)\n .filter(([_, fa]) => fa.includedCount >= 3 && fa.acceptRate >= 0.8)\n .sort((a, b) => b[1].acceptRate - a[1].acceptRate)\n .slice(0, 5);\n\n for (const [file, fa] of highAccept) {\n insights.push({\n type: 'positive',\n title: `${file} consistently leads to accepted output`,\n detail: `${Math.round(fa.acceptRate * 100)}% accept rate over ${fa.includedCount} selections`,\n impact: Math.round(fa.acceptRate * fa.includedCount),\n });\n }\n\n // Low acceptance files (might be noise)\n const lowAccept = Object.entries(model.fileAcceptance)\n .filter(([_, fa]) => fa.includedCount >= 3 && fa.acceptRate < 0.3)\n .sort((a, b) => a[1].acceptRate - b[1].acceptRate)\n .slice(0, 5);\n\n for (const [file, fa] of lowAccept) {\n insights.push({\n type: 'negative',\n title: `${file} often included but output rejected`,\n detail: `Only ${Math.round(fa.acceptRate * 100)}% accept rate — may be adding noise`,\n impact: Math.round((1 - fa.acceptRate) * fa.includedCount * 2),\n });\n }\n\n // Best task types\n const bestTasks = Object.entries(model.taskTypeAcceptance)\n .filter(([_, ta]) => ta.totalCount >= 2)\n .sort((a, b) => b[1].acceptRate - a[1].acceptRate);\n\n for (const [taskType, ta] of bestTasks.slice(0, 3)) {\n insights.push({\n type: ta.acceptRate >= 0.7 ? 'positive' : 'opportunity',\n title: `${taskType} tasks: ${Math.round(ta.acceptRate * 100)}% acceptance`,\n detail: `${ta.acceptedCount}/${ta.totalCount} accepted, ${Math.round(ta.avgCompilable * 100)}% compilable`,\n impact: Math.round(ta.acceptRate * ta.totalCount * 3),\n });\n }\n\n // Power pairs (files that when included together → high acceptance)\n const powerPairs = Object.entries(model.pairAcceptance)\n .filter(([_, pa]) => pa.count >= 3 && pa.acceptRate >= 0.9)\n .sort((a, b) => b[1].acceptRate * b[1].count - a[1].acceptRate * a[1].count)\n .slice(0, 3);\n\n for (const [pair, pa] of powerPairs) {\n const [a, b] = pair.split('|');\n insights.push({\n type: 'positive',\n title: `Power pair: ${a} + ${b}`,\n detail: `${Math.round(pa.acceptRate * 100)}% acceptance when both included (${pa.count} times)`,\n impact: Math.round(pa.acceptRate * pa.count * 5),\n });\n }\n\n return insights.sort((a, b) => b.impact - a.impact);\n}\n\n// ===== PREDICTION: boost files based on feedback =====\n\nexport async function getFeedbackBoosts(\n projectPath: string,\n task: string,\n): Promise<Map<string, number>> {\n const model = await loadFeedbackModel(projectPath);\n const boosts = new Map<string, number>();\n\n if (model.totalFeedback < 3) return boosts; // not enough data\n\n const taskType = classifyTask(task);\n\n // Boost files with high acceptance rate\n for (const [file, fa] of Object.entries(model.fileAcceptance)) {\n if (fa.includedCount < 2) continue;\n\n // Positive boost for high acceptance\n if (fa.acceptRate >= 0.7) {\n boosts.set(file, (boosts.get(file) ?? 0) + fa.acceptRate * 5);\n }\n\n // Negative boost (penalty) for consistently rejected\n if (fa.acceptRate < 0.2 && fa.includedCount >= 3) {\n boosts.set(file, (boosts.get(file) ?? 0) - 3);\n }\n }\n\n // Boost based on task type patterns\n const tta = model.taskTypeAcceptance[taskType];\n if (tta && tta.totalCount >= 2) {\n // If this task type has high compilability, boost type files\n if (tta.avgCompilable >= 0.8) {\n // Context is already good for this task type, minor boost\n for (const [file, fa] of Object.entries(model.fileAcceptance)) {\n if (fa.acceptRate >= 0.8) {\n boosts.set(file, (boosts.get(file) ?? 0) + 1);\n }\n }\n }\n }\n\n return boosts;\n}\n\n// ===== RENDER =====\n\nexport function renderFeedbackReport(model: FeedbackModel): string {\n const lines: string[] = [];\n\n lines.push('');\n lines.push(` ╔══════════════════════════════════════════════════╗`);\n lines.push(` ║ 📊 Feedback Loop Report ║`);\n lines.push(` ╠══════════════════════════════════════════════════╣`);\n lines.push(` ║ ║`);\n lines.push(` ║ Total feedback: ${pad(model.totalFeedback.toString(), 8)} ║`);\n lines.push(` ║ Accept rate: ${pad(Math.round(model.acceptRate * 100) + '%', 8)} ║`);\n lines.push(` ║ Tracked files: ${pad(Object.keys(model.fileAcceptance).length.toString(), 8)} ║`);\n lines.push(` ║ Task types: ${pad(Object.keys(model.taskTypeAcceptance).length.toString(), 8)} ║`);\n lines.push(` ║ ║`);\n\n if (model.insights.length > 0) {\n lines.push(` ║ Insights: ║`);\n for (const insight of model.insights.slice(0, 5)) {\n const icon = insight.type === 'positive' ? '✅' : insight.type === 'negative' ? '⚠️' : '💡';\n lines.push(` ║ ${icon} ${pad(insight.title, 43)} ║`);\n }\n }\n\n lines.push(` ║ ║`);\n lines.push(` ╚══════════════════════════════════════════════════╝`);\n\n return lines.join('\\n');\n}\n\nfunction pad(s: string, w: number): string { return s.padEnd(w).substring(0, w); }\n","import type { ProjectAnalysis, AnalyzedFile } from '../types/engine.js';\nimport { buildAdjacencyList } from './graph-utils.js';\n\n// ===== Semantic Fingerprints =====\n//\n// Understand what code DOES, not just its structure.\n//\n// Current tools know: \"src/auth/login.ts has 150 tokens, imports 3 files, risk 72\"\n// Semantic fingerprints add: \"this file handles user authentication via JWT,\n// exposes a login endpoint, depends on the user model\"\n//\n// How it works (no LLM required):\n// 1. Extract semantic signals from code: export names, class names, function names,\n// string literals, decorators, route patterns, env var usage\n// 2. Classify each file into semantic domains: auth, database, api, config, etc.\n// 3. Build a semantic graph: which domains depend on which\n// 4. For a given task, match task intent to semantic domains\n//\n// This is hard to copy because:\n// - It requires deep AST understanding per language\n// - The domain classification improves with data\n// - The task → domain mapping is learned, not hardcoded\n\nexport interface SemanticFingerprint {\n filePath: string;\n domains: SemanticDomain[];\n exports: string[];\n concepts: string[];\n patterns: CodePattern[];\n intentScore: Map<string, number>; // intent → relevance score\n}\n\nexport interface SemanticDomain {\n name: string;\n confidence: number; // 0-1\n signals: string[];\n}\n\nexport interface CodePattern {\n type: 'route' | 'model' | 'middleware' | 'config' | 'test' | 'type' | 'util' | 'entry' | 'event' | 'error';\n evidence: string;\n}\n\nexport interface SemanticAnalysis {\n files: SemanticFingerprint[];\n domainGraph: { from: string; to: string; strength: number }[];\n domainClusters: { domain: string; files: string[]; tokenBudget: number }[];\n}\n\n// ===== DOMAIN DETECTION =====\n\nconst DOMAIN_SIGNALS: Record<string, { pathPatterns: RegExp[]; namePatterns: RegExp[]; contentPatterns: RegExp[] }> = {\n auth: {\n pathPatterns: [/auth/i, /login/i, /session/i, /passport/i, /oauth/i, /jwt/i, /token/i],\n namePatterns: [/login/i, /logout/i, /authenticate/i, /authorize/i, /verify.*token/i, /sign.*in/i],\n contentPatterns: [/jwt/i, /bearer/i, /passport/i, /bcrypt/i, /session/i, /cookie/i, /oauth/i],\n },\n database: {\n pathPatterns: [/model/i, /schema/i, /migration/i, /seed/i, /prisma/i, /database/i, /db\\b/i],\n namePatterns: [/create.*model/i, /find.*by/i, /query/i, /migrate/i, /schema/i],\n contentPatterns: [/prisma/i, /mongoose/i, /sequelize/i, /typeorm/i, /knex/i, /SELECT/i, /CREATE TABLE/i],\n },\n api: {\n pathPatterns: [/route/i, /controller/i, /endpoint/i, /handler/i, /api\\b/i, /rest/i],\n namePatterns: [/router/i, /handler/i, /controller/i, /endpoint/i, /get|post|put|delete|patch/i],\n contentPatterns: [/express/i, /fastify/i, /koa/i, /hono/i, /app\\.(get|post|put|delete)/i, /\\.route\\(/i],\n },\n config: {\n pathPatterns: [/config/i, /env/i, /setting/i, /constant/i, /\\.env/i],\n namePatterns: [/config/i, /setting/i, /env/i, /constant/i],\n contentPatterns: [/process\\.env/i, /dotenv/i, /config\\(/i, /DATABASE_URL/i],\n },\n testing: {\n pathPatterns: [/test/i, /spec/i, /mock/i, /fixture/i, /__test/i],\n namePatterns: [/describe/i, /test/i, /expect/i, /mock/i, /fixture/i],\n contentPatterns: [/describe\\(/i, /it\\(/i, /expect\\(/i, /jest/i, /vitest/i, /mocha/i],\n },\n ui: {\n pathPatterns: [/component/i, /view/i, /page/i, /layout/i, /template/i, /style/i],\n namePatterns: [/render/i, /component/i, /view/i, /page/i, /layout/i],\n contentPatterns: [/react/i, /vue/i, /svelte/i, /jsx/i, /className/i, /useState/i, /html/i],\n },\n middleware: {\n pathPatterns: [/middleware/i, /interceptor/i, /guard/i, /filter/i, /pipe/i],\n namePatterns: [/middleware/i, /intercept/i, /guard/i, /filter/i, /pipe/i],\n contentPatterns: [/next\\(\\)/i, /req\\s*,\\s*res/i, /middleware/i, /use\\(/i],\n },\n types: {\n pathPatterns: [/type/i, /interface/i, /\\.d\\.ts$/i, /schema/i],\n namePatterns: [/interface/i, /type\\s+\\w/i, /enum/i, /schema/i],\n contentPatterns: [/export\\s+(interface|type|enum)\\s/i, /declare\\s/i, /\\.d\\.ts/i],\n },\n util: {\n pathPatterns: [/util/i, /helper/i, /lib\\b/i, /common/i, /shared/i, /tool/i],\n namePatterns: [/format/i, /parse/i, /validate/i, /convert/i, /transform/i, /helper/i],\n contentPatterns: [],\n },\n error: {\n pathPatterns: [/error/i, /exception/i, /fault/i],\n namePatterns: [/error/i, /exception/i, /throw/i, /catch/i, /fault/i],\n contentPatterns: [/extends\\s+Error/i, /throw\\s+new/i, /catch\\s*\\(/i, /error.*handler/i],\n },\n};\n\n// ===== INTENT MAPPING =====\n\nconst INTENT_DOMAINS: Record<string, string[]> = {\n 'authentication': ['auth', 'middleware', 'config', 'types'],\n 'authorization': ['auth', 'middleware', 'types'],\n 'database': ['database', 'types', 'config'],\n 'api': ['api', 'middleware', 'types', 'error'],\n 'routing': ['api', 'middleware'],\n 'testing': ['testing', 'types'],\n 'refactoring': ['types', 'util', 'config'],\n 'error handling': ['error', 'middleware', 'api'],\n 'configuration': ['config', 'types'],\n 'ui': ['ui', 'types', 'api'],\n 'performance': ['util', 'middleware', 'config'],\n 'security': ['auth', 'middleware', 'config', 'error'],\n 'deployment': ['config', 'error'],\n 'monitoring': ['middleware', 'error', 'config'],\n 'caching': ['middleware', 'config', 'util'],\n 'validation': ['types', 'middleware', 'util'],\n 'serialization': ['types', 'util'],\n 'logging': ['middleware', 'util', 'config'],\n};\n\n// ===== MAIN API =====\n\nexport function analyzeSemantics(analysis: ProjectAnalysis): SemanticAnalysis {\n const fingerprints: SemanticFingerprint[] = [];\n\n for (const file of analysis.files) {\n fingerprints.push(computeSemanticFingerprint(file));\n }\n\n // Build domain graph\n const adj = buildAdjacencyList(analysis.graph.edges);\n const domainGraph: SemanticAnalysis['domainGraph'] = [];\n\n for (const edge of analysis.graph.edges) {\n const fromFp = fingerprints.find((f) => f.filePath === edge.from);\n const toFp = fingerprints.find((f) => f.filePath === edge.to);\n if (fromFp && toFp) {\n for (const fromDomain of fromFp.domains) {\n for (const toDomain of toFp.domains) {\n if (fromDomain.name !== toDomain.name) {\n domainGraph.push({\n from: fromDomain.name,\n to: toDomain.name,\n strength: fromDomain.confidence * toDomain.confidence,\n });\n }\n }\n }\n }\n }\n\n // Cluster files by domain\n const domainFiles = new Map<string, string[]>();\n for (const fp of fingerprints) {\n const primaryDomain = fp.domains[0]?.name ?? 'unknown';\n if (!domainFiles.has(primaryDomain)) domainFiles.set(primaryDomain, []);\n domainFiles.get(primaryDomain)!.push(fp.filePath);\n }\n\n const domainClusters = [...domainFiles.entries()].map(([domain, files]) => {\n const totalTokens = files.reduce((sum, path) => {\n const f = analysis.files.find((af) => af.relativePath === path);\n return sum + (f?.tokens ?? 0);\n }, 0);\n return { domain, files, tokenBudget: totalTokens };\n });\n\n return { files: fingerprints, domainGraph, domainClusters };\n}\n\nfunction computeSemanticFingerprint(file: AnalyzedFile): SemanticFingerprint {\n const domains: SemanticDomain[] = [];\n const concepts: string[] = [];\n const patterns: CodePattern[] = [];\n\n // Detect domains from path, exports, and kind\n for (const [domainName, signals] of Object.entries(DOMAIN_SIGNALS)) {\n let confidence = 0;\n const evidences: string[] = [];\n\n // Path-based detection\n for (const pattern of signals.pathPatterns) {\n if (pattern.test(file.relativePath)) {\n confidence += 0.3;\n evidences.push(`path matches ${pattern.source}`);\n }\n }\n\n // Import-based detection (files importing domain-specific modules)\n for (const imp of file.imports ?? []) {\n for (const pattern of signals.namePatterns) {\n if (pattern.test(imp)) {\n confidence += 0.2;\n evidences.push(`imports ${imp}`);\n }\n }\n }\n\n // Kind-based detection\n if (file.kind === 'type' && domainName === 'types') confidence += 0.4;\n if (file.kind === 'test' && domainName === 'testing') confidence += 0.4;\n if (file.kind === 'entry' && domainName === 'api') confidence += 0.2;\n if (file.kind === 'config' && domainName === 'config') confidence += 0.4;\n\n if (confidence > 0.1) {\n domains.push({\n name: domainName,\n confidence: Math.min(1, confidence),\n signals: evidences.slice(0, 5),\n });\n }\n }\n\n // Sort domains by confidence\n domains.sort((a, b) => b.confidence - a.confidence);\n\n // Extract concepts from file path and imports\n const pathParts = file.relativePath.replace(/\\.[^.]+$/, '').split(/[\\/\\-_.]/);\n for (const part of pathParts) {\n const words = part.replace(/([A-Z])/g, ' $1').toLowerCase().trim().split(/\\s+/);\n concepts.push(...words.filter((w: string) => w.length > 2));\n }\n\n // Detect code patterns from file kind\n if (file.kind === 'type') patterns.push({ type: 'type', evidence: 'file kind' });\n if (file.kind === 'test') patterns.push({ type: 'test', evidence: 'file kind' });\n if (file.kind === 'entry') patterns.push({ type: 'entry', evidence: 'file kind' });\n if (file.kind === 'config') patterns.push({ type: 'config', evidence: 'file kind' });\n\n return {\n filePath: file.relativePath,\n domains,\n exports: file.imports ?? [],\n concepts: [...new Set(concepts)].slice(0, 20),\n patterns,\n intentScore: new Map(),\n };\n}\n\n// ===== SEMANTIC SELECTION =====\n\nexport function semanticBoosts(\n semantics: SemanticAnalysis,\n task: string,\n): Map<string, number> {\n const boosts = new Map<string, number>();\n const taskLower = task.toLowerCase();\n\n // 1. Extract intents from task\n const matchedIntents: { intent: string; domains: string[] }[] = [];\n for (const [intent, domains] of Object.entries(INTENT_DOMAINS)) {\n if (taskLower.includes(intent.split(' ')[0])) {\n matchedIntents.push({ intent, domains });\n }\n }\n\n // 2. Also extract domain keywords directly\n const directDomains = new Set<string>();\n for (const domainName of Object.keys(DOMAIN_SIGNALS)) {\n if (taskLower.includes(domainName)) {\n directDomains.add(domainName);\n }\n }\n\n // 3. Boost files whose domains match task intents\n for (const fp of semantics.files) {\n let boost = 0;\n\n for (const fileDomain of fp.domains) {\n // Direct domain match\n if (directDomains.has(fileDomain.name)) {\n boost += fileDomain.confidence * 8;\n }\n\n // Intent-based match\n for (const { domains } of matchedIntents) {\n if (domains.includes(fileDomain.name)) {\n boost += fileDomain.confidence * 5;\n }\n }\n }\n\n // Concept matching\n const taskWords = taskLower.replace(/[^a-z0-9\\s]/g, '').split(/\\s+/);\n for (const concept of fp.concepts) {\n if (taskWords.some((w) => w.includes(concept) || concept.includes(w))) {\n boost += 2;\n }\n }\n\n if (boost > 0) {\n boosts.set(fp.filePath, Math.round(boost * 10) / 10);\n }\n }\n\n return boosts;\n}\n\n// ===== RENDER =====\n\nexport function renderSemanticAnalysis(semantics: SemanticAnalysis): string {\n const lines: string[] = [];\n\n lines.push('');\n lines.push(` ╔══════════════════════════════════════════════════╗`);\n lines.push(` ║ 🧬 Semantic Analysis ║`);\n lines.push(` ╠══════════════════════════════════════════════════╣`);\n lines.push(` ║ ║`);\n\n // Domain clusters\n const sorted = [...semantics.domainClusters].sort((a, b) => b.files.length - a.files.length);\n for (const cluster of sorted.slice(0, 8)) {\n const tokens = cluster.tokenBudget >= 1000 ? `${(cluster.tokenBudget / 1000).toFixed(1)}K` : `${cluster.tokenBudget}`;\n lines.push(` ║ ${pad(cluster.domain, 14)} ${pad(cluster.files.length + ' files', 10)} ${pad(tokens + ' tok', 10)} ║`);\n }\n\n lines.push(` ║ ║`);\n\n // Domain connections\n const uniqueEdges = new Map<string, number>();\n for (const edge of semantics.domainGraph) {\n const key = `${edge.from} → ${edge.to}`;\n uniqueEdges.set(key, (uniqueEdges.get(key) ?? 0) + edge.strength);\n }\n const topEdges = [...uniqueEdges.entries()]\n .sort((a, b) => b[1] - a[1])\n .slice(0, 5);\n\n if (topEdges.length > 0) {\n lines.push(` ║ Domain Dependencies: ║`);\n for (const [edge, strength] of topEdges) {\n lines.push(` ║ ${pad(edge, 30)} (${strength.toFixed(1)}) ║`);\n }\n }\n\n lines.push(` ║ ║`);\n lines.push(` ╚══════════════════════════════════════════════════╝`);\n\n return lines.join('\\n');\n}\n\nfunction pad(s: string, w: number): string { return s.padEnd(w).substring(0, w); }\n","import type { ProjectAnalysis, AnalyzedFile } from '../types/engine.js';\nimport type { TaskType } from '../types/interact.js';\nimport { selectContext } from './selector.js';\nimport { buildAdjacencyList, bfsBidirectional } from './graph-utils.js';\nimport { classifyTask } from '../interact/router.js';\n\n// ===== Compilability Benchmark =====\n//\n// THE killer proof: CTO context → code that compiles. Naive → type errors.\n//\n// Measures:\n// 1. Type Availability — What % of referenced types/interfaces are in context?\n// 2. Import Chain Completeness — Can the AI follow the full import chain?\n// 3. Missing Symbols — Which specific types/interfaces are MISSING from context?\n// 4. Predicted Compile Errors — Estimate how many TS errors generated code would have\n//\n// The insight: if the AI generates `const result: ContextSelection = ...` but\n// ContextSelection interface is NOT in context, it will either:\n// a) Invent the type (wrong shape → runtime error)\n// b) Skip the type (any → no type safety)\n// c) Hallucinate properties (compile error)\n//\n// CTO always includes type files. Naive (alphabetical) almost never does.\n\nexport interface CompilabilityResult {\n project: string;\n task: string;\n budget: number;\n\n strategies: {\n cto: CompilabilityMetrics;\n naive: CompilabilityMetrics;\n random: CompilabilityMetrics;\n };\n\n comparison: {\n ctoVsNaiveTypeAvailability: number;\n ctoVsRandomTypeAvailability: number;\n ctoVsNaivePredictedErrors: number;\n naiveMissingTypes: string[];\n randomMissingTypes: string[];\n };\n\n verdict: string;\n}\n\nexport interface CompilabilityMetrics {\n // Type coverage\n typeFilesAvailable: number;\n typeFilesTotal: number;\n typeAvailabilityPercent: number;\n\n // Import chain analysis\n importChainsComplete: number;\n importChainsTotal: number;\n importCompletenessPercent: number;\n\n // Specific missing symbols\n missingTypeFiles: string[];\n missingDependencies: string[];\n\n // Predicted errors\n predictedTypeErrors: number;\n predictedImportErrors: number;\n predictedTotalErrors: number;\n\n // Compilability score (0-100)\n compilabilityScore: number;\n\n // Files and tokens\n filesSelected: number;\n tokensUsed: number;\n}\n\n// ===== MAIN API =====\n\nexport async function runCompilabilityBenchmark(\n analysis: ProjectAnalysis,\n task: string,\n budget: number = 50_000,\n): Promise<CompilabilityResult> {\n const taskType = classifyTask(task);\n\n // Identify all type files in the project\n const typeFiles = analysis.files.filter((f) => f.kind === 'type');\n const allTypePaths = new Set(typeFiles.map((f) => f.relativePath));\n\n // Build dependency graph\n const adj = buildAdjacencyList(analysis.graph.edges);\n\n // Identify task-relevant files (keyword + graph)\n const relevantFiles = findRelevantFiles(analysis, task);\n const relevantPaths = new Set(relevantFiles.map((f) => f.relativePath));\n\n // Find which type files are needed by relevant files\n const neededTypes = new Set<string>();\n for (const file of relevantFiles) {\n const deps = adj.forward.get(file.relativePath) ?? [];\n for (const dep of deps) {\n if (allTypePaths.has(dep)) neededTypes.add(dep);\n }\n }\n // Also add types that are transitively needed\n const expandedTypes = bfsBidirectional([...neededTypes], adj, 1);\n for (const t of expandedTypes) {\n if (allTypePaths.has(t)) neededTypes.add(t);\n }\n\n // === CTO selection ===\n const ctoSelection = await selectContext({ task, analysis, budget });\n const ctoPaths = new Set(ctoSelection.files.map((f) => f.relativePath));\n const ctoMetrics = computeCompilability(\n ctoPaths, ctoSelection.totalTokens, analysis, allTypePaths, neededTypes, adj, relevantPaths,\n );\n\n // === Naive selection (alphabetical) ===\n const naiveSorted = [...analysis.files].sort((a, b) => a.relativePath.localeCompare(b.relativePath));\n const naivePaths = new Set<string>();\n let naiveTokens = 0;\n for (const f of naiveSorted) {\n if (naiveTokens + f.tokens <= budget) {\n naivePaths.add(f.relativePath);\n naiveTokens += f.tokens;\n }\n }\n if (naivePaths.size === 0 && analysis.totalTokens <= budget) {\n for (const f of analysis.files) naivePaths.add(f.relativePath);\n naiveTokens = analysis.totalTokens;\n }\n const naiveMetrics = computeCompilability(\n naivePaths, naiveTokens, analysis, allTypePaths, neededTypes, adj, relevantPaths,\n );\n\n // === Random selection ===\n const shuffled = [...analysis.files].sort(() => Math.random() - 0.5);\n const randomPaths = new Set<string>();\n let randomTokens = 0;\n for (const f of shuffled) {\n if (randomTokens + f.tokens <= budget) {\n randomPaths.add(f.relativePath);\n randomTokens += f.tokens;\n }\n }\n const randomMetrics = computeCompilability(\n randomPaths, randomTokens, analysis, allTypePaths, neededTypes, adj, relevantPaths,\n );\n\n // Comparison\n const comparison = {\n ctoVsNaiveTypeAvailability: ctoMetrics.typeAvailabilityPercent - naiveMetrics.typeAvailabilityPercent,\n ctoVsRandomTypeAvailability: ctoMetrics.typeAvailabilityPercent - randomMetrics.typeAvailabilityPercent,\n ctoVsNaivePredictedErrors: naiveMetrics.predictedTotalErrors - ctoMetrics.predictedTotalErrors,\n naiveMissingTypes: naiveMetrics.missingTypeFiles,\n randomMissingTypes: randomMetrics.missingTypeFiles,\n };\n\n const verdict = generateVerdict(ctoMetrics, naiveMetrics, randomMetrics, comparison, analysis);\n\n return {\n project: analysis.projectName,\n task,\n budget,\n strategies: { cto: ctoMetrics, naive: naiveMetrics, random: randomMetrics },\n comparison,\n verdict,\n };\n}\n\n// ===== COMPILABILITY COMPUTATION =====\n\nfunction computeCompilability(\n selectedPaths: Set<string>,\n tokensUsed: number,\n analysis: ProjectAnalysis,\n allTypePaths: Set<string>,\n neededTypes: Set<string>,\n adj: ReturnType<typeof buildAdjacencyList>,\n relevantPaths: Set<string>,\n): CompilabilityMetrics {\n // Type availability: what % of needed type files are included?\n const typeFilesAvailable = [...neededTypes].filter((t) => selectedPaths.has(t)).length;\n const typeFilesTotal = neededTypes.size;\n const typeAvailabilityPercent = typeFilesTotal > 0\n ? Math.round((typeFilesAvailable / typeFilesTotal) * 100) : 100;\n\n // Import chain completeness\n let chainsComplete = 0;\n let chainsTotal = 0;\n\n for (const path of selectedPaths) {\n if (!relevantPaths.has(path)) continue;\n const deps = adj.forward.get(path) ?? [];\n for (const dep of deps) {\n chainsTotal++;\n if (selectedPaths.has(dep)) chainsComplete++;\n }\n }\n const importCompletenessPercent = chainsTotal > 0\n ? Math.round((chainsComplete / chainsTotal) * 100) : 100;\n\n // Missing type files\n const missingTypeFiles = [...neededTypes].filter((t) => !selectedPaths.has(t));\n\n // Missing dependencies (non-type files that are imported but not included)\n const missingDeps: string[] = [];\n for (const path of selectedPaths) {\n const deps = adj.forward.get(path) ?? [];\n for (const dep of deps) {\n if (!selectedPaths.has(dep) && !allTypePaths.has(dep)) {\n if (!missingDeps.includes(dep)) missingDeps.push(dep);\n }\n }\n }\n\n // Predicted errors\n // Each missing type file → ~3 type errors (avg interface has 3 usages)\n const predictedTypeErrors = missingTypeFiles.length * 3;\n\n // Each broken import chain → 1 import error\n const predictedImportErrors = chainsTotal - chainsComplete;\n\n const predictedTotalErrors = predictedTypeErrors + predictedImportErrors;\n\n // Compilability score (0-100)\n const typeWeight = 0.6;\n const importWeight = 0.4;\n const compilabilityScore = Math.round(\n typeAvailabilityPercent * typeWeight +\n importCompletenessPercent * importWeight,\n );\n\n return {\n typeFilesAvailable,\n typeFilesTotal,\n typeAvailabilityPercent,\n importChainsComplete: chainsComplete,\n importChainsTotal: chainsTotal,\n importCompletenessPercent,\n missingTypeFiles,\n missingDependencies: missingDeps.slice(0, 20),\n predictedTypeErrors,\n predictedImportErrors,\n predictedTotalErrors,\n compilabilityScore,\n filesSelected: selectedPaths.size,\n tokensUsed,\n };\n}\n\n// ===== RELEVANT FILE FINDER =====\n\nfunction findRelevantFiles(analysis: ProjectAnalysis, task: string): AnalyzedFile[] {\n const keywords = task.toLowerCase()\n .replace(/[^a-z0-9\\s]/g, '')\n .split(/\\s+/)\n .filter((w) => w.length > 2);\n\n const stopWords = new Set([\n 'the', 'and', 'for', 'with', 'from', 'that', 'this', 'fix', 'add',\n 'remove', 'update', 'change', 'refactor', 'implement', 'create',\n 'build', 'make', 'code', 'file', 'module', 'function',\n ]);\n const filtered = keywords.filter((w) => !stopWords.has(w));\n\n const adj = buildAdjacencyList(analysis.graph.edges);\n const scored = new Map<string, number>();\n\n for (const file of analysis.files) {\n let score = 0;\n for (const kw of filtered) {\n if (file.relativePath.toLowerCase().includes(kw)) score += 10;\n }\n if (file.riskScore >= 60) score += 5;\n if (file.isHub) score += 3;\n if (file.kind === 'entry') score += 3;\n if (file.kind === 'type') score += 2;\n if (score > 0) scored.set(file.relativePath, score);\n }\n\n // Expand via deps\n const seeds = [...scored.keys()];\n const expanded = bfsBidirectional(seeds, adj, 1);\n for (const path of expanded) {\n if (!scored.has(path)) scored.set(path, 1);\n }\n\n return analysis.files\n .filter((f) => scored.has(f.relativePath))\n .sort((a, b) => (scored.get(b.relativePath) ?? 0) - (scored.get(a.relativePath) ?? 0));\n}\n\n// ===== VERDICT =====\n\nfunction generateVerdict(\n cto: CompilabilityMetrics,\n naive: CompilabilityMetrics,\n random: CompilabilityMetrics,\n comp: CompilabilityResult['comparison'],\n analysis: ProjectAnalysis,\n): string {\n const lines: string[] = [];\n\n lines.push('## Compilability Verdict');\n lines.push('');\n\n if (cto.compilabilityScore > naive.compilabilityScore) {\n const errorDiff = comp.ctoVsNaivePredictedErrors;\n lines.push(`**CTO context produces code with ${errorDiff} fewer predicted compile errors than naive.**`);\n } else {\n lines.push('**All strategies produce similar compilability for this task.**');\n }\n lines.push('');\n\n // Type availability\n lines.push('### Type Availability');\n lines.push(`- CTO: ${cto.typeAvailabilityPercent}% of needed type files (${cto.typeFilesAvailable}/${cto.typeFilesTotal})`);\n lines.push(`- Naive: ${naive.typeAvailabilityPercent}% (${naive.typeFilesAvailable}/${naive.typeFilesTotal})`);\n lines.push(`- Random: ${random.typeAvailabilityPercent}% (${random.typeFilesAvailable}/${random.typeFilesTotal})`);\n lines.push('');\n\n // Missing types (the killer data)\n if (comp.naiveMissingTypes.length > 0) {\n lines.push('### Types Missing from Naive Context');\n lines.push('Without these, AI-generated code will have type errors:');\n for (const t of comp.naiveMissingTypes) {\n lines.push(`- ❌ \\`${t}\\``);\n }\n lines.push('');\n }\n\n // Predicted errors\n lines.push('### Predicted Compile Errors');\n lines.push(`- CTO: ~${cto.predictedTotalErrors} errors (${cto.predictedTypeErrors} type + ${cto.predictedImportErrors} import)`);\n lines.push(`- Naive: ~${naive.predictedTotalErrors} errors (${naive.predictedTypeErrors} type + ${naive.predictedImportErrors} import)`);\n lines.push(`- Random: ~${random.predictedTotalErrors} errors (${random.predictedTypeErrors} type + ${random.predictedImportErrors} import)`);\n\n return lines.join('\\n');\n}\n\n// ===== RENDERING =====\n\nexport function renderCompilabilityBenchmark(result: CompilabilityResult): string {\n const { cto, naive, random } = result.strategies;\n const lines: string[] = [];\n\n lines.push('');\n lines.push(` ╔══════════════════════════════════════════════════════════════════╗`);\n lines.push(` ║ 🔧 Compilability Benchmark — ${pad(result.project, 20)} ║`);\n lines.push(` ║ Task: ${pad(result.task.substring(0, 48), 48)} ║`);\n lines.push(` ╠══════════════════════════════════════════════════════════════════╣`);\n lines.push(` ║ ║`);\n lines.push(` ║ ${pad('Metric', 26)} ${pad('CTO', 10)} ${pad('Naive', 10)} ${pad('Random', 10)} ║`);\n lines.push(` ║ ${'─'.repeat(56)} ║`);\n lines.push(` ║ ${pad('Compilability Score', 26)} ${pad(cto.compilabilityScore + '/100', 10)} ${pad(naive.compilabilityScore + '/100', 10)} ${pad(random.compilabilityScore + '/100', 10)} ║`);\n lines.push(` ║ ${pad('Type Availability', 26)} ${pad(cto.typeAvailabilityPercent + '%', 10)} ${pad(naive.typeAvailabilityPercent + '%', 10)} ${pad(random.typeAvailabilityPercent + '%', 10)} ║`);\n lines.push(` ║ ${pad('Import Completeness', 26)} ${pad(cto.importCompletenessPercent + '%', 10)} ${pad(naive.importCompletenessPercent + '%', 10)} ${pad(random.importCompletenessPercent + '%', 10)} ║`);\n lines.push(` ║ ${pad('Predicted Type Errors', 26)} ${pad(cto.predictedTypeErrors.toString(), 10)} ${pad(naive.predictedTypeErrors.toString(), 10)} ${pad(random.predictedTypeErrors.toString(), 10)} ║`);\n lines.push(` ║ ${pad('Predicted Import Errors', 26)} ${pad(cto.predictedImportErrors.toString(), 10)} ${pad(naive.predictedImportErrors.toString(), 10)} ${pad(random.predictedImportErrors.toString(), 10)} ║`);\n lines.push(` ║ ${pad('TOTAL Predicted Errors', 26)} ${pad(cto.predictedTotalErrors.toString(), 10)} ${pad(naive.predictedTotalErrors.toString(), 10)} ${pad(random.predictedTotalErrors.toString(), 10)} ║`);\n lines.push(` ║ ${'─'.repeat(56)} ║`);\n lines.push(` ║ ${pad('Type files included', 26)} ${pad(`${cto.typeFilesAvailable}/${cto.typeFilesTotal}`, 10)} ${pad(`${naive.typeFilesAvailable}/${naive.typeFilesTotal}`, 10)} ${pad(`${random.typeFilesAvailable}/${random.typeFilesTotal}`, 10)} ║`);\n lines.push(` ║ ${pad('Tokens used', 26)} ${pad(fmt(cto.tokensUsed), 10)} ${pad(fmt(naive.tokensUsed), 10)} ${pad(fmt(random.tokensUsed), 10)} ║`);\n lines.push(` ║ ║`);\n\n if (result.comparison.naiveMissingTypes.length > 0) {\n lines.push(` ║ ❌ Naive MISSING types (will cause hallucinated types): ║`);\n for (const t of result.comparison.naiveMissingTypes.slice(0, 5)) {\n lines.push(` ║ ${pad(t, 55)} ║`);\n }\n lines.push(` ║ ║`);\n }\n\n if (result.comparison.ctoVsNaivePredictedErrors > 0) {\n lines.push(` ║ 🏆 CTO produces ~${result.comparison.ctoVsNaivePredictedErrors} FEWER compile errors than naive ║`);\n }\n\n lines.push(` ║ ║`);\n lines.push(` ╚══════════════════════════════════════════════════════════════════╝`);\n\n return lines.join('\\n');\n}\n\nfunction pad(s: string, w: number): string { return s.padEnd(w).substring(0, w); }\nfunction fmt(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`;\n return n.toString();\n}\n","import { resolve, join, dirname, relative, basename } from 'node:path';\nimport { readFile, writeFile, mkdir, rm, readdir, stat, cp } from 'node:fs/promises';\nimport { execSync } from 'node:child_process';\nimport type { ProjectAnalysis, AnalyzedFile } from '../types/engine.js';\nimport { selectContext } from './selector.js';\nimport { buildAdjacencyList } from './graph-utils.js';\n\n// ===== Compile Proof =====\n//\n// THE definitive proof: run the actual TypeScript compiler.\n//\n// How it works:\n// 1. For each strategy (CTO, naive, random):\n// a. Create a temp directory with ONLY the selected files\n// b. Generate a \"consumer\" file that imports & uses the project's types\n// c. Run `tsc --noEmit` and count REAL errors\n// 2. Compare: CTO context → 0 errors. Naive → many errors.\n//\n// This is not a prediction. This is the TypeScript compiler saying\n// \"this code WILL NOT COMPILE with naive context.\"\n\nexport interface CompileProofResult {\n project: string;\n task: string;\n budget: number;\n\n cto: CompileProofStrategy;\n naive: CompileProofStrategy;\n random: CompileProofStrategy;\n\n headline: string;\n details: string;\n}\n\nexport interface CompileProofStrategy {\n name: string;\n filesIncluded: number;\n tokensUsed: number;\n typeFilesIncluded: string[];\n typeFilesMissing: string[];\n\n // REAL tsc output\n compileErrors: number;\n errorMessages: string[];\n compiles: boolean;\n}\n\n// ===== MAIN =====\n\nexport async function runCompileProof(\n analysis: ProjectAnalysis,\n task: string,\n budget: number = 50_000,\n): Promise<CompileProofResult> {\n const projectPath = resolve(analysis.projectPath);\n\n // Identify type files\n const typeFiles = analysis.files.filter((f) => f.kind === 'type');\n const typePaths = typeFiles.map((f) => f.relativePath);\n\n // === CTO selection ===\n const ctoSelection = await selectContext({ task, analysis, budget });\n const ctoPaths = new Set(ctoSelection.files.map((f) => f.relativePath));\n\n // === Naive selection (alphabetical) ===\n const naiveSorted = [...analysis.files].sort((a, b) =>\n a.relativePath.localeCompare(b.relativePath),\n );\n const naivePaths = new Set<string>();\n let naiveTokens = 0;\n for (const f of naiveSorted) {\n if (naiveTokens + f.tokens <= budget) {\n naivePaths.add(f.relativePath);\n naiveTokens += f.tokens;\n }\n }\n if (naivePaths.size === 0 && analysis.totalTokens <= budget) {\n for (const f of analysis.files) naivePaths.add(f.relativePath);\n naiveTokens = analysis.totalTokens;\n }\n\n // === Random selection ===\n const shuffled = [...analysis.files].sort(() => Math.random() - 0.5);\n const randomPaths = new Set<string>();\n let randomTokens = 0;\n for (const f of shuffled) {\n if (randomTokens + f.tokens <= budget) {\n randomPaths.add(f.relativePath);\n randomTokens += f.tokens;\n }\n }\n\n // Generate the consumer code — a file that imports and uses the project's key types\n const consumerCode = generateConsumerCode(analysis, typePaths);\n\n // Run tsc for each strategy\n const [ctoResult, naiveResult, randomResult] = await Promise.all([\n runTscWithContext('CTO', projectPath, ctoPaths, ctoSelection.totalTokens, typePaths, consumerCode),\n runTscWithContext('Naive', projectPath, naivePaths, naiveTokens, typePaths, consumerCode),\n runTscWithContext('Random', projectPath, randomPaths, randomTokens, typePaths, consumerCode),\n ]);\n\n // Headline\n const errorDiff = naiveResult.compileErrors - ctoResult.compileErrors;\n let headline: string;\n if (ctoResult.compiles && !naiveResult.compiles) {\n headline = `✅ CTO context compiles. ❌ Naive has ${naiveResult.compileErrors} real TypeScript errors.`;\n } else if (errorDiff > 0) {\n headline = `CTO has ${errorDiff} fewer compile errors than naive (${ctoResult.compileErrors} vs ${naiveResult.compileErrors}).`;\n } else {\n headline = `Both strategies compile for this task.`;\n }\n\n const details = generateDetails(ctoResult, naiveResult, randomResult);\n\n return {\n project: analysis.projectName,\n task,\n budget,\n cto: ctoResult,\n naive: naiveResult,\n random: randomResult,\n headline,\n details,\n };\n}\n\n// ===== CONSUMER CODE GENERATION =====\n\nfunction generateConsumerCode(analysis: ProjectAnalysis, typePaths: string[]): string {\n const lines: string[] = [];\n lines.push('// ======================================================================');\n lines.push('// COMPILE PROOF — Simulates realistic AI-generated code');\n lines.push('// This is what an AI assistant would generate when asked to work');\n lines.push('// with this codebase. Without type definitions, none of this compiles.');\n lines.push('// ======================================================================');\n lines.push('');\n\n // Filter out barrel/re-export files\n const nonBarrelTypes = typePaths.filter((tp) => {\n const name = basename(tp, '.ts');\n return name !== 'index' && name !== 'v2';\n });\n\n // Import from each type file\n for (const typePath of nonBarrelTypes) {\n const file = analysis.files.find((f) => f.relativePath === typePath);\n if (!file) continue;\n const importPath = './' + typePath.replace(/\\.ts$/, '.js');\n const moduleName = basename(typePath, '.ts').replace(/[^a-zA-Z0-9]/g, '_');\n lines.push(`import type * as ${moduleName} from '${importPath}';`);\n }\n\n lines.push('');\n\n // Generate realistic AI-like code that uses types deeply\n const knownTypes = extractKnownTypes(analysis, nonBarrelTypes);\n for (const { typeName, typePath } of knownTypes) {\n const moduleName = basename(typePath, '.ts').replace(/[^a-zA-Z0-9]/g, '_');\n\n // Type alias (AI always does this)\n lines.push(`type ${typeName} = ${moduleName}.${typeName};`);\n }\n lines.push('');\n\n // === Realistic function: \"analyze and select context\" ===\n lines.push('// Simulated AI output: a function that processes analysis results');\n lines.push('function processAnalysis(analysis: engine.ProjectAnalysis): void {');\n lines.push(' // Access nested properties (fails without types)');\n lines.push(' const files = analysis.files;');\n lines.push(' const totalTokens = analysis.totalTokens;');\n lines.push(' const graph = analysis.graph;');\n lines.push(' const hubs = graph.hubs;');\n lines.push(' const edges = graph.edges;');\n lines.push(' const risk = analysis.riskProfile;');\n lines.push(' const critical = risk.distribution.critical;');\n lines.push('');\n lines.push(' for (const file of files) {');\n lines.push(' const score = file.riskScore;');\n lines.push(' const kind = file.kind;');\n lines.push(' const hub = file.isHub;');\n lines.push(' const deps = file.imports;');\n lines.push(' const impact = file.exclusionImpact;');\n lines.push(' void [score, kind, hub, deps, impact];');\n lines.push(' }');\n lines.push('');\n lines.push(' for (const hub of hubs) {');\n lines.push(' void hub.relativePath;');\n lines.push(' void hub.dependents;');\n lines.push(' void hub.score;');\n lines.push(' }');\n lines.push('');\n lines.push(' for (const edge of edges) {');\n lines.push(' void edge.from;');\n lines.push(' void edge.to;');\n lines.push(' void edge.type;');\n lines.push(' }');\n lines.push('');\n lines.push(' void [totalTokens, critical];');\n lines.push('}');\n lines.push('');\n\n // === Realistic function: \"build context selection\" ===\n lines.push('// Simulated AI output: works with context selection results');\n lines.push('function handleSelection(selection: engine.ContextSelection): string[] {');\n lines.push(' const coverage = selection.coverage;');\n lines.push(' const coverageScore = coverage.score;');\n lines.push(' const missing = coverage.missingCritical;');\n lines.push('');\n lines.push(' const result: string[] = [];');\n lines.push(' for (const file of selection.files) {');\n lines.push(' const path = file.relativePath;');\n lines.push(' const tokens = file.tokens;');\n lines.push(' const level = file.pruneLevel;');\n lines.push(' const risk = file.riskScore;');\n lines.push(' result.push(`${path}: ${tokens}t, ${level}, risk=${risk}`);');\n lines.push(' }');\n lines.push('');\n lines.push(' void [coverageScore, missing, selection.budget, selection.hash];');\n lines.push(' return result;');\n lines.push('}');\n lines.push('');\n\n // === Realistic: object construction (what AI does when creating new instances) ===\n lines.push('// Simulated AI output: constructing objects with correct shapes');\n lines.push('function createMockFile(): engine.AnalyzedFile {');\n lines.push(' return {');\n lines.push(' path: \"/src/test.ts\",');\n lines.push(' relativePath: \"src/test.ts\",');\n lines.push(' extension: \".ts\",');\n lines.push(' size: 1000,');\n lines.push(' tokens: 250,');\n lines.push(' lines: 50,');\n lines.push(' lastModified: new Date(),');\n lines.push(' kind: \"source\",');\n lines.push(' imports: [],');\n lines.push(' importedBy: [],');\n lines.push(' isHub: false,');\n lines.push(' complexity: 5,');\n lines.push(' riskScore: 30,');\n lines.push(' riskFactors: [],');\n lines.push(' exclusionImpact: \"low\",');\n lines.push(' };');\n lines.push('}');\n lines.push('');\n\n lines.push('// Ensure all functions are used');\n lines.push('void processAnalysis;');\n lines.push('void handleSelection;');\n lines.push('void createMockFile;');\n lines.push('');\n lines.push('export {};');\n return lines.join('\\n');\n}\n\ninterface KnownType {\n typeName: string;\n typePath: string;\n sampleProperties: string[];\n}\n\nfunction extractKnownTypes(analysis: ProjectAnalysis, typePaths: string[]): KnownType[] {\n // Hardcode key types we know exist (from reading the type files)\n // In production this would be AST-extracted\n const types: KnownType[] = [];\n\n for (const tp of typePaths) {\n if (tp.includes('engine')) {\n types.push(\n { typeName: 'AnalyzedFile', typePath: tp, sampleProperties: ['relativePath', 'tokens', 'riskScore', 'kind', 'isHub'] },\n { typeName: 'ProjectAnalysis', typePath: tp, sampleProperties: ['files', 'totalFiles', 'totalTokens', 'graph', 'stack'] },\n { typeName: 'ContextSelection', typePath: tp, sampleProperties: ['files', 'totalTokens', 'budget', 'coverage', 'riskScore'] },\n { typeName: 'SelectedFile', typePath: tp, sampleProperties: ['relativePath', 'tokens', 'pruneLevel', 'riskScore'] },\n { typeName: 'CoverageResult', typePath: tp, sampleProperties: ['score', 'relevantFiles', 'missingCritical'] },\n { typeName: 'RiskProfile', typePath: tp, sampleProperties: ['distribution', 'topRiskFiles'] },\n { typeName: 'ProjectGraph', typePath: tp, sampleProperties: ['nodes', 'edges', 'hubs', 'clusters'] },\n );\n }\n if (tp.includes('interact')) {\n types.push(\n { typeName: 'TaskType', typePath: tp, sampleProperties: [] },\n );\n }\n if (tp.includes('config')) {\n types.push(\n { typeName: 'CTOConfig', typePath: tp, sampleProperties: [] },\n );\n }\n if (tp.includes('govern')) {\n types.push(\n { typeName: 'AuditEntry', typePath: tp, sampleProperties: [] },\n );\n }\n }\n\n return types;\n}\n\n// ===== TSC RUNNER =====\n\nasync function runTscWithContext(\n name: string,\n projectPath: string,\n selectedPaths: Set<string>,\n tokensUsed: number,\n typePaths: string[],\n consumerCode: string,\n): Promise<CompileProofStrategy> {\n const tmpDir = join(projectPath, '.cto', `compile-proof-${name.toLowerCase()}`);\n\n try {\n // Clean and create temp dir\n await rm(tmpDir, { recursive: true, force: true });\n await mkdir(tmpDir, { recursive: true });\n\n // Copy ONLY selected files to temp dir\n for (const filePath of selectedPaths) {\n const src = join(projectPath, filePath);\n const dest = join(tmpDir, filePath);\n try {\n await mkdir(dirname(dest), { recursive: true });\n await cp(src, dest);\n } catch {\n // File might not exist (e.g., already compiled output)\n }\n }\n\n // Write consumer file\n await writeFile(join(tmpDir, '_compile_test.ts'), consumerCode);\n\n // Write minimal tsconfig\n await writeFile(join(tmpDir, 'tsconfig.json'), JSON.stringify({\n compilerOptions: {\n target: 'ES2022',\n module: 'nodenext',\n moduleResolution: 'nodenext',\n strict: true,\n noEmit: true,\n skipLibCheck: true,\n esModuleInterop: true,\n },\n include: ['_compile_test.ts'],\n }, null, 2));\n\n // Run tsc\n let tscOutput = '';\n let compileErrors = 0;\n try {\n execSync('npx tsc --noEmit --pretty false 2>&1', {\n cwd: tmpDir,\n encoding: 'utf-8',\n timeout: 30_000,\n env: { ...process.env, NODE_ENV: 'production' },\n });\n // If we get here, no errors\n } catch (err: any) {\n tscOutput = err.stdout ?? err.message ?? '';\n }\n\n // Parse errors\n const errorLines = tscOutput\n .split('\\n')\n .filter((l: string) => l.includes('error TS'))\n .map((l: string) => l.trim());\n\n compileErrors = errorLines.length;\n\n // Which type files are included / missing\n const typeFilesIncluded = typePaths.filter((t) => selectedPaths.has(t));\n const typeFilesMissing = typePaths.filter((t) => !selectedPaths.has(t));\n\n return {\n name,\n filesIncluded: selectedPaths.size,\n tokensUsed,\n typeFilesIncluded,\n typeFilesMissing,\n compileErrors,\n errorMessages: errorLines.slice(0, 20), // top 20 errors\n compiles: compileErrors === 0,\n };\n } finally {\n // Cleanup\n await rm(tmpDir, { recursive: true, force: true }).catch(() => {});\n }\n}\n\n// ===== RENDERING =====\n\nfunction generateDetails(\n cto: CompileProofStrategy,\n naive: CompileProofStrategy,\n random: CompileProofStrategy,\n): string {\n const lines: string[] = [];\n\n lines.push('### Type Files Availability');\n lines.push(`- **CTO:** ${cto.typeFilesIncluded.length} included, ${cto.typeFilesMissing.length} missing`);\n lines.push(`- **Naive:** ${naive.typeFilesIncluded.length} included, ${naive.typeFilesMissing.length} missing`);\n lines.push(`- **Random:** ${random.typeFilesIncluded.length} included, ${random.typeFilesMissing.length} missing`);\n lines.push('');\n\n if (naive.typeFilesMissing.length > 0) {\n lines.push('### Missing from Naive (causes compile errors):');\n for (const t of naive.typeFilesMissing) {\n lines.push(`- ❌ \\`${t}\\``);\n }\n lines.push('');\n }\n\n if (naive.errorMessages.length > 0) {\n lines.push('### Sample Naive Compile Errors:');\n lines.push('```');\n for (const e of naive.errorMessages.slice(0, 10)) {\n lines.push(e);\n }\n lines.push('```');\n }\n\n return lines.join('\\n');\n}\n\nexport function renderCompileProof(result: CompileProofResult): string {\n const lines: string[] = [];\n\n lines.push('');\n lines.push(` ╔══════════════════════════════════════════════════════════════════════╗`);\n lines.push(` ║ 🔬 COMPILE PROOF — Real TypeScript Compiler Output ║`);\n lines.push(` ║ ${pad(result.project, 20)} · \"${pad(result.task.substring(0, 35), 35)}\" ║`);\n lines.push(` ╠══════════════════════════════════════════════════════════════════════╣`);\n lines.push(` ║ ║`);\n lines.push(` ║ ${pad('', 28)} ${pad('CTO', 12)} ${pad('Naive', 12)} ${pad('Random', 12)} ║`);\n lines.push(` ║ ${'─'.repeat(64)} ║`);\n lines.push(` ║ ${pad('Compiles?', 28)} ${pad(result.cto.compiles ? '✅ YES' : '❌ NO', 12)} ${pad(result.naive.compiles ? '✅ YES' : '❌ NO', 12)} ${pad(result.random.compiles ? '✅ YES' : '❌ NO', 12)} ║`);\n lines.push(` ║ ${pad('TypeScript Errors', 28)} ${pad(result.cto.compileErrors.toString(), 12)} ${pad(result.naive.compileErrors.toString(), 12)} ${pad(result.random.compileErrors.toString(), 12)} ║`);\n lines.push(` ║ ${pad('Type Files Included', 28)} ${pad(`${result.cto.typeFilesIncluded.length}/${result.cto.typeFilesIncluded.length + result.cto.typeFilesMissing.length}`, 12)} ${pad(`${result.naive.typeFilesIncluded.length}/${result.naive.typeFilesIncluded.length + result.naive.typeFilesMissing.length}`, 12)} ${pad(`${result.random.typeFilesIncluded.length}/${result.random.typeFilesIncluded.length + result.random.typeFilesMissing.length}`, 12)} ║`);\n lines.push(` ║ ${pad('Files in Context', 28)} ${pad(result.cto.filesIncluded.toString(), 12)} ${pad(result.naive.filesIncluded.toString(), 12)} ${pad(result.random.filesIncluded.toString(), 12)} ║`);\n lines.push(` ║ ${pad('Tokens Used', 28)} ${pad(fmt(result.cto.tokensUsed), 12)} ${pad(fmt(result.naive.tokensUsed), 12)} ${pad(fmt(result.random.tokensUsed), 12)} ║`);\n lines.push(` ║ ║`);\n\n if (result.naive.typeFilesMissing.length > 0) {\n lines.push(` ║ ❌ Types MISSING from Naive (AI will hallucinate these): ║`);\n for (const t of result.naive.typeFilesMissing) {\n lines.push(` ║ ${pad(t, 61)} ║`);\n }\n lines.push(` ║ ║`);\n }\n\n if (result.naive.errorMessages.length > 0) {\n lines.push(` ║ 📋 Sample tsc errors from Naive context: ║`);\n for (const e of result.naive.errorMessages.slice(0, 5)) {\n lines.push(` ║ ${pad(e.substring(0, 61), 61)} ║`);\n }\n lines.push(` ║ ║`);\n }\n\n lines.push(` ║ ${pad(result.headline, 66)} ║`);\n lines.push(` ║ ║`);\n lines.push(` ╚══════════════════════════════════════════════════════════════════════╝`);\n\n return lines.join('\\n');\n}\n\nfunction pad(s: string, w: number): string { return s.padEnd(w).substring(0, w); }\nfunction fmt(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`;\n return n.toString();\n}\n","import type { ProjectAnalysis, ContextSelection } from '../types/engine.js';\nimport { selectContext } from './selector.js';\nimport { estimateCost } from '../interact/estimator.js';\n\n// ===== Multi-Model Context Optimization =====\n//\n// Different AI models have different:\n// - Context windows (4K → 2M tokens)\n// - Pricing ($0.25/M → $15/M)\n// - Strengths (code gen, analysis, refactoring)\n//\n// CTO optimizes context PER MODEL:\n// - Small window? Aggressive pruning, only critical files\n// - Large window? Include more context, less pruning needed\n// - Expensive model? Minimize tokens, maximize signal-to-noise\n// - Cheap model? Include broader context for better understanding\n//\n// This is something NO competitor does. Cursor sends the same context\n// to every model. CTO adapts.\n\nexport interface ModelProfile {\n id: string;\n name: string;\n provider: 'openai' | 'anthropic' | 'google' | 'mistral' | 'meta' | 'custom';\n contextWindow: number;\n maxOutput: number;\n costPer1MInput: number;\n costPer1MOutput: number;\n strengths: ModelStrength[];\n recommendedBudgetPercent: number; // % of context window to use\n}\n\nexport type ModelStrength = 'code-generation' | 'analysis' | 'refactoring' | 'debugging' | 'documentation' | 'testing' | 'general';\n\nexport interface MultiModelResult {\n task: string;\n models: ModelOptimization[];\n recommendation: {\n bestValue: string;\n bestQuality: string;\n bestSpeed: string;\n reasoning: string;\n };\n}\n\nexport interface ModelOptimization {\n model: ModelProfile;\n budget: number;\n selection: ContextSelection;\n estimatedCost: number;\n qualityScore: number; // 0-100, estimated output quality\n recommendation: string;\n}\n\n// ===== MODEL REGISTRY =====\n\nexport const MODEL_REGISTRY: ModelProfile[] = [\n {\n id: 'gpt-4o',\n name: 'GPT-4o',\n provider: 'openai',\n contextWindow: 128_000,\n maxOutput: 16_384,\n costPer1MInput: 2.50,\n costPer1MOutput: 10.00,\n strengths: ['code-generation', 'analysis', 'general'],\n recommendedBudgetPercent: 40,\n },\n {\n id: 'gpt-4o-mini',\n name: 'GPT-4o Mini',\n provider: 'openai',\n contextWindow: 128_000,\n maxOutput: 16_384,\n costPer1MInput: 0.15,\n costPer1MOutput: 0.60,\n strengths: ['general', 'documentation'],\n recommendedBudgetPercent: 60,\n },\n {\n id: 'claude-sonnet-4',\n name: 'Claude Sonnet 4',\n provider: 'anthropic',\n contextWindow: 200_000,\n maxOutput: 64_000,\n costPer1MInput: 3.00,\n costPer1MOutput: 15.00,\n strengths: ['code-generation', 'refactoring', 'analysis', 'debugging'],\n recommendedBudgetPercent: 35,\n },\n {\n id: 'claude-haiku-3.5',\n name: 'Claude 3.5 Haiku',\n provider: 'anthropic',\n contextWindow: 200_000,\n maxOutput: 8_192,\n costPer1MInput: 0.80,\n costPer1MOutput: 4.00,\n strengths: ['general', 'testing', 'documentation'],\n recommendedBudgetPercent: 50,\n },\n {\n id: 'gemini-2.0-flash',\n name: 'Gemini 2.0 Flash',\n provider: 'google',\n contextWindow: 1_048_576,\n maxOutput: 8_192,\n costPer1MInput: 0.10,\n costPer1MOutput: 0.40,\n strengths: ['analysis', 'general'],\n recommendedBudgetPercent: 20,\n },\n {\n id: 'gemini-2.5-pro',\n name: 'Gemini 2.5 Pro',\n provider: 'google',\n contextWindow: 1_048_576,\n maxOutput: 65_536,\n costPer1MInput: 1.25,\n costPer1MOutput: 10.00,\n strengths: ['code-generation', 'analysis', 'refactoring'],\n recommendedBudgetPercent: 15,\n },\n {\n id: 'deepseek-v3',\n name: 'DeepSeek V3',\n provider: 'custom',\n contextWindow: 128_000,\n maxOutput: 8_192,\n costPer1MInput: 0.27,\n costPer1MOutput: 1.10,\n strengths: ['code-generation', 'debugging'],\n recommendedBudgetPercent: 50,\n },\n {\n id: 'codestral',\n name: 'Codestral',\n provider: 'mistral',\n contextWindow: 256_000,\n maxOutput: 8_192,\n costPer1MInput: 0.30,\n costPer1MOutput: 0.90,\n strengths: ['code-generation', 'refactoring'],\n recommendedBudgetPercent: 45,\n },\n];\n\n// ===== MAIN API =====\n\nexport async function optimizeForModels(\n analysis: ProjectAnalysis,\n task: string,\n models?: string[],\n): Promise<MultiModelResult> {\n const targetModels = models\n ? MODEL_REGISTRY.filter((m) => models.includes(m.id))\n : MODEL_REGISTRY;\n\n const optimizations: ModelOptimization[] = [];\n\n for (const model of targetModels) {\n const budget = Math.round(model.contextWindow * (model.recommendedBudgetPercent / 100));\n const selection = await selectContext({ task, analysis, budget });\n\n // Estimate cost\n const inputTokens = selection.totalTokens + 500; // + prompt overhead\n const outputTokens = Math.min(model.maxOutput, 4000); // estimated output\n const estimatedCost = (inputTokens / 1_000_000) * model.costPer1MInput +\n (outputTokens / 1_000_000) * model.costPer1MOutput;\n\n // Quality score based on coverage + model strength match\n const taskStrengthMatch = computeStrengthMatch(model, task);\n const coverageFactor = selection.coverage.score / 100;\n const budgetUtilization = selection.usedPercent / 100;\n const qualityScore = Math.round(\n taskStrengthMatch * 40 +\n coverageFactor * 35 +\n Math.min(1, budgetUtilization) * 25,\n );\n\n const recommendation = generateModelRecommendation(model, selection, qualityScore, estimatedCost);\n\n optimizations.push({\n model,\n budget,\n selection,\n estimatedCost,\n qualityScore,\n recommendation,\n });\n }\n\n // Sort by quality score\n optimizations.sort((a, b) => b.qualityScore - a.qualityScore);\n\n // Find best in each category\n const bestQuality = optimizations[0];\n const bestValue = optimizations.reduce((best, curr) =>\n (curr.qualityScore / Math.max(curr.estimatedCost, 0.0001)) >\n (best.qualityScore / Math.max(best.estimatedCost, 0.0001)) ? curr : best,\n );\n const cheapest = optimizations.reduce((best, curr) =>\n curr.estimatedCost < best.estimatedCost ? curr : best,\n );\n\n return {\n task,\n models: optimizations,\n recommendation: {\n bestValue: bestValue.model.id,\n bestQuality: bestQuality.model.id,\n bestSpeed: cheapest.model.id,\n reasoning: `Best quality: ${bestQuality.model.name} (${bestQuality.qualityScore}/100, $${bestQuality.estimatedCost.toFixed(4)}/call). ` +\n `Best value: ${bestValue.model.name} (${bestValue.qualityScore}/100, $${bestValue.estimatedCost.toFixed(4)}/call). ` +\n `Cheapest: ${cheapest.model.name} ($${cheapest.estimatedCost.toFixed(4)}/call).`,\n },\n };\n}\n\nfunction computeStrengthMatch(model: ModelProfile, task: string): number {\n const taskLower = task.toLowerCase();\n let matches = 0;\n let checks = 0;\n\n const strengthKeywords: Record<ModelStrength, string[]> = {\n 'code-generation': ['implement', 'create', 'build', 'add', 'write', 'generate'],\n 'analysis': ['analyze', 'understand', 'explain', 'review', 'investigate'],\n 'refactoring': ['refactor', 'optimize', 'improve', 'clean', 'restructure'],\n 'debugging': ['fix', 'debug', 'bug', 'error', 'issue', 'broken'],\n 'documentation': ['document', 'readme', 'comment', 'explain', 'describe'],\n 'testing': ['test', 'spec', 'coverage', 'unit', 'integration'],\n 'general': [],\n };\n\n for (const strength of model.strengths) {\n const keywords = strengthKeywords[strength];\n if (keywords.length === 0) continue;\n checks++;\n if (keywords.some((kw) => taskLower.includes(kw))) matches++;\n }\n\n if (checks === 0) return 0.7; // general model\n return 0.5 + (matches / checks) * 0.5;\n}\n\nfunction generateModelRecommendation(\n model: ModelProfile,\n selection: ContextSelection,\n quality: number,\n cost: number,\n): string {\n if (quality >= 90) return `Excellent for this task. ${selection.coverage.score}% coverage, great strength match.`;\n if (quality >= 70) return `Good choice. ${selection.coverage.score}% coverage at $${cost.toFixed(4)}/call.`;\n if (quality >= 50) return `Adequate. Consider a model with better ${model.strengths.length < 3 ? 'breadth' : 'specialization'}.`;\n return `Not ideal for this task type. Coverage: ${selection.coverage.score}%.`;\n}\n\n// ===== RENDERING =====\n\nexport function renderMultiModelResult(result: MultiModelResult): string {\n const lines: string[] = [];\n\n lines.push('');\n lines.push(` ╔══════════════════════════════════════════════════════════════════════════╗`);\n lines.push(` ║ 🎯 Multi-Model Optimization ║`);\n lines.push(` ║ Task: ${pad(result.task.substring(0, 58), 58)} ║`);\n lines.push(` ╠══════════════════════════════════════════════════════════════════════════╣`);\n lines.push(` ║ ║`);\n lines.push(` ║ ${pad('Model', 22)} ${pad('Budget', 10)} ${pad('Tokens', 10)} ${pad('Cover', 8)} ${pad('Quality', 10)} ${pad('$/call', 10)} ║`);\n lines.push(` ║ ${'─'.repeat(70)} ║`);\n\n for (const opt of result.models) {\n const isRec = opt.model.id === result.recommendation.bestValue;\n const prefix = isRec ? '★ ' : ' ';\n lines.push(` ║ ${prefix}${pad(opt.model.name, 20)} ${pad(fmt(opt.budget), 10)} ${pad(fmt(opt.selection.totalTokens), 10)} ${pad(opt.selection.coverage.score + '%', 8)} ${pad(opt.qualityScore + '/100', 10)} ${pad('$' + opt.estimatedCost.toFixed(4), 10)} ║`);\n }\n\n lines.push(` ║ ║`);\n lines.push(` ║ ★ = Best value ║`);\n lines.push(` ║ ${pad(result.recommendation.reasoning, 72)} ║`);\n lines.push(` ║ ║`);\n lines.push(` ╚══════════════════════════════════════════════════════════════════════════╝`);\n\n return lines.join('\\n');\n}\n\nfunction pad(s: string, w: number): string { return s.padEnd(w).substring(0, w); }\nfunction fmt(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`;\n return n.toString();\n}\n"],"mappings":"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","names":["readFile","stat","join","relative","resolve","basename","join","stat","readFile","relative","basename","resolve","readFile","join","existsSync","join","existsSync","readFile","createHash","readdir","stat","join","extname","relative","resolve","readdir","join","extname","stat","relative","createHash","resolve","resolve","resolve","resolve","resolve","risk","createHash","readFile","resolve","relative","Project","SyntaxKind","readFile","existsSync","join","TS_EXTENSIONS","emptyResult","readFile","Project","SyntaxKind","join","existsSync","getCascadeLevels","createHash","pad","pad","fmt","resolve","join","readFile","writeFile","mkdir","join","resolve","mkdir","readFile","writeFile","extractKeywords","join","basename","readFile","writeFile","mkdir","computeFingerprint","basename","join","readFile","createEmptyModel","mkdir","writeFile","resolve","join","readFile","writeFile","mkdir","join","resolve","mkdir","getModelPath","readFile","writeFile","createEmptyModel","pad","pad","generateVerdict","pad","fmt","resolve","join","dirname","basename","writeFile","mkdir","resolve","basename","join","mkdir","dirname","writeFile","pad","fmt","MODEL_REGISTRY","pad","fmt"]}
1
+ {"version":3,"sources":["../../src/engine/analyzer.ts","../../src/types/engine.ts","../../src/types/config.ts","../../src/engine/tokenizer.ts","../../src/engine/graph.ts","../../src/engine/risk.ts","../../src/engine/graph-utils.ts","../../src/engine/config.ts","../../src/engine/cache.ts","../../src/engine/watcher.ts","../../src/engine/pr-context.ts","../../src/engine/selector.ts","../../src/govern/secrets.ts","../../src/engine/pruner.ts","../../src/engine/coverage.ts","../../src/engine/budget.ts","../../src/engine/score.ts","../../src/engine/benchmark.ts","../../src/engine/quality-benchmark.ts","../../src/interact/router.ts","../../src/interact/prompt.ts","../../src/engine/predictor.ts","../../src/engine/cross-repo.ts","../../src/engine/feedback.ts","../../src/engine/semantic.ts","../../src/engine/compilability.ts","../../src/engine/compile-proof.ts","../../src/engine/multi-model.ts"],"sourcesContent":["import { readFile, readdir, stat } from 'node:fs/promises';\nimport { join, extname, relative, resolve, basename } from 'node:path';\nimport { createHash } from 'node:crypto';\nimport type {\n AnalyzedFile,\n FileKind,\n ProjectAnalysis,\n WalkEntry,\n WalkOptions,\n} from '../types/engine.js';\nimport { DEFAULT_RISK_WEIGHTS } from '../types/engine.js';\nimport type { CTOConfig } from '../types/config.js';\nimport { DEFAULT_CONFIG } from '../types/config.js';\nimport { estimateTokens, countTokensChars4 } from './tokenizer.js';\nimport { buildProjectGraph } from './graph.js';\nimport { scoreAllFiles } from './risk.js';\n\n// ===== FILE WALKING =====\n\nfunction matchesPattern(filename: string, patterns: string[]): boolean {\n for (const pattern of patterns) {\n if (pattern.startsWith('*.')) {\n const ext = pattern.slice(1);\n if (filename.endsWith(ext)) return true;\n } else if (filename === pattern) {\n return true;\n }\n }\n return false;\n}\n\nexport async function walkProject(\n rootPath: string,\n options: WalkOptions,\n): Promise<WalkEntry[]> {\n const results: WalkEntry[] = [];\n const { ignoreDirs, ignorePatterns, extensions, maxDepth = 20 } = options;\n const ignoreDirSet = new Set(ignoreDirs);\n\n async function walk(dir: string, depth: number): Promise<void> {\n if (depth > maxDepth) return;\n\n let entries;\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n const promises: Promise<void>[] = [];\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n\n if (entry.isDirectory()) {\n if (!ignoreDirSet.has(entry.name) && !entry.name.startsWith('.')) {\n promises.push(walk(fullPath, depth + 1));\n }\n } else if (entry.isFile()) {\n const ext = extname(entry.name).slice(1).toLowerCase();\n if (ext && extensions.includes(ext) && !matchesPattern(entry.name, ignorePatterns)) {\n promises.push(\n (async () => {\n const fileStat = await stat(fullPath).catch(() => null);\n if (!fileStat) return;\n\n let lines = 0;\n try {\n const content = await readFile(fullPath, 'utf-8');\n lines = content.split('\\n').length;\n } catch {\n lines = 0;\n }\n\n results.push({\n path: fullPath,\n relativePath: relative(rootPath, fullPath),\n extension: ext,\n size: fileStat.size,\n lastModified: fileStat.mtime,\n lines,\n });\n })(),\n );\n }\n }\n }\n\n await Promise.all(promises);\n }\n\n await walk(rootPath, 0);\n return results;\n}\n\n// ===== FILE KIND DETECTION =====\n\nconst TYPE_PATTERNS = [/types?\\//i, /\\.d\\.ts$/, /interfaces?\\//i];\nconst TEST_PATTERNS = [/\\.test\\.[jt]sx?$/, /\\.spec\\.[jt]sx?$/, /\\/__tests__\\//, /\\/tests?\\//];\nconst CONFIG_PATTERNS = [/\\.config\\.[jt]s$/, /rc\\.[jt]s$/, /\\.env/, /tsconfig/, /package\\.json$/, /\\.yml$/, /\\.yaml$/, /\\.toml$/];\nconst ENTRY_PATTERNS = [/^index\\.[jt]sx?$/, /^main\\.[jt]sx?$/, /^app\\.[jt]sx?$/, /^server\\.[jt]sx?$/];\n\nexport function classifyFileKind(relativePath: string): FileKind {\n const filename = basename(relativePath);\n\n if (TYPE_PATTERNS.some((p) => p.test(relativePath))) return 'type';\n if (TEST_PATTERNS.some((p) => p.test(relativePath))) return 'test';\n if (CONFIG_PATTERNS.some((p) => p.test(relativePath) || p.test(filename))) return 'config';\n if (ENTRY_PATTERNS.some((p) => p.test(filename))) return 'entry';\n return 'source';\n}\n\n// ===== STACK DETECTION =====\n\nexport function detectStack(files: WalkEntry[]): string[] {\n const stack: string[] = [];\n const extensions = new Set(files.map((f) => f.extension));\n const paths = files.map((f) => f.relativePath.toLowerCase());\n\n if (extensions.has('ts') || extensions.has('tsx')) stack.push('TypeScript');\n else if (extensions.has('js') || extensions.has('jsx')) stack.push('JavaScript');\n if (extensions.has('py')) stack.push('Python');\n if (extensions.has('go')) stack.push('Go');\n if (extensions.has('rs')) stack.push('Rust');\n if (extensions.has('java')) stack.push('Java');\n if (extensions.has('kt')) stack.push('Kotlin');\n if (extensions.has('rb')) stack.push('Ruby');\n if (extensions.has('php')) stack.push('PHP');\n if (extensions.has('cs')) stack.push('C#');\n if (extensions.has('c') || extensions.has('cpp')) stack.push('C/C++');\n\n if (paths.some((p) => p.includes('next.config'))) stack.push('Next.js');\n if (paths.some((p) => p.includes('nuxt.config'))) stack.push('Nuxt');\n if (paths.some((p) => p.includes('angular.json'))) stack.push('Angular');\n\n return stack;\n}\n\n// ===== MAIN ANALYSIS PIPELINE =====\n\nexport async function analyzeProject(\n projectPath: string,\n config?: Partial<CTOConfig>,\n): Promise<ProjectAnalysis> {\n const absPath = resolve(projectPath);\n const projectName = basename(absPath);\n const mergedConfig = mergeConfig(DEFAULT_CONFIG, config);\n\n // 1. Walk project files\n const allExtensions = [\n ...mergedConfig.analysis.extensions.code,\n ...mergedConfig.analysis.extensions.config,\n ...mergedConfig.analysis.extensions.docs,\n ];\n\n const walkEntries = await walkProject(absPath, {\n ignoreDirs: mergedConfig.analysis.ignore.dirs,\n ignorePatterns: mergedConfig.analysis.ignore.patterns,\n extensions: allExtensions,\n maxDepth: mergedConfig.analysis.maxDepth,\n });\n\n // 2. Estimate tokens and build initial AnalyzedFile[]\n const tokenMethod = mergedConfig.tokens.method;\n const files: AnalyzedFile[] = [];\n\n for (const entry of walkEntries) {\n let tokens: number;\n if (tokenMethod === 'tiktoken') {\n try {\n const content = await readFile(entry.path, 'utf-8');\n tokens = estimateTokens(content, entry.size, 'tiktoken');\n } catch {\n tokens = countTokensChars4(entry.size);\n }\n } else {\n tokens = countTokensChars4(entry.size);\n }\n\n files.push({\n path: entry.path,\n relativePath: entry.relativePath,\n extension: entry.extension,\n size: entry.size,\n tokens,\n lines: entry.lines,\n lastModified: entry.lastModified,\n kind: classifyFileKind(entry.relativePath),\n\n // Graph data — populated by graph analysis\n imports: [],\n importedBy: [],\n isHub: false,\n complexity: 0,\n\n // Risk data — populated by risk analysis\n riskScore: 0,\n riskFactors: [],\n exclusionImpact: 'none',\n });\n }\n\n // 3. Build dependency graph (AST-based, best-effort)\n const graph = buildProjectGraph(absPath, files);\n\n // 4. Enrich files with graph data\n for (const file of files) {\n const nodeImports: string[] = [];\n const nodeImportedBy: string[] = [];\n\n for (const edge of graph.edges) {\n if (edge.from === file.relativePath) nodeImports.push(edge.to);\n if (edge.to === file.relativePath) nodeImportedBy.push(edge.from);\n }\n\n file.imports = nodeImports;\n file.importedBy = nodeImportedBy;\n file.isHub = graph.hubs.some((h) => h.relativePath === file.relativePath);\n }\n\n // 5. Score risk for all files\n const riskWeights = mergedConfig.risk.weights;\n scoreAllFiles(files, graph, riskWeights);\n\n // 6. Build risk profile\n const riskProfile = {\n distribution: {\n critical: files.filter((f) => f.riskScore >= 80).length,\n high: files.filter((f) => f.riskScore >= 60 && f.riskScore < 80).length,\n medium: files.filter((f) => f.riskScore >= 30 && f.riskScore < 60).length,\n low: files.filter((f) => f.riskScore < 30).length,\n },\n topRiskFiles: [...files].sort((a, b) => b.riskScore - a.riskScore).slice(0, 10),\n overallComplexity: files.length > 0\n ? files.reduce((s, f) => s + f.complexity, 0) / files.length\n : 0,\n };\n\n // 7. Build analysis hash for determinism\n const totalTokens = files.reduce((s, f) => s + f.tokens, 0);\n const hashInput = files\n .map((f) => `${f.relativePath}:${f.tokens}:${f.riskScore}`)\n .sort()\n .join('|');\n const hash = createHash('sha256').update(hashInput).digest('hex').substring(0, 16);\n\n const stack = detectStack(walkEntries);\n\n return {\n projectPath: absPath,\n projectName,\n analyzedAt: new Date(),\n hash,\n files,\n totalFiles: files.length,\n totalTokens,\n graph,\n riskProfile,\n stack,\n tokenMethod,\n };\n}\n\n// ===== CONFIG MERGE =====\n\nfunction mergeConfig(base: CTOConfig, overrides?: Partial<CTOConfig>): CTOConfig {\n if (!overrides) return base;\n\n return {\n ...base,\n ...overrides,\n analysis: {\n ...base.analysis,\n ...overrides.analysis,\n extensions: {\n ...base.analysis.extensions,\n ...overrides.analysis?.extensions,\n },\n ignore: {\n ...base.analysis.ignore,\n ...overrides.analysis?.ignore,\n },\n },\n risk: {\n ...base.risk,\n ...overrides.risk,\n weights: {\n ...base.risk.weights,\n ...overrides.risk?.weights,\n },\n },\n interaction: {\n ...base.interaction,\n ...overrides.interaction,\n },\n tokens: {\n ...base.tokens,\n ...overrides.tokens,\n },\n governance: {\n ...base.governance,\n ...overrides.governance,\n },\n };\n}\n","// ===== Layer 1: Context Intelligence Engine Types =====\n\n// ===== FILE ANALYSIS =====\n\nexport interface AnalyzedFile {\n path: string;\n relativePath: string;\n extension: string;\n size: number;\n tokens: number;\n lines: number;\n lastModified: Date;\n kind: FileKind;\n\n // Graph data (populated after graph analysis)\n imports: string[];\n importedBy: string[];\n isHub: boolean;\n complexity: number;\n\n // Risk data (populated after risk analysis)\n riskScore: number;\n riskFactors: RiskFactor[];\n exclusionImpact: ExclusionImpact;\n}\n\nexport type FileKind = 'source' | 'type' | 'test' | 'config' | 'entry' | 'asset';\nexport type ExclusionImpact = 'critical' | 'high' | 'medium' | 'low' | 'none';\n\n// ===== PROJECT ANALYSIS =====\n\nexport interface ProjectAnalysis {\n projectPath: string;\n projectName: string;\n analyzedAt: Date;\n hash: string;\n\n files: AnalyzedFile[];\n totalFiles: number;\n totalTokens: number;\n\n graph: ProjectGraph;\n riskProfile: RiskProfile;\n stack: string[];\n tokenMethod: 'chars4' | 'tiktoken';\n}\n\n// ===== DEPENDENCY GRAPH =====\n\nexport interface ProjectGraph {\n nodes: string[];\n edges: GraphEdge[];\n hubs: HubNode[];\n leaves: string[];\n orphans: string[];\n clusters: FileCluster[];\n}\n\nexport interface GraphEdge {\n from: string;\n to: string;\n type: 'import' | 'export' | 're-export';\n}\n\nexport interface HubNode {\n relativePath: string;\n dependents: number;\n dependencies: number;\n score: number;\n}\n\nexport interface FileCluster {\n id: string;\n name: string;\n files: string[];\n totalTokens: number;\n internalEdges: number;\n externalEdges: number;\n cohesion: number;\n}\n\n// ===== RISK MODEL =====\n\nexport interface RiskProfile {\n distribution: {\n critical: number;\n high: number;\n medium: number;\n low: number;\n };\n topRiskFiles: AnalyzedFile[];\n overallComplexity: number;\n}\n\nexport interface RiskFactor {\n type: RiskFactorType;\n score: number;\n weight: number;\n detail: string;\n}\n\nexport type RiskFactorType =\n | 'hub'\n | 'type-provider'\n | 'complexity'\n | 'recency'\n | 'config'\n | 'churn';\n\nexport interface RiskWeights {\n hub: number;\n typeProvider: number;\n complexity: number;\n recency: number;\n config: number;\n churn: number;\n}\n\nexport const DEFAULT_RISK_WEIGHTS: RiskWeights = {\n hub: 30,\n typeProvider: 25,\n complexity: 15,\n recency: 15,\n config: 10,\n churn: 5,\n};\n\n// ===== CONTEXT COVERAGE =====\n\nexport interface CoverageResult {\n score: number;\n relevantFiles: string[];\n includedRelevant: string[];\n missingRelevant: string[];\n missingCritical: string[];\n explanation: string;\n}\n\n// ===== CONTEXT SELECTION =====\n\nexport interface ContextSelection {\n files: SelectedFile[];\n totalTokens: number;\n budget: number;\n usedPercent: number;\n\n coverage: CoverageResult;\n riskScore: number;\n deterministic: boolean;\n hash: string;\n\n decisions: SelectionDecision[];\n}\n\nexport interface SelectedFile {\n relativePath: string;\n tokens: number;\n originalTokens: number;\n pruneLevel: PruneLevel;\n riskScore: number;\n reason: string;\n}\n\nexport type PruneLevel = 'full' | 'signatures' | 'skeleton' | 'excluded';\n\nexport interface SelectionDecision {\n file: string;\n action: 'include-full' | 'include-signatures' | 'include-skeleton' | 'exclude';\n reason: string;\n alternatives?: string;\n}\n\n// ===== BUDGET =====\n\nexport interface BudgetPlan {\n budget: number;\n used: number;\n remaining: number;\n fillPercent: number;\n files: BudgetEntry[];\n}\n\nexport interface BudgetEntry {\n relativePath: string;\n originalTokens: number;\n allocatedTokens: number;\n pruneLevel: PruneLevel;\n included: boolean;\n reason: string;\n}\n\n// ===== PRUNING =====\n\nexport interface PrunedContent {\n relativePath: string;\n originalTokens: number;\n prunedTokens: number;\n pruneLevel: PruneLevel;\n content: string;\n savingsPercent: number;\n}\n\n// ===== WALKER =====\n\nexport interface WalkEntry {\n path: string;\n relativePath: string;\n extension: string;\n size: number;\n lastModified: Date;\n lines: number;\n}\n\nexport interface WalkOptions {\n ignoreDirs: string[];\n ignorePatterns: string[];\n extensions: string[];\n maxDepth?: number;\n}\n","// ===== Configuration Types =====\n\nimport type { RiskWeights } from './engine.js';\n\nexport interface CTOConfig {\n version: string;\n\n analysis: {\n extensions: {\n code: string[];\n config: string[];\n docs: string[];\n };\n ignore: {\n dirs: string[];\n patterns: string[];\n };\n maxDepth: number;\n };\n\n risk: {\n weights: RiskWeights;\n };\n\n interaction: {\n defaultBudget: number;\n defaultModel: string;\n };\n\n tokens: {\n method: 'chars4' | 'tiktoken';\n };\n\n governance: {\n auditEnabled: boolean;\n secretDetection: boolean;\n retentionDays: number;\n };\n}\n\nexport const DEFAULT_CONFIG: CTOConfig = {\n version: '2.0',\n\n analysis: {\n extensions: {\n code: ['ts', 'tsx', 'js', 'jsx', 'py', 'go', 'rs', 'java', 'kt', 'rb', 'php', 'c', 'cpp', 'h', 'hpp', 'cs'],\n config: ['json', 'yml', 'yaml', 'toml'],\n docs: ['md', 'txt', 'rst'],\n },\n ignore: {\n dirs: ['node_modules', 'dist', 'build', '.git', 'coverage', '__pycache__', '.next', 'vendor', '.cto'],\n patterns: ['*.min.js', '*.map', '*.lock', '*.generated.*'],\n },\n maxDepth: 20,\n },\n\n risk: {\n weights: {\n hub: 30,\n typeProvider: 25,\n complexity: 15,\n recency: 15,\n config: 10,\n churn: 5,\n },\n },\n\n interaction: {\n defaultBudget: 50_000,\n defaultModel: 'claude-sonnet-4',\n },\n\n tokens: {\n method: 'chars4',\n },\n\n governance: {\n auditEnabled: true,\n secretDetection: true,\n retentionDays: 90,\n },\n};\n","import { encodingForModel } from 'js-tiktoken';\nimport { readFile, stat } from 'node:fs/promises';\n\nconst CHARS_PER_TOKEN = 4;\n\nlet encoder: ReturnType<typeof encodingForModel> | null = null;\n\nfunction getEncoder() {\n if (!encoder) {\n encoder = encodingForModel('claude-3-5-sonnet-20241022' as Parameters<typeof encodingForModel>[0]);\n }\n return encoder;\n}\n\nexport function countTokensTiktoken(text: string): number {\n try {\n const enc = getEncoder();\n const tokens = enc.encode(text);\n return tokens.length;\n } catch {\n return Math.ceil(text.length / CHARS_PER_TOKEN);\n }\n}\n\nexport function countTokensChars4(sizeInBytes: number): number {\n return Math.ceil(sizeInBytes / CHARS_PER_TOKEN);\n}\n\nexport function estimateTokens(\n content: string,\n sizeInBytes: number,\n method: 'chars4' | 'tiktoken' = 'chars4',\n): number {\n if (method === 'tiktoken') {\n return countTokensTiktoken(content);\n }\n return countTokensChars4(sizeInBytes);\n}\n\nexport async function estimateFileTokens(\n filePath: string,\n method: 'chars4' | 'tiktoken' = 'chars4',\n): Promise<number> {\n if (method === 'chars4') {\n const s = await stat(filePath);\n return countTokensChars4(s.size);\n }\n\n try {\n const content = await readFile(filePath, 'utf-8');\n return countTokensTiktoken(content);\n } catch {\n const s = await stat(filePath);\n return countTokensChars4(s.size);\n }\n}\n\nexport function freeEncoder(): void {\n encoder = null;\n}\n","import { Project, SyntaxKind, type SourceFile, type Node } from 'ts-morph';\nimport { resolve, relative, dirname, join, basename } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport type {\n AnalyzedFile,\n ProjectGraph,\n GraphEdge,\n HubNode,\n FileCluster,\n} from '../types/engine.js';\n\nconst TS_EXTENSIONS = new Set(['ts', 'tsx', 'js', 'jsx', 'mts', 'mjs', 'cts', 'cjs']);\n\n// ===== PROJECT CREATION =====\n\nexport function createProject(projectPath: string, filePaths: string[]): Project {\n const tsConfigPath = join(projectPath, 'tsconfig.json');\n const hasTsConfig = existsSync(tsConfigPath);\n\n const project = new Project({\n tsConfigFilePath: hasTsConfig ? tsConfigPath : undefined,\n skipAddingFilesFromTsConfig: true,\n compilerOptions: hasTsConfig\n ? undefined\n : {\n allowJs: true,\n jsx: 4 as any, // JsxEmit.ReactJSX\n esModuleInterop: true,\n moduleResolution: 100 as any, // Bundler\n },\n });\n\n const tsFiles = filePaths.filter((f) => {\n const ext = f.split('.').pop()?.toLowerCase() ?? '';\n return TS_EXTENSIONS.has(ext);\n });\n\n for (const filePath of tsFiles) {\n try {\n project.addSourceFileAtPath(filePath);\n } catch {\n // skip files that can't be parsed\n }\n }\n\n return project;\n}\n\n// ===== DEPENDENCY GRAPH =====\n\nexport function buildProjectGraph(\n projectPath: string,\n files: AnalyzedFile[],\n): ProjectGraph {\n const absPath = resolve(projectPath);\n\n const tsFiles = files\n .filter((f) => TS_EXTENSIONS.has(f.extension))\n .map((f) => f.path);\n\n if (tsFiles.length === 0) {\n return emptyGraph(files);\n }\n\n let project: Project;\n try {\n project = createProject(projectPath, tsFiles);\n } catch {\n return emptyGraph(files);\n }\n\n const edges: GraphEdge[] = [];\n const nodeSet = new Set<string>();\n\n for (const sourceFile of project.getSourceFiles()) {\n const fromRel = relative(absPath, sourceFile.getFilePath());\n if (fromRel.startsWith('..') || fromRel.includes('node_modules')) continue;\n nodeSet.add(fromRel);\n\n // Imports\n for (const imp of sourceFile.getImportDeclarations()) {\n const moduleSpecifier = imp.getModuleSpecifierValue();\n const resolved = resolveImport(sourceFile, moduleSpecifier, absPath);\n if (resolved) {\n nodeSet.add(resolved);\n edges.push({ from: fromRel, to: resolved, type: 'import' });\n }\n }\n\n // Re-exports\n for (const exp of sourceFile.getExportDeclarations()) {\n const moduleSpecifier = exp.getModuleSpecifierValue();\n if (moduleSpecifier) {\n const resolved = resolveImport(sourceFile, moduleSpecifier, absPath);\n if (resolved) {\n nodeSet.add(resolved);\n edges.push({ from: fromRel, to: resolved, type: 're-export' });\n }\n }\n }\n }\n\n const nodes = Array.from(nodeSet);\n\n // Calculate import counts\n const importedByCount = new Map<string, number>();\n const importCount = new Map<string, number>();\n\n for (const edge of edges) {\n importedByCount.set(edge.to, (importedByCount.get(edge.to) ?? 0) + 1);\n importCount.set(edge.from, (importCount.get(edge.from) ?? 0) + 1);\n }\n\n // Identify hubs using normalized in-degree centrality (Freeman, 1978).\n // centrality = in-degree / (N - 1), then combined with out-degree for a\n // \"betweenness-lite\" score: score = (in-degree × 2 + out-degree) / (N - 1 + 1)\n // This normalizes by graph size so hub detection is consistent across projects.\n const N = Math.max(nodes.length, 1);\n const hubs: HubNode[] = nodes\n .map((node) => {\n const inDeg = importedByCount.get(node) ?? 0;\n const outDeg = importCount.get(node) ?? 0;\n // Normalized centrality score (0-100 scale)\n const centrality = N > 1 ? (inDeg / (N - 1)) * 100 : 0;\n const score = Math.round(centrality + outDeg * (100 / (2 * N)));\n return {\n relativePath: node,\n dependents: inDeg,\n dependencies: outDeg,\n score: Math.min(100, score),\n };\n })\n .filter((h) => h.dependents >= 3 || h.score >= 15)\n .sort((a, b) => b.score - a.score);\n\n // Identify leaves (files that import but are not imported by anyone)\n const leaves = nodes.filter(\n (node) => (importedByCount.get(node) ?? 0) === 0 && (importCount.get(node) ?? 0) > 0,\n );\n\n // Identify orphans (files with no connections at all)\n const connectedNodes = new Set<string>();\n for (const edge of edges) {\n connectedNodes.add(edge.from);\n connectedNodes.add(edge.to);\n }\n const allFileNodes = new Set(files.map((f) => f.relativePath));\n const orphans = Array.from(allFileNodes).filter((n) => !connectedNodes.has(n));\n\n // Detect clusters using Union-Find for true connected components,\n // then refine with directory grouping for naming.\n const clusters = detectClusters(nodes, edges, files);\n\n // Enrich files with complexity (AST-based)\n enrichComplexity(project, absPath, files);\n\n return { nodes, edges, hubs, leaves, orphans, clusters };\n}\n\n// ===== CLUSTER DETECTION (Union-Find + directory naming) =====\n\nclass UnionFind {\n parent: Map<string, string>;\n rank: Map<string, number>;\n\n constructor(nodes: string[]) {\n this.parent = new Map();\n this.rank = new Map();\n for (const n of nodes) {\n this.parent.set(n, n);\n this.rank.set(n, 0);\n }\n }\n\n find(x: string): string {\n const p = this.parent.get(x);\n if (p === undefined) return x;\n if (p !== x) {\n this.parent.set(x, this.find(p)); // path compression\n }\n return this.parent.get(x)!;\n }\n\n union(a: string, b: string): void {\n const ra = this.find(a);\n const rb = this.find(b);\n if (ra === rb) return;\n const rankA = this.rank.get(ra) ?? 0;\n const rankB = this.rank.get(rb) ?? 0;\n if (rankA < rankB) {\n this.parent.set(ra, rb);\n } else if (rankA > rankB) {\n this.parent.set(rb, ra);\n } else {\n this.parent.set(rb, ra);\n this.rank.set(ra, rankA + 1);\n }\n }\n}\n\nfunction detectClusters(\n nodes: string[],\n edges: GraphEdge[],\n files: AnalyzedFile[],\n): FileCluster[] {\n // 1. Build connected components using Union-Find (O(E × α(V)))\n const uf = new UnionFind(nodes);\n for (const edge of edges) {\n uf.union(edge.from, edge.to);\n }\n\n // 2. Group by component root\n const components = new Map<string, string[]>();\n for (const node of nodes) {\n const root = uf.find(node);\n if (!components.has(root)) components.set(root, []);\n components.get(root)!.push(node);\n }\n\n // 3. For each component, derive a human-readable name from common directory prefix\n const tokenMap = new Map(files.map((f) => [f.relativePath, f.tokens]));\n const clusters: FileCluster[] = [];\n\n for (const [, groupFiles] of components) {\n if (groupFiles.length < 2) continue;\n\n // Find common directory prefix for naming\n const name = commonPrefix(groupFiles);\n const fileSet = new Set(groupFiles);\n let internalEdges = 0;\n let externalEdges = 0;\n\n for (const edge of edges) {\n const fromIn = fileSet.has(edge.from);\n const toIn = fileSet.has(edge.to);\n if (fromIn && toIn) internalEdges++;\n else if (fromIn || toIn) externalEdges++;\n }\n\n const totalEdges = internalEdges + externalEdges;\n const cohesion = totalEdges > 0 ? internalEdges / totalEdges : 0;\n const totalTokens = groupFiles.reduce((s, f) => s + (tokenMap.get(f) ?? 0), 0);\n\n clusters.push({\n id: name.replace(/[^a-zA-Z0-9]/g, '-') || `cluster-${clusters.length}`,\n name: name || `cluster-${clusters.length}`,\n files: groupFiles,\n totalTokens,\n internalEdges,\n externalEdges,\n cohesion: Math.round(cohesion * 100) / 100,\n });\n }\n\n return clusters.sort((a, b) => b.files.length - a.files.length);\n}\n\nfunction commonPrefix(paths: string[]): string {\n if (paths.length === 0) return '';\n const parts = paths.map((p) => p.split('/'));\n const prefix: string[] = [];\n for (let i = 0; i < parts[0].length - 1; i++) {\n const segment = parts[0][i];\n if (parts.every((p) => p[i] === segment)) {\n prefix.push(segment);\n } else break;\n }\n return prefix.join('/') || parts[0][0];\n}\n\n// ===== COMPLEXITY ANALYSIS =====\n\nfunction enrichComplexity(\n project: Project,\n absPath: string,\n files: AnalyzedFile[],\n): void {\n const fileMap = new Map(files.map((f) => [f.relativePath, f]));\n\n for (const sourceFile of project.getSourceFiles()) {\n const relPath = relative(absPath, sourceFile.getFilePath());\n if (relPath.startsWith('..') || relPath.includes('node_modules')) continue;\n\n const file = fileMap.get(relPath);\n if (!file) continue;\n\n let totalComplexity = 0;\n\n // Function declarations\n for (const func of sourceFile.getFunctions()) {\n totalComplexity += calculateCyclomaticComplexity(func);\n }\n\n // Class methods\n for (const cls of sourceFile.getClasses()) {\n for (const method of cls.getMethods()) {\n totalComplexity += calculateCyclomaticComplexity(method);\n }\n }\n\n // Arrow functions assigned to variables\n for (const varDecl of sourceFile.getVariableDeclarations()) {\n const init = varDecl.getInitializer();\n if (init && (init.getKind() === SyntaxKind.ArrowFunction || init.getKind() === SyntaxKind.FunctionExpression)) {\n totalComplexity += calculateCyclomaticComplexity(init);\n }\n }\n\n file.complexity = Math.max(1, totalComplexity);\n }\n}\n\nfunction calculateCyclomaticComplexity(node: Node): number {\n let complexity = 1;\n\n node.forEachDescendant((descendant) => {\n switch (descendant.getKind()) {\n case SyntaxKind.IfStatement:\n case SyntaxKind.ConditionalExpression:\n case SyntaxKind.ForStatement:\n case SyntaxKind.ForInStatement:\n case SyntaxKind.ForOfStatement:\n case SyntaxKind.WhileStatement:\n case SyntaxKind.DoStatement:\n case SyntaxKind.CaseClause:\n case SyntaxKind.CatchClause:\n complexity++;\n break;\n case SyntaxKind.BinaryExpression: {\n // FIX: Check the operator token kind directly instead of getText()\n // to avoid double-counting nested logical expressions.\n // getText() on `a && (b || c)` returns the full text including\n // the inner `||`, which would match both operators from the outer node.\n const opToken = (descendant as any).getOperatorToken?.();\n if (opToken) {\n const kind = opToken.getKind();\n if (\n kind === SyntaxKind.AmpersandAmpersandToken ||\n kind === SyntaxKind.BarBarToken ||\n kind === SyntaxKind.QuestionQuestionToken\n ) {\n complexity++;\n }\n }\n break;\n }\n }\n });\n\n return complexity;\n}\n\n// ===== IMPORT RESOLUTION =====\n\nfunction resolveImport(\n sourceFile: SourceFile,\n moduleSpecifier: string,\n projectRoot: string,\n): string | null {\n if (!moduleSpecifier.startsWith('.')) return null;\n\n const sourceDir = dirname(sourceFile.getFilePath());\n const basePath = resolve(sourceDir, moduleSpecifier);\n\n const extensions = ['.ts', '.tsx', '.js', '.jsx', '/index.ts', '/index.tsx', '/index.js', '/index.jsx'];\n\n for (const ext of extensions) {\n const candidate = basePath.endsWith(ext) ? basePath : basePath + ext;\n if (existsSync(candidate)) {\n const rel = relative(projectRoot, candidate);\n if (!rel.startsWith('..')) return rel;\n }\n }\n\n // .js → .ts resolution\n if (moduleSpecifier.endsWith('.js')) {\n const tsPath = basePath.replace(/\\.js$/, '.ts');\n if (existsSync(tsPath)) {\n const rel = relative(projectRoot, tsPath);\n if (!rel.startsWith('..')) return rel;\n }\n }\n\n return null;\n}\n\n// ===== HELPERS =====\n\nfunction emptyGraph(files: AnalyzedFile[]): ProjectGraph {\n return {\n nodes: files.map((f) => f.relativePath),\n edges: [],\n hubs: [],\n leaves: [],\n orphans: files.map((f) => f.relativePath),\n clusters: [],\n };\n}\n","import type {\n AnalyzedFile,\n RiskFactor,\n RiskFactorType,\n RiskWeights,\n ExclusionImpact,\n ProjectGraph,\n} from '../types/engine.js';\nimport { DEFAULT_RISK_WEIGHTS } from '../types/engine.js';\n\n// ===== RISK SCORING ENGINE =====\n//\n// Each file gets a riskScore ∈ [0, 100] representing the risk of EXCLUDING it\n// from AI context. Higher score = more dangerous to exclude.\n//\n// riskScore(file) = Σ(factor.score × factor.weight) / Σ(factor.weight)\n\nexport function scoreAllFiles(\n files: AnalyzedFile[],\n graph: ProjectGraph,\n weights: RiskWeights = DEFAULT_RISK_WEIGHTS,\n): void {\n // Pre-compute type provider map: files that export types used by others\n const typeProviderUsage = computeTypeProviderUsage(files, graph);\n\n for (const file of files) {\n const factors = computeRiskFactors(file, graph, typeProviderUsage, weights);\n file.riskFactors = factors;\n file.riskScore = computeWeightedScore(factors);\n file.exclusionImpact = scoreToImpact(file.riskScore);\n }\n}\n\nexport function scoreFile(\n file: AnalyzedFile,\n graph: ProjectGraph,\n weights: RiskWeights = DEFAULT_RISK_WEIGHTS,\n): number {\n const typeProviderUsage = computeTypeProviderUsage([file], graph);\n const factors = computeRiskFactors(file, graph, typeProviderUsage, weights);\n file.riskFactors = factors;\n file.riskScore = computeWeightedScore(factors);\n file.exclusionImpact = scoreToImpact(file.riskScore);\n return file.riskScore;\n}\n\n// ===== FACTOR COMPUTATION =====\n\nfunction computeRiskFactors(\n file: AnalyzedFile,\n graph: ProjectGraph,\n typeProviderUsage: Map<string, number>,\n weights: RiskWeights,\n): RiskFactor[] {\n const factors: RiskFactor[] = [];\n\n // 1. Hub factor — how many files depend on this file\n factors.push(computeHubFactor(file, weights.hub));\n\n // 2. Type provider factor — exports types used by other files\n factors.push(computeTypeProviderFactor(file, typeProviderUsage, weights.typeProvider));\n\n // 3. Complexity factor — cyclomatic complexity\n factors.push(computeComplexityFactor(file, weights.complexity));\n\n // 4. Recency factor — how recently modified\n factors.push(computeRecencyFactor(file, weights.recency));\n\n // 5. Config factor — is it a config or entry point\n factors.push(computeConfigFactor(file, weights.config));\n\n // 6. Churn factor — based on complexity as proxy (git integration deferred)\n factors.push(computeChurnFactor(file, weights.churn));\n\n return factors;\n}\n\nfunction computeHubFactor(file: AnalyzedFile, weight: number): RiskFactor {\n const dependents = file.importedBy.length;\n\n // Logarithmic scaling: score = min(100, 100 × log₂(1 + dependents) / log₂(1 + K))\n // K=12 means 12 dependents → score 100. Based on information theory:\n // each doubling of dependents adds equal marginal risk.\n const K = 12;\n const score = dependents === 0\n ? 0\n : Math.min(100, Math.round(100 * Math.log2(1 + dependents) / Math.log2(1 + K)));\n\n const detail = dependents === 0\n ? 'No dependents'\n : `Hub: ${dependents} file(s) depend on this (score ${score}/100)`;\n\n return { type: 'hub', score, weight, detail };\n}\n\nfunction computeTypeProviderFactor(\n file: AnalyzedFile,\n usage: Map<string, number>,\n weight: number,\n): RiskFactor {\n const isTypeFile = file.kind === 'type';\n const consumers = usage.get(file.relativePath) ?? 0;\n\n let score: number;\n let detail: string;\n\n if (isTypeFile && consumers >= 4) {\n score = 100;\n detail = `Type provider: used by ${consumers} files (critical type source)`;\n } else if (isTypeFile && consumers >= 1) {\n score = 50;\n detail = `Type provider: used by ${consumers} files`;\n } else if (isTypeFile) {\n score = 30;\n detail = 'Type file (no detected consumers)';\n } else {\n score = 0;\n detail = 'Not a type provider';\n }\n\n return { type: 'type-provider', score, weight, detail };\n}\n\nfunction computeComplexityFactor(file: AnalyzedFile, weight: number): RiskFactor {\n const c = file.complexity;\n\n // Logarithmic scaling: score = min(100, 100 × ln(1 + c) / ln(1 + K))\n // K=30 means complexity 30 → score 100. ln provides diminishing returns\n // for very complex files (consistent with McCabe 1976 thresholds).\n const K = 30;\n const score = Math.min(100, Math.round(100 * Math.log(1 + c) / Math.log(1 + K)));\n\n const detail = c >= 30\n ? `Very high complexity: ${c} (AI needs full context)`\n : c >= 10\n ? `High complexity: ${c}`\n : `Complexity: ${c}`;\n\n return { type: 'complexity', score, weight, detail };\n}\n\nfunction computeRecencyFactor(file: AnalyzedFile, weight: number): RiskFactor {\n const now = Date.now();\n const modified = new Date(file.lastModified).getTime();\n const daysAgo = (now - modified) / (1000 * 60 * 60 * 24);\n\n // Exponential decay with half-life of 7 days.\n // score = 100 × 2^(-daysAgo / halfLife)\n // This is the standard temporal decay model used in information retrieval\n // (Lv & Zhai, 2011 — \"Adaptive Relevance Feedback\").\n const HALF_LIFE = 7;\n const score = Math.round(100 * Math.pow(2, -daysAgo / HALF_LIFE));\n\n const detail = daysAgo <= 1\n ? 'Modified today'\n : `Modified ${Math.round(daysAgo)} days ago (decay score ${score})`;\n\n return { type: 'recency', score, weight, detail };\n}\n\nfunction computeConfigFactor(file: AnalyzedFile, weight: number): RiskFactor {\n let score: number;\n let detail: string;\n\n if (file.kind === 'entry') {\n score = 90;\n detail = 'Entry point — critical for understanding app structure';\n } else if (file.kind === 'config') {\n score = 80;\n detail = 'Configuration file — affects runtime behavior';\n } else {\n score = 0;\n detail = 'Regular source file';\n }\n\n return { type: 'config', score, weight, detail };\n}\n\nfunction computeChurnFactor(file: AnalyzedFile, weight: number): RiskFactor {\n // PROXY: Without git integration, approximate churn as geometric mean of\n // complexity signal and recency signal. This avoids double-weighting\n // (since complexity and recency have their own factors) by using the\n // *interaction* term only — high churn requires BOTH high complexity AND\n // recent modification simultaneously.\n //\n // TODO: Replace with real git churn (commit count in last 30 days) when\n // git integration is added. Proxy weight is intentionally low (5%).\n const complexitySignal = Math.min(file.complexity / 20, 1);\n const now = Date.now();\n const daysAgo = (now - new Date(file.lastModified).getTime()) / (1000 * 60 * 60 * 24);\n const recencySignal = Math.pow(2, -daysAgo / 7); // same half-life as recency factor\n\n // Geometric mean ensures both signals must be high for a high score\n const score = Math.round(Math.sqrt(complexitySignal * recencySignal) * 100);\n const detail = score >= 50\n ? 'Likely under active development (complex + recent)'\n : score >= 20\n ? 'Some recent activity'\n : 'Stable — low churn (proxy estimate)';\n\n return { type: 'churn', score, weight, detail };\n}\n\n// ===== HELPERS =====\n\nfunction computeWeightedScore(factors: RiskFactor[]): number {\n let totalWeightedScore = 0;\n let totalWeight = 0;\n\n for (const factor of factors) {\n totalWeightedScore += factor.score * factor.weight;\n totalWeight += factor.weight;\n }\n\n if (totalWeight === 0) return 0;\n return Math.round(totalWeightedScore / totalWeight);\n}\n\nfunction scoreToImpact(score: number): ExclusionImpact {\n if (score >= 80) return 'critical';\n if (score >= 60) return 'high';\n if (score >= 30) return 'medium';\n if (score > 0) return 'low';\n return 'none';\n}\n\nfunction computeTypeProviderUsage(\n files: AnalyzedFile[],\n graph: ProjectGraph,\n): Map<string, number> {\n const usage = new Map<string, number>();\n\n // Count how many files import each type file\n const typeFiles = new Set(\n files.filter((f) => f.kind === 'type').map((f) => f.relativePath),\n );\n\n for (const edge of graph.edges) {\n if (typeFiles.has(edge.to)) {\n usage.set(edge.to, (usage.get(edge.to) ?? 0) + 1);\n }\n }\n\n return usage;\n}\n","import type { GraphEdge } from '../types/engine.js';\n\n// ===== SHARED GRAPH UTILITIES =====\n\nexport interface AdjacencyList {\n forward: Map<string, string[]>; // file → files it imports\n reverse: Map<string, string[]>; // file → files that import it\n}\n\nexport function buildAdjacencyList(edges: GraphEdge[]): AdjacencyList {\n const forward = new Map<string, string[]>();\n const reverse = new Map<string, string[]>();\n\n for (const edge of edges) {\n if (!forward.has(edge.from)) forward.set(edge.from, []);\n forward.get(edge.from)!.push(edge.to);\n\n if (!reverse.has(edge.to)) reverse.set(edge.to, []);\n reverse.get(edge.to)!.push(edge.from);\n }\n\n return { forward, reverse };\n}\n\nexport function bfsBidirectional(\n seeds: string[],\n adj: AdjacencyList,\n depth: number,\n): Set<string> {\n const result = new Set(seeds);\n let frontier = [...seeds];\n const visited = new Set<string>();\n\n for (let d = 0; d < depth; d++) {\n const nextFrontier: string[] = [];\n\n for (const node of frontier) {\n if (visited.has(node)) continue;\n visited.add(node);\n\n // Forward neighbors (imports)\n const fwd = adj.forward.get(node);\n if (fwd) {\n for (const neighbor of fwd) {\n if (!visited.has(neighbor)) {\n result.add(neighbor);\n nextFrontier.push(neighbor);\n }\n }\n }\n\n // Reverse neighbors (imported by)\n const rev = adj.reverse.get(node);\n if (rev) {\n for (const neighbor of rev) {\n if (!visited.has(neighbor)) {\n result.add(neighbor);\n nextFrontier.push(neighbor);\n }\n }\n }\n }\n\n frontier = nextFrontier;\n }\n\n return result;\n}\n\nexport function matchGlob(path: string, pattern: string): boolean {\n const regexStr = pattern\n .replace(/\\./g, '\\\\.')\n .replace(/\\*\\*/g, '§§')\n .replace(/\\*/g, '[^/]*')\n .replace(/§§/g, '.*')\n .replace(/\\?/g, '.');\n\n try {\n return new RegExp(`^${regexStr}$`).test(path);\n } catch {\n return false;\n }\n}\n","import { readFile, writeFile, mkdir } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { parse as parseYAML, stringify as stringifyYAML } from 'yaml';\nimport type { CTOConfig } from '../types/config.js';\nimport { DEFAULT_CONFIG } from '../types/config.js';\n\n// ===== CONFIG FILE SUPPORT =====\n//\n// Loads and saves .cto/config.yml per the ARCHITECTURE.md spec.\n// Deep-merges user config on top of DEFAULT_CONFIG so partial\n// configs work correctly.\n\nconst CONFIG_DIR = '.cto';\nconst CONFIG_FILE = 'config.yml';\nconst POLICY_FILE = 'policy.yml';\n\nexport function getConfigPath(projectPath: string): string {\n return join(projectPath, CONFIG_DIR, CONFIG_FILE);\n}\n\nexport function getPolicyPath(projectPath: string): string {\n return join(projectPath, CONFIG_DIR, POLICY_FILE);\n}\n\nexport function getCTODir(projectPath: string): string {\n return join(projectPath, CONFIG_DIR);\n}\n\nexport async function loadConfig(projectPath: string): Promise<CTOConfig> {\n const configPath = getConfigPath(projectPath);\n\n if (!existsSync(configPath)) {\n return { ...DEFAULT_CONFIG };\n }\n\n try {\n const raw = await readFile(configPath, 'utf-8');\n const userConfig = parseYAML(raw) as Partial<CTOConfig>;\n return deepMerge(DEFAULT_CONFIG, userConfig) as CTOConfig;\n } catch {\n return { ...DEFAULT_CONFIG };\n }\n}\n\nexport async function saveConfig(\n projectPath: string,\n config: CTOConfig,\n): Promise<string> {\n const ctoDir = getCTODir(projectPath);\n await mkdir(ctoDir, { recursive: true });\n\n const configPath = getConfigPath(projectPath);\n const yamlContent = stringifyYAML(config, { indent: 2 });\n await writeFile(configPath, yamlContent, 'utf-8');\n return configPath;\n}\n\nexport async function initProjectConfig(projectPath: string): Promise<{\n configPath: string;\n policyPath: string;\n created: string[];\n}> {\n const ctoDir = getCTODir(projectPath);\n await mkdir(join(ctoDir, 'snapshots'), { recursive: true });\n\n const created: string[] = [];\n\n // Create config.yml if it doesn't exist\n const configPath = getConfigPath(projectPath);\n if (!existsSync(configPath)) {\n await saveConfig(projectPath, DEFAULT_CONFIG);\n created.push(configPath);\n }\n\n // Create policy.yml if it doesn't exist\n const policyPath = getPolicyPath(projectPath);\n if (!existsSync(policyPath)) {\n const defaultPolicy = {\n version: '1.0',\n name: 'default',\n rules: [\n {\n id: 'types-always',\n type: 'include-always',\n pattern: '**/types/**',\n reason: 'Type definitions provide essential context',\n enabled: true,\n },\n {\n id: 'no-env',\n type: 'exclude-always',\n pattern: '**/*.env*',\n reason: 'Environment files must never be sent to AI',\n enabled: true,\n },\n {\n id: 'no-secrets',\n type: 'secret-block',\n reason: 'Files with detected secrets are blocked',\n enabled: true,\n },\n {\n id: 'test-budget',\n type: 'budget-limit',\n category: 'test',\n threshold: 20,\n reason: 'Test files should not exceed 20% of budget',\n enabled: true,\n },\n {\n id: 'min-coverage',\n type: 'coverage-minimum',\n threshold: 70,\n reason: 'Warn if context coverage drops below 70%',\n enabled: true,\n },\n ],\n };\n const yamlContent = stringifyYAML(defaultPolicy, { indent: 2 });\n await writeFile(policyPath, yamlContent, 'utf-8');\n created.push(policyPath);\n }\n\n return { configPath, policyPath, created };\n}\n\nexport async function loadPolicyFromYAML(projectPath: string): Promise<import('../types/govern.js').PolicySet | null> {\n const policyPath = getPolicyPath(projectPath);\n if (!existsSync(policyPath)) return null;\n\n try {\n const raw = await readFile(policyPath, 'utf-8');\n return parseYAML(raw) as import('../types/govern.js').PolicySet;\n } catch {\n return null;\n }\n}\n\n// ===== HELPERS =====\n\nfunction deepMerge(target: Record<string, any>, source: Record<string, any>): Record<string, any> {\n const result = { ...target };\n\n for (const key of Object.keys(source)) {\n if (\n source[key] !== null &&\n typeof source[key] === 'object' &&\n !Array.isArray(source[key]) &&\n typeof target[key] === 'object' &&\n !Array.isArray(target[key])\n ) {\n result[key] = deepMerge(target[key], source[key]);\n } else if (source[key] !== undefined) {\n result[key] = source[key];\n }\n }\n\n return result;\n}\n","import { createHash } from 'node:crypto';\nimport { readdir, stat } from 'node:fs/promises';\nimport { join, extname, relative, resolve } from 'node:path';\nimport type { ProjectAnalysis } from '../types/engine.js';\nimport type { CTOConfig } from '../types/config.js';\nimport { DEFAULT_CONFIG } from '../types/config.js';\nimport { analyzeProject } from './analyzer.js';\n\n// ===== Analysis Cache =====\n//\n// Problem: analyzeProject() is expensive (file walk + AST parse + token count + graph build).\n// MCP tools and CLI commands call it on every invocation.\n//\n// Solution: Two-level cache with lightweight fingerprint invalidation.\n// 1. Compute a fast fingerprint: hash of (sorted file paths + mtimes)\n// Cost: O(n) readdir + stat, no file reads, no AST, no token counting\n// 2. If fingerprint matches cached entry → return cached analysis (instant)\n// 3. If fingerprint differs → full re-analysis, update cache\n//\n// TTL: Safety net. Even if fingerprint matches, expire after maxAgeMs.\n//\n// Reference: Content-addressable caching (Git object model principle)\n\ninterface CacheEntry {\n analysis: ProjectAnalysis;\n fingerprint: string;\n createdAt: number;\n hits: number;\n}\n\ninterface CacheOptions {\n maxAgeMs: number;\n maxEntries: number;\n enabled: boolean;\n}\n\nconst DEFAULT_CACHE_OPTIONS: CacheOptions = {\n maxAgeMs: 5 * 60 * 1000, // 5 minutes\n maxEntries: 10,\n enabled: true,\n};\n\n// In-memory LRU-ish cache\nconst cache = new Map<string, CacheEntry>();\nlet cacheOptions: CacheOptions = { ...DEFAULT_CACHE_OPTIONS };\n\n// ===== FINGERPRINT =====\n\n// Fast fingerprint: walk directory, collect paths + mtimes, hash them.\n// ~10-100x faster than full analysis (no file reads, no AST, no tokenization).\nasync function computeFingerprint(\n rootPath: string,\n config: CTOConfig = DEFAULT_CONFIG,\n): Promise<string> {\n const entries: string[] = [];\n const allExtensions = new Set([\n ...config.analysis.extensions.code,\n ...config.analysis.extensions.config,\n ...config.analysis.extensions.docs,\n ]);\n const ignoreDirSet = new Set(config.analysis.ignore.dirs);\n\n async function walk(dir: string, depth: number): Promise<void> {\n if (depth > config.analysis.maxDepth) return;\n\n let dirEntries;\n try {\n dirEntries = await readdir(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n const promises: Promise<void>[] = [];\n\n for (const entry of dirEntries) {\n const fullPath = join(dir, entry.name);\n\n if (entry.isDirectory()) {\n if (!ignoreDirSet.has(entry.name) && !entry.name.startsWith('.')) {\n promises.push(walk(fullPath, depth + 1));\n }\n } else if (entry.isFile()) {\n const ext = extname(entry.name).slice(1).toLowerCase();\n if (ext && allExtensions.has(ext)) {\n promises.push(\n (async () => {\n try {\n const s = await stat(fullPath);\n const rel = relative(rootPath, fullPath);\n // Include path + mtime + size for change detection\n entries.push(`${rel}:${s.mtimeMs.toFixed(0)}:${s.size}`);\n } catch {\n // skip inaccessible files\n }\n })(),\n );\n }\n }\n }\n\n await Promise.all(promises);\n }\n\n await walk(rootPath, 0);\n\n // Sort for determinism\n entries.sort();\n return createHash('sha256').update(entries.join('|')).digest('hex').substring(0, 16);\n}\n\n// ===== PUBLIC API =====\n\n/**\n * Get a project analysis, using cache when possible.\n *\n * Cache hit: ~1-5ms (fingerprint check only)\n * Cache miss: full analyzeProject() + cache update\n */\nexport async function getCachedAnalysis(\n projectPath: string,\n config?: Partial<CTOConfig>,\n): Promise<ProjectAnalysis> {\n const absPath = resolve(projectPath);\n\n if (!cacheOptions.enabled) {\n return analyzeProject(absPath, config);\n }\n\n const existing = cache.get(absPath);\n\n // Check TTL first (cheap)\n if (existing) {\n const age = Date.now() - existing.createdAt;\n if (age > cacheOptions.maxAgeMs) {\n cache.delete(absPath);\n }\n }\n\n // Compute fingerprint\n const mergedConfig = config\n ? { ...DEFAULT_CONFIG, ...config } as CTOConfig\n : DEFAULT_CONFIG;\n const fingerprint = await computeFingerprint(absPath, mergedConfig);\n\n // Cache hit: fingerprint matches\n const cached = cache.get(absPath);\n if (cached && cached.fingerprint === fingerprint) {\n cached.hits++;\n return cached.analysis;\n }\n\n // Cache miss: full analysis\n const analysis = await analyzeProject(absPath, config);\n\n // Evict oldest entry if at capacity\n if (cache.size >= cacheOptions.maxEntries) {\n const oldest = [...cache.entries()].sort(\n (a, b) => a[1].createdAt - b[1].createdAt,\n )[0];\n if (oldest) cache.delete(oldest[0]);\n }\n\n cache.set(absPath, {\n analysis,\n fingerprint,\n createdAt: Date.now(),\n hits: 0,\n });\n\n return analysis;\n}\n\n/**\n * Invalidate cache for a specific project (e.g., after a known file change).\n */\nexport function invalidateCache(projectPath?: string): void {\n if (projectPath) {\n cache.delete(resolve(projectPath));\n } else {\n cache.clear();\n }\n}\n\n/**\n * Get cache statistics for debugging/monitoring.\n */\nexport function getCacheStats(): {\n entries: number;\n totalHits: number;\n projects: { path: string; hits: number; ageMs: number }[];\n} {\n const now = Date.now();\n const projects = [...cache.entries()].map(([path, entry]) => ({\n path,\n hits: entry.hits,\n ageMs: now - entry.createdAt,\n }));\n\n return {\n entries: cache.size,\n totalHits: projects.reduce((s, p) => s + p.hits, 0),\n projects,\n };\n}\n\n/**\n * Configure cache behavior.\n */\nexport function configureCache(options: Partial<CacheOptions>): void {\n cacheOptions = { ...cacheOptions, ...options };\n if (!cacheOptions.enabled) {\n cache.clear();\n }\n}\n","import chokidar from 'chokidar';\nimport { resolve } from 'node:path';\nimport { EventEmitter } from 'node:events';\nimport type { CTOConfig } from '../types/config.js';\nimport { DEFAULT_CONFIG } from '../types/config.js';\nimport { invalidateCache } from './cache.js';\n\n// ===== Project Watcher =====\n//\n// Watches a project directory for file changes and invalidates the analysis cache.\n// Designed for long-running processes (MCP server, CLI watch mode).\n//\n// Key properties:\n// - Debounced: coalesces rapid changes into one cache invalidation\n// - Lightweight: no re-analysis on change, just cache invalidation\n// - Auto-managed: watchProject() returns a handle to stop watching\n// - Observable: emits events for logging/UI\n\nexport interface WatcherOptions {\n debounceMs?: number;\n config?: Partial<CTOConfig>;\n}\n\nexport interface FileChangeEvent {\n type: 'add' | 'change' | 'unlink';\n path: string;\n timestamp: Date;\n}\n\nexport class ProjectWatcher extends EventEmitter {\n private watcher: chokidar.FSWatcher | null = null;\n private projectPath: string;\n private debounceMs: number;\n private config: CTOConfig;\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private pendingChanges: FileChangeEvent[] = [];\n private running = false;\n\n constructor(projectPath: string, options: WatcherOptions = {}) {\n super();\n this.projectPath = resolve(projectPath);\n this.debounceMs = options.debounceMs ?? 500;\n this.config = { ...DEFAULT_CONFIG, ...options.config } as CTOConfig;\n }\n\n async start(): Promise<void> {\n if (this.running) return;\n\n const allExtensions = [\n ...this.config.analysis.extensions.code,\n ...this.config.analysis.extensions.config,\n ...this.config.analysis.extensions.docs,\n ];\n\n const globs = allExtensions.map((ext) => `**/*.${ext}`);\n\n this.watcher = chokidar.watch(globs, {\n cwd: this.projectPath,\n ignored: [\n ...this.config.analysis.ignore.dirs.map((d) => `**/${d}/**`),\n ...this.config.analysis.ignore.patterns,\n ],\n persistent: true,\n ignoreInitial: true,\n awaitWriteFinish: {\n stabilityThreshold: 200,\n pollInterval: 50,\n },\n });\n\n this.watcher.on('add', (path) => this.handleEvent('add', path));\n this.watcher.on('change', (path) => this.handleEvent('change', path));\n this.watcher.on('unlink', (path) => this.handleEvent('unlink', path));\n this.watcher.on('error', (error) => this.emit('error', error));\n\n this.running = true;\n this.emit('started', { projectPath: this.projectPath });\n }\n\n async stop(): Promise<void> {\n if (!this.running) return;\n\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n\n // Flush any pending changes\n if (this.pendingChanges.length > 0) {\n this.flush();\n }\n\n if (this.watcher) {\n await this.watcher.close();\n this.watcher = null;\n }\n\n this.running = false;\n this.emit('stopped', { projectPath: this.projectPath });\n }\n\n isRunning(): boolean {\n return this.running;\n }\n\n getProjectPath(): string {\n return this.projectPath;\n }\n\n private handleEvent(type: FileChangeEvent['type'], filePath: string): void {\n const event: FileChangeEvent = {\n type,\n path: filePath,\n timestamp: new Date(),\n };\n\n this.pendingChanges.push(event);\n this.emit('fileChange', event);\n\n // Debounce: coalesce rapid changes into one cache invalidation\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n }\n\n this.debounceTimer = setTimeout(() => {\n this.flush();\n }, this.debounceMs);\n }\n\n private flush(): void {\n const changes = [...this.pendingChanges];\n this.pendingChanges = [];\n\n if (changes.length === 0) return;\n\n // Invalidate the cache for this project\n invalidateCache(this.projectPath);\n\n this.emit('cacheInvalidated', {\n projectPath: this.projectPath,\n changedFiles: changes.length,\n changes,\n });\n }\n}\n\n// ===== Managed Watchers =====\n//\n// For long-running processes (MCP server): auto-watch projects,\n// one watcher per project, with cleanup on shutdown.\n\nconst activeWatchers = new Map<string, ProjectWatcher>();\n\n/**\n * Start watching a project. Returns the watcher instance.\n * If already watching, returns the existing watcher.\n */\nexport async function watchProject(\n projectPath: string,\n options?: WatcherOptions,\n): Promise<ProjectWatcher> {\n const absPath = resolve(projectPath);\n\n const existing = activeWatchers.get(absPath);\n if (existing && existing.isRunning()) {\n return existing;\n }\n\n const watcher = new ProjectWatcher(absPath, options);\n await watcher.start();\n activeWatchers.set(absPath, watcher);\n\n return watcher;\n}\n\n/**\n * Stop watching a specific project.\n */\nexport async function unwatchProject(projectPath: string): Promise<void> {\n const absPath = resolve(projectPath);\n const watcher = activeWatchers.get(absPath);\n if (watcher) {\n await watcher.stop();\n activeWatchers.delete(absPath);\n }\n}\n\n/**\n * Stop all active watchers. Call on process shutdown.\n */\nexport async function unwatchAll(): Promise<void> {\n const stopPromises = [...activeWatchers.values()].map((w) => w.stop());\n await Promise.all(stopPromises);\n activeWatchers.clear();\n}\n\n/**\n * Get all actively watched projects.\n */\nexport function getActiveWatchers(): { path: string; running: boolean }[] {\n return [...activeWatchers.entries()].map(([path, w]) => ({\n path,\n running: w.isRunning(),\n }));\n}\n","import { resolve } from 'node:path';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport type { ProjectAnalysis, AnalyzedFile } from '../types/engine.js';\nimport { buildAdjacencyList, bfsBidirectional } from './graph-utils.js';\n\n// ===== PR Context — Git-diff Aware Context Selection =====\n//\n// When the task is \"review this PR\", sending the entire project is wasteful.\n// This module:\n// 1. Extracts changed files from git diff (branch comparison or working dir)\n// 2. Expands to transitive dependencies using BFS on the adjacency list\n// 3. Prioritizes by risk score (high-risk changed files first)\n// 4. Returns a structured PR context with change categorization\n//\n// Complexity: O(|changed| × depth) for BFS expansion\n\nconst exec = promisify(execFile);\n\nasync function git(args: string[], cwd: string): Promise<string> {\n try {\n const { stdout } = await exec('git', args, { cwd, maxBuffer: 10 * 1024 * 1024 });\n return stdout.trim();\n } catch {\n return '';\n }\n}\n\n// ===== TYPES =====\n\nexport type ChangeType = 'added' | 'modified' | 'deleted' | 'renamed';\n\nexport interface ChangedFile {\n relativePath: string;\n changeType: ChangeType;\n linesAdded: number;\n linesRemoved: number;\n}\n\nexport interface PRContextResult {\n baseBranch: string;\n currentBranch: string;\n isGitRepo: boolean;\n\n changedFiles: ChangedFile[];\n dependencyFiles: string[];\n allRelevantFiles: AnalyzedFile[];\n\n totalChangedTokens: number;\n totalContextTokens: number;\n\n riskSummary: {\n critical: number;\n high: number;\n medium: number;\n low: number;\n maxRiskFile: string;\n maxRiskScore: number;\n };\n\n renderedSummary: string;\n}\n\nexport interface PRContextOptions {\n baseBranch?: string;\n depth?: number;\n includeTests?: boolean;\n}\n\n// ===== GIT OPERATIONS =====\n\nasync function isGitRepo(projectPath: string): Promise<boolean> {\n const result = await git(['rev-parse', '--is-inside-work-tree'], projectPath);\n return result === 'true';\n}\n\nasync function getCurrentBranch(projectPath: string): Promise<string> {\n return git(['rev-parse', '--abbrev-ref', 'HEAD'], projectPath);\n}\n\nasync function getChangedFilesFromDiff(\n projectPath: string,\n baseBranch?: string,\n): Promise<ChangedFile[]> {\n const results = new Map<string, ChangedFile>();\n\n // Working directory changes (unstaged)\n const workingDiff = await git(['diff', '--numstat', 'HEAD'], projectPath);\n parseDiffNumstat(workingDiff, results, 'modified');\n\n // Staged changes\n const stagedDiff = await git(['diff', '--numstat', '--cached'], projectPath);\n parseDiffNumstat(stagedDiff, results, 'modified');\n\n // Untracked files\n const untracked = await git(['ls-files', '--others', '--exclude-standard'], projectPath);\n for (const line of untracked.split('\\n')) {\n const f = line.trim();\n if (f && !results.has(f)) {\n results.set(f, { relativePath: f, changeType: 'added', linesAdded: 0, linesRemoved: 0 });\n }\n }\n\n // Branch comparison (if baseBranch provided)\n if (baseBranch) {\n // Check if base branch exists\n const branchExists = await git(['rev-parse', '--verify', baseBranch], projectPath);\n if (branchExists) {\n const branchDiff = await git(['diff', '--numstat', `${baseBranch}...HEAD`], projectPath);\n parseDiffNumstat(branchDiff, results, 'modified');\n\n // Detect newly added files (in HEAD but not in base)\n const nameStatus = await git(['diff', '--name-status', `${baseBranch}...HEAD`], projectPath);\n for (const line of nameStatus.split('\\n')) {\n const parts = line.trim().split('\\t');\n if (parts.length >= 2) {\n const status = parts[0];\n const filePath = parts[parts.length - 1];\n if (results.has(filePath)) {\n const existing = results.get(filePath)!;\n if (status === 'A') existing.changeType = 'added';\n else if (status === 'D') existing.changeType = 'deleted';\n else if (status.startsWith('R')) existing.changeType = 'renamed';\n }\n }\n }\n }\n }\n\n return [...results.values()];\n}\n\nfunction parseDiffNumstat(\n output: string,\n results: Map<string, ChangedFile>,\n defaultType: ChangeType,\n): void {\n for (const line of output.split('\\n')) {\n const parts = line.trim().split('\\t');\n if (parts.length < 3) continue;\n\n const added = parts[0] === '-' ? 0 : parseInt(parts[0], 10) || 0;\n const removed = parts[1] === '-' ? 0 : parseInt(parts[1], 10) || 0;\n const filePath = parts[2];\n\n if (!filePath) continue;\n\n const existing = results.get(filePath);\n if (existing) {\n existing.linesAdded = Math.max(existing.linesAdded, added);\n existing.linesRemoved = Math.max(existing.linesRemoved, removed);\n } else {\n results.set(filePath, {\n relativePath: filePath,\n changeType: defaultType,\n linesAdded: added,\n linesRemoved: removed,\n });\n }\n }\n}\n\n// ===== MAIN API =====\n\n/**\n * Generate PR-focused context by analyzing git changes and expanding dependencies.\n *\n * @param analysis - Project analysis (from analyzeProject or getCachedAnalysis)\n * @param options - PR context options (baseBranch, depth, includeTests)\n * @returns Structured PR context with changed files, dependencies, risk summary\n */\nexport async function generatePRContext(\n analysis: ProjectAnalysis,\n options: PRContextOptions = {},\n): Promise<PRContextResult> {\n const projectPath = resolve(analysis.projectPath);\n const baseBranch = options.baseBranch ?? 'main';\n const depth = options.depth ?? 2;\n const includeTests = options.includeTests ?? false;\n\n // Check git repo\n const gitRepo = await isGitRepo(projectPath);\n if (!gitRepo) {\n return emptyResult(baseBranch);\n }\n\n const currentBranch = await getCurrentBranch(projectPath);\n\n // 1. Get changed files from git\n const changedFiles = await getChangedFilesFromDiff(projectPath, baseBranch);\n\n if (changedFiles.length === 0) {\n return {\n ...emptyResult(baseBranch),\n currentBranch,\n isGitRepo: true,\n renderedSummary: '# PR Context\\n\\nNo changed files detected.',\n };\n }\n\n // 2. Filter to files that exist in our analysis\n const analysisFileSet = new Set(analysis.files.map((f) => f.relativePath));\n const validChangedPaths = changedFiles\n .filter((c) => c.changeType !== 'deleted' && analysisFileSet.has(c.relativePath))\n .map((c) => c.relativePath);\n\n // 3. Expand dependencies using BFS on adjacency list\n const adj = buildAdjacencyList(analysis.graph.edges);\n const expanded = bfsBidirectional(validChangedPaths, adj, depth);\n\n // Separate changed files from dependency-only files\n const changedSet = new Set(validChangedPaths);\n const dependencyFiles = [...expanded].filter((f) => !changedSet.has(f));\n\n // 4. Filter tests if not included\n const allRelevantPaths = new Set(expanded);\n if (!includeTests) {\n for (const path of allRelevantPaths) {\n const file = analysis.files.find((f) => f.relativePath === path);\n if (file && file.kind === 'test') {\n // Keep if it was directly changed, remove if it's a dependency\n if (!changedSet.has(path)) {\n allRelevantPaths.delete(path);\n }\n }\n }\n }\n\n // 5. Collect AnalyzedFile objects, sorted by risk score (descending)\n const allRelevantFiles = analysis.files\n .filter((f) => allRelevantPaths.has(f.relativePath))\n .sort((a, b) => b.riskScore - a.riskScore);\n\n // 6. Compute token totals\n const changedAnalyzed = allRelevantFiles.filter((f) => changedSet.has(f.relativePath));\n const totalChangedTokens = changedAnalyzed.reduce((s, f) => s + f.tokens, 0);\n const totalContextTokens = allRelevantFiles.reduce((s, f) => s + f.tokens, 0);\n\n // 7. Risk summary\n const riskSummary = {\n critical: allRelevantFiles.filter((f) => f.riskScore >= 80).length,\n high: allRelevantFiles.filter((f) => f.riskScore >= 60 && f.riskScore < 80).length,\n medium: allRelevantFiles.filter((f) => f.riskScore >= 30 && f.riskScore < 60).length,\n low: allRelevantFiles.filter((f) => f.riskScore < 30).length,\n maxRiskFile: allRelevantFiles[0]?.relativePath ?? '',\n maxRiskScore: allRelevantFiles[0]?.riskScore ?? 0,\n };\n\n // 8. Render summary\n const renderedSummary = renderSummary(\n analysis,\n currentBranch,\n baseBranch,\n changedFiles,\n dependencyFiles,\n allRelevantFiles,\n changedSet,\n riskSummary,\n totalChangedTokens,\n totalContextTokens,\n );\n\n return {\n baseBranch,\n currentBranch,\n isGitRepo: true,\n changedFiles,\n dependencyFiles: dependencyFiles.filter((f) => allRelevantPaths.has(f)),\n allRelevantFiles,\n totalChangedTokens,\n totalContextTokens,\n riskSummary,\n renderedSummary,\n };\n}\n\n// ===== RENDERING =====\n\nfunction renderSummary(\n analysis: ProjectAnalysis,\n currentBranch: string,\n baseBranch: string,\n changedFiles: ChangedFile[],\n dependencyFiles: string[],\n allRelevant: AnalyzedFile[],\n changedSet: Set<string>,\n risk: PRContextResult['riskSummary'],\n changedTokens: number,\n totalTokens: number,\n): string {\n const lines: string[] = [];\n\n lines.push(`## PR Context — ${analysis.projectName}`);\n lines.push('');\n lines.push(`**Branch:** ${currentBranch} ← ${baseBranch}`);\n lines.push(`**Changed:** ${changedFiles.length} files | **Dependencies:** ${dependencyFiles.length} files`);\n lines.push(`**Tokens:** ~${Math.round(changedTokens / 1000)}K changed + ~${Math.round((totalTokens - changedTokens) / 1000)}K context = ~${Math.round(totalTokens / 1000)}K total`);\n lines.push('');\n\n // Risk banner\n if (risk.critical > 0 || risk.high > 0) {\n lines.push(`⚠️ **Risk:** ${risk.critical} critical + ${risk.high} high-risk files affected`);\n lines.push(`**Highest risk:** ${risk.maxRiskFile} (score: ${risk.maxRiskScore})`);\n lines.push('');\n }\n\n // Changed files\n lines.push('### Changed Files');\n lines.push('');\n\n const sortedChanged = changedFiles\n .filter((c) => c.changeType !== 'deleted')\n .sort((a, b) => {\n const fa = allRelevant.find((f) => f.relativePath === a.relativePath);\n const fb = allRelevant.find((f) => f.relativePath === b.relativePath);\n return (fb?.riskScore ?? 0) - (fa?.riskScore ?? 0);\n });\n\n for (const c of sortedChanged) {\n const file = allRelevant.find((f) => f.relativePath === c.relativePath);\n const risk = file ? ` risk:${file.riskScore}` : '';\n const delta = c.linesAdded || c.linesRemoved\n ? ` (+${c.linesAdded}/-${c.linesRemoved})`\n : '';\n const badge = c.changeType === 'added' ? ' 🆕' : c.changeType === 'renamed' ? ' 📝' : '';\n lines.push(`- \\`${c.relativePath}\\`${delta}${risk}${badge}`);\n }\n\n // Deleted files\n const deleted = changedFiles.filter((c) => c.changeType === 'deleted');\n if (deleted.length > 0) {\n lines.push('');\n lines.push(`**Deleted:** ${deleted.map((d) => `\\`${d.relativePath}\\``).join(', ')}`);\n }\n\n // Dependencies\n if (dependencyFiles.length > 0) {\n lines.push('');\n lines.push('### Dependencies (included for context)');\n lines.push('');\n\n const depWithInfo = dependencyFiles\n .map((d) => {\n const file = allRelevant.find((f) => f.relativePath === d);\n return { path: d, riskScore: file?.riskScore ?? 0, tokens: file?.tokens ?? 0 };\n })\n .sort((a, b) => b.riskScore - a.riskScore);\n\n for (const d of depWithInfo) {\n lines.push(`- \\`${d.path}\\` risk:${d.riskScore} ~${Math.round(d.tokens / 1000)}K tokens`);\n }\n }\n\n lines.push('');\n lines.push('### Review Focus');\n lines.push('');\n lines.push('- Review changed files for correctness, especially high-risk files');\n lines.push('- Dependencies are included for type/interface context — not for review');\n lines.push(`- ${analysis.totalFiles - allRelevant.length} files excluded (not affected by this change)`);\n\n return lines.join('\\n');\n}\n\n// ===== HELPERS =====\n\nfunction emptyResult(baseBranch: string): PRContextResult {\n return {\n baseBranch,\n currentBranch: '',\n isGitRepo: false,\n changedFiles: [],\n dependencyFiles: [],\n allRelevantFiles: [],\n totalChangedTokens: 0,\n totalContextTokens: 0,\n riskSummary: { critical: 0, high: 0, medium: 0, low: 0, maxRiskFile: '', maxRiskScore: 0 },\n renderedSummary: '# PR Context\\n\\nNot a git repository.',\n };\n}\n","import { createHash } from 'node:crypto';\nimport type {\n AnalyzedFile,\n ProjectAnalysis,\n ContextSelection,\n SelectedFile,\n SelectionDecision,\n PruneLevel,\n CoverageResult,\n} from '../types/engine.js';\nimport type { PolicySet, PolicyRule } from '../types/govern.js';\nimport { scanFileForSecrets } from '../govern/secrets.js';\nimport { pruneFile } from './pruner.js';\nimport { calculateCoverage } from './coverage.js';\nimport { getPruneLevelForRisk } from './budget.js';\nimport { buildAdjacencyList, bfsBidirectional, matchGlob } from './graph-utils.js';\n\n// ===== DETERMINISTIC CONTEXT SELECTION =====\n//\n// Given a task, analysis, budget, and policies → always returns the same file set.\n// No randomness, no heuristics that change over time.\n//\n// Algorithm:\n// 1. Identify target files from task description\n// 2. Expand via dependency graph (BFS, depth=2)\n// 3. Apply policies (include-always, exclude-always)\n// 4. Score & rank by riskScore\n// 5. Greedy allocation with cascading prune levels\n// 6. Validate policies\n// 7. Calculate coverage score\n// 8. Hash for reproducibility\n\nexport interface SelectionInput {\n task: string;\n analysis: ProjectAnalysis;\n budget: number;\n policies?: PolicySet;\n depth?: number;\n}\n\nexport async function selectContext(input: SelectionInput): Promise<ContextSelection> {\n const { task, analysis, budget, policies, depth = 2 } = input;\n const decisions: SelectionDecision[] = [];\n\n // 1. Identify target files from task description\n const targetPaths = identifyTargetFiles(task, analysis.files);\n if (targetPaths.length > 0) {\n decisions.push({\n file: targetPaths.join(', '),\n action: 'include-full',\n reason: `Target file(s) identified from task description`,\n });\n }\n\n // 2. Expand via dependency graph (O(V+E) using adjacency list)\n const adj = buildAdjacencyList(analysis.graph.edges);\n const expandedPaths = targetPaths.length > 0\n ? Array.from(bfsBidirectional(targetPaths, adj, depth))\n : [];\n const expansionCount = expandedPaths.length - targetPaths.length;\n if (expansionCount > 0) {\n decisions.push({\n file: `${expansionCount} dependencies`,\n action: 'include-full',\n reason: `Expanded ${targetPaths.length} target(s) to ${expandedPaths.length} files via dependency graph (depth ${depth})`,\n });\n }\n\n // 2b. Add type providers of expanded files as candidates.\n // This aligns with coverage.ts which counts type providers as \"relevant\".\n // Without this, coverage would flag missing critical type files that the\n // selector never considered as candidates — a consistency bug.\n const allFileMap = new Map(analysis.files.map((f) => [f.relativePath, f]));\n if (targetPaths.length > 0) {\n for (const path of expandedPaths) {\n const file = allFileMap.get(path);\n if (!file) continue;\n for (const imp of file.imports) {\n const impFile = allFileMap.get(imp);\n if (impFile && impFile.kind === 'type') {\n expandedPaths.push(imp);\n }\n }\n }\n }\n\n // 3. Apply policies\n const { mustInclude, mustExclude } = applyPolicies(analysis.files, policies);\n\n // Merge: targets + expanded + must-include → candidate set\n const candidateSet = new Set([...expandedPaths, ...mustInclude]);\n\n // If no targets identified, use all files (filtered by exclude)\n if (targetPaths.length === 0) {\n for (const f of analysis.files) {\n candidateSet.add(f.relativePath);\n }\n }\n\n // Remove must-exclude\n for (const ex of mustExclude) {\n candidateSet.delete(ex);\n decisions.push({\n file: ex,\n action: 'exclude',\n reason: 'Excluded by policy',\n });\n }\n\n // 3b. secret-block: scan candidate files for secrets and exclude them\n const hasSecretBlock = policies?.rules.some(\n (r) => r.type === 'secret-block' && r.enabled,\n );\n if (hasSecretBlock) {\n for (const path of Array.from(candidateSet)) {\n const file = allFileMap.get(path);\n if (!file) continue;\n const findings = await scanFileForSecrets(\n file.path,\n analysis.projectPath,\n );\n if (findings.length > 0) {\n candidateSet.delete(path);\n decisions.push({\n file: path,\n action: 'exclude',\n reason: `Blocked: ${findings.length} secret(s) detected (${findings.map((f) => f.type).join(', ')})`,\n });\n }\n }\n }\n\n // 4. Sort candidates by riskScore descending\n const candidates = Array.from(candidateSet)\n .map((p) => allFileMap.get(p))\n .filter((f): f is AnalyzedFile => f !== undefined)\n .sort((a, b) => {\n // Targets always first\n const aIsTarget = targetPaths.includes(a.relativePath) ? 0 : 1;\n const bIsTarget = targetPaths.includes(b.relativePath) ? 0 : 1;\n if (aIsTarget !== bIsTarget) return aIsTarget - bIsTarget;\n\n // Then must-include\n const aIsMust = mustInclude.has(a.relativePath) ? 0 : 1;\n const bIsMust = mustInclude.has(b.relativePath) ? 0 : 1;\n if (aIsMust !== bIsMust) return aIsMust - bIsMust;\n\n // Then by riskScore\n return b.riskScore - a.riskScore;\n });\n\n // 5. Greedy allocation with cascading prune levels\n const selectedFiles: SelectedFile[] = [];\n let usedTokens = 0;\n\n for (const file of candidates) {\n const isTarget = targetPaths.includes(file.relativePath);\n const isMustInclude = mustInclude.has(file.relativePath);\n const defaultLevel = isTarget ? 'full' : getPruneLevelForRisk(file.riskScore);\n const levels = getCascadeLevels(defaultLevel);\n\n let included = false;\n\n for (const level of levels) {\n if (level === 'excluded') break;\n\n let tokens: number;\n if (level === 'full') {\n tokens = file.tokens;\n } else {\n const pruned = await pruneFile(file, level);\n tokens = pruned.prunedTokens;\n }\n\n if (usedTokens + tokens <= budget) {\n usedTokens += tokens;\n selectedFiles.push({\n relativePath: file.relativePath,\n tokens,\n originalTokens: file.tokens,\n pruneLevel: level,\n riskScore: file.riskScore,\n reason: buildReason(file, level, isTarget, isMustInclude),\n });\n\n if (level !== defaultLevel) {\n decisions.push({\n file: file.relativePath,\n action: `include-${level}` as SelectionDecision['action'],\n reason: `Downgraded from ${defaultLevel} to ${level} due to budget constraint`,\n alternatives: `Would need ${file.tokens - tokens} more tokens for ${defaultLevel}`,\n });\n }\n\n included = true;\n break;\n }\n }\n\n if (!included) {\n decisions.push({\n file: file.relativePath,\n action: 'exclude',\n reason: `Budget exhausted (risk: ${file.riskScore}, needs ${file.tokens} tokens)`,\n });\n }\n }\n\n // 6. Calculate coverage\n const includedPaths = selectedFiles.map((f) => f.relativePath);\n const coverage = calculateCoverage(\n targetPaths,\n includedPaths,\n analysis.files,\n analysis.graph,\n depth,\n );\n\n // 7. Calculate overall risk of the selection (lower = better)\n const includedSet = new Set(includedPaths);\n const excludedFiles = analysis.files.filter(\n (f) => !includedSet.has(f.relativePath),\n );\n const excludedRisk = excludedFiles.length > 0\n ? Math.round(excludedFiles.reduce((s, f) => s + f.riskScore, 0) / excludedFiles.length)\n : 0;\n\n // 8. Hash for determinism\n const hashInput = selectedFiles\n .map((f) => `${f.relativePath}:${f.pruneLevel}`)\n .sort()\n .join('|') + `|budget:${budget}`;\n const hash = createHash('sha256').update(hashInput).digest('hex').substring(0, 16);\n\n return {\n files: selectedFiles,\n totalTokens: usedTokens,\n budget,\n usedPercent: budget > 0 ? Math.round((usedTokens / budget) * 100 * 10) / 10 : 0,\n coverage,\n riskScore: excludedRisk,\n deterministic: true,\n hash,\n decisions,\n };\n}\n\n// ===== TARGET IDENTIFICATION =====\n\nfunction identifyTargetFiles(task: string, files: AnalyzedFile[]): string[] {\n const targets: string[] = [];\n\n // Extract file paths mentioned in the task\n // Matches patterns like: src/foo/bar.ts, ./utils.js, components/Header.tsx\n const pathPattern = /(?:^|\\s|[\"'`])([.\\w/-]+\\.[a-zA-Z]{1,4})(?:\\s|$|[\"'`]|,|:)/g;\n let match: RegExpExecArray | null;\n\n while ((match = pathPattern.exec(task)) !== null) {\n const candidate = match[1];\n // Find matching file\n const found = files.find(\n (f) => f.relativePath === candidate || f.relativePath.endsWith(candidate),\n );\n if (found && !targets.includes(found.relativePath)) {\n targets.push(found.relativePath);\n }\n }\n\n return targets;\n}\n\n// ===== POLICY APPLICATION =====\n\nfunction applyPolicies(\n files: AnalyzedFile[],\n policies?: PolicySet,\n): { mustInclude: Set<string>; mustExclude: Set<string> } {\n const mustInclude = new Set<string>();\n const mustExclude = new Set<string>();\n\n if (!policies) return { mustInclude, mustExclude };\n\n for (const rule of policies.rules) {\n if (!rule.enabled) continue;\n\n if (rule.type === 'include-always' && rule.pattern) {\n for (const file of files) {\n if (matchGlob(file.relativePath, rule.pattern)) {\n mustInclude.add(file.relativePath);\n }\n }\n }\n\n if (rule.type === 'exclude-always' && rule.pattern) {\n for (const file of files) {\n if (matchGlob(file.relativePath, rule.pattern)) {\n mustExclude.add(file.relativePath);\n }\n }\n }\n\n // secret-block is handled separately in applyPoliciesAsync\n // because it requires file I/O (scanning file contents)\n }\n\n return { mustInclude, mustExclude };\n}\n\n// ===== HELPERS =====\n\nfunction getCascadeLevels(startLevel: PruneLevel): PruneLevel[] {\n const all: PruneLevel[] = ['full', 'signatures', 'skeleton', 'excluded'];\n const startIdx = all.indexOf(startLevel);\n return all.slice(startIdx);\n}\n\nfunction buildReason(\n file: AnalyzedFile,\n level: PruneLevel,\n isTarget: boolean,\n isMustInclude: boolean,\n): string {\n if (isTarget) return 'Target file';\n if (isMustInclude) return 'Required by policy';\n\n const impact = file.exclusionImpact;\n const levelStr = level === 'full' ? 'full content' : level;\n\n if (impact === 'critical') return `Critical dependency (risk ${file.riskScore}) — ${levelStr}`;\n if (impact === 'high') return `High-risk dependency (risk ${file.riskScore}) — ${levelStr}`;\n if (impact === 'medium') return `Medium relevance (risk ${file.riskScore}) — ${levelStr}`;\n return `Low relevance (risk ${file.riskScore}) — ${levelStr}`;\n}\n","import { readFile } from 'node:fs/promises';\nimport { resolve, relative } from 'node:path';\nimport type { SecretFinding, SecretType } from '../types/govern.js';\n\n// ===== SECRET DETECTION ENGINE =====\n\ninterface SecretPattern {\n type: SecretType;\n pattern: RegExp;\n severity: SecretFinding['severity'];\n description: string;\n}\n\nconst BUILTIN_PATTERNS: { type: SecretType; source: string; flags: string; severity: SecretFinding['severity']; description: string }[] = [\n // API Keys\n { type: 'api-key', source: '(?:api[_-]?key|apikey)\\\\s*[:=]\\\\s*[\\'\"]?([a-zA-Z0-9_\\\\-]{20,})[\\'\"]?', flags: 'gi', severity: 'critical', description: 'API Key' },\n { type: 'api-key', source: 'sk-[a-zA-Z0-9]{20,}', flags: 'g', severity: 'critical', description: 'OpenAI/Anthropic API Key' },\n { type: 'api-key', source: 'sk-ant-[a-zA-Z0-9\\\\-]{20,}', flags: 'g', severity: 'critical', description: 'Anthropic API Key' },\n\n // AWS\n { type: 'aws-key', source: 'AKIA[0-9A-Z]{16}', flags: 'g', severity: 'critical', description: 'AWS Access Key ID' },\n { type: 'aws-key', source: '(?:aws_secret_access_key|aws_secret)\\\\s*[:=]\\\\s*[\\'\"]?([a-zA-Z0-9/+=]{40})[\\'\"]?', flags: 'gi', severity: 'critical', description: 'AWS Secret Key' },\n\n // Private Keys\n { type: 'private-key', source: '-----BEGIN (?:RSA |EC |DSA )?PRIVATE KEY-----', flags: 'g', severity: 'critical', description: 'Private Key' },\n { type: 'private-key', source: '-----BEGIN OPENSSH PRIVATE KEY-----', flags: 'g', severity: 'critical', description: 'SSH Private Key' },\n\n // Passwords\n { type: 'password', source: '(?:password|passwd|pwd)\\\\s*[:=]\\\\s*[\\'\"]([^\\'\"]{8,})[\\'\"](?!\\\\s*\\\\{)', flags: 'gi', severity: 'high', description: 'Hardcoded Password' },\n { type: 'password', source: '(?:DB_PASSWORD|DATABASE_PASSWORD|MYSQL_PASSWORD|POSTGRES_PASSWORD)\\\\s*[:=]\\\\s*[\\'\"]?([^\\'\"{}\\\\s]{4,})[\\'\"]?', flags: 'gi', severity: 'high', description: 'Database Password' },\n\n // Tokens\n { type: 'token', source: '(?:bearer|token|auth_token|access_token|refresh_token)\\\\s*[:=]\\\\s*[\\'\"]([a-zA-Z0-9_\\\\-.]{20,})[\\'\"](?!\\\\s*\\\\{)', flags: 'gi', severity: 'high', description: 'Auth Token' },\n { type: 'token', source: 'ghp_[a-zA-Z0-9]{36}', flags: 'g', severity: 'critical', description: 'GitHub Personal Access Token' },\n { type: 'token', source: 'gho_[a-zA-Z0-9]{36}', flags: 'g', severity: 'critical', description: 'GitHub OAuth Token' },\n { type: 'token', source: 'glpat-[a-zA-Z0-9\\\\-]{20,}', flags: 'g', severity: 'critical', description: 'GitLab Personal Access Token' },\n { type: 'token', source: 'npm_[a-zA-Z0-9]{36}', flags: 'g', severity: 'high', description: 'npm Token' },\n\n // Connection strings\n { type: 'connection-string', source: '(?:mongodb(?:\\\\+srv)?|postgres(?:ql)?|mysql|redis|amqp):\\\\/\\\\/[^\\\\s\\'\"]+:[^\\\\s\\'\"]+@[^\\\\s\\'\"]+', flags: 'gi', severity: 'critical', description: 'Database Connection String' },\n { type: 'connection-string', source: '(?:DATABASE_URL|REDIS_URL|MONGODB_URI)\\\\s*[:=]\\\\s*[\\'\"]?([^\\\\s\\'\"]{10,})[\\'\"]?', flags: 'gi', severity: 'high', description: 'Database URL' },\n\n // Environment variables with secrets\n { type: 'env-variable', source: '(?:SECRET|PRIVATE|ENCRYPTION)[_-]?(?:KEY|TOKEN|PASS)\\\\s*[:=]\\\\s*[\\'\"]?([^\\\\s\\'\"]{8,})[\\'\"]?', flags: 'gi', severity: 'high', description: 'Secret Environment Variable' },\n\n // Stripe\n { type: 'api-key', source: 'sk_live_[a-zA-Z0-9]{24,}', flags: 'g', severity: 'critical', description: 'Stripe Live Secret Key' },\n { type: 'api-key', source: 'pk_live_[a-zA-Z0-9]{24,}', flags: 'g', severity: 'high', description: 'Stripe Live Publishable Key' },\n { type: 'api-key', source: 'rk_live_[a-zA-Z0-9]{24,}', flags: 'g', severity: 'critical', description: 'Stripe Restricted Key' },\n\n // Slack\n { type: 'token', source: 'xoxb-[0-9]{10,}-[0-9]{10,}-[a-zA-Z0-9]{24,}', flags: 'g', severity: 'critical', description: 'Slack Bot Token' },\n { type: 'token', source: 'xoxp-[0-9]{10,}-[0-9]{10,}-[a-zA-Z0-9]{24,}', flags: 'g', severity: 'critical', description: 'Slack User Token' },\n { type: 'api-key', source: 'https://hooks\\\\.slack\\\\.com/services/T[a-zA-Z0-9_]+/B[a-zA-Z0-9_]+/[a-zA-Z0-9_]+', flags: 'g', severity: 'high', description: 'Slack Webhook URL' },\n\n // Google\n { type: 'api-key', source: 'AIza[0-9A-Za-z_-]{35}', flags: 'g', severity: 'high', description: 'Google API Key' },\n { type: 'token', source: 'ya29\\\\.[0-9A-Za-z_-]+', flags: 'g', severity: 'high', description: 'Google OAuth Token' },\n\n // Azure\n { type: 'api-key', source: '(?:AccountKey|SharedAccessKey)\\\\s*=\\\\s*[a-zA-Z0-9+/=]{40,}', flags: 'g', severity: 'critical', description: 'Azure Storage Key' },\n\n // Twilio\n { type: 'api-key', source: 'AC[a-f0-9]{32}', flags: 'g', severity: 'high', description: 'Twilio Account SID' },\n\n // SendGrid\n { type: 'api-key', source: 'SG\\\\.[a-zA-Z0-9_-]{22}\\\\.[a-zA-Z0-9_-]{43}', flags: 'g', severity: 'critical', description: 'SendGrid API Key' },\n\n // JWT\n { type: 'token', source: 'eyJ[a-zA-Z0-9_-]{10,}\\\\.eyJ[a-zA-Z0-9_-]{10,}\\\\.[a-zA-Z0-9_-]{10,}', flags: 'g', severity: 'high', description: 'JSON Web Token' },\n\n // PII\n { type: 'pii', source: '\\\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\\\.[A-Z|a-z]{2,}\\\\b', flags: 'g', severity: 'medium', description: 'Email Address (PII)' },\n { type: 'pii', source: '\\\\b\\\\d{3}[-.]?\\\\d{2}[-.]?\\\\d{4}\\\\b', flags: 'g', severity: 'high', description: 'Possible SSN (PII)' },\n];\n\nfunction buildPatterns(customPatterns: string[] = []): SecretPattern[] {\n const patterns: SecretPattern[] = BUILTIN_PATTERNS.map((def) => ({\n type: def.type,\n pattern: new RegExp(def.source, def.flags),\n severity: def.severity,\n description: def.description,\n }));\n\n for (const custom of customPatterns) {\n try {\n patterns.push({\n type: 'custom',\n pattern: new RegExp(custom, 'gi'),\n severity: 'medium',\n description: `Custom pattern: ${custom}`,\n });\n } catch { /* skip invalid regex */ }\n }\n\n return patterns;\n}\n\nexport function scanContentForSecrets(\n content: string,\n filePath: string,\n customPatterns: string[] = [],\n): SecretFinding[] {\n const findings: SecretFinding[] = [];\n const lines = content.split('\\n');\n const allPatterns = buildPatterns(customPatterns);\n\n for (const secretPattern of allPatterns) {\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n secretPattern.pattern.lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = secretPattern.pattern.exec(line)) !== null) {\n const matchText = match[0];\n if (isTemplateOrPlaceholder(matchText)) continue;\n\n findings.push({\n type: secretPattern.type,\n file: filePath,\n line: i + 1,\n match: matchText,\n redacted: redactSecret(matchText),\n severity: secretPattern.severity,\n });\n }\n }\n }\n\n return deduplicateFindings(findings);\n}\n\nexport async function scanFileForSecrets(\n filePath: string,\n projectPath: string,\n customPatterns: string[] = [],\n): Promise<SecretFinding[]> {\n try {\n const content = await readFile(filePath, 'utf-8');\n const relPath = relative(resolve(projectPath), resolve(filePath));\n return scanContentForSecrets(content, relPath, customPatterns);\n } catch {\n return [];\n }\n}\n\nexport async function scanProjectForSecrets(\n projectPath: string,\n filePaths: string[],\n customPatterns: string[] = [],\n): Promise<SecretFinding[]> {\n const allFindings: SecretFinding[] = [];\n\n for (const fp of filePaths) {\n const findings = await scanFileForSecrets(fp, projectPath, customPatterns);\n allFindings.push(...findings);\n }\n\n return allFindings.sort((a, b) => {\n const severityOrder = { critical: 0, high: 1, medium: 2, low: 3 };\n return severityOrder[a.severity] - severityOrder[b.severity];\n });\n}\n\nexport function sanitizeContent(content: string, customPatterns: string[] = []): string {\n let sanitized = content;\n const allPatterns = buildPatterns(customPatterns);\n\n for (const secretPattern of allPatterns) {\n sanitized = sanitized.replace(secretPattern.pattern, (match) => {\n if (isTemplateOrPlaceholder(match)) return match;\n return redactSecret(match);\n });\n }\n\n return sanitized;\n}\n\nfunction redactSecret(value: string): string {\n if (value.length <= 8) return '***REDACTED***';\n const prefix = value.substring(0, 4);\n const suffix = value.substring(value.length - 2);\n return `${prefix}${'*'.repeat(Math.min(value.length - 6, 20))}${suffix}`;\n}\n\nfunction isTemplateOrPlaceholder(value: string): boolean {\n const placeholders = [\n /\\$\\{.*\\}/, /\\{\\{.*\\}\\}/, /%[sd]/, /<[A-Z_]+>/, /YOUR_.*_HERE/i,\n /\\bCHANGE_ME\\b/i, /\\bPLACEHOLDER\\b/i, /\\bexample\\b/i, /\\bTODO\\b/i, /xxx+/i,\n /\\breplace.?me\\b/i, /\\bdummy\\b/i, /\\btest_?key\\b/i, /\\bsample\\b/i,\n ];\n return placeholders.some((p) => p.test(value));\n}\n\nfunction deduplicateFindings(findings: SecretFinding[]): SecretFinding[] {\n const seen = new Set<string>();\n return findings.filter((f) => {\n const key = `${f.file}:${f.line}:${f.type}:${f.match}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\n// ===== ENTROPY ANALYSIS =====\n\nfunction shannonEntropy(str: string): number {\n const freq = new Map<string, number>();\n for (const ch of str) {\n freq.set(ch, (freq.get(ch) || 0) + 1);\n }\n let entropy = 0;\n for (const count of freq.values()) {\n const p = count / str.length;\n if (p > 0) entropy -= p * Math.log2(p);\n }\n return entropy;\n}\n\nconst HIGH_ENTROPY_RE = /['\"]([a-zA-Z0-9+/=_\\-]{30,})['\"]|=\\s*['\"]?([a-zA-Z0-9+/=_\\-]{30,})['\"]?/g;\n\nconst ENTROPY_SKIP = [\n /^[a-f0-9]{32,}$/i, // hex hashes\n /^[A-Z_]{30,}$/, // all-caps constants\n /^[a-z_]{30,}$/, // all-lowercase identifiers\n /^[a-zA-Z0-9+/]+=+$/, // base64 padding\n /^[a-z]+[A-Z][a-zA-Z]+$/, // camelCase identifiers\n /sha\\d+-/i, // integrity hashes (sha256-, sha512-)\n];\n\nexport function scanContentForHighEntropy(\n content: string,\n filePath: string,\n threshold: number = 5.0,\n): SecretFinding[] {\n const findings: SecretFinding[] = [];\n const lines = content.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (line.trim().startsWith('//') || line.trim().startsWith('#') || line.trim().startsWith('*')) continue;\n\n HIGH_ENTROPY_RE.lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = HIGH_ENTROPY_RE.exec(line)) !== null) {\n const value = match[1] || match[2];\n if (!value || value.length < 40) continue;\n if (isTemplateOrPlaceholder(value)) continue;\n if (ENTROPY_SKIP.some((p) => p.test(value))) continue;\n\n const entropy = shannonEntropy(value);\n if (entropy >= threshold) {\n findings.push({\n type: 'high-entropy',\n file: filePath,\n line: i + 1,\n match: value,\n redacted: redactSecret(value),\n severity: entropy >= 5.0 ? 'high' : 'medium',\n });\n }\n }\n }\n\n return deduplicateFindings(findings);\n}\n\n// ===== FULL PROJECT AUDIT =====\n\nexport interface AuditResult {\n findings: SecretFinding[];\n summary: {\n totalFiles: number;\n filesScanned: number;\n filesWithSecrets: number;\n totalFindings: number;\n bySeverity: { critical: number; high: number; medium: number; low: number };\n byType: Record<string, number>;\n };\n recommendations: string[];\n}\n\nexport async function auditProject(\n projectPath: string,\n filePaths: string[],\n options: { customPatterns?: string[]; entropyThreshold?: number; includePII?: boolean } = {},\n): Promise<AuditResult> {\n const { customPatterns = [], entropyThreshold = 4.5, includePII = true } = options;\n const allFindings: SecretFinding[] = [];\n const filesWithSecrets = new Set<string>();\n\n for (const fp of filePaths) {\n try {\n const content = await readFile(fp, 'utf-8');\n const relPath = relative(resolve(projectPath), resolve(fp));\n\n // Skip test files and declaration files for entropy (too many false positives)\n const isTestFile = /\\.(test|spec|mock)\\.[jt]sx?$/.test(relPath) || relPath.includes('__tests__');\n const isDtsFile = relPath.endsWith('.d.ts');\n\n // Pattern-based detection\n let findings = scanContentForSecrets(content, relPath, customPatterns);\n\n // Filter PII if not wanted\n if (!includePII) {\n findings = findings.filter((f) => f.type !== 'pii');\n }\n\n // Entropy-based detection (skip test/declaration files — too noisy)\n const entropyFindings = (isTestFile || isDtsFile)\n ? []\n : scanContentForHighEntropy(content, relPath, entropyThreshold);\n\n const combined = [...findings, ...entropyFindings];\n if (combined.length > 0) {\n filesWithSecrets.add(relPath);\n allFindings.push(...combined);\n }\n } catch {\n // skip unreadable files\n }\n }\n\n // Sort by severity\n allFindings.sort((a, b) => {\n const order = { critical: 0, high: 1, medium: 2, low: 3 };\n return order[a.severity] - order[b.severity];\n });\n\n // Build summary\n const bySeverity = { critical: 0, high: 0, medium: 0, low: 0 };\n const byType: Record<string, number> = {};\n for (const f of allFindings) {\n bySeverity[f.severity]++;\n byType[f.type] = (byType[f.type] || 0) + 1;\n }\n\n // Generate recommendations\n const recommendations: string[] = [];\n if (bySeverity.critical > 0) {\n recommendations.push('CRITICAL: Rotate all detected credentials immediately. They may already be compromised.');\n }\n if (byType['password'] > 0) {\n recommendations.push('Move passwords to environment variables or a secrets manager (AWS Secrets Manager, Vault, etc.).');\n }\n if (byType['api-key'] > 0 || byType['aws-key'] > 0) {\n recommendations.push('Use environment variables for API keys. Never commit them to source control.');\n }\n if (byType['connection-string'] > 0) {\n recommendations.push('Database connection strings should use environment variables, not hardcoded values.');\n }\n if (byType['private-key'] > 0) {\n recommendations.push('Private keys should NEVER be in source code. Use a key management service.');\n }\n if (byType['pii'] > 0) {\n recommendations.push('PII detected. Review for GDPR/CCPA compliance. Consider data anonymization.');\n }\n if (byType['high-entropy'] > 0) {\n recommendations.push('High-entropy strings detected that may be secrets. Review manually.');\n }\n if (allFindings.length > 0) {\n recommendations.push('Add a .gitignore entry for .env files if not already present.');\n recommendations.push('Run `npx cto-ai-cli --audit` regularly or add to CI pipeline.');\n }\n if (allFindings.length === 0) {\n recommendations.push('No secrets detected. Great job keeping your codebase clean!');\n }\n\n return {\n findings: allFindings,\n summary: {\n totalFiles: filePaths.length,\n filesScanned: filePaths.length,\n filesWithSecrets: filesWithSecrets.size,\n totalFindings: allFindings.length,\n bySeverity,\n byType,\n },\n recommendations,\n };\n}\n","import { Project, SyntaxKind, type SourceFile } from 'ts-morph';\nimport { readFile } from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { AnalyzedFile, PruneLevel, PrunedContent } from '../types/engine.js';\nimport { countTokensChars4 } from './tokenizer.js';\n\nconst TS_EXTENSIONS = new Set(['ts', 'tsx', 'js', 'jsx', 'mts', 'mjs']);\n\n// ===== PUBLIC API =====\n\nexport async function pruneFile(\n file: AnalyzedFile,\n level: PruneLevel,\n): Promise<PrunedContent> {\n if (level === 'excluded') {\n return emptyResult(file, 'excluded');\n }\n\n if (level === 'full') {\n return fullContent(file);\n }\n\n const ext = file.extension.toLowerCase();\n const isTS = TS_EXTENSIONS.has(ext);\n\n if (isTS) {\n return pruneTypeScript(file, level);\n }\n\n return pruneGeneric(file, level);\n}\n\nexport async function pruneFiles(\n files: AnalyzedFile[],\n levelFn: (file: AnalyzedFile) => PruneLevel,\n): Promise<PrunedContent[]> {\n const results: PrunedContent[] = [];\n\n for (const file of files) {\n const level = levelFn(file);\n const pruned = await pruneFile(file, level);\n results.push(pruned);\n }\n\n return results;\n}\n\n// ===== TYPESCRIPT AST-BASED PRUNING =====\n\nasync function pruneTypeScript(\n file: AnalyzedFile,\n level: PruneLevel,\n): Promise<PrunedContent> {\n let content: string;\n try {\n content = await readFile(file.path, 'utf-8');\n } catch {\n return emptyResult(file, level);\n }\n\n let project: Project;\n try {\n const tsConfigPath = findTsConfig(file.path);\n project = new Project({\n tsConfigFilePath: tsConfigPath,\n skipAddingFilesFromTsConfig: true,\n compilerOptions: tsConfigPath\n ? undefined\n : { allowJs: true, esModuleInterop: true },\n });\n project.createSourceFile(file.path, content, { overwrite: true });\n } catch {\n // Fallback to generic pruning if AST fails\n return pruneGenericFromContent(file, content, level);\n }\n\n const sourceFile = project.getSourceFiles()[0];\n if (!sourceFile) {\n return pruneGenericFromContent(file, content, level);\n }\n\n const prunedContent = level === 'signatures'\n ? extractSignaturesAST(sourceFile)\n : extractSkeletonAST(sourceFile);\n\n const prunedTokens = countTokensChars4(Buffer.byteLength(prunedContent, 'utf-8'));\n const savingsPercent = file.tokens > 0 ? ((file.tokens - prunedTokens) / file.tokens) * 100 : 0;\n\n return {\n relativePath: file.relativePath,\n originalTokens: file.tokens,\n prunedTokens,\n pruneLevel: level,\n content: prunedContent,\n savingsPercent: Math.max(0, savingsPercent),\n };\n}\n\n// ===== SIGNATURES: Keep imports, type defs, function signatures, class outlines =====\n\nfunction extractSignaturesAST(sf: SourceFile): string {\n const parts: string[] = [];\n\n // Imports\n for (const imp of sf.getImportDeclarations()) {\n parts.push(imp.getText());\n }\n\n if (parts.length > 0) parts.push('');\n\n // Type aliases\n for (const ta of sf.getTypeAliases()) {\n addJSDoc(ta, parts);\n parts.push(ta.getText());\n }\n\n // Interfaces\n for (const iface of sf.getInterfaces()) {\n addJSDoc(iface, parts);\n parts.push(iface.getText());\n }\n\n // Enums\n for (const en of sf.getEnums()) {\n addJSDoc(en, parts);\n parts.push(en.getText());\n }\n\n // Function declarations — signature only\n for (const fn of sf.getFunctions()) {\n addJSDoc(fn, parts);\n const isExported = fn.isExported();\n const isAsync = fn.isAsync();\n const name = fn.getName() ?? '<anonymous>';\n const params = fn.getParameters().map((p) => p.getText()).join(', ');\n const returnType = fn.getReturnTypeNode()?.getText();\n const returnStr = returnType ? `: ${returnType}` : '';\n\n const prefix = isExported ? 'export ' : '';\n const asyncStr = isAsync ? 'async ' : '';\n parts.push(`${prefix}${asyncStr}function ${name}(${params})${returnStr} { /* ... */ }`);\n }\n\n // Variable declarations (const/let with arrow functions)\n for (const stmt of sf.getVariableStatements()) {\n for (const decl of stmt.getDeclarations()) {\n const init = decl.getInitializer();\n if (init && (init.getKind() === SyntaxKind.ArrowFunction || init.getKind() === SyntaxKind.FunctionExpression)) {\n addJSDoc(stmt, parts);\n const isExported = stmt.isExported();\n const prefix = isExported ? 'export ' : '';\n const kind = stmt.getDeclarationKind();\n const name = decl.getName();\n const typeNode = decl.getTypeNode()?.getText();\n const typeStr = typeNode ? `: ${typeNode}` : '';\n parts.push(`${prefix}${kind} ${name}${typeStr} = /* ... */;`);\n } else {\n // Non-function variables: keep full declaration\n addJSDoc(stmt, parts);\n parts.push(stmt.getText());\n }\n }\n }\n\n // Classes — outline with method signatures\n for (const cls of sf.getClasses()) {\n addJSDoc(cls, parts);\n const isExported = cls.isExported();\n const prefix = isExported ? 'export ' : '';\n const name = cls.getName() ?? '<anonymous>';\n const ext = cls.getExtends()?.getText();\n const impl = cls.getImplements().map((i) => i.getText()).join(', ');\n let header = `${prefix}class ${name}`;\n if (ext) header += ` extends ${ext}`;\n if (impl) header += ` implements ${impl}`;\n header += ' {';\n parts.push(header);\n\n // Properties\n for (const prop of cls.getProperties()) {\n parts.push(` ${prop.getText()}`);\n }\n\n // Constructor\n const ctor = cls.getConstructors()[0];\n if (ctor) {\n const ctorParams = ctor.getParameters().map((p) => p.getText()).join(', ');\n parts.push(` constructor(${ctorParams}) { /* ... */ }`);\n }\n\n // Methods — signature only\n for (const method of cls.getMethods()) {\n const isStatic = method.isStatic();\n const isAsync = method.isAsync();\n const methodName = method.getName();\n const methodParams = method.getParameters().map((p) => p.getText()).join(', ');\n const returnType = method.getReturnTypeNode()?.getText();\n const returnStr = returnType ? `: ${returnType}` : '';\n const staticStr = isStatic ? 'static ' : '';\n const asyncStr = isAsync ? 'async ' : '';\n parts.push(` ${staticStr}${asyncStr}${methodName}(${methodParams})${returnStr} { /* ... */ }`);\n }\n\n parts.push('}');\n }\n\n // Re-exports\n for (const exp of sf.getExportDeclarations()) {\n parts.push(exp.getText());\n }\n\n // Export assignments\n for (const exp of sf.getExportAssignments()) {\n parts.push(exp.getText());\n }\n\n return parts.join('\\n');\n}\n\n// ===== SKELETON: Keep only declarations, no bodies at all =====\n\nfunction extractSkeletonAST(sf: SourceFile): string {\n const parts: string[] = [];\n\n // Imports\n for (const imp of sf.getImportDeclarations()) {\n parts.push(imp.getText());\n }\n\n if (parts.length > 0) parts.push('');\n\n // Type aliases — full\n for (const ta of sf.getTypeAliases()) {\n if (ta.isExported()) parts.push(ta.getText());\n }\n\n // Interfaces — name + extends only\n for (const iface of sf.getInterfaces()) {\n if (!iface.isExported()) continue;\n const ext = iface.getExtends().map((e) => e.getText());\n const extStr = ext.length > 0 ? ` extends ${ext.join(', ')}` : '';\n parts.push(`export interface ${iface.getName()}${extStr} { /* ${iface.getProperties().length} props */ }`);\n }\n\n // Enums — name only\n for (const en of sf.getEnums()) {\n if (!en.isExported()) continue;\n const members = en.getMembers().map((m) => m.getName());\n parts.push(`export enum ${en.getName()} { ${members.join(', ')} }`);\n }\n\n // Functions — name + params only\n for (const fn of sf.getFunctions()) {\n if (!fn.isExported()) continue;\n const name = fn.getName() ?? '<anonymous>';\n const params = fn.getParameters().map((p) => p.getText()).join(', ');\n parts.push(`export function ${name}(${params});`);\n }\n\n // Classes — name + method names only\n for (const cls of sf.getClasses()) {\n if (!cls.isExported()) continue;\n const methods = cls.getMethods().map((m) => m.getName());\n parts.push(`export class ${cls.getName()} { /* methods: ${methods.join(', ')} */ }`);\n }\n\n // Re-exports\n for (const exp of sf.getExportDeclarations()) {\n parts.push(exp.getText());\n }\n\n return parts.join('\\n');\n}\n\n// ===== GENERIC PRUNING (non-TS files) =====\n\nasync function pruneGeneric(\n file: AnalyzedFile,\n level: PruneLevel,\n): Promise<PrunedContent> {\n let content: string;\n try {\n content = await readFile(file.path, 'utf-8');\n } catch {\n return emptyResult(file, level);\n }\n\n return pruneGenericFromContent(file, content, level);\n}\n\nfunction pruneGenericFromContent(\n file: AnalyzedFile,\n content: string,\n level: PruneLevel,\n): PrunedContent {\n const lines = content.split('\\n');\n let result: string[];\n\n if (level === 'signatures') {\n result = lines.filter((line) => {\n const t = line.trim();\n return (\n t === '' ||\n t.startsWith('#') ||\n t.startsWith('//') ||\n t.startsWith('import ') ||\n t.startsWith('from ') ||\n t.startsWith('export ') ||\n t.startsWith('def ') ||\n t.startsWith('async def ') ||\n t.startsWith('class ') ||\n t.startsWith('function ') ||\n t.startsWith('const ') ||\n t.startsWith('let ') ||\n t.startsWith('var ') ||\n /^(pub |fn |struct |enum |impl |mod |use )/.test(t)\n );\n });\n } else {\n // skeleton: even more aggressive — only declarations\n result = lines.filter((line) => {\n const t = line.trim();\n return (\n t.startsWith('import ') ||\n t.startsWith('from ') ||\n t.startsWith('export ') ||\n t.startsWith('def ') ||\n t.startsWith('class ') ||\n t.startsWith('function ') ||\n /^(pub |fn |struct |enum |mod |use )/.test(t)\n );\n });\n }\n\n const prunedContent = result.join('\\n');\n const prunedTokens = countTokensChars4(Buffer.byteLength(prunedContent, 'utf-8'));\n const savingsPercent = file.tokens > 0 ? ((file.tokens - prunedTokens) / file.tokens) * 100 : 0;\n\n return {\n relativePath: file.relativePath,\n originalTokens: file.tokens,\n prunedTokens,\n pruneLevel: level,\n content: prunedContent,\n savingsPercent: Math.max(0, savingsPercent),\n };\n}\n\n// ===== HELPERS =====\n\nasync function fullContent(file: AnalyzedFile): Promise<PrunedContent> {\n let content = '';\n try {\n content = await readFile(file.path, 'utf-8');\n } catch { /* empty */ }\n\n return {\n relativePath: file.relativePath,\n originalTokens: file.tokens,\n prunedTokens: file.tokens,\n pruneLevel: 'full',\n content,\n savingsPercent: 0,\n };\n}\n\nfunction emptyResult(file: AnalyzedFile, level: PruneLevel): PrunedContent {\n return {\n relativePath: file.relativePath,\n originalTokens: file.tokens,\n prunedTokens: 0,\n pruneLevel: level,\n content: '',\n savingsPercent: 100,\n };\n}\n\nfunction addJSDoc(node: { getJsDocs?: () => { getText(): string }[] }, parts: string[]): void {\n if (!node.getJsDocs) return;\n const docs = node.getJsDocs();\n if (docs.length > 0) {\n parts.push(docs[0].getText());\n }\n}\n\nfunction findTsConfig(filePath: string): string | undefined {\n let dir = filePath;\n for (let i = 0; i < 10; i++) {\n dir = join(dir, '..');\n const candidate = join(dir, 'tsconfig.json');\n if (existsSync(candidate)) return candidate;\n }\n return undefined;\n}\n","import type {\n AnalyzedFile,\n ProjectGraph,\n CoverageResult,\n} from '../types/engine.js';\nimport { buildAdjacencyList, bfsBidirectional } from './graph-utils.js';\n\n// ===== CONTEXT COVERAGE SCORING =====\n//\n// Given a set of included files and a task's target files, calculate\n// how much of the \"relevant universe\" is covered.\n//\n// coverageScore = |includedRelevant| / |relevantFiles| × 100\n//\n// \"Relevant\" = target files + their dependencies (up to `depth` levels)\n// + type providers used by included files.\n\nexport function calculateCoverage(\n targetPaths: string[],\n includedPaths: string[],\n allFiles: AnalyzedFile[],\n graph: ProjectGraph,\n depth: number = 2,\n): CoverageResult {\n // 1. Find all relevant files: targets + their dependency cone\n // Uses adjacency list for O(V+E) BFS instead of scanning all edges per node.\n const adj = buildAdjacencyList(graph.edges);\n const relevantSet = targetPaths.length > 0\n ? bfsBidirectional(targetPaths, adj, depth)\n : new Set<string>();\n const includedSet = new Set(includedPaths);\n\n // Also add type providers used by included files\n const tempFileMap = new Map(allFiles.map((f) => [f.relativePath, f]));\n for (const path of includedPaths) {\n const file = tempFileMap.get(path);\n if (!file) continue;\n\n for (const imp of file.imports) {\n const impFile = tempFileMap.get(imp);\n if (impFile && impFile.kind === 'type') {\n relevantSet.add(imp);\n }\n }\n }\n\n // 2. Calculate coverage\n const relevantFiles = Array.from(relevantSet);\n const includedRelevant = relevantFiles.filter((f) => includedSet.has(f));\n const missingRelevant = relevantFiles.filter((f) => !includedSet.has(f));\n\n // Missing critical = missing files with critical/high exclusion impact\n const missingCritical = missingRelevant.filter((f) => {\n const file = tempFileMap.get(f);\n return file && (file.exclusionImpact === 'critical' || file.exclusionImpact === 'high');\n });\n\n // Risk-weighted coverage: missing a high-risk file hurts more than missing a low-risk one.\n // score = Σ(riskScore of included relevant) / Σ(riskScore of all relevant) × 100\n // Falls back to count-based if no risk data is available.\n const fileMap = new Map(allFiles.map((f) => [f.relativePath, f]));\n let totalRelevantRisk = 0;\n let includedRelevantRisk = 0;\n\n for (const f of relevantFiles) {\n const risk = fileMap.get(f)?.riskScore ?? 1;\n totalRelevantRisk += risk;\n if (includedSet.has(f)) {\n includedRelevantRisk += risk;\n }\n }\n\n const score = totalRelevantRisk > 0\n ? Math.round((includedRelevantRisk / totalRelevantRisk) * 100)\n : relevantFiles.length > 0\n ? Math.round((includedRelevant.length / relevantFiles.length) * 100)\n : 100;\n\n // Build explanation\n let explanation: string;\n if (score >= 90) {\n explanation = `Excellent coverage (${score}%): AI has nearly all relevant context.`;\n } else if (score >= 70) {\n explanation = `Good coverage (${score}%): Most relevant files included.`;\n if (missingCritical.length > 0) {\n explanation += ` Warning: ${missingCritical.length} critical file(s) missing.`;\n }\n } else if (score >= 50) {\n explanation = `Partial coverage (${score}%): Significant context is missing.`;\n if (missingCritical.length > 0) {\n explanation += ` ${missingCritical.length} critical file(s) not included — AI quality will degrade.`;\n }\n } else {\n explanation = `Low coverage (${score}%): Most relevant files are excluded. AI response quality will be poor.`;\n }\n\n return {\n score,\n relevantFiles,\n includedRelevant,\n missingRelevant,\n missingCritical,\n explanation,\n };\n}\n","import type { AnalyzedFile, BudgetPlan, BudgetEntry, PruneLevel } from '../types/engine.js';\nimport { pruneFile } from './pruner.js';\n\n// ===== BUDGET OPTIMIZER =====\n//\n// Greedy knapsack with cascading prune levels.\n// Files are sorted by riskScore (descending) — highest risk first.\n// Each file is tried at progressively smaller prune levels until it fits.\n\nexport function getPruneLevelForRisk(riskScore: number): PruneLevel {\n if (riskScore >= 80) return 'full'; // critical — include everything, no cascading\n if (riskScore >= 60) return 'full'; // high — try full first, can cascade\n if (riskScore >= 30) return 'signatures'; // medium — signatures by default\n return 'skeleton'; // low — skeleton\n}\n\nexport function isCriticalRisk(riskScore: number): boolean {\n return riskScore >= 80;\n}\n\nexport async function optimizeBudget(\n files: AnalyzedFile[],\n budget: number,\n): Promise<BudgetPlan> {\n const entries: BudgetEntry[] = [];\n let used = 0;\n\n // Sort by riskScore descending — most important files first\n const sorted = [...files].sort((a, b) => b.riskScore - a.riskScore);\n\n for (const file of sorted) {\n const defaultLevel = getPruneLevelForRisk(file.riskScore);\n\n // Try cascading prune levels: full → signatures → skeleton → excluded\n const levelsToTry = getCascadeLevels(defaultLevel);\n\n let included = false;\n\n for (const level of levelsToTry) {\n if (level === 'excluded') break;\n\n if (level === 'full') {\n if (used + file.tokens <= budget) {\n used += file.tokens;\n entries.push({\n relativePath: file.relativePath,\n originalTokens: file.tokens,\n allocatedTokens: file.tokens,\n pruneLevel: 'full',\n included: true,\n reason: `Risk ${file.riskScore} — included in full`,\n });\n included = true;\n break;\n }\n } else {\n const pruned = await pruneFile(file, level);\n if (pruned.prunedTokens > 0 && used + pruned.prunedTokens <= budget) {\n used += pruned.prunedTokens;\n entries.push({\n relativePath: file.relativePath,\n originalTokens: file.tokens,\n allocatedTokens: pruned.prunedTokens,\n pruneLevel: level,\n included: true,\n reason: `Risk ${file.riskScore} — pruned to ${level} (budget constraint)`,\n });\n included = true;\n break;\n }\n }\n }\n\n if (!included) {\n entries.push({\n relativePath: file.relativePath,\n originalTokens: file.tokens,\n allocatedTokens: 0,\n pruneLevel: 'excluded',\n included: false,\n reason: `Risk ${file.riskScore} — excluded (budget exhausted, ${file.tokens} tokens)`,\n });\n }\n }\n\n return {\n budget,\n used,\n remaining: budget - used,\n fillPercent: budget > 0 ? Math.round((used / budget) * 100 * 10) / 10 : 0,\n files: entries,\n };\n}\n\n// ===== HELPERS =====\n\nfunction getCascadeLevels(startLevel: PruneLevel): PruneLevel[] {\n const all: PruneLevel[] = ['full', 'signatures', 'skeleton', 'excluded'];\n const startIdx = all.indexOf(startLevel);\n return all.slice(startIdx);\n}\n","import type { ProjectAnalysis, AnalyzedFile } from '../types/engine.js';\nimport type { ContextSelection } from '../types/engine.js';\nimport { selectContext } from './selector.js';\nimport { calculateCoverage } from './coverage.js';\nimport { buildAdjacencyList } from './graph-utils.js';\n\n// ===== Context Score™ =====\n//\n// A single 0-100 metric that quantifies how well a project's context\n// can be optimized for AI consumption.\n//\n// The score answers: \"If I send this project to an AI with CTO,\n// how much value am I getting per token?\"\n//\n// Dimensions:\n// 1. Efficiency (30%) — How much can we compress without losing value?\n// 2. Coverage (25%) — How much of the relevant universe do we capture?\n// 3. Risk Control (20%) — Are high-risk files properly prioritized?\n// 4. Structure (15%) — How well-organized is the codebase for AI consumption?\n// 5. Governance (10%) — Is the project set up for safe, auditable AI use?\n//\n// Grade scale:\n// A+ (95-100) | A (90-94) | A- (85-89)\n// B+ (80-84) | B (75-79) | B- (70-74)\n// C+ (65-69) | C (60-64) | C- (55-59)\n// D (40-54) | F (0-39)\n\nexport type Grade = 'A+' | 'A' | 'A-' | 'B+' | 'B' | 'B-' | 'C+' | 'C' | 'C-' | 'D' | 'F';\n\nexport interface ContextScore {\n overall: number;\n grade: Grade;\n\n dimensions: {\n efficiency: DimensionScore;\n coverage: DimensionScore;\n riskControl: DimensionScore;\n structure: DimensionScore;\n governance: DimensionScore;\n };\n\n insights: ScoreInsight[];\n\n comparison: {\n naiveTokens: number;\n optimizedTokens: number;\n savedTokens: number;\n savedPercent: number;\n monthlySavingsUSD: number;\n };\n\n meta: {\n projectName: string;\n totalFiles: number;\n totalTokens: number;\n analyzedAt: Date;\n };\n}\n\nexport interface DimensionScore {\n score: number;\n weight: number;\n weighted: number;\n detail: string;\n}\n\nexport interface ScoreInsight {\n type: 'strength' | 'weakness' | 'opportunity';\n title: string;\n detail: string;\n impact: 'high' | 'medium' | 'low';\n}\n\n// ===== MAIN API =====\n\n/**\n * Compute the Context Score™ for a project.\n *\n * @param analysis - Project analysis (from analyzeProject or getCachedAnalysis)\n * @param task - Representative task (default: \"general code review\")\n * @param budget - Token budget (default: 50000)\n */\nexport async function computeContextScore(\n analysis: ProjectAnalysis,\n task: string = 'general code review and refactoring',\n budget: number = 50_000,\n): Promise<ContextScore> {\n // Run context selection to get real numbers\n const selection = await selectContext({ task, analysis, budget });\n\n const insights: ScoreInsight[] = [];\n\n // 1. EFFICIENCY (30%) — compression ratio + pruning effectiveness\n const efficiency = scoreEfficiency(analysis, selection, insights);\n\n // 2. COVERAGE (25%) — how much of the relevant universe is captured\n const coverage = scoreCoverage(analysis, selection, insights);\n\n // 3. RISK CONTROL (20%) — high-risk file prioritization\n const riskControl = scoreRiskControl(analysis, selection, insights);\n\n // 4. STRUCTURE (15%) — codebase organization for AI\n const structure = scoreStructure(analysis, insights);\n\n // 5. GOVERNANCE (10%) — project setup for safe AI use\n const governance = scoreGovernance(analysis, insights);\n\n // Overall\n const overall = Math.round(\n efficiency.weighted + coverage.weighted + riskControl.weighted +\n structure.weighted + governance.weighted\n );\n\n const grade = scoreToGrade(overall);\n\n // Comparison: CTO vs naive (send everything)\n const naiveTokens = analysis.totalTokens;\n const optimizedTokens = selection.totalTokens;\n const savedTokens = naiveTokens - optimizedTokens;\n const savedPercent = naiveTokens > 0 ? Math.round((savedTokens / naiveTokens) * 100) : 0;\n\n // Monthly savings estimate: assume 40 interactions/day, 20 working days\n // Claude Sonnet: $3/M input tokens\n const interactionsPerMonth = 40 * 20;\n const costPerMToken = 3; // $/M tokens (Sonnet)\n const naiveMonthlyCost = (naiveTokens / 1_000_000) * costPerMToken * interactionsPerMonth;\n const optimizedMonthlyCost = (optimizedTokens / 1_000_000) * costPerMToken * interactionsPerMonth;\n const monthlySavingsUSD = Math.round((naiveMonthlyCost - optimizedMonthlyCost) * 100) / 100;\n\n return {\n overall,\n grade,\n dimensions: {\n efficiency,\n coverage,\n riskControl,\n structure,\n governance,\n },\n insights: insights.sort((a, b) => {\n const order = { high: 0, medium: 1, low: 2 };\n return order[a.impact] - order[b.impact];\n }),\n comparison: {\n naiveTokens,\n optimizedTokens,\n savedTokens,\n savedPercent,\n monthlySavingsUSD,\n },\n meta: {\n projectName: analysis.projectName,\n totalFiles: analysis.totalFiles,\n totalTokens: analysis.totalTokens,\n analyzedAt: analysis.analyzedAt,\n },\n };\n}\n\n// ===== DIMENSION SCORERS =====\n\nfunction scoreEfficiency(\n analysis: ProjectAnalysis,\n selection: ContextSelection,\n insights: ScoreInsight[],\n): DimensionScore {\n const weight = 30;\n\n // Compression ratio: how much we reduced tokens\n const ratio = analysis.totalTokens > 0\n ? 1 - (selection.totalTokens / analysis.totalTokens)\n : 0;\n\n // File selectivity: what % of files were excluded\n const selectivity = analysis.totalFiles > 0\n ? 1 - (selection.files.length / analysis.totalFiles)\n : 0;\n\n // Pruning effectiveness: how many files got pruned (signatures/skeleton)\n const prunedFiles = selection.files.filter(\n (f) => f.pruneLevel === 'signatures' || f.pruneLevel === 'skeleton'\n ).length;\n const pruneRatio = selection.files.length > 0\n ? prunedFiles / selection.files.length\n : 0;\n\n // Weighted combination\n const raw = (ratio * 0.5 + selectivity * 0.3 + pruneRatio * 0.2) * 100;\n const score = Math.min(100, Math.max(0, Math.round(raw)));\n const weighted = (score / 100) * weight;\n\n if (ratio > 0.7) {\n insights.push({\n type: 'strength',\n title: 'Excellent compression',\n detail: `${Math.round(ratio * 100)}% token reduction while maintaining context quality`,\n impact: 'high',\n });\n }\n\n if (ratio < 0.3 && analysis.totalTokens > 20_000) {\n insights.push({\n type: 'weakness',\n title: 'Low compression opportunity',\n detail: 'Most files are needed. Consider splitting the project into smaller modules.',\n impact: 'medium',\n });\n }\n\n return {\n score,\n weight,\n weighted,\n detail: `${Math.round(ratio * 100)}% compression, ${prunedFiles}/${selection.files.length} files pruned`,\n };\n}\n\nfunction scoreCoverage(\n analysis: ProjectAnalysis,\n selection: ContextSelection,\n insights: ScoreInsight[],\n): DimensionScore {\n const weight = 25;\n\n const coverageScore = selection.coverage.score;\n const missingCritical = selection.coverage.missingCritical.length;\n\n // Penalize missing critical files heavily\n let penalty = 0;\n if (missingCritical > 0) {\n penalty = Math.min(30, missingCritical * 10);\n insights.push({\n type: 'weakness',\n title: `${missingCritical} critical file(s) missing from context`,\n detail: `Missing: ${selection.coverage.missingCritical.slice(0, 3).join(', ')}${missingCritical > 3 ? ` +${missingCritical - 3} more` : ''}`,\n impact: 'high',\n });\n }\n\n const score = Math.min(100, Math.max(0, Math.round(coverageScore - penalty)));\n const weighted = (score / 100) * weight;\n\n if (coverageScore >= 90 && missingCritical === 0) {\n insights.push({\n type: 'strength',\n title: 'Excellent context coverage',\n detail: `${coverageScore}% of the relevant universe captured with zero critical gaps`,\n impact: 'high',\n });\n }\n\n return {\n score,\n weight,\n weighted,\n detail: `${coverageScore}% coverage, ${missingCritical} critical gaps`,\n };\n}\n\nfunction scoreRiskControl(\n analysis: ProjectAnalysis,\n selection: ContextSelection,\n insights: ScoreInsight[],\n): DimensionScore {\n const weight = 20;\n\n const dist = analysis.riskProfile.distribution;\n const totalFiles = analysis.totalFiles;\n\n // What % of critical+high risk files are included in the selection?\n const criticalFiles = analysis.files.filter((f) => f.riskScore >= 80);\n const highFiles = analysis.files.filter((f) => f.riskScore >= 60 && f.riskScore < 80);\n const selectedPaths = new Set(selection.files.map((f) => f.relativePath));\n\n const criticalIncluded = criticalFiles.filter((f) => selectedPaths.has(f.relativePath)).length;\n const highIncluded = highFiles.filter((f) => selectedPaths.has(f.relativePath)).length;\n\n const criticalCoverage = criticalFiles.length > 0\n ? criticalIncluded / criticalFiles.length\n : 1;\n const highCoverage = highFiles.length > 0\n ? highIncluded / highFiles.length\n : 1;\n\n // Risk distribution health: fewer critical files = healthier\n const criticalRatio = totalFiles > 0 ? dist.critical / totalFiles : 0;\n const healthScore = Math.max(0, 1 - criticalRatio * 5); // penalize heavy critical\n\n const raw = (criticalCoverage * 0.5 + highCoverage * 0.3 + healthScore * 0.2) * 100;\n const score = Math.min(100, Math.max(0, Math.round(raw)));\n const weighted = (score / 100) * weight;\n\n if (criticalCoverage === 1 && criticalFiles.length > 0) {\n insights.push({\n type: 'strength',\n title: 'All critical files included',\n detail: `${criticalFiles.length} critical-risk files are captured in context`,\n impact: 'high',\n });\n }\n\n if (criticalRatio > 0.2) {\n insights.push({\n type: 'opportunity',\n title: 'High concentration of critical files',\n detail: `${dist.critical} files (${Math.round(criticalRatio * 100)}%) are critical risk. Consider refactoring complex modules.`,\n impact: 'medium',\n });\n }\n\n return {\n score,\n weight,\n weighted,\n detail: `${criticalIncluded}/${criticalFiles.length} critical + ${highIncluded}/${highFiles.length} high-risk files included`,\n };\n}\n\nfunction scoreStructure(\n analysis: ProjectAnalysis,\n insights: ScoreInsight[],\n): DimensionScore {\n const weight = 15;\n\n const graph = analysis.graph;\n const totalFiles = analysis.totalFiles;\n\n // Cluster cohesion: well-organized projects have clear clusters\n const avgCohesion = graph.clusters.length > 0\n ? graph.clusters.reduce((s, c) => s + c.cohesion, 0) / graph.clusters.length\n : 0;\n\n // Orphan penalty: too many orphans = poor structure\n const orphanRatio = totalFiles > 0 ? graph.orphans.length / totalFiles : 0;\n\n // Hub concentration: too few hubs = flat, too many = coupled\n const hubRatio = totalFiles > 0 ? graph.hubs.length / totalFiles : 0;\n const hubHealth = hubRatio > 0.02 && hubRatio < 0.15 ? 1 : Math.max(0, 1 - Math.abs(hubRatio - 0.08) * 10);\n\n // Type coverage: having type files is good for AI\n const typeFiles = analysis.files.filter((f) => f.kind === 'type').length;\n const typeRatio = totalFiles > 0 ? typeFiles / totalFiles : 0;\n const typeScore = Math.min(1, typeRatio * 10); // reward up to 10% types\n\n const raw = (avgCohesion * 0.3 + (1 - orphanRatio) * 0.3 + hubHealth * 0.2 + typeScore * 0.2) * 100;\n const score = Math.min(100, Math.max(0, Math.round(raw)));\n const weighted = (score / 100) * weight;\n\n if (orphanRatio > 0.5) {\n insights.push({\n type: 'weakness',\n title: 'Many orphan files',\n detail: `${graph.orphans.length} files (${Math.round(orphanRatio * 100)}%) have no imports/exports. AI gets less context from the dependency graph.`,\n impact: 'medium',\n });\n }\n\n if (graph.clusters.length > 0 && avgCohesion > 0.7) {\n insights.push({\n type: 'strength',\n title: 'Well-organized module structure',\n detail: `${graph.clusters.length} cohesive clusters (avg cohesion: ${(avgCohesion * 100).toFixed(0)}%). CTO can efficiently select relevant modules.`,\n impact: 'medium',\n });\n }\n\n return {\n score,\n weight,\n weighted,\n detail: `${graph.clusters.length} clusters, ${graph.orphans.length} orphans, ${graph.hubs.length} hubs`,\n };\n}\n\nfunction scoreGovernance(\n analysis: ProjectAnalysis,\n insights: ScoreInsight[],\n): DimensionScore {\n const weight = 10;\n\n // Check for config/policy/type organization\n const hasTypes = analysis.files.some((f) => f.kind === 'type');\n const hasConfig = analysis.files.some((f) => f.kind === 'config');\n const hasTests = analysis.files.some((f) => f.kind === 'test');\n\n let score = 50; // baseline\n\n if (hasTypes) { score += 15; }\n if (hasConfig) { score += 10; }\n if (hasTests) { score += 15; }\n\n // Stack detection: known stacks get better AI support\n if (analysis.stack.length > 0) { score += 10; }\n\n score = Math.min(100, score);\n const weighted = (score / 100) * weight;\n\n if (!hasTests) {\n insights.push({\n type: 'opportunity',\n title: 'No test files detected',\n detail: 'Adding tests helps CTO understand code intent and provides better context boundaries.',\n impact: 'low',\n });\n }\n\n if (!hasTypes) {\n insights.push({\n type: 'opportunity',\n title: 'No type definition files',\n detail: 'Type files dramatically improve AI code generation accuracy. Consider adding interfaces/types.',\n impact: 'medium',\n });\n }\n\n return {\n score,\n weight,\n weighted,\n detail: `types:${hasTypes ? '✓' : '✗'} tests:${hasTests ? '✓' : '✗'} config:${hasConfig ? '✓' : '✗'} stack:${analysis.stack.join(',') || 'unknown'}`,\n };\n}\n\n// ===== HELPERS =====\n\nfunction scoreToGrade(score: number): Grade {\n if (score >= 95) return 'A+';\n if (score >= 90) return 'A';\n if (score >= 85) return 'A-';\n if (score >= 80) return 'B+';\n if (score >= 75) return 'B';\n if (score >= 70) return 'B-';\n if (score >= 65) return 'C+';\n if (score >= 60) return 'C';\n if (score >= 55) return 'C-';\n if (score >= 40) return 'D';\n return 'F';\n}\n\n// ===== RENDERING =====\n\n/**\n * Render the Context Score as a beautiful terminal-friendly string.\n */\nexport function renderContextScore(score: ContextScore): string {\n const lines: string[] = [];\n\n const gradeColor = score.grade.startsWith('A') ? '🟢'\n : score.grade.startsWith('B') ? '🔵'\n : score.grade.startsWith('C') ? '🟡'\n : '🔴';\n\n lines.push('');\n lines.push(` ╔══════════════════════════════════════════════════╗`);\n lines.push(` ║ ║`);\n lines.push(` ║ ${gradeColor} Context Score™ ${padCenter(score.overall.toString(), 3)} / 100 Grade: ${padCenter(score.grade, 2)} ║`);\n lines.push(` ║ ║`);\n lines.push(` ║ ${score.meta.projectName.padEnd(20).substring(0, 20)} ║`);\n lines.push(` ║ ${score.meta.totalFiles} files · ${Math.round(score.meta.totalTokens / 1000)}K tokens ║`);\n lines.push(` ║ ║`);\n lines.push(` ╠══════════════════════════════════════════════════╣`);\n\n // Dimensions\n const dims = [\n { label: 'Efficiency', dim: score.dimensions.efficiency },\n { label: 'Coverage', dim: score.dimensions.coverage },\n { label: 'Risk Control', dim: score.dimensions.riskControl },\n { label: 'Structure', dim: score.dimensions.structure },\n { label: 'Governance', dim: score.dimensions.governance },\n ];\n\n lines.push(` ║ ║`);\n\n for (const { label, dim } of dims) {\n const bar = renderBar(dim.score, 20);\n const pct = dim.score.toString().padStart(3);\n lines.push(` ║ ${label.padEnd(14)} ${bar} ${pct}% (×${dim.weight}%) ║`);\n }\n\n lines.push(` ║ ║`);\n lines.push(` ╠══════════════════════════════════════════════════╣`);\n\n // Comparison\n lines.push(` ║ ║`);\n lines.push(` ║ 💰 vs. Sending Everything: ║`);\n lines.push(` ║ Tokens saved: ${formatNumber(score.comparison.savedTokens).padEnd(12)} (${score.comparison.savedPercent}%) ║`);\n lines.push(` ║ Monthly savings: $${score.comparison.monthlySavingsUSD.toFixed(2).padEnd(10)} ║`);\n lines.push(` ║ (${score.comparison.optimizedTokens.toLocaleString()} vs ${score.comparison.naiveTokens.toLocaleString()} tokens) ║`);\n lines.push(` ║ ║`);\n\n // Insights\n if (score.insights.length > 0) {\n lines.push(` ╠══════════════════════════════════════════════════╣`);\n lines.push(` ║ ║`);\n\n const top = score.insights.slice(0, 5);\n for (const insight of top) {\n const icon = insight.type === 'strength' ? '✅'\n : insight.type === 'weakness' ? '⚠️'\n : '💡';\n const title = insight.title.substring(0, 44).padEnd(44);\n lines.push(` ║ ${icon} ${title} ║`);\n }\n\n lines.push(` ║ ║`);\n }\n\n lines.push(` ╚══════════════════════════════════════════════════╝`);\n lines.push('');\n\n return lines.join('\\n');\n}\n\nfunction renderBar(pct: number, width: number): string {\n const filled = Math.round((pct / 100) * width);\n const empty = width - filled;\n return '█'.repeat(filled) + '░'.repeat(empty);\n}\n\nfunction padCenter(str: string, width: number): string {\n const pad = Math.max(0, width - str.length);\n const left = Math.floor(pad / 2);\n return ' '.repeat(left) + str + ' '.repeat(pad - left);\n}\n\nfunction formatNumber(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`;\n return n.toString();\n}\n","import type { ProjectAnalysis } from '../types/engine.js';\nimport { selectContext } from './selector.js';\n\n// ===== Benchmark Engine =====\n//\n// Proves CTO works with real numbers. Compares three strategies:\n// 1. CTO (risk-aware, deterministic selection)\n// 2. Naive (send everything — what most people do)\n// 3. Random (randomly pick files up to budget — baseline)\n//\n// Measures: tokens, coverage, cost, time\n\nexport interface BenchmarkResult {\n project: string;\n totalFiles: number;\n totalTokens: number;\n budget: number;\n task: string;\n\n strategies: {\n cto: StrategyResult;\n naive: StrategyResult;\n random: StrategyResult;\n };\n\n winner: 'cto' | 'naive' | 'random';\n ctoAdvantage: {\n vsNaiveTokensSaved: number;\n vsNaiveTokensSavedPercent: number;\n vsRandomCoverageGain: number;\n vsNaiveCostSavedMonthlyUSD: number;\n };\n}\n\nexport interface StrategyResult {\n filesSelected: number;\n tokensUsed: number;\n coverageScore: number;\n criticalFilesCovered: number;\n criticalFilesTotal: number;\n highRiskCovered: number;\n highRiskTotal: number;\n costPerInteractionUSD: number;\n timeMs: number;\n}\n\n/**\n * Run a full benchmark comparing CTO vs naive vs random selection.\n */\nexport async function runBenchmark(\n analysis: ProjectAnalysis,\n task: string = 'general code review and refactoring',\n budget: number = 50_000,\n): Promise<BenchmarkResult> {\n const criticalFiles = analysis.files.filter((f) => f.riskScore >= 80);\n const highRiskFiles = analysis.files.filter((f) => f.riskScore >= 60 && f.riskScore < 80);\n\n // ===== STRATEGY 1: CTO (risk-aware selection) =====\n const ctoStart = performance.now();\n const ctoSelection = await selectContext({ task, analysis, budget });\n const ctoTime = performance.now() - ctoStart;\n\n const ctoSelectedPaths = new Set(ctoSelection.files.map((f) => f.relativePath));\n const ctoCritical = criticalFiles.filter((f) => ctoSelectedPaths.has(f.relativePath)).length;\n const ctoHigh = highRiskFiles.filter((f) => ctoSelectedPaths.has(f.relativePath)).length;\n\n const cto: StrategyResult = {\n filesSelected: ctoSelection.files.length,\n tokensUsed: ctoSelection.totalTokens,\n coverageScore: ctoSelection.coverage.score,\n criticalFilesCovered: ctoCritical,\n criticalFilesTotal: criticalFiles.length,\n highRiskCovered: ctoHigh,\n highRiskTotal: highRiskFiles.length,\n costPerInteractionUSD: (ctoSelection.totalTokens / 1_000_000) * 3, // Sonnet pricing\n timeMs: Math.round(ctoTime),\n };\n\n // ===== STRATEGY 2: NAIVE (send everything up to budget) =====\n const naiveStart = performance.now();\n const naiveFiles = [...analysis.files].sort((a, b) => a.relativePath.localeCompare(b.relativePath));\n let naiveTokens = 0;\n let naiveCount = 0;\n const naiveSelectedPaths = new Set<string>();\n\n for (const f of naiveFiles) {\n if (naiveTokens + f.tokens <= budget) {\n naiveTokens += f.tokens;\n naiveCount++;\n naiveSelectedPaths.add(f.relativePath);\n }\n }\n // If budget exceeds total, include everything\n if (naiveTokens === 0 && analysis.totalTokens <= budget) {\n naiveTokens = analysis.totalTokens;\n naiveCount = analysis.totalFiles;\n for (const f of analysis.files) naiveSelectedPaths.add(f.relativePath);\n }\n const naiveTime = performance.now() - naiveStart;\n\n const naiveCritical = criticalFiles.filter((f) => naiveSelectedPaths.has(f.relativePath)).length;\n const naiveHigh = highRiskFiles.filter((f) => naiveSelectedPaths.has(f.relativePath)).length;\n\n // Naive coverage: just count how many of the relevant files are included\n const naiveCoverage = analysis.totalFiles > 0\n ? Math.round((naiveCount / analysis.totalFiles) * 100)\n : 0;\n\n const naive: StrategyResult = {\n filesSelected: naiveCount,\n tokensUsed: naiveTokens > 0 ? naiveTokens : analysis.totalTokens,\n coverageScore: naiveTokens > 0 ? naiveCoverage : 100,\n criticalFilesCovered: naiveCritical,\n criticalFilesTotal: criticalFiles.length,\n highRiskCovered: naiveHigh,\n highRiskTotal: highRiskFiles.length,\n costPerInteractionUSD: ((naiveTokens > 0 ? naiveTokens : analysis.totalTokens) / 1_000_000) * 3,\n timeMs: Math.round(naiveTime),\n };\n\n // ===== STRATEGY 3: RANDOM (randomly pick files up to budget) =====\n const randomStart = performance.now();\n const shuffled = [...analysis.files].sort(() => Math.random() - 0.5);\n let randomTokens = 0;\n let randomCount = 0;\n const randomSelectedPaths = new Set<string>();\n\n for (const f of shuffled) {\n if (randomTokens + f.tokens <= budget) {\n randomTokens += f.tokens;\n randomCount++;\n randomSelectedPaths.add(f.relativePath);\n }\n }\n const randomTime = performance.now() - randomStart;\n\n const randomCritical = criticalFiles.filter((f) => randomSelectedPaths.has(f.relativePath)).length;\n const randomHigh = highRiskFiles.filter((f) => randomSelectedPaths.has(f.relativePath)).length;\n const randomCoverage = analysis.totalFiles > 0\n ? Math.round((randomCount / analysis.totalFiles) * 100)\n : 0;\n\n const random: StrategyResult = {\n filesSelected: randomCount,\n tokensUsed: randomTokens,\n coverageScore: randomCoverage,\n criticalFilesCovered: randomCritical,\n criticalFilesTotal: criticalFiles.length,\n highRiskCovered: randomHigh,\n highRiskTotal: highRiskFiles.length,\n costPerInteractionUSD: (randomTokens / 1_000_000) * 3,\n timeMs: Math.round(randomTime),\n };\n\n // ===== DETERMINE WINNER =====\n // Score: coverage * 0.5 + criticalCoverage * 0.3 + tokenEfficiency * 0.2\n const ctoScore = computeStrategyScore(cto, budget);\n const naiveScore = computeStrategyScore(naive, budget);\n const randomScore = computeStrategyScore(random, budget);\n\n const winner = ctoScore >= naiveScore && ctoScore >= randomScore ? 'cto'\n : naiveScore >= randomScore ? 'naive' : 'random';\n\n // Monthly savings: 40 interactions/day × 20 days\n const interactionsPerMonth = 800;\n const vsNaiveCostSaved = (naive.costPerInteractionUSD - cto.costPerInteractionUSD) * interactionsPerMonth;\n\n return {\n project: analysis.projectName,\n totalFiles: analysis.totalFiles,\n totalTokens: analysis.totalTokens,\n budget,\n task,\n strategies: { cto, naive, random },\n winner,\n ctoAdvantage: {\n vsNaiveTokensSaved: naive.tokensUsed - cto.tokensUsed,\n vsNaiveTokensSavedPercent: naive.tokensUsed > 0\n ? Math.round(((naive.tokensUsed - cto.tokensUsed) / naive.tokensUsed) * 100)\n : 0,\n vsRandomCoverageGain: cto.coverageScore - random.coverageScore,\n vsNaiveCostSavedMonthlyUSD: Math.round(vsNaiveCostSaved * 100) / 100,\n },\n };\n}\n\nfunction computeStrategyScore(strategy: StrategyResult, budget: number): number {\n const coverageWeight = strategy.coverageScore / 100;\n const criticalWeight = strategy.criticalFilesTotal > 0\n ? strategy.criticalFilesCovered / strategy.criticalFilesTotal\n : 1;\n const efficiency = budget > 0 ? 1 - (strategy.tokensUsed / budget) : 0;\n\n return coverageWeight * 0.5 + criticalWeight * 0.3 + Math.max(0, efficiency) * 0.2;\n}\n\n/**\n * Render benchmark results as a formatted comparison table.\n */\nexport function renderBenchmark(result: BenchmarkResult): string {\n const lines: string[] = [];\n const { cto, naive, random } = result.strategies;\n\n lines.push('');\n lines.push(` ╔══════════════════════════════════════════════════════════════╗`);\n lines.push(` ║ ⚡ CTO Benchmark — ${result.project.substring(0, 20).padEnd(20)} ║`);\n lines.push(` ╠══════════════════════════════════════════════════════════════╣`);\n lines.push(` ║ ║`);\n lines.push(` ║ ${pad('Metric', 20)} ${pad('CTO', 12)} ${pad('Naive', 12)} ${pad('Random', 12)} ║`);\n lines.push(` ║ ${'─'.repeat(56)} ║`);\n lines.push(` ║ ${pad('Files selected', 20)} ${pad(cto.filesSelected.toString(), 12)} ${pad(naive.filesSelected.toString(), 12)} ${pad(random.filesSelected.toString(), 12)} ║`);\n lines.push(` ║ ${pad('Tokens used', 20)} ${pad(fmt(cto.tokensUsed), 12)} ${pad(fmt(naive.tokensUsed), 12)} ${pad(fmt(random.tokensUsed), 12)} ║`);\n lines.push(` ║ ${pad('Coverage', 20)} ${pad(cto.coverageScore + '%', 12)} ${pad(naive.coverageScore + '%', 12)} ${pad(random.coverageScore + '%', 12)} ║`);\n lines.push(` ║ ${pad('Critical files', 20)} ${pad(`${cto.criticalFilesCovered}/${cto.criticalFilesTotal}`, 12)} ${pad(`${naive.criticalFilesCovered}/${naive.criticalFilesTotal}`, 12)} ${pad(`${random.criticalFilesCovered}/${random.criticalFilesTotal}`, 12)} ║`);\n lines.push(` ║ ${pad('High-risk files', 20)} ${pad(`${cto.highRiskCovered}/${cto.highRiskTotal}`, 12)} ${pad(`${naive.highRiskCovered}/${naive.highRiskTotal}`, 12)} ${pad(`${random.highRiskCovered}/${random.highRiskTotal}`, 12)} ║`);\n lines.push(` ║ ${pad('Cost/interaction', 20)} ${pad('$' + cto.costPerInteractionUSD.toFixed(4), 12)} ${pad('$' + naive.costPerInteractionUSD.toFixed(4), 12)} ${pad('$' + random.costPerInteractionUSD.toFixed(4), 12)} ║`);\n lines.push(` ║ ${pad('Time', 20)} ${pad(cto.timeMs + 'ms', 12)} ${pad(naive.timeMs + 'ms', 12)} ${pad(random.timeMs + 'ms', 12)} ║`);\n lines.push(` ║ ║`);\n lines.push(` ╠══════════════════════════════════════════════════════════════╣`);\n lines.push(` ║ ║`);\n lines.push(` ║ 🏆 Winner: ${result.winner.toUpperCase().padEnd(48)} ║`);\n\n if (result.ctoAdvantage.vsNaiveTokensSavedPercent > 0) {\n lines.push(` ║ 📉 ${result.ctoAdvantage.vsNaiveTokensSavedPercent}% fewer tokens than naive ║`);\n }\n if (result.ctoAdvantage.vsRandomCoverageGain > 0) {\n lines.push(` ║ 📈 +${result.ctoAdvantage.vsRandomCoverageGain}% better coverage than random ║`);\n }\n if (result.ctoAdvantage.vsNaiveCostSavedMonthlyUSD > 0) {\n lines.push(` ║ 💰 $${result.ctoAdvantage.vsNaiveCostSavedMonthlyUSD.toFixed(2)}/mo saved vs naive (800 interactions) ║`);\n }\n\n lines.push(` ║ ║`);\n lines.push(` ╚══════════════════════════════════════════════════════════════╝`);\n lines.push('');\n\n return lines.join('\\n');\n}\n\nfunction pad(s: string, w: number): string { return s.padEnd(w).substring(0, w); }\nfunction fmt(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`;\n return n.toString();\n}\n","import { resolve } from 'node:path';\nimport { readFile } from 'node:fs/promises';\nimport type { ProjectAnalysis, AnalyzedFile, ContextSelection } from '../types/engine.js';\nimport type { TaskType } from '../types/interact.js';\nimport { selectContext } from './selector.js';\nimport { buildAdjacencyList, bfsBidirectional } from './graph-utils.js';\nimport { classifyTask } from '../interact/router.js';\nimport { buildPrompt } from '../interact/prompt.js';\nimport { countTokensChars4 } from './tokenizer.js';\n\n// ===== Quality Benchmark =====\n//\n// Proves that CTO context → better AI output by comparing prompt quality\n// across three strategies: CTO (risk-aware), Naive (alphabetical), Random.\n//\n// Metrics:\n// 1. Relevance Score — What % of included files are actually relevant to the task?\n// 2. Completeness Score — What % of task-critical files are included?\n// 3. Noise Ratio — What % of tokens are wasted on irrelevant files?\n// 4. Type Coverage — Are type definitions included for the selected files?\n// 5. Dependency Closure — Are transitive deps of relevant files included?\n//\n// These are PROXY metrics for output quality. The claim:\n// Higher relevance + completeness → fewer hallucinations + more correct code.\n\nexport interface QualityBenchmarkResult {\n project: string;\n task: string;\n taskType: TaskType;\n budget: number;\n\n strategies: {\n cto: QualityMetrics;\n naive: QualityMetrics;\n random: QualityMetrics;\n };\n\n comparison: {\n ctoVsNaiveRelevance: number;\n ctoVsRandomRelevance: number;\n ctoVsNaiveCompleteness: number;\n ctoVsRandomCompleteness: number;\n ctoNoiseReduction: number;\n };\n\n prompts: {\n cto: { rendered: string; tokens: number };\n naive: { rendered: string; tokens: number };\n };\n\n verdict: string;\n}\n\nexport interface QualityMetrics {\n filesSelected: number;\n tokensUsed: number;\n\n relevanceScore: number;\n completenessScore: number;\n noiseRatio: number;\n typeCoverage: number;\n dependencyClosure: number;\n\n relevantFilesIncluded: number;\n relevantFilesTotal: number;\n typeFilesIncluded: number;\n typeFilesNeeded: number;\n depsIncluded: number;\n depsNeeded: number;\n}\n\n// ===== MAIN API =====\n\n/**\n * Run a quality benchmark comparing CTO vs naive vs random context selection.\n * Measures relevance, completeness, noise, and dependency closure.\n */\nexport async function runQualityBenchmark(\n analysis: ProjectAnalysis,\n task: string,\n budget: number = 50_000,\n): Promise<QualityBenchmarkResult> {\n const taskType = classifyTask(task);\n\n // 1. Identify task-relevant files using keyword matching + graph expansion\n const relevantFiles = identifyRelevantFiles(analysis, task, taskType);\n const relevantPaths = new Set(relevantFiles.map((f) => f.relativePath));\n\n // 2. Identify type files needed by relevant files\n const typeFilesNeeded = findTypeFiles(analysis, relevantFiles);\n const typePaths = new Set(typeFilesNeeded.map((f) => f.relativePath));\n\n // 3. Identify transitive deps of relevant files\n const adj = buildAdjacencyList(analysis.graph.edges);\n const depsNeeded = bfsBidirectional(\n relevantFiles.map((f) => f.relativePath),\n adj,\n 2,\n );\n\n // 4. Run CTO selection\n const ctoSelection = await selectContext({ task, analysis, budget });\n const ctoMetrics = computeMetrics(\n ctoSelection.files.map((f) => f.relativePath),\n ctoSelection.totalTokens,\n analysis,\n relevantPaths,\n typePaths,\n depsNeeded,\n );\n\n // 5. Run Naive selection (alphabetical, up to budget)\n const naiveFiles = [...analysis.files]\n .sort((a, b) => a.relativePath.localeCompare(b.relativePath));\n const naiveSelected: string[] = [];\n let naiveTokens = 0;\n for (const f of naiveFiles) {\n if (naiveTokens + f.tokens <= budget) {\n naiveSelected.push(f.relativePath);\n naiveTokens += f.tokens;\n }\n }\n if (naiveSelected.length === 0 && analysis.totalTokens <= budget) {\n for (const f of analysis.files) naiveSelected.push(f.relativePath);\n naiveTokens = analysis.totalTokens;\n }\n const naiveMetrics = computeMetrics(\n naiveSelected, naiveTokens, analysis, relevantPaths, typePaths, depsNeeded,\n );\n\n // 6. Run Random selection\n const shuffled = [...analysis.files].sort(() => Math.random() - 0.5);\n const randomSelected: string[] = [];\n let randomTokens = 0;\n for (const f of shuffled) {\n if (randomTokens + f.tokens <= budget) {\n randomSelected.push(f.relativePath);\n randomTokens += f.tokens;\n }\n }\n const randomMetrics = computeMetrics(\n randomSelected, randomTokens, analysis, relevantPaths, typePaths, depsNeeded,\n );\n\n // 7. Generate actual prompts for CTO vs Naive\n const ctoPrompt = buildPrompt({\n task,\n taskType,\n analysis,\n selection: ctoSelection,\n enableCoT: true,\n });\n\n // Build a fake selection for naive to generate its prompt\n const naiveSelectionFiles = naiveSelected.map((p) => {\n const f = analysis.files.find((af) => af.relativePath === p);\n return {\n relativePath: p,\n tokens: f?.tokens ?? 0,\n originalTokens: f?.tokens ?? 0,\n pruneLevel: 'full' as const,\n riskScore: f?.riskScore ?? 0,\n reason: 'alphabetical inclusion',\n };\n });\n const naiveFakeSelection: ContextSelection = {\n files: naiveSelectionFiles,\n totalTokens: naiveTokens,\n budget,\n usedPercent: budget > 0 ? (naiveTokens / budget) * 100 : 0,\n coverage: { score: naiveMetrics.completenessScore, missingCritical: [], missingRelevant: [], relevantFiles: [], includedRelevant: [], explanation: 'naive selection' },\n riskScore: 0,\n deterministic: false,\n hash: '',\n decisions: [],\n };\n const naivePrompt = buildPrompt({\n task,\n taskType,\n analysis,\n selection: naiveFakeSelection,\n enableCoT: true,\n });\n\n // 8. Comparison\n const comparison = {\n ctoVsNaiveRelevance: ctoMetrics.relevanceScore - naiveMetrics.relevanceScore,\n ctoVsRandomRelevance: ctoMetrics.relevanceScore - randomMetrics.relevanceScore,\n ctoVsNaiveCompleteness: ctoMetrics.completenessScore - naiveMetrics.completenessScore,\n ctoVsRandomCompleteness: ctoMetrics.completenessScore - randomMetrics.completenessScore,\n ctoNoiseReduction: naiveMetrics.noiseRatio - ctoMetrics.noiseRatio,\n };\n\n // 9. Verdict\n const verdict = generateVerdict(ctoMetrics, naiveMetrics, randomMetrics, comparison);\n\n return {\n project: analysis.projectName,\n task,\n taskType,\n budget,\n strategies: {\n cto: ctoMetrics,\n naive: naiveMetrics,\n random: randomMetrics,\n },\n comparison,\n prompts: {\n cto: { rendered: ctoPrompt.rendered, tokens: ctoPrompt.totalTokens },\n naive: { rendered: naivePrompt.rendered, tokens: naivePrompt.totalTokens },\n },\n verdict,\n };\n}\n\n// ===== RELEVANCE IDENTIFICATION =====\n\nfunction identifyRelevantFiles(\n analysis: ProjectAnalysis,\n task: string,\n taskType: TaskType,\n): AnalyzedFile[] {\n const keywords = extractKeywords(task);\n const scored = new Map<string, number>();\n\n for (const file of analysis.files) {\n let relevance = 0;\n\n // Keyword match in path\n for (const kw of keywords) {\n if (file.relativePath.toLowerCase().includes(kw)) {\n relevance += 10;\n }\n }\n\n // High risk = likely important\n if (file.riskScore >= 60) relevance += 5;\n\n // Hub files are often relevant\n if (file.isHub) relevance += 3;\n\n // Entry points\n if (file.kind === 'entry') relevance += 3;\n\n // Type files that define interfaces used across the project\n if (file.kind === 'type') relevance += 2;\n\n // Task-type specific boosts\n if (taskType === 'test' && file.kind === 'test') relevance += 8;\n if (taskType === 'refactor' && file.complexity > 10) relevance += 4;\n if (taskType === 'debug' && file.riskScore >= 40) relevance += 4;\n\n if (relevance > 0) {\n scored.set(file.relativePath, relevance);\n }\n }\n\n // Expand via dependencies\n const adj = buildAdjacencyList(analysis.graph.edges);\n const seeds = [...scored.keys()];\n const expanded = bfsBidirectional(seeds, adj, 1);\n\n // Add expanded files with lower score\n for (const path of expanded) {\n if (!scored.has(path)) {\n scored.set(path, 1);\n }\n }\n\n // Return files sorted by relevance\n return analysis.files\n .filter((f) => scored.has(f.relativePath))\n .sort((a, b) => (scored.get(b.relativePath) ?? 0) - (scored.get(a.relativePath) ?? 0));\n}\n\nfunction extractKeywords(task: string): string[] {\n const stopWords = new Set([\n 'the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been', 'being',\n 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could',\n 'should', 'may', 'might', 'can', 'shall', 'to', 'of', 'in', 'for',\n 'on', 'with', 'at', 'by', 'from', 'as', 'into', 'through', 'and',\n 'but', 'or', 'nor', 'not', 'so', 'yet', 'both', 'either', 'neither',\n 'this', 'that', 'these', 'those', 'it', 'its', 'my', 'your', 'our',\n 'their', 'his', 'her', 'fix', 'add', 'remove', 'update', 'change',\n 'refactor', 'implement', 'create', 'build', 'make', 'code', 'file',\n ]);\n\n return task\n .toLowerCase()\n .replace(/[^a-z0-9\\s]/g, '')\n .split(/\\s+/)\n .filter((w) => w.length > 2 && !stopWords.has(w));\n}\n\nfunction findTypeFiles(\n analysis: ProjectAnalysis,\n relevantFiles: AnalyzedFile[],\n): AnalyzedFile[] {\n const adj = buildAdjacencyList(analysis.graph.edges);\n const typeFiles = new Set<string>();\n\n for (const file of relevantFiles) {\n // Find forward deps that are type files\n const deps = adj.forward.get(file.relativePath) ?? [];\n for (const dep of deps) {\n const depFile = analysis.files.find((f) => f.relativePath === dep);\n if (depFile && depFile.kind === 'type') {\n typeFiles.add(dep);\n }\n }\n }\n\n return analysis.files.filter((f) => typeFiles.has(f.relativePath));\n}\n\n// ===== METRICS COMPUTATION =====\n\nfunction computeMetrics(\n selectedPaths: string[],\n tokensUsed: number,\n analysis: ProjectAnalysis,\n relevantPaths: Set<string>,\n typePaths: Set<string>,\n depsNeeded: Set<string>,\n): QualityMetrics {\n const selected = new Set(selectedPaths);\n\n // Relevance: what % of selected files are actually relevant?\n const relevantIncluded = selectedPaths.filter((p) => relevantPaths.has(p)).length;\n const relevanceScore = selectedPaths.length > 0\n ? Math.round((relevantIncluded / selectedPaths.length) * 100)\n : 0;\n\n // Completeness: what % of relevant files are included?\n const completenessHits = [...relevantPaths].filter((p) => selected.has(p)).length;\n const completenessScore = relevantPaths.size > 0\n ? Math.round((completenessHits / relevantPaths.size) * 100)\n : 100;\n\n // Noise: what % of tokens are spent on irrelevant files?\n let irrelevantTokens = 0;\n for (const path of selectedPaths) {\n if (!relevantPaths.has(path)) {\n const f = analysis.files.find((af) => af.relativePath === path);\n irrelevantTokens += f?.tokens ?? 0;\n }\n }\n const noiseRatio = tokensUsed > 0\n ? Math.min(100, Math.round((irrelevantTokens / tokensUsed) * 100))\n : 0;\n\n // Type coverage: are needed type files included?\n const typeIncluded = [...typePaths].filter((p) => selected.has(p)).length;\n const typeCoverage = typePaths.size > 0\n ? Math.round((typeIncluded / typePaths.size) * 100)\n : 100;\n\n // Dependency closure: are transitive deps included?\n const depsIncluded = [...depsNeeded].filter((p) => selected.has(p)).length;\n const dependencyClosure = depsNeeded.size > 0\n ? Math.round((depsIncluded / depsNeeded.size) * 100)\n : 100;\n\n return {\n filesSelected: selectedPaths.length,\n tokensUsed,\n relevanceScore,\n completenessScore,\n noiseRatio,\n typeCoverage,\n dependencyClosure,\n relevantFilesIncluded: relevantIncluded,\n relevantFilesTotal: relevantPaths.size,\n typeFilesIncluded: typeIncluded,\n typeFilesNeeded: typePaths.size,\n depsIncluded,\n depsNeeded: depsNeeded.size,\n };\n}\n\n// ===== VERDICT =====\n\nfunction generateVerdict(\n cto: QualityMetrics,\n naive: QualityMetrics,\n random: QualityMetrics,\n comp: QualityBenchmarkResult['comparison'],\n): string {\n const lines: string[] = [];\n\n lines.push('## Quality Verdict');\n lines.push('');\n\n // Headline\n if (comp.ctoVsNaiveRelevance > 0 && comp.ctoVsNaiveCompleteness > 0) {\n lines.push(`**CTO produces higher-quality context than both naive and random selection.**`);\n } else if (comp.ctoVsRandomRelevance > 0) {\n lines.push(`**CTO produces higher-quality context than random selection.**`);\n } else {\n lines.push(`**All strategies perform similarly for this task.**`);\n }\n lines.push('');\n\n // Relevance\n lines.push(`### Relevance (higher = less hallucination risk)`);\n lines.push(`- CTO: ${cto.relevanceScore}% of included files are relevant`);\n lines.push(`- Naive: ${naive.relevanceScore}% relevant`);\n lines.push(`- Random: ${random.relevanceScore}% relevant`);\n if (comp.ctoVsNaiveRelevance > 0) {\n lines.push(`- **CTO includes ${comp.ctoVsNaiveRelevance}% more relevant files than naive**`);\n }\n lines.push('');\n\n // Completeness\n lines.push(`### Completeness (higher = more correct code generation)`);\n lines.push(`- CTO: ${cto.completenessScore}% of required files included`);\n lines.push(`- Naive: ${naive.completenessScore}% complete`);\n lines.push(`- Random: ${random.completenessScore}% complete`);\n if (comp.ctoVsNaiveCompleteness > 0) {\n lines.push(`- **CTO captures ${comp.ctoVsNaiveCompleteness}% more required files**`);\n }\n lines.push('');\n\n // Noise\n lines.push(`### Noise (lower = less distraction for the AI)`);\n lines.push(`- CTO: ${cto.noiseRatio}% noise`);\n lines.push(`- Naive: ${naive.noiseRatio}% noise`);\n lines.push(`- Random: ${random.noiseRatio}% noise`);\n if (comp.ctoNoiseReduction > 0) {\n lines.push(`- **CTO reduces noise by ${comp.ctoNoiseReduction} percentage points**`);\n }\n lines.push('');\n\n // Type coverage\n lines.push(`### Type Coverage (higher = fewer type errors in generated code)`);\n lines.push(`- CTO: ${cto.typeCoverage}% | Naive: ${naive.typeCoverage}% | Random: ${random.typeCoverage}%`);\n lines.push('');\n\n // Dependency closure\n lines.push(`### Dependency Closure (higher = AI understands import chain)`);\n lines.push(`- CTO: ${cto.dependencyClosure}% | Naive: ${naive.dependencyClosure}% | Random: ${random.dependencyClosure}%`);\n\n return lines.join('\\n');\n}\n\n// ===== RENDERING =====\n\nexport function renderQualityBenchmark(result: QualityBenchmarkResult): string {\n const { cto, naive, random } = result.strategies;\n const lines: string[] = [];\n\n lines.push('');\n lines.push(` ╔══════════════════════════════════════════════════════════════════╗`);\n lines.push(` ║ 🔬 Quality Benchmark — ${pad(result.project, 20)} ║`);\n lines.push(` ║ Task: ${pad(result.task.substring(0, 45), 45)} ║`);\n lines.push(` ╠══════════════════════════════════════════════════════════════════╣`);\n lines.push(` ║ ║`);\n lines.push(` ║ ${pad('Metric', 22)} ${pad('CTO', 12)} ${pad('Naive', 12)} ${pad('Random', 12)} ║`);\n lines.push(` ║ ${'─'.repeat(58)} ║`);\n lines.push(` ║ ${pad('Relevance', 22)} ${pad(cto.relevanceScore + '%', 12)} ${pad(naive.relevanceScore + '%', 12)} ${pad(random.relevanceScore + '%', 12)} ║`);\n lines.push(` ║ ${pad('Completeness', 22)} ${pad(cto.completenessScore + '%', 12)} ${pad(naive.completenessScore + '%', 12)} ${pad(random.completenessScore + '%', 12)} ║`);\n lines.push(` ║ ${pad('Noise ratio', 22)} ${pad(cto.noiseRatio + '%', 12)} ${pad(naive.noiseRatio + '%', 12)} ${pad(random.noiseRatio + '%', 12)} ║`);\n lines.push(` ║ ${pad('Type coverage', 22)} ${pad(cto.typeCoverage + '%', 12)} ${pad(naive.typeCoverage + '%', 12)} ${pad(random.typeCoverage + '%', 12)} ║`);\n lines.push(` ║ ${pad('Dependency closure', 22)} ${pad(cto.dependencyClosure + '%', 12)} ${pad(naive.dependencyClosure + '%', 12)} ${pad(random.dependencyClosure + '%', 12)} ║`);\n lines.push(` ║ ${'─'.repeat(58)} ║`);\n lines.push(` ║ ${pad('Relevant files', 22)} ${pad(`${cto.relevantFilesIncluded}/${cto.relevantFilesTotal}`, 12)} ${pad(`${naive.relevantFilesIncluded}/${naive.relevantFilesTotal}`, 12)} ${pad(`${random.relevantFilesIncluded}/${random.relevantFilesTotal}`, 12)} ║`);\n lines.push(` ║ ${pad('Type files', 22)} ${pad(`${cto.typeFilesIncluded}/${cto.typeFilesNeeded}`, 12)} ${pad(`${naive.typeFilesIncluded}/${naive.typeFilesNeeded}`, 12)} ${pad(`${random.typeFilesIncluded}/${random.typeFilesNeeded}`, 12)} ║`);\n lines.push(` ║ ${pad('Tokens used', 22)} ${pad(fmt(cto.tokensUsed), 12)} ${pad(fmt(naive.tokensUsed), 12)} ${pad(fmt(random.tokensUsed), 12)} ║`);\n lines.push(` ║ ║`);\n\n // Comparison highlights\n const c = result.comparison;\n if (c.ctoVsNaiveRelevance > 0) {\n lines.push(` ║ 📈 +${c.ctoVsNaiveRelevance}% more relevant files than naive ║`);\n }\n if (c.ctoVsNaiveCompleteness > 0) {\n lines.push(` ║ ✅ +${c.ctoVsNaiveCompleteness}% more complete context than naive ║`);\n }\n if (c.ctoNoiseReduction > 0) {\n lines.push(` ║ 🔇 ${c.ctoNoiseReduction}% less noise than naive ║`);\n }\n\n lines.push(` ║ ║`);\n lines.push(` ╚══════════════════════════════════════════════════════════════════╝`);\n lines.push('');\n\n return lines.join('\\n');\n}\n\nfunction pad(s: string, w: number): string { return s.padEnd(w).substring(0, w); }\nfunction fmt(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`;\n return n.toString();\n}\n","import type { TaskType, ModelChoice, ModelSpec, ModelId } from '../types/interact.js';\nimport type { ProjectAnalysis } from '../types/engine.js';\n\n// ===== MODEL REGISTRY =====\n\nexport const MODEL_REGISTRY: ModelSpec[] = [\n {\n id: 'claude-haiku-3.5',\n name: 'Claude 3.5 Haiku',\n tier: 'fast',\n pricing: { inputPerMillion: 0.80, outputPerMillion: 4.00, cacheReadPerMillion: 0.08 },\n contextWindow: 200_000,\n strengths: ['speed', 'simple-tasks', 'low-cost'],\n },\n {\n id: 'claude-sonnet-4',\n name: 'Claude Sonnet 4',\n tier: 'balanced',\n pricing: { inputPerMillion: 3.00, outputPerMillion: 15.00, cacheReadPerMillion: 0.30 },\n contextWindow: 200_000,\n strengths: ['code-generation', 'refactoring', 'balanced-reasoning'],\n },\n {\n id: 'claude-opus-4',\n name: 'Claude Opus 4',\n tier: 'reasoning',\n pricing: { inputPerMillion: 15.00, outputPerMillion: 75.00, cacheReadPerMillion: 1.50 },\n contextWindow: 200_000,\n strengths: ['deep-reasoning', 'architecture', 'complex-debugging'],\n },\n];\n\n// ===== ROUTING RULES =====\n\ninterface RoutingRule {\n task: TaskType;\n defaultModel: ModelId;\n upgradeIf: (analysis: ProjectAnalysis) => boolean;\n upgradeTo: ModelId;\n reason: string;\n upgradeReason: string;\n}\n\nconst ROUTING_RULES: RoutingRule[] = [\n {\n task: 'simple-edit',\n defaultModel: 'claude-haiku-3.5',\n upgradeIf: () => false,\n upgradeTo: 'claude-haiku-3.5',\n reason: 'Simple edits are best handled by fast models',\n upgradeReason: '',\n },\n {\n task: 'docs',\n defaultModel: 'claude-haiku-3.5',\n upgradeIf: (a) => a.totalTokens > 100_000,\n upgradeTo: 'claude-sonnet-4',\n reason: 'Documentation tasks are straightforward',\n upgradeReason: 'Large codebase — Sonnet provides better understanding',\n },\n {\n task: 'test',\n defaultModel: 'claude-sonnet-4',\n upgradeIf: (a) => a.riskProfile.overallComplexity > 15,\n upgradeTo: 'claude-opus-4',\n reason: 'Test generation requires good code understanding',\n upgradeReason: 'High complexity codebase — Opus for better test coverage',\n },\n {\n task: 'debug',\n defaultModel: 'claude-sonnet-4',\n upgradeIf: (a) => a.riskProfile.distribution.critical > 5,\n upgradeTo: 'claude-opus-4',\n reason: 'Debugging requires solid reasoning about code flow',\n upgradeReason: 'Many critical files involved — Opus for deeper analysis',\n },\n {\n task: 'refactor',\n defaultModel: 'claude-sonnet-4',\n upgradeIf: (a) => a.totalFiles > 50 && a.riskProfile.overallComplexity > 10,\n upgradeTo: 'claude-opus-4',\n reason: 'Refactoring needs good structural understanding',\n upgradeReason: 'Large + complex project — Opus for safer refactoring',\n },\n {\n task: 'review',\n defaultModel: 'claude-sonnet-4',\n upgradeIf: (a) => a.riskProfile.distribution.critical > 3,\n upgradeTo: 'claude-opus-4',\n reason: 'Code review benefits from balanced reasoning',\n upgradeReason: 'Critical code under review — Opus for thorough analysis',\n },\n {\n task: 'feature',\n defaultModel: 'claude-sonnet-4',\n upgradeIf: (a) => a.totalFiles > 100,\n upgradeTo: 'claude-opus-4',\n reason: 'Feature development needs code generation + understanding',\n upgradeReason: 'Large codebase — Opus for better integration',\n },\n {\n task: 'architecture',\n defaultModel: 'claude-opus-4',\n upgradeIf: () => false,\n upgradeTo: 'claude-opus-4',\n reason: 'Architecture decisions require deep reasoning',\n upgradeReason: '',\n },\n];\n\n// ===== TASK CLASSIFICATION =====\n\nconst TASK_KEYWORDS: Record<TaskType, string[]> = {\n debug: ['debug', 'fix', 'bug', 'error', 'issue', 'broken', 'crash', 'failing', 'wrong'],\n review: ['review', 'check', 'assess', 'evaluate', 'audit', 'inspect', 'critique'],\n refactor: ['refactor', 'restructure', 'reorganize', 'clean up', 'simplify', 'extract', 'move'],\n test: ['test', 'spec', 'coverage', 'unit test', 'integration test', 'e2e'],\n docs: ['document', 'docs', 'readme', 'jsdoc', 'comment', 'explain'],\n feature: ['add', 'implement', 'create', 'build', 'new', 'feature', 'endpoint'],\n architecture: ['architecture', 'design', 'system', 'structure', 'migrate', 'pattern'],\n 'simple-edit': ['rename', 'typo', 'update', 'change', 'modify', 'tweak', 'adjust'],\n};\n\nexport function classifyTask(taskDescription: string): TaskType {\n const lower = taskDescription.toLowerCase();\n\n // Score each task type by keyword matches\n let bestType: TaskType = 'simple-edit';\n let bestScore = 0;\n\n for (const [type, keywords] of Object.entries(TASK_KEYWORDS) as [TaskType, string[]][]) {\n let score = 0;\n for (const kw of keywords) {\n if (lower.includes(kw)) score++;\n }\n if (score > bestScore) {\n bestScore = score;\n bestType = type;\n }\n }\n\n return bestType;\n}\n\n// ===== MODEL ROUTING =====\n\nexport function routeModel(\n taskType: TaskType,\n analysis: ProjectAnalysis,\n preferredModel?: ModelId,\n): ModelChoice {\n // If user explicitly chose a model, respect it\n if (preferredModel) {\n const spec = MODEL_REGISTRY.find((m) => m.id === preferredModel);\n if (spec) {\n return {\n model: preferredModel,\n reason: 'User-specified model',\n confidence: 1.0,\n alternatives: buildAlternatives(preferredModel, taskType),\n };\n }\n }\n\n // Find routing rule for this task\n const rule = ROUTING_RULES.find((r) => r.task === taskType);\n if (!rule) {\n return {\n model: 'claude-sonnet-4',\n reason: 'Default model for unrecognized task type',\n confidence: 0.5,\n alternatives: buildAlternatives('claude-sonnet-4', taskType),\n };\n }\n\n // Check if upgrade is warranted\n const shouldUpgrade = rule.upgradeIf(analysis);\n const model = shouldUpgrade ? rule.upgradeTo : rule.defaultModel;\n const reason = shouldUpgrade ? rule.upgradeReason : rule.reason;\n\n return {\n model,\n reason,\n confidence: shouldUpgrade ? 0.8 : 0.9,\n alternatives: buildAlternatives(model, taskType),\n };\n}\n\n// ===== HELPERS =====\n\nfunction buildAlternatives(chosenModel: ModelId, taskType: TaskType) {\n return MODEL_REGISTRY\n .filter((m) => m.id !== chosenModel)\n .map((m) => {\n const chosen = MODEL_REGISTRY.find((r) => r.id === chosenModel)!;\n const costDelta = m.pricing.inputPerMillion - chosen.pricing.inputPerMillion;\n const tradeoff = costDelta > 0\n ? `More capable but ${(costDelta / chosen.pricing.inputPerMillion * 100).toFixed(0)}% more expensive`\n : `${Math.abs(costDelta / chosen.pricing.inputPerMillion * 100).toFixed(0)}% cheaper but less capable`;\n\n return { model: m.id, costDelta, tradeoff };\n });\n}\n\nexport function getModelSpec(modelId: ModelId): ModelSpec | undefined {\n return MODEL_REGISTRY.find((m) => m.id === modelId);\n}\n","import type { StructuredPrompt, PromptSection, TaskType } from '../types/interact.js';\nimport type { ContextSelection, ProjectAnalysis } from '../types/engine.js';\nimport { countTokensChars4 } from '../engine/tokenizer.js';\n\n// ===== STRUCTURED PROMPT BUILDER =====\n//\n// Not templates. Not libraries.\n// Task-aware prompt construction with sections that can be measured and optimized.\n\nexport interface PromptOptions {\n task: string;\n taskType: TaskType;\n analysis: ProjectAnalysis;\n selection: ContextSelection;\n enableCoT?: boolean;\n enableConstraints?: boolean;\n enableAntiHallucination?: boolean;\n}\n\nexport function buildPrompt(options: PromptOptions): StructuredPrompt {\n const {\n task,\n taskType,\n analysis,\n selection,\n enableCoT = true,\n enableConstraints = true,\n enableAntiHallucination = true,\n } = options;\n\n const sections: PromptSection[] = [];\n\n // 1. System section — role priming\n sections.push(buildSystemSection(analysis.stack, taskType));\n\n // 2. Context section — project info + selected files\n sections.push(buildContextSection(analysis, selection));\n\n // 3. Task section — what the user wants\n sections.push(buildTaskSection(task, taskType));\n\n // 4. Constraints section — safety rails\n if (enableConstraints) {\n sections.push(buildConstraintsSection(analysis.stack, taskType));\n }\n\n // 5. Chain-of-thought section\n if (enableCoT) {\n sections.push(buildCoTSection(taskType));\n }\n\n // 6. Anti-hallucination section\n if (enableAntiHallucination) {\n sections.push(buildAntiHallucinationSection());\n }\n\n // 7. Output format section\n sections.push(buildFormatSection(taskType));\n\n const rendered = sections.map((s) => s.content).join('\\n\\n---\\n\\n');\n const totalTokens = sections.reduce((s, sec) => s + sec.tokens, 0);\n\n return { sections, totalTokens, rendered };\n}\n\n// ===== SECTION BUILDERS =====\n\nfunction buildSystemSection(stack: string[], taskType: TaskType): PromptSection {\n const stackStr = stack.length > 0 ? stack.join(', ') : 'software';\n const taskRole = TASK_ROLES[taskType] ?? 'engineer';\n\n const content = [\n `You are a senior ${stackStr} ${taskRole} with deep expertise in clean architecture, testing, and production-quality code.`,\n 'You prioritize correctness, readability, and maintainability.',\n 'You never make assumptions without evidence from the code.',\n ].join(' ');\n\n return makeSection('system', 'system', content);\n}\n\nfunction buildContextSection(\n analysis: ProjectAnalysis,\n selection: ContextSelection,\n): PromptSection {\n const lines: string[] = [];\n\n lines.push(`## Project: ${analysis.projectName}`);\n lines.push(`Stack: ${analysis.stack.join(', ') || 'Unknown'}`);\n lines.push(`Files analyzed: ${analysis.totalFiles} | Tokens: ~${Math.round(analysis.totalTokens / 1000)}K`);\n lines.push(`Context coverage: ${selection.coverage.score}% | Risk score: ${selection.riskScore}/100`);\n lines.push('');\n\n // List included files with their prune levels\n lines.push('### Included Files');\n lines.push('');\n\n const fullFiles = selection.files.filter((f) => f.pruneLevel === 'full');\n const sigFiles = selection.files.filter((f) => f.pruneLevel === 'signatures');\n const skelFiles = selection.files.filter((f) => f.pruneLevel === 'skeleton');\n\n if (fullFiles.length > 0) {\n lines.push('**Full content (read these first):**');\n for (const f of fullFiles) {\n lines.push(`- \\`${f.relativePath}\\` (~${Math.round(f.tokens / 1000)}K tokens) — ${f.reason}`);\n }\n lines.push('');\n }\n\n if (sigFiles.length > 0) {\n lines.push('**Signatures only (reference as needed):**');\n for (const f of sigFiles) {\n lines.push(`- \\`${f.relativePath}\\` (~${Math.round(f.tokens / 1000)}K tokens)`);\n }\n lines.push('');\n }\n\n if (skelFiles.length > 0) {\n lines.push('**Skeleton (structure overview):**');\n for (const f of skelFiles) {\n lines.push(`- \\`${f.relativePath}\\``);\n }\n lines.push('');\n }\n\n if (selection.coverage.missingCritical.length > 0) {\n lines.push('⚠️ **Missing critical files** (not included due to budget):');\n for (const f of selection.coverage.missingCritical) {\n lines.push(`- \\`${f}\\``);\n }\n lines.push('');\n }\n\n const content = lines.join('\\n');\n return makeSection('context', 'context', content);\n}\n\nfunction buildTaskSection(task: string, taskType: TaskType): PromptSection {\n const content = [\n '## Task',\n '',\n task,\n '',\n `Task type: **${taskType}**`,\n ].join('\\n');\n\n return makeSection('task', 'task', content);\n}\n\nfunction buildConstraintsSection(stack: string[], taskType: TaskType): PromptSection {\n const lines: string[] = ['## Constraints', ''];\n\n lines.push('- **Do NOT** delete or modify existing tests unless explicitly asked');\n lines.push('- **Do NOT** change function signatures that are part of the public API');\n lines.push('- **Do NOT** introduce new dependencies without mentioning it');\n lines.push('- **Always** handle errors explicitly (no silent catches)');\n lines.push('- **Always** preserve existing code style and conventions');\n lines.push('- **Prefer** minimal changes — smallest diff that solves the problem');\n\n if (stack.includes('TypeScript')) {\n lines.push('- **Always** use strict TypeScript types (no `any` unless unavoidable)');\n lines.push('- **Always** add explicit return types to exported functions');\n }\n\n if (taskType === 'refactor') {\n lines.push('- **Do NOT** change behavior — refactoring must be behavior-preserving');\n lines.push('- **Verify** all existing tests still pass after changes');\n }\n\n if (taskType === 'test') {\n lines.push('- Use AAA pattern: Arrange, Act, Assert');\n lines.push('- Test boundaries, null/undefined, async errors, type edges');\n lines.push('- Use descriptive test names: \"should [expected] when [condition]\"');\n }\n\n return makeSection('constraints', 'constraints', lines.join('\\n'));\n}\n\nfunction buildCoTSection(taskType: TaskType): PromptSection {\n const steps = COT_STEPS[taskType] ?? COT_STEPS['simple-edit'];\n\n const lines: string[] = ['## Thinking Process', '', 'Before writing any code:'];\n steps.forEach((step, i) => {\n lines.push(`${i + 1}. ${step}`);\n });\n\n return makeSection('cot', 'constraints', lines.join('\\n'));\n}\n\nfunction buildAntiHallucinationSection(): PromptSection {\n const content = [\n '## Important',\n '',\n '- Only reference files, functions, and APIs that exist in the provided context',\n '- If you are unsure about something, say so explicitly',\n '- Do NOT invent function signatures, types, or module paths',\n '- If the context is insufficient to complete the task, explain what is missing',\n ].join('\\n');\n\n return makeSection('anti-hallucination', 'constraints', content);\n}\n\nfunction buildFormatSection(taskType: TaskType): PromptSection {\n const lines: string[] = ['## Output Format', ''];\n\n if (taskType === 'review') {\n lines.push('Provide findings in priority order: Critical > Major > Minor > Nitpick');\n lines.push('For each finding: file, line, issue, and concrete suggestion with code');\n } else if (taskType === 'architecture') {\n lines.push('Present 2-3 options with trade-offs, then recommend one with justification');\n } else if (taskType === 'debug') {\n lines.push('1. Root cause analysis');\n lines.push('2. Minimal fix');\n lines.push('3. Explanation of why the fix works');\n lines.push('4. Edge cases to consider');\n } else {\n lines.push('Provide clean, production-ready code with brief explanations of key decisions');\n }\n\n return makeSection('format', 'format', lines.join('\\n'));\n}\n\n// ===== CONSTANTS =====\n\nconst TASK_ROLES: Record<TaskType, string> = {\n debug: 'debugger',\n review: 'code reviewer',\n refactor: 'architect',\n test: 'test engineer',\n docs: 'technical writer',\n feature: 'engineer',\n architecture: 'systems architect',\n 'simple-edit': 'engineer',\n};\n\nconst COT_STEPS: Record<TaskType, string[]> = {\n debug: [\n '**Reproduce** — Understand the exact symptom and when it occurs',\n '**Hypothesize** — List the most likely root causes (max 3)',\n '**Verify** — Check each hypothesis against the code',\n '**Fix** — Apply the minimal fix that addresses the root cause',\n '**Validate** — Explain why the fix works and what edge cases it covers',\n ],\n review: [\n '**Understand** — Read the code and understand its purpose',\n '**Assess** — Evaluate correctness, readability, performance, security',\n '**Prioritize** — Rank issues by severity (critical > major > minor)',\n '**Suggest** — Provide concrete, actionable improvements with code',\n ],\n refactor: [\n '**Analyze** — Identify code smells and structural issues',\n '**Plan** — Define the target structure before changing anything',\n '**Preserve** — Ensure behavior doesn\\'t change',\n '**Refactor** — Apply changes incrementally',\n '**Verify** — Confirm all existing tests still pass',\n ],\n test: [\n '**Identify** — What needs testing? (happy path, edge cases, errors)',\n '**Structure** — Use AAA pattern: Arrange, Act, Assert',\n '**Cover** — Test boundaries, null/undefined, async errors',\n '**Isolate** — Mock external dependencies, test units independently',\n ],\n docs: [\n '**Read** — Understand the code before documenting',\n '**Structure** — Organize by audience (API users, contributors, operators)',\n '**Write** — Clear, concise, with examples',\n ],\n feature: [\n '**Clarify** — Restate the requirement in your own words',\n '**Design** — Plan the approach (types, interfaces, flow)',\n '**Implement** — Build incrementally, starting with types',\n '**Test** — Write tests alongside implementation',\n '**Integrate** — Ensure no regressions',\n ],\n architecture: [\n '**Context** — Understand current architecture and constraints',\n '**Options** — Present 2-3 viable approaches with trade-offs',\n '**Recommend** — Choose the best and explain why',\n '**Plan** — Define migration steps',\n '**Risks** — Identify risks and mitigation strategies',\n ],\n 'simple-edit': [\n '**Understand** — Read the relevant code',\n '**Plan** — Think before writing',\n '**Implement** — Write clean, well-typed code',\n '**Verify** — Check for edge cases',\n ],\n};\n\n// ===== HELPERS =====\n\nfunction makeSection(\n id: string,\n role: PromptSection['role'],\n content: string,\n): PromptSection {\n const tokens = countTokensChars4(Buffer.byteLength(content, 'utf-8'));\n return { id, role, content, tokens };\n}\n","import { resolve, join } from 'node:path';\nimport { readFile, writeFile, mkdir } from 'node:fs/promises';\nimport type { ProjectAnalysis, AnalyzedFile } from '../types/engine.js';\nimport type { TaskType } from '../types/interact.js';\nimport { classifyTask } from '../interact/router.js';\nimport { buildAdjacencyList, bfsBidirectional } from './graph-utils.js';\n\n// ===== ML-based Context Predictor =====\n//\n// Learns from past context selections to improve future ones.\n//\n// How it works:\n// 1. Every time context is selected, record: (taskType, keywords) → selectedFiles\n// 2. Build a frequency model: for each (taskType, keyword) pair, track which files\n// were selected and how often\n// 3. On future selections, boost files that were historically useful for similar tasks\n//\n// Storage: .cto/predictor.json (per-project)\n//\n// This is a simple frequency-based approach (not a neural net), but it:\n// - Learns from YOUR usage patterns\n// - Gets better over time\n// - Is fully transparent (you can inspect the model)\n// - Works offline, no API calls\n\nexport interface PredictorModel {\n version: number;\n trainedAt: string;\n totalObservations: number;\n\n // taskType → { filePath → selectionCount }\n taskTypeFrequency: Record<string, Record<string, number>>;\n\n // keyword → { filePath → selectionCount }\n keywordFrequency: Record<string, Record<string, number>>;\n\n // filePath → { totalSelections, avgRiskScore, avgTokens }\n fileStats: Record<string, {\n totalSelections: number;\n avgRiskScore: number;\n avgTokens: number;\n lastSelected: string;\n }>;\n\n // Co-occurrence: when file A is selected, file B is also selected\n coSelection: Record<string, Record<string, number>>;\n}\n\nexport interface PredictionResult {\n filePath: string;\n predictedScore: number;\n reasons: string[];\n}\n\nexport interface PredictorConfig {\n maxCoSelectionPairs: number;\n decayFactor: number;\n minObservations: number;\n}\n\nconst DEFAULT_PREDICTOR_CONFIG: PredictorConfig = {\n maxCoSelectionPairs: 500,\n decayFactor: 0.95, // slight decay to favor recent patterns\n minObservations: 2, // need at least 2 observations before predicting\n};\n\n// ===== LOAD / SAVE =====\n\nasync function getModelPath(projectPath: string): Promise<string> {\n const ctoDir = join(resolve(projectPath), '.cto');\n await mkdir(ctoDir, { recursive: true });\n return join(ctoDir, 'predictor.json');\n}\n\nexport async function loadModel(projectPath: string): Promise<PredictorModel> {\n try {\n const path = await getModelPath(projectPath);\n const raw = await readFile(path, 'utf-8');\n return JSON.parse(raw);\n } catch {\n return createEmptyModel();\n }\n}\n\nexport async function saveModel(projectPath: string, model: PredictorModel): Promise<void> {\n const path = await getModelPath(projectPath);\n await writeFile(path, JSON.stringify(model, null, 2));\n}\n\nfunction createEmptyModel(): PredictorModel {\n return {\n version: 1,\n trainedAt: new Date().toISOString(),\n totalObservations: 0,\n taskTypeFrequency: {},\n keywordFrequency: {},\n fileStats: {},\n coSelection: {},\n };\n}\n\n// ===== TRAINING (record an observation) =====\n\nexport async function recordSelection(\n projectPath: string,\n task: string,\n selectedFiles: { relativePath: string; riskScore: number; tokens: number }[],\n): Promise<PredictorModel> {\n const model = await loadModel(projectPath);\n const taskType = classifyTask(task);\n const keywords = extractKeywords(task);\n\n model.totalObservations++;\n model.trainedAt = new Date().toISOString();\n\n const selectedPaths = selectedFiles.map((f) => f.relativePath);\n\n // 1. Update taskType → file frequency\n if (!model.taskTypeFrequency[taskType]) {\n model.taskTypeFrequency[taskType] = {};\n }\n for (const path of selectedPaths) {\n model.taskTypeFrequency[taskType][path] = (model.taskTypeFrequency[taskType][path] ?? 0) + 1;\n }\n\n // 2. Update keyword → file frequency\n for (const kw of keywords) {\n if (!model.keywordFrequency[kw]) {\n model.keywordFrequency[kw] = {};\n }\n for (const path of selectedPaths) {\n model.keywordFrequency[kw][path] = (model.keywordFrequency[kw][path] ?? 0) + 1;\n }\n }\n\n // 3. Update file stats\n for (const file of selectedFiles) {\n const existing = model.fileStats[file.relativePath];\n if (existing) {\n const n = existing.totalSelections;\n existing.totalSelections = n + 1;\n existing.avgRiskScore = (existing.avgRiskScore * n + file.riskScore) / (n + 1);\n existing.avgTokens = (existing.avgTokens * n + file.tokens) / (n + 1);\n existing.lastSelected = new Date().toISOString();\n } else {\n model.fileStats[file.relativePath] = {\n totalSelections: 1,\n avgRiskScore: file.riskScore,\n avgTokens: file.tokens,\n lastSelected: new Date().toISOString(),\n };\n }\n }\n\n // 4. Update co-selection (top pairs only to limit model size)\n const topFiles = selectedPaths.slice(0, 20); // only track top 20 per observation\n for (let i = 0; i < topFiles.length; i++) {\n const a = topFiles[i];\n if (!model.coSelection[a]) model.coSelection[a] = {};\n for (let j = i + 1; j < topFiles.length; j++) {\n const b = topFiles[j];\n model.coSelection[a][b] = (model.coSelection[a][b] ?? 0) + 1;\n if (!model.coSelection[b]) model.coSelection[b] = {};\n model.coSelection[b][a] = (model.coSelection[b][a] ?? 0) + 1;\n }\n }\n\n // Prune co-selection if too large\n pruneCoSelection(model, DEFAULT_PREDICTOR_CONFIG.maxCoSelectionPairs);\n\n await saveModel(projectPath, model);\n return model;\n}\n\n// ===== PREDICTION =====\n\nexport async function predictRelevantFiles(\n projectPath: string,\n task: string,\n analysis: ProjectAnalysis,\n config: Partial<PredictorConfig> = {},\n): Promise<PredictionResult[]> {\n const cfg = { ...DEFAULT_PREDICTOR_CONFIG, ...config };\n const model = await loadModel(projectPath);\n\n if (model.totalObservations < cfg.minObservations) {\n return []; // not enough data to predict\n }\n\n const taskType = classifyTask(task);\n const keywords = extractKeywords(task);\n const scores = new Map<string, { score: number; reasons: string[] }>();\n\n // Helper to add score\n const boost = (path: string, amount: number, reason: string) => {\n const existing = scores.get(path) ?? { score: 0, reasons: [] };\n existing.score += amount;\n existing.reasons.push(reason);\n scores.set(path, existing);\n };\n\n // 1. TaskType frequency boost (weight: 3x)\n const taskFreqs = model.taskTypeFrequency[taskType];\n if (taskFreqs) {\n const maxFreq = Math.max(...Object.values(taskFreqs));\n for (const [path, freq] of Object.entries(taskFreqs)) {\n const normalized = maxFreq > 0 ? freq / maxFreq : 0;\n boost(path, normalized * 30, `${taskType} task history (${freq}× selected)`);\n }\n }\n\n // 2. Keyword frequency boost (weight: 2x per keyword)\n for (const kw of keywords) {\n const kwFreqs = model.keywordFrequency[kw];\n if (kwFreqs) {\n const maxFreq = Math.max(...Object.values(kwFreqs));\n for (const [path, freq] of Object.entries(kwFreqs)) {\n const normalized = maxFreq > 0 ? freq / maxFreq : 0;\n boost(path, normalized * 20, `keyword \"${kw}\" (${freq}× selected)`);\n }\n }\n }\n\n // 3. General selection frequency boost (weight: 1x)\n for (const [path, stats] of Object.entries(model.fileStats)) {\n const freqRatio = model.totalObservations > 0\n ? stats.totalSelections / model.totalObservations\n : 0;\n if (freqRatio > 0.3) { // selected in >30% of all observations\n boost(path, freqRatio * 10, `frequently selected (${stats.totalSelections}/${model.totalObservations})`);\n }\n }\n\n // 4. Co-selection boost — if high-score files have co-selected partners, boost them\n const topPredicted = [...scores.entries()]\n .sort((a, b) => b[1].score - a[1].score)\n .slice(0, 10)\n .map(([path]) => path);\n\n for (const topPath of topPredicted) {\n const coFiles = model.coSelection[topPath];\n if (coFiles) {\n for (const [coPath, count] of Object.entries(coFiles)) {\n if (count >= 2) {\n boost(coPath, count * 2, `co-selected with ${topPath} (${count}×)`);\n }\n }\n }\n }\n\n // Filter to files that exist in the current analysis\n const existingPaths = new Set(analysis.files.map((f) => f.relativePath));\n const results: PredictionResult[] = [];\n\n for (const [path, data] of scores) {\n if (existingPaths.has(path)) {\n results.push({\n filePath: path,\n predictedScore: Math.round(data.score * 10) / 10,\n reasons: data.reasons.slice(0, 5),\n });\n }\n }\n\n return results\n .sort((a, b) => b.predictedScore - a.predictedScore)\n .slice(0, 50); // top 50 predictions\n}\n\n// ===== INTEGRATION: boost selector scores =====\n\nexport async function getPredictorBoosts(\n projectPath: string,\n task: string,\n analysis: ProjectAnalysis,\n): Promise<Map<string, number>> {\n const predictions = await predictRelevantFiles(projectPath, task, analysis);\n const boosts = new Map<string, number>();\n\n if (predictions.length === 0) return boosts;\n\n // Normalize to 0-10 boost range\n const maxScore = predictions[0]?.predictedScore ?? 1;\n for (const p of predictions) {\n const normalized = maxScore > 0 ? (p.predictedScore / maxScore) * 10 : 0;\n boosts.set(p.filePath, normalized);\n }\n\n return boosts;\n}\n\n// ===== MODEL STATS =====\n\nexport function getModelStats(model: PredictorModel): {\n observations: number;\n taskTypes: number;\n keywords: number;\n trackedFiles: number;\n coSelectionPairs: number;\n trainedAt: string;\n} {\n const coSelectionPairs = Object.values(model.coSelection)\n .reduce((s, pairs) => s + Object.keys(pairs).length, 0) / 2;\n\n return {\n observations: model.totalObservations,\n taskTypes: Object.keys(model.taskTypeFrequency).length,\n keywords: Object.keys(model.keywordFrequency).length,\n trackedFiles: Object.keys(model.fileStats).length,\n coSelectionPairs: Math.round(coSelectionPairs),\n trainedAt: model.trainedAt,\n };\n}\n\n// ===== HELPERS =====\n\nfunction extractKeywords(task: string): string[] {\n const stopWords = new Set([\n 'the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been', 'being',\n 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could',\n 'should', 'may', 'might', 'can', 'shall', 'to', 'of', 'in', 'for',\n 'on', 'with', 'at', 'by', 'from', 'as', 'into', 'through', 'and',\n 'but', 'or', 'not', 'this', 'that', 'it', 'its',\n 'fix', 'add', 'remove', 'update', 'change', 'refactor', 'implement',\n 'create', 'build', 'make', 'code', 'file', 'module', 'function',\n ]);\n\n return task\n .toLowerCase()\n .replace(/[^a-z0-9\\s]/g, '')\n .split(/\\s+/)\n .filter((w) => w.length > 2 && !stopWords.has(w));\n}\n\nfunction pruneCoSelection(model: PredictorModel, maxPairs: number): void {\n const totalPairs = Object.values(model.coSelection)\n .reduce((s, pairs) => s + Object.keys(pairs).length, 0) / 2;\n\n if (totalPairs <= maxPairs) return;\n\n // Collect all pairs with their counts\n const allPairs: { a: string; b: string; count: number }[] = [];\n for (const [a, pairs] of Object.entries(model.coSelection)) {\n for (const [b, count] of Object.entries(pairs)) {\n if (a < b) allPairs.push({ a, b, count });\n }\n }\n\n // Sort by count descending, keep top maxPairs\n allPairs.sort((x, y) => y.count - x.count);\n const keep = new Set(allPairs.slice(0, maxPairs).map((p) => `${p.a}|${p.b}`));\n\n // Rebuild\n model.coSelection = {};\n for (const pair of allPairs) {\n if (keep.has(`${pair.a}|${pair.b}`)) {\n if (!model.coSelection[pair.a]) model.coSelection[pair.a] = {};\n if (!model.coSelection[pair.b]) model.coSelection[pair.b] = {};\n model.coSelection[pair.a][pair.b] = pair.count;\n model.coSelection[pair.b][pair.a] = pair.count;\n }\n }\n}\n","import { resolve, join, basename } from 'node:path';\nimport { readFile, writeFile, mkdir } from 'node:fs/promises';\nimport type { ProjectAnalysis, AnalyzedFile } from '../types/engine.js';\nimport type { TaskType } from '../types/interact.js';\nimport { classifyTask } from '../interact/router.js';\n\n// ===== Cross-Repo Intelligence =====\n//\n// Learns patterns ACROSS repositories:\n// - \"When working on auth in Express-like projects, these file patterns matter\"\n// - \"TypeScript projects with >200 files always need types/*.ts for refactoring\"\n// - \"Test tasks in monorepos need the shared fixtures directory\"\n//\n// This is the MOAT. Cursor/Copilot optimize per-file.\n// We optimize per-project-archetype × task-type.\n//\n// How it works:\n// 1. Every project gets a \"fingerprint\": { stack, size-class, structure-pattern }\n// 2. Every selection is recorded with: fingerprint × taskType × file-patterns\n// 3. On new projects, match fingerprint → predict useful patterns\n//\n// Storage: ~/.cto/global-intelligence.json (cross-project, user-level)\n\nexport interface ProjectFingerprint {\n stack: string[];\n sizeClass: 'tiny' | 'small' | 'medium' | 'large' | 'huge';\n hasTypes: boolean;\n hasTests: boolean;\n isMonorepo: boolean;\n entryPointPatterns: string[];\n dominantLanguage: string;\n}\n\nexport interface CrossRepoModel {\n version: number;\n updatedAt: string;\n totalProjects: number;\n totalObservations: number;\n\n // fingerprint-hash → archetype name\n archetypes: Record<string, ArchetypeProfile>;\n\n // Patterns that work across ALL archetypes\n universalPatterns: PatternStats[];\n}\n\nexport interface ArchetypeProfile {\n name: string;\n fingerprint: ProjectFingerprint;\n projectCount: number;\n observationCount: number;\n\n // taskType → file pattern → { hitRate, avgRelevanceBoost }\n taskPatterns: Record<string, Record<string, PatternStats>>;\n\n // File kinds that are always important for this archetype\n criticalKinds: { kind: string; importance: number }[];\n\n // Directory patterns that matter\n criticalDirs: { pattern: string; importance: number }[];\n}\n\nexport interface PatternStats {\n pattern: string;\n hitCount: number;\n totalSelections: number;\n hitRate: number;\n avgRelevanceBoost: number;\n}\n\nexport interface CrossRepoPrediction {\n filePath: string;\n boost: number;\n reason: string;\n confidence: number; // 0-1, based on how many observations back this\n}\n\n// ===== FINGERPRINTING =====\n\nexport function computeFingerprint(analysis: ProjectAnalysis): ProjectFingerprint {\n const totalFiles = analysis.totalFiles;\n\n const sizeClass: ProjectFingerprint['sizeClass'] =\n totalFiles < 20 ? 'tiny'\n : totalFiles < 100 ? 'small'\n : totalFiles < 500 ? 'medium'\n : totalFiles < 2000 ? 'large'\n : 'huge';\n\n const hasTypes = analysis.files.some((f) => f.kind === 'type');\n const hasTests = analysis.files.some((f) => f.kind === 'test');\n\n // Detect monorepo: has packages/ or apps/ with multiple package.json\n const isMonorepo = analysis.files.some((f) =>\n f.relativePath.startsWith('packages/') || f.relativePath.startsWith('apps/')\n );\n\n const entryPointPatterns = analysis.files\n .filter((f) => f.kind === 'entry')\n .map((f) => extractPattern(f.relativePath))\n .filter((p, i, arr) => arr.indexOf(p) === i)\n .slice(0, 5);\n\n // Dominant language from stack\n const dominantLanguage = analysis.stack[0] ?? 'unknown';\n\n return {\n stack: analysis.stack.slice(0, 5),\n sizeClass,\n hasTypes,\n hasTests,\n isMonorepo,\n entryPointPatterns,\n dominantLanguage,\n };\n}\n\nfunction extractPattern(filePath: string): string {\n // Convert specific path to pattern: src/engine/analyzer.ts → src/*/analyzer.*\n const parts = filePath.split('/');\n if (parts.length <= 1) return filePath;\n if (parts.length === 2) return `${parts[0]}/*`;\n return `${parts[0]}/*/${basename(filePath).replace(/\\.[^.]+$/, '.*')}`;\n}\n\nfunction fingerprintHash(fp: ProjectFingerprint): string {\n return `${fp.dominantLanguage}_${fp.sizeClass}_${fp.hasTypes ? 'T' : 'F'}${fp.hasTests ? 'T' : 'F'}${fp.isMonorepo ? 'M' : 'S'}`;\n}\n\n// ===== MODEL STORAGE =====\n\nfunction getGlobalModelPath(): string {\n const home = process.env.HOME ?? process.env.USERPROFILE ?? '/tmp';\n return join(home, '.cto', 'global-intelligence.json');\n}\n\nexport async function loadGlobalModel(): Promise<CrossRepoModel> {\n try {\n const raw = await readFile(getGlobalModelPath(), 'utf-8');\n return JSON.parse(raw);\n } catch {\n return createEmptyModel();\n }\n}\n\nexport async function saveGlobalModel(model: CrossRepoModel): Promise<void> {\n const dir = join(getGlobalModelPath(), '..');\n await mkdir(dir, { recursive: true });\n await writeFile(getGlobalModelPath(), JSON.stringify(model, null, 2));\n}\n\nfunction createEmptyModel(): CrossRepoModel {\n return {\n version: 1,\n updatedAt: new Date().toISOString(),\n totalProjects: 0,\n totalObservations: 0,\n archetypes: {},\n universalPatterns: [],\n };\n}\n\n// ===== TRAINING =====\n\nexport async function recordCrossRepoSelection(\n analysis: ProjectAnalysis,\n task: string,\n selectedFiles: { relativePath: string; riskScore: number; tokens: number }[],\n): Promise<CrossRepoModel> {\n const model = await loadGlobalModel();\n const fp = computeFingerprint(analysis);\n const hash = fingerprintHash(fp);\n const taskType = classifyTask(task);\n\n model.totalObservations++;\n model.updatedAt = new Date().toISOString();\n\n // Get or create archetype\n if (!model.archetypes[hash]) {\n model.totalProjects++;\n model.archetypes[hash] = {\n name: `${fp.dominantLanguage}-${fp.sizeClass}${fp.isMonorepo ? '-monorepo' : ''}`,\n fingerprint: fp,\n projectCount: 1,\n observationCount: 0,\n taskPatterns: {},\n criticalKinds: [],\n criticalDirs: [],\n };\n }\n\n const archetype = model.archetypes[hash];\n archetype.observationCount++;\n\n // Record file patterns for this task type\n if (!archetype.taskPatterns[taskType]) {\n archetype.taskPatterns[taskType] = {};\n }\n\n const patterns = archetype.taskPatterns[taskType];\n\n for (const file of selectedFiles) {\n const pattern = extractPattern(file.relativePath);\n if (!patterns[pattern]) {\n patterns[pattern] = {\n pattern,\n hitCount: 0,\n totalSelections: 0,\n hitRate: 0,\n avgRelevanceBoost: 0,\n };\n }\n const p = patterns[pattern];\n p.hitCount++;\n p.totalSelections = archetype.observationCount;\n p.hitRate = p.hitCount / p.totalSelections;\n // Boost proportional to risk score (higher risk = more important)\n p.avgRelevanceBoost = (p.avgRelevanceBoost * (p.hitCount - 1) + file.riskScore) / p.hitCount;\n }\n\n // Update critical kinds\n const kindCounts = new Map<string, number>();\n for (const file of selectedFiles) {\n const af = analysis.files.find((f) => f.relativePath === file.relativePath);\n if (af) {\n kindCounts.set(af.kind, (kindCounts.get(af.kind) ?? 0) + 1);\n }\n }\n archetype.criticalKinds = [...kindCounts.entries()]\n .map(([kind, count]) => ({ kind, importance: count / selectedFiles.length }))\n .sort((a, b) => b.importance - a.importance)\n .slice(0, 10);\n\n // Update critical dirs\n const dirCounts = new Map<string, number>();\n for (const file of selectedFiles) {\n const dir = file.relativePath.split('/').slice(0, -1).join('/');\n if (dir) dirCounts.set(dir, (dirCounts.get(dir) ?? 0) + 1);\n }\n archetype.criticalDirs = [...dirCounts.entries()]\n .map(([pattern, count]) => ({ pattern, importance: count / selectedFiles.length }))\n .sort((a, b) => b.importance - a.importance)\n .slice(0, 10);\n\n // Update universal patterns (patterns that appear in >50% of archetypes)\n updateUniversalPatterns(model);\n\n await saveGlobalModel(model);\n return model;\n}\n\nfunction updateUniversalPatterns(model: CrossRepoModel): void {\n const patternCounts = new Map<string, { count: number; totalBoost: number }>();\n const archetypeCount = Object.keys(model.archetypes).length;\n\n for (const archetype of Object.values(model.archetypes)) {\n const seenPatterns = new Set<string>();\n for (const taskPatterns of Object.values(archetype.taskPatterns)) {\n for (const [pattern, stats] of Object.entries(taskPatterns)) {\n if (!seenPatterns.has(pattern)) {\n seenPatterns.add(pattern);\n const entry = patternCounts.get(pattern) ?? { count: 0, totalBoost: 0 };\n entry.count++;\n entry.totalBoost += stats.avgRelevanceBoost;\n patternCounts.set(pattern, entry);\n }\n }\n }\n }\n\n model.universalPatterns = [...patternCounts.entries()]\n .filter(([_, data]) => data.count / archetypeCount > 0.5) // >50% of archetypes\n .map(([pattern, data]) => ({\n pattern,\n hitCount: data.count,\n totalSelections: archetypeCount,\n hitRate: data.count / archetypeCount,\n avgRelevanceBoost: data.totalBoost / data.count,\n }))\n .sort((a, b) => b.hitRate - a.hitRate)\n .slice(0, 20);\n}\n\n// ===== PREDICTION =====\n\nexport async function predictFromCrossRepo(\n analysis: ProjectAnalysis,\n task: string,\n): Promise<CrossRepoPrediction[]> {\n const model = await loadGlobalModel();\n const fp = computeFingerprint(analysis);\n const hash = fingerprintHash(fp);\n const taskType = classifyTask(task);\n\n const predictions: CrossRepoPrediction[] = [];\n\n // 1. Match exact archetype\n const archetype = model.archetypes[hash];\n if (archetype && archetype.observationCount >= 2) {\n const taskPatterns = archetype.taskPatterns[taskType] ?? {};\n\n for (const file of analysis.files) {\n const pattern = extractPattern(file.relativePath);\n const stats = taskPatterns[pattern];\n\n if (stats && stats.hitRate > 0.3) {\n predictions.push({\n filePath: file.relativePath,\n boost: stats.hitRate * stats.avgRelevanceBoost / 10,\n reason: `pattern \"${pattern}\" selected ${Math.round(stats.hitRate * 100)}% of the time for ${taskType} tasks in ${archetype.name} projects`,\n confidence: Math.min(1, archetype.observationCount / 10),\n });\n }\n }\n\n // Critical kind boost\n for (const file of analysis.files) {\n const af = analysis.files.find((f) => f.relativePath === file.relativePath);\n if (!af) continue;\n const critKind = archetype.criticalKinds.find((k) => k.kind === af.kind);\n if (critKind && critKind.importance > 0.2) {\n const existing = predictions.find((p) => p.filePath === file.relativePath);\n if (existing) {\n existing.boost += critKind.importance * 3;\n existing.reason += ` + ${af.kind} files are critical (${Math.round(critKind.importance * 100)}%)`;\n } else {\n predictions.push({\n filePath: file.relativePath,\n boost: critKind.importance * 3,\n reason: `${af.kind} files are critical in ${archetype.name} projects (${Math.round(critKind.importance * 100)}%)`,\n confidence: Math.min(1, archetype.observationCount / 10),\n });\n }\n }\n }\n }\n\n // 2. Similar archetype matching (fuzzy)\n for (const [otherHash, otherArchetype] of Object.entries(model.archetypes)) {\n if (otherHash === hash) continue;\n const similarity = computeSimilarity(fp, otherArchetype.fingerprint);\n if (similarity < 0.5) continue;\n\n const taskPatterns = otherArchetype.taskPatterns[taskType] ?? {};\n for (const file of analysis.files) {\n const pattern = extractPattern(file.relativePath);\n const stats = taskPatterns[pattern];\n\n if (stats && stats.hitRate > 0.5) {\n const existing = predictions.find((p) => p.filePath === file.relativePath);\n const boost = stats.hitRate * similarity * stats.avgRelevanceBoost / 20;\n if (existing) {\n existing.boost += boost;\n } else {\n predictions.push({\n filePath: file.relativePath,\n boost,\n reason: `similar project pattern (${otherArchetype.name}, ${Math.round(similarity * 100)}% match)`,\n confidence: similarity * Math.min(1, otherArchetype.observationCount / 10),\n });\n }\n }\n }\n }\n\n // 3. Universal patterns boost\n for (const universalPattern of model.universalPatterns) {\n for (const file of analysis.files) {\n const pattern = extractPattern(file.relativePath);\n if (pattern === universalPattern.pattern) {\n const existing = predictions.find((p) => p.filePath === file.relativePath);\n if (existing) {\n existing.boost += universalPattern.hitRate * 2;\n } else {\n predictions.push({\n filePath: file.relativePath,\n boost: universalPattern.hitRate * 2,\n reason: `universal pattern across ${universalPattern.hitCount} project types`,\n confidence: universalPattern.hitRate,\n });\n }\n }\n }\n }\n\n return predictions\n .sort((a, b) => b.boost - a.boost)\n .slice(0, 50);\n}\n\nfunction computeSimilarity(a: ProjectFingerprint, b: ProjectFingerprint): number {\n let score = 0;\n let maxScore = 0;\n\n // Language match (most important)\n maxScore += 3;\n if (a.dominantLanguage === b.dominantLanguage) score += 3;\n\n // Size class proximity\n maxScore += 2;\n const sizes = ['tiny', 'small', 'medium', 'large', 'huge'];\n const aDist = sizes.indexOf(a.sizeClass);\n const bDist = sizes.indexOf(b.sizeClass);\n const sizeDiff = Math.abs(aDist - bDist);\n score += Math.max(0, 2 - sizeDiff);\n\n // Structural matches\n maxScore += 1; if (a.hasTypes === b.hasTypes) score += 1;\n maxScore += 1; if (a.hasTests === b.hasTests) score += 1;\n maxScore += 1; if (a.isMonorepo === b.isMonorepo) score += 1;\n\n // Stack overlap\n maxScore += 2;\n const stackOverlap = a.stack.filter((s) => b.stack.includes(s)).length;\n const maxStack = Math.max(a.stack.length, b.stack.length, 1);\n score += (stackOverlap / maxStack) * 2;\n\n return score / maxScore;\n}\n\n// ===== STATS =====\n\nexport function getCrossRepoStats(model: CrossRepoModel): {\n totalProjects: number;\n totalObservations: number;\n archetypes: { name: string; projects: number; observations: number }[];\n universalPatterns: number;\n} {\n return {\n totalProjects: model.totalProjects,\n totalObservations: model.totalObservations,\n archetypes: Object.values(model.archetypes).map((a) => ({\n name: a.name,\n projects: a.projectCount,\n observations: a.observationCount,\n })),\n universalPatterns: model.universalPatterns.length,\n };\n}\n","import { resolve, join } from 'node:path';\nimport { readFile, writeFile, mkdir } from 'node:fs/promises';\nimport type { ProjectAnalysis } from '../types/engine.js';\nimport type { TaskType } from '../types/interact.js';\nimport { classifyTask } from '../interact/router.js';\n\n// ===== Output Feedback Loop =====\n//\n// The flywheel that makes CTO impossible to replicate:\n//\n// 1. User asks AI to do a task with CTO context\n// 2. AI generates code\n// 3. User ACCEPTS or REJECTS the output\n// 4. CTO records: { task, context, outcome }\n// 5. Over time: learn which context selections lead to ACCEPTED outputs\n//\n// This creates a feedback loop:\n// More users → more feedback → better selections → more users\n//\n// Metrics tracked per context selection:\n// - accepted: boolean (user kept the code)\n// - compilable: boolean (code passed type check)\n// - testsPassed: number (how many tests passed)\n// - linesAccepted: number (lines of generated code kept)\n// - timeToAccept: number (seconds from generation to accept — faster = better context)\n//\n// Storage: .cto/feedback.json (per-project)\n\nexport interface FeedbackEntry {\n id: string;\n timestamp: string;\n task: string;\n taskType: TaskType;\n\n // What context was used\n contextHash: string;\n filesIncluded: string[];\n tokensUsed: number;\n budget: number;\n\n // Outcome\n outcome: FeedbackOutcome;\n\n // Optional metadata\n model?: string;\n promptTokens?: number;\n}\n\nexport interface FeedbackOutcome {\n accepted: boolean;\n compilable?: boolean;\n testsPassed?: number;\n testsTotal?: number;\n linesGenerated?: number;\n linesAccepted?: number;\n timeToAcceptMs?: number;\n userRating?: 1 | 2 | 3 | 4 | 5;\n notes?: string;\n}\n\nexport interface FeedbackModel {\n version: number;\n updatedAt: string;\n totalFeedback: number;\n acceptRate: number;\n\n // file → acceptance stats\n fileAcceptance: Record<string, {\n includedCount: number;\n acceptedCount: number;\n acceptRate: number;\n avgTimeToAccept: number;\n }>;\n\n // taskType → acceptance stats\n taskTypeAcceptance: Record<string, {\n totalCount: number;\n acceptedCount: number;\n acceptRate: number;\n avgCompilable: number;\n }>;\n\n // file pair → when both included, acceptance rate\n pairAcceptance: Record<string, {\n count: number;\n acceptedCount: number;\n acceptRate: number;\n }>;\n\n // Insights derived from feedback\n insights: FeedbackInsight[];\n}\n\nexport interface FeedbackInsight {\n type: 'positive' | 'negative' | 'opportunity';\n title: string;\n detail: string;\n impact: number; // 0-100\n}\n\n// ===== STORAGE =====\n\nasync function getFeedbackPath(projectPath: string): Promise<string> {\n const ctoDir = join(resolve(projectPath), '.cto');\n await mkdir(ctoDir, { recursive: true });\n return join(ctoDir, 'feedback.json');\n}\n\nasync function getModelPath(projectPath: string): Promise<string> {\n const ctoDir = join(resolve(projectPath), '.cto');\n await mkdir(ctoDir, { recursive: true });\n return join(ctoDir, 'feedback-model.json');\n}\n\nexport async function loadFeedback(projectPath: string): Promise<FeedbackEntry[]> {\n try {\n const raw = await readFile(await getFeedbackPath(projectPath), 'utf-8');\n return JSON.parse(raw);\n } catch {\n return [];\n }\n}\n\nasync function saveFeedback(projectPath: string, entries: FeedbackEntry[]): Promise<void> {\n await writeFile(await getFeedbackPath(projectPath), JSON.stringify(entries, null, 2));\n}\n\nexport async function loadFeedbackModel(projectPath: string): Promise<FeedbackModel> {\n try {\n const raw = await readFile(await getModelPath(projectPath), 'utf-8');\n return JSON.parse(raw);\n } catch {\n return createEmptyModel();\n }\n}\n\nasync function saveFeedbackModel(projectPath: string, model: FeedbackModel): Promise<void> {\n await writeFile(await getModelPath(projectPath), JSON.stringify(model, null, 2));\n}\n\nfunction createEmptyModel(): FeedbackModel {\n return {\n version: 1,\n updatedAt: new Date().toISOString(),\n totalFeedback: 0,\n acceptRate: 0,\n fileAcceptance: {},\n taskTypeAcceptance: {},\n pairAcceptance: {},\n insights: [],\n };\n}\n\n// ===== RECORD FEEDBACK =====\n\nexport async function recordFeedback(\n projectPath: string,\n entry: Omit<FeedbackEntry, 'id' | 'timestamp' | 'taskType'>,\n): Promise<FeedbackModel> {\n const entries = await loadFeedback(projectPath);\n\n const fullEntry: FeedbackEntry = {\n ...entry,\n id: `fb_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,\n timestamp: new Date().toISOString(),\n taskType: classifyTask(entry.task),\n };\n\n entries.push(fullEntry);\n\n // Keep last 1000 entries\n const trimmed = entries.slice(-1000);\n await saveFeedback(projectPath, trimmed);\n\n // Rebuild model\n const model = rebuildModel(trimmed);\n await saveFeedbackModel(projectPath, model);\n\n return model;\n}\n\n// ===== MODEL BUILDING =====\n\nfunction rebuildModel(entries: FeedbackEntry[]): FeedbackModel {\n const model = createEmptyModel();\n model.totalFeedback = entries.length;\n\n let acceptedTotal = 0;\n\n for (const entry of entries) {\n const accepted = entry.outcome.accepted;\n if (accepted) acceptedTotal++;\n\n // File acceptance\n for (const file of entry.filesIncluded) {\n if (!model.fileAcceptance[file]) {\n model.fileAcceptance[file] = {\n includedCount: 0,\n acceptedCount: 0,\n acceptRate: 0,\n avgTimeToAccept: 0,\n };\n }\n const fa = model.fileAcceptance[file];\n fa.includedCount++;\n if (accepted) fa.acceptedCount++;\n fa.acceptRate = fa.acceptedCount / fa.includedCount;\n if (entry.outcome.timeToAcceptMs) {\n fa.avgTimeToAccept = (fa.avgTimeToAccept * (fa.includedCount - 1) + entry.outcome.timeToAcceptMs) / fa.includedCount;\n }\n }\n\n // Task type acceptance\n const tt = entry.taskType;\n if (!model.taskTypeAcceptance[tt]) {\n model.taskTypeAcceptance[tt] = {\n totalCount: 0,\n acceptedCount: 0,\n acceptRate: 0,\n avgCompilable: 0,\n };\n }\n const tta = model.taskTypeAcceptance[tt];\n tta.totalCount++;\n if (accepted) tta.acceptedCount++;\n tta.acceptRate = tta.acceptedCount / tta.totalCount;\n if (entry.outcome.compilable !== undefined) {\n tta.avgCompilable = (tta.avgCompilable * (tta.totalCount - 1) + (entry.outcome.compilable ? 1 : 0)) / tta.totalCount;\n }\n\n // Pair acceptance (top 10 files per entry to limit combinatorics)\n const topFiles = entry.filesIncluded.slice(0, 10);\n for (let i = 0; i < topFiles.length; i++) {\n for (let j = i + 1; j < topFiles.length; j++) {\n const key = [topFiles[i], topFiles[j]].sort().join('|');\n if (!model.pairAcceptance[key]) {\n model.pairAcceptance[key] = { count: 0, acceptedCount: 0, acceptRate: 0 };\n }\n const pa = model.pairAcceptance[key];\n pa.count++;\n if (accepted) pa.acceptedCount++;\n pa.acceptRate = pa.acceptedCount / pa.count;\n }\n }\n }\n\n model.acceptRate = entries.length > 0 ? acceptedTotal / entries.length : 0;\n\n // Generate insights\n model.insights = generateInsights(model);\n\n return model;\n}\n\nfunction generateInsights(model: FeedbackModel): FeedbackInsight[] {\n const insights: FeedbackInsight[] = [];\n\n // High acceptance files\n const highAccept = Object.entries(model.fileAcceptance)\n .filter(([_, fa]) => fa.includedCount >= 3 && fa.acceptRate >= 0.8)\n .sort((a, b) => b[1].acceptRate - a[1].acceptRate)\n .slice(0, 5);\n\n for (const [file, fa] of highAccept) {\n insights.push({\n type: 'positive',\n title: `${file} consistently leads to accepted output`,\n detail: `${Math.round(fa.acceptRate * 100)}% accept rate over ${fa.includedCount} selections`,\n impact: Math.round(fa.acceptRate * fa.includedCount),\n });\n }\n\n // Low acceptance files (might be noise)\n const lowAccept = Object.entries(model.fileAcceptance)\n .filter(([_, fa]) => fa.includedCount >= 3 && fa.acceptRate < 0.3)\n .sort((a, b) => a[1].acceptRate - b[1].acceptRate)\n .slice(0, 5);\n\n for (const [file, fa] of lowAccept) {\n insights.push({\n type: 'negative',\n title: `${file} often included but output rejected`,\n detail: `Only ${Math.round(fa.acceptRate * 100)}% accept rate — may be adding noise`,\n impact: Math.round((1 - fa.acceptRate) * fa.includedCount * 2),\n });\n }\n\n // Best task types\n const bestTasks = Object.entries(model.taskTypeAcceptance)\n .filter(([_, ta]) => ta.totalCount >= 2)\n .sort((a, b) => b[1].acceptRate - a[1].acceptRate);\n\n for (const [taskType, ta] of bestTasks.slice(0, 3)) {\n insights.push({\n type: ta.acceptRate >= 0.7 ? 'positive' : 'opportunity',\n title: `${taskType} tasks: ${Math.round(ta.acceptRate * 100)}% acceptance`,\n detail: `${ta.acceptedCount}/${ta.totalCount} accepted, ${Math.round(ta.avgCompilable * 100)}% compilable`,\n impact: Math.round(ta.acceptRate * ta.totalCount * 3),\n });\n }\n\n // Power pairs (files that when included together → high acceptance)\n const powerPairs = Object.entries(model.pairAcceptance)\n .filter(([_, pa]) => pa.count >= 3 && pa.acceptRate >= 0.9)\n .sort((a, b) => b[1].acceptRate * b[1].count - a[1].acceptRate * a[1].count)\n .slice(0, 3);\n\n for (const [pair, pa] of powerPairs) {\n const [a, b] = pair.split('|');\n insights.push({\n type: 'positive',\n title: `Power pair: ${a} + ${b}`,\n detail: `${Math.round(pa.acceptRate * 100)}% acceptance when both included (${pa.count} times)`,\n impact: Math.round(pa.acceptRate * pa.count * 5),\n });\n }\n\n return insights.sort((a, b) => b.impact - a.impact);\n}\n\n// ===== PREDICTION: boost files based on feedback =====\n\nexport async function getFeedbackBoosts(\n projectPath: string,\n task: string,\n): Promise<Map<string, number>> {\n const model = await loadFeedbackModel(projectPath);\n const boosts = new Map<string, number>();\n\n if (model.totalFeedback < 3) return boosts; // not enough data\n\n const taskType = classifyTask(task);\n\n // Boost files with high acceptance rate\n for (const [file, fa] of Object.entries(model.fileAcceptance)) {\n if (fa.includedCount < 2) continue;\n\n // Positive boost for high acceptance\n if (fa.acceptRate >= 0.7) {\n boosts.set(file, (boosts.get(file) ?? 0) + fa.acceptRate * 5);\n }\n\n // Negative boost (penalty) for consistently rejected\n if (fa.acceptRate < 0.2 && fa.includedCount >= 3) {\n boosts.set(file, (boosts.get(file) ?? 0) - 3);\n }\n }\n\n // Boost based on task type patterns\n const tta = model.taskTypeAcceptance[taskType];\n if (tta && tta.totalCount >= 2) {\n // If this task type has high compilability, boost type files\n if (tta.avgCompilable >= 0.8) {\n // Context is already good for this task type, minor boost\n for (const [file, fa] of Object.entries(model.fileAcceptance)) {\n if (fa.acceptRate >= 0.8) {\n boosts.set(file, (boosts.get(file) ?? 0) + 1);\n }\n }\n }\n }\n\n return boosts;\n}\n\n// ===== RENDER =====\n\nexport function renderFeedbackReport(model: FeedbackModel): string {\n const lines: string[] = [];\n\n lines.push('');\n lines.push(` ╔══════════════════════════════════════════════════╗`);\n lines.push(` ║ 📊 Feedback Loop Report ║`);\n lines.push(` ╠══════════════════════════════════════════════════╣`);\n lines.push(` ║ ║`);\n lines.push(` ║ Total feedback: ${pad(model.totalFeedback.toString(), 8)} ║`);\n lines.push(` ║ Accept rate: ${pad(Math.round(model.acceptRate * 100) + '%', 8)} ║`);\n lines.push(` ║ Tracked files: ${pad(Object.keys(model.fileAcceptance).length.toString(), 8)} ║`);\n lines.push(` ║ Task types: ${pad(Object.keys(model.taskTypeAcceptance).length.toString(), 8)} ║`);\n lines.push(` ║ ║`);\n\n if (model.insights.length > 0) {\n lines.push(` ║ Insights: ║`);\n for (const insight of model.insights.slice(0, 5)) {\n const icon = insight.type === 'positive' ? '✅' : insight.type === 'negative' ? '⚠️' : '💡';\n lines.push(` ║ ${icon} ${pad(insight.title, 43)} ║`);\n }\n }\n\n lines.push(` ║ ║`);\n lines.push(` ╚══════════════════════════════════════════════════╝`);\n\n return lines.join('\\n');\n}\n\nfunction pad(s: string, w: number): string { return s.padEnd(w).substring(0, w); }\n","import type { ProjectAnalysis, AnalyzedFile } from '../types/engine.js';\nimport { buildAdjacencyList } from './graph-utils.js';\n\n// ===== Semantic Fingerprints =====\n//\n// Understand what code DOES, not just its structure.\n//\n// Current tools know: \"src/auth/login.ts has 150 tokens, imports 3 files, risk 72\"\n// Semantic fingerprints add: \"this file handles user authentication via JWT,\n// exposes a login endpoint, depends on the user model\"\n//\n// How it works (no LLM required):\n// 1. Extract semantic signals from code: export names, class names, function names,\n// string literals, decorators, route patterns, env var usage\n// 2. Classify each file into semantic domains: auth, database, api, config, etc.\n// 3. Build a semantic graph: which domains depend on which\n// 4. For a given task, match task intent to semantic domains\n//\n// This is hard to copy because:\n// - It requires deep AST understanding per language\n// - The domain classification improves with data\n// - The task → domain mapping is learned, not hardcoded\n\nexport interface SemanticFingerprint {\n filePath: string;\n domains: SemanticDomain[];\n exports: string[];\n concepts: string[];\n patterns: CodePattern[];\n intentScore: Map<string, number>; // intent → relevance score\n}\n\nexport interface SemanticDomain {\n name: string;\n confidence: number; // 0-1\n signals: string[];\n}\n\nexport interface CodePattern {\n type: 'route' | 'model' | 'middleware' | 'config' | 'test' | 'type' | 'util' | 'entry' | 'event' | 'error';\n evidence: string;\n}\n\nexport interface SemanticAnalysis {\n files: SemanticFingerprint[];\n domainGraph: { from: string; to: string; strength: number }[];\n domainClusters: { domain: string; files: string[]; tokenBudget: number }[];\n}\n\n// ===== DOMAIN DETECTION =====\n\nconst DOMAIN_SIGNALS: Record<string, { pathPatterns: RegExp[]; namePatterns: RegExp[]; contentPatterns: RegExp[] }> = {\n auth: {\n pathPatterns: [/auth/i, /login/i, /session/i, /passport/i, /oauth/i, /jwt/i, /token/i],\n namePatterns: [/login/i, /logout/i, /authenticate/i, /authorize/i, /verify.*token/i, /sign.*in/i],\n contentPatterns: [/jwt/i, /bearer/i, /passport/i, /bcrypt/i, /session/i, /cookie/i, /oauth/i],\n },\n database: {\n pathPatterns: [/model/i, /schema/i, /migration/i, /seed/i, /prisma/i, /database/i, /db\\b/i],\n namePatterns: [/create.*model/i, /find.*by/i, /query/i, /migrate/i, /schema/i],\n contentPatterns: [/prisma/i, /mongoose/i, /sequelize/i, /typeorm/i, /knex/i, /SELECT/i, /CREATE TABLE/i],\n },\n api: {\n pathPatterns: [/route/i, /controller/i, /endpoint/i, /handler/i, /api\\b/i, /rest/i],\n namePatterns: [/router/i, /handler/i, /controller/i, /endpoint/i, /get|post|put|delete|patch/i],\n contentPatterns: [/express/i, /fastify/i, /koa/i, /hono/i, /app\\.(get|post|put|delete)/i, /\\.route\\(/i],\n },\n config: {\n pathPatterns: [/config/i, /env/i, /setting/i, /constant/i, /\\.env/i],\n namePatterns: [/config/i, /setting/i, /env/i, /constant/i],\n contentPatterns: [/process\\.env/i, /dotenv/i, /config\\(/i, /DATABASE_URL/i],\n },\n testing: {\n pathPatterns: [/test/i, /spec/i, /mock/i, /fixture/i, /__test/i],\n namePatterns: [/describe/i, /test/i, /expect/i, /mock/i, /fixture/i],\n contentPatterns: [/describe\\(/i, /it\\(/i, /expect\\(/i, /jest/i, /vitest/i, /mocha/i],\n },\n ui: {\n pathPatterns: [/component/i, /view/i, /page/i, /layout/i, /template/i, /style/i],\n namePatterns: [/render/i, /component/i, /view/i, /page/i, /layout/i],\n contentPatterns: [/react/i, /vue/i, /svelte/i, /jsx/i, /className/i, /useState/i, /html/i],\n },\n middleware: {\n pathPatterns: [/middleware/i, /interceptor/i, /guard/i, /filter/i, /pipe/i],\n namePatterns: [/middleware/i, /intercept/i, /guard/i, /filter/i, /pipe/i],\n contentPatterns: [/next\\(\\)/i, /req\\s*,\\s*res/i, /middleware/i, /use\\(/i],\n },\n types: {\n pathPatterns: [/type/i, /interface/i, /\\.d\\.ts$/i, /schema/i],\n namePatterns: [/interface/i, /type\\s+\\w/i, /enum/i, /schema/i],\n contentPatterns: [/export\\s+(interface|type|enum)\\s/i, /declare\\s/i, /\\.d\\.ts/i],\n },\n util: {\n pathPatterns: [/util/i, /helper/i, /lib\\b/i, /common/i, /shared/i, /tool/i],\n namePatterns: [/format/i, /parse/i, /validate/i, /convert/i, /transform/i, /helper/i],\n contentPatterns: [],\n },\n error: {\n pathPatterns: [/error/i, /exception/i, /fault/i],\n namePatterns: [/error/i, /exception/i, /throw/i, /catch/i, /fault/i],\n contentPatterns: [/extends\\s+Error/i, /throw\\s+new/i, /catch\\s*\\(/i, /error.*handler/i],\n },\n};\n\n// ===== INTENT MAPPING =====\n\nconst INTENT_DOMAINS: Record<string, string[]> = {\n 'authentication': ['auth', 'middleware', 'config', 'types'],\n 'authorization': ['auth', 'middleware', 'types'],\n 'database': ['database', 'types', 'config'],\n 'api': ['api', 'middleware', 'types', 'error'],\n 'routing': ['api', 'middleware'],\n 'testing': ['testing', 'types'],\n 'refactoring': ['types', 'util', 'config'],\n 'error handling': ['error', 'middleware', 'api'],\n 'configuration': ['config', 'types'],\n 'ui': ['ui', 'types', 'api'],\n 'performance': ['util', 'middleware', 'config'],\n 'security': ['auth', 'middleware', 'config', 'error'],\n 'deployment': ['config', 'error'],\n 'monitoring': ['middleware', 'error', 'config'],\n 'caching': ['middleware', 'config', 'util'],\n 'validation': ['types', 'middleware', 'util'],\n 'serialization': ['types', 'util'],\n 'logging': ['middleware', 'util', 'config'],\n};\n\n// ===== MAIN API =====\n\nexport function analyzeSemantics(analysis: ProjectAnalysis): SemanticAnalysis {\n const fingerprints: SemanticFingerprint[] = [];\n\n for (const file of analysis.files) {\n fingerprints.push(computeSemanticFingerprint(file));\n }\n\n // Build domain graph\n const adj = buildAdjacencyList(analysis.graph.edges);\n const domainGraph: SemanticAnalysis['domainGraph'] = [];\n\n for (const edge of analysis.graph.edges) {\n const fromFp = fingerprints.find((f) => f.filePath === edge.from);\n const toFp = fingerprints.find((f) => f.filePath === edge.to);\n if (fromFp && toFp) {\n for (const fromDomain of fromFp.domains) {\n for (const toDomain of toFp.domains) {\n if (fromDomain.name !== toDomain.name) {\n domainGraph.push({\n from: fromDomain.name,\n to: toDomain.name,\n strength: fromDomain.confidence * toDomain.confidence,\n });\n }\n }\n }\n }\n }\n\n // Cluster files by domain\n const domainFiles = new Map<string, string[]>();\n for (const fp of fingerprints) {\n const primaryDomain = fp.domains[0]?.name ?? 'unknown';\n if (!domainFiles.has(primaryDomain)) domainFiles.set(primaryDomain, []);\n domainFiles.get(primaryDomain)!.push(fp.filePath);\n }\n\n const domainClusters = [...domainFiles.entries()].map(([domain, files]) => {\n const totalTokens = files.reduce((sum, path) => {\n const f = analysis.files.find((af) => af.relativePath === path);\n return sum + (f?.tokens ?? 0);\n }, 0);\n return { domain, files, tokenBudget: totalTokens };\n });\n\n return { files: fingerprints, domainGraph, domainClusters };\n}\n\nfunction computeSemanticFingerprint(file: AnalyzedFile): SemanticFingerprint {\n const domains: SemanticDomain[] = [];\n const concepts: string[] = [];\n const patterns: CodePattern[] = [];\n\n // Detect domains from path, exports, and kind\n for (const [domainName, signals] of Object.entries(DOMAIN_SIGNALS)) {\n let confidence = 0;\n const evidences: string[] = [];\n\n // Path-based detection\n for (const pattern of signals.pathPatterns) {\n if (pattern.test(file.relativePath)) {\n confidence += 0.3;\n evidences.push(`path matches ${pattern.source}`);\n }\n }\n\n // Import-based detection (files importing domain-specific modules)\n for (const imp of file.imports ?? []) {\n for (const pattern of signals.namePatterns) {\n if (pattern.test(imp)) {\n confidence += 0.2;\n evidences.push(`imports ${imp}`);\n }\n }\n }\n\n // Kind-based detection\n if (file.kind === 'type' && domainName === 'types') confidence += 0.4;\n if (file.kind === 'test' && domainName === 'testing') confidence += 0.4;\n if (file.kind === 'entry' && domainName === 'api') confidence += 0.2;\n if (file.kind === 'config' && domainName === 'config') confidence += 0.4;\n\n if (confidence > 0.1) {\n domains.push({\n name: domainName,\n confidence: Math.min(1, confidence),\n signals: evidences.slice(0, 5),\n });\n }\n }\n\n // Sort domains by confidence\n domains.sort((a, b) => b.confidence - a.confidence);\n\n // Extract concepts from file path and imports\n const pathParts = file.relativePath.replace(/\\.[^.]+$/, '').split(/[\\/\\-_.]/);\n for (const part of pathParts) {\n const words = part.replace(/([A-Z])/g, ' $1').toLowerCase().trim().split(/\\s+/);\n concepts.push(...words.filter((w: string) => w.length > 2));\n }\n\n // Detect code patterns from file kind\n if (file.kind === 'type') patterns.push({ type: 'type', evidence: 'file kind' });\n if (file.kind === 'test') patterns.push({ type: 'test', evidence: 'file kind' });\n if (file.kind === 'entry') patterns.push({ type: 'entry', evidence: 'file kind' });\n if (file.kind === 'config') patterns.push({ type: 'config', evidence: 'file kind' });\n\n return {\n filePath: file.relativePath,\n domains,\n exports: file.imports ?? [],\n concepts: [...new Set(concepts)].slice(0, 20),\n patterns,\n intentScore: new Map(),\n };\n}\n\n// ===== SEMANTIC SELECTION =====\n\nexport function semanticBoosts(\n semantics: SemanticAnalysis,\n task: string,\n): Map<string, number> {\n const boosts = new Map<string, number>();\n const taskLower = task.toLowerCase();\n\n // 1. Extract intents from task\n const matchedIntents: { intent: string; domains: string[] }[] = [];\n for (const [intent, domains] of Object.entries(INTENT_DOMAINS)) {\n if (taskLower.includes(intent.split(' ')[0])) {\n matchedIntents.push({ intent, domains });\n }\n }\n\n // 2. Also extract domain keywords directly\n const directDomains = new Set<string>();\n for (const domainName of Object.keys(DOMAIN_SIGNALS)) {\n if (taskLower.includes(domainName)) {\n directDomains.add(domainName);\n }\n }\n\n // 3. Boost files whose domains match task intents\n for (const fp of semantics.files) {\n let boost = 0;\n\n for (const fileDomain of fp.domains) {\n // Direct domain match\n if (directDomains.has(fileDomain.name)) {\n boost += fileDomain.confidence * 8;\n }\n\n // Intent-based match\n for (const { domains } of matchedIntents) {\n if (domains.includes(fileDomain.name)) {\n boost += fileDomain.confidence * 5;\n }\n }\n }\n\n // Concept matching\n const taskWords = taskLower.replace(/[^a-z0-9\\s]/g, '').split(/\\s+/);\n for (const concept of fp.concepts) {\n if (taskWords.some((w) => w.includes(concept) || concept.includes(w))) {\n boost += 2;\n }\n }\n\n if (boost > 0) {\n boosts.set(fp.filePath, Math.round(boost * 10) / 10);\n }\n }\n\n return boosts;\n}\n\n// ===== RENDER =====\n\nexport function renderSemanticAnalysis(semantics: SemanticAnalysis): string {\n const lines: string[] = [];\n\n lines.push('');\n lines.push(` ╔══════════════════════════════════════════════════╗`);\n lines.push(` ║ 🧬 Semantic Analysis ║`);\n lines.push(` ╠══════════════════════════════════════════════════╣`);\n lines.push(` ║ ║`);\n\n // Domain clusters\n const sorted = [...semantics.domainClusters].sort((a, b) => b.files.length - a.files.length);\n for (const cluster of sorted.slice(0, 8)) {\n const tokens = cluster.tokenBudget >= 1000 ? `${(cluster.tokenBudget / 1000).toFixed(1)}K` : `${cluster.tokenBudget}`;\n lines.push(` ║ ${pad(cluster.domain, 14)} ${pad(cluster.files.length + ' files', 10)} ${pad(tokens + ' tok', 10)} ║`);\n }\n\n lines.push(` ║ ║`);\n\n // Domain connections\n const uniqueEdges = new Map<string, number>();\n for (const edge of semantics.domainGraph) {\n const key = `${edge.from} → ${edge.to}`;\n uniqueEdges.set(key, (uniqueEdges.get(key) ?? 0) + edge.strength);\n }\n const topEdges = [...uniqueEdges.entries()]\n .sort((a, b) => b[1] - a[1])\n .slice(0, 5);\n\n if (topEdges.length > 0) {\n lines.push(` ║ Domain Dependencies: ║`);\n for (const [edge, strength] of topEdges) {\n lines.push(` ║ ${pad(edge, 30)} (${strength.toFixed(1)}) ║`);\n }\n }\n\n lines.push(` ║ ║`);\n lines.push(` ╚══════════════════════════════════════════════════╝`);\n\n return lines.join('\\n');\n}\n\nfunction pad(s: string, w: number): string { return s.padEnd(w).substring(0, w); }\n","import type { ProjectAnalysis, AnalyzedFile } from '../types/engine.js';\nimport type { TaskType } from '../types/interact.js';\nimport { selectContext } from './selector.js';\nimport { buildAdjacencyList, bfsBidirectional } from './graph-utils.js';\nimport { classifyTask } from '../interact/router.js';\n\n// ===== Compilability Benchmark =====\n//\n// THE killer proof: CTO context → code that compiles. Naive → type errors.\n//\n// Measures:\n// 1. Type Availability — What % of referenced types/interfaces are in context?\n// 2. Import Chain Completeness — Can the AI follow the full import chain?\n// 3. Missing Symbols — Which specific types/interfaces are MISSING from context?\n// 4. Predicted Compile Errors — Estimate how many TS errors generated code would have\n//\n// The insight: if the AI generates `const result: ContextSelection = ...` but\n// ContextSelection interface is NOT in context, it will either:\n// a) Invent the type (wrong shape → runtime error)\n// b) Skip the type (any → no type safety)\n// c) Hallucinate properties (compile error)\n//\n// CTO always includes type files. Naive (alphabetical) almost never does.\n\nexport interface CompilabilityResult {\n project: string;\n task: string;\n budget: number;\n\n strategies: {\n cto: CompilabilityMetrics;\n naive: CompilabilityMetrics;\n random: CompilabilityMetrics;\n };\n\n comparison: {\n ctoVsNaiveTypeAvailability: number;\n ctoVsRandomTypeAvailability: number;\n ctoVsNaivePredictedErrors: number;\n naiveMissingTypes: string[];\n randomMissingTypes: string[];\n };\n\n verdict: string;\n}\n\nexport interface CompilabilityMetrics {\n // Type coverage\n typeFilesAvailable: number;\n typeFilesTotal: number;\n typeAvailabilityPercent: number;\n\n // Import chain analysis\n importChainsComplete: number;\n importChainsTotal: number;\n importCompletenessPercent: number;\n\n // Specific missing symbols\n missingTypeFiles: string[];\n missingDependencies: string[];\n\n // Predicted errors\n predictedTypeErrors: number;\n predictedImportErrors: number;\n predictedTotalErrors: number;\n\n // Compilability score (0-100)\n compilabilityScore: number;\n\n // Files and tokens\n filesSelected: number;\n tokensUsed: number;\n}\n\n// ===== MAIN API =====\n\nexport async function runCompilabilityBenchmark(\n analysis: ProjectAnalysis,\n task: string,\n budget: number = 50_000,\n): Promise<CompilabilityResult> {\n const taskType = classifyTask(task);\n\n // Identify all type files in the project\n const typeFiles = analysis.files.filter((f) => f.kind === 'type');\n const allTypePaths = new Set(typeFiles.map((f) => f.relativePath));\n\n // Build dependency graph\n const adj = buildAdjacencyList(analysis.graph.edges);\n\n // Identify task-relevant files (keyword + graph)\n const relevantFiles = findRelevantFiles(analysis, task);\n const relevantPaths = new Set(relevantFiles.map((f) => f.relativePath));\n\n // Find which type files are needed by relevant files\n const neededTypes = new Set<string>();\n for (const file of relevantFiles) {\n const deps = adj.forward.get(file.relativePath) ?? [];\n for (const dep of deps) {\n if (allTypePaths.has(dep)) neededTypes.add(dep);\n }\n }\n // Also add types that are transitively needed\n const expandedTypes = bfsBidirectional([...neededTypes], adj, 1);\n for (const t of expandedTypes) {\n if (allTypePaths.has(t)) neededTypes.add(t);\n }\n\n // === CTO selection ===\n const ctoSelection = await selectContext({ task, analysis, budget });\n const ctoPaths = new Set(ctoSelection.files.map((f) => f.relativePath));\n const ctoMetrics = computeCompilability(\n ctoPaths, ctoSelection.totalTokens, analysis, allTypePaths, neededTypes, adj, relevantPaths,\n );\n\n // === Naive selection (alphabetical) ===\n const naiveSorted = [...analysis.files].sort((a, b) => a.relativePath.localeCompare(b.relativePath));\n const naivePaths = new Set<string>();\n let naiveTokens = 0;\n for (const f of naiveSorted) {\n if (naiveTokens + f.tokens <= budget) {\n naivePaths.add(f.relativePath);\n naiveTokens += f.tokens;\n }\n }\n if (naivePaths.size === 0 && analysis.totalTokens <= budget) {\n for (const f of analysis.files) naivePaths.add(f.relativePath);\n naiveTokens = analysis.totalTokens;\n }\n const naiveMetrics = computeCompilability(\n naivePaths, naiveTokens, analysis, allTypePaths, neededTypes, adj, relevantPaths,\n );\n\n // === Random selection ===\n const shuffled = [...analysis.files].sort(() => Math.random() - 0.5);\n const randomPaths = new Set<string>();\n let randomTokens = 0;\n for (const f of shuffled) {\n if (randomTokens + f.tokens <= budget) {\n randomPaths.add(f.relativePath);\n randomTokens += f.tokens;\n }\n }\n const randomMetrics = computeCompilability(\n randomPaths, randomTokens, analysis, allTypePaths, neededTypes, adj, relevantPaths,\n );\n\n // Comparison\n const comparison = {\n ctoVsNaiveTypeAvailability: ctoMetrics.typeAvailabilityPercent - naiveMetrics.typeAvailabilityPercent,\n ctoVsRandomTypeAvailability: ctoMetrics.typeAvailabilityPercent - randomMetrics.typeAvailabilityPercent,\n ctoVsNaivePredictedErrors: naiveMetrics.predictedTotalErrors - ctoMetrics.predictedTotalErrors,\n naiveMissingTypes: naiveMetrics.missingTypeFiles,\n randomMissingTypes: randomMetrics.missingTypeFiles,\n };\n\n const verdict = generateVerdict(ctoMetrics, naiveMetrics, randomMetrics, comparison, analysis);\n\n return {\n project: analysis.projectName,\n task,\n budget,\n strategies: { cto: ctoMetrics, naive: naiveMetrics, random: randomMetrics },\n comparison,\n verdict,\n };\n}\n\n// ===== COMPILABILITY COMPUTATION =====\n\nfunction computeCompilability(\n selectedPaths: Set<string>,\n tokensUsed: number,\n analysis: ProjectAnalysis,\n allTypePaths: Set<string>,\n neededTypes: Set<string>,\n adj: ReturnType<typeof buildAdjacencyList>,\n relevantPaths: Set<string>,\n): CompilabilityMetrics {\n // Type availability: what % of needed type files are included?\n const typeFilesAvailable = [...neededTypes].filter((t) => selectedPaths.has(t)).length;\n const typeFilesTotal = neededTypes.size;\n const typeAvailabilityPercent = typeFilesTotal > 0\n ? Math.round((typeFilesAvailable / typeFilesTotal) * 100) : 100;\n\n // Import chain completeness\n let chainsComplete = 0;\n let chainsTotal = 0;\n\n for (const path of selectedPaths) {\n if (!relevantPaths.has(path)) continue;\n const deps = adj.forward.get(path) ?? [];\n for (const dep of deps) {\n chainsTotal++;\n if (selectedPaths.has(dep)) chainsComplete++;\n }\n }\n const importCompletenessPercent = chainsTotal > 0\n ? Math.round((chainsComplete / chainsTotal) * 100) : 100;\n\n // Missing type files\n const missingTypeFiles = [...neededTypes].filter((t) => !selectedPaths.has(t));\n\n // Missing dependencies (non-type files that are imported but not included)\n const missingDeps: string[] = [];\n for (const path of selectedPaths) {\n const deps = adj.forward.get(path) ?? [];\n for (const dep of deps) {\n if (!selectedPaths.has(dep) && !allTypePaths.has(dep)) {\n if (!missingDeps.includes(dep)) missingDeps.push(dep);\n }\n }\n }\n\n // Predicted errors\n // Each missing type file → ~3 type errors (avg interface has 3 usages)\n const predictedTypeErrors = missingTypeFiles.length * 3;\n\n // Each broken import chain → 1 import error\n const predictedImportErrors = chainsTotal - chainsComplete;\n\n const predictedTotalErrors = predictedTypeErrors + predictedImportErrors;\n\n // Compilability score (0-100)\n const typeWeight = 0.6;\n const importWeight = 0.4;\n const compilabilityScore = Math.round(\n typeAvailabilityPercent * typeWeight +\n importCompletenessPercent * importWeight,\n );\n\n return {\n typeFilesAvailable,\n typeFilesTotal,\n typeAvailabilityPercent,\n importChainsComplete: chainsComplete,\n importChainsTotal: chainsTotal,\n importCompletenessPercent,\n missingTypeFiles,\n missingDependencies: missingDeps.slice(0, 20),\n predictedTypeErrors,\n predictedImportErrors,\n predictedTotalErrors,\n compilabilityScore,\n filesSelected: selectedPaths.size,\n tokensUsed,\n };\n}\n\n// ===== RELEVANT FILE FINDER =====\n\nfunction findRelevantFiles(analysis: ProjectAnalysis, task: string): AnalyzedFile[] {\n const keywords = task.toLowerCase()\n .replace(/[^a-z0-9\\s]/g, '')\n .split(/\\s+/)\n .filter((w) => w.length > 2);\n\n const stopWords = new Set([\n 'the', 'and', 'for', 'with', 'from', 'that', 'this', 'fix', 'add',\n 'remove', 'update', 'change', 'refactor', 'implement', 'create',\n 'build', 'make', 'code', 'file', 'module', 'function',\n ]);\n const filtered = keywords.filter((w) => !stopWords.has(w));\n\n const adj = buildAdjacencyList(analysis.graph.edges);\n const scored = new Map<string, number>();\n\n for (const file of analysis.files) {\n let score = 0;\n for (const kw of filtered) {\n if (file.relativePath.toLowerCase().includes(kw)) score += 10;\n }\n if (file.riskScore >= 60) score += 5;\n if (file.isHub) score += 3;\n if (file.kind === 'entry') score += 3;\n if (file.kind === 'type') score += 2;\n if (score > 0) scored.set(file.relativePath, score);\n }\n\n // Expand via deps\n const seeds = [...scored.keys()];\n const expanded = bfsBidirectional(seeds, adj, 1);\n for (const path of expanded) {\n if (!scored.has(path)) scored.set(path, 1);\n }\n\n return analysis.files\n .filter((f) => scored.has(f.relativePath))\n .sort((a, b) => (scored.get(b.relativePath) ?? 0) - (scored.get(a.relativePath) ?? 0));\n}\n\n// ===== VERDICT =====\n\nfunction generateVerdict(\n cto: CompilabilityMetrics,\n naive: CompilabilityMetrics,\n random: CompilabilityMetrics,\n comp: CompilabilityResult['comparison'],\n analysis: ProjectAnalysis,\n): string {\n const lines: string[] = [];\n\n lines.push('## Compilability Verdict');\n lines.push('');\n\n if (cto.compilabilityScore > naive.compilabilityScore) {\n const errorDiff = comp.ctoVsNaivePredictedErrors;\n lines.push(`**CTO context produces code with ${errorDiff} fewer predicted compile errors than naive.**`);\n } else {\n lines.push('**All strategies produce similar compilability for this task.**');\n }\n lines.push('');\n\n // Type availability\n lines.push('### Type Availability');\n lines.push(`- CTO: ${cto.typeAvailabilityPercent}% of needed type files (${cto.typeFilesAvailable}/${cto.typeFilesTotal})`);\n lines.push(`- Naive: ${naive.typeAvailabilityPercent}% (${naive.typeFilesAvailable}/${naive.typeFilesTotal})`);\n lines.push(`- Random: ${random.typeAvailabilityPercent}% (${random.typeFilesAvailable}/${random.typeFilesTotal})`);\n lines.push('');\n\n // Missing types (the killer data)\n if (comp.naiveMissingTypes.length > 0) {\n lines.push('### Types Missing from Naive Context');\n lines.push('Without these, AI-generated code will have type errors:');\n for (const t of comp.naiveMissingTypes) {\n lines.push(`- ❌ \\`${t}\\``);\n }\n lines.push('');\n }\n\n // Predicted errors\n lines.push('### Predicted Compile Errors');\n lines.push(`- CTO: ~${cto.predictedTotalErrors} errors (${cto.predictedTypeErrors} type + ${cto.predictedImportErrors} import)`);\n lines.push(`- Naive: ~${naive.predictedTotalErrors} errors (${naive.predictedTypeErrors} type + ${naive.predictedImportErrors} import)`);\n lines.push(`- Random: ~${random.predictedTotalErrors} errors (${random.predictedTypeErrors} type + ${random.predictedImportErrors} import)`);\n\n return lines.join('\\n');\n}\n\n// ===== RENDERING =====\n\nexport function renderCompilabilityBenchmark(result: CompilabilityResult): string {\n const { cto, naive, random } = result.strategies;\n const lines: string[] = [];\n\n lines.push('');\n lines.push(` ╔══════════════════════════════════════════════════════════════════╗`);\n lines.push(` ║ 🔧 Compilability Benchmark — ${pad(result.project, 20)} ║`);\n lines.push(` ║ Task: ${pad(result.task.substring(0, 48), 48)} ║`);\n lines.push(` ╠══════════════════════════════════════════════════════════════════╣`);\n lines.push(` ║ ║`);\n lines.push(` ║ ${pad('Metric', 26)} ${pad('CTO', 10)} ${pad('Naive', 10)} ${pad('Random', 10)} ║`);\n lines.push(` ║ ${'─'.repeat(56)} ║`);\n lines.push(` ║ ${pad('Compilability Score', 26)} ${pad(cto.compilabilityScore + '/100', 10)} ${pad(naive.compilabilityScore + '/100', 10)} ${pad(random.compilabilityScore + '/100', 10)} ║`);\n lines.push(` ║ ${pad('Type Availability', 26)} ${pad(cto.typeAvailabilityPercent + '%', 10)} ${pad(naive.typeAvailabilityPercent + '%', 10)} ${pad(random.typeAvailabilityPercent + '%', 10)} ║`);\n lines.push(` ║ ${pad('Import Completeness', 26)} ${pad(cto.importCompletenessPercent + '%', 10)} ${pad(naive.importCompletenessPercent + '%', 10)} ${pad(random.importCompletenessPercent + '%', 10)} ║`);\n lines.push(` ║ ${pad('Predicted Type Errors', 26)} ${pad(cto.predictedTypeErrors.toString(), 10)} ${pad(naive.predictedTypeErrors.toString(), 10)} ${pad(random.predictedTypeErrors.toString(), 10)} ║`);\n lines.push(` ║ ${pad('Predicted Import Errors', 26)} ${pad(cto.predictedImportErrors.toString(), 10)} ${pad(naive.predictedImportErrors.toString(), 10)} ${pad(random.predictedImportErrors.toString(), 10)} ║`);\n lines.push(` ║ ${pad('TOTAL Predicted Errors', 26)} ${pad(cto.predictedTotalErrors.toString(), 10)} ${pad(naive.predictedTotalErrors.toString(), 10)} ${pad(random.predictedTotalErrors.toString(), 10)} ║`);\n lines.push(` ║ ${'─'.repeat(56)} ║`);\n lines.push(` ║ ${pad('Type files included', 26)} ${pad(`${cto.typeFilesAvailable}/${cto.typeFilesTotal}`, 10)} ${pad(`${naive.typeFilesAvailable}/${naive.typeFilesTotal}`, 10)} ${pad(`${random.typeFilesAvailable}/${random.typeFilesTotal}`, 10)} ║`);\n lines.push(` ║ ${pad('Tokens used', 26)} ${pad(fmt(cto.tokensUsed), 10)} ${pad(fmt(naive.tokensUsed), 10)} ${pad(fmt(random.tokensUsed), 10)} ║`);\n lines.push(` ║ ║`);\n\n if (result.comparison.naiveMissingTypes.length > 0) {\n lines.push(` ║ ❌ Naive MISSING types (will cause hallucinated types): ║`);\n for (const t of result.comparison.naiveMissingTypes.slice(0, 5)) {\n lines.push(` ║ ${pad(t, 55)} ║`);\n }\n lines.push(` ║ ║`);\n }\n\n if (result.comparison.ctoVsNaivePredictedErrors > 0) {\n lines.push(` ║ 🏆 CTO produces ~${result.comparison.ctoVsNaivePredictedErrors} FEWER compile errors than naive ║`);\n }\n\n lines.push(` ║ ║`);\n lines.push(` ╚══════════════════════════════════════════════════════════════════╝`);\n\n return lines.join('\\n');\n}\n\nfunction pad(s: string, w: number): string { return s.padEnd(w).substring(0, w); }\nfunction fmt(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`;\n return n.toString();\n}\n","import { resolve, join, dirname, relative, basename } from 'node:path';\nimport { readFile, writeFile, mkdir, rm, readdir, stat, cp } from 'node:fs/promises';\nimport { execSync } from 'node:child_process';\nimport type { ProjectAnalysis, AnalyzedFile } from '../types/engine.js';\nimport { selectContext } from './selector.js';\nimport { buildAdjacencyList } from './graph-utils.js';\n\n// ===== Compile Proof =====\n//\n// THE definitive proof: run the actual TypeScript compiler.\n//\n// How it works:\n// 1. For each strategy (CTO, naive, random):\n// a. Create a temp directory with ONLY the selected files\n// b. Generate a \"consumer\" file that imports & uses the project's types\n// c. Run `tsc --noEmit` and count REAL errors\n// 2. Compare: CTO context → 0 errors. Naive → many errors.\n//\n// This is not a prediction. This is the TypeScript compiler saying\n// \"this code WILL NOT COMPILE with naive context.\"\n\nexport interface CompileProofResult {\n project: string;\n task: string;\n budget: number;\n\n cto: CompileProofStrategy;\n naive: CompileProofStrategy;\n random: CompileProofStrategy;\n\n headline: string;\n details: string;\n}\n\nexport interface CompileProofStrategy {\n name: string;\n filesIncluded: number;\n tokensUsed: number;\n typeFilesIncluded: string[];\n typeFilesMissing: string[];\n\n // REAL tsc output\n compileErrors: number;\n errorMessages: string[];\n compiles: boolean;\n}\n\n// ===== MAIN =====\n\nexport async function runCompileProof(\n analysis: ProjectAnalysis,\n task: string,\n budget: number = 50_000,\n): Promise<CompileProofResult> {\n const projectPath = resolve(analysis.projectPath);\n\n // Identify type files\n const typeFiles = analysis.files.filter((f) => f.kind === 'type');\n const typePaths = typeFiles.map((f) => f.relativePath);\n\n // === CTO selection ===\n const ctoSelection = await selectContext({ task, analysis, budget });\n const ctoPaths = new Set(ctoSelection.files.map((f) => f.relativePath));\n\n // === Naive selection (alphabetical) ===\n const naiveSorted = [...analysis.files].sort((a, b) =>\n a.relativePath.localeCompare(b.relativePath),\n );\n const naivePaths = new Set<string>();\n let naiveTokens = 0;\n for (const f of naiveSorted) {\n if (naiveTokens + f.tokens <= budget) {\n naivePaths.add(f.relativePath);\n naiveTokens += f.tokens;\n }\n }\n if (naivePaths.size === 0 && analysis.totalTokens <= budget) {\n for (const f of analysis.files) naivePaths.add(f.relativePath);\n naiveTokens = analysis.totalTokens;\n }\n\n // === Random selection ===\n const shuffled = [...analysis.files].sort(() => Math.random() - 0.5);\n const randomPaths = new Set<string>();\n let randomTokens = 0;\n for (const f of shuffled) {\n if (randomTokens + f.tokens <= budget) {\n randomPaths.add(f.relativePath);\n randomTokens += f.tokens;\n }\n }\n\n // Generate the consumer code — a file that imports and uses the project's key types\n const consumerCode = generateConsumerCode(analysis, typePaths);\n\n // Run tsc for each strategy\n const [ctoResult, naiveResult, randomResult] = await Promise.all([\n runTscWithContext('CTO', projectPath, ctoPaths, ctoSelection.totalTokens, typePaths, consumerCode),\n runTscWithContext('Naive', projectPath, naivePaths, naiveTokens, typePaths, consumerCode),\n runTscWithContext('Random', projectPath, randomPaths, randomTokens, typePaths, consumerCode),\n ]);\n\n // Headline\n const errorDiff = naiveResult.compileErrors - ctoResult.compileErrors;\n let headline: string;\n if (ctoResult.compiles && !naiveResult.compiles) {\n headline = `✅ CTO context compiles. ❌ Naive has ${naiveResult.compileErrors} real TypeScript errors.`;\n } else if (errorDiff > 0) {\n headline = `CTO has ${errorDiff} fewer compile errors than naive (${ctoResult.compileErrors} vs ${naiveResult.compileErrors}).`;\n } else {\n headline = `Both strategies compile for this task.`;\n }\n\n const details = generateDetails(ctoResult, naiveResult, randomResult);\n\n return {\n project: analysis.projectName,\n task,\n budget,\n cto: ctoResult,\n naive: naiveResult,\n random: randomResult,\n headline,\n details,\n };\n}\n\n// ===== CONSUMER CODE GENERATION =====\n\nfunction generateConsumerCode(analysis: ProjectAnalysis, typePaths: string[]): string {\n const lines: string[] = [];\n lines.push('// ======================================================================');\n lines.push('// COMPILE PROOF — Simulates realistic AI-generated code');\n lines.push('// This is what an AI assistant would generate when asked to work');\n lines.push('// with this codebase. Without type definitions, none of this compiles.');\n lines.push('// ======================================================================');\n lines.push('');\n\n // Filter out barrel/re-export files\n const nonBarrelTypes = typePaths.filter((tp) => {\n const name = basename(tp, '.ts');\n return name !== 'index' && name !== 'v2';\n });\n\n // Import from each type file\n for (const typePath of nonBarrelTypes) {\n const file = analysis.files.find((f) => f.relativePath === typePath);\n if (!file) continue;\n const importPath = './' + typePath.replace(/\\.ts$/, '.js');\n const moduleName = basename(typePath, '.ts').replace(/[^a-zA-Z0-9]/g, '_');\n lines.push(`import type * as ${moduleName} from '${importPath}';`);\n }\n\n lines.push('');\n\n // Generate realistic AI-like code that uses types deeply\n const knownTypes = extractKnownTypes(analysis, nonBarrelTypes);\n for (const { typeName, typePath } of knownTypes) {\n const moduleName = basename(typePath, '.ts').replace(/[^a-zA-Z0-9]/g, '_');\n\n // Type alias (AI always does this)\n lines.push(`type ${typeName} = ${moduleName}.${typeName};`);\n }\n lines.push('');\n\n // === Realistic function: \"analyze and select context\" ===\n lines.push('// Simulated AI output: a function that processes analysis results');\n lines.push('function processAnalysis(analysis: engine.ProjectAnalysis): void {');\n lines.push(' // Access nested properties (fails without types)');\n lines.push(' const files = analysis.files;');\n lines.push(' const totalTokens = analysis.totalTokens;');\n lines.push(' const graph = analysis.graph;');\n lines.push(' const hubs = graph.hubs;');\n lines.push(' const edges = graph.edges;');\n lines.push(' const risk = analysis.riskProfile;');\n lines.push(' const critical = risk.distribution.critical;');\n lines.push('');\n lines.push(' for (const file of files) {');\n lines.push(' const score = file.riskScore;');\n lines.push(' const kind = file.kind;');\n lines.push(' const hub = file.isHub;');\n lines.push(' const deps = file.imports;');\n lines.push(' const impact = file.exclusionImpact;');\n lines.push(' void [score, kind, hub, deps, impact];');\n lines.push(' }');\n lines.push('');\n lines.push(' for (const hub of hubs) {');\n lines.push(' void hub.relativePath;');\n lines.push(' void hub.dependents;');\n lines.push(' void hub.score;');\n lines.push(' }');\n lines.push('');\n lines.push(' for (const edge of edges) {');\n lines.push(' void edge.from;');\n lines.push(' void edge.to;');\n lines.push(' void edge.type;');\n lines.push(' }');\n lines.push('');\n lines.push(' void [totalTokens, critical];');\n lines.push('}');\n lines.push('');\n\n // === Realistic function: \"build context selection\" ===\n lines.push('// Simulated AI output: works with context selection results');\n lines.push('function handleSelection(selection: engine.ContextSelection): string[] {');\n lines.push(' const coverage = selection.coverage;');\n lines.push(' const coverageScore = coverage.score;');\n lines.push(' const missing = coverage.missingCritical;');\n lines.push('');\n lines.push(' const result: string[] = [];');\n lines.push(' for (const file of selection.files) {');\n lines.push(' const path = file.relativePath;');\n lines.push(' const tokens = file.tokens;');\n lines.push(' const level = file.pruneLevel;');\n lines.push(' const risk = file.riskScore;');\n lines.push(' result.push(`${path}: ${tokens}t, ${level}, risk=${risk}`);');\n lines.push(' }');\n lines.push('');\n lines.push(' void [coverageScore, missing, selection.budget, selection.hash];');\n lines.push(' return result;');\n lines.push('}');\n lines.push('');\n\n // === Realistic: object construction (what AI does when creating new instances) ===\n lines.push('// Simulated AI output: constructing objects with correct shapes');\n lines.push('function createMockFile(): engine.AnalyzedFile {');\n lines.push(' return {');\n lines.push(' path: \"/src/test.ts\",');\n lines.push(' relativePath: \"src/test.ts\",');\n lines.push(' extension: \".ts\",');\n lines.push(' size: 1000,');\n lines.push(' tokens: 250,');\n lines.push(' lines: 50,');\n lines.push(' lastModified: new Date(),');\n lines.push(' kind: \"source\",');\n lines.push(' imports: [],');\n lines.push(' importedBy: [],');\n lines.push(' isHub: false,');\n lines.push(' complexity: 5,');\n lines.push(' riskScore: 30,');\n lines.push(' riskFactors: [],');\n lines.push(' exclusionImpact: \"low\",');\n lines.push(' };');\n lines.push('}');\n lines.push('');\n\n lines.push('// Ensure all functions are used');\n lines.push('void processAnalysis;');\n lines.push('void handleSelection;');\n lines.push('void createMockFile;');\n lines.push('');\n lines.push('export {};');\n return lines.join('\\n');\n}\n\ninterface KnownType {\n typeName: string;\n typePath: string;\n sampleProperties: string[];\n}\n\nfunction extractKnownTypes(analysis: ProjectAnalysis, typePaths: string[]): KnownType[] {\n // Hardcode key types we know exist (from reading the type files)\n // In production this would be AST-extracted\n const types: KnownType[] = [];\n\n for (const tp of typePaths) {\n if (tp.includes('engine')) {\n types.push(\n { typeName: 'AnalyzedFile', typePath: tp, sampleProperties: ['relativePath', 'tokens', 'riskScore', 'kind', 'isHub'] },\n { typeName: 'ProjectAnalysis', typePath: tp, sampleProperties: ['files', 'totalFiles', 'totalTokens', 'graph', 'stack'] },\n { typeName: 'ContextSelection', typePath: tp, sampleProperties: ['files', 'totalTokens', 'budget', 'coverage', 'riskScore'] },\n { typeName: 'SelectedFile', typePath: tp, sampleProperties: ['relativePath', 'tokens', 'pruneLevel', 'riskScore'] },\n { typeName: 'CoverageResult', typePath: tp, sampleProperties: ['score', 'relevantFiles', 'missingCritical'] },\n { typeName: 'RiskProfile', typePath: tp, sampleProperties: ['distribution', 'topRiskFiles'] },\n { typeName: 'ProjectGraph', typePath: tp, sampleProperties: ['nodes', 'edges', 'hubs', 'clusters'] },\n );\n }\n if (tp.includes('interact')) {\n types.push(\n { typeName: 'TaskType', typePath: tp, sampleProperties: [] },\n );\n }\n if (tp.includes('config')) {\n types.push(\n { typeName: 'CTOConfig', typePath: tp, sampleProperties: [] },\n );\n }\n if (tp.includes('govern')) {\n types.push(\n { typeName: 'AuditEntry', typePath: tp, sampleProperties: [] },\n );\n }\n }\n\n return types;\n}\n\n// ===== TSC RUNNER =====\n\nasync function runTscWithContext(\n name: string,\n projectPath: string,\n selectedPaths: Set<string>,\n tokensUsed: number,\n typePaths: string[],\n consumerCode: string,\n): Promise<CompileProofStrategy> {\n const tmpDir = join(projectPath, '.cto', `compile-proof-${name.toLowerCase()}`);\n\n try {\n // Clean and create temp dir\n await rm(tmpDir, { recursive: true, force: true });\n await mkdir(tmpDir, { recursive: true });\n\n // Copy ONLY selected files to temp dir\n for (const filePath of selectedPaths) {\n const src = join(projectPath, filePath);\n const dest = join(tmpDir, filePath);\n try {\n await mkdir(dirname(dest), { recursive: true });\n await cp(src, dest);\n } catch {\n // File might not exist (e.g., already compiled output)\n }\n }\n\n // Write consumer file\n await writeFile(join(tmpDir, '_compile_test.ts'), consumerCode);\n\n // Write minimal tsconfig\n await writeFile(join(tmpDir, 'tsconfig.json'), JSON.stringify({\n compilerOptions: {\n target: 'ES2022',\n module: 'nodenext',\n moduleResolution: 'nodenext',\n strict: true,\n noEmit: true,\n skipLibCheck: true,\n esModuleInterop: true,\n },\n include: ['_compile_test.ts'],\n }, null, 2));\n\n // Run tsc\n let tscOutput = '';\n let compileErrors = 0;\n try {\n execSync('npx tsc --noEmit --pretty false 2>&1', {\n cwd: tmpDir,\n encoding: 'utf-8',\n timeout: 30_000,\n env: { ...process.env, NODE_ENV: 'production' },\n });\n // If we get here, no errors\n } catch (err: any) {\n tscOutput = err.stdout ?? err.message ?? '';\n }\n\n // Parse errors\n const errorLines = tscOutput\n .split('\\n')\n .filter((l: string) => l.includes('error TS'))\n .map((l: string) => l.trim());\n\n compileErrors = errorLines.length;\n\n // Which type files are included / missing\n const typeFilesIncluded = typePaths.filter((t) => selectedPaths.has(t));\n const typeFilesMissing = typePaths.filter((t) => !selectedPaths.has(t));\n\n return {\n name,\n filesIncluded: selectedPaths.size,\n tokensUsed,\n typeFilesIncluded,\n typeFilesMissing,\n compileErrors,\n errorMessages: errorLines.slice(0, 20), // top 20 errors\n compiles: compileErrors === 0,\n };\n } finally {\n // Cleanup\n await rm(tmpDir, { recursive: true, force: true }).catch(() => {});\n }\n}\n\n// ===== RENDERING =====\n\nfunction generateDetails(\n cto: CompileProofStrategy,\n naive: CompileProofStrategy,\n random: CompileProofStrategy,\n): string {\n const lines: string[] = [];\n\n lines.push('### Type Files Availability');\n lines.push(`- **CTO:** ${cto.typeFilesIncluded.length} included, ${cto.typeFilesMissing.length} missing`);\n lines.push(`- **Naive:** ${naive.typeFilesIncluded.length} included, ${naive.typeFilesMissing.length} missing`);\n lines.push(`- **Random:** ${random.typeFilesIncluded.length} included, ${random.typeFilesMissing.length} missing`);\n lines.push('');\n\n if (naive.typeFilesMissing.length > 0) {\n lines.push('### Missing from Naive (causes compile errors):');\n for (const t of naive.typeFilesMissing) {\n lines.push(`- ❌ \\`${t}\\``);\n }\n lines.push('');\n }\n\n if (naive.errorMessages.length > 0) {\n lines.push('### Sample Naive Compile Errors:');\n lines.push('```');\n for (const e of naive.errorMessages.slice(0, 10)) {\n lines.push(e);\n }\n lines.push('```');\n }\n\n return lines.join('\\n');\n}\n\nexport function renderCompileProof(result: CompileProofResult): string {\n const lines: string[] = [];\n\n lines.push('');\n lines.push(` ╔══════════════════════════════════════════════════════════════════════╗`);\n lines.push(` ║ 🔬 COMPILE PROOF — Real TypeScript Compiler Output ║`);\n lines.push(` ║ ${pad(result.project, 20)} · \"${pad(result.task.substring(0, 35), 35)}\" ║`);\n lines.push(` ╠══════════════════════════════════════════════════════════════════════╣`);\n lines.push(` ║ ║`);\n lines.push(` ║ ${pad('', 28)} ${pad('CTO', 12)} ${pad('Naive', 12)} ${pad('Random', 12)} ║`);\n lines.push(` ║ ${'─'.repeat(64)} ║`);\n lines.push(` ║ ${pad('Compiles?', 28)} ${pad(result.cto.compiles ? '✅ YES' : '❌ NO', 12)} ${pad(result.naive.compiles ? '✅ YES' : '❌ NO', 12)} ${pad(result.random.compiles ? '✅ YES' : '❌ NO', 12)} ║`);\n lines.push(` ║ ${pad('TypeScript Errors', 28)} ${pad(result.cto.compileErrors.toString(), 12)} ${pad(result.naive.compileErrors.toString(), 12)} ${pad(result.random.compileErrors.toString(), 12)} ║`);\n lines.push(` ║ ${pad('Type Files Included', 28)} ${pad(`${result.cto.typeFilesIncluded.length}/${result.cto.typeFilesIncluded.length + result.cto.typeFilesMissing.length}`, 12)} ${pad(`${result.naive.typeFilesIncluded.length}/${result.naive.typeFilesIncluded.length + result.naive.typeFilesMissing.length}`, 12)} ${pad(`${result.random.typeFilesIncluded.length}/${result.random.typeFilesIncluded.length + result.random.typeFilesMissing.length}`, 12)} ║`);\n lines.push(` ║ ${pad('Files in Context', 28)} ${pad(result.cto.filesIncluded.toString(), 12)} ${pad(result.naive.filesIncluded.toString(), 12)} ${pad(result.random.filesIncluded.toString(), 12)} ║`);\n lines.push(` ║ ${pad('Tokens Used', 28)} ${pad(fmt(result.cto.tokensUsed), 12)} ${pad(fmt(result.naive.tokensUsed), 12)} ${pad(fmt(result.random.tokensUsed), 12)} ║`);\n lines.push(` ║ ║`);\n\n if (result.naive.typeFilesMissing.length > 0) {\n lines.push(` ║ ❌ Types MISSING from Naive (AI will hallucinate these): ║`);\n for (const t of result.naive.typeFilesMissing) {\n lines.push(` ║ ${pad(t, 61)} ║`);\n }\n lines.push(` ║ ║`);\n }\n\n if (result.naive.errorMessages.length > 0) {\n lines.push(` ║ 📋 Sample tsc errors from Naive context: ║`);\n for (const e of result.naive.errorMessages.slice(0, 5)) {\n lines.push(` ║ ${pad(e.substring(0, 61), 61)} ║`);\n }\n lines.push(` ║ ║`);\n }\n\n lines.push(` ║ ${pad(result.headline, 66)} ║`);\n lines.push(` ║ ║`);\n lines.push(` ╚══════════════════════════════════════════════════════════════════════╝`);\n\n return lines.join('\\n');\n}\n\nfunction pad(s: string, w: number): string { return s.padEnd(w).substring(0, w); }\nfunction fmt(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`;\n return n.toString();\n}\n","import type { ProjectAnalysis, ContextSelection } from '../types/engine.js';\nimport { selectContext } from './selector.js';\nimport { estimateCost } from '../interact/estimator.js';\n\n// ===== Multi-Model Context Optimization =====\n//\n// Different AI models have different:\n// - Context windows (4K → 2M tokens)\n// - Pricing ($0.25/M → $15/M)\n// - Strengths (code gen, analysis, refactoring)\n//\n// CTO optimizes context PER MODEL:\n// - Small window? Aggressive pruning, only critical files\n// - Large window? Include more context, less pruning needed\n// - Expensive model? Minimize tokens, maximize signal-to-noise\n// - Cheap model? Include broader context for better understanding\n//\n// This is something NO competitor does. Cursor sends the same context\n// to every model. CTO adapts.\n\nexport interface ModelProfile {\n id: string;\n name: string;\n provider: 'openai' | 'anthropic' | 'google' | 'mistral' | 'meta' | 'custom';\n contextWindow: number;\n maxOutput: number;\n costPer1MInput: number;\n costPer1MOutput: number;\n strengths: ModelStrength[];\n recommendedBudgetPercent: number; // % of context window to use\n}\n\nexport type ModelStrength = 'code-generation' | 'analysis' | 'refactoring' | 'debugging' | 'documentation' | 'testing' | 'general';\n\nexport interface MultiModelResult {\n task: string;\n models: ModelOptimization[];\n recommendation: {\n bestValue: string;\n bestQuality: string;\n bestSpeed: string;\n reasoning: string;\n };\n}\n\nexport interface ModelOptimization {\n model: ModelProfile;\n budget: number;\n selection: ContextSelection;\n estimatedCost: number;\n qualityScore: number; // 0-100, estimated output quality\n recommendation: string;\n}\n\n// ===== MODEL REGISTRY =====\n\nexport const MODEL_REGISTRY: ModelProfile[] = [\n {\n id: 'gpt-4o',\n name: 'GPT-4o',\n provider: 'openai',\n contextWindow: 128_000,\n maxOutput: 16_384,\n costPer1MInput: 2.50,\n costPer1MOutput: 10.00,\n strengths: ['code-generation', 'analysis', 'general'],\n recommendedBudgetPercent: 40,\n },\n {\n id: 'gpt-4o-mini',\n name: 'GPT-4o Mini',\n provider: 'openai',\n contextWindow: 128_000,\n maxOutput: 16_384,\n costPer1MInput: 0.15,\n costPer1MOutput: 0.60,\n strengths: ['general', 'documentation'],\n recommendedBudgetPercent: 60,\n },\n {\n id: 'claude-sonnet-4',\n name: 'Claude Sonnet 4',\n provider: 'anthropic',\n contextWindow: 200_000,\n maxOutput: 64_000,\n costPer1MInput: 3.00,\n costPer1MOutput: 15.00,\n strengths: ['code-generation', 'refactoring', 'analysis', 'debugging'],\n recommendedBudgetPercent: 35,\n },\n {\n id: 'claude-haiku-3.5',\n name: 'Claude 3.5 Haiku',\n provider: 'anthropic',\n contextWindow: 200_000,\n maxOutput: 8_192,\n costPer1MInput: 0.80,\n costPer1MOutput: 4.00,\n strengths: ['general', 'testing', 'documentation'],\n recommendedBudgetPercent: 50,\n },\n {\n id: 'gemini-2.0-flash',\n name: 'Gemini 2.0 Flash',\n provider: 'google',\n contextWindow: 1_048_576,\n maxOutput: 8_192,\n costPer1MInput: 0.10,\n costPer1MOutput: 0.40,\n strengths: ['analysis', 'general'],\n recommendedBudgetPercent: 20,\n },\n {\n id: 'gemini-2.5-pro',\n name: 'Gemini 2.5 Pro',\n provider: 'google',\n contextWindow: 1_048_576,\n maxOutput: 65_536,\n costPer1MInput: 1.25,\n costPer1MOutput: 10.00,\n strengths: ['code-generation', 'analysis', 'refactoring'],\n recommendedBudgetPercent: 15,\n },\n {\n id: 'deepseek-v3',\n name: 'DeepSeek V3',\n provider: 'custom',\n contextWindow: 128_000,\n maxOutput: 8_192,\n costPer1MInput: 0.27,\n costPer1MOutput: 1.10,\n strengths: ['code-generation', 'debugging'],\n recommendedBudgetPercent: 50,\n },\n {\n id: 'codestral',\n name: 'Codestral',\n provider: 'mistral',\n contextWindow: 256_000,\n maxOutput: 8_192,\n costPer1MInput: 0.30,\n costPer1MOutput: 0.90,\n strengths: ['code-generation', 'refactoring'],\n recommendedBudgetPercent: 45,\n },\n];\n\n// ===== MAIN API =====\n\nexport async function optimizeForModels(\n analysis: ProjectAnalysis,\n task: string,\n models?: string[],\n): Promise<MultiModelResult> {\n const targetModels = models\n ? MODEL_REGISTRY.filter((m) => models.includes(m.id))\n : MODEL_REGISTRY;\n\n const optimizations: ModelOptimization[] = [];\n\n for (const model of targetModels) {\n const budget = Math.round(model.contextWindow * (model.recommendedBudgetPercent / 100));\n const selection = await selectContext({ task, analysis, budget });\n\n // Estimate cost\n const inputTokens = selection.totalTokens + 500; // + prompt overhead\n const outputTokens = Math.min(model.maxOutput, 4000); // estimated output\n const estimatedCost = (inputTokens / 1_000_000) * model.costPer1MInput +\n (outputTokens / 1_000_000) * model.costPer1MOutput;\n\n // Quality score based on coverage + model strength match\n const taskStrengthMatch = computeStrengthMatch(model, task);\n const coverageFactor = selection.coverage.score / 100;\n const budgetUtilization = selection.usedPercent / 100;\n const qualityScore = Math.round(\n taskStrengthMatch * 40 +\n coverageFactor * 35 +\n Math.min(1, budgetUtilization) * 25,\n );\n\n const recommendation = generateModelRecommendation(model, selection, qualityScore, estimatedCost);\n\n optimizations.push({\n model,\n budget,\n selection,\n estimatedCost,\n qualityScore,\n recommendation,\n });\n }\n\n // Sort by quality score\n optimizations.sort((a, b) => b.qualityScore - a.qualityScore);\n\n // Find best in each category\n const bestQuality = optimizations[0];\n const bestValue = optimizations.reduce((best, curr) =>\n (curr.qualityScore / Math.max(curr.estimatedCost, 0.0001)) >\n (best.qualityScore / Math.max(best.estimatedCost, 0.0001)) ? curr : best,\n );\n const cheapest = optimizations.reduce((best, curr) =>\n curr.estimatedCost < best.estimatedCost ? curr : best,\n );\n\n return {\n task,\n models: optimizations,\n recommendation: {\n bestValue: bestValue.model.id,\n bestQuality: bestQuality.model.id,\n bestSpeed: cheapest.model.id,\n reasoning: `Best quality: ${bestQuality.model.name} (${bestQuality.qualityScore}/100, $${bestQuality.estimatedCost.toFixed(4)}/call). ` +\n `Best value: ${bestValue.model.name} (${bestValue.qualityScore}/100, $${bestValue.estimatedCost.toFixed(4)}/call). ` +\n `Cheapest: ${cheapest.model.name} ($${cheapest.estimatedCost.toFixed(4)}/call).`,\n },\n };\n}\n\nfunction computeStrengthMatch(model: ModelProfile, task: string): number {\n const taskLower = task.toLowerCase();\n let matches = 0;\n let checks = 0;\n\n const strengthKeywords: Record<ModelStrength, string[]> = {\n 'code-generation': ['implement', 'create', 'build', 'add', 'write', 'generate'],\n 'analysis': ['analyze', 'understand', 'explain', 'review', 'investigate'],\n 'refactoring': ['refactor', 'optimize', 'improve', 'clean', 'restructure'],\n 'debugging': ['fix', 'debug', 'bug', 'error', 'issue', 'broken'],\n 'documentation': ['document', 'readme', 'comment', 'explain', 'describe'],\n 'testing': ['test', 'spec', 'coverage', 'unit', 'integration'],\n 'general': [],\n };\n\n for (const strength of model.strengths) {\n const keywords = strengthKeywords[strength];\n if (keywords.length === 0) continue;\n checks++;\n if (keywords.some((kw) => taskLower.includes(kw))) matches++;\n }\n\n if (checks === 0) return 0.7; // general model\n return 0.5 + (matches / checks) * 0.5;\n}\n\nfunction generateModelRecommendation(\n model: ModelProfile,\n selection: ContextSelection,\n quality: number,\n cost: number,\n): string {\n if (quality >= 90) return `Excellent for this task. ${selection.coverage.score}% coverage, great strength match.`;\n if (quality >= 70) return `Good choice. ${selection.coverage.score}% coverage at $${cost.toFixed(4)}/call.`;\n if (quality >= 50) return `Adequate. Consider a model with better ${model.strengths.length < 3 ? 'breadth' : 'specialization'}.`;\n return `Not ideal for this task type. Coverage: ${selection.coverage.score}%.`;\n}\n\n// ===== RENDERING =====\n\nexport function renderMultiModelResult(result: MultiModelResult): string {\n const lines: string[] = [];\n\n lines.push('');\n lines.push(` ╔══════════════════════════════════════════════════════════════════════════╗`);\n lines.push(` ║ 🎯 Multi-Model Optimization ║`);\n lines.push(` ║ Task: ${pad(result.task.substring(0, 58), 58)} ║`);\n lines.push(` ╠══════════════════════════════════════════════════════════════════════════╣`);\n lines.push(` ║ ║`);\n lines.push(` ║ ${pad('Model', 22)} ${pad('Budget', 10)} ${pad('Tokens', 10)} ${pad('Cover', 8)} ${pad('Quality', 10)} ${pad('$/call', 10)} ║`);\n lines.push(` ║ ${'─'.repeat(70)} ║`);\n\n for (const opt of result.models) {\n const isRec = opt.model.id === result.recommendation.bestValue;\n const prefix = isRec ? '★ ' : ' ';\n lines.push(` ║ ${prefix}${pad(opt.model.name, 20)} ${pad(fmt(opt.budget), 10)} ${pad(fmt(opt.selection.totalTokens), 10)} ${pad(opt.selection.coverage.score + '%', 8)} ${pad(opt.qualityScore + '/100', 10)} ${pad('$' + opt.estimatedCost.toFixed(4), 10)} ║`);\n }\n\n lines.push(` ║ ║`);\n lines.push(` ║ ★ = Best value ║`);\n lines.push(` ║ ${pad(result.recommendation.reasoning, 72)} ║`);\n lines.push(` ║ ║`);\n lines.push(` ╚══════════════════════════════════════════════════════════════════════════╝`);\n\n return lines.join('\\n');\n}\n\nfunction pad(s: string, w: number): string { return s.padEnd(w).substring(0, w); }\nfunction fmt(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`;\n return n.toString();\n}\n"],"mappings":"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","names":["readFile","stat","join","relative","resolve","basename","join","stat","readFile","relative","basename","resolve","readFile","join","existsSync","join","existsSync","readFile","createHash","readdir","stat","join","extname","relative","resolve","readdir","join","extname","stat","relative","createHash","resolve","resolve","resolve","resolve","resolve","risk","createHash","readFile","resolve","relative","Project","SyntaxKind","readFile","existsSync","join","TS_EXTENSIONS","emptyResult","readFile","Project","SyntaxKind","join","existsSync","getCascadeLevels","createHash","pad","pad","fmt","resolve","join","readFile","writeFile","mkdir","join","resolve","mkdir","readFile","writeFile","extractKeywords","join","basename","readFile","writeFile","mkdir","computeFingerprint","basename","join","readFile","createEmptyModel","mkdir","writeFile","resolve","join","readFile","writeFile","mkdir","join","resolve","mkdir","getModelPath","readFile","writeFile","createEmptyModel","pad","pad","generateVerdict","pad","fmt","resolve","join","dirname","basename","writeFile","mkdir","resolve","basename","join","mkdir","dirname","writeFile","pad","fmt","MODEL_REGISTRY","pad","fmt"]}