inspect-mcp 0.2.0 → 0.2.1

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/runtime/index.ts","../src/types/index.ts","../src/config/index.ts","../src/services/scanner/project-detector.ts","../src/services/scanner/file-tree-builder.ts","../src/services/git/index.ts","../src/services/cache/index.ts","../src/services/parser/symbol-index.ts","../src/services/parser/grammar-loader.ts","../src/services/parser/index.ts","../src/services/parser/extractors/typescript.ts","../src/services/parser/extractors/python.ts","../src/services/parser/extractors/java.ts","../src/services/parser/extractors/index.ts","../src/services/parser/utils.ts","../src/services/parser/dependency-graph.ts","../src/services/parser/import-extractors/typescript.ts","../src/services/parser/import-extractors/python.ts","../src/services/parser/import-extractors/java.ts","../src/services/parser/import-extractors/index.ts","../src/services/parser/path-resolver.ts","../src/services/health/index.ts","../src/services/health/parsers.ts","../src/services/scanner/index.ts","../src/services/impact/usage-finder.ts","../src/services/differ/test-association.ts","../src/services/impact/index.ts","../src/services/differ/blast-radius.ts","../src/services/differ/symbol-diff.ts","../src/services/differ/health-diff.ts","../src/services/differ/index.ts","../src/services/scanner/compact-formatter.ts","../src/index.ts"],"sourcesContent":["/**\n * MCP server setup, tool registration, and command routing.\n */\n\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { z } from \"zod\";\nimport { InspectParamsSchema } from \"../types/index.js\";\nimport { scan } from \"../services/scanner/index.js\";\nimport { analyzeImpact } from \"../services/impact/index.js\";\nimport { changed } from \"../services/differ/index.js\";\nimport { compactify } from \"../services/scanner/compact-formatter.js\";\n\n/**\n * Create and configure the MCP server with the `inspect` tool.\n */\nexport function createServer(): Server {\n const server = new Server(\n {\n name: \"inspect-mcp\",\n version: \"0.1.0\",\n },\n {\n capabilities: {\n tools: {},\n },\n },\n );\n\n // Register available tools\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n {\n name: \"inspect\",\n description:\n \"Analyze a codebase and return structured project info, file tree, symbols, dependencies, and health status. Commands: scan (full/incremental scan), changed (delta since last scan), impact (dependency analysis for a target).\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n command: {\n type: \"string\",\n enum: [\"scan\", \"changed\", \"impact\"],\n default: \"scan\",\n description: \"Command to execute\",\n },\n path: {\n type: \"string\",\n description: \"Absolute path to the project root directory\",\n },\n include_health: {\n type: \"boolean\",\n default: false,\n description: \"Run linter/type-checker and include health results\",\n },\n target: {\n type: \"string\",\n description:\n \"For impact command: file_path or file_path:symbol_name to analyze\",\n },\n compact: {\n type: \"boolean\",\n default: true,\n description:\n \"Return compact summary (default: true). Set to false for full JSON output.\",\n },\n },\n required: [\"path\"],\n },\n },\n ],\n }));\n\n // Handle tool calls\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n if (request.params.name !== \"inspect\") {\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ error: `Unknown tool: ${request.params.name}` }),\n },\n ],\n isError: true,\n };\n }\n\n // Validate parameters at the boundary\n const parseResult = InspectParamsSchema.safeParse(request.params.arguments);\n if (!parseResult.success) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"Invalid parameters\",\n details: parseResult.error.issues,\n }),\n },\n ],\n isError: true,\n };\n }\n\n const params = parseResult.data;\n return routeCommand(params);\n });\n\n return server;\n}\n\n/**\n * Route a validated command to the appropriate handler.\n */\nasync function routeCommand(params: z.infer<typeof InspectParamsSchema>) {\n try {\n switch (params.command) {\n case \"scan\": {\n const fullResult = await scan(params.path, params.include_health);\n const result = params.compact ? compactify(fullResult) : fullResult;\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n };\n }\n\n case \"changed\": {\n const changedResult = await changed(params.path, params.include_health);\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(changedResult, null, 2) }],\n };\n }\n\n case \"impact\": {\n if (!params.target) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"The 'target' parameter is required for the impact command.\",\n }),\n },\n ],\n isError: true,\n };\n }\n const impactResult = await analyzeImpact(params.path, params.target);\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(impactResult, null, 2) }],\n };\n }\n\n default: {\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ error: `Unknown command: ${params.command}` }),\n },\n ],\n isError: true,\n };\n }\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ error: \"Internal error\", message }),\n },\n ],\n isError: true,\n };\n }\n}\n\n/**\n * Start the MCP server on stdio transport.\n */\nexport async function startServer(): Promise<void> {\n const server = createServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n","/**\n * Shared type definitions for inspect-mcp.\n *\n * This module defines all Zod schemas and their inferred TypeScript types.\n * Types layer must NOT import from any other layer.\n */\n\nimport { z } from \"zod\";\n\n// ---------------------------------------------------------------------------\n// Project Info\n// ---------------------------------------------------------------------------\n\nexport const DetectedToolsSchema = z.object({\n linter: z.string().nullable(),\n type_checker: z.string().nullable(),\n test_runner: z.string().nullable(),\n formatter: z.string().nullable(),\n});\n\nexport type DetectedTools = z.infer<typeof DetectedToolsSchema>;\n\nexport const SubProjectSchema = z.object({\n path: z.string(),\n language: z.string(),\n framework: z.string().nullable(),\n package_manager: z.string().nullable(),\n detected_tools: DetectedToolsSchema,\n});\n\nexport type SubProject = z.infer<typeof SubProjectSchema>;\n\nexport const ProjectInfoSchema = z.object({\n name: z.string(),\n language: z.string(),\n framework: z.string().nullable(),\n framework_version: z.string().nullable(),\n package_manager: z.string().nullable(),\n runtime: z.string().nullable(),\n entry_points: z.array(z.string()),\n scripts: z.record(z.string(), z.string()),\n detected_tools: DetectedToolsSchema,\n sub_projects: z.array(SubProjectSchema).optional(),\n});\n\nexport type ProjectInfo = z.infer<typeof ProjectInfoSchema>;\n\n// ---------------------------------------------------------------------------\n// File Tree\n// ---------------------------------------------------------------------------\n\nexport const CollapsedDirSchema = z.object({\n _collapsed: z.literal(true),\n file_count: z.number(),\n});\n\nexport type CollapsedDir = z.infer<typeof CollapsedDirSchema>;\n\nexport const FileEntrySchema = z.object({\n size: z.number(),\n symbols: z.number().optional(),\n});\n\nexport type FileEntry = z.infer<typeof FileEntrySchema>;\n\n/**\n * A file tree node is either a collapsed directory summary, a file entry,\n * or a nested record of more tree nodes.\n */\nexport type FileTreeEntry = CollapsedDir | FileEntry | { [key: string]: FileTreeEntry };\n\n// We can't directly do recursive Zod, so we use z.lazy for the tree schema.\nexport const FileTreeEntrySchema: z.ZodType<FileTreeEntry> = z.lazy(() =>\n z.union([CollapsedDirSchema, FileEntrySchema, z.record(z.string(), FileTreeEntrySchema)]),\n);\n\n// ---------------------------------------------------------------------------\n// Symbols\n// ---------------------------------------------------------------------------\n\nexport const SymbolKindEnum = z.enum([\n \"function\",\n \"arrow_function\",\n \"class\",\n \"interface\",\n \"type_alias\",\n \"method\",\n \"field\",\n \"enum\",\n \"constant\",\n \"constructor\",\n \"package\",\n]);\n\nexport type SymbolKind = z.infer<typeof SymbolKindEnum>;\n\nexport const VisibilityEnum = z.enum([\"public\", \"private\", \"protected\", \"package\"]);\n\nexport type Visibility = z.infer<typeof VisibilityEnum>;\n\nexport const SymbolSchema = z.object({\n /** Symbol name. */\n name: z.string(),\n /** What kind of symbol this is. */\n kind: SymbolKindEnum,\n /** Whether the symbol is exported / public. */\n exported: z.boolean(),\n /** 1-based start line. */\n line: z.number(),\n /** 1-based end line. */\n end_line: z.number().optional(),\n /** Human-readable signature (e.g. \"(id: string) => Promise<User>\"). */\n signature: z.string().nullable().optional(),\n /** Visibility modifier (Java: public/private/protected/package). */\n visibility: VisibilityEnum.nullable().optional(),\n /** Annotations / decorators (Java annotations, Python decorators). */\n annotations: z.array(z.string()).optional(),\n /** Whether the symbol is async. */\n is_async: z.boolean().optional(),\n});\n\nexport type Symbol = z.infer<typeof SymbolSchema>;\n\n// ---------------------------------------------------------------------------\n// Cache\n// ---------------------------------------------------------------------------\n\nexport const CacheStatusSchema = z.object({\n status: z.enum([\"fresh\", \"incremental_update\", \"cache_hit\", \"no_cache\"]),\n git_head: z.string().nullable(),\n scanned_at: z.string(),\n scan_duration_ms: z.number(),\n files_rescanned: z.number().optional(),\n});\n\nexport type CacheStatus = z.infer<typeof CacheStatusSchema>;\n\n// ---------------------------------------------------------------------------\n// Health\n// ---------------------------------------------------------------------------\n\nexport const HealthIssueSeverityEnum = z.enum([\"error\", \"warning\", \"info\"]);\n\nexport type HealthIssueSeverity = z.infer<typeof HealthIssueSeverityEnum>;\n\nexport const HealthIssueSchema = z.object({\n file: z.string(),\n line: z.number().nullable(),\n column: z.number().nullable(),\n severity: HealthIssueSeverityEnum,\n code: z.string().nullable(),\n message: z.string(),\n tool: z.string(),\n});\n\nexport type HealthIssue = z.infer<typeof HealthIssueSchema>;\n\nexport const HealthToolResultSchema = z.object({\n tool: z.string(),\n success: z.boolean(),\n run_duration_ms: z.number(),\n error_count: z.number(),\n warning_count: z.number(),\n error_message: z.string().nullable(),\n});\n\nexport type HealthToolResult = z.infer<typeof HealthToolResultSchema>;\n\nexport const HealthResultSchema = z.object({\n tools_run: z.array(HealthToolResultSchema),\n total_errors: z.number(),\n total_warnings: z.number(),\n issues: z.array(HealthIssueSchema),\n run_duration_ms: z.number(),\n});\n\nexport type HealthResult = z.infer<typeof HealthResultSchema>;\n\nexport const HealthDiffSchema = z.object({\n new_issues: z.array(HealthIssueSchema),\n resolved_issues: z.array(HealthIssueSchema),\n});\n\nexport type HealthDiff = z.infer<typeof HealthDiffSchema>;\n\n// ---------------------------------------------------------------------------\n// Dependencies\n// ---------------------------------------------------------------------------\n\nexport const DependencyEntrySchema = z.object({\n imports_from: z.array(z.string()),\n imported_by: z.array(z.string()),\n});\n\nexport type DependencyEntry = z.infer<typeof DependencyEntrySchema>;\n\n// ---------------------------------------------------------------------------\n// Scan Result\n// ---------------------------------------------------------------------------\n\nexport const ScanResultSchema = z.object({\n project: ProjectInfoSchema,\n tree: z.record(z.string(), FileTreeEntrySchema),\n symbols: z.record(z.string(), z.array(SymbolSchema)).nullable(),\n dependencies: z.record(z.string(), DependencyEntrySchema).nullable(),\n health: HealthResultSchema.nullable(),\n cache: CacheStatusSchema,\n});\n\nexport type ScanResult = z.infer<typeof ScanResultSchema>;\n\n// ---------------------------------------------------------------------------\n// Compact Scan Result (agent-friendly summary)\n// ---------------------------------------------------------------------------\n\nexport const DirSummarySchema = z.object({\n files: z.number(),\n languages: z.array(z.string()),\n key_dirs: z.array(z.string()).optional(),\n collapsed: z.boolean().optional(),\n});\n\nexport type DirSummary = z.infer<typeof DirSummarySchema>;\n\nexport const CompactScanResultSchema = z.object({\n project: ProjectInfoSchema,\n structure: z.record(z.string(), DirSummarySchema),\n symbols_summary: z.object({\n total: z.number(),\n by_kind: z.record(z.string(), z.number()),\n key_exports: z.array(z.string()),\n }).nullable(),\n dependencies_summary: z.object({\n total_files: z.number(),\n most_imported: z.array(z.string()),\n most_importing: z.array(z.string()),\n }).nullable(),\n health: HealthResultSchema.nullable(),\n cache: CacheStatusSchema,\n});\n\nexport type CompactScanResult = z.infer<typeof CompactScanResultSchema>;\n\n// ---------------------------------------------------------------------------\n// Changed Result\n// ---------------------------------------------------------------------------\n\nexport const ChangedResultSchema = z.object({\n changes: z.object({\n since_commit: z.string(),\n current_commit: z.string(),\n files_changed: z.array(\n z.object({\n path: z.string(),\n status: z.enum([\"added\", \"modified\", \"deleted\", \"renamed\"]),\n source: z.enum([\"pull\", \"local_commit\", \"uncommitted\"]),\n author: z.string().nullable(),\n commit_message: z.string().nullable(),\n }),\n ),\n blast_radius: z.array(\n z.object({\n changed_file: z.string(),\n affected_files: z.array(z.string()),\n reason: z.string(),\n }),\n ),\n new_symbols: z.array(z.object({ file: z.string(), symbol: SymbolSchema })),\n removed_symbols: z.array(z.object({ file: z.string(), symbol: SymbolSchema })),\n modified_symbols: z.array(\n z.object({ file: z.string(), before: SymbolSchema, after: SymbolSchema }),\n ),\n }),\n health_diff: HealthDiffSchema.nullable(),\n cache: CacheStatusSchema,\n});\n\nexport type ChangedResult = z.infer<typeof ChangedResultSchema>;\n\n// ---------------------------------------------------------------------------\n// Impact Result\n// ---------------------------------------------------------------------------\n\nexport const UsageSiteSchema = z.object({\n line: z.number(),\n context: z.string(),\n});\n\nexport type UsageSite = z.infer<typeof UsageSiteSchema>;\n\nexport const DirectDependentSchema = z.object({\n file: z.string(),\n usages: z.array(UsageSiteSchema),\n});\n\nexport type DirectDependent = z.infer<typeof DirectDependentSchema>;\n\nexport const TransitiveDependentSchema = z.object({\n file: z.string(),\n via: z.string(),\n depth: z.number(),\n});\n\nexport type TransitiveDependent = z.infer<typeof TransitiveDependentSchema>;\n\nexport const TestCoverageSchema = z.object({\n test_files_found: z.array(z.string()),\n imports_target: z.boolean(),\n});\n\nexport type TestCoverage = z.infer<typeof TestCoverageSchema>;\n\nexport const ImpactResultSchema = z.object({\n target: z.object({\n file: z.string(),\n symbol: z.string().nullable(),\n kind: z.string().nullable(),\n line: z.number().nullable(),\n signature: z.string().nullable(),\n }),\n dependents: z.object({\n direct: z.array(DirectDependentSchema),\n transitive: z.array(TransitiveDependentSchema),\n }),\n risk_assessment: z.object({\n direct_dependents: z.number(),\n total_usages: z.number(),\n transitive_dependents: z.number(),\n test_coverage: TestCoverageSchema.nullable(),\n }),\n});\n\nexport type ImpactResult = z.infer<typeof ImpactResultSchema>;\n\n// ---------------------------------------------------------------------------\n// Inspect Config (user-facing configuration)\n// ---------------------------------------------------------------------------\n\nexport const InspectConfigSchema = z.object({\n collapse_dirs: z.array(z.string()).optional(),\n ignore_patterns: z.array(z.string()).optional(),\n max_file_size_kb: z.number().optional(),\n tree_depth: z.number().optional(),\n health_timeout_ms: z.number().optional(),\n languages: z.array(z.string()).optional(),\n path_aliases: z.union([z.literal(\"auto\"), z.record(z.string(), z.string())]).optional(),\n});\n\nexport type InspectConfig = z.infer<typeof InspectConfigSchema>;\n\n// ---------------------------------------------------------------------------\n// MCP Tool Parameters\n// ---------------------------------------------------------------------------\n\nexport const InspectParamsSchema = z.object({\n command: z.enum([\"scan\", \"changed\", \"impact\"]).default(\"scan\"),\n path: z.string(),\n include_health: z.boolean().default(false),\n target: z.string().optional(),\n compact: z.boolean().default(true),\n});\n\nexport type InspectParams = z.infer<typeof InspectParamsSchema>;\n\n// ---------------------------------------------------------------------------\n// Cache Meta (internal cache metadata)\n// ---------------------------------------------------------------------------\n\nexport const CacheMetaSchema = z.object({\n version: z.string(),\n git_head: z.string().nullable(),\n scanned_at: z.string(),\n});\n\nexport type CacheMeta = z.infer<typeof CacheMetaSchema>;\n","/**\n * Configuration loading and defaults.\n *\n * May import from Types layer only.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { InspectConfigSchema, type InspectConfig } from \"../types/index.js\";\n\n/** Default collapse directories — heavy or generated content that should be summarised. */\nexport const DEFAULT_COLLAPSE_DIRS = [\n \"node_modules\",\n \"dist\",\n \"build\",\n \".next\",\n \"target\",\n \"__pycache__\",\n \".git\",\n \"venv\",\n \".venv\",\n \"vendor\",\n];\n\n/** Default ignore patterns — files that add noise to the tree. */\nexport const DEFAULT_IGNORE_PATTERNS = [\"*.min.js\", \"*.generated.*\", \"*.d.ts\", \"*.map\"];\n\n/** Default max file size in KB above which files are skipped during parsing. */\nexport const DEFAULT_MAX_FILE_SIZE_KB = 100;\n\n/** Default tree depth limit. */\nexport const DEFAULT_TREE_DEPTH = 6;\n\n/** Default health check timeout per tool in milliseconds. */\nexport const DEFAULT_HEALTH_TIMEOUT_MS = 15_000;\n\n/** Auto-collapse threshold — dirs with more than this many files and no source code. */\nexport const AUTO_COLLAPSE_FILE_THRESHOLD = 500;\n\n/** Tool version written into cache metadata. */\nexport const TOOL_VERSION = \"0.2.0\";\n\n/**\n * Resolved configuration with all defaults applied.\n */\nexport interface ResolvedConfig {\n collapse_dirs: string[];\n ignore_patterns: string[];\n max_file_size_kb: number;\n tree_depth: number;\n health_timeout_ms: number;\n path_aliases?: Record<string, string> | \"auto\";\n}\n\n/**\n * Load optional `inspect.config.json` from the project root.\n * Falls back to defaults for any unspecified fields.\n */\nexport function loadConfig(projectRoot: string): ResolvedConfig {\n const defaults: ResolvedConfig = {\n collapse_dirs: DEFAULT_COLLAPSE_DIRS,\n ignore_patterns: DEFAULT_IGNORE_PATTERNS,\n max_file_size_kb: DEFAULT_MAX_FILE_SIZE_KB,\n tree_depth: DEFAULT_TREE_DEPTH,\n health_timeout_ms: DEFAULT_HEALTH_TIMEOUT_MS,\n };\n\n const candidates = [\n path.join(projectRoot, \"inspect.config.json\"),\n path.join(projectRoot, \".inspect\", \"config.json\"),\n ];\n\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n try {\n const raw = JSON.parse(fs.readFileSync(candidate, \"utf-8\"));\n const parsed = InspectConfigSchema.parse(raw);\n return {\n collapse_dirs: parsed.collapse_dirs ?? defaults.collapse_dirs,\n ignore_patterns: parsed.ignore_patterns ?? defaults.ignore_patterns,\n max_file_size_kb: parsed.max_file_size_kb ?? defaults.max_file_size_kb,\n tree_depth: parsed.tree_depth ?? defaults.tree_depth,\n health_timeout_ms: parsed.health_timeout_ms ?? defaults.health_timeout_ms,\n path_aliases: parsed.path_aliases,\n };\n } catch {\n // Invalid config file — fall through to defaults\n }\n }\n }\n\n return defaults;\n}\n","/**\n * Project detection engine.\n *\n * Uses a registry of detectors that examine config files in the project root\n * to determine language, framework, package manager, entry points, and tools.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { ProjectInfo, DetectedTools, SubProject } from \"../../types/index.js\";\n\n// ---------------------------------------------------------------------------\n// Detector registry\n// ---------------------------------------------------------------------------\n\ninterface DetectorEntry {\n /** File to look for in the project root. */\n file: string;\n /** Parse the file content and return partial ProjectInfo, or null if not applicable. */\n detect: (content: string, projectRoot: string) => Partial<ProjectInfo> | null;\n}\n\nconst detectors: DetectorEntry[] = [\n { file: \"package.json\", detect: detectNodeProject },\n { file: \"pyproject.toml\", detect: detectPythonProject },\n { file: \"Cargo.toml\", detect: detectRustProject },\n { file: \"go.mod\", detect: detectGoProject },\n { file: \"pom.xml\", detect: detectJavaProject },\n { file: \"build.gradle\", detect: detectGradleProject },\n { file: \"build.gradle.kts\", detect: detectGradleProject },\n { file: \"Gemfile\", detect: detectRubyProject },\n];\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Detect project information by examining config files in the project root.\n * Runs detectors in priority order and returns the first match merged with\n * tool detection results.\n */\nexport function detectProject(projectRoot: string): ProjectInfo {\n let info: Partial<ProjectInfo> | null = null;\n\n for (const detector of detectors) {\n const filePath = path.join(projectRoot, detector.file);\n if (fs.existsSync(filePath)) {\n try {\n const content = fs.readFileSync(filePath, \"utf-8\");\n info = detector.detect(content, projectRoot);\n if (info) break;\n } catch {\n // Unreadable file — skip\n }\n }\n }\n\n const detectedTools = detectTools(projectRoot);\n const projectName = info?.name ?? path.basename(projectRoot);\n\n const baseResult: ProjectInfo = {\n name: projectName,\n language: info?.language ?? \"unknown\",\n framework: info?.framework ?? null,\n framework_version: info?.framework_version ?? null,\n package_manager: info?.package_manager ?? null,\n runtime: info?.runtime ?? null,\n entry_points: info?.entry_points ?? detectConventionalEntryPoints(projectRoot),\n scripts: info?.scripts ?? {},\n detected_tools: detectedTools,\n };\n\n // If root detection failed, try monorepo sub-project detection\n if (baseResult.language === \"unknown\") {\n const subProjects = detectSubProjects(projectRoot);\n if (subProjects.length > 0) {\n baseResult.language = subProjects.length === 1 ? subProjects[0].language : \"multi\";\n baseResult.sub_projects = subProjects;\n if (subProjects.length === 1) {\n baseResult.framework = subProjects[0].framework;\n baseResult.package_manager = subProjects[0].package_manager;\n baseResult.detected_tools = subProjects[0].detected_tools;\n }\n }\n }\n\n return baseResult;\n}\n\n// ---------------------------------------------------------------------------\n// Node.js / package.json detector\n// ---------------------------------------------------------------------------\n\nfunction detectNodeProject(content: string, projectRoot: string): Partial<ProjectInfo> | null {\n let pkg: Record<string, unknown>;\n try {\n pkg = JSON.parse(content);\n } catch {\n return null;\n }\n\n const deps: Record<string, string> = {\n ...((pkg.dependencies as Record<string, string>) ?? {}),\n ...((pkg.devDependencies as Record<string, string>) ?? {}),\n };\n\n // Framework detection\n let framework: string | null = null;\n let frameworkVersion: string | null = null;\n\n if (deps[\"next\"]) {\n framework = \"nextjs\";\n frameworkVersion = cleanVersion(deps[\"next\"]);\n } else if (deps[\"@angular/core\"]) {\n framework = \"angular\";\n frameworkVersion = cleanVersion(deps[\"@angular/core\"]);\n } else if (deps[\"vue\"]) {\n framework = \"vue\";\n frameworkVersion = cleanVersion(deps[\"vue\"]);\n } else if (deps[\"react\"]) {\n framework = \"react\";\n frameworkVersion = cleanVersion(deps[\"react\"]);\n } else if (deps[\"express\"]) {\n framework = \"express\";\n frameworkVersion = cleanVersion(deps[\"express\"]);\n }\n\n // Language\n const language = deps[\"typescript\"] ? \"typescript\" : \"javascript\";\n\n // Package manager\n const packageManager = detectPackageManager(projectRoot, pkg);\n\n // Scripts\n const scripts: Record<string, string> = {};\n if (pkg.scripts && typeof pkg.scripts === \"object\") {\n for (const [k, v] of Object.entries(pkg.scripts as Record<string, string>)) {\n scripts[k] = v;\n }\n }\n\n // Entry points\n const entryPoints = detectNodeEntryPoints(pkg, projectRoot);\n\n return {\n name: (pkg.name as string) ?? path.basename(projectRoot),\n language,\n framework,\n framework_version: frameworkVersion,\n package_manager: packageManager,\n runtime: \"node\",\n entry_points: entryPoints,\n scripts,\n };\n}\n\nfunction cleanVersion(ver: string): string {\n return ver.replace(/^[\\^~>=<]+/, \"\");\n}\n\nfunction detectPackageManager(\n projectRoot: string,\n pkg: Record<string, unknown>,\n): string {\n // Check packageManager field first (corepack)\n if (typeof pkg.packageManager === \"string\") {\n const pm = pkg.packageManager as string;\n if (pm.startsWith(\"pnpm\")) return \"pnpm\";\n if (pm.startsWith(\"yarn\")) return \"yarn\";\n if (pm.startsWith(\"npm\")) return \"npm\";\n if (pm.startsWith(\"bun\")) return \"bun\";\n }\n\n // Lockfile sniffing\n if (fs.existsSync(path.join(projectRoot, \"pnpm-lock.yaml\"))) return \"pnpm\";\n if (fs.existsSync(path.join(projectRoot, \"yarn.lock\"))) return \"yarn\";\n if (fs.existsSync(path.join(projectRoot, \"bun.lockb\"))) return \"bun\";\n if (fs.existsSync(path.join(projectRoot, \"package-lock.json\"))) return \"npm\";\n\n return \"npm\"; // default fallback\n}\n\nfunction detectNodeEntryPoints(\n pkg: Record<string, unknown>,\n projectRoot: string,\n): string[] {\n const entries: string[] = [];\n\n // main field\n if (typeof pkg.main === \"string\") entries.push(pkg.main);\n\n // Conventional paths\n const conventionalPaths = [\n \"src/index.ts\",\n \"src/index.tsx\",\n \"src/index.js\",\n \"src/main.ts\",\n \"src/main.tsx\",\n \"src/app/layout.tsx\",\n \"src/app/page.tsx\",\n \"index.ts\",\n \"index.js\",\n ];\n\n for (const p of conventionalPaths) {\n if (fs.existsSync(path.join(projectRoot, p)) && !entries.includes(p)) {\n entries.push(p);\n }\n }\n\n return entries;\n}\n\n// ---------------------------------------------------------------------------\n// Python / pyproject.toml detector\n// ---------------------------------------------------------------------------\n\nfunction detectPythonProject(content: string, projectRoot: string): Partial<ProjectInfo> | null {\n // Simple TOML parsing for the fields we care about.\n // We avoid pulling in a full TOML parser to keep deps minimal.\n const name = extractTomlValue(content, \"name\") ?? path.basename(projectRoot);\n\n let framework: string | null = null;\n let frameworkVersion: string | null = null;\n\n // Check dependencies for frameworks (order matters — first match wins)\n const pyFrameworks: Array<{ names: string[]; label: string }> = [\n { names: [\"fastapi\", \"FastAPI\"], label: \"fastapi\" },\n { names: [\"django\", \"Django\"], label: \"django\" },\n { names: [\"flask\", \"Flask\"], label: \"flask\" },\n { names: [\"streamlit\", \"Streamlit\"], label: \"streamlit\" },\n { names: [\"gradio\", \"Gradio\"], label: \"gradio\" },\n ];\n\n for (const fw of pyFrameworks) {\n if (fw.names.some((n) => content.includes(n))) {\n framework = fw.label;\n frameworkVersion = extractTomlDependencyVersion(content, fw.names[0]);\n break;\n }\n }\n\n // Package manager\n let packageManager: string | null = null;\n if (content.includes(\"[tool.poetry]\")) {\n packageManager = \"poetry\";\n } else if (fs.existsSync(path.join(projectRoot, \"Pipfile\"))) {\n packageManager = \"pipenv\";\n } else if (fs.existsSync(path.join(projectRoot, \"uv.lock\"))) {\n packageManager = \"uv\";\n } else {\n packageManager = \"pip\";\n }\n\n // Entry points\n const entryPoints: string[] = [];\n const pyEntries = [\"src/main.py\", \"main.py\", \"app/main.py\", \"app.py\", \"manage.py\"];\n for (const p of pyEntries) {\n if (fs.existsSync(path.join(projectRoot, p))) {\n entryPoints.push(p);\n }\n }\n\n return {\n name,\n language: \"python\",\n framework,\n framework_version: frameworkVersion,\n package_manager: packageManager,\n runtime: \"python\",\n entry_points: entryPoints,\n scripts: {},\n };\n}\n\n// ---------------------------------------------------------------------------\n// Rust / Cargo.toml detector\n// ---------------------------------------------------------------------------\n\nfunction detectRustProject(content: string, projectRoot: string): Partial<ProjectInfo> | null {\n const name = extractTomlValue(content, \"name\") ?? path.basename(projectRoot);\n const edition = extractTomlValue(content, \"edition\");\n\n // Detect common Rust web frameworks in [dependencies]\n let framework: string | null = null;\n const rustFrameworks: Array<{ dep: string; label: string }> = [\n { dep: \"actix-web\", label: \"actix-web\" },\n { dep: \"axum\", label: \"axum\" },\n { dep: \"rocket\", label: \"rocket\" },\n { dep: \"tokio\", label: \"tokio\" },\n ];\n for (const fw of rustFrameworks) {\n // Match dependency name in TOML (e.g. `actix-web = ` or `actix-web.`)\n const depRegex = new RegExp(`^\\\\s*${fw.dep.replace(\"-\", \"[-]\")}\\\\s*[=.]`, \"m\");\n if (depRegex.test(content)) {\n framework = fw.label;\n break;\n }\n }\n\n const entryPoints: string[] = [];\n if (fs.existsSync(path.join(projectRoot, \"src/main.rs\"))) entryPoints.push(\"src/main.rs\");\n if (fs.existsSync(path.join(projectRoot, \"src/lib.rs\"))) entryPoints.push(\"src/lib.rs\");\n\n return {\n name,\n language: \"rust\",\n framework,\n framework_version: edition ? `edition-${edition}` : null,\n package_manager: \"cargo\",\n runtime: \"rust\",\n entry_points: entryPoints,\n scripts: {},\n };\n}\n\n// ---------------------------------------------------------------------------\n// Go / go.mod detector\n// ---------------------------------------------------------------------------\n\nfunction detectGoProject(content: string, projectRoot: string): Partial<ProjectInfo> | null {\n // Extract module path from first line: module github.com/user/repo\n const moduleMatch = content.match(/^module\\s+(.+)$/m);\n const modulePath = moduleMatch?.[1]?.trim() ?? \"\";\n const name = modulePath.split(\"/\").pop() ?? path.basename(projectRoot);\n\n const entryPoints: string[] = [];\n if (fs.existsSync(path.join(projectRoot, \"main.go\"))) entryPoints.push(\"main.go\");\n if (fs.existsSync(path.join(projectRoot, \"cmd\"))) {\n // Common Go pattern: cmd/<name>/main.go\n try {\n const cmdDirs = fs.readdirSync(path.join(projectRoot, \"cmd\"), { withFileTypes: true });\n for (const d of cmdDirs) {\n if (d.isDirectory()) {\n const mainGo = path.join(\"cmd\", d.name, \"main.go\");\n if (fs.existsSync(path.join(projectRoot, mainGo))) {\n entryPoints.push(mainGo);\n }\n }\n }\n } catch {\n // skip\n }\n }\n\n // Extract Go version from `go X.Y` line\n const goVersionMatch = content.match(/^go\\s+(\\d+\\.\\d+(?:\\.\\d+)?)/m);\n const goVersion = goVersionMatch?.[1] ?? null;\n\n // Detect common Go frameworks\n let framework: string | null = null;\n const goFrameworks: Array<{ path: string; label: string }> = [\n { path: \"github.com/gin-gonic/gin\", label: \"gin\" },\n { path: \"github.com/labstack/echo\", label: \"echo\" },\n { path: \"github.com/gofiber/fiber\", label: \"fiber\" },\n { path: \"github.com/go-chi/chi\", label: \"chi\" },\n ];\n for (const fw of goFrameworks) {\n if (content.includes(fw.path)) {\n framework = fw.label;\n break;\n }\n }\n\n return {\n name,\n language: \"go\",\n framework,\n framework_version: goVersion,\n package_manager: \"go\",\n runtime: \"go\",\n entry_points: entryPoints,\n scripts: {},\n };\n}\n\n// ---------------------------------------------------------------------------\n// Java / pom.xml detector\n// ---------------------------------------------------------------------------\n\nfunction detectJavaProject(content: string, projectRoot: string): Partial<ProjectInfo> | null {\n // Simple XML extraction\n const nameMatch = content.match(/<artifactId>([^<]+)<\\/artifactId>/);\n const name = nameMatch?.[1] ?? path.basename(projectRoot);\n\n let framework: string | null = null;\n let frameworkVersion: string | null = null;\n\n if (content.includes(\"spring-boot\")) {\n framework = \"spring-boot\";\n // Try to extract version from spring-boot-starter-parent <version> tag\n const parentMatch = content.match(\n /spring-boot-starter-parent[\\s\\S]*?<version>([^<]+)<\\/version>/,\n );\n frameworkVersion = parentMatch?.[1] ?? null;\n } else if (content.includes(\"quarkus\")) {\n framework = \"quarkus\";\n } else if (content.includes(\"micronaut\")) {\n framework = \"micronaut\";\n }\n\n const entryPoints: string[] = [];\n // Convention: src/main/java\n if (fs.existsSync(path.join(projectRoot, \"src/main/java\"))) {\n entryPoints.push(\"src/main/java\");\n }\n\n return {\n name,\n language: \"java\",\n framework,\n framework_version: frameworkVersion,\n package_manager: \"maven\",\n runtime: \"jvm\",\n entry_points: entryPoints,\n scripts: {},\n };\n}\n\n// ---------------------------------------------------------------------------\n// Gradle detector\n// ---------------------------------------------------------------------------\n\nfunction detectGradleProject(content: string, projectRoot: string): Partial<ProjectInfo> | null {\n const name = path.basename(projectRoot);\n const language = content.includes(\"kotlin\") || content.includes(\".kt\") ? \"kotlin\" : \"java\";\n\n let framework: string | null = null;\n if (content.includes(\"spring-boot\") || content.includes(\"org.springframework.boot\")) {\n framework = \"spring-boot\";\n } else if (content.includes(\"quarkus\")) {\n framework = \"quarkus\";\n } else if (content.includes(\"micronaut\")) {\n framework = \"micronaut\";\n }\n\n const entryPoints: string[] = [];\n if (fs.existsSync(path.join(projectRoot, \"src/main/java\"))) {\n entryPoints.push(\"src/main/java\");\n }\n if (fs.existsSync(path.join(projectRoot, \"src/main/kotlin\"))) {\n entryPoints.push(\"src/main/kotlin\");\n }\n\n return {\n name,\n language,\n framework,\n framework_version: null,\n package_manager: \"gradle\",\n runtime: \"jvm\",\n entry_points: entryPoints,\n scripts: {},\n };\n}\n\n// ---------------------------------------------------------------------------\n// Ruby / Gemfile detector\n// ---------------------------------------------------------------------------\n\nfunction detectRubyProject(content: string, projectRoot: string): Partial<ProjectInfo> | null {\n const name = path.basename(projectRoot);\n const framework = content.includes(\"rails\") || content.includes(\"'rails'\") ? \"rails\" : null;\n\n const entryPoints: string[] = [];\n if (fs.existsSync(path.join(projectRoot, \"config.ru\"))) entryPoints.push(\"config.ru\");\n if (fs.existsSync(path.join(projectRoot, \"app\"))) entryPoints.push(\"app/\");\n\n return {\n name,\n language: \"ruby\",\n framework,\n framework_version: null,\n package_manager: \"bundler\",\n runtime: \"ruby\",\n entry_points: entryPoints,\n scripts: {},\n };\n}\n\n// ---------------------------------------------------------------------------\n// Monorepo sub-project detection\n// ---------------------------------------------------------------------------\n\n/** Common workspace directory names that contain nested sub-projects. */\nconst WORKSPACE_DIR_NAMES = new Set([\n \"packages\",\n \"workspace\",\n \"workspaces\",\n \"libs\",\n \"apps\",\n \"modules\",\n \"services\",\n \"projects\",\n]);\n\n/**\n * Scan child directories for config files when root detection fails.\n * Also recurses into common workspace directories (packages/, libs/, apps/, etc.).\n * Returns sub-project info for each child that has a recognized config file.\n */\nfunction detectSubProjects(projectRoot: string): SubProject[] {\n const subProjects: SubProject[] = [];\n scanDirForSubProjects(projectRoot, projectRoot, subProjects, 0, 2);\n return subProjects;\n}\n\nfunction scanDirForSubProjects(\n dir: string,\n projectRoot: string,\n subProjects: SubProject[],\n depth: number,\n maxDepth: number,\n): void {\n if (depth >= maxDepth) return;\n\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (!entry.isDirectory() || entry.name.startsWith(\".\")) continue;\n\n const childPath = path.join(dir, entry.name);\n let detected = false;\n\n // Try each detector on this directory\n for (const detector of detectors) {\n const filePath = path.join(childPath, detector.file);\n if (fs.existsSync(filePath)) {\n try {\n const content = fs.readFileSync(filePath, \"utf-8\");\n const info = detector.detect(content, childPath);\n if (info?.language) {\n subProjects.push({\n path: path.relative(projectRoot, childPath),\n language: info.language,\n framework: info.framework ?? null,\n package_manager: info.package_manager ?? null,\n detected_tools: detectTools(childPath),\n });\n detected = true;\n break;\n }\n } catch {\n // skip\n }\n }\n }\n\n // If no config found and this looks like a workspace dir, recurse into it\n if (!detected && WORKSPACE_DIR_NAMES.has(entry.name.toLowerCase())) {\n scanDirForSubProjects(childPath, projectRoot, subProjects, depth + 1, maxDepth);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Tool detection (cross-language)\n// ---------------------------------------------------------------------------\n\nfunction detectTools(projectRoot: string): DetectedTools {\n const tools: DetectedTools = {\n linter: null,\n type_checker: null,\n test_runner: null,\n formatter: null,\n };\n\n // Linter\n const eslintFiles = [\n \".eslintrc\",\n \".eslintrc.js\",\n \".eslintrc.cjs\",\n \".eslintrc.json\",\n \".eslintrc.yaml\",\n \".eslintrc.yml\",\n \"eslint.config.js\",\n \"eslint.config.mjs\",\n \"eslint.config.cjs\",\n \"eslint.config.ts\",\n ];\n for (const f of eslintFiles) {\n if (fs.existsSync(path.join(projectRoot, f))) {\n tools.linter = \"eslint\";\n break;\n }\n }\n\n // Ruff (Python linter)\n if (\n !tools.linter &&\n (fs.existsSync(path.join(projectRoot, \"ruff.toml\")) ||\n fs.existsSync(path.join(projectRoot, \".ruff.toml\")))\n ) {\n tools.linter = \"ruff\";\n }\n // Also check pyproject.toml for [tool.ruff]\n if (!tools.linter) {\n const pyproject = path.join(projectRoot, \"pyproject.toml\");\n if (fs.existsSync(pyproject)) {\n try {\n const content = fs.readFileSync(pyproject, \"utf-8\");\n if (content.includes(\"[tool.ruff]\")) {\n tools.linter = \"ruff\";\n }\n } catch {\n // skip\n }\n }\n }\n\n // Clippy (Rust linter)\n if (!tools.linter && fs.existsSync(path.join(projectRoot, \"Cargo.toml\"))) {\n tools.linter = \"clippy\";\n }\n\n // Type checker\n if (fs.existsSync(path.join(projectRoot, \"tsconfig.json\"))) {\n tools.type_checker = \"tsc\";\n }\n // mypy\n if (\n fs.existsSync(path.join(projectRoot, \"mypy.ini\")) ||\n fs.existsSync(path.join(projectRoot, \".mypy.ini\"))\n ) {\n tools.type_checker = \"mypy\";\n }\n // Also check pyproject.toml for [tool.mypy]\n if (!tools.type_checker) {\n const pyproject = path.join(projectRoot, \"pyproject.toml\");\n if (fs.existsSync(pyproject)) {\n try {\n const content = fs.readFileSync(pyproject, \"utf-8\");\n if (content.includes(\"[tool.mypy]\")) {\n tools.type_checker = \"mypy\";\n }\n } catch {\n // skip\n }\n }\n }\n\n // Test runner\n const jestFiles = [\n \"jest.config.js\",\n \"jest.config.ts\",\n \"jest.config.cjs\",\n \"jest.config.mjs\",\n \"jest.config.json\",\n ];\n const vitestFiles = [\n \"vitest.config.ts\",\n \"vitest.config.js\",\n \"vitest.config.mjs\",\n ];\n\n for (const f of vitestFiles) {\n if (fs.existsSync(path.join(projectRoot, f))) {\n tools.test_runner = \"vitest\";\n break;\n }\n }\n if (!tools.test_runner) {\n for (const f of jestFiles) {\n if (fs.existsSync(path.join(projectRoot, f))) {\n tools.test_runner = \"jest\";\n break;\n }\n }\n }\n // pytest\n if (!tools.test_runner) {\n const pyproject = path.join(projectRoot, \"pyproject.toml\");\n if (fs.existsSync(pyproject)) {\n try {\n const content = fs.readFileSync(pyproject, \"utf-8\");\n if (content.includes(\"[tool.pytest]\") || content.includes(\"pytest\")) {\n tools.test_runner = \"pytest\";\n }\n } catch {\n // skip\n }\n }\n }\n\n // Formatter\n const prettierFiles = [\n \".prettierrc\",\n \".prettierrc.js\",\n \".prettierrc.cjs\",\n \".prettierrc.json\",\n \".prettierrc.yaml\",\n \".prettierrc.yml\",\n \".prettierrc.toml\",\n \"prettier.config.js\",\n \"prettier.config.cjs\",\n \"prettier.config.mjs\",\n ];\n for (const f of prettierFiles) {\n if (fs.existsSync(path.join(projectRoot, f))) {\n tools.formatter = \"prettier\";\n break;\n }\n }\n\n // Check for biome\n if (!tools.formatter && fs.existsSync(path.join(projectRoot, \"biome.json\"))) {\n tools.formatter = \"biome\";\n }\n\n return tools;\n}\n\n// ---------------------------------------------------------------------------\n// Conventional entry point detection (when no config file matched)\n// ---------------------------------------------------------------------------\n\nfunction detectConventionalEntryPoints(projectRoot: string): string[] {\n const entries: string[] = [];\n const candidates = [\n \"src/index.ts\",\n \"src/index.js\",\n \"src/main.ts\",\n \"src/main.py\",\n \"main.go\",\n \"src/main.rs\",\n \"src/lib.rs\",\n \"index.ts\",\n \"index.js\",\n \"main.py\",\n \"app.py\",\n ];\n for (const p of candidates) {\n if (fs.existsSync(path.join(projectRoot, p))) {\n entries.push(p);\n }\n }\n return entries;\n}\n\n// ---------------------------------------------------------------------------\n// Minimal TOML value extraction\n// ---------------------------------------------------------------------------\n\n/**\n * Extract a simple string value from TOML content.\n * Handles: key = \"value\" patterns. Not a full TOML parser.\n */\nfunction extractTomlValue(content: string, key: string): string | null {\n const regex = new RegExp(`^\\\\s*${key}\\\\s*=\\\\s*\"([^\"]*)\"`, \"m\");\n const match = content.match(regex);\n return match?.[1] ?? null;\n}\n\n/**\n * Extract a dependency version from TOML content.\n *\n * Handles two common formats:\n * 1. Poetry-style: `packageName = \"^0.100.0\"` or `packageName = {version = \"...\"}`\n * 2. PEP 621 array entries: `\"packageName>=0.100.0\"` inside `[project.dependencies]`\n *\n * Returns the cleaned version (without ^, ~, >=, etc.) or null.\n */\nfunction extractTomlDependencyVersion(content: string, packageName: string): string | null {\n // Try Poetry-style: packageName = \"^1.2.3\"\n const poetryRegex = new RegExp(\n `^\\\\s*${packageName}\\\\s*=\\\\s*\"([^\"]*)\"`,\n \"im\",\n );\n const poetryMatch = content.match(poetryRegex);\n if (poetryMatch?.[1]) {\n return cleanVersion(poetryMatch[1]);\n }\n\n // Try PEP 621 array entries: \"packageName>=1.2.3\" or \"packageName==1.2.3\"\n const pep621Regex = new RegExp(\n `\"${packageName}\\\\s*([><=!~]+\\\\s*[\\\\d][^\"]*)\"`,\n \"i\",\n );\n const pep621Match = content.match(pep621Regex);\n if (pep621Match?.[1]) {\n return cleanVersion(pep621Match[1]);\n }\n\n return null;\n}\n","/**\n * Smart file tree builder.\n *\n * Walks a project directory recursively and returns a structured tree\n * with collapse rules for heavy/generated directories.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { FileTreeEntry, CollapsedDir, FileEntry } from \"../../types/index.js\";\nimport type { ResolvedConfig } from \"../../config/index.js\";\nimport { AUTO_COLLAPSE_FILE_THRESHOLD } from \"../../config/index.js\";\n\n/** Source code extensions used for the auto-collapse heuristic. */\nconst SOURCE_EXTENSIONS = new Set([\n \".ts\",\n \".tsx\",\n \".js\",\n \".jsx\",\n \".mjs\",\n \".cjs\",\n \".py\",\n \".rs\",\n \".go\",\n \".java\",\n \".kt\",\n \".rb\",\n \".c\",\n \".cpp\",\n \".h\",\n \".hpp\",\n \".cs\",\n \".swift\",\n \".scala\",\n \".clj\",\n \".ex\",\n \".exs\",\n \".lua\",\n \".sh\",\n \".bash\",\n \".zsh\",\n \".fish\",\n \".vue\",\n \".svelte\",\n]);\n\n/**\n * Build a file tree for the given project root.\n */\nexport function buildFileTree(\n projectRoot: string,\n config: ResolvedConfig,\n): Record<string, FileTreeEntry> {\n return walkDirectory(projectRoot, projectRoot, config, 0);\n}\n\n// ---------------------------------------------------------------------------\n// Internal\n// ---------------------------------------------------------------------------\n\nfunction walkDirectory(\n dirPath: string,\n projectRoot: string,\n config: ResolvedConfig,\n depth: number,\n): Record<string, FileTreeEntry> {\n const result: Record<string, FileTreeEntry> = {};\n\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dirPath, { withFileTypes: true });\n } catch {\n return result;\n }\n\n // Separate into dirs and files, sort alphabetically within each group\n const dirs = entries.filter((e) => e.isDirectory()).sort((a, b) => a.name.localeCompare(b.name));\n const files = entries.filter((e) => e.isFile()).sort((a, b) => a.name.localeCompare(b.name));\n\n // Process directories first\n for (const dir of dirs) {\n const dirName = dir.name + \"/\";\n const fullPath = path.join(dirPath, dir.name);\n\n // Check if this directory should be collapsed\n if (config.collapse_dirs.includes(dir.name)) {\n result[dirName] = collapseDirectory(fullPath);\n continue;\n }\n\n // Depth limit\n if (depth >= config.tree_depth) {\n result[dirName] = collapseDirectory(fullPath);\n continue;\n }\n\n // Auto-collapse: dirs with >500 files and no source code\n const autoCollapseResult = shouldAutoCollapse(fullPath);\n if (autoCollapseResult !== null) {\n result[dirName] = autoCollapseResult;\n continue;\n }\n\n // Recurse\n result[dirName] = walkDirectory(fullPath, projectRoot, config, depth + 1);\n }\n\n // Process files\n for (const file of files) {\n if (shouldIgnoreFile(file.name, config.ignore_patterns)) {\n continue;\n }\n\n const fullPath = path.join(dirPath, file.name);\n let size = 0;\n try {\n const stat = fs.statSync(fullPath);\n size = stat.size;\n } catch {\n // Skip files we can't stat\n continue;\n }\n\n const entry: FileEntry = { size };\n result[file.name] = entry;\n }\n\n return result;\n}\n\n/**\n * Count all files in a directory recursively and return a collapsed entry.\n */\nfunction collapseDirectory(dirPath: string): CollapsedDir {\n return {\n _collapsed: true,\n file_count: countFiles(dirPath),\n };\n}\n\n/**\n * Recursively count files in a directory. Capped at 100k to avoid\n * spending too long on massive directories.\n */\nfunction countFiles(dirPath: string, limit = 100_000): number {\n let count = 0;\n const stack = [dirPath];\n\n while (stack.length > 0 && count < limit) {\n const current = stack.pop()!;\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(current, { withFileTypes: true });\n } catch {\n continue;\n }\n for (const entry of entries) {\n if (count >= limit) break;\n if (entry.isFile()) {\n count++;\n } else if (entry.isDirectory()) {\n stack.push(path.join(current, entry.name));\n }\n }\n }\n\n return count;\n}\n\n/**\n * Check whether a directory should be auto-collapsed.\n * Returns a CollapsedDir if yes, null if no.\n */\nfunction shouldAutoCollapse(dirPath: string): CollapsedDir | null {\n let fileCount = 0;\n let hasSource = false;\n const stack = [dirPath];\n\n while (stack.length > 0 && fileCount <= AUTO_COLLAPSE_FILE_THRESHOLD) {\n const current = stack.pop()!;\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(current, { withFileTypes: true });\n } catch {\n continue;\n }\n for (const entry of entries) {\n if (entry.isFile()) {\n fileCount++;\n if (!hasSource) {\n const ext = path.extname(entry.name).toLowerCase();\n if (SOURCE_EXTENSIONS.has(ext)) {\n hasSource = true;\n }\n }\n } else if (entry.isDirectory()) {\n stack.push(path.join(current, entry.name));\n }\n }\n }\n\n if (fileCount > AUTO_COLLAPSE_FILE_THRESHOLD && !hasSource) {\n return { _collapsed: true, file_count: fileCount };\n }\n\n return null;\n}\n\n/**\n * Check if a filename matches any of the ignore patterns.\n * Supports basic glob matching: `*` matches any sequence of chars.\n */\nfunction shouldIgnoreFile(fileName: string, patterns: string[]): boolean {\n for (const pattern of patterns) {\n if (matchGlob(pattern, fileName)) return true;\n }\n return false;\n}\n\n/**\n * Simple glob matcher. Supports `*` as wildcard.\n */\nfunction matchGlob(pattern: string, input: string): boolean {\n const regex = new RegExp(\n \"^\" + pattern.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\").replace(/\\*/g, \".*\") + \"$\",\n );\n return regex.test(input);\n}\n","/**\n * Git service — shell out to `git` CLI for repository operations.\n */\n\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * Get the current HEAD commit hash (short form).\n * Returns null if the path is not a git repository.\n */\nexport async function getHead(projectRoot: string): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"rev-parse\", \"--short\", \"HEAD\"], {\n cwd: projectRoot,\n });\n return stdout.trim() || null;\n } catch {\n return null;\n }\n}\n\n/**\n * Check whether a path is inside a git repository.\n */\nexport async function isGitRepo(projectRoot: string): Promise<boolean> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"rev-parse\", \"--is-inside-work-tree\"],\n { cwd: projectRoot },\n );\n return stdout.trim() === \"true\";\n } catch {\n return false;\n }\n}\n\n/**\n * Get the full HEAD commit hash.\n * Returns null if the path is not a git repository.\n */\nexport async function getFullHead(projectRoot: string): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"rev-parse\", \"HEAD\"], {\n cwd: projectRoot,\n });\n return stdout.trim() || null;\n } catch {\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Diff & Change Detection (Phase 5)\n// ---------------------------------------------------------------------------\n\n/** A file change entry from git diff. */\nexport interface GitFileChange {\n path: string;\n status: string;\n oldPath?: string;\n}\n\n/**\n * Get files changed between a commit and HEAD via `git diff --name-status`.\n */\nexport async function getDiffNameStatus(\n projectRoot: string,\n sinceCommit: string,\n): Promise<GitFileChange[]> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"diff\", \"--name-status\", sinceCommit, \"HEAD\"],\n { cwd: projectRoot },\n );\n return parseDiffNameStatus(stdout);\n } catch {\n return [];\n }\n}\n\n/**\n * Get uncommitted changes (staged + unstaged + untracked).\n */\nexport async function getUncommittedChanges(\n projectRoot: string,\n): Promise<GitFileChange[]> {\n const changes = new Map<string, GitFileChange>();\n\n // Staged changes (index vs HEAD)\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"diff\", \"--name-status\", \"--cached\"],\n { cwd: projectRoot },\n );\n for (const entry of parseDiffNameStatus(stdout)) {\n changes.set(entry.path, entry);\n }\n } catch {\n // skip\n }\n\n // Unstaged changes (working tree vs index)\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"diff\", \"--name-status\"],\n { cwd: projectRoot },\n );\n for (const entry of parseDiffNameStatus(stdout)) {\n changes.set(entry.path, entry);\n }\n } catch {\n // skip\n }\n\n // Untracked files\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"ls-files\", \"--others\", \"--exclude-standard\"],\n { cwd: projectRoot },\n );\n for (const line of stdout.split(\"\\n\")) {\n const trimmed = line.trim();\n if (trimmed) {\n changes.set(trimmed, { path: trimmed, status: \"A\" });\n }\n }\n } catch {\n // skip\n }\n\n return [...changes.values()];\n}\n\n/**\n * Get commit hashes that came from upstream (pull) in a given range.\n * Returns empty set if no upstream is configured.\n */\nexport async function getPullCommitHashes(\n projectRoot: string,\n sinceCommit: string,\n): Promise<Set<string>> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"log\", \"--format=%H\", `${sinceCommit}..@{upstream}`],\n { cwd: projectRoot },\n );\n const hashes = new Set<string>();\n for (const line of stdout.split(\"\\n\")) {\n const trimmed = line.trim();\n if (trimmed) hashes.add(trimmed);\n }\n return hashes;\n } catch {\n return new Set();\n }\n}\n\n/**\n * Get the most recent commit info for a file in a given range.\n */\nexport async function getFileCommitInfo(\n projectRoot: string,\n filePath: string,\n sinceCommit: string,\n): Promise<{ hash: string; author: string; message: string } | null> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"log\", \"-1\", \"--format=%H|||%an|||%s\", `${sinceCommit}..HEAD`, \"--\", filePath],\n { cwd: projectRoot },\n );\n const trimmed = stdout.trim();\n if (!trimmed) return null;\n\n const parts = trimmed.split(\"|||\");\n if (parts.length < 3) return null;\n\n return {\n hash: parts[0],\n author: parts[1],\n message: parts.slice(2).join(\"|||\"),\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Get the current user's email from git config.\n */\nexport async function getUserEmail(projectRoot: string): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"config\", \"user.email\"],\n { cwd: projectRoot },\n );\n return stdout.trim() || null;\n } catch {\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Parse git diff --name-status output. */\nfunction parseDiffNameStatus(output: string): GitFileChange[] {\n const results: GitFileChange[] = [];\n\n for (const line of output.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n const parts = trimmed.split(\"\\t\");\n if (parts.length < 2) continue;\n\n const status = parts[0];\n\n if (status.startsWith(\"R\")) {\n // Rename: R100\\told_path\\tnew_path\n results.push({\n path: parts[2] || parts[1],\n status: \"R\",\n oldPath: parts[1],\n });\n } else {\n results.push({\n path: parts[1],\n status: status.charAt(0), // Normalize to single char (A, M, D)\n });\n }\n }\n\n return results;\n}\n","/**\n * Cache service — read/write `.inspect/` directory for persistent state.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { ScanResultSchema, CacheMetaSchema, type ScanResult, type CacheMeta } from \"../../types/index.js\";\nimport { TOOL_VERSION } from \"../../config/index.js\";\n\nconst INSPECT_DIR = \".inspect\";\nconst STATE_FILE = \"state.json\";\nconst META_FILE = \"meta.json\";\n\n/**\n * Read the cached scan result from `.inspect/state.json`.\n * Returns null if cache does not exist or is invalid.\n */\nexport function readCache(projectRoot: string): ScanResult | null {\n const statePath = path.join(projectRoot, INSPECT_DIR, STATE_FILE);\n if (!fs.existsSync(statePath)) return null;\n\n try {\n const raw = JSON.parse(fs.readFileSync(statePath, \"utf-8\"));\n return ScanResultSchema.parse(raw);\n } catch {\n return null;\n }\n}\n\n/**\n * Read cache metadata from `.inspect/meta.json`.\n * Returns null if metadata does not exist or is invalid.\n */\nexport function readMeta(projectRoot: string): CacheMeta | null {\n const metaPath = path.join(projectRoot, INSPECT_DIR, META_FILE);\n if (!fs.existsSync(metaPath)) return null;\n\n try {\n const raw = JSON.parse(fs.readFileSync(metaPath, \"utf-8\"));\n return CacheMetaSchema.parse(raw);\n } catch {\n return null;\n }\n}\n\n/**\n * Write scan result and metadata to the `.inspect/` directory.\n */\nexport function writeCache(\n projectRoot: string,\n result: ScanResult,\n gitHead: string | null,\n): void {\n const inspectDir = path.join(projectRoot, INSPECT_DIR);\n if (!fs.existsSync(inspectDir)) {\n fs.mkdirSync(inspectDir, { recursive: true });\n }\n\n const meta: CacheMeta = {\n version: TOOL_VERSION,\n git_head: gitHead,\n scanned_at: new Date().toISOString(),\n };\n\n fs.writeFileSync(\n path.join(inspectDir, STATE_FILE),\n JSON.stringify(result, null, 2),\n \"utf-8\",\n );\n\n fs.writeFileSync(\n path.join(inspectDir, META_FILE),\n JSON.stringify(meta, null, 2),\n \"utf-8\",\n );\n}\n\n/**\n * Check whether the cache is still valid by comparing the stored HEAD\n * with the current HEAD.\n */\nexport function isCacheValid(projectRoot: string, currentHead: string | null): boolean {\n const meta = readMeta(projectRoot);\n if (!meta) return false;\n if (meta.version !== TOOL_VERSION) return false;\n return meta.git_head === currentHead;\n}\n\n/**\n * Remove the `.inspect/` directory entirely.\n */\nexport function clearCache(projectRoot: string): void {\n const inspectDir = path.join(projectRoot, INSPECT_DIR);\n if (fs.existsSync(inspectDir)) {\n fs.rmSync(inspectDir, { recursive: true, force: true });\n }\n}\n","/**\n * Symbol index builder.\n *\n * Collects all parseable source files from a project, parses them\n * in parallel with a concurrency limit, and returns a symbol index.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { Symbol } from \"../../types/index.js\";\nimport type { ResolvedConfig } from \"../../config/index.js\";\nimport { parseSource, getGrammarForFile } from \"./index.js\";\nimport { getExtractor } from \"./extractors/index.js\";\nimport { collectSourceFiles, withConcurrency, DEFAULT_CONCURRENCY } from \"./utils.js\";\n\n/**\n * Build a symbol index for all parseable files in the project.\n *\n * @returns Map of relative file path to symbol array.\n */\nexport async function buildSymbolIndex(\n projectRoot: string,\n config: ResolvedConfig,\n preCollectedFiles?: string[],\n): Promise<Record<string, Symbol[]>> {\n const files = preCollectedFiles ?? collectSourceFiles(projectRoot, config);\n const index: Record<string, Symbol[]> = {};\n\n await withConcurrency(\n files.map((filePath) => async () => {\n const relativePath = path.relative(projectRoot, filePath);\n const symbols = await extractSymbolsFromFile(filePath, relativePath);\n if (symbols && symbols.length > 0) {\n index[relativePath] = symbols;\n }\n }),\n DEFAULT_CONCURRENCY,\n );\n\n return index;\n}\n\n/**\n * Incrementally update a cached symbol index by re-parsing only changed files.\n *\n * @param cached The previous symbol index from cache.\n * @param changedFiles Relative paths of files that were added or modified.\n * @param deletedFiles Relative paths of files that were deleted.\n * @param projectRoot Absolute path to the project root.\n * @returns Updated symbol index.\n */\nexport async function updateSymbolIndex(\n cached: Record<string, Symbol[]>,\n changedFiles: string[],\n deletedFiles: string[],\n projectRoot: string,\n): Promise<Record<string, Symbol[]>> {\n const index: Record<string, Symbol[]> = { ...cached };\n\n // Remove deleted files\n for (const file of deletedFiles) {\n delete index[file];\n }\n\n // Re-parse changed files\n await withConcurrency(\n changedFiles.map((relativePath) => async () => {\n const symbols = await extractSymbolsForFile(projectRoot, relativePath);\n if (symbols.length > 0) {\n index[relativePath] = symbols;\n } else {\n delete index[relativePath];\n }\n }),\n DEFAULT_CONCURRENCY,\n );\n\n return index;\n}\n\n// ---------------------------------------------------------------------------\n// Symbol extraction\n// ---------------------------------------------------------------------------\n\n/**\n * Extract symbols from a single file.\n *\n * @param projectRoot Absolute path to the project root.\n * @param relativePath Project-relative file path.\n * @returns Array of symbols, or empty array if extraction fails.\n */\nexport async function extractSymbolsForFile(\n projectRoot: string,\n relativePath: string,\n): Promise<Symbol[]> {\n const filePath = path.join(projectRoot, relativePath);\n const symbols = await extractSymbolsFromFile(filePath, relativePath);\n return symbols ?? [];\n}\n\nasync function extractSymbolsFromFile(\n filePath: string,\n relativePath: string,\n): Promise<Symbol[] | null> {\n let source: string;\n try {\n source = fs.readFileSync(filePath, \"utf-8\");\n } catch {\n return null;\n }\n\n const tree = await parseSource(relativePath, source);\n if (!tree) return null;\n\n const grammarName = getGrammarForFile(relativePath);\n if (!grammarName) return null;\n\n const extractor = getExtractor(grammarName);\n if (!extractor) return null;\n\n return extractor.extract(tree, relativePath);\n}\n","/**\n * Tree-sitter WASM grammar loader.\n *\n * Handles one-time Parser.init() and lazy-loads language grammars from\n * the tree-sitter-wasms package. Grammars are cached after first load.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { createRequire } from \"node:module\";\nimport Parser from \"web-tree-sitter\";\n\nconst require = createRequire(import.meta.url);\n\n// ---------------------------------------------------------------------------\n// Singleton init\n// ---------------------------------------------------------------------------\n\nlet initPromise: Promise<void> | null = null;\n\n/**\n * Initialize the tree-sitter WASM runtime. Safe to call multiple times —\n * only the first call does real work.\n */\nexport function ensureInit(): Promise<void> {\n if (!initPromise) {\n initPromise = Parser.init();\n }\n return initPromise;\n}\n\n// ---------------------------------------------------------------------------\n// Grammar cache\n// ---------------------------------------------------------------------------\n\nconst grammarCache = new Map<string, Parser.Language>();\n\n/**\n * Resolve the filesystem path to a `.wasm` grammar file shipped by\n * the `tree-sitter-wasms` package.\n */\nfunction resolveGrammarPath(grammarName: string): string {\n // tree-sitter-wasms stores files at out/tree-sitter-<lang>.wasm\n const wasmFile = `tree-sitter-${grammarName}.wasm`;\n\n const fromNodeModules = path.join(\n path.dirname(require.resolve(\"tree-sitter-wasms/package.json\")),\n \"out\",\n wasmFile,\n );\n if (fs.existsSync(fromNodeModules)) return fromNodeModules;\n\n throw new Error(`Grammar WASM not found for \"${grammarName}\" at ${fromNodeModules}`);\n}\n\n/**\n * Load a tree-sitter language grammar by name. Caches the result so\n * subsequent calls for the same grammar are instant.\n *\n * @param grammarName — the grammar identifier (e.g. \"typescript\", \"java\")\n */\nexport async function loadGrammar(grammarName: string): Promise<Parser.Language> {\n const cached = grammarCache.get(grammarName);\n if (cached) return cached;\n\n await ensureInit();\n\n const wasmPath = resolveGrammarPath(grammarName);\n const language = await Parser.Language.load(wasmPath);\n\n grammarCache.set(grammarName, language);\n return language;\n}\n\n/**\n * Create a new Parser instance configured for a given grammar.\n */\nexport async function createParser(grammarName: string): Promise<Parser> {\n await ensureInit();\n const language = await loadGrammar(grammarName);\n const parser = new Parser();\n parser.setLanguage(language);\n return parser;\n}\n\n/**\n * Reset internal state. Only used in tests.\n */\nexport function _resetForTesting(): void {\n grammarCache.clear();\n initPromise = null;\n}\n","/**\n * Parser service — public API for tree-sitter parsing.\n *\n * Maps file extensions to tree-sitter grammars and provides a single\n * `parseSource` entry point for the rest of the application.\n */\n\nimport type Parser from \"web-tree-sitter\";\nimport { createParser } from \"./grammar-loader.js\";\n\n// ---------------------------------------------------------------------------\n// Extension → grammar mapping\n// ---------------------------------------------------------------------------\n\nconst EXTENSION_TO_GRAMMAR: Record<string, string> = {\n \".ts\": \"typescript\",\n \".tsx\": \"typescript\",\n \".js\": \"javascript\",\n \".jsx\": \"javascript\",\n \".mjs\": \"javascript\",\n \".cjs\": \"javascript\",\n \".py\": \"python\",\n \".java\": \"java\",\n};\n\n/** File extensions that the parser service can handle. */\nexport const SUPPORTED_EXTENSIONS = new Set(Object.keys(EXTENSION_TO_GRAMMAR));\n\n/**\n * Get the grammar name for a file path based on its extension.\n * Returns null if the extension is not supported.\n */\nexport function getGrammarForFile(filePath: string): string | null {\n const ext = getExtension(filePath);\n return EXTENSION_TO_GRAMMAR[ext] ?? null;\n}\n\n// ---------------------------------------------------------------------------\n// Parser cache (one parser per grammar)\n// ---------------------------------------------------------------------------\n\nconst parserCache = new Map<string, Promise<Parser>>();\n\nfunction getOrCreateParser(grammarName: string): Promise<Parser> {\n let p = parserCache.get(grammarName);\n if (!p) {\n p = createParser(grammarName);\n parserCache.set(grammarName, p);\n }\n return p;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Parse source code using the appropriate tree-sitter grammar.\n *\n * @param filePath — used to determine the language grammar (by extension)\n * @param source — the source code text to parse\n * @returns the parsed Tree, or null if the file extension is unsupported\n */\nexport async function parseSource(filePath: string, source: string): Promise<Parser.Tree | null> {\n const grammarName = getGrammarForFile(filePath);\n if (!grammarName) return null;\n\n const parser = await getOrCreateParser(grammarName);\n return parser.parse(source);\n}\n\n/**\n * Reset internal state. Only used in tests.\n */\nexport function _resetForTesting(): void {\n parserCache.clear();\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction getExtension(filePath: string): string {\n const lastDot = filePath.lastIndexOf(\".\");\n if (lastDot === -1) return \"\";\n return filePath.slice(lastDot);\n}\n","/**\n * TypeScript / JavaScript symbol extractor.\n *\n * Extracts functions, arrow functions, classes (with methods/fields),\n * interfaces, and type aliases from TypeScript/JavaScript ASTs.\n * Works for both TS and JS — JS simply won't produce interface or\n * type_alias nodes.\n */\n\nimport type Parser from \"web-tree-sitter\";\nimport type { Symbol, SymbolKind } from \"../../../types/index.js\";\nimport type { SymbolExtractor } from \"./types.js\";\n\ntype SyntaxNode = Parser.SyntaxNode;\n\nexport class TypeScriptExtractor implements SymbolExtractor {\n extract(tree: Parser.Tree, _filePath: string): Symbol[] {\n const symbols: Symbol[] = [];\n this.visitTopLevel(tree.rootNode, symbols);\n return symbols;\n }\n\n private visitTopLevel(root: SyntaxNode, symbols: Symbol[]): void {\n for (let i = 0; i < root.childCount; i++) {\n const node = root.child(i)!;\n\n if (node.type === \"export_statement\") {\n this.extractExport(node, symbols);\n } else {\n this.extractDeclaration(node, false, symbols);\n }\n }\n }\n\n private extractExport(node: SyntaxNode, symbols: Symbol[]): void {\n const isDefault = node.children.some((c) => c.type === \"default\");\n\n for (let i = 0; i < node.childCount; i++) {\n const child = node.child(i)!;\n this.extractDeclaration(child, true, symbols, isDefault);\n }\n }\n\n private extractDeclaration(\n node: SyntaxNode,\n exported: boolean,\n symbols: Symbol[],\n isDefault = false,\n ): void {\n switch (node.type) {\n case \"function_declaration\":\n symbols.push(this.buildFunctionSymbol(node, exported, \"function\"));\n break;\n\n case \"lexical_declaration\":\n case \"variable_declaration\":\n this.extractVariableDeclarations(node, exported, symbols);\n break;\n\n case \"class_declaration\":\n this.extractClass(node, exported, isDefault, symbols);\n break;\n\n case \"interface_declaration\":\n symbols.push(this.buildSimpleSymbol(node, exported, \"interface\"));\n break;\n\n case \"type_alias_declaration\":\n symbols.push(this.buildSimpleSymbol(node, exported, \"type_alias\"));\n break;\n }\n }\n\n private buildFunctionSymbol(\n node: SyntaxNode,\n exported: boolean,\n kind: SymbolKind,\n ): Symbol {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n const isAsync = node.children.some((c) => c.type === \"async\");\n const signature = this.extractFunctionSignature(node);\n\n return {\n name,\n kind,\n exported,\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n signature,\n is_async: isAsync || undefined,\n };\n }\n\n private extractVariableDeclarations(\n node: SyntaxNode,\n exported: boolean,\n symbols: Symbol[],\n ): void {\n for (let i = 0; i < node.childCount; i++) {\n const child = node.child(i)!;\n if (child.type !== \"variable_declarator\") continue;\n\n const nameNode = child.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n const valueNode = child.childForFieldName(\"value\");\n\n if (valueNode?.type === \"arrow_function\") {\n const isAsync = valueNode.children.some((c) => c.type === \"async\");\n const signature = this.extractArrowSignature(valueNode);\n symbols.push({\n name,\n kind: \"arrow_function\",\n exported,\n line: child.startPosition.row + 1,\n end_line: child.endPosition.row + 1,\n signature,\n is_async: isAsync || undefined,\n });\n } else {\n symbols.push({\n name,\n kind: \"constant\",\n exported,\n line: child.startPosition.row + 1,\n end_line: child.endPosition.row + 1,\n });\n }\n }\n }\n\n private extractClass(\n node: SyntaxNode,\n exported: boolean,\n isDefault: boolean,\n symbols: Symbol[],\n ): void {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? (isDefault ? \"(default)\" : \"(anonymous)\");\n\n symbols.push({\n name,\n kind: \"class\",\n exported,\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n });\n\n const body = node.childForFieldName(\"body\");\n if (!body) return;\n\n for (let i = 0; i < body.childCount; i++) {\n const member = body.child(i)!;\n\n if (member.type === \"method_definition\") {\n this.extractMethod(member, symbols);\n } else if (member.type === \"public_field_definition\") {\n this.extractField(member, symbols);\n }\n }\n }\n\n private extractMethod(node: SyntaxNode, symbols: Symbol[]): void {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n const isAsync = node.children.some((c) => c.type === \"async\");\n const signature = this.extractFunctionSignature(node);\n\n symbols.push({\n name,\n kind: \"method\",\n exported: false,\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n signature,\n is_async: isAsync || undefined,\n });\n }\n\n private extractField(node: SyntaxNode, symbols: Symbol[]): void {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n const typeAnnotation = node.children.find((c) => c.type === \"type_annotation\");\n const signature = typeAnnotation ? typeAnnotation.text.slice(2).trim() : null;\n\n symbols.push({\n name,\n kind: \"field\",\n exported: false,\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n signature,\n });\n }\n\n private buildSimpleSymbol(\n node: SyntaxNode,\n exported: boolean,\n kind: SymbolKind,\n ): Symbol {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n\n return {\n name,\n kind,\n exported,\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n };\n }\n\n private extractFunctionSignature(node: SyntaxNode): string | null {\n const params = node.children.find((c) => c.type === \"formal_parameters\");\n const returnType = node.children.find((c) => c.type === \"type_annotation\");\n\n if (!params) return null;\n\n let sig = params.text;\n if (returnType) {\n sig += returnType.text;\n }\n return sig;\n }\n\n private extractArrowSignature(node: SyntaxNode): string | null {\n const params = node.children.find((c) => c.type === \"formal_parameters\");\n const returnType = node.children.find((c) => c.type === \"type_annotation\");\n\n if (!params) return null;\n\n let sig = params.text;\n if (returnType) {\n sig += returnType.text;\n }\n return sig;\n }\n}\n","/**\n * Python symbol extractor.\n *\n * Extracts module-level functions, classes (with methods), and uses\n * __all__ for export control or _ prefix convention for private symbols.\n */\n\nimport type Parser from \"web-tree-sitter\";\nimport type { Symbol } from \"../../../types/index.js\";\nimport type { SymbolExtractor } from \"./types.js\";\n\ntype SyntaxNode = Parser.SyntaxNode;\n\nexport class PythonExtractor implements SymbolExtractor {\n extract(tree: Parser.Tree, _filePath: string): Symbol[] {\n const symbols: Symbol[] = [];\n const allList = this.extractAllList(tree.rootNode);\n\n for (let i = 0; i < tree.rootNode.childCount; i++) {\n const node = tree.rootNode.child(i)!;\n this.visitTopLevel(node, symbols, allList);\n }\n\n return symbols;\n }\n\n /**\n * Extract the __all__ list if present. Returns null if not defined,\n * meaning all non-underscore symbols are considered exported.\n */\n private extractAllList(root: SyntaxNode): Set<string> | null {\n for (let i = 0; i < root.childCount; i++) {\n const node = root.child(i)!;\n if (node.type !== \"expression_statement\") continue;\n\n const assignment = node.child(0);\n if (assignment?.type !== \"assignment\") continue;\n\n const left = assignment.childForFieldName(\"left\");\n if (left?.type !== \"identifier\" || left.text !== \"__all__\") continue;\n\n const right = assignment.childForFieldName(\"right\");\n if (!right || right.type !== \"list\") continue;\n\n const names = new Set<string>();\n for (let j = 0; j < right.childCount; j++) {\n const elem = right.child(j)!;\n if (elem.type === \"string\") {\n // Strip quotes\n const raw = elem.text;\n const unquoted = raw.slice(1, -1);\n if (unquoted) names.add(unquoted);\n }\n }\n return names;\n }\n return null;\n }\n\n private visitTopLevel(\n node: SyntaxNode,\n symbols: Symbol[],\n allList: Set<string> | null,\n ): void {\n if (node.type === \"function_definition\") {\n symbols.push(this.buildFunction(node, allList));\n } else if (node.type === \"class_definition\") {\n this.extractClass(node, allList, symbols);\n } else if (node.type === \"decorated_definition\") {\n this.extractDecorated(node, allList, symbols);\n }\n }\n\n private isExported(name: string, allList: Set<string> | null): boolean {\n if (allList) return allList.has(name);\n return !name.startsWith(\"_\");\n }\n\n private buildFunction(\n node: SyntaxNode,\n allList: Set<string> | null,\n ): Symbol {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n const isAsync = node.children.some((c) => c.type === \"async\");\n const signature = this.extractPythonSignature(node);\n const decorators = this.getDecorators(node);\n\n return {\n name,\n kind: \"function\",\n exported: this.isExported(name, allList),\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n signature,\n is_async: isAsync || undefined,\n annotations: decorators.length > 0 ? decorators : undefined,\n };\n }\n\n private extractDecorated(\n node: SyntaxNode,\n allList: Set<string> | null,\n symbols: Symbol[],\n ): void {\n const decorators = this.getDecorators(node);\n const definition = node.children.find(\n (c) => c.type === \"function_definition\" || c.type === \"class_definition\",\n );\n if (!definition) return;\n\n if (definition.type === \"function_definition\") {\n const sym = this.buildFunction(definition, allList);\n sym.annotations = decorators.length > 0 ? decorators : undefined;\n sym.line = node.startPosition.row + 1;\n symbols.push(sym);\n } else if (definition.type === \"class_definition\") {\n this.extractClass(definition, allList, symbols, decorators, node.startPosition.row + 1);\n }\n }\n\n private extractClass(\n node: SyntaxNode,\n allList: Set<string> | null,\n symbols: Symbol[],\n decorators: string[] = [],\n startLine?: number,\n ): void {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n\n symbols.push({\n name,\n kind: \"class\",\n exported: this.isExported(name, allList),\n line: startLine ?? node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n annotations: decorators.length > 0 ? decorators : undefined,\n });\n\n const body = node.childForFieldName(\"body\");\n if (!body) return;\n\n for (let i = 0; i < body.childCount; i++) {\n const child = body.child(i)!;\n if (child.type === \"function_definition\") {\n this.extractMethod(child, symbols);\n } else if (child.type === \"decorated_definition\") {\n this.extractDecoratedMethod(child, symbols);\n }\n }\n }\n\n private extractMethod(\n node: SyntaxNode,\n symbols: Symbol[],\n decorators: string[] = [],\n startLine?: number,\n ): void {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n const isAsync = node.children.some((c) => c.type === \"async\");\n const signature = this.extractPythonSignature(node, true);\n\n symbols.push({\n name,\n kind: \"method\",\n exported: false,\n line: startLine ?? node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n signature,\n is_async: isAsync || undefined,\n annotations: decorators.length > 0 ? decorators : undefined,\n });\n }\n\n private extractDecoratedMethod(\n node: SyntaxNode,\n symbols: Symbol[],\n ): void {\n const decorators = this.getDecorators(node);\n const definition = node.children.find((c) => c.type === \"function_definition\");\n if (!definition) return;\n this.extractMethod(definition, symbols, decorators, node.startPosition.row + 1);\n }\n\n private getDecorators(node: SyntaxNode): string[] {\n return node.children\n .filter((c) => c.type === \"decorator\")\n .map((d) => {\n // The decorator text includes the @, skip it\n return d.text.startsWith(\"@\") ? d.text.slice(1) : d.text;\n });\n }\n\n private extractPythonSignature(\n node: SyntaxNode,\n isMethod = false,\n ): string | null {\n const params = node.childForFieldName(\"parameters\");\n if (!params) return null;\n\n let paramText = params.text;\n\n // For methods, strip self/cls first parameter\n if (isMethod) {\n paramText = this.stripSelfParam(paramText);\n }\n\n // Check for return type\n const returnTypeNode = node.childForFieldName(\"return_type\");\n if (returnTypeNode) {\n paramText += \" -> \" + returnTypeNode.text;\n }\n\n return paramText;\n }\n\n private stripSelfParam(paramText: string): string {\n // Remove 'self' or 'cls' as first param\n // (self, name: str) -> (name: str)\n // (self) -> ()\n const inner = paramText.slice(1, -1).trim();\n const parts = inner.split(\",\").map((p) => p.trim());\n if (parts.length > 0 && (parts[0] === \"self\" || parts[0] === \"cls\")) {\n parts.shift();\n }\n return \"(\" + parts.join(\", \") + \")\";\n }\n}\n","/**\n * Java symbol extractor.\n *\n * Extracts classes, interfaces, enums, methods, fields, constructors,\n * annotations, and visibility modifiers. Package declarations are\n * included as `kind: \"package\"` symbols.\n */\n\nimport type Parser from \"web-tree-sitter\";\nimport type { Symbol, Visibility, SymbolKind } from \"../../../types/index.js\";\nimport type { SymbolExtractor } from \"./types.js\";\n\ntype SyntaxNode = Parser.SyntaxNode;\n\nexport class JavaExtractor implements SymbolExtractor {\n extract(tree: Parser.Tree, _filePath: string): Symbol[] {\n const symbols: Symbol[] = [];\n\n for (let i = 0; i < tree.rootNode.childCount; i++) {\n const node = tree.rootNode.child(i)!;\n this.visitTopLevel(node, symbols);\n }\n\n return symbols;\n }\n\n private visitTopLevel(node: SyntaxNode, symbols: Symbol[]): void {\n switch (node.type) {\n case \"package_declaration\":\n this.extractPackage(node, symbols);\n break;\n case \"class_declaration\":\n this.extractClass(node, symbols);\n break;\n case \"interface_declaration\":\n this.extractInterface(node, symbols);\n break;\n case \"enum_declaration\":\n this.extractEnum(node, symbols);\n break;\n }\n }\n\n private extractPackage(node: SyntaxNode, symbols: Symbol[]): void {\n // Package name is a scoped_identifier or identifier child\n const nameNode = node.children.find(\n (c) => c.type === \"scoped_identifier\" || c.type === \"identifier\",\n );\n if (!nameNode) return;\n\n symbols.push({\n name: nameNode.text,\n kind: \"package\",\n exported: true,\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n });\n }\n\n private extractClass(node: SyntaxNode, symbols: Symbol[]): void {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n const { visibility, annotations, modifierFlags } = this.parseModifiers(node);\n\n symbols.push({\n name,\n kind: \"class\",\n exported: visibility === \"public\",\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n visibility,\n annotations: this.buildAnnotationsList(annotations, modifierFlags),\n });\n\n const body = node.childForFieldName(\"body\");\n if (!body) return;\n this.extractClassMembers(body, symbols);\n }\n\n private extractInterface(node: SyntaxNode, symbols: Symbol[]): void {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n const { visibility, annotations, modifierFlags } = this.parseModifiers(node);\n\n symbols.push({\n name,\n kind: \"interface\",\n exported: visibility === \"public\",\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n visibility,\n annotations: this.buildAnnotationsList(annotations, modifierFlags),\n });\n\n const body = node.childForFieldName(\"body\");\n if (!body) return;\n\n // Interface methods\n for (let i = 0; i < body.childCount; i++) {\n const child = body.child(i)!;\n if (child.type === \"method_declaration\") {\n this.extractMethod(child, symbols);\n }\n }\n }\n\n private extractEnum(node: SyntaxNode, symbols: Symbol[]): void {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n const { visibility, annotations, modifierFlags } = this.parseModifiers(node);\n\n symbols.push({\n name,\n kind: \"enum\",\n exported: visibility === \"public\",\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n visibility,\n annotations: this.buildAnnotationsList(annotations, modifierFlags),\n });\n }\n\n private extractClassMembers(body: SyntaxNode, symbols: Symbol[]): void {\n for (let i = 0; i < body.childCount; i++) {\n const child = body.child(i)!;\n\n switch (child.type) {\n case \"method_declaration\":\n this.extractMethod(child, symbols);\n break;\n case \"field_declaration\":\n this.extractField(child, symbols);\n break;\n case \"constructor_declaration\":\n this.extractConstructor(child, symbols);\n break;\n case \"class_declaration\":\n this.extractClass(child, symbols);\n break;\n case \"interface_declaration\":\n this.extractInterface(child, symbols);\n break;\n case \"enum_declaration\":\n this.extractEnum(child, symbols);\n break;\n }\n }\n }\n\n private extractMethod(node: SyntaxNode, symbols: Symbol[]): void {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n const { visibility, annotations, modifierFlags } = this.parseModifiers(node);\n const signature = this.buildMethodSignature(node);\n\n symbols.push({\n name,\n kind: \"method\",\n exported: visibility === \"public\",\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n signature,\n visibility,\n annotations: this.buildAnnotationsList(annotations, modifierFlags),\n });\n }\n\n private extractField(node: SyntaxNode, symbols: Symbol[]): void {\n const { visibility, annotations, modifierFlags } = this.parseModifiers(node);\n\n // Type is the first non-modifiers child that's a type\n const typeNode = node.children.find(\n (c) =>\n c.type !== \"modifiers\" &&\n c.type !== \";\" &&\n c.type !== \"variable_declarator\",\n );\n\n // Variable declarator contains the name\n const declarator = node.children.find((c) => c.type === \"variable_declarator\");\n const nameNode = declarator?.childForFieldName(\"name\");\n const name = nameNode?.text ?? declarator?.text?.split(/\\s*=/)?.[0]?.trim() ?? \"(unknown)\";\n\n const typeName = typeNode?.text ?? null;\n\n symbols.push({\n name,\n kind: \"field\",\n exported: visibility === \"public\",\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n signature: typeName,\n visibility,\n annotations: this.buildAnnotationsList(annotations, modifierFlags),\n });\n }\n\n private extractConstructor(node: SyntaxNode, symbols: Symbol[]): void {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n const { visibility, annotations, modifierFlags } = this.parseModifiers(node);\n const params = node.childForFieldName(\"parameters\");\n\n symbols.push({\n name,\n kind: \"constructor\",\n exported: visibility === \"public\",\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n signature: params?.text ?? \"()\",\n visibility,\n annotations: this.buildAnnotationsList(annotations, modifierFlags),\n });\n }\n\n // ---------------------------------------------------------------------------\n // Modifier / annotation parsing\n // ---------------------------------------------------------------------------\n\n private parseModifiers(node: SyntaxNode): {\n visibility: Visibility;\n annotations: string[];\n modifierFlags: string[];\n } {\n const modifiersNode = node.children.find((c) => c.type === \"modifiers\");\n if (!modifiersNode) {\n return { visibility: \"package\", annotations: [], modifierFlags: [] };\n }\n\n let visibility: Visibility = \"package\";\n const annotations: string[] = [];\n const modifierFlags: string[] = [];\n\n for (let i = 0; i < modifiersNode.childCount; i++) {\n const child = modifiersNode.child(i)!;\n\n switch (child.type) {\n case \"public\":\n visibility = \"public\";\n break;\n case \"private\":\n visibility = \"private\";\n break;\n case \"protected\":\n visibility = \"protected\";\n break;\n case \"static\":\n case \"final\":\n case \"abstract\":\n case \"synchronized\":\n case \"native\":\n modifierFlags.push(child.type);\n break;\n case \"marker_annotation\":\n case \"annotation\": {\n const text = child.text;\n annotations.push(text.startsWith(\"@\") ? text.slice(1) : text);\n break;\n }\n }\n }\n\n return { visibility, annotations, modifierFlags };\n }\n\n private buildAnnotationsList(\n annotations: string[],\n modifierFlags: string[],\n ): string[] | undefined {\n const all = [...annotations, ...modifierFlags];\n return all.length > 0 ? all : undefined;\n }\n\n // ---------------------------------------------------------------------------\n // Signature building\n // ---------------------------------------------------------------------------\n\n private buildMethodSignature(node: SyntaxNode): string | null {\n const returnType = node.children.find(\n (c) =>\n c.type !== \"modifiers\" &&\n c.type !== \"identifier\" &&\n c.type !== \"formal_parameters\" &&\n c.type !== \"throws\" &&\n c.type !== \"block\" &&\n c.type !== \";\" &&\n c.type !== \"type_parameters\",\n );\n const params = node.childForFieldName(\"parameters\");\n const throwsNode = node.children.find((c) => c.type === \"throws\");\n\n if (!params) return null;\n\n let sig = \"\";\n if (returnType) sig += returnType.text + \" \";\n\n // Get method name\n const nameNode = node.childForFieldName(\"name\");\n sig += (nameNode?.text ?? \"\") + params.text;\n\n if (throwsNode) {\n sig += \" \" + throwsNode.text;\n }\n\n return sig;\n }\n}\n","/**\n * Extractor registry — maps grammar names to symbol extractors.\n */\n\nimport type { SymbolExtractor } from \"./types.js\";\nimport { TypeScriptExtractor } from \"./typescript.js\";\nimport { PythonExtractor } from \"./python.js\";\nimport { JavaExtractor } from \"./java.js\";\n\nconst extractors: Record<string, SymbolExtractor> = {\n typescript: new TypeScriptExtractor(),\n javascript: new TypeScriptExtractor(), // JS is a subset; same extractor works\n python: new PythonExtractor(),\n java: new JavaExtractor(),\n};\n\n/**\n * Get the symbol extractor for a grammar name.\n * Returns null if no extractor exists for the grammar.\n */\nexport function getExtractor(grammarName: string): SymbolExtractor | null {\n return extractors[grammarName] ?? null;\n}\n","/**\n * Shared utilities for the parser service.\n *\n * Extracted from symbol-index.ts to be reused by the dependency graph builder.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { ResolvedConfig } from \"../../config/index.js\";\nimport { SUPPORTED_EXTENSIONS } from \"./index.js\";\n\n/** Default concurrency for parallel parsing. */\nexport const DEFAULT_CONCURRENCY = 8;\n\n// ---------------------------------------------------------------------------\n// File collection\n// ---------------------------------------------------------------------------\n\n/**\n * Collect all parseable source files from a project directory.\n *\n * Respects collapse_dirs, ignore_patterns, and max_file_size_kb from the\n * resolved configuration. Does NOT apply tree_depth — that limit is only\n * for the display tree. The parser must walk as deep as needed to find all\n * source files (Java projects commonly reach depth 8+).\n */\nexport function collectSourceFiles(\n projectRoot: string,\n config: ResolvedConfig,\n): string[] {\n const files: string[] = [];\n const maxSizeBytes = config.max_file_size_kb * 1024;\n\n walk(projectRoot, projectRoot, config, files, maxSizeBytes);\n return files;\n}\n\nfunction walk(\n dirPath: string,\n projectRoot: string,\n config: ResolvedConfig,\n files: string[],\n maxSizeBytes: number,\n): void {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dirPath, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n const fullPath = path.join(dirPath, entry.name);\n\n if (entry.isDirectory()) {\n if (config.collapse_dirs.includes(entry.name)) continue;\n walk(fullPath, projectRoot, config, files, maxSizeBytes);\n } else if (entry.isFile()) {\n const ext = path.extname(entry.name).toLowerCase();\n if (!SUPPORTED_EXTENSIONS.has(ext)) continue;\n if (matchesIgnorePattern(entry.name, config.ignore_patterns)) continue;\n\n try {\n const stat = fs.statSync(fullPath);\n if (stat.size > maxSizeBytes) continue;\n } catch {\n continue;\n }\n\n files.push(fullPath);\n }\n }\n}\n\n/**\n * Check if a filename matches any of the given ignore patterns.\n */\nexport function matchesIgnorePattern(fileName: string, patterns: string[]): boolean {\n for (const pattern of patterns) {\n const regex = new RegExp(\n \"^\" + pattern.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\").replace(/\\*/g, \".*\") + \"$\",\n );\n if (regex.test(fileName)) return true;\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Concurrency helper\n// ---------------------------------------------------------------------------\n\n/**\n * Execute an array of async tasks with a concurrency limit.\n */\nexport async function withConcurrency(\n tasks: (() => Promise<void>)[],\n limit: number,\n): Promise<void> {\n let index = 0;\n\n async function runNext(): Promise<void> {\n while (index < tasks.length) {\n const currentIndex = index++;\n await tasks[currentIndex]();\n }\n }\n\n const workers = Array.from(\n { length: Math.min(limit, tasks.length) },\n () => runNext(),\n );\n await Promise.all(workers);\n}\n","/**\n * Dependency graph builder.\n *\n * Builds a bidirectional dependency map for all source files in a project:\n * for each file, stores which files it imports from and which files import it.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { DependencyEntry } from \"../../types/index.js\";\nimport type { ResolvedConfig } from \"../../config/index.js\";\nimport { parseSource, getGrammarForFile } from \"./index.js\";\nimport { getImportExtractor } from \"./import-extractors/index.js\";\nimport {\n resolveTypeScriptImport,\n resolvePythonImport,\n resolveJavaImport,\n buildJavaPackageIndex,\n buildPythonPackageIndex,\n type JavaPackageIndex,\n type PythonPackageIndex,\n} from \"./path-resolver.js\";\nimport { collectSourceFiles, withConcurrency, DEFAULT_CONCURRENCY } from \"./utils.js\";\n\n/**\n * Build a bidirectional dependency graph for a project.\n *\n * @returns Map of project-relative file path to its dependency entry.\n */\nexport async function buildDependencyGraph(\n projectRoot: string,\n config: ResolvedConfig,\n preCollectedFiles?: string[],\n): Promise<Record<string, DependencyEntry>> {\n const files = preCollectedFiles ?? collectSourceFiles(projectRoot, config);\n const relativePaths = files.map((f) => path.relative(projectRoot, f));\n\n // Build Java package index if there are any .java files\n let javaPackageIndex: JavaPackageIndex | null = null;\n if (files.some((f) => f.endsWith(\".java\"))) {\n javaPackageIndex = buildJavaPackageIndex(projectRoot);\n }\n\n // Build Python package index if there are any .py files\n let pythonPackageIndex: PythonPackageIndex | null = null;\n if (files.some((f) => f.endsWith(\".py\"))) {\n pythonPackageIndex = buildPythonPackageIndex(projectRoot);\n }\n\n // Resolve path aliases: use config value if provided, otherwise auto-detect\n const pathAliases =\n config.path_aliases === \"auto\" || config.path_aliases === undefined\n ? loadPathAliases(projectRoot)\n : config.path_aliases;\n\n // Forward adjacency: file → [files it imports from]\n const forwardEdges: Record<string, Set<string>> = {};\n\n // Process each file to extract its imports\n await withConcurrency(\n files.map((filePath, idx) => async () => {\n const relativePath = relativePaths[idx];\n const deps = await extractDependencies(\n filePath,\n relativePath,\n projectRoot,\n pathAliases,\n javaPackageIndex,\n pythonPackageIndex,\n );\n if (deps.length > 0) {\n forwardEdges[relativePath] = new Set(deps);\n }\n }),\n DEFAULT_CONCURRENCY,\n );\n\n // Build the bidirectional graph\n const graph: Record<string, DependencyEntry> = {};\n const allFiles = new Set(relativePaths);\n\n // Initialize entries for all files that participate in the graph\n for (const file of allFiles) {\n if (forwardEdges[file] || isImportedBy(file, forwardEdges)) {\n if (!graph[file]) {\n graph[file] = { imports_from: [], imported_by: [] };\n }\n }\n }\n\n // Fill forward edges (imports_from)\n for (const [file, deps] of Object.entries(forwardEdges)) {\n if (!graph[file]) {\n graph[file] = { imports_from: [], imported_by: [] };\n }\n graph[file].imports_from = [...deps].sort();\n }\n\n // Fill reverse edges (imported_by)\n for (const [file, deps] of Object.entries(forwardEdges)) {\n for (const dep of deps) {\n if (!graph[dep]) {\n graph[dep] = { imports_from: [], imported_by: [] };\n }\n graph[dep].imported_by.push(file);\n }\n }\n\n // Sort imported_by for deterministic output\n for (const entry of Object.values(graph)) {\n entry.imported_by.sort();\n }\n\n return graph;\n}\n\n/**\n * Incrementally update a cached dependency graph by re-extracting only changed files.\n *\n * @param cached The previous dependency graph from cache.\n * @param changedFiles Relative paths of files that were added or modified.\n * @param deletedFiles Relative paths of files that were deleted.\n * @param projectRoot Absolute path to the project root.\n * @param config Resolved configuration.\n * @returns Updated dependency graph.\n */\nexport async function updateDependencyGraph(\n cached: Record<string, DependencyEntry>,\n changedFiles: string[],\n deletedFiles: string[],\n projectRoot: string,\n config: ResolvedConfig,\n): Promise<Record<string, DependencyEntry>> {\n // Rebuild forward edges from cached graph\n const forwardEdges: Record<string, Set<string>> = {};\n for (const [file, entry] of Object.entries(cached)) {\n if (entry.imports_from.length > 0) {\n forwardEdges[file] = new Set(entry.imports_from);\n }\n }\n\n // Remove deleted files\n for (const file of deletedFiles) {\n delete forwardEdges[file];\n }\n\n // Re-extract dependencies for changed files\n const allFiles = collectSourceFiles(projectRoot, config);\n\n let javaPackageIndex: JavaPackageIndex | null = null;\n if (allFiles.some((f) => f.endsWith(\".java\"))) {\n javaPackageIndex = buildJavaPackageIndex(projectRoot);\n }\n\n let pythonPackageIndex: PythonPackageIndex | null = null;\n if (allFiles.some((f) => f.endsWith(\".py\"))) {\n pythonPackageIndex = buildPythonPackageIndex(projectRoot);\n }\n\n const pathAliases =\n config.path_aliases === \"auto\" || config.path_aliases === undefined\n ? loadPathAliases(projectRoot)\n : config.path_aliases;\n\n await withConcurrency(\n changedFiles.map((relativePath) => async () => {\n const filePath = path.join(projectRoot, relativePath);\n const deps = await extractDependencies(\n filePath,\n relativePath,\n projectRoot,\n pathAliases,\n javaPackageIndex,\n pythonPackageIndex,\n );\n if (deps.length > 0) {\n forwardEdges[relativePath] = new Set(deps);\n } else {\n delete forwardEdges[relativePath];\n }\n }),\n DEFAULT_CONCURRENCY,\n );\n\n // Rebuild the full bidirectional graph from forward edges\n const graph: Record<string, DependencyEntry> = {};\n\n // Collect all files that participate\n const allParticipants = new Set<string>();\n for (const [file, deps] of Object.entries(forwardEdges)) {\n allParticipants.add(file);\n for (const dep of deps) {\n allParticipants.add(dep);\n }\n }\n\n for (const file of allParticipants) {\n graph[file] = { imports_from: [], imported_by: [] };\n }\n\n // Fill forward edges\n for (const [file, deps] of Object.entries(forwardEdges)) {\n graph[file].imports_from = [...deps].sort();\n }\n\n // Fill reverse edges\n for (const [file, deps] of Object.entries(forwardEdges)) {\n for (const dep of deps) {\n if (graph[dep]) {\n graph[dep].imported_by.push(file);\n }\n }\n }\n\n // Sort imported_by for deterministic output\n for (const entry of Object.values(graph)) {\n entry.imported_by.sort();\n }\n\n return graph;\n}\n\n/**\n * Check if a file is imported by any other file.\n */\nfunction isImportedBy(file: string, forwardEdges: Record<string, Set<string>>): boolean {\n for (const deps of Object.values(forwardEdges)) {\n if (deps.has(file)) return true;\n }\n return false;\n}\n\n/**\n * Extract resolved dependency paths for a single file.\n */\nasync function extractDependencies(\n filePath: string,\n relativePath: string,\n projectRoot: string,\n pathAliases: Record<string, string> | undefined,\n javaPackageIndex: JavaPackageIndex | null,\n pythonPackageIndex: PythonPackageIndex | null,\n): Promise<string[]> {\n let source: string;\n try {\n source = fs.readFileSync(filePath, \"utf-8\");\n } catch {\n return [];\n }\n\n const tree = await parseSource(relativePath, source);\n if (!tree) return [];\n\n const grammarName = getGrammarForFile(relativePath);\n if (!grammarName) return [];\n\n const extractor = getImportExtractor(grammarName);\n if (!extractor) return [];\n\n const rawImports = extractor.extract(tree);\n const resolved: string[] = [];\n\n for (const imp of rawImports) {\n let resolvedPath: string | null = null;\n\n switch (grammarName) {\n case \"typescript\":\n case \"javascript\":\n resolvedPath = resolveTypeScriptImport(\n imp.source,\n relativePath,\n projectRoot,\n pathAliases,\n );\n break;\n\n case \"python\":\n resolvedPath = resolvePythonImport(\n imp.source,\n relativePath,\n projectRoot,\n pythonPackageIndex ?? undefined,\n );\n break;\n\n case \"java\":\n if (javaPackageIndex) {\n const javaResult = resolveJavaImport(imp.source, javaPackageIndex);\n if (Array.isArray(javaResult)) {\n for (const p of javaResult) {\n if (p !== relativePath) {\n resolved.push(p);\n }\n }\n } else {\n resolvedPath = javaResult;\n }\n }\n break;\n }\n\n if (resolvedPath && resolvedPath !== relativePath) {\n resolved.push(resolvedPath);\n }\n }\n\n // Deduplicate\n return [...new Set(resolved)];\n}\n\n/**\n * Load path aliases from tsconfig.json compilerOptions.paths.\n */\nfunction loadPathAliases(projectRoot: string): Record<string, string> | undefined {\n const tsconfigPath = path.join(projectRoot, \"tsconfig.json\");\n if (!fs.existsSync(tsconfigPath)) return undefined;\n\n try {\n const raw = fs.readFileSync(tsconfigPath, \"utf-8\");\n // Strip comments (simple heuristic — handles // and /* */ in JSON)\n const stripped = raw\n .replace(/\\/\\/.*$/gm, \"\")\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\");\n const tsconfig = JSON.parse(stripped);\n\n const paths = tsconfig?.compilerOptions?.paths;\n if (!paths || typeof paths !== \"object\") return undefined;\n\n const result: Record<string, string> = {};\n for (const [key, values] of Object.entries(paths)) {\n if (Array.isArray(values) && values.length > 0) {\n result[key] = values[0] as string;\n }\n }\n\n return Object.keys(result).length > 0 ? result : undefined;\n } catch {\n return undefined;\n }\n}\n","/**\n * TypeScript/JavaScript import extractor.\n *\n * Handles:\n * - ES6 imports: import { x } from \"y\", import x from \"y\", import * as x from \"y\"\n * - CJS require: const x = require(\"y\")\n * - Dynamic import: import(\"y\")\n * - Re-exports: export { x } from \"y\", export * from \"y\"\n * - Side-effect imports: import \"y\"\n */\n\nimport type Parser from \"web-tree-sitter\";\nimport type { ImportExtractor, ExtractedImport } from \"./types.js\";\n\nexport class TypeScriptImportExtractor implements ImportExtractor {\n /** Extract all imports from a TypeScript/JavaScript AST. */\n extract(tree: Parser.Tree): ExtractedImport[] {\n const imports: ExtractedImport[] = [];\n this.visit(tree.rootNode, imports);\n return imports;\n }\n\n private visit(node: Parser.SyntaxNode, imports: ExtractedImport[]): void {\n switch (node.type) {\n case \"import_statement\": {\n this.extractImportStatement(node, imports);\n break;\n }\n\n case \"export_statement\": {\n // Re-exports: export { x } from \"y\" or export * from \"y\"\n const source = node.childForFieldName(\"source\");\n if (source) {\n const specifiers = this.extractSpecifiers(node);\n imports.push({\n source: stripQuotes(source.text),\n specifiers,\n kind: \"static\",\n });\n }\n break;\n }\n\n case \"lexical_declaration\":\n case \"variable_declaration\": {\n // CJS: const x = require(\"y\")\n this.extractRequire(node, imports);\n break;\n }\n\n case \"expression_statement\": {\n // Side-effect require: require(\"y\")\n // Or dynamic import as statement: import(\"y\")\n this.extractExpressionStatement(node, imports);\n break;\n }\n\n case \"call_expression\": {\n // Dynamic import: import(\"y\") in any position\n this.extractDynamicImport(node, imports);\n return; // Don't recurse into children, we handled it\n }\n }\n\n for (let i = 0; i < node.childCount; i++) {\n this.visit(node.child(i)!, imports);\n }\n }\n\n private extractImportStatement(node: Parser.SyntaxNode, imports: ExtractedImport[]): void {\n const source = node.childForFieldName(\"source\");\n if (!source) return;\n\n const sourceText = stripQuotes(source.text);\n const specifiers = this.extractSpecifiers(node);\n\n // Side-effect import: import \"y\" (no specifiers, no default, no namespace)\n const hasClause = node.children.some(\n (c) =>\n c.type === \"import_clause\" ||\n c.type === \"named_imports\" ||\n c.type === \"namespace_import\",\n );\n\n imports.push({\n source: sourceText,\n specifiers,\n kind: specifiers.length === 0 && !hasClause ? \"side_effect\" : \"static\",\n });\n }\n\n private extractSpecifiers(node: Parser.SyntaxNode): string[] {\n const specifiers: string[] = [];\n\n for (let i = 0; i < node.childCount; i++) {\n const child = node.child(i)!;\n\n if (child.type === \"import_clause\") {\n for (let j = 0; j < child.childCount; j++) {\n const clause = child.child(j)!;\n if (clause.type === \"identifier\") {\n specifiers.push(clause.text);\n } else if (clause.type === \"named_imports\") {\n this.extractNamedImports(clause, specifiers);\n } else if (clause.type === \"namespace_import\") {\n const name = clause.children.find((c) => c.type === \"identifier\");\n if (name) specifiers.push(\"* as \" + name.text);\n }\n }\n } else if (child.type === \"named_imports\") {\n this.extractNamedImports(child, specifiers);\n } else if (child.type === \"export_clause\") {\n for (let j = 0; j < child.childCount; j++) {\n const spec = child.child(j)!;\n if (spec.type === \"export_specifier\") {\n const name = spec.childForFieldName(\"name\");\n if (name) specifiers.push(name.text);\n }\n }\n }\n }\n\n return specifiers;\n }\n\n private extractNamedImports(node: Parser.SyntaxNode, specifiers: string[]): void {\n for (let i = 0; i < node.childCount; i++) {\n const child = node.child(i)!;\n if (child.type === \"import_specifier\") {\n const name = child.childForFieldName(\"name\");\n if (name) specifiers.push(name.text);\n }\n }\n }\n\n private extractRequire(node: Parser.SyntaxNode, imports: ExtractedImport[]): void {\n // Look for require() calls in variable declarations\n for (let i = 0; i < node.childCount; i++) {\n const declarator = node.child(i)!;\n if (declarator.type !== \"variable_declarator\") continue;\n\n const value = declarator.childForFieldName(\"value\");\n if (!value || value.type !== \"call_expression\") continue;\n\n const fn = value.childForFieldName(\"function\");\n if (!fn || fn.text !== \"require\") continue;\n\n const args = value.childForFieldName(\"arguments\");\n if (!args) continue;\n\n const firstArg = args.children.find(\n (c) => c.type === \"string\" || c.type === \"template_string\",\n );\n if (!firstArg) continue;\n\n imports.push({\n source: stripQuotes(firstArg.text),\n specifiers: [],\n kind: \"require\",\n });\n }\n }\n\n private extractExpressionStatement(node: Parser.SyntaxNode, imports: ExtractedImport[]): void {\n const expr = node.children[0];\n if (!expr) return;\n\n if (expr.type === \"call_expression\") {\n const fn = expr.childForFieldName(\"function\");\n if (fn && fn.text === \"require\") {\n const args = expr.childForFieldName(\"arguments\");\n if (args) {\n const firstArg = args.children.find(\n (c) => c.type === \"string\" || c.type === \"template_string\",\n );\n if (firstArg) {\n imports.push({\n source: stripQuotes(firstArg.text),\n specifiers: [],\n kind: \"side_effect\",\n });\n }\n }\n }\n }\n }\n\n private extractDynamicImport(node: Parser.SyntaxNode, imports: ExtractedImport[]): void {\n // import(\"module\")\n const fn = node.childForFieldName(\"function\");\n if (!fn) return;\n\n // In tree-sitter, dynamic import is a call_expression where function is \"import\"\n if (fn.type !== \"import\") return;\n\n const args = node.childForFieldName(\"arguments\");\n if (!args) return;\n\n const firstArg = args.children.find(\n (c) => c.type === \"string\" || c.type === \"template_string\",\n );\n if (!firstArg) return;\n\n imports.push({\n source: stripQuotes(firstArg.text),\n specifiers: [],\n kind: \"dynamic\",\n });\n }\n}\n\n/** Remove surrounding quotes from a string literal. */\nfunction stripQuotes(text: string): string {\n if (\n (text.startsWith('\"') && text.endsWith('\"')) ||\n (text.startsWith(\"'\") && text.endsWith(\"'\")) ||\n (text.startsWith(\"`\") && text.endsWith(\"`\"))\n ) {\n return text.slice(1, -1);\n }\n return text;\n}\n","/**\n * Python import extractor.\n *\n * Handles:\n * - import module\n * - import module as alias\n * - from module import name\n * - from .relative import name\n * - from ..parent import name\n */\n\nimport type Parser from \"web-tree-sitter\";\nimport type { ImportExtractor, ExtractedImport } from \"./types.js\";\n\nexport class PythonImportExtractor implements ImportExtractor {\n /** Extract all imports from a Python AST. */\n extract(tree: Parser.Tree): ExtractedImport[] {\n const imports: ExtractedImport[] = [];\n this.visit(tree.rootNode, imports);\n return imports;\n }\n\n private visit(node: Parser.SyntaxNode, imports: ExtractedImport[]): void {\n switch (node.type) {\n case \"import_statement\": {\n this.extractImport(node, imports);\n break;\n }\n case \"import_from_statement\": {\n this.extractFromImport(node, imports);\n break;\n }\n }\n\n for (let i = 0; i < node.childCount; i++) {\n this.visit(node.child(i)!, imports);\n }\n }\n\n private extractImport(node: Parser.SyntaxNode, imports: ExtractedImport[]): void {\n // import module, import module as alias, import a, b\n for (let i = 0; i < node.childCount; i++) {\n const child = node.child(i)!;\n if (child.type === \"dotted_name\") {\n imports.push({\n source: child.text,\n specifiers: [],\n kind: \"static\",\n });\n } else if (child.type === \"aliased_import\") {\n const name = child.childForFieldName(\"name\");\n if (name) {\n imports.push({\n source: name.text,\n specifiers: [],\n kind: \"static\",\n });\n }\n }\n }\n }\n\n private extractFromImport(node: Parser.SyntaxNode, imports: ExtractedImport[]): void {\n // from <module> import <names>\n const moduleName = node.childForFieldName(\"module_name\");\n const source = moduleName ? moduleName.text : \"\";\n\n // Count leading dots for relative imports\n let dots = \"\";\n for (let i = 0; i < node.childCount; i++) {\n const child = node.child(i)!;\n if (child.type === \"relative_import\") {\n // The relative_import node contains dots and optionally a dotted_name\n const dotText = child.children\n .filter((c) => c.type === \"import_prefix\" || c.type === \".\")\n .map((c) => c.text)\n .join(\"\");\n const dottedName = child.children.find((c) => c.type === \"dotted_name\");\n dots = dotText;\n if (dottedName) {\n imports.push({\n source: dots + dottedName.text,\n specifiers: this.extractSpecifiers(node),\n kind: \"static\",\n });\n return;\n }\n }\n }\n\n // Build the full source with dots prefix\n const fullSource = dots ? dots + source : source;\n\n imports.push({\n source: fullSource,\n specifiers: this.extractSpecifiers(node),\n kind: \"static\",\n });\n }\n\n private extractSpecifiers(node: Parser.SyntaxNode): string[] {\n const specifiers: string[] = [];\n for (let i = 0; i < node.childCount; i++) {\n const child = node.child(i)!;\n if (child.type === \"dotted_name\") {\n // Skip the module name (first dotted_name after \"from\")\n // Specifiers come after \"import\"\n const prevSibling = child.previousSibling;\n if (prevSibling && (prevSibling.type === \"import\" || prevSibling.text === \",\")) {\n specifiers.push(child.text);\n }\n } else if (child.type === \"aliased_import\") {\n const name = child.childForFieldName(\"name\");\n if (name) specifiers.push(name.text);\n } else if (child.type === \"wildcard_import\") {\n specifiers.push(\"*\");\n }\n }\n return specifiers;\n }\n}\n","/**\n * Java import extractor.\n *\n * Handles:\n * - import com.example.auth.UserService;\n * - import com.example.auth.*;\n * - import static com.example.Utils.method;\n */\n\nimport type Parser from \"web-tree-sitter\";\nimport type { ImportExtractor, ExtractedImport } from \"./types.js\";\n\nexport class JavaImportExtractor implements ImportExtractor {\n /** Extract all imports from a Java AST. */\n extract(tree: Parser.Tree): ExtractedImport[] {\n const imports: ExtractedImport[] = [];\n this.visit(tree.rootNode, imports);\n return imports;\n }\n\n private visit(node: Parser.SyntaxNode, imports: ExtractedImport[]): void {\n if (node.type === \"import_declaration\") {\n this.extractImportDeclaration(node, imports);\n }\n\n for (let i = 0; i < node.childCount; i++) {\n this.visit(node.child(i)!, imports);\n }\n }\n\n private extractImportDeclaration(node: Parser.SyntaxNode, imports: ExtractedImport[]): void {\n // The full import text: \"import com.example.auth.UserService;\"\n // or \"import static com.example.Utils.method;\"\n // We need to extract the scoped identifier\n let source = \"\";\n\n for (let i = 0; i < node.childCount; i++) {\n const child = node.child(i)!;\n if (child.type === \"scoped_identifier\" || child.type === \"identifier\") {\n source = child.text;\n } else if (child.type === \"asterisk\") {\n // import com.example.*; — the scoped_identifier is before the asterisk\n // source should already be set from scoped_identifier\n source = source ? source + \".*\" : \"*\";\n }\n }\n\n if (!source) return;\n\n // Check if it's a wildcard import\n const isWildcard = source.endsWith(\".*\");\n const specifiers = isWildcard ? [\"*\"] : [source.split(\".\").pop()!];\n\n imports.push({\n source,\n specifiers,\n kind: \"static\",\n });\n }\n}\n","/**\n * Import extractor registry — maps grammar names to import extractors.\n */\n\nimport type { ImportExtractor } from \"./types.js\";\nimport { TypeScriptImportExtractor } from \"./typescript.js\";\nimport { PythonImportExtractor } from \"./python.js\";\nimport { JavaImportExtractor } from \"./java.js\";\n\nconst extractors: Record<string, ImportExtractor> = {\n typescript: new TypeScriptImportExtractor(),\n javascript: new TypeScriptImportExtractor(),\n python: new PythonImportExtractor(),\n java: new JavaImportExtractor(),\n};\n\n/**\n * Get the import extractor for a grammar name.\n * Returns null if no extractor exists for the grammar.\n */\nexport function getImportExtractor(grammarName: string): ImportExtractor | null {\n return extractors[grammarName] ?? null;\n}\n","/**\n * Path resolver — resolves raw import paths to project-relative file paths.\n *\n * Handles TS/JS relative imports, Python relative/absolute imports,\n * and Java fully-qualified class imports via a package→file index.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\n// ---------------------------------------------------------------------------\n// TS/JS Resolution\n// ---------------------------------------------------------------------------\n\n/** Extensions to try when resolving TS/JS imports. */\nconst TS_EXTENSIONS = [\".ts\", \".tsx\", \".js\", \".jsx\", \".mjs\", \".cjs\"];\n\n/** Index files to try when an import resolves to a directory. */\nconst INDEX_FILES = TS_EXTENSIONS.map((ext) => \"index\" + ext);\n\n/**\n * Resolve a TS/JS import source relative to the importing file.\n *\n * @returns Project-relative path or null if unresolvable/external.\n */\nexport function resolveTypeScriptImport(\n importSource: string,\n importerRelPath: string,\n projectRoot: string,\n pathAliases?: Record<string, string>,\n): string | null {\n // Skip external/bare imports (no . prefix and no alias match)\n if (!importSource.startsWith(\".\")) {\n // Try path aliases\n if (pathAliases) {\n const resolved = resolveAlias(importSource, pathAliases, projectRoot);\n if (resolved) return resolved;\n }\n return null;\n }\n\n const importerDir = path.dirname(path.join(projectRoot, importerRelPath));\n const resolved = path.resolve(importerDir, importSource);\n\n return tryResolveFile(resolved, projectRoot);\n}\n\n/**\n * Try to resolve a path alias (e.g. @/utils → src/utils).\n */\nfunction resolveAlias(\n importSource: string,\n aliases: Record<string, string>,\n projectRoot: string,\n): string | null {\n for (const [prefix, replacement] of Object.entries(aliases)) {\n // Exact match or prefix with /\n const aliasPrefix = prefix.endsWith(\"/*\") ? prefix.slice(0, -2) : prefix;\n if (importSource === aliasPrefix || importSource.startsWith(aliasPrefix + \"/\")) {\n const rest = importSource.slice(aliasPrefix.length);\n const targetBase = replacement.endsWith(\"/*\") ? replacement.slice(0, -2) : replacement;\n const resolved = path.resolve(projectRoot, targetBase + rest);\n return tryResolveFile(resolved, projectRoot);\n }\n }\n return null;\n}\n\n/**\n * Try to resolve a path to an actual file, with extension and index resolution.\n */\nfunction tryResolveFile(resolved: string, projectRoot: string): string | null {\n // Direct match (already has extension)\n if (hasSourceExtension(resolved) && fs.existsSync(resolved)) {\n return path.relative(projectRoot, resolved);\n }\n\n // Try adding extensions\n for (const ext of TS_EXTENSIONS) {\n const withExt = resolved + ext;\n if (fs.existsSync(withExt)) {\n return path.relative(projectRoot, withExt);\n }\n }\n\n // Try as directory with index file\n for (const indexFile of INDEX_FILES) {\n const withIndex = path.join(resolved, indexFile);\n if (fs.existsSync(withIndex)) {\n return path.relative(projectRoot, withIndex);\n }\n }\n\n return null;\n}\n\nfunction hasSourceExtension(filePath: string): boolean {\n return TS_EXTENSIONS.some((ext) => filePath.endsWith(ext));\n}\n\n// ---------------------------------------------------------------------------\n// Python Resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve a Python import source relative to the importing file.\n *\n * @returns Project-relative path or null if unresolvable/external.\n */\nexport function resolvePythonImport(\n importSource: string,\n importerRelPath: string,\n projectRoot: string,\n pythonPackageIndex?: PythonPackageIndex,\n): string | null {\n // Count leading dots for relative imports\n let dotCount = 0;\n while (dotCount < importSource.length && importSource[dotCount] === \".\") {\n dotCount++;\n }\n\n if (dotCount > 0) {\n // Relative import\n const modulePath = importSource.slice(dotCount).replace(/\\./g, \"/\");\n const importerDir = path.dirname(path.join(projectRoot, importerRelPath));\n\n // In Python: 1 dot = current package (importer's dir),\n // 2 dots = parent package, etc. Each additional dot goes one level higher.\n // So from app/sub/main.py: `.` = app/sub/, `..` = app/, `...` = root\n let baseDir = importerDir;\n for (let i = 1; i < dotCount; i++) {\n baseDir = path.dirname(baseDir);\n }\n\n return resolvePythonModule(baseDir, modulePath, projectRoot);\n }\n\n // Absolute import — check if first segment is a local directory\n const segments = importSource.split(\".\");\n const firstSegment = segments[0];\n const localDir = path.join(projectRoot, firstSegment);\n\n if (fs.existsSync(localDir) && fs.statSync(localDir).isDirectory()) {\n const modulePath = segments.join(\"/\");\n return resolvePythonModule(projectRoot, modulePath, projectRoot);\n }\n\n // Not found at root — use package index for monorepo/src layouts\n if (pythonPackageIndex) {\n const packageRoot = pythonPackageIndex.get(firstSegment);\n if (packageRoot) {\n const modulePath = segments.join(\"/\");\n return resolvePythonModule(packageRoot, modulePath, projectRoot);\n }\n }\n\n return null;\n}\n\n/**\n * Resolve a Python module path to a file.\n */\nfunction resolvePythonModule(\n baseDir: string,\n modulePath: string,\n projectRoot: string,\n): string | null {\n if (!modulePath) {\n // from . import X — refers to __init__.py in current package\n const initPath = path.join(baseDir, \"__init__.py\");\n if (fs.existsSync(initPath)) {\n return path.relative(projectRoot, initPath);\n }\n return null;\n }\n\n const full = path.resolve(baseDir, modulePath);\n\n // Try as .py file\n const pyFile = full + \".py\";\n if (fs.existsSync(pyFile)) {\n return path.relative(projectRoot, pyFile);\n }\n\n // Try as package (__init__.py)\n const initFile = path.join(full, \"__init__.py\");\n if (fs.existsSync(initFile)) {\n return path.relative(projectRoot, initFile);\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Python package index\n// ---------------------------------------------------------------------------\n\n/**\n * Index mapping top-level Python package name to its parent directory.\n *\n * Built by scanning the project for all `__init__.py` files and recording\n * the root package (topmost directory containing `__init__.py` in a chain).\n * This is analogous to `JavaPackageIndex` but maps package name → resolution base.\n */\nexport type PythonPackageIndex = Map<string, string>;\n\n/** Directories to skip when scanning for Python packages. */\nconst PYTHON_SKIP_DIRS = new Set([\n \"node_modules\", \"dist\", \"build\", \"__pycache__\",\n \".venv\", \"venv\", \".git\", \".tox\", \".mypy_cache\",\n \".pytest_cache\", \"target\", \".next\",\n]);\n\n/**\n * Build an index of top-level Python packages found anywhere in the project.\n *\n * For each `__init__.py`, walks up to find the root package (the topmost\n * directory in a contiguous chain of `__init__.py` files), then records\n * `packageName → parentDir` so that absolute imports like\n * `from mylib.config import X` can be resolved.\n */\nexport function buildPythonPackageIndex(projectRoot: string): PythonPackageIndex {\n const index: PythonPackageIndex = new Map();\n scanForInitFiles(projectRoot, projectRoot, index);\n return index;\n}\n\nfunction scanForInitFiles(\n dir: string,\n projectRoot: string,\n index: PythonPackageIndex,\n): void {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (!entry.isDirectory() || entry.name.startsWith(\".\")) continue;\n if (PYTHON_SKIP_DIRS.has(entry.name)) continue;\n\n const childDir = path.join(dir, entry.name);\n const initPath = path.join(childDir, \"__init__.py\");\n\n if (fs.existsSync(initPath)) {\n // Found a package — walk up to find the root package\n const rootPackageDir = findRootPackage(childDir);\n const rootPackageName = path.basename(rootPackageDir);\n\n // Only record if not already indexed (first match wins — breadth-first)\n if (!index.has(rootPackageName)) {\n index.set(rootPackageName, path.dirname(rootPackageDir));\n }\n }\n\n // Continue scanning deeper (packages can be nested in non-package dirs like src/)\n scanForInitFiles(childDir, projectRoot, index);\n }\n}\n\n/**\n * Walk up from a package directory to find the topmost directory\n * in a contiguous chain of `__init__.py` files.\n *\n * e.g. for `sub/src/mylib/models/`, if `mylib/` and `models/` both have\n * `__init__.py` but `src/` does not, returns `sub/src/mylib/`.\n */\nfunction findRootPackage(packageDir: string): string {\n let current = packageDir;\n while (true) {\n const parent = path.dirname(current);\n const parentInit = path.join(parent, \"__init__.py\");\n if (fs.existsSync(parentInit)) {\n current = parent;\n } else {\n return current;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Java Resolution\n// ---------------------------------------------------------------------------\n\n/** Index mapping fully-qualified class name to project-relative path. */\nexport type JavaPackageIndex = Map<string, string>;\n\n/**\n * Build a package→file index by scanning all .java files and extracting package declarations.\n */\nexport function buildJavaPackageIndex(projectRoot: string): JavaPackageIndex {\n const index: JavaPackageIndex = new Map();\n scanJavaFiles(projectRoot, projectRoot, index);\n return index;\n}\n\nfunction scanJavaFiles(\n dirPath: string,\n projectRoot: string,\n index: JavaPackageIndex,\n): void {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dirPath, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n const fullPath = path.join(dirPath, entry.name);\n\n if (entry.isDirectory()) {\n // Skip common non-source dirs\n if (\n entry.name === \"node_modules\" ||\n entry.name === \".git\" ||\n entry.name === \"target\" ||\n entry.name === \"build\" ||\n entry.name === \"dist\"\n ) {\n continue;\n }\n scanJavaFiles(fullPath, projectRoot, index);\n } else if (entry.isFile() && entry.name.endsWith(\".java\")) {\n const relativePath = path.relative(projectRoot, fullPath);\n const packageName = readJavaPackage(fullPath);\n const className = entry.name.replace(\".java\", \"\");\n const fqcn = packageName ? `${packageName}.${className}` : className;\n index.set(fqcn, relativePath);\n }\n }\n}\n\n/**\n * Read the package declaration from a Java file.\n * Only reads the first few lines for performance.\n */\nfunction readJavaPackage(filePath: string): string | null {\n let content: string;\n try {\n // Read only the first 2KB — package declaration is always near the top\n const buf = Buffer.alloc(2048);\n const fd = fs.openSync(filePath, \"r\");\n const bytesRead = fs.readSync(fd, buf, 0, 2048, 0);\n fs.closeSync(fd);\n content = buf.toString(\"utf-8\", 0, bytesRead);\n } catch {\n return null;\n }\n\n const match = content.match(/^\\s*package\\s+([\\w.]+)\\s*;/m);\n return match ? match[1] : null;\n}\n\n/**\n * Resolve a Java import to a project-relative file path using the package index.\n *\n * For named imports, returns a single path (or null if external).\n * For wildcard imports (`com.example.*`), returns an array of all matching\n * files in the package (or null if none match).\n *\n * @returns Project-relative path(s) or null if the class is external.\n */\nexport function resolveJavaImport(\n importSource: string,\n packageIndex: JavaPackageIndex,\n): string | string[] | null {\n // Wildcard import: com.example.* — resolve to all direct classes in the package\n if (importSource.endsWith(\".*\")) {\n const packagePrefix = importSource.slice(0, -2); // strip \".*\"\n const prefixWithDot = packagePrefix + \".\";\n const matches: string[] = [];\n for (const [fqcn, filePath] of packageIndex) {\n // Match only direct children — no additional dots after the prefix\n if (fqcn.startsWith(prefixWithDot) && !fqcn.slice(prefixWithDot.length).includes(\".\")) {\n matches.push(filePath);\n }\n }\n return matches.length > 0 ? matches : null;\n }\n\n // Direct lookup (fully-qualified class name)\n const direct = packageIndex.get(importSource);\n if (direct) return direct;\n\n return null;\n}\n","/**\n * Health runner service — executes detected linters/type-checkers and returns structured results.\n *\n * Only runs tools that are already configured in the project.\n * Never installs tools. Each tool has a configurable timeout.\n */\n\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type { DetectedTools, HealthResult, HealthIssue, HealthToolResult } from \"../../types/index.js\";\nimport { parsers, type ToolOutputParser } from \"./parsers.js\";\n\nconst execFileAsync = promisify(execFile);\n\n/** A configured tool runner. */\ninterface ToolRunner {\n /** Tool name (matches DetectedTools key value). */\n name: string;\n /** Command to execute. */\n command: string;\n /** Arguments to pass. */\n args: string[];\n /** Output parser for this tool. */\n parser: ToolOutputParser;\n}\n\n/** Build the list of tool runners based on detected tools. */\nfunction buildRunners(detectedTools: DetectedTools): ToolRunner[] {\n const runners: ToolRunner[] = [];\n\n if (detectedTools.linter) {\n const parser = parsers[detectedTools.linter];\n if (parser) {\n runners.push(getRunnerConfig(detectedTools.linter, parser));\n }\n }\n\n if (detectedTools.type_checker) {\n const parser = parsers[detectedTools.type_checker];\n if (parser) {\n runners.push(getRunnerConfig(detectedTools.type_checker, parser));\n }\n }\n\n return runners;\n}\n\n/** Get the command configuration for a tool. */\nfunction getRunnerConfig(tool: string, parser: ToolOutputParser): ToolRunner {\n switch (tool) {\n case \"eslint\":\n return { name: \"eslint\", command: \"npx\", args: [\"eslint\", \".\", \"--format\", \"json\"], parser };\n case \"tsc\":\n return { name: \"tsc\", command: \"npx\", args: [\"tsc\", \"--noEmit\", \"--pretty\", \"false\"], parser };\n case \"mypy\":\n return { name: \"mypy\", command: \"mypy\", args: [\".\", \"--no-error-summary\", \"--output\", \"json\"], parser };\n case \"ruff\":\n return { name: \"ruff\", command: \"ruff\", args: [\"check\", \".\", \"--output-format\", \"json\"], parser };\n case \"clippy\":\n return { name: \"clippy\", command: \"cargo\", args: [\"clippy\", \"--message-format\", \"json\"], parser };\n default:\n return { name: tool, command: tool, args: [], parser };\n }\n}\n\n/**\n * Run all detected health tools and return structured results.\n *\n * @param projectRoot Absolute path to the project root.\n * @param detectedTools Tools detected during project scanning.\n * @param timeoutMs Timeout per tool in milliseconds.\n */\nexport async function runHealthChecks(\n projectRoot: string,\n detectedTools: DetectedTools,\n timeoutMs: number,\n): Promise<HealthResult> {\n const overallStart = Date.now();\n const runners = buildRunners(detectedTools);\n\n const toolResults: HealthToolResult[] = [];\n const allIssues: HealthIssue[] = [];\n\n // Run tools sequentially to avoid resource contention\n for (const runner of runners) {\n const result = await runTool(runner, projectRoot, timeoutMs);\n toolResults.push(result.toolResult);\n allIssues.push(...result.issues);\n }\n\n const totalErrors = allIssues.filter((i) => i.severity === \"error\").length;\n const totalWarnings = allIssues.filter((i) => i.severity === \"warning\").length;\n\n return {\n tools_run: toolResults,\n total_errors: totalErrors,\n total_warnings: totalWarnings,\n issues: allIssues,\n run_duration_ms: Date.now() - overallStart,\n };\n}\n\n/** Run a single tool and parse its output. */\nasync function runTool(\n runner: ToolRunner,\n projectRoot: string,\n timeoutMs: number,\n): Promise<{ toolResult: HealthToolResult; issues: HealthIssue[] }> {\n const start = Date.now();\n\n try {\n const { stdout, stderr } = await execFileAsync(runner.command, runner.args, {\n cwd: projectRoot,\n timeout: timeoutMs,\n maxBuffer: 10 * 1024 * 1024, // 10MB\n env: { ...process.env, FORCE_COLOR: \"0\", NO_COLOR: \"1\" },\n });\n\n const issues = runner.parser(stdout || stderr, runner.name);\n const errorCount = issues.filter((i) => i.severity === \"error\").length;\n const warningCount = issues.filter((i) => i.severity === \"warning\").length;\n\n return {\n toolResult: {\n tool: runner.name,\n success: true,\n run_duration_ms: Date.now() - start,\n error_count: errorCount,\n warning_count: warningCount,\n error_message: null,\n },\n issues,\n };\n } catch (err: unknown) {\n const duration = Date.now() - start;\n\n // Many tools exit non-zero when they find issues — that's expected\n if (isExecError(err) && err.stdout) {\n const issues = runner.parser(err.stdout, runner.name);\n const errorCount = issues.filter((i) => i.severity === \"error\").length;\n const warningCount = issues.filter((i) => i.severity === \"warning\").length;\n\n return {\n toolResult: {\n tool: runner.name,\n success: true,\n run_duration_ms: duration,\n error_count: errorCount,\n warning_count: warningCount,\n error_message: null,\n },\n issues,\n };\n }\n\n // Actual failure (tool not found, timeout, etc.)\n const message = err instanceof Error ? err.message : String(err);\n const isTimeout = message.includes(\"TIMEOUT\") || message.includes(\"timed out\");\n\n return {\n toolResult: {\n tool: runner.name,\n success: false,\n run_duration_ms: duration,\n error_count: 0,\n warning_count: 0,\n error_message: isTimeout ? `Timed out after ${timeoutMs}ms` : message,\n },\n issues: [],\n };\n }\n}\n\n/** Type guard for exec errors that have stdout/stderr. */\nfunction isExecError(err: unknown): err is Error & { stdout: string; stderr: string } {\n return err instanceof Error && \"stdout\" in err;\n}\n","/**\n * Output parsers for health check tools.\n *\n * Each parser takes raw stdout from a tool and returns structured health issues.\n */\n\nimport type { HealthIssue, HealthIssueSeverity } from \"../../types/index.js\";\n\n/** A function that parses tool output into structured issues. */\nexport type ToolOutputParser = (output: string, toolName: string) => HealthIssue[];\n\n/** Registry of output parsers keyed by tool name. */\nexport const parsers: Record<string, ToolOutputParser> = {\n eslint: parseEslintOutput,\n tsc: parseTscOutput,\n mypy: parseMypyOutput,\n ruff: parseRuffOutput,\n clippy: parseClippyOutput,\n};\n\n// ---------------------------------------------------------------------------\n// ESLint: --format json\n// ---------------------------------------------------------------------------\n\ninterface EslintFileResult {\n filePath: string;\n messages: Array<{\n line: number;\n column: number;\n severity: 1 | 2;\n ruleId: string | null;\n message: string;\n }>;\n}\n\n/** Parse ESLint JSON output. */\nfunction parseEslintOutput(output: string, toolName: string): HealthIssue[] {\n const issues: HealthIssue[] = [];\n\n let results: EslintFileResult[];\n try {\n results = JSON.parse(output);\n } catch {\n return issues;\n }\n\n if (!Array.isArray(results)) return issues;\n\n for (const file of results) {\n for (const msg of file.messages) {\n issues.push({\n file: file.filePath,\n line: msg.line ?? null,\n column: msg.column ?? null,\n severity: msg.severity === 2 ? \"error\" : \"warning\",\n code: msg.ruleId ?? null,\n message: msg.message,\n tool: toolName,\n });\n }\n }\n\n return issues;\n}\n\n// ---------------------------------------------------------------------------\n// TypeScript: tsc --noEmit --pretty false\n// ---------------------------------------------------------------------------\n\n/**\n * Parse tsc plain-text output.\n * Format: `file(line,col): error TSxxxx: message`\n */\nfunction parseTscOutput(output: string, toolName: string): HealthIssue[] {\n const issues: HealthIssue[] = [];\n const lineRegex = /^(.+?)\\((\\d+),(\\d+)\\):\\s+(error|warning)\\s+(TS\\d+):\\s+(.+)$/;\n\n for (const line of output.split(\"\\n\")) {\n const match = line.match(lineRegex);\n if (match) {\n issues.push({\n file: match[1],\n line: parseInt(match[2], 10),\n column: parseInt(match[3], 10),\n severity: match[4] as HealthIssueSeverity,\n code: match[5],\n message: match[6],\n tool: toolName,\n });\n }\n }\n\n return issues;\n}\n\n// ---------------------------------------------------------------------------\n// mypy: --output json\n// ---------------------------------------------------------------------------\n\ninterface MypyJsonLine {\n file: string;\n line: number;\n column: number;\n severity: string;\n code: string;\n message: string;\n}\n\n/** Parse mypy JSON output (one JSON object per line). */\nfunction parseMypyOutput(output: string, toolName: string): HealthIssue[] {\n const issues: HealthIssue[] = [];\n\n for (const line of output.split(\"\\n\")) {\n if (!line.trim()) continue;\n\n let entry: MypyJsonLine;\n try {\n entry = JSON.parse(line);\n } catch {\n // mypy may also output plain text — try the plain format\n const parsed = parseMypyPlainLine(line, toolName);\n if (parsed) issues.push(parsed);\n continue;\n }\n\n issues.push({\n file: entry.file,\n line: entry.line ?? null,\n column: entry.column ?? null,\n severity: mapMypySeverity(entry.severity),\n code: entry.code ?? null,\n message: entry.message,\n tool: toolName,\n });\n }\n\n return issues;\n}\n\n/** Parse a mypy plain-text error line: `file:line: severity: message [code]` */\nfunction parseMypyPlainLine(line: string, toolName: string): HealthIssue | null {\n const match = line.match(/^(.+?):(\\d+):\\s+(error|warning|note):\\s+(.+?)(?:\\s+\\[(.+?)\\])?$/);\n if (!match) return null;\n\n return {\n file: match[1],\n line: parseInt(match[2], 10),\n column: null,\n severity: mapMypySeverity(match[3]),\n code: match[5] ?? null,\n message: match[4],\n tool: toolName,\n };\n}\n\nfunction mapMypySeverity(severity: string): HealthIssueSeverity {\n if (severity === \"error\") return \"error\";\n if (severity === \"warning\") return \"warning\";\n return \"info\";\n}\n\n// ---------------------------------------------------------------------------\n// Ruff: --output-format json\n// ---------------------------------------------------------------------------\n\ninterface RuffJsonEntry {\n filename: string;\n location: { row: number; column: number };\n code: string;\n message: string;\n}\n\n/** Parse Ruff JSON output. */\nfunction parseRuffOutput(output: string, toolName: string): HealthIssue[] {\n const issues: HealthIssue[] = [];\n\n let entries: RuffJsonEntry[];\n try {\n entries = JSON.parse(output);\n } catch {\n return issues;\n }\n\n if (!Array.isArray(entries)) return issues;\n\n for (const entry of entries) {\n issues.push({\n file: entry.filename,\n line: entry.location?.row ?? null,\n column: entry.location?.column ?? null,\n severity: \"warning\",\n code: entry.code ?? null,\n message: entry.message,\n tool: toolName,\n });\n }\n\n return issues;\n}\n\n// ---------------------------------------------------------------------------\n// Clippy: cargo clippy --message-format json\n// ---------------------------------------------------------------------------\n\ninterface CargoMessage {\n reason?: string;\n message?: {\n level: string;\n code?: { code: string } | null;\n message: string;\n spans: Array<{\n file_name: string;\n line_start: number;\n column_start: number;\n }>;\n };\n}\n\n/** Parse Clippy JSON output (one JSON object per line). */\nfunction parseClippyOutput(output: string, toolName: string): HealthIssue[] {\n const issues: HealthIssue[] = [];\n\n for (const line of output.split(\"\\n\")) {\n if (!line.trim()) continue;\n\n let entry: CargoMessage;\n try {\n entry = JSON.parse(line);\n } catch {\n continue;\n }\n\n if (entry.reason !== \"compiler-message\" || !entry.message) continue;\n\n const msg = entry.message;\n const span = msg.spans[0];\n\n if (msg.level === \"error\" || msg.level === \"warning\") {\n issues.push({\n file: span?.file_name ?? \"\",\n line: span?.line_start ?? null,\n column: span?.column_start ?? null,\n severity: msg.level === \"error\" ? \"error\" : \"warning\",\n code: msg.code?.code ?? null,\n message: msg.message,\n tool: toolName,\n });\n }\n }\n\n return issues;\n}\n","/**\n * Scanner service — orchestrates project detection and file tree building.\n *\n * This is the main entry point for the `scan` command.\n * Supports three scan paths:\n * A) Cache hit — same HEAD, no uncommitted changes → return cached result\n * B) Incremental — HEAD moved or uncommitted changes, <50% files changed\n * C) Full scan — no cache or >50% files changed\n */\n\nimport type { ScanResult, CacheStatus, FileTreeEntry, FileEntry, Symbol, HealthResult, DependencyEntry } from \"../../types/index.js\";\nimport { loadConfig, type ResolvedConfig } from \"../../config/index.js\";\nimport { detectProject } from \"./project-detector.js\";\nimport { buildFileTree } from \"./file-tree-builder.js\";\nimport { getHead, getDiffNameStatus, getUncommittedChanges, type GitFileChange } from \"../git/index.js\";\nimport { readCache, readMeta, writeCache, isCacheValid } from \"../cache/index.js\";\nimport { buildSymbolIndex, updateSymbolIndex } from \"../parser/symbol-index.js\";\nimport { buildDependencyGraph, updateDependencyGraph } from \"../parser/dependency-graph.js\";\nimport { runHealthChecks } from \"../health/index.js\";\nimport { collectSourceFiles } from \"../parser/utils.js\";\n\n/** Threshold: if changed files exceed this fraction of total, do a full scan. */\nconst INCREMENTAL_THRESHOLD = 0.5;\n\n/** Prefix for the cache directory — changes here are not user changes. */\nconst CACHE_DIR_PREFIX = \".inspect/\";\n\n/** Filter out cache directory files from git change lists. */\nfunction filterCacheFiles(changes: GitFileChange[]): GitFileChange[] {\n return changes.filter((c) => !c.path.startsWith(CACHE_DIR_PREFIX));\n}\n\n/**\n * Config files that affect how source files are parsed or resolved.\n * If any of these change, a full scan is needed because the incremental\n * path only re-parses changed source files — it won't re-resolve existing\n * files against new config settings (path aliases, ignore rules, etc.).\n */\nconst CONFIG_FILES_AFFECTING_PARSE = new Set([\n \"tsconfig.json\",\n \"inspect.config.json\",\n \".inspect/config.json\",\n]);\n\n/** Check whether any changed path is a config file that affects parsing. */\nfunction hasConfigChange(changedPaths: Iterable<string>): boolean {\n for (const p of changedPaths) {\n if (CONFIG_FILES_AFFECTING_PARSE.has(p)) return true;\n }\n return false;\n}\n\n/**\n * Run a scan of the project at the given path.\n *\n * Uses cached results when possible, incrementally updates when efficient,\n * and falls back to a full scan otherwise.\n *\n * @param projectRoot Absolute path to the project root.\n * @param includeHealth When true, run detected linters/type-checkers.\n */\nexport async function scan(projectRoot: string, includeHealth = false): Promise<ScanResult> {\n const startTime = Date.now();\n const config = loadConfig(projectRoot);\n const gitHead = await getHead(projectRoot);\n\n // Try Path A: Cache hit\n // Only use cached result when health state matches the caller's request:\n // if health is requested the cache must have it, if not requested the cache must lack it.\n const cachedResult = readCache(projectRoot);\n const healthMatches = cachedResult\n ? includeHealth ? cachedResult.health !== null : cachedResult.health === null\n : false;\n if (cachedResult && healthMatches && isCacheValid(projectRoot, gitHead)) {\n const uncommitted = filterCacheFiles(await getUncommittedChanges(projectRoot));\n if (uncommitted.length === 0) {\n return {\n ...cachedResult,\n cache: {\n status: \"cache_hit\",\n git_head: gitHead,\n scanned_at: new Date().toISOString(),\n scan_duration_ms: Date.now() - startTime,\n },\n };\n }\n }\n\n // Try Path B: Incremental update\n if (cachedResult) {\n const meta = readMeta(projectRoot);\n const cachedHead = meta?.git_head ?? null;\n\n // Collect all changed files (committed since cached HEAD + uncommitted)\n const changedFileMap = new Map<string, string>();\n\n if (cachedHead && cachedHead !== gitHead) {\n const committed = filterCacheFiles(await getDiffNameStatus(projectRoot, cachedHead));\n for (const entry of committed) {\n changedFileMap.set(entry.path, entry.status);\n }\n }\n\n const uncommitted = filterCacheFiles(await getUncommittedChanges(projectRoot));\n for (const entry of uncommitted) {\n changedFileMap.set(entry.path, entry.status);\n }\n\n // Config file changes invalidate all cached symbols/deps — full scan required\n if (hasConfigChange(changedFileMap.keys())) {\n return fullScan(projectRoot, config, gitHead, includeHealth, startTime);\n }\n\n // Check threshold — use max of current and cached file counts to avoid\n // edge cases where deleting files inflates the ratio\n const sourceFiles = collectSourceFiles(projectRoot, config);\n const cachedFileCount = Object.keys(cachedResult.symbols ?? {}).length;\n const totalFiles = Math.max(sourceFiles.length, cachedFileCount);\n const changedCount = changedFileMap.size;\n\n if (totalFiles > 0 && changedCount / totalFiles <= INCREMENTAL_THRESHOLD) {\n const result = await incrementalScan(\n projectRoot,\n config,\n cachedResult,\n changedFileMap,\n gitHead,\n includeHealth,\n startTime,\n );\n return result;\n }\n }\n\n // Path C: Full scan\n return fullScan(projectRoot, config, gitHead, includeHealth, startTime);\n}\n\n// ---------------------------------------------------------------------------\n// Scan path implementations\n// ---------------------------------------------------------------------------\n\n/**\n * Path B: Incrementally update cached results by re-parsing only changed files.\n */\nasync function incrementalScan(\n projectRoot: string,\n config: ResolvedConfig,\n cachedResult: ScanResult,\n changedFileMap: Map<string, string>,\n gitHead: string | null,\n includeHealth: boolean,\n startTime: number,\n): Promise<ScanResult> {\n const changedFiles: string[] = [];\n const deletedFiles: string[] = [];\n\n for (const [filePath, status] of changedFileMap) {\n if (status === \"D\") {\n deletedFiles.push(filePath);\n } else {\n changedFiles.push(filePath);\n }\n }\n\n const project = detectProject(projectRoot);\n const tree = buildFileTree(projectRoot, config);\n\n // Incrementally update symbols and dependencies in parallel\n const cachedSymbols = cachedResult.symbols ?? {};\n const cachedDeps = cachedResult.dependencies ?? {};\n\n const [symbols, dependencies] = await Promise.all([\n updateSymbolIndex(cachedSymbols, changedFiles, deletedFiles, projectRoot),\n updateDependencyGraph(cachedDeps, changedFiles, deletedFiles, projectRoot, config),\n ]);\n\n enrichTreeWithSymbolCounts(tree, symbols);\n\n let health: HealthResult | null = null;\n if (includeHealth) {\n health = await runHealthChecks(projectRoot, project.detected_tools, config.health_timeout_ms);\n }\n\n const cache: CacheStatus = {\n status: \"incremental_update\",\n git_head: gitHead,\n scanned_at: new Date().toISOString(),\n scan_duration_ms: Date.now() - startTime,\n files_rescanned: changedFiles.length + deletedFiles.length,\n };\n\n const result: ScanResult = {\n project,\n tree,\n symbols: Object.keys(symbols).length > 0 ? symbols : null,\n dependencies: Object.keys(dependencies).length > 0 ? dependencies : null,\n health,\n cache,\n };\n\n writeCache(projectRoot, result, gitHead);\n return result;\n}\n\n/**\n * Path C: Full scan — rebuild everything from scratch.\n */\nasync function fullScan(\n projectRoot: string,\n config: ResolvedConfig,\n gitHead: string | null,\n includeHealth: boolean,\n startTime: number,\n): Promise<ScanResult> {\n const project = detectProject(projectRoot);\n const tree = buildFileTree(projectRoot, config);\n\n const sourceFiles = collectSourceFiles(projectRoot, config);\n\n const [symbols, dependencies] = await Promise.all([\n buildSymbolIndex(projectRoot, config, sourceFiles),\n buildDependencyGraph(projectRoot, config, sourceFiles),\n ]);\n\n enrichTreeWithSymbolCounts(tree, symbols);\n\n let health: HealthResult | null = null;\n if (includeHealth) {\n health = await runHealthChecks(projectRoot, project.detected_tools, config.health_timeout_ms);\n }\n\n const cache: CacheStatus = {\n status: \"fresh\",\n git_head: gitHead,\n scanned_at: new Date().toISOString(),\n scan_duration_ms: Date.now() - startTime,\n };\n\n const result: ScanResult = {\n project,\n tree,\n symbols: Object.keys(symbols).length > 0 ? symbols : null,\n dependencies: Object.keys(dependencies).length > 0 ? dependencies : null,\n health,\n cache,\n };\n\n writeCache(projectRoot, result, gitHead);\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Walk the file tree and set the `symbols` count on each FileEntry\n * that has corresponding entries in the symbol index.\n */\nfunction enrichTreeWithSymbolCounts(\n tree: Record<string, FileTreeEntry>,\n symbols: Record<string, Symbol[]>,\n prefix = \"\",\n): void {\n for (const [key, value] of Object.entries(tree)) {\n if (isFileEntry(value)) {\n const filePath = prefix + key;\n const syms = symbols[filePath];\n if (syms) {\n value.symbols = syms.length;\n }\n } else if (isDirectoryEntry(value)) {\n enrichTreeWithSymbolCounts(\n value as Record<string, FileTreeEntry>,\n symbols,\n prefix + key,\n );\n }\n }\n}\n\nfunction isFileEntry(entry: FileTreeEntry): entry is FileEntry {\n return \"size\" in entry && !(\"_collapsed\" in entry);\n}\n\nfunction isDirectoryEntry(entry: FileTreeEntry): boolean {\n return !(\"size\" in entry) && !(\"_collapsed\" in entry);\n}\n","/**\n * Usage finder — searches dependent files for actual usages of a symbol.\n *\n * Uses tree-sitter to find identifier nodes that match the symbol name,\n * filtering out import statements to focus on actual usage sites.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type Parser from \"web-tree-sitter\";\nimport type { UsageSite } from \"../../types/index.js\";\nimport { parseSource } from \"../parser/index.js\";\n\n/**\n * Find all usage sites of a symbol within a file.\n *\n * @param symbolName The symbol name to search for.\n * @param filePath Project-relative path of the file to search.\n * @param projectRoot Absolute path to the project root.\n * @returns Array of usage sites (line number + context).\n */\nexport async function findUsageSites(\n symbolName: string,\n filePath: string,\n projectRoot: string,\n): Promise<UsageSite[]> {\n const absolutePath = path.join(projectRoot, filePath);\n let source: string;\n try {\n source = fs.readFileSync(absolutePath, \"utf-8\");\n } catch {\n return [];\n }\n\n const tree = await parseSource(filePath, source);\n if (!tree) return [];\n\n const lines = source.split(\"\\n\");\n const usages: UsageSite[] = [];\n\n findIdentifiers(tree.rootNode, symbolName, lines, usages);\n return usages;\n}\n\n/**\n * Recursively walk the AST looking for identifier nodes matching the symbol name.\n * Skip identifiers that are part of import statements.\n */\nfunction findIdentifiers(\n node: Parser.SyntaxNode,\n symbolName: string,\n lines: string[],\n usages: UsageSite[],\n): void {\n // Skip import-related nodes\n if (isImportNode(node)) return;\n\n if (\n (node.type === \"identifier\" || node.type === \"type_identifier\" || node.type === \"property_identifier\") &&\n node.text === symbolName\n ) {\n const line = node.startPosition.row + 1; // 1-indexed\n const context = lines[node.startPosition.row]?.trim() ?? \"\";\n\n // Avoid duplicate lines (e.g. multiple references on same line)\n if (!usages.some((u) => u.line === line)) {\n usages.push({ line, context });\n }\n }\n\n for (let i = 0; i < node.childCount; i++) {\n findIdentifiers(node.child(i)!, symbolName, lines, usages);\n }\n}\n\n/**\n * Check if a node is an import statement (should be skipped for usage finding).\n */\nfunction isImportNode(node: Parser.SyntaxNode): boolean {\n return (\n node.type === \"import_statement\" ||\n node.type === \"import_from_statement\" ||\n node.type === \"import_declaration\" ||\n (node.type === \"export_statement\" && node.children.some((c) => c.type === \"string\"))\n );\n}\n","/**\n * Test file association — finds test files for a given source file.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { DependencyEntry } from \"../../types/index.js\";\n\n/** Common test file suffixes/patterns. */\nconst TEST_SUFFIXES = [\".test\", \".spec\", \"_test\", \"_spec\"];\n\n/** Common test directory names. */\nconst TEST_DIRS = [\"__tests__\", \"tests\", \"test\"];\n\n/**\n * Find test files associated with a source file.\n *\n * Uses two strategies:\n * 1. Co-located test files (e.g. foo.ts → foo.test.ts)\n * 2. Test directory mirrors (e.g. src/foo.ts → tests/foo.test.ts or __tests__/foo.test.ts)\n */\nexport function findTestFiles(sourceFile: string, allFiles: string[]): string[] {\n const results: string[] = [];\n const parsed = path.parse(sourceFile);\n const baseName = parsed.name; // e.g. \"utils\" from \"src/utils.ts\"\n const ext = parsed.ext; // e.g. \".ts\"\n\n for (const file of allFiles) {\n const fileParsed = path.parse(file);\n\n // Check if this file is a test file for our source\n for (const suffix of TEST_SUFFIXES) {\n if (fileParsed.name === baseName + suffix && fileParsed.ext === ext) {\n results.push(file);\n }\n }\n }\n\n return [...new Set(results)];\n}\n\n/**\n * Check if a test file imports the target file (directly or transitively).\n */\nexport function checkTestImportsTarget(\n testFile: string,\n targetFile: string,\n dependencies: Record<string, DependencyEntry>,\n): boolean {\n const entry = dependencies[testFile];\n if (!entry) return false;\n\n // Direct import\n if (entry.imports_from.includes(targetFile)) return true;\n\n // One level of transitivity\n for (const dep of entry.imports_from) {\n const depEntry = dependencies[dep];\n if (depEntry && depEntry.imports_from.includes(targetFile)) return true;\n }\n\n return false;\n}\n","/**\n * Impact analysis service.\n *\n * Analyzes the impact of changing a file or symbol by computing\n * direct and transitive dependents, usage sites, and test coverage.\n */\n\nimport type {\n ImpactResult,\n DependencyEntry,\n Symbol,\n DirectDependent,\n TransitiveDependent,\n TestCoverage,\n} from \"../../types/index.js\";\nimport type { ResolvedConfig } from \"../../config/index.js\";\nimport { loadConfig } from \"../../config/index.js\";\nimport { buildSymbolIndex } from \"../parser/symbol-index.js\";\nimport { buildDependencyGraph } from \"../parser/dependency-graph.js\";\nimport { findUsageSites } from \"./usage-finder.js\";\nimport { findTestFiles, checkTestImportsTarget } from \"../differ/test-association.js\";\nimport { collectSourceFiles } from \"../parser/utils.js\";\nimport * as path from \"node:path\";\n\n/** Maximum transitive depth to walk. */\nconst MAX_TRANSITIVE_DEPTH = 2;\n\n/**\n * Analyze the impact of changing a target file or symbol.\n *\n * @param projectRoot Absolute path to the project root.\n * @param target Target string in format \"file_path\" or \"file_path:symbol_name\".\n * @returns Impact analysis result.\n */\nexport async function analyzeImpact(\n projectRoot: string,\n target: string,\n): Promise<ImpactResult> {\n const config = loadConfig(projectRoot);\n\n // Parse target string\n const { file, symbolName } = parseTarget(target);\n\n // Build symbol index and dependency graph\n const [symbols, dependencies] = await Promise.all([\n buildSymbolIndex(projectRoot, config),\n buildDependencyGraph(projectRoot, config),\n ]);\n\n // Look up target symbol info\n const targetSymbol = symbolName ? findSymbol(symbols, file, symbolName) : null;\n\n // Get direct dependents\n const depEntry = dependencies[file];\n const directFiles = depEntry ? depEntry.imported_by : [];\n\n // Find usage sites for the symbol in each direct dependent\n const directDependents: DirectDependent[] = [];\n if (symbolName) {\n for (const depFile of directFiles) {\n const usages = await findUsageSites(symbolName, depFile, projectRoot);\n directDependents.push({ file: depFile, usages });\n }\n } else {\n // File-level impact — no usage site search\n for (const depFile of directFiles) {\n directDependents.push({ file: depFile, usages: [] });\n }\n }\n\n // Compute transitive dependents\n const transitiveDependents = computeTransitiveDependents(\n directFiles,\n dependencies,\n file,\n );\n\n // Find test files\n const allFiles = collectSourceFiles(projectRoot, config).map(\n (f) => path.relative(projectRoot, f),\n );\n const testFiles = findTestFiles(file, allFiles);\n const testCoverage: TestCoverage = {\n test_files_found: testFiles,\n imports_target: testFiles.some((tf) =>\n checkTestImportsTarget(tf, file, dependencies),\n ),\n };\n\n // Total usage count\n const totalUsages = directDependents.reduce((sum, d) => sum + d.usages.length, 0);\n\n return {\n target: {\n file,\n symbol: symbolName,\n kind: targetSymbol?.kind ?? null,\n line: targetSymbol?.line ?? null,\n signature: targetSymbol?.signature ?? null,\n },\n dependents: {\n direct: directDependents,\n transitive: transitiveDependents,\n },\n risk_assessment: {\n direct_dependents: directDependents.length,\n total_usages: totalUsages,\n transitive_dependents: transitiveDependents.length,\n test_coverage: testCoverage,\n },\n };\n}\n\n/**\n * Parse a target string into file path and optional symbol name.\n */\nfunction parseTarget(target: string): { file: string; symbolName: string | null } {\n const colonIndex = target.lastIndexOf(\":\");\n if (colonIndex > 0 && colonIndex < target.length - 1) {\n // Check if this looks like a symbol separator vs. a path component\n // On Windows paths can have C:, so check if the part after : looks like a symbol\n const afterColon = target.slice(colonIndex + 1);\n if (!afterColon.includes(\"/\") && !afterColon.includes(\"\\\\\")) {\n return {\n file: target.slice(0, colonIndex),\n symbolName: afterColon,\n };\n }\n }\n return { file: target, symbolName: null };\n}\n\n/**\n * Find a symbol in the symbol index by file and name.\n */\nfunction findSymbol(\n symbols: Record<string, Symbol[]>,\n file: string,\n name: string,\n): Symbol | null {\n const fileSymbols = symbols[file];\n if (!fileSymbols) return null;\n return fileSymbols.find((s) => s.name === name) ?? null;\n}\n\n/**\n * Compute transitive dependents by walking imported_by edges from direct dependents.\n */\nfunction computeTransitiveDependents(\n directFiles: string[],\n dependencies: Record<string, DependencyEntry>,\n targetFile: string,\n): TransitiveDependent[] {\n const directSet = new Set(directFiles);\n const visited = new Set<string>([targetFile, ...directFiles]);\n const result: TransitiveDependent[] = [];\n\n // BFS from direct dependents\n interface QueueItem {\n file: string;\n via: string;\n depth: number;\n }\n\n const queue: QueueItem[] = [];\n\n // Seed with files that import the direct dependents\n for (const directFile of directFiles) {\n const entry = dependencies[directFile];\n if (!entry) continue;\n\n for (const importer of entry.imported_by) {\n if (!visited.has(importer)) {\n queue.push({ file: importer, via: directFile, depth: 2 });\n visited.add(importer);\n }\n }\n }\n\n while (queue.length > 0) {\n const item = queue.shift()!;\n result.push({\n file: item.file,\n via: item.via,\n depth: item.depth,\n });\n\n // Don't go deeper than MAX_TRANSITIVE_DEPTH\n if (item.depth >= MAX_TRANSITIVE_DEPTH) continue;\n\n const entry = dependencies[item.file];\n if (!entry) continue;\n\n for (const importer of entry.imported_by) {\n if (!visited.has(importer)) {\n queue.push({ file: importer, via: item.file, depth: item.depth + 1 });\n visited.add(importer);\n }\n }\n }\n\n return result;\n}\n","/**\n * Blast radius computation — finds files affected by a set of changed files.\n */\n\nimport type { DependencyEntry } from \"../../types/index.js\";\n\nexport interface BlastRadiusEntry {\n changed_file: string;\n affected_files: string[];\n reason: string;\n}\n\n/**\n * Compute blast radius for a set of changed files using a dependency graph.\n *\n * For each changed file, finds all files that import it (directly) and\n * are not themselves in the changed set.\n */\nexport function computeBlastRadius(\n changedFiles: string[],\n dependencies: Record<string, DependencyEntry> | null,\n): BlastRadiusEntry[] {\n if (!dependencies) return [];\n\n const changedSet = new Set(changedFiles);\n const results: BlastRadiusEntry[] = [];\n\n for (const file of changedFiles) {\n const entry = dependencies[file];\n if (!entry) continue;\n\n const affected = entry.imported_by.filter((f) => !changedSet.has(f));\n if (affected.length === 0) continue;\n\n results.push({\n changed_file: file,\n affected_files: affected,\n reason: `imports ${file}`,\n });\n }\n\n return results;\n}\n","/**\n * Symbol diff — compares cached symbols against current symbols for changed files.\n */\n\nimport type { Symbol } from \"../../types/index.js\";\n\nexport interface SymbolDiffResult {\n new_symbols: Array<{ file: string; symbol: Symbol }>;\n removed_symbols: Array<{ file: string; symbol: Symbol }>;\n modified_symbols: Array<{ file: string; before: Symbol; after: Symbol }>;\n}\n\n/**\n * Diff symbols between cached state and current state for changed files.\n */\nexport function diffSymbols(\n cachedSymbols: Record<string, Symbol[]> | null,\n currentSymbols: Record<string, Symbol[]>,\n addedFiles: string[],\n deletedFiles: string[],\n modifiedFiles: string[],\n): SymbolDiffResult {\n const result: SymbolDiffResult = {\n new_symbols: [],\n removed_symbols: [],\n modified_symbols: [],\n };\n\n // Added files: all symbols are new\n for (const file of addedFiles) {\n const symbols = currentSymbols[file];\n if (symbols) {\n for (const symbol of symbols) {\n result.new_symbols.push({ file, symbol });\n }\n }\n }\n\n // Deleted files: all cached symbols are removed\n for (const file of deletedFiles) {\n const symbols = cachedSymbols?.[file];\n if (symbols) {\n for (const symbol of symbols) {\n result.removed_symbols.push({ file, symbol });\n }\n }\n }\n\n // Modified files: compare per-symbol\n for (const file of modifiedFiles) {\n const cached = cachedSymbols?.[file] ?? [];\n const current = currentSymbols[file] ?? [];\n\n const cachedMap = buildSymbolMap(cached);\n const currentMap = buildSymbolMap(current);\n\n // Find removed and modified\n for (const [key, cachedSym] of cachedMap) {\n const currentSym = currentMap.get(key);\n if (!currentSym) {\n result.removed_symbols.push({ file, symbol: cachedSym });\n } else if (!symbolsEqual(cachedSym, currentSym)) {\n result.modified_symbols.push({ file, before: cachedSym, after: currentSym });\n }\n }\n\n // Find new\n for (const [key, currentSym] of currentMap) {\n if (!cachedMap.has(key)) {\n result.new_symbols.push({ file, symbol: currentSym });\n }\n }\n }\n\n return result;\n}\n\n/** Build a map of symbols keyed by (name, kind). */\nfunction buildSymbolMap(symbols: Symbol[]): Map<string, Symbol> {\n const map = new Map<string, Symbol>();\n for (const sym of symbols) {\n map.set(`${sym.name}::${sym.kind}`, sym);\n }\n return map;\n}\n\n/** Check if two symbols are equal (all fields). */\nfunction symbolsEqual(a: Symbol, b: Symbol): boolean {\n return (\n a.name === b.name &&\n a.kind === b.kind &&\n a.exported === b.exported &&\n a.line === b.line &&\n a.end_line === b.end_line &&\n a.signature === b.signature &&\n a.visibility === b.visibility &&\n a.is_async === b.is_async &&\n arraysEqual(a.annotations, b.annotations)\n );\n}\n\nfunction arraysEqual(a?: string[], b?: string[]): boolean {\n if (!a && !b) return true;\n if (!a || !b) return false;\n if (a.length !== b.length) return false;\n return a.every((v, i) => v === b[i]);\n}\n","/**\n * Health diff — compares cached health issues against current health results.\n */\n\nimport type { HealthIssue, HealthDiff, HealthResult } from \"../../types/index.js\";\n\n/**\n * Compare cached health issues against fresh health results.\n *\n * @returns HealthDiff with new and resolved issues, or null if either input is null.\n */\nexport function diffHealth(\n cachedHealth: HealthResult | null,\n currentHealth: HealthResult | null,\n): HealthDiff | null {\n if (!cachedHealth || !currentHealth) return null;\n\n const cachedKeys = new Set(cachedHealth.issues.map(issueKey));\n const currentKeys = new Set(currentHealth.issues.map(issueKey));\n\n const newIssues = currentHealth.issues.filter((i) => !cachedKeys.has(issueKey(i)));\n const resolvedIssues = cachedHealth.issues.filter((i) => !currentKeys.has(issueKey(i)));\n\n return {\n new_issues: newIssues,\n resolved_issues: resolvedIssues,\n };\n}\n\n/** Composite key for matching health issues. */\nfunction issueKey(issue: HealthIssue): string {\n return `${issue.file}:${issue.line}:${issue.code}:${issue.tool}`;\n}\n","/**\n * Differ service — computes changes since the last scan.\n *\n * This is the main entry point for the `changed` command.\n * It is read-only and does NOT update the cache.\n */\n\nimport * as path from \"node:path\";\nimport type { ChangedResult, CacheStatus, Symbol } from \"../../types/index.js\";\nimport { loadConfig } from \"../../config/index.js\";\nimport { readCache, readMeta } from \"../cache/index.js\";\nimport {\n getHead,\n getDiffNameStatus,\n getUncommittedChanges,\n getPullCommitHashes,\n getFileCommitInfo,\n type GitFileChange,\n} from \"../git/index.js\";\nimport { computeBlastRadius } from \"./blast-radius.js\";\nimport { diffSymbols } from \"./symbol-diff.js\";\nimport { diffHealth } from \"./health-diff.js\";\nimport { runHealthChecks } from \"../health/index.js\";\nimport { extractSymbolsForFile } from \"../parser/symbol-index.js\";\nimport { detectProject } from \"../scanner/project-detector.js\";\nimport { withConcurrency, DEFAULT_CONCURRENCY } from \"../parser/utils.js\";\n\n/** Map git status codes to ChangedResult status strings. */\ntype FileStatus = \"added\" | \"modified\" | \"deleted\" | \"renamed\";\n\nfunction mapStatus(gitStatus: string): FileStatus {\n switch (gitStatus) {\n case \"A\": return \"added\";\n case \"D\": return \"deleted\";\n case \"R\": return \"renamed\";\n default: return \"modified\";\n }\n}\n\n/**\n * Compute changes since the last scan.\n *\n * @param projectRoot Absolute path to the project root.\n * @param includeHealth When true, run health checks and diff against cached health.\n * @throws Error if no cache exists or cache has no git HEAD.\n */\nexport async function changed(\n projectRoot: string,\n includeHealth: boolean,\n): Promise<ChangedResult> {\n const startTime = Date.now();\n\n // 1. Read cache\n const cachedScan = readCache(projectRoot);\n const meta = readMeta(projectRoot);\n if (!cachedScan || !meta) {\n throw new Error(\"No cached scan found. Run 'scan' first.\");\n }\n\n const sinceCommit = meta.git_head;\n if (!sinceCommit) {\n throw new Error(\"Cached scan has no git HEAD. Run 'scan' in a git repository first.\");\n }\n\n // 2. Get current HEAD\n const currentHead = await getHead(projectRoot);\n if (!currentHead) {\n throw new Error(\"Not a git repository or git is not available.\");\n }\n\n // 3. Get changes\n const [committedChanges, uncommittedChanges] = await Promise.all([\n getDiffNameStatus(projectRoot, sinceCommit),\n getUncommittedChanges(projectRoot),\n ]);\n\n // 4. Merge changes — uncommitted wins for same path\n const mergedChanges = mergeChanges(committedChanges, uncommittedChanges);\n\n // 5. Attribution\n const pullHashes = await getPullCommitHashes(projectRoot, sinceCommit);\n\n const filesChanged = await buildFilesChanged(\n mergedChanges,\n committedChanges,\n uncommittedChanges,\n pullHashes,\n projectRoot,\n sinceCommit,\n );\n\n // 6. Classify files by status\n const addedFiles = filesChanged.filter((f) => f.status === \"added\").map((f) => f.path);\n const deletedFiles = filesChanged.filter((f) => f.status === \"deleted\").map((f) => f.path);\n const modifiedFiles = filesChanged.filter((f) => f.status === \"modified\" || f.status === \"renamed\").map((f) => f.path);\n const changedPaths = [...addedFiles, ...modifiedFiles, ...deletedFiles];\n\n // 7. Blast radius\n const blastRadius = computeBlastRadius(changedPaths, cachedScan.dependencies);\n\n // 8. Re-parse changed files for symbol diff\n const filesToParse = [...addedFiles, ...modifiedFiles];\n const currentSymbols: Record<string, Symbol[]> = {};\n\n await withConcurrency(\n filesToParse.map((relPath) => async () => {\n const symbols = await extractSymbolsForFile(projectRoot, relPath);\n if (symbols.length > 0) {\n currentSymbols[relPath] = symbols;\n }\n }),\n DEFAULT_CONCURRENCY,\n );\n\n // 9. Symbol diff\n const symbolDiff = diffSymbols(\n cachedScan.symbols,\n currentSymbols,\n addedFiles,\n deletedFiles,\n modifiedFiles,\n );\n\n // 10. Health diff\n let healthDiff = null;\n if (includeHealth) {\n const config = loadConfig(projectRoot);\n const project = detectProject(projectRoot);\n const currentHealth = await runHealthChecks(\n projectRoot,\n project.detected_tools,\n config.health_timeout_ms,\n );\n healthDiff = diffHealth(cachedScan.health, currentHealth);\n }\n\n const cache: CacheStatus = {\n status: \"cache_hit\",\n git_head: currentHead,\n scanned_at: new Date().toISOString(),\n scan_duration_ms: Date.now() - startTime,\n };\n\n return {\n changes: {\n since_commit: sinceCommit,\n current_commit: currentHead,\n files_changed: filesChanged,\n blast_radius: blastRadius,\n new_symbols: symbolDiff.new_symbols,\n removed_symbols: symbolDiff.removed_symbols,\n modified_symbols: symbolDiff.modified_symbols,\n },\n health_diff: healthDiff,\n cache,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Merge committed and uncommitted changes. Uncommitted wins for same path. */\nfunction mergeChanges(\n committed: GitFileChange[],\n uncommitted: GitFileChange[],\n): GitFileChange[] {\n const merged = new Map<string, GitFileChange>();\n\n for (const change of committed) {\n merged.set(change.path, change);\n }\n\n for (const change of uncommitted) {\n merged.set(change.path, change);\n }\n\n return [...merged.values()];\n}\n\n/** Build the files_changed array with attribution. */\nasync function buildFilesChanged(\n merged: GitFileChange[],\n committed: GitFileChange[],\n uncommitted: GitFileChange[],\n pullHashes: Set<string>,\n projectRoot: string,\n sinceCommit: string,\n): Promise<ChangedResult[\"changes\"][\"files_changed\"]> {\n const committedPaths = new Set(committed.map((c) => c.path));\n const uncommittedPaths = new Set(uncommitted.map((c) => c.path));\n\n const results: ChangedResult[\"changes\"][\"files_changed\"] = [];\n\n for (const change of merged) {\n const isUncommitted = uncommittedPaths.has(change.path);\n const isCommitted = committedPaths.has(change.path);\n\n let source: \"pull\" | \"local_commit\" | \"uncommitted\";\n let author: string | null = null;\n let commitMessage: string | null = null;\n\n if (isUncommitted && !isCommitted) {\n source = \"uncommitted\";\n } else if (isCommitted) {\n const info = await getFileCommitInfo(projectRoot, change.path, sinceCommit);\n if (info) {\n author = info.author;\n commitMessage = info.message;\n source = pullHashes.has(info.hash) ? \"pull\" : \"local_commit\";\n } else {\n source = \"local_commit\";\n }\n // If also uncommitted, override source\n if (isUncommitted) {\n source = \"uncommitted\";\n }\n } else {\n source = \"uncommitted\";\n }\n\n results.push({\n path: change.path,\n status: mapStatus(change.status),\n source,\n author,\n commit_message: commitMessage,\n });\n }\n\n return results;\n}\n","/**\n * Compact output formatter.\n *\n * Transforms a full ScanResult into a CompactScanResult that uses ~2-3k tokens\n * instead of ~15-20k, giving agents what they need for orientation without noise.\n */\n\nimport * as path from \"node:path\";\nimport type {\n ScanResult,\n CompactScanResult,\n DirSummary,\n FileTreeEntry,\n FileEntry,\n CollapsedDir,\n Symbol,\n DependencyEntry,\n} from \"../../types/index.js\";\n\n/** Max number of key exports to include in the summary. */\nconst MAX_KEY_EXPORTS = 15;\n\n/** Max number of top files for most_imported / most_importing. */\nconst MAX_TOP_FILES = 5;\n\n/**\n * Convert a full ScanResult to a compact agent-friendly summary.\n */\nexport function compactify(result: ScanResult): CompactScanResult {\n return {\n project: result.project,\n structure: summarizeTree(result.tree),\n symbols_summary: summarizeSymbols(result.symbols, result.dependencies),\n dependencies_summary: summarizeDependencies(result.dependencies),\n health: result.health,\n cache: result.cache,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Tree summarization\n// ---------------------------------------------------------------------------\n\n/**\n * Summarize the file tree into one entry per top-level directory.\n */\nfunction summarizeTree(tree: Record<string, FileTreeEntry>): Record<string, DirSummary> {\n const structure: Record<string, DirSummary> = {};\n\n for (const [key, value] of Object.entries(tree)) {\n if (isCollapsed(value)) {\n structure[key + \"/\"] = {\n files: (value as CollapsedDir).file_count,\n languages: [],\n collapsed: true,\n };\n } else if (isFileEntry(value)) {\n // Root-level file — group into a synthetic \"_root\" entry\n if (!structure[\".\"]) {\n structure[\".\"] = { files: 0, languages: [] };\n }\n structure[\".\"].files++;\n const lang = extToLanguage(key);\n if (lang && !structure[\".\"].languages.includes(lang)) {\n structure[\".\"].languages.push(lang);\n }\n } else {\n // Directory — summarize recursively\n const dirEntry = value as Record<string, FileTreeEntry>;\n const files: string[] = [];\n const langs = new Set<string>();\n const keyDirs: string[] = [];\n\n collectDirStats(dirEntry, files, langs, keyDirs, \"\", 1);\n\n structure[key + \"/\"] = {\n files: files.length,\n languages: [...langs].sort(),\n ...(keyDirs.length > 0 ? { key_dirs: keyDirs.slice(0, 8) } : {}),\n };\n }\n }\n\n return structure;\n}\n\nfunction collectDirStats(\n tree: Record<string, FileTreeEntry>,\n files: string[],\n langs: Set<string>,\n keyDirs: string[],\n prefix: string,\n depth: number,\n): void {\n for (const [key, value] of Object.entries(tree)) {\n if (isCollapsed(value)) {\n // Skip collapsed dirs\n } else if (isFileEntry(value)) {\n files.push(prefix + key);\n const lang = extToLanguage(key);\n if (lang) langs.add(lang);\n } else {\n // Subdirectory — track as key_dir if depth 1\n if (depth === 1) {\n keyDirs.push(key + \"/\");\n }\n collectDirStats(\n value as Record<string, FileTreeEntry>,\n files,\n langs,\n keyDirs,\n prefix + key + \"/\",\n depth + 1,\n );\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Symbol summarization\n// ---------------------------------------------------------------------------\n\nfunction summarizeSymbols(\n symbols: Record<string, Symbol[]> | null,\n dependencies: Record<string, DependencyEntry> | null,\n): CompactScanResult[\"symbols_summary\"] {\n if (!symbols || Object.keys(symbols).length === 0) return null;\n\n let total = 0;\n const byKind: Record<string, number> = {};\n const exportedSymbols: { name: string; file: string; kind: string }[] = [];\n\n for (const [file, syms] of Object.entries(symbols)) {\n for (const sym of syms) {\n total++;\n byKind[sym.kind] = (byKind[sym.kind] ?? 0) + 1;\n if (sym.exported) {\n exportedSymbols.push({ name: sym.name, file, kind: sym.kind });\n }\n }\n }\n\n // Rank exported symbols by import count (fan-in) if dependency data available\n let keyExports: string[];\n if (dependencies) {\n const importCount = new Map<string, number>();\n for (const entry of Object.values(dependencies)) {\n for (const dep of entry.imported_by) {\n importCount.set(dep, (importCount.get(dep) ?? 0) + 1);\n }\n }\n\n // Score each exported symbol by its file's fan-in\n exportedSymbols.sort((a, b) => {\n const scoreA = importCount.get(a.file) ?? 0;\n const scoreB = importCount.get(b.file) ?? 0;\n return scoreB - scoreA;\n });\n }\n\n // Prefer classes/interfaces over plain functions for key_exports\n const priorityKinds = new Set([\"class\", \"interface\", \"type_alias\", \"enum\"]);\n const priority = exportedSymbols.filter((s) => priorityKinds.has(s.kind));\n const rest = exportedSymbols.filter((s) => !priorityKinds.has(s.kind));\n const ranked = [...priority, ...rest];\n\n // Deduplicate by name\n const seen = new Set<string>();\n keyExports = [];\n for (const sym of ranked) {\n if (!seen.has(sym.name) && keyExports.length < MAX_KEY_EXPORTS) {\n seen.add(sym.name);\n keyExports.push(sym.name);\n }\n }\n\n return { total, by_kind: byKind, key_exports: keyExports };\n}\n\n// ---------------------------------------------------------------------------\n// Dependency summarization\n// ---------------------------------------------------------------------------\n\nfunction summarizeDependencies(\n dependencies: Record<string, DependencyEntry> | null,\n): CompactScanResult[\"dependencies_summary\"] {\n if (!dependencies || Object.keys(dependencies).length === 0) return null;\n\n const totalFiles = Object.keys(dependencies).length;\n\n // Most imported: files with highest imported_by count\n const byImportedBy = Object.entries(dependencies)\n .map(([file, entry]) => ({ file, count: entry.imported_by.length }))\n .filter((e) => e.count > 0)\n .sort((a, b) => b.count - a.count)\n .slice(0, MAX_TOP_FILES)\n .map((e) => e.file);\n\n // Most importing: files with highest imports_from count\n const byImportsFrom = Object.entries(dependencies)\n .map(([file, entry]) => ({ file, count: entry.imports_from.length }))\n .filter((e) => e.count > 0)\n .sort((a, b) => b.count - a.count)\n .slice(0, MAX_TOP_FILES)\n .map((e) => e.file);\n\n return {\n total_files: totalFiles,\n most_imported: byImportedBy,\n most_importing: byImportsFrom,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction isFileEntry(entry: FileTreeEntry): entry is FileEntry {\n return \"size\" in entry && !(\"_collapsed\" in entry);\n}\n\nfunction isCollapsed(entry: FileTreeEntry): entry is CollapsedDir {\n return \"_collapsed\" in entry;\n}\n\nconst EXT_LANG_MAP: Record<string, string> = {\n \".ts\": \"typescript\",\n \".tsx\": \"typescript\",\n \".js\": \"javascript\",\n \".jsx\": \"javascript\",\n \".py\": \"python\",\n \".java\": \"java\",\n \".rs\": \"rust\",\n \".go\": \"go\",\n \".rb\": \"ruby\",\n \".kt\": \"kotlin\",\n \".json\": \"json\",\n \".yaml\": \"yaml\",\n \".yml\": \"yaml\",\n \".toml\": \"toml\",\n \".md\": \"markdown\",\n};\n\nfunction extToLanguage(fileName: string): string | null {\n const ext = path.extname(fileName).toLowerCase();\n return EXT_LANG_MAP[ext] ?? null;\n}\n","/**\n * inspect-mcp — Codebase intelligence MCP server.\n *\n * Entry point: starts the MCP server on stdio transport.\n */\n\nimport { startServer } from \"./runtime/index.js\";\n\nstartServer().catch((err) => {\n process.stderr.write(`Fatal: ${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n});\n"],"mappings":"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","names":["fs","path","fs","path","fs","path","fs","path","fs","path","require","fs","path","fs","path","extractors","fs","path","resolved","execFile","promisify","execFileAsync","promisify","execFile","fs","path","path","path","path","isFileEntry"]}
1
+ {"version":3,"sources":["../src/runtime/index.ts","../src/types/index.ts","../src/config/index.ts","../src/services/scanner/project-detector.ts","../src/services/scanner/file-tree-builder.ts","../src/services/git/index.ts","../src/services/cache/index.ts","../src/services/parser/symbol-index.ts","../src/services/parser/grammar-loader.ts","../src/services/parser/index.ts","../src/services/parser/extractors/typescript.ts","../src/services/parser/extractors/python.ts","../src/services/parser/extractors/java.ts","../src/services/parser/extractors/index.ts","../src/services/parser/utils.ts","../src/services/parser/dependency-graph.ts","../src/services/parser/import-extractors/typescript.ts","../src/services/parser/import-extractors/python.ts","../src/services/parser/import-extractors/java.ts","../src/services/parser/import-extractors/index.ts","../src/services/parser/path-resolver.ts","../src/services/health/index.ts","../src/services/health/parsers.ts","../src/services/scanner/index.ts","../src/services/impact/usage-finder.ts","../src/services/differ/test-association.ts","../src/services/impact/index.ts","../src/services/differ/blast-radius.ts","../src/services/differ/symbol-diff.ts","../src/services/differ/health-diff.ts","../src/services/differ/index.ts","../src/services/scanner/compact-formatter.ts","../src/index.ts"],"sourcesContent":["/**\n * MCP server setup, tool registration, and command routing.\n */\n\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { z } from \"zod\";\nimport { InspectParamsSchema } from \"../types/index.js\";\nimport { scan } from \"../services/scanner/index.js\";\nimport { analyzeImpact } from \"../services/impact/index.js\";\nimport { changed } from \"../services/differ/index.js\";\nimport { compactify } from \"../services/scanner/compact-formatter.js\";\n\n/**\n * Create and configure the MCP server with the `inspect` tool.\n */\nexport function createServer(): Server {\n const server = new Server(\n {\n name: \"inspect-mcp\",\n version: \"0.1.0\",\n },\n {\n capabilities: {\n tools: {},\n },\n },\n );\n\n // Register available tools\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n {\n name: \"inspect\",\n description:\n \"Analyze a codebase and return structured project info, file tree, symbols, dependencies, and health status. Commands: scan (full/incremental scan), changed (delta since last scan), impact (dependency analysis for a target).\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n command: {\n type: \"string\",\n enum: [\"scan\", \"changed\", \"impact\"],\n default: \"scan\",\n description: \"Command to execute\",\n },\n path: {\n type: \"string\",\n description: \"Absolute path to the project root directory\",\n },\n include_health: {\n type: \"boolean\",\n default: false,\n description: \"Run linter/type-checker and include health results\",\n },\n target: {\n type: \"string\",\n description:\n \"For impact command: file_path or file_path:symbol_name to analyze\",\n },\n compact: {\n type: \"boolean\",\n default: true,\n description:\n \"Return compact summary (default: true). Set to false for full JSON output.\",\n },\n },\n required: [\"path\"],\n },\n },\n ],\n }));\n\n // Handle tool calls\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n if (request.params.name !== \"inspect\") {\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ error: `Unknown tool: ${request.params.name}` }),\n },\n ],\n isError: true,\n };\n }\n\n // Validate parameters at the boundary\n const parseResult = InspectParamsSchema.safeParse(request.params.arguments);\n if (!parseResult.success) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"Invalid parameters\",\n details: parseResult.error.issues,\n }),\n },\n ],\n isError: true,\n };\n }\n\n const params = parseResult.data;\n return routeCommand(params);\n });\n\n return server;\n}\n\n/**\n * Route a validated command to the appropriate handler.\n */\nasync function routeCommand(params: z.infer<typeof InspectParamsSchema>) {\n try {\n switch (params.command) {\n case \"scan\": {\n const fullResult = await scan(params.path, params.include_health);\n const result = params.compact ? compactify(fullResult) : fullResult;\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n };\n }\n\n case \"changed\": {\n const changedResult = await changed(params.path, params.include_health);\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(changedResult, null, 2) }],\n };\n }\n\n case \"impact\": {\n if (!params.target) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"The 'target' parameter is required for the impact command.\",\n }),\n },\n ],\n isError: true,\n };\n }\n const impactResult = await analyzeImpact(params.path, params.target);\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(impactResult, null, 2) }],\n };\n }\n\n default: {\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ error: `Unknown command: ${params.command}` }),\n },\n ],\n isError: true,\n };\n }\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ error: \"Internal error\", message }),\n },\n ],\n isError: true,\n };\n }\n}\n\n/**\n * Start the MCP server on stdio transport.\n */\nexport async function startServer(): Promise<void> {\n const server = createServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n","/**\n * Shared type definitions for inspect-mcp.\n *\n * This module defines all Zod schemas and their inferred TypeScript types.\n * Types layer must NOT import from any other layer.\n */\n\nimport { z } from \"zod\";\n\n// ---------------------------------------------------------------------------\n// Project Info\n// ---------------------------------------------------------------------------\n\nexport const DetectedToolsSchema = z.object({\n linter: z.string().nullable(),\n type_checker: z.string().nullable(),\n test_runner: z.string().nullable(),\n formatter: z.string().nullable(),\n});\n\nexport type DetectedTools = z.infer<typeof DetectedToolsSchema>;\n\nexport const SubProjectSchema = z.object({\n path: z.string(),\n language: z.string(),\n framework: z.string().nullable(),\n package_manager: z.string().nullable(),\n detected_tools: DetectedToolsSchema,\n});\n\nexport type SubProject = z.infer<typeof SubProjectSchema>;\n\nexport const ProjectInfoSchema = z.object({\n name: z.string(),\n language: z.string(),\n framework: z.string().nullable(),\n framework_version: z.string().nullable(),\n package_manager: z.string().nullable(),\n runtime: z.string().nullable(),\n entry_points: z.array(z.string()),\n scripts: z.record(z.string(), z.string()),\n detected_tools: DetectedToolsSchema,\n sub_projects: z.array(SubProjectSchema).optional(),\n});\n\nexport type ProjectInfo = z.infer<typeof ProjectInfoSchema>;\n\n// ---------------------------------------------------------------------------\n// File Tree\n// ---------------------------------------------------------------------------\n\nexport const CollapsedDirSchema = z.object({\n _collapsed: z.literal(true),\n file_count: z.number(),\n});\n\nexport type CollapsedDir = z.infer<typeof CollapsedDirSchema>;\n\nexport const FileEntrySchema = z.object({\n size: z.number(),\n symbols: z.number().optional(),\n});\n\nexport type FileEntry = z.infer<typeof FileEntrySchema>;\n\n/**\n * A file tree node is either a collapsed directory summary, a file entry,\n * or a nested record of more tree nodes.\n */\nexport type FileTreeEntry = CollapsedDir | FileEntry | { [key: string]: FileTreeEntry };\n\n// We can't directly do recursive Zod, so we use z.lazy for the tree schema.\nexport const FileTreeEntrySchema: z.ZodType<FileTreeEntry> = z.lazy(() =>\n z.union([CollapsedDirSchema, FileEntrySchema, z.record(z.string(), FileTreeEntrySchema)]),\n);\n\n// ---------------------------------------------------------------------------\n// Symbols\n// ---------------------------------------------------------------------------\n\nexport const SymbolKindEnum = z.enum([\n \"function\",\n \"arrow_function\",\n \"class\",\n \"interface\",\n \"type_alias\",\n \"method\",\n \"field\",\n \"enum\",\n \"constant\",\n \"constructor\",\n \"package\",\n]);\n\nexport type SymbolKind = z.infer<typeof SymbolKindEnum>;\n\nexport const VisibilityEnum = z.enum([\"public\", \"private\", \"protected\", \"package\"]);\n\nexport type Visibility = z.infer<typeof VisibilityEnum>;\n\nexport const SymbolSchema = z.object({\n /** Symbol name. */\n name: z.string(),\n /** What kind of symbol this is. */\n kind: SymbolKindEnum,\n /** Whether the symbol is exported / public. */\n exported: z.boolean(),\n /** 1-based start line. */\n line: z.number(),\n /** 1-based end line. */\n end_line: z.number().optional(),\n /** Human-readable signature (e.g. \"(id: string) => Promise<User>\"). */\n signature: z.string().nullable().optional(),\n /** Visibility modifier (Java: public/private/protected/package). */\n visibility: VisibilityEnum.nullable().optional(),\n /** Annotations / decorators (Java annotations, Python decorators). */\n annotations: z.array(z.string()).optional(),\n /** Whether the symbol is async. */\n is_async: z.boolean().optional(),\n});\n\nexport type Symbol = z.infer<typeof SymbolSchema>;\n\n// ---------------------------------------------------------------------------\n// Cache\n// ---------------------------------------------------------------------------\n\nexport const CacheStatusSchema = z.object({\n status: z.enum([\"fresh\", \"incremental_update\", \"cache_hit\", \"no_cache\"]),\n git_head: z.string().nullable(),\n scanned_at: z.string(),\n scan_duration_ms: z.number(),\n files_rescanned: z.number().optional(),\n});\n\nexport type CacheStatus = z.infer<typeof CacheStatusSchema>;\n\n// ---------------------------------------------------------------------------\n// Health\n// ---------------------------------------------------------------------------\n\nexport const HealthIssueSeverityEnum = z.enum([\"error\", \"warning\", \"info\"]);\n\nexport type HealthIssueSeverity = z.infer<typeof HealthIssueSeverityEnum>;\n\nexport const HealthIssueSchema = z.object({\n file: z.string(),\n line: z.number().nullable(),\n column: z.number().nullable(),\n severity: HealthIssueSeverityEnum,\n code: z.string().nullable(),\n message: z.string(),\n tool: z.string(),\n});\n\nexport type HealthIssue = z.infer<typeof HealthIssueSchema>;\n\nexport const HealthToolResultSchema = z.object({\n tool: z.string(),\n success: z.boolean(),\n run_duration_ms: z.number(),\n error_count: z.number(),\n warning_count: z.number(),\n error_message: z.string().nullable(),\n});\n\nexport type HealthToolResult = z.infer<typeof HealthToolResultSchema>;\n\nexport const HealthResultSchema = z.object({\n tools_run: z.array(HealthToolResultSchema),\n total_errors: z.number(),\n total_warnings: z.number(),\n issues: z.array(HealthIssueSchema),\n run_duration_ms: z.number(),\n});\n\nexport type HealthResult = z.infer<typeof HealthResultSchema>;\n\nexport const HealthDiffSchema = z.object({\n new_issues: z.array(HealthIssueSchema),\n resolved_issues: z.array(HealthIssueSchema),\n});\n\nexport type HealthDiff = z.infer<typeof HealthDiffSchema>;\n\n// ---------------------------------------------------------------------------\n// Dependencies\n// ---------------------------------------------------------------------------\n\nexport const DependencyEntrySchema = z.object({\n imports_from: z.array(z.string()),\n imported_by: z.array(z.string()),\n});\n\nexport type DependencyEntry = z.infer<typeof DependencyEntrySchema>;\n\n// ---------------------------------------------------------------------------\n// Scan Result\n// ---------------------------------------------------------------------------\n\nexport const ScanResultSchema = z.object({\n project: ProjectInfoSchema,\n tree: z.record(z.string(), FileTreeEntrySchema),\n symbols: z.record(z.string(), z.array(SymbolSchema)).nullable(),\n dependencies: z.record(z.string(), DependencyEntrySchema).nullable(),\n health: HealthResultSchema.nullable(),\n cache: CacheStatusSchema,\n});\n\nexport type ScanResult = z.infer<typeof ScanResultSchema>;\n\n// ---------------------------------------------------------------------------\n// Compact Scan Result (agent-friendly summary)\n// ---------------------------------------------------------------------------\n\nexport const DirSummarySchema = z.object({\n files: z.number(),\n languages: z.array(z.string()),\n key_dirs: z.array(z.string()).optional(),\n collapsed: z.boolean().optional(),\n});\n\nexport type DirSummary = z.infer<typeof DirSummarySchema>;\n\nexport const CompactScanResultSchema = z.object({\n project: ProjectInfoSchema,\n structure: z.record(z.string(), DirSummarySchema),\n symbols_summary: z.object({\n total: z.number(),\n by_kind: z.record(z.string(), z.number()),\n key_exports: z.array(z.string()),\n }).nullable(),\n dependencies_summary: z.object({\n total_files: z.number(),\n most_imported: z.array(z.string()),\n most_importing: z.array(z.string()),\n }).nullable(),\n health: HealthResultSchema.nullable(),\n cache: CacheStatusSchema,\n});\n\nexport type CompactScanResult = z.infer<typeof CompactScanResultSchema>;\n\n// ---------------------------------------------------------------------------\n// Changed Result\n// ---------------------------------------------------------------------------\n\nexport const ChangedResultSchema = z.object({\n changes: z.object({\n since_commit: z.string(),\n current_commit: z.string(),\n files_changed: z.array(\n z.object({\n path: z.string(),\n status: z.enum([\"added\", \"modified\", \"deleted\", \"renamed\"]),\n source: z.enum([\"pull\", \"local_commit\", \"uncommitted\"]),\n author: z.string().nullable(),\n commit_message: z.string().nullable(),\n }),\n ),\n blast_radius: z.array(\n z.object({\n changed_file: z.string(),\n affected_files: z.array(z.string()),\n reason: z.string(),\n }),\n ),\n new_symbols: z.array(z.object({ file: z.string(), symbol: SymbolSchema })),\n removed_symbols: z.array(z.object({ file: z.string(), symbol: SymbolSchema })),\n modified_symbols: z.array(\n z.object({ file: z.string(), before: SymbolSchema, after: SymbolSchema }),\n ),\n }),\n health_diff: HealthDiffSchema.nullable(),\n cache: CacheStatusSchema,\n});\n\nexport type ChangedResult = z.infer<typeof ChangedResultSchema>;\n\n// ---------------------------------------------------------------------------\n// Impact Result\n// ---------------------------------------------------------------------------\n\nexport const UsageSiteSchema = z.object({\n line: z.number(),\n context: z.string(),\n});\n\nexport type UsageSite = z.infer<typeof UsageSiteSchema>;\n\nexport const DirectDependentSchema = z.object({\n file: z.string(),\n usages: z.array(UsageSiteSchema),\n});\n\nexport type DirectDependent = z.infer<typeof DirectDependentSchema>;\n\nexport const TransitiveDependentSchema = z.object({\n file: z.string(),\n via: z.string(),\n depth: z.number(),\n});\n\nexport type TransitiveDependent = z.infer<typeof TransitiveDependentSchema>;\n\nexport const TestCoverageSchema = z.object({\n test_files_found: z.array(z.string()),\n imports_target: z.boolean(),\n});\n\nexport type TestCoverage = z.infer<typeof TestCoverageSchema>;\n\nexport const ImpactResultSchema = z.object({\n target: z.object({\n file: z.string(),\n symbol: z.string().nullable(),\n kind: z.string().nullable(),\n line: z.number().nullable(),\n signature: z.string().nullable(),\n }),\n dependents: z.object({\n direct: z.array(DirectDependentSchema),\n transitive: z.array(TransitiveDependentSchema),\n }),\n risk_assessment: z.object({\n direct_dependents: z.number(),\n total_usages: z.number(),\n transitive_dependents: z.number(),\n test_coverage: TestCoverageSchema.nullable(),\n }),\n});\n\nexport type ImpactResult = z.infer<typeof ImpactResultSchema>;\n\n// ---------------------------------------------------------------------------\n// Inspect Config (user-facing configuration)\n// ---------------------------------------------------------------------------\n\nexport const InspectConfigSchema = z.object({\n collapse_dirs: z.array(z.string()).optional(),\n ignore_patterns: z.array(z.string()).optional(),\n max_file_size_kb: z.number().optional(),\n tree_depth: z.number().optional(),\n health_timeout_ms: z.number().optional(),\n languages: z.array(z.string()).optional(),\n path_aliases: z.union([z.literal(\"auto\"), z.record(z.string(), z.string())]).optional(),\n});\n\nexport type InspectConfig = z.infer<typeof InspectConfigSchema>;\n\n// ---------------------------------------------------------------------------\n// MCP Tool Parameters\n// ---------------------------------------------------------------------------\n\nexport const InspectParamsSchema = z.object({\n command: z.enum([\"scan\", \"changed\", \"impact\"]).default(\"scan\"),\n path: z.string(),\n include_health: z.boolean().default(false),\n target: z.string().optional(),\n compact: z.boolean().default(true),\n});\n\nexport type InspectParams = z.infer<typeof InspectParamsSchema>;\n\n// ---------------------------------------------------------------------------\n// Cache Meta (internal cache metadata)\n// ---------------------------------------------------------------------------\n\nexport const CacheMetaSchema = z.object({\n version: z.string(),\n git_head: z.string().nullable(),\n scanned_at: z.string(),\n});\n\nexport type CacheMeta = z.infer<typeof CacheMetaSchema>;\n","/**\n * Configuration loading and defaults.\n *\n * May import from Types layer only.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { InspectConfigSchema, type InspectConfig } from \"../types/index.js\";\n\n/** Default collapse directories — heavy or generated content that should be summarised. */\nexport const DEFAULT_COLLAPSE_DIRS = [\n \"node_modules\",\n \"dist\",\n \"build\",\n \".next\",\n \"target\",\n \"__pycache__\",\n \".git\",\n \"venv\",\n \".venv\",\n \"vendor\",\n];\n\n/** Default ignore patterns — files that add noise to the tree. */\nexport const DEFAULT_IGNORE_PATTERNS = [\"*.min.js\", \"*.generated.*\", \"*.d.ts\", \"*.map\"];\n\n/** Default max file size in KB above which files are skipped during parsing. */\nexport const DEFAULT_MAX_FILE_SIZE_KB = 100;\n\n/** Default tree depth limit. */\nexport const DEFAULT_TREE_DEPTH = 6;\n\n/** Default health check timeout per tool in milliseconds. */\nexport const DEFAULT_HEALTH_TIMEOUT_MS = 15_000;\n\n/** Auto-collapse threshold — dirs with more than this many files and no source code. */\nexport const AUTO_COLLAPSE_FILE_THRESHOLD = 500;\n\n/** Tool version written into cache metadata. */\nexport const TOOL_VERSION = \"0.2.0\";\n\n/**\n * Resolved configuration with all defaults applied.\n */\nexport interface ResolvedConfig {\n collapse_dirs: string[];\n ignore_patterns: string[];\n max_file_size_kb: number;\n tree_depth: number;\n health_timeout_ms: number;\n path_aliases?: Record<string, string> | \"auto\";\n}\n\n/**\n * Load optional `inspect.config.json` from the project root.\n * Falls back to defaults for any unspecified fields.\n */\nexport function loadConfig(projectRoot: string): ResolvedConfig {\n const defaults: ResolvedConfig = {\n collapse_dirs: DEFAULT_COLLAPSE_DIRS,\n ignore_patterns: DEFAULT_IGNORE_PATTERNS,\n max_file_size_kb: DEFAULT_MAX_FILE_SIZE_KB,\n tree_depth: DEFAULT_TREE_DEPTH,\n health_timeout_ms: DEFAULT_HEALTH_TIMEOUT_MS,\n };\n\n const candidates = [\n path.join(projectRoot, \"inspect.config.json\"),\n path.join(projectRoot, \".inspect\", \"config.json\"),\n ];\n\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n try {\n const raw = JSON.parse(fs.readFileSync(candidate, \"utf-8\"));\n const parsed = InspectConfigSchema.parse(raw);\n return {\n collapse_dirs: parsed.collapse_dirs ?? defaults.collapse_dirs,\n ignore_patterns: parsed.ignore_patterns ?? defaults.ignore_patterns,\n max_file_size_kb: parsed.max_file_size_kb ?? defaults.max_file_size_kb,\n tree_depth: parsed.tree_depth ?? defaults.tree_depth,\n health_timeout_ms: parsed.health_timeout_ms ?? defaults.health_timeout_ms,\n path_aliases: parsed.path_aliases,\n };\n } catch {\n // Invalid config file — fall through to defaults\n }\n }\n }\n\n return defaults;\n}\n","/**\n * Project detection engine.\n *\n * Uses a registry of detectors that examine config files in the project root\n * to determine language, framework, package manager, entry points, and tools.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { ProjectInfo, DetectedTools, SubProject } from \"../../types/index.js\";\n\n// ---------------------------------------------------------------------------\n// Detector registry\n// ---------------------------------------------------------------------------\n\ninterface DetectorEntry {\n /** File to look for in the project root. */\n file: string;\n /** Parse the file content and return partial ProjectInfo, or null if not applicable. */\n detect: (content: string, projectRoot: string) => Partial<ProjectInfo> | null;\n}\n\nconst detectors: DetectorEntry[] = [\n { file: \"package.json\", detect: detectNodeProject },\n { file: \"pyproject.toml\", detect: detectPythonProject },\n { file: \"Cargo.toml\", detect: detectRustProject },\n { file: \"go.mod\", detect: detectGoProject },\n { file: \"pom.xml\", detect: detectJavaProject },\n { file: \"build.gradle\", detect: detectGradleProject },\n { file: \"build.gradle.kts\", detect: detectGradleProject },\n { file: \"Gemfile\", detect: detectRubyProject },\n];\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Detect project information by examining config files in the project root.\n * Runs detectors in priority order and returns the first match merged with\n * tool detection results.\n */\nexport function detectProject(projectRoot: string): ProjectInfo {\n let info: Partial<ProjectInfo> | null = null;\n\n for (const detector of detectors) {\n const filePath = path.join(projectRoot, detector.file);\n if (fs.existsSync(filePath)) {\n try {\n const content = fs.readFileSync(filePath, \"utf-8\");\n info = detector.detect(content, projectRoot);\n if (info) break;\n } catch {\n // Unreadable file — skip\n }\n }\n }\n\n const detectedTools = detectTools(projectRoot);\n const projectName = info?.name ?? path.basename(projectRoot);\n\n const baseResult: ProjectInfo = {\n name: projectName,\n language: info?.language ?? \"unknown\",\n framework: info?.framework ?? null,\n framework_version: info?.framework_version ?? null,\n package_manager: info?.package_manager ?? null,\n runtime: info?.runtime ?? null,\n entry_points: info?.entry_points ?? detectConventionalEntryPoints(projectRoot),\n scripts: info?.scripts ?? {},\n detected_tools: detectedTools,\n };\n\n // If root detection failed, try monorepo sub-project detection\n if (baseResult.language === \"unknown\") {\n const subProjects = detectSubProjects(projectRoot);\n if (subProjects.length > 0) {\n baseResult.language = subProjects.length === 1 ? subProjects[0].language : \"multi\";\n baseResult.sub_projects = subProjects;\n if (subProjects.length === 1) {\n baseResult.framework = subProjects[0].framework;\n baseResult.package_manager = subProjects[0].package_manager;\n baseResult.detected_tools = subProjects[0].detected_tools;\n }\n }\n }\n\n return baseResult;\n}\n\n// ---------------------------------------------------------------------------\n// Node.js / package.json detector\n// ---------------------------------------------------------------------------\n\nfunction detectNodeProject(content: string, projectRoot: string): Partial<ProjectInfo> | null {\n let pkg: Record<string, unknown>;\n try {\n pkg = JSON.parse(content);\n } catch {\n return null;\n }\n\n const deps: Record<string, string> = {\n ...((pkg.dependencies as Record<string, string>) ?? {}),\n ...((pkg.devDependencies as Record<string, string>) ?? {}),\n };\n\n // Framework detection\n let framework: string | null = null;\n let frameworkVersion: string | null = null;\n\n if (deps[\"next\"]) {\n framework = \"nextjs\";\n frameworkVersion = cleanVersion(deps[\"next\"]);\n } else if (deps[\"@angular/core\"]) {\n framework = \"angular\";\n frameworkVersion = cleanVersion(deps[\"@angular/core\"]);\n } else if (deps[\"vue\"]) {\n framework = \"vue\";\n frameworkVersion = cleanVersion(deps[\"vue\"]);\n } else if (deps[\"react\"]) {\n framework = \"react\";\n frameworkVersion = cleanVersion(deps[\"react\"]);\n } else if (deps[\"express\"]) {\n framework = \"express\";\n frameworkVersion = cleanVersion(deps[\"express\"]);\n }\n\n // Language\n const language = deps[\"typescript\"] ? \"typescript\" : \"javascript\";\n\n // Package manager\n const packageManager = detectPackageManager(projectRoot, pkg);\n\n // Scripts\n const scripts: Record<string, string> = {};\n if (pkg.scripts && typeof pkg.scripts === \"object\") {\n for (const [k, v] of Object.entries(pkg.scripts as Record<string, string>)) {\n scripts[k] = v;\n }\n }\n\n // Entry points\n const entryPoints = detectNodeEntryPoints(pkg, projectRoot);\n\n return {\n name: (pkg.name as string) ?? path.basename(projectRoot),\n language,\n framework,\n framework_version: frameworkVersion,\n package_manager: packageManager,\n runtime: \"node\",\n entry_points: entryPoints,\n scripts,\n };\n}\n\nfunction cleanVersion(ver: string): string {\n return ver.replace(/^[\\^~>=<]+/, \"\");\n}\n\nfunction detectPackageManager(\n projectRoot: string,\n pkg: Record<string, unknown>,\n): string {\n // Check packageManager field first (corepack)\n if (typeof pkg.packageManager === \"string\") {\n const pm = pkg.packageManager as string;\n if (pm.startsWith(\"pnpm\")) return \"pnpm\";\n if (pm.startsWith(\"yarn\")) return \"yarn\";\n if (pm.startsWith(\"npm\")) return \"npm\";\n if (pm.startsWith(\"bun\")) return \"bun\";\n }\n\n // Lockfile sniffing\n if (fs.existsSync(path.join(projectRoot, \"pnpm-lock.yaml\"))) return \"pnpm\";\n if (fs.existsSync(path.join(projectRoot, \"yarn.lock\"))) return \"yarn\";\n if (fs.existsSync(path.join(projectRoot, \"bun.lockb\"))) return \"bun\";\n if (fs.existsSync(path.join(projectRoot, \"package-lock.json\"))) return \"npm\";\n\n return \"npm\"; // default fallback\n}\n\nfunction detectNodeEntryPoints(\n pkg: Record<string, unknown>,\n projectRoot: string,\n): string[] {\n const entries: string[] = [];\n\n // main field\n if (typeof pkg.main === \"string\") entries.push(pkg.main);\n\n // Conventional paths\n const conventionalPaths = [\n \"src/index.ts\",\n \"src/index.tsx\",\n \"src/index.js\",\n \"src/main.ts\",\n \"src/main.tsx\",\n \"src/app/layout.tsx\",\n \"src/app/page.tsx\",\n \"index.ts\",\n \"index.js\",\n ];\n\n for (const p of conventionalPaths) {\n if (fs.existsSync(path.join(projectRoot, p)) && !entries.includes(p)) {\n entries.push(p);\n }\n }\n\n return entries;\n}\n\n// ---------------------------------------------------------------------------\n// Python / pyproject.toml detector\n// ---------------------------------------------------------------------------\n\nfunction detectPythonProject(content: string, projectRoot: string): Partial<ProjectInfo> | null {\n // Simple TOML parsing for the fields we care about.\n // We avoid pulling in a full TOML parser to keep deps minimal.\n const name = extractTomlValue(content, \"name\") ?? path.basename(projectRoot);\n\n let framework: string | null = null;\n let frameworkVersion: string | null = null;\n\n // Check dependencies for frameworks (order matters — first match wins)\n const pyFrameworks: Array<{ names: string[]; label: string }> = [\n { names: [\"fastapi\", \"FastAPI\"], label: \"fastapi\" },\n { names: [\"django\", \"Django\"], label: \"django\" },\n { names: [\"flask\", \"Flask\"], label: \"flask\" },\n { names: [\"streamlit\", \"Streamlit\"], label: \"streamlit\" },\n { names: [\"gradio\", \"Gradio\"], label: \"gradio\" },\n ];\n\n for (const fw of pyFrameworks) {\n if (fw.names.some((n) => content.includes(n))) {\n framework = fw.label;\n frameworkVersion = extractTomlDependencyVersion(content, fw.names[0]);\n break;\n }\n }\n\n // Package manager\n let packageManager: string | null = null;\n if (content.includes(\"[tool.poetry]\")) {\n packageManager = \"poetry\";\n } else if (fs.existsSync(path.join(projectRoot, \"Pipfile\"))) {\n packageManager = \"pipenv\";\n } else if (fs.existsSync(path.join(projectRoot, \"uv.lock\"))) {\n packageManager = \"uv\";\n } else {\n packageManager = \"pip\";\n }\n\n // Entry points\n const entryPoints: string[] = [];\n const pyEntries = [\"src/main.py\", \"main.py\", \"app/main.py\", \"app.py\", \"manage.py\"];\n for (const p of pyEntries) {\n if (fs.existsSync(path.join(projectRoot, p))) {\n entryPoints.push(p);\n }\n }\n\n return {\n name,\n language: \"python\",\n framework,\n framework_version: frameworkVersion,\n package_manager: packageManager,\n runtime: \"python\",\n entry_points: entryPoints,\n scripts: {},\n };\n}\n\n// ---------------------------------------------------------------------------\n// Rust / Cargo.toml detector\n// ---------------------------------------------------------------------------\n\nfunction detectRustProject(content: string, projectRoot: string): Partial<ProjectInfo> | null {\n const name = extractTomlValue(content, \"name\") ?? path.basename(projectRoot);\n const edition = extractTomlValue(content, \"edition\");\n\n // Detect common Rust web frameworks in [dependencies]\n let framework: string | null = null;\n const rustFrameworks: Array<{ dep: string; label: string }> = [\n { dep: \"actix-web\", label: \"actix-web\" },\n { dep: \"axum\", label: \"axum\" },\n { dep: \"rocket\", label: \"rocket\" },\n { dep: \"tokio\", label: \"tokio\" },\n ];\n for (const fw of rustFrameworks) {\n // Match dependency name in TOML (e.g. `actix-web = ` or `actix-web.`)\n const depRegex = new RegExp(`^\\\\s*${fw.dep.replace(\"-\", \"[-]\")}\\\\s*[=.]`, \"m\");\n if (depRegex.test(content)) {\n framework = fw.label;\n break;\n }\n }\n\n const entryPoints: string[] = [];\n if (fs.existsSync(path.join(projectRoot, \"src/main.rs\"))) entryPoints.push(\"src/main.rs\");\n if (fs.existsSync(path.join(projectRoot, \"src/lib.rs\"))) entryPoints.push(\"src/lib.rs\");\n\n return {\n name,\n language: \"rust\",\n framework,\n framework_version: edition ? `edition-${edition}` : null,\n package_manager: \"cargo\",\n runtime: \"rust\",\n entry_points: entryPoints,\n scripts: {},\n };\n}\n\n// ---------------------------------------------------------------------------\n// Go / go.mod detector\n// ---------------------------------------------------------------------------\n\nfunction detectGoProject(content: string, projectRoot: string): Partial<ProjectInfo> | null {\n // Extract module path from first line: module github.com/user/repo\n const moduleMatch = content.match(/^module\\s+(.+)$/m);\n const modulePath = moduleMatch?.[1]?.trim() ?? \"\";\n const name = modulePath.split(\"/\").pop() ?? path.basename(projectRoot);\n\n const entryPoints: string[] = [];\n if (fs.existsSync(path.join(projectRoot, \"main.go\"))) entryPoints.push(\"main.go\");\n if (fs.existsSync(path.join(projectRoot, \"cmd\"))) {\n // Common Go pattern: cmd/<name>/main.go\n try {\n const cmdDirs = fs.readdirSync(path.join(projectRoot, \"cmd\"), { withFileTypes: true });\n for (const d of cmdDirs) {\n if (d.isDirectory()) {\n const mainGo = path.join(\"cmd\", d.name, \"main.go\");\n if (fs.existsSync(path.join(projectRoot, mainGo))) {\n entryPoints.push(mainGo);\n }\n }\n }\n } catch {\n // skip\n }\n }\n\n // Extract Go version from `go X.Y` line\n const goVersionMatch = content.match(/^go\\s+(\\d+\\.\\d+(?:\\.\\d+)?)/m);\n const goVersion = goVersionMatch?.[1] ?? null;\n\n // Detect common Go frameworks\n let framework: string | null = null;\n const goFrameworks: Array<{ path: string; label: string }> = [\n { path: \"github.com/gin-gonic/gin\", label: \"gin\" },\n { path: \"github.com/labstack/echo\", label: \"echo\" },\n { path: \"github.com/gofiber/fiber\", label: \"fiber\" },\n { path: \"github.com/go-chi/chi\", label: \"chi\" },\n ];\n for (const fw of goFrameworks) {\n if (content.includes(fw.path)) {\n framework = fw.label;\n break;\n }\n }\n\n return {\n name,\n language: \"go\",\n framework,\n framework_version: goVersion,\n package_manager: \"go\",\n runtime: \"go\",\n entry_points: entryPoints,\n scripts: {},\n };\n}\n\n// ---------------------------------------------------------------------------\n// Java / pom.xml detector\n// ---------------------------------------------------------------------------\n\nfunction detectJavaProject(content: string, projectRoot: string): Partial<ProjectInfo> | null {\n // Simple XML extraction\n const nameMatch = content.match(/<artifactId>([^<]+)<\\/artifactId>/);\n const name = nameMatch?.[1] ?? path.basename(projectRoot);\n\n let framework: string | null = null;\n let frameworkVersion: string | null = null;\n\n if (content.includes(\"spring-boot\")) {\n framework = \"spring-boot\";\n // Try to extract version from spring-boot-starter-parent <version> tag\n const parentMatch = content.match(\n /spring-boot-starter-parent[\\s\\S]*?<version>([^<]+)<\\/version>/,\n );\n frameworkVersion = parentMatch?.[1] ?? null;\n } else if (content.includes(\"quarkus\")) {\n framework = \"quarkus\";\n } else if (content.includes(\"micronaut\")) {\n framework = \"micronaut\";\n }\n\n const entryPoints: string[] = [];\n // Convention: src/main/java\n if (fs.existsSync(path.join(projectRoot, \"src/main/java\"))) {\n entryPoints.push(\"src/main/java\");\n }\n\n return {\n name,\n language: \"java\",\n framework,\n framework_version: frameworkVersion,\n package_manager: \"maven\",\n runtime: \"jvm\",\n entry_points: entryPoints,\n scripts: {},\n };\n}\n\n// ---------------------------------------------------------------------------\n// Gradle detector\n// ---------------------------------------------------------------------------\n\nfunction detectGradleProject(content: string, projectRoot: string): Partial<ProjectInfo> | null {\n const name = path.basename(projectRoot);\n const language = content.includes(\"kotlin\") || content.includes(\".kt\") ? \"kotlin\" : \"java\";\n\n let framework: string | null = null;\n if (content.includes(\"spring-boot\") || content.includes(\"org.springframework.boot\")) {\n framework = \"spring-boot\";\n } else if (content.includes(\"quarkus\")) {\n framework = \"quarkus\";\n } else if (content.includes(\"micronaut\")) {\n framework = \"micronaut\";\n }\n\n const entryPoints: string[] = [];\n if (fs.existsSync(path.join(projectRoot, \"src/main/java\"))) {\n entryPoints.push(\"src/main/java\");\n }\n if (fs.existsSync(path.join(projectRoot, \"src/main/kotlin\"))) {\n entryPoints.push(\"src/main/kotlin\");\n }\n\n return {\n name,\n language,\n framework,\n framework_version: null,\n package_manager: \"gradle\",\n runtime: \"jvm\",\n entry_points: entryPoints,\n scripts: {},\n };\n}\n\n// ---------------------------------------------------------------------------\n// Ruby / Gemfile detector\n// ---------------------------------------------------------------------------\n\nfunction detectRubyProject(content: string, projectRoot: string): Partial<ProjectInfo> | null {\n const name = path.basename(projectRoot);\n const framework = content.includes(\"rails\") || content.includes(\"'rails'\") ? \"rails\" : null;\n\n const entryPoints: string[] = [];\n if (fs.existsSync(path.join(projectRoot, \"config.ru\"))) entryPoints.push(\"config.ru\");\n if (fs.existsSync(path.join(projectRoot, \"app\"))) entryPoints.push(\"app/\");\n\n return {\n name,\n language: \"ruby\",\n framework,\n framework_version: null,\n package_manager: \"bundler\",\n runtime: \"ruby\",\n entry_points: entryPoints,\n scripts: {},\n };\n}\n\n// ---------------------------------------------------------------------------\n// Monorepo sub-project detection\n// ---------------------------------------------------------------------------\n\n/** Common workspace directory names that contain nested sub-projects. */\nconst WORKSPACE_DIR_NAMES = new Set([\n \"packages\",\n \"workspace\",\n \"workspaces\",\n \"libs\",\n \"apps\",\n \"modules\",\n \"services\",\n \"projects\",\n]);\n\n/**\n * Scan child directories for config files when root detection fails.\n * Also recurses into common workspace directories (packages/, libs/, apps/, etc.).\n * Returns sub-project info for each child that has a recognized config file.\n */\nfunction detectSubProjects(projectRoot: string): SubProject[] {\n const subProjects: SubProject[] = [];\n scanDirForSubProjects(projectRoot, projectRoot, subProjects, 0, 2);\n return subProjects;\n}\n\nfunction scanDirForSubProjects(\n dir: string,\n projectRoot: string,\n subProjects: SubProject[],\n depth: number,\n maxDepth: number,\n): void {\n if (depth >= maxDepth) return;\n\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (!entry.isDirectory() || entry.name.startsWith(\".\")) continue;\n\n const childPath = path.join(dir, entry.name);\n let detected = false;\n\n // Try each detector on this directory\n for (const detector of detectors) {\n const filePath = path.join(childPath, detector.file);\n if (fs.existsSync(filePath)) {\n try {\n const content = fs.readFileSync(filePath, \"utf-8\");\n const info = detector.detect(content, childPath);\n if (info?.language) {\n subProjects.push({\n path: path.relative(projectRoot, childPath),\n language: info.language,\n framework: info.framework ?? null,\n package_manager: info.package_manager ?? null,\n detected_tools: detectTools(childPath),\n });\n detected = true;\n break;\n }\n } catch {\n // skip\n }\n }\n }\n\n // If no config found and this looks like a workspace dir, recurse into it\n if (!detected && WORKSPACE_DIR_NAMES.has(entry.name.toLowerCase())) {\n scanDirForSubProjects(childPath, projectRoot, subProjects, depth + 1, maxDepth);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Tool detection (cross-language)\n// ---------------------------------------------------------------------------\n\nfunction detectTools(projectRoot: string): DetectedTools {\n const tools: DetectedTools = {\n linter: null,\n type_checker: null,\n test_runner: null,\n formatter: null,\n };\n\n // Linter\n const eslintFiles = [\n \".eslintrc\",\n \".eslintrc.js\",\n \".eslintrc.cjs\",\n \".eslintrc.json\",\n \".eslintrc.yaml\",\n \".eslintrc.yml\",\n \"eslint.config.js\",\n \"eslint.config.mjs\",\n \"eslint.config.cjs\",\n \"eslint.config.ts\",\n ];\n for (const f of eslintFiles) {\n if (fs.existsSync(path.join(projectRoot, f))) {\n tools.linter = \"eslint\";\n break;\n }\n }\n\n // Ruff (Python linter)\n if (\n !tools.linter &&\n (fs.existsSync(path.join(projectRoot, \"ruff.toml\")) ||\n fs.existsSync(path.join(projectRoot, \".ruff.toml\")))\n ) {\n tools.linter = \"ruff\";\n }\n // Also check pyproject.toml for [tool.ruff]\n if (!tools.linter) {\n const pyproject = path.join(projectRoot, \"pyproject.toml\");\n if (fs.existsSync(pyproject)) {\n try {\n const content = fs.readFileSync(pyproject, \"utf-8\");\n if (content.includes(\"[tool.ruff]\")) {\n tools.linter = \"ruff\";\n }\n } catch {\n // skip\n }\n }\n }\n\n // Clippy (Rust linter)\n if (!tools.linter && fs.existsSync(path.join(projectRoot, \"Cargo.toml\"))) {\n tools.linter = \"clippy\";\n }\n\n // Type checker\n if (fs.existsSync(path.join(projectRoot, \"tsconfig.json\"))) {\n tools.type_checker = \"tsc\";\n }\n // mypy\n if (\n fs.existsSync(path.join(projectRoot, \"mypy.ini\")) ||\n fs.existsSync(path.join(projectRoot, \".mypy.ini\"))\n ) {\n tools.type_checker = \"mypy\";\n }\n // Also check pyproject.toml for [tool.mypy]\n if (!tools.type_checker) {\n const pyproject = path.join(projectRoot, \"pyproject.toml\");\n if (fs.existsSync(pyproject)) {\n try {\n const content = fs.readFileSync(pyproject, \"utf-8\");\n if (content.includes(\"[tool.mypy]\")) {\n tools.type_checker = \"mypy\";\n }\n } catch {\n // skip\n }\n }\n }\n\n // Test runner\n const jestFiles = [\n \"jest.config.js\",\n \"jest.config.ts\",\n \"jest.config.cjs\",\n \"jest.config.mjs\",\n \"jest.config.json\",\n ];\n const vitestFiles = [\n \"vitest.config.ts\",\n \"vitest.config.js\",\n \"vitest.config.mjs\",\n ];\n\n for (const f of vitestFiles) {\n if (fs.existsSync(path.join(projectRoot, f))) {\n tools.test_runner = \"vitest\";\n break;\n }\n }\n if (!tools.test_runner) {\n for (const f of jestFiles) {\n if (fs.existsSync(path.join(projectRoot, f))) {\n tools.test_runner = \"jest\";\n break;\n }\n }\n }\n // pytest\n if (!tools.test_runner) {\n const pyproject = path.join(projectRoot, \"pyproject.toml\");\n if (fs.existsSync(pyproject)) {\n try {\n const content = fs.readFileSync(pyproject, \"utf-8\");\n if (content.includes(\"[tool.pytest]\") || content.includes(\"pytest\")) {\n tools.test_runner = \"pytest\";\n }\n } catch {\n // skip\n }\n }\n }\n\n // Formatter\n const prettierFiles = [\n \".prettierrc\",\n \".prettierrc.js\",\n \".prettierrc.cjs\",\n \".prettierrc.json\",\n \".prettierrc.yaml\",\n \".prettierrc.yml\",\n \".prettierrc.toml\",\n \"prettier.config.js\",\n \"prettier.config.cjs\",\n \"prettier.config.mjs\",\n ];\n for (const f of prettierFiles) {\n if (fs.existsSync(path.join(projectRoot, f))) {\n tools.formatter = \"prettier\";\n break;\n }\n }\n\n // Check for biome\n if (!tools.formatter && fs.existsSync(path.join(projectRoot, \"biome.json\"))) {\n tools.formatter = \"biome\";\n }\n\n return tools;\n}\n\n// ---------------------------------------------------------------------------\n// Conventional entry point detection (when no config file matched)\n// ---------------------------------------------------------------------------\n\nfunction detectConventionalEntryPoints(projectRoot: string): string[] {\n const entries: string[] = [];\n const candidates = [\n \"src/index.ts\",\n \"src/index.js\",\n \"src/main.ts\",\n \"src/main.py\",\n \"main.go\",\n \"src/main.rs\",\n \"src/lib.rs\",\n \"index.ts\",\n \"index.js\",\n \"main.py\",\n \"app.py\",\n ];\n for (const p of candidates) {\n if (fs.existsSync(path.join(projectRoot, p))) {\n entries.push(p);\n }\n }\n return entries;\n}\n\n// ---------------------------------------------------------------------------\n// Minimal TOML value extraction\n// ---------------------------------------------------------------------------\n\n/**\n * Extract a simple string value from TOML content.\n * Handles: key = \"value\" patterns. Not a full TOML parser.\n */\nfunction extractTomlValue(content: string, key: string): string | null {\n const regex = new RegExp(`^\\\\s*${key}\\\\s*=\\\\s*\"([^\"]*)\"`, \"m\");\n const match = content.match(regex);\n return match?.[1] ?? null;\n}\n\n/**\n * Extract a dependency version from TOML content.\n *\n * Handles two common formats:\n * 1. Poetry-style: `packageName = \"^0.100.0\"` or `packageName = {version = \"...\"}`\n * 2. PEP 621 array entries: `\"packageName>=0.100.0\"` inside `[project.dependencies]`\n *\n * Returns the cleaned version (without ^, ~, >=, etc.) or null.\n */\nfunction extractTomlDependencyVersion(content: string, packageName: string): string | null {\n // Try Poetry-style: packageName = \"^1.2.3\"\n const poetryRegex = new RegExp(\n `^\\\\s*${packageName}\\\\s*=\\\\s*\"([^\"]*)\"`,\n \"im\",\n );\n const poetryMatch = content.match(poetryRegex);\n if (poetryMatch?.[1]) {\n return cleanVersion(poetryMatch[1]);\n }\n\n // Try PEP 621 array entries: \"packageName>=1.2.3\" or \"packageName==1.2.3\"\n const pep621Regex = new RegExp(\n `\"${packageName}\\\\s*([><=!~]+\\\\s*[\\\\d][^\"]*)\"`,\n \"i\",\n );\n const pep621Match = content.match(pep621Regex);\n if (pep621Match?.[1]) {\n return cleanVersion(pep621Match[1]);\n }\n\n return null;\n}\n","/**\n * Smart file tree builder.\n *\n * Walks a project directory recursively and returns a structured tree\n * with collapse rules for heavy/generated directories.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { FileTreeEntry, CollapsedDir, FileEntry } from \"../../types/index.js\";\nimport type { ResolvedConfig } from \"../../config/index.js\";\nimport { AUTO_COLLAPSE_FILE_THRESHOLD } from \"../../config/index.js\";\n\n/** Source code extensions used for the auto-collapse heuristic. */\nconst SOURCE_EXTENSIONS = new Set([\n \".ts\",\n \".tsx\",\n \".js\",\n \".jsx\",\n \".mjs\",\n \".cjs\",\n \".py\",\n \".rs\",\n \".go\",\n \".java\",\n \".kt\",\n \".rb\",\n \".c\",\n \".cpp\",\n \".h\",\n \".hpp\",\n \".cs\",\n \".swift\",\n \".scala\",\n \".clj\",\n \".ex\",\n \".exs\",\n \".lua\",\n \".sh\",\n \".bash\",\n \".zsh\",\n \".fish\",\n \".vue\",\n \".svelte\",\n]);\n\n/**\n * Build a file tree for the given project root.\n */\nexport function buildFileTree(\n projectRoot: string,\n config: ResolvedConfig,\n): Record<string, FileTreeEntry> {\n return walkDirectory(projectRoot, projectRoot, config, 0);\n}\n\n// ---------------------------------------------------------------------------\n// Internal\n// ---------------------------------------------------------------------------\n\nfunction walkDirectory(\n dirPath: string,\n projectRoot: string,\n config: ResolvedConfig,\n depth: number,\n): Record<string, FileTreeEntry> {\n const result: Record<string, FileTreeEntry> = {};\n\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dirPath, { withFileTypes: true });\n } catch {\n return result;\n }\n\n // Separate into dirs and files, sort alphabetically within each group\n const dirs = entries.filter((e) => e.isDirectory()).sort((a, b) => a.name.localeCompare(b.name));\n const files = entries.filter((e) => e.isFile()).sort((a, b) => a.name.localeCompare(b.name));\n\n // Process directories first\n for (const dir of dirs) {\n const dirName = dir.name + \"/\";\n const fullPath = path.join(dirPath, dir.name);\n\n // Check if this directory should be collapsed\n if (config.collapse_dirs.includes(dir.name)) {\n result[dirName] = collapseDirectory(fullPath);\n continue;\n }\n\n // Depth limit\n if (depth >= config.tree_depth) {\n result[dirName] = collapseDirectory(fullPath);\n continue;\n }\n\n // Auto-collapse: dirs with >500 files and no source code\n const autoCollapseResult = shouldAutoCollapse(fullPath);\n if (autoCollapseResult !== null) {\n result[dirName] = autoCollapseResult;\n continue;\n }\n\n // Recurse\n result[dirName] = walkDirectory(fullPath, projectRoot, config, depth + 1);\n }\n\n // Process files\n for (const file of files) {\n if (shouldIgnoreFile(file.name, config.ignore_patterns)) {\n continue;\n }\n\n const fullPath = path.join(dirPath, file.name);\n let size = 0;\n try {\n const stat = fs.statSync(fullPath);\n size = stat.size;\n } catch {\n // Skip files we can't stat\n continue;\n }\n\n const entry: FileEntry = { size };\n result[file.name] = entry;\n }\n\n return result;\n}\n\n/**\n * Count all files in a directory recursively and return a collapsed entry.\n */\nfunction collapseDirectory(dirPath: string): CollapsedDir {\n return {\n _collapsed: true,\n file_count: countFiles(dirPath),\n };\n}\n\n/**\n * Recursively count files in a directory. Capped at 100k to avoid\n * spending too long on massive directories.\n */\nfunction countFiles(dirPath: string, limit = 100_000): number {\n let count = 0;\n const stack = [dirPath];\n\n while (stack.length > 0 && count < limit) {\n const current = stack.pop()!;\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(current, { withFileTypes: true });\n } catch {\n continue;\n }\n for (const entry of entries) {\n if (count >= limit) break;\n if (entry.isFile()) {\n count++;\n } else if (entry.isDirectory()) {\n stack.push(path.join(current, entry.name));\n }\n }\n }\n\n return count;\n}\n\n/**\n * Check whether a directory should be auto-collapsed.\n * Returns a CollapsedDir if yes, null if no.\n */\nfunction shouldAutoCollapse(dirPath: string): CollapsedDir | null {\n let fileCount = 0;\n let hasSource = false;\n const stack = [dirPath];\n\n while (stack.length > 0 && fileCount <= AUTO_COLLAPSE_FILE_THRESHOLD) {\n const current = stack.pop()!;\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(current, { withFileTypes: true });\n } catch {\n continue;\n }\n for (const entry of entries) {\n if (entry.isFile()) {\n fileCount++;\n if (!hasSource) {\n const ext = path.extname(entry.name).toLowerCase();\n if (SOURCE_EXTENSIONS.has(ext)) {\n hasSource = true;\n }\n }\n } else if (entry.isDirectory()) {\n stack.push(path.join(current, entry.name));\n }\n }\n }\n\n if (fileCount > AUTO_COLLAPSE_FILE_THRESHOLD && !hasSource) {\n return { _collapsed: true, file_count: fileCount };\n }\n\n return null;\n}\n\n/**\n * Check if a filename matches any of the ignore patterns.\n * Supports basic glob matching: `*` matches any sequence of chars.\n */\nfunction shouldIgnoreFile(fileName: string, patterns: string[]): boolean {\n for (const pattern of patterns) {\n if (matchGlob(pattern, fileName)) return true;\n }\n return false;\n}\n\n/**\n * Simple glob matcher. Supports `*` as wildcard.\n */\nfunction matchGlob(pattern: string, input: string): boolean {\n const regex = new RegExp(\n \"^\" + pattern.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\").replace(/\\*/g, \".*\") + \"$\",\n );\n return regex.test(input);\n}\n","/**\n * Git service — shell out to `git` CLI for repository operations.\n */\n\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * Get the current HEAD commit hash (short form).\n * Returns null if the path is not a git repository.\n */\nexport async function getHead(projectRoot: string): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"rev-parse\", \"--short\", \"HEAD\"], {\n cwd: projectRoot,\n });\n return stdout.trim() || null;\n } catch {\n return null;\n }\n}\n\n/**\n * Check whether a path is inside a git repository.\n */\nexport async function isGitRepo(projectRoot: string): Promise<boolean> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"rev-parse\", \"--is-inside-work-tree\"],\n { cwd: projectRoot },\n );\n return stdout.trim() === \"true\";\n } catch {\n return false;\n }\n}\n\n/**\n * Get the full HEAD commit hash.\n * Returns null if the path is not a git repository.\n */\nexport async function getFullHead(projectRoot: string): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"rev-parse\", \"HEAD\"], {\n cwd: projectRoot,\n });\n return stdout.trim() || null;\n } catch {\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Diff & Change Detection (Phase 5)\n// ---------------------------------------------------------------------------\n\n/** A file change entry from git diff. */\nexport interface GitFileChange {\n path: string;\n status: string;\n oldPath?: string;\n}\n\n/**\n * Get files changed between a commit and HEAD via `git diff --name-status`.\n */\nexport async function getDiffNameStatus(\n projectRoot: string,\n sinceCommit: string,\n): Promise<GitFileChange[]> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"diff\", \"--name-status\", sinceCommit, \"HEAD\"],\n { cwd: projectRoot },\n );\n return parseDiffNameStatus(stdout);\n } catch {\n return [];\n }\n}\n\n/**\n * Get uncommitted changes (staged + unstaged + untracked).\n */\nexport async function getUncommittedChanges(\n projectRoot: string,\n): Promise<GitFileChange[]> {\n const changes = new Map<string, GitFileChange>();\n\n // Staged changes (index vs HEAD)\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"diff\", \"--name-status\", \"--cached\"],\n { cwd: projectRoot },\n );\n for (const entry of parseDiffNameStatus(stdout)) {\n changes.set(entry.path, entry);\n }\n } catch {\n // skip\n }\n\n // Unstaged changes (working tree vs index)\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"diff\", \"--name-status\"],\n { cwd: projectRoot },\n );\n for (const entry of parseDiffNameStatus(stdout)) {\n changes.set(entry.path, entry);\n }\n } catch {\n // skip\n }\n\n // Untracked files\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"ls-files\", \"--others\", \"--exclude-standard\"],\n { cwd: projectRoot },\n );\n for (const line of stdout.split(\"\\n\")) {\n const trimmed = line.trim();\n if (trimmed) {\n changes.set(trimmed, { path: trimmed, status: \"A\" });\n }\n }\n } catch {\n // skip\n }\n\n return [...changes.values()];\n}\n\n/**\n * Get commit hashes that came from upstream (pull) in a given range.\n * Returns empty set if no upstream is configured.\n */\nexport async function getPullCommitHashes(\n projectRoot: string,\n sinceCommit: string,\n): Promise<Set<string>> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"log\", \"--format=%H\", `${sinceCommit}..@{upstream}`],\n { cwd: projectRoot },\n );\n const hashes = new Set<string>();\n for (const line of stdout.split(\"\\n\")) {\n const trimmed = line.trim();\n if (trimmed) hashes.add(trimmed);\n }\n return hashes;\n } catch {\n return new Set();\n }\n}\n\n/**\n * Get the most recent commit info for a file in a given range.\n */\nexport async function getFileCommitInfo(\n projectRoot: string,\n filePath: string,\n sinceCommit: string,\n): Promise<{ hash: string; author: string; message: string } | null> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"log\", \"-1\", \"--format=%H|||%an|||%s\", `${sinceCommit}..HEAD`, \"--\", filePath],\n { cwd: projectRoot },\n );\n const trimmed = stdout.trim();\n if (!trimmed) return null;\n\n const parts = trimmed.split(\"|||\");\n if (parts.length < 3) return null;\n\n return {\n hash: parts[0],\n author: parts[1],\n message: parts.slice(2).join(\"|||\"),\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Get the current user's email from git config.\n */\nexport async function getUserEmail(projectRoot: string): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"config\", \"user.email\"],\n { cwd: projectRoot },\n );\n return stdout.trim() || null;\n } catch {\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Parse git diff --name-status output. */\nfunction parseDiffNameStatus(output: string): GitFileChange[] {\n const results: GitFileChange[] = [];\n\n for (const line of output.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n const parts = trimmed.split(\"\\t\");\n if (parts.length < 2) continue;\n\n const status = parts[0];\n\n if (status.startsWith(\"R\")) {\n // Rename: R100\\told_path\\tnew_path\n results.push({\n path: parts[2] || parts[1],\n status: \"R\",\n oldPath: parts[1],\n });\n } else {\n results.push({\n path: parts[1],\n status: status.charAt(0), // Normalize to single char (A, M, D)\n });\n }\n }\n\n return results;\n}\n","/**\n * Cache service — read/write `.inspect/` directory for persistent state.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { ScanResultSchema, CacheMetaSchema, type ScanResult, type CacheMeta } from \"../../types/index.js\";\nimport { TOOL_VERSION } from \"../../config/index.js\";\n\nconst INSPECT_DIR = \".inspect\";\nconst STATE_FILE = \"state.json\";\nconst META_FILE = \"meta.json\";\n\n/**\n * Read the cached scan result from `.inspect/state.json`.\n * Returns null if cache does not exist or is invalid.\n */\nexport function readCache(projectRoot: string): ScanResult | null {\n const statePath = path.join(projectRoot, INSPECT_DIR, STATE_FILE);\n if (!fs.existsSync(statePath)) return null;\n\n try {\n const raw = JSON.parse(fs.readFileSync(statePath, \"utf-8\"));\n return ScanResultSchema.parse(raw);\n } catch {\n return null;\n }\n}\n\n/**\n * Read cache metadata from `.inspect/meta.json`.\n * Returns null if metadata does not exist or is invalid.\n */\nexport function readMeta(projectRoot: string): CacheMeta | null {\n const metaPath = path.join(projectRoot, INSPECT_DIR, META_FILE);\n if (!fs.existsSync(metaPath)) return null;\n\n try {\n const raw = JSON.parse(fs.readFileSync(metaPath, \"utf-8\"));\n return CacheMetaSchema.parse(raw);\n } catch {\n return null;\n }\n}\n\n/**\n * Write scan result and metadata to the `.inspect/` directory.\n */\nexport function writeCache(\n projectRoot: string,\n result: ScanResult,\n gitHead: string | null,\n): void {\n const inspectDir = path.join(projectRoot, INSPECT_DIR);\n if (!fs.existsSync(inspectDir)) {\n fs.mkdirSync(inspectDir, { recursive: true });\n }\n\n const meta: CacheMeta = {\n version: TOOL_VERSION,\n git_head: gitHead,\n scanned_at: new Date().toISOString(),\n };\n\n fs.writeFileSync(\n path.join(inspectDir, STATE_FILE),\n JSON.stringify(result, null, 2),\n \"utf-8\",\n );\n\n fs.writeFileSync(\n path.join(inspectDir, META_FILE),\n JSON.stringify(meta, null, 2),\n \"utf-8\",\n );\n}\n\n/**\n * Check whether the cache is still valid by comparing the stored HEAD\n * with the current HEAD.\n */\nexport function isCacheValid(projectRoot: string, currentHead: string | null): boolean {\n const meta = readMeta(projectRoot);\n if (!meta) return false;\n if (meta.version !== TOOL_VERSION) return false;\n return meta.git_head === currentHead;\n}\n\n/**\n * Remove the `.inspect/` directory entirely.\n */\nexport function clearCache(projectRoot: string): void {\n const inspectDir = path.join(projectRoot, INSPECT_DIR);\n if (fs.existsSync(inspectDir)) {\n fs.rmSync(inspectDir, { recursive: true, force: true });\n }\n}\n","/**\n * Symbol index builder.\n *\n * Collects all parseable source files from a project, parses them\n * in parallel with a concurrency limit, and returns a symbol index.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { Symbol } from \"../../types/index.js\";\nimport type { ResolvedConfig } from \"../../config/index.js\";\nimport { parseSource, getGrammarForFile } from \"./index.js\";\nimport { getExtractor } from \"./extractors/index.js\";\nimport { collectSourceFiles, withConcurrency, DEFAULT_CONCURRENCY } from \"./utils.js\";\n\n/**\n * Build a symbol index for all parseable files in the project.\n *\n * @returns Map of relative file path to symbol array.\n */\nexport async function buildSymbolIndex(\n projectRoot: string,\n config: ResolvedConfig,\n preCollectedFiles?: string[],\n): Promise<Record<string, Symbol[]>> {\n const files = preCollectedFiles ?? collectSourceFiles(projectRoot, config);\n const index: Record<string, Symbol[]> = {};\n\n await withConcurrency(\n files.map((filePath) => async () => {\n const relativePath = path.relative(projectRoot, filePath);\n const symbols = await extractSymbolsFromFile(filePath, relativePath);\n if (symbols && symbols.length > 0) {\n index[relativePath] = symbols;\n }\n }),\n DEFAULT_CONCURRENCY,\n );\n\n return index;\n}\n\n/**\n * Incrementally update a cached symbol index by re-parsing only changed files.\n *\n * @param cached The previous symbol index from cache.\n * @param changedFiles Relative paths of files that were added or modified.\n * @param deletedFiles Relative paths of files that were deleted.\n * @param projectRoot Absolute path to the project root.\n * @returns Updated symbol index.\n */\nexport async function updateSymbolIndex(\n cached: Record<string, Symbol[]>,\n changedFiles: string[],\n deletedFiles: string[],\n projectRoot: string,\n): Promise<Record<string, Symbol[]>> {\n const index: Record<string, Symbol[]> = { ...cached };\n\n // Remove deleted files\n for (const file of deletedFiles) {\n delete index[file];\n }\n\n // Re-parse changed files\n await withConcurrency(\n changedFiles.map((relativePath) => async () => {\n const symbols = await extractSymbolsForFile(projectRoot, relativePath);\n if (symbols.length > 0) {\n index[relativePath] = symbols;\n } else {\n delete index[relativePath];\n }\n }),\n DEFAULT_CONCURRENCY,\n );\n\n return index;\n}\n\n// ---------------------------------------------------------------------------\n// Symbol extraction\n// ---------------------------------------------------------------------------\n\n/**\n * Extract symbols from a single file.\n *\n * @param projectRoot Absolute path to the project root.\n * @param relativePath Project-relative file path.\n * @returns Array of symbols, or empty array if extraction fails.\n */\nexport async function extractSymbolsForFile(\n projectRoot: string,\n relativePath: string,\n): Promise<Symbol[]> {\n const filePath = path.join(projectRoot, relativePath);\n const symbols = await extractSymbolsFromFile(filePath, relativePath);\n return symbols ?? [];\n}\n\nasync function extractSymbolsFromFile(\n filePath: string,\n relativePath: string,\n): Promise<Symbol[] | null> {\n let source: string;\n try {\n source = fs.readFileSync(filePath, \"utf-8\");\n } catch {\n return null;\n }\n\n const tree = await parseSource(relativePath, source);\n if (!tree) return null;\n\n const grammarName = getGrammarForFile(relativePath);\n if (!grammarName) return null;\n\n const extractor = getExtractor(grammarName);\n if (!extractor) return null;\n\n return extractor.extract(tree, relativePath);\n}\n","/**\n * Tree-sitter WASM grammar loader.\n *\n * Handles one-time Parser.init() and lazy-loads language grammars from\n * the tree-sitter-wasms package. Grammars are cached after first load.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { createRequire } from \"node:module\";\nimport Parser from \"web-tree-sitter\";\n\nconst require = createRequire(import.meta.url);\n\n// ---------------------------------------------------------------------------\n// Singleton init\n// ---------------------------------------------------------------------------\n\nlet initPromise: Promise<void> | null = null;\n\n/**\n * Initialize the tree-sitter WASM runtime. Safe to call multiple times —\n * only the first call does real work.\n */\nexport function ensureInit(): Promise<void> {\n if (!initPromise) {\n initPromise = Parser.init();\n }\n return initPromise;\n}\n\n// ---------------------------------------------------------------------------\n// Grammar cache\n// ---------------------------------------------------------------------------\n\nconst grammarCache = new Map<string, Parser.Language>();\n\n/**\n * Resolve the filesystem path to a `.wasm` grammar file shipped by\n * the `tree-sitter-wasms` package.\n */\nfunction resolveGrammarPath(grammarName: string): string {\n // tree-sitter-wasms stores files at out/tree-sitter-<lang>.wasm\n const wasmFile = `tree-sitter-${grammarName}.wasm`;\n\n const fromNodeModules = path.join(\n path.dirname(require.resolve(\"tree-sitter-wasms/package.json\")),\n \"out\",\n wasmFile,\n );\n if (fs.existsSync(fromNodeModules)) return fromNodeModules;\n\n throw new Error(`Grammar WASM not found for \"${grammarName}\" at ${fromNodeModules}`);\n}\n\n/**\n * Load a tree-sitter language grammar by name. Caches the result so\n * subsequent calls for the same grammar are instant.\n *\n * @param grammarName — the grammar identifier (e.g. \"typescript\", \"java\")\n */\nexport async function loadGrammar(grammarName: string): Promise<Parser.Language> {\n const cached = grammarCache.get(grammarName);\n if (cached) return cached;\n\n await ensureInit();\n\n const wasmPath = resolveGrammarPath(grammarName);\n const language = await Parser.Language.load(wasmPath);\n\n grammarCache.set(grammarName, language);\n return language;\n}\n\n/**\n * Create a new Parser instance configured for a given grammar.\n */\nexport async function createParser(grammarName: string): Promise<Parser> {\n await ensureInit();\n const language = await loadGrammar(grammarName);\n const parser = new Parser();\n parser.setLanguage(language);\n return parser;\n}\n\n/**\n * Reset internal state. Only used in tests.\n */\nexport function _resetForTesting(): void {\n grammarCache.clear();\n initPromise = null;\n}\n","/**\n * Parser service — public API for tree-sitter parsing.\n *\n * Maps file extensions to tree-sitter grammars and provides a single\n * `parseSource` entry point for the rest of the application.\n */\n\nimport type Parser from \"web-tree-sitter\";\nimport { createParser } from \"./grammar-loader.js\";\n\n// ---------------------------------------------------------------------------\n// Extension → grammar mapping\n// ---------------------------------------------------------------------------\n\nconst EXTENSION_TO_GRAMMAR: Record<string, string> = {\n \".ts\": \"typescript\",\n \".tsx\": \"typescript\",\n \".js\": \"javascript\",\n \".jsx\": \"javascript\",\n \".mjs\": \"javascript\",\n \".cjs\": \"javascript\",\n \".py\": \"python\",\n \".java\": \"java\",\n};\n\n/** File extensions that the parser service can handle. */\nexport const SUPPORTED_EXTENSIONS = new Set(Object.keys(EXTENSION_TO_GRAMMAR));\n\n/**\n * Get the grammar name for a file path based on its extension.\n * Returns null if the extension is not supported.\n */\nexport function getGrammarForFile(filePath: string): string | null {\n const ext = getExtension(filePath);\n return EXTENSION_TO_GRAMMAR[ext] ?? null;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Parse source code using the appropriate tree-sitter grammar.\n *\n * Creates a fresh parser per call. Tree-sitter WASM parsers are NOT safe\n * to use concurrently — sharing a single instance across parallel async\n * tasks causes WASM memory corruption (\"Aborted()\" crashes). Grammar\n * loading is cached so the overhead is just the Parser() constructor.\n *\n * @param filePath — used to determine the language grammar (by extension)\n * @param source — the source code text to parse\n * @returns the parsed Tree, or null if the file extension is unsupported\n */\nexport async function parseSource(filePath: string, source: string): Promise<Parser.Tree | null> {\n const grammarName = getGrammarForFile(filePath);\n if (!grammarName) return null;\n\n const parser = await createParser(grammarName);\n return parser.parse(source);\n}\n\n/**\n * Reset internal state. Only used in tests.\n */\nexport function _resetForTesting(): void {\n // grammar cache lives in grammar-loader.ts\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction getExtension(filePath: string): string {\n const lastDot = filePath.lastIndexOf(\".\");\n if (lastDot === -1) return \"\";\n return filePath.slice(lastDot);\n}\n","/**\n * TypeScript / JavaScript symbol extractor.\n *\n * Extracts functions, arrow functions, classes (with methods/fields),\n * interfaces, and type aliases from TypeScript/JavaScript ASTs.\n * Works for both TS and JS — JS simply won't produce interface or\n * type_alias nodes.\n */\n\nimport type Parser from \"web-tree-sitter\";\nimport type { Symbol, SymbolKind } from \"../../../types/index.js\";\nimport type { SymbolExtractor } from \"./types.js\";\n\ntype SyntaxNode = Parser.SyntaxNode;\n\nexport class TypeScriptExtractor implements SymbolExtractor {\n extract(tree: Parser.Tree, _filePath: string): Symbol[] {\n const symbols: Symbol[] = [];\n this.visitTopLevel(tree.rootNode, symbols);\n return symbols;\n }\n\n private visitTopLevel(root: SyntaxNode, symbols: Symbol[]): void {\n for (let i = 0; i < root.childCount; i++) {\n const node = root.child(i)!;\n\n if (node.type === \"export_statement\") {\n this.extractExport(node, symbols);\n } else {\n this.extractDeclaration(node, false, symbols);\n }\n }\n }\n\n private extractExport(node: SyntaxNode, symbols: Symbol[]): void {\n const isDefault = node.children.some((c) => c.type === \"default\");\n\n for (let i = 0; i < node.childCount; i++) {\n const child = node.child(i)!;\n this.extractDeclaration(child, true, symbols, isDefault);\n }\n }\n\n private extractDeclaration(\n node: SyntaxNode,\n exported: boolean,\n symbols: Symbol[],\n isDefault = false,\n ): void {\n switch (node.type) {\n case \"function_declaration\":\n symbols.push(this.buildFunctionSymbol(node, exported, \"function\"));\n break;\n\n case \"lexical_declaration\":\n case \"variable_declaration\":\n this.extractVariableDeclarations(node, exported, symbols);\n break;\n\n case \"class_declaration\":\n this.extractClass(node, exported, isDefault, symbols);\n break;\n\n case \"interface_declaration\":\n symbols.push(this.buildSimpleSymbol(node, exported, \"interface\"));\n break;\n\n case \"type_alias_declaration\":\n symbols.push(this.buildSimpleSymbol(node, exported, \"type_alias\"));\n break;\n }\n }\n\n private buildFunctionSymbol(\n node: SyntaxNode,\n exported: boolean,\n kind: SymbolKind,\n ): Symbol {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n const isAsync = node.children.some((c) => c.type === \"async\");\n const signature = this.extractFunctionSignature(node);\n\n return {\n name,\n kind,\n exported,\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n signature,\n is_async: isAsync || undefined,\n };\n }\n\n private extractVariableDeclarations(\n node: SyntaxNode,\n exported: boolean,\n symbols: Symbol[],\n ): void {\n for (let i = 0; i < node.childCount; i++) {\n const child = node.child(i)!;\n if (child.type !== \"variable_declarator\") continue;\n\n const nameNode = child.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n const valueNode = child.childForFieldName(\"value\");\n\n if (valueNode?.type === \"arrow_function\") {\n const isAsync = valueNode.children.some((c) => c.type === \"async\");\n const signature = this.extractArrowSignature(valueNode);\n symbols.push({\n name,\n kind: \"arrow_function\",\n exported,\n line: child.startPosition.row + 1,\n end_line: child.endPosition.row + 1,\n signature,\n is_async: isAsync || undefined,\n });\n } else {\n symbols.push({\n name,\n kind: \"constant\",\n exported,\n line: child.startPosition.row + 1,\n end_line: child.endPosition.row + 1,\n });\n }\n }\n }\n\n private extractClass(\n node: SyntaxNode,\n exported: boolean,\n isDefault: boolean,\n symbols: Symbol[],\n ): void {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? (isDefault ? \"(default)\" : \"(anonymous)\");\n\n symbols.push({\n name,\n kind: \"class\",\n exported,\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n });\n\n const body = node.childForFieldName(\"body\");\n if (!body) return;\n\n for (let i = 0; i < body.childCount; i++) {\n const member = body.child(i)!;\n\n if (member.type === \"method_definition\") {\n this.extractMethod(member, symbols);\n } else if (member.type === \"public_field_definition\") {\n this.extractField(member, symbols);\n }\n }\n }\n\n private extractMethod(node: SyntaxNode, symbols: Symbol[]): void {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n const isAsync = node.children.some((c) => c.type === \"async\");\n const signature = this.extractFunctionSignature(node);\n\n symbols.push({\n name,\n kind: \"method\",\n exported: false,\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n signature,\n is_async: isAsync || undefined,\n });\n }\n\n private extractField(node: SyntaxNode, symbols: Symbol[]): void {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n const typeAnnotation = node.children.find((c) => c.type === \"type_annotation\");\n const signature = typeAnnotation ? typeAnnotation.text.slice(2).trim() : null;\n\n symbols.push({\n name,\n kind: \"field\",\n exported: false,\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n signature,\n });\n }\n\n private buildSimpleSymbol(\n node: SyntaxNode,\n exported: boolean,\n kind: SymbolKind,\n ): Symbol {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n\n return {\n name,\n kind,\n exported,\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n };\n }\n\n private extractFunctionSignature(node: SyntaxNode): string | null {\n const params = node.children.find((c) => c.type === \"formal_parameters\");\n const returnType = node.children.find((c) => c.type === \"type_annotation\");\n\n if (!params) return null;\n\n let sig = params.text;\n if (returnType) {\n sig += returnType.text;\n }\n return sig;\n }\n\n private extractArrowSignature(node: SyntaxNode): string | null {\n const params = node.children.find((c) => c.type === \"formal_parameters\");\n const returnType = node.children.find((c) => c.type === \"type_annotation\");\n\n if (!params) return null;\n\n let sig = params.text;\n if (returnType) {\n sig += returnType.text;\n }\n return sig;\n }\n}\n","/**\n * Python symbol extractor.\n *\n * Extracts module-level functions, classes (with methods), and uses\n * __all__ for export control or _ prefix convention for private symbols.\n */\n\nimport type Parser from \"web-tree-sitter\";\nimport type { Symbol } from \"../../../types/index.js\";\nimport type { SymbolExtractor } from \"./types.js\";\n\ntype SyntaxNode = Parser.SyntaxNode;\n\nexport class PythonExtractor implements SymbolExtractor {\n extract(tree: Parser.Tree, _filePath: string): Symbol[] {\n const symbols: Symbol[] = [];\n const allList = this.extractAllList(tree.rootNode);\n\n for (let i = 0; i < tree.rootNode.childCount; i++) {\n const node = tree.rootNode.child(i)!;\n this.visitTopLevel(node, symbols, allList);\n }\n\n return symbols;\n }\n\n /**\n * Extract the __all__ list if present. Returns null if not defined,\n * meaning all non-underscore symbols are considered exported.\n */\n private extractAllList(root: SyntaxNode): Set<string> | null {\n for (let i = 0; i < root.childCount; i++) {\n const node = root.child(i)!;\n if (node.type !== \"expression_statement\") continue;\n\n const assignment = node.child(0);\n if (assignment?.type !== \"assignment\") continue;\n\n const left = assignment.childForFieldName(\"left\");\n if (left?.type !== \"identifier\" || left.text !== \"__all__\") continue;\n\n const right = assignment.childForFieldName(\"right\");\n if (!right || right.type !== \"list\") continue;\n\n const names = new Set<string>();\n for (let j = 0; j < right.childCount; j++) {\n const elem = right.child(j)!;\n if (elem.type === \"string\") {\n // Strip quotes\n const raw = elem.text;\n const unquoted = raw.slice(1, -1);\n if (unquoted) names.add(unquoted);\n }\n }\n return names;\n }\n return null;\n }\n\n private visitTopLevel(\n node: SyntaxNode,\n symbols: Symbol[],\n allList: Set<string> | null,\n ): void {\n if (node.type === \"function_definition\") {\n symbols.push(this.buildFunction(node, allList));\n } else if (node.type === \"class_definition\") {\n this.extractClass(node, allList, symbols);\n } else if (node.type === \"decorated_definition\") {\n this.extractDecorated(node, allList, symbols);\n }\n }\n\n private isExported(name: string, allList: Set<string> | null): boolean {\n if (allList) return allList.has(name);\n return !name.startsWith(\"_\");\n }\n\n private buildFunction(\n node: SyntaxNode,\n allList: Set<string> | null,\n ): Symbol {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n const isAsync = node.children.some((c) => c.type === \"async\");\n const signature = this.extractPythonSignature(node);\n const decorators = this.getDecorators(node);\n\n return {\n name,\n kind: \"function\",\n exported: this.isExported(name, allList),\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n signature,\n is_async: isAsync || undefined,\n annotations: decorators.length > 0 ? decorators : undefined,\n };\n }\n\n private extractDecorated(\n node: SyntaxNode,\n allList: Set<string> | null,\n symbols: Symbol[],\n ): void {\n const decorators = this.getDecorators(node);\n const definition = node.children.find(\n (c) => c.type === \"function_definition\" || c.type === \"class_definition\",\n );\n if (!definition) return;\n\n if (definition.type === \"function_definition\") {\n const sym = this.buildFunction(definition, allList);\n sym.annotations = decorators.length > 0 ? decorators : undefined;\n sym.line = node.startPosition.row + 1;\n symbols.push(sym);\n } else if (definition.type === \"class_definition\") {\n this.extractClass(definition, allList, symbols, decorators, node.startPosition.row + 1);\n }\n }\n\n private extractClass(\n node: SyntaxNode,\n allList: Set<string> | null,\n symbols: Symbol[],\n decorators: string[] = [],\n startLine?: number,\n ): void {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n\n symbols.push({\n name,\n kind: \"class\",\n exported: this.isExported(name, allList),\n line: startLine ?? node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n annotations: decorators.length > 0 ? decorators : undefined,\n });\n\n const body = node.childForFieldName(\"body\");\n if (!body) return;\n\n for (let i = 0; i < body.childCount; i++) {\n const child = body.child(i)!;\n if (child.type === \"function_definition\") {\n this.extractMethod(child, symbols);\n } else if (child.type === \"decorated_definition\") {\n this.extractDecoratedMethod(child, symbols);\n }\n }\n }\n\n private extractMethod(\n node: SyntaxNode,\n symbols: Symbol[],\n decorators: string[] = [],\n startLine?: number,\n ): void {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n const isAsync = node.children.some((c) => c.type === \"async\");\n const signature = this.extractPythonSignature(node, true);\n\n symbols.push({\n name,\n kind: \"method\",\n exported: false,\n line: startLine ?? node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n signature,\n is_async: isAsync || undefined,\n annotations: decorators.length > 0 ? decorators : undefined,\n });\n }\n\n private extractDecoratedMethod(\n node: SyntaxNode,\n symbols: Symbol[],\n ): void {\n const decorators = this.getDecorators(node);\n const definition = node.children.find((c) => c.type === \"function_definition\");\n if (!definition) return;\n this.extractMethod(definition, symbols, decorators, node.startPosition.row + 1);\n }\n\n private getDecorators(node: SyntaxNode): string[] {\n return node.children\n .filter((c) => c.type === \"decorator\")\n .map((d) => {\n // The decorator text includes the @, skip it\n return d.text.startsWith(\"@\") ? d.text.slice(1) : d.text;\n });\n }\n\n private extractPythonSignature(\n node: SyntaxNode,\n isMethod = false,\n ): string | null {\n const params = node.childForFieldName(\"parameters\");\n if (!params) return null;\n\n let paramText = params.text;\n\n // For methods, strip self/cls first parameter\n if (isMethod) {\n paramText = this.stripSelfParam(paramText);\n }\n\n // Check for return type\n const returnTypeNode = node.childForFieldName(\"return_type\");\n if (returnTypeNode) {\n paramText += \" -> \" + returnTypeNode.text;\n }\n\n return paramText;\n }\n\n private stripSelfParam(paramText: string): string {\n // Remove 'self' or 'cls' as first param\n // (self, name: str) -> (name: str)\n // (self) -> ()\n const inner = paramText.slice(1, -1).trim();\n const parts = inner.split(\",\").map((p) => p.trim());\n if (parts.length > 0 && (parts[0] === \"self\" || parts[0] === \"cls\")) {\n parts.shift();\n }\n return \"(\" + parts.join(\", \") + \")\";\n }\n}\n","/**\n * Java symbol extractor.\n *\n * Extracts classes, interfaces, enums, methods, fields, constructors,\n * annotations, and visibility modifiers. Package declarations are\n * included as `kind: \"package\"` symbols.\n */\n\nimport type Parser from \"web-tree-sitter\";\nimport type { Symbol, Visibility, SymbolKind } from \"../../../types/index.js\";\nimport type { SymbolExtractor } from \"./types.js\";\n\ntype SyntaxNode = Parser.SyntaxNode;\n\nexport class JavaExtractor implements SymbolExtractor {\n extract(tree: Parser.Tree, _filePath: string): Symbol[] {\n const symbols: Symbol[] = [];\n\n for (let i = 0; i < tree.rootNode.childCount; i++) {\n const node = tree.rootNode.child(i)!;\n this.visitTopLevel(node, symbols);\n }\n\n return symbols;\n }\n\n private visitTopLevel(node: SyntaxNode, symbols: Symbol[]): void {\n switch (node.type) {\n case \"package_declaration\":\n this.extractPackage(node, symbols);\n break;\n case \"class_declaration\":\n this.extractClass(node, symbols);\n break;\n case \"interface_declaration\":\n this.extractInterface(node, symbols);\n break;\n case \"enum_declaration\":\n this.extractEnum(node, symbols);\n break;\n }\n }\n\n private extractPackage(node: SyntaxNode, symbols: Symbol[]): void {\n // Package name is a scoped_identifier or identifier child\n const nameNode = node.children.find(\n (c) => c.type === \"scoped_identifier\" || c.type === \"identifier\",\n );\n if (!nameNode) return;\n\n symbols.push({\n name: nameNode.text,\n kind: \"package\",\n exported: true,\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n });\n }\n\n private extractClass(node: SyntaxNode, symbols: Symbol[]): void {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n const { visibility, annotations, modifierFlags } = this.parseModifiers(node);\n\n symbols.push({\n name,\n kind: \"class\",\n exported: visibility === \"public\",\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n visibility,\n annotations: this.buildAnnotationsList(annotations, modifierFlags),\n });\n\n const body = node.childForFieldName(\"body\");\n if (!body) return;\n this.extractClassMembers(body, symbols);\n }\n\n private extractInterface(node: SyntaxNode, symbols: Symbol[]): void {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n const { visibility, annotations, modifierFlags } = this.parseModifiers(node);\n\n symbols.push({\n name,\n kind: \"interface\",\n exported: visibility === \"public\",\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n visibility,\n annotations: this.buildAnnotationsList(annotations, modifierFlags),\n });\n\n const body = node.childForFieldName(\"body\");\n if (!body) return;\n\n // Interface methods\n for (let i = 0; i < body.childCount; i++) {\n const child = body.child(i)!;\n if (child.type === \"method_declaration\") {\n this.extractMethod(child, symbols);\n }\n }\n }\n\n private extractEnum(node: SyntaxNode, symbols: Symbol[]): void {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n const { visibility, annotations, modifierFlags } = this.parseModifiers(node);\n\n symbols.push({\n name,\n kind: \"enum\",\n exported: visibility === \"public\",\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n visibility,\n annotations: this.buildAnnotationsList(annotations, modifierFlags),\n });\n }\n\n private extractClassMembers(body: SyntaxNode, symbols: Symbol[]): void {\n for (let i = 0; i < body.childCount; i++) {\n const child = body.child(i)!;\n\n switch (child.type) {\n case \"method_declaration\":\n this.extractMethod(child, symbols);\n break;\n case \"field_declaration\":\n this.extractField(child, symbols);\n break;\n case \"constructor_declaration\":\n this.extractConstructor(child, symbols);\n break;\n case \"class_declaration\":\n this.extractClass(child, symbols);\n break;\n case \"interface_declaration\":\n this.extractInterface(child, symbols);\n break;\n case \"enum_declaration\":\n this.extractEnum(child, symbols);\n break;\n }\n }\n }\n\n private extractMethod(node: SyntaxNode, symbols: Symbol[]): void {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n const { visibility, annotations, modifierFlags } = this.parseModifiers(node);\n const signature = this.buildMethodSignature(node);\n\n symbols.push({\n name,\n kind: \"method\",\n exported: visibility === \"public\",\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n signature,\n visibility,\n annotations: this.buildAnnotationsList(annotations, modifierFlags),\n });\n }\n\n private extractField(node: SyntaxNode, symbols: Symbol[]): void {\n const { visibility, annotations, modifierFlags } = this.parseModifiers(node);\n\n // Type is the first non-modifiers child that's a type\n const typeNode = node.children.find(\n (c) =>\n c.type !== \"modifiers\" &&\n c.type !== \";\" &&\n c.type !== \"variable_declarator\",\n );\n\n // Variable declarator contains the name\n const declarator = node.children.find((c) => c.type === \"variable_declarator\");\n const nameNode = declarator?.childForFieldName(\"name\");\n const name = nameNode?.text ?? declarator?.text?.split(/\\s*=/)?.[0]?.trim() ?? \"(unknown)\";\n\n const typeName = typeNode?.text ?? null;\n\n symbols.push({\n name,\n kind: \"field\",\n exported: visibility === \"public\",\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n signature: typeName,\n visibility,\n annotations: this.buildAnnotationsList(annotations, modifierFlags),\n });\n }\n\n private extractConstructor(node: SyntaxNode, symbols: Symbol[]): void {\n const nameNode = node.childForFieldName(\"name\");\n const name = nameNode?.text ?? \"(anonymous)\";\n const { visibility, annotations, modifierFlags } = this.parseModifiers(node);\n const params = node.childForFieldName(\"parameters\");\n\n symbols.push({\n name,\n kind: \"constructor\",\n exported: visibility === \"public\",\n line: node.startPosition.row + 1,\n end_line: node.endPosition.row + 1,\n signature: params?.text ?? \"()\",\n visibility,\n annotations: this.buildAnnotationsList(annotations, modifierFlags),\n });\n }\n\n // ---------------------------------------------------------------------------\n // Modifier / annotation parsing\n // ---------------------------------------------------------------------------\n\n private parseModifiers(node: SyntaxNode): {\n visibility: Visibility;\n annotations: string[];\n modifierFlags: string[];\n } {\n const modifiersNode = node.children.find((c) => c.type === \"modifiers\");\n if (!modifiersNode) {\n return { visibility: \"package\", annotations: [], modifierFlags: [] };\n }\n\n let visibility: Visibility = \"package\";\n const annotations: string[] = [];\n const modifierFlags: string[] = [];\n\n for (let i = 0; i < modifiersNode.childCount; i++) {\n const child = modifiersNode.child(i)!;\n\n switch (child.type) {\n case \"public\":\n visibility = \"public\";\n break;\n case \"private\":\n visibility = \"private\";\n break;\n case \"protected\":\n visibility = \"protected\";\n break;\n case \"static\":\n case \"final\":\n case \"abstract\":\n case \"synchronized\":\n case \"native\":\n modifierFlags.push(child.type);\n break;\n case \"marker_annotation\":\n case \"annotation\": {\n const text = child.text;\n annotations.push(text.startsWith(\"@\") ? text.slice(1) : text);\n break;\n }\n }\n }\n\n return { visibility, annotations, modifierFlags };\n }\n\n private buildAnnotationsList(\n annotations: string[],\n modifierFlags: string[],\n ): string[] | undefined {\n const all = [...annotations, ...modifierFlags];\n return all.length > 0 ? all : undefined;\n }\n\n // ---------------------------------------------------------------------------\n // Signature building\n // ---------------------------------------------------------------------------\n\n private buildMethodSignature(node: SyntaxNode): string | null {\n const returnType = node.children.find(\n (c) =>\n c.type !== \"modifiers\" &&\n c.type !== \"identifier\" &&\n c.type !== \"formal_parameters\" &&\n c.type !== \"throws\" &&\n c.type !== \"block\" &&\n c.type !== \";\" &&\n c.type !== \"type_parameters\",\n );\n const params = node.childForFieldName(\"parameters\");\n const throwsNode = node.children.find((c) => c.type === \"throws\");\n\n if (!params) return null;\n\n let sig = \"\";\n if (returnType) sig += returnType.text + \" \";\n\n // Get method name\n const nameNode = node.childForFieldName(\"name\");\n sig += (nameNode?.text ?? \"\") + params.text;\n\n if (throwsNode) {\n sig += \" \" + throwsNode.text;\n }\n\n return sig;\n }\n}\n","/**\n * Extractor registry — maps grammar names to symbol extractors.\n */\n\nimport type { SymbolExtractor } from \"./types.js\";\nimport { TypeScriptExtractor } from \"./typescript.js\";\nimport { PythonExtractor } from \"./python.js\";\nimport { JavaExtractor } from \"./java.js\";\n\nconst extractors: Record<string, SymbolExtractor> = {\n typescript: new TypeScriptExtractor(),\n javascript: new TypeScriptExtractor(), // JS is a subset; same extractor works\n python: new PythonExtractor(),\n java: new JavaExtractor(),\n};\n\n/**\n * Get the symbol extractor for a grammar name.\n * Returns null if no extractor exists for the grammar.\n */\nexport function getExtractor(grammarName: string): SymbolExtractor | null {\n return extractors[grammarName] ?? null;\n}\n","/**\n * Shared utilities for the parser service.\n *\n * Extracted from symbol-index.ts to be reused by the dependency graph builder.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { ResolvedConfig } from \"../../config/index.js\";\nimport { SUPPORTED_EXTENSIONS } from \"./index.js\";\n\n/** Default concurrency for parallel parsing. */\nexport const DEFAULT_CONCURRENCY = 8;\n\n// ---------------------------------------------------------------------------\n// File collection\n// ---------------------------------------------------------------------------\n\n/**\n * Collect all parseable source files from a project directory.\n *\n * Respects collapse_dirs, ignore_patterns, and max_file_size_kb from the\n * resolved configuration. Does NOT apply tree_depth — that limit is only\n * for the display tree. The parser must walk as deep as needed to find all\n * source files (Java projects commonly reach depth 8+).\n */\nexport function collectSourceFiles(\n projectRoot: string,\n config: ResolvedConfig,\n): string[] {\n const files: string[] = [];\n const maxSizeBytes = config.max_file_size_kb * 1024;\n\n walk(projectRoot, projectRoot, config, files, maxSizeBytes);\n return files;\n}\n\nfunction walk(\n dirPath: string,\n projectRoot: string,\n config: ResolvedConfig,\n files: string[],\n maxSizeBytes: number,\n): void {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dirPath, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n const fullPath = path.join(dirPath, entry.name);\n\n if (entry.isDirectory()) {\n if (config.collapse_dirs.includes(entry.name)) continue;\n walk(fullPath, projectRoot, config, files, maxSizeBytes);\n } else if (entry.isFile()) {\n const ext = path.extname(entry.name).toLowerCase();\n if (!SUPPORTED_EXTENSIONS.has(ext)) continue;\n if (matchesIgnorePattern(entry.name, config.ignore_patterns)) continue;\n\n try {\n const stat = fs.statSync(fullPath);\n if (stat.size > maxSizeBytes) continue;\n } catch {\n continue;\n }\n\n files.push(fullPath);\n }\n }\n}\n\n/**\n * Check if a filename matches any of the given ignore patterns.\n */\nexport function matchesIgnorePattern(fileName: string, patterns: string[]): boolean {\n for (const pattern of patterns) {\n const regex = new RegExp(\n \"^\" + pattern.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\").replace(/\\*/g, \".*\") + \"$\",\n );\n if (regex.test(fileName)) return true;\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Concurrency helper\n// ---------------------------------------------------------------------------\n\n/**\n * Execute an array of async tasks with a concurrency limit.\n */\nexport async function withConcurrency(\n tasks: (() => Promise<void>)[],\n limit: number,\n): Promise<void> {\n let index = 0;\n\n async function runNext(): Promise<void> {\n while (index < tasks.length) {\n const currentIndex = index++;\n await tasks[currentIndex]();\n }\n }\n\n const workers = Array.from(\n { length: Math.min(limit, tasks.length) },\n () => runNext(),\n );\n await Promise.all(workers);\n}\n","/**\n * Dependency graph builder.\n *\n * Builds a bidirectional dependency map for all source files in a project:\n * for each file, stores which files it imports from and which files import it.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { DependencyEntry } from \"../../types/index.js\";\nimport type { ResolvedConfig } from \"../../config/index.js\";\nimport { parseSource, getGrammarForFile } from \"./index.js\";\nimport { getImportExtractor } from \"./import-extractors/index.js\";\nimport {\n resolveTypeScriptImport,\n resolvePythonImport,\n resolveJavaImport,\n buildJavaPackageIndex,\n buildPythonPackageIndex,\n type JavaPackageIndex,\n type PythonPackageIndex,\n} from \"./path-resolver.js\";\nimport { collectSourceFiles, withConcurrency, DEFAULT_CONCURRENCY } from \"./utils.js\";\n\n/**\n * Build a bidirectional dependency graph for a project.\n *\n * @returns Map of project-relative file path to its dependency entry.\n */\nexport async function buildDependencyGraph(\n projectRoot: string,\n config: ResolvedConfig,\n preCollectedFiles?: string[],\n): Promise<Record<string, DependencyEntry>> {\n const files = preCollectedFiles ?? collectSourceFiles(projectRoot, config);\n const relativePaths = files.map((f) => path.relative(projectRoot, f));\n\n // Build Java package index if there are any .java files\n let javaPackageIndex: JavaPackageIndex | null = null;\n if (files.some((f) => f.endsWith(\".java\"))) {\n javaPackageIndex = buildJavaPackageIndex(projectRoot);\n }\n\n // Build Python package index if there are any .py files\n let pythonPackageIndex: PythonPackageIndex | null = null;\n if (files.some((f) => f.endsWith(\".py\"))) {\n pythonPackageIndex = buildPythonPackageIndex(projectRoot);\n }\n\n // Resolve path aliases: use config value if provided, otherwise auto-detect\n const pathAliases =\n config.path_aliases === \"auto\" || config.path_aliases === undefined\n ? loadPathAliases(projectRoot)\n : config.path_aliases;\n\n // Forward adjacency: file → [files it imports from]\n const forwardEdges: Record<string, Set<string>> = {};\n\n // Process each file to extract its imports\n await withConcurrency(\n files.map((filePath, idx) => async () => {\n const relativePath = relativePaths[idx];\n const deps = await extractDependencies(\n filePath,\n relativePath,\n projectRoot,\n pathAliases,\n javaPackageIndex,\n pythonPackageIndex,\n );\n if (deps.length > 0) {\n forwardEdges[relativePath] = new Set(deps);\n }\n }),\n DEFAULT_CONCURRENCY,\n );\n\n // Build the bidirectional graph\n const graph: Record<string, DependencyEntry> = {};\n const allFiles = new Set(relativePaths);\n\n // Initialize entries for all files that participate in the graph\n for (const file of allFiles) {\n if (forwardEdges[file] || isImportedBy(file, forwardEdges)) {\n if (!graph[file]) {\n graph[file] = { imports_from: [], imported_by: [] };\n }\n }\n }\n\n // Fill forward edges (imports_from)\n for (const [file, deps] of Object.entries(forwardEdges)) {\n if (!graph[file]) {\n graph[file] = { imports_from: [], imported_by: [] };\n }\n graph[file].imports_from = [...deps].sort();\n }\n\n // Fill reverse edges (imported_by)\n for (const [file, deps] of Object.entries(forwardEdges)) {\n for (const dep of deps) {\n if (!graph[dep]) {\n graph[dep] = { imports_from: [], imported_by: [] };\n }\n graph[dep].imported_by.push(file);\n }\n }\n\n // Sort imported_by for deterministic output\n for (const entry of Object.values(graph)) {\n entry.imported_by.sort();\n }\n\n return graph;\n}\n\n/**\n * Incrementally update a cached dependency graph by re-extracting only changed files.\n *\n * @param cached The previous dependency graph from cache.\n * @param changedFiles Relative paths of files that were added or modified.\n * @param deletedFiles Relative paths of files that were deleted.\n * @param projectRoot Absolute path to the project root.\n * @param config Resolved configuration.\n * @returns Updated dependency graph.\n */\nexport async function updateDependencyGraph(\n cached: Record<string, DependencyEntry>,\n changedFiles: string[],\n deletedFiles: string[],\n projectRoot: string,\n config: ResolvedConfig,\n): Promise<Record<string, DependencyEntry>> {\n // Rebuild forward edges from cached graph\n const forwardEdges: Record<string, Set<string>> = {};\n for (const [file, entry] of Object.entries(cached)) {\n if (entry.imports_from.length > 0) {\n forwardEdges[file] = new Set(entry.imports_from);\n }\n }\n\n // Remove deleted files\n for (const file of deletedFiles) {\n delete forwardEdges[file];\n }\n\n // Re-extract dependencies for changed files\n const allFiles = collectSourceFiles(projectRoot, config);\n\n let javaPackageIndex: JavaPackageIndex | null = null;\n if (allFiles.some((f) => f.endsWith(\".java\"))) {\n javaPackageIndex = buildJavaPackageIndex(projectRoot);\n }\n\n let pythonPackageIndex: PythonPackageIndex | null = null;\n if (allFiles.some((f) => f.endsWith(\".py\"))) {\n pythonPackageIndex = buildPythonPackageIndex(projectRoot);\n }\n\n const pathAliases =\n config.path_aliases === \"auto\" || config.path_aliases === undefined\n ? loadPathAliases(projectRoot)\n : config.path_aliases;\n\n await withConcurrency(\n changedFiles.map((relativePath) => async () => {\n const filePath = path.join(projectRoot, relativePath);\n const deps = await extractDependencies(\n filePath,\n relativePath,\n projectRoot,\n pathAliases,\n javaPackageIndex,\n pythonPackageIndex,\n );\n if (deps.length > 0) {\n forwardEdges[relativePath] = new Set(deps);\n } else {\n delete forwardEdges[relativePath];\n }\n }),\n DEFAULT_CONCURRENCY,\n );\n\n // Rebuild the full bidirectional graph from forward edges\n const graph: Record<string, DependencyEntry> = {};\n\n // Collect all files that participate\n const allParticipants = new Set<string>();\n for (const [file, deps] of Object.entries(forwardEdges)) {\n allParticipants.add(file);\n for (const dep of deps) {\n allParticipants.add(dep);\n }\n }\n\n for (const file of allParticipants) {\n graph[file] = { imports_from: [], imported_by: [] };\n }\n\n // Fill forward edges\n for (const [file, deps] of Object.entries(forwardEdges)) {\n graph[file].imports_from = [...deps].sort();\n }\n\n // Fill reverse edges\n for (const [file, deps] of Object.entries(forwardEdges)) {\n for (const dep of deps) {\n if (graph[dep]) {\n graph[dep].imported_by.push(file);\n }\n }\n }\n\n // Sort imported_by for deterministic output\n for (const entry of Object.values(graph)) {\n entry.imported_by.sort();\n }\n\n return graph;\n}\n\n/**\n * Check if a file is imported by any other file.\n */\nfunction isImportedBy(file: string, forwardEdges: Record<string, Set<string>>): boolean {\n for (const deps of Object.values(forwardEdges)) {\n if (deps.has(file)) return true;\n }\n return false;\n}\n\n/**\n * Extract resolved dependency paths for a single file.\n */\nasync function extractDependencies(\n filePath: string,\n relativePath: string,\n projectRoot: string,\n pathAliases: Record<string, string> | undefined,\n javaPackageIndex: JavaPackageIndex | null,\n pythonPackageIndex: PythonPackageIndex | null,\n): Promise<string[]> {\n let source: string;\n try {\n source = fs.readFileSync(filePath, \"utf-8\");\n } catch {\n return [];\n }\n\n const tree = await parseSource(relativePath, source);\n if (!tree) return [];\n\n const grammarName = getGrammarForFile(relativePath);\n if (!grammarName) return [];\n\n const extractor = getImportExtractor(grammarName);\n if (!extractor) return [];\n\n const rawImports = extractor.extract(tree);\n const resolved: string[] = [];\n\n for (const imp of rawImports) {\n let resolvedPath: string | null = null;\n\n switch (grammarName) {\n case \"typescript\":\n case \"javascript\":\n resolvedPath = resolveTypeScriptImport(\n imp.source,\n relativePath,\n projectRoot,\n pathAliases,\n );\n break;\n\n case \"python\":\n resolvedPath = resolvePythonImport(\n imp.source,\n relativePath,\n projectRoot,\n pythonPackageIndex ?? undefined,\n );\n break;\n\n case \"java\":\n if (javaPackageIndex) {\n const javaResult = resolveJavaImport(imp.source, javaPackageIndex);\n if (Array.isArray(javaResult)) {\n for (const p of javaResult) {\n if (p !== relativePath) {\n resolved.push(p);\n }\n }\n } else {\n resolvedPath = javaResult;\n }\n }\n break;\n }\n\n if (resolvedPath && resolvedPath !== relativePath) {\n resolved.push(resolvedPath);\n }\n }\n\n // Deduplicate\n return [...new Set(resolved)];\n}\n\n/**\n * Load path aliases from tsconfig.json compilerOptions.paths.\n */\nfunction loadPathAliases(projectRoot: string): Record<string, string> | undefined {\n const tsconfigPath = path.join(projectRoot, \"tsconfig.json\");\n if (!fs.existsSync(tsconfigPath)) return undefined;\n\n try {\n const raw = fs.readFileSync(tsconfigPath, \"utf-8\");\n // Strip comments (simple heuristic — handles // and /* */ in JSON)\n const stripped = raw\n .replace(/\\/\\/.*$/gm, \"\")\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\");\n const tsconfig = JSON.parse(stripped);\n\n const paths = tsconfig?.compilerOptions?.paths;\n if (!paths || typeof paths !== \"object\") return undefined;\n\n const result: Record<string, string> = {};\n for (const [key, values] of Object.entries(paths)) {\n if (Array.isArray(values) && values.length > 0) {\n result[key] = values[0] as string;\n }\n }\n\n return Object.keys(result).length > 0 ? result : undefined;\n } catch {\n return undefined;\n }\n}\n","/**\n * TypeScript/JavaScript import extractor.\n *\n * Handles:\n * - ES6 imports: import { x } from \"y\", import x from \"y\", import * as x from \"y\"\n * - CJS require: const x = require(\"y\")\n * - Dynamic import: import(\"y\")\n * - Re-exports: export { x } from \"y\", export * from \"y\"\n * - Side-effect imports: import \"y\"\n */\n\nimport type Parser from \"web-tree-sitter\";\nimport type { ImportExtractor, ExtractedImport } from \"./types.js\";\n\nexport class TypeScriptImportExtractor implements ImportExtractor {\n /** Extract all imports from a TypeScript/JavaScript AST. */\n extract(tree: Parser.Tree): ExtractedImport[] {\n const imports: ExtractedImport[] = [];\n this.visit(tree.rootNode, imports);\n return imports;\n }\n\n private visit(node: Parser.SyntaxNode, imports: ExtractedImport[]): void {\n switch (node.type) {\n case \"import_statement\": {\n this.extractImportStatement(node, imports);\n break;\n }\n\n case \"export_statement\": {\n // Re-exports: export { x } from \"y\" or export * from \"y\"\n const source = node.childForFieldName(\"source\");\n if (source) {\n const specifiers = this.extractSpecifiers(node);\n imports.push({\n source: stripQuotes(source.text),\n specifiers,\n kind: \"static\",\n });\n }\n break;\n }\n\n case \"lexical_declaration\":\n case \"variable_declaration\": {\n // CJS: const x = require(\"y\")\n this.extractRequire(node, imports);\n break;\n }\n\n case \"expression_statement\": {\n // Side-effect require: require(\"y\")\n // Or dynamic import as statement: import(\"y\")\n this.extractExpressionStatement(node, imports);\n break;\n }\n\n case \"call_expression\": {\n // Dynamic import: import(\"y\") in any position\n this.extractDynamicImport(node, imports);\n return; // Don't recurse into children, we handled it\n }\n }\n\n for (let i = 0; i < node.childCount; i++) {\n this.visit(node.child(i)!, imports);\n }\n }\n\n private extractImportStatement(node: Parser.SyntaxNode, imports: ExtractedImport[]): void {\n const source = node.childForFieldName(\"source\");\n if (!source) return;\n\n const sourceText = stripQuotes(source.text);\n const specifiers = this.extractSpecifiers(node);\n\n // Side-effect import: import \"y\" (no specifiers, no default, no namespace)\n const hasClause = node.children.some(\n (c) =>\n c.type === \"import_clause\" ||\n c.type === \"named_imports\" ||\n c.type === \"namespace_import\",\n );\n\n imports.push({\n source: sourceText,\n specifiers,\n kind: specifiers.length === 0 && !hasClause ? \"side_effect\" : \"static\",\n });\n }\n\n private extractSpecifiers(node: Parser.SyntaxNode): string[] {\n const specifiers: string[] = [];\n\n for (let i = 0; i < node.childCount; i++) {\n const child = node.child(i)!;\n\n if (child.type === \"import_clause\") {\n for (let j = 0; j < child.childCount; j++) {\n const clause = child.child(j)!;\n if (clause.type === \"identifier\") {\n specifiers.push(clause.text);\n } else if (clause.type === \"named_imports\") {\n this.extractNamedImports(clause, specifiers);\n } else if (clause.type === \"namespace_import\") {\n const name = clause.children.find((c) => c.type === \"identifier\");\n if (name) specifiers.push(\"* as \" + name.text);\n }\n }\n } else if (child.type === \"named_imports\") {\n this.extractNamedImports(child, specifiers);\n } else if (child.type === \"export_clause\") {\n for (let j = 0; j < child.childCount; j++) {\n const spec = child.child(j)!;\n if (spec.type === \"export_specifier\") {\n const name = spec.childForFieldName(\"name\");\n if (name) specifiers.push(name.text);\n }\n }\n }\n }\n\n return specifiers;\n }\n\n private extractNamedImports(node: Parser.SyntaxNode, specifiers: string[]): void {\n for (let i = 0; i < node.childCount; i++) {\n const child = node.child(i)!;\n if (child.type === \"import_specifier\") {\n const name = child.childForFieldName(\"name\");\n if (name) specifiers.push(name.text);\n }\n }\n }\n\n private extractRequire(node: Parser.SyntaxNode, imports: ExtractedImport[]): void {\n // Look for require() calls in variable declarations\n for (let i = 0; i < node.childCount; i++) {\n const declarator = node.child(i)!;\n if (declarator.type !== \"variable_declarator\") continue;\n\n const value = declarator.childForFieldName(\"value\");\n if (!value || value.type !== \"call_expression\") continue;\n\n const fn = value.childForFieldName(\"function\");\n if (!fn || fn.text !== \"require\") continue;\n\n const args = value.childForFieldName(\"arguments\");\n if (!args) continue;\n\n const firstArg = args.children.find(\n (c) => c.type === \"string\" || c.type === \"template_string\",\n );\n if (!firstArg) continue;\n\n imports.push({\n source: stripQuotes(firstArg.text),\n specifiers: [],\n kind: \"require\",\n });\n }\n }\n\n private extractExpressionStatement(node: Parser.SyntaxNode, imports: ExtractedImport[]): void {\n const expr = node.children[0];\n if (!expr) return;\n\n if (expr.type === \"call_expression\") {\n const fn = expr.childForFieldName(\"function\");\n if (fn && fn.text === \"require\") {\n const args = expr.childForFieldName(\"arguments\");\n if (args) {\n const firstArg = args.children.find(\n (c) => c.type === \"string\" || c.type === \"template_string\",\n );\n if (firstArg) {\n imports.push({\n source: stripQuotes(firstArg.text),\n specifiers: [],\n kind: \"side_effect\",\n });\n }\n }\n }\n }\n }\n\n private extractDynamicImport(node: Parser.SyntaxNode, imports: ExtractedImport[]): void {\n // import(\"module\")\n const fn = node.childForFieldName(\"function\");\n if (!fn) return;\n\n // In tree-sitter, dynamic import is a call_expression where function is \"import\"\n if (fn.type !== \"import\") return;\n\n const args = node.childForFieldName(\"arguments\");\n if (!args) return;\n\n const firstArg = args.children.find(\n (c) => c.type === \"string\" || c.type === \"template_string\",\n );\n if (!firstArg) return;\n\n imports.push({\n source: stripQuotes(firstArg.text),\n specifiers: [],\n kind: \"dynamic\",\n });\n }\n}\n\n/** Remove surrounding quotes from a string literal. */\nfunction stripQuotes(text: string): string {\n if (\n (text.startsWith('\"') && text.endsWith('\"')) ||\n (text.startsWith(\"'\") && text.endsWith(\"'\")) ||\n (text.startsWith(\"`\") && text.endsWith(\"`\"))\n ) {\n return text.slice(1, -1);\n }\n return text;\n}\n","/**\n * Python import extractor.\n *\n * Handles:\n * - import module\n * - import module as alias\n * - from module import name\n * - from .relative import name\n * - from ..parent import name\n */\n\nimport type Parser from \"web-tree-sitter\";\nimport type { ImportExtractor, ExtractedImport } from \"./types.js\";\n\nexport class PythonImportExtractor implements ImportExtractor {\n /** Extract all imports from a Python AST. */\n extract(tree: Parser.Tree): ExtractedImport[] {\n const imports: ExtractedImport[] = [];\n this.visit(tree.rootNode, imports);\n return imports;\n }\n\n private visit(node: Parser.SyntaxNode, imports: ExtractedImport[]): void {\n switch (node.type) {\n case \"import_statement\": {\n this.extractImport(node, imports);\n break;\n }\n case \"import_from_statement\": {\n this.extractFromImport(node, imports);\n break;\n }\n }\n\n for (let i = 0; i < node.childCount; i++) {\n this.visit(node.child(i)!, imports);\n }\n }\n\n private extractImport(node: Parser.SyntaxNode, imports: ExtractedImport[]): void {\n // import module, import module as alias, import a, b\n for (let i = 0; i < node.childCount; i++) {\n const child = node.child(i)!;\n if (child.type === \"dotted_name\") {\n imports.push({\n source: child.text,\n specifiers: [],\n kind: \"static\",\n });\n } else if (child.type === \"aliased_import\") {\n const name = child.childForFieldName(\"name\");\n if (name) {\n imports.push({\n source: name.text,\n specifiers: [],\n kind: \"static\",\n });\n }\n }\n }\n }\n\n private extractFromImport(node: Parser.SyntaxNode, imports: ExtractedImport[]): void {\n // from <module> import <names>\n const moduleName = node.childForFieldName(\"module_name\");\n const source = moduleName ? moduleName.text : \"\";\n\n // Count leading dots for relative imports\n let dots = \"\";\n for (let i = 0; i < node.childCount; i++) {\n const child = node.child(i)!;\n if (child.type === \"relative_import\") {\n // The relative_import node contains dots and optionally a dotted_name\n const dotText = child.children\n .filter((c) => c.type === \"import_prefix\" || c.type === \".\")\n .map((c) => c.text)\n .join(\"\");\n const dottedName = child.children.find((c) => c.type === \"dotted_name\");\n dots = dotText;\n if (dottedName) {\n imports.push({\n source: dots + dottedName.text,\n specifiers: this.extractSpecifiers(node),\n kind: \"static\",\n });\n return;\n }\n }\n }\n\n // Build the full source with dots prefix\n const fullSource = dots ? dots + source : source;\n\n imports.push({\n source: fullSource,\n specifiers: this.extractSpecifiers(node),\n kind: \"static\",\n });\n }\n\n private extractSpecifiers(node: Parser.SyntaxNode): string[] {\n const specifiers: string[] = [];\n for (let i = 0; i < node.childCount; i++) {\n const child = node.child(i)!;\n if (child.type === \"dotted_name\") {\n // Skip the module name (first dotted_name after \"from\")\n // Specifiers come after \"import\"\n const prevSibling = child.previousSibling;\n if (prevSibling && (prevSibling.type === \"import\" || prevSibling.text === \",\")) {\n specifiers.push(child.text);\n }\n } else if (child.type === \"aliased_import\") {\n const name = child.childForFieldName(\"name\");\n if (name) specifiers.push(name.text);\n } else if (child.type === \"wildcard_import\") {\n specifiers.push(\"*\");\n }\n }\n return specifiers;\n }\n}\n","/**\n * Java import extractor.\n *\n * Handles:\n * - import com.example.auth.UserService;\n * - import com.example.auth.*;\n * - import static com.example.Utils.method;\n */\n\nimport type Parser from \"web-tree-sitter\";\nimport type { ImportExtractor, ExtractedImport } from \"./types.js\";\n\nexport class JavaImportExtractor implements ImportExtractor {\n /** Extract all imports from a Java AST. */\n extract(tree: Parser.Tree): ExtractedImport[] {\n const imports: ExtractedImport[] = [];\n this.visit(tree.rootNode, imports);\n return imports;\n }\n\n private visit(node: Parser.SyntaxNode, imports: ExtractedImport[]): void {\n if (node.type === \"import_declaration\") {\n this.extractImportDeclaration(node, imports);\n }\n\n for (let i = 0; i < node.childCount; i++) {\n this.visit(node.child(i)!, imports);\n }\n }\n\n private extractImportDeclaration(node: Parser.SyntaxNode, imports: ExtractedImport[]): void {\n // The full import text: \"import com.example.auth.UserService;\"\n // or \"import static com.example.Utils.method;\"\n // We need to extract the scoped identifier\n let source = \"\";\n\n for (let i = 0; i < node.childCount; i++) {\n const child = node.child(i)!;\n if (child.type === \"scoped_identifier\" || child.type === \"identifier\") {\n source = child.text;\n } else if (child.type === \"asterisk\") {\n // import com.example.*; — the scoped_identifier is before the asterisk\n // source should already be set from scoped_identifier\n source = source ? source + \".*\" : \"*\";\n }\n }\n\n if (!source) return;\n\n // Check if it's a wildcard import\n const isWildcard = source.endsWith(\".*\");\n const specifiers = isWildcard ? [\"*\"] : [source.split(\".\").pop()!];\n\n imports.push({\n source,\n specifiers,\n kind: \"static\",\n });\n }\n}\n","/**\n * Import extractor registry — maps grammar names to import extractors.\n */\n\nimport type { ImportExtractor } from \"./types.js\";\nimport { TypeScriptImportExtractor } from \"./typescript.js\";\nimport { PythonImportExtractor } from \"./python.js\";\nimport { JavaImportExtractor } from \"./java.js\";\n\nconst extractors: Record<string, ImportExtractor> = {\n typescript: new TypeScriptImportExtractor(),\n javascript: new TypeScriptImportExtractor(),\n python: new PythonImportExtractor(),\n java: new JavaImportExtractor(),\n};\n\n/**\n * Get the import extractor for a grammar name.\n * Returns null if no extractor exists for the grammar.\n */\nexport function getImportExtractor(grammarName: string): ImportExtractor | null {\n return extractors[grammarName] ?? null;\n}\n","/**\n * Path resolver — resolves raw import paths to project-relative file paths.\n *\n * Handles TS/JS relative imports, Python relative/absolute imports,\n * and Java fully-qualified class imports via a package→file index.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\n// ---------------------------------------------------------------------------\n// TS/JS Resolution\n// ---------------------------------------------------------------------------\n\n/** Extensions to try when resolving TS/JS imports. */\nconst TS_EXTENSIONS = [\".ts\", \".tsx\", \".js\", \".jsx\", \".mjs\", \".cjs\"];\n\n/** Index files to try when an import resolves to a directory. */\nconst INDEX_FILES = TS_EXTENSIONS.map((ext) => \"index\" + ext);\n\n/**\n * Resolve a TS/JS import source relative to the importing file.\n *\n * @returns Project-relative path or null if unresolvable/external.\n */\nexport function resolveTypeScriptImport(\n importSource: string,\n importerRelPath: string,\n projectRoot: string,\n pathAliases?: Record<string, string>,\n): string | null {\n // Skip external/bare imports (no . prefix and no alias match)\n if (!importSource.startsWith(\".\")) {\n // Try path aliases\n if (pathAliases) {\n const resolved = resolveAlias(importSource, pathAliases, projectRoot);\n if (resolved) return resolved;\n }\n return null;\n }\n\n const importerDir = path.dirname(path.join(projectRoot, importerRelPath));\n const resolved = path.resolve(importerDir, importSource);\n\n return tryResolveFile(resolved, projectRoot);\n}\n\n/**\n * Try to resolve a path alias (e.g. @/utils → src/utils).\n */\nfunction resolveAlias(\n importSource: string,\n aliases: Record<string, string>,\n projectRoot: string,\n): string | null {\n for (const [prefix, replacement] of Object.entries(aliases)) {\n // Exact match or prefix with /\n const aliasPrefix = prefix.endsWith(\"/*\") ? prefix.slice(0, -2) : prefix;\n if (importSource === aliasPrefix || importSource.startsWith(aliasPrefix + \"/\")) {\n const rest = importSource.slice(aliasPrefix.length);\n const targetBase = replacement.endsWith(\"/*\") ? replacement.slice(0, -2) : replacement;\n const resolved = path.resolve(projectRoot, targetBase + rest);\n return tryResolveFile(resolved, projectRoot);\n }\n }\n return null;\n}\n\n/**\n * Try to resolve a path to an actual file, with extension and index resolution.\n */\nfunction tryResolveFile(resolved: string, projectRoot: string): string | null {\n // Direct match (already has extension)\n if (hasSourceExtension(resolved) && fs.existsSync(resolved)) {\n return path.relative(projectRoot, resolved);\n }\n\n // Try adding extensions\n for (const ext of TS_EXTENSIONS) {\n const withExt = resolved + ext;\n if (fs.existsSync(withExt)) {\n return path.relative(projectRoot, withExt);\n }\n }\n\n // Try as directory with index file\n for (const indexFile of INDEX_FILES) {\n const withIndex = path.join(resolved, indexFile);\n if (fs.existsSync(withIndex)) {\n return path.relative(projectRoot, withIndex);\n }\n }\n\n return null;\n}\n\nfunction hasSourceExtension(filePath: string): boolean {\n return TS_EXTENSIONS.some((ext) => filePath.endsWith(ext));\n}\n\n// ---------------------------------------------------------------------------\n// Python Resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve a Python import source relative to the importing file.\n *\n * @returns Project-relative path or null if unresolvable/external.\n */\nexport function resolvePythonImport(\n importSource: string,\n importerRelPath: string,\n projectRoot: string,\n pythonPackageIndex?: PythonPackageIndex,\n): string | null {\n // Count leading dots for relative imports\n let dotCount = 0;\n while (dotCount < importSource.length && importSource[dotCount] === \".\") {\n dotCount++;\n }\n\n if (dotCount > 0) {\n // Relative import\n const modulePath = importSource.slice(dotCount).replace(/\\./g, \"/\");\n const importerDir = path.dirname(path.join(projectRoot, importerRelPath));\n\n // In Python: 1 dot = current package (importer's dir),\n // 2 dots = parent package, etc. Each additional dot goes one level higher.\n // So from app/sub/main.py: `.` = app/sub/, `..` = app/, `...` = root\n let baseDir = importerDir;\n for (let i = 1; i < dotCount; i++) {\n baseDir = path.dirname(baseDir);\n }\n\n return resolvePythonModule(baseDir, modulePath, projectRoot);\n }\n\n // Absolute import — check if first segment is a local directory\n const segments = importSource.split(\".\");\n const firstSegment = segments[0];\n const localDir = path.join(projectRoot, firstSegment);\n\n if (fs.existsSync(localDir) && fs.statSync(localDir).isDirectory()) {\n const modulePath = segments.join(\"/\");\n return resolvePythonModule(projectRoot, modulePath, projectRoot);\n }\n\n // Not found at root — use package index for monorepo/src layouts\n if (pythonPackageIndex) {\n const packageRoot = pythonPackageIndex.get(firstSegment);\n if (packageRoot) {\n const modulePath = segments.join(\"/\");\n return resolvePythonModule(packageRoot, modulePath, projectRoot);\n }\n }\n\n return null;\n}\n\n/**\n * Resolve a Python module path to a file.\n */\nfunction resolvePythonModule(\n baseDir: string,\n modulePath: string,\n projectRoot: string,\n): string | null {\n if (!modulePath) {\n // from . import X — refers to __init__.py in current package\n const initPath = path.join(baseDir, \"__init__.py\");\n if (fs.existsSync(initPath)) {\n return path.relative(projectRoot, initPath);\n }\n return null;\n }\n\n const full = path.resolve(baseDir, modulePath);\n\n // Try as .py file\n const pyFile = full + \".py\";\n if (fs.existsSync(pyFile)) {\n return path.relative(projectRoot, pyFile);\n }\n\n // Try as package (__init__.py)\n const initFile = path.join(full, \"__init__.py\");\n if (fs.existsSync(initFile)) {\n return path.relative(projectRoot, initFile);\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Python package index\n// ---------------------------------------------------------------------------\n\n/**\n * Index mapping top-level Python package name to its parent directory.\n *\n * Built by scanning the project for all `__init__.py` files and recording\n * the root package (topmost directory containing `__init__.py` in a chain).\n * This is analogous to `JavaPackageIndex` but maps package name → resolution base.\n */\nexport type PythonPackageIndex = Map<string, string>;\n\n/** Directories to skip when scanning for Python packages. */\nconst PYTHON_SKIP_DIRS = new Set([\n \"node_modules\", \"dist\", \"build\", \"__pycache__\",\n \".venv\", \"venv\", \".git\", \".tox\", \".mypy_cache\",\n \".pytest_cache\", \"target\", \".next\",\n]);\n\n/**\n * Build an index of top-level Python packages found anywhere in the project.\n *\n * For each `__init__.py`, walks up to find the root package (the topmost\n * directory in a contiguous chain of `__init__.py` files), then records\n * `packageName → parentDir` so that absolute imports like\n * `from mylib.config import X` can be resolved.\n */\nexport function buildPythonPackageIndex(projectRoot: string): PythonPackageIndex {\n const index: PythonPackageIndex = new Map();\n scanForInitFiles(projectRoot, projectRoot, index);\n return index;\n}\n\nfunction scanForInitFiles(\n dir: string,\n projectRoot: string,\n index: PythonPackageIndex,\n): void {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (!entry.isDirectory() || entry.name.startsWith(\".\")) continue;\n if (PYTHON_SKIP_DIRS.has(entry.name)) continue;\n\n const childDir = path.join(dir, entry.name);\n const initPath = path.join(childDir, \"__init__.py\");\n\n if (fs.existsSync(initPath)) {\n // Found a package — walk up to find the root package\n const rootPackageDir = findRootPackage(childDir);\n const rootPackageName = path.basename(rootPackageDir);\n\n // Only record if not already indexed (first match wins — breadth-first)\n if (!index.has(rootPackageName)) {\n index.set(rootPackageName, path.dirname(rootPackageDir));\n }\n }\n\n // Continue scanning deeper (packages can be nested in non-package dirs like src/)\n scanForInitFiles(childDir, projectRoot, index);\n }\n}\n\n/**\n * Walk up from a package directory to find the topmost directory\n * in a contiguous chain of `__init__.py` files.\n *\n * e.g. for `sub/src/mylib/models/`, if `mylib/` and `models/` both have\n * `__init__.py` but `src/` does not, returns `sub/src/mylib/`.\n */\nfunction findRootPackage(packageDir: string): string {\n let current = packageDir;\n while (true) {\n const parent = path.dirname(current);\n const parentInit = path.join(parent, \"__init__.py\");\n if (fs.existsSync(parentInit)) {\n current = parent;\n } else {\n return current;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Java Resolution\n// ---------------------------------------------------------------------------\n\n/** Index mapping fully-qualified class name to project-relative path. */\nexport type JavaPackageIndex = Map<string, string>;\n\n/**\n * Build a package→file index by scanning all .java files and extracting package declarations.\n */\nexport function buildJavaPackageIndex(projectRoot: string): JavaPackageIndex {\n const index: JavaPackageIndex = new Map();\n scanJavaFiles(projectRoot, projectRoot, index);\n return index;\n}\n\nfunction scanJavaFiles(\n dirPath: string,\n projectRoot: string,\n index: JavaPackageIndex,\n): void {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dirPath, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n const fullPath = path.join(dirPath, entry.name);\n\n if (entry.isDirectory()) {\n // Skip common non-source dirs\n if (\n entry.name === \"node_modules\" ||\n entry.name === \".git\" ||\n entry.name === \"target\" ||\n entry.name === \"build\" ||\n entry.name === \"dist\"\n ) {\n continue;\n }\n scanJavaFiles(fullPath, projectRoot, index);\n } else if (entry.isFile() && entry.name.endsWith(\".java\")) {\n const relativePath = path.relative(projectRoot, fullPath);\n const packageName = readJavaPackage(fullPath);\n const className = entry.name.replace(\".java\", \"\");\n const fqcn = packageName ? `${packageName}.${className}` : className;\n index.set(fqcn, relativePath);\n }\n }\n}\n\n/**\n * Read the package declaration from a Java file.\n * Only reads the first few lines for performance.\n */\nfunction readJavaPackage(filePath: string): string | null {\n let content: string;\n try {\n // Read only the first 2KB — package declaration is always near the top\n const buf = Buffer.alloc(2048);\n const fd = fs.openSync(filePath, \"r\");\n const bytesRead = fs.readSync(fd, buf, 0, 2048, 0);\n fs.closeSync(fd);\n content = buf.toString(\"utf-8\", 0, bytesRead);\n } catch {\n return null;\n }\n\n const match = content.match(/^\\s*package\\s+([\\w.]+)\\s*;/m);\n return match ? match[1] : null;\n}\n\n/**\n * Resolve a Java import to a project-relative file path using the package index.\n *\n * For named imports, returns a single path (or null if external).\n * For wildcard imports (`com.example.*`), returns an array of all matching\n * files in the package (or null if none match).\n *\n * @returns Project-relative path(s) or null if the class is external.\n */\nexport function resolveJavaImport(\n importSource: string,\n packageIndex: JavaPackageIndex,\n): string | string[] | null {\n // Wildcard import: com.example.* — resolve to all direct classes in the package\n if (importSource.endsWith(\".*\")) {\n const packagePrefix = importSource.slice(0, -2); // strip \".*\"\n const prefixWithDot = packagePrefix + \".\";\n const matches: string[] = [];\n for (const [fqcn, filePath] of packageIndex) {\n // Match only direct children — no additional dots after the prefix\n if (fqcn.startsWith(prefixWithDot) && !fqcn.slice(prefixWithDot.length).includes(\".\")) {\n matches.push(filePath);\n }\n }\n return matches.length > 0 ? matches : null;\n }\n\n // Direct lookup (fully-qualified class name)\n const direct = packageIndex.get(importSource);\n if (direct) return direct;\n\n return null;\n}\n","/**\n * Health runner service — executes detected linters/type-checkers and returns structured results.\n *\n * Only runs tools that are already configured in the project.\n * Never installs tools. Each tool has a configurable timeout.\n */\n\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type { DetectedTools, HealthResult, HealthIssue, HealthToolResult } from \"../../types/index.js\";\nimport { parsers, type ToolOutputParser } from \"./parsers.js\";\n\nconst execFileAsync = promisify(execFile);\n\n/** A configured tool runner. */\ninterface ToolRunner {\n /** Tool name (matches DetectedTools key value). */\n name: string;\n /** Command to execute. */\n command: string;\n /** Arguments to pass. */\n args: string[];\n /** Output parser for this tool. */\n parser: ToolOutputParser;\n}\n\n/** Build the list of tool runners based on detected tools. */\nfunction buildRunners(detectedTools: DetectedTools): ToolRunner[] {\n const runners: ToolRunner[] = [];\n\n if (detectedTools.linter) {\n const parser = parsers[detectedTools.linter];\n if (parser) {\n runners.push(getRunnerConfig(detectedTools.linter, parser));\n }\n }\n\n if (detectedTools.type_checker) {\n const parser = parsers[detectedTools.type_checker];\n if (parser) {\n runners.push(getRunnerConfig(detectedTools.type_checker, parser));\n }\n }\n\n return runners;\n}\n\n/** Get the command configuration for a tool. */\nfunction getRunnerConfig(tool: string, parser: ToolOutputParser): ToolRunner {\n switch (tool) {\n case \"eslint\":\n return { name: \"eslint\", command: \"npx\", args: [\"eslint\", \".\", \"--format\", \"json\"], parser };\n case \"tsc\":\n return { name: \"tsc\", command: \"npx\", args: [\"tsc\", \"--noEmit\", \"--pretty\", \"false\"], parser };\n case \"mypy\":\n return { name: \"mypy\", command: \"mypy\", args: [\".\", \"--no-error-summary\", \"--output\", \"json\"], parser };\n case \"ruff\":\n return { name: \"ruff\", command: \"ruff\", args: [\"check\", \".\", \"--output-format\", \"json\"], parser };\n case \"clippy\":\n return { name: \"clippy\", command: \"cargo\", args: [\"clippy\", \"--message-format\", \"json\"], parser };\n default:\n return { name: tool, command: tool, args: [], parser };\n }\n}\n\n/**\n * Run all detected health tools and return structured results.\n *\n * @param projectRoot Absolute path to the project root.\n * @param detectedTools Tools detected during project scanning.\n * @param timeoutMs Timeout per tool in milliseconds.\n */\nexport async function runHealthChecks(\n projectRoot: string,\n detectedTools: DetectedTools,\n timeoutMs: number,\n): Promise<HealthResult> {\n const overallStart = Date.now();\n const runners = buildRunners(detectedTools);\n\n const toolResults: HealthToolResult[] = [];\n const allIssues: HealthIssue[] = [];\n\n // Run tools sequentially to avoid resource contention\n for (const runner of runners) {\n const result = await runTool(runner, projectRoot, timeoutMs);\n toolResults.push(result.toolResult);\n allIssues.push(...result.issues);\n }\n\n const totalErrors = allIssues.filter((i) => i.severity === \"error\").length;\n const totalWarnings = allIssues.filter((i) => i.severity === \"warning\").length;\n\n return {\n tools_run: toolResults,\n total_errors: totalErrors,\n total_warnings: totalWarnings,\n issues: allIssues,\n run_duration_ms: Date.now() - overallStart,\n };\n}\n\n/** Run a single tool and parse its output. */\nasync function runTool(\n runner: ToolRunner,\n projectRoot: string,\n timeoutMs: number,\n): Promise<{ toolResult: HealthToolResult; issues: HealthIssue[] }> {\n const start = Date.now();\n\n try {\n const { stdout, stderr } = await execFileAsync(runner.command, runner.args, {\n cwd: projectRoot,\n timeout: timeoutMs,\n maxBuffer: 10 * 1024 * 1024, // 10MB\n env: { ...process.env, FORCE_COLOR: \"0\", NO_COLOR: \"1\" },\n });\n\n const issues = runner.parser(stdout || stderr, runner.name);\n const errorCount = issues.filter((i) => i.severity === \"error\").length;\n const warningCount = issues.filter((i) => i.severity === \"warning\").length;\n\n return {\n toolResult: {\n tool: runner.name,\n success: true,\n run_duration_ms: Date.now() - start,\n error_count: errorCount,\n warning_count: warningCount,\n error_message: null,\n },\n issues,\n };\n } catch (err: unknown) {\n const duration = Date.now() - start;\n\n // Many tools exit non-zero when they find issues — that's expected\n if (isExecError(err) && err.stdout) {\n const issues = runner.parser(err.stdout, runner.name);\n const errorCount = issues.filter((i) => i.severity === \"error\").length;\n const warningCount = issues.filter((i) => i.severity === \"warning\").length;\n\n return {\n toolResult: {\n tool: runner.name,\n success: true,\n run_duration_ms: duration,\n error_count: errorCount,\n warning_count: warningCount,\n error_message: null,\n },\n issues,\n };\n }\n\n // Actual failure (tool not found, timeout, etc.)\n const message = err instanceof Error ? err.message : String(err);\n const isTimeout = message.includes(\"TIMEOUT\") || message.includes(\"timed out\");\n\n return {\n toolResult: {\n tool: runner.name,\n success: false,\n run_duration_ms: duration,\n error_count: 0,\n warning_count: 0,\n error_message: isTimeout ? `Timed out after ${timeoutMs}ms` : message,\n },\n issues: [],\n };\n }\n}\n\n/** Type guard for exec errors that have stdout/stderr. */\nfunction isExecError(err: unknown): err is Error & { stdout: string; stderr: string } {\n return err instanceof Error && \"stdout\" in err;\n}\n","/**\n * Output parsers for health check tools.\n *\n * Each parser takes raw stdout from a tool and returns structured health issues.\n */\n\nimport type { HealthIssue, HealthIssueSeverity } from \"../../types/index.js\";\n\n/** A function that parses tool output into structured issues. */\nexport type ToolOutputParser = (output: string, toolName: string) => HealthIssue[];\n\n/** Registry of output parsers keyed by tool name. */\nexport const parsers: Record<string, ToolOutputParser> = {\n eslint: parseEslintOutput,\n tsc: parseTscOutput,\n mypy: parseMypyOutput,\n ruff: parseRuffOutput,\n clippy: parseClippyOutput,\n};\n\n// ---------------------------------------------------------------------------\n// ESLint: --format json\n// ---------------------------------------------------------------------------\n\ninterface EslintFileResult {\n filePath: string;\n messages: Array<{\n line: number;\n column: number;\n severity: 1 | 2;\n ruleId: string | null;\n message: string;\n }>;\n}\n\n/** Parse ESLint JSON output. */\nfunction parseEslintOutput(output: string, toolName: string): HealthIssue[] {\n const issues: HealthIssue[] = [];\n\n let results: EslintFileResult[];\n try {\n results = JSON.parse(output);\n } catch {\n return issues;\n }\n\n if (!Array.isArray(results)) return issues;\n\n for (const file of results) {\n for (const msg of file.messages) {\n issues.push({\n file: file.filePath,\n line: msg.line ?? null,\n column: msg.column ?? null,\n severity: msg.severity === 2 ? \"error\" : \"warning\",\n code: msg.ruleId ?? null,\n message: msg.message,\n tool: toolName,\n });\n }\n }\n\n return issues;\n}\n\n// ---------------------------------------------------------------------------\n// TypeScript: tsc --noEmit --pretty false\n// ---------------------------------------------------------------------------\n\n/**\n * Parse tsc plain-text output.\n * Format: `file(line,col): error TSxxxx: message`\n */\nfunction parseTscOutput(output: string, toolName: string): HealthIssue[] {\n const issues: HealthIssue[] = [];\n const lineRegex = /^(.+?)\\((\\d+),(\\d+)\\):\\s+(error|warning)\\s+(TS\\d+):\\s+(.+)$/;\n\n for (const line of output.split(\"\\n\")) {\n const match = line.match(lineRegex);\n if (match) {\n issues.push({\n file: match[1],\n line: parseInt(match[2], 10),\n column: parseInt(match[3], 10),\n severity: match[4] as HealthIssueSeverity,\n code: match[5],\n message: match[6],\n tool: toolName,\n });\n }\n }\n\n return issues;\n}\n\n// ---------------------------------------------------------------------------\n// mypy: --output json\n// ---------------------------------------------------------------------------\n\ninterface MypyJsonLine {\n file: string;\n line: number;\n column: number;\n severity: string;\n code: string;\n message: string;\n}\n\n/** Parse mypy JSON output (one JSON object per line). */\nfunction parseMypyOutput(output: string, toolName: string): HealthIssue[] {\n const issues: HealthIssue[] = [];\n\n for (const line of output.split(\"\\n\")) {\n if (!line.trim()) continue;\n\n let entry: MypyJsonLine;\n try {\n entry = JSON.parse(line);\n } catch {\n // mypy may also output plain text — try the plain format\n const parsed = parseMypyPlainLine(line, toolName);\n if (parsed) issues.push(parsed);\n continue;\n }\n\n issues.push({\n file: entry.file,\n line: entry.line ?? null,\n column: entry.column ?? null,\n severity: mapMypySeverity(entry.severity),\n code: entry.code ?? null,\n message: entry.message,\n tool: toolName,\n });\n }\n\n return issues;\n}\n\n/** Parse a mypy plain-text error line: `file:line: severity: message [code]` */\nfunction parseMypyPlainLine(line: string, toolName: string): HealthIssue | null {\n const match = line.match(/^(.+?):(\\d+):\\s+(error|warning|note):\\s+(.+?)(?:\\s+\\[(.+?)\\])?$/);\n if (!match) return null;\n\n return {\n file: match[1],\n line: parseInt(match[2], 10),\n column: null,\n severity: mapMypySeverity(match[3]),\n code: match[5] ?? null,\n message: match[4],\n tool: toolName,\n };\n}\n\nfunction mapMypySeverity(severity: string): HealthIssueSeverity {\n if (severity === \"error\") return \"error\";\n if (severity === \"warning\") return \"warning\";\n return \"info\";\n}\n\n// ---------------------------------------------------------------------------\n// Ruff: --output-format json\n// ---------------------------------------------------------------------------\n\ninterface RuffJsonEntry {\n filename: string;\n location: { row: number; column: number };\n code: string;\n message: string;\n}\n\n/** Parse Ruff JSON output. */\nfunction parseRuffOutput(output: string, toolName: string): HealthIssue[] {\n const issues: HealthIssue[] = [];\n\n let entries: RuffJsonEntry[];\n try {\n entries = JSON.parse(output);\n } catch {\n return issues;\n }\n\n if (!Array.isArray(entries)) return issues;\n\n for (const entry of entries) {\n issues.push({\n file: entry.filename,\n line: entry.location?.row ?? null,\n column: entry.location?.column ?? null,\n severity: \"warning\",\n code: entry.code ?? null,\n message: entry.message,\n tool: toolName,\n });\n }\n\n return issues;\n}\n\n// ---------------------------------------------------------------------------\n// Clippy: cargo clippy --message-format json\n// ---------------------------------------------------------------------------\n\ninterface CargoMessage {\n reason?: string;\n message?: {\n level: string;\n code?: { code: string } | null;\n message: string;\n spans: Array<{\n file_name: string;\n line_start: number;\n column_start: number;\n }>;\n };\n}\n\n/** Parse Clippy JSON output (one JSON object per line). */\nfunction parseClippyOutput(output: string, toolName: string): HealthIssue[] {\n const issues: HealthIssue[] = [];\n\n for (const line of output.split(\"\\n\")) {\n if (!line.trim()) continue;\n\n let entry: CargoMessage;\n try {\n entry = JSON.parse(line);\n } catch {\n continue;\n }\n\n if (entry.reason !== \"compiler-message\" || !entry.message) continue;\n\n const msg = entry.message;\n const span = msg.spans[0];\n\n if (msg.level === \"error\" || msg.level === \"warning\") {\n issues.push({\n file: span?.file_name ?? \"\",\n line: span?.line_start ?? null,\n column: span?.column_start ?? null,\n severity: msg.level === \"error\" ? \"error\" : \"warning\",\n code: msg.code?.code ?? null,\n message: msg.message,\n tool: toolName,\n });\n }\n }\n\n return issues;\n}\n","/**\n * Scanner service — orchestrates project detection and file tree building.\n *\n * This is the main entry point for the `scan` command.\n * Supports three scan paths:\n * A) Cache hit — same HEAD, no uncommitted changes → return cached result\n * B) Incremental — HEAD moved or uncommitted changes, <50% files changed\n * C) Full scan — no cache or >50% files changed\n */\n\nimport type { ScanResult, CacheStatus, FileTreeEntry, FileEntry, Symbol, HealthResult, DependencyEntry } from \"../../types/index.js\";\nimport { loadConfig, type ResolvedConfig } from \"../../config/index.js\";\nimport { detectProject } from \"./project-detector.js\";\nimport { buildFileTree } from \"./file-tree-builder.js\";\nimport { getHead, getDiffNameStatus, getUncommittedChanges, type GitFileChange } from \"../git/index.js\";\nimport { readCache, readMeta, writeCache, isCacheValid } from \"../cache/index.js\";\nimport { buildSymbolIndex, updateSymbolIndex } from \"../parser/symbol-index.js\";\nimport { buildDependencyGraph, updateDependencyGraph } from \"../parser/dependency-graph.js\";\nimport { runHealthChecks } from \"../health/index.js\";\nimport { collectSourceFiles } from \"../parser/utils.js\";\n\n/** Threshold: if changed files exceed this fraction of total, do a full scan. */\nconst INCREMENTAL_THRESHOLD = 0.5;\n\n/** Prefix for the cache directory — changes here are not user changes. */\nconst CACHE_DIR_PREFIX = \".inspect/\";\n\n/** Filter out cache directory files from git change lists. */\nfunction filterCacheFiles(changes: GitFileChange[]): GitFileChange[] {\n return changes.filter((c) => !c.path.startsWith(CACHE_DIR_PREFIX));\n}\n\n/**\n * Config files that affect how source files are parsed or resolved.\n * If any of these change, a full scan is needed because the incremental\n * path only re-parses changed source files — it won't re-resolve existing\n * files against new config settings (path aliases, ignore rules, etc.).\n */\nconst CONFIG_FILES_AFFECTING_PARSE = new Set([\n \"tsconfig.json\",\n \"inspect.config.json\",\n \".inspect/config.json\",\n]);\n\n/** Check whether any changed path is a config file that affects parsing. */\nfunction hasConfigChange(changedPaths: Iterable<string>): boolean {\n for (const p of changedPaths) {\n if (CONFIG_FILES_AFFECTING_PARSE.has(p)) return true;\n }\n return false;\n}\n\n/**\n * Run a scan of the project at the given path.\n *\n * Uses cached results when possible, incrementally updates when efficient,\n * and falls back to a full scan otherwise.\n *\n * @param projectRoot Absolute path to the project root.\n * @param includeHealth When true, run detected linters/type-checkers.\n */\nexport async function scan(projectRoot: string, includeHealth = false): Promise<ScanResult> {\n const startTime = Date.now();\n const config = loadConfig(projectRoot);\n const gitHead = await getHead(projectRoot);\n\n // Try Path A: Cache hit\n // Only use cached result when health state matches the caller's request:\n // if health is requested the cache must have it, if not requested the cache must lack it.\n const cachedResult = readCache(projectRoot);\n const healthMatches = cachedResult\n ? includeHealth ? cachedResult.health !== null : cachedResult.health === null\n : false;\n if (cachedResult && healthMatches && isCacheValid(projectRoot, gitHead)) {\n const uncommitted = filterCacheFiles(await getUncommittedChanges(projectRoot));\n if (uncommitted.length === 0) {\n return {\n ...cachedResult,\n cache: {\n status: \"cache_hit\",\n git_head: gitHead,\n scanned_at: new Date().toISOString(),\n scan_duration_ms: Date.now() - startTime,\n },\n };\n }\n }\n\n // Try Path B: Incremental update\n if (cachedResult) {\n const meta = readMeta(projectRoot);\n const cachedHead = meta?.git_head ?? null;\n\n // Collect all changed files (committed since cached HEAD + uncommitted)\n const changedFileMap = new Map<string, string>();\n\n if (cachedHead && cachedHead !== gitHead) {\n const committed = filterCacheFiles(await getDiffNameStatus(projectRoot, cachedHead));\n for (const entry of committed) {\n changedFileMap.set(entry.path, entry.status);\n }\n }\n\n const uncommitted = filterCacheFiles(await getUncommittedChanges(projectRoot));\n for (const entry of uncommitted) {\n changedFileMap.set(entry.path, entry.status);\n }\n\n // Config file changes invalidate all cached symbols/deps — full scan required\n if (hasConfigChange(changedFileMap.keys())) {\n return fullScan(projectRoot, config, gitHead, includeHealth, startTime);\n }\n\n // Check threshold — use max of current and cached file counts to avoid\n // edge cases where deleting files inflates the ratio\n const sourceFiles = collectSourceFiles(projectRoot, config);\n const cachedFileCount = Object.keys(cachedResult.symbols ?? {}).length;\n const totalFiles = Math.max(sourceFiles.length, cachedFileCount);\n const changedCount = changedFileMap.size;\n\n if (totalFiles > 0 && changedCount / totalFiles <= INCREMENTAL_THRESHOLD) {\n const result = await incrementalScan(\n projectRoot,\n config,\n cachedResult,\n changedFileMap,\n gitHead,\n includeHealth,\n startTime,\n );\n return result;\n }\n }\n\n // Path C: Full scan\n return fullScan(projectRoot, config, gitHead, includeHealth, startTime);\n}\n\n// ---------------------------------------------------------------------------\n// Scan path implementations\n// ---------------------------------------------------------------------------\n\n/**\n * Path B: Incrementally update cached results by re-parsing only changed files.\n */\nasync function incrementalScan(\n projectRoot: string,\n config: ResolvedConfig,\n cachedResult: ScanResult,\n changedFileMap: Map<string, string>,\n gitHead: string | null,\n includeHealth: boolean,\n startTime: number,\n): Promise<ScanResult> {\n const changedFiles: string[] = [];\n const deletedFiles: string[] = [];\n\n for (const [filePath, status] of changedFileMap) {\n if (status === \"D\") {\n deletedFiles.push(filePath);\n } else {\n changedFiles.push(filePath);\n }\n }\n\n const project = detectProject(projectRoot);\n const tree = buildFileTree(projectRoot, config);\n\n // Incrementally update symbols and dependencies in parallel\n const cachedSymbols = cachedResult.symbols ?? {};\n const cachedDeps = cachedResult.dependencies ?? {};\n\n const [symbols, dependencies] = await Promise.all([\n updateSymbolIndex(cachedSymbols, changedFiles, deletedFiles, projectRoot),\n updateDependencyGraph(cachedDeps, changedFiles, deletedFiles, projectRoot, config),\n ]);\n\n enrichTreeWithSymbolCounts(tree, symbols);\n\n let health: HealthResult | null = null;\n if (includeHealth) {\n health = await runHealthChecks(projectRoot, project.detected_tools, config.health_timeout_ms);\n }\n\n const cache: CacheStatus = {\n status: \"incremental_update\",\n git_head: gitHead,\n scanned_at: new Date().toISOString(),\n scan_duration_ms: Date.now() - startTime,\n files_rescanned: changedFiles.length + deletedFiles.length,\n };\n\n const result: ScanResult = {\n project,\n tree,\n symbols: Object.keys(symbols).length > 0 ? symbols : null,\n dependencies: Object.keys(dependencies).length > 0 ? dependencies : null,\n health,\n cache,\n };\n\n writeCache(projectRoot, result, gitHead);\n return result;\n}\n\n/**\n * Path C: Full scan — rebuild everything from scratch.\n */\nasync function fullScan(\n projectRoot: string,\n config: ResolvedConfig,\n gitHead: string | null,\n includeHealth: boolean,\n startTime: number,\n): Promise<ScanResult> {\n const project = detectProject(projectRoot);\n const tree = buildFileTree(projectRoot, config);\n\n const sourceFiles = collectSourceFiles(projectRoot, config);\n\n const [symbols, dependencies] = await Promise.all([\n buildSymbolIndex(projectRoot, config, sourceFiles),\n buildDependencyGraph(projectRoot, config, sourceFiles),\n ]);\n\n enrichTreeWithSymbolCounts(tree, symbols);\n\n let health: HealthResult | null = null;\n if (includeHealth) {\n health = await runHealthChecks(projectRoot, project.detected_tools, config.health_timeout_ms);\n }\n\n const cache: CacheStatus = {\n status: \"fresh\",\n git_head: gitHead,\n scanned_at: new Date().toISOString(),\n scan_duration_ms: Date.now() - startTime,\n };\n\n const result: ScanResult = {\n project,\n tree,\n symbols: Object.keys(symbols).length > 0 ? symbols : null,\n dependencies: Object.keys(dependencies).length > 0 ? dependencies : null,\n health,\n cache,\n };\n\n writeCache(projectRoot, result, gitHead);\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Walk the file tree and set the `symbols` count on each FileEntry\n * that has corresponding entries in the symbol index.\n */\nfunction enrichTreeWithSymbolCounts(\n tree: Record<string, FileTreeEntry>,\n symbols: Record<string, Symbol[]>,\n prefix = \"\",\n): void {\n for (const [key, value] of Object.entries(tree)) {\n if (isFileEntry(value)) {\n const filePath = prefix + key;\n const syms = symbols[filePath];\n if (syms) {\n value.symbols = syms.length;\n }\n } else if (isDirectoryEntry(value)) {\n enrichTreeWithSymbolCounts(\n value as Record<string, FileTreeEntry>,\n symbols,\n prefix + key,\n );\n }\n }\n}\n\nfunction isFileEntry(entry: FileTreeEntry): entry is FileEntry {\n return \"size\" in entry && !(\"_collapsed\" in entry);\n}\n\nfunction isDirectoryEntry(entry: FileTreeEntry): boolean {\n return !(\"size\" in entry) && !(\"_collapsed\" in entry);\n}\n","/**\n * Usage finder — searches dependent files for actual usages of a symbol.\n *\n * Uses tree-sitter to find identifier nodes that match the symbol name,\n * filtering out import statements to focus on actual usage sites.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type Parser from \"web-tree-sitter\";\nimport type { UsageSite } from \"../../types/index.js\";\nimport { parseSource } from \"../parser/index.js\";\n\n/**\n * Find all usage sites of a symbol within a file.\n *\n * @param symbolName The symbol name to search for.\n * @param filePath Project-relative path of the file to search.\n * @param projectRoot Absolute path to the project root.\n * @returns Array of usage sites (line number + context).\n */\nexport async function findUsageSites(\n symbolName: string,\n filePath: string,\n projectRoot: string,\n): Promise<UsageSite[]> {\n const absolutePath = path.join(projectRoot, filePath);\n let source: string;\n try {\n source = fs.readFileSync(absolutePath, \"utf-8\");\n } catch {\n return [];\n }\n\n const tree = await parseSource(filePath, source);\n if (!tree) return [];\n\n const lines = source.split(\"\\n\");\n const usages: UsageSite[] = [];\n\n findIdentifiers(tree.rootNode, symbolName, lines, usages);\n return usages;\n}\n\n/**\n * Recursively walk the AST looking for identifier nodes matching the symbol name.\n * Skip identifiers that are part of import statements.\n */\nfunction findIdentifiers(\n node: Parser.SyntaxNode,\n symbolName: string,\n lines: string[],\n usages: UsageSite[],\n): void {\n // Skip import-related nodes\n if (isImportNode(node)) return;\n\n if (\n (node.type === \"identifier\" || node.type === \"type_identifier\" || node.type === \"property_identifier\") &&\n node.text === symbolName\n ) {\n const line = node.startPosition.row + 1; // 1-indexed\n const context = lines[node.startPosition.row]?.trim() ?? \"\";\n\n // Avoid duplicate lines (e.g. multiple references on same line)\n if (!usages.some((u) => u.line === line)) {\n usages.push({ line, context });\n }\n }\n\n for (let i = 0; i < node.childCount; i++) {\n findIdentifiers(node.child(i)!, symbolName, lines, usages);\n }\n}\n\n/**\n * Check if a node is an import statement (should be skipped for usage finding).\n */\nfunction isImportNode(node: Parser.SyntaxNode): boolean {\n return (\n node.type === \"import_statement\" ||\n node.type === \"import_from_statement\" ||\n node.type === \"import_declaration\" ||\n (node.type === \"export_statement\" && node.children.some((c) => c.type === \"string\"))\n );\n}\n","/**\n * Test file association — finds test files for a given source file.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { DependencyEntry } from \"../../types/index.js\";\n\n/** Common test file suffixes/patterns. */\nconst TEST_SUFFIXES = [\".test\", \".spec\", \"_test\", \"_spec\"];\n\n/** Common test directory names. */\nconst TEST_DIRS = [\"__tests__\", \"tests\", \"test\"];\n\n/**\n * Find test files associated with a source file.\n *\n * Uses two strategies:\n * 1. Co-located test files (e.g. foo.ts → foo.test.ts)\n * 2. Test directory mirrors (e.g. src/foo.ts → tests/foo.test.ts or __tests__/foo.test.ts)\n */\nexport function findTestFiles(sourceFile: string, allFiles: string[]): string[] {\n const results: string[] = [];\n const parsed = path.parse(sourceFile);\n const baseName = parsed.name; // e.g. \"utils\" from \"src/utils.ts\"\n const ext = parsed.ext; // e.g. \".ts\"\n\n for (const file of allFiles) {\n const fileParsed = path.parse(file);\n\n // Check if this file is a test file for our source\n for (const suffix of TEST_SUFFIXES) {\n if (fileParsed.name === baseName + suffix && fileParsed.ext === ext) {\n results.push(file);\n }\n }\n }\n\n return [...new Set(results)];\n}\n\n/**\n * Check if a test file imports the target file (directly or transitively).\n */\nexport function checkTestImportsTarget(\n testFile: string,\n targetFile: string,\n dependencies: Record<string, DependencyEntry>,\n): boolean {\n const entry = dependencies[testFile];\n if (!entry) return false;\n\n // Direct import\n if (entry.imports_from.includes(targetFile)) return true;\n\n // One level of transitivity\n for (const dep of entry.imports_from) {\n const depEntry = dependencies[dep];\n if (depEntry && depEntry.imports_from.includes(targetFile)) return true;\n }\n\n return false;\n}\n","/**\n * Impact analysis service.\n *\n * Analyzes the impact of changing a file or symbol by computing\n * direct and transitive dependents, usage sites, and test coverage.\n */\n\nimport type {\n ImpactResult,\n DependencyEntry,\n Symbol,\n DirectDependent,\n TransitiveDependent,\n TestCoverage,\n} from \"../../types/index.js\";\nimport type { ResolvedConfig } from \"../../config/index.js\";\nimport { loadConfig } from \"../../config/index.js\";\nimport { buildSymbolIndex } from \"../parser/symbol-index.js\";\nimport { buildDependencyGraph } from \"../parser/dependency-graph.js\";\nimport { findUsageSites } from \"./usage-finder.js\";\nimport { findTestFiles, checkTestImportsTarget } from \"../differ/test-association.js\";\nimport { collectSourceFiles } from \"../parser/utils.js\";\nimport * as path from \"node:path\";\n\n/** Maximum transitive depth to walk. */\nconst MAX_TRANSITIVE_DEPTH = 2;\n\n/**\n * Analyze the impact of changing a target file or symbol.\n *\n * @param projectRoot Absolute path to the project root.\n * @param target Target string in format \"file_path\" or \"file_path:symbol_name\".\n * @returns Impact analysis result.\n */\nexport async function analyzeImpact(\n projectRoot: string,\n target: string,\n): Promise<ImpactResult> {\n const config = loadConfig(projectRoot);\n\n // Parse target string\n const { file, symbolName } = parseTarget(target);\n\n // Build symbol index and dependency graph\n const [symbols, dependencies] = await Promise.all([\n buildSymbolIndex(projectRoot, config),\n buildDependencyGraph(projectRoot, config),\n ]);\n\n // Look up target symbol info\n const targetSymbol = symbolName ? findSymbol(symbols, file, symbolName) : null;\n\n // Get direct dependents\n const depEntry = dependencies[file];\n const directFiles = depEntry ? depEntry.imported_by : [];\n\n // Find usage sites for the symbol in each direct dependent\n const directDependents: DirectDependent[] = [];\n if (symbolName) {\n for (const depFile of directFiles) {\n const usages = await findUsageSites(symbolName, depFile, projectRoot);\n directDependents.push({ file: depFile, usages });\n }\n } else {\n // File-level impact — no usage site search\n for (const depFile of directFiles) {\n directDependents.push({ file: depFile, usages: [] });\n }\n }\n\n // Compute transitive dependents\n const transitiveDependents = computeTransitiveDependents(\n directFiles,\n dependencies,\n file,\n );\n\n // Find test files\n const allFiles = collectSourceFiles(projectRoot, config).map(\n (f) => path.relative(projectRoot, f),\n );\n const testFiles = findTestFiles(file, allFiles);\n const testCoverage: TestCoverage = {\n test_files_found: testFiles,\n imports_target: testFiles.some((tf) =>\n checkTestImportsTarget(tf, file, dependencies),\n ),\n };\n\n // Total usage count\n const totalUsages = directDependents.reduce((sum, d) => sum + d.usages.length, 0);\n\n return {\n target: {\n file,\n symbol: symbolName,\n kind: targetSymbol?.kind ?? null,\n line: targetSymbol?.line ?? null,\n signature: targetSymbol?.signature ?? null,\n },\n dependents: {\n direct: directDependents,\n transitive: transitiveDependents,\n },\n risk_assessment: {\n direct_dependents: directDependents.length,\n total_usages: totalUsages,\n transitive_dependents: transitiveDependents.length,\n test_coverage: testCoverage,\n },\n };\n}\n\n/**\n * Parse a target string into file path and optional symbol name.\n */\nfunction parseTarget(target: string): { file: string; symbolName: string | null } {\n const colonIndex = target.lastIndexOf(\":\");\n if (colonIndex > 0 && colonIndex < target.length - 1) {\n // Check if this looks like a symbol separator vs. a path component\n // On Windows paths can have C:, so check if the part after : looks like a symbol\n const afterColon = target.slice(colonIndex + 1);\n if (!afterColon.includes(\"/\") && !afterColon.includes(\"\\\\\")) {\n return {\n file: target.slice(0, colonIndex),\n symbolName: afterColon,\n };\n }\n }\n return { file: target, symbolName: null };\n}\n\n/**\n * Find a symbol in the symbol index by file and name.\n */\nfunction findSymbol(\n symbols: Record<string, Symbol[]>,\n file: string,\n name: string,\n): Symbol | null {\n const fileSymbols = symbols[file];\n if (!fileSymbols) return null;\n return fileSymbols.find((s) => s.name === name) ?? null;\n}\n\n/**\n * Compute transitive dependents by walking imported_by edges from direct dependents.\n */\nfunction computeTransitiveDependents(\n directFiles: string[],\n dependencies: Record<string, DependencyEntry>,\n targetFile: string,\n): TransitiveDependent[] {\n const directSet = new Set(directFiles);\n const visited = new Set<string>([targetFile, ...directFiles]);\n const result: TransitiveDependent[] = [];\n\n // BFS from direct dependents\n interface QueueItem {\n file: string;\n via: string;\n depth: number;\n }\n\n const queue: QueueItem[] = [];\n\n // Seed with files that import the direct dependents\n for (const directFile of directFiles) {\n const entry = dependencies[directFile];\n if (!entry) continue;\n\n for (const importer of entry.imported_by) {\n if (!visited.has(importer)) {\n queue.push({ file: importer, via: directFile, depth: 2 });\n visited.add(importer);\n }\n }\n }\n\n while (queue.length > 0) {\n const item = queue.shift()!;\n result.push({\n file: item.file,\n via: item.via,\n depth: item.depth,\n });\n\n // Don't go deeper than MAX_TRANSITIVE_DEPTH\n if (item.depth >= MAX_TRANSITIVE_DEPTH) continue;\n\n const entry = dependencies[item.file];\n if (!entry) continue;\n\n for (const importer of entry.imported_by) {\n if (!visited.has(importer)) {\n queue.push({ file: importer, via: item.file, depth: item.depth + 1 });\n visited.add(importer);\n }\n }\n }\n\n return result;\n}\n","/**\n * Blast radius computation — finds files affected by a set of changed files.\n */\n\nimport type { DependencyEntry } from \"../../types/index.js\";\n\nexport interface BlastRadiusEntry {\n changed_file: string;\n affected_files: string[];\n reason: string;\n}\n\n/**\n * Compute blast radius for a set of changed files using a dependency graph.\n *\n * For each changed file, finds all files that import it (directly) and\n * are not themselves in the changed set.\n */\nexport function computeBlastRadius(\n changedFiles: string[],\n dependencies: Record<string, DependencyEntry> | null,\n): BlastRadiusEntry[] {\n if (!dependencies) return [];\n\n const changedSet = new Set(changedFiles);\n const results: BlastRadiusEntry[] = [];\n\n for (const file of changedFiles) {\n const entry = dependencies[file];\n if (!entry) continue;\n\n const affected = entry.imported_by.filter((f) => !changedSet.has(f));\n if (affected.length === 0) continue;\n\n results.push({\n changed_file: file,\n affected_files: affected,\n reason: `imports ${file}`,\n });\n }\n\n return results;\n}\n","/**\n * Symbol diff — compares cached symbols against current symbols for changed files.\n */\n\nimport type { Symbol } from \"../../types/index.js\";\n\nexport interface SymbolDiffResult {\n new_symbols: Array<{ file: string; symbol: Symbol }>;\n removed_symbols: Array<{ file: string; symbol: Symbol }>;\n modified_symbols: Array<{ file: string; before: Symbol; after: Symbol }>;\n}\n\n/**\n * Diff symbols between cached state and current state for changed files.\n */\nexport function diffSymbols(\n cachedSymbols: Record<string, Symbol[]> | null,\n currentSymbols: Record<string, Symbol[]>,\n addedFiles: string[],\n deletedFiles: string[],\n modifiedFiles: string[],\n): SymbolDiffResult {\n const result: SymbolDiffResult = {\n new_symbols: [],\n removed_symbols: [],\n modified_symbols: [],\n };\n\n // Added files: all symbols are new\n for (const file of addedFiles) {\n const symbols = currentSymbols[file];\n if (symbols) {\n for (const symbol of symbols) {\n result.new_symbols.push({ file, symbol });\n }\n }\n }\n\n // Deleted files: all cached symbols are removed\n for (const file of deletedFiles) {\n const symbols = cachedSymbols?.[file];\n if (symbols) {\n for (const symbol of symbols) {\n result.removed_symbols.push({ file, symbol });\n }\n }\n }\n\n // Modified files: compare per-symbol\n for (const file of modifiedFiles) {\n const cached = cachedSymbols?.[file] ?? [];\n const current = currentSymbols[file] ?? [];\n\n const cachedMap = buildSymbolMap(cached);\n const currentMap = buildSymbolMap(current);\n\n // Find removed and modified\n for (const [key, cachedSym] of cachedMap) {\n const currentSym = currentMap.get(key);\n if (!currentSym) {\n result.removed_symbols.push({ file, symbol: cachedSym });\n } else if (!symbolsEqual(cachedSym, currentSym)) {\n result.modified_symbols.push({ file, before: cachedSym, after: currentSym });\n }\n }\n\n // Find new\n for (const [key, currentSym] of currentMap) {\n if (!cachedMap.has(key)) {\n result.new_symbols.push({ file, symbol: currentSym });\n }\n }\n }\n\n return result;\n}\n\n/** Build a map of symbols keyed by (name, kind). */\nfunction buildSymbolMap(symbols: Symbol[]): Map<string, Symbol> {\n const map = new Map<string, Symbol>();\n for (const sym of symbols) {\n map.set(`${sym.name}::${sym.kind}`, sym);\n }\n return map;\n}\n\n/** Check if two symbols are equal (all fields). */\nfunction symbolsEqual(a: Symbol, b: Symbol): boolean {\n return (\n a.name === b.name &&\n a.kind === b.kind &&\n a.exported === b.exported &&\n a.line === b.line &&\n a.end_line === b.end_line &&\n a.signature === b.signature &&\n a.visibility === b.visibility &&\n a.is_async === b.is_async &&\n arraysEqual(a.annotations, b.annotations)\n );\n}\n\nfunction arraysEqual(a?: string[], b?: string[]): boolean {\n if (!a && !b) return true;\n if (!a || !b) return false;\n if (a.length !== b.length) return false;\n return a.every((v, i) => v === b[i]);\n}\n","/**\n * Health diff — compares cached health issues against current health results.\n */\n\nimport type { HealthIssue, HealthDiff, HealthResult } from \"../../types/index.js\";\n\n/**\n * Compare cached health issues against fresh health results.\n *\n * @returns HealthDiff with new and resolved issues, or null if either input is null.\n */\nexport function diffHealth(\n cachedHealth: HealthResult | null,\n currentHealth: HealthResult | null,\n): HealthDiff | null {\n if (!cachedHealth || !currentHealth) return null;\n\n const cachedKeys = new Set(cachedHealth.issues.map(issueKey));\n const currentKeys = new Set(currentHealth.issues.map(issueKey));\n\n const newIssues = currentHealth.issues.filter((i) => !cachedKeys.has(issueKey(i)));\n const resolvedIssues = cachedHealth.issues.filter((i) => !currentKeys.has(issueKey(i)));\n\n return {\n new_issues: newIssues,\n resolved_issues: resolvedIssues,\n };\n}\n\n/** Composite key for matching health issues. */\nfunction issueKey(issue: HealthIssue): string {\n return `${issue.file}:${issue.line}:${issue.code}:${issue.tool}`;\n}\n","/**\n * Differ service — computes changes since the last scan.\n *\n * This is the main entry point for the `changed` command.\n * It is read-only and does NOT update the cache.\n */\n\nimport * as path from \"node:path\";\nimport type { ChangedResult, CacheStatus, Symbol } from \"../../types/index.js\";\nimport { loadConfig } from \"../../config/index.js\";\nimport { readCache, readMeta } from \"../cache/index.js\";\nimport {\n getHead,\n getDiffNameStatus,\n getUncommittedChanges,\n getPullCommitHashes,\n getFileCommitInfo,\n type GitFileChange,\n} from \"../git/index.js\";\nimport { computeBlastRadius } from \"./blast-radius.js\";\nimport { diffSymbols } from \"./symbol-diff.js\";\nimport { diffHealth } from \"./health-diff.js\";\nimport { runHealthChecks } from \"../health/index.js\";\nimport { extractSymbolsForFile } from \"../parser/symbol-index.js\";\nimport { detectProject } from \"../scanner/project-detector.js\";\nimport { withConcurrency, DEFAULT_CONCURRENCY } from \"../parser/utils.js\";\n\n/** Map git status codes to ChangedResult status strings. */\ntype FileStatus = \"added\" | \"modified\" | \"deleted\" | \"renamed\";\n\nfunction mapStatus(gitStatus: string): FileStatus {\n switch (gitStatus) {\n case \"A\": return \"added\";\n case \"D\": return \"deleted\";\n case \"R\": return \"renamed\";\n default: return \"modified\";\n }\n}\n\n/**\n * Compute changes since the last scan.\n *\n * @param projectRoot Absolute path to the project root.\n * @param includeHealth When true, run health checks and diff against cached health.\n * @throws Error if no cache exists or cache has no git HEAD.\n */\nexport async function changed(\n projectRoot: string,\n includeHealth: boolean,\n): Promise<ChangedResult> {\n const startTime = Date.now();\n\n // 1. Read cache\n const cachedScan = readCache(projectRoot);\n const meta = readMeta(projectRoot);\n if (!cachedScan || !meta) {\n throw new Error(\"No cached scan found. Run 'scan' first.\");\n }\n\n const sinceCommit = meta.git_head;\n if (!sinceCommit) {\n throw new Error(\"Cached scan has no git HEAD. Run 'scan' in a git repository first.\");\n }\n\n // 2. Get current HEAD\n const currentHead = await getHead(projectRoot);\n if (!currentHead) {\n throw new Error(\"Not a git repository or git is not available.\");\n }\n\n // 3. Get changes\n const [committedChanges, uncommittedChanges] = await Promise.all([\n getDiffNameStatus(projectRoot, sinceCommit),\n getUncommittedChanges(projectRoot),\n ]);\n\n // 4. Merge changes — uncommitted wins for same path\n const mergedChanges = mergeChanges(committedChanges, uncommittedChanges);\n\n // 5. Attribution\n const pullHashes = await getPullCommitHashes(projectRoot, sinceCommit);\n\n const filesChanged = await buildFilesChanged(\n mergedChanges,\n committedChanges,\n uncommittedChanges,\n pullHashes,\n projectRoot,\n sinceCommit,\n );\n\n // 6. Classify files by status\n const addedFiles = filesChanged.filter((f) => f.status === \"added\").map((f) => f.path);\n const deletedFiles = filesChanged.filter((f) => f.status === \"deleted\").map((f) => f.path);\n const modifiedFiles = filesChanged.filter((f) => f.status === \"modified\" || f.status === \"renamed\").map((f) => f.path);\n const changedPaths = [...addedFiles, ...modifiedFiles, ...deletedFiles];\n\n // 7. Blast radius\n const blastRadius = computeBlastRadius(changedPaths, cachedScan.dependencies);\n\n // 8. Re-parse changed files for symbol diff\n const filesToParse = [...addedFiles, ...modifiedFiles];\n const currentSymbols: Record<string, Symbol[]> = {};\n\n await withConcurrency(\n filesToParse.map((relPath) => async () => {\n const symbols = await extractSymbolsForFile(projectRoot, relPath);\n if (symbols.length > 0) {\n currentSymbols[relPath] = symbols;\n }\n }),\n DEFAULT_CONCURRENCY,\n );\n\n // 9. Symbol diff\n const symbolDiff = diffSymbols(\n cachedScan.symbols,\n currentSymbols,\n addedFiles,\n deletedFiles,\n modifiedFiles,\n );\n\n // 10. Health diff\n let healthDiff = null;\n if (includeHealth) {\n const config = loadConfig(projectRoot);\n const project = detectProject(projectRoot);\n const currentHealth = await runHealthChecks(\n projectRoot,\n project.detected_tools,\n config.health_timeout_ms,\n );\n healthDiff = diffHealth(cachedScan.health, currentHealth);\n }\n\n const cache: CacheStatus = {\n status: \"cache_hit\",\n git_head: currentHead,\n scanned_at: new Date().toISOString(),\n scan_duration_ms: Date.now() - startTime,\n };\n\n return {\n changes: {\n since_commit: sinceCommit,\n current_commit: currentHead,\n files_changed: filesChanged,\n blast_radius: blastRadius,\n new_symbols: symbolDiff.new_symbols,\n removed_symbols: symbolDiff.removed_symbols,\n modified_symbols: symbolDiff.modified_symbols,\n },\n health_diff: healthDiff,\n cache,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Merge committed and uncommitted changes. Uncommitted wins for same path. */\nfunction mergeChanges(\n committed: GitFileChange[],\n uncommitted: GitFileChange[],\n): GitFileChange[] {\n const merged = new Map<string, GitFileChange>();\n\n for (const change of committed) {\n merged.set(change.path, change);\n }\n\n for (const change of uncommitted) {\n merged.set(change.path, change);\n }\n\n return [...merged.values()];\n}\n\n/** Build the files_changed array with attribution. */\nasync function buildFilesChanged(\n merged: GitFileChange[],\n committed: GitFileChange[],\n uncommitted: GitFileChange[],\n pullHashes: Set<string>,\n projectRoot: string,\n sinceCommit: string,\n): Promise<ChangedResult[\"changes\"][\"files_changed\"]> {\n const committedPaths = new Set(committed.map((c) => c.path));\n const uncommittedPaths = new Set(uncommitted.map((c) => c.path));\n\n const results: ChangedResult[\"changes\"][\"files_changed\"] = [];\n\n for (const change of merged) {\n const isUncommitted = uncommittedPaths.has(change.path);\n const isCommitted = committedPaths.has(change.path);\n\n let source: \"pull\" | \"local_commit\" | \"uncommitted\";\n let author: string | null = null;\n let commitMessage: string | null = null;\n\n if (isUncommitted && !isCommitted) {\n source = \"uncommitted\";\n } else if (isCommitted) {\n const info = await getFileCommitInfo(projectRoot, change.path, sinceCommit);\n if (info) {\n author = info.author;\n commitMessage = info.message;\n source = pullHashes.has(info.hash) ? \"pull\" : \"local_commit\";\n } else {\n source = \"local_commit\";\n }\n // If also uncommitted, override source\n if (isUncommitted) {\n source = \"uncommitted\";\n }\n } else {\n source = \"uncommitted\";\n }\n\n results.push({\n path: change.path,\n status: mapStatus(change.status),\n source,\n author,\n commit_message: commitMessage,\n });\n }\n\n return results;\n}\n","/**\n * Compact output formatter.\n *\n * Transforms a full ScanResult into a CompactScanResult that uses ~2-3k tokens\n * instead of ~15-20k, giving agents what they need for orientation without noise.\n */\n\nimport * as path from \"node:path\";\nimport type {\n ScanResult,\n CompactScanResult,\n DirSummary,\n FileTreeEntry,\n FileEntry,\n CollapsedDir,\n Symbol,\n DependencyEntry,\n} from \"../../types/index.js\";\n\n/** Max number of key exports to include in the summary. */\nconst MAX_KEY_EXPORTS = 15;\n\n/** Max number of top files for most_imported / most_importing. */\nconst MAX_TOP_FILES = 5;\n\n/**\n * Convert a full ScanResult to a compact agent-friendly summary.\n */\nexport function compactify(result: ScanResult): CompactScanResult {\n return {\n project: result.project,\n structure: summarizeTree(result.tree),\n symbols_summary: summarizeSymbols(result.symbols, result.dependencies),\n dependencies_summary: summarizeDependencies(result.dependencies),\n health: result.health,\n cache: result.cache,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Tree summarization\n// ---------------------------------------------------------------------------\n\n/**\n * Summarize the file tree into one entry per top-level directory.\n */\nfunction summarizeTree(tree: Record<string, FileTreeEntry>): Record<string, DirSummary> {\n const structure: Record<string, DirSummary> = {};\n\n for (const [key, value] of Object.entries(tree)) {\n if (isCollapsed(value)) {\n structure[key + \"/\"] = {\n files: (value as CollapsedDir).file_count,\n languages: [],\n collapsed: true,\n };\n } else if (isFileEntry(value)) {\n // Root-level file — group into a synthetic \"_root\" entry\n if (!structure[\".\"]) {\n structure[\".\"] = { files: 0, languages: [] };\n }\n structure[\".\"].files++;\n const lang = extToLanguage(key);\n if (lang && !structure[\".\"].languages.includes(lang)) {\n structure[\".\"].languages.push(lang);\n }\n } else {\n // Directory — summarize recursively\n const dirEntry = value as Record<string, FileTreeEntry>;\n const files: string[] = [];\n const langs = new Set<string>();\n const keyDirs: string[] = [];\n\n collectDirStats(dirEntry, files, langs, keyDirs, \"\", 1);\n\n structure[key + \"/\"] = {\n files: files.length,\n languages: [...langs].sort(),\n ...(keyDirs.length > 0 ? { key_dirs: keyDirs.slice(0, 8) } : {}),\n };\n }\n }\n\n return structure;\n}\n\nfunction collectDirStats(\n tree: Record<string, FileTreeEntry>,\n files: string[],\n langs: Set<string>,\n keyDirs: string[],\n prefix: string,\n depth: number,\n): void {\n for (const [key, value] of Object.entries(tree)) {\n if (isCollapsed(value)) {\n // Skip collapsed dirs\n } else if (isFileEntry(value)) {\n files.push(prefix + key);\n const lang = extToLanguage(key);\n if (lang) langs.add(lang);\n } else {\n // Subdirectory — track as key_dir if depth 1\n if (depth === 1) {\n keyDirs.push(key + \"/\");\n }\n collectDirStats(\n value as Record<string, FileTreeEntry>,\n files,\n langs,\n keyDirs,\n prefix + key + \"/\",\n depth + 1,\n );\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Symbol summarization\n// ---------------------------------------------------------------------------\n\nfunction summarizeSymbols(\n symbols: Record<string, Symbol[]> | null,\n dependencies: Record<string, DependencyEntry> | null,\n): CompactScanResult[\"symbols_summary\"] {\n if (!symbols || Object.keys(symbols).length === 0) return null;\n\n let total = 0;\n const byKind: Record<string, number> = {};\n const exportedSymbols: { name: string; file: string; kind: string }[] = [];\n\n for (const [file, syms] of Object.entries(symbols)) {\n for (const sym of syms) {\n total++;\n byKind[sym.kind] = (byKind[sym.kind] ?? 0) + 1;\n if (sym.exported) {\n exportedSymbols.push({ name: sym.name, file, kind: sym.kind });\n }\n }\n }\n\n // Rank exported symbols by import count (fan-in) if dependency data available\n let keyExports: string[];\n if (dependencies) {\n const importCount = new Map<string, number>();\n for (const entry of Object.values(dependencies)) {\n for (const dep of entry.imported_by) {\n importCount.set(dep, (importCount.get(dep) ?? 0) + 1);\n }\n }\n\n // Score each exported symbol by its file's fan-in\n exportedSymbols.sort((a, b) => {\n const scoreA = importCount.get(a.file) ?? 0;\n const scoreB = importCount.get(b.file) ?? 0;\n return scoreB - scoreA;\n });\n }\n\n // Prefer classes/interfaces over plain functions for key_exports\n const priorityKinds = new Set([\"class\", \"interface\", \"type_alias\", \"enum\"]);\n const priority = exportedSymbols.filter((s) => priorityKinds.has(s.kind));\n const rest = exportedSymbols.filter((s) => !priorityKinds.has(s.kind));\n const ranked = [...priority, ...rest];\n\n // Deduplicate by name\n const seen = new Set<string>();\n keyExports = [];\n for (const sym of ranked) {\n if (!seen.has(sym.name) && keyExports.length < MAX_KEY_EXPORTS) {\n seen.add(sym.name);\n keyExports.push(sym.name);\n }\n }\n\n return { total, by_kind: byKind, key_exports: keyExports };\n}\n\n// ---------------------------------------------------------------------------\n// Dependency summarization\n// ---------------------------------------------------------------------------\n\nfunction summarizeDependencies(\n dependencies: Record<string, DependencyEntry> | null,\n): CompactScanResult[\"dependencies_summary\"] {\n if (!dependencies || Object.keys(dependencies).length === 0) return null;\n\n const totalFiles = Object.keys(dependencies).length;\n\n // Most imported: files with highest imported_by count\n const byImportedBy = Object.entries(dependencies)\n .map(([file, entry]) => ({ file, count: entry.imported_by.length }))\n .filter((e) => e.count > 0)\n .sort((a, b) => b.count - a.count)\n .slice(0, MAX_TOP_FILES)\n .map((e) => e.file);\n\n // Most importing: files with highest imports_from count\n const byImportsFrom = Object.entries(dependencies)\n .map(([file, entry]) => ({ file, count: entry.imports_from.length }))\n .filter((e) => e.count > 0)\n .sort((a, b) => b.count - a.count)\n .slice(0, MAX_TOP_FILES)\n .map((e) => e.file);\n\n return {\n total_files: totalFiles,\n most_imported: byImportedBy,\n most_importing: byImportsFrom,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction isFileEntry(entry: FileTreeEntry): entry is FileEntry {\n return \"size\" in entry && !(\"_collapsed\" in entry);\n}\n\nfunction isCollapsed(entry: FileTreeEntry): entry is CollapsedDir {\n return \"_collapsed\" in entry;\n}\n\nconst EXT_LANG_MAP: Record<string, string> = {\n \".ts\": \"typescript\",\n \".tsx\": \"typescript\",\n \".js\": \"javascript\",\n \".jsx\": \"javascript\",\n \".py\": \"python\",\n \".java\": \"java\",\n \".rs\": \"rust\",\n \".go\": \"go\",\n \".rb\": \"ruby\",\n \".kt\": \"kotlin\",\n \".json\": \"json\",\n \".yaml\": \"yaml\",\n \".yml\": \"yaml\",\n \".toml\": \"toml\",\n \".md\": \"markdown\",\n};\n\nfunction extToLanguage(fileName: string): string | null {\n const ext = path.extname(fileName).toLowerCase();\n return EXT_LANG_MAP[ext] ?? null;\n}\n","/**\n * inspect-mcp — Codebase intelligence MCP server.\n *\n * Entry point: starts the MCP server on stdio transport.\n */\n\nimport { startServer } from \"./runtime/index.js\";\n\nstartServer().catch((err) => {\n process.stderr.write(`Fatal: ${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n});\n"],"mappings":"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","names":["fs","path","fs","path","fs","path","fs","path","fs","path","require","fs","path","fs","path","extractors","fs","path","resolved","execFile","promisify","execFileAsync","promisify","execFile","fs","path","path","path","path","isFileEntry"]}