@ctxo/cli 0.13.0 → 0.14.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/README.md +20 -4
- package/dist/chunk-2Q76LH2H.js +186 -0
- package/dist/chunk-2Q76LH2H.js.map +1 -0
- package/dist/chunk-72CEQEQD.js +53 -0
- package/dist/chunk-72CEQEQD.js.map +1 -0
- package/dist/chunk-7HSA5JVP.js +1049 -0
- package/dist/chunk-7HSA5JVP.js.map +1 -0
- package/dist/chunk-G4BMKCKG.js +76 -0
- package/dist/chunk-G4BMKCKG.js.map +1 -0
- package/dist/chunk-L2CAUER6.js +508 -0
- package/dist/chunk-L2CAUER6.js.map +1 -0
- package/dist/chunk-LAX6VVBU.js +98 -0
- package/dist/chunk-LAX6VVBU.js.map +1 -0
- package/dist/chunk-SRQZDGFZ.js +128 -0
- package/dist/chunk-SRQZDGFZ.js.map +1 -0
- package/dist/{chunk-DT3ZH4AU.js → chunk-X4TVFJ4C.js} +6 -1
- package/dist/chunk-X4TVFJ4C.js.map +1 -0
- package/dist/{chunk-BYX3UFBJ.js → chunk-ZL36YS2V.js} +785 -1624
- package/dist/chunk-ZL36YS2V.js.map +1 -0
- package/dist/{cli-router-RR4CM62C.js → cli-router-AZCDNX5R.js} +982 -506
- package/dist/cli-router-AZCDNX5R.js.map +1 -0
- package/dist/index.js +13 -2874
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +747 -0
- package/dist/internal.js +13 -0
- package/dist/{json-index-reader-OXTRTGE6.js → json-index-reader-DBW32TCN.js} +6 -4
- package/dist/json-index-reader-DBW32TCN.js.map +1 -0
- package/dist/mcp-server-6YG2QE6E.js +2604 -0
- package/dist/mcp-server-6YG2QE6E.js.map +1 -0
- package/dist/module-host-KNMKS62R.js +13 -0
- package/dist/module-host-KNMKS62R.js.map +1 -0
- package/dist/module-loader-B3LYF3W7.js +14 -0
- package/dist/module-loader-B3LYF3W7.js.map +1 -0
- package/dist/plugin-discovery-XRXI3IJF.js +13 -0
- package/dist/plugin-discovery-XRXI3IJF.js.map +1 -0
- package/llms-full.txt +105 -1
- package/llms.txt +21 -1
- package/package.json +15 -4
- package/dist/chunk-BYX3UFBJ.js.map +0 -1
- package/dist/chunk-DT3ZH4AU.js.map +0 -1
- package/dist/cli-router-RR4CM62C.js.map +0 -1
- /package/dist/{json-index-reader-OXTRTGE6.js.map → internal.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mcp-server.ts","../src/adapters/transport/http-server-transport.ts","../src/core/masking/masking-pipeline.ts","../src/adapters/mcp/get-why-context.ts","../src/core/overlay/snapshot-staleness.ts","../src/adapters/mcp/get-change-intelligence.ts","../src/core/change-intelligence/churn-analyzer.ts","../src/core/change-intelligence/health-scorer.ts","../src/adapters/mcp/get-blast-radius.ts","../src/adapters/mcp/get-architectural-overlay.ts","../src/adapters/mcp/get-dead-code.ts","../src/adapters/mcp/get-context-for-task.ts","../src/core/context-assembly/task-context-strategy.ts","../src/core/context-assembly/context-assembler.ts","../src/adapters/mcp/get-ranked-context.ts","../src/core/search/fuzzy-corrector.ts","../src/core/search/search-engine.ts","../src/adapters/mcp/search-symbols.ts","../src/adapters/mcp/get-changed-symbols.ts","../src/adapters/mcp/find-importers.ts","../src/adapters/mcp/get-class-hierarchy.ts","../src/adapters/mcp/get-symbol-importance.ts","../src/adapters/mcp/get-pr-impact.ts","../src/adapters/stats/with-recording.ts","../src/adapters/mcp/module-tool-handler.ts","../src/core/overlay/cluster-label-masker.ts"],"sourcesContent":["/**\n * The MCP composition root (ADR-018): wires the storage, git, masking and recording adapters to the 14\n * tool handlers and starts the server on stdio or HTTP. The entry (`index.ts`) imports this file only when\n * it starts the server, so the CLI commands and the hook route never load the MCP SDK.\n */\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { startHttpTransport } from './adapters/transport/http-server-transport.js';\nimport { z } from 'zod';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { createLogger } from './core/logger.js';\nimport { SymbolKindSchema, EdgeKindSchema } from './core/types.js';\nimport { SqliteStorageAdapter } from './adapters/storage/sqlite-storage-adapter.js';\nimport { CoChangeReader } from './adapters/storage/co-change-reader.js';\nimport { MaskingPipeline, type MaskingPatternConfig } from './core/masking/masking-pipeline.js';\nimport { handleGetLogicSlice } from './adapters/mcp/get-logic-slice.js';\nimport { handleGetWhyContext } from './adapters/mcp/get-why-context.js';\nimport { handleGetChangeIntelligence } from './adapters/mcp/get-change-intelligence.js';\nimport { SimpleGitAdapter } from './adapters/git/simple-git-adapter.js';\nimport { handleGetBlastRadius } from './adapters/mcp/get-blast-radius.js';\nimport { handleGetArchitecturalOverlay, OVERLAY_MODES } from './adapters/mcp/get-architectural-overlay.js';\nimport { ContextsViewReader } from './adapters/storage/contexts-view-reader.js';\nimport { handleFindDeadCode } from './adapters/mcp/get-dead-code.js';\nimport { handleGetContextForTask } from './adapters/mcp/get-context-for-task.js';\nimport { handleGetRankedContext } from './adapters/mcp/get-ranked-context.js';\nimport { handleSearchSymbols } from './adapters/mcp/search-symbols.js';\nimport { handleGetChangedSymbols } from './adapters/mcp/get-changed-symbols.js';\nimport { handleFindImporters } from './adapters/mcp/find-importers.js';\nimport { handleGetClassHierarchy } from './adapters/mcp/get-class-hierarchy.js';\nimport { handleGetSymbolImportance } from './adapters/mcp/get-symbol-importance.js';\nimport { handleGetPrImpact } from './adapters/mcp/get-pr-impact.js';\nimport { SessionRecorderAdapter } from './adapters/stats/session-recorder-adapter.js';\nimport { withRecording } from './adapters/stats/with-recording.js';\nimport { collectEnrichers } from './adapters/mcp/enrich-payload.js';\nimport { CORE_TOOL_NAMES, collectModuleTools, handleModuleTool, moduleInputShape } from './adapters/mcp/module-tool-handler.js';\nimport type { StalenessCheck } from './adapters/mcp/get-logic-slice.js';\nimport type { LoadedModule } from './adapters/modules/module-loader.js';\nimport type { ISessionRecorderPort } from './ports/i-session-recorder-port.js';\nimport type { ICoChangePort } from './ports/i-co-change-port.js';\nimport type { IStoragePort } from './ports/i-storage-port.js';\nimport type { IGitPort } from './ports/i-git-port.js';\nimport type { IMaskingPort } from './ports/i-masking-port.js';\nimport { detectWorkspace } from './adapters/workspace/single-package-workspace.js';\nimport { setWorkspaceMeta } from './core/response-envelope.js';\nimport { loadConfig, maskingClusterLabelPatterns, statsEnabled } from './core/config/load-config.js';\nimport { ClusterLabelMasker } from './core/overlay/cluster-label-masker.js';\nimport { loadModulesFor } from './cli/module-commands.js';\n\nconst log = createLogger('ctxo:mcp');\n\nfunction loadMaskingConfig(ctxoRoot: string): MaskingPipeline {\n const jsonConfigPath = join(ctxoRoot, 'masking.json');\n\n // Try JSON masking config first\n if (existsSync(jsonConfigPath)) {\n try {\n const raw = readFileSync(jsonConfigPath, 'utf-8');\n const patterns: MaskingPatternConfig[] = JSON.parse(raw);\n log.info(`Loaded ${patterns.length} custom masking pattern(s)`);\n return MaskingPipeline.fromConfig(patterns);\n } catch (err) {\n log.error(`Failed to load masking config: ${(err as Error).message}`);\n }\n }\n\n return new MaskingPipeline();\n}\n\nfunction readStatsEnabled(ctxoRoot: string): boolean {\n return statsEnabled(loadConfig(ctxoRoot).config);\n}\n\nconst PKG_VERSION: string = (() => {\n try {\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = dirname(__filename);\n const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8')) as { version?: string };\n return pkg.version ?? '0.0.0';\n } catch {\n return '0.0.0';\n }\n})();\n\nexport interface StartMcpServerOptions {\n /** Serve over HTTP on this port; stdio when absent. */\n readonly httpPort?: number;\n}\n\n/** Starts the MCP server for the project in the working directory, over HTTP or stdio. */\nexport async function startMcpServer(options: StartMcpServerOptions = {}): Promise<void> {\n // Initialize adapters\n const ctxoRoot = '.ctxo';\n const workspace = detectWorkspace(process.cwd());\n setWorkspaceMeta({ root: workspace.root });\n const storage = new SqliteStorageAdapter(ctxoRoot, { allowProductionPath: true });\n await storage.init();\n\n const masking = loadMaskingConfig(ctxoRoot);\n const clusterLabelMasker = new ClusterLabelMasker(\n maskingClusterLabelPatterns(loadConfig(ctxoRoot).config),\n );\n const git = new SimpleGitAdapter(process.cwd());\n // One reader for the whole server (every HTTP session too): it caches the co-change matrix by mtime.\n const coChange = new CoChangeReader(ctxoRoot);\n\n // Session recording (opt-out via config.yaml stats.enabled: false)\n const recorder: ISessionRecorderPort | null = readStatsEnabled(ctxoRoot)\n ? new SessionRecorderAdapter(storage.getDb(), () => storage.persist())\n : null;\n\n // Create MCP server\n const server = new McpServer({ name: 'ctxo', version: PKG_VERSION });\n\n // Staleness detection\n const { StalenessDetector } = await import('./core/staleness/staleness-detector.js');\n const staleness = new StalenessDetector(process.cwd(), ctxoRoot);\n\n // Opt-in modules (@ctxo/domain), loaded once for the server and every HTTP session. The project root is\n // the directory whose .ctxo the server reads. Never rejects: without a module the core runs unchanged.\n const modules = await loadModulesFor(workspace.root, 'mcp');\n\n registerTools(server, storage, masking, git, staleness, recorder, ctxoRoot, clusterLabelMasker, coChange, modules);\n\n // Start MCP server — HTTP mode or stdio mode\n if (options.httpPort !== undefined) {\n await startHttpTransport(async () => {\n const s = new McpServer({ name: 'ctxo', version: PKG_VERSION });\n registerTools(s, storage, masking, git, staleness, recorder, ctxoRoot, clusterLabelMasker, coChange, modules);\n return s;\n }, options.httpPort);\n } else {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n }\n}\n\n/**\n * Registers the 14 core tools, then the tools of the loaded modules, on `server`. A module's enrichers\n * reach the six core tools with an enrich seam; a module tool named like a core tool, or one whose input\n * schema cannot be built, is skipped with a warning. Exported for tests.\n */\nexport function registerTools(\n server: McpServer,\n storage: IStoragePort,\n masking: IMaskingPort,\n git: IGitPort,\n staleness: StalenessCheck | undefined,\n recorder: ISessionRecorderPort | null,\n ctxoRoot = '.ctxo',\n clusterLabelMasker?: ClusterLabelMasker,\n coChange?: ICoChangePort,\n modules: readonly LoadedModule[] = [],\n): void {\n const enrichers = collectEnrichers(modules);\n\n // Tool annotations — all Ctxo tools are read-only index queries\n const toolAnnotations = {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n } as const;\n\n // The tools that resolve a symbol id through the graph also take the 2-part id of a SQL object.\n const SYMBOL_ID_FORMAT = 'format: file::name::kind; a SQL table, view or procedure also as name::kind, for example dbo.loans::table';\n\n // Register tools — each handler wrapped with session recording\n const logicSliceHandler = withRecording('get_logic_slice', handleGetLogicSlice(storage, masking, staleness, ctxoRoot, enrichers.get('get_logic_slice')), recorder);\n const whyContextHandler = withRecording('get_why_context', handleGetWhyContext(storage, git, masking, staleness, ctxoRoot, clusterLabelMasker, enrichers.get('get_why_context')), recorder);\n const changeIntelligenceHandler = withRecording('get_change_intelligence', handleGetChangeIntelligence(storage, git, masking, staleness, ctxoRoot), recorder);\n\n server.registerTool(\n 'get_logic_slice',\n {\n description: 'Retrieve a symbol and all its transitive dependencies as a Logic-Slice. Use this when you need to UNDERSTAND what a symbol depends on (downstream view). L1=signature only, L2=direct deps, L3=full closure, L4=with token budget and symbol annotations (attributes, columns; only L4 includes them). Use `intent` to filter dependencies by keyword (e.g., \"core\", \"adapter\"). All responses include `_meta` with item counts and truncation info. For impact analysis (what BREAKS if this changes), use get_blast_radius instead. For task-specific context, use get_context_for_task. With @ctxo/domain and a registry, the root symbol carries `context` (its named context id).',\n inputSchema: {\n symbolId: z.string().optional().describe(`Single symbol ID (${SYMBOL_ID_FORMAT})`),\n symbolIds: z.array(z.string()).optional().describe('Batch: array of symbol IDs'),\n level: z.number().min(1).max(4).optional().default(3).describe('Detail level (L1=signature, L2=direct deps, L3=full closure, L4=with token budget and annotations)'),\n intent: z.string().optional().describe('Filter dependencies by intent keywords (e.g., \"core\", \"adapter\")'),\n },\n annotations: toolAnnotations,\n },\n (args) => logicSliceHandler(args),\n );\n\n server.registerTool(\n 'get_why_context',\n {\n description: 'Retrieve git commit history intent and anti-pattern warnings (reverts, rollbacks) for a symbol. Use this when you need to understand WHY code was written this way or whether it has a history of problems. Pair with get_change_intelligence for complexity/churn scores. With @ctxo/domain and a registry, `contextDrift` reports the named context of the symbol: its share of cross-context edges over time and files that moved between contexts.',\n inputSchema: {\n symbolId: z.string().min(1).describe(`The symbol ID (${SYMBOL_ID_FORMAT})`),\n maxCommits: z.number().int().min(1).optional().describe('Limit commit history to N most recent commits'),\n },\n annotations: toolAnnotations,\n },\n (args) => whyContextHandler(args),\n );\n\n server.registerTool(\n 'get_change_intelligence',\n {\n description: 'Retrieve complexity x churn composite score for a symbol — identifies hotspots that are both complex and frequently changed. Use this to prioritize refactoring targets or assess risk before modifying code. For git history details, use get_why_context. For impact scope, use get_blast_radius.',\n inputSchema: {\n symbolId: z.string().min(1).describe('The symbol ID (format: file::name::kind)'),\n },\n annotations: toolAnnotations,\n },\n (args) => changeIntelligenceHandler(args),\n );\n\n const blastRadiusHandler = withRecording('get_blast_radius', handleGetBlastRadius(storage, masking, staleness, ctxoRoot, git, clusterLabelMasker, coChange, enrichers.get('get_blast_radius')), recorder);\n\n server.registerTool(\n 'get_blast_radius',\n {\n description: 'BEFORE modifying any symbol (a function, class, method or type, or a SQL table, view or procedure), call this to understand impact. Returns every symbol that depends on the target, directly or transitively, with risk scores that fall with depth. Each dependent is in the tier of its strongest edge: confirmed (`calls`, `extends`, `implements` and the data edges `reads`, `writes`, `executes`), likely (co-changed or `uses`), and potential (`imports`). When co-change history exists, `coChangedFiles` lists up to 10 files that often change together with the target\\'s file but have no dependency path to it (informational: not counted in the tiers or risk scores). Use `confidence` to filter by tier, `intent` to filter by keyword. Large results are auto-truncated with `_meta.hint` for drill-in. For what a symbol DEPENDS ON (downstream), use get_logic_slice instead. For full PR-level analysis, use get_pr_impact. With @ctxo/domain and a registry, each impacted symbol carries `context` (its named context id).',\n inputSchema: {\n symbolId: z.string().min(1).describe(`The symbol ID (${SYMBOL_ID_FORMAT}). Every definition of a SQL object, and its name::kind id, has the same dependents`),\n confidence: z.enum(['confirmed', 'likely', 'potential']).optional().describe('Filter by confidence tier'),\n intent: z.string().optional().describe('Filter impacted symbols by intent keywords (e.g., \"test\", \"adapter\")'),\n },\n annotations: toolAnnotations,\n },\n (args) => blastRadiusHandler(args),\n );\n\n const overlayHandler = withRecording('get_architectural_overlay', handleGetArchitecturalOverlay(storage, masking, staleness, git, clusterLabelMasker, new ContextsViewReader(ctxoRoot)), recorder);\n\n server.registerTool(\n 'get_architectural_overlay',\n {\n description: 'Get the project architecture map. mode \"both\" (default) returns the regex layer map (Domain, Infrastructure, Adapter, Test, Composition, Configuration) plus data-driven Louvain communities; \"regex\" or \"communities\" returns one of them. mode \"contexts\" returns candidate bounded contexts computed by `ctxo index`: file-level clusters of dependencies and co-change with hub files damped. The summary lists every candidate with label, size, cohesion and top terms, plus hubs and name collisions (type names whose shapes differ between candidates). Use this when onboarding to a new codebase, validating layer boundaries, or preparing a context map. For symbol-level analysis, use get_logic_slice or get_blast_radius. Pass candidate: <id> for one candidate in full: its files, cross-candidate edges, co-change pairs, hubs and collisions. The summary also gives each candidate\\'s sharedTableCount and the totals dataResourcesTotal, sharedResourcesTotal and externalResourcesTotal. With candidate: <id>, the detail adds sharedTables (SQL tables and views that files of this candidate and at least one other read or write, with access modes per candidate; up to the first 15 by name, each with up to 10 accesses) and the candidate\\'s own dataResources (up to the first 15 by name, each with its access modes, writer count, the owning candidate when only one writes it, and an external flag for resources that no .sql file defines). Both lists hold fewer entries when the response limit requires; sharedTableCount and dataResourcesTotal keep the full counts, and ctxo contexts --json has the full lists.',\n inputSchema: {\n layer: z.string().optional().describe('Filter by specific layer name'),\n mode: z.enum(OVERLAY_MODES).optional().describe('View to return: \"both\" (default) layers plus communities, \"regex\" layer map, \"communities\" Louvain clusters, \"contexts\" candidate contexts (file level)'),\n candidate: z.number().int().positive().optional().describe('With mode \"contexts\": the id of one candidate to return in full (files, terms, cross edges, co-change pairs, its hubs and collisions); omit for the summary of all candidates'),\n },\n annotations: toolAnnotations,\n },\n (args) => overlayHandler(args),\n );\n\n const deadCodeHandler = withRecording('find_dead_code', handleFindDeadCode(storage, masking, staleness, ctxoRoot), recorder);\n\n server.registerTool(\n 'find_dead_code',\n {\n description: 'Find unreachable symbols and files that are never imported or called anywhere. Use this during cleanup, refactoring, or before deleting code to confirm it is truly unused. Symbols in .sql files are never reported. Use `intent` to filter results by keyword (e.g., \"adapter\", \"function\"). Large results are auto-truncated with `_meta`. For reverse dependency lookup of a specific symbol, use find_importers instead.',\n inputSchema: {\n includeTests: z.boolean().optional().default(false).describe('Include test files (default test globs and files with a test-framework annotation such as @Test) in analysis (default: exclude)'),\n intent: z.string().optional().describe('Filter dead code results by intent keywords (e.g., \"adapter\", \"function\")'),\n },\n annotations: toolAnnotations,\n },\n (args) => deadCodeHandler(args),\n );\n\n const contextForTaskHandler = withRecording('get_context_for_task', handleGetContextForTask(storage, masking, staleness, ctxoRoot, coChange), recorder);\n\n server.registerTool(\n 'get_context_for_task',\n {\n description: 'Get task-optimized context for a symbol based on what you are about to do. Specify taskType: \"fix\" (bug investigation - includes history + anti-patterns), \"extend\" (add feature - includes deps + blast radius), \"refactor\" (restructure - includes importers + complexity), or \"understand\" (learn - includes full slice + architecture). Context entries that depend on the symbol (its blast radius) carry an optional `confidence` tier: confirmed, likely or potential, where co-change history can raise potential to likely. This is the BEST starting point when you know both the symbol and your intent.',\n inputSchema: {\n symbolId: z.string().min(1).describe(`The symbol ID (${SYMBOL_ID_FORMAT})`),\n taskType: z.enum(['fix', 'extend', 'refactor', 'understand']).describe('Task type determines which context is most relevant'),\n tokenBudget: z.number().optional().default(4000).describe('Max tokens for context (default 4000)'),\n },\n annotations: toolAnnotations,\n },\n (args) => contextForTaskHandler(args),\n );\n\n const rankedContextHandler = withRecording('get_ranked_context', handleGetRankedContext(storage, masking, staleness, ctxoRoot), recorder);\n\n server.registerTool(\n 'get_ranked_context',\n {\n description: 'Search and rank symbols by relevance to a natural language query, packed within a token budget. Uses BM25 text matching + PageRank importance scoring. Results include `_meta` with truncation info. Use this when you have a question or topic but do not know which specific symbol to look at. For exact symbol name search, use search_symbols instead.',\n inputSchema: {\n query: z.string().min(1).describe('Search query (matches symbol names)'),\n tokenBudget: z.number().optional().default(4000).describe('Max tokens for results (default 4000)'),\n strategy: z.enum(['combined', 'dependency', 'importance']).optional().default('combined').describe('Ranking strategy'),\n searchMode: z.enum(['fts', 'legacy']).optional().default('fts').describe('\"fts\" (default): BM25 ranking with camelCase splitting, trigram fallback and typo correction; \"legacy\": substring matching; strategy \"importance\" always uses legacy matching'),\n },\n annotations: toolAnnotations,\n },\n (args) => rankedContextHandler(args),\n );\n\n const searchSymbolsHandler = withRecording('search_symbols', handleSearchSymbols(storage, masking, staleness, ctxoRoot, undefined, enrichers.get('search_symbols')), recorder);\n\n server.registerTool(\n 'search_symbols',\n {\n description: 'Search symbols by exact name or regex pattern across the codebase index. Use this when you know (part of) the symbol name and need to find its ID for use with other tools. For semantic/relevance-based search, use get_ranked_context instead. With @ctxo/domain and a registry, each result carries `context` (its named context id).',\n inputSchema: {\n pattern: z.string().min(1).describe('Search pattern (substring or regex)'),\n kind: SymbolKindSchema.optional().describe('Filter by symbol kind (table, view and procedure come from SQL plugins)'),\n filePattern: z.string().optional().describe('Filter by file path substring'),\n limit: z.number().int().min(1).max(100).optional().default(25).describe('Max results (default 25)'),\n mode: z.enum(['regex', 'fts']).optional().default('regex').describe('\"regex\" (default): case-insensitive regex or substring match on names; \"fts\": BM25 relevance search'),\n },\n annotations: toolAnnotations,\n },\n (args) => searchSymbolsHandler(args),\n );\n\n const changedSymbolsHandler = withRecording('get_changed_symbols', handleGetChangedSymbols(storage, git, masking, staleness, ctxoRoot), recorder);\n\n server.registerTool(\n 'get_changed_symbols',\n {\n description: 'Get symbols in recently changed files based on git diff. Use this to see what was modified in recent commits. For full PR risk assessment (changed symbols + blast radius + co-changes), use get_pr_impact instead.',\n inputSchema: {\n since: z.string().optional().default('HEAD~1').describe('Git ref to diff against (default HEAD~1)'),\n maxFiles: z.number().int().min(1).optional().default(50).describe('Max changed files to process (default 50)'),\n },\n annotations: toolAnnotations,\n },\n (args) => changedSymbolsHandler(args),\n );\n\n const findImportersHandler = withRecording('find_importers', handleFindImporters(storage, masking, staleness, ctxoRoot, enrichers.get('find_importers')), recorder);\n\n server.registerTool(\n 'find_importers',\n {\n description: 'Find all symbols that import or depend on a given symbol (reverse dependency / \"who uses this?\"). Use this to check if a symbol is safe to modify or delete. Supports transitive traversal for deep impact chains. Use `intent` to filter by keyword (e.g., \"test\", \"core\"). For forward dependencies (what this symbol uses), use get_logic_slice. For aggregated impact with risk scores, use get_blast_radius. With @ctxo/domain and a registry, each importer carries `context` (its named context id).',\n inputSchema: {\n symbolId: z.string().min(1).describe(`The symbol ID (${SYMBOL_ID_FORMAT}). Every definition of a SQL object, and its name::kind id, has the same importers`),\n edgeKinds: z.array(EdgeKindSchema).optional().describe('Filter by edge kinds (reads, writes and executes are data access)'),\n transitive: z.boolean().optional().default(false).describe('Follow transitive reverse edges (default false)'),\n maxDepth: z.number().int().min(1).max(10).optional().default(5).describe('Max BFS depth for transitive mode (default 5)'),\n intent: z.string().optional().describe('Filter importers by intent keywords (e.g., \"test\", \"core\", \"adapter\")'),\n },\n annotations: toolAnnotations,\n },\n (args) => findImportersHandler(args),\n );\n\n const classHierarchyHandler = withRecording('get_class_hierarchy', handleGetClassHierarchy(storage, masking, staleness, ctxoRoot), recorder);\n\n server.registerTool(\n 'get_class_hierarchy',\n {\n description: 'Get class inheritance hierarchy — ancestors (extends/implements chain) and descendants (subclasses). Use this when working with OOP code to understand type relationships before modifying a base class or interface. For dependency-based relationships (imports/calls), use get_logic_slice or find_importers.',\n inputSchema: {\n symbolId: z.string().min(1).optional().describe('Root symbol ID (omit for full project hierarchy)'),\n direction: z.enum(['ancestors', 'descendants', 'both']).optional().default('both').describe('Traversal direction (default both)'),\n },\n annotations: toolAnnotations,\n },\n (args) => classHierarchyHandler(args),\n );\n\n const symbolImportanceHandler = withRecording('get_symbol_importance', handleGetSymbolImportance(storage, masking, staleness, ctxoRoot), recorder);\n\n server.registerTool(\n 'get_symbol_importance',\n {\n description: 'Rank symbols by structural importance using PageRank centrality on the dependency graph. Use this to identify the most critical symbols in the codebase — high-PageRank symbols are heavily depended upon and risky to change. For finding unused/unimportant code, use find_dead_code instead.',\n inputSchema: {\n limit: z.number().int().min(1).max(200).optional().default(25).describe('Max results (default 25)'),\n kind: SymbolKindSchema.optional().describe('Filter by symbol kind (table, view and procedure come from SQL plugins)'),\n filePattern: z.string().optional().describe('Filter by file path substring'),\n damping: z.number().min(0).max(1).optional().default(0.85).describe('PageRank damping factor (default 0.85)'),\n },\n annotations: toolAnnotations,\n },\n (args) => symbolImportanceHandler(args),\n );\n\n const prImpactHandler = withRecording('get_pr_impact', handleGetPrImpact(storage, git, masking, staleness, ctxoRoot, clusterLabelMasker, coChange, enrichers.get('get_pr_impact')), recorder);\n\n server.registerTool(\n 'get_pr_impact',\n {\n description: 'Analyze the full impact of a PR or recent changes in a SINGLE call — combines changed symbols + blast radius + co-change history into one risk assessment. Results include `_meta` with truncation info. Use this FIRST when reviewing a PR or evaluating recent commits. For single-symbol analysis, use get_blast_radius instead. With @ctxo/domain and a registry, changed symbols carry `context` and `contextBoundaryViolations` lists edges that touch them and cross a context boundary outside its contracts.',\n inputSchema: {\n since: z.string().optional().default('HEAD~1').describe('Git ref to diff against (default HEAD~1)'),\n maxFiles: z.number().int().min(1).optional().default(50).describe('Max changed files to analyze'),\n confidence: z.enum(['confirmed', 'likely', 'potential']).optional().describe('Filter impacted symbols by confidence tier'),\n },\n annotations: toolAnnotations,\n },\n (args) => prImpactHandler(args),\n );\n\n // Module tools (ADR-018) come after the core tools, with the same annotations and session recording; the\n // handler adds the envelope, masking and the staleness warning. A tool that fails to register is skipped.\n const indexedFiles = () => storage.listIndexedFiles();\n for (const tool of collectModuleTools(modules, CORE_TOOL_NAMES)) {\n try {\n const moduleToolHandler = withRecording(tool.name, handleModuleTool(tool, masking, staleness, indexedFiles), recorder);\n server.registerTool(\n tool.name,\n { description: tool.description, inputSchema: moduleInputShape(tool, z), annotations: toolAnnotations },\n (args) => moduleToolHandler(args),\n );\n } catch (err) {\n log.warn(`Module tool \"${tool.name}\" was not registered: ${(err as Error).message}`);\n }\n }\n\n // Register empty resource/prompt capabilities to prevent -32601 errors\n // from MCP clients that unconditionally call listResources/listPrompts\n server.resource('ctxo-status', 'ctxo://status', async (uri) => ({\n contents: [{ uri: uri.href, text: 'Ctxo MCP server is running.' }],\n }));\n}\n","import { createServer, type Server, type IncomingMessage, type ServerResponse } from 'node:http';\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport { randomUUID } from 'node:crypto';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { createLogger } from '../../core/logger.js';\n\nconst log = createLogger('ctxo:http');\n\n/**\n * Factory function that creates and registers all tools on a fresh McpServer.\n * Passed in from the composition root so this adapter doesn't import tool handlers.\n */\nexport type ServerFactory = () => Promise<McpServer>;\n\n/**\n * Starts ctxo MCP over HTTP. Each browser session gets its own McpServer + transport.\n * This avoids the \"already connected\" error when multiple clients connect.\n *\n * Usage:\n * CTXO_HTTP_PORT=3001 ctxo\n * ctxo --http\n */\nexport async function startHttpTransport(\n serverFactory: ServerFactory,\n port: number,\n): Promise<{ httpServer: Server }> {\n // Map of session ID -> { transport, server }\n const sessions = new Map<string, { transport: StreamableHTTPServerTransport; server: McpServer }>();\n\n const httpServer = createServer(async (req: IncomingMessage, res: ServerResponse) => {\n // CORS\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Accept, Mcp-Session-Id');\n res.setHeader('Access-Control-Expose-Headers', 'Mcp-Session-Id');\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n const sessionId = req.headers['mcp-session-id'] as string | undefined;\n\n // Existing session\n if (sessionId && sessions.has(sessionId)) {\n try {\n await sessions.get(sessionId)!.transport.handleRequest(req, res);\n } catch (err) {\n log.error('Request error: %s', (err as Error).message);\n if (!res.headersSent) { res.writeHead(500); res.end(); }\n }\n return;\n }\n\n // Invalid session\n if (sessionId && !sessions.has(sessionId)) {\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ jsonrpc: '2.0', error: { code: -32001, message: 'Session not found' }, id: null }));\n return;\n }\n\n // New session — create fresh server + transport\n try {\n const server = await serverFactory();\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: () => randomUUID(),\n });\n\n transport.onclose = () => {\n if (transport.sessionId) {\n sessions.delete(transport.sessionId);\n log.info('Session closed: %s', transport.sessionId);\n }\n };\n\n await server.connect(transport);\n await transport.handleRequest(req, res);\n\n if (transport.sessionId) {\n sessions.set(transport.sessionId, { transport, server });\n log.info('New session: %s (total: %d)', transport.sessionId, sessions.size);\n }\n } catch (err) {\n log.error('Session creation error: %s', (err as Error).message);\n if (!res.headersSent) { res.writeHead(500); res.end(); }\n }\n });\n\n return new Promise((resolve, reject) => {\n httpServer.on('error', reject);\n httpServer.listen(port, () => {\n log.info('MCP HTTP server listening on http://localhost:%d', port);\n process.stderr.write(`[ctxo] MCP HTTP server running at http://localhost:${port}\\n`);\n resolve({ httpServer });\n });\n });\n}\n","const DEFAULT_PATTERNS: Array<{ regex: RegExp; label: string }> = [\n // AWS Access Key IDs (AKIA...)\n { regex: /AKIA[0-9A-Z]{16}/g, label: 'AWS_KEY' },\n // AWS Secret Access Keys (40 char base64 containing / or +). The `[A-Za-z0-9=]*[/+]`\n // lookahead is scoped to the token itself (not `.*`, which would reach a later `/` in\n // the surrounding text, e.g. a file path in JSON, and wrongly redact hex-only git SHAs).\n { regex: /(?<![A-Za-z0-9/+])(?=[A-Za-z0-9/+=]{40}(?![A-Za-z0-9/+=]))(?=[A-Za-z0-9=]*[/+])[A-Za-z0-9/+=]{40}/g, label: 'AWS_SECRET' },\n // JWT tokens (eyJ...)\n { regex: /eyJ[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}/g, label: 'JWT' },\n // Private IPv4 (10.x.x.x, 172.16-31.x.x, 192.168.x.x)\n { regex: /\\b(?:10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|172\\.(?:1[6-9]|2\\d|3[01])\\.\\d{1,3}\\.\\d{1,3}|192\\.168\\.\\d{1,3}\\.\\d{1,3})\\b/g, label: 'PRIVATE_IP' },\n // Private IPv6 (fc00::/7)\n { regex: /\\b[fF][cCdD][0-9a-fA-F]{0,2}(?::[0-9a-fA-F]{1,4}){1,7}\\b/g, label: 'PRIVATE_IPV6' },\n // Environment variable assignments for secrets\n { regex: /(?:_SECRET|_KEY|_TOKEN|_PASSWORD)\\s*=\\s*['\"]?[^\\s'\"]{8,}['\"]?/g, label: 'ENV_SECRET' },\n // GCP service account keys\n { regex:/\"private_key\"\\s*:\\s*\"-----BEGIN[^\"]+\"/g, label: 'GCP_KEY' },\n // Azure connection strings\n { regex: /AccountKey=[A-Za-z0-9+/=]{20,}/g, label: 'AZURE_KEY' },\n];\n\nexport interface MaskingPatternConfig {\n readonly pattern: string;\n readonly flags?: string;\n readonly label: string;\n}\n\nexport class MaskingPipeline {\n private readonly patterns: Array<{ regex: RegExp; label: string }>;\n\n constructor(additionalPatterns: Array<{ regex: RegExp; label: string }> = []) {\n // Clone RegExp objects to avoid shared mutable lastIndex state\n this.patterns = [...DEFAULT_PATTERNS, ...additionalPatterns].map(({ regex, label }) => ({\n regex: new RegExp(regex.source, regex.flags),\n label,\n }));\n }\n\n static fromConfig(configPatterns: MaskingPatternConfig[]): MaskingPipeline {\n const additional: Array<{ regex: RegExp; label: string }> = [];\n\n for (const { pattern, flags, label } of configPatterns) {\n try {\n additional.push({ regex: new RegExp(pattern, flags ?? 'g'), label });\n } catch (err) {\n console.error(`[ctxo:masking] Invalid regex pattern \"${pattern}\": ${(err as Error).message}`);\n }\n }\n\n return new MaskingPipeline(additional);\n }\n\n mask(text: string): string {\n if (text.length === 0) return text;\n\n let result = text;\n for (const { regex, label } of this.patterns) {\n result = result.replace(regex, `[REDACTED:${label}]`);\n }\n return result;\n }\n}\n","import { z } from 'zod';\nimport type { IStoragePort } from '../../ports/i-storage-port.js';\nimport type { IGitPort } from '../../ports/i-git-port.js';\nimport type { IMaskingPort } from '../../ports/i-masking-port.js';\nimport { RevertDetector } from '../../core/why-context/revert-detector.js';\nimport { DriftDetector } from '../../core/overlay/drift-detector.js';\nimport { buildSnapshotStaleness } from '../../core/overlay/snapshot-staleness.js';\nimport type { ClusterLabelMasker } from '../../core/overlay/cluster-label-masker.js';\nimport { JsonIndexReader } from '../storage/json-index-reader.js';\nimport type { AntiPattern, CommitIntent, FileIndex } from '../../core/types.js';\nimport type { SymbolGraph } from '../../core/graph/symbol-graph.js';\nimport type { StalenessCheck } from './get-logic-slice.js';\nimport { buildGraphFromIndices, buildGraphFromStorage } from './get-logic-slice.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\nimport type { ResponseEnricher } from '../../ports/i-ctxo-module.js';\nimport { applyEnricher } from './enrich-payload.js';\n\n/** The graph of the committed index, or of the SQLite storage when that has no symbols (as `getGraphAndFiles`). */\nfunction graphOf(indices: readonly FileIndex[], storage: IStoragePort): SymbolGraph {\n const graph = buildGraphFromIndices(indices);\n return graph.nodeCount > 0 ? graph : buildGraphFromStorage(storage);\n}\n\nexport const InputSchema = z.object({\n symbolId: z.string().min(1),\n maxCommits: z.number().int().min(1).optional(),\n});\n\nexport function handleGetWhyContext(\n storage: IStoragePort,\n git: IGitPort,\n masking: IMaskingPort,\n staleness?: StalenessCheck,\n ctxoRoot = '.ctxo',\n clusterLabelMasker?: ClusterLabelMasker,\n enrich?: ResponseEnricher,\n) {\n const revertDetector = new RevertDetector();\n const indexReader = new JsonIndexReader(ctxoRoot);\n const driftDetector = new DriftDetector();\n\n return async (args: Record<string, unknown>) => {\n try {\n const parsed = InputSchema.safeParse(args);\n if (!parsed.success) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: parsed.error.message }) }],\n };\n }\n\n const { symbolId: inputId, maxCommits } = parsed.data;\n\n // Committed index first (FR16: anti-patterns persist in committed index)\n const indices = indexReader.readAll();\n\n // Resolve the id once. An exact id is looked up directly; anything else (a 2-part data id, a fuzzy id)\n // through the graph, so a 2-part id reads the history of its winning definition's file.\n const symbolId = storage.getSymbolById(inputId)\n ? inputId\n : graphOf(indices, storage).getNode(inputId)?.symbolId;\n if (!symbolId) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ found: false, hint: 'Symbol not found. Run \"ctxo index\" to build the codebase index.' }) }],\n };\n }\n\n const filePath = symbolId.split('::')[0]!;\n const fileIndex = indices.find((i) => i.file === filePath);\n\n let commitHistory: CommitIntent[];\n let antiPatterns: AntiPattern[];\n\n if (fileIndex && fileIndex.intent.length > 0) {\n commitHistory = fileIndex.intent;\n antiPatterns = fileIndex.antiPatterns;\n } else {\n // Fallback: compute on-demand from git\n const commits = await git.getCommitHistory(filePath);\n commitHistory = commits.map((c) => ({\n hash: c.hash,\n message: c.message,\n date: c.date,\n kind: 'commit' as const,\n }));\n antiPatterns = revertDetector.detect(commits);\n }\n\n // Query-time limit: slice to maxCommits if provided\n const limitedHistory = maxCommits ? commitHistory.slice(0, maxCommits) : commitHistory;\n\n // Assemble result — separation of concerns: no changeIntelligence here\n // Use get_change_intelligence tool for complexity/churn scoring\n const responsePayload: Record<string, unknown> = {\n commitHistory: limitedHistory,\n antiPatternWarnings: antiPatterns,\n };\n\n if (antiPatterns.length > 0) {\n responsePayload.warningBadge = '⚠ Anti-pattern detected';\n }\n\n const rawSnapshot = storage.readCommunities();\n const currentSnapshot =\n rawSnapshot && clusterLabelMasker?.isEnabled()\n ? clusterLabelMasker.maskSnapshot(rawSnapshot)\n : rawSnapshot;\n if (currentSnapshot) {\n const history = storage.listCommunityHistory();\n const drift = driftDetector.detect(currentSnapshot, history);\n const relevant = drift.events.filter((event) => event.symbolId === symbolId);\n if (relevant.length > 0 || drift.hint) {\n responsePayload.driftSignals = {\n events: relevant,\n confidence: drift.confidence,\n snapshotsAvailable: drift.snapshotsAvailable,\n distinctCommits: drift.distinctCommits,\n stabilitySummary: drift.stability,\n ...(drift.hint ? { hint: drift.hint } : {}),\n };\n }\n }\n\n // The same envelope as every other tool: _meta with the item counts, plus snapshotStaleness when known.\n const stalenessMeta = await buildSnapshotStaleness(storage, git);\n const extras = stalenessMeta ? { snapshotStaleness: stalenessMeta } : undefined;\n const enriched = applyEnricher(enrich, responsePayload, parsed.data, 'get_why_context');\n const payload = masking.mask(JSON.stringify(wrapResponse(enriched, extras)));\n\n const content: Array<{ type: 'text'; text: string }> = [];\n if (staleness) {\n const warning = staleness.check(storage.listIndexedFiles());\n if (warning) content.push({ type: 'text', text: `⚠️ ${warning.message}` });\n }\n content.push({ type: 'text', text: payload });\n\n return { content };\n } catch (err) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: (err as Error).message }) }],\n };\n }\n };\n}\n","import type { CommunitySnapshot } from '../types.js';\n\nexport interface SnapshotStaleness {\n readonly snapshotCommit: string;\n readonly currentHeadCommit?: string;\n readonly commitsBehind?: number;\n readonly hint?: string;\n}\n\n/**\n * Narrow structural views of the capabilities this module needs from the\n * storage and git adapters. We declare them here (in core/) rather than\n * importing the full IStoragePort / IGitPort interfaces from ports/ so the\n * hexagonal boundary holds: core/ knows nothing about ports/. Callers pass\n * their existing port-typed adapters — they satisfy these shapes structurally.\n */\nexport interface SnapshotStalenessStorage {\n readCommunities(): CommunitySnapshot | undefined;\n}\n\nexport interface SnapshotStalenessGit {\n getHeadSha?(): Promise<string | undefined> | string | undefined;\n countCommitsBetween?(sha: string): Promise<number | undefined> | number | undefined;\n}\n\n/**\n * Summarise how far the persisted community snapshot has drifted from the\n * current git HEAD. Callers merge this into MCP `_meta` so AI agents know\n * whether cluster / drift / boundary data reflects the HEAD they are about\n * to edit or a stale history point.\n *\n * Returns undefined when no snapshot exists (nothing to report) or when git\n * is unavailable and no comparison is possible.\n */\nexport async function buildSnapshotStaleness(\n storage: SnapshotStalenessStorage,\n git: SnapshotStalenessGit,\n): Promise<SnapshotStaleness | undefined> {\n const snapshot = storage.readCommunities();\n if (!snapshot || !snapshot.commitSha || snapshot.commitSha === 'nocommit') return undefined;\n\n const getHead = git.getHeadSha?.bind(git);\n const countBetween = git.countCommitsBetween?.bind(git);\n const head = getHead ? await getHead() : undefined;\n\n if (!head) {\n // Git unavailable — still report the snapshot anchor so callers know what\n // commit the snapshot was computed against.\n return { snapshotCommit: snapshot.commitSha };\n }\n\n if (head === snapshot.commitSha) {\n return {\n snapshotCommit: snapshot.commitSha,\n currentHeadCommit: head,\n commitsBehind: 0,\n };\n }\n\n const behind = countBetween ? await countBetween(snapshot.commitSha) : undefined;\n\n const result: SnapshotStaleness = {\n snapshotCommit: snapshot.commitSha,\n currentHeadCommit: head,\n ...(typeof behind === 'number' ? { commitsBehind: behind } : {}),\n };\n\n if (typeof behind === 'number' && behind > 0) {\n return {\n ...result,\n hint: `Community snapshot is ${behind} commit${behind === 1 ? '' : 's'} behind HEAD. Run \\`ctxo index\\` to refresh cluster / drift / boundary data.`,\n };\n }\n if (behind === undefined) {\n // HEAD resolved but snapshot sha unknown to git (force-push, rebased, etc.).\n return {\n ...result,\n hint: 'Snapshot commit is not reachable from HEAD — it may have been rebased away. Run `ctxo index` to re-anchor.',\n };\n }\n return result;\n}\n","import { z } from 'zod';\nimport type { IStoragePort } from '../../ports/i-storage-port.js';\nimport type { IGitPort } from '../../ports/i-git-port.js';\nimport type { IMaskingPort } from '../../ports/i-masking-port.js';\nimport { ChurnAnalyzer } from '../../core/change-intelligence/churn-analyzer.js';\nimport { JsonIndexReader } from '../storage/json-index-reader.js';\nimport type { StalenessCheck } from './get-logic-slice.js';\nimport { HealthScorer } from '../../core/change-intelligence/health-scorer.js';\n\nexport const InputSchema = z.object({\n symbolId: z.string().min(1),\n});\n\nexport function handleGetChangeIntelligence(\n storage: IStoragePort,\n git: IGitPort,\n masking: IMaskingPort,\n staleness?: StalenessCheck,\n ctxoRoot = '.ctxo',\n) {\n const churnAnalyzer = new ChurnAnalyzer();\n const healthScorer = new HealthScorer();\n const indexReader = new JsonIndexReader(ctxoRoot);\n\n return async (args: Record<string, unknown>) => {\n try {\n const parsed = InputSchema.safeParse(args);\n if (!parsed.success) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: parsed.error.message }) }],\n };\n }\n\n const { symbolId } = parsed.data;\n\n const symbol = storage.getSymbolById(symbolId);\n if (!symbol) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ found: false, hint: 'Symbol not found. Run \"ctxo index\" to build the codebase index.' }) }],\n };\n }\n\n const filePath = symbolId.split('::')[0]!;\n const normalizePath = (p: string) => p.replace(/\\\\/g, '/');\n\n // Get churn data for all files in parallel\n const allFiles = storage.listIndexedFiles();\n const churnResults = await Promise.all(allFiles.map((f) => git.getFileChurn(f)));\n\n const maxChurn = Math.max(1, ...churnResults.map((c) => c.commitCount));\n const targetChurn = churnResults.find((c) => normalizePath(c.filePath) === normalizePath(filePath));\n const commitCount = targetChurn?.commitCount ?? 0;\n\n const normalizedChurn = churnAnalyzer.normalize(commitCount, maxChurn);\n\n // Read cyclomatic complexity from committed index\n const indices = indexReader.readAll();\n const fileIndex = indices.find((i) => i.file === filePath);\n const complexityEntries = fileIndex?.complexity ?? [];\n\n // Storage knows the symbol but its JSON index is missing on disk — SQLite and\n // `.ctxo/index/` have drifted. Surface it so the caller does not mistake the\n // fallback `complexity: 0` score for a real \"low risk\" verdict.\n const indexMissingWarning = !fileIndex\n ? `JSON index for ${filePath} not found on disk — complexity falls back to 0. Run \"ctxo index\" to resync.`\n : undefined;\n\n // Exact match first, then aggregate (max of methods for class-level queries)\n let cyclomatic = complexityEntries.find((c) => c.symbolId === symbolId)?.cyclomatic;\n if (cyclomatic === undefined) {\n // For class/file: use max complexity of all methods in this file\n const symbolName = symbolId.split('::')[1] ?? '';\n const relatedEntries = complexityEntries.filter((c) =>\n c.symbolId.startsWith(`${filePath}::${symbolName}.`),\n );\n cyclomatic = relatedEntries.length > 0\n ? Math.max(...relatedEntries.map((c) => c.cyclomatic))\n : 1;\n }\n // Normalize: cyclomatic 1=0, 10+=1.0\n const normalizedComplexity = Math.min((cyclomatic - 1) / 9, 1);\n\n const score = healthScorer.score(symbolId, normalizedComplexity, normalizedChurn);\n\n const payload = masking.mask(JSON.stringify(score));\n\n const content: Array<{ type: 'text'; text: string }> = [];\n if (staleness) {\n const warning = staleness.check(storage.listIndexedFiles());\n if (warning) content.push({ type: 'text', text: `⚠️ ${warning.message}` });\n }\n if (indexMissingWarning) {\n content.push({ type: 'text', text: `⚠️ ${indexMissingWarning}` });\n }\n content.push({ type: 'text', text: payload });\n\n return { content };\n } catch (err) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: (err as Error).message }) }],\n };\n }\n };\n}\n","export class ChurnAnalyzer {\n normalize(commitCount: number, maxCommitCount: number): number {\n if (maxCommitCount <= 0) return 0;\n if (commitCount < 0) {\n throw new Error(`Invalid commit count: ${commitCount}`);\n }\n return Math.min(commitCount / maxCommitCount, 1);\n }\n}\n","import type { ChangeIntelligenceScore, ScoreBand } from '../types.js';\n\nexport class HealthScorer {\n score(symbolId: string, complexity: number, churn: number): ChangeIntelligenceScore {\n const composite = complexity * churn;\n const band = this.toBand(composite);\n\n return { symbolId, complexity, churn, composite, band };\n }\n\n private toBand(composite: number): ScoreBand {\n if (composite < 0.3) return 'low';\n if (composite < 0.7) return 'medium';\n return 'high';\n }\n}\n","import { z } from 'zod';\nimport type { IGitPort } from '../../ports/i-git-port.js';\nimport type { IStoragePort } from '../../ports/i-storage-port.js';\nimport type { IMaskingPort } from '../../ports/i-masking-port.js';\nimport type { ICoChangePort } from '../../ports/i-co-change-port.js';\nimport { BlastRadiusCalculator } from '../../core/blast-radius/blast-radius-calculator.js';\nimport { findCoChangedFilesForBlastRadius } from '../../core/blast-radius/co-changed-files.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\nimport { buildSnapshotStaleness } from '../../core/overlay/snapshot-staleness.js';\nimport type { ClusterLabelMasker } from '../../core/overlay/cluster-label-masker.js';\nimport { filterByIntent } from '../../core/intent-filter.js';\nimport type { CommunitySnapshot } from '../../core/types.js';\nimport type { StalenessCheck } from './get-logic-slice.js';\nimport { getGraphAndFiles } from './get-logic-slice.js';\nimport type { ResponseEnricher } from '../../ports/i-ctxo-module.js';\nimport { applyEnricher } from './enrich-payload.js';\n\ninterface ClusterBreakdown {\n readonly byCluster: Record<string, number>;\n readonly crossClusterCount: number;\n readonly multiClusterHint?: string;\n}\n\nfunction computeClusterBreakdown(\n snapshot: CommunitySnapshot,\n rootSymbolId: string,\n impactedSymbolIds: readonly string[],\n): ClusterBreakdown | undefined {\n if (impactedSymbolIds.length === 0) return undefined;\n const assignment = new Map<string, { id: number; label: string }>();\n for (const entry of snapshot.communities) {\n assignment.set(entry.symbolId, { id: entry.communityId, label: entry.communityLabel });\n }\n const rootCluster = assignment.get(rootSymbolId);\n const byCluster: Record<string, number> = {};\n let crossClusterCount = 0;\n for (const symbolId of impactedSymbolIds) {\n const cluster = assignment.get(symbolId);\n if (!cluster) continue;\n const label = cluster.label || `community-${cluster.id}`;\n byCluster[label] = (byCluster[label] ?? 0) + 1;\n if (rootCluster && cluster.id !== rootCluster.id) crossClusterCount++;\n }\n const clusterCount = Object.keys(byCluster).length;\n const multiClusterHint =\n clusterCount >= 3\n ? `Change impacts ${clusterCount} clusters — multi-team review recommended.`\n : undefined;\n return { byCluster, crossClusterCount, multiClusterHint };\n}\n\nexport const InputSchema = z.object({\n symbolId: z.string().min(1),\n confidence: z.enum(['confirmed', 'likely', 'potential']).optional(),\n intent: z.string().optional().describe('Filter results by intent keywords (e.g., \"test\", \"adapter\", \"security\")'),\n});\n\nexport function handleGetBlastRadius(\n storage: IStoragePort,\n masking: IMaskingPort,\n staleness?: StalenessCheck,\n ctxoRoot = '.ctxo',\n git?: IGitPort,\n clusterLabelMasker?: ClusterLabelMasker,\n coChange?: ICoChangePort,\n enrich?: ResponseEnricher,\n) {\n const calculator = new BlastRadiusCalculator();\n const getGraph = () => getGraphAndFiles(ctxoRoot, storage);\n\n return async (args: Record<string, unknown>) => {\n try {\n const parsed = InputSchema.safeParse(args);\n if (!parsed.success) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: parsed.error.message }) }],\n };\n }\n\n const { symbolId } = parsed.data;\n const { graph, indexedFiles } = getGraph();\n\n // Resolve the id once: a 2-part data id names its winning definition. The response echoes the id as given.\n const root = graph.getNode(symbolId);\n if (!root) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ found: false, hint: 'Symbol not found. Run \"ctxo index\" to build the codebase index.' }) }],\n };\n }\n const rootId = root.symbolId;\n\n // Read per call: the port caches by mtime, so a matrix rewritten while the server runs is picked up.\n const coChangeMap = coChange?.readCoChangeMap();\n const result = calculator.calculate(graph, rootId, coChangeMap);\n\n // Apply confidence filter if requested\n let symbols = result.impactedSymbols;\n if (parsed.data.confidence) {\n symbols = symbols.filter(s => s.confidence === parsed.data.confidence);\n }\n\n // Apply intent filter if requested\n symbols = filterByIntent(symbols as unknown as Record<string, unknown>[], parsed.data.intent) as unknown as typeof symbols;\n\n const confirmedCount = symbols.filter(s => s.confidence === 'confirmed').length;\n const likelyCount = symbols.filter(s => s.confidence === 'likely').length;\n const potentialCount = symbols.filter(s => s.confidence === 'potential').length;\n\n const rawSnapshot = storage.readCommunities();\n const snapshot =\n rawSnapshot && clusterLabelMasker?.isEnabled()\n ? clusterLabelMasker.maskSnapshot(rawSnapshot)\n : rawSnapshot;\n const clusterBreakdown = snapshot\n ? computeClusterBreakdown(snapshot, rootId, symbols.map((s) => s.symbolId))\n : undefined;\n\n const body: Record<string, unknown> = {\n symbolId,\n impactScore: symbols.length,\n directDependentsCount: result.directDependentsCount,\n confirmedCount,\n likelyCount,\n potentialCount,\n overallRiskScore: result.overallRiskScore,\n impactedSymbols: symbols,\n };\n if (clusterBreakdown) {\n body.byCluster = clusterBreakdown.byCluster;\n body.crossClusterEdges = clusterBreakdown.crossClusterCount;\n if (clusterBreakdown.multiClusterHint) {\n body.multiClusterHint = clusterBreakdown.multiClusterHint;\n }\n }\n\n // Files that change together with the root's file but have no dependency path to it. From the\n // unfiltered result: the confidence and intent filters above shape the impactedSymbols list only.\n const coChangedFiles = findCoChangedFilesForBlastRadius(coChangeMap, rootId, result.impactedSymbols);\n if (coChangedFiles.length > 0) body.coChangedFiles = coChangedFiles;\n\n const stalenessMeta = git ? await buildSnapshotStaleness(storage, git) : undefined;\n const extras = stalenessMeta ? { snapshotStaleness: stalenessMeta } : undefined;\n const enriched = applyEnricher(enrich, body, parsed.data, 'get_blast_radius');\n const payload = masking.mask(JSON.stringify(wrapResponse(enriched, extras)));\n\n const content: Array<{ type: 'text'; text: string }> = [];\n if (staleness) {\n const warning = staleness.check(indexedFiles);\n if (warning) content.push({ type: 'text', text: `⚠️ ${warning.message}` });\n }\n content.push({ type: 'text', text: payload });\n\n return { content };\n } catch (err) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: (err as Error).message }) }],\n };\n }\n };\n}\n","import { z } from 'zod';\nimport type { IGitPort } from '../../ports/i-git-port.js';\nimport type { IStoragePort } from '../../ports/i-storage-port.js';\nimport type { IMaskingPort } from '../../ports/i-masking-port.js';\nimport { ArchitecturalOverlay } from '../../core/overlay/architectural-overlay.js';\nimport { compareCodepoint } from '../../core/compare-codepoint.js';\nimport { getThreshold, wrapResponse, type WrapResponseExtras } from '../../core/response-envelope.js';\nimport { buildSnapshotStaleness } from '../../core/overlay/snapshot-staleness.js';\nimport type { ClusterLabelMasker } from '../../core/overlay/cluster-label-masker.js';\nimport type { CommunitySnapshot, GodNode } from '../../core/types.js';\nimport type { ContextsView } from '../../core/contexts-view/contexts-view-builder.js';\nimport type { TermCollision } from '../../core/contexts-view/context-terms.js';\nimport type { CandidateSharedTable } from '../../core/contexts-view/data-coupling.js';\nimport type { IContextsViewPort } from '../../ports/i-contexts-view-port.js';\nimport type { StalenessCheck } from './get-logic-slice.js';\n\nexport const OVERLAY_MODES = ['regex', 'communities', 'both', 'contexts'] as const;\n\nexport const InputSchema = z.object({\n layer: z.string().optional(),\n mode: z.enum(OVERLAY_MODES).optional(),\n candidate: z.number().int().positive().optional(),\n});\n\nexport interface CommunityOverlayCluster {\n id: number;\n label: string;\n memberCount: number;\n members: string[];\n godNodes: string[];\n}\n\nexport interface CommunityOverlay {\n clusters: CommunityOverlayCluster[];\n modularity: number;\n edgeQuality: CommunitySnapshot['edgeQuality'];\n crossClusterEdges: number;\n computedAt: string;\n commitSha: string;\n}\n\nexport function buildCommunityOverlay(\n snapshot: CommunitySnapshot,\n options: { memberPreviewLimit?: number } = {},\n): CommunityOverlay {\n const previewLimit = options.memberPreviewLimit ?? 15;\n const byCluster = new Map<number, string[]>();\n for (const entry of snapshot.communities) {\n const list = byCluster.get(entry.communityId) ?? [];\n list.push(entry.symbolId);\n byCluster.set(entry.communityId, list);\n }\n const labelFor = new Map<number, string>();\n for (const entry of snapshot.communities) {\n if (!labelFor.has(entry.communityId)) {\n labelFor.set(entry.communityId, entry.communityLabel);\n }\n }\n const godNodesByCommunity = new Map<number, Set<string>>();\n for (const god of snapshot.godNodes as readonly GodNode[]) {\n for (const communityId of god.bridgedCommunities) {\n const set = godNodesByCommunity.get(communityId) ?? new Set<string>();\n set.add(god.symbolId);\n godNodesByCommunity.set(communityId, set);\n }\n }\n\n const clusters: CommunityOverlayCluster[] = [];\n for (const [id, members] of byCluster) {\n members.sort();\n clusters.push({\n id,\n label: labelFor.get(id) ?? `community-${id}`,\n memberCount: members.length,\n members: members.slice(0, previewLimit),\n godNodes: [...(godNodesByCommunity.get(id) ?? [])].sort(),\n });\n }\n clusters.sort((a, b) => b.memberCount - a.memberCount || a.id - b.id);\n\n return {\n clusters,\n modularity: snapshot.modularity,\n edgeQuality: snapshot.edgeQuality,\n crossClusterEdges: snapshot.crossClusterEdges,\n computedAt: snapshot.computedAt,\n commitSha: snapshot.commitSha,\n };\n}\n\n/** Hubs and collisions listed in the summary, and hubs in the detail (R24); the totals say how many there are. */\nconst HUB_COLLISION_LIMIT = 50;\n/** Top terms per candidate in the summary. */\nconst SUMMARY_TERM_LIMIT = 5;\n/** Files of the candidate in the detail. */\nconst DETAIL_FILE_LIMIT = 15;\n/** Collisions in the detail. */\nconst DETAIL_COLLISION_LIMIT = 10;\n/** The candidate's own occurrences per collision, and members per occurrence, in the detail. */\nconst DETAIL_OCCURRENCE_LIMIT = 5;\n/** Shared tables of the candidate, and the candidate's own data resources, in the detail. */\nconst DETAIL_DATA_LIMIT = 15;\n/** Accesses per shared table in the detail. */\nconst DETAIL_ACCESS_LIMIT = 10;\n\nconst NO_VIEW_HINT = 'No contexts view available. Run ctxo index to generate one.';\nconst SUMMARY_HINT = 'Pass candidate: <id> for one candidate in full; run ctxo contexts --json for the whole view.';\nconst DETAIL_HINT = 'Run ctxo contexts --json for full member sets.';\n\n/** Masks candidate labels, after seeding the masker in sorted order so the `[masked-cluster-N]` numbering is stable. */\nfunction labelMaskerFor(view: ContextsView, labelMasker: ClusterLabelMasker | undefined): (label: string) => string {\n const masker = labelMasker?.isEnabled() ? labelMasker : undefined;\n if (!masker) return (label) => label;\n for (const label of [...new Set(view.candidates.map((c) => c.label))].sort(compareCodepoint)) masker.mask(label);\n return (label) => masker.mask(label);\n}\n\n/** The summary fields of a collision: its name, minimum Jaccard, the ids of the candidates it spans and its size. */\nfunction collisionSummary(collision: TermCollision) {\n return {\n name: collision.name,\n minJaccard: collision.minJaccard,\n candidates: [...new Set(collision.occurrences.map((occurrence) => occurrence.candidate))].sort((a, b) => a - b),\n occurrenceCount: collision.occurrences.length,\n };\n}\n\n/**\n * Every candidate in brief, plus the capped hubs and collisions: small enough to list the whole view. Data\n * coupling appears as counts only (`sharedTableCount` on a candidate with any, and the three resource\n * totals); the lists are in the detail and in `ctxo contexts --json`.\n */\nfunction contextsSummary(view: ContextsView, maskLabel: (label: string) => string): Record<string, unknown> {\n return {\n commitSha: view.commitSha,\n coverage: view.coverage,\n candidates: view.candidates.map((candidate) => ({\n id: candidate.id,\n label: maskLabel(candidate.label),\n fingerprint: candidate.fingerprint,\n fileCount: candidate.fileCount,\n cohesion: candidate.cohesion,\n topTerms: candidate.topTerms.slice(0, SUMMARY_TERM_LIMIT),\n ...(candidate.sharedTables.length > 0 ? { sharedTableCount: candidate.sharedTables.length } : {}),\n })),\n hubs: view.hubs.slice(0, HUB_COLLISION_LIMIT).map((hub) => ({\n file: hub.file,\n reasons: hub.reasons,\n ...(hub.candidate !== undefined ? { candidate: hub.candidate } : {}),\n })),\n hubsTotal: view.hubs.length,\n collisions: view.collisions.slice(0, HUB_COLLISION_LIMIT).map(collisionSummary),\n collisionsTotal: view.collisions.length,\n unclustered: { count: view.unclustered.count },\n dataResourcesTotal: view.dataResources.length,\n sharedResourcesTotal: view.dataResources.filter((resource) => resource.accesses.length >= 2).length,\n externalResourcesTotal: view.dataResources.filter((resource) => resource.external).length,\n hint: SUMMARY_HINT,\n };\n}\n\n/**\n * A shared table in the detail: its accesses capped at `DETAIL_ACCESS_LIMIT` by candidate id, the requesting\n * candidate's own access always kept, with `accessCount`.\n */\nfunction sharedTableDetail(table: CandidateSharedTable, id: number) {\n const own = table.accesses.filter((access) => access.candidate === id);\n const others = table.accesses.filter((access) => access.candidate !== id).slice(0, DETAIL_ACCESS_LIMIT - own.length);\n return {\n ...table,\n accesses: [...own, ...others].sort((a, b) => a.candidate - b.candidate),\n accessCount: table.accesses.length,\n };\n}\n\n/** The resources the candidate reads or writes, compact: its own modes and the writer count. */\nfunction ownDataResources(view: ContextsView, id: number) {\n const own: Array<Record<string, unknown>> = [];\n for (const resource of view.dataResources) {\n const access = resource.accesses.find((entry) => entry.candidate === id);\n if (!access) continue;\n own.push({\n name: resource.name,\n ...(resource.kind !== undefined ? { kind: resource.kind } : {}),\n external: resource.external,\n modes: access.modes,\n ...(resource.owner !== undefined ? { owner: resource.owner } : {}),\n writerCount: resource.writers.length,\n });\n }\n return own;\n}\n\n/**\n * One candidate in full (files capped), the hubs assigned to it (at most `HUB_COLLISION_LIMIT`) and the\n * collisions it takes part in (at most `DETAIL_COLLISION_LIMIT`), each list with its total. A collision carries\n * its summary fields plus this candidate's own occurrences only, at most `DETAIL_OCCURRENCE_LIMIT`, each as\n * `{ symbolId, members, memberCount }` with the first members in view order: the file is part of the symbol\n * ID, and the other candidates are named in `candidates`. The candidate's `sharedTables` keep at most the first\n * `DETAIL_DATA_LIMIT` by name (with `sharedTableCount`), each with at most `DETAIL_ACCESS_LIMIT` accesses (with\n * `accessCount`); `dataResources` lists at most the first `DETAIL_DATA_LIMIT` resources it reads or writes, by\n * name, with `dataResourcesTotal`. No array here is truncatable, so these caps are what keeps the response\n * within the limit, and `fitDataToLimit` then drops trailing data entries while it is still over.\n */\nfunction contextsDetail(\n view: ContextsView,\n id: number,\n maskLabel: (label: string) => string,\n extras: WrapResponseExtras | undefined,\n): Record<string, unknown> {\n const candidate = view.candidates.find((c) => c.id === id);\n if (!candidate) {\n return { found: false, hint: `No candidate ${id} in the contexts view. Call without candidate for the list.` };\n }\n const hubs = view.hubs.filter((hub) => hub.candidate === id);\n const collisions = view.collisions.filter((collision) =>\n collision.occurrences.some((occurrence) => occurrence.candidate === id),\n );\n const dataResources = ownDataResources(view, id);\n const shownTables = candidate.sharedTables.slice(0, DETAIL_DATA_LIMIT).map((table) => sharedTableDetail(table, id));\n const shownResources = dataResources.slice(0, DETAIL_DATA_LIMIT);\n const body = {\n commitSha: view.commitSha,\n candidate: {\n ...candidate,\n label: maskLabel(candidate.label),\n files: candidate.files.slice(0, DETAIL_FILE_LIMIT),\n sharedTables: shownTables,\n sharedTableCount: candidate.sharedTables.length,\n },\n hubs: hubs\n .slice(0, HUB_COLLISION_LIMIT)\n .map((hub) => ({ file: hub.file, reasons: hub.reasons, dependents: hub.dependents, damping: hub.damping })),\n hubsTotal: hubs.length,\n collisions: collisions.slice(0, DETAIL_COLLISION_LIMIT).map((collision) => ({\n ...collisionSummary(collision),\n occurrences: collision.occurrences\n .filter((occurrence) => occurrence.candidate === id)\n .slice(0, DETAIL_OCCURRENCE_LIMIT)\n .map((occurrence) => ({\n symbolId: occurrence.symbolId,\n members: occurrence.members.slice(0, DETAIL_OCCURRENCE_LIMIT),\n memberCount: occurrence.members.length,\n })),\n })),\n collisionsTotal: collisions.length,\n dataResources: shownResources,\n dataResourcesTotal: dataResources.length,\n hint: DETAIL_HINT,\n };\n fitDataToLimit(body, shownTables, shownResources, extras);\n return body;\n}\n\n/**\n * K33: the detail must fit the response limit (`CTXO_RESPONSE_LIMIT`, default 8192), and only its data lists\n * may shrink. While the body, serialised as the envelope sends it, is over the limit, the last entry (by name)\n * of the longer of `sharedTables` and `dataResources` is dropped, `dataResources` on a tie. `sharedTableCount`\n * and `dataResourcesTotal` keep the full totals. The lists are the body's own arrays, shortened in place; every\n * other field stays whole. Deterministic: the same input drops the same entries.\n */\nfunction fitDataToLimit(\n body: Record<string, unknown>,\n tables: unknown[],\n resources: unknown[],\n extras: WrapResponseExtras | undefined,\n): void {\n const limit = getThreshold();\n const size = () => Buffer.byteLength(JSON.stringify(wrapResponse(body, extras)), 'utf-8');\n while ((tables.length > 0 || resources.length > 0) && size() > limit) {\n if (resources.length >= tables.length) resources.pop();\n else tables.pop();\n }\n}\n\n/**\n * Builds the `mode: \"contexts\"` body from the (read-only, shared, deep-frozen) view: the summary of every\n * candidate, or with `candidate` that one candidate in full. Only copies are built (`map`, `slice`, spread):\n * the view must never be sorted or spliced in place. The full view stays in the artifact and in\n * `ctxo contexts --json`; `settings` is left out here. `extras` are the envelope extras the response is sent\n * with, so the detail is measured as it is sent.\n */\nexport function buildContextsOverlay(\n view: ContextsView | undefined,\n options: { candidate?: number; labelMasker?: ClusterLabelMasker; extras?: WrapResponseExtras } = {},\n): Record<string, unknown> {\n if (!view) return { found: false, hint: NO_VIEW_HINT };\n const maskLabel = labelMaskerFor(view, options.labelMasker);\n return options.candidate === undefined\n ? contextsSummary(view, maskLabel)\n : contextsDetail(view, options.candidate, maskLabel, options.extras);\n}\n\nexport function handleGetArchitecturalOverlay(\n storage: IStoragePort,\n masking: IMaskingPort,\n staleness?: StalenessCheck,\n git?: IGitPort,\n clusterLabelMasker?: ClusterLabelMasker,\n contextsView?: IContextsViewPort,\n) {\n const overlay = new ArchitecturalOverlay();\n\n return async (args: Record<string, unknown>) => {\n try {\n const parsed = InputSchema.safeParse(args);\n if (!parsed.success) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: parsed.error.message }) }],\n };\n }\n\n const files = storage.listIndexedFiles();\n const result = overlay.classify(files);\n const mode = parsed.data.mode ?? 'both';\n\n const buildContent = (payloadStr: string) => {\n const content: Array<{ type: 'text'; text: string }> = [];\n if (staleness) {\n const warning = staleness.check(files);\n if (warning) content.push({ type: 'text', text: `⚠️ ${warning.message}` });\n }\n content.push({ type: 'text', text: payloadStr });\n return content;\n };\n\n const stalenessMeta = git ? await buildSnapshotStaleness(storage, git) : undefined;\n const extras = stalenessMeta ? { snapshotStaleness: stalenessMeta } : undefined;\n\n // Filter by layer if specified (regex-mode semantics always apply here)\n if (parsed.data.layer) {\n const filtered = result.layers[parsed.data.layer];\n const payload = masking.mask(\n JSON.stringify(wrapResponse({ layer: parsed.data.layer, files: filtered ?? [] }, extras)),\n );\n return { content: buildContent(payload) };\n }\n\n if (mode === 'contexts') {\n const body = buildContextsOverlay(contextsView?.readContextsView(), {\n candidate: parsed.data.candidate,\n labelMasker: clusterLabelMasker,\n extras,\n });\n const payload = masking.mask(JSON.stringify(wrapResponse(body, extras)));\n return { content: buildContent(payload) };\n }\n\n const rawSnapshot = mode === 'regex' ? undefined : storage.readCommunities();\n const snapshot =\n rawSnapshot && clusterLabelMasker?.isEnabled()\n ? clusterLabelMasker.maskSnapshot(rawSnapshot)\n : rawSnapshot;\n const community = snapshot ? buildCommunityOverlay(snapshot) : undefined;\n\n const body: Record<string, unknown> = {};\n if (mode !== 'communities') body.layers = result.layers;\n if (community) body.communities = community;\n if (mode === 'communities' && !community) {\n body.hint = 'No community snapshot available. Run `ctxo index` to generate one.';\n }\n\n const payload = masking.mask(JSON.stringify(wrapResponse(body, extras)));\n return { content: buildContent(payload) };\n } catch (err) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: (err as Error).message }) }],\n };\n }\n };\n}\n","import { z } from 'zod';\nimport type { IStoragePort } from '../../ports/i-storage-port.js';\nimport type { IMaskingPort } from '../../ports/i-masking-port.js';\nimport { DeadCodeDetector } from '../../core/dead-code/dead-code-detector.js';\nimport { getGraphAndFiles } from './get-logic-slice.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\nimport { filterByIntent } from '../../core/intent-filter.js';\nimport type { StalenessCheck } from './get-logic-slice.js';\n\nexport const InputSchema = z.object({\n includeTests: z.boolean().optional().default(false),\n intent: z.string().optional().describe('Filter dead code results by intent keywords (e.g., \"adapter\", \"core\", \"function\")'),\n});\n\nexport function handleFindDeadCode(\n storage: IStoragePort,\n masking: IMaskingPort,\n staleness?: StalenessCheck,\n ctxoRoot = '.ctxo',\n) {\n const detector = new DeadCodeDetector();\n\n const getGraph = () => getGraphAndFiles(ctxoRoot, storage);\n\n return (args: Record<string, unknown>) => {\n try {\n const parsed = InputSchema.safeParse(args);\n if (!parsed.success) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: parsed.error.message }) }],\n };\n }\n\n const { graph, indexedFiles } = getGraph();\n const result = detector.detect(graph, { includeTests: parsed.data.includeTests });\n\n // Apply intent filter to deadSymbols if requested\n const filtered = {\n ...result,\n deadSymbols: filterByIntent(result.deadSymbols as unknown as Record<string, unknown>[], parsed.data.intent) as unknown as typeof result.deadSymbols,\n };\n\n const payload = masking.mask(JSON.stringify(wrapResponse(filtered as unknown as Record<string, unknown>)));\n\n const content: Array<{ type: 'text'; text: string }> = [];\n if (staleness) {\n const warning = staleness.check(indexedFiles);\n if (warning) content.push({ type: 'text', text: `⚠️ ${warning.message}` });\n }\n content.push({ type: 'text', text: payload });\n\n return { content };\n } catch (err) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: (err as Error).message }) }],\n };\n }\n };\n}\n","import { z } from 'zod';\nimport type { IStoragePort } from '../../ports/i-storage-port.js';\nimport type { IMaskingPort } from '../../ports/i-masking-port.js';\nimport type { ICoChangePort } from '../../ports/i-co-change-port.js';\nimport { ContextAssembler } from '../../core/context-assembly/context-assembler.js';\nimport { JsonIndexReader } from '../storage/json-index-reader.js';\nimport { getGraphAndFiles } from './get-logic-slice.js';\nimport type { StalenessCheck } from './get-logic-slice.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\n\nconst TaskTypeSchema = z.enum(['fix', 'extend', 'refactor', 'understand']);\n\nexport const InputSchema = z.object({\n symbolId: z.string().min(1),\n taskType: TaskTypeSchema,\n tokenBudget: z.number().min(100).optional().default(4000),\n});\n\nexport function handleGetContextForTask(\n storage: IStoragePort,\n masking: IMaskingPort,\n staleness?: StalenessCheck,\n ctxoRoot = '.ctxo',\n coChange?: ICoChangePort,\n) {\n const assembler = new ContextAssembler();\n const indexReader = new JsonIndexReader(ctxoRoot);\n\n const getGraph = () => getGraphAndFiles(ctxoRoot, storage);\n\n return (args: Record<string, unknown>) => {\n try {\n const parsed = InputSchema.safeParse(args);\n if (!parsed.success) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: parsed.error.message }) }],\n };\n }\n\n const { symbolId, taskType, tokenBudget } = parsed.data;\n const { graph, indexedFiles } = getGraph();\n const indices = indexReader.readAll();\n\n const result = assembler.assembleForTask(graph, symbolId, taskType, indices, tokenBudget, coChange?.readCoChangeMap());\n\n if (!result) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ found: false, hint: 'Symbol not found. Run \"ctxo index\".' }) }],\n };\n }\n\n const payload = masking.mask(JSON.stringify(wrapResponse(result as unknown as Record<string, unknown>)));\n\n const content: Array<{ type: 'text'; text: string }> = [];\n if (staleness) {\n const warning = staleness.check(indexedFiles);\n if (warning) content.push({ type: 'text', text: `⚠️ ${warning.message}` });\n }\n content.push({ type: 'text', text: payload });\n\n return { content };\n } catch (err) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: (err as Error).message }) }],\n };\n }\n };\n}\n","export type TaskType = 'fix' | 'extend' | 'refactor' | 'understand';\n\nexport interface ScoringWeights {\n readonly directDependency: number;\n readonly interfaceTypeDef: number;\n readonly blastRadiusDependent: number;\n readonly highComplexity: number;\n readonly antiPatternHistory: number;\n}\n\nconst TASK_WEIGHTS: Record<TaskType, ScoringWeights> = {\n fix: {\n directDependency: 0.3,\n interfaceTypeDef: 0.1,\n blastRadiusDependent: 0.1,\n highComplexity: 0.2,\n antiPatternHistory: 0.3,\n },\n extend: {\n directDependency: 0.4,\n interfaceTypeDef: 0.5,\n blastRadiusDependent: 0.1,\n highComplexity: 0.0,\n antiPatternHistory: 0.0,\n },\n refactor: {\n directDependency: 0.2,\n interfaceTypeDef: 0.1,\n blastRadiusDependent: 0.5,\n highComplexity: 0.1,\n antiPatternHistory: 0.1,\n },\n understand: {\n directDependency: 0.5,\n interfaceTypeDef: 0.3,\n blastRadiusDependent: 0.1,\n highComplexity: 0.1,\n antiPatternHistory: 0.0,\n },\n};\n\nexport function getWeightsForTask(taskType: TaskType): ScoringWeights {\n return TASK_WEIGHTS[taskType];\n}\n","import type { SymbolGraph } from '../graph/symbol-graph.js';\nimport { SYMBOL_KINDS, type SymbolNode, type SymbolKind, type FileIndex, type CoChangeEntry } from '../types.js';\nimport { LogicSliceQuery } from '../logic-slice/logic-slice-query.js';\nimport { BlastRadiusCalculator, type ImpactConfidence } from '../blast-radius/blast-radius-calculator.js';\nimport { withoutAnnotations } from '../detail-levels/detail-formatter.js';\nimport { type TaskType, type ScoringWeights, getWeightsForTask } from './task-context-strategy.js';\n\nexport interface ContextEntry {\n readonly symbolId: string;\n readonly name: string;\n readonly kind: SymbolKind;\n readonly file: string;\n readonly relevanceScore: number;\n readonly reason: string;\n readonly lines: number;\n readonly tokens: number;\n /**\n * The blast radius tier of a dependent of the target (what breaks if the target changes). Absent on\n * entries that are not dependents, such as the target's own dependencies.\n */\n readonly confidence?: ImpactConfidence;\n}\n\nexport interface TaskContextResult {\n readonly target: SymbolNode;\n readonly taskType: TaskType;\n readonly context: ContextEntry[];\n readonly totalTokens: number;\n readonly tokenBudget: number;\n readonly warnings: string[];\n}\n\nexport interface RankedContextResult {\n readonly query: string;\n readonly strategy: string;\n readonly results: Array<{\n readonly symbolId: string;\n readonly name: string;\n readonly kind: SymbolKind;\n readonly file: string;\n readonly relevanceScore: number;\n readonly importanceScore: number;\n readonly combinedScore: number;\n readonly tokens: number;\n }>;\n readonly totalTokens: number;\n readonly tokenBudget: number;\n}\n\nconst DEFAULT_TOKEN_BUDGET = 4000;\n\nexport class ContextAssembler {\n private readonly logicSlice = new LogicSliceQuery();\n private readonly blastRadius = new BlastRadiusCalculator();\n\n /**\n * `coChangeMap` is the same lookup `get_blast_radius` uses: with it, a potential dependent whose file\n * co-changes with the target's becomes likely. It changes the tier shown on an entry, not which entries\n * make the context or how they rank.\n */\n assembleForTask(\n graph: SymbolGraph,\n symbolId: string,\n taskType: TaskType,\n indices: readonly FileIndex[],\n tokenBudget = DEFAULT_TOKEN_BUDGET,\n coChangeMap?: Map<string, CoChangeEntry[]>,\n ): TaskContextResult | undefined {\n // Resolve the id once: a 2-part data id names its winning definition.\n const target = graph.getNode(symbolId);\n if (!target) return undefined;\n const targetId = target.symbolId;\n\n const weights = getWeightsForTask(taskType);\n\n // Gather forward deps + reverse deps\n const slice = this.logicSlice.getLogicSlice(graph, targetId);\n const blastResult = this.blastRadius.calculate(graph, targetId, coChangeMap);\n\n // Build candidate pool (deduplicated)\n const candidateMap = new Map<string, { node: SymbolNode; signals: Signals }>();\n\n // Forward dependencies\n if (slice) {\n for (const dep of slice.dependencies) {\n candidateMap.set(dep.symbolId, {\n node: dep,\n signals: { isDirectDep: true, isInterfaceOrType: this.isInterfaceOrType(dep.kind), isDependent: false, complexity: 0, hasAntiPattern: false },\n });\n }\n }\n\n // Reverse dependents (blast radius) — fall back to a synthetic node when\n // the edge source has no matching symbols[] entry (e.g. test files that\n // only import). Without this, symbols whose importers are all such files\n // would produce an empty context even when reverse edges clearly exist.\n for (const entry of blastResult.impactedSymbols) {\n const node = graph.getNode(entry.symbolId) ?? synthesizeNodeFromId(entry.symbolId);\n if (!node) continue;\n\n const existing = candidateMap.get(entry.symbolId);\n if (existing) {\n existing.signals.isDependent = true;\n existing.signals.dependentConfidence = entry.confidence;\n } else {\n candidateMap.set(entry.symbolId, {\n node,\n signals: { isDirectDep: false, isInterfaceOrType: this.isInterfaceOrType(node.kind), isDependent: true, dependentConfidence: entry.confidence, complexity: 0, hasAntiPattern: false },\n });\n }\n }\n\n // Enrich with complexity + anti-patterns from index\n const fileIndexMap = new Map(indices.map((i) => [i.file, i]));\n for (const [sid, candidate] of candidateMap) {\n const file = sid.split('::')[0] ?? '';\n const fileIndex = fileIndexMap.get(file);\n\n if (fileIndex) {\n const complexity = fileIndex.complexity?.find((c) => c.symbolId === sid);\n candidate.signals.complexity = complexity?.cyclomatic ?? 0;\n candidate.signals.hasAntiPattern = fileIndex.antiPatterns.length > 0;\n }\n }\n\n // Score and rank\n const scored = [...candidateMap.entries()].map(([, { node, signals }]) => ({\n entry: this.buildContextEntry(node, signals, weights),\n score: this.computeScore(signals, weights),\n }));\n\n scored.sort((a, b) => b.score - a.score);\n\n // Greedy pack within token budget\n const context: ContextEntry[] = [];\n let totalTokens = 0;\n\n for (const { entry } of scored) {\n if (totalTokens + entry.tokens > tokenBudget) continue;\n context.push(entry);\n totalTokens += entry.tokens;\n }\n\n // Warnings\n const warnings: string[] = [];\n const targetFile = targetId.split('::')[0] ?? '';\n const targetIndex = fileIndexMap.get(targetFile);\n if (targetIndex && targetIndex.antiPatterns.length > 0) {\n warnings.push(`⚠ Target symbol has ${targetIndex.antiPatterns.length} anti-pattern(s) in file history`);\n }\n\n // The target leaves its annotations out, as logic slices below L4 do (see withoutAnnotations).\n return { target: withoutAnnotations(target), taskType, context, totalTokens, tokenBudget, warnings };\n }\n\n assembleRanked(\n graph: SymbolGraph,\n query: string,\n strategy: 'combined' | 'dependency' | 'importance' = 'combined',\n tokenBudget = DEFAULT_TOKEN_BUDGET,\n ): RankedContextResult {\n const allNodes = graph.allNodes();\n const queryLower = query.toLowerCase();\n\n // Compute max reverse edges for importance normalization\n let maxReverseEdges = 1;\n for (const node of allNodes) {\n const count = graph.getReverseEdges(node.symbolId).length;\n if (count > maxReverseEdges) maxReverseEdges = count;\n }\n\n // Score each symbol\n const scored = allNodes.map((node) => {\n const relevanceScore = this.computeTextRelevance(node.name, queryLower);\n const importanceScore = graph.getReverseEdges(node.symbolId).length / maxReverseEdges;\n\n let combinedScore: number;\n switch (strategy) {\n case 'dependency':\n combinedScore = relevanceScore;\n break;\n case 'importance':\n combinedScore = importanceScore;\n break;\n default:\n combinedScore = relevanceScore * 0.6 + importanceScore * 0.4;\n }\n\n return {\n symbolId: node.symbolId,\n name: node.name,\n kind: node.kind,\n file: node.symbolId.split('::')[0] ?? '',\n relevanceScore: Math.round(relevanceScore * 1000) / 1000,\n importanceScore: Math.round(importanceScore * 1000) / 1000,\n combinedScore: Math.round(combinedScore * 1000) / 1000,\n tokens: this.estimateTokens(node),\n };\n });\n\n // Filter zero-relevance for text-based strategies\n const filtered = strategy === 'importance'\n ? scored\n : scored.filter((s) => s.relevanceScore > 0 || s.importanceScore > 0.1);\n\n filtered.sort((a, b) => b.combinedScore - a.combinedScore);\n\n // Greedy pack\n const results: typeof filtered = [];\n let totalTokens = 0;\n\n for (const item of filtered) {\n if (totalTokens + item.tokens > tokenBudget) continue;\n results.push(item);\n totalTokens += item.tokens;\n }\n\n return { query, strategy, results, totalTokens, tokenBudget };\n }\n\n private computeTextRelevance(name: string, queryLower: string): number {\n const nameLower = name.toLowerCase();\n if (nameLower === queryLower) return 1.0;\n if (nameLower.includes(queryLower)) return 0.7;\n if (queryLower.split(/\\s+/).some((word) => nameLower.includes(word))) return 0.4;\n return 0;\n }\n\n private computeScore(signals: Signals, weights: ScoringWeights): number {\n let score = 0;\n if (signals.isDirectDep) score += weights.directDependency;\n if (signals.isInterfaceOrType) score += weights.interfaceTypeDef;\n if (signals.isDependent) score += weights.blastRadiusDependent;\n if (signals.complexity > 5) score += weights.highComplexity;\n if (signals.hasAntiPattern) score += weights.antiPatternHistory;\n return Math.round(score * 1000) / 1000;\n }\n\n private buildContextEntry(node: SymbolNode, signals: Signals, weights: ScoringWeights): ContextEntry {\n const reasons: string[] = [];\n if (signals.isDirectDep) reasons.push('direct dependency');\n if (signals.isInterfaceOrType) reasons.push('type/interface definition');\n if (signals.isDependent) reasons.push('blast radius dependent');\n if (signals.complexity > 5) reasons.push(`high complexity (CC=${signals.complexity})`);\n if (signals.hasAntiPattern) reasons.push('anti-pattern history');\n\n return {\n symbolId: node.symbolId,\n name: node.name,\n kind: node.kind,\n file: node.symbolId.split('::')[0] ?? '',\n relevanceScore: this.computeScore(signals, weights),\n reason: reasons.join(', ') || 'related symbol',\n lines: node.endLine - node.startLine + 1,\n tokens: this.estimateTokens(node),\n ...(signals.dependentConfidence ? { confidence: signals.dependentConfidence } : {}),\n };\n }\n\n private isInterfaceOrType(kind: SymbolKind): boolean {\n return kind === 'interface' || kind === 'type';\n }\n\n estimateTokensPublic(node: SymbolNode): number {\n return this.estimateTokens(node);\n }\n\n private estimateTokens(node: SymbolNode): number {\n // Use byte offsets for accurate estimation when available (~4 chars per token)\n if (node.startOffset !== undefined && node.endOffset !== undefined) {\n return Math.ceil((node.endOffset - node.startOffset) / 4);\n }\n return (node.endLine - node.startLine + 1) * 10;\n }\n}\n\ninterface Signals {\n isDirectDep: boolean;\n isInterfaceOrType: boolean;\n isDependent: boolean;\n /** The blast radius tier of the dependency; set exactly when `isDependent` is. */\n dependentConfidence?: ImpactConfidence;\n complexity: number;\n hasAntiPattern: boolean;\n}\n\nconst VALID_SYMBOL_KINDS: ReadonlySet<string> = new Set<string>(SYMBOL_KINDS);\n\n/**\n * Build a minimal SymbolNode from a symbolId string. Used when a blast-radius\n * entry points at an orphan edge source (no matching symbols[] entry in the\n * index). startLine/endLine are 0 so token estimation falls back to a small\n * default without over-counting missing source ranges.\n */\nfunction synthesizeNodeFromId(symbolId: string): SymbolNode | undefined {\n const parts = symbolId.split('::');\n if (parts.length !== 3) return undefined;\n const [file, name, kindRaw] = parts;\n if (!file || !name || !kindRaw) return undefined;\n const kind = VALID_SYMBOL_KINDS.has(kindRaw) ? (kindRaw as SymbolKind) : 'variable';\n return { symbolId, name, kind, startLine: 0, endLine: 0 };\n}\n","import { z } from 'zod';\nimport type { IStoragePort } from '../../ports/i-storage-port.js';\nimport type { IMaskingPort } from '../../ports/i-masking-port.js';\nimport { ContextAssembler } from '../../core/context-assembly/context-assembler.js';\nimport { getGraphAndFiles } from './get-logic-slice.js';\nimport type { StalenessCheck } from './get-logic-slice.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\nimport { SearchEngine } from '../../core/search/search-engine.js';\nimport type { ISearchPort } from '../../ports/i-search-port.js';\nimport { createLogger } from '../../core/logger.js';\n\nconst log = createLogger('ctxo:search');\n\nexport const InputSchema = z.object({\n query: z.string().min(1),\n tokenBudget: z.number().min(100).optional().default(4000),\n strategy: z.enum(['combined', 'dependency', 'importance']).optional().default('combined'),\n searchMode: z.enum(['fts', 'legacy']).optional().default('fts'),\n});\n\nexport function handleGetRankedContext(\n storage: IStoragePort,\n masking: IMaskingPort,\n staleness?: StalenessCheck,\n ctxoRoot = '.ctxo',\n searchEngine?: ISearchPort,\n) {\n const assembler = new ContextAssembler();\n const engine: ISearchPort = searchEngine ?? new SearchEngine();\n\n const getGraph = () => getGraphAndFiles(ctxoRoot, storage);\n\n let lastNodeCount = -1;\n\n return (args: Record<string, unknown>) => {\n try {\n const parsed = InputSchema.safeParse(args);\n if (!parsed.success) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: parsed.error.message }) }],\n };\n }\n\n const { query, tokenBudget, strategy, searchMode } = parsed.data;\n const { graph, indexedFiles } = getGraph();\n\n // Use new search engine when mode is 'fts'\n if (searchMode === 'fts' && strategy !== 'importance') {\n // Rebuild search index when graph changes (detected by node count change)\n const currentNodeCount = graph.nodeCount;\n if (currentNodeCount !== lastNodeCount) {\n const allNodes = graph.allNodes();\n // Compute PageRank scores (normalized reverse edge count)\n const pageRankScores = new Map<string, number>();\n let maxReverseEdges = 1;\n for (const node of allNodes) {\n const count = graph.getReverseEdges(node.symbolId).length;\n if (count > maxReverseEdges) maxReverseEdges = count;\n }\n for (const node of allNodes) {\n const count = graph.getReverseEdges(node.symbolId).length;\n pageRankScores.set(node.symbolId, count / maxReverseEdges);\n }\n\n engine.buildIndex(allNodes, pageRankScores);\n lastNodeCount = currentNodeCount;\n log.info(`Search engine: ${engine.getTier()} (${allNodes.length} symbols)`);\n }\n\n const searchResult = engine.search(query, 100);\n\n // Greedy pack within token budget\n const results: Array<{\n symbolId: string;\n name: string;\n kind: string;\n file: string;\n relevanceScore: number;\n importanceScore: number;\n combinedScore: number;\n tokens: number;\n }> = [];\n let totalTokens = 0;\n\n for (const sr of searchResult.results) {\n const node = graph.getNode(sr.symbolId);\n const tokens = node ? assembler.estimateTokensPublic(node) : 90;\n\n if (totalTokens + tokens > tokenBudget) continue;\n results.push({\n symbolId: sr.symbolId,\n name: sr.name,\n kind: sr.kind,\n file: sr.filePath,\n relevanceScore: Math.round(sr.relevanceScore * 1000) / 1000,\n importanceScore: Math.round(sr.importanceScore * 1000) / 1000,\n combinedScore: Math.round(sr.combinedScore * 1000) / 1000,\n tokens,\n });\n totalTokens += tokens;\n }\n\n const payload = masking.mask(JSON.stringify(wrapResponse({\n query,\n strategy,\n results,\n totalTokens,\n tokenBudget,\n searchMetrics: searchResult.metrics,\n ...(searchResult.fuzzyCorrection ? { fuzzyCorrection: searchResult.fuzzyCorrection } : {}),\n })));\n\n const content: Array<{ type: 'text'; text: string }> = [];\n if (staleness) {\n const warning = staleness.check(indexedFiles);\n if (warning) content.push({ type: 'text', text: `⚠️ ${warning.message}` });\n }\n content.push({ type: 'text', text: payload });\n\n return { content };\n }\n\n // Legacy mode: use existing substring matching\n const result = assembler.assembleRanked(graph, query, strategy, tokenBudget);\n\n const payload = masking.mask(JSON.stringify(wrapResponse(result as unknown as Record<string, unknown>)));\n\n const content: Array<{ type: 'text'; text: string }> = [];\n if (staleness) {\n const warning = staleness.check(indexedFiles);\n if (warning) content.push({ type: 'text', text: `⚠️ ${warning.message}` });\n }\n content.push({ type: 'text', text: payload });\n\n return { content };\n } catch (err) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: (err as Error).message }) }],\n };\n }\n };\n}\n","/**\n * Fuzzy Corrector — Damerau-Levenshtein based typo correction.\n *\n * Uses adaptive thresholds: d≤1 for terms ≤5 chars, d≤2 for longer terms.\n * Vocabulary is built from tokenized symbol names during index build.\n */\n\nimport type { FuzzyCorrection } from '../types.js';\n\nexport class FuzzyCorrector {\n /** term → frequency (for tie-breaking) */\n private vocabulary: Map<string, number> = new Map();\n\n buildVocabulary(termFrequencies: Map<string, number>): void {\n this.vocabulary = new Map(termFrequencies);\n }\n\n /**\n * Attempt to correct query tokens.\n * Returns null if no correction found or no improvement possible.\n */\n correct(queryTokens: string[]): FuzzyCorrection | null {\n if (this.vocabulary.size === 0) return null;\n\n const corrections: FuzzyCorrection['corrections'] = [];\n const correctedTokens: string[] = [];\n let anyChanged = false;\n\n for (const token of queryTokens) {\n // Skip very short tokens (1-2 chars) — too many false matches\n if (token.length <= 2) {\n correctedTokens.push(token);\n continue;\n }\n\n // Check if token exists in vocabulary (exact match)\n if (this.vocabulary.has(token)) {\n correctedTokens.push(token);\n continue;\n }\n\n const maxDist = token.length <= 5 ? 1 : 2;\n const best = this.findClosest(token, maxDist);\n\n if (best) {\n corrections.push({\n original: token,\n corrected: best.term,\n distance: best.distance,\n });\n correctedTokens.push(best.term);\n anyChanged = true;\n } else {\n correctedTokens.push(token);\n }\n }\n\n if (!anyChanged) return null;\n\n return {\n originalQuery: queryTokens.join(' '),\n correctedQuery: correctedTokens.join(' '),\n corrections,\n };\n }\n\n /**\n * Find the closest vocabulary term within maxDistance.\n * Tie-breaks by frequency (higher = preferred).\n */\n private findClosest(\n token: string,\n maxDistance: number,\n ): { term: string; distance: number } | null {\n let bestTerm: string | null = null;\n let bestDist = maxDistance + 1;\n let bestFreq = -1;\n\n for (const [vocabTerm, freq] of this.vocabulary) {\n // Quick length filter: Damerau-Levenshtein ≥ |len difference|\n if (Math.abs(vocabTerm.length - token.length) > maxDistance) continue;\n\n const dist = damerauLevenshtein(token, vocabTerm);\n if (dist <= maxDistance) {\n if (dist < bestDist || (dist === bestDist && freq > bestFreq)) {\n bestTerm = vocabTerm;\n bestDist = dist;\n bestFreq = freq;\n }\n }\n }\n\n return bestTerm !== null ? { term: bestTerm, distance: bestDist } : null;\n }\n}\n\n/**\n * Damerau-Levenshtein distance.\n * Includes transpositions as a single edit operation.\n * \"tokne\" → \"token\" = distance 1 (transposition), not 2 (delete + insert).\n */\nexport function damerauLevenshtein(a: string, b: string): number {\n const lenA = a.length;\n const lenB = b.length;\n\n if (lenA === 0) return lenB;\n if (lenB === 0) return lenA;\n\n // Optimal string alignment distance (restricted edit distance)\n const d: number[][] = Array.from({ length: lenA + 1 }, () => new Array<number>(lenB + 1).fill(0));\n\n for (let i = 0; i <= lenA; i++) d[i]![0] = i;\n for (let j = 0; j <= lenB; j++) d[0]![j] = j;\n\n for (let i = 1; i <= lenA; i++) {\n for (let j = 1; j <= lenB; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n d[i]![j] = Math.min(\n d[i - 1]![j]! + 1, // deletion\n d[i]![j - 1]! + 1, // insertion\n d[i - 1]![j - 1]! + cost, // substitution\n );\n\n // Transposition\n if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {\n d[i]![j] = Math.min(d[i]![j]!, d[i - 2]![j - 2]! + cost);\n }\n }\n }\n\n return d[lenA]![lenB]!;\n}\n","/**\n * In-memory BM25 Search Engine (Tier 2)\n *\n * Implements two-phase cascade search:\n * Phase 1: Exact + tokenized matching with BM25 scoring\n * Phase 2: Trigram/partial matching (activated when Phase 1 returns < threshold results)\n * Phase 3: Fuzzy correction (activated when Phase 1+2 return < threshold results)\n *\n * Scoring: BM25 * (1 + pageRankWeight * pageRankScore) * bigramBoost\n */\n\nimport type { SymbolNode, SearchResponse, SearchResult, SearchMetrics } from '../types.js';\nimport { SymbolTokenizer } from './symbol-tokenizer.js';\nimport { FuzzyCorrector } from './fuzzy-corrector.js';\nimport { createLogger } from '../logger.js';\n\nconst log = createLogger('ctxo:search');\n\n/** BM25 parameters tuned for code search (short documents) */\ninterface BM25Config {\n k1: number; // term frequency saturation (default: 1.2)\n b: number; // length normalization (default: 0.25 — low for short symbol names)\n}\n\ninterface SearchEngineConfig {\n bm25: BM25Config;\n /** Weight of PageRank boost: finalScore = bm25 * (1 + pageRankWeight * pr) */\n pageRankWeight: number;\n /** Score penalty for Phase 2 (trigram) results */\n trigramPenalty: number;\n /** Threshold: if Phase 1 returns fewer results, activate Phase 2 */\n phase2Threshold: number;\n /** Threshold: if Phase 1+2 return fewer results, activate fuzzy correction */\n fuzzyThreshold: number;\n /** Maximum results per phase */\n maxPerPhase: number;\n}\n\nconst DEFAULT_CONFIG: SearchEngineConfig = {\n bm25: { k1: 1.2, b: 0.25 },\n pageRankWeight: 0.5,\n trigramPenalty: 0.8,\n phase2Threshold: 3,\n fuzzyThreshold: 3,\n maxPerPhase: 50,\n};\n\n/** A document in the inverted index (one per symbol) */\ninterface IndexedDocument {\n symbolId: string;\n name: string;\n kind: string;\n filePath: string;\n /** Tokenized name (from SymbolTokenizer) */\n tokens: string[];\n /** Token count (document length for BM25) */\n length: number;\n}\n\n/** Posting list entry */\ninterface Posting {\n docIndex: number;\n termFrequency: number;\n}\n\nexport class SearchEngine {\n private readonly config: SearchEngineConfig;\n private readonly tokenizer: SymbolTokenizer;\n private readonly fuzzy: FuzzyCorrector;\n\n // Primary index (exact + tokenized)\n private documents: IndexedDocument[] = [];\n private primaryIndex: Map<string, Posting[]> = new Map();\n private avgDocLength = 0;\n\n // Trigram index (character 3-grams)\n private trigramIndex: Map<string, Posting[]> = new Map();\n\n // PageRank scores\n private pageRankScores: Map<string, number> = new Map();\n\n constructor(config?: Partial<SearchEngineConfig>) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n this.tokenizer = new SymbolTokenizer({ includeOriginal: true, includeFilePath: true });\n this.fuzzy = new FuzzyCorrector();\n }\n\n getTier(): 'fts5' | 'in-memory' | 'legacy' {\n return 'in-memory';\n }\n\n buildIndex(symbols: SymbolNode[], pageRankScores?: Map<string, number>): void {\n const start = performance.now();\n this.documents = [];\n this.primaryIndex = new Map();\n this.trigramIndex = new Map();\n this.pageRankScores = pageRankScores ?? new Map();\n\n let totalLength = 0;\n const vocabFreq = new Map<string, number>();\n\n for (const sym of symbols) {\n const filePath = sym.symbolId.split('::')[0] ?? '';\n const tokens = this.tokenizer.tokenize(sym.name, filePath);\n const doc: IndexedDocument = {\n symbolId: sym.symbolId,\n name: sym.name,\n kind: sym.kind,\n filePath,\n tokens,\n length: tokens.length,\n };\n const docIndex = this.documents.length;\n this.documents.push(doc);\n totalLength += tokens.length;\n\n // Build primary inverted index\n const termFreqs = new Map<string, number>();\n for (const token of tokens) {\n termFreqs.set(token, (termFreqs.get(token) ?? 0) + 1);\n vocabFreq.set(token, (vocabFreq.get(token) ?? 0) + 1);\n }\n for (const [term, tf] of termFreqs) {\n let postings = this.primaryIndex.get(term);\n if (!postings) {\n postings = [];\n this.primaryIndex.set(term, postings);\n }\n postings.push({ docIndex, termFrequency: tf });\n }\n\n // Build trigram index from symbol name (lowercased)\n const nameLower = sym.name.toLowerCase();\n const trigrams = this.extractTrigrams(nameLower);\n const trigramFreqs = new Map<string, number>();\n for (const tri of trigrams) {\n trigramFreqs.set(tri, (trigramFreqs.get(tri) ?? 0) + 1);\n }\n for (const [tri, tf] of trigramFreqs) {\n let postings = this.trigramIndex.get(tri);\n if (!postings) {\n postings = [];\n this.trigramIndex.set(tri, postings);\n }\n postings.push({ docIndex, termFrequency: tf });\n }\n }\n\n this.avgDocLength = this.documents.length > 0 ? totalLength / this.documents.length : 1;\n\n // Build vocabulary for fuzzy corrector\n this.fuzzy.buildVocabulary(vocabFreq);\n\n const elapsed = performance.now() - start;\n log.info(`Index built: ${symbols.length} symbols, ${this.primaryIndex.size} terms, ${this.trigramIndex.size} trigrams (${elapsed.toFixed(0)}ms)`);\n }\n\n search(query: string, limit = 50): SearchResponse {\n const start = performance.now();\n const queryTokens = this.tokenizer.tokenizeQuery(query);\n\n if (queryTokens.length === 0) {\n return this.emptyResponse(query, start);\n }\n\n const metrics: SearchMetrics = {\n porterHits: 0,\n trigramHits: 0,\n phase2Activated: false,\n fuzzyApplied: false,\n latencyMs: 0,\n };\n\n // Phase 1: Primary index search (exact + tokenized)\n const phase1Scores = this.bm25Search(queryTokens, this.primaryIndex);\n metrics.porterHits = phase1Scores.size;\n\n let allScores = phase1Scores;\n\n // Phase 2: Trigram search (if Phase 1 insufficient)\n if (phase1Scores.size < this.config.phase2Threshold) {\n metrics.phase2Activated = true;\n const queryLower = query.toLowerCase();\n\n // Skip trigram for very short queries (< 3 chars produces no useful trigrams)\n if (queryLower.length >= 3) {\n const queryTrigrams = this.extractTrigrams(queryLower);\n const phase2Scores = this.bm25Search(queryTrigrams, this.trigramIndex);\n metrics.trigramHits = phase2Scores.size;\n\n // Merge: union by symbolId, Phase 2 with penalty\n allScores = this.mergeScores(phase1Scores, phase2Scores, this.config.trigramPenalty);\n }\n }\n\n // Phase 3: Fuzzy correction (if still insufficient)\n let fuzzyCorrection: SearchResponse['fuzzyCorrection'];\n if (allScores.size < this.config.fuzzyThreshold) {\n const correction = this.fuzzy.correct(queryTokens);\n if (correction) {\n metrics.fuzzyApplied = true;\n fuzzyCorrection = correction;\n const correctedTokens = this.tokenizer.tokenizeQuery(correction.correctedQuery);\n const fuzzyScores = this.bm25Search(correctedTokens, this.primaryIndex);\n\n // Merge fuzzy results (with slight penalty)\n allScores = this.mergeScores(allScores, fuzzyScores, 0.9);\n\n // Also try trigram on corrected query\n if (allScores.size < this.config.fuzzyThreshold && correction.correctedQuery.length >= 3) {\n const correctedTrigrams = this.extractTrigrams(correction.correctedQuery.toLowerCase());\n const fuzzyTrigramScores = this.bm25Search(correctedTrigrams, this.trigramIndex);\n allScores = this.mergeScores(allScores, fuzzyTrigramScores, this.config.trigramPenalty * 0.9);\n }\n }\n }\n\n // Snapshot raw BM25 relevance scores before boosts\n const rawRelevance = new Map(allScores);\n\n // Apply bigram boost for multi-word queries (applies to ALL paths including fuzzy)\n const effectiveQueryTerms = fuzzyCorrection\n ? this.tokenizer.tokenizeQuery(fuzzyCorrection.correctedQuery)\n : queryTokens;\n\n if (effectiveQueryTerms.length >= 2) {\n for (const [docIdx, score] of allScores) {\n const doc = this.documents[docIdx]!;\n const boost = this.bigramBoost(effectiveQueryTerms, doc.tokens);\n allScores.set(docIdx, score * boost);\n }\n }\n\n // Apply PageRank boost (applies to ALL paths including fuzzy)\n for (const [docIdx, score] of allScores) {\n const doc = this.documents[docIdx]!;\n const pr = this.pageRankScores.get(doc.symbolId) ?? 0;\n allScores.set(docIdx, score * (1 + this.config.pageRankWeight * pr));\n }\n\n metrics.latencyMs = performance.now() - start;\n const results = this.buildResults(allScores, rawRelevance, limit);\n\n const phaseInfo = metrics.phase2Activated ? 'phase2=yes' : 'phase2=no';\n if (fuzzyCorrection) {\n log.info(`search \"${query}\" → fuzzy \"${fuzzyCorrection.correctedQuery}\": ${results.length} results (${metrics.latencyMs.toFixed(0)}ms)`);\n } else {\n log.info(`search \"${query}\": ${results.length} results, porter=${metrics.porterHits} trigram=${metrics.trigramHits} ${phaseInfo} (${metrics.latencyMs.toFixed(0)}ms)`);\n }\n\n return { query, results, metrics, ...(fuzzyCorrection ? { fuzzyCorrection } : {}) };\n }\n\n updateFile(filePath: string, symbols: SymbolNode[]): void {\n // Remove old documents for this file\n const oldIndices = new Set<number>();\n for (let i = 0; i < this.documents.length; i++) {\n if (this.documents[i]!.filePath === filePath) {\n oldIndices.add(i);\n }\n }\n\n if (oldIndices.size === 0 && symbols.length === 0) return;\n\n // Full rebuild (simpler and correct for incremental updates)\n const allSymbols: SymbolNode[] = [];\n for (let i = 0; i < this.documents.length; i++) {\n if (!oldIndices.has(i)) {\n const doc = this.documents[i]!;\n allSymbols.push({\n symbolId: doc.symbolId,\n name: doc.name,\n kind: doc.kind as SymbolNode['kind'],\n startLine: 0,\n endLine: 0,\n });\n }\n }\n allSymbols.push(...symbols);\n this.buildIndex(allSymbols, this.pageRankScores);\n }\n\n /**\n * BM25 scoring over an inverted index.\n * Returns Map<docIndex, score>\n */\n private bm25Search(queryTerms: string[], index: Map<string, Posting[]>): Map<number, number> {\n const scores = new Map<number, number>();\n const N = this.documents.length;\n const { k1, b } = this.config.bm25;\n\n for (const term of queryTerms) {\n const postings = index.get(term);\n if (!postings) continue;\n\n const df = postings.length; // document frequency\n // IDF: log((N - df + 0.5) / (df + 0.5) + 1)\n const idf = Math.log((N - df + 0.5) / (df + 0.5) + 1);\n\n for (const { docIndex, termFrequency } of postings) {\n const doc = this.documents[docIndex]!;\n const tf = termFrequency;\n const docLen = doc.length;\n\n // BM25 term score\n const numerator = tf * (k1 + 1);\n const denominator = tf + k1 * (1 - b + b * (docLen / this.avgDocLength));\n const termScore = idf * (numerator / denominator);\n\n scores.set(docIndex, (scores.get(docIndex) ?? 0) + termScore);\n }\n }\n\n // Boost exact name matches (FR-1.9: 3-5x higher)\n const queryJoined = queryTerms.join('');\n for (const [docIdx, score] of scores) {\n const doc = this.documents[docIdx]!;\n const nameLower = doc.name.toLowerCase();\n if (nameLower === queryJoined || nameLower === queryTerms.join(' ')) {\n scores.set(docIdx, score * 5.0);\n }\n }\n\n return scores;\n }\n\n /**\n * Merge two score maps. Phase 2 scores are penalized.\n */\n private mergeScores(\n primary: Map<number, number>,\n secondary: Map<number, number>,\n penalty: number,\n ): Map<number, number> {\n const merged = new Map(primary);\n for (const [docIdx, score] of secondary) {\n const existing = merged.get(docIdx);\n const penalized = score * penalty;\n if (existing !== undefined) {\n merged.set(docIdx, Math.max(existing, penalized));\n } else {\n merged.set(docIdx, penalized);\n }\n }\n return merged;\n }\n\n /**\n * Bigram boost for multi-word queries.\n * Each adjacent query term pair found adjacent in symbol tokens → 2x boost.\n */\n private bigramBoost(queryTerms: string[], symbolTokens: string[]): number {\n if (queryTerms.length < 2) return 1.0;\n\n let adjacentPairs = 0;\n for (let i = 0; i < queryTerms.length - 1; i++) {\n const idxA = symbolTokens.findIndex((t) => t.includes(queryTerms[i]!));\n const idxB = symbolTokens.findIndex((t) => t.includes(queryTerms[i + 1]!));\n if (idxA >= 0 && idxB >= 0 && Math.abs(idxA - idxB) === 1) {\n adjacentPairs++;\n }\n }\n\n return 1 + adjacentPairs * 2.0;\n }\n\n /**\n * Extract character trigrams from a string.\n * \"sqlite\" → [\"sql\", \"qli\", \"lit\", \"ite\"]\n */\n private extractTrigrams(text: string): string[] {\n const trigrams: string[] = [];\n for (let i = 0; i <= text.length - 3; i++) {\n trigrams.push(text.substring(i, i + 3));\n }\n return trigrams;\n }\n\n private buildResults(\n combinedScores: Map<number, number>,\n rawRelevance: Map<number, number>,\n limit: number,\n ): SearchResult[] {\n const entries = [...combinedScores.entries()]\n .sort((a, b) => b[1] - a[1])\n .slice(0, limit);\n\n return entries.map(([docIdx, combined]) => {\n const doc = this.documents[docIdx]!;\n const pr = this.pageRankScores.get(doc.symbolId) ?? 0;\n return {\n symbolId: doc.symbolId,\n name: doc.name,\n kind: doc.kind,\n filePath: doc.filePath,\n relevanceScore: rawRelevance.get(docIdx) ?? 0,\n importanceScore: pr,\n combinedScore: combined,\n };\n });\n }\n\n private emptyResponse(query: string, start: number): SearchResponse {\n return {\n query,\n results: [],\n metrics: {\n porterHits: 0,\n trigramHits: 0,\n phase2Activated: false,\n fuzzyApplied: false,\n latencyMs: performance.now() - start,\n },\n };\n }\n}\n","import { z } from 'zod';\nimport type { IStoragePort } from '../../ports/i-storage-port.js';\nimport type { IMaskingPort } from '../../ports/i-masking-port.js';\nimport type { StalenessCheck } from './get-logic-slice.js';\nimport { getGraphAndFiles } from './get-logic-slice.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\nimport { SearchEngine } from '../../core/search/search-engine.js';\nimport { SymbolKindSchema } from '../../core/types.js';\nimport type { ISearchPort } from '../../ports/i-search-port.js';\nimport type { ResponseEnricher } from '../../ports/i-ctxo-module.js';\nimport { applyEnricher } from './enrich-payload.js';\n\nexport const InputSchema = z.object({\n pattern: z.string().min(1),\n kind: SymbolKindSchema.optional(),\n filePattern: z.string().optional(),\n limit: z.number().int().min(1).max(100).optional().default(25),\n mode: z.enum(['regex', 'fts']).optional().default('regex'),\n});\n\nexport function handleSearchSymbols(\n storage: IStoragePort,\n masking: IMaskingPort,\n staleness?: StalenessCheck,\n ctxoRoot = '.ctxo',\n searchEngine?: ISearchPort,\n enrich?: ResponseEnricher,\n) {\n const engine: ISearchPort = searchEngine ?? new SearchEngine();\n let lastFtsNodeCount = -1;\n\n const getGraph = () => getGraphAndFiles(ctxoRoot, storage);\n\n return (args: Record<string, unknown>) => {\n try {\n const parsed = InputSchema.safeParse(args);\n if (!parsed.success) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: parsed.error.message }) }],\n };\n }\n\n const { pattern, kind, filePattern, limit, mode } = parsed.data;\n const { graph, indexedFiles } = getGraph();\n const allNodes = graph.allNodes();\n\n // FTS mode: use search engine\n if (mode === 'fts') {\n if (allNodes.length !== lastFtsNodeCount) {\n engine.buildIndex(allNodes);\n lastFtsNodeCount = allNodes.length;\n }\n\n const searchResult = engine.search(pattern, limit);\n let ftsResults = searchResult.results;\n\n // Apply kind filter\n if (kind) {\n ftsResults = ftsResults.filter((r) => r.kind === kind);\n }\n // Apply file pattern filter\n if (filePattern) {\n const fp = filePattern.toLowerCase();\n ftsResults = ftsResults.filter((r) => r.filePath.toLowerCase().includes(fp));\n }\n\n const results = ftsResults.slice(0, limit).map((r) => {\n const node = graph.getNode(r.symbolId);\n return {\n symbolId: r.symbolId,\n name: r.name,\n kind: r.kind,\n file: r.filePath,\n startLine: node?.startLine ?? 0,\n endLine: node?.endLine ?? 0,\n relevanceScore: Math.round(r.relevanceScore * 1000) / 1000,\n };\n });\n\n const body = applyEnricher(enrich, {\n totalMatches: ftsResults.length,\n results,\n searchMetrics: searchResult.metrics,\n ...(searchResult.fuzzyCorrection ? { fuzzyCorrection: searchResult.fuzzyCorrection } : {}),\n }, parsed.data, 'search_symbols');\n const payload = masking.mask(JSON.stringify(wrapResponse(body)));\n\n const content: Array<{ type: 'text'; text: string }> = [];\n if (staleness) {\n const warning = staleness.check(indexedFiles);\n if (warning) content.push({ type: 'text', text: `⚠️ ${warning.message}` });\n }\n content.push({ type: 'text', text: payload });\n\n return { content };\n }\n\n // Legacy regex mode (default)\n let matcher: (name: string) => boolean;\n try {\n const regex = new RegExp(pattern, 'i');\n matcher = (name: string) => regex.test(name);\n } catch {\n const lowerPattern = pattern.toLowerCase();\n matcher = (name: string) => name.toLowerCase().includes(lowerPattern);\n }\n\n const matches = allNodes.filter((node) => {\n if (!matcher(node.name)) return false;\n if (kind && node.kind !== kind) return false;\n if (filePattern) {\n const file = node.symbolId.split('::')[0] ?? '';\n if (!file.toLowerCase().includes(filePattern.toLowerCase())) return false;\n }\n return true;\n });\n\n const results = matches.slice(0, limit).map((node) => ({\n symbolId: node.symbolId,\n name: node.name,\n kind: node.kind,\n file: node.symbolId.split('::')[0],\n startLine: node.startLine,\n endLine: node.endLine,\n }));\n\n const body = applyEnricher(enrich, { totalMatches: matches.length, results }, parsed.data, 'search_symbols');\n const payload = masking.mask(JSON.stringify(wrapResponse(body)));\n\n const content: Array<{ type: 'text'; text: string }> = [];\n if (staleness) {\n const warning = staleness.check(indexedFiles);\n if (warning) content.push({ type: 'text', text: `⚠️ ${warning.message}` });\n }\n content.push({ type: 'text', text: payload });\n\n return { content };\n } catch (err) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: (err as Error).message }) }],\n };\n }\n };\n}\n","import { z } from 'zod';\nimport type { IStoragePort } from '../../ports/i-storage-port.js';\nimport type { IGitPort } from '../../ports/i-git-port.js';\nimport type { IMaskingPort } from '../../ports/i-masking-port.js';\nimport type { StalenessCheck } from './get-logic-slice.js';\nimport { getGraphAndFiles } from './get-logic-slice.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\n\nexport const InputSchema = z.object({\n since: z.string().optional().default('HEAD~1'),\n maxFiles: z.number().int().min(1).optional().default(50),\n});\n\nexport function handleGetChangedSymbols(\n storage: IStoragePort,\n git: IGitPort,\n masking: IMaskingPort,\n staleness?: StalenessCheck,\n ctxoRoot = '.ctxo',\n) {\n const getGraph = () => getGraphAndFiles(ctxoRoot, storage);\n\n return async (args: Record<string, unknown>) => {\n try {\n const parsed = InputSchema.safeParse(args);\n if (!parsed.success) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: parsed.error.message }) }],\n };\n }\n\n const { since, maxFiles } = parsed.data;\n const changedPaths = await git.getChangedFiles(since);\n const { graph, indexedFiles } = getGraph();\n\n // Index all nodes by file for fast lookup\n const nodesByFile = new Map<string, Array<{ symbolId: string; name: string; kind: string; startLine: number; endLine: number }>>();\n for (const node of graph.allNodes()) {\n const file = node.symbolId.split('::')[0] ?? '';\n const existing = nodesByFile.get(file) ?? [];\n existing.push({ symbolId: node.symbolId, name: node.name, kind: node.kind, startLine: node.startLine, endLine: node.endLine });\n nodesByFile.set(file, existing);\n }\n\n const files: Array<{ file: string; symbols: Array<{ symbolId: string; name: string; kind: string; startLine: number; endLine: number }> }> = [];\n let totalSymbols = 0;\n\n for (const filePath of changedPaths.slice(0, maxFiles)) {\n const symbols = nodesByFile.get(filePath);\n if (symbols && symbols.length > 0) {\n files.push({ file: filePath, symbols });\n totalSymbols += symbols.length;\n }\n }\n\n const payload = masking.mask(JSON.stringify(wrapResponse({\n since,\n changedFiles: files.length,\n changedSymbols: totalSymbols,\n files,\n })));\n\n const content: Array<{ type: 'text'; text: string }> = [];\n if (staleness) {\n const warning = staleness.check(indexedFiles);\n if (warning) content.push({ type: 'text', text: `⚠️ ${warning.message}` });\n }\n content.push({ type: 'text', text: payload });\n\n return { content };\n } catch (err) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: (err as Error).message }) }],\n };\n }\n };\n}\n","import { z } from 'zod';\nimport type { IStoragePort } from '../../ports/i-storage-port.js';\nimport type { IMaskingPort } from '../../ports/i-masking-port.js';\nimport type { StalenessCheck } from './get-logic-slice.js';\nimport { getGraphAndFiles } from './get-logic-slice.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\nimport { filterByIntent } from '../../core/intent-filter.js';\nimport { EdgeKindSchema, type EdgeKind } from '../../core/types.js';\nimport type { ResponseEnricher } from '../../ports/i-ctxo-module.js';\nimport { applyEnricher } from './enrich-payload.js';\n\nexport const InputSchema = z.object({\n symbolId: z.string().min(1),\n edgeKinds: z.array(EdgeKindSchema).optional(),\n transitive: z.boolean().optional().default(false),\n maxDepth: z.number().int().min(1).max(10).optional().default(5),\n intent: z.string().optional().describe('Filter results by intent keywords (e.g., \"test\", \"adapter\", \"core\")'),\n});\n\nexport function handleFindImporters(\n storage: IStoragePort,\n masking: IMaskingPort,\n staleness?: StalenessCheck,\n ctxoRoot = '.ctxo',\n enrich?: ResponseEnricher,\n) {\n const getGraph = () => getGraphAndFiles(ctxoRoot, storage);\n\n return (args: Record<string, unknown>) => {\n try {\n const parsed = InputSchema.safeParse(args);\n if (!parsed.success) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: parsed.error.message }) }],\n };\n }\n\n const { symbolId, edgeKinds, transitive, maxDepth } = parsed.data;\n const { graph, indexedFiles } = getGraph();\n\n // Resolve the id once: a 2-part data id names its winning definition. getDependentEdges gives every\n // copy of a table, view or procedure the importers of the resource.\n const root = graph.getNode(symbolId);\n if (!root) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ found: false, hint: 'Symbol not found. Run \"ctxo index\" to build the codebase index.' }) }],\n };\n }\n const rootId = root.symbolId;\n\n const importers: Array<{\n symbolId: string;\n name: string;\n kind: string;\n file: string;\n edgeKind: string;\n edgeKinds?: string[];\n depth: number;\n }> = [];\n\n if (!transitive) {\n // Direct importers only — deduplicate by symbolId, aggregate edgeKinds\n const reverseEdges = graph.getDependentEdges(rootId);\n const seen = new Map<string, typeof importers[0]>();\n for (const edge of reverseEdges) {\n if (edgeKinds && !edgeKinds.includes(edge.kind as EdgeKind)) continue;\n const node = graph.getNode(edge.from);\n if (node) {\n const existing = seen.get(node.symbolId);\n if (existing) {\n if (!existing.edgeKinds!.includes(edge.kind)) {\n existing.edgeKinds!.push(edge.kind);\n }\n } else {\n const entry = {\n symbolId: node.symbolId,\n name: node.name,\n kind: node.kind,\n file: node.symbolId.split('::')[0] ?? '',\n edgeKind: edge.kind,\n edgeKinds: [edge.kind],\n depth: 1,\n };\n seen.set(node.symbolId, entry);\n importers.push(entry);\n }\n }\n }\n } else {\n // BFS for transitive importers. No definition of the same resource counts as an importer of another.\n const definitions = graph.dataResourceIdentity(rootId)?.definitions.map((definition) => definition.symbolId) ?? [];\n const visited = new Set<string>([rootId, ...definitions]);\n const queue: Array<{ id: string; depth: number }> = [{ id: rootId, depth: 0 }];\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n if (current.depth >= maxDepth) continue;\n\n const reverseEdges = graph.getDependentEdges(current.id);\n for (const edge of reverseEdges) {\n if (edgeKinds && !edgeKinds.includes(edge.kind as EdgeKind)) continue;\n if (visited.has(edge.from)) continue;\n visited.add(edge.from);\n\n const node = graph.getNode(edge.from);\n if (node) {\n const depth = current.depth + 1;\n importers.push({\n symbolId: node.symbolId,\n name: node.name,\n kind: node.kind,\n file: node.symbolId.split('::')[0] ?? '',\n edgeKind: edge.kind,\n depth,\n });\n queue.push({ id: edge.from, depth });\n }\n }\n }\n }\n\n // Sort by depth ascending\n importers.sort((a, b) => a.depth - b.depth);\n\n // Apply intent filter if requested\n const filtered = filterByIntent(importers, parsed.data.intent);\n\n const body = applyEnricher(enrich, {\n symbolId,\n importerCount: filtered.length,\n importers: filtered,\n }, parsed.data, 'find_importers');\n const payload = masking.mask(JSON.stringify(wrapResponse(body)));\n\n const content: Array<{ type: 'text'; text: string }> = [];\n if (staleness) {\n const warning = staleness.check(indexedFiles);\n if (warning) content.push({ type: 'text', text: `⚠️ ${warning.message}` });\n }\n content.push({ type: 'text', text: payload });\n\n return { content };\n } catch (err) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: (err as Error).message }) }],\n };\n }\n };\n}\n","import { z } from 'zod';\nimport type { IStoragePort } from '../../ports/i-storage-port.js';\nimport type { IMaskingPort } from '../../ports/i-masking-port.js';\nimport type { StalenessCheck } from './get-logic-slice.js';\nimport { getGraphAndFiles } from './get-logic-slice.js';\nimport type { SymbolGraph } from '../../core/graph/symbol-graph.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\nimport type { EdgeKind } from '../../core/types.js';\n\n/** The edge kinds that make up a class hierarchy. Data access edges (reads, writes, executes) never do. */\nexport const HIERARCHY_EDGE_KINDS: ReadonlySet<EdgeKind> = new Set<EdgeKind>(['extends', 'implements']);\n\nexport const InputSchema = z.object({\n symbolId: z.string().min(1).optional(),\n direction: z.enum(['ancestors', 'descendants', 'both']).optional().default('both'),\n});\n\nexport function handleGetClassHierarchy(\n storage: IStoragePort,\n masking: IMaskingPort,\n staleness?: StalenessCheck,\n ctxoRoot = '.ctxo',\n) {\n const getGraph = () => getGraphAndFiles(ctxoRoot, storage);\n\n return (args: Record<string, unknown>) => {\n try {\n const parsed = InputSchema.safeParse(args);\n if (!parsed.success) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: parsed.error.message }) }],\n };\n }\n\n const { symbolId, direction } = parsed.data;\n const { graph, indexedFiles } = getGraph();\n\n if (symbolId) {\n return handleRooted(graph, symbolId, direction, masking, staleness, indexedFiles);\n }\n\n return handleFull(graph, masking, staleness, indexedFiles);\n } catch (err) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: (err as Error).message }) }],\n };\n }\n };\n\n function handleRooted(\n graph: SymbolGraph,\n symbolId: string,\n direction: 'ancestors' | 'descendants' | 'both',\n maskingPort: IMaskingPort,\n stalenessCheck: StalenessCheck | undefined,\n indexedFiles: string[],\n ) {\n if (!graph.hasNode(symbolId)) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ found: false, hint: 'Symbol not found. Run \"ctxo index\" to build the codebase index.' }) }],\n };\n }\n\n type HierarchyEntry = { symbolId: string; name: string; kind: string; file: string; edgeKind: string; depth: number };\n const ancestors: HierarchyEntry[] = [];\n const descendants: HierarchyEntry[] = [];\n\n const isHierarchyEdge = (kind: string) => HIERARCHY_EDGE_KINDS.has(kind as EdgeKind);\n\n // Ancestors: follow forward edges (this symbol extends/implements X)\n if (direction === 'ancestors' || direction === 'both') {\n const visited = new Set<string>([symbolId]);\n const queue: Array<{ id: string; depth: number }> = [{ id: symbolId, depth: 0 }];\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n for (const edge of graph.getForwardEdges(current.id)) {\n if (!isHierarchyEdge(edge.kind)) continue;\n if (visited.has(edge.to)) continue;\n visited.add(edge.to);\n\n const node = graph.getNode(edge.to);\n if (node) {\n const depth = current.depth + 1;\n ancestors.push({\n symbolId: node.symbolId,\n name: node.name,\n kind: node.kind,\n file: node.symbolId.split('::')[0] ?? '',\n edgeKind: edge.kind,\n depth,\n });\n queue.push({ id: edge.to, depth });\n }\n }\n }\n }\n\n // Descendants: follow reverse edges (X extends/implements this symbol)\n if (direction === 'descendants' || direction === 'both') {\n const visited = new Set<string>([symbolId]);\n const queue: Array<{ id: string; depth: number }> = [{ id: symbolId, depth: 0 }];\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n for (const edge of graph.getReverseEdges(current.id)) {\n if (!isHierarchyEdge(edge.kind)) continue;\n if (visited.has(edge.from)) continue;\n visited.add(edge.from);\n\n const node = graph.getNode(edge.from);\n if (node) {\n const depth = current.depth + 1;\n descendants.push({\n symbolId: node.symbolId,\n name: node.name,\n kind: node.kind,\n file: node.symbolId.split('::')[0] ?? '',\n edgeKind: edge.kind,\n depth,\n });\n queue.push({ id: edge.from, depth });\n }\n }\n }\n }\n\n const result: Record<string, unknown> = { symbolId };\n if (direction === 'ancestors' || direction === 'both') result.ancestors = ancestors;\n if (direction === 'descendants' || direction === 'both') result.descendants = descendants;\n\n const payload = maskingPort.mask(JSON.stringify(wrapResponse(result)));\n const content: Array<{ type: 'text'; text: string }> = [];\n if (stalenessCheck) {\n const warning = stalenessCheck.check(indexedFiles);\n if (warning) content.push({ type: 'text', text: `⚠️ ${warning.message}` });\n }\n content.push({ type: 'text', text: payload });\n\n return { content };\n }\n\n function handleFull(\n graph: SymbolGraph,\n maskingPort: IMaskingPort,\n stalenessCheck: StalenessCheck | undefined,\n indexedFiles: string[],\n ) {\n const isHierarchyEdge = (kind: string) => HIERARCHY_EDGE_KINDS.has(kind as EdgeKind);\n const hierarchyEdges = graph.allEdges().filter((e) => isHierarchyEdge(e.kind));\n\n // Collect all nodes involved in hierarchy edges\n const involved = new Set<string>();\n for (const edge of hierarchyEdges) {\n involved.add(edge.from);\n involved.add(edge.to);\n }\n\n // Find roots: nodes that are targets but never sources of extends/implements (true base classes/interfaces)\n const sources = new Set(hierarchyEdges.map((e) => e.from));\n const roots = [...involved].filter((id) => !sources.has(id));\n\n // If no clear roots, use all involved nodes as potential roots (handles cycles)\n const rootSet = roots.length > 0 ? roots : [...involved];\n\n type TreeNode = { symbolId: string; name: string; kind: string; file: string; edgeKind?: string; children: TreeNode[] };\n\n function buildTree(rootId: string, visited: Set<string>): TreeNode | undefined {\n const node = graph.getNode(rootId);\n if (!node) return undefined;\n visited.add(rootId);\n\n const children: TreeNode[] = [];\n for (const edge of graph.getReverseEdges(rootId)) {\n if (!isHierarchyEdge(edge.kind)) continue;\n if (visited.has(edge.from)) continue;\n const child = buildTree(edge.from, visited);\n if (child) {\n child.edgeKind = edge.kind;\n children.push(child);\n }\n }\n\n return {\n symbolId: node.symbolId,\n name: node.name,\n kind: node.kind,\n file: node.symbolId.split('::')[0] ?? '',\n children,\n };\n }\n\n const visited = new Set<string>();\n const hierarchies: TreeNode[] = [];\n for (const rootId of rootSet) {\n if (visited.has(rootId)) continue;\n const tree = buildTree(rootId, visited);\n if (tree) hierarchies.push(tree);\n }\n\n const payload = maskingPort.mask(JSON.stringify(wrapResponse({\n hierarchies,\n totalClasses: involved.size,\n totalEdges: hierarchyEdges.length,\n })));\n\n const content: Array<{ type: 'text'; text: string }> = [];\n if (stalenessCheck) {\n const warning = stalenessCheck.check(indexedFiles);\n if (warning) content.push({ type: 'text', text: `⚠️ ${warning.message}` });\n }\n content.push({ type: 'text', text: payload });\n\n return { content };\n }\n}\n","import { z } from 'zod';\nimport type { IStoragePort } from '../../ports/i-storage-port.js';\nimport type { IMaskingPort } from '../../ports/i-masking-port.js';\nimport { PageRankCalculator } from '../../core/importance/pagerank-calculator.js';\nimport type { StalenessCheck } from './get-logic-slice.js';\nimport { getGraphAndFiles } from './get-logic-slice.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\nimport { SymbolKindSchema } from '../../core/types.js';\n\nexport const InputSchema = z.object({\n limit: z.number().int().min(1).max(200).optional().default(25),\n kind: SymbolKindSchema.optional(),\n filePattern: z.string().optional(),\n damping: z.number().min(0).max(1).optional().default(0.85),\n});\n\nexport function handleGetSymbolImportance(\n storage: IStoragePort,\n masking: IMaskingPort,\n staleness?: StalenessCheck,\n ctxoRoot = '.ctxo',\n) {\n const calculator = new PageRankCalculator();\n const getGraph = () => getGraphAndFiles(ctxoRoot, storage);\n\n return (args: Record<string, unknown>) => {\n try {\n const parsed = InputSchema.safeParse(args);\n if (!parsed.success) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: parsed.error.message }) }],\n };\n }\n\n const { limit, kind, filePattern, damping } = parsed.data;\n const { graph, indexedFiles } = getGraph();\n\n const result = calculator.calculate(graph, { damping, limit: graph.nodeCount, maxIterations: 100 });\n\n // Filter after full PageRank computation (filtering before would distort scores)\n let filtered = result.rankings;\n if (kind) {\n filtered = filtered.filter((e) => e.kind === kind);\n }\n if (filePattern) {\n const lowerPattern = filePattern.toLowerCase();\n filtered = filtered.filter((e) => e.file.toLowerCase().includes(lowerPattern));\n }\n filtered = filtered.slice(0, limit);\n\n const payload = masking.mask(JSON.stringify(wrapResponse({\n rankings: filtered,\n totalSymbols: result.totalSymbols,\n iterations: result.iterations,\n converged: result.converged,\n damping,\n })));\n\n const content: Array<{ type: 'text'; text: string }> = [];\n if (staleness) {\n const warning = staleness.check(indexedFiles);\n if (warning) content.push({ type: 'text', text: `⚠️ ${warning.message}` });\n }\n content.push({ type: 'text', text: payload });\n\n return { content };\n } catch (err) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: (err as Error).message }) }],\n };\n }\n };\n}\n","import { z } from 'zod';\nimport type { IStoragePort } from '../../ports/i-storage-port.js';\nimport type { IGitPort } from '../../ports/i-git-port.js';\nimport type { IMaskingPort } from '../../ports/i-masking-port.js';\nimport type { ICoChangePort } from '../../ports/i-co-change-port.js';\nimport type { StalenessCheck } from './get-logic-slice.js';\nimport { getGraphAndFiles } from './get-logic-slice.js';\nimport { BlastRadiusCalculator } from '../../core/blast-radius/blast-radius-calculator.js';\nimport { BoundaryViolationDetector } from '../../core/overlay/boundary-violation-detector.js';\nimport { buildSnapshotStaleness } from '../../core/overlay/snapshot-staleness.js';\nimport type { ClusterLabelMasker } from '../../core/overlay/cluster-label-masker.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\nimport type { CommunitySnapshot } from '../../core/types.js';\nimport type { ResponseEnricher } from '../../ports/i-ctxo-module.js';\nimport { applyEnricher } from './enrich-payload.js';\n\nexport const InputSchema = z.object({\n since: z.string().optional().default('HEAD~1'),\n maxFiles: z.number().int().min(1).optional().default(50),\n confidence: z.enum(['confirmed', 'likely', 'potential']).optional(),\n});\n\nfunction computeClustersAffected(\n snapshot: CommunitySnapshot,\n changedSymbolIds: ReadonlySet<string>,\n): Array<{ id: number; label: string; symbolCount: number }> {\n const totals = new Map<number, { label: string; count: number }>();\n for (const entry of snapshot.communities) {\n if (!changedSymbolIds.has(entry.symbolId)) continue;\n const existing = totals.get(entry.communityId);\n if (existing) {\n existing.count += 1;\n } else {\n totals.set(entry.communityId, { label: entry.communityLabel, count: 1 });\n }\n }\n return [...totals.entries()]\n .map(([id, { label, count }]) => ({ id, label, symbolCount: count }))\n .sort((a, b) => b.symbolCount - a.symbolCount || a.id - b.id);\n}\n\nexport function handleGetPrImpact(\n storage: IStoragePort,\n git: IGitPort,\n masking: IMaskingPort,\n staleness?: StalenessCheck,\n ctxoRoot = '.ctxo',\n clusterLabelMasker?: ClusterLabelMasker,\n coChange?: ICoChangePort,\n enrich?: ResponseEnricher,\n) {\n const calculator = new BlastRadiusCalculator();\n const getGraph = () => getGraphAndFiles(ctxoRoot, storage);\n\n return async (args: Record<string, unknown>) => {\n try {\n const parsed = InputSchema.safeParse(args);\n if (!parsed.success) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: parsed.error.message }) }],\n };\n }\n\n const { since, maxFiles, confidence: confFilter } = parsed.data;\n\n // Step 1: Get changed files\n const changedPaths = await git.getChangedFiles(since);\n if (changedPaths.length === 0) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ since, changedFiles: 0, changedSymbols: 0, totalImpact: 0, riskLevel: 'low', files: [], summary: { confirmedTotal: 0, likelyTotal: 0, potentialTotal: 0, highRiskSymbols: [] } }) }],\n };\n }\n\n // Step 2: Build graph + load co-changes\n const { graph, indexedFiles } = getGraph();\n const coChangeMap = coChange?.readCoChangeMap();\n\n // Step 3: Map files → symbols\n const allNodes = graph.allNodes();\n const nodesByFile = new Map<string, typeof allNodes>();\n for (const node of allNodes) {\n const file = node.symbolId.split('::')[0]!;\n let list = nodesByFile.get(file);\n if (!list) { list = []; nodesByFile.set(file, list); }\n list.push(node);\n }\n\n // Step 4: For each changed file, compute blast radius per symbol\n const limitedPaths = changedPaths.slice(0, maxFiles);\n let totalImpact = 0;\n let confirmedTotal = 0;\n let likelyTotal = 0;\n let potentialTotal = 0;\n const highRiskSymbols: string[] = [];\n\n const files: Array<{\n file: string;\n symbols: Array<{\n symbolId: string;\n name: string;\n kind: string;\n blast: {\n impactScore: number;\n confirmedCount: number;\n likelyCount: number;\n potentialCount: number;\n riskScore: number;\n topImpacted: Array<unknown>;\n };\n }>;\n coChangedWith?: string[];\n }> = [];\n\n for (const filePath of limitedPaths) {\n const symbols = nodesByFile.get(filePath);\n if (!symbols || symbols.length === 0) continue;\n\n const fileSymbols: typeof files[0]['symbols'] = [];\n\n for (const sym of symbols) {\n const result = calculator.calculate(graph, sym.symbolId, coChangeMap);\n\n let impacted = result.impactedSymbols;\n if (confFilter) {\n impacted = impacted.filter(s => s.confidence === confFilter);\n }\n\n const impactScore = impacted.length;\n const confirmed = impacted.filter(s => s.confidence === 'confirmed').length;\n const likely = impacted.filter(s => s.confidence === 'likely').length;\n const potential = impacted.filter(s => s.confidence === 'potential').length;\n\n totalImpact += impactScore;\n confirmedTotal += confirmed;\n likelyTotal += likely;\n potentialTotal += potential;\n\n if (result.overallRiskScore > 0.7) {\n highRiskSymbols.push(sym.symbolId);\n }\n\n const topImpacted = impacted\n .sort((a, b) => b.riskScore - a.riskScore)\n .slice(0, 10);\n\n fileSymbols.push({\n symbolId: sym.symbolId,\n name: sym.name,\n kind: sym.kind,\n blast: {\n impactScore,\n confirmedCount: confirmed,\n likelyCount: likely,\n potentialCount: potential,\n riskScore: result.overallRiskScore,\n topImpacted,\n },\n });\n }\n\n // Co-changed files for this file\n let coChangedWith: string[] | undefined;\n if (coChangeMap) {\n const entries = coChangeMap.get(filePath);\n if (entries && entries.length > 0) {\n // The map is the port's cached copy, shared with every other call: sort a copy of the list.\n coChangedWith = [...entries]\n .sort((a, b) => b.frequency - a.frequency)\n .slice(0, 5)\n .map(e => e.file1 === filePath ? e.file2 : e.file1);\n }\n }\n\n files.push({\n file: filePath,\n symbols: fileSymbols,\n ...(coChangedWith ? { coChangedWith } : {}),\n });\n }\n\n // Step 5: Compute risk level\n const maxRisk = files.reduce((max, f) => {\n const fileMax = f.symbols.reduce((m, s) => Math.max(m, s.blast.riskScore), 0);\n return Math.max(max, fileMax);\n }, 0);\n const riskLevel = maxRisk > 0.7 ? 'high' : maxRisk > 0.3 ? 'medium' : 'low';\n\n const changedSymbols = files.reduce((sum, f) => sum + f.symbols.length, 0);\n\n const rawSnapshot = storage.readCommunities();\n const snapshot =\n rawSnapshot && clusterLabelMasker?.isEnabled()\n ? clusterLabelMasker.maskSnapshot(rawSnapshot)\n : rawSnapshot;\n const history = snapshot ? storage.listCommunityHistory() : [];\n let boundarySection: Record<string, unknown> | undefined;\n let clustersAffected: Array<{ id: number; label: string; symbolCount: number }> | undefined;\n\n if (snapshot) {\n const detector = new BoundaryViolationDetector();\n const violationResult = detector.detect(graph, snapshot, history);\n const changedSymbolIds = new Set<string>();\n for (const file of files) {\n for (const sym of file.symbols) changedSymbolIds.add(sym.symbolId);\n }\n const relevant = violationResult.violations.filter(\n (v) => changedSymbolIds.has(v.from.symbolId) || changedSymbolIds.has(v.to.symbolId),\n );\n boundarySection = {\n violations: relevant,\n confidence: violationResult.confidence,\n snapshotsAvailable: violationResult.snapshotsAvailable,\n distinctCommits: violationResult.distinctCommits,\n ...(violationResult.hint ? { hint: violationResult.hint } : {}),\n };\n clustersAffected = computeClustersAffected(snapshot, changedSymbolIds);\n }\n\n const body: Record<string, unknown> = {\n since,\n changedFiles: files.length,\n changedSymbols,\n totalImpact,\n riskLevel,\n files,\n summary: {\n confirmedTotal,\n likelyTotal,\n potentialTotal,\n highRiskSymbols: highRiskSymbols.slice(0, 10),\n },\n };\n if (boundarySection) body.boundaryViolations = boundarySection;\n if (clustersAffected && clustersAffected.length > 0) body.clustersAffected = clustersAffected;\n\n const stalenessMeta = await buildSnapshotStaleness(storage, git);\n const extras = stalenessMeta ? { snapshotStaleness: stalenessMeta } : undefined;\n const enriched = applyEnricher(enrich, body, parsed.data, 'get_pr_impact');\n const payload = masking.mask(JSON.stringify(wrapResponse(enriched, extras)));\n\n const content: Array<{ type: 'text'; text: string }> = [];\n if (staleness) {\n const warning = staleness.check(indexedFiles);\n if (warning) content.push({ type: 'text', text: `⚠️ ${warning.message}` });\n }\n content.push({ type: 'text', text: payload });\n\n return { content };\n } catch (err) {\n return {\n content: [{ type: 'text' as const, text: JSON.stringify({ error: true, message: (err as Error).message }) }],\n };\n }\n };\n}\n","import type { ISessionRecorderPort, SessionEvent } from '../../ports/i-session-recorder-port.js';\n\ntype McpToolResult = { content: Array<{ type: 'text'; text: string }> };\ntype McpHandler = (args: Record<string, unknown>) => McpToolResult | Promise<McpToolResult>;\n\n/**\n * Wraps an MCP handler with session recording.\n * Recording is fire-and-forget — errors are swallowed, never affect tool response.\n *\n * @param toolName - MCP tool name (e.g., 'get_logic_slice')\n * @param handler - Original handler function (sync or async)\n * @param recorder - Session recorder (null = recording disabled, zero overhead)\n */\nexport function withRecording(\n toolName: string,\n handler: McpHandler,\n recorder: ISessionRecorderPort | null,\n): McpHandler {\n if (!recorder) return handler;\n\n return (args: Record<string, unknown>) => {\n const start = performance.now();\n const resultOrPromise = handler(args);\n\n // Handle async handlers\n if (resultOrPromise instanceof Promise) {\n return resultOrPromise.then((result) => {\n recordEvent(toolName, args, result, performance.now() - start, recorder);\n return result;\n });\n }\n\n // Sync handler\n const latencyMs = performance.now() - start;\n recordEvent(toolName, args, resultOrPromise, latencyMs, recorder);\n return resultOrPromise;\n };\n}\n\nfunction recordEvent(\n toolName: string,\n args: Record<string, unknown>,\n result: McpToolResult,\n latencyMs: number,\n recorder: ISessionRecorderPort,\n): void {\n try {\n const responseText = result.content\n .filter((c) => c.type === 'text')\n .map((c) => c.text)\n .join('');\n\n let truncated = false;\n try {\n const parsed = JSON.parse(responseText);\n truncated = parsed?._meta?.truncated ?? false;\n } catch { /* non-JSON response, ignore */ }\n\n const responseBytes = Buffer.byteLength(responseText, 'utf-8');\n\n // Extract detail level: args.level (number) → 'L1'...'L4'\n const rawLevel = args['level'];\n let detailLevel: SessionEvent['detailLevel'] = null;\n if (typeof rawLevel === 'number' && rawLevel >= 1 && rawLevel <= 4) {\n detailLevel = `L${rawLevel}` as SessionEvent['detailLevel'];\n }\n\n const event: SessionEvent = {\n tool: toolName,\n symbolId: (typeof args['symbolId'] === 'string' ? args['symbolId'] : null),\n detailLevel,\n responseTokens: Math.ceil(responseBytes / 4),\n responseBytes,\n latencyMs,\n truncated,\n };\n\n recorder.record(event);\n } catch {\n // Recording failure must never affect tool response\n }\n}\n","import type { z, ZodRawShape } from 'zod';\nimport type { IMaskingPort } from '../../ports/i-masking-port.js';\nimport type { CoreToolName, LoadedModule, ModuleToolDefinition } from '../../ports/i-ctxo-module.js';\nimport type { StalenessCheck } from './get-logic-slice.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\nimport { createLogger } from '../../core/logger.js';\nimport { describeError } from '../../core/describe-error.js';\n\nconst log = createLogger('ctxo:modules');\n\n/** What an MCP tool handler resolves to: text content only. */\nexport type McpToolResult = { content: Array<{ type: 'text'; text: string }> };\n\n/** Every core tool name, once; the `satisfies` makes the compiler reject a missing or unknown name. */\nconst CORE_TOOLS = {\n get_logic_slice: true,\n get_why_context: true,\n get_change_intelligence: true,\n get_blast_radius: true,\n get_architectural_overlay: true,\n find_dead_code: true,\n get_context_for_task: true,\n get_ranked_context: true,\n search_symbols: true,\n get_changed_symbols: true,\n find_importers: true,\n get_class_hierarchy: true,\n get_symbol_importance: true,\n get_pr_impact: true,\n} as const satisfies Record<CoreToolName, true>;\n\n/** The 14 tools the MCP server registers itself. A module tool may not take one of these names. */\nexport const CORE_TOOL_NAMES: ReadonlySet<CoreToolName> = new Set(Object.keys(CORE_TOOLS) as CoreToolName[]);\n\n/**\n * The tools the loaded modules register, in load order. A tool named like a core tool, or like a tool an\n * earlier module registered, is skipped with a warning, and so is a tool without a name or a handler. A\n * module whose `registerTools` throws contributes nothing and the others still count.\n */\nexport function collectModuleTools(\n modules: readonly LoadedModule[],\n reserved: ReadonlySet<string>,\n): ModuleToolDefinition[] {\n const tools = new Map<string, ModuleToolDefinition>();\n for (const module of modules) {\n const register = module.registration.registerTools;\n if (typeof register !== 'function') continue;\n try {\n register.call(module.registration, {\n registerTool: (tool: ModuleToolDefinition) => {\n if (typeof tool?.name !== 'string' || tool.name.length === 0 || typeof tool.handler !== 'function') {\n log.warn(`${module.name} registered a tool without a name or a handler; it was ignored`);\n } else if (reserved.has(tool.name)) {\n log.warn(`${module.name} tool \"${tool.name}\" has the name of a core tool and was ignored`);\n } else if (tools.has(tool.name)) {\n log.warn(`${module.name} tool \"${tool.name}\" is already registered and was ignored`);\n } else {\n tools.set(tool.name, tool);\n }\n },\n });\n } catch (err) {\n log.warn(`${module.name} could not register its tools: ${(err as Error).message}`);\n }\n }\n return [...tools.values()];\n}\n\n/**\n * The input schema of a module tool, built with the host's zod. Throws when the factory throws or returns\n * anything but an object of zod types, so a bad schema fails its own registration instead of `listTools`.\n */\nexport function moduleInputShape(tool: ModuleToolDefinition, zod: typeof z): ZodRawShape {\n const shape: unknown = tool.inputSchema(zod);\n const isZodType = (value: unknown) =>\n typeof value === 'object' && value !== null && typeof (value as { safeParse?: unknown }).safeParse === 'function';\n if (shape === null || typeof shape !== 'object' || Array.isArray(shape) || !Object.values(shape).every(isZodType)) {\n throw new Error('its input schema is not an object of zod types');\n }\n return shape as ZodRawShape;\n}\n\n/**\n * The MCP handler of a module tool: the module's result goes through the `_meta` envelope and masking like\n * a core tool's payload, after the staleness warning when the index is stale. Never throws: a throwing\n * handler, or one that returns something other than an object, gives `{ error: true, message }`.\n */\nexport function handleModuleTool(\n tool: ModuleToolDefinition,\n masking: IMaskingPort,\n staleness: StalenessCheck | undefined,\n indexedFiles: () => readonly string[],\n): (args: Record<string, unknown>) => Promise<McpToolResult> {\n return async (args: Record<string, unknown>) => {\n try {\n const result: unknown = await tool.handler(args);\n if (result === null || typeof result !== 'object' || Array.isArray(result)) {\n throw new Error(`Module tool ${tool.name} returned no payload object`);\n }\n const payload = masking.mask(JSON.stringify(wrapResponse(result as Record<string, unknown>)));\n\n const content: McpToolResult['content'] = [];\n if (staleness) {\n const warning = staleness.check(indexedFiles());\n if (warning) content.push({ type: 'text', text: `⚠️ ${warning.message}` });\n }\n content.push({ type: 'text', text: payload });\n return { content };\n } catch (err) {\n // A module's error text is not the core's: it is masked like its payloads.\n const message = describeError(err);\n return { content: [{ type: 'text', text: masking.mask(JSON.stringify({ error: true, message })) }] };\n }\n };\n}\n","import type { CommunityEntry, CommunitySnapshot, GodNode } from '../types.js';\nimport { makeGlobMatcher } from '../config/load-config.js';\n\n/**\n * Replace sensitive cluster labels with `[masked-cluster-N]`. Labels matching\n * any configured glob (e.g. `internal-*`, `*-vault`, `src/payment-*`) are\n * rewritten deterministically so MCP tool responses never leak org-sensitive\n * directory names to AI agents over the stdio channel.\n *\n * Determinism matters: drift-detector compares labels across snapshots, so\n * the same input label must always produce the same mask. We seed the mask\n * counter from the snapshot's sorted, unique label set.\n */\nexport class ClusterLabelMasker {\n private readonly matcher: (input: string) => boolean;\n private readonly enabled: boolean;\n private readonly labelCache = new Map<string, string>();\n\n constructor(patterns: readonly string[]) {\n this.enabled = patterns.length > 0;\n this.matcher = this.enabled ? makeGlobMatcher([...patterns]) : () => false;\n }\n\n isEnabled(): boolean {\n return this.enabled;\n }\n\n mask(label: string): string {\n if (!this.enabled) return label;\n if (!this.matcher(label)) return label;\n const cached = this.labelCache.get(label);\n if (cached) return cached;\n const masked = `[masked-cluster-${this.labelCache.size + 1}]`;\n this.labelCache.set(label, masked);\n return masked;\n }\n\n maskSnapshot(snapshot: CommunitySnapshot): CommunitySnapshot {\n if (!this.enabled) return snapshot;\n // Seed the cache in sorted order so output is stable across runs.\n const uniqueLabels = [...new Set(snapshot.communities.map((c) => c.communityLabel))].sort();\n for (const label of uniqueLabels) this.mask(label);\n\n const maskedCommunities: CommunityEntry[] = snapshot.communities.map((entry) => ({\n ...entry,\n communityLabel: this.mask(entry.communityLabel),\n }));\n const maskedGodNodes: GodNode[] = snapshot.godNodes.map((g) => ({ ...g }));\n return { ...snapshot, communities: maskedCommunities, godNodes: maskedGodNodes };\n }\n}\n"],"mappings":"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","names":["z","z","InputSchema","z","z","InputSchema","z","z","InputSchema","z","payload","body","z","InputSchema","z","z","z","InputSchema","z","log","log","InputSchema","z","payload","content","z","InputSchema","z","results","body","payload","content","z","InputSchema","z","z","InputSchema","z","z","InputSchema","z","visited","z","InputSchema","z","z","InputSchema","z","log","log","z"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
createModuleHost
|
|
4
|
+
} from "./chunk-G4BMKCKG.js";
|
|
5
|
+
import "./chunk-L2CAUER6.js";
|
|
6
|
+
import "./chunk-7HSA5JVP.js";
|
|
7
|
+
import "./chunk-72CEQEQD.js";
|
|
8
|
+
import "./chunk-X4TVFJ4C.js";
|
|
9
|
+
import "./chunk-5DSKZJNN.js";
|
|
10
|
+
export {
|
|
11
|
+
createModuleHost
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=module-host-KNMKS62R.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
DOMAIN_MODULE_PACKAGE,
|
|
4
|
+
loadCtxoModules,
|
|
5
|
+
sameMinor
|
|
6
|
+
} from "./chunk-LAX6VVBU.js";
|
|
7
|
+
import "./chunk-2Q76LH2H.js";
|
|
8
|
+
import "./chunk-5DSKZJNN.js";
|
|
9
|
+
export {
|
|
10
|
+
DOMAIN_MODULE_PACKAGE,
|
|
11
|
+
loadCtxoModules,
|
|
12
|
+
sameMinor
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=module-loader-B3LYF3W7.js.map
|