trace-mcp 0.1.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.
- package/LICENSE +137 -0
- package/README.md +298 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +21188 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +656 -0
- package/dist/index.js +6797 -0
- package/dist/index.js.map +1 -0
- package/package.json +74 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server.ts","../src/tools/project.ts","../src/tools/navigation.ts","../src/db/fts.ts","../src/utils/source-reader.ts","../src/utils/env-parser.ts","../src/scoring/hybrid.ts","../src/scoring/pagerank.ts","../src/errors.ts","../src/ai/search.ts","../src/utils/token-counter.ts","../src/tools/components.ts","../src/tools/impact.ts","../src/tools/context.ts","../src/scoring/assembly.ts","../src/indexer/pipeline.ts","../src/logger.ts","../src/plugin-api/executor.ts","../src/utils/hasher.ts","../src/utils/security.ts","../src/indexer/monorepo.ts","../src/indexer/resolvers/es-modules.ts","../src/ai/fallback.ts","../src/ai/ollama.ts","../src/ai/openai.ts","../src/ai/vector-store.ts","../src/ai/inference-cache.ts","../src/ai/prompts.ts","../src/ai/summarization-pipeline.ts","../src/ai/reranker.ts","../src/ai/index.ts","../src/tools/ai-tools.ts","../src/scoring/structured-assembly.ts","../src/tools/middleware-chain.ts","../src/tools/module-graph.ts","../src/indexer/plugins/framework/nestjs/index.ts","../src/tools/di-tree.ts","../src/tools/rn-navigation.ts","../src/tools/screen-context.ts","../src/tools/flow.ts","../src/tools/model.ts","../src/tools/schema.ts","../src/tools/events.ts","../src/tools/references.ts","../src/tools/call-graph.ts","../src/tools/livewire.ts","../src/tools/nova.ts","../src/tools/tests.ts","../src/tools/introspect.ts","../src/db/schema.ts","../src/db/store.ts","../src/plugin-api/registry.ts","../src/config.ts"],"sourcesContent":["import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { Store } from './db/store.js';\nimport type { PluginRegistry } from './plugin-api/registry.js';\nimport type { TraceMcpConfig } from './config.js';\nimport { getIndexHealth, getProjectMap } from './tools/project.js';\nimport { getSymbol, search, getFileOutline, type SearchResultItemProjected } from './tools/navigation.js';\nimport { getComponentTree } from './tools/components.js';\nimport { getChangeImpact } from './tools/impact.js';\nimport { getFeatureContext } from './tools/context.js';\nimport { IndexingPipeline } from './indexer/pipeline.js';\nimport { formatToolError } from './errors.js';\nimport { validatePath } from './utils/security.js';\nimport { logger } from './logger.js';\nimport { createAIProvider, BlobVectorStore, type AIProvider, type RerankerService } from './ai/index.js';\nimport { LLMReranker } from './ai/reranker.js';\nimport { registerAITools } from './tools/ai-tools.js';\nimport { getMiddlewareChain } from './tools/middleware-chain.js';\nimport { getModuleGraph } from './tools/module-graph.js';\nimport { getDITree } from './tools/di-tree.js';\nimport { getNavigationGraph } from './tools/rn-navigation.js';\nimport { getScreenContext } from './tools/screen-context.js';\nimport { getRequestFlow } from './tools/flow.js';\nimport { getModelContext } from './tools/model.js';\nimport { getSchema } from './tools/schema.js';\nimport { getEventGraph } from './tools/events.js';\nimport { findReferences } from './tools/references.js';\nimport { getCallGraph } from './tools/call-graph.js';\nimport { getLivewireContext } from './tools/livewire.js';\nimport { getNovaResource } from './tools/nova.js';\nimport { getTestsFor } from './tools/tests.js';\nimport { getImplementations, getApiSurface, getPluginRegistry, getTypeHierarchy, getDeadExports, getDependencyGraph, getUntestedExports, selfAudit } from './tools/introspect.js';\n\n/** Compact JSON — no pretty-printing; saves 25–35% tokens on every response */\nfunction j(value: unknown): string {\n return JSON.stringify(value);\n}\n\nexport function createServer(\n store: Store,\n registry: PluginRegistry,\n config: TraceMcpConfig,\n rootPath?: string,\n): McpServer {\n const server = new McpServer({\n name: 'trace-mcp',\n version: '0.1.0',\n });\n\n const projectRoot = rootPath ?? process.cwd();\n\n // AI layer (optional)\n const aiProvider: AIProvider = createAIProvider(config);\n const vectorStore = config.ai?.enabled ? new BlobVectorStore(store.db) : null;\n const embeddingService = config.ai?.enabled ? aiProvider.embedding() : null;\n const reranker: RerankerService | null = config.ai?.enabled\n ? new LLMReranker(aiProvider.fastInference())\n : null;\n\n // Determine which framework plugins are registered → drives dynamic tool registration\n const frameworkNames = new Set(\n registry.getAllFrameworkPlugins().map((p) => p.manifest.name),\n );\n const has = (...names: string[]) => names.some((n) => frameworkNames.has(n));\n\n /** Validate a user-supplied path stays within projectRoot; returns error response on failure */\n function guardPath(filePath: string): { content: [{ type: 'text'; text: string }]; isError: true } | null {\n const check = validatePath(filePath, projectRoot);\n if (check.isErr()) {\n return { content: [{ type: 'text', text: j(formatToolError(check.error)) }], isError: true };\n }\n return null;\n }\n\n // --- Core Tools (always registered) ---\n\n server.tool(\n 'get_index_health',\n 'Get index status, statistics, and health information',\n {},\n async () => {\n const result = getIndexHealth(store, config);\n return { content: [{ type: 'text', text: j(result) }] };\n },\n );\n\n server.tool(\n 'reindex',\n 'Trigger (re)indexing of the project or a subdirectory',\n {\n path: z.string().max(512).optional().describe('Subdirectory to index (default: project root)'),\n force: z.boolean().optional().describe('Skip hash check and reindex all files'),\n },\n async ({ path: indexPath, force }) => {\n if (indexPath) {\n const blocked = guardPath(indexPath);\n if (blocked) return blocked;\n }\n logger.info({ path: indexPath, force }, 'Reindex requested');\n const pipeline = new IndexingPipeline(store, registry, config, projectRoot);\n\n const result = indexPath\n ? await pipeline.indexFiles([indexPath])\n : await pipeline.indexAll(force ?? false);\n\n return { content: [{ type: 'text', text: j({ status: 'completed', ...result }) }] };\n },\n );\n\n server.tool(\n 'get_project_map',\n 'Get project overview: frameworks, statistics, languages. Use summary_only=true for a lightweight token-saving version.',\n {\n summary_only: z.boolean().optional().describe('Return only framework list + counts (default false)'),\n },\n async ({ summary_only }) => {\n const result = getProjectMap(store, registry, summary_only ?? false);\n return { content: [{ type: 'text', text: j(result) }] };\n },\n );\n\n // --- Env Vars Tool ---\n\n server.tool(\n 'get_env_vars',\n 'List environment variable keys from .env files with inferred value types/formats. Never exposes actual values — only keys, types (string/number/boolean/empty), and formats (url/email/ip/path/uuid/json/base64/csv/dsn/etc). Use to understand project configuration without accessing secrets.',\n {\n pattern: z.string().max(256).optional().describe('Filter keys by pattern (e.g. \"DB_\" or \"REDIS\")'),\n file: z.string().max(512).optional().describe('Filter by specific .env file path'),\n },\n async ({ pattern, file }) => {\n let vars = pattern ? store.searchEnvVars(pattern) : store.getAllEnvVars();\n\n if (file) {\n vars = vars.filter((v) => v.file_path === file || v.file_path.endsWith(file));\n }\n\n if (vars.length === 0) {\n return { content: [{ type: 'text', text: 'No env vars found. Run indexing first or adjust the filter.' }] };\n }\n\n // Group by file\n const grouped: Record<string, { key: string; type: string; format: string | null; comment: string | null }[]> = {};\n for (const v of vars) {\n const arr = grouped[v.file_path] ??= [];\n arr.push({\n key: v.key,\n type: v.value_type,\n format: v.value_format,\n comment: v.comment,\n });\n }\n\n return { content: [{ type: 'text', text: j(grouped) }] };\n },\n );\n\n // --- Level 1 Navigation Tools ---\n\n server.tool(\n 'get_symbol',\n 'Look up a symbol by symbol_id or FQN and return its source code',\n {\n symbol_id: z.string().max(512).optional().describe('The symbol_id to look up'),\n fqn: z.string().max(512).optional().describe('The fully qualified name to look up'),\n max_lines: z.number().int().min(1).max(10000).optional().describe('Truncate source to this many lines (omit for full source)'),\n },\n async ({ symbol_id, fqn, max_lines }) => {\n const result = getSymbol(store, projectRoot, { symbolId: symbol_id, fqn, maxLines: max_lines });\n if (result.isErr()) {\n return { content: [{ type: 'text', text: j(formatToolError(result.error)) }], isError: true };\n }\n const { symbol, file, source, truncated } = result.value;\n return {\n content: [{\n type: 'text',\n text: j({\n symbol_id: symbol.symbol_id,\n name: symbol.name,\n kind: symbol.kind,\n fqn: symbol.fqn,\n signature: symbol.signature,\n summary: symbol.summary,\n file: file.path,\n line_start: symbol.line_start,\n line_end: symbol.line_end,\n source,\n ...(truncated ? { truncated: true } : {}),\n }),\n }],\n };\n },\n );\n\n server.tool(\n 'search',\n 'Search symbols using full-text search with optional filters',\n {\n query: z.string().min(1).max(500).describe('Search query'),\n kind: z.string().max(64).optional().describe('Filter by symbol kind (class, method, function, etc.)'),\n language: z.string().max(64).optional().describe('Filter by language'),\n file_pattern: z.string().max(512).optional().describe('Filter by file path pattern'),\n implements: z.string().max(256).optional().describe('Filter to classes implementing this interface'),\n extends: z.string().max(256).optional().describe('Filter to classes/interfaces extending this name'),\n limit: z.number().int().min(1).max(500).optional().describe('Max results (default 20)'),\n offset: z.number().int().min(0).max(50000).optional().describe('Offset for pagination'),\n },\n async ({ query, kind, language, file_pattern, limit, offset, implements: impl, extends: ext }) => {\n const result = await search(\n store,\n query,\n { kind, language, filePattern: file_pattern, implements: impl, extends: ext },\n limit ?? 20,\n offset ?? 0,\n { vectorStore, embeddingService, reranker },\n );\n // Project to AI-useful fields only — strips DB internals (id, file_id, byte offsets, etc.)\n const items: SearchResultItemProjected[] = result.items.map(({ symbol, file, score }) => ({\n symbol_id: symbol.symbol_id,\n name: symbol.name,\n kind: symbol.kind,\n fqn: symbol.fqn,\n signature: symbol.signature,\n summary: symbol.summary,\n file: file.path,\n line: symbol.line_start,\n score,\n }));\n return { content: [{ type: 'text', text: j({ items, total: result.total, search_mode: result.search_mode }) }] };\n },\n );\n\n server.tool(\n 'get_file_outline',\n 'Get all symbols for a file (signatures only, no bodies)',\n {\n path: z.string().max(512).describe('Relative file path'),\n },\n async ({ path: filePath }) => {\n const blocked = guardPath(filePath);\n if (blocked) return blocked;\n const result = getFileOutline(store, filePath);\n if (result.isErr()) {\n return { content: [{ type: 'text', text: j(formatToolError(result.error)) }], isError: true };\n }\n return { content: [{ type: 'text', text: j(result.value) }] };\n },\n );\n\n server.tool(\n 'get_change_impact',\n 'Determine what depends on a file or symbol (reverse dependency analysis)',\n {\n file_path: z.string().max(512).optional().describe('Relative file path to analyze'),\n symbol_id: z.string().max(512).optional().describe('Symbol ID to analyze'),\n depth: z.number().int().min(1).max(20).optional().describe('Max traversal depth (default 3)'),\n max_dependents: z.number().int().min(1).max(5000).optional().describe('Cap on returned dependents (default 200)'),\n },\n async ({ file_path, symbol_id, depth, max_dependents }) => {\n if (file_path) {\n const blocked = guardPath(file_path);\n if (blocked) return blocked;\n }\n const result = getChangeImpact(\n store,\n { filePath: file_path, symbolId: symbol_id },\n depth ?? 3,\n max_dependents ?? 200,\n );\n if (result.isErr()) {\n return { content: [{ type: 'text', text: j(formatToolError(result.error)) }], isError: true };\n }\n return { content: [{ type: 'text', text: j(result.value) }] };\n },\n );\n\n server.tool(\n 'get_feature_context',\n 'Find relevant symbols and code for a feature description using FTS + graph expansion',\n {\n description: z.string().min(1).max(2000).describe('Natural language description of the feature to find context for'),\n token_budget: z.number().int().min(100).max(100000).optional().describe('Max tokens for assembled context (default 4000)'),\n },\n async ({ description, token_budget }) => {\n const result = getFeatureContext(store, projectRoot, description, token_budget ?? 4000);\n return { content: [{ type: 'text', text: j(result) }] };\n },\n );\n\n // --- Level 2 Framework Tools ---\n\n if (has('vue', 'nuxt', 'inertia')) {\n server.tool(\n 'get_component_tree',\n 'Build a component render tree starting from a given .vue file',\n {\n component_path: z.string().max(512).describe('Relative path to the root .vue file'),\n depth: z.number().int().min(1).max(20).optional().describe('Max tree depth (default 3)'),\n token_budget: z.number().int().min(100).max(100000).optional().describe('Max tokens for the tree (default 8000)'),\n },\n async ({ component_path, depth, token_budget }) => {\n const blocked = guardPath(component_path);\n if (blocked) return blocked;\n const result = getComponentTree(store, component_path, depth ?? 3, token_budget ?? 8000);\n if (result.isErr()) {\n return { content: [{ type: 'text', text: j(formatToolError(result.error)) }], isError: true };\n }\n return { content: [{ type: 'text', text: j(result.value) }] };\n },\n );\n }\n\n // --- Level 3 Framework-Specific Tools ---\n\n if (has('express', 'nestjs', 'laravel', 'fastapi', 'flask', 'drf', 'spring', 'rails', 'fastify', 'hono', 'trpc')) {\n server.tool(\n 'get_request_flow',\n 'Trace request flow for a URL+method: route → middleware → controller → service (Laravel/Express/NestJS/Fastify/Hono/tRPC/FastAPI/Flask/DRF)',\n {\n url: z.string().max(512).describe('Route URL (e.g. /api/users)'),\n method: z.string().max(64).optional().describe('HTTP method (default GET)'),\n },\n async ({ url, method }) => {\n const result = getRequestFlow(store, url, method ?? 'GET');\n if (result.isErr()) {\n return { content: [{ type: 'text', text: j(formatToolError(result.error)) }], isError: true };\n }\n return { content: [{ type: 'text', text: j(result.value) }] };\n },\n );\n }\n\n if (has('express', 'nestjs', 'fastapi', 'flask', 'spring')) {\n server.tool(\n 'get_middleware_chain',\n 'Trace middleware chain for a route URL (Express/NestJS/FastAPI/Flask)',\n {\n url: z.string().max(512).describe('Route URL to trace middleware for'),\n },\n async ({ url }) => {\n const result = getMiddlewareChain(store, projectRoot, url);\n if (result.isErr()) {\n return { content: [{ type: 'text', text: j(formatToolError(result.error)) }], isError: true };\n }\n return { content: [{ type: 'text', text: j(result.value) }] };\n },\n );\n }\n\n if (has('nestjs')) {\n server.tool(\n 'get_module_graph',\n 'Build NestJS module dependency graph (module -> imports -> controllers -> providers -> exports)',\n {\n module_name: z.string().max(256).describe('NestJS module class name (e.g. AppModule)'),\n },\n async ({ module_name }) => {\n const result = getModuleGraph(store, projectRoot, module_name);\n if (result.isErr()) {\n return { content: [{ type: 'text', text: j(formatToolError(result.error)) }], isError: true };\n }\n return { content: [{ type: 'text', text: j(result.value) }] };\n },\n );\n\n server.tool(\n 'get_di_tree',\n 'Trace NestJS dependency injection tree (what a service injects + who injects it)',\n {\n service_name: z.string().max(256).describe('NestJS service/provider class name'),\n },\n async ({ service_name }) => {\n const result = getDITree(store, service_name);\n if (result.isErr()) {\n return { content: [{ type: 'text', text: j(formatToolError(result.error)) }], isError: true };\n }\n return { content: [{ type: 'text', text: j(result.value) }] };\n },\n );\n }\n\n if (has('react-native')) {\n server.tool(\n 'get_navigation_graph',\n 'Build React Native navigation tree from screens, navigators, and deep links',\n {},\n async () => {\n const result = getNavigationGraph(store);\n if (result.isErr()) {\n return { content: [{ type: 'text', text: j(formatToolError(result.error)) }], isError: true };\n }\n return { content: [{ type: 'text', text: j(result.value) }] };\n },\n );\n\n server.tool(\n 'get_screen_context',\n 'Get full context for a React Native screen: navigator, navigation edges, deep link, platform variants, native modules',\n {\n screen_name: z.string().max(256).describe('Screen name (e.g. ProfileScreen or Profile)'),\n },\n async ({ screen_name }) => {\n const result = getScreenContext(store, screen_name);\n if (result.isErr()) {\n return { content: [{ type: 'text', text: j(formatToolError(result.error)) }], isError: true };\n }\n return { content: [{ type: 'text', text: j(result.value) }] };\n },\n );\n }\n\n if (has('laravel', 'mongoose', 'sequelize', 'prisma', 'typeorm', 'drizzle', 'sqlalchemy')) {\n server.tool(\n 'get_model_context',\n 'Get full model context: relationships, schema, and metadata (Eloquent/Mongoose/Sequelize/SQLAlchemy/Prisma/TypeORM/Drizzle)',\n {\n model_name: z.string().max(256).describe('Model class name (e.g. User, Post)'),\n },\n async ({ model_name }) => {\n const result = getModelContext(store, model_name);\n if (result.isErr()) {\n return { content: [{ type: 'text', text: j(formatToolError(result.error)) }], isError: true };\n }\n return { content: [{ type: 'text', text: j(result.value) }] };\n },\n );\n\n server.tool(\n 'get_schema',\n 'Get database schema reconstructed from migrations or ORM model definitions',\n {\n table_name: z.string().max(256).optional().describe('Table/collection/model name (omit for all)'),\n },\n async ({ table_name }) => {\n const result = getSchema(store, table_name);\n if (result.isErr()) {\n return { content: [{ type: 'text', text: j(formatToolError(result.error)) }], isError: true };\n }\n return { content: [{ type: 'text', text: j(result.value) }] };\n },\n );\n }\n\n if (has('laravel', 'nestjs', 'celery', 'django', 'socketio')) {\n server.tool(\n 'get_event_graph',\n 'Get event/signal/task dispatch graph (Laravel events, Django signals, NestJS events, Celery tasks, Socket.io events)',\n {\n event_name: z.string().max(256).optional().describe('Filter to a specific event class name'),\n },\n async ({ event_name }) => {\n const result = getEventGraph(store, event_name);\n if (result.isErr()) {\n return { content: [{ type: 'text', text: j(formatToolError(result.error)) }], isError: true };\n }\n return { content: [{ type: 'text', text: j(result.value) }] };\n },\n );\n }\n\n server.tool(\n 'find_references',\n 'Find all places that reference a symbol or file (incoming edges: imports, calls, renders, dispatches, etc.)',\n {\n symbol_id: z.string().max(512).optional().describe('Symbol ID to find references for'),\n fqn: z.string().max(512).optional().describe('Fully qualified name to find references for'),\n file_path: z.string().max(512).optional().describe('File path to find references for'),\n },\n async ({ symbol_id, fqn, file_path }) => {\n if (file_path) {\n const blocked = guardPath(file_path);\n if (blocked) return blocked;\n }\n const result = findReferences(store, { symbolId: symbol_id, fqn, filePath: file_path });\n if (result.isErr()) {\n return { content: [{ type: 'text', text: j(formatToolError(result.error)) }], isError: true };\n }\n return { content: [{ type: 'text', text: j(result.value) }] };\n },\n );\n\n server.tool(\n 'get_call_graph',\n 'Build a bidirectional call graph centered on a symbol (who it calls + who calls it)',\n {\n symbol_id: z.string().max(512).optional().describe('Symbol ID to center the graph on'),\n fqn: z.string().max(512).optional().describe('Fully qualified name to center the graph on'),\n depth: z.number().int().min(1).max(20).optional().describe('Traversal depth on each side (default 2)'),\n },\n async ({ symbol_id, fqn, depth }) => {\n const result = getCallGraph(store, { symbolId: symbol_id, fqn }, depth ?? 2);\n if (result.isErr()) {\n return { content: [{ type: 'text', text: j(formatToolError(result.error)) }], isError: true };\n }\n return { content: [{ type: 'text', text: j(result.value) }] };\n },\n );\n\n server.tool(\n 'get_tests_for',\n 'Find test files and test functions that cover a given symbol or file',\n {\n symbol_id: z.string().max(512).optional().describe('Symbol ID to find tests for'),\n fqn: z.string().max(512).optional().describe('Fully qualified name to find tests for'),\n file_path: z.string().max(512).optional().describe('File path to find tests for'),\n },\n async ({ symbol_id, fqn, file_path }) => {\n if (file_path) {\n const blocked = guardPath(file_path);\n if (blocked) return blocked;\n }\n const result = getTestsFor(store, { symbolId: symbol_id, fqn, filePath: file_path });\n if (result.isErr()) {\n return { content: [{ type: 'text', text: j(formatToolError(result.error)) }], isError: true };\n }\n return { content: [{ type: 'text', text: j(result.value) }] };\n },\n );\n\n if (has('laravel')) {\n server.tool(\n 'get_livewire_context',\n 'Get full context for a Livewire component: properties, actions, events, view, child components',\n {\n component_name: z.string().max(256).describe('Livewire component class name or FQN (e.g. UserProfile or App\\\\Livewire\\\\UserProfile)'),\n },\n async ({ component_name }) => {\n const result = getLivewireContext(store, component_name);\n if (result.isErr()) {\n return { content: [{ type: 'text', text: j(formatToolError(result.error)) }], isError: true };\n }\n return { content: [{ type: 'text', text: j(result.value) }] };\n },\n );\n\n server.tool(\n 'get_nova_resource',\n 'Get full context for a Laravel Nova resource: model, fields, actions, filters, lenses, metrics',\n {\n resource_name: z.string().max(256).describe('Nova resource class name or FQN (e.g. User or App\\\\Nova\\\\User)'),\n },\n async ({ resource_name }) => {\n const result = getNovaResource(store, resource_name);\n if (result.isErr()) {\n return { content: [{ type: 'text', text: j(formatToolError(result.error)) }], isError: true };\n }\n return { content: [{ type: 'text', text: j(result.value) }] };\n },\n );\n }\n\n if (has('zustand-redux')) {\n server.tool(\n 'get_state_stores',\n 'List all Zustand stores and Redux Toolkit slices with their state fields, actions/reducers, and dispatch sites',\n {},\n async () => {\n const routes = store.getAllRoutes();\n const stores = routes.filter((r) => r.method === 'STORE' || r.method === 'SLICE');\n const dispatches = routes.filter((r) => r.method === 'DISPATCH');\n return {\n content: [{\n type: 'text',\n text: j({\n stores: stores.map((s) => ({\n type: s.method === 'STORE' ? 'zustand' : 'redux',\n name: s.uri.replace(/^(zustand|redux):/, ''),\n handler: s.handler,\n metadata: s.metadata ? JSON.parse(s.metadata) : null,\n })),\n dispatches: dispatches.map((d) => ({\n action: d.uri.replace(/^action:/, ''),\n file: d.file_id ? store.getFileById(d.file_id)?.path : null,\n })),\n totalStores: stores.length,\n totalDispatches: dispatches.length,\n }),\n }],\n };\n },\n );\n }\n\n // --- Self-Development / Introspection Tools ---\n\n server.tool(\n 'get_implementations',\n 'Find all classes that implement or extend a given interface or base class',\n {\n name: z.string().max(256).describe('Interface or base class name (e.g. UserRepositoryInterface)'),\n },\n async ({ name }) => {\n const result = getImplementations(store, name);\n return { content: [{ type: 'text', text: j(result) }] };\n },\n );\n\n server.tool(\n 'get_api_surface',\n 'List all exported symbols (public API) of a file or matching files',\n {\n file_pattern: z.string().max(512).optional().describe('Glob-style pattern to filter files (e.g. src/services/*.ts)'),\n },\n async ({ file_pattern }) => {\n const result = getApiSurface(store, file_pattern);\n return { content: [{ type: 'text', text: j(result) }] };\n },\n );\n\n server.tool(\n 'get_plugin_registry',\n 'List all registered indexer plugins and the edge types they emit',\n {},\n async () => {\n const result = getPluginRegistry(store, registry, frameworkNames);\n return { content: [{ type: 'text', text: j(result) }] };\n },\n );\n\n server.tool(\n 'get_type_hierarchy',\n 'Walk TypeScript class/interface hierarchy: ancestors (what it extends/implements) and descendants (what extends/implements it)',\n {\n name: z.string().max(256).describe('Class or interface name (e.g. \"LanguagePlugin\", \"Store\")'),\n max_depth: z.number().int().min(1).max(20).optional().describe('Max traversal depth (default 10)'),\n },\n async ({ name, max_depth }) => {\n const result = getTypeHierarchy(store, name, max_depth ?? 10);\n return { content: [{ type: 'text', text: j(result) }] };\n },\n );\n\n server.tool(\n 'get_dead_exports',\n 'Find exported symbols never imported by any other file — dead code candidates',\n {\n file_pattern: z.string().max(512).optional().describe('Filter files by glob pattern (e.g. \"src/tools/*.ts\")'),\n },\n async ({ file_pattern }) => {\n const result = getDeadExports(store, file_pattern);\n return { content: [{ type: 'text', text: j(result) }] };\n },\n );\n\n server.tool(\n 'get_dependency_graph',\n 'Show file-level dependency graph: what a file imports and what imports it (requires reindex for ESM edge resolution)',\n {\n file_path: z.string().max(512).describe('Relative file path to analyze (e.g. \"src/server.ts\")'),\n },\n async ({ file_path }) => {\n const blocked = guardPath(file_path);\n if (blocked) return blocked;\n const result = getDependencyGraph(store, file_path);\n return { content: [{ type: 'text', text: j(result) }] };\n },\n );\n\n server.tool(\n 'get_untested_exports',\n 'Find exported public symbols with no matching test file — test coverage gaps',\n {\n file_pattern: z.string().max(512).optional().describe('Filter by file glob pattern (e.g. \"src/tools/%\")'),\n },\n async ({ file_pattern }) => {\n const result = getUntestedExports(store, file_pattern);\n return { content: [{ type: 'text', text: j(result) }] };\n },\n );\n\n\n server.tool('self_audit', 'One-shot project health audit: dead exports, untested code, dependency hotspots, heritage metrics', {}, async () => {\n return { content: [{ type: 'text', text: j(selfAudit(store)) }] };\n });\n // --- Resources ---\n\n server.resource(\n 'project-map',\n 'project://map',\n { mimeType: 'application/json', description: 'Project map (frameworks, stats, structure)' },\n async () => {\n const result = getProjectMap(store, registry);\n return {\n contents: [{ uri: 'project://map', mimeType: 'application/json', text: j(result) }],\n };\n },\n );\n\n server.resource(\n 'project-health',\n 'project://health',\n { mimeType: 'application/json', description: 'Index health status' },\n async () => {\n const result = getIndexHealth(store, config);\n return {\n contents: [{ uri: 'project://health', mimeType: 'application/json', text: j(result) }],\n };\n },\n );\n\n // --- AI-powered tools (registered only when AI is enabled) ---\n if (config.ai?.enabled) {\n registerAITools(server, {\n store,\n smartInference: aiProvider.inference(),\n fastInference: aiProvider.fastInference(),\n embeddingService,\n vectorStore,\n reranker,\n projectRoot,\n });\n }\n\n return server;\n}\n","import type { Store, IndexStats } from '../db/store.js';\nimport type { PluginRegistry } from '../plugin-api/registry.js';\nimport type { TraceMcpConfig } from '../config.js';\n\nexport interface IndexHealthResult {\n status: 'ok' | 'degraded' | 'empty';\n stats: IndexStats;\n schemaVersion: number;\n config: {\n dbPath: string;\n includePatterns: string[];\n excludePatterns: string[];\n };\n warnings: string[];\n}\n\nexport function getIndexHealth(\n store: Store,\n config: TraceMcpConfig,\n): IndexHealthResult {\n const stats = store.getStats();\n const warnings: string[] = [];\n\n let status: 'ok' | 'degraded' | 'empty' = 'ok';\n if (stats.totalFiles === 0) {\n status = 'empty';\n } else if (stats.partialFiles > 0 || stats.errorFiles > 0) {\n status = 'degraded';\n if (stats.partialFiles > 0) warnings.push(`${stats.partialFiles} files parsed partially`);\n if (stats.errorFiles > 0) warnings.push(`${stats.errorFiles} files failed to parse`);\n }\n\n const versionRow = store.db.prepare(\"SELECT value FROM schema_meta WHERE key = 'schema_version'\").get() as { value: string } | undefined;\n\n return {\n status,\n stats,\n schemaVersion: versionRow ? Number(versionRow.value) : 0,\n config: {\n dbPath: config.db.path,\n includePatterns: config.include,\n excludePatterns: config.exclude,\n },\n warnings,\n };\n}\n\nexport interface ProjectMapResult {\n frameworks: string[];\n stats: IndexStats;\n languages: { language: string; count: number }[];\n}\n\nexport interface ProjectMapSummary {\n frameworks: string[];\n fileCount: number;\n symbolCount: number;\n languages: string[];\n}\n\nexport function getProjectMap(store: Store, registry: PluginRegistry, summaryOnly?: boolean): ProjectMapResult | ProjectMapSummary {\n const stats = store.getStats();\n const frameworks = registry.getAllFrameworkPlugins().map((p) => p.manifest.name);\n\n if (summaryOnly) {\n const languageRows = store.db.prepare(\n 'SELECT language FROM files WHERE language IS NOT NULL GROUP BY language ORDER BY COUNT(*) DESC',\n ).all() as { language: string }[];\n return {\n frameworks,\n fileCount: stats.totalFiles,\n symbolCount: stats.totalSymbols,\n languages: languageRows.map((r) => r.language),\n };\n }\n\n const languageRows = store.db.prepare(\n 'SELECT language, COUNT(*) as count FROM files WHERE language IS NOT NULL GROUP BY language ORDER BY count DESC',\n ).all() as { language: string; count: number }[];\n\n return {\n frameworks,\n stats,\n languages: languageRows,\n };\n}\n","import path from 'node:path';\nimport type { Store, SymbolRow, FileRow } from '../db/store.js';\nimport { searchFts, type FtsResult, type FtsFilters } from '../db/fts.js';\nimport { readByteRange } from '../utils/source-reader.js';\nimport { hybridScore, getTypeBonus, computeRecency } from '../scoring/hybrid.js';\nimport { computePageRank } from '../scoring/pagerank.js';\nimport { notFound, type TraceMcpResult } from '../errors.js';\nimport { ok, err } from 'neverthrow';\nimport { hybridSearch as aiHybridSearch } from '../ai/search.js';\nimport type { VectorStore, EmbeddingService, RerankerService } from '../ai/interfaces.js';\n\n// ─── get_symbol ─────────────────────────────────────────────\n\nexport interface GetSymbolResult {\n symbol: SymbolRow;\n file: FileRow;\n source: string;\n truncated?: boolean;\n}\n\nexport function getSymbol(\n store: Store,\n rootPath: string,\n opts: { symbolId?: string; fqn?: string; maxLines?: number },\n): TraceMcpResult<GetSymbolResult> {\n let symbol: SymbolRow | undefined;\n\n if (opts.symbolId) {\n symbol = store.getSymbolBySymbolId(opts.symbolId);\n } else if (opts.fqn) {\n symbol = store.getSymbolByFqn(opts.fqn);\n }\n\n if (!symbol) {\n return err(notFound(opts.symbolId ?? opts.fqn ?? 'unknown'));\n }\n\n const file = store.getFileById(symbol.file_id);\n if (!file) {\n return err(notFound(`file:${symbol.file_id}`));\n }\n\n const absPath = path.resolve(rootPath, file.path);\n let source: string;\n let truncated: boolean | undefined;\n try {\n source = readByteRange(absPath, symbol.byte_start, symbol.byte_end);\n if (opts.maxLines != null) {\n const lines = source.split('\\n');\n if (lines.length > opts.maxLines) {\n source = lines.slice(0, opts.maxLines).join('\\n') + '\\n// ... truncated';\n truncated = true;\n }\n }\n } catch {\n source = symbol.signature ?? '// source unavailable';\n }\n\n return ok({ symbol, file, source, ...(truncated ? { truncated: true } : {}) });\n}\n\n// ─── search ─────────────────────────────────────────────────\n\nexport interface SearchFilters {\n kind?: string;\n language?: string;\n filePattern?: string;\n /** Filter to symbols that implement this interface (metadata.implements contains value) */\n implements?: string;\n /** Filter to symbols that extend this class/interface (metadata.extends contains value) */\n extends?: string;\n}\n\nexport interface SearchResultItem {\n symbol: SymbolRow;\n file: FileRow;\n score: number;\n}\n\n/** Projected search item: only fields useful to an AI client */\nexport interface SearchResultItemProjected {\n symbol_id: string;\n name: string;\n kind: string;\n fqn: string | null;\n signature: string | null;\n summary: string | null;\n file: string;\n line: number | null;\n score: number;\n}\n\nexport interface SearchAIOptions {\n vectorStore?: VectorStore | null;\n embeddingService?: EmbeddingService | null;\n reranker?: RerankerService | null;\n}\n\nexport interface SearchResult {\n items: SearchResultItem[];\n total: number;\n search_mode?: 'hybrid_ai' | 'fts';\n}\n\nexport async function search(\n store: Store,\n query: string,\n filters?: SearchFilters,\n limit = 20,\n offset = 0,\n aiOptions?: SearchAIOptions,\n): Promise<SearchResult> {\n const fetchLimit = limit + offset + 50;\n const useAI = !!(aiOptions?.vectorStore && aiOptions?.embeddingService);\n\n // Build initial candidates: (symbolIdStr, relevance [0,1])\n let candidates: Array<{ symbolIdStr: string; relevance: number }>;\n let searchMode: 'hybrid_ai' | 'fts';\n\n if (useAI) {\n const hybridResults = await aiHybridSearch(\n store.db,\n query,\n aiOptions!.vectorStore!,\n aiOptions!.embeddingService!,\n fetchLimit,\n aiOptions?.reranker,\n );\n if (hybridResults.length === 0) return { items: [], total: 0, search_mode: 'hybrid_ai' };\n // Normalize RRF scores (already positive, descending)\n const maxScore = hybridResults[0].score || 1;\n candidates = hybridResults.map((r) => ({\n symbolIdStr: r.symbolIdStr,\n relevance: r.score / maxScore,\n }));\n searchMode = 'hybrid_ai';\n } else {\n const ftsFilters: FtsFilters = {\n kind: filters?.kind,\n language: filters?.language,\n filePattern: filters?.filePattern,\n };\n const ftsResults = searchFts(store.db, query, fetchLimit, 0, ftsFilters);\n if (ftsResults.length === 0) return { items: [], total: 0, search_mode: 'fts' };\n // BM25 ranks are negative: lower = better match\n const minRank = Math.min(...ftsResults.map((r) => r.rank));\n const maxRank = Math.max(...ftsResults.map((r) => r.rank));\n const rankSpread = maxRank - minRank || 1;\n candidates = ftsResults.map((r) => ({\n symbolIdStr: r.symbolIdStr,\n relevance: 1 - (r.rank - minRank) / rankSpread,\n }));\n searchMode = 'fts';\n }\n\n // Build PageRank map\n const pagerankMap = computePageRank(store.db);\n const maxPr = Math.max(...pagerankMap.values(), 0.001);\n const now = new Date();\n const scored: SearchResultItem[] = [];\n\n // Batch-fetch all candidate symbols in one query\n const symbolIdStrs = candidates.map((c) => c.symbolIdStr);\n const allSymbols = symbolIdStrs.length > 0\n ? store.db.prepare(\n `SELECT * FROM symbols WHERE symbol_id IN (${symbolIdStrs.map(() => '?').join(',')})`,\n ).all(...symbolIdStrs) as import('../db/store.js').SymbolRow[]\n : [];\n const symbolByIdStr = new Map(allSymbols.map((s) => [s.symbol_id, s]));\n\n // Batch-fetch files and node IDs\n const fileIds = [...new Set(allSymbols.map((s) => s.file_id))];\n const fileMap = store.getFilesByIds(fileIds);\n const symIds = allSymbols.map((s) => s.id);\n const nodeMap = store.getNodeIdsBatch('symbol', symIds);\n\n // Heritage post-filter: implements / extends (checks symbol metadata)\n const heritageFilter = filters?.implements || filters?.extends;\n\n for (const candidate of candidates) {\n const symbol = symbolByIdStr.get(candidate.symbolIdStr);\n if (!symbol) continue;\n\n if (heritageFilter && symbol.metadata) {\n const meta = typeof symbol.metadata === 'string'\n ? JSON.parse(symbol.metadata) as Record<string, unknown>\n : symbol.metadata as Record<string, unknown>;\n\n if (filters?.implements) {\n const impl = meta['implements'];\n if (!Array.isArray(impl) || !(impl as string[]).includes(filters.implements)) continue;\n }\n if (filters?.extends) {\n const ext = meta['extends'];\n const extArr = Array.isArray(ext) ? ext as string[] : typeof ext === 'string' ? [ext] : [];\n if (!extArr.includes(filters.extends)) continue;\n }\n } else if (heritageFilter) {\n continue; // no metadata → can't match heritage filter\n }\n\n const file = fileMap.get(symbol.file_id);\n if (!file) continue;\n\n const nodeId = nodeMap.get(symbol.id);\n const pr = nodeId ? (pagerankMap.get(nodeId) ?? 0) / maxPr : 0;\n const recency = computeRecency(file.indexed_at, now);\n const typeBonus = getTypeBonus(symbol.kind);\n\n const score = hybridScore({ relevance: candidate.relevance, pagerank: pr, recency, typeBonus });\n scored.push({ symbol, file, score });\n }\n\n scored.sort((a, b) => b.score - a.score);\n const total = scored.length;\n const items = scored.slice(offset, offset + limit);\n\n return { items, total, search_mode: searchMode };\n}\n\n// ─── get_file_outline ───────────────────────────────────────\n\nexport interface FileOutlineSymbol {\n symbolId: string;\n name: string;\n kind: string;\n fqn: string | null;\n signature: string | null;\n lineStart: number | null;\n lineEnd: number | null;\n}\n\nexport interface FileOutlineResult {\n path: string;\n language: string | null;\n symbols: FileOutlineSymbol[];\n}\n\nexport function getFileOutline(\n store: Store,\n filePath: string,\n): TraceMcpResult<FileOutlineResult> {\n const file = store.getFile(filePath);\n if (!file) {\n return err(notFound(filePath));\n }\n\n const symbols = store.getSymbolsByFile(file.id);\n\n return ok({\n path: file.path,\n language: file.language,\n symbols: symbols.map((s) => ({\n symbolId: s.symbol_id,\n name: s.name,\n kind: s.kind,\n fqn: s.fqn,\n signature: s.signature,\n lineStart: s.line_start,\n lineEnd: s.line_end,\n })),\n });\n}\n","import type Database from 'better-sqlite3';\n\nexport interface FtsResult {\n symbolId: number;\n rank: number;\n name: string;\n fqn: string | null;\n kind: string;\n fileId: number;\n symbolIdStr: string;\n}\n\nexport interface FtsFilters {\n kind?: string;\n language?: string;\n filePattern?: string;\n}\n\nexport function searchFts(\n db: Database.Database,\n query: string,\n limit = 20,\n offset = 0,\n filters?: FtsFilters,\n): FtsResult[] {\n // Escape FTS5 special characters\n const escaped = escapeFtsQuery(query);\n if (!escaped) return [];\n\n const conditions: string[] = ['symbols_fts MATCH ?'];\n const params: unknown[] = [escaped];\n\n // Push filters into SQL to avoid fetching excess rows\n if (filters?.kind) {\n conditions.push('s.kind = ?');\n params.push(filters.kind);\n }\n if (filters?.language) {\n conditions.push('f.language = ?');\n params.push(filters.language);\n }\n if (filters?.filePattern) {\n conditions.push('f.path LIKE ?');\n params.push(`%${filters.filePattern}%`);\n }\n\n const needsFileJoin = filters?.language || filters?.filePattern;\n const fileJoin = needsFileJoin ? 'JOIN files f ON f.id = s.file_id' : '';\n\n const sql = `\n SELECT\n s.id as symbolId,\n rank as rank,\n s.name,\n s.fqn,\n s.kind,\n s.file_id as fileId,\n s.symbol_id as symbolIdStr\n FROM symbols_fts fts\n JOIN symbols s ON s.id = fts.rowid\n ${fileJoin}\n WHERE ${conditions.join(' AND ')}\n ORDER BY rank\n LIMIT ? OFFSET ?\n `;\n\n params.push(limit, offset);\n return db.prepare(sql).all(...params) as FtsResult[];\n}\n\nexport function escapeFtsQuery(query: string): string {\n // Remove special FTS5 characters, then strip boolean keywords that survive as whole words\n const cleaned = query\n .replace(/['\"(){}[\\]*:^~!@#$%&]/g, ' ')\n .replace(/\\b(OR|AND|NOT)\\b/gi, ' ')\n .trim();\n if (!cleaned) return '';\n\n // Split into terms and wrap each in quotes for exact phrase matching\n const terms = cleaned.split(/\\s+/).filter(Boolean);\n return terms.map((t) => `\"${t}\"`).join(' ');\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { redactEnvFile } from './env-parser.js';\n\n/**\n * Read source code from a file using byte offsets. O(1) retrieval.\n */\nexport function readByteRange(\n filePath: string,\n byteStart: number,\n byteEnd: number,\n): string {\n if (byteEnd <= byteStart || byteStart < 0) return '';\n const fd = fs.openSync(filePath, 'r');\n try {\n const length = byteEnd - byteStart;\n const buffer = Buffer.alloc(length);\n const bytesRead = fs.readSync(fd, buffer, 0, length, byteStart);\n return buffer.subarray(0, bytesRead).toString('utf8');\n } finally {\n fs.closeSync(fd);\n }\n}\n\nconst ENV_BASENAME_RE = /^\\.env(\\..+)?$/;\n\n/** Check if a file path is a .env file. */\nexport function isEnvFile(filePath: string): boolean {\n return ENV_BASENAME_RE.test(path.basename(filePath));\n}\n\n/**\n * Read a file safely — if it's a .env file, redact values and return only\n * keys with type hints. For all other files, return content as-is.\n */\nexport function readFileSafe(filePath: string): string {\n const content = fs.readFileSync(filePath, 'utf-8');\n if (isEnvFile(filePath)) {\n return redactEnvFile(content);\n }\n return content;\n}\n","/**\n * Parses .env files and extracts keys with inferred value types/formats.\n * Never exposes actual values — only structural metadata.\n */\n\nexport type EnvValueType = 'string' | 'number' | 'boolean' | 'empty';\n\nexport type EnvValueFormat =\n | 'url'\n | 'email'\n | 'ip'\n | 'host:port'\n | 'path'\n | 'uuid'\n | 'json'\n | 'base64'\n | 'csv'\n | 'integer'\n | 'float'\n | 'cron'\n | 'duration'\n | 'semver'\n | 'hex'\n | 'dsn'\n | null;\n\nexport interface EnvEntry {\n key: string;\n valueType: EnvValueType;\n valueFormat: EnvValueFormat;\n comment: string | null;\n /** Whether the value was wrapped in quotes */\n quoted: boolean;\n line: number;\n}\n\n// ─── Format detectors (order matters: most specific first) ───────────\n\nconst FORMAT_DETECTORS: Array<{ format: EnvValueFormat; test: (v: string) => boolean }> = [\n // UUID: 8-4-4-4-12 hex digits\n { format: 'uuid', test: (v) => /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v) },\n // URL: scheme://...\n { format: 'url', test: (v) => /^https?:\\/\\/.+/i.test(v) || /^(redis|amqp|mqtt|ftp|ftps|ssh|wss?|mongodb(\\+srv)?|postgres(ql)?|mysql|sqlite):\\/\\/.+/i.test(v) },\n // DSN: scheme://user:pass@host or scheme://host — covers DB connection strings not caught by URL\n { format: 'dsn', test: (v) => /^[a-z][a-z0-9+.-]*:\\/\\/.+/i.test(v) },\n // Email\n { format: 'email', test: (v) => /^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$/.test(v) },\n // Semver: 1.2.3 or v1.2.3 with optional pre-release\n { format: 'semver', test: (v) => /^v?\\d+\\.\\d+\\.\\d+(-[\\w.]+)?(\\+[\\w.]+)?$/.test(v) },\n // IP v4\n { format: 'ip', test: (v) => /^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/.test(v) },\n // host:port (after IP check to not conflict)\n { format: 'host:port', test: (v) => /^[\\w.-]+:\\d{1,5}$/.test(v) },\n // Cron expression (5 or 6 fields)\n { format: 'cron', test: (v) => /^(\\S+\\s+){4,5}\\S+$/.test(v) && /[*\\/,\\-]/.test(v) },\n // JSON object or array\n { format: 'json', test: (v) => (v.startsWith('{') && v.endsWith('}')) || (v.startsWith('[') && v.endsWith(']')) },\n // CSV: contains commas (and not JSON)\n { format: 'csv', test: (v) => v.includes(',') && !v.startsWith('{') && !v.startsWith('[') },\n // Duration: 30s, 5m, 2h, 1d, 500ms\n { format: 'duration', test: (v) => /^\\d+(ms|s|m|h|d)$/i.test(v) },\n // Hex string (at least 8 chars to avoid matching short words)\n { format: 'hex', test: (v) => /^(0x)?[0-9a-f]{8,}$/i.test(v) && !/^\\d+$/.test(v) },\n // Base64: long alphanumeric with padding or mixed case + digits (at least 16 chars)\n { format: 'base64', test: (v) => v.length >= 16 && /^[A-Za-z0-9+/]+=*$/.test(v) && /[A-Z]/.test(v) && /[a-z]/.test(v) },\n // Absolute path (unix or windows)\n { format: 'path', test: (v) => /^(\\/[\\w.-]+)+\\/?$/.test(v) || /^[A-Z]:\\\\/.test(v) },\n];\n\nfunction inferType(value: string): { valueType: EnvValueType; valueFormat: EnvValueFormat } {\n if (value === '') return { valueType: 'empty', valueFormat: null };\n\n // Boolean\n if (/^(true|false|yes|no|on|off|1|0)$/i.test(value)) {\n return { valueType: 'boolean', valueFormat: null };\n }\n\n // Integer\n if (/^-?\\d+$/.test(value)) {\n return { valueType: 'number', valueFormat: 'integer' };\n }\n\n // Float\n if (/^-?\\d+\\.\\d+$/.test(value)) {\n return { valueType: 'number', valueFormat: 'float' };\n }\n\n // String with format detection\n for (const { format, test } of FORMAT_DETECTORS) {\n if (test(value)) {\n return { valueType: 'string', valueFormat: format };\n }\n }\n\n return { valueType: 'string', valueFormat: null };\n}\n\n/**\n * Strip surrounding quotes from a value and return whether it was quoted.\n */\nfunction unquote(raw: string): { value: string; quoted: boolean } {\n if (\n (raw.startsWith('\"') && raw.endsWith('\"')) ||\n (raw.startsWith(\"'\") && raw.endsWith(\"'\"))\n ) {\n return { value: raw.slice(1, -1), quoted: true };\n }\n return { value: raw, quoted: false };\n}\n\n/**\n * Parse a .env file content and return structured entries without actual values.\n */\nexport function parseEnvFile(content: string): EnvEntry[] {\n const entries: EnvEntry[] = [];\n const lines = content.split('\\n');\n let pendingComment: string | null = null;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i].trim();\n\n // Blank line resets pending comment\n if (line === '') {\n pendingComment = null;\n continue;\n }\n\n // Comment line — accumulate for next variable\n if (line.startsWith('#')) {\n const commentText = line.slice(1).trim();\n pendingComment = pendingComment ? `${pendingComment} ${commentText}` : commentText;\n continue;\n }\n\n // Variable line: KEY=VALUE or export KEY=VALUE\n const match = line.match(/^(?:export\\s+)?([A-Za-z_][A-Za-z0-9_]*)=(.*)/);\n if (!match) {\n pendingComment = null;\n continue;\n }\n\n const key = match[1];\n const rawValue = match[2].trim();\n\n // Strip inline comment (only for unquoted values)\n let effectiveRaw = rawValue;\n if (!rawValue.startsWith('\"') && !rawValue.startsWith(\"'\")) {\n const commentIdx = rawValue.indexOf(' #');\n if (commentIdx !== -1) {\n effectiveRaw = rawValue.slice(0, commentIdx).trim();\n }\n }\n\n const { value, quoted } = unquote(effectiveRaw);\n const { valueType, valueFormat } = inferType(value);\n\n entries.push({\n key,\n valueType,\n valueFormat,\n comment: pendingComment,\n quoted,\n line: i + 1,\n });\n\n pendingComment = null;\n }\n\n return entries;\n}\n\n/**\n * Redact .env file content: keep keys and comments, replace values with type hints.\n * Used by source-reader to safely expose .env structure without secrets.\n */\nexport function redactEnvFile(content: string): string {\n const entries = parseEnvFile(content);\n const lines = content.split('\\n');\n const result: string[] = [];\n\n const entryByLine = new Map<number, EnvEntry>();\n for (const e of entries) {\n entryByLine.set(e.line, e);\n }\n\n for (let i = 0; i < lines.length; i++) {\n const entry = entryByLine.get(i + 1);\n if (entry) {\n const typeHint = formatTypeHint(entry);\n result.push(`${entry.key}=${typeHint}`);\n } else {\n // Keep comments and blank lines as-is\n result.push(lines[i]);\n }\n }\n\n return result.join('\\n');\n}\n\nfunction formatTypeHint(entry: EnvEntry): string {\n if (entry.valueType === 'empty') return '<empty>';\n if (entry.valueFormat) return `<${entry.valueType}:${entry.valueFormat}>`;\n return `<${entry.valueType}>`;\n}\n","export interface HybridScoreParams {\n /** FTS5 BM25 rank, normalized 0-1 */\n relevance: number;\n /** PageRank score (already normalized 0-1) */\n pagerank: number;\n /** Recency factor 0-1 based on indexed_at */\n recency: number;\n /** Bonus based on symbol kind 0-1 */\n typeBonus: number;\n}\n\n/**\n * Weighted hybrid score combining multiple signals.\n *\n * Weights: relevance 50%, pagerank 25%, recency 15%, typeBonus 10%.\n */\nexport function hybridScore(params: HybridScoreParams): number {\n return (\n 0.50 * params.relevance +\n 0.25 * params.pagerank +\n 0.15 * params.recency +\n 0.10 * params.typeBonus\n );\n}\n\nconst KIND_BONUS: Record<string, number> = {\n class: 1.0,\n interface: 0.9,\n trait: 0.9,\n enum: 0.8,\n function: 0.7,\n method: 0.6,\n type: 0.5,\n constant: 0.4,\n property: 0.3,\n variable: 0.2,\n enum_case: 0.3,\n namespace: 0.1,\n};\n\n/** Get type bonus for a symbol kind. */\nexport function getTypeBonus(kind: string): number {\n return KIND_BONUS[kind] ?? 0.1;\n}\n\n/**\n * Convert an indexed_at timestamp to a 0-1 recency score.\n * Score decays over `maxAgeDays` (default 30).\n */\nexport function computeRecency(\n indexedAt: string,\n now?: Date,\n maxAgeDays = 30,\n): number {\n const d = new Date(indexedAt);\n const ref = now ?? new Date();\n const ageMs = ref.getTime() - d.getTime();\n const ageDays = ageMs / (1000 * 60 * 60 * 24);\n return Math.max(0, 1 - ageDays / maxAgeDays);\n}\n","import type Database from 'better-sqlite3';\n\ninterface EdgeRecord {\n source_node_id: number;\n target_node_id: number;\n}\n\n/** Cached PageRank result keyed by DB filename + edge count */\nlet _cache: { dbName: string; edgeCount: number; result: Map<number, number> } | null = null;\n\n/** Invalidate the cache (call after bulk edge inserts, e.g. reindex) */\nexport function invalidatePageRankCache(): void {\n _cache = null;\n}\n\n/**\n * Simple PageRank on the edges graph.\n * Results are cached and invalidated when the edge count changes.\n */\nexport function computePageRank(\n db: Database.Database,\n iterations = 20,\n dampingFactor = 0.85,\n): Map<number, number> {\n // Fast cache check: if same DB and edge count hasn't changed, reuse\n const dbName = db.name;\n const countRow = db.prepare('SELECT COUNT(*) as cnt FROM edges WHERE resolved = 1').get() as { cnt: number };\n if (_cache && _cache.dbName === dbName && _cache.edgeCount === countRow.cnt) {\n return _cache.result;\n }\n\n const edges = db.prepare(\n 'SELECT source_node_id, target_node_id FROM edges WHERE resolved = 1',\n ).all() as EdgeRecord[];\n\n // Collect all unique node IDs\n const nodeSet = new Set<number>();\n const outgoing = new Map<number, number[]>();\n\n for (const edge of edges) {\n nodeSet.add(edge.source_node_id);\n nodeSet.add(edge.target_node_id);\n\n let targets = outgoing.get(edge.source_node_id);\n if (!targets) {\n targets = [];\n outgoing.set(edge.source_node_id, targets);\n }\n targets.push(edge.target_node_id);\n }\n\n const nodes = Array.from(nodeSet);\n const n = nodes.length;\n if (n === 0) return new Map();\n\n // Initialize scores\n const scores = new Map<number, number>();\n const initialScore = 1 / n;\n for (const nodeId of nodes) {\n scores.set(nodeId, initialScore);\n }\n\n // Iterate\n const base = (1 - dampingFactor) / n;\n\n for (let iter = 0; iter < iterations; iter++) {\n const newScores = new Map<number, number>();\n for (const nodeId of nodes) {\n newScores.set(nodeId, base);\n }\n\n // Accumulate rank mass lost to sink nodes (no outgoing edges) and redistribute\n // evenly across all nodes to conserve total rank mass.\n let sinkMass = 0;\n\n for (const nodeId of nodes) {\n const targets = outgoing.get(nodeId);\n if (!targets || targets.length === 0) {\n sinkMass += (scores.get(nodeId) ?? 0) * dampingFactor;\n continue;\n }\n\n const share = (scores.get(nodeId) ?? 0) * dampingFactor / targets.length;\n for (const target of targets) {\n newScores.set(target, (newScores.get(target) ?? base) + share);\n }\n }\n\n // Distribute sink mass equally to all nodes\n if (sinkMass > 0) {\n const sinkShare = sinkMass / n;\n for (const nodeId of nodes) {\n newScores.set(nodeId, (newScores.get(nodeId) ?? base) + sinkShare);\n }\n }\n\n for (const nodeId of nodes) {\n scores.set(nodeId, newScores.get(nodeId) ?? base);\n }\n }\n\n _cache = { dbName, edgeCount: countRow.cnt, result: scores };\n return scores;\n}\n","import { err, ok, Result } from 'neverthrow';\n\nexport type TraceMcpError =\n | { code: 'PARSE_ERROR'; file: string; partial: boolean; message: string }\n | { code: 'NOT_FOUND'; id: string; candidates?: string[] }\n | { code: 'RESOLUTION_FAILED'; path: string; message: string }\n | { code: 'TIMEOUT'; operation: string; ms: number }\n | { code: 'SECURITY_VIOLATION'; detail: string }\n | { code: 'PLUGIN_ERROR'; plugin: string; message: string }\n | { code: 'DB_ERROR'; message: string }\n | { code: 'CONFIG_ERROR'; message: string }\n | { code: 'VALIDATION_ERROR'; message: string; details?: unknown };\n\nexport type TraceMcpResult<T> = Result<T, TraceMcpError>;\n\nexport function parseError(file: string, message: string, partial = false): TraceMcpError {\n return { code: 'PARSE_ERROR', file, partial, message };\n}\n\nexport function notFound(id: string, candidates?: string[]): TraceMcpError {\n return { code: 'NOT_FOUND', id, candidates };\n}\n\nexport function securityViolation(detail: string): TraceMcpError {\n return { code: 'SECURITY_VIOLATION', detail };\n}\n\nexport function pluginError(plugin: string, message: string): TraceMcpError {\n return { code: 'PLUGIN_ERROR', plugin, message };\n}\n\nexport function dbError(message: string): TraceMcpError {\n return { code: 'DB_ERROR', message };\n}\n\nexport function configError(message: string): TraceMcpError {\n return { code: 'CONFIG_ERROR', message };\n}\n\nexport function validationError(message: string, details?: unknown): TraceMcpError {\n return { code: 'VALIDATION_ERROR', message, details };\n}\n\nexport function formatToolError(error: TraceMcpError): object {\n const base: Record<string, unknown> = {\n code: error.code,\n message: 'message' in error ? error.message : ('detail' in error ? error.detail : error.code),\n };\n\n if (error.code === 'NOT_FOUND' && error.candidates?.length) {\n base.suggestions = error.candidates;\n base.help = 'Use search() to find the correct symbol_id';\n }\n\n return { error: base };\n}\n\nexport { ok, err, Result };\n","/**\n * Hybrid search: combines FTS5 + vector search using Reciprocal Rank Fusion (RRF).\n * Falls back to FTS5-only when AI is unavailable.\n */\nimport type Database from 'better-sqlite3';\nimport { searchFts, type FtsResult } from '../db/fts.js';\nimport type { VectorStore, EmbeddingService, RerankerService } from './interfaces.js';\n\nexport interface HybridSearchResult {\n symbolId: number;\n name: string;\n fqn: string | null;\n kind: string;\n fileId: number;\n symbolIdStr: string;\n score: number;\n}\n\nconst RRF_K = 60;\n\n/**\n * Combine FTS5 + vector search using RRF (Reciprocal Rank Fusion).\n *\n * When vectorStore/embeddingService are null, falls back to FTS5-only.\n */\nexport async function hybridSearch(\n db: Database.Database,\n query: string,\n vectorStore: VectorStore | null,\n embeddingService: EmbeddingService | null,\n limit: number,\n reranker?: RerankerService | null,\n): Promise<HybridSearchResult[]> {\n // 1. FTS5 search\n const ftsResults = searchFts(db, query, limit * 3);\n\n // Build FTS rank map: symbolId -> rank position (0-based)\n const ftsRanked = new Map<number, { rank: number; result: FtsResult }>();\n for (let i = 0; i < ftsResults.length; i++) {\n ftsRanked.set(ftsResults[i].symbolId, { rank: i, result: ftsResults[i] });\n }\n\n // 2. Vector search (if available)\n const vectorRanked = new Map<number, number>();\n\n if (vectorStore && embeddingService) {\n try {\n const queryEmbedding = await embeddingService.embed(query);\n if (queryEmbedding.length > 0) {\n const vectorResults = vectorStore.search(queryEmbedding, limit * 3);\n for (let i = 0; i < vectorResults.length; i++) {\n vectorRanked.set(vectorResults[i].id, i);\n }\n }\n } catch {\n // Vector search failed, continue with FTS-only\n }\n }\n\n // 3. RRF fusion\n const allIds = new Set([...ftsRanked.keys(), ...vectorRanked.keys()]);\n const fused: HybridSearchResult[] = [];\n\n for (const id of allIds) {\n let score = 0;\n\n const ftsEntry = ftsRanked.get(id);\n if (ftsEntry !== undefined) {\n score += 1 / (RRF_K + ftsEntry.rank);\n }\n\n const vecRank = vectorRanked.get(id);\n if (vecRank !== undefined) {\n score += 1 / (RRF_K + vecRank);\n }\n\n // We need name/fqn/kind/fileId — get from FTS if available, else look up\n if (ftsEntry) {\n fused.push({\n symbolId: id,\n name: ftsEntry.result.name,\n fqn: ftsEntry.result.fqn,\n kind: ftsEntry.result.kind,\n fileId: ftsEntry.result.fileId,\n symbolIdStr: ftsEntry.result.symbolIdStr,\n score,\n });\n } else {\n // Symbol only in vector results — look up from DB\n const row = db.prepare(\n 'SELECT id, name, fqn, kind, file_id, symbol_id FROM symbols WHERE id = ?',\n ).get(id) as { id: number; name: string; fqn: string | null; kind: string; file_id: number; symbol_id: string } | undefined;\n\n if (row) {\n fused.push({\n symbolId: id,\n name: row.name,\n fqn: row.fqn,\n kind: row.kind,\n fileId: row.file_id,\n symbolIdStr: row.symbol_id,\n score,\n });\n }\n }\n }\n\n // 4. Sort by RRF score descending\n fused.sort((a, b) => b.score - a.score);\n\n // 5. Optional reranking\n if (reranker && fused.length > 1) {\n try {\n const candidates = fused.slice(0, limit * 2);\n const docs = candidates.map((c) => ({\n id: c.symbolId,\n text: [c.kind, c.fqn ?? c.name, c.name].join(' '),\n }));\n const reranked = await reranker.rerank(query, docs, limit);\n const rerankedIds = new Map(reranked.map((r) => [r.id, r.score]));\n const result: HybridSearchResult[] = [];\n for (const r of reranked) {\n const original = candidates.find((c) => c.symbolId === r.id);\n if (original) {\n result.push({ ...original, score: r.score });\n }\n }\n return result;\n } catch {\n // Reranker failed, fall through to RRF-only results\n }\n }\n\n return fused.slice(0, limit);\n}\n","/**\n * Token estimation: chars/4 * 1.15\n * Trade-off: speed > accuracy, ~15-20% margin.\n */\nexport function estimateTokens(text: string): number {\n return Math.ceil((text.length / 4) * 1.15);\n}\n","import type { Store, ComponentRow } from '../db/store.js';\nimport { ok, err, type TraceMcpResult } from '../errors.js';\nimport { notFound } from '../errors.js';\nimport { estimateTokens } from '../utils/token-counter.js';\n\nexport interface ComponentTreeNode {\n name: string;\n path: string;\n props?: string[];\n emits?: string[];\n slots?: string[];\n composables?: string[];\n children: ComponentTreeNode[];\n}\n\nexport interface ComponentTreeResult {\n root: ComponentTreeNode;\n totalComponents: number;\n truncated?: boolean;\n}\n\n/**\n * Build a component tree starting from a given file path.\n *\n * Resolves child components via renders_component edges in the graph,\n * recursing up to `depth` levels.\n */\nexport function getComponentTree(\n store: Store,\n componentPath: string,\n depth = 3,\n tokenBudget = 8000,\n): TraceMcpResult<ComponentTreeResult> {\n const file = store.getFile(componentPath);\n if (!file) {\n return err(notFound(componentPath));\n }\n\n const component = store.getComponentByFileId(file.id);\n if (!component) {\n return err(notFound(componentPath, ['File exists but has no component entry']));\n }\n\n const visited = new Set<string>();\n const budgetRef = { remaining: tokenBudget, truncated: false };\n const root = buildNode(store, component, file.path, depth, visited, budgetRef);\n\n return ok({\n root,\n totalComponents: visited.size,\n ...(budgetRef.truncated ? { truncated: true } : {}),\n });\n}\n\nfunction buildNode(\n store: Store,\n comp: ComponentRow,\n filePath: string,\n remainingDepth: number,\n visited: Set<string>,\n budget: { remaining: number; truncated: boolean },\n): ComponentTreeNode {\n visited.add(filePath);\n\n const node: ComponentTreeNode = {\n name: comp.name,\n path: filePath,\n children: [],\n };\n\n // Parse stored JSON fields (gracefully handle corrupted data)\n try {\n if (comp.props) {\n const parsed = JSON.parse(comp.props) as Record<string, unknown>;\n node.props = Object.keys(parsed);\n }\n } catch { /* corrupted JSON */ }\n try {\n if (comp.emits) node.emits = JSON.parse(comp.emits) as string[];\n } catch { /* corrupted JSON */ }\n try {\n if (comp.slots) node.slots = JSON.parse(comp.slots) as string[];\n } catch { /* corrupted JSON */ }\n try {\n if (comp.composables) node.composables = JSON.parse(comp.composables) as string[];\n } catch { /* corrupted JSON */ }\n\n budget.remaining -= estimateTokens(JSON.stringify(node));\n if (budget.remaining <= 0 || remainingDepth <= 0) return node;\n\n // Find child components via renders_component edges\n const symbols = store.getSymbolsByFile(\n store.getFile(filePath)?.id ?? -1,\n );\n const classSymbol = symbols.find((s) => s.kind === 'class');\n if (!classSymbol) return node;\n\n const symbolNodeId = store.getNodeId('symbol', classSymbol.id);\n if (symbolNodeId == null) return node;\n\n const outEdges = store.getOutgoingEdges(symbolNodeId);\n const renderEdges = outEdges.filter((e) => e.edge_type_name === 'renders_component');\n\n for (const edge of renderEdges) {\n if (budget.remaining <= 0) {\n budget.truncated = true;\n break;\n }\n\n const targetRef = store.getNodeByNodeId(edge.target_node_id);\n if (!targetRef || targetRef.node_type !== 'symbol') continue;\n\n const targetSymbol = store.getSymbolById(targetRef.ref_id);\n if (!targetSymbol) continue;\n\n const targetFile = store.getFileById(targetSymbol.file_id);\n if (!targetFile || visited.has(targetFile.path)) continue;\n\n const targetComp = store.getComponentByFileId(targetFile.id);\n if (!targetComp) continue;\n\n const childNode = buildNode(store, targetComp, targetFile.path, remainingDepth - 1, visited, budget);\n node.children.push(childNode);\n }\n\n return node;\n}\n","import type { Store } from '../db/store.js';\nimport { ok, err, type TraceMcpResult } from '../errors.js';\nimport { notFound } from '../errors.js';\n\nexport interface PennantUsageSite {\n filePath: string;\n line: number;\n usageType: string;\n}\n\nexport interface PennantImpactResult {\n featureName: string;\n definedIn: { filePath: string; line: number }[];\n checkedBy: PennantUsageSite[];\n gatedRoutes: { filePath: string; line: number }[];\n}\n\nexport interface ChangeImpactResult {\n target: { path: string; symbolId?: string };\n dependents: {\n path: string;\n symbolId?: string;\n edgeType: string;\n depth: number;\n }[];\n totalAffected: number;\n truncated?: boolean;\n /** Populated when the target is a Pennant feature flag name */\n pennant?: PennantImpactResult;\n}\n\n/**\n * Determine the impact of changing a file or symbol.\n *\n * Traverses INCOMING edges (who depends on this?) up to `depth` levels,\n * returning all affected files/symbols with their edge types.\n */\nexport function getChangeImpact(\n store: Store,\n opts: { filePath?: string; symbolId?: string },\n depth = 3,\n maxDependents = 200,\n): TraceMcpResult<ChangeImpactResult> {\n let startNodeId: number | undefined;\n let targetPath: string;\n let targetSymbolId: string | undefined;\n\n if (opts.symbolId) {\n const sym = store.getSymbolBySymbolId(opts.symbolId);\n if (!sym) {\n return err(notFound(opts.symbolId));\n }\n startNodeId = store.getNodeId('symbol', sym.id);\n const file = store.getFileById(sym.file_id);\n targetPath = file?.path ?? 'unknown';\n targetSymbolId = opts.symbolId;\n } else if (opts.filePath) {\n const file = store.getFile(opts.filePath);\n if (!file) {\n return err(notFound(opts.filePath));\n }\n targetPath = file.path;\n\n // Start from the file's primary symbol (class) or the file node itself\n const symbols = store.getSymbolsByFile(file.id);\n const primarySymbol = symbols.find((s) => s.kind === 'class') ?? symbols[0];\n if (primarySymbol) {\n startNodeId = store.getNodeId('symbol', primarySymbol.id);\n targetSymbolId = primarySymbol.symbol_id;\n } else {\n startNodeId = store.getNodeId('file', file.id);\n }\n } else {\n return err(notFound('', ['Provide either filePath or symbolId']));\n }\n\n // Check if this might be a Pennant feature flag name (if no node found via symbol/file)\n const pennant = getPennantImpact(store, opts.symbolId ?? opts.filePath ?? '');\n\n if (startNodeId == null) {\n return ok({\n target: { path: targetPath, symbolId: targetSymbolId },\n dependents: [],\n totalAffected: 0,\n });\n }\n\n // Traverse incoming edges recursively\n const dependents: ChangeImpactResult['dependents'] = [];\n const visited = new Set<number>();\n visited.add(startNodeId);\n\n traverseIncoming(store, startNodeId, 1, depth, visited, dependents, maxDependents);\n\n const truncated = dependents.length >= maxDependents;\n\n return ok({\n target: { path: targetPath, symbolId: targetSymbolId },\n dependents,\n totalAffected: dependents.length,\n ...(truncated ? { truncated: true } : {}),\n ...(pennant ? { pennant } : {}),\n });\n}\n\nfunction traverseIncoming(\n store: Store,\n nodeId: number,\n currentDepth: number,\n maxDepth: number,\n visited: Set<number>,\n dependents: ChangeImpactResult['dependents'],\n maxDependents: number,\n): void {\n if (currentDepth > maxDepth) return;\n if (dependents.length >= maxDependents) return;\n\n const incomingEdges = store.getIncomingEdges(nodeId);\n\n for (const edge of incomingEdges) {\n if (dependents.length >= maxDependents) break;\n\n const sourceNodeId = edge.source_node_id;\n if (visited.has(sourceNodeId)) continue;\n visited.add(sourceNodeId);\n\n const nodeRef = store.getNodeByNodeId(sourceNodeId);\n if (!nodeRef) continue;\n\n let filePath: string | undefined;\n let symbolId: string | undefined;\n\n if (nodeRef.node_type === 'symbol') {\n const sym = store.getSymbolById(nodeRef.ref_id);\n if (sym) {\n symbolId = sym.symbol_id;\n const file = store.getFileById(sym.file_id);\n filePath = file?.path;\n }\n } else if (nodeRef.node_type === 'file') {\n const file = store.getFileById(nodeRef.ref_id);\n filePath = file?.path;\n }\n\n if (filePath) {\n dependents.push({\n path: filePath,\n symbolId,\n edgeType: edge.edge_type_name,\n depth: currentDepth,\n });\n }\n\n // Continue traversal\n traverseIncoming(store, sourceNodeId, currentDepth + 1, maxDepth, visited, dependents, maxDependents);\n }\n}\n\n/**\n * Search Pennant feature flag edges for a given feature name.\n * Returns null if no matches found.\n */\nfunction getPennantImpact(store: Store, name: string): PennantImpactResult | null {\n if (!name) return null;\n\n const definedIn: { filePath: string; line: number }[] = [];\n const checkedBy: PennantUsageSite[] = [];\n const gatedRoutes: { filePath: string; line: number }[] = [];\n\n for (const edgeType of ['feature_defined_in', 'feature_checked_by', 'feature_gates_route']) {\n const edges = store.getEdgesByType(edgeType);\n for (const edge of edges) {\n if (!edge.metadata) continue;\n let meta: Record<string, unknown>;\n try { meta = JSON.parse(edge.metadata) as Record<string, unknown>; } catch { continue; }\n if (meta.featureName !== name) continue;\n\n const filePath = String(meta.filePath ?? '');\n const line = Number(meta.line ?? 0);\n\n if (edgeType === 'feature_defined_in') {\n definedIn.push({ filePath, line });\n } else if (edgeType === 'feature_checked_by') {\n checkedBy.push({ filePath, line, usageType: String(meta.usageType ?? '') });\n } else if (edgeType === 'feature_gates_route') {\n gatedRoutes.push({ filePath, line });\n }\n }\n }\n\n if (definedIn.length === 0 && checkedBy.length === 0 && gatedRoutes.length === 0) return null;\n return { featureName: name, definedIn, checkedBy, gatedRoutes };\n}\n","/**\n * get_feature_context tool — finds relevant symbols for a feature description\n * using FTS5 search + graph expansion + hybrid scoring + token budget assembly.\n */\nimport path from 'node:path';\nimport type { Store, SymbolRow, FileRow } from '../db/store.js';\nimport { hybridScore, getTypeBonus, computeRecency } from '../scoring/hybrid.js';\nimport { computePageRank } from '../scoring/pagerank.js';\nimport { assembleContext, type ContextItem } from '../scoring/assembly.js';\nimport { readByteRange } from '../utils/source-reader.js';\n\nexport interface FeatureContextResult {\n description: string;\n items: FeatureContextItem[];\n totalTokens: number;\n truncated: boolean;\n}\n\nexport interface FeatureContextItem {\n symbolId: string;\n name: string;\n kind: string;\n fqn: string | null;\n filePath: string;\n score: number;\n detail: 'full' | 'no_source' | 'signature_only';\n content: string;\n tokens: number;\n}\n\nconst 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', 'during',\n 'and', 'or', 'but', 'not', 'no', 'nor', 'so', 'yet', 'both', 'either',\n 'neither', 'each', 'every', 'all', 'any', 'few', 'more', 'most', 'other',\n 'some', 'such', 'than', 'too', 'very', 'just', 'about', 'above', 'after',\n 'before', 'between', 'under', 'over', 'out', 'up', 'down', 'off', 'then',\n 'once', 'here', 'there', 'when', 'where', 'why', 'how', 'what', 'which',\n 'who', 'whom', 'this', 'that', 'these', 'those', 'it', 'its',\n]);\n\n/**\n * Tokenize a feature description into search terms.\n * Splits by spaces, camelCase, and snake_case, then removes stopwords.\n */\nexport function tokenizeDescription(description: string): string[] {\n const raw = description\n // Split camelCase\n .replace(/([a-z])([A-Z])/g, '$1 $2')\n // Split snake_case\n .replace(/_/g, ' ')\n // Remove non-alphanumeric\n .replace(/[^a-zA-Z0-9\\s]/g, ' ')\n .toLowerCase()\n .split(/\\s+/)\n .filter(Boolean);\n\n // Remove stopwords and very short tokens\n return [...new Set(raw.filter((t) => t.length > 1 && !STOPWORDS.has(t)))];\n}\n\nexport function getFeatureContext(\n store: Store,\n rootPath: string,\n description: string,\n tokenBudget = 4000,\n): FeatureContextResult {\n const tokens = tokenizeDescription(description);\n\n if (tokens.length === 0) {\n return { description, items: [], totalTokens: 0, truncated: false };\n }\n\n // Build FTS5 query: each token as a quoted term joined by OR\n const ftsQuery = tokens.map((t) => `\"${t}\"`).join(' OR ');\n\n // Single query: join symbols + files to avoid N+1 lookups in the scoring loop\n interface FtsFullRow {\n symbolId: number;\n symbolIdStr: string;\n rank: number;\n name: string;\n fqn: string | null;\n kind: string;\n byteStart: number;\n byteEnd: number;\n signature: string | null;\n fileId: number;\n filePath: string;\n indexedAt: string;\n }\n\n const ftsResults = store.db.prepare(`\n SELECT\n s.id AS symbolId,\n s.symbol_id AS symbolIdStr,\n rank AS rank,\n s.name,\n s.fqn,\n s.kind,\n s.byte_start AS byteStart,\n s.byte_end AS byteEnd,\n s.signature,\n f.id AS fileId,\n f.path AS filePath,\n f.indexed_at AS indexedAt\n FROM symbols_fts fts\n JOIN symbols s ON s.id = fts.rowid\n JOIN files f ON f.id = s.file_id\n WHERE symbols_fts MATCH ?\n ORDER BY rank\n LIMIT 100\n `).all(ftsQuery) as FtsFullRow[];\n\n if (ftsResults.length === 0) {\n return { description, items: [], totalTokens: 0, truncated: false };\n }\n\n // Build PageRank map\n const pagerankMap = computePageRank(store.db);\n const maxPr = Math.max(...pagerankMap.values(), 0.001);\n\n // Normalize FTS ranks\n const minRank = Math.min(...ftsResults.map((r) => r.rank));\n const maxRank = Math.max(...ftsResults.map((r) => r.rank));\n const rankSpread = maxRank - minRank || 1;\n\n const now = new Date();\n\n // Batch-resolve node IDs for all FTS results in one query (avoids 100× getNodeId)\n const ftsSymIds = ftsResults.map((r) => r.symbolId);\n const ftsNodeMap = store.getNodeIdsBatch('symbol', ftsSymIds);\n\n // Score FTS results — no extra DB lookups needed, all data from the JOIN above\n type ScoredSymbol = { symbol: SymbolRow; file: FileRow; score: number };\n const scored: ScoredSymbol[] = [];\n const scoredById = new Map<string, ScoredSymbol>(); // symbolIdStr → entry for O(1) lookup later\n const seenIds = new Set<number>();\n\n for (const fts of ftsResults) {\n seenIds.add(fts.symbolId);\n\n const relevance = 1 - (fts.rank - minRank) / rankSpread;\n const nodeId = ftsNodeMap.get(fts.symbolId);\n const pr = nodeId ? (pagerankMap.get(nodeId) ?? 0) / maxPr : 0;\n const recency = computeRecency(fts.indexedAt, now);\n const typeBonus = getTypeBonus(fts.kind);\n\n const score = hybridScore({ relevance, pagerank: pr, recency, typeBonus });\n\n // Reconstruct minimal SymbolRow / FileRow shapes needed downstream\n const symbol = {\n id: fts.symbolId,\n symbol_id: fts.symbolIdStr,\n name: fts.name,\n kind: fts.kind,\n fqn: fts.fqn,\n byte_start: fts.byteStart,\n byte_end: fts.byteEnd,\n signature: fts.signature,\n file_id: fts.fileId,\n } as SymbolRow;\n\n const file = {\n id: fts.fileId,\n path: fts.filePath,\n indexed_at: fts.indexedAt,\n } as FileRow;\n\n const entry: ScoredSymbol = { symbol, file, score };\n scored.push(entry);\n scoredById.set(fts.symbolIdStr, entry);\n }\n\n // Sort by initial score before graph expansion so we expand the best matches\n scored.sort((a, b) => b.score - a.score);\n\n // Graph expansion: follow edges 1 hop for top results\n const topResults = scored.slice(0, 10);\n\n // Batch-resolve node IDs for top results (1 query)\n const topSymIds = topResults.map((item) => item.symbol.id);\n const topNodeMap = store.getNodeIdsBatch('symbol', topSymIds);\n const topNodeIds = topResults.map((item) => topNodeMap.get(item.symbol.id)).filter((id): id is number => id != null);\n\n // Fetch all adjacent edges in one query, then batch-resolve refs/symbols/files\n const allEdges = store.getEdgesForNodesBatch(topNodeIds);\n\n const otherNodeIds = [...new Set(allEdges.map((e) =>\n e.pivot_node_id === e.source_node_id ? e.target_node_id : e.source_node_id,\n ))];\n const nodeRefs = store.getNodeRefsBatch(otherNodeIds);\n const symbolRefIds = [...nodeRefs.values()].filter((r) => r.nodeType === 'symbol').map((r) => r.refId);\n const symbolMap = store.getSymbolsByIds(symbolRefIds);\n const fileIds = [...new Set([...symbolMap.values()].map((s) => s.file_id))];\n const fileMap = store.getFilesByIds(fileIds);\n\n for (const edge of allEdges) {\n const otherNodeId = edge.pivot_node_id === edge.source_node_id\n ? edge.target_node_id\n : edge.source_node_id;\n\n const nodeRef = nodeRefs.get(otherNodeId);\n if (!nodeRef || nodeRef.nodeType !== 'symbol') continue;\n\n const sym = symbolMap.get(nodeRef.refId);\n if (!sym || seenIds.has(sym.id)) continue;\n seenIds.add(sym.id);\n\n const file = fileMap.get(sym.file_id);\n if (!file) continue;\n\n const pr = (pagerankMap.get(otherNodeId) ?? 0) / maxPr;\n const recency = computeRecency(file.indexed_at, now);\n const typeBonus = getTypeBonus(sym.kind);\n\n // Graph-expanded items get a reduced relevance score\n const score = hybridScore({ relevance: 0.3, pagerank: pr, recency, typeBonus });\n const entry: ScoredSymbol = { symbol: sym, file, score };\n scored.push(entry);\n scoredById.set(sym.symbol_id, entry);\n }\n\n // Sort by score\n scored.sort((a, b) => b.score - a.score);\n\n // Build context items for assembly\n const contextItems: ContextItem[] = scored.map((item) => {\n const meta = `[${item.symbol.kind}] ${item.symbol.fqn ?? item.symbol.name} (${item.file.path})`;\n\n let source: string | undefined;\n try {\n const absPath = path.resolve(rootPath, item.file.path);\n source = readByteRange(absPath, item.symbol.byte_start, item.symbol.byte_end);\n } catch { /* source unavailable */ }\n\n return {\n id: item.symbol.symbol_id,\n score: item.score,\n source,\n signature: item.symbol.signature ?? undefined,\n metadata: meta,\n };\n });\n\n // Assemble within token budget\n const assembled = assembleContext(contextItems, tokenBudget);\n\n // Build result items\n const items: FeatureContextItem[] = assembled.items.map((ai) => {\n const sym = scoredById.get(ai.id)!;\n return {\n symbolId: ai.id,\n name: sym.symbol.name,\n kind: sym.symbol.kind,\n fqn: sym.symbol.fqn,\n filePath: sym.file.path,\n score: ai.score,\n detail: ai.detail,\n content: ai.content,\n tokens: ai.tokens,\n };\n });\n\n return {\n description,\n items,\n totalTokens: assembled.totalTokens,\n truncated: assembled.truncated,\n };\n}\n","import { estimateTokens } from '../utils/token-counter.js';\n\nexport interface ContextItem {\n id: string;\n score: number;\n /** Full source code of the symbol */\n source?: string;\n /** Just the signature */\n signature?: string;\n /** Metadata line (kind, fqn, file, etc.) */\n metadata: string;\n}\n\nexport type DetailLevel = 'full' | 'no_source' | 'signature_only';\n\nexport interface AssembledItem {\n id: string;\n score: number;\n detail: DetailLevel;\n content: string;\n tokens: number;\n}\n\nexport interface AssembledContext {\n items: AssembledItem[];\n totalTokens: number;\n truncated: boolean;\n}\n\n/**\n * Greedy context assembly within a token budget.\n *\n * Items are sorted by score descending. For each item, we try:\n * 1. full (source + metadata)\n * 2. no_source (signature + metadata)\n * 3. signature_only (just signature)\n * We pick the highest detail level that fits the remaining budget.\n */\nexport function assembleContext(\n items: ContextItem[],\n tokenBudget: number,\n): AssembledContext {\n const sorted = [...items].sort((a, b) => b.score - a.score);\n const result: AssembledItem[] = [];\n let totalTokens = 0;\n let truncated = false;\n\n for (const item of sorted) {\n const remaining = tokenBudget - totalTokens;\n if (remaining <= 0) {\n truncated = true;\n break;\n }\n\n const assembled = tryAssemble(item, remaining);\n if (assembled) {\n result.push(assembled);\n totalTokens += assembled.tokens;\n } else {\n truncated = true;\n }\n }\n\n return { items: result, totalTokens, truncated };\n}\n\nfunction tryAssemble(item: ContextItem, remainingTokens: number): AssembledItem | null {\n // Try full\n if (item.source) {\n const content = `${item.metadata}\\n${item.source}`;\n const tokens = estimateTokens(content);\n if (tokens <= remainingTokens) {\n return { id: item.id, score: item.score, detail: 'full', content, tokens };\n }\n }\n\n // Try no_source (signature + metadata)\n if (item.signature) {\n const content = `${item.metadata}\\n${item.signature}`;\n const tokens = estimateTokens(content);\n if (tokens <= remainingTokens) {\n return { id: item.id, score: item.score, detail: 'no_source', content, tokens };\n }\n }\n\n // Try signature_only\n if (item.signature) {\n const tokens = estimateTokens(item.signature);\n if (tokens <= remainingTokens) {\n return { id: item.id, score: item.score, detail: 'signature_only', content: item.signature, tokens };\n }\n }\n\n return null;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport fg from 'fast-glob';\nimport type { Store } from '../db/store.js';\nimport type { PluginRegistry } from '../plugin-api/registry.js';\nimport type { TraceMcpConfig } from '../config.js';\nimport type { ResolveContext, RawEdge } from '../plugin-api/types.js';\nimport { executeLanguagePlugin, executeFrameworkExtractNodes, executeFrameworkResolveEdges } from '../plugin-api/executor.js';\nimport { hashContent } from '../utils/hasher.js';\nimport { validatePath, validateFileSize, isSensitiveFile } from '../utils/security.js';\nimport { logger } from '../logger.js';\nimport { detectWorkspaces, type WorkspaceInfo } from './monorepo.js';\nimport { EsModuleResolver } from './resolvers/es-modules.js';\nimport { parseEnvFile } from '../utils/env-parser.js';\n\nexport interface IndexingResult {\n totalFiles: number;\n indexed: number;\n skipped: number;\n errors: number;\n durationMs: number;\n}\n\nexport class IndexingPipeline {\n constructor(\n private store: Store,\n private registry: PluginRegistry,\n private config: TraceMcpConfig,\n private rootPath: string,\n ) {}\n\n private workspaces: WorkspaceInfo[] = [];\n // Serializes concurrent indexAll/indexFiles calls — prevents a watcher-triggered\n // indexFiles from racing with an in-progress indexAll (which would overwrite files\n // the watcher already re-indexed with stale content).\n private _lock: Promise<unknown> = Promise.resolve();\n // Cached once per pipeline instance — package.json / composer.json don't change mid-run.\n private _projectContext: ReturnType<typeof this._buildProjectContext> | undefined;\n // File content cache: avoids re-reading files from disk during resolveEdges (Pass 2).\n private _fileContentCache = new Map<string, string>();\n // Pending import edges: collected in Pass 1, resolved to file→file edges in Pass 2d.\n private _pendingImports = new Map<number, { from: string; specifiers: string[]; relPath: string }[]>();\n\n async indexAll(force?: boolean): Promise<IndexingResult> {\n const result = this._lock.then(async () => {\n const start = Date.now();\n this.workspaces = detectWorkspaces(this.rootPath);\n if (this.workspaces.length > 0) {\n logger.info({ workspaces: this.workspaces.map((w) => w.name) }, 'Detected workspaces');\n }\n const filePaths = await this.collectFiles();\n return this.runPipeline(filePaths, force ?? false, start);\n });\n this._lock = result.catch(() => {});\n return result as Promise<IndexingResult>;\n }\n\n /** Remove deleted files from the index. */\n deleteFiles(filePaths: string[]): void {\n for (const fp of filePaths) {\n const relPath = path.isAbsolute(fp) ? path.relative(this.rootPath, fp) : fp;\n const file = this.store.getFile(relPath);\n if (file) {\n this.store.deleteFile(file.id);\n logger.info({ file: relPath }, 'Deleted file from index');\n }\n }\n }\n\n async indexFiles(filePaths: string[]): Promise<IndexingResult> {\n const result = this._lock.then(async () => {\n const start = Date.now();\n const relPaths: string[] = [];\n for (const fp of filePaths) {\n const rel = path.isAbsolute(fp) ? path.relative(this.rootPath, fp) : fp;\n const check = validatePath(rel, this.rootPath);\n if (check.isErr()) {\n logger.warn({ file: fp }, 'Path traversal blocked in indexFiles');\n continue;\n }\n relPaths.push(rel);\n }\n return this.runPipeline(relPaths, false, start);\n });\n this._lock = result.catch(() => {});\n return result as Promise<IndexingResult>;\n }\n\n private async runPipeline(\n relPaths: string[],\n force: boolean,\n startMs: number,\n ): Promise<IndexingResult> {\n const result: IndexingResult = {\n totalFiles: relPaths.length,\n indexed: 0,\n skipped: 0,\n errors: 0,\n durationMs: 0,\n };\n\n // Clear cached project context so framework activation uses fresh package.json/composer.json\n this._projectContext = undefined;\n\n // Register edge types from framework plugins\n this.registerFrameworkEdgeTypes();\n\n // Pass 1: per-file extraction\n for (const relPath of relPaths) {\n const ok = await this.indexSingleFile(relPath, force);\n if (ok === 'indexed') result.indexed++;\n else if (ok === 'skipped') result.skipped++;\n else result.errors++;\n }\n\n // Pass 2: resolve edges (framework plugins)\n await this.resolveEdges();\n\n // Pass 2b: ORM associations → graph edges (resolved after all entities indexed)\n this.resolveOrmAssociationEdges();\n\n // Pass 2c: TypeScript heritage → graph edges (extends/implements → find_references)\n this.resolveTypeScriptHeritageEdges();\n\n // Pass 2d: ES module imports → file→file edges (enables dependency graph + dead export analysis)\n this.resolveEsmImportEdges();\n\n // Pass 2e: test_covers edges — test file imports source file → test_covers edge\n this.resolveTestCoversEdges();\n\n // Pass 3: Index .env files (keys + type metadata only, never store values)\n await this.indexEnvFiles(force);\n\n // Release memory — file content is no longer needed after Pass 2\n this._fileContentCache.clear();\n this._pendingImports.clear();\n\n result.durationMs = Date.now() - startMs;\n logger.info(result, 'Indexing pipeline completed');\n return result;\n }\n\n private async indexSingleFile(\n relPath: string,\n force: boolean,\n ): Promise<'indexed' | 'skipped' | 'error'> {\n const absPath = path.resolve(this.rootPath, relPath);\n\n // Defence-in-depth: reject paths that escape the project root\n const pathCheck = validatePath(relPath, this.rootPath);\n if (pathCheck.isErr()) {\n logger.warn({ file: relPath }, 'Path traversal blocked');\n return 'error';\n }\n\n // Reject symlinks to prevent escaping the project root\n try {\n if (fs.lstatSync(absPath).isSymbolicLink()) {\n logger.warn({ file: relPath }, 'Symlink skipped');\n return 'error';\n }\n } catch {\n // lstat failed — file may not exist; readFileSync below will catch it\n }\n\n // Block sensitive files (credentials, keys, secrets) from indexing\n if (isSensitiveFile(relPath)) {\n logger.warn({ file: relPath }, 'Sensitive file blocked from indexing');\n return 'skipped';\n }\n\n let content: Buffer;\n try {\n content = fs.readFileSync(absPath);\n } catch {\n logger.warn({ file: relPath }, 'Cannot read file');\n return 'error';\n }\n\n // Reject oversized files (default 1 MB) to prevent OOM\n const sizeCheck = validateFileSize(content.length);\n if (sizeCheck.isErr()) {\n logger.warn({ file: relPath, size: content.length }, 'File too large, skipping');\n return 'error';\n }\n\n // Cache content for Pass 2 (resolveEdges reads files again)\n this._fileContentCache.set(relPath, content.toString('utf-8'));\n\n const hash = hashContent(content);\n const existing = this.store.getFile(relPath);\n\n // Skip if unchanged\n if (!force && existing && existing.content_hash === hash) {\n return 'skipped';\n }\n\n // Find matching language plugin\n const plugin = this.registry.getLanguagePluginForFile(relPath);\n if (!plugin) {\n return 'skipped';\n }\n\n // Execute language plugin\n const parseResult = await executeLanguagePlugin(plugin, relPath, content);\n if (parseResult.isErr()) {\n logger.error({ file: relPath, error: parseResult.error }, 'Language plugin failed');\n return 'error';\n }\n\n const parsed = parseResult.value;\n const language = parsed.language ?? this.detectLanguage(relPath);\n\n // Determine workspace for this file\n const workspace = this.resolveWorkspace(relPath);\n\n // Upsert file record\n let fileId: number;\n if (existing) {\n fileId = existing.id;\n this.store.deleteSymbolsByFile(fileId);\n this.store.deleteEdgesForFileNodes(fileId);\n this.store.deleteEntitiesByFile(fileId);\n this.store.updateFileHash(fileId, hash, content.length);\n this.store.updateFileStatus(fileId, parsed.status, parsed.frameworkRole);\n if (workspace) this.store.updateFileWorkspace(fileId, workspace);\n } else {\n fileId = this.store.insertFile(relPath, language, hash, content.length, workspace);\n if (parsed.status !== 'ok' || parsed.frameworkRole) {\n this.store.updateFileStatus(fileId, parsed.status, parsed.frameworkRole);\n }\n }\n\n // Insert symbols\n if (parsed.symbols.length > 0) {\n this.store.insertSymbols(fileId, parsed.symbols);\n }\n\n // Insert edges from language plugin\n if (parsed.edges?.length) {\n // Separate import edges (need ESM resolution in pass 2d) from other edges\n const importEdges: typeof parsed.edges = [];\n const otherEdges: typeof parsed.edges = [];\n for (const edge of parsed.edges) {\n if (edge.edgeType === 'imports' && !edge.sourceNodeType && !edge.sourceSymbolId) {\n importEdges.push(edge);\n } else {\n otherEdges.push(edge);\n }\n }\n if (otherEdges.length > 0) this.storeRawEdges(otherEdges);\n if (importEdges.length > 0) {\n this._pendingImports.set(\n fileId,\n importEdges.map((e) => ({\n from: (e.metadata as Record<string, unknown>)?.['from'] as string ?? '',\n specifiers: ((e.metadata as Record<string, unknown>)?.['specifiers'] as string[]) ?? [],\n relPath,\n })),\n );\n }\n }\n\n // Insert routes, components, migrations, ORM models\n if (parsed.routes?.length) {\n for (const r of parsed.routes) this.store.insertRoute(r, fileId);\n }\n if (parsed.components?.length) {\n for (const c of parsed.components) this.store.insertComponent(c, fileId);\n }\n if (parsed.migrations?.length) {\n for (const m of parsed.migrations) this.store.insertMigration(m, fileId);\n }\n if (parsed.ormModels?.length) {\n this.storeOrmResults(parsed.ormModels, parsed.ormAssociations ?? [], fileId);\n }\n\n // Framework extractNodes (pass 1)\n await this.runFrameworkExtractNodes(relPath, content, language, fileId);\n\n return 'indexed';\n }\n\n private async runFrameworkExtractNodes(\n relPath: string,\n content: Buffer,\n language: string,\n fileId: number,\n ): Promise<void> {\n const ctx = this.buildProjectContext();\n const activeResult = this.registry.getActiveFrameworkPlugins(ctx);\n if (activeResult.isErr()) {\n logger.warn({ error: activeResult.error }, 'Failed to get active framework plugins');\n return;\n }\n\n for (const plugin of activeResult.value) {\n const result = await executeFrameworkExtractNodes(plugin, relPath, content, language);\n if (result.isErr() || !result.value) continue;\n\n const fwResult = result.value;\n if (fwResult.symbols.length > 0) {\n this.store.insertSymbols(fileId, fwResult.symbols);\n }\n if (fwResult.edges?.length) {\n this.storeRawEdges(fwResult.edges);\n }\n if (fwResult.routes?.length) {\n for (const r of fwResult.routes) this.store.insertRoute(r, fileId);\n }\n if (fwResult.components?.length) {\n for (const c of fwResult.components) this.store.insertComponent(c, fileId);\n }\n if (fwResult.migrations?.length) {\n for (const m of fwResult.migrations) this.store.insertMigration(m, fileId);\n }\n if (fwResult.ormModels?.length) {\n this.storeOrmResults(fwResult.ormModels, fwResult.ormAssociations ?? [], fileId);\n }\n if (fwResult.rnScreens?.length) {\n for (const s of fwResult.rnScreens) this.store.insertRnScreen(s, fileId);\n }\n if (fwResult.frameworkRole) {\n this.store.updateFileStatus(fileId, fwResult.status, fwResult.frameworkRole);\n }\n }\n }\n\n private storeOrmResults(\n models: import('../plugin-api/types.js').RawOrmModel[],\n associations: import('../plugin-api/types.js').RawOrmAssociation[],\n fileId: number,\n ): void {\n // Insert models first, collect name → id map\n const modelIdMap = new Map<string, number>();\n for (const m of models) {\n const id = this.store.insertOrmModel(m, fileId);\n modelIdMap.set(m.name, id);\n }\n\n // Insert associations — resolve target ID best-effort (may be null if not indexed yet)\n for (const assoc of associations) {\n const sourceId = modelIdMap.get(assoc.sourceModelName)\n ?? this.store.getOrmModelByName(assoc.sourceModelName)?.id;\n if (sourceId == null) continue;\n\n const targetId = modelIdMap.get(assoc.targetModelName)\n ?? this.store.getOrmModelByName(assoc.targetModelName)?.id\n ?? null;\n\n this.store.insertOrmAssociation(\n sourceId,\n targetId,\n assoc.targetModelName,\n assoc.kind,\n assoc.options,\n fileId,\n );\n }\n }\n\n private async resolveEdges(): Promise<void> {\n const ctx = this.buildProjectContext();\n const activeResult = this.registry.getActiveFrameworkPlugins(ctx);\n if (activeResult.isErr()) return;\n\n const resolveCtx = this.buildResolveContext();\n\n for (const plugin of activeResult.value) {\n const result = await executeFrameworkResolveEdges(plugin, resolveCtx);\n if (result.isErr()) continue;\n this.storeRawEdges(result.value);\n }\n }\n\n /** Convert ORM associations (orm_associations table) into graph edges. */\n private resolveOrmAssociationEdges(): void {\n const associations = this.store.getAllOrmAssociations();\n if (associations.length === 0) return;\n\n // Build model ID → ORM type map\n const allModels = this.store.getAllOrmModels();\n const modelOrmMap = new Map<number, string>();\n for (const m of allModels) {\n modelOrmMap.set(m.id, m.orm);\n }\n\n // ORM-specific kind → edge type name mapping\n const ormKindToEdgeType: Record<string, Record<string, string>> = {\n mongoose: {\n ref: 'mongoose_references',\n discriminator: 'mongoose_discriminates',\n },\n sequelize: {\n hasMany: 'sequelize_has_many',\n belongsTo: 'sequelize_belongs_to',\n belongsToMany: 'sequelize_belongs_to_many',\n hasOne: 'sequelize_has_one',\n },\n typeorm: {\n OneToMany: 'typeorm_one_to_many',\n ManyToOne: 'typeorm_many_to_one',\n OneToOne: 'typeorm_one_to_one',\n ManyToMany: 'typeorm_many_to_many',\n },\n prisma: {\n hasMany: 'prisma_relation',\n belongsTo: 'prisma_relation',\n },\n drizzle: {\n hasMany: 'drizzle_relation',\n belongsTo: 'drizzle_relation',\n },\n };\n\n for (const assoc of associations) {\n // Resolve target model if it wasn't available during Pass 1\n let targetModelId = assoc.target_model_id;\n if (targetModelId == null && assoc.target_model_name) {\n const target = this.store.getOrmModelByName(assoc.target_model_name);\n if (target) targetModelId = target.id;\n }\n if (targetModelId == null) continue;\n\n const sourceNodeId = this.store.getNodeId('orm_model', assoc.source_model_id);\n const targetNodeId = this.store.getNodeId('orm_model', targetModelId);\n if (sourceNodeId == null || targetNodeId == null) continue;\n\n const orm = modelOrmMap.get(assoc.source_model_id) ?? 'unknown';\n const ormMap = ormKindToEdgeType[orm];\n const edgeType = ormMap?.[assoc.kind] ?? `orm_${assoc.kind}`;\n const insertResult = this.store.insertEdge(sourceNodeId, targetNodeId, edgeType, true, undefined, false);\n if (insertResult.isErr()) {\n logger.warn({ edgeType, orm, kind: assoc.kind, error: insertResult.error }, 'Failed to insert ORM edge');\n }\n }\n }\n\n /**\n * Pass 2c: Resolve TypeScript extends/implements metadata into graph edges.\n * Builds a class/interface name → symbol DB id map, then creates\n * ts_extends and ts_implements edges for all symbols that have heritage metadata.\n */\n private resolveTypeScriptHeritageEdges(): void {\n const symbolsWithHeritage = this.store.getSymbolsWithHeritage();\n if (symbolsWithHeritage.length === 0) return;\n\n // Build name → {id, kind} index across ALL TypeScript symbols (classes + interfaces)\n const nameIndex = new Map<string, { id: number; kind: string }[]>();\n const allSymbols = this.store.db.prepare(\n \"SELECT id, name, kind FROM symbols WHERE kind IN ('class', 'interface')\",\n ).all() as { id: number; name: string; kind: string }[];\n\n for (const s of allSymbols) {\n const list = nameIndex.get(s.name) ?? [];\n list.push({ id: s.id, kind: s.kind });\n nameIndex.set(s.name, list);\n }\n\n let created = 0;\n\n for (const sym of symbolsWithHeritage) {\n let meta: Record<string, unknown> = {};\n try { if (sym.metadata) meta = JSON.parse(sym.metadata) as Record<string, unknown>; } catch { continue; }\n const sourceNodeId = this.store.getNodeId('symbol', sym.id);\n if (sourceNodeId == null) continue;\n\n // Process extends\n const ext = meta['extends'];\n const extNames = Array.isArray(ext) ? ext as string[] : typeof ext === 'string' ? [ext] : [];\n for (const targetName of extNames) {\n const targets = nameIndex.get(targetName);\n if (!targets?.length) continue;\n const target = targets[0]; // first match\n const targetNodeId = this.store.getNodeId('symbol', target.id);\n if (targetNodeId == null) continue;\n this.store.insertEdge(sourceNodeId, targetNodeId, 'ts_extends', true);\n created++;\n }\n\n // Process implements\n const impl = meta['implements'];\n if (Array.isArray(impl)) {\n for (const targetName of impl as string[]) {\n const targets = nameIndex.get(targetName);\n if (!targets?.length) continue;\n const target = targets.find((t) => t.kind === 'interface') ?? targets[0];\n const targetNodeId = this.store.getNodeId('symbol', target.id);\n if (targetNodeId == null) continue;\n this.store.insertEdge(sourceNodeId, targetNodeId, 'ts_implements', true);\n created++;\n }\n }\n }\n\n if (created > 0) {\n logger.info({ edges: created }, 'TypeScript heritage edges resolved');\n }\n }\n\n /**\n * Pass 2d: Resolve ES module import specifiers to file→file graph edges.\n * Uses the pending imports collected during Pass 1 + the EsModuleResolver.\n */\n private resolveEsmImportEdges(): void {\n if (this._pendingImports.size === 0) return;\n\n let resolver: EsModuleResolver;\n try {\n const tsconfigPath = fs.existsSync(path.join(this.rootPath, 'tsconfig.json'))\n ? path.join(this.rootPath, 'tsconfig.json')\n : undefined;\n resolver = new EsModuleResolver(this.rootPath, tsconfigPath);\n } catch {\n logger.warn('EsModuleResolver init failed — skipping import edge resolution');\n return;\n }\n\n let created = 0;\n\n // Pre-build lookup maps to avoid N+1 per file/import\n const pendingFileIds = Array.from(this._pendingImports.keys());\n const fileMap = this.store.getFilesByIds(pendingFileIds);\n const fileNodeMap = this.store.getNodeIdsBatch('file', pendingFileIds);\n\n // Pre-build path → file lookup for target resolution\n const allFiles = this.store.getAllFiles();\n const pathToFile = new Map<string, { id: number }>();\n for (const f of allFiles) pathToFile.set(f.path, f);\n const allFileIds = allFiles.map((f) => f.id);\n const allFileNodeMap = this.store.getNodeIdsBatch('file', allFileIds);\n\n for (const [fileId, imports] of this._pendingImports) {\n const file = fileMap.get(fileId);\n if (!file) continue;\n\n const absSource = path.resolve(this.rootPath, file.path);\n const sourceNodeId = fileNodeMap.get(fileId);\n if (sourceNodeId == null) continue;\n\n for (const { from, specifiers } of imports) {\n // Skip bare specifiers (node_modules) — only resolve project-local imports\n if (!from.startsWith('.') && !from.startsWith('/') && !from.startsWith('@/') && !from.startsWith('~')) continue;\n\n const resolved = resolver.resolve(from, absSource);\n if (!resolved) continue;\n\n const relTarget = path.relative(this.rootPath, resolved);\n const targetFile = pathToFile.get(relTarget);\n if (!targetFile) continue;\n\n const targetNodeId = allFileNodeMap.get(targetFile.id);\n if (targetNodeId == null) continue;\n\n this.store.insertEdge(\n sourceNodeId,\n targetNodeId,\n 'imports',\n true,\n { from, specifiers },\n );\n created++;\n }\n }\n\n if (created > 0) {\n logger.info({ edges: created }, 'ES module import edges resolved');\n }\n }\n\n private static readonly TEST_PATH_RE = /\\.(test|spec)\\.[jt]sx?$|__tests__\\//;\n\n /**\n * Pass 2e: Create test_covers edges.\n * For each test file, examine its outgoing `imports` edges.\n * If the imported file is NOT a test file, create a `test_covers` edge:\n * test_file →[test_covers]→ source_file\n */\n private resolveTestCoversEdges(): void {\n const allFiles = this.store.getAllFiles();\n const testFiles = allFiles.filter((f) => IndexingPipeline.TEST_PATH_RE.test(f.path));\n if (testFiles.length === 0) return;\n\n let created = 0;\n\n for (const testFile of testFiles) {\n const testNodeId = this.store.getNodeId('file', testFile.id);\n if (testNodeId == null) continue;\n\n // Get outgoing import edges from this test file\n const outgoing = this.store.getOutgoingEdges(testNodeId);\n\n for (const edge of outgoing) {\n if (edge.edge_type_name !== 'imports') continue;\n\n const targetRef = this.store.getNodeRef(edge.target_node_id);\n if (!targetRef || targetRef.nodeType !== 'file') continue;\n\n const targetFile = this.store.getFileById(targetRef.refId);\n if (!targetFile) continue;\n\n // Skip if target is also a test file\n if (IndexingPipeline.TEST_PATH_RE.test(targetFile.path)) continue;\n\n // Create test_covers edge: test → source\n this.store.insertEdge(\n testNodeId,\n edge.target_node_id,\n 'test_covers',\n true,\n { test_file: testFile.path },\n );\n created++;\n }\n }\n\n if (created > 0) {\n logger.info({ edges: created }, 'test_covers edges resolved');\n }\n }\n\n private storeRawEdges(edges: RawEdge[]): void {\n if (edges.length === 0) return;\n\n // ── Pre-load all caches to eliminate per-edge SELECTs ──\n\n // 1. symbolIdStr → nodeId\n const symbolIdStrs = new Set<string>();\n for (const edge of edges) {\n if (edge.sourceSymbolId) symbolIdStrs.add(edge.sourceSymbolId);\n if (edge.targetSymbolId) symbolIdStrs.add(edge.targetSymbolId);\n }\n\n const symbolNodeCache = new Map<string, number>();\n if (symbolIdStrs.size > 0) {\n const arr = Array.from(symbolIdStrs);\n const placeholders = arr.map(() => '?').join(',');\n const rows = this.store.db.prepare(\n `SELECT s.symbol_id, n.id AS node_id\n FROM symbols s\n JOIN nodes n ON n.node_type = 'symbol' AND n.ref_id = s.id\n WHERE s.symbol_id IN (${placeholders})`,\n ).all(...arr) as Array<{ symbol_id: string; node_id: number }>;\n for (const row of rows) {\n symbolNodeCache.set(row.symbol_id, row.node_id);\n }\n }\n\n // 2. (nodeType, refId) → nodeId — batch by nodeType\n const refIdsByType = new Map<string, Set<number>>();\n for (const edge of edges) {\n if (edge.sourceNodeType && edge.sourceRefId != null) {\n let s = refIdsByType.get(edge.sourceNodeType);\n if (!s) { s = new Set(); refIdsByType.set(edge.sourceNodeType, s); }\n s.add(edge.sourceRefId);\n }\n if (edge.targetNodeType && edge.targetRefId != null) {\n let s = refIdsByType.get(edge.targetNodeType);\n if (!s) { s = new Set(); refIdsByType.set(edge.targetNodeType, s); }\n s.add(edge.targetRefId);\n }\n }\n const typeRefCache = new Map<string, number>(); // \"type:refId\" → nodeId\n for (const [nodeType, refIds] of refIdsByType) {\n const batch = this.store.getNodeIdsBatch(nodeType, Array.from(refIds));\n for (const [refId, nodeId] of batch) {\n typeRefCache.set(`${nodeType}:${refId}`, nodeId);\n }\n }\n\n // 3. edgeTypeName → edgeTypeId (avoids per-edge SELECT in insertEdge)\n const edgeTypeNames = new Set<string>();\n for (const edge of edges) edgeTypeNames.add(edge.edgeType);\n const edgeTypeCache = new Map<string, number>();\n for (const name of edgeTypeNames) {\n const row = this.store.db.prepare('SELECT id FROM edge_types WHERE name = ?').get(name) as { id: number } | undefined;\n if (row) edgeTypeCache.set(name, row.id);\n }\n\n // ── Batch all inserts in a single transaction with a prepared statement ──\n const insertStmt = this.store.db.prepare(\n `INSERT OR IGNORE INTO edges (source_node_id, target_node_id, edge_type_id, resolved, metadata, is_cross_ws)\n VALUES (?, ?, ?, ?, ?, ?)`,\n );\n\n const insertBatch = this.store.db.transaction(() => {\n for (const edge of edges) {\n const sourceNodeId = this.resolveNodeId(edge, symbolNodeCache, typeRefCache);\n if (sourceNodeId == null) continue;\n // For source-only edges (e.g. livewire_dispatches, livewire_listens) where\n // there is no target node, use the source as target to preserve the edge + metadata.\n const targetNodeId = this.resolveTargetNodeId(edge, symbolNodeCache, typeRefCache) ?? sourceNodeId;\n\n const edgeTypeId = edgeTypeCache.get(edge.edgeType);\n if (edgeTypeId == null) continue;\n\n const isCrossWs = this.isEdgeCrossWorkspace(sourceNodeId, targetNodeId);\n\n insertStmt.run(\n sourceNodeId,\n targetNodeId,\n edgeTypeId,\n (edge.resolved ?? true) ? 1 : 0,\n edge.metadata ? JSON.stringify(edge.metadata) : null,\n isCrossWs ? 1 : 0,\n );\n }\n });\n insertBatch();\n }\n\n private resolveNodeId(\n edge: RawEdge,\n symbolNodeCache: Map<string, number>,\n typeRefCache: Map<string, number>,\n ): number | undefined {\n if (edge.sourceNodeType && edge.sourceRefId != null) {\n return typeRefCache.get(`${edge.sourceNodeType}:${edge.sourceRefId}`)\n ?? this.store.getNodeId(edge.sourceNodeType, edge.sourceRefId);\n }\n if (edge.sourceSymbolId) {\n return symbolNodeCache.get(edge.sourceSymbolId);\n }\n return undefined;\n }\n\n private resolveTargetNodeId(\n edge: RawEdge,\n symbolNodeCache: Map<string, number>,\n typeRefCache: Map<string, number>,\n ): number | undefined {\n if (edge.targetNodeType && edge.targetRefId != null) {\n return typeRefCache.get(`${edge.targetNodeType}:${edge.targetRefId}`)\n ?? this.store.getNodeId(edge.targetNodeType, edge.targetRefId);\n }\n if (edge.targetSymbolId) {\n return symbolNodeCache.get(edge.targetSymbolId);\n }\n return undefined;\n }\n\n private buildProjectContext() {\n if (!this._projectContext) {\n this._projectContext = this._buildProjectContext();\n }\n return this._projectContext;\n }\n\n private _buildProjectContext() {\n let packageJson: Record<string, unknown> | undefined;\n try {\n const pkgPath = path.resolve(this.rootPath, 'package.json');\n const content = fs.readFileSync(pkgPath, 'utf-8');\n packageJson = JSON.parse(content) as Record<string, unknown>;\n } catch {\n // No package.json found\n }\n\n let composerJson: Record<string, unknown> | undefined;\n try {\n const composerPath = path.resolve(this.rootPath, 'composer.json');\n const content = fs.readFileSync(composerPath, 'utf-8');\n composerJson = JSON.parse(content) as Record<string, unknown>;\n } catch {\n // No composer.json found\n }\n\n let pyprojectToml: Record<string, unknown> | undefined;\n try {\n const tomlPath = path.resolve(this.rootPath, 'pyproject.toml');\n const content = fs.readFileSync(tomlPath, 'utf-8');\n // Lightweight TOML parse — extract [project] dependencies and [tool.poetry] dependencies\n const deps: string[] = [];\n const depBlockRe = /\\[(?:project|tool\\.poetry)\\.?dependencies\\]([^[]*)/g;\n let m: RegExpExecArray | null;\n while ((m = depBlockRe.exec(content)) !== null) {\n const block = m[1];\n for (const line of block.split('\\n')) {\n const pkg = line.match(/^\\s*([a-zA-Z0-9_-]+)/);\n if (pkg) deps.push(pkg[1].toLowerCase());\n }\n }\n // Also parse inline dependencies array: dependencies = [\"fastapi>=0.100\", ...]\n const inlineDeps = content.match(/dependencies\\s*=\\s*\\[([^\\]]*)\\]/);\n if (inlineDeps) {\n const items = inlineDeps[1].matchAll(/[\"']([a-zA-Z0-9_-]+)[^\"']*[\"']/g);\n for (const item of items) {\n deps.push(item[1].toLowerCase());\n }\n }\n pyprojectToml = { _parsedDeps: deps, _raw: content } as Record<string, unknown>;\n } catch {\n // No pyproject.toml found\n }\n\n let requirementsTxt: string[] | undefined;\n try {\n const reqPath = path.resolve(this.rootPath, 'requirements.txt');\n const content = fs.readFileSync(reqPath, 'utf-8');\n requirementsTxt = content\n .split('\\n')\n .map((l) => l.replace(/#.*/, '').trim())\n .filter((l) => l && !l.startsWith('-'))\n .map((l) => l.split(/[>=<!\\[;]/)[0].trim().toLowerCase());\n } catch {\n // No requirements.txt found\n }\n\n return {\n rootPath: this.rootPath,\n packageJson,\n composerJson,\n pyprojectToml,\n requirementsTxt,\n configFiles: [],\n };\n }\n\n private registerFrameworkEdgeTypes(): void {\n const ctx = this.buildProjectContext();\n const activeResult = this.registry.getActiveFrameworkPlugins(ctx);\n if (activeResult.isErr()) return;\n\n for (const plugin of activeResult.value) {\n const schema = plugin.registerSchema();\n if (schema.edgeTypes) {\n for (const et of schema.edgeTypes) {\n this.store.ensureEdgeType(et.name, et.category, et.description ?? '');\n }\n }\n }\n }\n\n private buildResolveContext(): ResolveContext {\n const store = this.store;\n return {\n rootPath: this.rootPath,\n getAllFiles: () => store.getAllFiles().map((f) => ({\n id: f.id,\n path: f.path,\n language: f.language,\n })),\n getSymbolsByFile: (fileId: number) =>\n store.getSymbolsByFile(fileId).map((s) => ({\n id: s.id,\n symbolId: s.symbol_id,\n name: s.name,\n kind: s.kind,\n fqn: s.fqn,\n lineStart: s.line_start,\n lineEnd: s.line_end,\n metadata: s.metadata ? JSON.parse(s.metadata) as Record<string, unknown> : null,\n })),\n getSymbolByFqn: (fqn: string) => {\n const s = store.getSymbolByFqn(fqn);\n return s ? { id: s.id, symbolId: s.symbol_id } : undefined;\n },\n getNodeId: (nodeType: string, refId: number) => store.getNodeId(nodeType, refId),\n createNodeIfNeeded: (nodeType: string, refId: number) => store.createNode(nodeType, refId),\n readFile: (relPath: string) => {\n // Use Pass 1 cache first, fall back to disk\n const cached = this._fileContentCache.get(relPath);\n if (cached !== undefined) return cached;\n try {\n return fs.readFileSync(path.resolve(this.rootPath, relPath), 'utf-8');\n } catch { return undefined; }\n },\n };\n }\n\n private resolveWorkspace(relPath: string): string | null {\n for (const ws of this.workspaces) {\n if (relPath.startsWith(ws.path + '/') || relPath === ws.path) {\n return ws.name;\n }\n }\n return null;\n }\n\n private isEdgeCrossWorkspace(sourceNodeId: number, targetNodeId: number): boolean {\n if (this.workspaces.length === 0) return false;\n\n const sourceWs = this.getWorkspaceForNode(sourceNodeId);\n const targetWs = this.getWorkspaceForNode(targetNodeId);\n\n if (sourceWs == null || targetWs == null) return false;\n return sourceWs !== targetWs;\n }\n\n private getWorkspaceForNode(nodeId: number): string | null {\n const ref = this.store.getNodeRef(nodeId);\n if (!ref) return null;\n\n if (ref.nodeType === 'file') {\n const file = this.store.getFileById(ref.refId);\n return file?.workspace ?? null;\n }\n if (ref.nodeType === 'symbol') {\n const sym = this.store.getSymbolById(ref.refId);\n if (!sym) return null;\n const file = this.store.getFileById(sym.file_id);\n return file?.workspace ?? null;\n }\n return null;\n }\n\n private async collectFiles(): Promise<string[]> {\n const entries = await fg(this.config.include, {\n cwd: this.rootPath,\n ignore: this.config.exclude,\n dot: false,\n absolute: false,\n onlyFiles: true,\n });\n return entries;\n }\n\n // ─── .env file indexing ───────────────────────────────────────────\n\n private static readonly ENV_GLOB = ['.env', '.env.*', '.env.local', '**/.env', '**/.env.*'];\n\n private async indexEnvFiles(force: boolean): Promise<void> {\n const envPaths = await fg(IndexingPipeline.ENV_GLOB, {\n cwd: this.rootPath,\n ignore: this.config.exclude,\n dot: true,\n absolute: false,\n onlyFiles: true,\n });\n\n if (envPaths.length === 0) return;\n\n logger.info({ count: envPaths.length }, 'Indexing .env files (keys only)');\n\n for (const relPath of envPaths) {\n const absPath = path.resolve(this.rootPath, relPath);\n\n // Defence-in-depth\n const pathCheck = validatePath(relPath, this.rootPath);\n if (pathCheck.isErr()) continue;\n\n let content: string;\n try {\n content = fs.readFileSync(absPath, 'utf-8');\n } catch {\n logger.warn({ file: relPath }, 'Cannot read .env file');\n continue;\n }\n\n const hash = hashContent(Buffer.from(content));\n const existing = this.store.getFile(relPath);\n\n if (!force && existing && existing.content_hash === hash) continue;\n\n const entries = parseEnvFile(content);\n\n // Upsert file record (language = 'env', framework_role = 'config')\n let fileId: number;\n if (existing) {\n fileId = existing.id;\n this.store.deleteEnvVarsByFile(fileId);\n this.store.updateFileHash(fileId, hash, content.length);\n } else {\n fileId = this.store.insertFile(relPath, 'env', hash, content.length);\n this.store.updateFileStatus(fileId, 'ok', 'config');\n }\n\n for (const entry of entries) {\n this.store.insertEnvVar(fileId, {\n key: entry.key,\n valueType: entry.valueType,\n valueFormat: entry.valueFormat,\n comment: entry.comment,\n quoted: entry.quoted,\n line: entry.line,\n });\n }\n\n logger.debug({ file: relPath, keys: entries.length }, '.env file indexed');\n }\n }\n\n private detectLanguage(filePath: string): string {\n const ext = path.extname(filePath).slice(1);\n const map: Record<string, string> = {\n php: 'php',\n ts: 'typescript',\n tsx: 'typescript',\n js: 'javascript',\n jsx: 'javascript',\n mjs: 'javascript',\n mts: 'typescript',\n vue: 'vue',\n };\n return map[ext] ?? ext;\n }\n}\n","import pino from 'pino';\n\nconst level = process.env.TRACE_MCP_LOG_LEVEL ?? 'info';\n\nexport const logger = pino({\n name: 'trace-mcp',\n level,\n transport:\n process.env.NODE_ENV !== 'production'\n ? { target: 'pino/file', options: { destination: 2 } } // stderr\n : undefined,\n});\n","import type { LanguagePlugin, FrameworkPlugin, FileParseResult, RawEdge, ResolveContext } from './types.js';\nimport { ok, err, type TraceMcpResult } from '../errors.js';\nimport { pluginError, parseError } from '../errors.js';\nimport { logger } from '../logger.js';\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\nexport async function executeLanguagePlugin(\n plugin: LanguagePlugin,\n filePath: string,\n content: Buffer,\n timeoutMs = DEFAULT_TIMEOUT_MS,\n): Promise<TraceMcpResult<FileParseResult>> {\n try {\n const result = await withTimeout(\n () => plugin.extractSymbols(filePath, content),\n timeoutMs,\n `${plugin.manifest.name}.extractSymbols`,\n );\n return result;\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n logger.error({ plugin: plugin.manifest.name, file: filePath, error: msg }, 'Language plugin error');\n return ok({\n language: undefined,\n status: 'error',\n symbols: [],\n warnings: [`Plugin ${plugin.manifest.name} failed: ${msg}`],\n });\n }\n}\n\nexport async function executeFrameworkExtractNodes(\n plugin: FrameworkPlugin,\n filePath: string,\n content: Buffer,\n language: string,\n timeoutMs = DEFAULT_TIMEOUT_MS,\n): Promise<TraceMcpResult<FileParseResult | null>> {\n if (!plugin.extractNodes) return ok(null);\n\n try {\n const result = await withTimeout(\n () => plugin.extractNodes!(filePath, content, language),\n timeoutMs,\n `${plugin.manifest.name}.extractNodes`,\n );\n return result.map((r) => r as FileParseResult | null);\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n logger.error({ plugin: plugin.manifest.name, file: filePath, error: msg }, 'Framework extractNodes error');\n return ok(null);\n }\n}\n\nexport async function executeFrameworkResolveEdges(\n plugin: FrameworkPlugin,\n ctx: ResolveContext,\n timeoutMs = DEFAULT_TIMEOUT_MS,\n): Promise<TraceMcpResult<RawEdge[]>> {\n if (!plugin.resolveEdges) return ok([]);\n\n try {\n const result = await withTimeout(\n () => plugin.resolveEdges!(ctx),\n timeoutMs,\n `${plugin.manifest.name}.resolveEdges`,\n );\n return result;\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n logger.error({ plugin: plugin.manifest.name, error: msg }, 'Framework resolveEdges error');\n return ok([]);\n }\n}\n\nasync function withTimeout<T>(\n fn: () => T,\n timeoutMs: number,\n operationName: string,\n): Promise<T> {\n // For synchronous functions, just call directly\n const result = fn();\n\n if (result instanceof Promise) {\n return Promise.race([\n result,\n new Promise<never>((_, reject) =>\n setTimeout(\n () => reject(new Error(`Timeout: ${operationName} exceeded ${timeoutMs}ms`)),\n timeoutMs,\n ),\n ),\n ]);\n }\n\n return result;\n}\n","import crypto from 'node:crypto';\nimport fs from 'node:fs';\n\n/** Hash file content for change detection. MD5 for speed. */\nexport function hashContent(content: Buffer): string {\n return crypto.createHash('md5').update(content).digest('hex');\n}\n\n/** Convenience: read file and hash in one call. */\nexport function hashFile(filePath: string): string {\n const content = fs.readFileSync(filePath);\n return hashContent(content);\n}\n","import path from 'node:path';\nimport { ok, err, type TraceMcpResult } from '../errors.js';\nimport { securityViolation } from '../errors.js';\n\nconst DEFAULT_SECRET_PATTERNS = [\n /password/i,\n /secret/i,\n /token/i,\n /key/i,\n /credential/i,\n /api_key/i,\n /private_key/i,\n];\n\n// ─── Sensitive file detection ─────────────────────────────────────────\n// Filename/extension patterns that indicate credential or key files.\n// Matches jcodemunch-mcp's SECRET_PATTERNS for consistency across tools.\n\nconst SENSITIVE_FILE_PATTERNS = [\n // Env files (handled specially by env-parser, but still blocked from raw indexing)\n '.env', '.env.*', '*.env',\n // Certificates & keys\n '*.pem', '*.key', '*.p12', '*.pfx', '*.crt', '*.cer',\n // Keystores\n '*.keystore', '*.jks',\n // Credential files\n '*.credentials', '*.token', '*.secrets',\n 'credentials.json', 'service-account*.json',\n // SSH keys\n 'id_rsa', 'id_rsa.*', 'id_ed25519', 'id_ed25519.*', 'id_dsa', 'id_ecdsa',\n // Auth / config files with secrets\n '.htpasswd', '.netrc', '.npmrc', '.pypirc',\n // Broad wildcard (with doc exemption below)\n '*secret*',\n];\n\n// Documentation extensions where the broad *secret* glob produces false positives\n// (e.g. docs/secrets-handling.md is documentation, not a credential file).\nconst DOC_SAFE_EXTENSIONS = new Set([\n '.md', '.markdown', '.mdx', '.rst', '.txt',\n '.adoc', '.asciidoc', '.asc', '.html', '.htm', '.ipynb',\n]);\n\n// Patterns exempt from doc-extension files\nconst DOC_EXEMPT_PATTERNS = new Set(['*secret*']);\n\n/**\n * Check if a file path matches known sensitive/credential file patterns.\n * Uses filename/extension matching, not content inspection.\n */\nexport function isSensitiveFile(filePath: string): boolean {\n const name = path.basename(filePath).toLowerCase();\n const ext = path.extname(name);\n\n for (const pattern of SENSITIVE_FILE_PATTERNS) {\n // Skip broad patterns for documentation files\n if (DOC_EXEMPT_PATTERNS.has(pattern) && DOC_SAFE_EXTENSIONS.has(ext)) {\n continue;\n }\n if (matchGlob(name, pattern)) return true;\n }\n return false;\n}\n\n/** Simple glob match supporting * wildcard and .ext.* suffix patterns. */\nfunction matchGlob(name: string, pattern: string): boolean {\n // Exact match\n if (name === pattern) return true;\n\n // .env.* → matches .env.local, .env.production, etc.\n if (pattern === '.env.*' && /^\\.env\\..+$/.test(name)) return true;\n\n // id_rsa.* → matches id_rsa.pub, etc.\n if (pattern.endsWith('.*') && !pattern.startsWith('*')) {\n const prefix = pattern.slice(0, -2);\n if (name === prefix || (name.startsWith(prefix + '.') && name.length > prefix.length + 1)) {\n return true;\n }\n }\n\n // *.ext → matches any file with that extension\n if (pattern.startsWith('*.') && !pattern.includes('*', 1)) {\n const ext = pattern.slice(1); // .pem, .key, etc.\n if (name.endsWith(ext)) return true;\n }\n\n // *substring* → contains match\n if (pattern.startsWith('*') && pattern.endsWith('*') && pattern.length > 2) {\n const sub = pattern.slice(1, -1);\n if (name.includes(sub)) return true;\n }\n\n // service-account*.json → prefix + suffix\n if (pattern.includes('*') && !pattern.startsWith('*') && !pattern.endsWith('*')) {\n const starIdx = pattern.indexOf('*');\n const prefix = pattern.slice(0, starIdx);\n const suffix = pattern.slice(starIdx + 1);\n if (name.startsWith(prefix) && name.endsWith(suffix)) return true;\n }\n\n return false;\n}\n\nconst DEFAULT_MAX_FILE_SIZE = 1_048_576; // 1 MB\n\nconst ARTISAN_WHITELIST = new Set(['route:list', 'model:show', 'event:list']);\n\nexport interface SecurityConfig {\n secretPatterns?: string[];\n maxFileSizeBytes?: number;\n rootPath: string;\n}\n\nexport function validatePath(filePath: string, rootPath: string): TraceMcpResult<string> {\n const resolved = path.resolve(rootPath, filePath);\n const normalizedRoot = path.resolve(rootPath);\n\n if (!resolved.startsWith(normalizedRoot + path.sep) && resolved !== normalizedRoot) {\n return err(securityViolation(`Path traversal detected: ${filePath}`));\n }\n\n return ok(resolved);\n}\n\nexport function detectSecrets(\n content: string,\n patterns?: string[],\n): { found: boolean; matches: string[] } {\n const regexes: RegExp[] = [];\n if (patterns?.length) {\n for (const p of patterns) {\n try { regexes.push(new RegExp(p, 'i')); } catch { /* skip invalid regex */ }\n }\n } else {\n regexes.push(...DEFAULT_SECRET_PATTERNS);\n }\n\n const matches: string[] = [];\n for (const regex of regexes) {\n if (regex.test(content)) {\n matches.push(regex.source);\n }\n }\n\n return { found: matches.length > 0, matches };\n}\n\nexport function validateFileSize(\n sizeBytes: number,\n maxBytes?: number,\n): TraceMcpResult<void> {\n const limit = maxBytes ?? DEFAULT_MAX_FILE_SIZE;\n if (sizeBytes > limit) {\n return err(\n securityViolation(`File size ${sizeBytes} exceeds limit ${limit}`),\n );\n }\n return ok(undefined);\n}\n\n/** Escape a string for safe interpolation into a RegExp constructor. */\nexport function escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport function validateArtisanCommand(command: string): TraceMcpResult<string> {\n if (!ARTISAN_WHITELIST.has(command)) {\n return err(\n securityViolation(\n `Artisan command '${command}' not in whitelist: [${[...ARTISAN_WHITELIST].join(', ')}]`,\n ),\n );\n }\n return ok(command);\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport fg from 'fast-glob';\nimport { logger } from '../logger.js';\n\nexport interface WorkspaceInfo {\n name: string;\n path: string; // relative to root\n}\n\n/**\n * Detect monorepo workspaces from pnpm-workspace.yaml, package.json, or composer.json.\n * Returns an empty array if no workspace config is found.\n */\nexport function detectWorkspaces(rootPath: string): WorkspaceInfo[] {\n // 1. pnpm-workspace.yaml\n const pnpmResult = detectPnpmWorkspaces(rootPath);\n if (pnpmResult.length > 0) return pnpmResult;\n\n // 2. package.json workspaces (npm/yarn)\n const npmResult = detectNpmWorkspaces(rootPath);\n if (npmResult.length > 0) return npmResult;\n\n // 3. composer.json path repositories\n const composerResult = detectComposerWorkspaces(rootPath);\n if (composerResult.length > 0) return composerResult;\n\n return [];\n}\n\nfunction detectPnpmWorkspaces(rootPath: string): WorkspaceInfo[] {\n const yamlPath = path.join(rootPath, 'pnpm-workspace.yaml');\n if (!fs.existsSync(yamlPath)) return [];\n\n try {\n const content = fs.readFileSync(yamlPath, 'utf-8');\n const parsed = parseYaml(content) as { packages?: string[] } | null;\n if (!parsed?.packages?.length) return [];\n\n return expandGlobPatterns(rootPath, parsed.packages);\n } catch (e) {\n logger.warn({ error: e }, 'Failed to parse pnpm-workspace.yaml');\n return [];\n }\n}\n\nfunction detectNpmWorkspaces(rootPath: string): WorkspaceInfo[] {\n const pkgPath = path.join(rootPath, 'package.json');\n if (!fs.existsSync(pkgPath)) return [];\n\n try {\n const content = fs.readFileSync(pkgPath, 'utf-8');\n const pkg = JSON.parse(content) as { workspaces?: string[] | { packages?: string[] } };\n\n let patterns: string[] | undefined;\n if (Array.isArray(pkg.workspaces)) {\n patterns = pkg.workspaces;\n } else if (pkg.workspaces?.packages) {\n patterns = pkg.workspaces.packages;\n }\n\n if (!patterns?.length) return [];\n return expandGlobPatterns(rootPath, patterns);\n } catch (e) {\n logger.warn({ error: e }, 'Failed to parse package.json workspaces');\n return [];\n }\n}\n\nfunction detectComposerWorkspaces(rootPath: string): WorkspaceInfo[] {\n const composerPath = path.join(rootPath, 'composer.json');\n if (!fs.existsSync(composerPath)) return [];\n\n try {\n const content = fs.readFileSync(composerPath, 'utf-8');\n const composer = JSON.parse(content) as {\n repositories?: Array<{ type?: string; url?: string }>;\n };\n\n if (!composer.repositories?.length) return [];\n\n const pathRepos = composer.repositories.filter((r) => r.type === 'path' && r.url);\n if (pathRepos.length === 0) return [];\n\n const patterns = pathRepos.map((r) => r.url!);\n return expandGlobPatterns(rootPath, patterns);\n } catch (e) {\n logger.warn({ error: e }, 'Failed to parse composer.json repositories');\n return [];\n }\n}\n\nfunction expandGlobPatterns(rootPath: string, patterns: string[]): WorkspaceInfo[] {\n const workspaces: WorkspaceInfo[] = [];\n const seen = new Set<string>();\n\n for (const pattern of patterns) {\n // Filter out negated patterns\n if (pattern.startsWith('!')) continue;\n\n const matches = fg.sync(pattern, {\n cwd: rootPath,\n onlyDirectories: true,\n absolute: false,\n });\n\n for (const match of matches) {\n const relPath = match.replace(/\\\\/g, '/');\n if (seen.has(relPath)) continue;\n\n // Must have a package.json or composer.json to be a valid workspace\n const hasPackageJson = fs.existsSync(path.join(rootPath, relPath, 'package.json'));\n const hasComposerJson = fs.existsSync(path.join(rootPath, relPath, 'composer.json'));\n\n if (!hasPackageJson && !hasComposerJson) continue;\n\n // Derive name from package.json/composer.json\n const name = resolveWorkspaceName(rootPath, relPath);\n seen.add(relPath);\n workspaces.push({ name, path: relPath });\n }\n }\n\n return workspaces;\n}\n\nfunction resolveWorkspaceName(rootPath: string, relPath: string): string {\n // Try package.json name\n try {\n const pkgPath = path.join(rootPath, relPath, 'package.json');\n if (fs.existsSync(pkgPath)) {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) as { name?: string };\n if (pkg.name) return pkg.name;\n }\n } catch { /* ignore */ }\n\n // Try composer.json name\n try {\n const composerPath = path.join(rootPath, relPath, 'composer.json');\n if (fs.existsSync(composerPath)) {\n const composer = JSON.parse(fs.readFileSync(composerPath, 'utf-8')) as { name?: string };\n if (composer.name) return composer.name;\n }\n } catch { /* ignore */ }\n\n // Fallback to directory name\n return path.basename(relPath);\n}\n","/**\n * ES Module Resolver — uses oxc-resolver to resolve import specifiers\n * following Node.js / TypeScript resolution rules.\n */\nimport path from 'node:path';\nimport { ResolverFactory } from 'oxc-resolver';\nimport type { NapiResolveOptions, TsconfigOptions } from 'oxc-resolver';\n\nexport class EsModuleResolver {\n private resolver: ResolverFactory;\n\n constructor(rootPath: string, tsconfigPath?: string) {\n const options: NapiResolveOptions = {\n conditionNames: ['import', 'require', 'node', 'default'],\n extensions: ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.json'],\n mainFields: ['module', 'main'],\n // TypeScript emits `import './foo.js'` but the source file is `foo.ts`.\n // extensionAlias maps .js → [.ts, .tsx, .js, .jsx] so the resolver finds .ts files.\n extensionAlias: {\n '.js': ['.ts', '.tsx', '.js', '.jsx'],\n '.mjs': ['.mts', '.mjs'],\n '.cjs': ['.cts', '.cjs'],\n },\n };\n\n if (tsconfigPath) {\n const tsconfig: TsconfigOptions = { configFile: tsconfigPath };\n options.tsconfig = tsconfig;\n }\n\n this.resolver = new ResolverFactory(options);\n }\n\n /** Resolve a specifier from a given source file. Returns the absolute path or undefined. */\n resolve(specifier: string, fromFile: string): string | undefined {\n const result = this.resolver.sync(path.dirname(fromFile), specifier);\n return result.path ?? undefined;\n }\n}\n","/**\n * No-op AI provider for when AI is disabled or unavailable.\n * All methods either return safe defaults or throw clear errors.\n */\nimport type { AIProvider, EmbeddingService, InferenceService } from './interfaces.js';\n\nclass FallbackEmbeddingService implements EmbeddingService {\n async embed(_text: string): Promise<number[]> {\n return [];\n }\n\n async embedBatch(_texts: string[]): Promise<number[][]> {\n return [];\n }\n\n dimensions(): number {\n return 0;\n }\n}\n\nclass FallbackInferenceService implements InferenceService {\n async generate(_prompt: string): Promise<string> {\n return '';\n }\n}\n\nexport class FallbackProvider implements AIProvider {\n async isAvailable(): Promise<boolean> {\n return false;\n }\n\n embedding(): EmbeddingService {\n return new FallbackEmbeddingService();\n }\n\n inference(): InferenceService {\n return new FallbackInferenceService();\n }\n\n fastInference(): InferenceService {\n return new FallbackInferenceService();\n }\n}\n","/**\n * Ollama AI provider — connects to a local Ollama instance via its HTTP API.\n */\nimport type { AIProvider, EmbeddingService, InferenceService } from './interfaces.js';\nimport { logger } from '../logger.js';\n\nexport interface OllamaConfig {\n baseUrl: string;\n embeddingModel: string;\n inferenceModel: string;\n fastModel: string;\n embeddingDimensions?: number;\n}\n\nclass OllamaEmbeddingService implements EmbeddingService {\n constructor(\n private baseUrl: string,\n private model: string,\n private dims: number,\n ) {}\n\n async embed(text: string): Promise<number[]> {\n const resp = await fetch(`${this.baseUrl}/api/embed`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ model: this.model, input: text }),\n signal: AbortSignal.timeout(30_000),\n });\n\n if (!resp.ok) {\n throw new Error(`Ollama embed failed: ${resp.status} ${resp.statusText}`);\n }\n\n const data = (await resp.json()) as { embeddings: number[][] };\n return data.embeddings[0] ?? [];\n }\n\n async embedBatch(texts: string[]): Promise<number[][]> {\n const resp = await fetch(`${this.baseUrl}/api/embed`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ model: this.model, input: texts }),\n signal: AbortSignal.timeout(30_000),\n });\n\n if (!resp.ok) {\n throw new Error(`Ollama embed batch failed: ${resp.status} ${resp.statusText}`);\n }\n\n const data = (await resp.json()) as { embeddings: number[][] };\n return data.embeddings;\n }\n\n dimensions(): number {\n return this.dims;\n }\n}\n\nclass OllamaInferenceService implements InferenceService {\n constructor(\n private baseUrl: string,\n private model: string,\n ) {}\n\n async generate(prompt: string, options?: { maxTokens?: number; temperature?: number }): Promise<string> {\n const body: Record<string, unknown> = {\n model: this.model,\n prompt,\n stream: false,\n };\n\n if (options?.maxTokens || options?.temperature !== undefined) {\n body.options = {\n ...(options.maxTokens ? { num_predict: options.maxTokens } : {}),\n ...(options.temperature !== undefined ? { temperature: options.temperature } : {}),\n };\n }\n\n const resp = await fetch(`${this.baseUrl}/api/generate`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(60_000),\n });\n\n if (!resp.ok) {\n throw new Error(`Ollama generate failed: ${resp.status} ${resp.statusText}`);\n }\n\n const data = (await resp.json()) as { response: string };\n return data.response;\n }\n}\n\nexport class OllamaProvider implements AIProvider {\n private config: OllamaConfig;\n\n constructor(config: OllamaConfig) {\n this.config = config;\n }\n\n async isAvailable(): Promise<boolean> {\n try {\n const resp = await fetch(`${this.config.baseUrl}/api/tags`, {\n signal: AbortSignal.timeout(2000),\n });\n return resp.ok;\n } catch {\n logger.debug('Ollama not available');\n return false;\n }\n }\n\n embedding(): EmbeddingService {\n return new OllamaEmbeddingService(\n this.config.baseUrl,\n this.config.embeddingModel,\n this.config.embeddingDimensions ?? 768,\n );\n }\n\n inference(): InferenceService {\n return new OllamaInferenceService(\n this.config.baseUrl,\n this.config.inferenceModel,\n );\n }\n\n fastInference(): InferenceService {\n return new OllamaInferenceService(\n this.config.baseUrl,\n this.config.fastModel,\n );\n }\n}\n","/**\n * OpenAI AI provider — connects to the OpenAI API (or any OpenAI-compatible endpoint).\n * Uses fetch directly; no SDK dependency required.\n */\nimport type { AIProvider, EmbeddingService, InferenceService } from './interfaces.js';\nimport { logger } from '../logger.js';\n\nexport interface OpenAIConfig {\n apiKey: string;\n baseUrl: string;\n embeddingModel: string;\n embeddingDimensions: number;\n inferenceModel: string;\n fastModel: string;\n}\n\nclass OpenAIEmbeddingService implements EmbeddingService {\n constructor(\n private baseUrl: string,\n private apiKey: string,\n private model: string,\n private dims: number,\n ) {}\n\n async embed(text: string): Promise<number[]> {\n const results = await this.embedBatch([text]);\n return results[0] ?? [];\n }\n\n async embedBatch(texts: string[]): Promise<number[][]> {\n const resp = await fetch(`${this.baseUrl}/embeddings`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify({ model: this.model, input: texts }),\n signal: AbortSignal.timeout(30_000),\n });\n\n if (!resp.ok) {\n const body = await resp.text().catch(() => '');\n // Truncate body to avoid leaking sensitive data in error messages\n const safeBody = body.length > 200 ? body.slice(0, 200) + '…' : body;\n throw new Error(`OpenAI embeddings failed: ${resp.status} ${resp.statusText} — ${safeBody}`);\n }\n\n const data = (await resp.json()) as { data: { index: number; embedding: number[] }[] };\n // OpenAI returns data sorted by index, but let's be safe\n const result: number[][] = new Array(texts.length).fill(null);\n for (const item of data.data) {\n result[item.index] = item.embedding;\n }\n return result;\n }\n\n dimensions(): number {\n return this.dims;\n }\n}\n\nclass OpenAIInferenceService implements InferenceService {\n constructor(\n private baseUrl: string,\n private apiKey: string,\n private model: string,\n ) {}\n\n async generate(\n prompt: string,\n options?: { maxTokens?: number; temperature?: number },\n ): Promise<string> {\n const resp = await fetch(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify({\n model: this.model,\n messages: [{ role: 'user', content: prompt }],\n ...(options?.maxTokens ? { max_tokens: options.maxTokens } : {}),\n ...(options?.temperature !== undefined ? { temperature: options.temperature } : {}),\n }),\n signal: AbortSignal.timeout(60_000),\n });\n\n if (!resp.ok) {\n const body = await resp.text().catch(() => '');\n const safeBody = body.length > 200 ? body.slice(0, 200) + '…' : body;\n throw new Error(`OpenAI chat failed: ${resp.status} ${resp.statusText} — ${safeBody}`);\n }\n\n const data = (await resp.json()) as { choices: { message: { content: string } }[] };\n return data.choices[0]?.message?.content ?? '';\n }\n}\n\nexport class OpenAIProvider implements AIProvider {\n private config: OpenAIConfig;\n\n constructor(config: OpenAIConfig) {\n this.config = config;\n }\n\n async isAvailable(): Promise<boolean> {\n try {\n const resp = await fetch(`${this.config.baseUrl}/models`, {\n headers: { Authorization: `Bearer ${this.config.apiKey}` },\n signal: AbortSignal.timeout(3000),\n });\n return resp.ok;\n } catch {\n logger.debug('OpenAI not available');\n return false;\n }\n }\n\n embedding(): EmbeddingService {\n return new OpenAIEmbeddingService(\n this.config.baseUrl,\n this.config.apiKey,\n this.config.embeddingModel,\n this.config.embeddingDimensions,\n );\n }\n\n inference(): InferenceService {\n return new OpenAIInferenceService(\n this.config.baseUrl,\n this.config.apiKey,\n this.config.inferenceModel,\n );\n }\n\n fastInference(): InferenceService {\n return new OpenAIInferenceService(\n this.config.baseUrl,\n this.config.apiKey,\n this.config.fastModel,\n );\n }\n}\n","/**\n * BLOB-based vector store using SQLite.\n * Stores embeddings as Float32Array buffers, searches via brute-force cosine similarity.\n * Fine for codebases with <10K symbols.\n */\nimport type Database from 'better-sqlite3';\nimport type { VectorStore } from './interfaces.js';\n\nconst CREATE_TABLE = `\nCREATE TABLE IF NOT EXISTS symbol_embeddings (\n symbol_id INTEGER PRIMARY KEY REFERENCES symbols(id) ON DELETE CASCADE,\n embedding BLOB NOT NULL\n)`;\n\nexport class BlobVectorStore implements VectorStore {\n constructor(private db: Database.Database) {\n this.ensureTable();\n }\n\n private ensureTable(): void {\n this.db.exec(CREATE_TABLE);\n }\n\n insert(id: number, vector: number[]): void {\n const buf = Buffer.from(new Float32Array(vector).buffer);\n this.db.prepare(\n 'INSERT OR REPLACE INTO symbol_embeddings (symbol_id, embedding) VALUES (?, ?)',\n ).run(id, buf);\n }\n\n search(query: number[], limit: number): { id: number; score: number }[] {\n const rows = this.db.prepare(\n 'SELECT symbol_id, embedding FROM symbol_embeddings',\n ).all() as { symbol_id: number; embedding: Buffer }[];\n\n if (rows.length === 0) return [];\n\n const queryArr = new Float32Array(query);\n const queryNorm = vecNorm(queryArr);\n if (queryNorm === 0) return [];\n\n const scored: { id: number; score: number }[] = [];\n\n for (const row of rows) {\n const embedding = new Float32Array(\n row.embedding.buffer,\n row.embedding.byteOffset,\n row.embedding.byteLength / 4,\n );\n const sim = cosineSimilarity(queryArr, embedding, queryNorm);\n scored.push({ id: row.symbol_id, score: sim });\n }\n\n scored.sort((a, b) => b.score - a.score);\n return scored.slice(0, limit);\n }\n\n delete(id: number): void {\n this.db.prepare('DELETE FROM symbol_embeddings WHERE symbol_id = ?').run(id);\n }\n\n count(): number {\n const row = this.db.prepare('SELECT COUNT(*) as cnt FROM symbol_embeddings').get() as { cnt: number };\n return row.cnt;\n }\n}\n\nfunction vecNorm(v: Float32Array): number {\n let sum = 0;\n for (let i = 0; i < v.length; i++) {\n sum += v[i] * v[i];\n }\n return Math.sqrt(sum);\n}\n\nfunction cosineSimilarity(a: Float32Array, b: Float32Array, aNorm?: number): number {\n if (a.length !== b.length) return 0;\n\n let dot = 0;\n let bSumSq = 0;\n\n for (let i = 0; i < a.length; i++) {\n dot += a[i] * b[i];\n bSumSq += b[i] * b[i];\n }\n\n const normA = aNorm ?? vecNorm(a);\n const normB = Math.sqrt(bSumSq);\n\n if (normA === 0 || normB === 0) return 0;\n return dot / (normA * normB);\n}\n","/**\n * Content-addressable inference cache backed by SQLite.\n * Key = sha256(model + '\\0' + prompt) → cached response.\n */\nimport type Database from 'better-sqlite3';\nimport { createHash } from 'node:crypto';\nimport { logger } from '../logger.js';\n\nexport class InferenceCache {\n constructor(private db: Database.Database) {}\n\n private cacheKey(model: string, prompt: string): string {\n return createHash('sha256').update(model + '\\0' + prompt).digest('hex');\n }\n\n get(model: string, prompt: string): string | null {\n const key = this.cacheKey(model, prompt);\n const row = this.db.prepare(\n `SELECT response FROM inference_cache\n WHERE cache_key = ?\n AND datetime(created_at, '+' || ttl_days || ' days') > datetime('now')`,\n ).get(key) as { response: string } | undefined;\n if (row) {\n logger.debug({ model, cacheKey: key.slice(0, 12) }, 'Inference cache hit');\n }\n return row?.response ?? null;\n }\n\n set(model: string, prompt: string, response: string): void {\n const key = this.cacheKey(model, prompt);\n const promptHash = createHash('sha256').update(prompt).digest('hex');\n this.db.prepare(\n `INSERT OR REPLACE INTO inference_cache (cache_key, model, prompt_hash, response, created_at, ttl_days)\n VALUES (?, ?, ?, ?, datetime('now'), 90)`,\n ).run(key, model, promptHash, response);\n }\n\n evictExpired(): number {\n const result = this.db.prepare(\n `DELETE FROM inference_cache\n WHERE datetime(created_at, '+' || ttl_days || ' days') <= datetime('now')`,\n ).run();\n const count = result.changes;\n if (count > 0) {\n logger.info({ evicted: count }, 'Evicted expired inference cache entries');\n }\n return count;\n }\n}\n","/**\n * Versioned prompt templates for all AI tasks.\n * When a template changes, the prompt text changes → cache key changes → fresh generation.\n */\n\nexport interface PromptTemplate {\n version: number;\n build: (vars: Record<string, string>) => string;\n maxTokens: number;\n temperature: number;\n}\n\nexport const PROMPTS = {\n summarize_symbol: {\n version: 1,\n build: (v) => {\n const parts = [`Summarize this ${v.kind} in one concise sentence. Focus on WHAT it does, not HOW.`];\n parts.push(`Name: ${v.name}`);\n if (v.fqn) parts.push(`FQN: ${v.fqn}`);\n if (v.signature) parts.push(`Signature: ${v.signature}`);\n if (v.source) parts.push(`Source:\\n${v.source}`);\n parts.push('Summary:');\n return parts.join('\\n');\n },\n maxTokens: 100,\n temperature: 0.1,\n },\n\n explain_symbol: {\n version: 1,\n build: (v) => {\n const parts = [\n `Explain this ${v.kind} in detail. Cover: purpose, key behaviors, relationships with other code, and usage patterns.`,\n `Name: ${v.name}`,\n ];\n if (v.fqn) parts.push(`FQN: ${v.fqn}`);\n if (v.signature) parts.push(`Signature: ${v.signature}`);\n if (v.source) parts.push(`Source:\\n${v.source}`);\n if (v.context) parts.push(`Related context:\\n${v.context}`);\n parts.push('Explanation:');\n return parts.join('\\n');\n },\n maxTokens: 500,\n temperature: 0.3,\n },\n\n suggest_tests: {\n version: 1,\n build: (v) => {\n const parts = [\n 'Suggest test cases for this code. For each test, provide a description and what it should verify.',\n `Name: ${v.name}`,\n `Kind: ${v.kind}`,\n ];\n if (v.signature) parts.push(`Signature: ${v.signature}`);\n if (v.source) parts.push(`Source:\\n${v.source}`);\n if (v.dependencies) parts.push(`Dependencies:\\n${v.dependencies}`);\n parts.push('Respond in JSON: [{ \"description\": \"...\", \"verifies\": \"...\" }]');\n return parts.join('\\n');\n },\n maxTokens: 800,\n temperature: 0.3,\n },\n\n review_change: {\n version: 1,\n build: (v) => {\n const parts = [\n 'Review this code change. Identify potential issues, bugs, or improvements.',\n `File: ${v.filePath}`,\n ];\n if (v.diff) parts.push(`Diff:\\n${v.diff}`);\n if (v.blastRadius) parts.push(`Affected dependents:\\n${v.blastRadius}`);\n parts.push('Respond in JSON: { \"issues\": [{ \"severity\": \"high|medium|low\", \"description\": \"...\", \"suggestion\": \"...\" }], \"summary\": \"...\" }');\n return parts.join('\\n');\n },\n maxTokens: 800,\n temperature: 0.2,\n },\n\n explain_architecture: {\n version: 1,\n build: (v) => {\n const parts = [\n 'Analyze the architecture of this codebase scope. Describe layers, key patterns, and data flow.',\n ];\n if (v.scope) parts.push(`Scope: ${v.scope}`);\n if (v.context) parts.push(`Key symbols and structure:\\n${v.context}`);\n parts.push('Respond in JSON: { \"overview\": \"...\", \"layers\": [\"...\"], \"key_patterns\": [\"...\"], \"data_flow\": [\"...\"] }');\n return parts.join('\\n');\n },\n maxTokens: 1000,\n temperature: 0.3,\n },\n\n rerank: {\n version: 1,\n build: (v) => {\n return `Rate the relevance of each document to the query on a scale of 0-10.\nQuery: ${v.query}\n\nDocuments:\n${v.documents}\n\nRespond with one score per line, in order: just the number, nothing else.`;\n },\n maxTokens: 200,\n temperature: 0.0,\n },\n} satisfies Record<string, PromptTemplate>;\n","/**\n * AI-powered summarization pipeline.\n * Runs after indexing to populate the symbols.summary column using the fast inference model.\n * Uses CachedInferenceService to avoid redundant LLM calls across re-indexes.\n */\nimport type { InferenceService } from './interfaces.js';\nimport type { Store } from '../db/store.js';\nimport { PROMPTS } from './prompts.js';\nimport { logger } from '../logger.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nexport interface SummarizationConfig {\n batchSize: number;\n kinds: string[];\n}\n\nconst MAX_SOURCE_LINES = 80;\n\nexport class SummarizationPipeline {\n constructor(\n private store: Store,\n private inferenceService: InferenceService,\n private rootPath: string,\n private config: SummarizationConfig,\n ) {}\n\n async summarizeUnsummarized(): Promise<number> {\n let totalSummarized = 0;\n let batch: ReturnType<Store['getUnsummarizedSymbols']>;\n\n do {\n batch = this.store.getUnsummarizedSymbols(this.config.kinds, this.config.batchSize);\n if (batch.length === 0) break;\n\n const results = await this.summarizeBatch(batch);\n for (const { id, summary } of results) {\n this.store.updateSymbolSummary(id, summary);\n totalSummarized++;\n }\n\n logger.debug({ batch: batch.length, total: totalSummarized }, 'Summarization batch complete');\n } while (batch.length === this.config.batchSize);\n\n if (totalSummarized > 0) {\n logger.info({ totalSummarized }, 'Symbol summarization complete');\n }\n return totalSummarized;\n }\n\n private async summarizeBatch(\n symbols: ReturnType<Store['getUnsummarizedSymbols']>,\n ): Promise<{ id: number; summary: string }[]> {\n const results: { id: number; summary: string }[] = [];\n const template = PROMPTS.summarize_symbol;\n\n for (const sym of symbols) {\n try {\n const source = this.readSource(sym.file_path, sym.byte_start, sym.byte_end);\n const prompt = template.build({\n kind: sym.kind,\n name: sym.name,\n fqn: sym.fqn ?? '',\n signature: sym.signature ?? '',\n source: source ?? '',\n });\n\n const summary = await this.inferenceService.generate(prompt, {\n maxTokens: template.maxTokens,\n temperature: template.temperature,\n });\n\n const cleaned = summary.trim();\n if (cleaned) {\n results.push({ id: sym.id, summary: cleaned });\n }\n } catch (e) {\n logger.warn({ symbolId: sym.id, name: sym.name, error: e }, 'Failed to summarize symbol');\n }\n }\n\n return results;\n }\n\n private readSource(filePath: string, byteStart: number, byteEnd: number): string | null {\n try {\n const absPath = path.resolve(this.rootPath, filePath);\n const content = fs.readFileSync(absPath, 'utf-8');\n const slice = content.slice(byteStart, byteEnd);\n const lines = slice.split('\\n');\n if (lines.length > MAX_SOURCE_LINES) {\n return lines.slice(0, MAX_SOURCE_LINES).join('\\n') + '\\n// ... truncated';\n }\n return slice;\n } catch {\n return null;\n }\n }\n}\n","/**\n * LLM-based reranker — uses a fast inference model to re-score search results.\n * Falls back to original order on parse failure.\n */\nimport type { InferenceService, RerankerService } from './interfaces.js';\nimport { PROMPTS } from './prompts.js';\nimport { logger } from '../logger.js';\n\nexport class LLMReranker implements RerankerService {\n constructor(private inference: InferenceService) {}\n\n async rerank(\n query: string,\n documents: { id: number; text: string }[],\n topK: number,\n ): Promise<{ id: number; score: number }[]> {\n if (documents.length === 0) return [];\n if (documents.length <= 1) return documents.map((d) => ({ id: d.id, score: 1 }));\n\n try {\n const docsText = documents\n .map((d, i) => `[${i + 1}] ${d.text.slice(0, 200)}`)\n .join('\\n');\n\n const prompt = PROMPTS.rerank.build({\n query,\n documents: docsText,\n });\n\n const response = await this.inference.generate(prompt, {\n maxTokens: PROMPTS.rerank.maxTokens,\n temperature: PROMPTS.rerank.temperature,\n });\n\n const scores = this.parseScores(response, documents.length);\n if (!scores) {\n logger.debug('Reranker: failed to parse scores, keeping original order');\n return documents.slice(0, topK).map((d, i) => ({\n id: d.id,\n score: documents.length - i,\n }));\n }\n\n const scored = documents.map((d, i) => ({\n id: d.id,\n score: scores[i] ?? 0,\n }));\n\n scored.sort((a, b) => b.score - a.score);\n return scored.slice(0, topK);\n } catch (e) {\n logger.warn({ error: e }, 'Reranker failed, keeping original order');\n return documents.slice(0, topK).map((d, i) => ({\n id: d.id,\n score: documents.length - i,\n }));\n }\n }\n\n private parseScores(response: string, expectedCount: number): number[] | null {\n const lines = response.trim().split('\\n').map((l) => l.trim()).filter(Boolean);\n const scores: number[] = [];\n\n for (const line of lines) {\n const match = line.match(/(\\d+(?:\\.\\d+)?)/);\n if (match) {\n scores.push(parseFloat(match[1]));\n }\n if (scores.length >= expectedCount) break;\n }\n\n if (scores.length !== expectedCount) return null;\n return scores;\n }\n}\n","/**\n * AI layer factory — creates the appropriate provider based on config.\n * Returns FallbackProvider when AI is disabled.\n */\nimport type { TraceMcpConfig } from '../config.js';\nimport type { AIProvider } from './interfaces.js';\nimport { FallbackProvider } from './fallback.js';\nimport { OllamaProvider } from './ollama.js';\nimport { OpenAIProvider } from './openai.js';\nimport { logger } from '../logger.js';\n\nexport function createAIProvider(config: TraceMcpConfig): AIProvider {\n if (!config.ai?.enabled) {\n return new FallbackProvider();\n }\n\n if (config.ai.provider === 'openai') {\n const apiKey = config.ai.api_key ?? process.env.OPENAI_API_KEY ?? '';\n if (!apiKey) {\n logger.warn('OpenAI provider selected but no api_key configured — falling back to FallbackProvider');\n return new FallbackProvider();\n }\n return new OpenAIProvider({\n apiKey,\n baseUrl: config.ai.base_url ?? 'https://api.openai.com/v1',\n embeddingModel: config.ai.embedding_model ?? 'text-embedding-3-small',\n embeddingDimensions: config.ai.embedding_dimensions ?? 1536,\n inferenceModel: config.ai.inference_model ?? 'gpt-4o-mini',\n fastModel: config.ai.fast_model ?? 'gpt-4o-mini',\n });\n }\n\n if (config.ai.provider === 'ollama') {\n return new OllamaProvider({\n baseUrl: config.ai.base_url ?? 'http://localhost:11434',\n embeddingModel: config.ai.embedding_model ?? 'nomic-embed-text',\n inferenceModel: config.ai.inference_model ?? 'qwen2.5-coder:7b',\n fastModel: config.ai.fast_model ?? 'qwen2.5-coder:1.5b',\n embeddingDimensions: config.ai.embedding_dimensions,\n });\n }\n\n return new FallbackProvider();\n}\n\nexport type { AIProvider, EmbeddingService, InferenceService, VectorStore, RerankerService } from './interfaces.js';\nexport { FallbackProvider } from './fallback.js';\nexport { OllamaProvider } from './ollama.js';\nexport { OpenAIProvider } from './openai.js';\nexport { BlobVectorStore } from './vector-store.js';\nexport { hybridSearch } from './search.js';\nexport { EmbeddingPipeline } from './embedding-pipeline.js';\nexport { InferenceCache } from './inference-cache.js';\nexport { CachedInferenceService } from './cached-inference.js';\nexport { SummarizationPipeline } from './summarization-pipeline.js';\nexport { PROMPTS } from './prompts.js';\nexport { LLMReranker } from './reranker.js';\nexport type { PromptTemplate } from './prompts.js';\n","/**\n * AI-powered MCP tools — require AI to be enabled.\n * Each tool gracefully returns an error message when AI is disabled.\n */\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { Store, SymbolRow, FileRow } from '../db/store.js';\nimport type { InferenceService, EmbeddingService, VectorStore, RerankerService } from '../ai/interfaces.js';\nimport { PROMPTS } from '../ai/prompts.js';\nimport { readByteRange } from '../utils/source-reader.js';\nimport { assembleStructuredContext, renderStructuredContext } from '../scoring/structured-assembly.js';\nimport type { ContextItem } from '../scoring/assembly.js';\nimport { getChangeImpact } from './impact.js';\nimport path from 'node:path';\n\ninterface AIToolsContext {\n store: Store;\n smartInference: InferenceService;\n fastInference: InferenceService;\n embeddingService: EmbeddingService | null;\n vectorStore: VectorStore | null;\n reranker: RerankerService | null;\n projectRoot: string;\n}\n\nfunction j(value: unknown): string {\n return JSON.stringify(value);\n}\n\nfunction symbolToContextItem(sym: SymbolRow, file: FileRow, projectRoot: string, score = 1): ContextItem {\n const source = readSourceSafe(file.path, sym.byte_start, sym.byte_end, projectRoot);\n return {\n id: sym.symbol_id,\n score,\n source: source ?? undefined,\n signature: sym.signature ?? undefined,\n metadata: `${sym.kind} ${sym.fqn ?? sym.name} — ${file.path}`,\n };\n}\n\nfunction readSourceSafe(filePath: string, byteStart: number, byteEnd: number, projectRoot: string): string | null {\n try {\n const absPath = path.resolve(projectRoot, filePath);\n return readByteRange(absPath, byteStart, byteEnd);\n } catch {\n return null;\n }\n}\n\nfunction resolveSymbol(store: Store, opts: { symbolId?: string; fqn?: string }): { sym: SymbolRow; file: FileRow } | null {\n let sym: SymbolRow | undefined;\n if (opts.symbolId) {\n sym = store.getSymbolBySymbolId(opts.symbolId);\n } else if (opts.fqn) {\n sym = store.getSymbolByFqn(opts.fqn);\n }\n if (!sym) return null;\n const file = store.getFileById(sym.file_id);\n if (!file) return null;\n return { sym, file };\n}\n\nfunction gatherRelatedSymbols(\n store: Store,\n sym: SymbolRow,\n projectRoot: string,\n): { dependencies: ContextItem[]; callers: ContextItem[]; typeContext: ContextItem[] } {\n const dependencies: ContextItem[] = [];\n const callers: ContextItem[] = [];\n const typeContext: ContextItem[] = [];\n\n const symNodeId = store.getNodeId('symbol', sym.id);\n if (!symNodeId) return { dependencies, callers, typeContext };\n\n // Outgoing edges = dependencies\n const outEdges = store.getOutgoingEdges(symNodeId);\n for (const edge of outEdges.slice(0, 10)) {\n const ref = store.getNodeRef(edge.target_node_id);\n if (!ref || ref.nodeType !== 'symbol') continue;\n const depSym = store.getSymbolById(ref.refId);\n if (!depSym) continue;\n const depFile = store.getFileById(depSym.file_id);\n if (!depFile) continue;\n dependencies.push(symbolToContextItem(depSym, depFile, projectRoot, 0.5));\n }\n\n // Incoming edges = callers\n const inEdges = store.getIncomingEdges(symNodeId);\n for (const edge of inEdges.slice(0, 10)) {\n const ref = store.getNodeRef(edge.source_node_id);\n if (!ref || ref.nodeType !== 'symbol') continue;\n const callerSym = store.getSymbolById(ref.refId);\n if (!callerSym) continue;\n const callerFile = store.getFileById(callerSym.file_id);\n if (!callerFile) continue;\n callers.push(symbolToContextItem(callerSym, callerFile, projectRoot, 0.3));\n }\n\n // Type hierarchy\n if (sym.metadata) {\n try {\n const meta = JSON.parse(sym.metadata);\n const parents = [...(meta.extends ? [meta.extends].flat() : []), ...(meta.implements ?? [])];\n for (const parentName of parents.slice(0, 5)) {\n const parentSym = store.getSymbolByName(parentName);\n if (!parentSym) continue;\n const parentFile = store.getFileById(parentSym.file_id);\n if (!parentFile) continue;\n typeContext.push(symbolToContextItem(parentSym, parentFile, projectRoot, 0.4));\n }\n } catch { /* ignore parse errors */ }\n }\n\n return { dependencies, callers, typeContext };\n}\n\nexport function registerAITools(\n server: McpServer,\n ctx: AIToolsContext,\n): void {\n const { store, smartInference, embeddingService, vectorStore, reranker, projectRoot } = ctx;\n\n // ─── explain_symbol ──────────────────────────────────────\n server.tool(\n 'explain_symbol',\n 'Explain a symbol in detail using AI — purpose, behavior, relationships, usage patterns',\n {\n symbol_id: z.string().optional().describe('Symbol ID (e.g. src/auth.ts::AuthService#class)'),\n fqn: z.string().optional().describe('Fully qualified name'),\n },\n async ({ symbol_id, fqn }) => {\n const resolved = resolveSymbol(store, { symbolId: symbol_id, fqn });\n if (!resolved) {\n return { content: [{ type: 'text', text: j({ error: 'Symbol not found' }) }], isError: true };\n }\n const { sym, file } = resolved;\n const primary = [symbolToContextItem(sym, file, projectRoot)];\n const related = gatherRelatedSymbols(store, sym, projectRoot);\n\n const structured = assembleStructuredContext({\n primary,\n dependencies: related.dependencies,\n callers: related.callers,\n typeContext: related.typeContext,\n totalBudget: 4000,\n });\n\n const contextStr = renderStructuredContext(structured);\n const prompt = PROMPTS.explain_symbol.build({\n kind: sym.kind,\n name: sym.name,\n fqn: sym.fqn ?? '',\n signature: sym.signature ?? '',\n source: primary[0].source ?? '',\n context: contextStr,\n });\n\n const explanation = await smartInference.generate(prompt, {\n maxTokens: PROMPTS.explain_symbol.maxTokens,\n temperature: PROMPTS.explain_symbol.temperature,\n });\n\n return {\n content: [{\n type: 'text',\n text: j({\n symbol_id: sym.symbol_id,\n name: sym.name,\n kind: sym.kind,\n file: file.path,\n explanation,\n related_symbols: [\n ...related.dependencies.map((d) => d.id),\n ...related.callers.map((c) => c.id),\n ...related.typeContext.map((t) => t.id),\n ],\n }),\n }],\n };\n },\n );\n\n // ─── suggest_tests ───────────────────────────────────────\n server.tool(\n 'suggest_tests',\n 'Suggest test cases for a symbol using AI',\n {\n symbol_id: z.string().optional().describe('Symbol ID'),\n fqn: z.string().optional().describe('Fully qualified name'),\n },\n async ({ symbol_id, fqn }) => {\n const resolved = resolveSymbol(store, { symbolId: symbol_id, fqn });\n if (!resolved) {\n return { content: [{ type: 'text', text: j({ error: 'Symbol not found' }) }], isError: true };\n }\n const { sym, file } = resolved;\n const source = readSourceSafe(file.path, sym.byte_start, sym.byte_end, projectRoot);\n const related = gatherRelatedSymbols(store, sym, projectRoot);\n\n const depsStr = related.dependencies.map((d) => d.metadata).join('\\n');\n\n const prompt = PROMPTS.suggest_tests.build({\n kind: sym.kind,\n name: sym.name,\n signature: sym.signature ?? '',\n source: source ?? '',\n dependencies: depsStr,\n });\n\n const response = await smartInference.generate(prompt, {\n maxTokens: PROMPTS.suggest_tests.maxTokens,\n temperature: PROMPTS.suggest_tests.temperature,\n });\n\n let suggestions: unknown;\n try {\n suggestions = JSON.parse(response);\n } catch {\n suggestions = [{ description: response, verifies: 'See description' }];\n }\n\n return {\n content: [{\n type: 'text',\n text: j({\n symbol_id: sym.symbol_id,\n name: sym.name,\n suggestions,\n }),\n }],\n };\n },\n );\n\n // ─── review_change ───────────────────────────────────────\n server.tool(\n 'review_change',\n 'AI-powered review of a file change — identify issues, risks, and suggestions',\n {\n file_path: z.string().describe('File path relative to project root'),\n diff: z.string().optional().describe('Git diff content (if not provided, reviews full file)'),\n },\n async ({ file_path, diff }) => {\n const impactResult = getChangeImpact(store, { filePath: file_path });\n const blastRadius = impactResult.isOk()\n ? impactResult.value.dependents.map((d) => `${d.edgeType}: ${d.path}`).join('\\n')\n : '';\n\n const prompt = PROMPTS.review_change.build({\n filePath: file_path,\n diff: diff ?? '',\n blastRadius,\n });\n\n const response = await smartInference.generate(prompt, {\n maxTokens: PROMPTS.review_change.maxTokens,\n temperature: PROMPTS.review_change.temperature,\n });\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(response);\n } catch {\n parsed = { issues: [], summary: response };\n }\n\n return { content: [{ type: 'text', text: j(parsed) }] };\n },\n );\n\n // ─── find_similar ────────────────────────────────────────\n server.tool(\n 'find_similar',\n 'Find semantically similar symbols using vector search + optional AI reranking',\n {\n symbol_id: z.string().optional().describe('Symbol ID to find similar code to'),\n query: z.string().optional().describe('Free-text query (used if no symbol_id)'),\n limit: z.number().int().min(1).max(50).optional().describe('Max results (default 10)'),\n },\n async ({ symbol_id, query, limit: maxResults }) => {\n const resultLimit = maxResults ?? 10;\n\n if (!embeddingService || !vectorStore) {\n return { content: [{ type: 'text', text: j({ error: 'Vector search requires AI embeddings to be enabled' }) }], isError: true };\n }\n\n let queryText: string;\n if (symbol_id) {\n const sym = store.getSymbolBySymbolId(symbol_id);\n if (!sym) {\n return { content: [{ type: 'text', text: j({ error: 'Symbol not found' }) }], isError: true };\n }\n queryText = [sym.kind, sym.fqn ?? sym.name, sym.signature ?? '', sym.summary ?? ''].join(' ');\n } else if (query) {\n queryText = query;\n } else {\n return { content: [{ type: 'text', text: j({ error: 'Provide symbol_id or query' }) }], isError: true };\n }\n\n const embedding = await embeddingService.embed(queryText);\n if (embedding.length === 0) {\n return { content: [{ type: 'text', text: j({ results: [] }) }] };\n }\n\n let vectorResults = vectorStore.search(embedding, resultLimit * 3);\n\n // Exclude the source symbol from results\n if (symbol_id) {\n const srcSym = store.getSymbolBySymbolId(symbol_id);\n if (srcSym) {\n vectorResults = vectorResults.filter((r) => r.id !== srcSym.id);\n }\n }\n\n // Optional reranking\n if (reranker && vectorResults.length > 1) {\n const docs = vectorResults.map((r) => {\n const sym = store.getSymbolById(r.id);\n return { id: r.id, text: sym ? `${sym.kind} ${sym.fqn ?? sym.name} ${sym.signature ?? ''}` : '' };\n });\n try {\n const reranked = await reranker.rerank(queryText, docs, resultLimit);\n vectorResults = reranked.map((r) => ({ id: r.id, score: r.score }));\n } catch { /* keep original order */ }\n }\n\n const results = vectorResults.slice(0, resultLimit).map((r) => {\n const sym = store.getSymbolById(r.id);\n const file = sym ? store.getFileById(sym.file_id) : undefined;\n return {\n symbol_id: sym?.symbol_id,\n name: sym?.name,\n kind: sym?.kind,\n fqn: sym?.fqn,\n file: file?.path,\n similarity: Math.round(r.score * 1000) / 1000,\n summary: sym?.summary ?? null,\n };\n }).filter((r) => r.symbol_id);\n\n return { content: [{ type: 'text', text: j({ results }) }] };\n },\n );\n\n // ─── explain_architecture ────────────────────────────────\n server.tool(\n 'explain_architecture',\n 'AI-powered architecture analysis — layers, patterns, and data flow',\n {\n scope: z.string().optional().describe('Scope to analyze (e.g. \"authentication\", \"data layer\", or empty for full project)'),\n token_budget: z.number().int().min(500).max(16000).optional().describe('Token budget for context (default 6000)'),\n },\n async ({ scope, token_budget }) => {\n const budget = token_budget ?? 6000;\n\n // Gather key symbols via FTS if scope provided, otherwise top symbols by kind\n const symbols: ContextItem[] = [];\n\n if (scope) {\n // Use FTS to find relevant symbols\n const ftsQuery = scope.split(/\\s+/).map((t) => `\"${t}\"`).join(' OR ');\n const ftsResults = store.db.prepare(`\n SELECT s.*, f.path as file_path\n FROM symbols_fts fts\n JOIN symbols s ON s.id = fts.rowid\n JOIN files f ON f.id = s.file_id\n WHERE symbols_fts MATCH ?\n ORDER BY rank\n LIMIT 30\n `).all(ftsQuery) as (SymbolRow & { file_path: string })[];\n\n for (const row of ftsResults) {\n const file = store.getFileById(row.file_id);\n if (!file) continue;\n symbols.push(symbolToContextItem(row, file, projectRoot, 0.5));\n }\n } else {\n // Get top classes/interfaces as architectural anchors\n const topSymbols = store.db.prepare(`\n SELECT s.*, f.path as file_path\n FROM symbols s\n JOIN files f ON f.id = s.file_id\n WHERE s.kind IN ('class', 'interface', 'trait')\n LIMIT 30\n `).all() as (SymbolRow & { file_path: string })[];\n\n for (const row of topSymbols) {\n const file = store.getFileById(row.file_id);\n if (!file) continue;\n symbols.push(symbolToContextItem(row, file, projectRoot, 0.5));\n }\n }\n\n const assembled = assembleStructuredContext({\n primary: symbols,\n dependencies: [],\n callers: [],\n typeContext: [],\n totalBudget: budget,\n budgetWeights: { primary: 1.0, dependencies: 0, callers: 0, typeContext: 0 },\n });\n\n const contextStr = renderStructuredContext(assembled);\n const prompt = PROMPTS.explain_architecture.build({\n scope: scope ?? 'full project',\n context: contextStr,\n });\n\n const response = await smartInference.generate(prompt, {\n maxTokens: PROMPTS.explain_architecture.maxTokens,\n temperature: PROMPTS.explain_architecture.temperature,\n });\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(response);\n } catch {\n parsed = { overview: response, layers: [], key_patterns: [], data_flow: [] };\n }\n\n return { content: [{ type: 'text', text: j(parsed) }] };\n },\n );\n}\n","/**\n * Structured context assembly for AI tools.\n * Groups items by role (primary, dependencies, callers, type context)\n * and allocates token budget proportionally.\n */\nimport { assembleContext, type ContextItem, type AssembledItem } from './assembly.js';\n\nexport interface StructuredContextRequest {\n primary: ContextItem[];\n dependencies: ContextItem[];\n callers: ContextItem[];\n typeContext: ContextItem[];\n totalBudget: number;\n budgetWeights?: { primary: number; dependencies: number; callers: number; typeContext: number };\n}\n\nexport interface StructuredContextResult {\n primary: AssembledItem[];\n dependencies: AssembledItem[];\n callers: AssembledItem[];\n typeContext: AssembledItem[];\n totalTokens: number;\n truncated: boolean;\n}\n\nconst DEFAULT_WEIGHTS = { primary: 0.4, dependencies: 0.3, callers: 0.2, typeContext: 0.1 };\n\nexport function assembleStructuredContext(request: StructuredContextRequest): StructuredContextResult {\n const weights = request.budgetWeights ?? DEFAULT_WEIGHTS;\n const budget = request.totalBudget;\n\n const primaryResult = assembleContext(request.primary, Math.floor(budget * weights.primary));\n const depsResult = assembleContext(request.dependencies, Math.floor(budget * weights.dependencies));\n const callersResult = assembleContext(request.callers, Math.floor(budget * weights.callers));\n const typeResult = assembleContext(request.typeContext, Math.floor(budget * weights.typeContext));\n\n return {\n primary: primaryResult.items,\n dependencies: depsResult.items,\n callers: callersResult.items,\n typeContext: typeResult.items,\n totalTokens: primaryResult.totalTokens + depsResult.totalTokens + callersResult.totalTokens + typeResult.totalTokens,\n truncated: primaryResult.truncated || depsResult.truncated || callersResult.truncated || typeResult.truncated,\n };\n}\n\n/**\n * Render structured context into a flat string for LLM prompts.\n */\nexport function renderStructuredContext(result: StructuredContextResult): string {\n const sections: string[] = [];\n\n if (result.primary.length > 0) {\n sections.push('=== Primary Symbol ===\\n' + result.primary.map((i) => i.content).join('\\n\\n'));\n }\n if (result.dependencies.length > 0) {\n sections.push('=== Dependencies ===\\n' + result.dependencies.map((i) => i.content).join('\\n\\n'));\n }\n if (result.callers.length > 0) {\n sections.push('=== Callers ===\\n' + result.callers.map((i) => i.content).join('\\n\\n'));\n }\n if (result.typeContext.length > 0) {\n sections.push('=== Type Hierarchy ===\\n' + result.typeContext.map((i) => i.content).join('\\n\\n'));\n }\n\n return sections.join('\\n\\n');\n}\n","/**\n * get_middleware_chain — Trace middleware for a given route URL.\n *\n * Express: app-level -> router-level -> route-level middleware.\n * NestJS: guards -> pipes -> interceptors -> filters.\n * Flask: global before_request -> blueprint before_request -> route.\n * FastAPI: app middleware -> router middleware -> Depends().\n * Django: settings.MIDDLEWARE -> view decorators.\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport type { Store } from '../db/store.js';\nimport { ok, err, type TraceMcpResult } from '../errors.js';\nimport { escapeRegExp } from '../utils/security.js';\nimport { notFound } from '../errors.js';\n\nexport interface MiddlewareEntry {\n name: string;\n scope: 'global' | 'router' | 'route' | 'guard' | 'pipe' | 'interceptor' | 'filter'\n | 'before_request' | 'after_request' | 'error_handler' | 'depends' | 'middleware' | 'view_decorator';\n path?: string;\n file?: string;\n}\n\nexport interface MiddlewareChainResult {\n url: string;\n framework: 'express' | 'nestjs' | 'flask' | 'fastapi' | 'django' | 'unknown';\n chain: MiddlewareEntry[];\n}\n\n/**\n * Build middleware chain for a given URL.\n * Inspects indexed routes and file content to trace middleware layers.\n */\nexport function getMiddlewareChain(\n store: Store,\n rootPath: string,\n url: string,\n): TraceMcpResult<MiddlewareChainResult> {\n const allRoutes = store.getAllRoutes();\n\n // Find matching route\n const matchingRoute = allRoutes.find((r) => {\n const pattern = r.uri\n .replace(/:[^/]+/g, '\\0PARAM\\0')\n .replace(/\\{[^}]+\\}/g, '\\0PARAM\\0')\n .replace(/<[^>]+>/g, '\\0PARAM\\0') // Django/Flask: <int:pk>\n .split('\\0PARAM\\0')\n .map(escapeRegExp)\n .join('[^/]+');\n return new RegExp(`^${pattern}$`).test(url) || r.uri === url;\n });\n\n if (!matchingRoute) {\n return err(notFound(url, ['No matching route found. Run reindex first.']));\n }\n\n const chain: MiddlewareEntry[] = [];\n const allFiles = store.getAllFiles();\n\n // Detect framework\n const framework = detectFramework(allFiles);\n\n if (framework === 'express') {\n buildExpressChain(store, rootPath, url, allFiles, chain);\n } else if (framework === 'nestjs') {\n buildNestChain(store, rootPath, matchingRoute, allFiles, chain);\n } else if (framework === 'flask') {\n buildFlaskChain(store, rootPath, url, allFiles, chain);\n } else if (framework === 'fastapi') {\n buildFastAPIChain(store, rootPath, url, allFiles, chain);\n } else if (framework === 'django') {\n buildDjangoChain(store, rootPath, allFiles, chain);\n }\n\n // Add route-level middleware from the route itself\n if (matchingRoute.middleware) {\n try {\n const parsed = JSON.parse(matchingRoute.middleware) as { middleware?: string[] };\n for (const mw of parsed.middleware ?? []) {\n chain.push({ name: mw, scope: 'route', path: matchingRoute.uri });\n }\n } catch {\n // ignore malformed middleware JSON\n }\n }\n\n return ok({ url, framework, chain });\n}\n\ntype FileInfo = { id: number; path: string; framework_role: string | null };\n\nfunction detectFramework(allFiles: FileInfo[]): MiddlewareChainResult['framework'] {\n for (const f of allFiles) {\n const role = f.framework_role;\n if (!role) continue;\n if (role.startsWith('nest_')) return 'nestjs';\n if (role.startsWith('express_')) return 'express';\n if (role.startsWith('flask_')) return 'flask';\n if (role.startsWith('fastapi_')) return 'fastapi';\n if (role.startsWith('django_') || role === 'url_config') return 'django';\n }\n return 'unknown';\n}\n\nfunction readSource(rootPath: string, filePath: string): string | undefined {\n try {\n return fs.readFileSync(path.resolve(rootPath, filePath), 'utf-8');\n } catch {\n return undefined;\n }\n}\n\n// ─── Express ──────────────────────────────────────────────────\n\nfunction buildExpressChain(\n store: Store,\n rootPath: string,\n url: string,\n allFiles: FileInfo[],\n chain: MiddlewareEntry[],\n): void {\n const GLOBAL_MW_RE = /(?:app|router)\\s*\\.\\s*use\\s*\\(\\s*([A-Za-z][\\w.]*(?:\\s*\\(\\s*[^)]*\\))?)\\s*[,)]/g;\n const PATH_MW_RE = /(?:app|router)\\s*\\.\\s*use\\s*\\(\\s*['\"`]([^'\"`]+)['\"`]\\s*,\\s*([A-Za-z][\\w.]*)/g;\n\n for (const file of allFiles) {\n if (file.framework_role !== 'express_router' && file.framework_role !== 'express_middleware') continue;\n const source = readSource(rootPath, file.path);\n if (!source) continue;\n\n let match: RegExpExecArray | null;\n const globalRe = new RegExp(GLOBAL_MW_RE.source, 'g');\n while ((match = globalRe.exec(source)) !== null) {\n const name = match[1].trim();\n if (/^['\"`]/.test(name)) continue;\n chain.push({ name, scope: 'global', file: file.path });\n }\n\n const pathRe = new RegExp(PATH_MW_RE.source, 'g');\n while ((match = pathRe.exec(source)) !== null) {\n const mwPath = match[1];\n if (url.startsWith(mwPath)) {\n chain.push({ name: match[2], scope: 'router', path: mwPath, file: file.path });\n }\n }\n }\n}\n\n// ─── NestJS ───────────────────────────────────────────────────\n\nfunction buildNestChain(\n store: Store,\n rootPath: string,\n route: { uri: string; file_id: number | null },\n allFiles: FileInfo[],\n chain: MiddlewareEntry[],\n): void {\n const GUARDS_RE = /@UseGuards\\(\\s*([^)]+)\\s*\\)/g;\n const PIPES_RE = /@UsePipes\\(\\s*([^)]+)\\s*\\)/g;\n const INTERCEPTORS_RE = /@UseInterceptors\\(\\s*([^)]+)\\s*\\)/g;\n const FILTERS_RE = /@UseFilters\\(\\s*([^)]+)\\s*\\)/g;\n\n const controllerFiles = allFiles.filter((f) => f.framework_role === 'nest_controller');\n\n for (const file of controllerFiles) {\n const source = readSource(rootPath, file.path);\n if (!source) continue;\n\n const extractDecorators = (regex: RegExp, scope: MiddlewareEntry['scope']) => {\n const re = new RegExp(regex.source, 'g');\n let m: RegExpExecArray | null;\n while ((m = re.exec(source)) !== null) {\n const items = m[1].split(',').map((s) => s.trim()).filter(Boolean);\n for (const item of items) {\n chain.push({ name: item, scope, file: file.path });\n }\n }\n };\n\n extractDecorators(GUARDS_RE, 'guard');\n extractDecorators(PIPES_RE, 'pipe');\n extractDecorators(INTERCEPTORS_RE, 'interceptor');\n extractDecorators(FILTERS_RE, 'filter');\n }\n}\n\n// ─── Flask ────────────────────────────────────────────────────\n\nfunction buildFlaskChain(\n store: Store,\n rootPath: string,\n url: string,\n allFiles: FileInfo[],\n chain: MiddlewareEntry[],\n): void {\n // Leverage existing flask_before_request and flask_error_handler edges\n const beforeEdges = store.getEdgesByType('flask_before_request');\n for (const edge of beforeEdges) {\n const ref = store.getNodeRef(edge.source_node_id);\n if (!ref) continue;\n let filePath = '';\n let name = 'before_request';\n if (ref.nodeType === 'symbol') {\n const sym = store.getSymbolById(ref.refId);\n if (sym) {\n name = sym.name;\n const f = store.getFileById(sym.file_id);\n filePath = f?.path ?? '';\n }\n }\n chain.push({ name, scope: 'before_request', file: filePath });\n }\n\n const errorEdges = store.getEdgesByType('flask_error_handler');\n for (const edge of errorEdges) {\n const ref = store.getNodeRef(edge.source_node_id);\n if (!ref) continue;\n let name = 'error_handler';\n let filePath = '';\n if (ref.nodeType === 'symbol') {\n const sym = store.getSymbolById(ref.refId);\n if (sym) {\n name = sym.name;\n const f = store.getFileById(sym.file_id);\n filePath = f?.path ?? '';\n }\n }\n chain.push({ name, scope: 'error_handler', file: filePath });\n }\n\n // Also scan for route-level decorators in matching route files\n for (const file of allFiles) {\n if (file.framework_role !== 'flask_routes') continue;\n const source = readSource(rootPath, file.path);\n if (!source) continue;\n\n // @login_required, @auth.login_required etc. before route handlers\n const decoratorRe = /@([\\w.]+)\\s*(?:\\([^)]*\\))?\\s*\\n\\s*(?:@\\w[\\w.]*\\s*(?:\\([^)]*\\))?\\s*\\n\\s*)*def\\s+\\w+/g;\n let m: RegExpExecArray | null;\n while ((m = decoratorRe.exec(source)) !== null) {\n const dec = m[1];\n if (['app.route', 'bp.route', 'blueprint.route'].some((r) => dec.includes(r))) continue;\n if (dec.includes('route')) continue;\n chain.push({ name: `@${dec}`, scope: 'view_decorator', file: file.path });\n }\n }\n}\n\n// ─── FastAPI ──────────────────────────────────────────────────\n\nfunction buildFastAPIChain(\n store: Store,\n rootPath: string,\n url: string,\n allFiles: FileInfo[],\n chain: MiddlewareEntry[],\n): void {\n // Scan for app.add_middleware() calls\n for (const file of allFiles) {\n if (file.framework_role !== 'fastapi_routes' && file.framework_role !== 'fastapi_app') continue;\n const source = readSource(rootPath, file.path);\n if (!source) continue;\n\n // app.add_middleware(CORSMiddleware, ...) or app.add_middleware(Middleware)\n const addMwRe = /(?:app|router)\\s*\\.\\s*add_middleware\\s*\\(\\s*([\\w.]+)/g;\n let m: RegExpExecArray | null;\n while ((m = addMwRe.exec(source)) !== null) {\n chain.push({ name: m[1], scope: 'middleware', file: file.path });\n }\n }\n\n // Leverage fastapi_depends edges for route-level dependency chain\n const dependsEdges = store.getEdgesByType('fastapi_depends');\n for (const edge of dependsEdges) {\n const ref = store.getNodeRef(edge.source_node_id);\n if (!ref) continue;\n let name = 'Depends';\n let filePath = '';\n if (ref.nodeType === 'symbol') {\n const sym = store.getSymbolById(ref.refId);\n if (sym) {\n name = sym.name;\n const f = store.getFileById(sym.file_id);\n filePath = f?.path ?? '';\n }\n }\n chain.push({ name, scope: 'depends', file: filePath });\n }\n}\n\n// ─── Django ───────────────────────────────────────────────────\n\nfunction buildDjangoChain(\n store: Store,\n rootPath: string,\n allFiles: FileInfo[],\n chain: MiddlewareEntry[],\n): void {\n // 1. settings.py MIDDLEWARE list\n for (const file of allFiles) {\n if (!file.path.endsWith('settings.py') && !file.path.includes('settings/')) continue;\n const source = readSource(rootPath, file.path);\n if (!source) continue;\n\n // MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', ... ]\n const mwMatch = source.match(/MIDDLEWARE\\s*=\\s*\\[([\\s\\S]*?)\\]/);\n if (!mwMatch) continue;\n\n const items = mwMatch[1].match(/['\"]([^'\"]+)['\"]/g);\n if (items) {\n for (const item of items) {\n const name = item.replace(/['\"]/g, '');\n chain.push({ name, scope: 'global', file: file.path });\n }\n }\n }\n\n // 2. View-level decorators (@login_required, @permission_required, etc.)\n for (const file of allFiles) {\n if (file.framework_role !== 'view') continue;\n const source = readSource(rootPath, file.path);\n if (!source) continue;\n\n const decoratorRe = /@([\\w.]+)\\s*(?:\\([^)]*\\))?\\s*\\n\\s*(?:@\\w[\\w.]*\\s*(?:\\([^)]*\\))?\\s*\\n\\s*)*(?:def|class)\\s+\\w+/g;\n let m: RegExpExecArray | null;\n while ((m = decoratorRe.exec(source)) !== null) {\n const dec = m[1];\n // Skip routing decorators\n if (dec.includes('route') || dec.includes('api_view')) continue;\n chain.push({ name: `@${dec}`, scope: 'view_decorator', file: file.path });\n }\n }\n}\n","/**\n * get_module_graph — NestJS module dependency graph.\n *\n * Traces: module -> imports -> controllers -> providers -> exports.\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport type { Store } from '../db/store.js';\nimport { ok, err, type TraceMcpResult } from '../errors.js';\nimport { notFound } from '../errors.js';\nimport { extractModuleInfo } from '../indexer/plugins/framework/nestjs/index.js';\n\nexport interface ModuleGraphNode {\n name: string;\n file?: string;\n imports: string[];\n controllers: string[];\n providers: string[];\n exports: string[];\n}\n\nexport interface ModuleGraphResult {\n rootModule: string;\n modules: ModuleGraphNode[];\n}\n\n/**\n * Build module dependency graph starting from a named NestJS module.\n */\nexport function getModuleGraph(\n store: Store,\n rootPath: string,\n moduleName: string,\n): TraceMcpResult<ModuleGraphResult> {\n const allFiles = store.getAllFiles();\n const moduleFiles = allFiles.filter((f) => f.framework_role === 'nest_module');\n\n if (moduleFiles.length === 0) {\n return err(notFound(moduleName, ['No NestJS modules found. Run reindex first.']));\n }\n\n // Build map of module name -> info\n const moduleMap = new Map<string, ModuleGraphNode>();\n\n for (const file of moduleFiles) {\n let source: string;\n try {\n source = fs.readFileSync(path.resolve(rootPath, file.path), 'utf-8');\n } catch { continue; }\n\n const info = extractModuleInfo(source);\n if (!info) continue;\n\n // Extract class name from file\n const classMatch = source.match(/export\\s+class\\s+(\\w+)/);\n const name = classMatch?.[1] ?? path.basename(file.path, path.extname(file.path));\n\n moduleMap.set(name, {\n name,\n file: file.path,\n imports: info.imports,\n controllers: info.controllers,\n providers: info.providers,\n exports: info.exports,\n });\n }\n\n // Find root module\n const rootModule = moduleMap.get(moduleName);\n if (!rootModule) {\n const available = [...moduleMap.keys()];\n return err(notFound(moduleName, available.length > 0\n ? [`Available modules: ${available.join(', ')}`]\n : ['No NestJS modules found']));\n }\n\n // BFS to collect reachable modules\n const visited = new Set<string>();\n const queue = [moduleName];\n const result: ModuleGraphNode[] = [];\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n if (visited.has(current)) continue;\n visited.add(current);\n\n const mod = moduleMap.get(current);\n if (!mod) continue;\n\n result.push(mod);\n\n for (const imp of mod.imports) {\n if (!visited.has(imp)) {\n queue.push(imp);\n }\n }\n }\n\n return ok({ rootModule: moduleName, modules: result });\n}\n","/**\n * NestJSPlugin — detects NestJS projects and extracts modules, controllers,\n * routes, providers, and dependency injection edges.\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { ok, type TraceMcpResult } from '../../../../errors.js';\nimport { escapeRegExp } from '../../../../utils/security.js';\nimport type {\n FrameworkPlugin,\n PluginManifest,\n ProjectContext,\n FileParseResult,\n RawEdge,\n RawRoute,\n ResolveContext,\n} from '../../../../plugin-api/types.js';\n\nconst HTTP_METHODS = ['Get', 'Post', 'Put', 'Delete', 'Patch', 'Head', 'Options'] as const;\nconst CONTROLLER_RE = /@Controller\\(\\s*['\"`]([^'\"`]*)['\"`]\\s*\\)/;\nconst METHOD_DECORATOR_RE = (method: string) =>\n new RegExp(`@${escapeRegExp(method)}\\\\(\\\\s*(?:['\"\\`]([^'\"\\`]*)['\"\\`])?\\\\s*\\\\)`, 'g');\nconst MODULE_RE = /@Module\\(\\s*\\{([^}]*(?:\\{[^}]*\\}[^}]*)*)\\}\\s*\\)/s;\nconst INJECTABLE_RE = /@Injectable\\(\\)/;\nconst USE_GUARDS_RE = /@UseGuards\\(\\s*([^)]+)\\s*\\)/g;\nconst USE_PIPES_RE = /@UsePipes\\(\\s*([^)]+)\\s*\\)/g;\nconst USE_INTERCEPTORS_RE = /@UseInterceptors\\(\\s*([^)]+)\\s*\\)/g;\nconst CONSTRUCTOR_RE = /constructor\\s*\\(([^)]*)\\)/s;\nconst GATEWAY_RE = /@WebSocketGateway\\s*\\(/;\nconst SUBSCRIBE_RE = /@SubscribeMessage\\s*\\(\\s*['\"`]([^'\"`]+)['\"`]\\s*\\)/g;\nconst EVENT_PATTERN_RE = /@EventPattern\\s*\\(\\s*['\"`]([^'\"`]+)['\"`]\\s*\\)/g;\nconst MICROSERVICE_RE = /@(MessagePattern|EventPattern)\\s*\\(/;\n\n/** Extract array items from a module decorator property like `imports: [A, B]`. */\nfunction extractModuleArray(body: string, prop: string): string[] {\n const re = new RegExp(`${escapeRegExp(prop)}\\\\s*:\\\\s*\\\\[([^\\\\]]*?)\\\\]`, 's');\n const m = body.match(re);\n if (!m) return [];\n return m[1]\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n}\n\n/** Extract constructor parameter types for DI. */\nexport function extractConstructorDeps(source: string): string[] {\n const m = source.match(CONSTRUCTOR_RE);\n if (!m) return [];\n const params = m[1];\n const deps: string[] = [];\n // Match patterns like: private userService: UserService\n const paramRe = /(?:private|protected|public|readonly)\\s+\\w+\\s*:\\s*(\\w+)/g;\n let match: RegExpExecArray | null;\n while ((match = paramRe.exec(params)) !== null) {\n deps.push(match[1]);\n }\n return deps;\n}\n\n/** Extract route info from a controller file. */\nexport function extractControllerRoutes(\n source: string,\n filePath: string,\n): { basePath: string; routes: RawRoute[]; guards: string[] } {\n const controllerMatch = source.match(CONTROLLER_RE);\n const basePath = controllerMatch ? controllerMatch[1] : '';\n const routes: RawRoute[] = [];\n const guards: string[] = [];\n\n // Extract class-level guards\n const classGuardMatch = source.match(USE_GUARDS_RE);\n if (classGuardMatch) {\n for (const gm of classGuardMatch) {\n const inner = gm.match(/@UseGuards\\(\\s*([^)]+)\\s*\\)/);\n if (inner) {\n guards.push(\n ...inner[1].split(',').map((s) => s.trim()).filter(Boolean),\n );\n }\n }\n }\n\n for (const method of HTTP_METHODS) {\n const re = METHOD_DECORATOR_RE(method);\n let match: RegExpExecArray | null;\n while ((match = re.exec(source)) !== null) {\n const methodPath = match[1] ?? '';\n const segments = [basePath, methodPath].filter(Boolean);\n const uri = '/' + segments.join('/').replace(/\\/+/g, '/').replace(/^\\//, '');\n routes.push({\n method: method.toUpperCase(),\n uri: uri || '/',\n });\n }\n }\n\n return { basePath, routes, guards };\n}\n\nexport function extractGatewayEvents(source: string): string[] {\n const events: string[] = [];\n const re = new RegExp(SUBSCRIBE_RE.source, 'g');\n let m: RegExpExecArray | null;\n while ((m = re.exec(source)) !== null) {\n if (m[1]) events.push(m[1]);\n }\n return events;\n}\n\nexport function extractMicroservicePatterns(source: string): { type: 'message' | 'event'; pattern: string }[] {\n const results: { type: 'message' | 'event'; pattern: string }[] = [];\n const eventRe = new RegExp(EVENT_PATTERN_RE.source, 'g');\n let m: RegExpExecArray | null;\n while ((m = eventRe.exec(source)) !== null) {\n if (m[1]) results.push({ type: 'event', pattern: m[1] });\n }\n // @MessagePattern('cmd') or @MessagePattern({ cmd: 'sum' })\n const msgStr = /@MessagePattern\\s*\\(\\s*['\"`]([^'\"`]+)['\"`]\\s*\\)/g;\n while ((m = msgStr.exec(source)) !== null) {\n if (m[1]) results.push({ type: 'message', pattern: m[1] });\n }\n const msgObj = /@MessagePattern\\s*\\(\\s*\\{[^}]*cmd\\s*:\\s*['\"`]([^'\"`]+)['\"`]/g;\n while ((m = msgObj.exec(source)) !== null) {\n if (m[1]) results.push({ type: 'message', pattern: m[1] });\n }\n return results;\n}\n\n/** Extract module metadata. */\nexport function extractModuleInfo(source: string): {\n imports: string[];\n controllers: string[];\n providers: string[];\n exports: string[];\n} | null {\n const m = source.match(MODULE_RE);\n if (!m) return null;\n const body = m[1];\n return {\n imports: extractModuleArray(body, 'imports'),\n controllers: extractModuleArray(body, 'controllers'),\n providers: extractModuleArray(body, 'providers'),\n exports: extractModuleArray(body, 'exports'),\n };\n}\n\nexport class NestJSPlugin implements FrameworkPlugin {\n manifest: PluginManifest = {\n name: 'nestjs',\n version: '1.0.0',\n priority: 25,\n dependencies: [],\n };\n\n detect(ctx: ProjectContext): boolean {\n if (ctx.packageJson) {\n const deps = {\n ...(ctx.packageJson.dependencies as Record<string, string> | undefined),\n ...(ctx.packageJson.devDependencies as Record<string, string> | undefined),\n };\n if ('@nestjs/core' in deps) return true;\n }\n\n try {\n const pkgPath = path.join(ctx.rootPath, 'package.json');\n const content = fs.readFileSync(pkgPath, 'utf-8');\n const pkg = JSON.parse(content);\n const deps = {\n ...(pkg.dependencies as Record<string, string> | undefined),\n ...(pkg.devDependencies as Record<string, string> | undefined),\n };\n return '@nestjs/core' in deps;\n } catch {\n return false;\n }\n }\n\n registerSchema() {\n return {\n edgeTypes: [\n { name: 'nest_module_imports', category: 'nestjs', description: 'Module imports another module' },\n { name: 'nest_provides', category: 'nestjs', description: 'Module provides a service' },\n { name: 'nest_injects', category: 'nestjs', description: 'Constructor dependency injection' },\n { name: 'nest_guards', category: 'nestjs', description: 'UseGuards on controller/method' },\n { name: 'nest_pipes', category: 'nestjs', description: 'UsePipes on controller/method' },\n { name: 'nest_interceptors', category: 'nestjs', description: 'UseInterceptors on controller/method' },\n { name: 'nest_gateway_event', category: 'nestjs', description: 'WebSocket gateway @SubscribeMessage handler' },\n { name: 'nest_message_pattern', category: 'nestjs', description: 'Microservice @MessagePattern handler' },\n { name: 'nest_event_pattern', category: 'nestjs', description: 'Microservice @EventPattern handler' },\n ],\n };\n }\n\n extractNodes(\n filePath: string,\n content: Buffer,\n language: string,\n ): TraceMcpResult<FileParseResult> {\n if (language !== 'typescript') {\n return ok({ status: 'ok', symbols: [] });\n }\n\n const source = content.toString('utf-8');\n const result: FileParseResult = { status: 'ok', symbols: [], routes: [], edges: [] };\n\n // Controller with routes\n if (source.includes('@Controller')) {\n const { routes } = extractControllerRoutes(source, filePath);\n result.routes = routes;\n result.frameworkRole = 'nest_controller';\n }\n\n // Module\n if (source.includes('@Module')) {\n const moduleInfo = extractModuleInfo(source);\n if (moduleInfo) {\n result.frameworkRole = 'nest_module';\n }\n }\n\n // Injectable\n if (INJECTABLE_RE.test(source)) {\n result.frameworkRole = result.frameworkRole ?? 'nest_injectable';\n }\n\n // WebSocket Gateway\n if (GATEWAY_RE.test(source)) {\n result.frameworkRole = 'nest_gateway';\n const events = extractGatewayEvents(source);\n if (events.length > 0) {\n result.warnings = result.warnings ?? [];\n // store gateway events in metadata via a synthetic warning-free mechanism\n // Use routes as gateway event placeholders\n if (!result.routes) result.routes = [];\n for (const evt of events) {\n result.routes.push({ method: 'WS', uri: evt });\n }\n }\n }\n\n // Microservice handlers\n if (MICROSERVICE_RE.test(source)) {\n result.frameworkRole = result.frameworkRole ?? 'nest_microservice';\n const patterns = extractMicroservicePatterns(source);\n if (patterns.length > 0) {\n if (!result.routes) result.routes = [];\n for (const p of patterns) {\n result.routes.push({ method: p.type === 'message' ? 'MSG' : 'EVT', uri: p.pattern });\n }\n }\n }\n\n return ok(result);\n }\n\n resolveEdges(ctx: ResolveContext): TraceMcpResult<RawEdge[]> {\n const edges: RawEdge[] = [];\n const allFiles = ctx.getAllFiles();\n\n // TypeScript symbols don't carry PHP-style FQNs, so build a class-name → symbol\n // map as a fallback for DI/module resolution.\n const classSymbolByName = new Map<string, { id: number }>();\n for (const file of allFiles) {\n if (file.language !== 'typescript') continue;\n for (const sym of ctx.getSymbolsByFile(file.id)) {\n if (sym.kind === 'class') {\n classSymbolByName.set(sym.name, { id: sym.id });\n }\n }\n }\n\n /** Try FQN first (PHP-style), fall back to plain class name (TypeScript). */\n const resolve = (name: string) =>\n ctx.getSymbolByFqn(name) ?? classSymbolByName.get(name);\n\n for (const file of allFiles) {\n if (file.language !== 'typescript') continue;\n\n const source = ctx.readFile(file.path);\n if (!source) continue;\n\n // Module edges\n const moduleInfo = extractModuleInfo(source);\n if (moduleInfo) {\n const symbols = ctx.getSymbolsByFile(file.id);\n const moduleClass = symbols.find((s) => s.kind === 'class');\n if (moduleClass) {\n // imports\n for (const imp of moduleInfo.imports) {\n const target = resolve(imp);\n if (target) {\n edges.push({\n sourceNodeType: 'symbol',\n sourceRefId: moduleClass.id,\n targetNodeType: 'symbol',\n targetRefId: target.id,\n edgeType: 'nest_module_imports',\n });\n }\n }\n // providers\n for (const prov of moduleInfo.providers) {\n const target = resolve(prov);\n if (target) {\n edges.push({\n sourceNodeType: 'symbol',\n sourceRefId: moduleClass.id,\n targetNodeType: 'symbol',\n targetRefId: target.id,\n edgeType: 'nest_provides',\n });\n }\n }\n }\n }\n\n // Constructor injection edges\n const deps = extractConstructorDeps(source);\n if (deps.length > 0) {\n const symbols = ctx.getSymbolsByFile(file.id);\n const cls = symbols.find((s) => s.kind === 'class');\n if (cls) {\n for (const dep of deps) {\n const target = resolve(dep);\n if (target) {\n edges.push({\n sourceNodeType: 'symbol',\n sourceRefId: cls.id,\n targetNodeType: 'symbol',\n targetRefId: target.id,\n edgeType: 'nest_injects',\n metadata: { dependency: dep },\n });\n }\n }\n }\n }\n }\n\n return ok(edges);\n }\n}\n","/**\n * get_di_tree — NestJS dependency injection tree.\n *\n * Traces: service -> what it injects -> who injects it.\n */\nimport type { Store } from '../db/store.js';\nimport { ok, err, type TraceMcpResult } from '../errors.js';\nimport { notFound } from '../errors.js';\n\nexport interface DINode {\n name: string;\n symbolId?: string;\n file?: string;\n}\n\nexport interface DITreeResult {\n service: DINode;\n injects: DINode[]; // what this service depends on\n injectedBy: DINode[]; // what depends on this service\n}\n\n/**\n * Build a DI tree for a NestJS service.\n * Uses nest_injects edges from the graph.\n */\nexport function getDITree(\n store: Store,\n serviceName: string,\n): TraceMcpResult<DITreeResult> {\n // Find the service symbol by name or FQN\n const symbol = store.getSymbolByFqn(serviceName)\n ?? findSymbolByName(store, serviceName);\n\n if (!symbol) {\n return err(notFound(serviceName, ['Service not found. Try using the full class name.']));\n }\n\n const file = store.getFileById(symbol.file_id);\n const service: DINode = {\n name: symbol.name,\n symbolId: symbol.symbol_id,\n file: file?.path,\n };\n\n const nodeId = store.getNodeId('symbol', symbol.id);\n if (nodeId == null) {\n return ok({ service, injects: [], injectedBy: [] });\n }\n\n // What this service injects (outgoing nest_injects edges)\n const outEdges = store.getOutgoingEdges(nodeId);\n const injects: DINode[] = [];\n\n for (const edge of outEdges) {\n if (edge.edge_type_name !== 'nest_injects') continue;\n const targetRef = store.getNodeByNodeId(edge.target_node_id);\n if (!targetRef || targetRef.node_type !== 'symbol') continue;\n\n const targetSym = store.getSymbolById(targetRef.ref_id);\n if (!targetSym) continue;\n\n const targetFile = store.getFileById(targetSym.file_id);\n injects.push({\n name: targetSym.name,\n symbolId: targetSym.symbol_id,\n file: targetFile?.path,\n });\n }\n\n // Who injects this service (incoming nest_injects edges)\n const inEdges = store.getIncomingEdges(nodeId);\n const injectedBy: DINode[] = [];\n\n for (const edge of inEdges) {\n if (edge.edge_type_name !== 'nest_injects') continue;\n const sourceRef = store.getNodeByNodeId(edge.source_node_id);\n if (!sourceRef || sourceRef.node_type !== 'symbol') continue;\n\n const sourceSym = store.getSymbolById(sourceRef.ref_id);\n if (!sourceSym) continue;\n\n const sourceFile = store.getFileById(sourceSym.file_id);\n injectedBy.push({\n name: sourceSym.name,\n symbolId: sourceSym.symbol_id,\n file: sourceFile?.path,\n });\n }\n\n return ok({ service, injects, injectedBy });\n}\n\nfunction findSymbolByName(\n store: Store,\n name: string,\n): ReturnType<Store['getSymbolByFqn']> {\n return store.getSymbolByName(name, 'class');\n}\n","/**\n * get_navigation_graph — React Native navigation tree.\n *\n * Builds full navigation tree from RN screens + navigators.\n */\nimport type { Store, RnScreenRow } from '../db/store.js';\nimport { ok, type TraceMcpResult } from '../errors.js';\n\nexport interface NavigationNode {\n screen: string;\n component?: string;\n navigatorType?: string;\n deepLink?: string;\n navigatesTo: string[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface NavigationGraphResult {\n screens: NavigationNode[];\n navigatorTypes: string[];\n deepLinks: { screen: string; path: string }[];\n totalScreens: number;\n}\n\n/**\n * Build navigation graph from all indexed RN screens.\n */\nexport function getNavigationGraph(\n store: Store,\n): TraceMcpResult<NavigationGraphResult> {\n const allScreens = store.getAllRnScreens();\n\n // Build edges from edges table (rn_navigates_to)\n const navigatesMap = buildNavigatesMap(store, allScreens);\n\n const screens: NavigationNode[] = allScreens.map((s) => ({\n screen: s.name,\n component: s.component_path ?? undefined,\n navigatorType: s.navigator_type ?? undefined,\n deepLink: s.deep_link ?? undefined,\n navigatesTo: navigatesMap.get(s.name) ?? [],\n metadata: s.metadata ? JSON.parse(s.metadata) : undefined,\n }));\n\n const navigatorTypes = [\n ...new Set(allScreens.map((s) => s.navigator_type).filter(Boolean) as string[]),\n ];\n\n const deepLinks = allScreens\n .filter((s) => s.deep_link)\n .map((s) => ({ screen: s.name, path: s.deep_link! }));\n\n return ok({\n screens,\n navigatorTypes,\n deepLinks,\n totalScreens: allScreens.length,\n });\n}\n\n/**\n * Build a map of screen -> screens it navigates to,\n * using rn_navigates_to edges from the graph.\n */\nfunction buildNavigatesMap(\n store: Store,\n allScreens: RnScreenRow[],\n): Map<string, string[]> {\n const map = new Map<string, string[]>();\n\n // Pre-build nodeId → screenName lookup in one batch query (avoids O(edges*screens) N+1)\n const screenIds = allScreens.map((s) => s.id);\n const nodeIdMap = store.getNodeIdsBatch('rn_screen', screenIds);\n const nodeToScreen = new Map<number, string>();\n for (const screen of allScreens) {\n const nodeId = nodeIdMap.get(screen.id);\n if (nodeId !== undefined) nodeToScreen.set(nodeId, screen.name);\n }\n\n const navEdges = store.getEdgesByType('rn_navigates_to');\n for (const edge of navEdges) {\n const sourceName = nodeToScreen.get(edge.source_node_id);\n const targetName = nodeToScreen.get(edge.target_node_id);\n\n if (sourceName && targetName) {\n const existing = map.get(sourceName) ?? [];\n existing.push(targetName);\n map.set(sourceName, existing);\n }\n }\n\n return map;\n}\n","/**\n * get_screen_context tool — full context for a React Native screen.\n * Returns component info, navigator, navigation edges, deep link, platform variants.\n */\nimport type { Store, RnScreenRow } from '../db/store.js';\nimport { ok, err, type TraceMcpResult } from '../errors.js';\nimport { notFound } from '../errors.js';\n\nexport interface ScreenContextResult {\n screen: string;\n component: string | undefined;\n filePath: string | undefined;\n navigatorType: string | undefined;\n navigatedFrom: string[];\n navigatesTo: string[];\n deepLink: string | undefined;\n platformSpecific: Record<string, string>;\n nativeModulesUsed: string[];\n params: Record<string, unknown> | undefined;\n}\n\nexport function getScreenContext(\n store: Store,\n screenName: string,\n): TraceMcpResult<ScreenContextResult> {\n let screen = store.getRnScreenByName(screenName);\n\n if (!screen) {\n // Try case-insensitive partial match\n const all = store.getAllRnScreens();\n screen = all.find((s) =>\n s.name.toLowerCase().includes(screenName.toLowerCase()),\n );\n }\n\n if (!screen) {\n return err(notFound(`screen:${screenName}`));\n }\n\n return ok(buildContext(store, screen));\n}\n\nfunction buildContext(store: Store, screen: RnScreenRow): ScreenContextResult {\n const metadata = screen.metadata ? JSON.parse(screen.metadata) : {};\n\n // Find screens that navigate TO this screen (incoming rn_navigates_to edges)\n const allScreens = store.getAllRnScreens();\n const navigatedFrom: string[] = [];\n const navigatesTo: string[] = [];\n\n for (const other of allScreens) {\n if (other.id === screen.id) continue;\n const otherMeta = other.metadata ? JSON.parse(other.metadata) : {};\n const calls: string[] = otherMeta.navigationCalls ?? [];\n if (calls.includes(screen.name)) {\n navigatedFrom.push(other.name);\n }\n }\n\n // Find screens this screen navigates to (from its metadata.navigationCalls)\n const myCalls: string[] = metadata.navigationCalls ?? [];\n for (const target of myCalls) {\n const found = allScreens.find(\n (s) => s.name === target || s.component_path?.includes(target),\n );\n if (found) navigatesTo.push(found.name);\n else navigatesTo.push(target);\n }\n\n // Platform-specific variants from metadata\n const platformSpecific: Record<string, string> = metadata.platformSpecific ?? {};\n\n // Native modules from metadata\n const nativeModulesUsed: string[] = metadata.nativeModules ?? [];\n\n // File path from file_id\n let filePath: string | undefined;\n const file = store.getFileById(screen.file_id);\n if (file) filePath = file.path;\n\n // Params from options JSON\n let params: Record<string, unknown> | undefined;\n if (screen.options) {\n try {\n const opts = JSON.parse(screen.options);\n if (opts.params) params = opts.params;\n } catch {\n // ignore\n }\n }\n\n return {\n screen: screen.name,\n component: screen.component_path ?? undefined,\n filePath,\n navigatorType: screen.navigator_type ?? undefined,\n navigatedFrom,\n navigatesTo,\n deepLink: screen.deep_link ?? undefined,\n platformSpecific,\n nativeModulesUsed,\n params,\n };\n}\n","/**\n * get_request_flow tool — traces a request from URL to full handler chain.\n * URL -> Route -> Middleware -> Controller -> FormRequest -> Model\n */\nimport type { Store, RouteRow } from '../db/store.js';\nimport { ok, err, type TraceMcpResult } from '../errors.js';\nimport { notFound } from '../errors.js';\n\nexport interface RequestFlowStep {\n type: 'route' | 'middleware' | 'controller' | 'form_request' | 'model' | 'inertia_page';\n name: string;\n symbolId?: string;\n fqn?: string;\n details?: Record<string, unknown>;\n}\n\nexport interface RequestFlowResult {\n url: string;\n method: string;\n steps: RequestFlowStep[];\n _meta?: { warnings: string[] };\n}\n\nexport function getRequestFlow(\n store: Store,\n url: string,\n method: string,\n): TraceMcpResult<RequestFlowResult> {\n const normalizedMethod = method.toUpperCase();\n const steps: RequestFlowStep[] = [];\n const warnings: string[] = [];\n\n // 1. Find matching route\n const route = store.findRouteByPattern(url, normalizedMethod);\n if (!route) {\n return err(notFound(`route:${normalizedMethod} ${url}`));\n }\n\n steps.push({\n type: 'route',\n name: route.name ?? `${route.method} ${route.uri}`,\n details: {\n method: route.method,\n uri: route.uri,\n routeName: route.name,\n },\n });\n\n // 2. Parse middleware JSON and controller ref\n const { middleware, controllerRef } = parseRouteMiddleware(route);\n\n for (const m of middleware) {\n steps.push({ type: 'middleware', name: m });\n }\n\n // 3. Controller method\n const effectiveControllerRef = controllerRef ?? route.controller_symbol_id;\n if (effectiveControllerRef) {\n const ref = String(effectiveControllerRef);\n const [controllerFqn, actionName] = splitControllerRef(ref);\n\n const controllerSymbol = store.getSymbolByFqn(controllerFqn);\n const methodFqn = actionName ? `${controllerFqn}::${actionName}` : undefined;\n const methodSymbol = methodFqn ? store.getSymbolByFqn(methodFqn) : undefined;\n\n steps.push({\n type: 'controller',\n name: actionName ? `${controllerFqn}@${actionName}` : controllerFqn,\n symbolId: methodSymbol?.symbol_id ?? controllerSymbol?.symbol_id,\n fqn: methodFqn ?? controllerFqn,\n details: { action: actionName },\n });\n\n // 4. FormRequest — find validates_with edges from controller method\n // 5. Inertia — find inertia_renders edges from controller method OR class\n // Edges may be on the method or on the class symbol, so check both\n const symbolsToCheck = [methodSymbol, controllerSymbol].filter(Boolean) as typeof controllerSymbol[];\n const seenEdgeTypes = new Set<string>();\n\n for (const sym of symbolsToCheck) {\n if (!sym) continue;\n const nodeId = store.getNodeId('symbol', sym.id);\n if (!nodeId) continue;\n\n const outEdges = store.getOutgoingEdges(nodeId);\n for (const edge of outEdges) {\n if (edge.edge_type_name === 'validates_with' && !seenEdgeTypes.has('validates_with')) {\n const targetNode = store.getNodeByNodeId(edge.target_node_id);\n if (targetNode && targetNode.node_type === 'symbol') {\n const targetSym = store.getSymbolById(targetNode.ref_id);\n if (targetSym) {\n seenEdgeTypes.add('validates_with');\n steps.push({\n type: 'form_request',\n name: targetSym.fqn ?? targetSym.name,\n symbolId: targetSym.symbol_id,\n fqn: targetSym.fqn ?? undefined,\n });\n }\n }\n }\n\n if (edge.edge_type_name === 'inertia_renders') {\n const targetNode = store.getNodeByNodeId(edge.target_node_id);\n if (targetNode && targetNode.node_type === 'symbol') {\n const targetSym = store.getSymbolById(targetNode.ref_id);\n if (targetSym) {\n const meta = edge.metadata ? JSON.parse(edge.metadata) as Record<string, unknown> : {};\n const file = store.getFileById(targetSym.file_id);\n // Only include Inertia pages that are NOT already in steps\n const alreadyAdded = steps.some(\n (s) => s.type === 'inertia_page' && s.details?.pageName === meta.pageName,\n );\n if (!alreadyAdded) {\n steps.push({\n type: 'inertia_page',\n name: targetSym.name,\n symbolId: targetSym.symbol_id,\n details: {\n pageName: meta.pageName,\n propNames: meta.propNames,\n filePath: file?.path,\n },\n });\n }\n }\n }\n }\n }\n }\n }\n\n const result: RequestFlowResult = { url, method: normalizedMethod, steps };\n if (warnings.length > 0) {\n result._meta = { warnings };\n }\n return ok(result);\n}\n\n/** Parse the middleware JSON which may contain { middleware: [...], controllerRef: \"...\" }. */\nfunction parseRouteMiddleware(route: RouteRow): {\n middleware: string[];\n controllerRef: string | null;\n} {\n if (!route.middleware) return { middleware: [], controllerRef: null };\n\n try {\n const parsed = JSON.parse(route.middleware);\n if (Array.isArray(parsed)) {\n return { middleware: parsed, controllerRef: null };\n }\n if (typeof parsed === 'object' && parsed !== null) {\n return {\n middleware: Array.isArray(parsed.middleware) ? parsed.middleware : [],\n controllerRef: parsed.controllerRef ?? null,\n };\n }\n } catch {\n // not JSON\n }\n return { middleware: [], controllerRef: null };\n}\n\nfunction splitControllerRef(ref: string): [string, string | undefined] {\n // \"App\\Http\\Controllers\\UserController::store\"\n const lastSep = ref.lastIndexOf('::');\n if (lastSep > 0) {\n return [ref.substring(0, lastSep), ref.substring(lastSep + 2)];\n }\n return [ref, undefined];\n}\n","/**\n * get_model_context tool — assembles full context for an Eloquent, Mongoose, or Sequelize model.\n * Returns model symbol + relationships + schema + related controllers/requests.\n */\nimport type { Store, SymbolRow, OrmModelRow, OrmAssociationRow } from '../db/store.js';\nimport { ok, err, type TraceMcpResult } from '../errors.js';\nimport { notFound } from '../errors.js';\n\nexport interface ModelRelationship {\n type: string; // edge type name: has_many, belongs_to, etc.\n relatedModel: string;\n relatedSymbolId?: string;\n method?: string;\n}\n\nexport interface ModelSchema {\n tableName: string;\n columns: Record<string, unknown>[];\n operation: string;\n timestamp?: string;\n}\n\nexport interface EcosystemRef {\n name: string;\n fqn?: string;\n symbolId?: string;\n}\n\nexport interface ModelContextResult {\n model: {\n name: string;\n fqn: string;\n symbolId: string;\n filePath: string;\n orm?: string;\n collection?: string;\n };\n relationships: ModelRelationship[];\n schema: ModelSchema[];\n relatedControllers: { name: string; symbolId: string; fqn: string | null }[];\n relatedRequests: { name: string; symbolId: string; fqn: string | null }[];\n ormMetadata?: Record<string, unknown>;\n /** Nova resource referencing this model */\n nova?: { resource: EcosystemRef; actions: string[]; filters: string[]; lenses: string[]; metrics: string[] };\n /** Filament resource referencing this model */\n filament?: { resource: EcosystemRef; relationManagers: string[]; pages: string[]; widgets: string[] };\n /** Livewire components using this model */\n livewireComponents?: EcosystemRef[];\n /** Data classes (DTOs) wrapping this model */\n dataClasses?: EcosystemRef[];\n}\n\nexport function getModelContext(\n store: Store,\n modelName: string,\n): TraceMcpResult<ModelContextResult> {\n // --- Try Mongoose / Sequelize ORM models first ---\n const ormModel = store.getOrmModelByName(modelName);\n if (ormModel) {\n return buildOrmModelContext(store, ormModel);\n }\n\n // --- Fall back to Eloquent (symbol-based) ---\n let modelSymbol: SymbolRow | undefined;\n\n modelSymbol = store.getSymbolByFqn(modelName);\n if (!modelSymbol) {\n modelSymbol = store.getSymbolByFqn(`App\\\\Models\\\\${modelName}`);\n }\n if (!modelSymbol) {\n const allSymbols = store.db.prepare(\n \"SELECT * FROM symbols WHERE name = ? AND kind = 'class'\",\n ).all(modelName) as SymbolRow[];\n modelSymbol = allSymbols[0];\n }\n\n if (!modelSymbol) {\n return err(notFound(`model:${modelName}`));\n }\n\n const file = store.getFileById(modelSymbol.file_id);\n if (!file) {\n return err(notFound(`file for model:${modelName}`));\n }\n\n const relationships = getRelationships(store, modelSymbol);\n const schema = getModelSchema(store, modelName);\n const relatedControllers = getRelatedByRole(store, modelSymbol, 'controller');\n const relatedRequests = getRelatedByRole(store, modelSymbol, 'form_request');\n\n // Ecosystem: find Nova/Filament/Livewire/Data referencing this model\n const eco = getEcosystemRefs(store, modelSymbol);\n\n return ok({\n model: {\n name: modelSymbol.name,\n fqn: modelSymbol.fqn ?? modelSymbol.name,\n symbolId: modelSymbol.symbol_id,\n filePath: file.path,\n },\n relationships,\n schema,\n relatedControllers,\n relatedRequests,\n ...eco,\n });\n}\n\nfunction buildOrmModelContext(\n store: Store,\n ormModel: OrmModelRow,\n): TraceMcpResult<ModelContextResult> {\n const file = store.getFileById(ormModel.file_id);\n const metadata: Record<string, unknown> = ormModel.metadata\n ? JSON.parse(ormModel.metadata)\n : {};\n\n // Associations from orm_associations table\n const assocRows: OrmAssociationRow[] = store.getOrmAssociationsByModel(ormModel.id);\n const relationships: ModelRelationship[] = assocRows.map((a) => ({\n type: a.kind,\n relatedModel: a.target_model_name ?? '',\n method: a.options ? (JSON.parse(a.options) as { as?: string }).as : undefined,\n }));\n\n // Schema from fields column (Mongoose/Sequelize)\n const fields: Record<string, unknown>[] = ormModel.fields\n ? JSON.parse(ormModel.fields)\n : [];\n\n const schema: ModelSchema[] = fields.length > 0\n ? [{\n tableName: ormModel.collection_or_table ?? ormModel.name.toLowerCase() + 's',\n columns: fields,\n operation: 'schema',\n }]\n : [];\n\n return ok({\n model: {\n name: ormModel.name,\n fqn: ormModel.name,\n symbolId: `orm:${ormModel.name}`,\n filePath: file?.path ?? '',\n orm: ormModel.orm,\n collection: ormModel.collection_or_table ?? undefined,\n },\n relationships,\n schema,\n relatedControllers: [],\n relatedRequests: [],\n ormMetadata: metadata,\n });\n}\n\nfunction getRelationships(store: Store, modelSymbol: SymbolRow): ModelRelationship[] {\n const relationships: ModelRelationship[] = [];\n const nodeId = store.getNodeId('symbol', modelSymbol.id);\n if (!nodeId) return relationships;\n\n const relEdgeTypes = ['has_many', 'belongs_to', 'belongs_to_many', 'has_one', 'morphs_to'];\n\n const outEdges = store.getOutgoingEdges(nodeId);\n for (const edge of outEdges) {\n if (!relEdgeTypes.includes(edge.edge_type_name)) continue;\n\n const targetNode = store.getNodeByNodeId(edge.target_node_id);\n if (!targetNode || targetNode.node_type !== 'symbol') continue;\n\n const targetSym = store.getSymbolById(targetNode.ref_id);\n if (!targetSym) continue;\n\n const metadata = edge.metadata ? JSON.parse(edge.metadata) : {};\n relationships.push({\n type: edge.edge_type_name,\n relatedModel: targetSym.fqn ?? targetSym.name,\n relatedSymbolId: targetSym.symbol_id,\n method: metadata.method,\n });\n }\n\n // Also check incoming edges (e.g. belongs_to from other models)\n const inEdges = store.getIncomingEdges(nodeId);\n for (const edge of inEdges) {\n if (!relEdgeTypes.includes(edge.edge_type_name)) continue;\n\n const sourceNode = store.getNodeByNodeId(edge.source_node_id);\n if (!sourceNode || sourceNode.node_type !== 'symbol') continue;\n\n const sourceSym = store.getSymbolById(sourceNode.ref_id);\n if (!sourceSym) continue;\n\n const metadata = edge.metadata ? JSON.parse(edge.metadata) : {};\n relationships.push({\n type: `inverse:${edge.edge_type_name}`,\n relatedModel: sourceSym.fqn ?? sourceSym.name,\n relatedSymbolId: sourceSym.symbol_id,\n method: metadata.method,\n });\n }\n\n return relationships;\n}\n\nfunction getModelSchema(store: Store, modelName: string): ModelSchema[] {\n // Guess table name from model name (e.g. User -> users, BlogPost -> blog_posts)\n const tableName = modelNameToTable(modelName);\n const migrations = store.getMigrationsByTable(tableName);\n\n return migrations.map((m) => ({\n tableName: m.table_name,\n columns: m.columns ? JSON.parse(m.columns) : [],\n operation: m.operation,\n timestamp: m.timestamp ?? undefined,\n }));\n}\n\nfunction getRelatedByRole(\n store: Store,\n _modelSymbol: SymbolRow,\n _role: string,\n): { name: string; symbolId: string; fqn: string | null }[] {\n // For now, return empty — this requires more complex graph traversal\n // that would need checking file framework_roles\n return [];\n}\n\n/**\n * Find Nova, Filament, Livewire, and laravel-data references to a model.\n * Searches incoming edges targeting the model's node.\n */\nfunction getEcosystemRefs(store: Store, modelSymbol: SymbolRow): Partial<ModelContextResult> {\n const nodeId = store.getNodeId('symbol', modelSymbol.id);\n if (!nodeId) return {};\n\n const incoming = store.getIncomingEdges(nodeId);\n const result: Partial<ModelContextResult> = {};\n\n // Nova\n for (const edge of incoming) {\n if (edge.edge_type_name !== 'nova_resource_for') continue;\n const src = resolveSourceSymbol(store, edge.source_node_id);\n if (!src) continue;\n const srcNodeId = store.getNodeId('symbol', src.id);\n const actions: string[] = [];\n const filters: string[] = [];\n const lenses: string[] = [];\n const metrics: string[] = [];\n if (srcNodeId) {\n for (const out of store.getOutgoingEdges(srcNodeId)) {\n const name = resolveTargetName(store, out.target_node_id, out.metadata);\n if (out.edge_type_name === 'nova_action_on' && name) actions.push(name);\n if (out.edge_type_name === 'nova_filter_on' && name) filters.push(name);\n if (out.edge_type_name === 'nova_lens_on' && name) lenses.push(name);\n if (out.edge_type_name === 'nova_metric_queries' && name) metrics.push(name);\n }\n }\n result.nova = {\n resource: { name: src.name, fqn: src.fqn ?? undefined, symbolId: src.symbol_id },\n actions, filters, lenses, metrics,\n };\n break;\n }\n\n // Filament\n for (const edge of incoming) {\n if (edge.edge_type_name !== 'filament_resource_for') continue;\n const src = resolveSourceSymbol(store, edge.source_node_id);\n if (!src) continue;\n const srcNodeId = store.getNodeId('symbol', src.id);\n const relationManagers: string[] = [];\n const pages: string[] = [];\n const widgets: string[] = [];\n if (srcNodeId) {\n for (const out of store.getOutgoingEdges(srcNodeId)) {\n const name = resolveTargetName(store, out.target_node_id, out.metadata);\n if (out.edge_type_name === 'filament_relation_manager' && name) relationManagers.push(name);\n if (out.edge_type_name === 'filament_page_for' && name) pages.push(name);\n if (out.edge_type_name === 'filament_widget_queries' && name) widgets.push(name);\n }\n }\n result.filament = {\n resource: { name: src.name, fqn: src.fqn ?? undefined, symbolId: src.symbol_id },\n relationManagers, pages, widgets,\n };\n break;\n }\n\n // Livewire components using this model\n const lwComponents: EcosystemRef[] = [];\n for (const edge of incoming) {\n if (edge.edge_type_name !== 'livewire_uses_model') continue;\n const src = resolveSourceSymbol(store, edge.source_node_id);\n if (src) lwComponents.push({ name: src.name, fqn: src.fqn ?? undefined, symbolId: src.symbol_id });\n }\n if (lwComponents.length > 0) result.livewireComponents = lwComponents;\n\n // Data classes wrapping this model\n const dataClasses: EcosystemRef[] = [];\n for (const edge of incoming) {\n if (edge.edge_type_name !== 'data_wraps') continue;\n const src = resolveSourceSymbol(store, edge.source_node_id);\n if (src) dataClasses.push({ name: src.name, fqn: src.fqn ?? undefined, symbolId: src.symbol_id });\n }\n if (dataClasses.length > 0) result.dataClasses = dataClasses;\n\n return result;\n}\n\nfunction resolveSourceSymbol(store: Store, sourceNodeId: number): SymbolRow | undefined {\n const sourceNode = store.getNodeByNodeId(sourceNodeId);\n if (!sourceNode || sourceNode.node_type !== 'symbol') return undefined;\n return store.getSymbolById(sourceNode.ref_id);\n}\n\nfunction resolveTargetName(store: Store, targetNodeId: number, metadataStr: string | null): string | undefined {\n const targetNode = store.getNodeByNodeId(targetNodeId);\n if (targetNode?.node_type === 'symbol') {\n const sym = store.getSymbolById(targetNode.ref_id);\n if (sym) return sym.fqn ?? sym.name;\n }\n if (metadataStr) {\n try {\n const meta = JSON.parse(metadataStr) as Record<string, unknown>;\n if (meta.targetFqn) return String(meta.targetFqn);\n } catch { /* ignore */ }\n }\n return undefined;\n}\n\n/** Convert a model class name to a table name (simple pluralization). */\nfunction modelNameToTable(name: string): string {\n // Strip namespace\n const short = name.includes('\\\\') ? name.split('\\\\').pop()! : name;\n // Simple snake_case + plural\n const snake = short.replace(/([a-z])([A-Z])/g, '$1_$2').toLowerCase();\n // Simple pluralization\n if (snake.endsWith('y') && !/[aeiou]y$/.test(snake)) return snake.slice(0, -1) + 'ies';\n if (/(?:s|sh|ch|x|z)$/.test(snake)) return snake + 'es';\n return snake + 's';\n}\n","/**\n * get_schema tool — reconstructs database schema from migrations.\n * Returns columns, types, and structure for a table or all tables.\n */\nimport type { Store } from '../db/store.js';\nimport { ok, type TraceMcpResult } from '../errors.js';\n\nexport interface TableColumn {\n name: string;\n type: string;\n nullable?: boolean;\n unique?: boolean;\n primary?: boolean;\n foreign?: boolean;\n default?: string;\n autoIncrement?: boolean;\n}\n\nexport interface TableSchema {\n tableName: string;\n columns: TableColumn[];\n operations: { operation: string; timestamp?: string }[];\n}\n\nexport interface SchemaResult {\n tables: TableSchema[];\n /** Mongoose/Sequelize ORM schemas (collections or model schemas) */\n ormSchemas?: OrmSchema[];\n}\n\nexport interface OrmSchema {\n name: string;\n orm: string;\n collection: string | undefined;\n fields: Record<string, unknown>[];\n indexes?: Record<string, unknown>[];\n}\n\nexport function getSchema(\n store: Store,\n tableName?: string,\n): TraceMcpResult<SchemaResult> {\n const tables: TableSchema[] = [];\n const ormSchemas: OrmSchema[] = [];\n\n if (tableName) {\n // Try SQL migrations first\n const schema = reconstructTable(store, tableName);\n if (schema) tables.push(schema);\n\n // Also try ORM model by name or collection\n const allOrm = store.getAllOrmModels();\n const ormMatch = allOrm.find(\n (m) =>\n m.name.toLowerCase() === tableName.toLowerCase() ||\n m.collection_or_table?.toLowerCase() === tableName.toLowerCase(),\n );\n if (ormMatch) {\n ormSchemas.push(buildOrmSchema(ormMatch));\n }\n } else {\n // All SQL tables\n const migrations = store.getAllMigrations();\n const tableNames = [...new Set(migrations.map((m) => m.table_name))];\n for (const name of tableNames) {\n const schema = reconstructTable(store, name);\n if (schema) tables.push(schema);\n }\n\n // All ORM models\n for (const m of store.getAllOrmModels()) {\n ormSchemas.push(buildOrmSchema(m));\n }\n }\n\n return ok({\n tables,\n ...(ormSchemas.length > 0 ? { ormSchemas } : {}),\n });\n}\n\nfunction buildOrmSchema(model: { name: string; orm: string; collection_or_table: string | null; fields: string | null; metadata: string | null }): OrmSchema {\n const fields: Record<string, unknown>[] = model.fields ? JSON.parse(model.fields) : [];\n const meta: Record<string, unknown> = model.metadata ? JSON.parse(model.metadata) : {};\n return {\n name: model.name,\n orm: model.orm,\n collection: model.collection_or_table ?? undefined,\n fields,\n ...(meta.indexes ? { indexes: meta.indexes as Record<string, unknown>[] } : {}),\n };\n}\n\nfunction reconstructTable(store: Store, tableName: string): TableSchema | null {\n const migrations = store.getMigrationsByTable(tableName);\n if (migrations.length === 0) return null;\n\n const columns: TableColumn[] = [];\n const operations: { operation: string; timestamp?: string }[] = [];\n const columnMap = new Map<string, TableColumn>();\n\n for (const mig of migrations) {\n operations.push({\n operation: mig.operation,\n timestamp: mig.timestamp ?? undefined,\n });\n\n if (mig.operation === 'drop') {\n // Table dropped — clear columns\n columnMap.clear();\n continue;\n }\n\n if (mig.columns) {\n const cols = JSON.parse(mig.columns) as Record<string, unknown>[];\n for (const col of cols) {\n const name = col.name as string;\n if (!name) continue;\n\n const tableCol: TableColumn = {\n name,\n type: (col.type as string) ?? 'unknown',\n };\n if (col.nullable) tableCol.nullable = true;\n if (col.unique) tableCol.unique = true;\n if (col.primary) tableCol.primary = true;\n if (col.foreign) tableCol.foreign = true;\n if (col.autoIncrement) tableCol.autoIncrement = true;\n if (col.default !== undefined) tableCol.default = String(col.default);\n\n columnMap.set(name, tableCol);\n }\n }\n }\n\n return {\n tableName,\n columns: [...columnMap.values()],\n operations,\n };\n}\n","/**\n * get_event_graph tool — shows event/listener relationships.\n * Finds events, their listeners, and dispatchers.\n */\nimport type { Store, SymbolRow } from '../db/store.js';\nimport { ok, err, type TraceMcpResult } from '../errors.js';\nimport { notFound } from '../errors.js';\n\nexport interface BroadcastingInfo {\n channels: { name: string; type: string }[];\n broadcastAs?: string;\n payloadFields?: string[];\n}\n\nexport interface EventNode {\n name: string;\n fqn: string;\n symbolId: string;\n listeners: { name: string; fqn: string; symbolId: string }[];\n dispatchers: { name: string; fqn: string; symbolId: string }[];\n broadcasting?: BroadcastingInfo;\n}\n\nexport interface EventGraphResult {\n events: EventNode[];\n}\n\nexport function getEventGraph(\n store: Store,\n eventName?: string,\n): TraceMcpResult<EventGraphResult> {\n const events: EventNode[] = [];\n\n // Edge types that represent event-like relationships across frameworks\n const LISTENER_EDGE_TYPES = ['listens_to', 'django_signal_receiver'];\n const DISPATCH_EDGE_TYPES = ['dispatches', 'celery_dispatches'];\n\n if (eventName) {\n // Find specific event\n const eventSymbol = findEventSymbol(store, eventName);\n if (!eventSymbol) {\n return err(notFound(`event:${eventName}`));\n }\n const node = buildEventNode(store, eventSymbol, LISTENER_EDGE_TYPES, DISPATCH_EDGE_TYPES);\n events.push(node);\n } else {\n const seen = new Set<number>();\n\n // Find all events that have listener/dispatch edges targeting them\n for (const edgeType of [...LISTENER_EDGE_TYPES, ...DISPATCH_EDGE_TYPES]) {\n const edges = store.getEdgesByType(edgeType);\n for (const edge of edges) {\n if (seen.has(edge.target_node_id)) continue;\n seen.add(edge.target_node_id);\n\n const targetNode = store.getNodeByNodeId(edge.target_node_id);\n if (!targetNode || targetNode.node_type !== 'symbol') continue;\n\n const sym = store.getSymbolById(targetNode.ref_id);\n if (!sym) continue;\n\n events.push(buildEventNode(store, sym, LISTENER_EDGE_TYPES, DISPATCH_EDGE_TYPES));\n }\n }\n }\n\n return ok({ events });\n}\n\nfunction findEventSymbol(store: Store, name: string): SymbolRow | undefined {\n // Try FQN\n let sym = store.getSymbolByFqn(name);\n if (sym) return sym;\n\n // Try App\\Events\\ prefix\n sym = store.getSymbolByFqn(`App\\\\Events\\\\${name}`);\n if (sym) return sym;\n\n // Search by name\n const results = store.db.prepare(\n \"SELECT * FROM symbols WHERE name = ? AND kind = 'class'\",\n ).all(name) as SymbolRow[];\n return results[0];\n}\n\nfunction buildEventNode(\n store: Store,\n eventSymbol: SymbolRow,\n listenerEdgeTypes: string[],\n dispatchEdgeTypes: string[],\n): EventNode {\n const nodeId = store.getNodeId('symbol', eventSymbol.id);\n const listeners: { name: string; fqn: string; symbolId: string }[] = [];\n const dispatchers: { name: string; fqn: string; symbolId: string }[] = [];\n\n if (nodeId) {\n const inEdges = store.getIncomingEdges(nodeId);\n for (const edge of inEdges) {\n if (listenerEdgeTypes.includes(edge.edge_type_name)) {\n const sourceNode = store.getNodeByNodeId(edge.source_node_id);\n if (!sourceNode || sourceNode.node_type !== 'symbol') continue;\n const sym = store.getSymbolById(sourceNode.ref_id);\n if (sym) {\n listeners.push({ name: sym.name, fqn: sym.fqn ?? sym.name, symbolId: sym.symbol_id });\n }\n } else if (dispatchEdgeTypes.includes(edge.edge_type_name)) {\n const sourceNode = store.getNodeByNodeId(edge.source_node_id);\n if (!sourceNode || sourceNode.node_type !== 'symbol') continue;\n const sym = store.getSymbolById(sourceNode.ref_id);\n if (sym) {\n dispatchers.push({ name: sym.name, fqn: sym.fqn ?? sym.name, symbolId: sym.symbol_id });\n }\n }\n }\n }\n\n // Broadcasting: check for broadcasts_on and broadcast_as edges\n let broadcasting: BroadcastingInfo | undefined;\n if (nodeId) {\n const outEdges = store.getOutgoingEdges(nodeId);\n const channels: { name: string; type: string }[] = [];\n let broadcastAs: string | undefined;\n let payloadFields: string[] | undefined;\n\n for (const edge of outEdges) {\n const meta = edge.metadata ? JSON.parse(edge.metadata) as Record<string, unknown> : {};\n if (edge.edge_type_name === 'broadcasts_on') {\n channels.push({ name: String(meta.channelName ?? ''), type: String(meta.channelType ?? 'public') });\n } else if (edge.edge_type_name === 'broadcast_as') {\n broadcastAs = String(meta.broadcastAs ?? '');\n }\n }\n\n try {\n const symMeta = eventSymbol.metadata ? JSON.parse(eventSymbol.metadata) as Record<string, unknown> : {};\n if (Array.isArray(symMeta.payloadFields)) {\n payloadFields = symMeta.payloadFields as string[];\n }\n } catch { /* ignore */ }\n\n if (channels.length > 0) {\n broadcasting = { channels, broadcastAs, payloadFields };\n }\n }\n\n return {\n name: eventSymbol.name,\n fqn: eventSymbol.fqn ?? eventSymbol.name,\n symbolId: eventSymbol.symbol_id,\n listeners,\n dispatchers,\n broadcasting,\n };\n}\n","import type { Store, SymbolRow, FileRow } from '../db/store.js';\nimport { notFound, type TraceMcpResult } from '../errors.js';\nimport { ok, err } from 'neverthrow';\n\nexport interface ReferenceItem {\n /** Edge type describing the relationship (e.g. 'imports', 'calls', 'renders_component') */\n edge_type: string;\n /** Symbol that references the target (null if the referencing node is a file/route/component) */\n symbol: {\n symbol_id: string;\n name: string;\n kind: string;\n fqn: string | null;\n signature: string | null;\n line_start: number | null;\n } | null;\n file: string;\n}\n\nexport interface FindReferencesResult {\n target: {\n symbol_id?: string;\n file?: string;\n fqn?: string | null;\n };\n references: ReferenceItem[];\n total: number;\n}\n\n/**\n * Find all incoming references to a symbol or file node.\n * Returns every edge pointing at the target, with the referencing symbol resolved.\n */\nexport function findReferences(\n store: Store,\n opts: { symbolId?: string; fqn?: string; filePath?: string },\n): TraceMcpResult<FindReferencesResult> {\n let nodeId: number | undefined;\n let targetMeta: FindReferencesResult['target'] = {};\n\n if (opts.symbolId || opts.fqn) {\n let symbol: SymbolRow | undefined;\n if (opts.symbolId) {\n symbol = store.getSymbolBySymbolId(opts.symbolId);\n targetMeta.symbol_id = opts.symbolId;\n } else {\n symbol = store.getSymbolByFqn(opts.fqn!);\n targetMeta.fqn = opts.fqn;\n }\n if (!symbol) return err(notFound(opts.symbolId ?? opts.fqn ?? 'unknown'));\n const file = store.getFileById(symbol.file_id);\n if (file) targetMeta.file = file.path;\n nodeId = store.getNodeId('symbol', symbol.id);\n } else if (opts.filePath) {\n const file = store.getFile(opts.filePath);\n if (!file) return err(notFound(opts.filePath));\n targetMeta.file = file.path;\n nodeId = store.getNodeId('file', file.id);\n } else {\n return err(notFound('provide symbol_id, fqn, or file_path'));\n }\n\n if (nodeId === undefined) {\n // Node not in the graph (file indexed but no edges yet)\n return ok({ target: targetMeta, references: [], total: 0 });\n }\n\n const incomingEdges = store.getIncomingEdges(nodeId);\n const references: ReferenceItem[] = [];\n\n for (const edge of incomingEdges) {\n const sourceRef = store.getNodeRef(edge.source_node_id);\n if (!sourceRef) continue;\n\n let symbol: ReferenceItem['symbol'] = null;\n let filePath = '';\n\n if (sourceRef.nodeType === 'symbol') {\n const sym = store.getSymbolById(sourceRef.refId);\n if (!sym) continue;\n const f = store.getFileById(sym.file_id);\n filePath = f?.path ?? '';\n symbol = {\n symbol_id: sym.symbol_id,\n name: sym.name,\n kind: sym.kind,\n fqn: sym.fqn,\n signature: sym.signature,\n line_start: sym.line_start,\n };\n } else if (sourceRef.nodeType === 'file') {\n const f = store.getFileById(sourceRef.refId);\n filePath = f?.path ?? '';\n } else {\n // route / component / orm_model / rn_screen — just note the file via the ref table\n // We don't have a direct getById for all types, so skip detailed resolution\n filePath = `[${sourceRef.nodeType}:${sourceRef.refId}]`;\n }\n\n references.push({\n edge_type: edge.edge_type_name,\n symbol,\n file: filePath,\n });\n }\n\n return ok({ target: targetMeta, references, total: references.length });\n}\n","import type { Store } from '../db/store.js';\nimport { notFound, type TraceMcpResult } from '../errors.js';\nimport { ok, err } from 'neverthrow';\n\nexport interface CallGraphNode {\n symbol_id: string;\n name: string;\n kind: string;\n file: string;\n line: number | null;\n calls?: CallGraphNode[];\n called_by?: CallGraphNode[];\n}\n\nexport interface CallGraphResult {\n root: CallGraphNode;\n /** Edge types that were treated as calls */\n edge_types_used: string[];\n max_depth: number;\n}\n\nconst CALL_EDGE_TYPES = new Set([\n 'calls', 'references',\n // Framework-specific \"call\" semantics\n 'dispatches', 'routes_to', 'validates_with',\n 'nest_injects', 'graphql_resolves',\n]);\n\n/**\n * Build call graph centered on a symbol: who calls it (callers) and who it calls (callees).\n */\nconst MAX_DEPTH = 10;\n\nexport function getCallGraph(\n store: Store,\n opts: { symbolId?: string; fqn?: string },\n depth = 2,\n): TraceMcpResult<CallGraphResult> {\n depth = Math.min(depth, MAX_DEPTH);\n let symbol = opts.symbolId\n ? store.getSymbolBySymbolId(opts.symbolId)\n : opts.fqn ? store.getSymbolByFqn(opts.fqn) : undefined;\n\n if (!symbol) return err(notFound(opts.symbolId ?? opts.fqn ?? 'unknown'));\n\n const file = store.getFileById(symbol.file_id);\n const nodeId = store.getNodeId('symbol', symbol.id);\n if (!nodeId) {\n return ok({\n root: makeNode(symbol, file?.path ?? '', null, [], []),\n edge_types_used: [],\n max_depth: depth,\n });\n }\n\n const edgeTypesUsed = new Set<string>();\n const visited = new Set<number>();\n\n const rootNode = buildCallNode(store, symbol.id, nodeId, depth, visited, edgeTypesUsed);\n\n return ok({\n root: rootNode,\n edge_types_used: [...edgeTypesUsed],\n max_depth: depth,\n });\n}\n\nfunction buildCallNode(\n store: Store,\n symbolId: number,\n nodeId: number,\n depth: number,\n visited: Set<number>,\n edgeTypesUsed: Set<string>,\n): CallGraphNode {\n const symbol = store.getSymbolById(symbolId);\n const file = symbol ? store.getFileById(symbol.file_id) : undefined;\n\n if (!symbol) {\n return { symbol_id: '', name: '?', kind: 'unknown', file: '', line: null };\n }\n\n const node = makeNode(symbol, file?.path ?? '', symbol.line_start, [], []);\n visited.add(nodeId);\n\n if (depth <= 0) {\n delete node.calls;\n delete node.called_by;\n return node;\n }\n\n // Outgoing: what this symbol calls\n const outgoing = store.getOutgoingEdges(nodeId);\n for (const edge of outgoing) {\n if (!CALL_EDGE_TYPES.has(edge.edge_type_name)) continue;\n edgeTypesUsed.add(edge.edge_type_name);\n if (visited.has(edge.target_node_id)) continue;\n\n const ref = store.getNodeRef(edge.target_node_id);\n if (!ref || ref.nodeType !== 'symbol') continue;\n\n const child = buildCallNode(store, ref.refId, edge.target_node_id, depth - 1, new Set(visited), edgeTypesUsed);\n node.calls!.push(child);\n }\n\n // Incoming: who calls this symbol\n const incoming = store.getIncomingEdges(nodeId);\n for (const edge of incoming) {\n if (!CALL_EDGE_TYPES.has(edge.edge_type_name)) continue;\n edgeTypesUsed.add(edge.edge_type_name);\n if (visited.has(edge.source_node_id)) continue;\n\n const ref = store.getNodeRef(edge.source_node_id);\n if (!ref || ref.nodeType !== 'symbol') continue;\n\n const caller = buildCallNode(store, ref.refId, edge.source_node_id, depth - 1, new Set(visited), edgeTypesUsed);\n node.called_by!.push(caller);\n }\n\n // Prune empty arrays\n if (node.calls!.length === 0) delete node.calls;\n if (node.called_by!.length === 0) delete node.called_by;\n\n return node;\n}\n\nfunction makeNode(\n symbol: { symbol_id: string; name: string; kind: string },\n filePath: string,\n line: number | null,\n calls: CallGraphNode[],\n called_by: CallGraphNode[],\n): CallGraphNode {\n return { symbol_id: symbol.symbol_id, name: symbol.name, kind: symbol.kind, file: filePath, line, calls, called_by };\n}\n","import type { Store } from '../db/store.js';\nimport { notFound, type TraceMcpResult } from '../errors.js';\nimport { ok, err } from 'neverthrow';\n\nexport interface LivewireProperty {\n name: string;\n type?: string;\n is_lazy?: boolean;\n}\n\nexport interface LivewireAction {\n name: string;\n wire_targets?: string[]; // wire:click=\"methodName\" found in blade\n}\n\nexport interface LivewireContextResult {\n component_class: {\n symbol_id: string;\n name: string;\n file: string;\n };\n view?: {\n path: string;\n symbol_id?: string;\n };\n properties: LivewireProperty[];\n actions: LivewireAction[];\n events: {\n dispatches: string[];\n listens: string[];\n };\n child_components: string[];\n uses_model?: string;\n version?: 'v2' | 'v3';\n}\n\n/**\n * Get full context for a Livewire component: properties, actions,\n * events (dispatched/listened), associated view, and child components.\n */\nexport function getLivewireContext(\n store: Store,\n componentName: string,\n): TraceMcpResult<LivewireContextResult> {\n // Find the symbol for the Livewire component class\n const symbol = store.getSymbolByFqn(componentName)\n ?? findLivewireSymbol(store, componentName);\n\n if (!symbol) return err(notFound(componentName));\n\n const file = store.getFileById(symbol.file_id);\n if (!file) return err(notFound(`file for ${componentName}`));\n\n const nodeId = store.getNodeId('symbol', symbol.id);\n\n // Parse metadata stored by the Livewire indexer plugin\n let meta: Record<string, unknown> = {};\n try {\n if (symbol.metadata) meta = JSON.parse(symbol.metadata) as Record<string, unknown>;\n } catch { /* ignore */ }\n\n const properties: LivewireProperty[] = [];\n const actions: LivewireAction[] = [];\n\n // Extract properties from metadata\n if (Array.isArray(meta.properties)) {\n for (const p of meta.properties as Record<string, unknown>[]) {\n properties.push({ name: String(p.name ?? ''), type: p.type as string | undefined });\n }\n }\n\n // Extract actions/methods from metadata\n if (Array.isArray(meta.actions)) {\n for (const a of meta.actions as Record<string, unknown>[]) {\n actions.push({ name: String(a.name ?? '') });\n }\n }\n\n // Resolve edges for events, view, child components\n const dispatches: string[] = [];\n const listens: string[] = [];\n const childComponents: string[] = [];\n let viewPath: string | undefined;\n let viewSymbolId: string | undefined;\n let usesModel: string | undefined;\n\n if (nodeId !== undefined) {\n const outgoing = store.getOutgoingEdges(nodeId);\n for (const edge of outgoing) {\n switch (edge.edge_type_name) {\n case 'livewire_renders': {\n const ref = store.getNodeRef(edge.target_node_id);\n if (ref) {\n const target = ref.nodeType === 'file'\n ? store.getFileById(ref.refId)\n : store.getSymbolById(ref.refId);\n if (target && 'path' in target) viewPath = target.path;\n else if (target && 'symbol_id' in target) {\n viewSymbolId = target.symbol_id;\n const f = store.getFileById(target.file_id);\n if (f) viewPath = f.path;\n }\n }\n break;\n }\n case 'livewire_dispatches': {\n const edgeMeta = edge.metadata ? JSON.parse(edge.metadata) as Record<string, unknown> : {};\n if (edgeMeta.event) dispatches.push(String(edgeMeta.event));\n break;\n }\n case 'livewire_uses_model': {\n const ref = store.getNodeRef(edge.target_node_id);\n if (ref?.nodeType === 'symbol') {\n const s = store.getSymbolById(ref.refId);\n if (s) usesModel = s.name;\n }\n break;\n }\n case 'livewire_child_of':\n case 'livewire_form': {\n const ref = store.getNodeRef(edge.target_node_id);\n if (ref?.nodeType === 'symbol') {\n const s = store.getSymbolById(ref.refId);\n if (s) childComponents.push(s.name);\n }\n break;\n }\n }\n }\n\n const incoming = store.getIncomingEdges(nodeId);\n for (const edge of incoming) {\n if (edge.edge_type_name === 'livewire_listens') {\n const edgeMeta = edge.metadata ? JSON.parse(edge.metadata) as Record<string, unknown> : {};\n if (edgeMeta.event) listens.push(String(edgeMeta.event));\n }\n }\n }\n\n const version = (meta.version as 'v2' | 'v3' | undefined) ?? detectVersion(meta);\n\n return ok({\n component_class: {\n symbol_id: symbol.symbol_id,\n name: symbol.name,\n file: file.path,\n },\n view: viewPath ? { path: viewPath, symbol_id: viewSymbolId } : undefined,\n properties,\n actions,\n events: { dispatches, listens },\n child_components: childComponents,\n uses_model: usesModel,\n version,\n });\n}\n\nfunction findLivewireSymbol(store: Store, name: string) {\n return store.findSymbolByRole(name, 'livewire_component');\n}\n\nfunction detectVersion(meta: Record<string, unknown>): 'v2' | 'v3' | undefined {\n if (meta.isV3 === true || meta.useForms === true) return 'v3';\n if (meta.isV2 === true) return 'v2';\n return undefined;\n}\n","/**\n * get_nova_resource — assembles full context for a Laravel Nova resource.\n * Returns: model mapping, relationship fields, actions, filters, lenses, metrics.\n */\nimport type { Store } from '../db/store.js';\nimport { ok, err, type TraceMcpResult } from '../errors.js';\nimport { notFound } from '../errors.js';\n\nexport interface NovaFieldInfo {\n fieldType: string;\n label: string;\n attribute: string;\n targetResource?: string;\n}\n\nexport interface NovaResourceResult {\n resource: {\n name: string;\n fqn: string;\n symbolId: string;\n filePath: string;\n };\n model?: {\n name: string;\n fqn: string;\n symbolId?: string;\n };\n fields: NovaFieldInfo[];\n actions: string[];\n filters: string[];\n lenses: string[];\n metrics: string[];\n}\n\nexport function getNovaResource(\n store: Store,\n resourceName: string,\n): TraceMcpResult<NovaResourceResult> {\n // Find the Nova resource symbol\n const symbol = store.getSymbolByFqn(resourceName)\n ?? store.getSymbolByFqn(`App\\\\Nova\\\\${resourceName}`)\n ?? findNovaSymbol(store, resourceName);\n\n if (!symbol) return err(notFound(`nova_resource:${resourceName}`));\n\n const file = store.getFileById(symbol.file_id);\n if (!file) return err(notFound(`file for nova_resource:${resourceName}`));\n\n const nodeId = store.getNodeId('symbol', symbol.id);\n\n // Collect edges\n let modelInfo: NovaResourceResult['model'];\n const fields: NovaFieldInfo[] = [];\n const actions: string[] = [];\n const filters: string[] = [];\n const lenses: string[] = [];\n const metrics: string[] = [];\n\n if (nodeId !== undefined) {\n const outgoing = store.getOutgoingEdges(nodeId);\n for (const edge of outgoing) {\n const meta = edge.metadata ? JSON.parse(edge.metadata) as Record<string, unknown> : {};\n\n switch (edge.edge_type_name) {\n case 'nova_resource_for': {\n const targetNode = store.getNodeByNodeId(edge.target_node_id);\n if (targetNode?.node_type === 'symbol') {\n const targetSym = store.getSymbolById(targetNode.ref_id);\n if (targetSym) {\n modelInfo = {\n name: targetSym.name,\n fqn: targetSym.fqn ?? targetSym.name,\n symbolId: targetSym.symbol_id,\n };\n }\n }\n if (!modelInfo && meta.targetFqn) {\n modelInfo = { name: String(meta.targetFqn).split('\\\\').pop()!, fqn: String(meta.targetFqn) };\n }\n break;\n }\n case 'nova_field_relationship': {\n fields.push({\n fieldType: String(meta.fieldType ?? ''),\n label: String(meta.label ?? ''),\n attribute: String(meta.attribute ?? ''),\n targetResource: meta.targetFqn as string | undefined,\n });\n break;\n }\n case 'nova_action_on': {\n const name = resolveTargetName(store, edge.target_node_id, meta);\n if (name) actions.push(name);\n break;\n }\n case 'nova_filter_on': {\n const name = resolveTargetName(store, edge.target_node_id, meta);\n if (name) filters.push(name);\n break;\n }\n case 'nova_lens_on': {\n const name = resolveTargetName(store, edge.target_node_id, meta);\n if (name) lenses.push(name);\n break;\n }\n case 'nova_metric_queries': {\n const name = resolveTargetName(store, edge.target_node_id, meta);\n if (name) metrics.push(name);\n break;\n }\n }\n }\n }\n\n // Also try to extract from metadata if edges weren't resolved\n if (fields.length === 0 || actions.length === 0) {\n try {\n const meta = symbol.metadata ? JSON.parse(symbol.metadata) as Record<string, unknown> : {};\n if (Array.isArray(meta.fieldRelationships) && fields.length === 0) {\n for (const f of meta.fieldRelationships as Record<string, unknown>[]) {\n fields.push({\n fieldType: String(f.fieldType ?? ''),\n label: String(f.label ?? ''),\n attribute: String(f.attribute ?? ''),\n targetResource: f.targetResourceFqn as string | undefined,\n });\n }\n }\n if (Array.isArray(meta.actions) && actions.length === 0) {\n for (const a of meta.actions as string[]) actions.push(a);\n }\n if (Array.isArray(meta.filters) && filters.length === 0) {\n for (const f of meta.filters as string[]) filters.push(f);\n }\n if (Array.isArray(meta.lenses) && lenses.length === 0) {\n for (const l of meta.lenses as string[]) lenses.push(l);\n }\n if (Array.isArray(meta.metrics) && metrics.length === 0) {\n for (const m of meta.metrics as string[]) metrics.push(m);\n }\n if (!modelInfo && meta.modelFqn) {\n const fqn = String(meta.modelFqn);\n modelInfo = { name: fqn.split('\\\\').pop()!, fqn };\n }\n } catch { /* ignore */ }\n }\n\n return ok({\n resource: {\n name: symbol.name,\n fqn: symbol.fqn ?? symbol.name,\n symbolId: symbol.symbol_id,\n filePath: file.path,\n },\n model: modelInfo,\n fields,\n actions,\n filters,\n lenses,\n metrics,\n });\n}\n\nfunction findNovaSymbol(store: Store, name: string) {\n return store.findSymbolByRole(name, 'nova_resource');\n}\n\nfunction resolveTargetName(\n store: Store,\n targetNodeId: number,\n meta: Record<string, unknown>,\n): string | undefined {\n const targetNode = store.getNodeByNodeId(targetNodeId);\n if (targetNode?.node_type === 'symbol') {\n const sym = store.getSymbolById(targetNode.ref_id);\n if (sym) return sym.fqn ?? sym.name;\n }\n if (meta.targetFqn) return String(meta.targetFqn);\n return undefined;\n}\n","import path from 'node:path';\nimport type { Store } from '../db/store.js';\nimport { notFound, type TraceMcpResult } from '../errors.js';\nimport { ok, err } from 'neverthrow';\n\nexport interface TestReference {\n test_file: string;\n /** Symbol ID of the test function/method, if resolved */\n symbol_id?: string;\n test_name?: string;\n edge_type: string;\n}\n\nexport interface GetTestsForResult {\n target: { symbol_id?: string; file?: string };\n tests: TestReference[];\n total: number;\n}\n\n/**\n * Find test files/symbols that cover a given symbol or file.\n *\n * Strategy (in order):\n * 1. Walk incoming `test_covers` edges (explicit — for future use when\n * test frameworks emit these edges).\n * 2. Heuristic path-based matching: look for test files whose path contains\n * the target file's base name (e.g. UserService → user.service.spec.ts).\n * 3. FTS search for the symbol name inside files whose path matches\n * common test patterns.\n */\nexport function getTestsFor(\n store: Store,\n opts: { symbolId?: string; fqn?: string; filePath?: string },\n): TraceMcpResult<GetTestsForResult> {\n let targetFile: string | undefined;\n let targetSymbolId: string | undefined;\n let nodeId: number | undefined;\n\n if (opts.symbolId || opts.fqn) {\n const symbol = opts.symbolId\n ? store.getSymbolBySymbolId(opts.symbolId)\n : store.getSymbolByFqn(opts.fqn!);\n if (!symbol) return err(notFound(opts.symbolId ?? opts.fqn ?? 'unknown'));\n targetSymbolId = symbol.symbol_id;\n const f = store.getFileById(symbol.file_id);\n if (f) targetFile = f.path;\n nodeId = store.getNodeId('symbol', symbol.id);\n } else if (opts.filePath) {\n const f = store.getFile(opts.filePath);\n if (!f) return err(notFound(opts.filePath));\n targetFile = f.path;\n nodeId = store.getNodeId('file', f.id);\n } else {\n return err(notFound('provide symbol_id, fqn, or file_path'));\n }\n\n const tests: TestReference[] = [];\n const seen = new Set<string>();\n\n // Strategy 1: explicit test_covers edges\n if (nodeId !== undefined) {\n const incoming = store.getIncomingEdges(nodeId);\n for (const edge of incoming) {\n if (edge.edge_type_name !== 'test_covers') continue;\n const ref = store.getNodeRef(edge.source_node_id);\n if (!ref) continue;\n\n if (ref.nodeType === 'file') {\n const f = store.getFileById(ref.refId);\n if (!f || seen.has(f.path)) continue;\n seen.add(f.path);\n tests.push({ test_file: f.path, edge_type: 'test_covers' });\n } else if (ref.nodeType === 'symbol') {\n const s = store.getSymbolById(ref.refId);\n const f = s ? store.getFileById(s.file_id) : undefined;\n if (!s || !f || seen.has(f.path)) continue;\n seen.add(f.path);\n tests.push({\n test_file: f.path,\n symbol_id: s.symbol_id,\n test_name: s.name,\n edge_type: 'test_covers',\n });\n }\n }\n }\n\n // Strategy 2: heuristic path-based matching\n if (targetFile) {\n const baseName = path.basename(targetFile, path.extname(targetFile));\n // Normalize: UserService → user-service, userService → user-service\n const normalized = baseName\n .replace(/([A-Z])/g, (m) => `-${m.toLowerCase()}`)\n .replace(/^-/, '')\n .toLowerCase();\n const variants = [baseName.toLowerCase(), normalized];\n\n const allFiles = store.getAllFiles();\n for (const f of allFiles) {\n if (seen.has(f.path)) continue;\n if (!isTestFile(f.path)) continue;\n\n const testBase = path.basename(f.path).toLowerCase();\n if (variants.some((v) => testBase.includes(v))) {\n seen.add(f.path);\n tests.push({ test_file: f.path, edge_type: 'heuristic_path' });\n }\n }\n }\n\n return ok({\n target: { symbol_id: targetSymbolId, file: targetFile },\n tests,\n total: tests.length,\n });\n}\n\nconst TEST_PATTERNS = [\n /\\.test\\.[jt]sx?$/,\n /\\.spec\\.[jt]sx?$/,\n /_test\\.py$/,\n /test_\\w+\\.py$/,\n /Test\\.php$/,\n /tests?\\//,\n /__tests__\\//,\n];\n\nfunction isTestFile(filePath: string): boolean {\n return TEST_PATTERNS.some((re) => re.test(filePath));\n}\n","/**\n * Introspection tools — primarily useful for developing trace-mcp itself.\n *\n * Tools:\n * get_implementations — find all TypeScript classes/interfaces that\n * extend or implement a given name.\n * get_api_surface — list all exported symbols grouped by file.\n * get_plugin_registry — list registered plugins, their manifests,\n * and all known edge types.\n */\nimport type { Store, SymbolWithFilePath, SymbolRow } from '../db/store.js';\nimport type { PluginRegistry } from '../plugin-api/registry.js';\n\n/** Safely parse JSON metadata — returns empty object on malformed input. */\nfunction safeParseMeta(raw: string | null | undefined): Record<string, unknown> {\n if (!raw) return {};\n try { return JSON.parse(raw) as Record<string, unknown>; } catch { return {}; }\n}\n\n// ---------------------------------------------------------------------------\n// get_implementations\n// ---------------------------------------------------------------------------\n\nexport interface ImplementorItem {\n symbol_id: string;\n name: string;\n kind: string;\n signature: string | null;\n file: string;\n line: number | null;\n relation: 'implements' | 'extends';\n /** raw metadata.implements / metadata.extends value */\n via: string | string[];\n}\n\nexport interface GetImplementationsResult {\n target: string;\n implementors: ImplementorItem[];\n total: number;\n}\n\nexport function getImplementations(\n store: Store,\n name: string,\n): GetImplementationsResult {\n const rows = store.findImplementors(name);\n\n const implementors: ImplementorItem[] = rows.map((row) => {\n const meta = safeParseMeta(row.metadata);\n const imp = meta['implements'];\n const ext = meta['extends'];\n\n // Determine whether this is an implements or extends relation\n let relation: 'implements' | 'extends' = 'extends';\n let via: string | string[] = ext as string | string[];\n if (Array.isArray(imp) && imp.includes(name)) {\n relation = 'implements';\n via = imp;\n }\n\n return {\n symbol_id: row.symbol_id,\n name: row.name,\n kind: row.kind,\n signature: row.signature,\n file: row.file_path,\n line: row.line_start,\n relation,\n via,\n };\n });\n\n return { target: name, implementors, total: implementors.length };\n}\n\n// ---------------------------------------------------------------------------\n// get_api_surface\n// ---------------------------------------------------------------------------\n\nexport interface ApiSurfaceSymbol {\n symbol_id: string;\n name: string;\n kind: string;\n signature: string | null;\n line: number | null;\n default: boolean;\n}\n\nexport interface ApiSurfaceFile {\n file: string;\n exports: ApiSurfaceSymbol[];\n}\n\nexport interface GetApiSurfaceResult {\n file_pattern: string | null;\n files: ApiSurfaceFile[];\n total_symbols: number;\n}\n\nexport function getApiSurface(\n store: Store,\n filePattern?: string,\n): GetApiSurfaceResult {\n const rows = store.getExportedSymbols(filePattern);\n\n // Group by file\n const byFile = new Map<string, ApiSurfaceSymbol[]>();\n for (const row of rows) {\n const meta = safeParseMeta(row.metadata);\n const sym: ApiSurfaceSymbol = {\n symbol_id: row.symbol_id,\n name: row.name,\n kind: row.kind,\n signature: row.signature,\n line: row.line_start,\n default: Boolean(meta['default']),\n };\n const list = byFile.get(row.file_path) ?? [];\n list.push(sym);\n byFile.set(row.file_path, list);\n }\n\n const files: ApiSurfaceFile[] = [];\n for (const [file, exports] of byFile) {\n files.push({ file, exports });\n }\n\n return {\n file_pattern: filePattern ?? null,\n files,\n total_symbols: rows.length,\n };\n}\n\n// ---------------------------------------------------------------------------\n// get_plugin_registry\n// ---------------------------------------------------------------------------\n\nexport interface LanguagePluginInfo {\n name: string;\n version: string;\n priority: number;\n extensions: string[];\n}\n\nexport interface FrameworkPluginInfo {\n name: string;\n version: string;\n priority: number;\n dependencies: string[];\n active: boolean;\n}\n\nexport interface EdgeTypeInfo {\n name: string;\n category: string;\n description: string;\n}\n\nexport interface GetPluginRegistryResult {\n language_plugins: LanguagePluginInfo[];\n framework_plugins: FrameworkPluginInfo[];\n edge_types: EdgeTypeInfo[];\n active_frameworks: string[];\n}\n\nexport function getPluginRegistry(\n store: Store,\n registry: PluginRegistry,\n activeFrameworkNames: Set<string>,\n): GetPluginRegistryResult {\n const languagePlugins: LanguagePluginInfo[] = registry\n .getLanguagePlugins()\n .map((p) => ({\n name: p.manifest.name,\n version: p.manifest.version,\n priority: p.manifest.priority,\n extensions: p.supportedExtensions,\n }));\n\n const frameworkPlugins: FrameworkPluginInfo[] = registry\n .getAllFrameworkPlugins()\n .map((p) => ({\n name: p.manifest.name,\n version: p.manifest.version,\n priority: p.manifest.priority,\n dependencies: p.manifest.dependencies ?? [],\n active: activeFrameworkNames.has(p.manifest.name),\n }));\n\n const edgeTypes = store.getEdgeTypes();\n\n return {\n language_plugins: languagePlugins,\n framework_plugins: frameworkPlugins,\n edge_types: edgeTypes,\n active_frameworks: [...activeFrameworkNames].sort(),\n };\n}\n\n// ---------------------------------------------------------------------------\n// get_type_hierarchy\n// ---------------------------------------------------------------------------\n\nexport interface HierarchyNode {\n name: string;\n kind: string;\n symbol_id: string;\n file: string;\n line: number | null;\n relation: 'root' | 'extends' | 'implements';\n children: HierarchyNode[];\n}\n\nexport interface GetTypeHierarchyResult {\n root: string;\n ancestors: HierarchyNode[];\n descendants: HierarchyNode[];\n}\n\n/**\n * Walk TypeScript class/interface hierarchy up (ancestors) and down (descendants).\n * Uses metadata.extends / metadata.implements stored by the TypeScript plugin.\n */\nexport function getTypeHierarchy(\n store: Store,\n name: string,\n maxDepth = 10,\n): GetTypeHierarchyResult {\n // Walk UP: follow extends chain\n const ancestors: HierarchyNode[] = [];\n walkAncestors(store, name, ancestors, new Set(), maxDepth);\n\n // Walk DOWN: find implementors/subclasses recursively\n const descendants: HierarchyNode[] = [];\n walkDescendants(store, name, descendants, new Set(), maxDepth);\n\n return { root: name, ancestors, descendants };\n}\n\nfunction walkAncestors(\n store: Store,\n name: string,\n result: HierarchyNode[],\n visited: Set<string>,\n depth: number,\n): void {\n if (depth <= 0 || visited.has(name)) return;\n visited.add(name);\n\n // Find the symbol by name\n const sym = store.getSymbolByName(name, 'class') ?? store.getSymbolByName(name, 'interface');\n if (!sym) return;\n\n const meta = sym.metadata ? (JSON.parse(sym.metadata) as Record<string, unknown>) : {};\n const ext = meta['extends'];\n const extNames = Array.isArray(ext) ? ext as string[] : typeof ext === 'string' ? [ext] : [];\n const implNames = Array.isArray(meta['implements']) ? meta['implements'] as string[] : [];\n\n const file = store.getFileById(sym.file_id);\n\n for (const parentName of extNames) {\n const node: HierarchyNode = {\n name: parentName,\n kind: 'unknown',\n symbol_id: '',\n file: '',\n line: null,\n relation: 'extends',\n children: [],\n };\n // Try to resolve the parent\n const parentSym = store.getSymbolByName(parentName, 'class') ?? store.getSymbolByName(parentName, 'interface');\n if (parentSym) {\n const parentFile = store.getFileById(parentSym.file_id);\n node.kind = parentSym.kind;\n node.symbol_id = parentSym.symbol_id;\n node.file = parentFile?.path ?? '';\n node.line = parentSym.line_start;\n }\n result.push(node);\n walkAncestors(store, parentName, node.children, visited, depth - 1);\n }\n\n for (const ifaceName of implNames) {\n const node: HierarchyNode = {\n name: ifaceName,\n kind: 'interface',\n symbol_id: '',\n file: '',\n line: null,\n relation: 'implements',\n children: [],\n };\n const ifaceSym = store.getSymbolByName(ifaceName, 'interface');\n if (ifaceSym) {\n const ifaceFile = store.getFileById(ifaceSym.file_id);\n node.symbol_id = ifaceSym.symbol_id;\n node.file = ifaceFile?.path ?? '';\n node.line = ifaceSym.line_start;\n }\n result.push(node);\n walkAncestors(store, ifaceName, node.children, visited, depth - 1);\n }\n}\n\nfunction walkDescendants(\n store: Store,\n name: string,\n result: HierarchyNode[],\n visited: Set<string>,\n depth: number,\n): void {\n if (depth <= 0 || visited.has(name)) return;\n visited.add(name);\n\n const implementors = store.findImplementors(name);\n\n for (const row of implementors) {\n const meta = safeParseMeta(row.metadata);\n const impl = meta['implements'];\n const ext = meta['extends'];\n\n let relation: 'extends' | 'implements' = 'extends';\n if (Array.isArray(impl) && (impl as string[]).includes(name)) {\n relation = 'implements';\n }\n\n const node: HierarchyNode = {\n name: row.name,\n kind: row.kind,\n symbol_id: row.symbol_id,\n file: row.file_path,\n line: row.line_start,\n relation,\n children: [],\n };\n result.push(node);\n walkDescendants(store, row.name, node.children, visited, depth - 1);\n }\n}\n\n// ---------------------------------------------------------------------------\n// get_dead_exports\n// ---------------------------------------------------------------------------\n\nexport interface DeadExportItem {\n symbol_id: string;\n name: string;\n kind: string;\n file: string;\n line: number | null;\n}\n\nexport interface GetDeadExportsResult {\n file_pattern: string | null;\n dead_exports: DeadExportItem[];\n total_exports: number;\n total_dead: number;\n}\n\n/**\n * Find exported symbols that are never imported by any other file.\n * Cross-references exported symbols with import edge metadata (specifiers).\n * An export is \"dead\" if its name never appears as a specifier in any import edge.\n */\nexport function getDeadExports(\n store: Store,\n filePattern?: string,\n): GetDeadExportsResult {\n const exported = store.getExportedSymbols(filePattern);\n\n // Build a set of all imported specifier names across the entire project\n const importedNames = new Set<string>();\n const importEdges = store.getEdgesByType('imports');\n for (const edge of importEdges) {\n if (!edge.metadata) continue;\n const meta = typeof edge.metadata === 'string'\n ? JSON.parse(edge.metadata) as Record<string, unknown>\n : edge.metadata as Record<string, unknown>;\n const specifiers = meta['specifiers'];\n if (Array.isArray(specifiers)) {\n for (const s of specifiers) {\n if (typeof s === 'string') {\n // Handle \"* as name\" → add \"name\"\n const clean = s.startsWith('* as ') ? s.slice(5) : s;\n importedNames.add(clean);\n }\n }\n }\n }\n\n const dead: DeadExportItem[] = [];\n for (const sym of exported) {\n // Skip methods (their export is inherited from the class)\n if (sym.kind === 'method') continue;\n if (!importedNames.has(sym.name)) {\n dead.push({\n symbol_id: sym.symbol_id,\n name: sym.name,\n kind: sym.kind,\n file: sym.file_path,\n line: sym.line_start,\n });\n }\n }\n\n return {\n file_pattern: filePattern ?? null,\n dead_exports: dead,\n total_exports: exported.filter((s) => s.kind !== 'method').length,\n total_dead: dead.length,\n };\n}\n\n// ---------------------------------------------------------------------------\n// get_dependency_graph\n// ---------------------------------------------------------------------------\n\nexport interface DependencyEdge {\n source: string;\n target: string;\n specifiers: string[];\n}\n\nexport interface GetDependencyGraphResult {\n file: string;\n imports: DependencyEdge[];\n imported_by: DependencyEdge[];\n}\n\n/**\n * Show file-level dependency graph: what a file imports and what imports it.\n * Requires ESM import edges (resolved by the pipeline in Pass 2d).\n */\nexport function getDependencyGraph(\n store: Store,\n filePath: string,\n): GetDependencyGraphResult {\n const file = store.getFile(filePath);\n if (!file) {\n return { file: filePath, imports: [], imported_by: [] };\n }\n\n const nodeId = store.getNodeId('file', file.id);\n if (nodeId == null) {\n return { file: filePath, imports: [], imported_by: [] };\n }\n\n // Outgoing imports (what this file imports)\n const outgoing = store.getOutgoingEdges(nodeId)\n .filter((e) => e.edge_type_name === 'imports');\n const imports: DependencyEdge[] = [];\n for (const edge of outgoing) {\n const targetRef = store.getNodeRef(edge.target_node_id);\n if (!targetRef || targetRef.nodeType !== 'file') continue;\n const targetFile = store.getFileById(targetRef.refId);\n if (!targetFile) continue;\n const meta = edge.metadata\n ? (typeof edge.metadata === 'string' ? JSON.parse(edge.metadata) : edge.metadata) as Record<string, unknown>\n : {};\n imports.push({\n source: filePath,\n target: targetFile.path,\n specifiers: (meta['specifiers'] as string[]) ?? [],\n });\n }\n\n // Incoming imports (what imports this file)\n const incoming = store.getIncomingEdges(nodeId)\n .filter((e) => e.edge_type_name === 'imports');\n const importedBy: DependencyEdge[] = [];\n for (const edge of incoming) {\n const sourceRef = store.getNodeRef(edge.source_node_id);\n if (!sourceRef || sourceRef.nodeType !== 'file') continue;\n const sourceFile = store.getFileById(sourceRef.refId);\n if (!sourceFile) continue;\n const meta = edge.metadata\n ? (typeof edge.metadata === 'string' ? JSON.parse(edge.metadata) : edge.metadata) as Record<string, unknown>\n : {};\n importedBy.push({\n source: sourceFile.path,\n target: filePath,\n specifiers: (meta['specifiers'] as string[]) ?? [],\n });\n }\n\n return { file: filePath, imports, imported_by: importedBy };\n}\n\n// ---------------------------------------------------------------------------\n// get_untested_exports\n// ---------------------------------------------------------------------------\n\nexport interface UntestedExportItem {\n symbol_id: string;\n name: string;\n kind: string;\n file: string;\n line: number | null;\n signature: string | null;\n}\n\nexport interface GetUntestedExportsResult {\n file_pattern: string | null;\n untested: UntestedExportItem[];\n total_exports: number;\n total_untested: number;\n}\n\n/**\n * Find exported public symbols that have no associated test coverage.\n * Uses heuristic path matching: for each exported symbol, checks if any\n * test file in the project matches its file name or symbol name pattern.\n */\nexport function getUntestedExports(\n store: Store,\n filePattern?: string,\n): GetUntestedExportsResult {\n const exported = store.getExportedSymbols(filePattern)\n .filter((s) => s.kind !== 'method'); // methods inherit from class\n\n // Collect all test file paths\n const allFiles = store.getAllFiles();\n const testFiles = allFiles\n .filter((f) => /\\.(test|spec)\\.(ts|js|tsx|jsx)$/.test(f.path))\n .map((f) => f.path.toLowerCase());\n\n const untested: UntestedExportItem[] = [];\n\n for (const sym of exported) {\n // Normalize the source file name for matching\n const baseName = sym.file_path\n .replace(/\\.[^.]+$/, '') // strip extension\n .split('/').pop()! // get filename\n .toLowerCase();\n\n // Check if any test file references this source file\n const hasTest = testFiles.some((testPath) => {\n const testBase = testPath.split('/').pop()!;\n return (\n testBase.includes(baseName) ||\n testBase.includes(toKebab(sym.name))\n );\n });\n\n if (!hasTest) {\n untested.push({\n symbol_id: sym.symbol_id,\n name: sym.name,\n kind: sym.kind,\n file: sym.file_path,\n line: sym.line_start,\n signature: sym.signature,\n });\n }\n }\n\n return {\n file_pattern: filePattern ?? null,\n untested,\n total_exports: exported.length,\n total_untested: untested.length,\n };\n}\n\n/** Convert PascalCase/camelCase to kebab-case for test file matching */\nfunction toKebab(name: string): string {\n return name\n .replace(/([a-z])([A-Z])/g, '$1-$2')\n .replace(/([A-Z])([A-Z][a-z])/g, '$1-$2')\n .toLowerCase();\n}\n\n// ---------------------------------------------------------------------------\n// self_audit\n// ---------------------------------------------------------------------------\n\nexport interface SelfAuditResult {\n summary: {\n total_files: number;\n total_symbols: number;\n total_edges: number;\n total_exports: number;\n dead_exports: number;\n untested_exports: number;\n test_files: number;\n import_edges: number;\n heritage_edges: number;\n test_covers_edges: number;\n };\n dead_exports_top10: DeadExportItem[];\n untested_top10: UntestedExportItem[];\n /** Files with most incoming import edges (most depended-on) */\n most_imported_files: { file: string; imported_by_count: number }[];\n /** Files with most outgoing import edges (most dependencies) */\n most_dependent_files: { file: string; imports_count: number }[];\n /** Interfaces/classes with the most implementors */\n widest_interfaces: { name: string; implementor_count: number }[];\n}\n\n/**\n * One-shot project health audit — combines dead exports, untested exports,\n * dependency hotspots, and heritage metrics into a single report.\n */\nexport function selfAudit(store: Store): SelfAuditResult {\n const stats = store.getStats();\n\n // Dead exports\n const deadResult = getDeadExports(store);\n\n // Untested exports\n const untestedResult = getUntestedExports(store);\n\n // Edge type counts\n const importEdges = store.getEdgesByType('imports');\n const heritageExtends = store.getEdgesByType('ts_extends');\n const heritageImplements = store.getEdgesByType('ts_implements');\n const testCovers = store.getEdgesByType('test_covers');\n\n // Test files count\n const allFiles = store.getAllFiles();\n const testFileCount = allFiles.filter((f) =>\n /\\.(test|spec)\\.[jt]sx?$|__tests__\\//.test(f.path),\n ).length;\n\n // Most imported files (incoming import edges per file)\n const importedByCount = new Map<number, number>();\n for (const edge of importEdges) {\n importedByCount.set(\n edge.target_node_id,\n (importedByCount.get(edge.target_node_id) ?? 0) + 1,\n );\n }\n const mostImported = [...importedByCount.entries()]\n .sort((a, b) => b[1] - a[1])\n .slice(0, 10)\n .map(([nodeId, count]) => {\n const ref = store.getNodeRef(nodeId);\n const file = ref?.nodeType === 'file' ? store.getFileById(ref.refId) : undefined;\n return { file: file?.path ?? `[node:${nodeId}]`, imported_by_count: count };\n });\n\n // Most dependent files (outgoing import edges per file)\n const importsCount = new Map<number, number>();\n for (const edge of importEdges) {\n importsCount.set(\n edge.source_node_id,\n (importsCount.get(edge.source_node_id) ?? 0) + 1,\n );\n }\n const mostDependent = [...importsCount.entries()]\n .sort((a, b) => b[1] - a[1])\n .slice(0, 10)\n .map(([nodeId, count]) => {\n const ref = store.getNodeRef(nodeId);\n const file = ref?.nodeType === 'file' ? store.getFileById(ref.refId) : undefined;\n return { file: file?.path ?? `[node:${nodeId}]`, imports_count: count };\n });\n\n // Widest interfaces (most implementors via heritage metadata)\n const allClassesAndInterfaces = store.db.prepare(\n \"SELECT name, kind FROM symbols WHERE kind IN ('class', 'interface') AND json_extract(metadata, '$.exported') = 1\",\n ).all() as { name: string; kind: string }[];\n\n const interfaceCounts: { name: string; implementor_count: number }[] = [];\n for (const sym of allClassesAndInterfaces) {\n if (sym.kind !== 'interface') continue;\n const impls = store.findImplementors(sym.name);\n if (impls.length > 0) {\n interfaceCounts.push({ name: sym.name, implementor_count: impls.length });\n }\n }\n interfaceCounts.sort((a, b) => b.implementor_count - a.implementor_count);\n\n return {\n summary: {\n total_files: stats.totalFiles,\n total_symbols: stats.totalSymbols,\n total_edges: stats.totalEdges,\n total_exports: deadResult.total_exports,\n dead_exports: deadResult.total_dead,\n untested_exports: untestedResult.total_untested,\n test_files: testFileCount,\n import_edges: importEdges.length,\n heritage_edges: heritageExtends.length + heritageImplements.length,\n test_covers_edges: testCovers.length,\n },\n dead_exports_top10: deadResult.dead_exports.slice(0, 10),\n untested_top10: untestedResult.untested.slice(0, 10),\n most_imported_files: mostImported,\n most_dependent_files: mostDependent,\n widest_interfaces: interfaceCounts.slice(0, 10),\n };\n}\n","import Database from 'better-sqlite3';\nimport { logger } from '../logger.js';\n\nconst SCHEMA_VERSION = 5;\n\nconst DDL = `\n-- ============================================================\n-- UNIFIED ADDRESS SPACE\n-- ============================================================\n\nCREATE TABLE IF NOT EXISTS node_types (\n id INTEGER PRIMARY KEY,\n name TEXT NOT NULL UNIQUE\n);\n\nCREATE TABLE IF NOT EXISTS edge_types (\n id INTEGER PRIMARY KEY,\n name TEXT NOT NULL UNIQUE,\n category TEXT NOT NULL,\n directed INTEGER NOT NULL DEFAULT 1,\n description TEXT\n);\n\nCREATE TABLE IF NOT EXISTS nodes (\n id INTEGER PRIMARY KEY,\n node_type TEXT NOT NULL REFERENCES node_types(name),\n ref_id INTEGER NOT NULL,\n UNIQUE(node_type, ref_id)\n);\n\n-- ============================================================\n-- CONCRETE ENTITY TABLES\n-- ============================================================\n\nCREATE TABLE IF NOT EXISTS files (\n id INTEGER PRIMARY KEY,\n path TEXT NOT NULL UNIQUE,\n language TEXT,\n framework_role TEXT,\n status TEXT DEFAULT 'ok',\n content_hash TEXT,\n byte_length INTEGER,\n indexed_at TEXT NOT NULL,\n metadata TEXT,\n workspace TEXT\n);\n\nCREATE TABLE IF NOT EXISTS symbols (\n id INTEGER PRIMARY KEY,\n file_id INTEGER NOT NULL REFERENCES files(id) ON DELETE CASCADE,\n symbol_id TEXT NOT NULL UNIQUE,\n name TEXT NOT NULL,\n kind TEXT NOT NULL,\n fqn TEXT,\n parent_id INTEGER REFERENCES symbols(id),\n signature TEXT,\n summary TEXT,\n byte_start INTEGER NOT NULL,\n byte_end INTEGER NOT NULL,\n line_start INTEGER,\n line_end INTEGER,\n metadata TEXT\n);\n\nCREATE TABLE IF NOT EXISTS routes (\n id INTEGER PRIMARY KEY,\n method TEXT NOT NULL,\n uri TEXT NOT NULL,\n name TEXT,\n handler TEXT,\n controller_symbol_id INTEGER REFERENCES symbols(id),\n middleware TEXT,\n metadata TEXT,\n file_id INTEGER REFERENCES files(id),\n line INTEGER\n);\n\nCREATE TABLE IF NOT EXISTS components (\n id INTEGER PRIMARY KEY,\n file_id INTEGER NOT NULL REFERENCES files(id) ON DELETE CASCADE,\n name TEXT NOT NULL,\n kind TEXT NOT NULL,\n props TEXT,\n emits TEXT,\n slots TEXT,\n composables TEXT,\n framework TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS migrations (\n id INTEGER PRIMARY KEY,\n file_id INTEGER NOT NULL REFERENCES files(id) ON DELETE CASCADE,\n table_name TEXT NOT NULL,\n operation TEXT NOT NULL,\n columns TEXT,\n indices TEXT,\n timestamp TEXT\n);\n\n-- ============================================================\n-- ORM MODELS (Mongoose + Sequelize)\n-- ============================================================\n\nCREATE TABLE IF NOT EXISTS orm_models (\n id INTEGER PRIMARY KEY,\n file_id INTEGER NOT NULL REFERENCES files(id) ON DELETE CASCADE,\n name TEXT NOT NULL,\n orm TEXT NOT NULL,\n collection_or_table TEXT,\n fields TEXT,\n options TEXT,\n metadata TEXT\n);\n\nCREATE TABLE IF NOT EXISTS orm_associations (\n id INTEGER PRIMARY KEY,\n source_model_id INTEGER NOT NULL REFERENCES orm_models(id) ON DELETE CASCADE,\n target_model_id INTEGER REFERENCES orm_models(id),\n target_model_name TEXT,\n kind TEXT NOT NULL,\n options TEXT,\n file_id INTEGER REFERENCES files(id),\n line INTEGER\n);\n\n-- ============================================================\n-- REACT NATIVE SCREENS\n-- ============================================================\n\nCREATE TABLE IF NOT EXISTS rn_screens (\n id INTEGER PRIMARY KEY,\n file_id INTEGER NOT NULL REFERENCES files(id) ON DELETE CASCADE,\n name TEXT NOT NULL,\n component_path TEXT,\n navigator_type TEXT,\n options TEXT,\n deep_link TEXT,\n metadata TEXT\n);\n\n-- ============================================================\n-- ENV VARS (keys only — values are never stored)\n-- ============================================================\n\nCREATE TABLE IF NOT EXISTS env_vars (\n id INTEGER PRIMARY KEY,\n file_id INTEGER NOT NULL REFERENCES files(id) ON DELETE CASCADE,\n key TEXT NOT NULL,\n value_type TEXT NOT NULL,\n value_format TEXT,\n comment TEXT,\n quoted INTEGER NOT NULL DEFAULT 0,\n line INTEGER\n);\n\nCREATE INDEX IF NOT EXISTS idx_env_vars_file ON env_vars(file_id);\nCREATE INDEX IF NOT EXISTS idx_env_vars_key ON env_vars(key);\n\n-- ============================================================\n-- UNIFIED EDGES\n-- ============================================================\n\nCREATE TABLE IF NOT EXISTS edges (\n id INTEGER PRIMARY KEY,\n source_node_id INTEGER NOT NULL REFERENCES nodes(id) ON DELETE CASCADE,\n target_node_id INTEGER NOT NULL REFERENCES nodes(id) ON DELETE CASCADE,\n edge_type_id INTEGER NOT NULL REFERENCES edge_types(id),\n resolved INTEGER NOT NULL DEFAULT 1,\n metadata TEXT,\n is_cross_ws INTEGER NOT NULL DEFAULT 0,\n UNIQUE(source_node_id, target_node_id, edge_type_id)\n);\n\nCREATE INDEX IF NOT EXISTS idx_edges_source ON edges(source_node_id);\nCREATE INDEX IF NOT EXISTS idx_edges_target ON edges(target_node_id);\nCREATE INDEX IF NOT EXISTS idx_edges_type ON edges(edge_type_id);\nCREATE INDEX IF NOT EXISTS idx_symbols_file ON symbols(file_id);\nCREATE INDEX IF NOT EXISTS idx_symbols_kind ON symbols(kind);\nCREATE INDEX IF NOT EXISTS idx_symbols_fqn ON symbols(fqn);\nCREATE INDEX IF NOT EXISTS idx_nodes_type ON nodes(node_type);\n\n-- ============================================================\n-- FTS5 FULL-TEXT SEARCH\n-- ============================================================\n\nCREATE VIRTUAL TABLE IF NOT EXISTS symbols_fts USING fts5(\n name, fqn, signature, summary,\n content=symbols, content_rowid=id\n);\n\n-- ============================================================\n-- FTS5 TRIGGERS (keep in sync)\n-- ============================================================\n\nCREATE TRIGGER IF NOT EXISTS symbols_ai AFTER INSERT ON symbols BEGIN\n INSERT INTO symbols_fts(rowid, name, fqn, signature, summary)\n VALUES (new.id, new.name, new.fqn, new.signature, new.summary);\nEND;\n\nCREATE TRIGGER IF NOT EXISTS symbols_ad AFTER DELETE ON symbols BEGIN\n INSERT INTO symbols_fts(symbols_fts, rowid, name, fqn, signature, summary)\n VALUES ('delete', old.id, old.name, old.fqn, old.signature, old.summary);\nEND;\n\nCREATE TRIGGER IF NOT EXISTS symbols_au AFTER UPDATE ON symbols BEGIN\n INSERT INTO symbols_fts(symbols_fts, rowid, name, fqn, signature, summary)\n VALUES ('delete', old.id, old.name, old.fqn, old.signature, old.summary);\n INSERT INTO symbols_fts(rowid, name, fqn, signature, summary)\n VALUES (new.id, new.name, new.fqn, new.signature, new.summary);\nEND;\n\n-- ============================================================\n-- AI EMBEDDINGS (optional, for Phase 7)\n-- ============================================================\n\nCREATE TABLE IF NOT EXISTS symbol_embeddings (\n symbol_id INTEGER PRIMARY KEY REFERENCES symbols(id) ON DELETE CASCADE,\n embedding BLOB NOT NULL\n);\n\n-- ============================================================\n-- AI INFERENCE CACHE (optional, for cached summarization)\n-- ============================================================\n\nCREATE TABLE IF NOT EXISTS inference_cache (\n cache_key TEXT PRIMARY KEY,\n model TEXT NOT NULL,\n prompt_hash TEXT NOT NULL,\n response TEXT NOT NULL,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n ttl_days INTEGER DEFAULT 90\n);\nCREATE INDEX IF NOT EXISTS idx_inference_cache_model ON inference_cache(model);\n\n-- ============================================================\n-- SCHEMA VERSION\n-- ============================================================\n\nCREATE TABLE IF NOT EXISTS schema_meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n);\n\n-- Applied migration log (one row per migration that has been run)\nCREATE TABLE IF NOT EXISTS schema_migrations (\n version INTEGER PRIMARY KEY,\n applied_at TEXT NOT NULL\n);\n`;\n\nconst SEED_NODE_TYPES = ['symbol', 'file', 'route', 'component', 'migration', 'orm_model', 'rn_screen'];\n\nconst SEED_EDGE_TYPES = [\n // Core edges (added in v2 migration, must also be in seed for fresh DBs)\n { name: 'calls', category: 'core', description: 'Direct function/method call' },\n { name: 'references', category: 'core', description: 'Symbol reference (read/write)' },\n { name: 'unresolved', category: 'core', description: 'Phantom edge for unresolved targets' },\n { name: 'test_covers', category: 'core', description: 'Test file covers a symbol or file' },\n { name: 'esm_imports', category: 'core', description: 'ESM import (file→file)' },\n { name: 'graphql_resolves', category: 'graphql', description: 'Resolver implements a GraphQL field' },\n { name: 'graphql_references_type', category: 'graphql', description: 'Resolver/field references a GraphQL type' },\n // PHP language edges\n { name: 'imports', category: 'php', description: 'PHP use/import statement' },\n { name: 'extends', category: 'php', description: 'Class/interface extends' },\n { name: 'implements', category: 'php', description: 'Class implements interface' },\n { name: 'uses_trait', category: 'php', description: 'Class uses trait' },\n // TypeScript language edges\n { name: 'ts_extends', category: 'typescript', description: 'TypeScript class/interface extends' },\n { name: 'ts_implements', category: 'typescript', description: 'TypeScript class implements interface' },\n // Laravel framework edges\n { name: 'routes_to', category: 'laravel', description: 'Route -> Controller' },\n { name: 'has_many', category: 'laravel', description: 'Eloquent hasMany' },\n { name: 'belongs_to', category: 'laravel', description: 'Eloquent belongsTo' },\n { name: 'belongs_to_many', category: 'laravel', description: 'Eloquent belongsToMany' },\n { name: 'has_one', category: 'laravel', description: 'Eloquent hasOne' },\n { name: 'morphs_to', category: 'laravel', description: 'Eloquent morphTo' },\n { name: 'validates_with', category: 'laravel', description: 'Controller -> FormRequest' },\n { name: 'dispatches', category: 'laravel', description: 'Dispatches event/job' },\n { name: 'listens_to', category: 'laravel', description: 'Listener -> Event' },\n { name: 'middleware_guards', category: 'laravel', description: 'Route -> Middleware' },\n { name: 'migrates', category: 'laravel', description: 'Migration -> table' },\n // Vue framework edges\n { name: 'renders_component', category: 'vue', description: 'Parent component renders child in template' },\n { name: 'uses_composable', category: 'vue', description: 'Component calls a composable function' },\n { name: 'provides_slot', category: 'vue', description: 'Component provides a named slot' },\n // Inertia edges\n { name: 'inertia_renders', category: 'inertia', description: 'Controller renders Vue page via Inertia' },\n { name: 'passes_props', category: 'inertia', description: 'Controller passes props to Vue page' },\n // Nuxt edges\n { name: 'nuxt_auto_imports', category: 'nuxt', description: 'Auto-imported composable' },\n { name: 'api_calls', category: 'nuxt', description: 'fetch/useFetch API call' },\n { name: 'nuxt_shared_import', category: 'nuxt', description: 'Auto-imported shared utility or type' },\n // Blade edges\n { name: 'blade_extends', category: 'blade', description: '@extends directive' },\n { name: 'blade_includes', category: 'blade', description: '@include directive' },\n { name: 'blade_component', category: 'blade', description: '<x-component> or @component' },\n // Nova edges\n { name: 'nova_resource_for', category: 'nova', description: 'Nova Resource → Eloquent Model' },\n { name: 'nova_field_relationship', category: 'nova', description: 'Nova Resource → related Nova Resource via field' },\n { name: 'nova_action_on', category: 'nova', description: 'Action → Resource' },\n { name: 'nova_filter_on', category: 'nova', description: 'Filter → Resource' },\n { name: 'nova_lens_on', category: 'nova', description: 'Lens → Resource' },\n { name: 'nova_metric_queries', category: 'nova', description: 'Metric → Eloquent Model' },\n // Filament edges\n { name: 'filament_resource_for', category: 'filament', description: 'Resource → Eloquent Model' },\n { name: 'filament_relation_manager', category: 'filament', description: 'Resource → RelationManager' },\n { name: 'filament_form_relationship', category: 'filament', description: 'Form field →relationship() → Model' },\n { name: 'filament_page_for', category: 'filament', description: 'Page registered on Resource' },\n { name: 'filament_panel_registers', category: 'filament', description: 'PanelProvider → Resource/Page/Widget' },\n { name: 'filament_widget_queries', category: 'filament', description: 'Widget → Eloquent Model' },\n // Livewire edges\n { name: 'livewire_renders', category: 'livewire', description: 'Component class → Blade view' },\n { name: 'livewire_dispatches', category: 'livewire', description: 'Component dispatches event' },\n { name: 'livewire_listens', category: 'livewire', description: 'Component listens for event' },\n { name: 'livewire_child_of', category: 'livewire', description: 'Blade <livewire:child/> → Component' },\n { name: 'livewire_uses_model', category: 'livewire', description: 'Component → Eloquent Model' },\n { name: 'livewire_form', category: 'livewire', description: 'Component → Form class (v3)' },\n { name: 'livewire_action', category: 'livewire', description: 'wire:click → Component method' },\n // NestJS edges\n { name: 'nest_module_imports', category: 'nestjs', description: 'Module imports another module' },\n { name: 'nest_provides', category: 'nestjs', description: 'Module provides a service' },\n { name: 'nest_injects', category: 'nestjs', description: 'Constructor dependency injection' },\n { name: 'nest_guards', category: 'nestjs', description: 'UseGuards on controller/method' },\n { name: 'nest_pipes', category: 'nestjs', description: 'UsePipes on controller/method' },\n { name: 'nest_interceptors', category: 'nestjs', description: 'UseInterceptors on controller/method' },\n { name: 'nest_gateway_event', category: 'nestjs', description: 'WebSocket gateway @SubscribeMessage handler' },\n { name: 'nest_message_pattern', category: 'nestjs', description: 'Microservice @MessagePattern handler' },\n { name: 'nest_event_pattern', category: 'nestjs', description: 'Microservice @EventPattern handler' },\n // Next.js edges\n { name: 'next_renders_page', category: 'nextjs', description: 'Layout renders page' },\n { name: 'next_server_action', category: 'nextjs', description: 'Server action reference' },\n { name: 'next_middleware', category: 'nextjs', description: 'Middleware applies to routes' },\n { name: 'next_parallel_slot', category: 'nextjs', description: 'Parallel route slot' },\n { name: 'next_intercepting', category: 'nextjs', description: 'Intercepting route' },\n { name: 'next_data_fetching', category: 'nextjs', description: 'Pages Router data fetching function' },\n { name: 'next_template', category: 'nextjs', description: 'Template component for route segment' },\n // Express edges\n { name: 'express_route', category: 'express', description: 'Express route handler' },\n { name: 'express_middleware', category: 'express', description: 'Express middleware' },\n { name: 'express_mounts', category: 'express', description: 'Router mount via app.use' },\n { name: 'express_error_handler', category: 'express', description: '4-arg error handling middleware' },\n { name: 'express_param_handler', category: 'express', description: 'app.param() route parameter handler' },\n // Mongoose edges\n { name: 'mongoose_references', category: 'mongoose', description: 'ObjectId ref to another model' },\n { name: 'mongoose_has_virtual', category: 'mongoose', description: 'Schema virtual field' },\n { name: 'mongoose_has_middleware', category: 'mongoose', description: 'Schema pre/post hook' },\n { name: 'mongoose_has_method', category: 'mongoose', description: 'Schema instance method' },\n { name: 'mongoose_has_static', category: 'mongoose', description: 'Schema static method' },\n { name: 'mongoose_discriminates', category: 'mongoose', description: 'Model discriminator' },\n { name: 'mongoose_has_index', category: 'mongoose', description: 'Schema index' },\n { name: 'mongoose_uses_plugin', category: 'mongoose', description: 'Schema plugin' },\n // Sequelize edges\n { name: 'sequelize_has_many', category: 'sequelize', description: 'Sequelize hasMany association' },\n { name: 'sequelize_belongs_to', category: 'sequelize', description: 'Sequelize belongsTo association' },\n { name: 'sequelize_belongs_to_many', category: 'sequelize', description: 'Sequelize belongsToMany association' },\n { name: 'sequelize_has_one', category: 'sequelize', description: 'Sequelize hasOne association' },\n { name: 'sequelize_has_hook', category: 'sequelize', description: 'Sequelize lifecycle hook' },\n { name: 'sequelize_has_scope', category: 'sequelize', description: 'Sequelize named scope' },\n { name: 'sequelize_migrates', category: 'sequelize', description: 'Migration changes table schema' },\n // React Native edges\n { name: 'rn_navigates_to', category: 'react-native', description: 'navigation.navigate() to screen' },\n { name: 'rn_screen_in_navigator', category: 'react-native', description: 'Screen registered in navigator' },\n { name: 'rn_uses_native_module', category: 'react-native', description: 'Uses NativeModules/TurboModuleRegistry' },\n { name: 'rn_platform_specific', category: 'react-native', description: 'Platform-specific file variant' },\n { name: 'rn_deep_links_to', category: 'react-native', description: 'Deep link maps to screen' },\n { name: 'expo_route', category: 'expo-router', description: 'Expo Router file-based route' },\n { name: 'expo_layout', category: 'expo-router', description: 'Expo Router layout file' },\n // Python language edges\n { name: 'py_imports', category: 'python', description: 'Python import statement' },\n { name: 'py_reexports', category: 'python', description: '__init__.py re-export' },\n { name: 'py_param_type', category: 'python', description: 'Function parameter type annotation' },\n { name: 'py_return_type', category: 'python', description: 'Function return type annotation' },\n { name: 'py_inherits', category: 'python', description: 'Class inheritance' },\n { name: 'py_uses_decorator', category: 'python', description: 'Function/class uses decorator' },\n // Django edges\n { name: 'django_url_routes_to', category: 'django', description: 'URL pattern routes to view' },\n { name: 'django_includes_urls', category: 'django', description: 'include() sub-URL config' },\n { name: 'django_view_uses_model', category: 'django', description: 'View references model' },\n { name: 'django_view_template', category: 'django', description: 'View renders template' },\n { name: 'django_signal_receiver', category: 'django', description: '@receiver signal handler' },\n { name: 'django_admin_registers', category: 'django', description: 'Admin registers model' },\n { name: 'django_form_meta_model', category: 'django', description: 'ModelForm Meta.model' },\n { name: 'django_migrates', category: 'django', description: 'Django migration operation' },\n // FastAPI edges\n { name: 'fastapi_route', category: 'fastapi', description: 'FastAPI route decorator' },\n { name: 'fastapi_depends', category: 'fastapi', description: 'Depends() dependency injection' },\n { name: 'fastapi_request_model', category: 'fastapi', description: 'Request body Pydantic model' },\n { name: 'fastapi_response_model', category: 'fastapi', description: 'response_model parameter' },\n { name: 'fastapi_router_mounts', category: 'fastapi', description: 'include_router() mount' },\n // Flask edges\n { name: 'flask_route', category: 'flask', description: 'Flask @app.route decorator' },\n { name: 'flask_blueprint_mounts', category: 'flask', description: 'register_blueprint() mount' },\n { name: 'flask_before_request', category: 'flask', description: '@before_request hook' },\n { name: 'flask_error_handler', category: 'flask', description: '@errorhandler hook' },\n // SQLAlchemy edges\n { name: 'sqla_relationship', category: 'sqlalchemy', description: 'SQLAlchemy relationship()' },\n { name: 'sqla_fk', category: 'sqlalchemy', description: 'ForeignKey reference' },\n { name: 'sqla_migrates', category: 'sqlalchemy', description: 'Alembic migration operation' },\n // DRF edges\n { name: 'drf_serializer_model', category: 'drf', description: 'ModelSerializer Meta.model' },\n { name: 'drf_viewset_serializer', category: 'drf', description: 'ViewSet serializer_class' },\n { name: 'drf_router_registers', category: 'drf', description: 'router.register() ViewSet' },\n { name: 'drf_permission_guards', category: 'drf', description: 'permission_classes on ViewSet' },\n // Pydantic edges\n { name: 'pydantic_field_type', category: 'pydantic', description: 'BaseModel field type reference' },\n { name: 'pydantic_from_orm', category: 'pydantic', description: 'Model with from_attributes → ORM model' },\n // Celery edges\n { name: 'celery_task_registered', category: 'celery', description: '@app.task / @shared_task registration' },\n { name: 'celery_beat_schedule', category: 'celery', description: 'Beat schedule task entry' },\n { name: 'celery_dispatches', category: 'celery', description: '.delay() / .apply_async() dispatch' },\n // Pennant (feature flags) edges\n { name: 'feature_defined_in', category: 'pennant', description: 'Feature flag defined via Feature::define()' },\n { name: 'feature_checked_by', category: 'pennant', description: 'Feature flag checked in PHP/Blade' },\n { name: 'feature_gates_route', category: 'pennant', description: 'Route protected by features middleware' },\n // Broadcasting / Reverb edges\n { name: 'broadcasts_on', category: 'broadcasting', description: 'Event broadcasts on a channel' },\n { name: 'channel_authorized_by', category: 'broadcasting', description: 'Channel authorization callback or class' },\n { name: 'broadcast_as', category: 'broadcasting', description: 'Event broadcast name override' },\n // laravel-data edges\n { name: 'data_wraps', category: 'laravel-data', description: 'Data class wraps an Eloquent model' },\n { name: 'data_property_type', category: 'laravel-data', description: 'Data class property references another Data class' },\n { name: 'data_collection', category: 'laravel-data', description: 'DataCollection<T> references a Data class' },\n // State management (Zustand / Redux Toolkit)\n { name: 'zustand_store', category: 'state-management', description: 'Zustand store definition' },\n { name: 'redux_slice', category: 'state-management', description: 'Redux Toolkit slice definition' },\n { name: 'dispatches_action', category: 'state-management', description: 'Component dispatches a Redux/Zustand action' },\n { name: 'selects_state', category: 'state-management', description: 'Component selects state from store' },\n // tRPC edges\n { name: 'trpc_procedure', category: 'trpc', description: 'Procedure defined in router' },\n // Fastify edges\n { name: 'fastify_route', category: 'fastify', description: 'Route handler' },\n { name: 'fastify_hook', category: 'fastify', description: 'Lifecycle hook' },\n { name: 'fastify_plugin', category: 'fastify', description: 'Plugin registration' },\n // Socket.io edges\n { name: 'socketio_event', category: 'socketio', description: 'Event listener/emitter' },\n { name: 'socketio_namespace', category: 'socketio', description: 'Namespace definition' },\n // React (standalone) edges\n { name: 'react_renders', category: 'react', description: 'Parent component renders child via JSX' },\n { name: 'react_context_provides', category: 'react', description: 'Context.Provider usage' },\n { name: 'react_context_consumes', category: 'react', description: 'useContext() or use() call' },\n { name: 'react_lazy_loads', category: 'react', description: 'React.lazy(() => import(\"./X\"))' },\n { name: 'react_custom_hook_uses', category: 'react', description: 'Component calls a custom hook' },\n { name: 'react_use_client', category: 'react', description: \"'use client' directive (React 19)\" },\n { name: 'react_use_server', category: 'react', description: \"'use server' directive (React 19)\" },\n // Hono edges\n { name: 'hono_route', category: 'hono', description: 'Hono route handler' },\n { name: 'hono_middleware', category: 'hono', description: 'Hono middleware usage' },\n // Data fetching (React Query / SWR) edges\n { name: 'fetches_endpoint', category: 'data-fetching', description: 'useQuery/useSWR call referencing an API endpoint' },\n // Zod edges\n { name: 'zod_schema', category: 'zod', description: 'Zod schema definition' },\n // Testing framework edges\n { name: 'test_covers_route', category: 'testing', description: 'Test file visits/requests an API route' },\n { name: 'test_covers_component', category: 'testing', description: 'Test file mounts/renders a component' },\n { name: 'test_imports_module', category: 'testing', description: 'Test file imports the module under test' },\n // Workspace edges\n { name: 'workspace_import', category: 'workspace', description: 'Cross-workspace import' },\n { name: 'api_call', category: 'workspace', description: 'Cross-workspace API call' },\n { name: 'type_import', category: 'workspace', description: 'Cross-workspace type import' },\n];\n\n/**\n * Incremental migrations, keyed by target schema version.\n * Each entry runs exactly once, in version order.\n * Add new entries here whenever the schema changes.\n */\nconst MIGRATIONS: Record<number, (db: Database.Database) => void> = {\n 2: (db) => {\n // v2: add schema_migrations table (already in DDL via CREATE TABLE IF NOT EXISTS,\n // but mark it as applied for all future installs)\n db.exec(`\n INSERT OR IGNORE INTO edge_types (name, category, directed, description)\n VALUES\n ('calls', 'core', 1, 'Direct function/method call'),\n ('references', 'core', 1, 'Symbol reference (read/write)'),\n ('test_covers', 'core', 1, 'Test file covers a symbol or file'),\n ('graphql_resolves', 'graphql', 1, 'Resolver implements a GraphQL field'),\n ('graphql_references_type', 'graphql', 1, 'Resolver/field references a GraphQL type');\n `);\n },\n 3: (db) => {\n // v3: TypeScript heritage edges — enables find_references for extends/implements\n db.exec(`\n INSERT OR IGNORE INTO edge_types (name, category, directed, description)\n VALUES\n ('ts_extends', 'typescript', 1, 'TypeScript class/interface extends'),\n ('ts_implements', 'typescript', 1, 'TypeScript class implements interface');\n `);\n },\n 4: (db) => {\n // v4: AI inference cache for summarization pipeline\n db.exec(`\n CREATE TABLE IF NOT EXISTS inference_cache (\n cache_key TEXT PRIMARY KEY,\n model TEXT NOT NULL,\n prompt_hash TEXT NOT NULL,\n response TEXT NOT NULL,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n ttl_days INTEGER DEFAULT 90\n );\n CREATE INDEX IF NOT EXISTS idx_inference_cache_model ON inference_cache(model);\n `);\n },\n 5: (db) => {\n // v5: env_vars table — stores .env keys with type metadata, never stores values\n db.exec(`\n CREATE TABLE IF NOT EXISTS env_vars (\n id INTEGER PRIMARY KEY,\n file_id INTEGER NOT NULL REFERENCES files(id) ON DELETE CASCADE,\n key TEXT NOT NULL,\n value_type TEXT NOT NULL,\n value_format TEXT,\n comment TEXT,\n quoted INTEGER NOT NULL DEFAULT 0,\n line INTEGER\n );\n CREATE INDEX IF NOT EXISTS idx_env_vars_file ON env_vars(file_id);\n CREATE INDEX IF NOT EXISTS idx_env_vars_key ON env_vars(key);\n `);\n },\n};\n\nfunction runMigrations(db: Database.Database, fromVersion: number): void {\n const versions = Object.keys(MIGRATIONS)\n .map(Number)\n .filter((v) => v > fromVersion)\n .sort((a, b) => a - b);\n\n if (versions.length === 0) return;\n\n const insertMigration = db.prepare(\n \"INSERT OR IGNORE INTO schema_migrations (version, applied_at) VALUES (?, ?)\",\n );\n const updateVersion = db.prepare(\n \"INSERT OR REPLACE INTO schema_meta (key, value) VALUES ('schema_version', ?)\",\n );\n\n for (const version of versions) {\n logger.info({ version }, 'Running schema migration');\n db.transaction(() => {\n MIGRATIONS[version](db);\n insertMigration.run(version, new Date().toISOString());\n updateVersion.run(String(version));\n })();\n logger.info({ version }, 'Schema migration applied');\n }\n}\n\nexport function initializeDatabase(dbPath: string): Database.Database {\n const db = new Database(dbPath);\n\n // WAL mode for concurrent reads\n db.pragma('journal_mode = WAL');\n db.pragma('foreign_keys = ON');\n db.pragma('busy_timeout = 5000');\n\n db.exec(DDL);\n\n // Check schema version and run any pending migrations\n const versionRow = db.prepare(\"SELECT value FROM schema_meta WHERE key = 'schema_version'\").get() as { value: string } | undefined;\n\n if (!versionRow) {\n // Fresh database — seed and stamp with current version\n seedDatabase(db);\n db.prepare(\"INSERT INTO schema_meta (key, value) VALUES ('schema_version', ?)\").run(String(SCHEMA_VERSION));\n // Mark all migrations as already applied (they're baked into seed/DDL)\n const insertMigration = db.prepare(\n \"INSERT OR IGNORE INTO schema_migrations (version, applied_at) VALUES (?, ?)\",\n );\n const now = new Date().toISOString();\n for (const v of Object.keys(MIGRATIONS).map(Number)) {\n insertMigration.run(v, now);\n }\n } else {\n const currentVersion = parseInt(versionRow.value, 10);\n if (currentVersion < SCHEMA_VERSION) {\n logger.info({ from: currentVersion, to: SCHEMA_VERSION }, 'Schema upgrade required');\n runMigrations(db, currentVersion);\n }\n }\n\n logger.debug({ dbPath, schemaVersion: SCHEMA_VERSION }, 'Database initialized');\n return db;\n}\n\nfunction seedDatabase(db: Database.Database): void {\n const insertNodeType = db.prepare('INSERT OR IGNORE INTO node_types (name) VALUES (?)');\n for (const name of SEED_NODE_TYPES) {\n insertNodeType.run(name);\n }\n\n const insertEdgeType = db.prepare(\n 'INSERT OR IGNORE INTO edge_types (name, category, directed, description) VALUES (?, ?, 1, ?)',\n );\n for (const et of SEED_EDGE_TYPES) {\n insertEdgeType.run(et.name, et.category, et.description);\n }\n}\n\nexport function getTableNames(db: Database.Database): string[] {\n const rows = db.prepare(\n \"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name\",\n ).all() as { name: string }[];\n return rows.map((r) => r.name);\n}\n\nexport function getVirtualTableNames(db: Database.Database): string[] {\n const rows = db.prepare(\n \"SELECT name FROM sqlite_master WHERE type='table' AND sql LIKE '%VIRTUAL%' ORDER BY name\",\n ).all() as { name: string }[];\n return rows.map((r) => r.name);\n}\n","import type Database from 'better-sqlite3';\nimport type { RawSymbol, RawEdge, RawRoute, RawComponent, RawMigration, RawOrmModel, RawOrmAssociation, RawRnScreen } from '../plugin-api/types.js';\nimport { ok, err, type TraceMcpResult } from '../errors.js';\nimport { dbError } from '../errors.js';\n\nexport class Store {\n constructor(public readonly db: Database.Database) {}\n\n // --- Files ---\n\n insertFile(\n path: string,\n language: string | null,\n contentHash: string | null,\n byteLength: number | null,\n workspace?: string | null,\n ): number {\n const result = this.db.prepare(\n `INSERT INTO files (path, language, content_hash, byte_length, indexed_at, workspace)\n VALUES (?, ?, ?, ?, datetime('now'), ?)`,\n ).run(path, language, contentHash, byteLength, workspace ?? null);\n const fileId = Number(result.lastInsertRowid);\n\n // Create node in unified address space\n this.createNode('file', fileId);\n return fileId;\n }\n\n getFile(path: string): FileRow | undefined {\n return this.db.prepare('SELECT * FROM files WHERE path = ?').get(path) as FileRow | undefined;\n }\n\n getFileById(id: number): FileRow | undefined {\n return this.db.prepare('SELECT * FROM files WHERE id = ?').get(id) as FileRow | undefined;\n }\n\n getAllFiles(): FileRow[] {\n return this.db.prepare('SELECT * FROM files').all() as FileRow[];\n }\n\n updateFileWorkspace(fileId: number, workspace: string): void {\n this.db.prepare('UPDATE files SET workspace = ? WHERE id = ?').run(workspace, fileId);\n }\n\n getFilesByWorkspace(workspace: string): FileRow[] {\n return this.db.prepare('SELECT * FROM files WHERE workspace = ?').all(workspace) as FileRow[];\n }\n\n updateFileHash(fileId: number, hash: string, byteLength: number): void {\n this.db.prepare(\n \"UPDATE files SET content_hash = ?, byte_length = ?, indexed_at = datetime('now') WHERE id = ?\",\n ).run(hash, byteLength, fileId);\n }\n\n updateFileStatus(fileId: number, status: string, frameworkRole?: string): void {\n this.db.prepare(\n 'UPDATE files SET status = ?, framework_role = COALESCE(?, framework_role) WHERE id = ?',\n ).run(status, frameworkRole ?? null, fileId);\n }\n\n deleteFile(fileId: number): void {\n // Cascade deletes symbols, edges via nodes\n this.deleteEdgesForFileNodes(fileId);\n this.deleteEntitiesByFile(fileId);\n this.db.prepare('DELETE FROM nodes WHERE node_type = ? AND ref_id = ?').run('file', fileId);\n this.db.prepare('DELETE FROM files WHERE id = ?').run(fileId);\n }\n\n /** Delete routes, components, migrations, ORM models, and RN screens for a file (and their nodes). */\n deleteEntitiesByFile(fileId: number): void {\n for (const [table, nodeType] of [\n ['routes', 'route'],\n ['components', 'component'],\n ['migrations', 'migration'],\n ['orm_models', 'orm_model'],\n ['rn_screens', 'rn_screen'],\n ] as const) {\n const ids = this.db.prepare(`SELECT id FROM ${table} WHERE file_id = ?`).all(fileId) as { id: number }[];\n if (ids.length > 0) {\n const placeholders = ids.map(() => '?').join(',');\n const idValues = ids.map((r) => r.id);\n this.db.prepare(`DELETE FROM nodes WHERE node_type = ? AND ref_id IN (${placeholders})`).run(nodeType, ...idValues);\n this.db.prepare(`DELETE FROM ${table} WHERE file_id = ?`).run(fileId);\n }\n }\n }\n\n // --- Symbols ---\n\n insertSymbol(fileId: number, sym: RawSymbol): number {\n const parentId = sym.parentSymbolId\n ? (this.db.prepare('SELECT id FROM symbols WHERE symbol_id = ?').get(sym.parentSymbolId) as { id: number } | undefined)?.id ?? null\n : null;\n\n const result = this.db.prepare(\n `INSERT OR REPLACE INTO symbols (file_id, symbol_id, name, kind, fqn, parent_id, signature, byte_start, byte_end, line_start, line_end, metadata)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n fileId,\n sym.symbolId,\n sym.name,\n sym.kind,\n sym.fqn ?? null,\n parentId,\n sym.signature ?? null,\n sym.byteStart,\n sym.byteEnd,\n sym.lineStart ?? null,\n sym.lineEnd ?? null,\n sym.metadata ? JSON.stringify(sym.metadata) : null,\n );\n\n const symbolId = Number(result.lastInsertRowid);\n this.createNode('symbol', symbolId);\n return symbolId;\n }\n\n insertSymbols(fileId: number, symbols: RawSymbol[]): number[] {\n return this.db.transaction(() => {\n return symbols.map((s) => this.insertSymbol(fileId, s));\n })();\n }\n\n deleteSymbolsByFile(fileId: number): void {\n // Single subquery instead of N individual per-symbol DELETEs\n this.db.prepare(\n `DELETE FROM nodes WHERE node_type = 'symbol'\n AND ref_id IN (SELECT id FROM symbols WHERE file_id = ?)`,\n ).run(fileId);\n this.db.prepare('DELETE FROM symbols WHERE file_id = ?').run(fileId);\n }\n\n getSymbolsByFile(fileId: number): SymbolRow[] {\n return this.db.prepare('SELECT * FROM symbols WHERE file_id = ? ORDER BY byte_start').all(fileId) as SymbolRow[];\n }\n\n getSymbolBySymbolId(symbolId: string): SymbolRow | undefined {\n return this.db.prepare('SELECT * FROM symbols WHERE symbol_id = ?').get(symbolId) as SymbolRow | undefined;\n }\n\n getSymbolByFqn(fqn: string): SymbolRow | undefined {\n return this.db.prepare('SELECT * FROM symbols WHERE fqn = ?').get(fqn) as SymbolRow | undefined;\n }\n\n // --- Nodes ---\n\n createNode(nodeType: string, refId: number): number {\n const existing = this.db.prepare(\n 'SELECT id FROM nodes WHERE node_type = ? AND ref_id = ?',\n ).get(nodeType, refId) as { id: number } | undefined;\n\n if (existing) return existing.id;\n\n const result = this.db.prepare(\n 'INSERT INTO nodes (node_type, ref_id) VALUES (?, ?)',\n ).run(nodeType, refId);\n return Number(result.lastInsertRowid);\n }\n\n getNodeId(nodeType: string, refId: number): number | undefined {\n const row = this.db.prepare(\n 'SELECT id FROM nodes WHERE node_type = ? AND ref_id = ?',\n ).get(nodeType, refId) as { id: number } | undefined;\n return row?.id;\n }\n\n // --- Edges ---\n\n insertEdge(\n sourceNodeId: number,\n targetNodeId: number,\n edgeTypeName: string,\n resolved = true,\n metadata?: Record<string, unknown>,\n isCrossWs = false,\n ): TraceMcpResult<number> {\n const edgeType = this.db.prepare('SELECT id FROM edge_types WHERE name = ?').get(edgeTypeName) as { id: number } | undefined;\n if (!edgeType) {\n return err(dbError(`Unknown edge type: ${edgeTypeName}`));\n }\n\n try {\n const result = this.db.prepare(\n `INSERT OR IGNORE INTO edges (source_node_id, target_node_id, edge_type_id, resolved, metadata, is_cross_ws)\n VALUES (?, ?, ?, ?, ?, ?)`,\n ).run(sourceNodeId, targetNodeId, edgeType.id, resolved ? 1 : 0, metadata ? JSON.stringify(metadata) : null, isCrossWs ? 1 : 0);\n return ok(Number(result.lastInsertRowid));\n } catch (e) {\n return err(dbError(e instanceof Error ? e.message : String(e)));\n }\n }\n\n deleteEdgesForFileNodes(fileId: number): void {\n // Collect all node IDs for this file's symbols + file node in a single subquery\n this.db.prepare(`\n DELETE FROM edges WHERE source_node_id IN (\n SELECT n.id FROM nodes n\n WHERE (n.node_type = 'file' AND n.ref_id = ?)\n OR (n.node_type = 'symbol' AND n.ref_id IN (SELECT id FROM symbols WHERE file_id = ?))\n ) OR target_node_id IN (\n SELECT n.id FROM nodes n\n WHERE (n.node_type = 'file' AND n.ref_id = ?)\n OR (n.node_type = 'symbol' AND n.ref_id IN (SELECT id FROM symbols WHERE file_id = ?))\n )\n `).run(fileId, fileId, fileId, fileId);\n }\n\n // --- Graph Traversal ---\n\n traverseEdges(startNodeId: number, direction: 'outgoing' | 'incoming', depth: number): EdgeRow[] {\n const directionCol = direction === 'outgoing' ? 'source_node_id' : 'target_node_id';\n const otherCol = direction === 'outgoing' ? 'target_node_id' : 'source_node_id';\n\n const sql = `\n WITH RECURSIVE traverse(node_id, depth) AS (\n SELECT ?, 0\n UNION ALL\n SELECT e.${otherCol}, t.depth + 1\n FROM edges e\n JOIN traverse t ON e.${directionCol} = t.node_id\n WHERE t.depth < ?\n )\n SELECT DISTINCT e.*\n FROM traverse t\n JOIN edges e ON e.${directionCol} = t.node_id\n WHERE t.depth < ?\n `;\n\n return this.db.prepare(sql).all(startNodeId, depth, depth) as EdgeRow[];\n }\n\n // --- Routes ---\n\n insertRoute(route: RawRoute, fileId: number): number {\n // controller_symbol_id is an INTEGER FK to symbols.id\n // If controllerSymbolId is a string FQN ref, we store null for the FK\n // and encode it in the middleware JSON as { middleware: [...], controllerRef: \"...\" }\n let resolvedControllerSymId: number | null = null;\n let controllerRef: string | undefined;\n\n if (route.controllerSymbolId) {\n const asNum = Number(route.controllerSymbolId);\n if (!isNaN(asNum)) {\n resolvedControllerSymId = asNum;\n } else {\n controllerRef = route.controllerSymbolId;\n }\n }\n\n // Encode middleware + optional controllerRef together\n const mwArray = route.middleware ?? [];\n let middlewareJson: string | null = null;\n if (controllerRef || mwArray.length > 0) {\n middlewareJson = JSON.stringify({\n middleware: mwArray,\n ...(controllerRef ? { controllerRef } : {}),\n });\n }\n\n const result = this.db.prepare(\n `INSERT INTO routes (method, uri, name, controller_symbol_id, middleware, file_id, line)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n route.method,\n route.uri,\n route.name ?? null,\n resolvedControllerSymId,\n middlewareJson,\n fileId,\n route.line ?? null,\n );\n const routeId = Number(result.lastInsertRowid);\n this.createNode('route', routeId);\n return routeId;\n }\n\n // --- Components ---\n\n insertComponent(comp: RawComponent, fileId: number): number {\n const result = this.db.prepare(\n `INSERT INTO components (file_id, name, kind, props, emits, slots, composables, framework)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n fileId,\n comp.name,\n comp.kind,\n comp.props ? JSON.stringify(comp.props) : null,\n comp.emits ? JSON.stringify(comp.emits) : null,\n comp.slots ? JSON.stringify(comp.slots) : null,\n comp.composables ? JSON.stringify(comp.composables) : null,\n comp.framework,\n );\n const compId = Number(result.lastInsertRowid);\n this.createNode('component', compId);\n return compId;\n }\n\n getComponentByFileId(fileId: number): ComponentRow | undefined {\n return this.db.prepare('SELECT * FROM components WHERE file_id = ?').get(fileId) as ComponentRow | undefined;\n }\n\n getComponentByName(name: string): ComponentRow | undefined {\n return this.db.prepare('SELECT * FROM components WHERE name = ?').get(name) as ComponentRow | undefined;\n }\n\n getAllComponents(): ComponentRow[] {\n return this.db.prepare('SELECT * FROM components').all() as ComponentRow[];\n }\n\n /** Ensure an edge type exists in the database, inserting if missing. */\n ensureEdgeType(name: string, category: string, description: string): void {\n this.db.prepare(\n 'INSERT OR IGNORE INTO edge_types (name, category, directed, description) VALUES (?, ?, 1, ?)',\n ).run(name, category, description);\n }\n\n /** Get the edge type name by its id */\n getEdgeTypeName(edgeTypeId: number): string | undefined {\n const row = this.db.prepare('SELECT name FROM edge_types WHERE id = ?').get(edgeTypeId) as { name: string } | undefined;\n return row?.name;\n }\n\n /** Reverse-lookup: find which symbol/file a node refers to */\n getNodeRef(nodeId: number): { nodeType: string; refId: number } | undefined {\n return this.db.prepare('SELECT node_type AS nodeType, ref_id AS refId FROM nodes WHERE id = ?').get(nodeId) as { nodeType: string; refId: number } | undefined;\n }\n\n // --- Migrations ---\n\n insertMigration(mig: RawMigration, fileId: number): number {\n const result = this.db.prepare(\n `INSERT INTO migrations (file_id, table_name, operation, columns, indices, timestamp)\n VALUES (?, ?, ?, ?, ?, ?)`,\n ).run(\n fileId,\n mig.tableName,\n mig.operation,\n mig.columns ? JSON.stringify(mig.columns) : null,\n mig.indices ? JSON.stringify(mig.indices) : null,\n mig.timestamp ?? null,\n );\n const migId = Number(result.lastInsertRowid);\n this.createNode('migration', migId);\n return migId;\n }\n\n // --- Route queries ---\n\n getRouteByUriAndMethod(uri: string, method: string): RouteRow | undefined {\n return this.db.prepare(\n 'SELECT * FROM routes WHERE uri = ? AND method = ?',\n ).get(uri, method) as RouteRow | undefined;\n }\n\n getAllRoutes(): RouteRow[] {\n return this.db.prepare('SELECT * FROM routes').all() as RouteRow[];\n }\n\n findRouteByPattern(uri: string, method: string): RouteRow | undefined {\n const likePattern = uri.replace(/\\{[^}]+\\}/g, '%');\n const routes = this.db.prepare(\n 'SELECT * FROM routes WHERE method = ? AND uri LIKE ?',\n ).all(method.toUpperCase(), likePattern) as RouteRow[];\n const exact = routes.find((r) => r.uri === uri);\n return exact ?? routes[0];\n }\n\n // --- Migration queries ---\n\n getMigrationsByTable(tableName: string): MigrationRow[] {\n return this.db.prepare(\n 'SELECT * FROM migrations WHERE table_name = ? ORDER BY timestamp ASC',\n ).all(tableName) as MigrationRow[];\n }\n\n getAllMigrations(): MigrationRow[] {\n return this.db.prepare(\n 'SELECT * FROM migrations ORDER BY timestamp ASC',\n ).all() as MigrationRow[];\n }\n\n // --- Edge queries ---\n\n getEdgesByType(edgeTypeName: string): EdgeRow[] {\n const edgeType = this.db.prepare(\n 'SELECT id FROM edge_types WHERE name = ?',\n ).get(edgeTypeName) as { id: number } | undefined;\n if (!edgeType) return [];\n return this.db.prepare(\n 'SELECT * FROM edges WHERE edge_type_id = ?',\n ).all(edgeType.id) as EdgeRow[];\n }\n\n getOutgoingEdges(nodeId: number): (EdgeRow & { edge_type_name: string })[] {\n return this.db.prepare(\n `SELECT e.*, et.name as edge_type_name\n FROM edges e JOIN edge_types et ON e.edge_type_id = et.id\n WHERE e.source_node_id = ?`,\n ).all(nodeId) as (EdgeRow & { edge_type_name: string })[];\n }\n\n getIncomingEdges(nodeId: number): (EdgeRow & { edge_type_name: string })[] {\n return this.db.prepare(\n `SELECT e.*, et.name as edge_type_name\n FROM edges e JOIN edge_types et ON e.edge_type_id = et.id\n WHERE e.target_node_id = ?`,\n ).all(nodeId) as (EdgeRow & { edge_type_name: string })[];\n }\n\n // --- ORM Models ---\n\n insertOrmModel(model: RawOrmModel, fileId: number): number {\n const result = this.db.prepare(\n `INSERT INTO orm_models (file_id, name, orm, collection_or_table, fields, options, metadata)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n fileId,\n model.name,\n model.orm,\n model.collectionOrTable ?? null,\n model.fields ? JSON.stringify(model.fields) : null,\n model.options ? JSON.stringify(model.options) : null,\n model.metadata ? JSON.stringify(model.metadata) : null,\n );\n const modelId = Number(result.lastInsertRowid);\n this.createNode('orm_model', modelId);\n return modelId;\n }\n\n getOrmModelByName(name: string): OrmModelRow | undefined {\n return this.db.prepare('SELECT * FROM orm_models WHERE name = ?').get(name) as OrmModelRow | undefined;\n }\n\n getOrmModelsByOrm(orm: string): OrmModelRow[] {\n return this.db.prepare('SELECT * FROM orm_models WHERE orm = ?').all(orm) as OrmModelRow[];\n }\n\n getAllOrmModels(): OrmModelRow[] {\n return this.db.prepare('SELECT * FROM orm_models').all() as OrmModelRow[];\n }\n\n // --- ORM Associations ---\n\n insertOrmAssociation(\n sourceModelId: number,\n targetModelId: number | null,\n targetModelName: string,\n kind: string,\n options?: Record<string, unknown>,\n fileId?: number,\n line?: number,\n ): number {\n const result = this.db.prepare(\n `INSERT INTO orm_associations (source_model_id, target_model_id, target_model_name, kind, options, file_id, line)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n sourceModelId,\n targetModelId,\n targetModelName,\n kind,\n options ? JSON.stringify(options) : null,\n fileId ?? null,\n line ?? null,\n );\n return Number(result.lastInsertRowid);\n }\n\n getAllOrmAssociations(): OrmAssociationRow[] {\n return this.db.prepare('SELECT * FROM orm_associations').all() as OrmAssociationRow[];\n }\n\n getOrmAssociationsByModel(modelId: number): OrmAssociationRow[] {\n return this.db.prepare(\n 'SELECT * FROM orm_associations WHERE source_model_id = ?',\n ).all(modelId) as OrmAssociationRow[];\n }\n\n // --- React Native Screens ---\n\n insertRnScreen(screen: RawRnScreen, fileId: number): number {\n const result = this.db.prepare(\n `INSERT INTO rn_screens (file_id, name, component_path, navigator_type, options, deep_link, metadata)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n fileId,\n screen.name,\n screen.componentPath ?? null,\n screen.navigatorType ?? null,\n screen.options ? JSON.stringify(screen.options) : null,\n screen.deepLink ?? null,\n screen.metadata ? JSON.stringify(screen.metadata) : null,\n );\n const screenId = Number(result.lastInsertRowid);\n this.createNode('rn_screen', screenId);\n return screenId;\n }\n\n getRnScreenByName(name: string): RnScreenRow | undefined {\n return this.db.prepare('SELECT * FROM rn_screens WHERE name = ?').get(name) as RnScreenRow | undefined;\n }\n\n getAllRnScreens(): RnScreenRow[] {\n return this.db.prepare('SELECT * FROM rn_screens').all() as RnScreenRow[];\n }\n\n getSymbolById(id: number): SymbolRow | undefined {\n return this.db.prepare('SELECT * FROM symbols WHERE id = ?').get(id) as SymbolRow | undefined;\n }\n\n getNodeByNodeId(nodeId: number): { node_type: string; ref_id: number } | undefined {\n return this.db.prepare(\n 'SELECT node_type, ref_id FROM nodes WHERE id = ?',\n ).get(nodeId) as { node_type: string; ref_id: number } | undefined;\n }\n\n // --- Introspection queries ---\n\n findImplementors(name: string): SymbolWithFilePath[] {\n return this.db.prepare(\n `SELECT s.*, f.path as file_path\n FROM symbols s\n JOIN files f ON s.file_id = f.id\n WHERE s.metadata IS NOT NULL AND (\n json_extract(s.metadata, '$.implements') LIKE '%\"' || ? || '\"%'\n OR json_extract(s.metadata, '$.extends') LIKE '%\"' || ? || '\"%'\n OR json_extract(s.metadata, '$.extends') = ?\n )`,\n ).all(name, name, name) as SymbolWithFilePath[];\n }\n\n getExportedSymbols(filePattern?: string): SymbolWithFilePath[] {\n if (filePattern) {\n const likePattern = filePattern.replace(/\\*/g, '%').replace(/\\?/g, '_');\n return this.db.prepare(\n `SELECT s.*, f.path as file_path\n FROM symbols s\n JOIN files f ON s.file_id = f.id\n WHERE json_extract(s.metadata, '$.exported') = 1\n AND f.path LIKE ?`,\n ).all(likePattern) as SymbolWithFilePath[];\n }\n return this.db.prepare(\n `SELECT s.*, f.path as file_path\n FROM symbols s\n JOIN files f ON s.file_id = f.id\n WHERE json_extract(s.metadata, '$.exported') = 1`,\n ).all() as SymbolWithFilePath[];\n }\n\n getEdgeTypes(): EdgeTypeRow[] {\n return this.db.prepare(\n `SELECT name, category, COALESCE(description, '') as description FROM edge_types ORDER BY name`,\n ).all() as EdgeTypeRow[];\n }\n\n /**\n * Get all symbols that have heritage metadata (extends/implements).\n * Used by the TypeScript heritage resolver in the pipeline.\n */\n getSymbolsWithHeritage(): (SymbolRow & { file_path: string })[] {\n return this.db.prepare(`\n SELECT s.*, f.path AS file_path\n FROM symbols s\n JOIN files f ON s.file_id = f.id\n WHERE s.metadata IS NOT NULL\n AND (json_extract(s.metadata, '$.extends') IS NOT NULL\n OR json_extract(s.metadata, '$.implements') IS NOT NULL)\n `).all() as (SymbolRow & { file_path: string })[];\n }\n\n /**\n * Find a symbol by name and optional kind.\n * Returns the first match (prefers exact name match over substring).\n */\n getSymbolByName(name: string, kind?: string): SymbolRow | undefined {\n if (kind) {\n return this.db.prepare(\n 'SELECT * FROM symbols WHERE name = ? AND kind = ? LIMIT 1',\n ).get(name, kind) as SymbolRow | undefined;\n }\n return this.db.prepare(\n 'SELECT * FROM symbols WHERE name = ? LIMIT 1',\n ).get(name) as SymbolRow | undefined;\n }\n\n // --- Batch queries (avoid N+1) ---\n\n /** Resolve multiple node IDs in one query. Returns Map<refId, nodeId>. */\n getNodeIdsBatch(nodeType: string, refIds: number[]): Map<number, number> {\n const map = new Map<number, number>();\n if (refIds.length === 0) return map;\n const placeholders = refIds.map(() => '?').join(',');\n const rows = this.db.prepare(\n `SELECT ref_id, id FROM nodes WHERE node_type = ? AND ref_id IN (${placeholders})`,\n ).all(nodeType, ...refIds) as { ref_id: number; id: number }[];\n for (const row of rows) map.set(row.ref_id, row.id);\n return map;\n }\n\n /** Resolve multiple node refs in one query. Returns Map<nodeId, {nodeType, refId}>. */\n getNodeRefsBatch(nodeIds: number[]): Map<number, { nodeType: string; refId: number }> {\n const map = new Map<number, { nodeType: string; refId: number }>();\n if (nodeIds.length === 0) return map;\n const placeholders = nodeIds.map(() => '?').join(',');\n const rows = this.db.prepare(\n `SELECT id, node_type, ref_id FROM nodes WHERE id IN (${placeholders})`,\n ).all(...nodeIds) as { id: number; node_type: string; ref_id: number }[];\n for (const row of rows) map.set(row.id, { nodeType: row.node_type, refId: row.ref_id });\n return map;\n }\n\n /** Batch-fetch symbols by internal IDs. Returns Map<id, SymbolRow>. */\n getSymbolsByIds(ids: number[]): Map<number, SymbolRow> {\n const map = new Map<number, SymbolRow>();\n if (ids.length === 0) return map;\n const placeholders = ids.map(() => '?').join(',');\n const rows = this.db.prepare(\n `SELECT * FROM symbols WHERE id IN (${placeholders})`,\n ).all(...ids) as SymbolRow[];\n for (const row of rows) map.set(row.id, row);\n return map;\n }\n\n /** Batch-fetch files by internal IDs. Returns Map<id, FileRow>. */\n getFilesByIds(ids: number[]): Map<number, FileRow> {\n const map = new Map<number, FileRow>();\n if (ids.length === 0) return map;\n const placeholders = ids.map(() => '?').join(',');\n const rows = this.db.prepare(\n `SELECT * FROM files WHERE id IN (${placeholders})`,\n ).all(...ids) as FileRow[];\n for (const row of rows) map.set(row.id, row);\n return map;\n }\n\n /**\n * Fetch all edges where any of the given node IDs appear as source or target.\n * Returns edges annotated with edge_type_name and the pivot node id (the one from the input set).\n */\n getEdgesForNodesBatch(\n nodeIds: number[],\n ): Array<EdgeRow & { edge_type_name: string; pivot_node_id: number }> {\n if (nodeIds.length === 0) return [];\n const placeholders = nodeIds.map(() => '?').join(',');\n const rows = this.db.prepare(\n `SELECT e.*, et.name AS edge_type_name\n FROM edges e\n JOIN edge_types et ON e.edge_type_id = et.id\n WHERE e.source_node_id IN (${placeholders})\n OR e.target_node_id IN (${placeholders})`,\n ).all(...nodeIds, ...nodeIds) as (EdgeRow & { edge_type_name: string })[];\n\n const nodeSet = new Set(nodeIds);\n return rows.map((row) => ({\n ...row,\n pivot_node_id: nodeSet.has(row.source_node_id) ? row.source_node_id : row.target_node_id,\n }));\n }\n\n /** Find a class/interface symbol by name with optional framework_role filter. Single query with JOIN. */\n findSymbolByRole(name: string, frameworkRole?: string): SymbolRow | undefined {\n if (frameworkRole) {\n return this.db.prepare(\n `SELECT s.* FROM symbols s\n JOIN files f ON s.file_id = f.id\n WHERE f.framework_role = ?\n AND (s.name = ? OR s.fqn LIKE ?)\n LIMIT 1`,\n ).get(frameworkRole, name, `%\\\\${name}`) as SymbolRow | undefined;\n }\n return this.db.prepare(\n 'SELECT * FROM symbols WHERE name = ? AND kind = ? LIMIT 1',\n ).get(name, 'class') as SymbolRow | undefined;\n }\n\n // --- Env vars ---\n\n insertEnvVar(fileId: number, entry: {\n key: string;\n valueType: string;\n valueFormat: string | null;\n comment: string | null;\n quoted: boolean;\n line: number;\n }): number {\n return (this.db.prepare(\n `INSERT INTO env_vars (file_id, key, value_type, value_format, comment, quoted, line)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n fileId, entry.key, entry.valueType, entry.valueFormat,\n entry.comment, entry.quoted ? 1 : 0, entry.line,\n ) as { lastInsertRowid: number }).lastInsertRowid as number;\n }\n\n deleteEnvVarsByFile(fileId: number): void {\n this.db.prepare('DELETE FROM env_vars WHERE file_id = ?').run(fileId);\n }\n\n getEnvVarsByFile(fileId: number): EnvVarRow[] {\n return this.db.prepare(\n 'SELECT * FROM env_vars WHERE file_id = ? ORDER BY line',\n ).all(fileId) as EnvVarRow[];\n }\n\n getAllEnvVars(): (EnvVarRow & { file_path: string })[] {\n return this.db.prepare(\n `SELECT ev.*, f.path as file_path\n FROM env_vars ev\n JOIN files f ON ev.file_id = f.id\n ORDER BY f.path, ev.line`,\n ).all() as (EnvVarRow & { file_path: string })[];\n }\n\n searchEnvVars(pattern: string): (EnvVarRow & { file_path: string })[] {\n return this.db.prepare(\n `SELECT ev.*, f.path as file_path\n FROM env_vars ev\n JOIN files f ON ev.file_id = f.id\n WHERE ev.key LIKE ?\n ORDER BY f.path, ev.line`,\n ).all(`%${pattern}%`) as (EnvVarRow & { file_path: string })[];\n }\n\n // --- AI Summarization ---\n\n updateSymbolSummary(symbolId: number, summary: string): void {\n this.db.prepare('UPDATE symbols SET summary = ? WHERE id = ?').run(summary, symbolId);\n }\n\n getUnsummarizedSymbols(kinds: string[], limit: number): {\n id: number;\n name: string;\n fqn: string | null;\n kind: string;\n signature: string | null;\n file_path: string;\n byte_start: number;\n byte_end: number;\n }[] {\n if (kinds.length === 0) return [];\n const placeholders = kinds.map(() => '?').join(',');\n return this.db.prepare(`\n SELECT s.id, s.name, s.fqn, s.kind, s.signature, f.path as file_path, s.byte_start, s.byte_end\n FROM symbols s\n JOIN files f ON s.file_id = f.id\n WHERE s.summary IS NULL AND s.kind IN (${placeholders})\n LIMIT ?\n `).all(...kinds, limit) as {\n id: number;\n name: string;\n fqn: string | null;\n kind: string;\n signature: string | null;\n file_path: string;\n byte_start: number;\n byte_end: number;\n }[];\n }\n\n // --- Stats ---\n\n getStats(): IndexStats {\n const fileCount = (this.db.prepare('SELECT COUNT(*) as c FROM files').get() as { c: number }).c;\n const symbolCount = (this.db.prepare('SELECT COUNT(*) as c FROM symbols').get() as { c: number }).c;\n const edgeCount = (this.db.prepare('SELECT COUNT(*) as c FROM edges').get() as { c: number }).c;\n const nodeCount = (this.db.prepare('SELECT COUNT(*) as c FROM nodes').get() as { c: number }).c;\n const routeCount = (this.db.prepare('SELECT COUNT(*) as c FROM routes').get() as { c: number }).c;\n const componentCount = (this.db.prepare('SELECT COUNT(*) as c FROM components').get() as { c: number }).c;\n const migrationCount = (this.db.prepare('SELECT COUNT(*) as c FROM migrations').get() as { c: number }).c;\n\n const partialFiles = (this.db.prepare(\"SELECT COUNT(*) as c FROM files WHERE status = 'partial'\").get() as { c: number }).c;\n const errorFiles = (this.db.prepare(\"SELECT COUNT(*) as c FROM files WHERE status = 'error'\").get() as { c: number }).c;\n\n return {\n totalFiles: fileCount,\n totalSymbols: symbolCount,\n totalEdges: edgeCount,\n totalNodes: nodeCount,\n totalRoutes: routeCount,\n totalComponents: componentCount,\n totalMigrations: migrationCount,\n partialFiles,\n errorFiles,\n };\n }\n}\n\n// --- Row types ---\n\nexport interface FileRow {\n id: number;\n path: string;\n language: string | null;\n framework_role: string | null;\n status: string;\n content_hash: string | null;\n byte_length: number | null;\n indexed_at: string;\n metadata: string | null;\n workspace: string | null;\n}\n\nexport interface SymbolRow {\n id: number;\n file_id: number;\n symbol_id: string;\n name: string;\n kind: string;\n fqn: string | null;\n parent_id: number | null;\n signature: string | null;\n summary: string | null;\n byte_start: number;\n byte_end: number;\n line_start: number | null;\n line_end: number | null;\n metadata: string | null;\n}\n\nexport interface EdgeRow {\n id: number;\n source_node_id: number;\n target_node_id: number;\n edge_type_id: number;\n resolved: number;\n metadata: string | null;\n is_cross_ws: number;\n}\n\nexport interface RouteRow {\n id: number;\n method: string;\n uri: string;\n name: string | null;\n handler: string | null;\n controller_symbol_id: string | null;\n middleware: string | null;\n metadata: string | null;\n file_id: number | null;\n line: number | null;\n}\n\nexport interface MigrationRow {\n id: number;\n file_id: number;\n table_name: string;\n operation: string;\n columns: string | null;\n indices: string | null;\n timestamp: string | null;\n}\n\nexport interface ComponentRow {\n id: number;\n file_id: number;\n name: string;\n kind: string;\n props: string | null;\n emits: string | null;\n slots: string | null;\n composables: string | null;\n framework: string;\n}\n\nexport interface OrmModelRow {\n id: number;\n file_id: number;\n name: string;\n orm: string;\n collection_or_table: string | null;\n fields: string | null;\n options: string | null;\n metadata: string | null;\n}\n\nexport interface OrmAssociationRow {\n id: number;\n source_model_id: number;\n target_model_id: number | null;\n target_model_name: string | null;\n kind: string;\n options: string | null;\n file_id: number | null;\n line: number | null;\n}\n\nexport interface RnScreenRow {\n id: number;\n file_id: number;\n name: string;\n component_path: string | null;\n navigator_type: string | null;\n options: string | null;\n deep_link: string | null;\n metadata: string | null;\n}\n\nexport interface EnvVarRow {\n id: number;\n file_id: number;\n key: string;\n value_type: string;\n value_format: string | null;\n comment: string | null;\n quoted: number;\n line: number | null;\n}\n\nexport interface SymbolWithFilePath extends SymbolRow {\n file_path: string;\n}\n\nexport interface EdgeTypeRow {\n name: string;\n category: string;\n description: string;\n}\n\nexport interface IndexStats {\n totalFiles: number;\n totalSymbols: number;\n totalEdges: number;\n totalNodes: number;\n totalRoutes: number;\n totalComponents: number;\n totalMigrations: number;\n partialFiles: number;\n errorFiles: number;\n}\n","import type { LanguagePlugin, FrameworkPlugin, PluginManifest, ProjectContext } from './types.js';\nimport { ok, err, type TraceMcpResult } from '../errors.js';\nimport { pluginError } from '../errors.js';\n\nexport class PluginRegistry {\n private languagePlugins: LanguagePlugin[] = [];\n private frameworkPlugins: FrameworkPlugin[] = [];\n\n registerLanguagePlugin(plugin: LanguagePlugin): void {\n this.languagePlugins.push(plugin);\n }\n\n registerFrameworkPlugin(plugin: FrameworkPlugin): void {\n this.frameworkPlugins.push(plugin);\n }\n\n getLanguagePlugins(): LanguagePlugin[] {\n return this.sortByPriority(this.languagePlugins);\n }\n\n getActiveFrameworkPlugins(ctx: ProjectContext): TraceMcpResult<FrameworkPlugin[]> {\n const active = this.frameworkPlugins.filter((p) => p.detect(ctx));\n return this.topologicalSort(active);\n }\n\n getAllFrameworkPlugins(): FrameworkPlugin[] {\n return [...this.frameworkPlugins];\n }\n\n getLanguagePluginForFile(filePath: string): LanguagePlugin | undefined {\n const ext = filePath.slice(filePath.lastIndexOf('.'));\n const sorted = this.getLanguagePlugins();\n return sorted.find((p) => p.supportedExtensions.includes(ext));\n }\n\n private sortByPriority<T extends { manifest: PluginManifest }>(plugins: T[]): T[] {\n return [...plugins].sort((a, b) => a.manifest.priority - b.manifest.priority);\n }\n\n private topologicalSort(plugins: FrameworkPlugin[]): TraceMcpResult<FrameworkPlugin[]> {\n const nameMap = new Map<string, FrameworkPlugin>();\n for (const p of plugins) {\n nameMap.set(p.manifest.name, p);\n }\n\n const sorted: FrameworkPlugin[] = [];\n const visited = new Set<string>();\n const visiting = new Set<string>();\n\n const visit = (plugin: FrameworkPlugin): TraceMcpResult<void> => {\n const name = plugin.manifest.name;\n\n if (visiting.has(name)) {\n return err(\n pluginError(name, `Circular dependency detected involving plugin '${name}'`),\n );\n }\n\n if (visited.has(name)) return ok(undefined);\n\n visiting.add(name);\n\n for (const depName of plugin.manifest.dependencies ?? []) {\n const dep = nameMap.get(depName);\n if (dep) {\n const result = visit(dep);\n if (result.isErr()) return result;\n }\n // Missing dependency in active set is not an error — it may not be detected\n }\n\n visiting.delete(name);\n visited.add(name);\n sorted.push(plugin);\n\n return ok(undefined);\n };\n\n // Sort by priority first, then topological sort\n const prioritySorted = this.sortByPriority(plugins);\n for (const plugin of prioritySorted) {\n const result = visit(plugin);\n if (result.isErr()) return err(result.error);\n }\n\n return ok(sorted);\n }\n}\n","import { cosmiconfig } from 'cosmiconfig';\nimport { z } from 'zod';\nimport { ok, err, type TraceMcpResult } from './errors.js';\nimport { configError } from './errors.js';\nimport { logger } from './logger.js';\n\nconst SecurityConfigSchema = z.object({\n secret_patterns: z.array(z.string()).optional(),\n max_file_size_bytes: z.number().positive().optional(),\n}).optional();\n\nconst ArtisanConfigSchema = z.object({\n enabled: z.boolean().default(true),\n timeout: z.number().positive().default(10000),\n}).optional();\n\nconst FrameworkConfigSchema = z.object({\n laravel: z.object({\n artisan: ArtisanConfigSchema,\n graceful_degradation: z.boolean().default(true),\n }).optional(),\n}).optional();\n\nconst AiConfigSchema = z.object({\n enabled: z.boolean().default(false),\n provider: z.enum(['ollama', 'openai']).default('ollama'),\n base_url: z.string().optional(),\n api_key: z.string().optional(),\n inference_model: z.string().optional(),\n fast_model: z.string().optional(),\n embedding_model: z.string().optional(),\n embedding_dimensions: z.number().optional(),\n summarize_on_index: z.boolean().default(true),\n summarize_batch_size: z.number().positive().default(20),\n summarize_kinds: z.array(z.string()).default([\n 'class', 'function', 'method', 'interface', 'trait', 'enum', 'type',\n ]),\n reranker_model: z.string().optional(),\n}).optional();\n\nexport const TraceMcpConfigSchema = z.object({\n root: z.string().default('.'),\n include: z.array(z.string()).default([\n 'app/**/*.php',\n 'routes/**/*.php',\n 'database/migrations/**/*.php',\n 'resources/js/**/*.{vue,ts,tsx,js,jsx}',\n 'resources/views/**/*.blade.php',\n ]),\n exclude: z.array(z.string()).default([\n 'vendor/**', 'node_modules/**', '.git/**',\n 'storage/**', 'bootstrap/cache/**', '.nuxt/**',\n '**/.env', '**/.env.*',\n ]),\n db: z.object({\n path: z.string().default('.trace-mcp/index.db'),\n }).default({}),\n frameworks: FrameworkConfigSchema,\n ai: AiConfigSchema,\n plugins: z.array(z.string()).default([]),\n security: SecurityConfigSchema,\n});\n\nexport type TraceMcpConfig = z.infer<typeof TraceMcpConfigSchema>;\n\nexport async function loadConfig(searchFrom?: string): Promise<TraceMcpResult<TraceMcpConfig>> {\n const explorer = cosmiconfig('trace-mcp', {\n searchPlaces: [\n '.trace-mcp.json',\n '.trace-mcp',\n '.config/trace-mcp.json',\n 'package.json',\n ],\n });\n\n try {\n const result = searchFrom\n ? await explorer.search(searchFrom)\n : await explorer.search();\n\n const rawConfig = result?.config ?? {};\n\n // Env var overrides\n if (process.env.TRACE_MCP_DB_PATH) {\n rawConfig.db = rawConfig.db ?? {};\n rawConfig.db.path = process.env.TRACE_MCP_DB_PATH;\n }\n\n if (process.env.TRACE_MCP_LOG_LEVEL) {\n // Log level is handled by pino directly, but note it's available\n }\n\n const parsed = TraceMcpConfigSchema.safeParse(rawConfig);\n if (!parsed.success) {\n const issues = parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ');\n return err(configError(`Config validation failed: ${issues}`));\n }\n\n logger.debug({ configPath: result?.filepath ?? 'defaults' }, 'Config loaded');\n return ok(parsed.data);\n } catch (e) {\n return err(configError(e instanceof Error ? e.message : String(e)));\n }\n}\n"],"mappings":"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","names":["z","languageRows","path","ok","err","err","path","ok","path","path","fs","path","fg","fs","path","path","path","fs","path","path","fs","path","path","ok","fs","fg","fs","path","path","fs","path","fs","path","fs","path","fs","path","fs","path","ok","err","ok","err","ok","err","resolveTargetName","path","ok","err","path","j","z","path","z","z"]}
|