ctxo-mcp 0.4.0 → 0.4.2

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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/adapters/transport/http-server-transport.ts","../src/core/masking/masking-pipeline.ts","../src/adapters/mcp/get-logic-slice.ts","../src/core/graph/symbol-graph.ts","../src/core/logic-slice/logic-slice-query.ts","../src/core/detail-levels/detail-formatter.ts","../src/core/response-envelope.ts","../src/core/intent-filter.ts","../src/adapters/mcp/get-why-context.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/core/blast-radius/blast-radius-calculator.ts","../src/adapters/mcp/get-architectural-overlay.ts","../src/core/overlay/architectural-overlay.ts","../src/adapters/mcp/get-dead-code.ts","../src/core/dead-code/dead-code-detector.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/symbol-tokenizer.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/core/importance/pagerank-calculator.ts","../src/adapters/mcp/get-pr-impact.ts"],"sourcesContent":["import { 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 } from 'node:path';\nimport { createLogger } from './core/logger.js';\nimport { SqliteStorageAdapter } from './adapters/storage/sqlite-storage-adapter.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 } from './adapters/mcp/get-architectural-overlay.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';\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\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n\n // HTTP mode — check before CLI routing since --http is a server flag, not a CLI command\n const httpPortStr = process.env.CTXO_HTTP_PORT\n || (args.includes('--http') ? (args[args.indexOf('--port') + 1] || '3001') : null);\n\n if (!httpPortStr && args.length > 0) {\n // CLI mode\n const { CliRouter } = await import('./cli/cli-router.js');\n const router = new CliRouter(process.cwd());\n await router.route(args);\n return;\n }\n\n // Initialize adapters\n const ctxoRoot = '.ctxo';\n const storage = new SqliteStorageAdapter(ctxoRoot);\n await storage.init();\n\n const masking = loadMaskingConfig(ctxoRoot);\n const git = new SimpleGitAdapter(process.cwd());\n\n // Create MCP server\n const server = new McpServer({ name: 'ctxo', version: '0.1.0' });\n\n // Staleness detection\n const { StalenessDetector } = await import('./core/staleness/staleness-detector.js');\n const staleness = new StalenessDetector(process.cwd(), ctxoRoot);\n\n registerTools(server, storage, masking, git, staleness, ctxoRoot);\n\n // Start MCP server — HTTP mode or stdio mode\n if (httpPortStr) {\n await startHttpTransport(async () => {\n const s = new McpServer({ name: 'ctxo', version: '0.1.0' });\n registerTools(s, storage, masking, git, staleness, ctxoRoot);\n return s;\n }, parseInt(httpPortStr, 10));\n } else {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n }\n}\n\nfunction registerTools(\n server: McpServer,\n storage: SqliteStorageAdapter,\n masking: MaskingPipeline,\n git: SimpleGitAdapter,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n staleness: any,\n ctxoRoot = '.ctxo',\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 // Register tools\n const logicSliceHandler = handleGetLogicSlice(storage, masking, staleness, ctxoRoot);\n const whyContextHandler = handleGetWhyContext(storage, git, masking, staleness, ctxoRoot);\n const changeIntelligenceHandler = handleGetChangeIntelligence(storage, git, masking, staleness, ctxoRoot);\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. 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.',\n inputSchema: {\n symbolId: z.string().optional().describe('Single symbol ID (format: file::name::kind)'),\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)'),\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.',\n inputSchema: {\n symbolId: z.string().min(1).describe('The symbol ID (format: file::name::kind)'),\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 = handleGetBlastRadius(storage, masking, staleness, ctxoRoot);\n\n server.registerTool(\n 'get_blast_radius',\n {\n description: 'BEFORE modifying any function or class, call this to understand impact. Returns all symbols that would break if the target changes, split into confirmed (direct importers), likely (co-changed), and potential (transitive) tiers with 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.',\n inputSchema: {\n symbolId: z.string().min(1).describe('The symbol ID (format: file::name::kind)'),\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 = handleGetArchitecturalOverlay(storage, masking, staleness);\n\n server.registerTool(\n 'get_architectural_overlay',\n {\n description: 'Get the project architectural layer map — identifies which symbols belong to Domain, Infrastructure, and Adapter layers. Use this when onboarding to a new codebase or validating that a change respects layer boundaries. For symbol-level analysis, use get_logic_slice or get_blast_radius.',\n inputSchema: {\n layer: z.string().optional().describe('Filter by specific layer name'),\n },\n annotations: toolAnnotations,\n },\n (args) => overlayHandler(args),\n );\n\n const deadCodeHandler = handleFindDeadCode(storage, masking, staleness, ctxoRoot);\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. 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 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 = handleGetContextForTask(storage, masking, staleness, ctxoRoot);\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). 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 (format: file::name::kind)'),\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 = handleGetRankedContext(storage, masking, staleness, ctxoRoot);\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 },\n annotations: toolAnnotations,\n },\n (args) => rankedContextHandler(args),\n );\n\n const searchSymbolsHandler = handleSearchSymbols(storage, masking, staleness, ctxoRoot);\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.',\n inputSchema: {\n pattern: z.string().min(1).describe('Search pattern (substring or regex)'),\n kind: z.enum(['function', 'class', 'interface', 'method', 'variable', 'type']).optional().describe('Filter by symbol kind'),\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 },\n annotations: toolAnnotations,\n },\n (args) => searchSymbolsHandler(args),\n );\n\n const changedSymbolsHandler = handleGetChangedSymbols(storage, git, masking, staleness, ctxoRoot);\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 = handleFindImporters(storage, masking, staleness, ctxoRoot);\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.',\n inputSchema: {\n symbolId: z.string().min(1).describe('The symbol ID (format: file::name::kind)'),\n edgeKinds: z.array(z.enum(['imports', 'calls', 'extends', 'implements', 'uses'])).optional().describe('Filter by edge kinds'),\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 = handleGetClassHierarchy(storage, masking, staleness, ctxoRoot);\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 = handleGetSymbolImportance(storage, masking, staleness, ctxoRoot);\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: z.enum(['function', 'class', 'interface', 'method', 'variable', 'type']).optional().describe('Filter by symbol kind'),\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 = handleGetPrImpact(storage, git, masking, staleness, ctxoRoot);\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.',\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 // 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\nmain().catch((err: unknown) => {\n log.error('Fatal: %s', (err as Error).message);\n process.exit(1);\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 npx ctxo\n * npx 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 + — excludes hex-only git hashes)\n { regex: /(?<![A-Za-z0-9/+])(?=[A-Za-z0-9/+=]{40}(?![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 { IMaskingPort } from '../../ports/i-masking-port.js';\nimport { SymbolGraph } from '../../core/graph/symbol-graph.js';\nimport { JsonIndexReader } from '../storage/json-index-reader.js';\nimport { LogicSliceQuery } from '../../core/logic-slice/logic-slice-query.js';\nimport { DetailFormatter } from '../../core/detail-levels/detail-formatter.js';\nimport { DetailLevelSchema } from '../../core/types.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\nimport { filterByIntent } from '../../core/intent-filter.js';\n\nconst InputSchema = z.object({\n symbolId: z.string().min(1).optional(),\n symbolIds: z.array(z.string().min(1)).optional(),\n level: DetailLevelSchema.optional().default(3),\n intent: z.string().optional().describe('Filter dependencies by intent keywords (e.g., \"core\", \"adapter\", \"storage\")'),\n}).refine(\n (data) => data.symbolId || (data.symbolIds && data.symbolIds.length > 0),\n { message: 'Either symbolId or symbolIds must be provided' },\n);\n\nexport type GetLogicSliceInput = z.infer<typeof InputSchema>;\n\nexport function getLogicSliceInputSchema() {\n return {\n type: 'object' as const,\n properties: {\n symbolId: { type: 'string' as const, description: 'The symbol ID to retrieve (format: file::name::kind)' },\n level: { type: 'number' as const, enum: [1, 2, 3, 4], description: 'Detail level (1=minimal, 4=full)', default: 3 },\n },\n required: ['symbolId'] as const,\n };\n}\n\nexport function buildGraphFromStorage(storage: IStoragePort): SymbolGraph {\n const graph = new SymbolGraph();\n for (const sym of storage.getAllSymbols()) {\n graph.addNode(sym);\n }\n for (const edge of storage.getAllEdges()) {\n graph.addEdge(edge);\n }\n return graph;\n}\n\n/**\n * Build graph directly from JSON index files (bypasses SQLite cache).\n * Always reads fresh data from disk — works even if ctxo index ran in another process.\n */\nexport function buildGraphFromJsonIndex(ctxoRoot: string): SymbolGraph {\n const reader = new JsonIndexReader(ctxoRoot);\n const indices = reader.readAll();\n\n const graph = new SymbolGraph();\n // Phase 1: all nodes\n for (const fileIndex of indices) {\n for (const sym of fileIndex.symbols) {\n graph.addNode(sym);\n }\n }\n // Phase 2: all edges (fuzzy resolution active since nodes are loaded)\n for (const fileIndex of indices) {\n for (const edge of fileIndex.edges) {\n graph.addEdge(edge);\n }\n }\n return graph;\n}\n\nexport interface StalenessCheck {\n check(indexedFiles: readonly string[]): { message: string } | undefined;\n}\n\nexport function handleGetLogicSlice(\n storage: IStoragePort,\n masking: IMaskingPort,\n staleness?: StalenessCheck,\n ctxoRoot = '.ctxo',\n) {\n const query = new LogicSliceQuery();\n const formatter = new DetailFormatter();\n\n // Build graph fresh on each call — try JSON index first (always up to date),\n // fall back to SQLite storage (for tests and when JSON not available).\n const getGraph = () => {\n const jsonGraph = buildGraphFromJsonIndex(ctxoRoot);\n if (jsonGraph.nodeCount > 0) return jsonGraph;\n return buildGraphFromStorage(storage);\n };\n\n const handler = (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, symbolIds, level, intent } = parsed.data;\n const ids = symbolIds ?? (symbolId ? [symbolId] : []);\n\n const graph = getGraph();\n\n // Batch support: query multiple symbols\n const results = [];\n for (const id of ids) {\n const slice = query.getLogicSlice(graph, id);\n if (slice) {\n const formatted = formatter.format(slice, level) as unknown as Record<string, unknown>;\n // Apply intent filter to dependencies if present\n if (intent && Array.isArray(formatted['dependencies'])) {\n formatted['dependencies'] = filterByIntent(\n formatted['dependencies'] as Record<string, unknown>[],\n intent,\n );\n }\n results.push(formatted);\n } else {\n results.push({ found: false, symbolId: id, hint: 'Symbol not found. Run \"ctxo index\".' });\n }\n }\n\n // Single symbol: return directly. Batch: return array.\n const responseData = ids.length === 1 ? results[0] : { batch: true, results };\n\n // Apply masking\n const payload = masking.mask(JSON.stringify(wrapResponse(responseData as Record<string, unknown>)));\n\n // Check staleness\n const content: Array<{ type: 'text'; text: string }> = [];\n if (staleness) {\n const warning = staleness.check(storage.listIndexedFiles());\n if (warning) {\n content.push({ type: 'text', text: `⚠️ ${warning.message}` });\n }\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 return handler;\n}\n","import type { SymbolNode, GraphEdge } from '../types.js';\n\nexport class SymbolGraph {\n private readonly nodes = new Map<string, SymbolNode>();\n private readonly nodesByFileAndName = new Map<string, SymbolNode>();\n private readonly forwardEdges = new Map<string, GraphEdge[]>();\n private readonly reverseEdges = new Map<string, GraphEdge[]>();\n private edgeSet = new Set<string>();\n\n addNode(node: SymbolNode): void {\n this.nodes.set(node.symbolId, node);\n // Index by file::name (ignoring kind) for fuzzy edge resolution\n const [p0, p1] = node.symbolId.split('::');\n if (p0 !== undefined && p1 !== undefined) {\n this.nodesByFileAndName.set(`${p0}::${p1}`, node);\n }\n }\n\n addEdge(edge: GraphEdge): void {\n // Resolve edge endpoints: if exact ID not found, try fuzzy match by file::name\n const resolvedFrom = this.resolveNodeId(edge.from);\n const resolvedTo = this.resolveNodeId(edge.to);\n const resolvedEdge: GraphEdge = { from: resolvedFrom, to: resolvedTo, kind: edge.kind };\n\n const edgeKey = `${resolvedEdge.from}|${resolvedEdge.to}|${resolvedEdge.kind}`;\n if (this.edgeSet.has(edgeKey)) return;\n this.edgeSet.add(edgeKey);\n\n const forward = this.forwardEdges.get(resolvedEdge.from) ?? [];\n forward.push(resolvedEdge);\n this.forwardEdges.set(resolvedEdge.from, forward);\n\n const reverse = this.reverseEdges.get(resolvedEdge.to) ?? [];\n reverse.push(resolvedEdge);\n this.reverseEdges.set(resolvedEdge.to, reverse);\n }\n\n getNode(symbolId: string): SymbolNode | undefined {\n return this.nodes.get(symbolId) ?? this.resolveNodeFuzzy(symbolId);\n }\n\n private resolveNodeId(id: string): string {\n if (this.nodes.has(id)) return id;\n const [p0, p1] = id.split('::');\n if (p0 !== undefined && p1 !== undefined) {\n const fuzzyKey = `${p0}::${p1}`;\n const match = this.nodesByFileAndName.get(fuzzyKey);\n if (match) return match.symbolId;\n\n // Try .js → .ts extension swap (handles unresolved module specifiers)\n const jsToTs = p0.replace(/\\.js$/, '.ts');\n if (jsToTs !== p0) {\n const altKey = `${jsToTs}::${p1}`;\n const altMatch = this.nodesByFileAndName.get(altKey);\n if (altMatch) return altMatch.symbolId;\n }\n }\n return id;\n }\n\n private resolveNodeFuzzy(id: string): SymbolNode | undefined {\n const [p0, p1] = id.split('::');\n if (p0 !== undefined && p1 !== undefined) {\n const match = this.nodesByFileAndName.get(`${p0}::${p1}`);\n if (match) return match;\n\n // Try .js → .ts extension swap (consistent with resolveNodeId)\n const jsToTs = p0.replace(/\\.js$/, '.ts');\n if (jsToTs !== p0) {\n return this.nodesByFileAndName.get(`${jsToTs}::${p1}`);\n }\n }\n return undefined;\n }\n\n getForwardEdges(symbolId: string): GraphEdge[] {\n return this.forwardEdges.get(symbolId) ?? [];\n }\n\n getReverseEdges(symbolId: string): GraphEdge[] {\n return this.reverseEdges.get(symbolId) ?? [];\n }\n\n hasNode(symbolId: string): boolean {\n return this.nodes.has(symbolId) || this.resolveNodeFuzzy(symbolId) !== undefined;\n }\n\n get nodeCount(): number {\n return this.nodes.size;\n }\n\n get edgeCount(): number {\n return this.edgeSet.size;\n }\n\n allNodes(): SymbolNode[] {\n return [...this.nodes.values()];\n }\n\n allEdges(): GraphEdge[] {\n const edges: GraphEdge[] = [];\n for (const list of this.forwardEdges.values()) {\n edges.push(...list);\n }\n return edges;\n }\n}\n","import type { SymbolNode, GraphEdge, LogicSliceResult } from '../types.js';\nimport type { SymbolGraph } from '../graph/symbol-graph.js';\n\nexport class LogicSliceQuery {\n getLogicSlice(\n graph: SymbolGraph,\n symbolId: string,\n maxDepth: number = Infinity,\n ): LogicSliceResult | undefined {\n const root = graph.getNode(symbolId);\n if (!root) return undefined;\n\n const visited = new Set<string>([symbolId]);\n const dependencies: SymbolNode[] = [];\n const collectedEdges: GraphEdge[] = [];\n\n // BFS transitive closure\n const queue: Array<{ id: string; depth: number }> = [{ id: symbolId, depth: 0 }];\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n\n if (current.depth >= maxDepth) continue;\n\n const edges = graph.getForwardEdges(current.id);\n for (const edge of edges) {\n const depNode = graph.getNode(edge.to);\n // Only include edges whose target node exists in the graph\n if (!depNode) continue;\n\n collectedEdges.push(edge);\n\n if (visited.has(edge.to)) continue;\n visited.add(edge.to);\n\n dependencies.push(depNode);\n queue.push({ id: edge.to, depth: current.depth + 1 });\n }\n }\n\n return { root, dependencies, edges: collectedEdges };\n }\n}\n","import type {\n LogicSliceResult,\n FormattedSlice,\n DetailLevel,\n SymbolNode,\n GraphEdge,\n} from '../types.js';\n\nconst L1_MAX_LINES = 150;\nconst L4_TOKEN_BUDGET = 8000;\n\nexport class DetailFormatter {\n format(slice: LogicSliceResult, level: DetailLevel): FormattedSlice {\n switch (level) {\n case 1:\n return this.formatL1(slice);\n case 2:\n return this.formatL2(slice);\n case 3:\n return this.formatL3(slice);\n case 4:\n return this.formatL4(slice);\n }\n }\n\n private formatL1(slice: LogicSliceResult): FormattedSlice {\n const root = slice.root;\n const lineCount = root.endLine - root.startLine + 1;\n\n const clampedRoot: SymbolNode = lineCount > L1_MAX_LINES\n ? { ...root, endLine: root.startLine + L1_MAX_LINES - 1 }\n : root;\n\n return {\n root: clampedRoot,\n dependencies: [],\n edges: [],\n level: 1,\n levelDescription: 'L1: Root symbol signature only (no dependencies)',\n ...(lineCount > L1_MAX_LINES ? { truncation: { truncated: true as const, reason: 'token_budget_exceeded' as const } } : {}),\n };\n }\n\n private formatL2(slice: LogicSliceResult): FormattedSlice {\n // L2: root + depth-1 direct dependencies\n const directEdges = slice.edges.filter((e) => e.from === slice.root.symbolId);\n const directDepIds = new Set(directEdges.map((e) => e.to));\n const directDeps = slice.dependencies.filter((d) => directDepIds.has(d.symbolId));\n\n return {\n root: slice.root,\n dependencies: directDeps,\n edges: directEdges,\n level: 2,\n levelDescription: 'L2: Root + direct dependencies (depth 1)',\n };\n }\n\n private formatL3(slice: LogicSliceResult): FormattedSlice {\n return {\n root: slice.root,\n dependencies: slice.dependencies,\n edges: slice.edges,\n level: 3,\n levelDescription: 'L3: Full transitive dependency closure',\n };\n }\n\n private formatL4(slice: LogicSliceResult): FormattedSlice {\n // L4: full closure with token budget enforcement\n const estimatedTokens = this.estimateTokens(slice);\n\n if (estimatedTokens > L4_TOKEN_BUDGET) {\n // Truncate dependencies to fit budget\n const truncated = this.truncateToTokenBudget(slice, L4_TOKEN_BUDGET);\n return {\n ...truncated,\n level: 4,\n levelDescription: 'L4: Full closure with 8K token budget (truncated)',\n truncation: {\n truncated: true,\n reason: 'token_budget_exceeded',\n },\n };\n }\n\n return {\n root: slice.root,\n dependencies: slice.dependencies,\n edges: slice.edges,\n level: 4,\n levelDescription: 'L4: Full closure with 8K token budget',\n };\n }\n\n private estimateTokens(slice: LogicSliceResult): number {\n // Rough estimate: ~4 chars per token\n let chars = this.symbolCharEstimate(slice.root);\n for (const dep of slice.dependencies) {\n chars += this.symbolCharEstimate(dep);\n }\n for (const edge of slice.edges) {\n chars += (edge.from.length + edge.to.length + edge.kind.length + 10);\n }\n return Math.ceil(chars / 4);\n }\n\n private symbolCharEstimate(node: SymbolNode): number {\n // Use byte offsets for exact size when available, otherwise estimate from line count\n if (node.startOffset !== undefined && node.endOffset !== undefined) {\n return node.endOffset - node.startOffset;\n }\n return (node.endLine - node.startLine + 1) * 40;\n }\n\n private truncateToTokenBudget(\n slice: LogicSliceResult,\n budget: number,\n ): { root: SymbolNode; dependencies: SymbolNode[]; edges: GraphEdge[] } {\n let currentTokens = this.symbolCharEstimate(slice.root) / 4;\n const deps: SymbolNode[] = [];\n const includedIds = new Set<string>([slice.root.symbolId]);\n\n for (const dep of slice.dependencies) {\n const depTokens = this.symbolCharEstimate(dep) / 4;\n if (currentTokens + depTokens > budget) break;\n currentTokens += depTokens;\n deps.push(dep);\n includedIds.add(dep.symbolId);\n }\n\n const edges = slice.edges.filter(\n (e) => includedIds.has(e.from) && includedIds.has(e.to),\n );\n\n return { root: slice.root, dependencies: deps, edges };\n }\n}\n","/**\n * Response envelope — adds _meta field and truncates large payloads.\n *\n * Applied between payload construction and masking in every MCP handler.\n * Threshold default: 8192 bytes (~8KB). Configurable via CTXO_RESPONSE_LIMIT env.\n */\n\nconst DEFAULT_THRESHOLD = 8192;\n\nexport interface ResponseMeta {\n totalItems: number;\n returnedItems: number;\n truncated: boolean;\n totalBytes: number;\n hint?: string;\n}\n\n/**\n * Known array field names in tool responses that can be truncated.\n * Maps field name → drill-in hint for the LLM.\n */\nconst TRUNCATABLE_FIELDS: Record<string, string> = {\n impactedSymbols: 'Use search_symbols to find specific impacted symbols, or get_blast_radius with a confidence filter.',\n importers: 'Use find_importers with edgeKinds filter or maxDepth to narrow results.',\n deadSymbols: 'Use search_symbols with kind filter to find specific dead symbols.',\n unusedExports: 'Use find_importers to check specific symbols.',\n results: 'Use search_symbols or get_ranked_context with a narrower query.',\n rankings: 'Use get_symbol_importance with kind or filePattern filter to narrow results.',\n context: 'Use get_context_for_task with a smaller tokenBudget.',\n hierarchies: 'Use get_class_hierarchy with a specific symbolId.',\n scaffolding: 'Review the scaffolding markers directly in the listed files.',\n deadFiles: 'Use find_dead_code with includeTests to adjust scope.',\n files: 'Use get_changed_symbols with a narrower since ref or smaller maxFiles.',\n};\n\nfunction getThreshold(): number {\n const env = process.env['CTXO_RESPONSE_LIMIT'];\n if (env) {\n const n = parseInt(env, 10);\n if (!isNaN(n) && n > 0) return n;\n }\n return DEFAULT_THRESHOLD;\n}\n\n/**\n * Find the largest array field in a payload object that is in our truncatable list.\n */\nfunction findTruncatableArray(data: Record<string, unknown>): { key: string; arr: unknown[] } | null {\n let best: { key: string; arr: unknown[] } | null = null;\n for (const [key, value] of Object.entries(data)) {\n if (Array.isArray(value) && key in TRUNCATABLE_FIELDS) {\n if (!best || value.length > best.arr.length) {\n best = { key, arr: value };\n }\n }\n }\n return best;\n}\n\n/**\n * Wrap a payload object with _meta and truncate if needed.\n *\n * @param data - The raw response object (before JSON.stringify)\n * @returns The data object with _meta added (and arrays truncated if over threshold)\n */\nexport function wrapResponse(data: Record<string, unknown>): Record<string, unknown> {\n const threshold = getThreshold();\n const fullJson = JSON.stringify(data);\n const totalBytes = Buffer.byteLength(fullJson, 'utf-8');\n\n const truncatable = findTruncatableArray(data);\n const totalItems = truncatable ? truncatable.arr.length : 0;\n\n // Under threshold — return with _meta, no truncation\n if (totalBytes <= threshold) {\n return {\n ...data,\n _meta: {\n totalItems,\n returnedItems: totalItems,\n truncated: false,\n totalBytes,\n } satisfies ResponseMeta,\n };\n }\n\n // Over threshold — truncate the largest array\n if (!truncatable || truncatable.arr.length <= 1) {\n // No array to truncate, just add _meta\n return {\n ...data,\n _meta: {\n totalItems,\n returnedItems: totalItems,\n truncated: false,\n totalBytes,\n } satisfies ResponseMeta,\n };\n }\n\n // Binary search for the number of items that fit within threshold\n let lo = 1;\n let hi = truncatable.arr.length;\n\n while (lo < hi) {\n const mid = Math.ceil((lo + hi) / 2);\n const trial = {\n ...data,\n [truncatable.key]: truncatable.arr.slice(0, mid),\n _meta: {\n totalItems,\n returnedItems: mid,\n truncated: true,\n totalBytes,\n hint: TRUNCATABLE_FIELDS[truncatable.key],\n },\n };\n const size = Buffer.byteLength(JSON.stringify(trial), 'utf-8');\n if (size <= threshold) {\n lo = mid;\n } else {\n hi = mid - 1;\n }\n }\n\n const hint = TRUNCATABLE_FIELDS[truncatable.key];\n\n return {\n ...data,\n [truncatable.key]: truncatable.arr.slice(0, lo),\n _meta: {\n totalItems,\n returnedItems: lo,\n truncated: true,\n totalBytes,\n hint,\n } satisfies ResponseMeta,\n };\n}\n","/**\n * Intent-based result filtering for MCP tool responses.\n *\n * When an `intent` string is provided, filters array results to only include\n * entries whose text fields (symbolId, file, name, kind, edgeKind, reason)\n * match at least one keyword from the intent.\n *\n * Keywords are extracted by splitting the intent on whitespace and lowercasing.\n * A match is found when any keyword appears as a substring of any text field.\n */\n\n/**\n * Extract lowercase keywords from an intent string.\n * Filters out very short words (< 2 chars) to avoid noise.\n */\nfunction extractKeywords(intent: string): string[] {\n return intent\n .toLowerCase()\n .split(/\\s+/)\n .filter(w => w.length >= 2);\n}\n\n/**\n * Check if any keyword matches any of the given text values (case-insensitive substring).\n */\nfunction matchesAny(keywords: string[], values: string[]): boolean {\n const lower = values.map(v => v.toLowerCase());\n return keywords.some(kw => lower.some(v => v.includes(kw)));\n}\n\n/**\n * Collect all string values from a record for matching.\n * Extracts from known fields: symbolId, file, name, kind, edgeKind, edgeKinds, reason, confidence.\n */\nfunction collectMatchableStrings(entry: Record<string, unknown>): string[] {\n const strings: string[] = [];\n for (const key of ['symbolId', 'file', 'name', 'kind', 'edgeKind', 'reason', 'confidence']) {\n const v = entry[key];\n if (typeof v === 'string') strings.push(v);\n }\n const edgeKinds = entry['edgeKinds'];\n if (Array.isArray(edgeKinds)) {\n for (const ek of edgeKinds) {\n if (typeof ek === 'string') strings.push(ek);\n }\n }\n return strings;\n}\n\n/**\n * Filter an array of result entries by intent keywords.\n * Returns only entries where at least one keyword matches a text field.\n *\n * @param items - Array of result objects\n * @param intent - User intent string (e.g., \"test coverage\", \"adapter\", \"security\")\n * @returns Filtered array (empty if no matches)\n */\nexport function filterByIntent<T extends Record<string, unknown>>(\n items: T[],\n intent: string | undefined,\n): T[] {\n if (!intent || intent.trim().length === 0) return items;\n\n const keywords = extractKeywords(intent);\n if (keywords.length === 0) return items;\n\n return items.filter(item => {\n const strings = collectMatchableStrings(item);\n return matchesAny(keywords, strings);\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 { JsonIndexReader } from '../storage/json-index-reader.js';\nimport type { CommitIntent, AntiPattern } from '../../core/types.js';\nimport type { StalenessCheck } from './get-logic-slice.js';\n\nconst 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) {\n const revertDetector = new RevertDetector();\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, maxCommits } = 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\n // Try committed index first (FR16: anti-patterns persist in committed index)\n const indices = indexReader.readAll();\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 payload = masking.mask(JSON.stringify(responsePayload));\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 { 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\nconst 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 // 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 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 { IStoragePort } from '../../ports/i-storage-port.js';\nimport type { IMaskingPort } from '../../ports/i-masking-port.js';\nimport { BlastRadiusCalculator } from '../../core/blast-radius/blast-radius-calculator.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\nimport { filterByIntent } from '../../core/intent-filter.js';\nimport type { StalenessCheck } from './get-logic-slice.js';\nimport { buildGraphFromJsonIndex, buildGraphFromStorage } from './get-logic-slice.js';\n\nconst 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) {\n const calculator = new BlastRadiusCalculator();\n const getGraph = () => {\n const jsonGraph = buildGraphFromJsonIndex(ctxoRoot);\n if (jsonGraph.nodeCount > 0) return jsonGraph;\n return buildGraphFromStorage(storage);\n };\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 } = parsed.data;\n const graph = getGraph();\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 const result = calculator.calculate(graph, symbolId);\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 payload = masking.mask(JSON.stringify(wrapResponse({\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\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 { SymbolGraph } from '../graph/symbol-graph.js';\nimport type { CoChangeEntry } from '../types.js';\n\nexport type ImpactConfidence = 'confirmed' | 'likely' | 'potential';\n\nexport interface BlastRadiusEntry {\n readonly symbolId: string;\n readonly depth: number;\n readonly dependentCount: number;\n readonly riskScore: number;\n readonly confidence: ImpactConfidence;\n readonly edgeKinds: string[];\n readonly coChangeFrequency?: number;\n}\n\nexport interface BlastRadiusResult {\n readonly impactedSymbols: BlastRadiusEntry[];\n readonly directDependentsCount: number;\n readonly confirmedCount: number;\n readonly likelyCount: number;\n readonly potentialCount: number;\n readonly overallRiskScore: number;\n}\n\nconst CONFIRMED_KINDS = new Set(['calls', 'extends', 'implements']);\nconst LIKELY_KINDS = new Set(['uses']);\n\nconst CONFIDENCE_RANK: Record<ImpactConfidence, number> = {\n confirmed: 2,\n likely: 1,\n potential: 0,\n};\n\nfunction edgeKindToConfidence(kind: string): ImpactConfidence {\n if (CONFIRMED_KINDS.has(kind)) return 'confirmed';\n if (LIKELY_KINDS.has(kind)) return 'likely';\n return 'potential';\n}\n\nexport class BlastRadiusCalculator {\n calculate(graph: SymbolGraph, symbolId: string, coChangeMap?: Map<string, CoChangeEntry[]>): BlastRadiusResult {\n if (!graph.hasNode(symbolId)) {\n return { impactedSymbols: [], directDependentsCount: 0, confirmedCount: 0, likelyCount: 0, potentialCount: 0, overallRiskScore: 0 };\n }\n\n const sourceFile = symbolId.split('::')[0]!;\n\n const visited = new Set<string>([symbolId]);\n const rawEntries: Array<{ symbolId: string; depth: number; riskScore: number; confidence: ImpactConfidence; edgeKinds: string[]; coChangeFrequency?: number }> = [];\n\n // BFS via reverse edges (who depends on this symbol?)\n const queue: Array<{ id: string; depth: number }> = [{ id: symbolId, depth: 0 }];\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n\n const reverseEdges = graph.getReverseEdges(current.id);\n\n // Group edges by source node, pick strongest confidence per node\n // confirmed > likely > potential — collect all edge kinds\n const bestByNode = new Map<string, { confidence: ImpactConfidence; kinds: Set<string> }>();\n for (const edge of reverseEdges) {\n if (visited.has(edge.from)) continue;\n const conf = edgeKindToConfidence(edge.kind);\n const existing = bestByNode.get(edge.from);\n if (!existing) {\n bestByNode.set(edge.from, { confidence: conf, kinds: new Set([edge.kind]) });\n } else {\n existing.kinds.add(edge.kind);\n if (CONFIDENCE_RANK[conf] > CONFIDENCE_RANK[existing.confidence]) {\n existing.confidence = conf;\n }\n }\n }\n\n for (const [nodeId, info] of bestByNode) {\n visited.add(nodeId);\n if (!graph.hasNode(nodeId)) continue;\n\n const depth = current.depth + 1;\n const riskScore = 1 / Math.pow(depth, 0.7);\n\n // Co-change boost: if files frequently change together, upgrade potential → likely\n let confidence = info.confidence;\n let coChangeFrequency: number | undefined;\n if (coChangeMap) {\n const nodeFile = nodeId.split('::')[0]!;\n const coEntries = coChangeMap.get(sourceFile);\n if (coEntries) {\n const match = coEntries.find(e => e.file1 === nodeFile || e.file2 === nodeFile);\n if (match) {\n coChangeFrequency = match.frequency;\n if (confidence === 'potential' && match.frequency > 0.5) {\n confidence = 'likely';\n }\n }\n }\n }\n\n rawEntries.push({\n symbolId: nodeId,\n depth,\n riskScore: Math.round(riskScore * 1000) / 1000,\n confidence,\n edgeKinds: [...info.kinds],\n coChangeFrequency,\n });\n\n queue.push({ id: nodeId, depth });\n }\n }\n\n // GAP-30 FIX: compute dependentCount as blast-scope in-degree (not global)\n const blastSet = new Set(rawEntries.map((e) => e.symbolId));\n blastSet.add(symbolId);\n\n const entries: BlastRadiusEntry[] = rawEntries.map((e) => ({\n ...e,\n dependentCount: graph.getReverseEdges(e.symbolId).filter((re) => blastSet.has(re.from)).length,\n }));\n\n // Sort by depth ascending\n entries.sort((a, b) => a.depth - b.depth);\n\n const directDependentsCount = entries.filter((e) => e.depth === 1).length;\n\n // GAP-29 FIX: depth-weighted risk — direct dependents dominate\n const totalRisk = entries.reduce((sum, e) => sum + e.riskScore, 0);\n const overallRiskScore = Math.round(Math.min(totalRisk / Math.max(directDependentsCount, 1), 1) * 1000) / 1000;\n\n const confirmedCount = entries.filter((e) => e.confidence === 'confirmed').length;\n const likelyCount = entries.filter((e) => e.confidence === 'likely').length;\n const potentialCount = entries.filter((e) => e.confidence === 'potential').length;\n\n return { impactedSymbols: entries, directDependentsCount, confirmedCount, likelyCount, potentialCount, overallRiskScore };\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 { ArchitecturalOverlay } from '../../core/overlay/architectural-overlay.js';\nimport type { StalenessCheck } from './get-logic-slice.js';\n\nconst InputSchema = z.object({\n layer: z.string().optional(),\n});\n\nexport function handleGetArchitecturalOverlay(\n storage: IStoragePort,\n masking: IMaskingPort,\n staleness?: StalenessCheck,\n) {\n const overlay = new ArchitecturalOverlay();\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 files = storage.listIndexedFiles();\n const result = overlay.classify(files);\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 // Filter by layer if specified\n if (parsed.data.layer) {\n const filtered = result.layers[parsed.data.layer];\n const payload = masking.mask(JSON.stringify({ layer: parsed.data.layer, files: filtered ?? [] }));\n return { content: buildContent(payload) };\n }\n\n const payload = masking.mask(JSON.stringify(result));\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","export interface LayerRule {\n readonly pattern: RegExp;\n readonly layer: string;\n}\n\nexport interface OverlayResult {\n readonly layers: Record<string, string[]>;\n}\n\nconst DEFAULT_RULES: LayerRule[] = [\n // Test layer (matched first — __tests__, .test.ts, tests/, fixtures)\n { pattern: /__tests__/, layer: 'Test' },\n { pattern: /\\.test\\.ts$/, layer: 'Test' },\n { pattern: /\\btests\\b/, layer: 'Test' },\n { pattern: /\\bfixtures?\\b/, layer: 'Test' },\n // Composition root\n { pattern: /src\\/index\\.ts$/, layer: 'Composition' },\n // Domain\n { pattern: /\\bcore\\b/, layer: 'Domain' },\n { pattern: /\\bports?\\b/, layer: 'Domain' },\n // Adapter\n { pattern: /\\badapters?\\b/, layer: 'Adapter' },\n { pattern: /\\bcli\\b/, layer: 'Adapter' },\n // Infrastructure\n { pattern: /\\binfra\\b/, layer: 'Infrastructure' },\n { pattern: /\\bdb\\b/, layer: 'Infrastructure' },\n { pattern: /\\bqueue\\b/, layer: 'Infrastructure' },\n // Config files\n { pattern: /\\.(config|rc)\\.(ts|js|json)$/, layer: 'Configuration' },\n];\n\nexport class ArchitecturalOverlay {\n private readonly rules: LayerRule[];\n\n constructor(customRules?: LayerRule[]) {\n this.rules = (customRules ?? DEFAULT_RULES).map(({ pattern, layer }) => ({\n pattern: new RegExp(pattern.source, pattern.flags),\n layer,\n }));\n }\n\n classify(filePaths: readonly string[]): OverlayResult {\n const layers: Record<string, string[]> = {};\n\n for (const filePath of filePaths) {\n const layer = this.matchLayer(filePath);\n const list = layers[layer] ?? [];\n list.push(filePath);\n layers[layer] = list;\n }\n\n return { layers };\n }\n\n private matchLayer(filePath: string): string {\n for (const rule of this.rules) {\n if (rule.pattern.test(filePath)) {\n return rule.layer;\n }\n }\n return 'Unknown';\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 { buildGraphFromJsonIndex, buildGraphFromStorage } 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\nconst 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 = () => {\n const jsonGraph = buildGraphFromJsonIndex(ctxoRoot);\n if (jsonGraph.nodeCount > 0) return jsonGraph;\n return buildGraphFromStorage(storage);\n };\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 = 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(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 { SymbolGraph } from '../graph/symbol-graph.js';\nimport type { SymbolKind } from '../types.js';\n\nexport type DeadCodeConfidence = 1.0 | 0.9 | 0.7;\n\nexport interface DeadSymbolEntry {\n readonly symbolId: string;\n readonly file: string;\n readonly name: string;\n readonly kind: SymbolKind;\n readonly confidence: DeadCodeConfidence;\n readonly reason: string;\n readonly cascadeDepth?: number;\n}\n\nexport interface UnusedExportEntry {\n readonly symbolId: string;\n readonly file: string;\n readonly name: string;\n readonly kind: SymbolKind;\n}\n\nexport interface ScaffoldingEntry {\n readonly file: string;\n readonly line: number;\n readonly pattern: string;\n readonly text: string;\n}\n\nexport interface DeadCodeResult {\n readonly totalSymbols: number;\n readonly reachableSymbols: number;\n readonly deadSymbols: DeadSymbolEntry[];\n readonly unusedExports: UnusedExportEntry[];\n readonly deadFiles: string[];\n readonly scaffolding: ScaffoldingEntry[];\n readonly deadCodePercentage: number;\n}\n\n// Patterns for files to exclude from dead code analysis\nconst TEST_PATTERNS = [/__tests__/, /\\.test\\.ts$/, /\\.spec\\.ts$/, /\\btests\\//, /\\bfixtures?\\//];\nconst CONFIG_PATTERNS = [/\\.(config|rc)\\.(ts|js|json)$/, /tsconfig/, /eslint/, /\\.d\\.ts$/];\n\n// Framework lifecycle symbols — should never be flagged as dead\nconst FRAMEWORK_PATTERNS = [\n // Vitest\n /^(describe|it|expect|beforeAll|beforeEach|afterAll|afterEach|vi)$/,\n // MCP SDK\n /^(registerTool|registerPrompt|connect|close)$/,\n // Zod schemas (conventionally exported for validation)\n /Schema$/,\n // Node.js lifecycle\n /^main$/,\n];\n\n// Scaffolding / AI artifact patterns\nconst SCAFFOLDING_PATTERNS = [\n { regex: /\\bTODO\\b/i, pattern: 'TODO' },\n { regex: /\\bFIXME\\b/i, pattern: 'FIXME' },\n { regex: /\\bHACK\\b/i, pattern: 'HACK' },\n { regex: /\\bPLACEHOLDER\\b/i, pattern: 'PLACEHOLDER' },\n { regex: /\\bXXX\\b/, pattern: 'XXX' },\n { regex: /Phase\\s+\\d|Step\\s+\\d/i, pattern: 'PHASE/STEP' },\n { regex: /not\\s+(?:yet\\s+)?implement/i, pattern: 'NOT_IMPLEMENTED' },\n { regex: /temporary|temp\\s+fix/i, pattern: 'TEMPORARY' },\n];\n\nexport class DeadCodeDetector {\n detect(\n graph: SymbolGraph,\n options: { includeTests?: boolean; sourceContents?: Map<string, string> } = {},\n ): DeadCodeResult {\n const allNodes = graph.allNodes();\n\n // Filter candidates — exclude tests/config by default\n const candidates = options.includeTests\n ? allNodes\n : allNodes.filter((n) => {\n const file = n.symbolId.split('::')[0] ?? '';\n return !this.matchesAny(file, TEST_PATTERNS) && !this.matchesAny(file, CONFIG_PATTERNS);\n });\n\n if (candidates.length === 0) {\n return { totalSymbols: 0, reachableSymbols: 0, deadSymbols: [], unusedExports: [], deadFiles: [], scaffolding: this.detectScaffolding(options.sourceContents), deadCodePercentage: 0 };\n }\n\n // Dynamic entry point detection: symbols with zero reverse edges (no one imports them)\n const candidateIds = new Set(candidates.map((n) => n.symbolId));\n const entryPoints = new Set<string>();\n\n for (const node of candidates) {\n // Framework lifecycle symbols are always entry points (never dead)\n if (this.isFrameworkSymbol(node.name)) {\n entryPoints.add(node.symbolId);\n continue;\n }\n\n const reverseEdges = graph.getReverseEdges(node.symbolId);\n const forwardEdges = graph.getForwardEdges(node.symbolId);\n\n // Filter: only count reverse edges from OTHER candidates\n const incomingFromCandidates = reverseEdges.filter((e) => candidateIds.has(e.from) && e.from !== node.symbolId);\n\n if (incomingFromCandidates.length === 0) {\n const hasOutgoing = forwardEdges.some((e) => candidateIds.has(e.to));\n if (hasOutgoing || reverseEdges.length > 0) {\n entryPoints.add(node.symbolId);\n }\n }\n }\n\n // Forward BFS from all entry points — mark reachable symbols\n const reachable = new Set<string>();\n const queue = [...entryPoints];\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n if (reachable.has(current)) continue;\n reachable.add(current);\n\n for (const edge of graph.getForwardEdges(current)) {\n if (!reachable.has(edge.to) && candidateIds.has(edge.to)) {\n queue.push(edge.to);\n }\n }\n }\n\n // Dead = candidates not reachable from any entry point\n // These are \"island\" symbols — circular deps where the whole cluster is unreachable\n const deadIds = new Set<string>();\n for (const node of candidates) {\n if (!reachable.has(node.symbolId)) {\n deadIds.add(node.symbolId);\n }\n }\n\n // Compute cascade depth: how deep in the dead chain is this symbol?\n const cascadeDepthMap = this.computeCascadeDepths(graph, deadIds, candidateIds);\n\n // Compute confidence per dead symbol\n const deadSymbols: DeadSymbolEntry[] = [];\n for (const node of candidates) {\n if (!deadIds.has(node.symbolId)) continue;\n\n const file = node.symbolId.split('::')[0] ?? '';\n const confidence = this.computeConfidence(graph, node.symbolId, deadIds);\n const cascadeDepth = cascadeDepthMap.get(node.symbolId);\n\n deadSymbols.push({\n symbolId: node.symbolId,\n file,\n name: node.name,\n kind: node.kind,\n confidence,\n reason: this.describeReason(confidence),\n ...(cascadeDepth !== undefined && cascadeDepth > 0 ? { cascadeDepth } : {}),\n });\n }\n\n // Dead files = files where ALL candidate symbols are dead\n const fileStats = new Map<string, { total: number; dead: number }>();\n for (const node of candidates) {\n const file = node.symbolId.split('::')[0] ?? '';\n const stats = fileStats.get(file) ?? { total: 0, dead: 0 };\n stats.total++;\n if (deadIds.has(node.symbolId)) stats.dead++;\n fileStats.set(file, stats);\n }\n\n const deadFiles = [...fileStats.entries()]\n .filter(([, s]) => s.total > 0 && s.dead === s.total)\n .map(([file]) => file);\n\n // Unused exports: symbols with zero reverse edges from other candidates\n // Different from dead code: an unused export may be an entry point (reachable)\n // but still never imported by anyone\n const unusedExports: UnusedExportEntry[] = [];\n for (const node of candidates) {\n const reverseEdges = graph.getReverseEdges(node.symbolId);\n const externalImporters = reverseEdges.filter((e) =>\n candidateIds.has(e.from) && e.from !== node.symbolId,\n );\n\n if (externalImporters.length === 0 && !deadIds.has(node.symbolId)) {\n // Exported, reachable (entry point), but nobody imports it\n unusedExports.push({\n symbolId: node.symbolId,\n file: node.symbolId.split('::')[0] ?? '',\n name: node.name,\n kind: node.kind,\n });\n }\n }\n\n // Scaffolding detection: scan source contents for TODO/FIXME/HACK patterns\n const scaffolding = this.detectScaffolding(options.sourceContents);\n\n const deadCodePercentage = Math.round((deadSymbols.length / candidates.length) * 100 * 10) / 10;\n\n return {\n totalSymbols: candidates.length,\n reachableSymbols: reachable.size,\n deadSymbols,\n unusedExports,\n deadFiles,\n scaffolding,\n deadCodePercentage,\n };\n }\n\n private computeConfidence(\n graph: SymbolGraph,\n symbolId: string,\n deadIds: Set<string>,\n ): DeadCodeConfidence {\n const reverseEdges = graph.getReverseEdges(symbolId);\n\n // 1.0: Zero importers at all — definitely dead\n if (reverseEdges.length === 0) {\n return 1.0;\n }\n\n // 0.9: Has importers but they're all from test/config files\n const allImportersExcluded = reverseEdges.every((e) => {\n const importerFile = e.from.split('::')[0] ?? '';\n return this.matchesAny(importerFile, TEST_PATTERNS) || this.matchesAny(importerFile, CONFIG_PATTERNS);\n });\n if (allImportersExcluded) {\n return 0.9;\n }\n\n // 0.7: All importers are themselves dead (cascading dead code)\n const allImportersDead = reverseEdges.every((e) => deadIds.has(e.from));\n if (allImportersDead) {\n return 0.7;\n }\n\n // Shouldn't reach here if symbol is truly dead, but default to 0.7\n return 0.7;\n }\n\n private describeReason(confidence: DeadCodeConfidence): string {\n switch (confidence) {\n case 1.0:\n return 'Zero importers — no code references this symbol';\n case 0.9:\n return 'Only referenced from test/config files';\n case 0.7:\n return 'All importers are themselves dead (cascading)';\n }\n }\n\n private isFrameworkSymbol(name: string): boolean {\n return FRAMEWORK_PATTERNS.some((p) => p.test(name));\n }\n\n private computeCascadeDepths(\n graph: SymbolGraph,\n deadIds: Set<string>,\n candidateIds: Set<string>,\n ): Map<string, number> {\n const depths = new Map<string, number>();\n\n // Find root dead symbols (zero reverse edges from other dead symbols)\n const rootDead = new Set<string>();\n for (const id of deadIds) {\n const reverseEdges = graph.getReverseEdges(id);\n const deadImporters = reverseEdges.filter((e) => deadIds.has(e.from) && e.from !== id);\n if (deadImporters.length === 0) {\n rootDead.add(id);\n depths.set(id, 0);\n }\n }\n\n // BFS from root dead symbols to compute cascade depth\n const queue = [...rootDead].map((id) => ({ id, depth: 0 }));\n const visited = new Set(rootDead);\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n for (const edge of graph.getForwardEdges(current.id)) {\n if (deadIds.has(edge.to) && !visited.has(edge.to) && candidateIds.has(edge.to)) {\n const newDepth = current.depth + 1;\n depths.set(edge.to, newDepth);\n visited.add(edge.to);\n queue.push({ id: edge.to, depth: newDepth });\n }\n }\n }\n\n return depths;\n }\n\n private detectScaffolding(sourceContents?: Map<string, string>): ScaffoldingEntry[] {\n if (!sourceContents || sourceContents.size === 0) return [];\n\n const results: ScaffoldingEntry[] = [];\n\n for (const [file, content] of sourceContents) {\n // Skip test/config files\n if (this.matchesAny(file, TEST_PATTERNS) || this.matchesAny(file, CONFIG_PATTERNS)) continue;\n\n const lines = content.split('\\n');\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]!;\n for (const { regex, pattern } of SCAFFOLDING_PATTERNS) {\n if (regex.test(line)) {\n results.push({\n file,\n line: i + 1,\n pattern,\n text: line.trim().slice(0, 120),\n });\n break; // One match per line\n }\n }\n }\n }\n\n return results;\n }\n\n private matchesAny(value: string, patterns: RegExp[]): boolean {\n return patterns.some((p) => p.test(value));\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 { ContextAssembler } from '../../core/context-assembly/context-assembler.js';\nimport { JsonIndexReader } from '../storage/json-index-reader.js';\nimport { buildGraphFromJsonIndex, buildGraphFromStorage } 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\nconst 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) {\n const assembler = new ContextAssembler();\n const indexReader = new JsonIndexReader(ctxoRoot);\n\n const getGraph = () => {\n const jsonGraph = buildGraphFromJsonIndex(ctxoRoot);\n if (jsonGraph.nodeCount > 0) return jsonGraph;\n return buildGraphFromStorage(storage);\n };\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 = getGraph();\n const indices = indexReader.readAll();\n\n const result = assembler.assembleForTask(graph, symbolId, taskType, indices, tokenBudget);\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(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","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 type { SymbolNode, SymbolKind, FileIndex } from '../types.js';\nimport { LogicSliceQuery } from '../logic-slice/logic-slice-query.js';\nimport { BlastRadiusCalculator } from '../blast-radius/blast-radius-calculator.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\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 assembleForTask(\n graph: SymbolGraph,\n symbolId: string,\n taskType: TaskType,\n indices: readonly FileIndex[],\n tokenBudget = DEFAULT_TOKEN_BUDGET,\n ): TaskContextResult | undefined {\n const target = graph.getNode(symbolId);\n if (!target) return undefined;\n\n const weights = getWeightsForTask(taskType);\n\n // Gather forward deps + reverse deps\n const slice = this.logicSlice.getLogicSlice(graph, symbolId);\n const blastResult = this.blastRadius.calculate(graph, symbolId);\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)\n for (const entry of blastResult.impactedSymbols) {\n const node = graph.getNode(entry.symbolId);\n if (!node) continue;\n\n const existing = candidateMap.get(entry.symbolId);\n if (existing) {\n existing.signals.isDependent = true;\n } else {\n candidateMap.set(entry.symbolId, {\n node,\n signals: { isDirectDep: false, isInterfaceOrType: this.isInterfaceOrType(node.kind), isDependent: true, 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 = symbolId.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 return { 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 };\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 complexity: number;\n hasAntiPattern: boolean;\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 { buildGraphFromJsonIndex, buildGraphFromStorage } 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\nconst 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 fuzzy: z.boolean().optional().default(true),\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 = () => {\n const jsonGraph = buildGraphFromJsonIndex(ctxoRoot);\n if (jsonGraph.nodeCount > 0) return jsonGraph;\n return buildGraphFromStorage(storage);\n };\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 = 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(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 }\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(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","/**\n * Symbol Tokenizer — splits symbol names into searchable tokens.\n *\n * Handles camelCase, PascalCase, snake_case, kebab-case, and digit boundaries.\n * Used to populate FTS5 `tokenized_name` columns and to tokenize search queries.\n */\n\nconst STOP_WORDS = new Set([\n 'get', 'set', 'is', 'has', 'can', 'do', 'the', 'a', 'an', 'of', 'to', 'in',\n 'for', 'on', 'with', 'at', 'by', 'from', 'as', 'into', 'not', 'no', 'or',\n]);\n\nexport interface TokenizerOptions {\n /** Include stop-word tokens in output (default: false) */\n includeStopWords?: boolean;\n /** Include the full original name as an additional token (default: true) */\n includeOriginal?: boolean;\n /** Include file path segments as tokens (default: false) */\n includeFilePath?: boolean;\n}\n\nconst DEFAULT_OPTIONS: Required<TokenizerOptions> = {\n includeStopWords: false,\n includeOriginal: true,\n includeFilePath: false,\n};\n\nexport class SymbolTokenizer {\n private readonly options: Required<TokenizerOptions>;\n\n constructor(options?: TokenizerOptions) {\n this.options = { ...DEFAULT_OPTIONS, ...options };\n }\n\n /**\n * Tokenize a symbol name into searchable tokens.\n *\n * Examples:\n * \"getCoChangeMetrics\" → [\"get\", \"co\", \"change\", \"metrics\"] (or without stop words: [\"co\", \"change\", \"metrics\"])\n * \"SqliteStorageAdapter\" → [\"sqlite\", \"storage\", \"adapter\"]\n * \"i_storage_port\" → [\"i\", \"storage\", \"port\"]\n * \"BM25Scorer\" → [\"bm\", \"25\", \"scorer\"]\n * \"DB_PASSWORD\" → [\"db\", \"password\"]\n */\n tokenize(symbolName: string, filePath?: string): string[] {\n const splitTokens = SymbolTokenizer.splitName(symbolName);\n const lowered = splitTokens.map((t) => t.toLowerCase());\n\n const tokens: string[] = this.options.includeStopWords\n ? lowered\n : lowered.filter((t) => !STOP_WORDS.has(t));\n\n // Preserve original name as a token for exact matching\n if (this.options.includeOriginal) {\n const original = symbolName.toLowerCase();\n if (!tokens.includes(original)) {\n tokens.unshift(original);\n }\n }\n\n // Include file path segments\n if (this.options.includeFilePath && filePath) {\n const pathTokens = SymbolTokenizer.tokenizeFilePath(filePath);\n for (const pt of pathTokens) {\n if (!tokens.includes(pt)) {\n tokens.push(pt);\n }\n }\n }\n\n return tokens;\n }\n\n /**\n * Tokenize a search query. Queries use stop words and don't include originals.\n */\n tokenizeQuery(query: string): string[] {\n const words = query.trim().split(/\\s+/);\n const tokens: string[] = [];\n for (const word of words) {\n const split = SymbolTokenizer.splitName(word);\n for (const t of split) {\n const lowered = t.toLowerCase();\n if (lowered.length > 0 && !tokens.includes(lowered)) {\n tokens.push(lowered);\n }\n }\n }\n return tokens;\n }\n\n /**\n * Split a name into constituent words based on naming convention boundaries.\n *\n * Rules:\n * 1. Split on underscores and hyphens (snake_case, kebab-case)\n * 2. Split on camelCase/PascalCase boundaries (uppercase after lowercase)\n * 3. Split acronym boundaries (e.g., \"HTMLParser\" → [\"HTML\", \"Parser\"])\n * 4. Split on digit ↔ letter boundaries\n */\n static splitName(name: string): string[] {\n if (!name || name.length === 0) return [];\n\n // Step 1: Split on underscores, hyphens, dots, slashes\n const segments = name.split(/[_\\-./\\\\]+/).filter((s) => s.length > 0);\n\n const tokens: string[] = [];\n for (const segment of segments) {\n tokens.push(...SymbolTokenizer.splitCamelCase(segment));\n }\n\n return tokens.filter((t) => t.length > 0);\n }\n\n /**\n * Split a single segment on camelCase/PascalCase/digit boundaries.\n */\n private static splitCamelCase(segment: string): string[] {\n const tokens: string[] = [];\n let current = '';\n\n for (let i = 0; i < segment.length; i++) {\n const ch = segment[i]!;\n const prev = i > 0 ? segment[i - 1]! : '';\n\n // Boundary: letter → digit or digit → letter\n if (current.length > 0) {\n const prevIsDigit = isDigit(prev);\n const currIsDigit = isDigit(ch);\n if (prevIsDigit !== currIsDigit) {\n tokens.push(current);\n current = ch;\n continue;\n }\n }\n\n // Boundary: lowercase → uppercase (camelCase boundary)\n if (current.length > 0 && isLower(prev) && isUpper(ch)) {\n tokens.push(current);\n current = ch;\n continue;\n }\n\n // Acronym boundary: multiple uppercase followed by lowercase\n // \"HTMLParser\": H-T-M-L-P-a → when we hit 'a', current=\"HTMLP\"\n // We should split to \"HTML\" + \"Pa...\"\n if (current.length > 1 && isUpper(ch) === false && isUpper(prev) && !isDigit(ch)) {\n // prev is uppercase, current char is lowercase → split before prev\n const lastChar = current[current.length - 1]!;\n if (isUpper(lastChar)) {\n tokens.push(current.slice(0, -1));\n current = lastChar + ch;\n continue;\n }\n }\n\n current += ch;\n }\n\n if (current.length > 0) {\n tokens.push(current);\n }\n\n return tokens;\n }\n\n /**\n * Extract searchable tokens from a file path.\n * \"src/core/search/symbol-tokenizer.ts\" → [\"src\", \"core\", \"search\", \"symbol\", \"tokenizer\", \"ts\"]\n */\n static tokenizeFilePath(filePath: string): string[] {\n // Remove extension, split on separators\n const withoutExt = filePath.replace(/\\.[^.]+$/, '');\n const segments = withoutExt.split(/[/\\\\]+/);\n const tokens: string[] = [];\n for (const seg of segments) {\n const parts = seg.split(/[_\\-.]+/).filter((s) => s.length > 0);\n for (const p of parts) {\n const lowered = p.toLowerCase();\n if (lowered.length > 0 && !tokens.includes(lowered)) {\n tokens.push(lowered);\n }\n }\n }\n return tokens;\n }\n\n /** Check if a token is a stop word */\n static isStopWord(token: string): boolean {\n return STOP_WORDS.has(token.toLowerCase());\n }\n}\n\nfunction isUpper(ch: string): boolean {\n return ch >= 'A' && ch <= 'Z';\n}\n\nfunction isLower(ch: string): boolean {\n return ch >= 'a' && ch <= 'z';\n}\n\nfunction isDigit(ch: string): boolean {\n return ch >= '0' && ch <= '9';\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 { buildGraphFromJsonIndex, buildGraphFromStorage } 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';\n\nconst InputSchema = z.object({\n pattern: z.string().min(1),\n kind: z.enum(['function', 'class', 'interface', 'method', 'variable', 'type']).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) {\n const engine: ISearchPort = searchEngine ?? new SearchEngine();\n let lastFtsNodeCount = -1;\n\n const getGraph = () => {\n const jsonGraph = buildGraphFromJsonIndex(ctxoRoot);\n if (jsonGraph.nodeCount > 0) return jsonGraph;\n return buildGraphFromStorage(storage);\n };\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 = 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 payload = masking.mask(JSON.stringify(wrapResponse({\n totalMatches: ftsResults.length,\n results,\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(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 }\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 payload = masking.mask(JSON.stringify(wrapResponse({\n totalMatches: matches.length,\n results,\n })));\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 { 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 { buildGraphFromJsonIndex, buildGraphFromStorage } from './get-logic-slice.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\n\nconst 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 = () => {\n const jsonGraph = buildGraphFromJsonIndex(ctxoRoot);\n if (jsonGraph.nodeCount > 0) return jsonGraph;\n return buildGraphFromStorage(storage);\n };\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 = 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(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 { 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 { buildGraphFromJsonIndex, buildGraphFromStorage } from './get-logic-slice.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\nimport { filterByIntent } from '../../core/intent-filter.js';\n\nconst InputSchema = z.object({\n symbolId: z.string().min(1),\n edgeKinds: z.array(z.enum(['imports', 'calls', 'extends', 'implements', 'uses'])).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) {\n const getGraph = () => {\n const jsonGraph = buildGraphFromJsonIndex(ctxoRoot);\n if (jsonGraph.nodeCount > 0) return jsonGraph;\n return buildGraphFromStorage(storage);\n };\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 = getGraph();\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 const importers: Array<{\n symbolId: string;\n name: string;\n kind: string;\n file: string;\n edgeKind: string;\n depth: number;\n }> = [];\n\n if (!transitive) {\n // Direct importers only — deduplicate by symbolId, aggregate edgeKinds\n const reverseEdges = graph.getReverseEdges(symbolId);\n const seen = new Map<string, { node: typeof importers[0]; edgeKinds: string[] }>();\n for (const edge of reverseEdges) {\n if (edgeKinds && !edgeKinds.includes(edge.kind as 'imports' | 'calls' | 'extends' | 'implements' | 'uses')) 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 depth: 1,\n };\n seen.set(node.symbolId, { node: entry, edgeKinds: [edge.kind] });\n importers.push(entry);\n }\n }\n }\n } else {\n // BFS for transitive importers\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 if (current.depth >= maxDepth) continue;\n\n const reverseEdges = graph.getReverseEdges(current.id);\n for (const edge of reverseEdges) {\n if (edgeKinds && !edgeKinds.includes(edge.kind as 'imports' | 'calls' | 'extends' | 'implements' | 'uses')) 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 payload = masking.mask(JSON.stringify(wrapResponse({\n symbolId,\n importerCount: filtered.length,\n importers: filtered,\n })));\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 { 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 { buildGraphFromJsonIndex, buildGraphFromStorage } from './get-logic-slice.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\n\nconst 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 = () => {\n const jsonGraph = buildGraphFromJsonIndex(ctxoRoot);\n if (jsonGraph.nodeCount > 0) return jsonGraph;\n return buildGraphFromStorage(storage);\n };\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 = getGraph();\n\n if (symbolId) {\n return handleRooted(graph, symbolId, direction, masking, staleness, storage);\n }\n\n return handleFull(graph, masking, staleness, storage);\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: ReturnType<typeof getGraph>,\n symbolId: string,\n direction: 'ancestors' | 'descendants' | 'both',\n maskingPort: IMaskingPort,\n stalenessCheck: StalenessCheck | undefined,\n storagePort: IStoragePort,\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) => kind === 'extends' || kind === 'implements';\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(storagePort.listIndexedFiles());\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: ReturnType<typeof getGraph>,\n maskingPort: IMaskingPort,\n stalenessCheck: StalenessCheck | undefined,\n storagePort: IStoragePort,\n ) {\n const isHierarchyEdge = (kind: string) => kind === 'extends' || kind === 'implements';\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(storagePort.listIndexedFiles());\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 { buildGraphFromJsonIndex, buildGraphFromStorage } from './get-logic-slice.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\n\nconst InputSchema = z.object({\n limit: z.number().int().min(1).max(200).optional().default(25),\n kind: z.enum(['function', 'class', 'interface', 'method', 'variable', 'type']).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 = () => {\n const jsonGraph = buildGraphFromJsonIndex(ctxoRoot);\n if (jsonGraph.nodeCount > 0) return jsonGraph;\n return buildGraphFromStorage(storage);\n };\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 = 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(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 { SymbolGraph } from '../graph/symbol-graph.js';\n\nexport interface PageRankEntry {\n readonly symbolId: string;\n readonly name: string;\n readonly kind: string;\n readonly file: string;\n readonly score: number;\n readonly inDegree: number;\n readonly outDegree: number;\n}\n\nexport interface PageRankResult {\n readonly rankings: PageRankEntry[];\n readonly totalSymbols: number;\n readonly iterations: number;\n readonly converged: boolean;\n}\n\nexport interface PageRankOptions {\n readonly damping?: number;\n readonly maxIterations?: number;\n readonly tolerance?: number;\n readonly limit?: number;\n}\n\nconst DEFAULT_DAMPING = 0.85;\nconst DEFAULT_MAX_ITERATIONS = 100;\nconst DEFAULT_TOLERANCE = 1e-6;\nconst DEFAULT_LIMIT = 25;\n\nexport class PageRankCalculator {\n calculate(graph: SymbolGraph, options: PageRankOptions = {}): PageRankResult {\n const damping = options.damping ?? DEFAULT_DAMPING;\n const maxIterations = options.maxIterations ?? DEFAULT_MAX_ITERATIONS;\n const tolerance = options.tolerance ?? DEFAULT_TOLERANCE;\n const limit = options.limit ?? DEFAULT_LIMIT;\n\n const nodes = graph.allNodes();\n const n = nodes.length;\n\n if (n === 0) {\n return { rankings: [], totalSymbols: 0, iterations: 0, converged: true };\n }\n\n // Initialize scores uniformly\n const scores = new Map<string, number>();\n const initialScore = 1 / n;\n for (const node of nodes) {\n scores.set(node.symbolId, initialScore);\n }\n\n // Precompute out-degree for each node\n const outDegree = new Map<string, number>();\n for (const node of nodes) {\n outDegree.set(node.symbolId, graph.getForwardEdges(node.symbolId).length);\n }\n\n // Iterative PageRank\n // Edge direction: A->B means \"A depends on B\" (A imports/calls/uses B)\n // PageRank: B is important if many important nodes link to B\n // Score distribution: each node distributes its score via forward edges to dependencies\n // So we accumulate via reverse edges: for each node, sum score from nodes that point to it\n let iterations = 0;\n let converged = false;\n\n while (iterations < maxIterations) {\n const newScores = new Map<string, number>();\n const base = (1 - damping) / n;\n\n // Handle dangling nodes (no outgoing edges) — distribute their score evenly\n let danglingSum = 0;\n for (const node of nodes) {\n if ((outDegree.get(node.symbolId) ?? 0) === 0) {\n danglingSum += scores.get(node.symbolId) ?? 0;\n }\n }\n const danglingContrib = damping * danglingSum / n;\n\n for (const node of nodes) {\n let incomingScore = 0;\n\n // Sum contributions from all nodes that have a forward edge TO this node\n // (i.e., reverse edges of this node)\n const reverseEdges = graph.getReverseEdges(node.symbolId);\n const contributors = new Set<string>();\n for (const edge of reverseEdges) {\n if (contributors.has(edge.from)) continue; // deduplicate multi-edges\n contributors.add(edge.from);\n const fromScore = scores.get(edge.from) ?? 0;\n const fromOut = outDegree.get(edge.from) ?? 1;\n incomingScore += fromScore / fromOut;\n }\n\n newScores.set(node.symbolId, base + damping * incomingScore + danglingContrib);\n }\n\n // Check convergence\n let maxDelta = 0;\n for (const node of nodes) {\n const delta = Math.abs((newScores.get(node.symbolId) ?? 0) - (scores.get(node.symbolId) ?? 0));\n if (delta > maxDelta) maxDelta = delta;\n }\n\n // Update scores\n for (const [id, score] of newScores) {\n scores.set(id, score);\n }\n\n iterations++;\n\n if (maxDelta < tolerance) {\n converged = true;\n break;\n }\n }\n\n // Build ranked results\n const entries: PageRankEntry[] = nodes.map((node) => ({\n symbolId: node.symbolId,\n name: node.name,\n kind: node.kind,\n file: node.symbolId.split('::')[0] ?? '',\n score: Math.round((scores.get(node.symbolId) ?? 0) * 1_000_000) / 1_000_000,\n inDegree: graph.getReverseEdges(node.symbolId).length,\n outDegree: outDegree.get(node.symbolId) ?? 0,\n }));\n\n // Sort by score descending\n entries.sort((a, b) => b.score - a.score);\n\n return {\n rankings: entries.slice(0, limit),\n totalSymbols: n,\n iterations,\n converged,\n };\n }\n}\n","import { z } from 'zod';\nimport { readFileSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\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 { buildGraphFromJsonIndex, buildGraphFromStorage } from './get-logic-slice.js';\nimport { BlastRadiusCalculator } from '../../core/blast-radius/blast-radius-calculator.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\nimport { loadCoChangeMap } from '../../core/co-change/co-change-analyzer.js';\nimport type { CoChangeMatrix, CoChangeEntry } from '../../core/types.js';\n\nconst 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 loadCoChanges(ctxoRoot: string): Map<string, CoChangeEntry[]> | undefined {\n const path = join(ctxoRoot, 'index', 'co-changes.json');\n if (!existsSync(path)) return undefined;\n try {\n const matrix: CoChangeMatrix = JSON.parse(readFileSync(path, 'utf-8'));\n return loadCoChangeMap(matrix);\n } catch {\n return undefined;\n }\n}\n\nexport function handleGetPrImpact(\n storage: IStoragePort,\n git: IGitPort,\n masking: IMaskingPort,\n staleness?: StalenessCheck,\n ctxoRoot = '.ctxo',\n) {\n const calculator = new BlastRadiusCalculator();\n const getGraph = () => {\n const jsonGraph = buildGraphFromJsonIndex(ctxoRoot);\n if (jsonGraph.nodeCount > 0) return jsonGraph;\n return buildGraphFromStorage(storage);\n };\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 = getGraph();\n const coChangeMap = loadCoChanges(ctxoRoot);\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 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 payload = masking.mask(JSON.stringify(wrapResponse({\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\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"],"mappings":";;;;;;;;;;;;;;;AAAA,SAAS,iBAAiB;AAC1B,SAAS,4BAA4B;;;ACDrC,SAAS,oBAA4E;AACrF,SAAS,qCAAqC;AAC9C,SAAS,kBAAkB;AAI3B,IAAM,MAAM,aAAa,WAAW;AAgBpC,eAAsB,mBACpB,eACA,MACiC;AAEjC,QAAM,WAAW,oBAAI,IAA6E;AAElG,QAAM,aAAa,aAAa,OAAO,KAAsB,QAAwB;AAEnF,QAAI,UAAU,+BAA+B,GAAG;AAChD,QAAI,UAAU,gCAAgC,4BAA4B;AAC1E,QAAI,UAAU,gCAAgC,sCAAsC;AACpF,QAAI,UAAU,iCAAiC,gBAAgB;AAE/D,QAAI,IAAI,WAAW,WAAW;AAC5B,UAAI,UAAU,GAAG;AACjB,UAAI,IAAI;AACR;AAAA,IACF;AAEA,UAAM,YAAY,IAAI,QAAQ,gBAAgB;AAG9C,QAAI,aAAa,SAAS,IAAI,SAAS,GAAG;AACxC,UAAI;AACF,cAAM,SAAS,IAAI,SAAS,EAAG,UAAU,cAAc,KAAK,GAAG;AAAA,MACjE,SAAS,KAAK;AACZ,YAAI,MAAM,qBAAsB,IAAc,OAAO;AACrD,YAAI,CAAC,IAAI,aAAa;AAAE,cAAI,UAAU,GAAG;AAAG,cAAI,IAAI;AAAA,QAAG;AAAA,MACzD;AACA;AAAA,IACF;AAGA,QAAI,aAAa,CAAC,SAAS,IAAI,SAAS,GAAG;AACzC,UAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,UAAI,IAAI,KAAK,UAAU,EAAE,SAAS,OAAO,OAAO,EAAE,MAAM,QAAQ,SAAS,oBAAoB,GAAG,IAAI,KAAK,CAAC,CAAC;AAC3G;AAAA,IACF;AAGA,QAAI;AACF,YAAM,SAAS,MAAM,cAAc;AACnC,YAAM,YAAY,IAAI,8BAA8B;AAAA,QAClD,oBAAoB,MAAM,WAAW;AAAA,MACvC,CAAC;AAED,gBAAU,UAAU,MAAM;AACxB,YAAI,UAAU,WAAW;AACvB,mBAAS,OAAO,UAAU,SAAS;AACnC,cAAI,KAAK,sBAAsB,UAAU,SAAS;AAAA,QACpD;AAAA,MACF;AAEA,YAAM,OAAO,QAAQ,SAAS;AAC9B,YAAM,UAAU,cAAc,KAAK,GAAG;AAEtC,UAAI,UAAU,WAAW;AACvB,iBAAS,IAAI,UAAU,WAAW,EAAE,WAAW,OAAO,CAAC;AACvD,YAAI,KAAK,+BAA+B,UAAU,WAAW,SAAS,IAAI;AAAA,MAC5E;AAAA,IACF,SAAS,KAAK;AACZ,UAAI,MAAM,8BAA+B,IAAc,OAAO;AAC9D,UAAI,CAAC,IAAI,aAAa;AAAE,YAAI,UAAU,GAAG;AAAG,YAAI,IAAI;AAAA,MAAG;AAAA,IACzD;AAAA,EACF,CAAC;AAED,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,eAAW,GAAG,SAAS,MAAM;AAC7B,eAAW,OAAO,MAAM,MAAM;AAC5B,UAAI,KAAK,oDAAoD,IAAI;AACjE,cAAQ,OAAO,MAAM,sDAAsD,IAAI;AAAA,CAAI;AACnF,cAAQ,EAAE,WAAW,CAAC;AAAA,IACxB,CAAC;AAAA,EACH,CAAC;AACH;;;AD9FA,SAAS,KAAAA,WAAS;AAClB,SAAS,cAAAC,aAAY,gBAAAC,qBAAoB;AACzC,SAAS,QAAAC,aAAY;;;AELrB,IAAM,mBAA4D;AAAA;AAAA,EAEhE,EAAE,OAAO,qBAAqB,OAAO,UAAU;AAAA;AAAA,EAE/C,EAAE,OAAO,2FAA2F,OAAO,aAAa;AAAA;AAAA,EAExH,EAAE,OAAO,kEAAkE,OAAO,MAAM;AAAA;AAAA,EAExF,EAAE,OAAO,iHAAiH,OAAO,aAAa;AAAA;AAAA,EAE9I,EAAE,OAAO,6DAA6D,OAAO,eAAe;AAAA;AAAA,EAE5F,EAAE,OAAO,kEAAkE,OAAO,aAAa;AAAA;AAAA,EAE/F,EAAE,OAAM,0CAA0C,OAAO,UAAU;AAAA;AAAA,EAEnE,EAAE,OAAO,mCAAmC,OAAO,YAAY;AACjE;AAQO,IAAM,kBAAN,MAAM,iBAAgB;AAAA,EACV;AAAA,EAEjB,YAAY,qBAA8D,CAAC,GAAG;AAE5E,SAAK,WAAW,CAAC,GAAG,kBAAkB,GAAG,kBAAkB,EAAE,IAAI,CAAC,EAAE,OAAO,MAAM,OAAO;AAAA,MACtF,OAAO,IAAI,OAAO,MAAM,QAAQ,MAAM,KAAK;AAAA,MAC3C;AAAA,IACF,EAAE;AAAA,EACJ;AAAA,EAEA,OAAO,WAAW,gBAAyD;AACzE,UAAM,aAAsD,CAAC;AAE7D,eAAW,EAAE,SAAS,OAAO,MAAM,KAAK,gBAAgB;AACtD,UAAI;AACF,mBAAW,KAAK,EAAE,OAAO,IAAI,OAAO,SAAS,SAAS,GAAG,GAAG,MAAM,CAAC;AAAA,MACrE,SAAS,KAAK;AACZ,gBAAQ,MAAM,yCAAyC,OAAO,MAAO,IAAc,OAAO,EAAE;AAAA,MAC9F;AAAA,IACF;AAEA,WAAO,IAAI,iBAAgB,UAAU;AAAA,EACvC;AAAA,EAEA,KAAK,MAAsB;AACzB,QAAI,KAAK,WAAW,EAAG,QAAO;AAE9B,QAAI,SAAS;AACb,eAAW,EAAE,OAAO,MAAM,KAAK,KAAK,UAAU;AAC5C,eAAS,OAAO,QAAQ,OAAO,aAAa,KAAK,GAAG;AAAA,IACtD;AACA,WAAO;AAAA,EACT;AACF;;;AC3DA,SAAS,SAAS;;;ACEX,IAAM,cAAN,MAAkB;AAAA,EACN,QAAQ,oBAAI,IAAwB;AAAA,EACpC,qBAAqB,oBAAI,IAAwB;AAAA,EACjD,eAAe,oBAAI,IAAyB;AAAA,EAC5C,eAAe,oBAAI,IAAyB;AAAA,EACrD,UAAU,oBAAI,IAAY;AAAA,EAElC,QAAQ,MAAwB;AAC9B,SAAK,MAAM,IAAI,KAAK,UAAU,IAAI;AAElC,UAAM,CAAC,IAAI,EAAE,IAAI,KAAK,SAAS,MAAM,IAAI;AACzC,QAAI,OAAO,UAAa,OAAO,QAAW;AACxC,WAAK,mBAAmB,IAAI,GAAG,EAAE,KAAK,EAAE,IAAI,IAAI;AAAA,IAClD;AAAA,EACF;AAAA,EAEA,QAAQ,MAAuB;AAE7B,UAAM,eAAe,KAAK,cAAc,KAAK,IAAI;AACjD,UAAM,aAAa,KAAK,cAAc,KAAK,EAAE;AAC7C,UAAM,eAA0B,EAAE,MAAM,cAAc,IAAI,YAAY,MAAM,KAAK,KAAK;AAEtF,UAAM,UAAU,GAAG,aAAa,IAAI,IAAI,aAAa,EAAE,IAAI,aAAa,IAAI;AAC5E,QAAI,KAAK,QAAQ,IAAI,OAAO,EAAG;AAC/B,SAAK,QAAQ,IAAI,OAAO;AAExB,UAAM,UAAU,KAAK,aAAa,IAAI,aAAa,IAAI,KAAK,CAAC;AAC7D,YAAQ,KAAK,YAAY;AACzB,SAAK,aAAa,IAAI,aAAa,MAAM,OAAO;AAEhD,UAAM,UAAU,KAAK,aAAa,IAAI,aAAa,EAAE,KAAK,CAAC;AAC3D,YAAQ,KAAK,YAAY;AACzB,SAAK,aAAa,IAAI,aAAa,IAAI,OAAO;AAAA,EAChD;AAAA,EAEA,QAAQ,UAA0C;AAChD,WAAO,KAAK,MAAM,IAAI,QAAQ,KAAK,KAAK,iBAAiB,QAAQ;AAAA,EACnE;AAAA,EAEQ,cAAc,IAAoB;AACxC,QAAI,KAAK,MAAM,IAAI,EAAE,EAAG,QAAO;AAC/B,UAAM,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,IAAI;AAC9B,QAAI,OAAO,UAAa,OAAO,QAAW;AACxC,YAAM,WAAW,GAAG,EAAE,KAAK,EAAE;AAC7B,YAAM,QAAQ,KAAK,mBAAmB,IAAI,QAAQ;AAClD,UAAI,MAAO,QAAO,MAAM;AAGxB,YAAM,SAAS,GAAG,QAAQ,SAAS,KAAK;AACxC,UAAI,WAAW,IAAI;AACjB,cAAM,SAAS,GAAG,MAAM,KAAK,EAAE;AAC/B,cAAM,WAAW,KAAK,mBAAmB,IAAI,MAAM;AACnD,YAAI,SAAU,QAAO,SAAS;AAAA,MAChC;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,iBAAiB,IAAoC;AAC3D,UAAM,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,IAAI;AAC9B,QAAI,OAAO,UAAa,OAAO,QAAW;AACxC,YAAM,QAAQ,KAAK,mBAAmB,IAAI,GAAG,EAAE,KAAK,EAAE,EAAE;AACxD,UAAI,MAAO,QAAO;AAGlB,YAAM,SAAS,GAAG,QAAQ,SAAS,KAAK;AACxC,UAAI,WAAW,IAAI;AACjB,eAAO,KAAK,mBAAmB,IAAI,GAAG,MAAM,KAAK,EAAE,EAAE;AAAA,MACvD;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,gBAAgB,UAA+B;AAC7C,WAAO,KAAK,aAAa,IAAI,QAAQ,KAAK,CAAC;AAAA,EAC7C;AAAA,EAEA,gBAAgB,UAA+B;AAC7C,WAAO,KAAK,aAAa,IAAI,QAAQ,KAAK,CAAC;AAAA,EAC7C;AAAA,EAEA,QAAQ,UAA2B;AACjC,WAAO,KAAK,MAAM,IAAI,QAAQ,KAAK,KAAK,iBAAiB,QAAQ,MAAM;AAAA,EACzE;AAAA,EAEA,IAAI,YAAoB;AACtB,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA,EAEA,IAAI,YAAoB;AACtB,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EAEA,WAAyB;AACvB,WAAO,CAAC,GAAG,KAAK,MAAM,OAAO,CAAC;AAAA,EAChC;AAAA,EAEA,WAAwB;AACtB,UAAM,QAAqB,CAAC;AAC5B,eAAW,QAAQ,KAAK,aAAa,OAAO,GAAG;AAC7C,YAAM,KAAK,GAAG,IAAI;AAAA,IACpB;AACA,WAAO;AAAA,EACT;AACF;;;ACvGO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,cACE,OACA,UACA,WAAmB,UACW;AAC9B,UAAM,OAAO,MAAM,QAAQ,QAAQ;AACnC,QAAI,CAAC,KAAM,QAAO;AAElB,UAAM,UAAU,oBAAI,IAAY,CAAC,QAAQ,CAAC;AAC1C,UAAM,eAA6B,CAAC;AACpC,UAAM,iBAA8B,CAAC;AAGrC,UAAM,QAA8C,CAAC,EAAE,IAAI,UAAU,OAAO,EAAE,CAAC;AAE/E,WAAO,MAAM,SAAS,GAAG;AACvB,YAAM,UAAU,MAAM,MAAM;AAE5B,UAAI,QAAQ,SAAS,SAAU;AAE/B,YAAM,QAAQ,MAAM,gBAAgB,QAAQ,EAAE;AAC9C,iBAAW,QAAQ,OAAO;AACxB,cAAM,UAAU,MAAM,QAAQ,KAAK,EAAE;AAErC,YAAI,CAAC,QAAS;AAEd,uBAAe,KAAK,IAAI;AAExB,YAAI,QAAQ,IAAI,KAAK,EAAE,EAAG;AAC1B,gBAAQ,IAAI,KAAK,EAAE;AAEnB,qBAAa,KAAK,OAAO;AACzB,cAAM,KAAK,EAAE,IAAI,KAAK,IAAI,OAAO,QAAQ,QAAQ,EAAE,CAAC;AAAA,MACtD;AAAA,IACF;AAEA,WAAO,EAAE,MAAM,cAAc,OAAO,eAAe;AAAA,EACrD;AACF;;;AClCA,IAAM,eAAe;AACrB,IAAM,kBAAkB;AAEjB,IAAM,kBAAN,MAAsB;AAAA,EAC3B,OAAO,OAAyB,OAAoC;AAClE,YAAQ,OAAO;AAAA,MACb,KAAK;AACH,eAAO,KAAK,SAAS,KAAK;AAAA,MAC5B,KAAK;AACH,eAAO,KAAK,SAAS,KAAK;AAAA,MAC5B,KAAK;AACH,eAAO,KAAK,SAAS,KAAK;AAAA,MAC5B,KAAK;AACH,eAAO,KAAK,SAAS,KAAK;AAAA,IAC9B;AAAA,EACF;AAAA,EAEQ,SAAS,OAAyC;AACxD,UAAM,OAAO,MAAM;AACnB,UAAM,YAAY,KAAK,UAAU,KAAK,YAAY;AAElD,UAAM,cAA0B,YAAY,eACxC,EAAE,GAAG,MAAM,SAAS,KAAK,YAAY,eAAe,EAAE,IACtD;AAEJ,WAAO;AAAA,MACL,MAAM;AAAA,MACN,cAAc,CAAC;AAAA,MACf,OAAO,CAAC;AAAA,MACR,OAAO;AAAA,MACP,kBAAkB;AAAA,MAClB,GAAI,YAAY,eAAe,EAAE,YAAY,EAAE,WAAW,MAAe,QAAQ,wBAAiC,EAAE,IAAI,CAAC;AAAA,IAC3H;AAAA,EACF;AAAA,EAEQ,SAAS,OAAyC;AAExD,UAAM,cAAc,MAAM,MAAM,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM,KAAK,QAAQ;AAC5E,UAAM,eAAe,IAAI,IAAI,YAAY,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AACzD,UAAM,aAAa,MAAM,aAAa,OAAO,CAAC,MAAM,aAAa,IAAI,EAAE,QAAQ,CAAC;AAEhF,WAAO;AAAA,MACL,MAAM,MAAM;AAAA,MACZ,cAAc;AAAA,MACd,OAAO;AAAA,MACP,OAAO;AAAA,MACP,kBAAkB;AAAA,IACpB;AAAA,EACF;AAAA,EAEQ,SAAS,OAAyC;AACxD,WAAO;AAAA,MACL,MAAM,MAAM;AAAA,MACZ,cAAc,MAAM;AAAA,MACpB,OAAO,MAAM;AAAA,MACb,OAAO;AAAA,MACP,kBAAkB;AAAA,IACpB;AAAA,EACF;AAAA,EAEQ,SAAS,OAAyC;AAExD,UAAM,kBAAkB,KAAK,eAAe,KAAK;AAEjD,QAAI,kBAAkB,iBAAiB;AAErC,YAAM,YAAY,KAAK,sBAAsB,OAAO,eAAe;AACnE,aAAO;AAAA,QACL,GAAG;AAAA,QACH,OAAO;AAAA,QACP,kBAAkB;AAAA,QAClB,YAAY;AAAA,UACV,WAAW;AAAA,UACX,QAAQ;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,MAAM,MAAM;AAAA,MACZ,cAAc,MAAM;AAAA,MACpB,OAAO,MAAM;AAAA,MACb,OAAO;AAAA,MACP,kBAAkB;AAAA,IACpB;AAAA,EACF;AAAA,EAEQ,eAAe,OAAiC;AAEtD,QAAI,QAAQ,KAAK,mBAAmB,MAAM,IAAI;AAC9C,eAAW,OAAO,MAAM,cAAc;AACpC,eAAS,KAAK,mBAAmB,GAAG;AAAA,IACtC;AACA,eAAW,QAAQ,MAAM,OAAO;AAC9B,eAAU,KAAK,KAAK,SAAS,KAAK,GAAG,SAAS,KAAK,KAAK,SAAS;AAAA,IACnE;AACA,WAAO,KAAK,KAAK,QAAQ,CAAC;AAAA,EAC5B;AAAA,EAEQ,mBAAmB,MAA0B;AAEnD,QAAI,KAAK,gBAAgB,UAAa,KAAK,cAAc,QAAW;AAClE,aAAO,KAAK,YAAY,KAAK;AAAA,IAC/B;AACA,YAAQ,KAAK,UAAU,KAAK,YAAY,KAAK;AAAA,EAC/C;AAAA,EAEQ,sBACN,OACA,QACsE;AACtE,QAAI,gBAAgB,KAAK,mBAAmB,MAAM,IAAI,IAAI;AAC1D,UAAM,OAAqB,CAAC;AAC5B,UAAM,cAAc,oBAAI,IAAY,CAAC,MAAM,KAAK,QAAQ,CAAC;AAEzD,eAAW,OAAO,MAAM,cAAc;AACpC,YAAM,YAAY,KAAK,mBAAmB,GAAG,IAAI;AACjD,UAAI,gBAAgB,YAAY,OAAQ;AACxC,uBAAiB;AACjB,WAAK,KAAK,GAAG;AACb,kBAAY,IAAI,IAAI,QAAQ;AAAA,IAC9B;AAEA,UAAM,QAAQ,MAAM,MAAM;AAAA,MACxB,CAAC,MAAM,YAAY,IAAI,EAAE,IAAI,KAAK,YAAY,IAAI,EAAE,EAAE;AAAA,IACxD;AAEA,WAAO,EAAE,MAAM,MAAM,MAAM,cAAc,MAAM,MAAM;AAAA,EACvD;AACF;;;AClIA,IAAM,oBAAoB;AAc1B,IAAM,qBAA6C;AAAA,EACjD,iBAAiB;AAAA,EACjB,WAAW;AAAA,EACX,aAAa;AAAA,EACb,eAAe;AAAA,EACf,SAAS;AAAA,EACT,UAAU;AAAA,EACV,SAAS;AAAA,EACT,aAAa;AAAA,EACb,aAAa;AAAA,EACb,WAAW;AAAA,EACX,OAAO;AACT;AAEA,SAAS,eAAuB;AAC9B,QAAM,MAAM,QAAQ,IAAI,qBAAqB;AAC7C,MAAI,KAAK;AACP,UAAM,IAAI,SAAS,KAAK,EAAE;AAC1B,QAAI,CAAC,MAAM,CAAC,KAAK,IAAI,EAAG,QAAO;AAAA,EACjC;AACA,SAAO;AACT;AAKA,SAAS,qBAAqB,MAAuE;AACnG,MAAI,OAA+C;AACnD,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC/C,QAAI,MAAM,QAAQ,KAAK,KAAK,OAAO,oBAAoB;AACrD,UAAI,CAAC,QAAQ,MAAM,SAAS,KAAK,IAAI,QAAQ;AAC3C,eAAO,EAAE,KAAK,KAAK,MAAM;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAQO,SAAS,aAAa,MAAwD;AACnF,QAAM,YAAY,aAAa;AAC/B,QAAM,WAAW,KAAK,UAAU,IAAI;AACpC,QAAM,aAAa,OAAO,WAAW,UAAU,OAAO;AAEtD,QAAM,cAAc,qBAAqB,IAAI;AAC7C,QAAM,aAAa,cAAc,YAAY,IAAI,SAAS;AAG1D,MAAI,cAAc,WAAW;AAC3B,WAAO;AAAA,MACL,GAAG;AAAA,MACH,OAAO;AAAA,QACL;AAAA,QACA,eAAe;AAAA,QACf,WAAW;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,MAAI,CAAC,eAAe,YAAY,IAAI,UAAU,GAAG;AAE/C,WAAO;AAAA,MACL,GAAG;AAAA,MACH,OAAO;AAAA,QACL;AAAA,QACA,eAAe;AAAA,QACf,WAAW;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,MAAI,KAAK;AACT,MAAI,KAAK,YAAY,IAAI;AAEzB,SAAO,KAAK,IAAI;AACd,UAAM,MAAM,KAAK,MAAM,KAAK,MAAM,CAAC;AACnC,UAAM,QAAQ;AAAA,MACZ,GAAG;AAAA,MACH,CAAC,YAAY,GAAG,GAAG,YAAY,IAAI,MAAM,GAAG,GAAG;AAAA,MAC/C,OAAO;AAAA,QACL;AAAA,QACA,eAAe;AAAA,QACf,WAAW;AAAA,QACX;AAAA,QACA,MAAM,mBAAmB,YAAY,GAAG;AAAA,MAC1C;AAAA,IACF;AACA,UAAM,OAAO,OAAO,WAAW,KAAK,UAAU,KAAK,GAAG,OAAO;AAC7D,QAAI,QAAQ,WAAW;AACrB,WAAK;AAAA,IACP,OAAO;AACL,WAAK,MAAM;AAAA,IACb;AAAA,EACF;AAEA,QAAM,OAAO,mBAAmB,YAAY,GAAG;AAE/C,SAAO;AAAA,IACL,GAAG;AAAA,IACH,CAAC,YAAY,GAAG,GAAG,YAAY,IAAI,MAAM,GAAG,EAAE;AAAA,IAC9C,OAAO;AAAA,MACL;AAAA,MACA,eAAe;AAAA,MACf,WAAW;AAAA,MACX;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;AC3HA,SAAS,gBAAgB,QAA0B;AACjD,SAAO,OACJ,YAAY,EACZ,MAAM,KAAK,EACX,OAAO,OAAK,EAAE,UAAU,CAAC;AAC9B;AAKA,SAAS,WAAW,UAAoB,QAA2B;AACjE,QAAM,QAAQ,OAAO,IAAI,OAAK,EAAE,YAAY,CAAC;AAC7C,SAAO,SAAS,KAAK,QAAM,MAAM,KAAK,OAAK,EAAE,SAAS,EAAE,CAAC,CAAC;AAC5D;AAMA,SAAS,wBAAwB,OAA0C;AACzE,QAAM,UAAoB,CAAC;AAC3B,aAAW,OAAO,CAAC,YAAY,QAAQ,QAAQ,QAAQ,YAAY,UAAU,YAAY,GAAG;AAC1F,UAAM,IAAI,MAAM,GAAG;AACnB,QAAI,OAAO,MAAM,SAAU,SAAQ,KAAK,CAAC;AAAA,EAC3C;AACA,QAAM,YAAY,MAAM,WAAW;AACnC,MAAI,MAAM,QAAQ,SAAS,GAAG;AAC5B,eAAW,MAAM,WAAW;AAC1B,UAAI,OAAO,OAAO,SAAU,SAAQ,KAAK,EAAE;AAAA,IAC7C;AAAA,EACF;AACA,SAAO;AACT;AAUO,SAAS,eACd,OACA,QACK;AACL,MAAI,CAAC,UAAU,OAAO,KAAK,EAAE,WAAW,EAAG,QAAO;AAElD,QAAM,WAAW,gBAAgB,MAAM;AACvC,MAAI,SAAS,WAAW,EAAG,QAAO;AAElC,SAAO,MAAM,OAAO,UAAQ;AAC1B,UAAM,UAAU,wBAAwB,IAAI;AAC5C,WAAO,WAAW,UAAU,OAAO;AAAA,EACrC,CAAC;AACH;;;AL3DA,IAAM,cAAc,EAAE,OAAO;AAAA,EAC3B,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACrC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,SAAS;AAAA,EAC/C,OAAO,kBAAkB,SAAS,EAAE,QAAQ,CAAC;AAAA,EAC7C,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,6EAA6E;AACtH,CAAC,EAAE;AAAA,EACD,CAAC,SAAS,KAAK,YAAa,KAAK,aAAa,KAAK,UAAU,SAAS;AAAA,EACtE,EAAE,SAAS,gDAAgD;AAC7D;AAeO,SAAS,sBAAsB,SAAoC;AACxE,QAAM,QAAQ,IAAI,YAAY;AAC9B,aAAW,OAAO,QAAQ,cAAc,GAAG;AACzC,UAAM,QAAQ,GAAG;AAAA,EACnB;AACA,aAAW,QAAQ,QAAQ,YAAY,GAAG;AACxC,UAAM,QAAQ,IAAI;AAAA,EACpB;AACA,SAAO;AACT;AAMO,SAAS,wBAAwB,UAA+B;AACrE,QAAM,SAAS,IAAI,gBAAgB,QAAQ;AAC3C,QAAM,UAAU,OAAO,QAAQ;AAE/B,QAAM,QAAQ,IAAI,YAAY;AAE9B,aAAW,aAAa,SAAS;AAC/B,eAAW,OAAO,UAAU,SAAS;AACnC,YAAM,QAAQ,GAAG;AAAA,IACnB;AAAA,EACF;AAEA,aAAW,aAAa,SAAS;AAC/B,eAAW,QAAQ,UAAU,OAAO;AAClC,YAAM,QAAQ,IAAI;AAAA,IACpB;AAAA,EACF;AACA,SAAO;AACT;AAMO,SAAS,oBACd,SACA,SACA,WACA,WAAW,SACX;AACA,QAAM,QAAQ,IAAI,gBAAgB;AAClC,QAAM,YAAY,IAAI,gBAAgB;AAItC,QAAM,WAAW,MAAM;AACrB,UAAM,YAAY,wBAAwB,QAAQ;AAClD,QAAI,UAAU,YAAY,EAAG,QAAO;AACpC,WAAO,sBAAsB,OAAO;AAAA,EACtC;AAEA,QAAM,UAAU,CAAC,SAAkC;AACjD,QAAI;AACF,YAAM,SAAS,YAAY,UAAU,IAAI;AACzC,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAS,OAAO,MAAM,QAAQ,CAAC,EAAE,CAAC;AAAA,QAC3G;AAAA,MACF;AAEA,YAAM,EAAE,UAAU,WAAW,OAAO,OAAO,IAAI,OAAO;AACtD,YAAM,MAAM,cAAc,WAAW,CAAC,QAAQ,IAAI,CAAC;AAEnD,YAAM,QAAQ,SAAS;AAGvB,YAAM,UAAU,CAAC;AACjB,iBAAW,MAAM,KAAK;AACpB,cAAM,QAAQ,MAAM,cAAc,OAAO,EAAE;AAC3C,YAAI,OAAO;AACT,gBAAM,YAAY,UAAU,OAAO,OAAO,KAAK;AAE/C,cAAI,UAAU,MAAM,QAAQ,UAAU,cAAc,CAAC,GAAG;AACtD,sBAAU,cAAc,IAAI;AAAA,cAC1B,UAAU,cAAc;AAAA,cACxB;AAAA,YACF;AAAA,UACF;AACA,kBAAQ,KAAK,SAAS;AAAA,QACxB,OAAO;AACL,kBAAQ,KAAK,EAAE,OAAO,OAAO,UAAU,IAAI,MAAM,sCAAsC,CAAC;AAAA,QAC1F;AAAA,MACF;AAGA,YAAM,eAAe,IAAI,WAAW,IAAI,QAAQ,CAAC,IAAI,EAAE,OAAO,MAAM,QAAQ;AAG5E,YAAM,UAAU,QAAQ,KAAK,KAAK,UAAU,aAAa,YAAuC,CAAC,CAAC;AAGlG,YAAM,UAAiD,CAAC;AACxD,UAAI,WAAW;AACb,cAAM,UAAU,UAAU,MAAM,QAAQ,iBAAiB,CAAC;AAC1D,YAAI,SAAS;AACX,kBAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,gBAAM,QAAQ,OAAO,GAAG,CAAC;AAAA,QAC9D;AAAA,MACF;AACA,cAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC;AAE5C,aAAO,EAAE,QAAQ;AAAA,IACnB,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAU,IAAc,QAAQ,CAAC,EAAE,CAAC;AAAA,MAC7G;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;AMpJA,SAAS,KAAAC,UAAS;AASlB,IAAMC,eAAcC,GAAE,OAAO;AAAA,EAC3B,UAAUA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC1B,YAAYA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS;AAC/C,CAAC;AAEM,SAAS,oBACd,SACA,KACA,SACA,WACA,WAAW,SACX;AACA,QAAM,iBAAiB,IAAI,eAAe;AAC1C,QAAM,cAAc,IAAI,gBAAgB,QAAQ;AAEhD,SAAO,OAAO,SAAkC;AAC9C,QAAI;AACF,YAAM,SAASD,aAAY,UAAU,IAAI;AACzC,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAS,OAAO,MAAM,QAAQ,CAAC,EAAE,CAAC;AAAA,QAC3G;AAAA,MACF;AAEA,YAAM,EAAE,UAAU,WAAW,IAAI,OAAO;AAExC,YAAM,SAAS,QAAQ,cAAc,QAAQ;AAC7C,UAAI,CAAC,QAAQ;AACX,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,OAAO,MAAM,kEAAkE,CAAC,EAAE,CAAC;AAAA,QACtJ;AAAA,MACF;AAEA,YAAM,WAAW,SAAS,MAAM,IAAI,EAAE,CAAC;AAGvC,YAAM,UAAU,YAAY,QAAQ;AACpC,YAAM,YAAY,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ;AAEzD,UAAI;AACJ,UAAI;AAEJ,UAAI,aAAa,UAAU,OAAO,SAAS,GAAG;AAC5C,wBAAgB,UAAU;AAC1B,uBAAe,UAAU;AAAA,MAC3B,OAAO;AAEL,cAAM,UAAU,MAAM,IAAI,iBAAiB,QAAQ;AACnD,wBAAgB,QAAQ,IAAI,CAAC,OAAO;AAAA,UAClC,MAAM,EAAE;AAAA,UACR,SAAS,EAAE;AAAA,UACX,MAAM,EAAE;AAAA,UACR,MAAM;AAAA,QACR,EAAE;AACF,uBAAe,eAAe,OAAO,OAAO;AAAA,MAC9C;AAGA,YAAM,iBAAiB,aAAa,cAAc,MAAM,GAAG,UAAU,IAAI;AAIzE,YAAM,kBAA2C;AAAA,QAC/C,eAAe;AAAA,QACf,qBAAqB;AAAA,MACvB;AAEA,UAAI,aAAa,SAAS,GAAG;AAC3B,wBAAgB,eAAe;AAAA,MACjC;AAEA,YAAM,UAAU,QAAQ,KAAK,KAAK,UAAU,eAAe,CAAC;AAE5D,YAAM,UAAiD,CAAC;AACxD,UAAI,WAAW;AACb,cAAM,UAAU,UAAU,MAAM,QAAQ,iBAAiB,CAAC;AAC1D,YAAI,QAAS,SAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,gBAAM,QAAQ,OAAO,GAAG,CAAC;AAAA,MAC3E;AACA,cAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC;AAE5C,aAAO,EAAE,QAAQ;AAAA,IACnB,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAU,IAAc,QAAQ,CAAC,EAAE,CAAC;AAAA,MAC7G;AAAA,IACF;AAAA,EACF;AACF;;;AChGA,SAAS,KAAAE,UAAS;;;ACAX,IAAM,gBAAN,MAAoB;AAAA,EACzB,UAAU,aAAqB,gBAAgC;AAC7D,QAAI,kBAAkB,EAAG,QAAO;AAChC,QAAI,cAAc,GAAG;AACnB,YAAM,IAAI,MAAM,yBAAyB,WAAW,EAAE;AAAA,IACxD;AACA,WAAO,KAAK,IAAI,cAAc,gBAAgB,CAAC;AAAA,EACjD;AACF;;;ACNO,IAAM,eAAN,MAAmB;AAAA,EACxB,MAAM,UAAkB,YAAoB,OAAwC;AAClF,UAAM,YAAY,aAAa;AAC/B,UAAM,OAAO,KAAK,OAAO,SAAS;AAElC,WAAO,EAAE,UAAU,YAAY,OAAO,WAAW,KAAK;AAAA,EACxD;AAAA,EAEQ,OAAO,WAA8B;AAC3C,QAAI,YAAY,IAAK,QAAO;AAC5B,QAAI,YAAY,IAAK,QAAO;AAC5B,WAAO;AAAA,EACT;AACF;;;AFNA,IAAMC,eAAcC,GAAE,OAAO;AAAA,EAC3B,UAAUA,GAAE,OAAO,EAAE,IAAI,CAAC;AAC5B,CAAC;AAEM,SAAS,4BACd,SACA,KACA,SACA,WACA,WAAW,SACX;AACA,QAAM,gBAAgB,IAAI,cAAc;AACxC,QAAM,eAAe,IAAI,aAAa;AACtC,QAAM,cAAc,IAAI,gBAAgB,QAAQ;AAEhD,SAAO,OAAO,SAAkC;AAC9C,QAAI;AACF,YAAM,SAASD,aAAY,UAAU,IAAI;AACzC,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAS,OAAO,MAAM,QAAQ,CAAC,EAAE,CAAC;AAAA,QAC3G;AAAA,MACF;AAEA,YAAM,EAAE,SAAS,IAAI,OAAO;AAE5B,YAAM,SAAS,QAAQ,cAAc,QAAQ;AAC7C,UAAI,CAAC,QAAQ;AACX,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,OAAO,MAAM,kEAAkE,CAAC,EAAE,CAAC;AAAA,QACtJ;AAAA,MACF;AAEA,YAAM,WAAW,SAAS,MAAM,IAAI,EAAE,CAAC;AACvC,YAAM,gBAAgB,CAAC,MAAc,EAAE,QAAQ,OAAO,GAAG;AAGzD,YAAM,WAAW,QAAQ,iBAAiB;AAC1C,YAAM,eAAe,MAAM,QAAQ,IAAI,SAAS,IAAI,CAAC,MAAM,IAAI,aAAa,CAAC,CAAC,CAAC;AAE/E,YAAM,WAAW,KAAK,IAAI,GAAG,GAAG,aAAa,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC;AACtE,YAAM,cAAc,aAAa,KAAK,CAAC,MAAM,cAAc,EAAE,QAAQ,MAAM,cAAc,QAAQ,CAAC;AAClG,YAAM,cAAc,aAAa,eAAe;AAEhD,YAAM,kBAAkB,cAAc,UAAU,aAAa,QAAQ;AAGrE,YAAM,UAAU,YAAY,QAAQ;AACpC,YAAM,YAAY,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ;AACzD,YAAM,oBAAoB,WAAW,cAAc,CAAC;AAGpD,UAAI,aAAa,kBAAkB,KAAK,CAAC,MAAM,EAAE,aAAa,QAAQ,GAAG;AACzE,UAAI,eAAe,QAAW;AAE5B,cAAM,aAAa,SAAS,MAAM,IAAI,EAAE,CAAC,KAAK;AAC9C,cAAM,iBAAiB,kBAAkB;AAAA,UAAO,CAAC,MAC/C,EAAE,SAAS,WAAW,GAAG,QAAQ,KAAK,UAAU,GAAG;AAAA,QACrD;AACA,qBAAa,eAAe,SAAS,IACjC,KAAK,IAAI,GAAG,eAAe,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,IACnD;AAAA,MACN;AAEA,YAAM,uBAAuB,KAAK,KAAK,aAAa,KAAK,GAAG,CAAC;AAE7D,YAAM,QAAQ,aAAa,MAAM,UAAU,sBAAsB,eAAe;AAEhF,YAAM,UAAU,QAAQ,KAAK,KAAK,UAAU,KAAK,CAAC;AAElD,YAAM,UAAiD,CAAC;AACxD,UAAI,WAAW;AACb,cAAM,UAAU,UAAU,MAAM,QAAQ,iBAAiB,CAAC;AAC1D,YAAI,QAAS,SAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,gBAAM,QAAQ,OAAO,GAAG,CAAC;AAAA,MAC3E;AACA,cAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC;AAE5C,aAAO,EAAE,QAAQ;AAAA,IACnB,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAU,IAAc,QAAQ,CAAC,EAAE,CAAC;AAAA,MAC7G;AAAA,IACF;AAAA,EACF;AACF;;;AG7FA,SAAS,KAAAE,UAAS;;;ACwBlB,IAAM,kBAAkB,oBAAI,IAAI,CAAC,SAAS,WAAW,YAAY,CAAC;AAClE,IAAM,eAAe,oBAAI,IAAI,CAAC,MAAM,CAAC;AAErC,IAAM,kBAAoD;AAAA,EACxD,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,WAAW;AACb;AAEA,SAAS,qBAAqB,MAAgC;AAC5D,MAAI,gBAAgB,IAAI,IAAI,EAAG,QAAO;AACtC,MAAI,aAAa,IAAI,IAAI,EAAG,QAAO;AACnC,SAAO;AACT;AAEO,IAAM,wBAAN,MAA4B;AAAA,EACjC,UAAU,OAAoB,UAAkB,aAA+D;AAC7G,QAAI,CAAC,MAAM,QAAQ,QAAQ,GAAG;AAC5B,aAAO,EAAE,iBAAiB,CAAC,GAAG,uBAAuB,GAAG,gBAAgB,GAAG,aAAa,GAAG,gBAAgB,GAAG,kBAAkB,EAAE;AAAA,IACpI;AAEA,UAAM,aAAa,SAAS,MAAM,IAAI,EAAE,CAAC;AAEzC,UAAM,UAAU,oBAAI,IAAY,CAAC,QAAQ,CAAC;AAC1C,UAAM,aAA2J,CAAC;AAGlK,UAAM,QAA8C,CAAC,EAAE,IAAI,UAAU,OAAO,EAAE,CAAC;AAE/E,WAAO,MAAM,SAAS,GAAG;AACvB,YAAM,UAAU,MAAM,MAAM;AAE5B,YAAM,eAAe,MAAM,gBAAgB,QAAQ,EAAE;AAIrD,YAAM,aAAa,oBAAI,IAAkE;AACzF,iBAAW,QAAQ,cAAc;AAC/B,YAAI,QAAQ,IAAI,KAAK,IAAI,EAAG;AAC5B,cAAM,OAAO,qBAAqB,KAAK,IAAI;AAC3C,cAAM,WAAW,WAAW,IAAI,KAAK,IAAI;AACzC,YAAI,CAAC,UAAU;AACb,qBAAW,IAAI,KAAK,MAAM,EAAE,YAAY,MAAM,OAAO,oBAAI,IAAI,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC;AAAA,QAC7E,OAAO;AACL,mBAAS,MAAM,IAAI,KAAK,IAAI;AAC5B,cAAI,gBAAgB,IAAI,IAAI,gBAAgB,SAAS,UAAU,GAAG;AAChE,qBAAS,aAAa;AAAA,UACxB;AAAA,QACF;AAAA,MACF;AAEA,iBAAW,CAAC,QAAQ,IAAI,KAAK,YAAY;AACvC,gBAAQ,IAAI,MAAM;AAClB,YAAI,CAAC,MAAM,QAAQ,MAAM,EAAG;AAE5B,cAAM,QAAQ,QAAQ,QAAQ;AAC9B,cAAM,YAAY,IAAI,KAAK,IAAI,OAAO,GAAG;AAGzC,YAAI,aAAa,KAAK;AACtB,YAAI;AACJ,YAAI,aAAa;AACf,gBAAM,WAAW,OAAO,MAAM,IAAI,EAAE,CAAC;AACrC,gBAAM,YAAY,YAAY,IAAI,UAAU;AAC5C,cAAI,WAAW;AACb,kBAAM,QAAQ,UAAU,KAAK,OAAK,EAAE,UAAU,YAAY,EAAE,UAAU,QAAQ;AAC9E,gBAAI,OAAO;AACT,kCAAoB,MAAM;AAC1B,kBAAI,eAAe,eAAe,MAAM,YAAY,KAAK;AACvD,6BAAa;AAAA,cACf;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,mBAAW,KAAK;AAAA,UACd,UAAU;AAAA,UACV;AAAA,UACA,WAAW,KAAK,MAAM,YAAY,GAAI,IAAI;AAAA,UAC1C;AAAA,UACA,WAAW,CAAC,GAAG,KAAK,KAAK;AAAA,UACzB;AAAA,QACF,CAAC;AAED,cAAM,KAAK,EAAE,IAAI,QAAQ,MAAM,CAAC;AAAA,MAClC;AAAA,IACF;AAGA,UAAM,WAAW,IAAI,IAAI,WAAW,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC;AAC1D,aAAS,IAAI,QAAQ;AAErB,UAAM,UAA8B,WAAW,IAAI,CAAC,OAAO;AAAA,MACzD,GAAG;AAAA,MACH,gBAAgB,MAAM,gBAAgB,EAAE,QAAQ,EAAE,OAAO,CAAC,OAAO,SAAS,IAAI,GAAG,IAAI,CAAC,EAAE;AAAA,IAC1F,EAAE;AAGF,YAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAExC,UAAM,wBAAwB,QAAQ,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE;AAGnE,UAAM,YAAY,QAAQ,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,WAAW,CAAC;AACjE,UAAM,mBAAmB,KAAK,MAAM,KAAK,IAAI,YAAY,KAAK,IAAI,uBAAuB,CAAC,GAAG,CAAC,IAAI,GAAI,IAAI;AAE1G,UAAM,iBAAiB,QAAQ,OAAO,CAAC,MAAM,EAAE,eAAe,WAAW,EAAE;AAC3E,UAAM,cAAc,QAAQ,OAAO,CAAC,MAAM,EAAE,eAAe,QAAQ,EAAE;AACrE,UAAM,iBAAiB,QAAQ,OAAO,CAAC,MAAM,EAAE,eAAe,WAAW,EAAE;AAE3E,WAAO,EAAE,iBAAiB,SAAS,uBAAuB,gBAAgB,aAAa,gBAAgB,iBAAiB;AAAA,EAC1H;AACF;;;AD/HA,IAAMC,eAAcC,GAAE,OAAO;AAAA,EAC3B,UAAUA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC1B,YAAYA,GAAE,KAAK,CAAC,aAAa,UAAU,WAAW,CAAC,EAAE,SAAS;AAAA,EAClE,QAAQA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yEAAyE;AAClH,CAAC;AAEM,SAAS,qBACd,SACA,SACA,WACA,WAAW,SACX;AACA,QAAM,aAAa,IAAI,sBAAsB;AAC7C,QAAM,WAAW,MAAM;AACrB,UAAM,YAAY,wBAAwB,QAAQ;AAClD,QAAI,UAAU,YAAY,EAAG,QAAO;AACpC,WAAO,sBAAsB,OAAO;AAAA,EACtC;AAEA,SAAO,CAAC,SAAkC;AACxC,QAAI;AACF,YAAM,SAASD,aAAY,UAAU,IAAI;AACzC,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAS,OAAO,MAAM,QAAQ,CAAC,EAAE,CAAC;AAAA,QAC3G;AAAA,MACF;AAEA,YAAM,EAAE,SAAS,IAAI,OAAO;AAC5B,YAAM,QAAQ,SAAS;AAEvB,UAAI,CAAC,MAAM,QAAQ,QAAQ,GAAG;AAC5B,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,OAAO,MAAM,kEAAkE,CAAC,EAAE,CAAC;AAAA,QACtJ;AAAA,MACF;AAEA,YAAM,SAAS,WAAW,UAAU,OAAO,QAAQ;AAGnD,UAAI,UAAU,OAAO;AACrB,UAAI,OAAO,KAAK,YAAY;AAC1B,kBAAU,QAAQ,OAAO,OAAK,EAAE,eAAe,OAAO,KAAK,UAAU;AAAA,MACvE;AAGA,gBAAU,eAAe,SAAiD,OAAO,KAAK,MAAM;AAE5F,YAAM,iBAAiB,QAAQ,OAAO,OAAK,EAAE,eAAe,WAAW,EAAE;AACzE,YAAM,cAAc,QAAQ,OAAO,OAAK,EAAE,eAAe,QAAQ,EAAE;AACnE,YAAM,iBAAiB,QAAQ,OAAO,OAAK,EAAE,eAAe,WAAW,EAAE;AAEzE,YAAM,UAAU,QAAQ,KAAK,KAAK,UAAU,aAAa;AAAA,QACvD;AAAA,QACA,aAAa,QAAQ;AAAA,QACrB,uBAAuB,OAAO;AAAA,QAC9B;AAAA,QACA;AAAA,QACA;AAAA,QACA,kBAAkB,OAAO;AAAA,QACzB,iBAAiB;AAAA,MACnB,CAAC,CAAC,CAAC;AAEH,YAAM,UAAiD,CAAC;AACxD,UAAI,WAAW;AACb,cAAM,UAAU,UAAU,MAAM,QAAQ,iBAAiB,CAAC;AAC1D,YAAI,QAAS,SAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,gBAAM,QAAQ,OAAO,GAAG,CAAC;AAAA,MAC3E;AACA,cAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC;AAE5C,aAAO,EAAE,QAAQ;AAAA,IACnB,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAU,IAAc,QAAQ,CAAC,EAAE,CAAC;AAAA,MAC7G;AAAA,IACF;AAAA,EACF;AACF;;;AEtFA,SAAS,KAAAE,UAAS;;;ACSlB,IAAM,gBAA6B;AAAA;AAAA,EAEjC,EAAE,SAAS,aAAa,OAAO,OAAO;AAAA,EACtC,EAAE,SAAS,eAAe,OAAO,OAAO;AAAA,EACxC,EAAE,SAAS,aAAa,OAAO,OAAO;AAAA,EACtC,EAAE,SAAS,iBAAiB,OAAO,OAAO;AAAA;AAAA,EAE1C,EAAE,SAAS,mBAAmB,OAAO,cAAc;AAAA;AAAA,EAEnD,EAAE,SAAS,YAAY,OAAO,SAAS;AAAA,EACvC,EAAE,SAAS,cAAc,OAAO,SAAS;AAAA;AAAA,EAEzC,EAAE,SAAS,iBAAiB,OAAO,UAAU;AAAA,EAC7C,EAAE,SAAS,WAAW,OAAO,UAAU;AAAA;AAAA,EAEvC,EAAE,SAAS,aAAa,OAAO,iBAAiB;AAAA,EAChD,EAAE,SAAS,UAAU,OAAO,iBAAiB;AAAA,EAC7C,EAAE,SAAS,aAAa,OAAO,iBAAiB;AAAA;AAAA,EAEhD,EAAE,SAAS,gCAAgC,OAAO,gBAAgB;AACpE;AAEO,IAAM,uBAAN,MAA2B;AAAA,EACf;AAAA,EAEjB,YAAY,aAA2B;AACrC,SAAK,SAAS,eAAe,eAAe,IAAI,CAAC,EAAE,SAAS,MAAM,OAAO;AAAA,MACvE,SAAS,IAAI,OAAO,QAAQ,QAAQ,QAAQ,KAAK;AAAA,MACjD;AAAA,IACF,EAAE;AAAA,EACJ;AAAA,EAEA,SAAS,WAA6C;AACpD,UAAM,SAAmC,CAAC;AAE1C,eAAW,YAAY,WAAW;AAChC,YAAM,QAAQ,KAAK,WAAW,QAAQ;AACtC,YAAM,OAAO,OAAO,KAAK,KAAK,CAAC;AAC/B,WAAK,KAAK,QAAQ;AAClB,aAAO,KAAK,IAAI;AAAA,IAClB;AAEA,WAAO,EAAE,OAAO;AAAA,EAClB;AAAA,EAEQ,WAAW,UAA0B;AAC3C,eAAW,QAAQ,KAAK,OAAO;AAC7B,UAAI,KAAK,QAAQ,KAAK,QAAQ,GAAG;AAC/B,eAAO,KAAK;AAAA,MACd;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;;;ADxDA,IAAMC,eAAcC,GAAE,OAAO;AAAA,EAC3B,OAAOA,GAAE,OAAO,EAAE,SAAS;AAC7B,CAAC;AAEM,SAAS,8BACd,SACA,SACA,WACA;AACA,QAAM,UAAU,IAAI,qBAAqB;AAEzC,SAAO,CAAC,SAAkC;AACxC,QAAI;AACF,YAAM,SAASD,aAAY,UAAU,IAAI;AACzC,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAS,OAAO,MAAM,QAAQ,CAAC,EAAE,CAAC;AAAA,QAC3G;AAAA,MACF;AAEA,YAAM,QAAQ,QAAQ,iBAAiB;AACvC,YAAM,SAAS,QAAQ,SAAS,KAAK;AAErC,YAAM,eAAe,CAAC,eAAuB;AAC3C,cAAM,UAAiD,CAAC;AACxD,YAAI,WAAW;AACb,gBAAM,UAAU,UAAU,MAAM,KAAK;AACrC,cAAI,QAAS,SAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,gBAAM,QAAQ,OAAO,GAAG,CAAC;AAAA,QAC3E;AACA,gBAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,WAAW,CAAC;AAC/C,eAAO;AAAA,MACT;AAGA,UAAI,OAAO,KAAK,OAAO;AACrB,cAAM,WAAW,OAAO,OAAO,OAAO,KAAK,KAAK;AAChD,cAAME,WAAU,QAAQ,KAAK,KAAK,UAAU,EAAE,OAAO,OAAO,KAAK,OAAO,OAAO,YAAY,CAAC,EAAE,CAAC,CAAC;AAChG,eAAO,EAAE,SAAS,aAAaA,QAAO,EAAE;AAAA,MAC1C;AAEA,YAAM,UAAU,QAAQ,KAAK,KAAK,UAAU,MAAM,CAAC;AACnD,aAAO,EAAE,SAAS,aAAa,OAAO,EAAE;AAAA,IAC1C,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAU,IAAc,QAAQ,CAAC,EAAE,CAAC;AAAA,MAC7G;AAAA,IACF;AAAA,EACF;AACF;;;AEtDA,SAAS,KAAAC,UAAS;;;ACwClB,IAAM,gBAAgB,CAAC,aAAa,eAAe,eAAe,aAAa,eAAe;AAC9F,IAAM,kBAAkB,CAAC,gCAAgC,YAAY,UAAU,UAAU;AAGzF,IAAM,qBAAqB;AAAA;AAAA,EAEzB;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AACF;AAGA,IAAM,uBAAuB;AAAA,EAC3B,EAAE,OAAO,aAAa,SAAS,OAAO;AAAA,EACtC,EAAE,OAAO,cAAc,SAAS,QAAQ;AAAA,EACxC,EAAE,OAAO,aAAa,SAAS,OAAO;AAAA,EACtC,EAAE,OAAO,oBAAoB,SAAS,cAAc;AAAA,EACpD,EAAE,OAAO,WAAW,SAAS,MAAM;AAAA,EACnC,EAAE,OAAO,yBAAyB,SAAS,aAAa;AAAA,EACxD,EAAE,OAAO,+BAA+B,SAAS,kBAAkB;AAAA,EACnE,EAAE,OAAO,yBAAyB,SAAS,YAAY;AACzD;AAEO,IAAM,mBAAN,MAAuB;AAAA,EAC5B,OACE,OACA,UAA4E,CAAC,GAC7D;AAChB,UAAM,WAAW,MAAM,SAAS;AAGhC,UAAM,aAAa,QAAQ,eACvB,WACA,SAAS,OAAO,CAAC,MAAM;AACrB,YAAM,OAAO,EAAE,SAAS,MAAM,IAAI,EAAE,CAAC,KAAK;AAC1C,aAAO,CAAC,KAAK,WAAW,MAAM,aAAa,KAAK,CAAC,KAAK,WAAW,MAAM,eAAe;AAAA,IACxF,CAAC;AAEL,QAAI,WAAW,WAAW,GAAG;AAC3B,aAAO,EAAE,cAAc,GAAG,kBAAkB,GAAG,aAAa,CAAC,GAAG,eAAe,CAAC,GAAG,WAAW,CAAC,GAAG,aAAa,KAAK,kBAAkB,QAAQ,cAAc,GAAG,oBAAoB,EAAE;AAAA,IACvL;AAGA,UAAM,eAAe,IAAI,IAAI,WAAW,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC;AAC9D,UAAM,cAAc,oBAAI,IAAY;AAEpC,eAAW,QAAQ,YAAY;AAE7B,UAAI,KAAK,kBAAkB,KAAK,IAAI,GAAG;AACrC,oBAAY,IAAI,KAAK,QAAQ;AAC7B;AAAA,MACF;AAEA,YAAM,eAAe,MAAM,gBAAgB,KAAK,QAAQ;AACxD,YAAM,eAAe,MAAM,gBAAgB,KAAK,QAAQ;AAGxD,YAAM,yBAAyB,aAAa,OAAO,CAAC,MAAM,aAAa,IAAI,EAAE,IAAI,KAAK,EAAE,SAAS,KAAK,QAAQ;AAE9G,UAAI,uBAAuB,WAAW,GAAG;AACvC,cAAM,cAAc,aAAa,KAAK,CAAC,MAAM,aAAa,IAAI,EAAE,EAAE,CAAC;AACnE,YAAI,eAAe,aAAa,SAAS,GAAG;AAC1C,sBAAY,IAAI,KAAK,QAAQ;AAAA,QAC/B;AAAA,MACF;AAAA,IACF;AAGA,UAAM,YAAY,oBAAI,IAAY;AAClC,UAAM,QAAQ,CAAC,GAAG,WAAW;AAE7B,WAAO,MAAM,SAAS,GAAG;AACvB,YAAM,UAAU,MAAM,MAAM;AAC5B,UAAI,UAAU,IAAI,OAAO,EAAG;AAC5B,gBAAU,IAAI,OAAO;AAErB,iBAAW,QAAQ,MAAM,gBAAgB,OAAO,GAAG;AACjD,YAAI,CAAC,UAAU,IAAI,KAAK,EAAE,KAAK,aAAa,IAAI,KAAK,EAAE,GAAG;AACxD,gBAAM,KAAK,KAAK,EAAE;AAAA,QACpB;AAAA,MACF;AAAA,IACF;AAIA,UAAM,UAAU,oBAAI,IAAY;AAChC,eAAW,QAAQ,YAAY;AAC7B,UAAI,CAAC,UAAU,IAAI,KAAK,QAAQ,GAAG;AACjC,gBAAQ,IAAI,KAAK,QAAQ;AAAA,MAC3B;AAAA,IACF;AAGA,UAAM,kBAAkB,KAAK,qBAAqB,OAAO,SAAS,YAAY;AAG9E,UAAM,cAAiC,CAAC;AACxC,eAAW,QAAQ,YAAY;AAC7B,UAAI,CAAC,QAAQ,IAAI,KAAK,QAAQ,EAAG;AAEjC,YAAM,OAAO,KAAK,SAAS,MAAM,IAAI,EAAE,CAAC,KAAK;AAC7C,YAAM,aAAa,KAAK,kBAAkB,OAAO,KAAK,UAAU,OAAO;AACvE,YAAM,eAAe,gBAAgB,IAAI,KAAK,QAAQ;AAEtD,kBAAY,KAAK;AAAA,QACf,UAAU,KAAK;AAAA,QACf;AAAA,QACA,MAAM,KAAK;AAAA,QACX,MAAM,KAAK;AAAA,QACX;AAAA,QACA,QAAQ,KAAK,eAAe,UAAU;AAAA,QACtC,GAAI,iBAAiB,UAAa,eAAe,IAAI,EAAE,aAAa,IAAI,CAAC;AAAA,MAC3E,CAAC;AAAA,IACH;AAGA,UAAM,YAAY,oBAAI,IAA6C;AACnE,eAAW,QAAQ,YAAY;AAC7B,YAAM,OAAO,KAAK,SAAS,MAAM,IAAI,EAAE,CAAC,KAAK;AAC7C,YAAM,QAAQ,UAAU,IAAI,IAAI,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE;AACzD,YAAM;AACN,UAAI,QAAQ,IAAI,KAAK,QAAQ,EAAG,OAAM;AACtC,gBAAU,IAAI,MAAM,KAAK;AAAA,IAC3B;AAEA,UAAM,YAAY,CAAC,GAAG,UAAU,QAAQ,CAAC,EACtC,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,QAAQ,KAAK,EAAE,SAAS,EAAE,KAAK,EACnD,IAAI,CAAC,CAAC,IAAI,MAAM,IAAI;AAKvB,UAAM,gBAAqC,CAAC;AAC5C,eAAW,QAAQ,YAAY;AAC7B,YAAM,eAAe,MAAM,gBAAgB,KAAK,QAAQ;AACxD,YAAM,oBAAoB,aAAa;AAAA,QAAO,CAAC,MAC7C,aAAa,IAAI,EAAE,IAAI,KAAK,EAAE,SAAS,KAAK;AAAA,MAC9C;AAEA,UAAI,kBAAkB,WAAW,KAAK,CAAC,QAAQ,IAAI,KAAK,QAAQ,GAAG;AAEjE,sBAAc,KAAK;AAAA,UACjB,UAAU,KAAK;AAAA,UACf,MAAM,KAAK,SAAS,MAAM,IAAI,EAAE,CAAC,KAAK;AAAA,UACtC,MAAM,KAAK;AAAA,UACX,MAAM,KAAK;AAAA,QACb,CAAC;AAAA,MACH;AAAA,IACF;AAGA,UAAM,cAAc,KAAK,kBAAkB,QAAQ,cAAc;AAEjE,UAAM,qBAAqB,KAAK,MAAO,YAAY,SAAS,WAAW,SAAU,MAAM,EAAE,IAAI;AAE7F,WAAO;AAAA,MACL,cAAc,WAAW;AAAA,MACzB,kBAAkB,UAAU;AAAA,MAC5B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,kBACN,OACA,UACA,SACoB;AACpB,UAAM,eAAe,MAAM,gBAAgB,QAAQ;AAGnD,QAAI,aAAa,WAAW,GAAG;AAC7B,aAAO;AAAA,IACT;AAGA,UAAM,uBAAuB,aAAa,MAAM,CAAC,MAAM;AACrD,YAAM,eAAe,EAAE,KAAK,MAAM,IAAI,EAAE,CAAC,KAAK;AAC9C,aAAO,KAAK,WAAW,cAAc,aAAa,KAAK,KAAK,WAAW,cAAc,eAAe;AAAA,IACtG,CAAC;AACD,QAAI,sBAAsB;AACxB,aAAO;AAAA,IACT;AAGA,UAAM,mBAAmB,aAAa,MAAM,CAAC,MAAM,QAAQ,IAAI,EAAE,IAAI,CAAC;AACtE,QAAI,kBAAkB;AACpB,aAAO;AAAA,IACT;AAGA,WAAO;AAAA,EACT;AAAA,EAEQ,eAAe,YAAwC;AAC7D,YAAQ,YAAY;AAAA,MAClB,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,IACX;AAAA,EACF;AAAA,EAEQ,kBAAkB,MAAuB;AAC/C,WAAO,mBAAmB,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC;AAAA,EACpD;AAAA,EAEQ,qBACN,OACA,SACA,cACqB;AACrB,UAAM,SAAS,oBAAI,IAAoB;AAGvC,UAAM,WAAW,oBAAI,IAAY;AACjC,eAAW,MAAM,SAAS;AACxB,YAAM,eAAe,MAAM,gBAAgB,EAAE;AAC7C,YAAM,gBAAgB,aAAa,OAAO,CAAC,MAAM,QAAQ,IAAI,EAAE,IAAI,KAAK,EAAE,SAAS,EAAE;AACrF,UAAI,cAAc,WAAW,GAAG;AAC9B,iBAAS,IAAI,EAAE;AACf,eAAO,IAAI,IAAI,CAAC;AAAA,MAClB;AAAA,IACF;AAGA,UAAM,QAAQ,CAAC,GAAG,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,OAAO,EAAE,EAAE;AAC1D,UAAM,UAAU,IAAI,IAAI,QAAQ;AAEhC,WAAO,MAAM,SAAS,GAAG;AACvB,YAAM,UAAU,MAAM,MAAM;AAC5B,iBAAW,QAAQ,MAAM,gBAAgB,QAAQ,EAAE,GAAG;AACpD,YAAI,QAAQ,IAAI,KAAK,EAAE,KAAK,CAAC,QAAQ,IAAI,KAAK,EAAE,KAAK,aAAa,IAAI,KAAK,EAAE,GAAG;AAC9E,gBAAM,WAAW,QAAQ,QAAQ;AACjC,iBAAO,IAAI,KAAK,IAAI,QAAQ;AAC5B,kBAAQ,IAAI,KAAK,EAAE;AACnB,gBAAM,KAAK,EAAE,IAAI,KAAK,IAAI,OAAO,SAAS,CAAC;AAAA,QAC7C;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,kBAAkB,gBAA0D;AAClF,QAAI,CAAC,kBAAkB,eAAe,SAAS,EAAG,QAAO,CAAC;AAE1D,UAAM,UAA8B,CAAC;AAErC,eAAW,CAAC,MAAM,OAAO,KAAK,gBAAgB;AAE5C,UAAI,KAAK,WAAW,MAAM,aAAa,KAAK,KAAK,WAAW,MAAM,eAAe,EAAG;AAEpF,YAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,cAAM,OAAO,MAAM,CAAC;AACpB,mBAAW,EAAE,OAAO,QAAQ,KAAK,sBAAsB;AACrD,cAAI,MAAM,KAAK,IAAI,GAAG;AACpB,oBAAQ,KAAK;AAAA,cACX;AAAA,cACA,MAAM,IAAI;AAAA,cACV;AAAA,cACA,MAAM,KAAK,KAAK,EAAE,MAAM,GAAG,GAAG;AAAA,YAChC,CAAC;AACD;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,WAAW,OAAe,UAA6B;AAC7D,WAAO,SAAS,KAAK,CAAC,MAAM,EAAE,KAAK,KAAK,CAAC;AAAA,EAC3C;AACF;;;AD5TA,IAAMC,eAAcC,GAAE,OAAO;AAAA,EAC3B,cAAcA,GAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,KAAK;AAAA,EAClD,QAAQA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,mFAAmF;AAC5H,CAAC;AAEM,SAAS,mBACd,SACA,SACA,WACA,WAAW,SACX;AACA,QAAM,WAAW,IAAI,iBAAiB;AAEtC,QAAM,WAAW,MAAM;AACrB,UAAM,YAAY,wBAAwB,QAAQ;AAClD,QAAI,UAAU,YAAY,EAAG,QAAO;AACpC,WAAO,sBAAsB,OAAO;AAAA,EACtC;AAEA,SAAO,CAAC,SAAkC;AACxC,QAAI;AACF,YAAM,SAASD,aAAY,UAAU,IAAI;AACzC,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAS,OAAO,MAAM,QAAQ,CAAC,EAAE,CAAC;AAAA,QAC3G;AAAA,MACF;AAEA,YAAM,QAAQ,SAAS;AACvB,YAAM,SAAS,SAAS,OAAO,OAAO,EAAE,cAAc,OAAO,KAAK,aAAa,CAAC;AAGhF,YAAM,WAAW;AAAA,QACf,GAAG;AAAA,QACH,aAAa,eAAe,OAAO,aAAqD,OAAO,KAAK,MAAM;AAAA,MAC5G;AAEA,YAAM,UAAU,QAAQ,KAAK,KAAK,UAAU,aAAa,QAA8C,CAAC,CAAC;AAEzG,YAAM,UAAiD,CAAC;AACxD,UAAI,WAAW;AACb,cAAM,UAAU,UAAU,MAAM,QAAQ,iBAAiB,CAAC;AAC1D,YAAI,QAAS,SAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,gBAAM,QAAQ,OAAO,GAAG,CAAC;AAAA,MAC3E;AACA,cAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC;AAE5C,aAAO,EAAE,QAAQ;AAAA,IACnB,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAU,IAAc,QAAQ,CAAC,EAAE,CAAC;AAAA,MAC7G;AAAA,IACF;AAAA,EACF;AACF;;;AE9DA,SAAS,KAAAE,UAAS;;;ACUlB,IAAM,eAAiD;AAAA,EACrD,KAAK;AAAA,IACH,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,sBAAsB;AAAA,IACtB,gBAAgB;AAAA,IAChB,oBAAoB;AAAA,EACtB;AAAA,EACA,QAAQ;AAAA,IACN,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,sBAAsB;AAAA,IACtB,gBAAgB;AAAA,IAChB,oBAAoB;AAAA,EACtB;AAAA,EACA,UAAU;AAAA,IACR,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,sBAAsB;AAAA,IACtB,gBAAgB;AAAA,IAChB,oBAAoB;AAAA,EACtB;AAAA,EACA,YAAY;AAAA,IACV,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,sBAAsB;AAAA,IACtB,gBAAgB;AAAA,IAChB,oBAAoB;AAAA,EACtB;AACF;AAEO,SAAS,kBAAkB,UAAoC;AACpE,SAAO,aAAa,QAAQ;AAC9B;;;ACAA,IAAM,uBAAuB;AAEtB,IAAM,mBAAN,MAAuB;AAAA,EACX,aAAa,IAAI,gBAAgB;AAAA,EACjC,cAAc,IAAI,sBAAsB;AAAA,EAEzD,gBACE,OACA,UACA,UACA,SACA,cAAc,sBACiB;AAC/B,UAAM,SAAS,MAAM,QAAQ,QAAQ;AACrC,QAAI,CAAC,OAAQ,QAAO;AAEpB,UAAM,UAAU,kBAAkB,QAAQ;AAG1C,UAAM,QAAQ,KAAK,WAAW,cAAc,OAAO,QAAQ;AAC3D,UAAM,cAAc,KAAK,YAAY,UAAU,OAAO,QAAQ;AAG9D,UAAM,eAAe,oBAAI,IAAoD;AAG7E,QAAI,OAAO;AACT,iBAAW,OAAO,MAAM,cAAc;AACpC,qBAAa,IAAI,IAAI,UAAU;AAAA,UAC7B,MAAM;AAAA,UACN,SAAS,EAAE,aAAa,MAAM,mBAAmB,KAAK,kBAAkB,IAAI,IAAI,GAAG,aAAa,OAAO,YAAY,GAAG,gBAAgB,MAAM;AAAA,QAC9I,CAAC;AAAA,MACH;AAAA,IACF;AAGA,eAAW,SAAS,YAAY,iBAAiB;AAC/C,YAAM,OAAO,MAAM,QAAQ,MAAM,QAAQ;AACzC,UAAI,CAAC,KAAM;AAEX,YAAM,WAAW,aAAa,IAAI,MAAM,QAAQ;AAChD,UAAI,UAAU;AACZ,iBAAS,QAAQ,cAAc;AAAA,MACjC,OAAO;AACL,qBAAa,IAAI,MAAM,UAAU;AAAA,UAC/B;AAAA,UACA,SAAS,EAAE,aAAa,OAAO,mBAAmB,KAAK,kBAAkB,KAAK,IAAI,GAAG,aAAa,MAAM,YAAY,GAAG,gBAAgB,MAAM;AAAA,QAC/I,CAAC;AAAA,MACH;AAAA,IACF;AAGA,UAAM,eAAe,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAC5D,eAAW,CAAC,KAAK,SAAS,KAAK,cAAc;AAC3C,YAAM,OAAO,IAAI,MAAM,IAAI,EAAE,CAAC,KAAK;AACnC,YAAM,YAAY,aAAa,IAAI,IAAI;AAEvC,UAAI,WAAW;AACb,cAAM,aAAa,UAAU,YAAY,KAAK,CAAC,MAAM,EAAE,aAAa,GAAG;AACvE,kBAAU,QAAQ,aAAa,YAAY,cAAc;AACzD,kBAAU,QAAQ,iBAAiB,UAAU,aAAa,SAAS;AAAA,MACrE;AAAA,IACF;AAGA,UAAM,SAAS,CAAC,GAAG,aAAa,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,MAAM,QAAQ,CAAC,OAAO;AAAA,MACzE,OAAO,KAAK,kBAAkB,MAAM,SAAS,OAAO;AAAA,MACpD,OAAO,KAAK,aAAa,SAAS,OAAO;AAAA,IAC3C,EAAE;AAEF,WAAO,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAGvC,UAAM,UAA0B,CAAC;AACjC,QAAI,cAAc;AAElB,eAAW,EAAE,MAAM,KAAK,QAAQ;AAC9B,UAAI,cAAc,MAAM,SAAS,YAAa;AAC9C,cAAQ,KAAK,KAAK;AAClB,qBAAe,MAAM;AAAA,IACvB;AAGA,UAAM,WAAqB,CAAC;AAC5B,UAAM,aAAa,SAAS,MAAM,IAAI,EAAE,CAAC,KAAK;AAC9C,UAAM,cAAc,aAAa,IAAI,UAAU;AAC/C,QAAI,eAAe,YAAY,aAAa,SAAS,GAAG;AACtD,eAAS,KAAK,4BAAuB,YAAY,aAAa,MAAM,kCAAkC;AAAA,IACxG;AAEA,WAAO,EAAE,QAAQ,UAAU,SAAS,aAAa,aAAa,SAAS;AAAA,EACzE;AAAA,EAEA,eACE,OACA,OACA,WAAqD,YACrD,cAAc,sBACO;AACrB,UAAM,WAAW,MAAM,SAAS;AAChC,UAAM,aAAa,MAAM,YAAY;AAGrC,QAAI,kBAAkB;AACtB,eAAW,QAAQ,UAAU;AAC3B,YAAM,QAAQ,MAAM,gBAAgB,KAAK,QAAQ,EAAE;AACnD,UAAI,QAAQ,gBAAiB,mBAAkB;AAAA,IACjD;AAGA,UAAM,SAAS,SAAS,IAAI,CAAC,SAAS;AACpC,YAAM,iBAAiB,KAAK,qBAAqB,KAAK,MAAM,UAAU;AACtE,YAAM,kBAAkB,MAAM,gBAAgB,KAAK,QAAQ,EAAE,SAAS;AAEtE,UAAI;AACJ,cAAQ,UAAU;AAAA,QAChB,KAAK;AACH,0BAAgB;AAChB;AAAA,QACF,KAAK;AACH,0BAAgB;AAChB;AAAA,QACF;AACE,0BAAgB,iBAAiB,MAAM,kBAAkB;AAAA,MAC7D;AAEA,aAAO;AAAA,QACL,UAAU,KAAK;AAAA,QACf,MAAM,KAAK;AAAA,QACX,MAAM,KAAK;AAAA,QACX,MAAM,KAAK,SAAS,MAAM,IAAI,EAAE,CAAC,KAAK;AAAA,QACtC,gBAAgB,KAAK,MAAM,iBAAiB,GAAI,IAAI;AAAA,QACpD,iBAAiB,KAAK,MAAM,kBAAkB,GAAI,IAAI;AAAA,QACtD,eAAe,KAAK,MAAM,gBAAgB,GAAI,IAAI;AAAA,QAClD,QAAQ,KAAK,eAAe,IAAI;AAAA,MAClC;AAAA,IACF,CAAC;AAGD,UAAM,WAAW,aAAa,eAC1B,SACA,OAAO,OAAO,CAAC,MAAM,EAAE,iBAAiB,KAAK,EAAE,kBAAkB,GAAG;AAExE,aAAS,KAAK,CAAC,GAAG,MAAM,EAAE,gBAAgB,EAAE,aAAa;AAGzD,UAAM,UAA2B,CAAC;AAClC,QAAI,cAAc;AAElB,eAAW,QAAQ,UAAU;AAC3B,UAAI,cAAc,KAAK,SAAS,YAAa;AAC7C,cAAQ,KAAK,IAAI;AACjB,qBAAe,KAAK;AAAA,IACtB;AAEA,WAAO,EAAE,OAAO,UAAU,SAAS,aAAa,YAAY;AAAA,EAC9D;AAAA,EAEQ,qBAAqB,MAAc,YAA4B;AACrE,UAAM,YAAY,KAAK,YAAY;AACnC,QAAI,cAAc,WAAY,QAAO;AACrC,QAAI,UAAU,SAAS,UAAU,EAAG,QAAO;AAC3C,QAAI,WAAW,MAAM,KAAK,EAAE,KAAK,CAAC,SAAS,UAAU,SAAS,IAAI,CAAC,EAAG,QAAO;AAC7E,WAAO;AAAA,EACT;AAAA,EAEQ,aAAa,SAAkB,SAAiC;AACtE,QAAI,QAAQ;AACZ,QAAI,QAAQ,YAAa,UAAS,QAAQ;AAC1C,QAAI,QAAQ,kBAAmB,UAAS,QAAQ;AAChD,QAAI,QAAQ,YAAa,UAAS,QAAQ;AAC1C,QAAI,QAAQ,aAAa,EAAG,UAAS,QAAQ;AAC7C,QAAI,QAAQ,eAAgB,UAAS,QAAQ;AAC7C,WAAO,KAAK,MAAM,QAAQ,GAAI,IAAI;AAAA,EACpC;AAAA,EAEQ,kBAAkB,MAAkB,SAAkB,SAAuC;AACnG,UAAM,UAAoB,CAAC;AAC3B,QAAI,QAAQ,YAAa,SAAQ,KAAK,mBAAmB;AACzD,QAAI,QAAQ,kBAAmB,SAAQ,KAAK,2BAA2B;AACvE,QAAI,QAAQ,YAAa,SAAQ,KAAK,wBAAwB;AAC9D,QAAI,QAAQ,aAAa,EAAG,SAAQ,KAAK,uBAAuB,QAAQ,UAAU,GAAG;AACrF,QAAI,QAAQ,eAAgB,SAAQ,KAAK,sBAAsB;AAE/D,WAAO;AAAA,MACL,UAAU,KAAK;AAAA,MACf,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,MAAM,KAAK,SAAS,MAAM,IAAI,EAAE,CAAC,KAAK;AAAA,MACtC,gBAAgB,KAAK,aAAa,SAAS,OAAO;AAAA,MAClD,QAAQ,QAAQ,KAAK,IAAI,KAAK;AAAA,MAC9B,OAAO,KAAK,UAAU,KAAK,YAAY;AAAA,MACvC,QAAQ,KAAK,eAAe,IAAI;AAAA,IAClC;AAAA,EACF;AAAA,EAEQ,kBAAkB,MAA2B;AACnD,WAAO,SAAS,eAAe,SAAS;AAAA,EAC1C;AAAA,EAEA,qBAAqB,MAA0B;AAC7C,WAAO,KAAK,eAAe,IAAI;AAAA,EACjC;AAAA,EAEQ,eAAe,MAA0B;AAE/C,QAAI,KAAK,gBAAgB,UAAa,KAAK,cAAc,QAAW;AAClE,aAAO,KAAK,MAAM,KAAK,YAAY,KAAK,eAAe,CAAC;AAAA,IAC1D;AACA,YAAQ,KAAK,UAAU,KAAK,YAAY,KAAK;AAAA,EAC/C;AACF;;;AFrPA,IAAM,iBAAiBC,GAAE,KAAK,CAAC,OAAO,UAAU,YAAY,YAAY,CAAC;AAEzE,IAAMC,eAAcD,GAAE,OAAO;AAAA,EAC3B,UAAUA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC1B,UAAU;AAAA,EACV,aAAaA,GAAE,OAAO,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,QAAQ,GAAI;AAC1D,CAAC;AAEM,SAAS,wBACd,SACA,SACA,WACA,WAAW,SACX;AACA,QAAM,YAAY,IAAI,iBAAiB;AACvC,QAAM,cAAc,IAAI,gBAAgB,QAAQ;AAEhD,QAAM,WAAW,MAAM;AACrB,UAAM,YAAY,wBAAwB,QAAQ;AAClD,QAAI,UAAU,YAAY,EAAG,QAAO;AACpC,WAAO,sBAAsB,OAAO;AAAA,EACtC;AAEA,SAAO,CAAC,SAAkC;AACxC,QAAI;AACF,YAAM,SAASC,aAAY,UAAU,IAAI;AACzC,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAS,OAAO,MAAM,QAAQ,CAAC,EAAE,CAAC;AAAA,QAC3G;AAAA,MACF;AAEA,YAAM,EAAE,UAAU,UAAU,YAAY,IAAI,OAAO;AACnD,YAAM,QAAQ,SAAS;AACvB,YAAM,UAAU,YAAY,QAAQ;AAEpC,YAAM,SAAS,UAAU,gBAAgB,OAAO,UAAU,UAAU,SAAS,WAAW;AAExF,UAAI,CAAC,QAAQ;AACX,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,OAAO,MAAM,sCAAsC,CAAC,EAAE,CAAC;AAAA,QAC1H;AAAA,MACF;AAEA,YAAM,UAAU,QAAQ,KAAK,KAAK,UAAU,aAAa,MAA4C,CAAC,CAAC;AAEvG,YAAM,UAAiD,CAAC;AACxD,UAAI,WAAW;AACb,cAAM,UAAU,UAAU,MAAM,QAAQ,iBAAiB,CAAC;AAC1D,YAAI,QAAS,SAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,gBAAM,QAAQ,OAAO,GAAG,CAAC;AAAA,MAC3E;AACA,cAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC;AAE5C,aAAO,EAAE,QAAQ;AAAA,IACnB,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAU,IAAc,QAAQ,CAAC,EAAE,CAAC;AAAA,MAC7G;AAAA,IACF;AAAA,EACF;AACF;;;AGrEA,SAAS,KAAAC,UAAS;;;ACOlB,IAAM,aAAa,oBAAI,IAAI;AAAA,EACzB;AAAA,EAAO;AAAA,EAAO;AAAA,EAAM;AAAA,EAAO;AAAA,EAAO;AAAA,EAAM;AAAA,EAAO;AAAA,EAAK;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EACtE;AAAA,EAAO;AAAA,EAAM;AAAA,EAAQ;AAAA,EAAM;AAAA,EAAM;AAAA,EAAQ;AAAA,EAAM;AAAA,EAAQ;AAAA,EAAO;AAAA,EAAM;AACtE,CAAC;AAWD,IAAM,kBAA8C;AAAA,EAClD,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,iBAAiB;AACnB;AAEO,IAAM,kBAAN,MAAM,iBAAgB;AAAA,EACV;AAAA,EAEjB,YAAY,SAA4B;AACtC,SAAK,UAAU,EAAE,GAAG,iBAAiB,GAAG,QAAQ;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,SAAS,YAAoB,UAA6B;AACxD,UAAM,cAAc,iBAAgB,UAAU,UAAU;AACxD,UAAM,UAAU,YAAY,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC;AAEtD,UAAM,SAAmB,KAAK,QAAQ,mBAClC,UACA,QAAQ,OAAO,CAAC,MAAM,CAAC,WAAW,IAAI,CAAC,CAAC;AAG5C,QAAI,KAAK,QAAQ,iBAAiB;AAChC,YAAM,WAAW,WAAW,YAAY;AACxC,UAAI,CAAC,OAAO,SAAS,QAAQ,GAAG;AAC9B,eAAO,QAAQ,QAAQ;AAAA,MACzB;AAAA,IACF;AAGA,QAAI,KAAK,QAAQ,mBAAmB,UAAU;AAC5C,YAAM,aAAa,iBAAgB,iBAAiB,QAAQ;AAC5D,iBAAW,MAAM,YAAY;AAC3B,YAAI,CAAC,OAAO,SAAS,EAAE,GAAG;AACxB,iBAAO,KAAK,EAAE;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,OAAyB;AACrC,UAAM,QAAQ,MAAM,KAAK,EAAE,MAAM,KAAK;AACtC,UAAM,SAAmB,CAAC;AAC1B,eAAW,QAAQ,OAAO;AACxB,YAAM,QAAQ,iBAAgB,UAAU,IAAI;AAC5C,iBAAW,KAAK,OAAO;AACrB,cAAM,UAAU,EAAE,YAAY;AAC9B,YAAI,QAAQ,SAAS,KAAK,CAAC,OAAO,SAAS,OAAO,GAAG;AACnD,iBAAO,KAAK,OAAO;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,OAAO,UAAU,MAAwB;AACvC,QAAI,CAAC,QAAQ,KAAK,WAAW,EAAG,QAAO,CAAC;AAGxC,UAAM,WAAW,KAAK,MAAM,YAAY,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC;AAEpE,UAAM,SAAmB,CAAC;AAC1B,eAAW,WAAW,UAAU;AAC9B,aAAO,KAAK,GAAG,iBAAgB,eAAe,OAAO,CAAC;AAAA,IACxD;AAEA,WAAO,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,OAAe,eAAe,SAA2B;AACvD,UAAM,SAAmB,CAAC;AAC1B,QAAI,UAAU;AAEd,aAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,YAAM,KAAK,QAAQ,CAAC;AACpB,YAAM,OAAO,IAAI,IAAI,QAAQ,IAAI,CAAC,IAAK;AAGvC,UAAI,QAAQ,SAAS,GAAG;AACtB,cAAM,cAAc,QAAQ,IAAI;AAChC,cAAM,cAAc,QAAQ,EAAE;AAC9B,YAAI,gBAAgB,aAAa;AAC/B,iBAAO,KAAK,OAAO;AACnB,oBAAU;AACV;AAAA,QACF;AAAA,MACF;AAGA,UAAI,QAAQ,SAAS,KAAK,QAAQ,IAAI,KAAK,QAAQ,EAAE,GAAG;AACtD,eAAO,KAAK,OAAO;AACnB,kBAAU;AACV;AAAA,MACF;AAKA,UAAI,QAAQ,SAAS,KAAK,QAAQ,EAAE,MAAM,SAAS,QAAQ,IAAI,KAAK,CAAC,QAAQ,EAAE,GAAG;AAEhF,cAAM,WAAW,QAAQ,QAAQ,SAAS,CAAC;AAC3C,YAAI,QAAQ,QAAQ,GAAG;AACrB,iBAAO,KAAK,QAAQ,MAAM,GAAG,EAAE,CAAC;AAChC,oBAAU,WAAW;AACrB;AAAA,QACF;AAAA,MACF;AAEA,iBAAW;AAAA,IACb;AAEA,QAAI,QAAQ,SAAS,GAAG;AACtB,aAAO,KAAK,OAAO;AAAA,IACrB;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,iBAAiB,UAA4B;AAElD,UAAM,aAAa,SAAS,QAAQ,YAAY,EAAE;AAClD,UAAM,WAAW,WAAW,MAAM,QAAQ;AAC1C,UAAM,SAAmB,CAAC;AAC1B,eAAW,OAAO,UAAU;AAC1B,YAAM,QAAQ,IAAI,MAAM,SAAS,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC;AAC7D,iBAAW,KAAK,OAAO;AACrB,cAAM,UAAU,EAAE,YAAY;AAC9B,YAAI,QAAQ,SAAS,KAAK,CAAC,OAAO,SAAS,OAAO,GAAG;AACnD,iBAAO,KAAK,OAAO;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,OAAO,WAAW,OAAwB;AACxC,WAAO,WAAW,IAAI,MAAM,YAAY,CAAC;AAAA,EAC3C;AACF;AAEA,SAAS,QAAQ,IAAqB;AACpC,SAAO,MAAM,OAAO,MAAM;AAC5B;AAEA,SAAS,QAAQ,IAAqB;AACpC,SAAO,MAAM,OAAO,MAAM;AAC5B;AAEA,SAAS,QAAQ,IAAqB;AACpC,SAAO,MAAM,OAAO,MAAM;AAC5B;;;AClMO,IAAM,iBAAN,MAAqB;AAAA;AAAA,EAElB,aAAkC,oBAAI,IAAI;AAAA,EAElD,gBAAgB,iBAA4C;AAC1D,SAAK,aAAa,IAAI,IAAI,eAAe;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ,aAA+C;AACrD,QAAI,KAAK,WAAW,SAAS,EAAG,QAAO;AAEvC,UAAM,cAA8C,CAAC;AACrD,UAAM,kBAA4B,CAAC;AACnC,QAAI,aAAa;AAEjB,eAAW,SAAS,aAAa;AAE/B,UAAI,MAAM,UAAU,GAAG;AACrB,wBAAgB,KAAK,KAAK;AAC1B;AAAA,MACF;AAGA,UAAI,KAAK,WAAW,IAAI,KAAK,GAAG;AAC9B,wBAAgB,KAAK,KAAK;AAC1B;AAAA,MACF;AAEA,YAAM,UAAU,MAAM,UAAU,IAAI,IAAI;AACxC,YAAM,OAAO,KAAK,YAAY,OAAO,OAAO;AAE5C,UAAI,MAAM;AACR,oBAAY,KAAK;AAAA,UACf,UAAU;AAAA,UACV,WAAW,KAAK;AAAA,UAChB,UAAU,KAAK;AAAA,QACjB,CAAC;AACD,wBAAgB,KAAK,KAAK,IAAI;AAC9B,qBAAa;AAAA,MACf,OAAO;AACL,wBAAgB,KAAK,KAAK;AAAA,MAC5B;AAAA,IACF;AAEA,QAAI,CAAC,WAAY,QAAO;AAExB,WAAO;AAAA,MACL,eAAe,YAAY,KAAK,GAAG;AAAA,MACnC,gBAAgB,gBAAgB,KAAK,GAAG;AAAA,MACxC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,YACN,OACA,aAC2C;AAC3C,QAAI,WAA0B;AAC9B,QAAI,WAAW,cAAc;AAC7B,QAAI,WAAW;AAEf,eAAW,CAAC,WAAW,IAAI,KAAK,KAAK,YAAY;AAE/C,UAAI,KAAK,IAAI,UAAU,SAAS,MAAM,MAAM,IAAI,YAAa;AAE7D,YAAM,OAAO,mBAAmB,OAAO,SAAS;AAChD,UAAI,QAAQ,aAAa;AACvB,YAAI,OAAO,YAAa,SAAS,YAAY,OAAO,UAAW;AAC7D,qBAAW;AACX,qBAAW;AACX,qBAAW;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAEA,WAAO,aAAa,OAAO,EAAE,MAAM,UAAU,UAAU,SAAS,IAAI;AAAA,EACtE;AACF;AAOO,SAAS,mBAAmB,GAAW,GAAmB;AAC/D,QAAM,OAAO,EAAE;AACf,QAAM,OAAO,EAAE;AAEf,MAAI,SAAS,EAAG,QAAO;AACvB,MAAI,SAAS,EAAG,QAAO;AAGvB,QAAM,IAAgB,MAAM,KAAK,EAAE,QAAQ,OAAO,EAAE,GAAG,MAAM,IAAI,MAAc,OAAO,CAAC,EAAE,KAAK,CAAC,CAAC;AAEhG,WAAS,IAAI,GAAG,KAAK,MAAM,IAAK,GAAE,CAAC,EAAG,CAAC,IAAI;AAC3C,WAAS,IAAI,GAAG,KAAK,MAAM,IAAK,GAAE,CAAC,EAAG,CAAC,IAAI;AAE3C,WAAS,IAAI,GAAG,KAAK,MAAM,KAAK;AAC9B,aAAS,IAAI,GAAG,KAAK,MAAM,KAAK;AAC9B,YAAM,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,IAAI;AACzC,QAAE,CAAC,EAAG,CAAC,IAAI,KAAK;AAAA,QACd,EAAE,IAAI,CAAC,EAAG,CAAC,IAAK;AAAA;AAAA,QAChB,EAAE,CAAC,EAAG,IAAI,CAAC,IAAK;AAAA;AAAA,QAChB,EAAE,IAAI,CAAC,EAAG,IAAI,CAAC,IAAK;AAAA;AAAA,MACtB;AAGA,UAAI,IAAI,KAAK,IAAI,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG;AACpE,UAAE,CAAC,EAAG,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC,EAAG,CAAC,GAAI,EAAE,IAAI,CAAC,EAAG,IAAI,CAAC,IAAK,IAAI;AAAA,MACzD;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,IAAI,EAAG,IAAI;AACtB;;;ACnHA,IAAMC,OAAM,aAAa,aAAa;AAsBtC,IAAM,iBAAqC;AAAA,EACzC,MAAM,EAAE,IAAI,KAAK,GAAG,KAAK;AAAA,EACzB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,iBAAiB;AAAA,EACjB,gBAAgB;AAAA,EAChB,aAAa;AACf;AAoBO,IAAM,eAAN,MAAmB;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGT,YAA+B,CAAC;AAAA,EAChC,eAAuC,oBAAI,IAAI;AAAA,EAC/C,eAAe;AAAA;AAAA,EAGf,eAAuC,oBAAI,IAAI;AAAA;AAAA,EAG/C,iBAAsC,oBAAI,IAAI;AAAA,EAEtD,YAAY,QAAsC;AAChD,SAAK,SAAS,EAAE,GAAG,gBAAgB,GAAG,OAAO;AAC7C,SAAK,YAAY,IAAI,gBAAgB,EAAE,iBAAiB,MAAM,iBAAiB,KAAK,CAAC;AACrF,SAAK,QAAQ,IAAI,eAAe;AAAA,EAClC;AAAA,EAEA,UAA2C;AACzC,WAAO;AAAA,EACT;AAAA,EAEA,WAAW,SAAuB,gBAA4C;AAC5E,UAAM,QAAQ,YAAY,IAAI;AAC9B,SAAK,YAAY,CAAC;AAClB,SAAK,eAAe,oBAAI,IAAI;AAC5B,SAAK,eAAe,oBAAI,IAAI;AAC5B,SAAK,iBAAiB,kBAAkB,oBAAI,IAAI;AAEhD,QAAI,cAAc;AAClB,UAAM,YAAY,oBAAI,IAAoB;AAE1C,eAAW,OAAO,SAAS;AACzB,YAAM,WAAW,IAAI,SAAS,MAAM,IAAI,EAAE,CAAC,KAAK;AAChD,YAAM,SAAS,KAAK,UAAU,SAAS,IAAI,MAAM,QAAQ;AACzD,YAAM,MAAuB;AAAA,QAC3B,UAAU,IAAI;AAAA,QACd,MAAM,IAAI;AAAA,QACV,MAAM,IAAI;AAAA,QACV;AAAA,QACA;AAAA,QACA,QAAQ,OAAO;AAAA,MACjB;AACA,YAAM,WAAW,KAAK,UAAU;AAChC,WAAK,UAAU,KAAK,GAAG;AACvB,qBAAe,OAAO;AAGtB,YAAM,YAAY,oBAAI,IAAoB;AAC1C,iBAAW,SAAS,QAAQ;AAC1B,kBAAU,IAAI,QAAQ,UAAU,IAAI,KAAK,KAAK,KAAK,CAAC;AACpD,kBAAU,IAAI,QAAQ,UAAU,IAAI,KAAK,KAAK,KAAK,CAAC;AAAA,MACtD;AACA,iBAAW,CAAC,MAAM,EAAE,KAAK,WAAW;AAClC,YAAI,WAAW,KAAK,aAAa,IAAI,IAAI;AACzC,YAAI,CAAC,UAAU;AACb,qBAAW,CAAC;AACZ,eAAK,aAAa,IAAI,MAAM,QAAQ;AAAA,QACtC;AACA,iBAAS,KAAK,EAAE,UAAU,eAAe,GAAG,CAAC;AAAA,MAC/C;AAGA,YAAM,YAAY,IAAI,KAAK,YAAY;AACvC,YAAM,WAAW,KAAK,gBAAgB,SAAS;AAC/C,YAAM,eAAe,oBAAI,IAAoB;AAC7C,iBAAW,OAAO,UAAU;AAC1B,qBAAa,IAAI,MAAM,aAAa,IAAI,GAAG,KAAK,KAAK,CAAC;AAAA,MACxD;AACA,iBAAW,CAAC,KAAK,EAAE,KAAK,cAAc;AACpC,YAAI,WAAW,KAAK,aAAa,IAAI,GAAG;AACxC,YAAI,CAAC,UAAU;AACb,qBAAW,CAAC;AACZ,eAAK,aAAa,IAAI,KAAK,QAAQ;AAAA,QACrC;AACA,iBAAS,KAAK,EAAE,UAAU,eAAe,GAAG,CAAC;AAAA,MAC/C;AAAA,IACF;AAEA,SAAK,eAAe,KAAK,UAAU,SAAS,IAAI,cAAc,KAAK,UAAU,SAAS;AAGtF,SAAK,MAAM,gBAAgB,SAAS;AAEpC,UAAM,UAAU,YAAY,IAAI,IAAI;AACpC,IAAAA,KAAI,KAAK,gBAAgB,QAAQ,MAAM,aAAa,KAAK,aAAa,IAAI,WAAW,KAAK,aAAa,IAAI,cAAc,QAAQ,QAAQ,CAAC,CAAC,KAAK;AAAA,EAClJ;AAAA,EAEA,OAAO,OAAe,QAAQ,IAAoB;AAChD,UAAM,QAAQ,YAAY,IAAI;AAC9B,UAAM,cAAc,KAAK,UAAU,cAAc,KAAK;AAEtD,QAAI,YAAY,WAAW,GAAG;AAC5B,aAAO,KAAK,cAAc,OAAO,KAAK;AAAA,IACxC;AAEA,UAAM,UAAyB;AAAA,MAC7B,YAAY;AAAA,MACZ,aAAa;AAAA,MACb,iBAAiB;AAAA,MACjB,cAAc;AAAA,MACd,WAAW;AAAA,IACb;AAGA,UAAM,eAAe,KAAK,WAAW,aAAa,KAAK,YAAY;AACnE,YAAQ,aAAa,aAAa;AAElC,QAAI,YAAY;AAGhB,QAAI,aAAa,OAAO,KAAK,OAAO,iBAAiB;AACnD,cAAQ,kBAAkB;AAC1B,YAAM,aAAa,MAAM,YAAY;AAGrC,UAAI,WAAW,UAAU,GAAG;AAC1B,cAAM,gBAAgB,KAAK,gBAAgB,UAAU;AACrD,cAAM,eAAe,KAAK,WAAW,eAAe,KAAK,YAAY;AACrE,gBAAQ,cAAc,aAAa;AAGnC,oBAAY,KAAK,YAAY,cAAc,cAAc,KAAK,OAAO,cAAc;AAAA,MACrF;AAAA,IACF;AAGA,QAAI;AACJ,QAAI,UAAU,OAAO,KAAK,OAAO,gBAAgB;AAC/C,YAAM,aAAa,KAAK,MAAM,QAAQ,WAAW;AACjD,UAAI,YAAY;AACd,gBAAQ,eAAe;AACvB,0BAAkB;AAClB,cAAM,kBAAkB,KAAK,UAAU,cAAc,WAAW,cAAc;AAC9E,cAAM,cAAc,KAAK,WAAW,iBAAiB,KAAK,YAAY;AAGtE,oBAAY,KAAK,YAAY,WAAW,aAAa,GAAG;AAGxD,YAAI,UAAU,OAAO,KAAK,OAAO,kBAAkB,WAAW,eAAe,UAAU,GAAG;AACxF,gBAAM,oBAAoB,KAAK,gBAAgB,WAAW,eAAe,YAAY,CAAC;AACtF,gBAAM,qBAAqB,KAAK,WAAW,mBAAmB,KAAK,YAAY;AAC/E,sBAAY,KAAK,YAAY,WAAW,oBAAoB,KAAK,OAAO,iBAAiB,GAAG;AAAA,QAC9F;AAAA,MACF;AAAA,IACF;AAGA,UAAM,eAAe,IAAI,IAAI,SAAS;AAGtC,UAAM,sBAAsB,kBACxB,KAAK,UAAU,cAAc,gBAAgB,cAAc,IAC3D;AAEJ,QAAI,oBAAoB,UAAU,GAAG;AACnC,iBAAW,CAAC,QAAQ,KAAK,KAAK,WAAW;AACvC,cAAM,MAAM,KAAK,UAAU,MAAM;AACjC,cAAM,QAAQ,KAAK,YAAY,qBAAqB,IAAI,MAAM;AAC9D,kBAAU,IAAI,QAAQ,QAAQ,KAAK;AAAA,MACrC;AAAA,IACF;AAGA,eAAW,CAAC,QAAQ,KAAK,KAAK,WAAW;AACvC,YAAM,MAAM,KAAK,UAAU,MAAM;AACjC,YAAM,KAAK,KAAK,eAAe,IAAI,IAAI,QAAQ,KAAK;AACpD,gBAAU,IAAI,QAAQ,SAAS,IAAI,KAAK,OAAO,iBAAiB,GAAG;AAAA,IACrE;AAEA,YAAQ,YAAY,YAAY,IAAI,IAAI;AACxC,UAAM,UAAU,KAAK,aAAa,WAAW,cAAc,KAAK;AAEhE,UAAM,YAAY,QAAQ,kBAAkB,eAAe;AAC3D,QAAI,iBAAiB;AACnB,MAAAA,KAAI,KAAK,WAAW,KAAK,mBAAc,gBAAgB,cAAc,MAAM,QAAQ,MAAM,aAAa,QAAQ,UAAU,QAAQ,CAAC,CAAC,KAAK;AAAA,IACzI,OAAO;AACL,MAAAA,KAAI,KAAK,WAAW,KAAK,MAAM,QAAQ,MAAM,oBAAoB,QAAQ,UAAU,YAAY,QAAQ,WAAW,IAAI,SAAS,KAAK,QAAQ,UAAU,QAAQ,CAAC,CAAC,KAAK;AAAA,IACvK;AAEA,WAAO,EAAE,OAAO,SAAS,SAAS,GAAI,kBAAkB,EAAE,gBAAgB,IAAI,CAAC,EAAG;AAAA,EACpF;AAAA,EAEA,WAAW,UAAkB,SAA6B;AAExD,UAAM,aAAa,oBAAI,IAAY;AACnC,aAAS,IAAI,GAAG,IAAI,KAAK,UAAU,QAAQ,KAAK;AAC9C,UAAI,KAAK,UAAU,CAAC,EAAG,aAAa,UAAU;AAC5C,mBAAW,IAAI,CAAC;AAAA,MAClB;AAAA,IACF;AAEA,QAAI,WAAW,SAAS,KAAK,QAAQ,WAAW,EAAG;AAGnD,UAAM,aAA2B,CAAC;AAClC,aAAS,IAAI,GAAG,IAAI,KAAK,UAAU,QAAQ,KAAK;AAC9C,UAAI,CAAC,WAAW,IAAI,CAAC,GAAG;AACtB,cAAM,MAAM,KAAK,UAAU,CAAC;AAC5B,mBAAW,KAAK;AAAA,UACd,UAAU,IAAI;AAAA,UACd,MAAM,IAAI;AAAA,UACV,MAAM,IAAI;AAAA,UACV,WAAW;AAAA,UACX,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAAA,IACF;AACA,eAAW,KAAK,GAAG,OAAO;AAC1B,SAAK,WAAW,YAAY,KAAK,cAAc;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,WAAW,YAAsB,OAAoD;AAC3F,UAAM,SAAS,oBAAI,IAAoB;AACvC,UAAM,IAAI,KAAK,UAAU;AACzB,UAAM,EAAE,IAAI,EAAE,IAAI,KAAK,OAAO;AAE9B,eAAW,QAAQ,YAAY;AAC7B,YAAM,WAAW,MAAM,IAAI,IAAI;AAC/B,UAAI,CAAC,SAAU;AAEf,YAAM,KAAK,SAAS;AAEpB,YAAM,MAAM,KAAK,KAAK,IAAI,KAAK,QAAQ,KAAK,OAAO,CAAC;AAEpD,iBAAW,EAAE,UAAU,cAAc,KAAK,UAAU;AAClD,cAAM,MAAM,KAAK,UAAU,QAAQ;AACnC,cAAM,KAAK;AACX,cAAM,SAAS,IAAI;AAGnB,cAAM,YAAY,MAAM,KAAK;AAC7B,cAAM,cAAc,KAAK,MAAM,IAAI,IAAI,KAAK,SAAS,KAAK;AAC1D,cAAM,YAAY,OAAO,YAAY;AAErC,eAAO,IAAI,WAAW,OAAO,IAAI,QAAQ,KAAK,KAAK,SAAS;AAAA,MAC9D;AAAA,IACF;AAGA,UAAM,cAAc,WAAW,KAAK,EAAE;AACtC,eAAW,CAAC,QAAQ,KAAK,KAAK,QAAQ;AACpC,YAAM,MAAM,KAAK,UAAU,MAAM;AACjC,YAAM,YAAY,IAAI,KAAK,YAAY;AACvC,UAAI,cAAc,eAAe,cAAc,WAAW,KAAK,GAAG,GAAG;AACnE,eAAO,IAAI,QAAQ,QAAQ,CAAG;AAAA,MAChC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,YACN,SACA,WACA,SACqB;AACrB,UAAM,SAAS,IAAI,IAAI,OAAO;AAC9B,eAAW,CAAC,QAAQ,KAAK,KAAK,WAAW;AACvC,YAAM,WAAW,OAAO,IAAI,MAAM;AAClC,YAAM,YAAY,QAAQ;AAC1B,UAAI,aAAa,QAAW;AAC1B,eAAO,IAAI,QAAQ,KAAK,IAAI,UAAU,SAAS,CAAC;AAAA,MAClD,OAAO;AACL,eAAO,IAAI,QAAQ,SAAS;AAAA,MAC9B;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,YAAY,YAAsB,cAAgC;AACxE,QAAI,WAAW,SAAS,EAAG,QAAO;AAElC,QAAI,gBAAgB;AACpB,aAAS,IAAI,GAAG,IAAI,WAAW,SAAS,GAAG,KAAK;AAC9C,YAAM,OAAO,aAAa,UAAU,CAAC,MAAM,EAAE,SAAS,WAAW,CAAC,CAAE,CAAC;AACrE,YAAM,OAAO,aAAa,UAAU,CAAC,MAAM,EAAE,SAAS,WAAW,IAAI,CAAC,CAAE,CAAC;AACzE,UAAI,QAAQ,KAAK,QAAQ,KAAK,KAAK,IAAI,OAAO,IAAI,MAAM,GAAG;AACzD;AAAA,MACF;AAAA,IACF;AAEA,WAAO,IAAI,gBAAgB;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,gBAAgB,MAAwB;AAC9C,UAAM,WAAqB,CAAC;AAC5B,aAAS,IAAI,GAAG,KAAK,KAAK,SAAS,GAAG,KAAK;AACzC,eAAS,KAAK,KAAK,UAAU,GAAG,IAAI,CAAC,CAAC;AAAA,IACxC;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,aACN,gBACA,cACA,OACgB;AAChB,UAAM,UAAU,CAAC,GAAG,eAAe,QAAQ,CAAC,EACzC,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,EAC1B,MAAM,GAAG,KAAK;AAEjB,WAAO,QAAQ,IAAI,CAAC,CAAC,QAAQ,QAAQ,MAAM;AACzC,YAAM,MAAM,KAAK,UAAU,MAAM;AACjC,YAAM,KAAK,KAAK,eAAe,IAAI,IAAI,QAAQ,KAAK;AACpD,aAAO;AAAA,QACL,UAAU,IAAI;AAAA,QACd,MAAM,IAAI;AAAA,QACV,MAAM,IAAI;AAAA,QACV,UAAU,IAAI;AAAA,QACd,gBAAgB,aAAa,IAAI,MAAM,KAAK;AAAA,QAC5C,iBAAiB;AAAA,QACjB,eAAe;AAAA,MACjB;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEQ,cAAc,OAAe,OAA+B;AAClE,WAAO;AAAA,MACL;AAAA,MACA,SAAS,CAAC;AAAA,MACV,SAAS;AAAA,QACP,YAAY;AAAA,QACZ,aAAa;AAAA,QACb,iBAAiB;AAAA,QACjB,cAAc;AAAA,QACd,WAAW,YAAY,IAAI,IAAI;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AACF;;;AHpZA,IAAMC,OAAM,aAAa,aAAa;AAEtC,IAAMC,eAAcC,GAAE,OAAO;AAAA,EAC3B,OAAOA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACvB,aAAaA,GAAE,OAAO,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,QAAQ,GAAI;AAAA,EACxD,UAAUA,GAAE,KAAK,CAAC,YAAY,cAAc,YAAY,CAAC,EAAE,SAAS,EAAE,QAAQ,UAAU;AAAA,EACxF,OAAOA,GAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,IAAI;AAAA,EAC1C,YAAYA,GAAE,KAAK,CAAC,OAAO,QAAQ,CAAC,EAAE,SAAS,EAAE,QAAQ,KAAK;AAChE,CAAC;AAEM,SAAS,uBACd,SACA,SACA,WACA,WAAW,SACX,cACA;AACA,QAAM,YAAY,IAAI,iBAAiB;AACvC,QAAM,SAAsB,gBAAgB,IAAI,aAAa;AAE7D,QAAM,WAAW,MAAM;AACrB,UAAM,YAAY,wBAAwB,QAAQ;AAClD,QAAI,UAAU,YAAY,EAAG,QAAO;AACpC,WAAO,sBAAsB,OAAO;AAAA,EACtC;AAEA,MAAI,gBAAgB;AAEpB,SAAO,CAAC,SAAkC;AACxC,QAAI;AACF,YAAM,SAASD,aAAY,UAAU,IAAI;AACzC,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAS,OAAO,MAAM,QAAQ,CAAC,EAAE,CAAC;AAAA,QAC3G;AAAA,MACF;AAEA,YAAM,EAAE,OAAO,aAAa,UAAU,WAAW,IAAI,OAAO;AAC5D,YAAM,QAAQ,SAAS;AAGvB,UAAI,eAAe,SAAS,aAAa,cAAc;AAErD,cAAM,mBAAmB,MAAM;AAC/B,YAAI,qBAAqB,eAAe;AACtC,gBAAM,WAAW,MAAM,SAAS;AAEhC,gBAAM,iBAAiB,oBAAI,IAAoB;AAC/C,cAAI,kBAAkB;AACtB,qBAAW,QAAQ,UAAU;AAC3B,kBAAM,QAAQ,MAAM,gBAAgB,KAAK,QAAQ,EAAE;AACnD,gBAAI,QAAQ,gBAAiB,mBAAkB;AAAA,UACjD;AACA,qBAAW,QAAQ,UAAU;AAC3B,kBAAM,QAAQ,MAAM,gBAAgB,KAAK,QAAQ,EAAE;AACnD,2BAAe,IAAI,KAAK,UAAU,QAAQ,eAAe;AAAA,UAC3D;AAEA,iBAAO,WAAW,UAAU,cAAc;AAC1C,0BAAgB;AAChB,UAAAD,KAAI,KAAK,kBAAkB,OAAO,QAAQ,CAAC,KAAK,SAAS,MAAM,WAAW;AAAA,QAC5E;AAEA,cAAM,eAAe,OAAO,OAAO,OAAO,GAAG;AAG7C,cAAM,UASD,CAAC;AACN,YAAI,cAAc;AAElB,mBAAW,MAAM,aAAa,SAAS;AACrC,gBAAM,OAAO,MAAM,QAAQ,GAAG,QAAQ;AACtC,gBAAM,SAAS,OAAO,UAAU,qBAAqB,IAAI,IAAI;AAE7D,cAAI,cAAc,SAAS,YAAa;AACxC,kBAAQ,KAAK;AAAA,YACX,UAAU,GAAG;AAAA,YACb,MAAM,GAAG;AAAA,YACT,MAAM,GAAG;AAAA,YACT,MAAM,GAAG;AAAA,YACT,gBAAgB,KAAK,MAAM,GAAG,iBAAiB,GAAI,IAAI;AAAA,YACvD,iBAAiB,KAAK,MAAM,GAAG,kBAAkB,GAAI,IAAI;AAAA,YACzD,eAAe,KAAK,MAAM,GAAG,gBAAgB,GAAI,IAAI;AAAA,YACrD;AAAA,UACF,CAAC;AACD,yBAAe;AAAA,QACjB;AAEA,cAAMG,WAAU,QAAQ,KAAK,KAAK,UAAU,aAAa;AAAA,UACvD;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,eAAe,aAAa;AAAA,UAC5B,GAAI,aAAa,kBAAkB,EAAE,iBAAiB,aAAa,gBAAgB,IAAI,CAAC;AAAA,QAC1F,CAAC,CAAC,CAAC;AAEH,cAAMC,WAAiD,CAAC;AACxD,YAAI,WAAW;AACb,gBAAM,UAAU,UAAU,MAAM,QAAQ,iBAAiB,CAAC;AAC1D,cAAI,QAAS,CAAAA,SAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,gBAAM,QAAQ,OAAO,GAAG,CAAC;AAAA,QAC3E;AACA,QAAAA,SAAQ,KAAK,EAAE,MAAM,QAAQ,MAAMD,SAAQ,CAAC;AAE5C,eAAO,EAAE,SAAAC,SAAQ;AAAA,MACnB;AAGA,YAAM,SAAS,UAAU,eAAe,OAAO,OAAO,UAAU,WAAW;AAE3E,YAAM,UAAU,QAAQ,KAAK,KAAK,UAAU,aAAa,MAA4C,CAAC,CAAC;AAEvG,YAAM,UAAiD,CAAC;AACxD,UAAI,WAAW;AACb,cAAM,UAAU,UAAU,MAAM,QAAQ,iBAAiB,CAAC;AAC1D,YAAI,QAAS,SAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,gBAAM,QAAQ,OAAO,GAAG,CAAC;AAAA,MAC3E;AACA,cAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC;AAE5C,aAAO,EAAE,QAAQ;AAAA,IACnB,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAU,IAAc,QAAQ,CAAC,EAAE,CAAC;AAAA,MAC7G;AAAA,IACF;AAAA,EACF;AACF;;;AIlJA,SAAS,KAAAC,UAAS;AASlB,IAAMC,eAAcC,GAAE,OAAO;AAAA,EAC3B,SAASA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACzB,MAAMA,GAAE,KAAK,CAAC,YAAY,SAAS,aAAa,UAAU,YAAY,MAAM,CAAC,EAAE,SAAS;AAAA,EACxF,aAAaA,GAAE,OAAO,EAAE,SAAS;AAAA,EACjC,OAAOA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE;AAAA,EAC7D,MAAMA,GAAE,KAAK,CAAC,SAAS,KAAK,CAAC,EAAE,SAAS,EAAE,QAAQ,OAAO;AAC3D,CAAC;AAEM,SAAS,oBACd,SACA,SACA,WACA,WAAW,SACX,cACA;AACA,QAAM,SAAsB,gBAAgB,IAAI,aAAa;AAC7D,MAAI,mBAAmB;AAEvB,QAAM,WAAW,MAAM;AACrB,UAAM,YAAY,wBAAwB,QAAQ;AAClD,QAAI,UAAU,YAAY,EAAG,QAAO;AACpC,WAAO,sBAAsB,OAAO;AAAA,EACtC;AAEA,SAAO,CAAC,SAAkC;AACxC,QAAI;AACF,YAAM,SAASD,aAAY,UAAU,IAAI;AACzC,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAS,OAAO,MAAM,QAAQ,CAAC,EAAE,CAAC;AAAA,QAC3G;AAAA,MACF;AAEA,YAAM,EAAE,SAAS,MAAM,aAAa,OAAO,KAAK,IAAI,OAAO;AAC3D,YAAM,QAAQ,SAAS;AACvB,YAAM,WAAW,MAAM,SAAS;AAGhC,UAAI,SAAS,OAAO;AAClB,YAAI,SAAS,WAAW,kBAAkB;AACxC,iBAAO,WAAW,QAAQ;AAC1B,6BAAmB,SAAS;AAAA,QAC9B;AAEA,cAAM,eAAe,OAAO,OAAO,SAAS,KAAK;AACjD,YAAI,aAAa,aAAa;AAG9B,YAAI,MAAM;AACR,uBAAa,WAAW,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI;AAAA,QACvD;AAEA,YAAI,aAAa;AACf,gBAAM,KAAK,YAAY,YAAY;AACnC,uBAAa,WAAW,OAAO,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,SAAS,EAAE,CAAC;AAAA,QAC7E;AAEA,cAAME,WAAU,WAAW,MAAM,GAAG,KAAK,EAAE,IAAI,CAAC,MAAM;AACpD,gBAAM,OAAO,MAAM,QAAQ,EAAE,QAAQ;AACrC,iBAAO;AAAA,YACL,UAAU,EAAE;AAAA,YACZ,MAAM,EAAE;AAAA,YACR,MAAM,EAAE;AAAA,YACR,MAAM,EAAE;AAAA,YACR,WAAW,MAAM,aAAa;AAAA,YAC9B,SAAS,MAAM,WAAW;AAAA,YAC1B,gBAAgB,KAAK,MAAM,EAAE,iBAAiB,GAAI,IAAI;AAAA,UACxD;AAAA,QACF,CAAC;AAED,cAAMC,WAAU,QAAQ,KAAK,KAAK,UAAU,aAAa;AAAA,UACvD,cAAc,WAAW;AAAA,UACzB,SAAAD;AAAA,UACA,eAAe,aAAa;AAAA,UAC5B,GAAI,aAAa,kBAAkB,EAAE,iBAAiB,aAAa,gBAAgB,IAAI,CAAC;AAAA,QAC1F,CAAC,CAAC,CAAC;AAEH,cAAME,WAAiD,CAAC;AACxD,YAAI,WAAW;AACb,gBAAM,UAAU,UAAU,MAAM,QAAQ,iBAAiB,CAAC;AAC1D,cAAI,QAAS,CAAAA,SAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,gBAAM,QAAQ,OAAO,GAAG,CAAC;AAAA,QAC3E;AACA,QAAAA,SAAQ,KAAK,EAAE,MAAM,QAAQ,MAAMD,SAAQ,CAAC;AAE5C,eAAO,EAAE,SAAAC,SAAQ;AAAA,MACnB;AAGA,UAAI;AACJ,UAAI;AACF,cAAM,QAAQ,IAAI,OAAO,SAAS,GAAG;AACrC,kBAAU,CAAC,SAAiB,MAAM,KAAK,IAAI;AAAA,MAC7C,QAAQ;AACN,cAAM,eAAe,QAAQ,YAAY;AACzC,kBAAU,CAAC,SAAiB,KAAK,YAAY,EAAE,SAAS,YAAY;AAAA,MACtE;AAEA,YAAM,UAAU,SAAS,OAAO,CAAC,SAAS;AACxC,YAAI,CAAC,QAAQ,KAAK,IAAI,EAAG,QAAO;AAChC,YAAI,QAAQ,KAAK,SAAS,KAAM,QAAO;AACvC,YAAI,aAAa;AACf,gBAAM,OAAO,KAAK,SAAS,MAAM,IAAI,EAAE,CAAC,KAAK;AAC7C,cAAI,CAAC,KAAK,YAAY,EAAE,SAAS,YAAY,YAAY,CAAC,EAAG,QAAO;AAAA,QACtE;AACA,eAAO;AAAA,MACT,CAAC;AAED,YAAM,UAAU,QAAQ,MAAM,GAAG,KAAK,EAAE,IAAI,CAAC,UAAU;AAAA,QACrD,UAAU,KAAK;AAAA,QACf,MAAM,KAAK;AAAA,QACX,MAAM,KAAK;AAAA,QACX,MAAM,KAAK,SAAS,MAAM,IAAI,EAAE,CAAC;AAAA,QACjC,WAAW,KAAK;AAAA,QAChB,SAAS,KAAK;AAAA,MAChB,EAAE;AAEF,YAAM,UAAU,QAAQ,KAAK,KAAK,UAAU,aAAa;AAAA,QACvD,cAAc,QAAQ;AAAA,QACtB;AAAA,MACF,CAAC,CAAC,CAAC;AAEH,YAAM,UAAiD,CAAC;AACxD,UAAI,WAAW;AACb,cAAM,UAAU,UAAU,MAAM,QAAQ,iBAAiB,CAAC;AAC1D,YAAI,QAAS,SAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,gBAAM,QAAQ,OAAO,GAAG,CAAC;AAAA,MAC3E;AACA,cAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC;AAE5C,aAAO,EAAE,QAAQ;AAAA,IACnB,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAU,IAAc,QAAQ,CAAC,EAAE,CAAC;AAAA,MAC7G;AAAA,IACF;AAAA,EACF;AACF;;;AChJA,SAAS,KAAAC,WAAS;AAQlB,IAAMC,gBAAcC,IAAE,OAAO;AAAA,EAC3B,OAAOA,IAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,QAAQ;AAAA,EAC7C,UAAUA,IAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE;AACzD,CAAC;AAEM,SAAS,wBACd,SACA,KACA,SACA,WACA,WAAW,SACX;AACA,QAAM,WAAW,MAAM;AACrB,UAAM,YAAY,wBAAwB,QAAQ;AAClD,QAAI,UAAU,YAAY,EAAG,QAAO;AACpC,WAAO,sBAAsB,OAAO;AAAA,EACtC;AAEA,SAAO,OAAO,SAAkC;AAC9C,QAAI;AACF,YAAM,SAASD,cAAY,UAAU,IAAI;AACzC,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAS,OAAO,MAAM,QAAQ,CAAC,EAAE,CAAC;AAAA,QAC3G;AAAA,MACF;AAEA,YAAM,EAAE,OAAO,SAAS,IAAI,OAAO;AACnC,YAAM,eAAe,MAAM,IAAI,gBAAgB,KAAK;AACpD,YAAM,QAAQ,SAAS;AAGvB,YAAM,cAAc,oBAAI,IAAyG;AACjI,iBAAW,QAAQ,MAAM,SAAS,GAAG;AACnC,cAAM,OAAO,KAAK,SAAS,MAAM,IAAI,EAAE,CAAC,KAAK;AAC7C,cAAM,WAAW,YAAY,IAAI,IAAI,KAAK,CAAC;AAC3C,iBAAS,KAAK,EAAE,UAAU,KAAK,UAAU,MAAM,KAAK,MAAM,MAAM,KAAK,MAAM,WAAW,KAAK,WAAW,SAAS,KAAK,QAAQ,CAAC;AAC7H,oBAAY,IAAI,MAAM,QAAQ;AAAA,MAChC;AAEA,YAAM,QAAuI,CAAC;AAC9I,UAAI,eAAe;AAEnB,iBAAW,YAAY,aAAa,MAAM,GAAG,QAAQ,GAAG;AACtD,cAAM,UAAU,YAAY,IAAI,QAAQ;AACxC,YAAI,WAAW,QAAQ,SAAS,GAAG;AACjC,gBAAM,KAAK,EAAE,MAAM,UAAU,QAAQ,CAAC;AACtC,0BAAgB,QAAQ;AAAA,QAC1B;AAAA,MACF;AAEA,YAAM,UAAU,QAAQ,KAAK,KAAK,UAAU,aAAa;AAAA,QACvD;AAAA,QACA,cAAc,MAAM;AAAA,QACpB,gBAAgB;AAAA,QAChB;AAAA,MACF,CAAC,CAAC,CAAC;AAEH,YAAM,UAAiD,CAAC;AACxD,UAAI,WAAW;AACb,cAAM,UAAU,UAAU,MAAM,QAAQ,iBAAiB,CAAC;AAC1D,YAAI,QAAS,SAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,gBAAM,QAAQ,OAAO,GAAG,CAAC;AAAA,MAC3E;AACA,cAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC;AAE5C,aAAO,EAAE,QAAQ;AAAA,IACnB,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAU,IAAc,QAAQ,CAAC,EAAE,CAAC;AAAA,MAC7G;AAAA,IACF;AAAA,EACF;AACF;;;AChFA,SAAS,KAAAE,WAAS;AAQlB,IAAMC,gBAAcC,IAAE,OAAO;AAAA,EAC3B,UAAUA,IAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC1B,WAAWA,IAAE,MAAMA,IAAE,KAAK,CAAC,WAAW,SAAS,WAAW,cAAc,MAAM,CAAC,CAAC,EAAE,SAAS;AAAA,EAC3F,YAAYA,IAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,KAAK;AAAA,EAChD,UAAUA,IAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC;AAAA,EAC9D,QAAQA,IAAE,OAAO,EAAE,SAAS,EAAE,SAAS,qEAAqE;AAC9G,CAAC;AAEM,SAAS,oBACd,SACA,SACA,WACA,WAAW,SACX;AACA,QAAM,WAAW,MAAM;AACrB,UAAM,YAAY,wBAAwB,QAAQ;AAClD,QAAI,UAAU,YAAY,EAAG,QAAO;AACpC,WAAO,sBAAsB,OAAO;AAAA,EACtC;AAEA,SAAO,CAAC,SAAkC;AACxC,QAAI;AACF,YAAM,SAASD,cAAY,UAAU,IAAI;AACzC,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAS,OAAO,MAAM,QAAQ,CAAC,EAAE,CAAC;AAAA,QAC3G;AAAA,MACF;AAEA,YAAM,EAAE,UAAU,WAAW,YAAY,SAAS,IAAI,OAAO;AAC7D,YAAM,QAAQ,SAAS;AAEvB,UAAI,CAAC,MAAM,QAAQ,QAAQ,GAAG;AAC5B,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,OAAO,MAAM,kEAAkE,CAAC,EAAE,CAAC;AAAA,QACtJ;AAAA,MACF;AAEA,YAAM,YAOD,CAAC;AAEN,UAAI,CAAC,YAAY;AAEf,cAAM,eAAe,MAAM,gBAAgB,QAAQ;AACnD,cAAM,OAAO,oBAAI,IAAgE;AACjF,mBAAW,QAAQ,cAAc;AAC/B,cAAI,aAAa,CAAC,UAAU,SAAS,KAAK,IAA+D,EAAG;AAC5G,gBAAM,OAAO,MAAM,QAAQ,KAAK,IAAI;AACpC,cAAI,MAAM;AACR,kBAAM,WAAW,KAAK,IAAI,KAAK,QAAQ;AACvC,gBAAI,UAAU;AACZ,kBAAI,CAAC,SAAS,UAAU,SAAS,KAAK,IAAI,GAAG;AAC3C,yBAAS,UAAU,KAAK,KAAK,IAAI;AAAA,cACnC;AAAA,YACF,OAAO;AACL,oBAAM,QAAQ;AAAA,gBACZ,UAAU,KAAK;AAAA,gBACf,MAAM,KAAK;AAAA,gBACX,MAAM,KAAK;AAAA,gBACX,MAAM,KAAK,SAAS,MAAM,IAAI,EAAE,CAAC,KAAK;AAAA,gBACtC,UAAU,KAAK;AAAA,gBACf,OAAO;AAAA,cACT;AACA,mBAAK,IAAI,KAAK,UAAU,EAAE,MAAM,OAAO,WAAW,CAAC,KAAK,IAAI,EAAE,CAAC;AAC/D,wBAAU,KAAK,KAAK;AAAA,YACtB;AAAA,UACF;AAAA,QACF;AAAA,MACF,OAAO;AAEL,cAAM,UAAU,oBAAI,IAAY,CAAC,QAAQ,CAAC;AAC1C,cAAM,QAA8C,CAAC,EAAE,IAAI,UAAU,OAAO,EAAE,CAAC;AAE/E,eAAO,MAAM,SAAS,GAAG;AACvB,gBAAM,UAAU,MAAM,MAAM;AAC5B,cAAI,QAAQ,SAAS,SAAU;AAE/B,gBAAM,eAAe,MAAM,gBAAgB,QAAQ,EAAE;AACrD,qBAAW,QAAQ,cAAc;AAC/B,gBAAI,aAAa,CAAC,UAAU,SAAS,KAAK,IAA+D,EAAG;AAC5G,gBAAI,QAAQ,IAAI,KAAK,IAAI,EAAG;AAC5B,oBAAQ,IAAI,KAAK,IAAI;AAErB,kBAAM,OAAO,MAAM,QAAQ,KAAK,IAAI;AACpC,gBAAI,MAAM;AACR,oBAAM,QAAQ,QAAQ,QAAQ;AAC9B,wBAAU,KAAK;AAAA,gBACb,UAAU,KAAK;AAAA,gBACf,MAAM,KAAK;AAAA,gBACX,MAAM,KAAK;AAAA,gBACX,MAAM,KAAK,SAAS,MAAM,IAAI,EAAE,CAAC,KAAK;AAAA,gBACtC,UAAU,KAAK;AAAA,gBACf;AAAA,cACF,CAAC;AACD,oBAAM,KAAK,EAAE,IAAI,KAAK,MAAM,MAAM,CAAC;AAAA,YACrC;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,gBAAU,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAG1C,YAAM,WAAW,eAAe,WAAW,OAAO,KAAK,MAAM;AAE7D,YAAM,UAAU,QAAQ,KAAK,KAAK,UAAU,aAAa;AAAA,QACvD;AAAA,QACA,eAAe,SAAS;AAAA,QACxB,WAAW;AAAA,MACb,CAAC,CAAC,CAAC;AAEH,YAAM,UAAiD,CAAC;AACxD,UAAI,WAAW;AACb,cAAM,UAAU,UAAU,MAAM,QAAQ,iBAAiB,CAAC;AAC1D,YAAI,QAAS,SAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,gBAAM,QAAQ,OAAO,GAAG,CAAC;AAAA,MAC3E;AACA,cAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC;AAE5C,aAAO,EAAE,QAAQ;AAAA,IACnB,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAU,IAAc,QAAQ,CAAC,EAAE,CAAC;AAAA,MAC7G;AAAA,IACF;AAAA,EACF;AACF;;;AC5IA,SAAS,KAAAE,WAAS;AAOlB,IAAMC,gBAAcC,IAAE,OAAO;AAAA,EAC3B,UAAUA,IAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACrC,WAAWA,IAAE,KAAK,CAAC,aAAa,eAAe,MAAM,CAAC,EAAE,SAAS,EAAE,QAAQ,MAAM;AACnF,CAAC;AAEM,SAAS,wBACd,SACA,SACA,WACA,WAAW,SACX;AACA,QAAM,WAAW,MAAM;AACrB,UAAM,YAAY,wBAAwB,QAAQ;AAClD,QAAI,UAAU,YAAY,EAAG,QAAO;AACpC,WAAO,sBAAsB,OAAO;AAAA,EACtC;AAEA,SAAO,CAAC,SAAkC;AACxC,QAAI;AACF,YAAM,SAASD,cAAY,UAAU,IAAI;AACzC,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAS,OAAO,MAAM,QAAQ,CAAC,EAAE,CAAC;AAAA,QAC3G;AAAA,MACF;AAEA,YAAM,EAAE,UAAU,UAAU,IAAI,OAAO;AACvC,YAAM,QAAQ,SAAS;AAEvB,UAAI,UAAU;AACZ,eAAO,aAAa,OAAO,UAAU,WAAW,SAAS,WAAW,OAAO;AAAA,MAC7E;AAEA,aAAO,WAAW,OAAO,SAAS,WAAW,OAAO;AAAA,IACtD,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAU,IAAc,QAAQ,CAAC,EAAE,CAAC;AAAA,MAC7G;AAAA,IACF;AAAA,EACF;AAEA,WAAS,aACP,OACA,UACA,WACA,aACA,gBACA,aACA;AACA,QAAI,CAAC,MAAM,QAAQ,QAAQ,GAAG;AAC5B,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,OAAO,MAAM,kEAAkE,CAAC,EAAE,CAAC;AAAA,MACtJ;AAAA,IACF;AAGA,UAAM,YAA8B,CAAC;AACrC,UAAM,cAAgC,CAAC;AAEvC,UAAM,kBAAkB,CAAC,SAAiB,SAAS,aAAa,SAAS;AAGzE,QAAI,cAAc,eAAe,cAAc,QAAQ;AACrD,YAAM,UAAU,oBAAI,IAAY,CAAC,QAAQ,CAAC;AAC1C,YAAM,QAA8C,CAAC,EAAE,IAAI,UAAU,OAAO,EAAE,CAAC;AAE/E,aAAO,MAAM,SAAS,GAAG;AACvB,cAAM,UAAU,MAAM,MAAM;AAC5B,mBAAW,QAAQ,MAAM,gBAAgB,QAAQ,EAAE,GAAG;AACpD,cAAI,CAAC,gBAAgB,KAAK,IAAI,EAAG;AACjC,cAAI,QAAQ,IAAI,KAAK,EAAE,EAAG;AAC1B,kBAAQ,IAAI,KAAK,EAAE;AAEnB,gBAAM,OAAO,MAAM,QAAQ,KAAK,EAAE;AAClC,cAAI,MAAM;AACR,kBAAM,QAAQ,QAAQ,QAAQ;AAC9B,sBAAU,KAAK;AAAA,cACb,UAAU,KAAK;AAAA,cACf,MAAM,KAAK;AAAA,cACX,MAAM,KAAK;AAAA,cACX,MAAM,KAAK,SAAS,MAAM,IAAI,EAAE,CAAC,KAAK;AAAA,cACtC,UAAU,KAAK;AAAA,cACf;AAAA,YACF,CAAC;AACD,kBAAM,KAAK,EAAE,IAAI,KAAK,IAAI,MAAM,CAAC;AAAA,UACnC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,QAAI,cAAc,iBAAiB,cAAc,QAAQ;AACvD,YAAM,UAAU,oBAAI,IAAY,CAAC,QAAQ,CAAC;AAC1C,YAAM,QAA8C,CAAC,EAAE,IAAI,UAAU,OAAO,EAAE,CAAC;AAE/E,aAAO,MAAM,SAAS,GAAG;AACvB,cAAM,UAAU,MAAM,MAAM;AAC5B,mBAAW,QAAQ,MAAM,gBAAgB,QAAQ,EAAE,GAAG;AACpD,cAAI,CAAC,gBAAgB,KAAK,IAAI,EAAG;AACjC,cAAI,QAAQ,IAAI,KAAK,IAAI,EAAG;AAC5B,kBAAQ,IAAI,KAAK,IAAI;AAErB,gBAAM,OAAO,MAAM,QAAQ,KAAK,IAAI;AACpC,cAAI,MAAM;AACR,kBAAM,QAAQ,QAAQ,QAAQ;AAC9B,wBAAY,KAAK;AAAA,cACf,UAAU,KAAK;AAAA,cACf,MAAM,KAAK;AAAA,cACX,MAAM,KAAK;AAAA,cACX,MAAM,KAAK,SAAS,MAAM,IAAI,EAAE,CAAC,KAAK;AAAA,cACtC,UAAU,KAAK;AAAA,cACf;AAAA,YACF,CAAC;AACD,kBAAM,KAAK,EAAE,IAAI,KAAK,MAAM,MAAM,CAAC;AAAA,UACrC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,UAAM,SAAkC,EAAE,SAAS;AACnD,QAAI,cAAc,eAAe,cAAc,OAAQ,QAAO,YAAY;AAC1E,QAAI,cAAc,iBAAiB,cAAc,OAAQ,QAAO,cAAc;AAE9E,UAAM,UAAU,YAAY,KAAK,KAAK,UAAU,aAAa,MAAM,CAAC,CAAC;AACrE,UAAM,UAAiD,CAAC;AACxD,QAAI,gBAAgB;AAClB,YAAM,UAAU,eAAe,MAAM,YAAY,iBAAiB,CAAC;AACnE,UAAI,QAAS,SAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,gBAAM,QAAQ,OAAO,GAAG,CAAC;AAAA,IAC3E;AACA,YAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC;AAE5C,WAAO,EAAE,QAAQ;AAAA,EACnB;AAEA,WAAS,WACP,OACA,aACA,gBACA,aACA;AACA,UAAM,kBAAkB,CAAC,SAAiB,SAAS,aAAa,SAAS;AACzE,UAAM,iBAAiB,MAAM,SAAS,EAAE,OAAO,CAAC,MAAM,gBAAgB,EAAE,IAAI,CAAC;AAG7E,UAAM,WAAW,oBAAI,IAAY;AACjC,eAAW,QAAQ,gBAAgB;AACjC,eAAS,IAAI,KAAK,IAAI;AACtB,eAAS,IAAI,KAAK,EAAE;AAAA,IACtB;AAGA,UAAM,UAAU,IAAI,IAAI,eAAe,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AACzD,UAAM,QAAQ,CAAC,GAAG,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC;AAG3D,UAAM,UAAU,MAAM,SAAS,IAAI,QAAQ,CAAC,GAAG,QAAQ;AAIvD,aAAS,UAAU,QAAgBE,UAA4C;AAC7E,YAAM,OAAO,MAAM,QAAQ,MAAM;AACjC,UAAI,CAAC,KAAM,QAAO;AAClB,MAAAA,SAAQ,IAAI,MAAM;AAElB,YAAM,WAAuB,CAAC;AAC9B,iBAAW,QAAQ,MAAM,gBAAgB,MAAM,GAAG;AAChD,YAAI,CAAC,gBAAgB,KAAK,IAAI,EAAG;AACjC,YAAIA,SAAQ,IAAI,KAAK,IAAI,EAAG;AAC5B,cAAM,QAAQ,UAAU,KAAK,MAAMA,QAAO;AAC1C,YAAI,OAAO;AACT,gBAAM,WAAW,KAAK;AACtB,mBAAS,KAAK,KAAK;AAAA,QACrB;AAAA,MACF;AAEA,aAAO;AAAA,QACL,UAAU,KAAK;AAAA,QACf,MAAM,KAAK;AAAA,QACX,MAAM,KAAK;AAAA,QACX,MAAM,KAAK,SAAS,MAAM,IAAI,EAAE,CAAC,KAAK;AAAA,QACtC;AAAA,MACF;AAAA,IACF;AAEA,UAAM,UAAU,oBAAI,IAAY;AAChC,UAAM,cAA0B,CAAC;AACjC,eAAW,UAAU,SAAS;AAC5B,UAAI,QAAQ,IAAI,MAAM,EAAG;AACzB,YAAM,OAAO,UAAU,QAAQ,OAAO;AACtC,UAAI,KAAM,aAAY,KAAK,IAAI;AAAA,IACjC;AAEA,UAAM,UAAU,YAAY,KAAK,KAAK,UAAU,aAAa;AAAA,MAC3D;AAAA,MACA,cAAc,SAAS;AAAA,MACvB,YAAY,eAAe;AAAA,IAC7B,CAAC,CAAC,CAAC;AAEH,UAAM,UAAiD,CAAC;AACxD,QAAI,gBAAgB;AAClB,YAAM,UAAU,eAAe,MAAM,YAAY,iBAAiB,CAAC;AACnE,UAAI,QAAS,SAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,gBAAM,QAAQ,OAAO,GAAG,CAAC;AAAA,IAC3E;AACA,YAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC;AAE5C,WAAO,EAAE,QAAQ;AAAA,EACnB;AACF;;;ACtNA,SAAS,KAAAC,WAAS;;;AC0BlB,IAAM,kBAAkB;AACxB,IAAM,yBAAyB;AAC/B,IAAM,oBAAoB;AAC1B,IAAM,gBAAgB;AAEf,IAAM,qBAAN,MAAyB;AAAA,EAC9B,UAAU,OAAoB,UAA2B,CAAC,GAAmB;AAC3E,UAAM,UAAU,QAAQ,WAAW;AACnC,UAAM,gBAAgB,QAAQ,iBAAiB;AAC/C,UAAM,YAAY,QAAQ,aAAa;AACvC,UAAM,QAAQ,QAAQ,SAAS;AAE/B,UAAM,QAAQ,MAAM,SAAS;AAC7B,UAAM,IAAI,MAAM;AAEhB,QAAI,MAAM,GAAG;AACX,aAAO,EAAE,UAAU,CAAC,GAAG,cAAc,GAAG,YAAY,GAAG,WAAW,KAAK;AAAA,IACzE;AAGA,UAAM,SAAS,oBAAI,IAAoB;AACvC,UAAM,eAAe,IAAI;AACzB,eAAW,QAAQ,OAAO;AACxB,aAAO,IAAI,KAAK,UAAU,YAAY;AAAA,IACxC;AAGA,UAAM,YAAY,oBAAI,IAAoB;AAC1C,eAAW,QAAQ,OAAO;AACxB,gBAAU,IAAI,KAAK,UAAU,MAAM,gBAAgB,KAAK,QAAQ,EAAE,MAAM;AAAA,IAC1E;AAOA,QAAI,aAAa;AACjB,QAAI,YAAY;AAEhB,WAAO,aAAa,eAAe;AACjC,YAAM,YAAY,oBAAI,IAAoB;AAC1C,YAAM,QAAQ,IAAI,WAAW;AAG7B,UAAI,cAAc;AAClB,iBAAW,QAAQ,OAAO;AACxB,aAAK,UAAU,IAAI,KAAK,QAAQ,KAAK,OAAO,GAAG;AAC7C,yBAAe,OAAO,IAAI,KAAK,QAAQ,KAAK;AAAA,QAC9C;AAAA,MACF;AACA,YAAM,kBAAkB,UAAU,cAAc;AAEhD,iBAAW,QAAQ,OAAO;AACxB,YAAI,gBAAgB;AAIpB,cAAM,eAAe,MAAM,gBAAgB,KAAK,QAAQ;AACxD,cAAM,eAAe,oBAAI,IAAY;AACrC,mBAAW,QAAQ,cAAc;AAC/B,cAAI,aAAa,IAAI,KAAK,IAAI,EAAG;AACjC,uBAAa,IAAI,KAAK,IAAI;AAC1B,gBAAM,YAAY,OAAO,IAAI,KAAK,IAAI,KAAK;AAC3C,gBAAM,UAAU,UAAU,IAAI,KAAK,IAAI,KAAK;AAC5C,2BAAiB,YAAY;AAAA,QAC/B;AAEA,kBAAU,IAAI,KAAK,UAAU,OAAO,UAAU,gBAAgB,eAAe;AAAA,MAC/E;AAGA,UAAI,WAAW;AACf,iBAAW,QAAQ,OAAO;AACxB,cAAM,QAAQ,KAAK,KAAK,UAAU,IAAI,KAAK,QAAQ,KAAK,MAAM,OAAO,IAAI,KAAK,QAAQ,KAAK,EAAE;AAC7F,YAAI,QAAQ,SAAU,YAAW;AAAA,MACnC;AAGA,iBAAW,CAAC,IAAI,KAAK,KAAK,WAAW;AACnC,eAAO,IAAI,IAAI,KAAK;AAAA,MACtB;AAEA;AAEA,UAAI,WAAW,WAAW;AACxB,oBAAY;AACZ;AAAA,MACF;AAAA,IACF;AAGA,UAAM,UAA2B,MAAM,IAAI,CAAC,UAAU;AAAA,MACpD,UAAU,KAAK;AAAA,MACf,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,MAAM,KAAK,SAAS,MAAM,IAAI,EAAE,CAAC,KAAK;AAAA,MACtC,OAAO,KAAK,OAAO,OAAO,IAAI,KAAK,QAAQ,KAAK,KAAK,GAAS,IAAI;AAAA,MAClE,UAAU,MAAM,gBAAgB,KAAK,QAAQ,EAAE;AAAA,MAC/C,WAAW,UAAU,IAAI,KAAK,QAAQ,KAAK;AAAA,IAC7C,EAAE;AAGF,YAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAExC,WAAO;AAAA,MACL,UAAU,QAAQ,MAAM,GAAG,KAAK;AAAA,MAChC,cAAc;AAAA,MACd;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;ADlIA,IAAMC,gBAAcC,IAAE,OAAO;AAAA,EAC3B,OAAOA,IAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE;AAAA,EAC7D,MAAMA,IAAE,KAAK,CAAC,YAAY,SAAS,aAAa,UAAU,YAAY,MAAM,CAAC,EAAE,SAAS;AAAA,EACxF,aAAaA,IAAE,OAAO,EAAE,SAAS;AAAA,EACjC,SAASA,IAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,QAAQ,IAAI;AAC3D,CAAC;AAEM,SAAS,0BACd,SACA,SACA,WACA,WAAW,SACX;AACA,QAAM,aAAa,IAAI,mBAAmB;AAC1C,QAAM,WAAW,MAAM;AACrB,UAAM,YAAY,wBAAwB,QAAQ;AAClD,QAAI,UAAU,YAAY,EAAG,QAAO;AACpC,WAAO,sBAAsB,OAAO;AAAA,EACtC;AAEA,SAAO,CAAC,SAAkC;AACxC,QAAI;AACF,YAAM,SAASD,cAAY,UAAU,IAAI;AACzC,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAS,OAAO,MAAM,QAAQ,CAAC,EAAE,CAAC;AAAA,QAC3G;AAAA,MACF;AAEA,YAAM,EAAE,OAAO,MAAM,aAAa,QAAQ,IAAI,OAAO;AACrD,YAAM,QAAQ,SAAS;AAEvB,YAAM,SAAS,WAAW,UAAU,OAAO,EAAE,SAAS,OAAO,MAAM,WAAW,eAAe,IAAI,CAAC;AAGlG,UAAI,WAAW,OAAO;AACtB,UAAI,MAAM;AACR,mBAAW,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI;AAAA,MACnD;AACA,UAAI,aAAa;AACf,cAAM,eAAe,YAAY,YAAY;AAC7C,mBAAW,SAAS,OAAO,CAAC,MAAM,EAAE,KAAK,YAAY,EAAE,SAAS,YAAY,CAAC;AAAA,MAC/E;AACA,iBAAW,SAAS,MAAM,GAAG,KAAK;AAElC,YAAM,UAAU,QAAQ,KAAK,KAAK,UAAU,aAAa;AAAA,QACvD,UAAU;AAAA,QACV,cAAc,OAAO;AAAA,QACrB,YAAY,OAAO;AAAA,QACnB,WAAW,OAAO;AAAA,QAClB;AAAA,MACF,CAAC,CAAC,CAAC;AAEH,YAAM,UAAiD,CAAC;AACxD,UAAI,WAAW;AACb,cAAM,UAAU,UAAU,MAAM,QAAQ,iBAAiB,CAAC;AAC1D,YAAI,QAAS,SAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,gBAAM,QAAQ,OAAO,GAAG,CAAC;AAAA,MAC3E;AACA,cAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC;AAE5C,aAAO,EAAE,QAAQ;AAAA,IACnB,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAU,IAAc,QAAQ,CAAC,EAAE,CAAC;AAAA,MAC7G;AAAA,IACF;AAAA,EACF;AACF;;;AE3EA,SAAS,KAAAE,WAAS;AAClB,SAAS,cAAc,kBAAkB;AACzC,SAAS,YAAY;AAWrB,IAAMC,gBAAcC,IAAE,OAAO;AAAA,EAC3B,OAAOA,IAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,QAAQ;AAAA,EAC7C,UAAUA,IAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE;AAAA,EACvD,YAAYA,IAAE,KAAK,CAAC,aAAa,UAAU,WAAW,CAAC,EAAE,SAAS;AACpE,CAAC;AAED,SAAS,cAAc,UAA4D;AACjF,QAAM,OAAO,KAAK,UAAU,SAAS,iBAAiB;AACtD,MAAI,CAAC,WAAW,IAAI,EAAG,QAAO;AAC9B,MAAI;AACF,UAAM,SAAyB,KAAK,MAAM,aAAa,MAAM,OAAO,CAAC;AACrE,WAAO,gBAAgB,MAAM;AAAA,EAC/B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,kBACd,SACA,KACA,SACA,WACA,WAAW,SACX;AACA,QAAM,aAAa,IAAI,sBAAsB;AAC7C,QAAM,WAAW,MAAM;AACrB,UAAM,YAAY,wBAAwB,QAAQ;AAClD,QAAI,UAAU,YAAY,EAAG,QAAO;AACpC,WAAO,sBAAsB,OAAO;AAAA,EACtC;AAEA,SAAO,OAAO,SAAkC;AAC9C,QAAI;AACF,YAAM,SAASD,cAAY,UAAU,IAAI;AACzC,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAS,OAAO,MAAM,QAAQ,CAAC,EAAE,CAAC;AAAA,QAC3G;AAAA,MACF;AAEA,YAAM,EAAE,OAAO,UAAU,YAAY,WAAW,IAAI,OAAO;AAG3D,YAAM,eAAe,MAAM,IAAI,gBAAgB,KAAK;AACpD,UAAI,aAAa,WAAW,GAAG;AAC7B,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,cAAc,GAAG,gBAAgB,GAAG,aAAa,GAAG,WAAW,OAAO,OAAO,CAAC,GAAG,SAAS,EAAE,gBAAgB,GAAG,aAAa,GAAG,gBAAgB,GAAG,iBAAiB,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;AAAA,QAC/O;AAAA,MACF;AAGA,YAAM,QAAQ,SAAS;AACvB,YAAM,cAAc,cAAc,QAAQ;AAG1C,YAAM,WAAW,MAAM,SAAS;AAChC,YAAM,cAAc,oBAAI,IAA6B;AACrD,iBAAW,QAAQ,UAAU;AAC3B,cAAM,OAAO,KAAK,SAAS,MAAM,IAAI,EAAE,CAAC;AACxC,YAAI,OAAO,YAAY,IAAI,IAAI;AAC/B,YAAI,CAAC,MAAM;AAAE,iBAAO,CAAC;AAAG,sBAAY,IAAI,MAAM,IAAI;AAAA,QAAG;AACrD,aAAK,KAAK,IAAI;AAAA,MAChB;AAGA,YAAM,eAAe,aAAa,MAAM,GAAG,QAAQ;AACnD,UAAI,cAAc;AAClB,UAAI,iBAAiB;AACrB,UAAI,cAAc;AAClB,UAAI,iBAAiB;AACrB,YAAM,kBAA4B,CAAC;AAEnC,YAAM,QAgBD,CAAC;AAEN,iBAAW,YAAY,cAAc;AACnC,cAAM,UAAU,YAAY,IAAI,QAAQ;AACxC,YAAI,CAAC,WAAW,QAAQ,WAAW,EAAG;AAEtC,cAAM,cAA0C,CAAC;AAEjD,mBAAW,OAAO,SAAS;AACzB,gBAAM,SAAS,WAAW,UAAU,OAAO,IAAI,UAAU,WAAW;AAEpE,cAAI,WAAW,OAAO;AACtB,cAAI,YAAY;AACd,uBAAW,SAAS,OAAO,OAAK,EAAE,eAAe,UAAU;AAAA,UAC7D;AAEA,gBAAM,cAAc,SAAS;AAC7B,gBAAM,YAAY,SAAS,OAAO,OAAK,EAAE,eAAe,WAAW,EAAE;AACrE,gBAAM,SAAS,SAAS,OAAO,OAAK,EAAE,eAAe,QAAQ,EAAE;AAC/D,gBAAM,YAAY,SAAS,OAAO,OAAK,EAAE,eAAe,WAAW,EAAE;AAErE,yBAAe;AACf,4BAAkB;AAClB,yBAAe;AACf,4BAAkB;AAElB,cAAI,OAAO,mBAAmB,KAAK;AACjC,4BAAgB,KAAK,IAAI,QAAQ;AAAA,UACnC;AAEA,gBAAM,cAAc,SACjB,KAAK,CAAC,GAAG,MAAM,EAAE,YAAY,EAAE,SAAS,EACxC,MAAM,GAAG,EAAE;AAEd,sBAAY,KAAK;AAAA,YACf,UAAU,IAAI;AAAA,YACd,MAAM,IAAI;AAAA,YACV,MAAM,IAAI;AAAA,YACV,OAAO;AAAA,cACL;AAAA,cACA,gBAAgB;AAAA,cAChB,aAAa;AAAA,cACb,gBAAgB;AAAA,cAChB,WAAW,OAAO;AAAA,cAClB;AAAA,YACF;AAAA,UACF,CAAC;AAAA,QACH;AAGA,YAAI;AACJ,YAAI,aAAa;AACf,gBAAM,UAAU,YAAY,IAAI,QAAQ;AACxC,cAAI,WAAW,QAAQ,SAAS,GAAG;AACjC,4BAAgB,QACb,KAAK,CAAC,GAAG,MAAM,EAAE,YAAY,EAAE,SAAS,EACxC,MAAM,GAAG,CAAC,EACV,IAAI,OAAK,EAAE,UAAU,WAAW,EAAE,QAAQ,EAAE,KAAK;AAAA,UACtD;AAAA,QACF;AAEA,cAAM,KAAK;AAAA,UACT,MAAM;AAAA,UACN,SAAS;AAAA,UACT,GAAI,gBAAgB,EAAE,cAAc,IAAI,CAAC;AAAA,QAC3C,CAAC;AAAA,MACH;AAGA,YAAM,UAAU,MAAM,OAAO,CAAC,KAAK,MAAM;AACvC,cAAM,UAAU,EAAE,QAAQ,OAAO,CAAC,GAAG,MAAM,KAAK,IAAI,GAAG,EAAE,MAAM,SAAS,GAAG,CAAC;AAC5E,eAAO,KAAK,IAAI,KAAK,OAAO;AAAA,MAC9B,GAAG,CAAC;AACJ,YAAM,YAAY,UAAU,MAAM,SAAS,UAAU,MAAM,WAAW;AAEtE,YAAM,iBAAiB,MAAM,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,QAAQ,QAAQ,CAAC;AAEzE,YAAM,UAAU,QAAQ,KAAK,KAAK,UAAU,aAAa;AAAA,QACvD;AAAA,QACA,cAAc,MAAM;AAAA,QACpB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,UACA,iBAAiB,gBAAgB,MAAM,GAAG,EAAE;AAAA,QAC9C;AAAA,MACF,CAAC,CAAC,CAAC;AAEH,YAAM,UAAiD,CAAC;AACxD,UAAI,WAAW;AACb,cAAM,UAAU,UAAU,MAAM,QAAQ,iBAAiB,CAAC;AAC1D,YAAI,QAAS,SAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,gBAAM,QAAQ,OAAO,GAAG,CAAC;AAAA,MAC3E;AACA,cAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC;AAE5C,aAAO,EAAE,QAAQ;AAAA,IACnB,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM,SAAU,IAAc,QAAQ,CAAC,EAAE,CAAC;AAAA,MAC7G;AAAA,IACF;AAAA,EACF;AACF;;;AhCtLA,IAAME,OAAM,aAAa,UAAU;AAEnC,SAAS,kBAAkB,UAAmC;AAC5D,QAAM,iBAAiBC,MAAK,UAAU,cAAc;AAGpD,MAAIC,YAAW,cAAc,GAAG;AAC9B,QAAI;AACF,YAAM,MAAMC,cAAa,gBAAgB,OAAO;AAChD,YAAM,WAAmC,KAAK,MAAM,GAAG;AACvD,MAAAH,KAAI,KAAK,UAAU,SAAS,MAAM,4BAA4B;AAC9D,aAAO,gBAAgB,WAAW,QAAQ;AAAA,IAC5C,SAAS,KAAK;AACZ,MAAAA,KAAI,MAAM,kCAAmC,IAAc,OAAO,EAAE;AAAA,IACtE;AAAA,EACF;AAEA,SAAO,IAAI,gBAAgB;AAC7B;AAEA,eAAe,OAAsB;AACnC,QAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AAGjC,QAAM,cAAc,QAAQ,IAAI,mBAC1B,KAAK,SAAS,QAAQ,IAAK,KAAK,KAAK,QAAQ,QAAQ,IAAI,CAAC,KAAK,SAAU;AAE/E,MAAI,CAAC,eAAe,KAAK,SAAS,GAAG;AAEnC,UAAM,EAAE,UAAU,IAAI,MAAM,OAAO,0BAAqB;AACxD,UAAM,SAAS,IAAI,UAAU,QAAQ,IAAI,CAAC;AAC1C,UAAM,OAAO,MAAM,IAAI;AACvB;AAAA,EACF;AAGA,QAAM,WAAW;AACjB,QAAM,UAAU,IAAI,qBAAqB,QAAQ;AACjD,QAAM,QAAQ,KAAK;AAEnB,QAAM,UAAU,kBAAkB,QAAQ;AAC1C,QAAM,MAAM,IAAI,iBAAiB,QAAQ,IAAI,CAAC;AAG9C,QAAM,SAAS,IAAI,UAAU,EAAE,MAAM,QAAQ,SAAS,QAAQ,CAAC;AAG/D,QAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,kCAAwC;AACnF,QAAM,YAAY,IAAI,kBAAkB,QAAQ,IAAI,GAAG,QAAQ;AAE/D,gBAAc,QAAQ,SAAS,SAAS,KAAK,WAAW,QAAQ;AAGhE,MAAI,aAAa;AACf,UAAM,mBAAmB,YAAY;AACnC,YAAM,IAAI,IAAI,UAAU,EAAE,MAAM,QAAQ,SAAS,QAAQ,CAAC;AAC1D,oBAAc,GAAG,SAAS,SAAS,KAAK,WAAW,QAAQ;AAC3D,aAAO;AAAA,IACT,GAAG,SAAS,aAAa,EAAE,CAAC;AAAA,EAC9B,OAAO;AACL,UAAM,YAAY,IAAI,qBAAqB;AAC3C,UAAM,OAAO,QAAQ,SAAS;AAAA,EAChC;AACF;AAEA,SAAS,cACP,QACA,SACA,SACA,KAEA,WACA,WAAW,SACX;AAEA,QAAM,kBAAkB;AAAA,IACtB,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,eAAe;AAAA,EACjB;AAGA,QAAM,oBAAoB,oBAAoB,SAAS,SAAS,WAAW,QAAQ;AACnF,QAAM,oBAAoB,oBAAoB,SAAS,KAAK,SAAS,WAAW,QAAQ;AACxF,QAAM,4BAA4B,4BAA4B,SAAS,KAAK,SAAS,WAAW,QAAQ;AAExG,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,aAAa;AAAA,QACX,UAAUI,IAAE,OAAO,EAAE,SAAS,EAAE,SAAS,6CAA6C;AAAA,QACtF,WAAWA,IAAE,MAAMA,IAAE,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,4BAA4B;AAAA,QAC/E,OAAOA,IAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,SAAS,oFAAoF;AAAA,QACnJ,QAAQA,IAAE,OAAO,EAAE,SAAS,EAAE,SAAS,kEAAkE;AAAA,MAC3G;AAAA,MACA,aAAa;AAAA,IACf;AAAA,IACA,CAAC,SAAS,kBAAkB,IAAI;AAAA,EAClC;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,aAAa;AAAA,QACX,UAAUA,IAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,0CAA0C;AAAA,QAC/E,YAAYA,IAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,+CAA+C;AAAA,MACzG;AAAA,MACA,aAAa;AAAA,IACf;AAAA,IACA,CAAC,SAAS,kBAAkB,IAAI;AAAA,EAClC;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,aAAa;AAAA,QACX,UAAUA,IAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,0CAA0C;AAAA,MACjF;AAAA,MACA,aAAa;AAAA,IACf;AAAA,IACA,CAAC,SAAS,0BAA0B,IAAI;AAAA,EAC1C;AAEA,QAAM,qBAAqB,qBAAqB,SAAS,SAAS,WAAW,QAAQ;AAErF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,aAAa;AAAA,QACX,UAAUA,IAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,0CAA0C;AAAA,QAC/E,YAAYA,IAAE,KAAK,CAAC,aAAa,UAAU,WAAW,CAAC,EAAE,SAAS,EAAE,SAAS,2BAA2B;AAAA,QACxG,QAAQA,IAAE,OAAO,EAAE,SAAS,EAAE,SAAS,sEAAsE;AAAA,MAC/G;AAAA,MACA,aAAa;AAAA,IACf;AAAA,IACA,CAAC,SAAS,mBAAmB,IAAI;AAAA,EACnC;AAEA,QAAM,iBAAiB,8BAA8B,SAAS,SAAS,SAAS;AAEhF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,aAAa;AAAA,QACX,OAAOA,IAAE,OAAO,EAAE,SAAS,EAAE,SAAS,+BAA+B;AAAA,MACvE;AAAA,MACA,aAAa;AAAA,IACf;AAAA,IACA,CAAC,SAAS,eAAe,IAAI;AAAA,EAC/B;AAEA,QAAM,kBAAkB,mBAAmB,SAAS,SAAS,WAAW,QAAQ;AAEhF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,aAAa;AAAA,QACX,cAAcA,IAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,KAAK,EAAE,SAAS,mDAAmD;AAAA,QAChH,QAAQA,IAAE,OAAO,EAAE,SAAS,EAAE,SAAS,2EAA2E;AAAA,MACpH;AAAA,MACA,aAAa;AAAA,IACf;AAAA,IACA,CAAC,SAAS,gBAAgB,IAAI;AAAA,EAChC;AAEA,QAAM,wBAAwB,wBAAwB,SAAS,SAAS,WAAW,QAAQ;AAE3F,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,aAAa;AAAA,QACX,UAAUA,IAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,0CAA0C;AAAA,QAC/E,UAAUA,IAAE,KAAK,CAAC,OAAO,UAAU,YAAY,YAAY,CAAC,EAAE,SAAS,qDAAqD;AAAA,QAC5H,aAAaA,IAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,GAAI,EAAE,SAAS,uCAAuC;AAAA,MACnG;AAAA,MACA,aAAa;AAAA,IACf;AAAA,IACA,CAAC,SAAS,sBAAsB,IAAI;AAAA,EACtC;AAEA,QAAM,uBAAuB,uBAAuB,SAAS,SAAS,WAAW,QAAQ;AAEzF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,aAAa;AAAA,QACX,OAAOA,IAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,qCAAqC;AAAA,QACvE,aAAaA,IAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,GAAI,EAAE,SAAS,uCAAuC;AAAA,QACjG,UAAUA,IAAE,KAAK,CAAC,YAAY,cAAc,YAAY,CAAC,EAAE,SAAS,EAAE,QAAQ,UAAU,EAAE,SAAS,kBAAkB;AAAA,MACvH;AAAA,MACA,aAAa;AAAA,IACf;AAAA,IACA,CAAC,SAAS,qBAAqB,IAAI;AAAA,EACrC;AAEA,QAAM,uBAAuB,oBAAoB,SAAS,SAAS,WAAW,QAAQ;AAEtF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,aAAa;AAAA,QACX,SAASA,IAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,qCAAqC;AAAA,QACzE,MAAMA,IAAE,KAAK,CAAC,YAAY,SAAS,aAAa,UAAU,YAAY,MAAM,CAAC,EAAE,SAAS,EAAE,SAAS,uBAAuB;AAAA,QAC1H,aAAaA,IAAE,OAAO,EAAE,SAAS,EAAE,SAAS,+BAA+B;AAAA,QAC3E,OAAOA,IAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,SAAS,0BAA0B;AAAA,MACpG;AAAA,MACA,aAAa;AAAA,IACf;AAAA,IACA,CAAC,SAAS,qBAAqB,IAAI;AAAA,EACrC;AAEA,QAAM,wBAAwB,wBAAwB,SAAS,KAAK,SAAS,WAAW,QAAQ;AAEhG,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,aAAa;AAAA,QACX,OAAOA,IAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,QAAQ,EAAE,SAAS,0CAA0C;AAAA,QAClG,UAAUA,IAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,SAAS,2CAA2C;AAAA,MAC/G;AAAA,MACA,aAAa;AAAA,IACf;AAAA,IACA,CAAC,SAAS,sBAAsB,IAAI;AAAA,EACtC;AAEA,QAAM,uBAAuB,oBAAoB,SAAS,SAAS,WAAW,QAAQ;AAEtF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,aAAa;AAAA,QACX,UAAUA,IAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,0CAA0C;AAAA,QAC/E,WAAWA,IAAE,MAAMA,IAAE,KAAK,CAAC,WAAW,SAAS,WAAW,cAAc,MAAM,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,sBAAsB;AAAA,QAC5H,YAAYA,IAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,KAAK,EAAE,SAAS,iDAAiD;AAAA,QAC5G,UAAUA,IAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,SAAS,+CAA+C;AAAA,QACxH,QAAQA,IAAE,OAAO,EAAE,SAAS,EAAE,SAAS,uEAAuE;AAAA,MAChH;AAAA,MACA,aAAa;AAAA,IACf;AAAA,IACA,CAAC,SAAS,qBAAqB,IAAI;AAAA,EACrC;AAEA,QAAM,wBAAwB,wBAAwB,SAAS,SAAS,WAAW,QAAQ;AAE3F,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,aAAa;AAAA,QACX,UAAUA,IAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,kDAAkD;AAAA,QAClG,WAAWA,IAAE,KAAK,CAAC,aAAa,eAAe,MAAM,CAAC,EAAE,SAAS,EAAE,QAAQ,MAAM,EAAE,SAAS,oCAAoC;AAAA,MAClI;AAAA,MACA,aAAa;AAAA,IACf;AAAA,IACA,CAAC,SAAS,sBAAsB,IAAI;AAAA,EACtC;AAEA,QAAM,0BAA0B,0BAA0B,SAAS,SAAS,WAAW,QAAQ;AAE/F,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,aAAa;AAAA,QACX,OAAOA,IAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,SAAS,0BAA0B;AAAA,QAClG,MAAMA,IAAE,KAAK,CAAC,YAAY,SAAS,aAAa,UAAU,YAAY,MAAM,CAAC,EAAE,SAAS,EAAE,SAAS,uBAAuB;AAAA,QAC1H,aAAaA,IAAE,OAAO,EAAE,SAAS,EAAE,SAAS,+BAA+B;AAAA,QAC3E,SAASA,IAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,QAAQ,IAAI,EAAE,SAAS,wCAAwC;AAAA,MAC9G;AAAA,MACA,aAAa;AAAA,IACf;AAAA,IACA,CAAC,SAAS,wBAAwB,IAAI;AAAA,EACxC;AAEA,QAAM,kBAAkB,kBAAkB,SAAS,KAAK,SAAS,WAAW,QAAQ;AAEpF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,aAAa;AAAA,QACX,OAAOA,IAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,QAAQ,EAAE,SAAS,0CAA0C;AAAA,QAClG,UAAUA,IAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,SAAS,8BAA8B;AAAA,QAChG,YAAYA,IAAE,KAAK,CAAC,aAAa,UAAU,WAAW,CAAC,EAAE,SAAS,EAAE,SAAS,4CAA4C;AAAA,MAC3H;AAAA,MACA,aAAa;AAAA,IACf;AAAA,IACA,CAAC,SAAS,gBAAgB,IAAI;AAAA,EAChC;AAIA,SAAO,SAAS,eAAe,iBAAiB,OAAO,SAAS;AAAA,IAC9D,UAAU,CAAC,EAAE,KAAK,IAAI,MAAM,MAAM,8BAA8B,CAAC;AAAA,EACnE,EAAE;AACJ;AAEA,KAAK,EAAE,MAAM,CAAC,QAAiB;AAC7B,EAAAJ,KAAI,MAAM,aAAc,IAAc,OAAO;AAC7C,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["z","existsSync","readFileSync","join","z","InputSchema","z","z","InputSchema","z","z","InputSchema","z","z","InputSchema","z","payload","z","InputSchema","z","z","z","InputSchema","z","log","log","InputSchema","z","payload","content","z","InputSchema","z","results","payload","content","z","InputSchema","z","z","InputSchema","z","z","InputSchema","z","visited","z","InputSchema","z","z","InputSchema","z","log","join","existsSync","readFileSync","z"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/adapters/transport/http-server-transport.ts","../src/core/masking/masking-pipeline.ts","../src/adapters/mcp/get-logic-slice.ts","../src/core/graph/symbol-graph.ts","../src/core/logic-slice/logic-slice-query.ts","../src/core/detail-levels/detail-formatter.ts","../src/core/response-envelope.ts","../src/core/intent-filter.ts","../src/adapters/mcp/get-why-context.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/core/blast-radius/blast-radius-calculator.ts","../src/adapters/mcp/get-architectural-overlay.ts","../src/core/overlay/architectural-overlay.ts","../src/adapters/mcp/get-dead-code.ts","../src/core/dead-code/dead-code-detector.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/symbol-tokenizer.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/core/importance/pagerank-calculator.ts","../src/adapters/mcp/get-pr-impact.ts","../src/adapters/stats/with-recording.ts"],"sourcesContent":["import { 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 } from 'node:path';\nimport { createLogger } from './core/logger.js';\nimport { SqliteStorageAdapter } from './adapters/storage/sqlite-storage-adapter.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 } from './adapters/mcp/get-architectural-overlay.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 type { ISessionRecorderPort } from './ports/i-session-recorder-port.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 const configPath = join(ctxoRoot, 'config.yaml');\n if (!existsSync(configPath)) return true;\n\n try {\n const raw = readFileSync(configPath, 'utf-8');\n // Simple YAML parsing for stats.enabled — avoid importing yaml package\n const match = raw.match(/stats:\\s*\\n\\s*enabled:\\s*(true|false)/);\n if (match) return match[1] !== 'false';\n return true;\n } catch {\n return true;\n }\n}\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n\n // HTTP mode — check before CLI routing since --http is a server flag, not a CLI command\n const httpPortStr = process.env.CTXO_HTTP_PORT\n || (args.includes('--http') ? (args[args.indexOf('--port') + 1] || '3001') : null);\n\n if (!httpPortStr && args.length > 0) {\n // CLI mode\n const { CliRouter } = await import('./cli/cli-router.js');\n const router = new CliRouter(process.cwd());\n await router.route(args);\n return;\n }\n\n // Initialize adapters\n const ctxoRoot = '.ctxo';\n const storage = new SqliteStorageAdapter(ctxoRoot);\n await storage.init();\n\n const masking = loadMaskingConfig(ctxoRoot);\n const git = new SimpleGitAdapter(process.cwd());\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: '0.1.0' });\n\n // Staleness detection\n const { StalenessDetector } = await import('./core/staleness/staleness-detector.js');\n const staleness = new StalenessDetector(process.cwd(), ctxoRoot);\n\n registerTools(server, storage, masking, git, staleness, recorder, ctxoRoot);\n\n // Start MCP server — HTTP mode or stdio mode\n if (httpPortStr) {\n await startHttpTransport(async () => {\n const s = new McpServer({ name: 'ctxo', version: '0.1.0' });\n registerTools(s, storage, masking, git, staleness, recorder, ctxoRoot);\n return s;\n }, parseInt(httpPortStr, 10));\n } else {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n }\n}\n\nfunction registerTools(\n server: McpServer,\n storage: SqliteStorageAdapter,\n masking: MaskingPipeline,\n git: SimpleGitAdapter,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n staleness: any,\n recorder: ISessionRecorderPort | null,\n ctxoRoot = '.ctxo',\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 // Register tools — each handler wrapped with session recording\n const logicSliceHandler = withRecording('get_logic_slice', handleGetLogicSlice(storage, masking, staleness, ctxoRoot), recorder);\n const whyContextHandler = withRecording('get_why_context', handleGetWhyContext(storage, git, masking, staleness, ctxoRoot), 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. 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.',\n inputSchema: {\n symbolId: z.string().optional().describe('Single symbol ID (format: file::name::kind)'),\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)'),\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.',\n inputSchema: {\n symbolId: z.string().min(1).describe('The symbol ID (format: file::name::kind)'),\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), recorder);\n\n server.registerTool(\n 'get_blast_radius',\n {\n description: 'BEFORE modifying any function or class, call this to understand impact. Returns all symbols that would break if the target changes, split into confirmed (direct importers), likely (co-changed), and potential (transitive) tiers with 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.',\n inputSchema: {\n symbolId: z.string().min(1).describe('The symbol ID (format: file::name::kind)'),\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), recorder);\n\n server.registerTool(\n 'get_architectural_overlay',\n {\n description: 'Get the project architectural layer map — identifies which symbols belong to Domain, Infrastructure, and Adapter layers. Use this when onboarding to a new codebase or validating that a change respects layer boundaries. For symbol-level analysis, use get_logic_slice or get_blast_radius.',\n inputSchema: {\n layer: z.string().optional().describe('Filter by specific layer name'),\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. 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 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), 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). 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 (format: file::name::kind)'),\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 },\n annotations: toolAnnotations,\n },\n (args) => rankedContextHandler(args),\n );\n\n const searchSymbolsHandler = withRecording('search_symbols', handleSearchSymbols(storage, masking, staleness, ctxoRoot), 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.',\n inputSchema: {\n pattern: z.string().min(1).describe('Search pattern (substring or regex)'),\n kind: z.enum(['function', 'class', 'interface', 'method', 'variable', 'type']).optional().describe('Filter by symbol kind'),\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 },\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), 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.',\n inputSchema: {\n symbolId: z.string().min(1).describe('The symbol ID (format: file::name::kind)'),\n edgeKinds: z.array(z.enum(['imports', 'calls', 'extends', 'implements', 'uses'])).optional().describe('Filter by edge kinds'),\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: z.enum(['function', 'class', 'interface', 'method', 'variable', 'type']).optional().describe('Filter by symbol kind'),\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), 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.',\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 // 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\nmain().catch((err: unknown) => {\n log.error('Fatal: %s', (err as Error).message);\n process.exit(1);\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 npx ctxo\n * npx 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 + — excludes hex-only git hashes)\n { regex: /(?<![A-Za-z0-9/+])(?=[A-Za-z0-9/+=]{40}(?![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 { IMaskingPort } from '../../ports/i-masking-port.js';\nimport { SymbolGraph } from '../../core/graph/symbol-graph.js';\nimport { JsonIndexReader } from '../storage/json-index-reader.js';\nimport { LogicSliceQuery } from '../../core/logic-slice/logic-slice-query.js';\nimport { DetailFormatter } from '../../core/detail-levels/detail-formatter.js';\nimport { DetailLevelSchema } from '../../core/types.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\nimport { filterByIntent } from '../../core/intent-filter.js';\n\nconst InputSchema = z.object({\n symbolId: z.string().min(1).optional(),\n symbolIds: z.array(z.string().min(1)).optional(),\n level: DetailLevelSchema.optional().default(3),\n intent: z.string().optional().describe('Filter dependencies by intent keywords (e.g., \"core\", \"adapter\", \"storage\")'),\n}).refine(\n (data) => data.symbolId || (data.symbolIds && data.symbolIds.length > 0),\n { message: 'Either symbolId or symbolIds must be provided' },\n);\n\nexport type GetLogicSliceInput = z.infer<typeof InputSchema>;\n\nexport function getLogicSliceInputSchema() {\n return {\n type: 'object' as const,\n properties: {\n symbolId: { type: 'string' as const, description: 'The symbol ID to retrieve (format: file::name::kind)' },\n level: { type: 'number' as const, enum: [1, 2, 3, 4], description: 'Detail level (1=minimal, 4=full)', default: 3 },\n },\n required: ['symbolId'] as const,\n };\n}\n\nexport function buildGraphFromStorage(storage: IStoragePort): SymbolGraph {\n const graph = new SymbolGraph();\n for (const sym of storage.getAllSymbols()) {\n graph.addNode(sym);\n }\n for (const edge of storage.getAllEdges()) {\n graph.addEdge(edge);\n }\n return graph;\n}\n\n/**\n * Build graph directly from JSON index files (bypasses SQLite cache).\n * Always reads fresh data from disk — works even if ctxo index ran in another process.\n */\nexport function buildGraphFromJsonIndex(ctxoRoot: string): SymbolGraph {\n const reader = new JsonIndexReader(ctxoRoot);\n const indices = reader.readAll();\n\n const graph = new SymbolGraph();\n // Phase 1: all nodes\n for (const fileIndex of indices) {\n for (const sym of fileIndex.symbols) {\n graph.addNode(sym);\n }\n }\n // Phase 2: all edges (fuzzy resolution active since nodes are loaded)\n for (const fileIndex of indices) {\n for (const edge of fileIndex.edges) {\n graph.addEdge(edge);\n }\n }\n return graph;\n}\n\nexport interface StalenessCheck {\n check(indexedFiles: readonly string[]): { message: string } | undefined;\n}\n\nexport function handleGetLogicSlice(\n storage: IStoragePort,\n masking: IMaskingPort,\n staleness?: StalenessCheck,\n ctxoRoot = '.ctxo',\n) {\n const query = new LogicSliceQuery();\n const formatter = new DetailFormatter();\n\n // Build graph fresh on each call — try JSON index first (always up to date),\n // fall back to SQLite storage (for tests and when JSON not available).\n const getGraph = () => {\n const jsonGraph = buildGraphFromJsonIndex(ctxoRoot);\n if (jsonGraph.nodeCount > 0) return jsonGraph;\n return buildGraphFromStorage(storage);\n };\n\n const handler = (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, symbolIds, level, intent } = parsed.data;\n const ids = symbolIds ?? (symbolId ? [symbolId] : []);\n\n const graph = getGraph();\n\n // Batch support: query multiple symbols\n const results = [];\n for (const id of ids) {\n const slice = query.getLogicSlice(graph, id);\n if (slice) {\n const formatted = formatter.format(slice, level) as unknown as Record<string, unknown>;\n // Apply intent filter to dependencies if present\n if (intent && Array.isArray(formatted['dependencies'])) {\n formatted['dependencies'] = filterByIntent(\n formatted['dependencies'] as Record<string, unknown>[],\n intent,\n );\n }\n results.push(formatted);\n } else {\n results.push({ found: false, symbolId: id, hint: 'Symbol not found. Run \"ctxo index\".' });\n }\n }\n\n // Single symbol: return directly. Batch: return array.\n const responseData = ids.length === 1 ? results[0] : { batch: true, results };\n\n // Apply masking\n const payload = masking.mask(JSON.stringify(wrapResponse(responseData as Record<string, unknown>)));\n\n // Check staleness\n const content: Array<{ type: 'text'; text: string }> = [];\n if (staleness) {\n const warning = staleness.check(storage.listIndexedFiles());\n if (warning) {\n content.push({ type: 'text', text: `⚠️ ${warning.message}` });\n }\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 return handler;\n}\n","import type { SymbolNode, GraphEdge } from '../types.js';\n\nexport class SymbolGraph {\n private readonly nodes = new Map<string, SymbolNode>();\n private readonly nodesByFileAndName = new Map<string, SymbolNode>();\n private readonly forwardEdges = new Map<string, GraphEdge[]>();\n private readonly reverseEdges = new Map<string, GraphEdge[]>();\n private edgeSet = new Set<string>();\n\n addNode(node: SymbolNode): void {\n this.nodes.set(node.symbolId, node);\n // Index by file::name (ignoring kind) for fuzzy edge resolution\n const [p0, p1] = node.symbolId.split('::');\n if (p0 !== undefined && p1 !== undefined) {\n this.nodesByFileAndName.set(`${p0}::${p1}`, node);\n }\n }\n\n addEdge(edge: GraphEdge): void {\n // Resolve edge endpoints: if exact ID not found, try fuzzy match by file::name\n const resolvedFrom = this.resolveNodeId(edge.from);\n const resolvedTo = this.resolveNodeId(edge.to);\n const resolvedEdge: GraphEdge = { from: resolvedFrom, to: resolvedTo, kind: edge.kind };\n\n const edgeKey = `${resolvedEdge.from}|${resolvedEdge.to}|${resolvedEdge.kind}`;\n if (this.edgeSet.has(edgeKey)) return;\n this.edgeSet.add(edgeKey);\n\n const forward = this.forwardEdges.get(resolvedEdge.from) ?? [];\n forward.push(resolvedEdge);\n this.forwardEdges.set(resolvedEdge.from, forward);\n\n const reverse = this.reverseEdges.get(resolvedEdge.to) ?? [];\n reverse.push(resolvedEdge);\n this.reverseEdges.set(resolvedEdge.to, reverse);\n }\n\n getNode(symbolId: string): SymbolNode | undefined {\n return this.nodes.get(symbolId) ?? this.resolveNodeFuzzy(symbolId);\n }\n\n private resolveNodeId(id: string): string {\n if (this.nodes.has(id)) return id;\n const [p0, p1] = id.split('::');\n if (p0 !== undefined && p1 !== undefined) {\n const fuzzyKey = `${p0}::${p1}`;\n const match = this.nodesByFileAndName.get(fuzzyKey);\n if (match) return match.symbolId;\n\n // Try .js → .ts extension swap (handles unresolved module specifiers)\n const jsToTs = p0.replace(/\\.js$/, '.ts');\n if (jsToTs !== p0) {\n const altKey = `${jsToTs}::${p1}`;\n const altMatch = this.nodesByFileAndName.get(altKey);\n if (altMatch) return altMatch.symbolId;\n }\n }\n return id;\n }\n\n private resolveNodeFuzzy(id: string): SymbolNode | undefined {\n const [p0, p1] = id.split('::');\n if (p0 !== undefined && p1 !== undefined) {\n const match = this.nodesByFileAndName.get(`${p0}::${p1}`);\n if (match) return match;\n\n // Try .js → .ts extension swap (consistent with resolveNodeId)\n const jsToTs = p0.replace(/\\.js$/, '.ts');\n if (jsToTs !== p0) {\n return this.nodesByFileAndName.get(`${jsToTs}::${p1}`);\n }\n }\n return undefined;\n }\n\n getForwardEdges(symbolId: string): GraphEdge[] {\n return this.forwardEdges.get(symbolId) ?? [];\n }\n\n getReverseEdges(symbolId: string): GraphEdge[] {\n return this.reverseEdges.get(symbolId) ?? [];\n }\n\n hasNode(symbolId: string): boolean {\n return this.nodes.has(symbolId) || this.resolveNodeFuzzy(symbolId) !== undefined;\n }\n\n get nodeCount(): number {\n return this.nodes.size;\n }\n\n get edgeCount(): number {\n return this.edgeSet.size;\n }\n\n allNodes(): SymbolNode[] {\n return [...this.nodes.values()];\n }\n\n allEdges(): GraphEdge[] {\n const edges: GraphEdge[] = [];\n for (const list of this.forwardEdges.values()) {\n edges.push(...list);\n }\n return edges;\n }\n}\n","import type { SymbolNode, GraphEdge, LogicSliceResult } from '../types.js';\nimport type { SymbolGraph } from '../graph/symbol-graph.js';\n\nexport class LogicSliceQuery {\n getLogicSlice(\n graph: SymbolGraph,\n symbolId: string,\n maxDepth: number = Infinity,\n ): LogicSliceResult | undefined {\n const root = graph.getNode(symbolId);\n if (!root) return undefined;\n\n const visited = new Set<string>([symbolId]);\n const dependencies: SymbolNode[] = [];\n const collectedEdges: GraphEdge[] = [];\n\n // BFS transitive closure\n const queue: Array<{ id: string; depth: number }> = [{ id: symbolId, depth: 0 }];\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n\n if (current.depth >= maxDepth) continue;\n\n const edges = graph.getForwardEdges(current.id);\n for (const edge of edges) {\n const depNode = graph.getNode(edge.to);\n // Only include edges whose target node exists in the graph\n if (!depNode) continue;\n\n collectedEdges.push(edge);\n\n if (visited.has(edge.to)) continue;\n visited.add(edge.to);\n\n dependencies.push(depNode);\n queue.push({ id: edge.to, depth: current.depth + 1 });\n }\n }\n\n return { root, dependencies, edges: collectedEdges };\n }\n}\n","import type {\n LogicSliceResult,\n FormattedSlice,\n DetailLevel,\n SymbolNode,\n GraphEdge,\n} from '../types.js';\n\nconst L1_MAX_LINES = 150;\nconst L4_TOKEN_BUDGET = 8000;\n\nexport class DetailFormatter {\n format(slice: LogicSliceResult, level: DetailLevel): FormattedSlice {\n switch (level) {\n case 1:\n return this.formatL1(slice);\n case 2:\n return this.formatL2(slice);\n case 3:\n return this.formatL3(slice);\n case 4:\n return this.formatL4(slice);\n }\n }\n\n private formatL1(slice: LogicSliceResult): FormattedSlice {\n const root = slice.root;\n const lineCount = root.endLine - root.startLine + 1;\n\n const clampedRoot: SymbolNode = lineCount > L1_MAX_LINES\n ? { ...root, endLine: root.startLine + L1_MAX_LINES - 1 }\n : root;\n\n return {\n root: clampedRoot,\n dependencies: [],\n edges: [],\n level: 1,\n levelDescription: 'L1: Root symbol signature only (no dependencies)',\n ...(lineCount > L1_MAX_LINES ? { truncation: { truncated: true as const, reason: 'token_budget_exceeded' as const } } : {}),\n };\n }\n\n private formatL2(slice: LogicSliceResult): FormattedSlice {\n // L2: root + depth-1 direct dependencies\n const directEdges = slice.edges.filter((e) => e.from === slice.root.symbolId);\n const directDepIds = new Set(directEdges.map((e) => e.to));\n const directDeps = slice.dependencies.filter((d) => directDepIds.has(d.symbolId));\n\n return {\n root: slice.root,\n dependencies: directDeps,\n edges: directEdges,\n level: 2,\n levelDescription: 'L2: Root + direct dependencies (depth 1)',\n };\n }\n\n private formatL3(slice: LogicSliceResult): FormattedSlice {\n return {\n root: slice.root,\n dependencies: slice.dependencies,\n edges: slice.edges,\n level: 3,\n levelDescription: 'L3: Full transitive dependency closure',\n };\n }\n\n private formatL4(slice: LogicSliceResult): FormattedSlice {\n // L4: full closure with token budget enforcement\n const estimatedTokens = this.estimateTokens(slice);\n\n if (estimatedTokens > L4_TOKEN_BUDGET) {\n // Truncate dependencies to fit budget\n const truncated = this.truncateToTokenBudget(slice, L4_TOKEN_BUDGET);\n return {\n ...truncated,\n level: 4,\n levelDescription: 'L4: Full closure with 8K token budget (truncated)',\n truncation: {\n truncated: true,\n reason: 'token_budget_exceeded',\n },\n };\n }\n\n return {\n root: slice.root,\n dependencies: slice.dependencies,\n edges: slice.edges,\n level: 4,\n levelDescription: 'L4: Full closure with 8K token budget',\n };\n }\n\n private estimateTokens(slice: LogicSliceResult): number {\n // Rough estimate: ~4 chars per token\n let chars = this.symbolCharEstimate(slice.root);\n for (const dep of slice.dependencies) {\n chars += this.symbolCharEstimate(dep);\n }\n for (const edge of slice.edges) {\n chars += (edge.from.length + edge.to.length + edge.kind.length + 10);\n }\n return Math.ceil(chars / 4);\n }\n\n private symbolCharEstimate(node: SymbolNode): number {\n // Use byte offsets for exact size when available, otherwise estimate from line count\n if (node.startOffset !== undefined && node.endOffset !== undefined) {\n return node.endOffset - node.startOffset;\n }\n return (node.endLine - node.startLine + 1) * 40;\n }\n\n private truncateToTokenBudget(\n slice: LogicSliceResult,\n budget: number,\n ): { root: SymbolNode; dependencies: SymbolNode[]; edges: GraphEdge[] } {\n let currentTokens = this.symbolCharEstimate(slice.root) / 4;\n const deps: SymbolNode[] = [];\n const includedIds = new Set<string>([slice.root.symbolId]);\n\n for (const dep of slice.dependencies) {\n const depTokens = this.symbolCharEstimate(dep) / 4;\n if (currentTokens + depTokens > budget) break;\n currentTokens += depTokens;\n deps.push(dep);\n includedIds.add(dep.symbolId);\n }\n\n const edges = slice.edges.filter(\n (e) => includedIds.has(e.from) && includedIds.has(e.to),\n );\n\n return { root: slice.root, dependencies: deps, edges };\n }\n}\n","/**\n * Response envelope — adds _meta field and truncates large payloads.\n *\n * Applied between payload construction and masking in every MCP handler.\n * Threshold default: 8192 bytes (~8KB). Configurable via CTXO_RESPONSE_LIMIT env.\n */\n\nconst DEFAULT_THRESHOLD = 8192;\n\nexport interface ResponseMeta {\n totalItems: number;\n returnedItems: number;\n truncated: boolean;\n totalBytes: number;\n hint?: string;\n}\n\n/**\n * Known array field names in tool responses that can be truncated.\n * Maps field name → drill-in hint for the LLM.\n */\nconst TRUNCATABLE_FIELDS: Record<string, string> = {\n impactedSymbols: 'Use search_symbols to find specific impacted symbols, or get_blast_radius with a confidence filter.',\n importers: 'Use find_importers with edgeKinds filter or maxDepth to narrow results.',\n deadSymbols: 'Use search_symbols with kind filter to find specific dead symbols.',\n unusedExports: 'Use find_importers to check specific symbols.',\n results: 'Use search_symbols or get_ranked_context with a narrower query.',\n rankings: 'Use get_symbol_importance with kind or filePattern filter to narrow results.',\n context: 'Use get_context_for_task with a smaller tokenBudget.',\n hierarchies: 'Use get_class_hierarchy with a specific symbolId.',\n scaffolding: 'Review the scaffolding markers directly in the listed files.',\n deadFiles: 'Use find_dead_code with includeTests to adjust scope.',\n files: 'Use get_changed_symbols with a narrower since ref or smaller maxFiles.',\n};\n\nfunction getThreshold(): number {\n const env = process.env['CTXO_RESPONSE_LIMIT'];\n if (env) {\n const n = parseInt(env, 10);\n if (!isNaN(n) && n > 0) return n;\n }\n return DEFAULT_THRESHOLD;\n}\n\n/**\n * Find the largest array field in a payload object that is in our truncatable list.\n */\nfunction findTruncatableArray(data: Record<string, unknown>): { key: string; arr: unknown[] } | null {\n let best: { key: string; arr: unknown[] } | null = null;\n for (const [key, value] of Object.entries(data)) {\n if (Array.isArray(value) && key in TRUNCATABLE_FIELDS) {\n if (!best || value.length > best.arr.length) {\n best = { key, arr: value };\n }\n }\n }\n return best;\n}\n\n/**\n * Wrap a payload object with _meta and truncate if needed.\n *\n * @param data - The raw response object (before JSON.stringify)\n * @returns The data object with _meta added (and arrays truncated if over threshold)\n */\nexport function wrapResponse(data: Record<string, unknown>): Record<string, unknown> {\n const threshold = getThreshold();\n const fullJson = JSON.stringify(data);\n const totalBytes = Buffer.byteLength(fullJson, 'utf-8');\n\n const truncatable = findTruncatableArray(data);\n const totalItems = truncatable ? truncatable.arr.length : 0;\n\n // Under threshold — return with _meta, no truncation\n if (totalBytes <= threshold) {\n return {\n ...data,\n _meta: {\n totalItems,\n returnedItems: totalItems,\n truncated: false,\n totalBytes,\n } satisfies ResponseMeta,\n };\n }\n\n // Over threshold — truncate the largest array\n if (!truncatable || truncatable.arr.length <= 1) {\n // No array to truncate, just add _meta\n return {\n ...data,\n _meta: {\n totalItems,\n returnedItems: totalItems,\n truncated: false,\n totalBytes,\n } satisfies ResponseMeta,\n };\n }\n\n // Binary search for the number of items that fit within threshold\n let lo = 1;\n let hi = truncatable.arr.length;\n\n while (lo < hi) {\n const mid = Math.ceil((lo + hi) / 2);\n const trial = {\n ...data,\n [truncatable.key]: truncatable.arr.slice(0, mid),\n _meta: {\n totalItems,\n returnedItems: mid,\n truncated: true,\n totalBytes,\n hint: TRUNCATABLE_FIELDS[truncatable.key],\n },\n };\n const size = Buffer.byteLength(JSON.stringify(trial), 'utf-8');\n if (size <= threshold) {\n lo = mid;\n } else {\n hi = mid - 1;\n }\n }\n\n const hint = TRUNCATABLE_FIELDS[truncatable.key];\n\n return {\n ...data,\n [truncatable.key]: truncatable.arr.slice(0, lo),\n _meta: {\n totalItems,\n returnedItems: lo,\n truncated: true,\n totalBytes,\n hint,\n } satisfies ResponseMeta,\n };\n}\n","/**\n * Intent-based result filtering for MCP tool responses.\n *\n * When an `intent` string is provided, filters array results to only include\n * entries whose text fields (symbolId, file, name, kind, edgeKind, reason)\n * match at least one keyword from the intent.\n *\n * Keywords are extracted by splitting the intent on whitespace and lowercasing.\n * A match is found when any keyword appears as a substring of any text field.\n */\n\n/**\n * Extract lowercase keywords from an intent string.\n * Filters out very short words (< 2 chars) to avoid noise.\n */\nfunction extractKeywords(intent: string): string[] {\n return intent\n .toLowerCase()\n .split(/\\s+/)\n .filter(w => w.length >= 2);\n}\n\n/**\n * Check if any keyword matches any of the given text values (case-insensitive substring).\n */\nfunction matchesAny(keywords: string[], values: string[]): boolean {\n const lower = values.map(v => v.toLowerCase());\n return keywords.some(kw => lower.some(v => v.includes(kw)));\n}\n\n/**\n * Collect all string values from a record for matching.\n * Extracts from known fields: symbolId, file, name, kind, edgeKind, edgeKinds, reason, confidence.\n */\nfunction collectMatchableStrings(entry: Record<string, unknown>): string[] {\n const strings: string[] = [];\n for (const key of ['symbolId', 'file', 'name', 'kind', 'edgeKind', 'reason', 'confidence']) {\n const v = entry[key];\n if (typeof v === 'string') strings.push(v);\n }\n const edgeKinds = entry['edgeKinds'];\n if (Array.isArray(edgeKinds)) {\n for (const ek of edgeKinds) {\n if (typeof ek === 'string') strings.push(ek);\n }\n }\n return strings;\n}\n\n/**\n * Filter an array of result entries by intent keywords.\n * Returns only entries where at least one keyword matches a text field.\n *\n * @param items - Array of result objects\n * @param intent - User intent string (e.g., \"test coverage\", \"adapter\", \"security\")\n * @returns Filtered array (empty if no matches)\n */\nexport function filterByIntent<T extends Record<string, unknown>>(\n items: T[],\n intent: string | undefined,\n): T[] {\n if (!intent || intent.trim().length === 0) return items;\n\n const keywords = extractKeywords(intent);\n if (keywords.length === 0) return items;\n\n return items.filter(item => {\n const strings = collectMatchableStrings(item);\n return matchesAny(keywords, strings);\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 { JsonIndexReader } from '../storage/json-index-reader.js';\nimport type { CommitIntent, AntiPattern } from '../../core/types.js';\nimport type { StalenessCheck } from './get-logic-slice.js';\n\nconst 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) {\n const revertDetector = new RevertDetector();\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, maxCommits } = 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\n // Try committed index first (FR16: anti-patterns persist in committed index)\n const indices = indexReader.readAll();\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 payload = masking.mask(JSON.stringify(responsePayload));\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 { 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\nconst 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 // 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 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 { IStoragePort } from '../../ports/i-storage-port.js';\nimport type { IMaskingPort } from '../../ports/i-masking-port.js';\nimport { BlastRadiusCalculator } from '../../core/blast-radius/blast-radius-calculator.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\nimport { filterByIntent } from '../../core/intent-filter.js';\nimport type { StalenessCheck } from './get-logic-slice.js';\nimport { buildGraphFromJsonIndex, buildGraphFromStorage } from './get-logic-slice.js';\n\nconst 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) {\n const calculator = new BlastRadiusCalculator();\n const getGraph = () => {\n const jsonGraph = buildGraphFromJsonIndex(ctxoRoot);\n if (jsonGraph.nodeCount > 0) return jsonGraph;\n return buildGraphFromStorage(storage);\n };\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 } = parsed.data;\n const graph = getGraph();\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 const result = calculator.calculate(graph, symbolId);\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 payload = masking.mask(JSON.stringify(wrapResponse({\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\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 { SymbolGraph } from '../graph/symbol-graph.js';\nimport type { CoChangeEntry } from '../types.js';\n\nexport type ImpactConfidence = 'confirmed' | 'likely' | 'potential';\n\nexport interface BlastRadiusEntry {\n readonly symbolId: string;\n readonly depth: number;\n readonly dependentCount: number;\n readonly riskScore: number;\n readonly confidence: ImpactConfidence;\n readonly edgeKinds: string[];\n readonly coChangeFrequency?: number;\n}\n\nexport interface BlastRadiusResult {\n readonly impactedSymbols: BlastRadiusEntry[];\n readonly directDependentsCount: number;\n readonly confirmedCount: number;\n readonly likelyCount: number;\n readonly potentialCount: number;\n readonly overallRiskScore: number;\n}\n\nconst CONFIRMED_KINDS = new Set(['calls', 'extends', 'implements']);\nconst LIKELY_KINDS = new Set(['uses']);\n\nconst CONFIDENCE_RANK: Record<ImpactConfidence, number> = {\n confirmed: 2,\n likely: 1,\n potential: 0,\n};\n\nfunction edgeKindToConfidence(kind: string): ImpactConfidence {\n if (CONFIRMED_KINDS.has(kind)) return 'confirmed';\n if (LIKELY_KINDS.has(kind)) return 'likely';\n return 'potential';\n}\n\nexport class BlastRadiusCalculator {\n calculate(graph: SymbolGraph, symbolId: string, coChangeMap?: Map<string, CoChangeEntry[]>): BlastRadiusResult {\n if (!graph.hasNode(symbolId)) {\n return { impactedSymbols: [], directDependentsCount: 0, confirmedCount: 0, likelyCount: 0, potentialCount: 0, overallRiskScore: 0 };\n }\n\n const sourceFile = symbolId.split('::')[0]!;\n\n const visited = new Set<string>([symbolId]);\n const rawEntries: Array<{ symbolId: string; depth: number; riskScore: number; confidence: ImpactConfidence; edgeKinds: string[]; coChangeFrequency?: number }> = [];\n\n // BFS via reverse edges (who depends on this symbol?)\n const queue: Array<{ id: string; depth: number }> = [{ id: symbolId, depth: 0 }];\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n\n const reverseEdges = graph.getReverseEdges(current.id);\n\n // Group edges by source node, pick strongest confidence per node\n // confirmed > likely > potential — collect all edge kinds\n const bestByNode = new Map<string, { confidence: ImpactConfidence; kinds: Set<string> }>();\n for (const edge of reverseEdges) {\n if (visited.has(edge.from)) continue;\n const conf = edgeKindToConfidence(edge.kind);\n const existing = bestByNode.get(edge.from);\n if (!existing) {\n bestByNode.set(edge.from, { confidence: conf, kinds: new Set([edge.kind]) });\n } else {\n existing.kinds.add(edge.kind);\n if (CONFIDENCE_RANK[conf] > CONFIDENCE_RANK[existing.confidence]) {\n existing.confidence = conf;\n }\n }\n }\n\n for (const [nodeId, info] of bestByNode) {\n visited.add(nodeId);\n if (!graph.hasNode(nodeId)) continue;\n\n const depth = current.depth + 1;\n const riskScore = 1 / Math.pow(depth, 0.7);\n\n // Co-change boost: if files frequently change together, upgrade potential → likely\n let confidence = info.confidence;\n let coChangeFrequency: number | undefined;\n if (coChangeMap) {\n const nodeFile = nodeId.split('::')[0]!;\n const coEntries = coChangeMap.get(sourceFile);\n if (coEntries) {\n const match = coEntries.find(e => e.file1 === nodeFile || e.file2 === nodeFile);\n if (match) {\n coChangeFrequency = match.frequency;\n if (confidence === 'potential' && match.frequency > 0.5) {\n confidence = 'likely';\n }\n }\n }\n }\n\n rawEntries.push({\n symbolId: nodeId,\n depth,\n riskScore: Math.round(riskScore * 1000) / 1000,\n confidence,\n edgeKinds: [...info.kinds],\n coChangeFrequency,\n });\n\n queue.push({ id: nodeId, depth });\n }\n }\n\n // GAP-30 FIX: compute dependentCount as blast-scope in-degree (not global)\n const blastSet = new Set(rawEntries.map((e) => e.symbolId));\n blastSet.add(symbolId);\n\n const entries: BlastRadiusEntry[] = rawEntries.map((e) => ({\n ...e,\n dependentCount: graph.getReverseEdges(e.symbolId).filter((re) => blastSet.has(re.from)).length,\n }));\n\n // Sort by depth ascending\n entries.sort((a, b) => a.depth - b.depth);\n\n const directDependentsCount = entries.filter((e) => e.depth === 1).length;\n\n // GAP-29 FIX: depth-weighted risk — direct dependents dominate\n const totalRisk = entries.reduce((sum, e) => sum + e.riskScore, 0);\n const overallRiskScore = Math.round(Math.min(totalRisk / Math.max(directDependentsCount, 1), 1) * 1000) / 1000;\n\n const confirmedCount = entries.filter((e) => e.confidence === 'confirmed').length;\n const likelyCount = entries.filter((e) => e.confidence === 'likely').length;\n const potentialCount = entries.filter((e) => e.confidence === 'potential').length;\n\n return { impactedSymbols: entries, directDependentsCount, confirmedCount, likelyCount, potentialCount, overallRiskScore };\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 { ArchitecturalOverlay } from '../../core/overlay/architectural-overlay.js';\nimport type { StalenessCheck } from './get-logic-slice.js';\n\nconst InputSchema = z.object({\n layer: z.string().optional(),\n});\n\nexport function handleGetArchitecturalOverlay(\n storage: IStoragePort,\n masking: IMaskingPort,\n staleness?: StalenessCheck,\n) {\n const overlay = new ArchitecturalOverlay();\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 files = storage.listIndexedFiles();\n const result = overlay.classify(files);\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 // Filter by layer if specified\n if (parsed.data.layer) {\n const filtered = result.layers[parsed.data.layer];\n const payload = masking.mask(JSON.stringify({ layer: parsed.data.layer, files: filtered ?? [] }));\n return { content: buildContent(payload) };\n }\n\n const payload = masking.mask(JSON.stringify(result));\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","export interface LayerRule {\n readonly pattern: RegExp;\n readonly layer: string;\n}\n\nexport interface OverlayResult {\n readonly layers: Record<string, string[]>;\n}\n\nconst DEFAULT_RULES: LayerRule[] = [\n // Test layer (matched first — __tests__, .test.ts, tests/, fixtures)\n { pattern: /__tests__/, layer: 'Test' },\n { pattern: /\\.test\\.ts$/, layer: 'Test' },\n { pattern: /\\btests\\b/, layer: 'Test' },\n { pattern: /\\bfixtures?\\b/, layer: 'Test' },\n // Composition root\n { pattern: /src\\/index\\.ts$/, layer: 'Composition' },\n // Domain\n { pattern: /\\bcore\\b/, layer: 'Domain' },\n { pattern: /\\bports?\\b/, layer: 'Domain' },\n // Adapter\n { pattern: /\\badapters?\\b/, layer: 'Adapter' },\n { pattern: /\\bcli\\b/, layer: 'Adapter' },\n // Infrastructure\n { pattern: /\\binfra\\b/, layer: 'Infrastructure' },\n { pattern: /\\bdb\\b/, layer: 'Infrastructure' },\n { pattern: /\\bqueue\\b/, layer: 'Infrastructure' },\n // Config files\n { pattern: /\\.(config|rc)\\.(ts|js|json)$/, layer: 'Configuration' },\n];\n\nexport class ArchitecturalOverlay {\n private readonly rules: LayerRule[];\n\n constructor(customRules?: LayerRule[]) {\n this.rules = (customRules ?? DEFAULT_RULES).map(({ pattern, layer }) => ({\n pattern: new RegExp(pattern.source, pattern.flags),\n layer,\n }));\n }\n\n classify(filePaths: readonly string[]): OverlayResult {\n const layers: Record<string, string[]> = {};\n\n for (const filePath of filePaths) {\n const layer = this.matchLayer(filePath);\n const list = layers[layer] ?? [];\n list.push(filePath);\n layers[layer] = list;\n }\n\n return { layers };\n }\n\n private matchLayer(filePath: string): string {\n for (const rule of this.rules) {\n if (rule.pattern.test(filePath)) {\n return rule.layer;\n }\n }\n return 'Unknown';\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 { buildGraphFromJsonIndex, buildGraphFromStorage } 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\nconst 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 = () => {\n const jsonGraph = buildGraphFromJsonIndex(ctxoRoot);\n if (jsonGraph.nodeCount > 0) return jsonGraph;\n return buildGraphFromStorage(storage);\n };\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 = 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(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 { SymbolGraph } from '../graph/symbol-graph.js';\nimport type { SymbolKind } from '../types.js';\n\nexport type DeadCodeConfidence = 1.0 | 0.9 | 0.7;\n\nexport interface DeadSymbolEntry {\n readonly symbolId: string;\n readonly file: string;\n readonly name: string;\n readonly kind: SymbolKind;\n readonly confidence: DeadCodeConfidence;\n readonly reason: string;\n readonly cascadeDepth?: number;\n}\n\nexport interface UnusedExportEntry {\n readonly symbolId: string;\n readonly file: string;\n readonly name: string;\n readonly kind: SymbolKind;\n}\n\nexport interface ScaffoldingEntry {\n readonly file: string;\n readonly line: number;\n readonly pattern: string;\n readonly text: string;\n}\n\nexport interface DeadCodeResult {\n readonly totalSymbols: number;\n readonly reachableSymbols: number;\n readonly deadSymbols: DeadSymbolEntry[];\n readonly unusedExports: UnusedExportEntry[];\n readonly deadFiles: string[];\n readonly scaffolding: ScaffoldingEntry[];\n readonly deadCodePercentage: number;\n}\n\n// Patterns for files to exclude from dead code analysis\nconst TEST_PATTERNS = [/__tests__/, /\\.test\\.ts$/, /\\.spec\\.ts$/, /\\btests\\//, /\\bfixtures?\\//];\nconst CONFIG_PATTERNS = [/\\.(config|rc)\\.(ts|js|json)$/, /tsconfig/, /eslint/, /\\.d\\.ts$/];\n\n// Framework lifecycle symbols — should never be flagged as dead\nconst FRAMEWORK_PATTERNS = [\n // Vitest\n /^(describe|it|expect|beforeAll|beforeEach|afterAll|afterEach|vi)$/,\n // MCP SDK\n /^(registerTool|registerPrompt|connect|close)$/,\n // Zod schemas (conventionally exported for validation)\n /Schema$/,\n // Node.js lifecycle\n /^main$/,\n];\n\n// Scaffolding / AI artifact patterns\nconst SCAFFOLDING_PATTERNS = [\n { regex: /\\bTODO\\b/i, pattern: 'TODO' },\n { regex: /\\bFIXME\\b/i, pattern: 'FIXME' },\n { regex: /\\bHACK\\b/i, pattern: 'HACK' },\n { regex: /\\bPLACEHOLDER\\b/i, pattern: 'PLACEHOLDER' },\n { regex: /\\bXXX\\b/, pattern: 'XXX' },\n { regex: /Phase\\s+\\d|Step\\s+\\d/i, pattern: 'PHASE/STEP' },\n { regex: /not\\s+(?:yet\\s+)?implement/i, pattern: 'NOT_IMPLEMENTED' },\n { regex: /temporary|temp\\s+fix/i, pattern: 'TEMPORARY' },\n];\n\nexport class DeadCodeDetector {\n detect(\n graph: SymbolGraph,\n options: { includeTests?: boolean; sourceContents?: Map<string, string> } = {},\n ): DeadCodeResult {\n const allNodes = graph.allNodes();\n\n // Filter candidates — exclude tests/config by default\n const candidates = options.includeTests\n ? allNodes\n : allNodes.filter((n) => {\n const file = n.symbolId.split('::')[0] ?? '';\n return !this.matchesAny(file, TEST_PATTERNS) && !this.matchesAny(file, CONFIG_PATTERNS);\n });\n\n if (candidates.length === 0) {\n return { totalSymbols: 0, reachableSymbols: 0, deadSymbols: [], unusedExports: [], deadFiles: [], scaffolding: this.detectScaffolding(options.sourceContents), deadCodePercentage: 0 };\n }\n\n // Dynamic entry point detection: symbols with zero reverse edges (no one imports them)\n const candidateIds = new Set(candidates.map((n) => n.symbolId));\n const entryPoints = new Set<string>();\n\n for (const node of candidates) {\n // Framework lifecycle symbols are always entry points (never dead)\n if (this.isFrameworkSymbol(node.name)) {\n entryPoints.add(node.symbolId);\n continue;\n }\n\n const reverseEdges = graph.getReverseEdges(node.symbolId);\n const forwardEdges = graph.getForwardEdges(node.symbolId);\n\n // Filter: only count reverse edges from OTHER candidates\n const incomingFromCandidates = reverseEdges.filter((e) => candidateIds.has(e.from) && e.from !== node.symbolId);\n\n if (incomingFromCandidates.length === 0) {\n const hasOutgoing = forwardEdges.some((e) => candidateIds.has(e.to));\n if (hasOutgoing || reverseEdges.length > 0) {\n entryPoints.add(node.symbolId);\n }\n }\n }\n\n // Forward BFS from all entry points — mark reachable symbols\n const reachable = new Set<string>();\n const queue = [...entryPoints];\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n if (reachable.has(current)) continue;\n reachable.add(current);\n\n for (const edge of graph.getForwardEdges(current)) {\n if (!reachable.has(edge.to) && candidateIds.has(edge.to)) {\n queue.push(edge.to);\n }\n }\n }\n\n // Dead = candidates not reachable from any entry point\n // These are \"island\" symbols — circular deps where the whole cluster is unreachable\n const deadIds = new Set<string>();\n for (const node of candidates) {\n if (!reachable.has(node.symbolId)) {\n deadIds.add(node.symbolId);\n }\n }\n\n // Compute cascade depth: how deep in the dead chain is this symbol?\n const cascadeDepthMap = this.computeCascadeDepths(graph, deadIds, candidateIds);\n\n // Compute confidence per dead symbol\n const deadSymbols: DeadSymbolEntry[] = [];\n for (const node of candidates) {\n if (!deadIds.has(node.symbolId)) continue;\n\n const file = node.symbolId.split('::')[0] ?? '';\n const confidence = this.computeConfidence(graph, node.symbolId, deadIds);\n const cascadeDepth = cascadeDepthMap.get(node.symbolId);\n\n deadSymbols.push({\n symbolId: node.symbolId,\n file,\n name: node.name,\n kind: node.kind,\n confidence,\n reason: this.describeReason(confidence),\n ...(cascadeDepth !== undefined && cascadeDepth > 0 ? { cascadeDepth } : {}),\n });\n }\n\n // Dead files = files where ALL candidate symbols are dead\n const fileStats = new Map<string, { total: number; dead: number }>();\n for (const node of candidates) {\n const file = node.symbolId.split('::')[0] ?? '';\n const stats = fileStats.get(file) ?? { total: 0, dead: 0 };\n stats.total++;\n if (deadIds.has(node.symbolId)) stats.dead++;\n fileStats.set(file, stats);\n }\n\n const deadFiles = [...fileStats.entries()]\n .filter(([, s]) => s.total > 0 && s.dead === s.total)\n .map(([file]) => file);\n\n // Unused exports: symbols with zero reverse edges from other candidates\n // Different from dead code: an unused export may be an entry point (reachable)\n // but still never imported by anyone\n const unusedExports: UnusedExportEntry[] = [];\n for (const node of candidates) {\n const reverseEdges = graph.getReverseEdges(node.symbolId);\n const externalImporters = reverseEdges.filter((e) =>\n candidateIds.has(e.from) && e.from !== node.symbolId,\n );\n\n if (externalImporters.length === 0 && !deadIds.has(node.symbolId)) {\n // Exported, reachable (entry point), but nobody imports it\n unusedExports.push({\n symbolId: node.symbolId,\n file: node.symbolId.split('::')[0] ?? '',\n name: node.name,\n kind: node.kind,\n });\n }\n }\n\n // Scaffolding detection: scan source contents for TODO/FIXME/HACK patterns\n const scaffolding = this.detectScaffolding(options.sourceContents);\n\n const deadCodePercentage = Math.round((deadSymbols.length / candidates.length) * 100 * 10) / 10;\n\n return {\n totalSymbols: candidates.length,\n reachableSymbols: reachable.size,\n deadSymbols,\n unusedExports,\n deadFiles,\n scaffolding,\n deadCodePercentage,\n };\n }\n\n private computeConfidence(\n graph: SymbolGraph,\n symbolId: string,\n deadIds: Set<string>,\n ): DeadCodeConfidence {\n const reverseEdges = graph.getReverseEdges(symbolId);\n\n // 1.0: Zero importers at all — definitely dead\n if (reverseEdges.length === 0) {\n return 1.0;\n }\n\n // 0.9: Has importers but they're all from test/config files\n const allImportersExcluded = reverseEdges.every((e) => {\n const importerFile = e.from.split('::')[0] ?? '';\n return this.matchesAny(importerFile, TEST_PATTERNS) || this.matchesAny(importerFile, CONFIG_PATTERNS);\n });\n if (allImportersExcluded) {\n return 0.9;\n }\n\n // 0.7: All importers are themselves dead (cascading dead code)\n const allImportersDead = reverseEdges.every((e) => deadIds.has(e.from));\n if (allImportersDead) {\n return 0.7;\n }\n\n // Shouldn't reach here if symbol is truly dead, but default to 0.7\n return 0.7;\n }\n\n private describeReason(confidence: DeadCodeConfidence): string {\n switch (confidence) {\n case 1.0:\n return 'Zero importers — no code references this symbol';\n case 0.9:\n return 'Only referenced from test/config files';\n case 0.7:\n return 'All importers are themselves dead (cascading)';\n }\n }\n\n private isFrameworkSymbol(name: string): boolean {\n return FRAMEWORK_PATTERNS.some((p) => p.test(name));\n }\n\n private computeCascadeDepths(\n graph: SymbolGraph,\n deadIds: Set<string>,\n candidateIds: Set<string>,\n ): Map<string, number> {\n const depths = new Map<string, number>();\n\n // Find root dead symbols (zero reverse edges from other dead symbols)\n const rootDead = new Set<string>();\n for (const id of deadIds) {\n const reverseEdges = graph.getReverseEdges(id);\n const deadImporters = reverseEdges.filter((e) => deadIds.has(e.from) && e.from !== id);\n if (deadImporters.length === 0) {\n rootDead.add(id);\n depths.set(id, 0);\n }\n }\n\n // BFS from root dead symbols to compute cascade depth\n const queue = [...rootDead].map((id) => ({ id, depth: 0 }));\n const visited = new Set(rootDead);\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n for (const edge of graph.getForwardEdges(current.id)) {\n if (deadIds.has(edge.to) && !visited.has(edge.to) && candidateIds.has(edge.to)) {\n const newDepth = current.depth + 1;\n depths.set(edge.to, newDepth);\n visited.add(edge.to);\n queue.push({ id: edge.to, depth: newDepth });\n }\n }\n }\n\n return depths;\n }\n\n private detectScaffolding(sourceContents?: Map<string, string>): ScaffoldingEntry[] {\n if (!sourceContents || sourceContents.size === 0) return [];\n\n const results: ScaffoldingEntry[] = [];\n\n for (const [file, content] of sourceContents) {\n // Skip test/config files\n if (this.matchesAny(file, TEST_PATTERNS) || this.matchesAny(file, CONFIG_PATTERNS)) continue;\n\n const lines = content.split('\\n');\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]!;\n for (const { regex, pattern } of SCAFFOLDING_PATTERNS) {\n if (regex.test(line)) {\n results.push({\n file,\n line: i + 1,\n pattern,\n text: line.trim().slice(0, 120),\n });\n break; // One match per line\n }\n }\n }\n }\n\n return results;\n }\n\n private matchesAny(value: string, patterns: RegExp[]): boolean {\n return patterns.some((p) => p.test(value));\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 { ContextAssembler } from '../../core/context-assembly/context-assembler.js';\nimport { JsonIndexReader } from '../storage/json-index-reader.js';\nimport { buildGraphFromJsonIndex, buildGraphFromStorage } 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\nconst 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) {\n const assembler = new ContextAssembler();\n const indexReader = new JsonIndexReader(ctxoRoot);\n\n const getGraph = () => {\n const jsonGraph = buildGraphFromJsonIndex(ctxoRoot);\n if (jsonGraph.nodeCount > 0) return jsonGraph;\n return buildGraphFromStorage(storage);\n };\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 = getGraph();\n const indices = indexReader.readAll();\n\n const result = assembler.assembleForTask(graph, symbolId, taskType, indices, tokenBudget);\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(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","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 type { SymbolNode, SymbolKind, FileIndex } from '../types.js';\nimport { LogicSliceQuery } from '../logic-slice/logic-slice-query.js';\nimport { BlastRadiusCalculator } from '../blast-radius/blast-radius-calculator.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\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 assembleForTask(\n graph: SymbolGraph,\n symbolId: string,\n taskType: TaskType,\n indices: readonly FileIndex[],\n tokenBudget = DEFAULT_TOKEN_BUDGET,\n ): TaskContextResult | undefined {\n const target = graph.getNode(symbolId);\n if (!target) return undefined;\n\n const weights = getWeightsForTask(taskType);\n\n // Gather forward deps + reverse deps\n const slice = this.logicSlice.getLogicSlice(graph, symbolId);\n const blastResult = this.blastRadius.calculate(graph, symbolId);\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)\n for (const entry of blastResult.impactedSymbols) {\n const node = graph.getNode(entry.symbolId);\n if (!node) continue;\n\n const existing = candidateMap.get(entry.symbolId);\n if (existing) {\n existing.signals.isDependent = true;\n } else {\n candidateMap.set(entry.symbolId, {\n node,\n signals: { isDirectDep: false, isInterfaceOrType: this.isInterfaceOrType(node.kind), isDependent: true, 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 = symbolId.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 return { 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 };\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 complexity: number;\n hasAntiPattern: boolean;\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 { buildGraphFromJsonIndex, buildGraphFromStorage } 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\nconst 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 fuzzy: z.boolean().optional().default(true),\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 = () => {\n const jsonGraph = buildGraphFromJsonIndex(ctxoRoot);\n if (jsonGraph.nodeCount > 0) return jsonGraph;\n return buildGraphFromStorage(storage);\n };\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 = 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(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 }\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(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","/**\n * Symbol Tokenizer — splits symbol names into searchable tokens.\n *\n * Handles camelCase, PascalCase, snake_case, kebab-case, and digit boundaries.\n * Used to populate FTS5 `tokenized_name` columns and to tokenize search queries.\n */\n\nconst STOP_WORDS = new Set([\n 'get', 'set', 'is', 'has', 'can', 'do', 'the', 'a', 'an', 'of', 'to', 'in',\n 'for', 'on', 'with', 'at', 'by', 'from', 'as', 'into', 'not', 'no', 'or',\n]);\n\nexport interface TokenizerOptions {\n /** Include stop-word tokens in output (default: false) */\n includeStopWords?: boolean;\n /** Include the full original name as an additional token (default: true) */\n includeOriginal?: boolean;\n /** Include file path segments as tokens (default: false) */\n includeFilePath?: boolean;\n}\n\nconst DEFAULT_OPTIONS: Required<TokenizerOptions> = {\n includeStopWords: false,\n includeOriginal: true,\n includeFilePath: false,\n};\n\nexport class SymbolTokenizer {\n private readonly options: Required<TokenizerOptions>;\n\n constructor(options?: TokenizerOptions) {\n this.options = { ...DEFAULT_OPTIONS, ...options };\n }\n\n /**\n * Tokenize a symbol name into searchable tokens.\n *\n * Examples:\n * \"getCoChangeMetrics\" → [\"get\", \"co\", \"change\", \"metrics\"] (or without stop words: [\"co\", \"change\", \"metrics\"])\n * \"SqliteStorageAdapter\" → [\"sqlite\", \"storage\", \"adapter\"]\n * \"i_storage_port\" → [\"i\", \"storage\", \"port\"]\n * \"BM25Scorer\" → [\"bm\", \"25\", \"scorer\"]\n * \"DB_PASSWORD\" → [\"db\", \"password\"]\n */\n tokenize(symbolName: string, filePath?: string): string[] {\n const splitTokens = SymbolTokenizer.splitName(symbolName);\n const lowered = splitTokens.map((t) => t.toLowerCase());\n\n const tokens: string[] = this.options.includeStopWords\n ? lowered\n : lowered.filter((t) => !STOP_WORDS.has(t));\n\n // Preserve original name as a token for exact matching\n if (this.options.includeOriginal) {\n const original = symbolName.toLowerCase();\n if (!tokens.includes(original)) {\n tokens.unshift(original);\n }\n }\n\n // Include file path segments\n if (this.options.includeFilePath && filePath) {\n const pathTokens = SymbolTokenizer.tokenizeFilePath(filePath);\n for (const pt of pathTokens) {\n if (!tokens.includes(pt)) {\n tokens.push(pt);\n }\n }\n }\n\n return tokens;\n }\n\n /**\n * Tokenize a search query. Queries use stop words and don't include originals.\n */\n tokenizeQuery(query: string): string[] {\n const words = query.trim().split(/\\s+/);\n const tokens: string[] = [];\n for (const word of words) {\n const split = SymbolTokenizer.splitName(word);\n for (const t of split) {\n const lowered = t.toLowerCase();\n if (lowered.length > 0 && !tokens.includes(lowered)) {\n tokens.push(lowered);\n }\n }\n }\n return tokens;\n }\n\n /**\n * Split a name into constituent words based on naming convention boundaries.\n *\n * Rules:\n * 1. Split on underscores and hyphens (snake_case, kebab-case)\n * 2. Split on camelCase/PascalCase boundaries (uppercase after lowercase)\n * 3. Split acronym boundaries (e.g., \"HTMLParser\" → [\"HTML\", \"Parser\"])\n * 4. Split on digit ↔ letter boundaries\n */\n static splitName(name: string): string[] {\n if (!name || name.length === 0) return [];\n\n // Step 1: Split on underscores, hyphens, dots, slashes\n const segments = name.split(/[_\\-./\\\\]+/).filter((s) => s.length > 0);\n\n const tokens: string[] = [];\n for (const segment of segments) {\n tokens.push(...SymbolTokenizer.splitCamelCase(segment));\n }\n\n return tokens.filter((t) => t.length > 0);\n }\n\n /**\n * Split a single segment on camelCase/PascalCase/digit boundaries.\n */\n private static splitCamelCase(segment: string): string[] {\n const tokens: string[] = [];\n let current = '';\n\n for (let i = 0; i < segment.length; i++) {\n const ch = segment[i]!;\n const prev = i > 0 ? segment[i - 1]! : '';\n\n // Boundary: letter → digit or digit → letter\n if (current.length > 0) {\n const prevIsDigit = isDigit(prev);\n const currIsDigit = isDigit(ch);\n if (prevIsDigit !== currIsDigit) {\n tokens.push(current);\n current = ch;\n continue;\n }\n }\n\n // Boundary: lowercase → uppercase (camelCase boundary)\n if (current.length > 0 && isLower(prev) && isUpper(ch)) {\n tokens.push(current);\n current = ch;\n continue;\n }\n\n // Acronym boundary: multiple uppercase followed by lowercase\n // \"HTMLParser\": H-T-M-L-P-a → when we hit 'a', current=\"HTMLP\"\n // We should split to \"HTML\" + \"Pa...\"\n if (current.length > 1 && isUpper(ch) === false && isUpper(prev) && !isDigit(ch)) {\n // prev is uppercase, current char is lowercase → split before prev\n const lastChar = current[current.length - 1]!;\n if (isUpper(lastChar)) {\n tokens.push(current.slice(0, -1));\n current = lastChar + ch;\n continue;\n }\n }\n\n current += ch;\n }\n\n if (current.length > 0) {\n tokens.push(current);\n }\n\n return tokens;\n }\n\n /**\n * Extract searchable tokens from a file path.\n * \"src/core/search/symbol-tokenizer.ts\" → [\"src\", \"core\", \"search\", \"symbol\", \"tokenizer\", \"ts\"]\n */\n static tokenizeFilePath(filePath: string): string[] {\n // Remove extension, split on separators\n const withoutExt = filePath.replace(/\\.[^.]+$/, '');\n const segments = withoutExt.split(/[/\\\\]+/);\n const tokens: string[] = [];\n for (const seg of segments) {\n const parts = seg.split(/[_\\-.]+/).filter((s) => s.length > 0);\n for (const p of parts) {\n const lowered = p.toLowerCase();\n if (lowered.length > 0 && !tokens.includes(lowered)) {\n tokens.push(lowered);\n }\n }\n }\n return tokens;\n }\n\n /** Check if a token is a stop word */\n static isStopWord(token: string): boolean {\n return STOP_WORDS.has(token.toLowerCase());\n }\n}\n\nfunction isUpper(ch: string): boolean {\n return ch >= 'A' && ch <= 'Z';\n}\n\nfunction isLower(ch: string): boolean {\n return ch >= 'a' && ch <= 'z';\n}\n\nfunction isDigit(ch: string): boolean {\n return ch >= '0' && ch <= '9';\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 { buildGraphFromJsonIndex, buildGraphFromStorage } 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';\n\nconst InputSchema = z.object({\n pattern: z.string().min(1),\n kind: z.enum(['function', 'class', 'interface', 'method', 'variable', 'type']).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) {\n const engine: ISearchPort = searchEngine ?? new SearchEngine();\n let lastFtsNodeCount = -1;\n\n const getGraph = () => {\n const jsonGraph = buildGraphFromJsonIndex(ctxoRoot);\n if (jsonGraph.nodeCount > 0) return jsonGraph;\n return buildGraphFromStorage(storage);\n };\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 = 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 payload = masking.mask(JSON.stringify(wrapResponse({\n totalMatches: ftsResults.length,\n results,\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(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 }\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 payload = masking.mask(JSON.stringify(wrapResponse({\n totalMatches: matches.length,\n results,\n })));\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 { 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 { buildGraphFromJsonIndex, buildGraphFromStorage } from './get-logic-slice.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\n\nconst 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 = () => {\n const jsonGraph = buildGraphFromJsonIndex(ctxoRoot);\n if (jsonGraph.nodeCount > 0) return jsonGraph;\n return buildGraphFromStorage(storage);\n };\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 = 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(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 { 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 { buildGraphFromJsonIndex, buildGraphFromStorage } from './get-logic-slice.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\nimport { filterByIntent } from '../../core/intent-filter.js';\n\nconst InputSchema = z.object({\n symbolId: z.string().min(1),\n edgeKinds: z.array(z.enum(['imports', 'calls', 'extends', 'implements', 'uses'])).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) {\n const getGraph = () => {\n const jsonGraph = buildGraphFromJsonIndex(ctxoRoot);\n if (jsonGraph.nodeCount > 0) return jsonGraph;\n return buildGraphFromStorage(storage);\n };\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 = getGraph();\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 const importers: Array<{\n symbolId: string;\n name: string;\n kind: string;\n file: string;\n edgeKind: string;\n depth: number;\n }> = [];\n\n if (!transitive) {\n // Direct importers only — deduplicate by symbolId, aggregate edgeKinds\n const reverseEdges = graph.getReverseEdges(symbolId);\n const seen = new Map<string, { node: typeof importers[0]; edgeKinds: string[] }>();\n for (const edge of reverseEdges) {\n if (edgeKinds && !edgeKinds.includes(edge.kind as 'imports' | 'calls' | 'extends' | 'implements' | 'uses')) 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 depth: 1,\n };\n seen.set(node.symbolId, { node: entry, edgeKinds: [edge.kind] });\n importers.push(entry);\n }\n }\n }\n } else {\n // BFS for transitive importers\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 if (current.depth >= maxDepth) continue;\n\n const reverseEdges = graph.getReverseEdges(current.id);\n for (const edge of reverseEdges) {\n if (edgeKinds && !edgeKinds.includes(edge.kind as 'imports' | 'calls' | 'extends' | 'implements' | 'uses')) 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 payload = masking.mask(JSON.stringify(wrapResponse({\n symbolId,\n importerCount: filtered.length,\n importers: filtered,\n })));\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 { 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 { buildGraphFromJsonIndex, buildGraphFromStorage } from './get-logic-slice.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\n\nconst 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 = () => {\n const jsonGraph = buildGraphFromJsonIndex(ctxoRoot);\n if (jsonGraph.nodeCount > 0) return jsonGraph;\n return buildGraphFromStorage(storage);\n };\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 = getGraph();\n\n if (symbolId) {\n return handleRooted(graph, symbolId, direction, masking, staleness, storage);\n }\n\n return handleFull(graph, masking, staleness, storage);\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: ReturnType<typeof getGraph>,\n symbolId: string,\n direction: 'ancestors' | 'descendants' | 'both',\n maskingPort: IMaskingPort,\n stalenessCheck: StalenessCheck | undefined,\n storagePort: IStoragePort,\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) => kind === 'extends' || kind === 'implements';\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(storagePort.listIndexedFiles());\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: ReturnType<typeof getGraph>,\n maskingPort: IMaskingPort,\n stalenessCheck: StalenessCheck | undefined,\n storagePort: IStoragePort,\n ) {\n const isHierarchyEdge = (kind: string) => kind === 'extends' || kind === 'implements';\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(storagePort.listIndexedFiles());\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 { buildGraphFromJsonIndex, buildGraphFromStorage } from './get-logic-slice.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\n\nconst InputSchema = z.object({\n limit: z.number().int().min(1).max(200).optional().default(25),\n kind: z.enum(['function', 'class', 'interface', 'method', 'variable', 'type']).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 = () => {\n const jsonGraph = buildGraphFromJsonIndex(ctxoRoot);\n if (jsonGraph.nodeCount > 0) return jsonGraph;\n return buildGraphFromStorage(storage);\n };\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 = 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(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 { SymbolGraph } from '../graph/symbol-graph.js';\n\nexport interface PageRankEntry {\n readonly symbolId: string;\n readonly name: string;\n readonly kind: string;\n readonly file: string;\n readonly score: number;\n readonly inDegree: number;\n readonly outDegree: number;\n}\n\nexport interface PageRankResult {\n readonly rankings: PageRankEntry[];\n readonly totalSymbols: number;\n readonly iterations: number;\n readonly converged: boolean;\n}\n\nexport interface PageRankOptions {\n readonly damping?: number;\n readonly maxIterations?: number;\n readonly tolerance?: number;\n readonly limit?: number;\n}\n\nconst DEFAULT_DAMPING = 0.85;\nconst DEFAULT_MAX_ITERATIONS = 100;\nconst DEFAULT_TOLERANCE = 1e-6;\nconst DEFAULT_LIMIT = 25;\n\nexport class PageRankCalculator {\n calculate(graph: SymbolGraph, options: PageRankOptions = {}): PageRankResult {\n const damping = options.damping ?? DEFAULT_DAMPING;\n const maxIterations = options.maxIterations ?? DEFAULT_MAX_ITERATIONS;\n const tolerance = options.tolerance ?? DEFAULT_TOLERANCE;\n const limit = options.limit ?? DEFAULT_LIMIT;\n\n const nodes = graph.allNodes();\n const n = nodes.length;\n\n if (n === 0) {\n return { rankings: [], totalSymbols: 0, iterations: 0, converged: true };\n }\n\n // Initialize scores uniformly\n const scores = new Map<string, number>();\n const initialScore = 1 / n;\n for (const node of nodes) {\n scores.set(node.symbolId, initialScore);\n }\n\n // Precompute out-degree for each node\n const outDegree = new Map<string, number>();\n for (const node of nodes) {\n outDegree.set(node.symbolId, graph.getForwardEdges(node.symbolId).length);\n }\n\n // Iterative PageRank\n // Edge direction: A->B means \"A depends on B\" (A imports/calls/uses B)\n // PageRank: B is important if many important nodes link to B\n // Score distribution: each node distributes its score via forward edges to dependencies\n // So we accumulate via reverse edges: for each node, sum score from nodes that point to it\n let iterations = 0;\n let converged = false;\n\n while (iterations < maxIterations) {\n const newScores = new Map<string, number>();\n const base = (1 - damping) / n;\n\n // Handle dangling nodes (no outgoing edges) — distribute their score evenly\n let danglingSum = 0;\n for (const node of nodes) {\n if ((outDegree.get(node.symbolId) ?? 0) === 0) {\n danglingSum += scores.get(node.symbolId) ?? 0;\n }\n }\n const danglingContrib = damping * danglingSum / n;\n\n for (const node of nodes) {\n let incomingScore = 0;\n\n // Sum contributions from all nodes that have a forward edge TO this node\n // (i.e., reverse edges of this node)\n const reverseEdges = graph.getReverseEdges(node.symbolId);\n const contributors = new Set<string>();\n for (const edge of reverseEdges) {\n if (contributors.has(edge.from)) continue; // deduplicate multi-edges\n contributors.add(edge.from);\n const fromScore = scores.get(edge.from) ?? 0;\n const fromOut = outDegree.get(edge.from) ?? 1;\n incomingScore += fromScore / fromOut;\n }\n\n newScores.set(node.symbolId, base + damping * incomingScore + danglingContrib);\n }\n\n // Check convergence\n let maxDelta = 0;\n for (const node of nodes) {\n const delta = Math.abs((newScores.get(node.symbolId) ?? 0) - (scores.get(node.symbolId) ?? 0));\n if (delta > maxDelta) maxDelta = delta;\n }\n\n // Update scores\n for (const [id, score] of newScores) {\n scores.set(id, score);\n }\n\n iterations++;\n\n if (maxDelta < tolerance) {\n converged = true;\n break;\n }\n }\n\n // Build ranked results\n const entries: PageRankEntry[] = nodes.map((node) => ({\n symbolId: node.symbolId,\n name: node.name,\n kind: node.kind,\n file: node.symbolId.split('::')[0] ?? '',\n score: Math.round((scores.get(node.symbolId) ?? 0) * 1_000_000) / 1_000_000,\n inDegree: graph.getReverseEdges(node.symbolId).length,\n outDegree: outDegree.get(node.symbolId) ?? 0,\n }));\n\n // Sort by score descending\n entries.sort((a, b) => b.score - a.score);\n\n return {\n rankings: entries.slice(0, limit),\n totalSymbols: n,\n iterations,\n converged,\n };\n }\n}\n","import { z } from 'zod';\nimport { readFileSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\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 { buildGraphFromJsonIndex, buildGraphFromStorage } from './get-logic-slice.js';\nimport { BlastRadiusCalculator } from '../../core/blast-radius/blast-radius-calculator.js';\nimport { wrapResponse } from '../../core/response-envelope.js';\nimport { loadCoChangeMap } from '../../core/co-change/co-change-analyzer.js';\nimport type { CoChangeMatrix, CoChangeEntry } from '../../core/types.js';\n\nconst 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 loadCoChanges(ctxoRoot: string): Map<string, CoChangeEntry[]> | undefined {\n const path = join(ctxoRoot, 'index', 'co-changes.json');\n if (!existsSync(path)) return undefined;\n try {\n const matrix: CoChangeMatrix = JSON.parse(readFileSync(path, 'utf-8'));\n return loadCoChangeMap(matrix);\n } catch {\n return undefined;\n }\n}\n\nexport function handleGetPrImpact(\n storage: IStoragePort,\n git: IGitPort,\n masking: IMaskingPort,\n staleness?: StalenessCheck,\n ctxoRoot = '.ctxo',\n) {\n const calculator = new BlastRadiusCalculator();\n const getGraph = () => {\n const jsonGraph = buildGraphFromJsonIndex(ctxoRoot);\n if (jsonGraph.nodeCount > 0) return jsonGraph;\n return buildGraphFromStorage(storage);\n };\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 = getGraph();\n const coChangeMap = loadCoChanges(ctxoRoot);\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 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 payload = masking.mask(JSON.stringify(wrapResponse({\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\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 { 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"],"mappings":"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","names":["z","existsSync","readFileSync","join","z","InputSchema","z","z","InputSchema","z","z","InputSchema","z","z","InputSchema","z","payload","z","InputSchema","z","z","z","InputSchema","z","log","log","InputSchema","z","payload","content","z","InputSchema","z","results","payload","content","z","InputSchema","z","z","InputSchema","z","z","InputSchema","z","visited","z","InputSchema","z","z","InputSchema","z","log","join","existsSync","readFileSync","z"]}