scip-query 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (330) hide show
  1. package/IMPROVEMENTS.md +143 -0
  2. package/PLAN.md +320 -0
  3. package/README.md +1213 -0
  4. package/dist/chunk-2QZ23IBN.js +55 -0
  5. package/dist/chunk-2QZ23IBN.js.map +1 -0
  6. package/dist/chunk-36OMT7ZJ.js +144 -0
  7. package/dist/chunk-36OMT7ZJ.js.map +1 -0
  8. package/dist/chunk-3E2X7RIE.js +101 -0
  9. package/dist/chunk-3E2X7RIE.js.map +1 -0
  10. package/dist/chunk-3UOUTZQT.js +45 -0
  11. package/dist/chunk-3UOUTZQT.js.map +1 -0
  12. package/dist/chunk-3ZZJVBIO.js +88 -0
  13. package/dist/chunk-3ZZJVBIO.js.map +1 -0
  14. package/dist/chunk-4TYLS5XX.js +10 -0
  15. package/dist/chunk-4TYLS5XX.js.map +1 -0
  16. package/dist/chunk-5FGUEU7N.js +101 -0
  17. package/dist/chunk-5FGUEU7N.js.map +1 -0
  18. package/dist/chunk-5WTJAXY2.js +61 -0
  19. package/dist/chunk-5WTJAXY2.js.map +1 -0
  20. package/dist/chunk-6NBLIDF4.js +24 -0
  21. package/dist/chunk-6NBLIDF4.js.map +1 -0
  22. package/dist/chunk-6SXADWLW.js +43 -0
  23. package/dist/chunk-6SXADWLW.js.map +1 -0
  24. package/dist/chunk-6VJ6Q7IE.js +65 -0
  25. package/dist/chunk-6VJ6Q7IE.js.map +1 -0
  26. package/dist/chunk-7OZPA5OO.js +258 -0
  27. package/dist/chunk-7OZPA5OO.js.map +1 -0
  28. package/dist/chunk-BEPIEVLR.js +76 -0
  29. package/dist/chunk-BEPIEVLR.js.map +1 -0
  30. package/dist/chunk-BFSCMC22.js +42 -0
  31. package/dist/chunk-BFSCMC22.js.map +1 -0
  32. package/dist/chunk-BP2ATLK2.js +110 -0
  33. package/dist/chunk-BP2ATLK2.js.map +1 -0
  34. package/dist/chunk-CM454WL3.js +114 -0
  35. package/dist/chunk-CM454WL3.js.map +1 -0
  36. package/dist/chunk-DCKMSTJ4.js +74 -0
  37. package/dist/chunk-DCKMSTJ4.js.map +1 -0
  38. package/dist/chunk-DEZKCZXD.js +40 -0
  39. package/dist/chunk-DEZKCZXD.js.map +1 -0
  40. package/dist/chunk-DVWGWHFW.js +99 -0
  41. package/dist/chunk-DVWGWHFW.js.map +1 -0
  42. package/dist/chunk-EMDQWNYR.js +102 -0
  43. package/dist/chunk-EMDQWNYR.js.map +1 -0
  44. package/dist/chunk-FFSWWE5O.js +33 -0
  45. package/dist/chunk-FFSWWE5O.js.map +1 -0
  46. package/dist/chunk-FGXRVW7G.js +73 -0
  47. package/dist/chunk-FGXRVW7G.js.map +1 -0
  48. package/dist/chunk-FUHJCHS4.js +158 -0
  49. package/dist/chunk-FUHJCHS4.js.map +1 -0
  50. package/dist/chunk-GJFURBEW.js +64 -0
  51. package/dist/chunk-GJFURBEW.js.map +1 -0
  52. package/dist/chunk-GTILYBH6.js +102 -0
  53. package/dist/chunk-GTILYBH6.js.map +1 -0
  54. package/dist/chunk-JJP7KQND.js +1 -0
  55. package/dist/chunk-JJP7KQND.js.map +1 -0
  56. package/dist/chunk-JKP5GH6T.js +213 -0
  57. package/dist/chunk-JKP5GH6T.js.map +1 -0
  58. package/dist/chunk-KCBMVQL5.js +38 -0
  59. package/dist/chunk-KCBMVQL5.js.map +1 -0
  60. package/dist/chunk-KVSW5KYP.js +78 -0
  61. package/dist/chunk-KVSW5KYP.js.map +1 -0
  62. package/dist/chunk-LAWMH22O.js +172 -0
  63. package/dist/chunk-LAWMH22O.js.map +1 -0
  64. package/dist/chunk-LB7OS35Q.js +72 -0
  65. package/dist/chunk-LB7OS35Q.js.map +1 -0
  66. package/dist/chunk-LUSIFBXO.js +57 -0
  67. package/dist/chunk-LUSIFBXO.js.map +1 -0
  68. package/dist/chunk-MBVNHJVN.js +44 -0
  69. package/dist/chunk-MBVNHJVN.js.map +1 -0
  70. package/dist/chunk-MGNMHKX3.js +15 -0
  71. package/dist/chunk-MGNMHKX3.js.map +1 -0
  72. package/dist/chunk-N5KEREIA.js +41 -0
  73. package/dist/chunk-N5KEREIA.js.map +1 -0
  74. package/dist/chunk-NDSQYIWT.js +71 -0
  75. package/dist/chunk-NDSQYIWT.js.map +1 -0
  76. package/dist/chunk-NUZ4OMU3.js +28 -0
  77. package/dist/chunk-NUZ4OMU3.js.map +1 -0
  78. package/dist/chunk-QOV2R2WT.js +170 -0
  79. package/dist/chunk-QOV2R2WT.js.map +1 -0
  80. package/dist/chunk-SEFSL2GF.js +78 -0
  81. package/dist/chunk-SEFSL2GF.js.map +1 -0
  82. package/dist/chunk-T6ARFSBZ.js +103 -0
  83. package/dist/chunk-T6ARFSBZ.js.map +1 -0
  84. package/dist/chunk-TBP6BICL.js +46 -0
  85. package/dist/chunk-TBP6BICL.js.map +1 -0
  86. package/dist/chunk-TDNNOR6D.js +97 -0
  87. package/dist/chunk-TDNNOR6D.js.map +1 -0
  88. package/dist/chunk-TSPZOMHC.js +195 -0
  89. package/dist/chunk-TSPZOMHC.js.map +1 -0
  90. package/dist/chunk-UNTPVD36.js +55 -0
  91. package/dist/chunk-UNTPVD36.js.map +1 -0
  92. package/dist/chunk-VRUJH4BO.js +88 -0
  93. package/dist/chunk-VRUJH4BO.js.map +1 -0
  94. package/dist/chunk-VZ7AMAFL.js +76 -0
  95. package/dist/chunk-VZ7AMAFL.js.map +1 -0
  96. package/dist/chunk-XFXDXEUN.js +24 -0
  97. package/dist/chunk-XFXDXEUN.js.map +1 -0
  98. package/dist/chunk-YZAA4LYG.js +169 -0
  99. package/dist/chunk-YZAA4LYG.js.map +1 -0
  100. package/dist/chunk-Z73NYSBZ.js +92 -0
  101. package/dist/chunk-Z73NYSBZ.js.map +1 -0
  102. package/dist/chunk-ZJRYBOEE.js +125 -0
  103. package/dist/chunk-ZJRYBOEE.js.map +1 -0
  104. package/dist/cli.js +5798 -0
  105. package/dist/cli.js.map +1 -0
  106. package/dist/db-BxaevAyc.d.ts +683 -0
  107. package/dist/index.d.ts +254 -0
  108. package/dist/index.js +1271 -0
  109. package/dist/index.js.map +1 -0
  110. package/dist/postinstall.js +167 -0
  111. package/dist/postinstall.js.map +1 -0
  112. package/dist/queries/affected.d.ts +14 -0
  113. package/dist/queries/affected.js +9 -0
  114. package/dist/queries/affected.js.map +1 -0
  115. package/dist/queries/bottlenecks.d.ts +18 -0
  116. package/dist/queries/bottlenecks.js +8 -0
  117. package/dist/queries/bottlenecks.js.map +1 -0
  118. package/dist/queries/by-kind.d.ts +20 -0
  119. package/dist/queries/by-kind.js +10 -0
  120. package/dist/queries/by-kind.js.map +1 -0
  121. package/dist/queries/call-graph.d.ts +13 -0
  122. package/dist/queries/call-graph.js +9 -0
  123. package/dist/queries/call-graph.js.map +1 -0
  124. package/dist/queries/change-surface.d.ts +10 -0
  125. package/dist/queries/change-surface.js +9 -0
  126. package/dist/queries/change-surface.js.map +1 -0
  127. package/dist/queries/clean-signature.d.ts +9 -0
  128. package/dist/queries/clean-signature.js +7 -0
  129. package/dist/queries/clean-signature.js.map +1 -0
  130. package/dist/queries/code.d.ts +17 -0
  131. package/dist/queries/code.js +9 -0
  132. package/dist/queries/code.js.map +1 -0
  133. package/dist/queries/complexity-hotspots.d.ts +19 -0
  134. package/dist/queries/complexity-hotspots.js +9 -0
  135. package/dist/queries/complexity-hotspots.js.map +1 -0
  136. package/dist/queries/complexity.d.ts +13 -0
  137. package/dist/queries/complexity.js +9 -0
  138. package/dist/queries/complexity.js.map +1 -0
  139. package/dist/queries/convergence.d.ts +11 -0
  140. package/dist/queries/convergence.js +9 -0
  141. package/dist/queries/convergence.js.map +1 -0
  142. package/dist/queries/coupling.d.ts +17 -0
  143. package/dist/queries/coupling.js +9 -0
  144. package/dist/queries/coupling.js.map +1 -0
  145. package/dist/queries/cycles.d.ts +16 -0
  146. package/dist/queries/cycles.js +8 -0
  147. package/dist/queries/cycles.js.map +1 -0
  148. package/dist/queries/dataflow.d.ts +19 -0
  149. package/dist/queries/dataflow.js +9 -0
  150. package/dist/queries/dataflow.js.map +1 -0
  151. package/dist/queries/dead.d.ts +10 -0
  152. package/dist/queries/dead.js +9 -0
  153. package/dist/queries/dead.js.map +1 -0
  154. package/dist/queries/deep-chains.d.ts +16 -0
  155. package/dist/queries/deep-chains.js +8 -0
  156. package/dist/queries/deep-chains.js.map +1 -0
  157. package/dist/queries/deps.d.ts +9 -0
  158. package/dist/queries/deps.js +9 -0
  159. package/dist/queries/deps.js.map +1 -0
  160. package/dist/queries/diff-impact.d.ts +13 -0
  161. package/dist/queries/diff-impact.js +9 -0
  162. package/dist/queries/diff-impact.js.map +1 -0
  163. package/dist/queries/doc-coverage.d.ts +14 -0
  164. package/dist/queries/doc-coverage.js +8 -0
  165. package/dist/queries/doc-coverage.js.map +1 -0
  166. package/dist/queries/drift.d.ts +25 -0
  167. package/dist/queries/drift.js +8 -0
  168. package/dist/queries/drift.js.map +1 -0
  169. package/dist/queries/extract-candidates.d.ts +25 -0
  170. package/dist/queries/extract-candidates.js +9 -0
  171. package/dist/queries/extract-candidates.js.map +1 -0
  172. package/dist/queries/fan.d.ts +29 -0
  173. package/dist/queries/fan.js +14 -0
  174. package/dist/queries/fan.js.map +1 -0
  175. package/dist/queries/files.d.ts +6 -0
  176. package/dist/queries/files.js +7 -0
  177. package/dist/queries/files.js.map +1 -0
  178. package/dist/queries/health.d.ts +18 -0
  179. package/dist/queries/health.js +21 -0
  180. package/dist/queries/health.js.map +1 -0
  181. package/dist/queries/hierarchy.d.ts +13 -0
  182. package/dist/queries/hierarchy.js +8 -0
  183. package/dist/queries/hierarchy.js.map +1 -0
  184. package/dist/queries/hotspots.d.ts +13 -0
  185. package/dist/queries/hotspots.js +8 -0
  186. package/dist/queries/hotspots.js.map +1 -0
  187. package/dist/queries/imports.d.ts +19 -0
  188. package/dist/queries/imports.js +12 -0
  189. package/dist/queries/imports.js.map +1 -0
  190. package/dist/queries/index.d.ts +47 -0
  191. package/dist/queries/index.js +207 -0
  192. package/dist/queries/index.js.map +1 -0
  193. package/dist/queries/isolated.d.ts +14 -0
  194. package/dist/queries/isolated.js +9 -0
  195. package/dist/queries/isolated.js.map +1 -0
  196. package/dist/queries/members.d.ts +10 -0
  197. package/dist/queries/members.js +8 -0
  198. package/dist/queries/members.js.map +1 -0
  199. package/dist/queries/methods.d.ts +6 -0
  200. package/dist/queries/methods.js +8 -0
  201. package/dist/queries/methods.js.map +1 -0
  202. package/dist/queries/outline.d.ts +10 -0
  203. package/dist/queries/outline.js +8 -0
  204. package/dist/queries/outline.js.map +1 -0
  205. package/dist/queries/passthrough-candidates.d.ts +18 -0
  206. package/dist/queries/passthrough-candidates.js +9 -0
  207. package/dist/queries/passthrough-candidates.js.map +1 -0
  208. package/dist/queries/redundant-reexports.d.ts +22 -0
  209. package/dist/queries/redundant-reexports.js +8 -0
  210. package/dist/queries/redundant-reexports.js.map +1 -0
  211. package/dist/queries/refs.d.ts +6 -0
  212. package/dist/queries/refs.js +7 -0
  213. package/dist/queries/refs.js.map +1 -0
  214. package/dist/queries/similar-chains.d.ts +29 -0
  215. package/dist/queries/similar-chains.js +8 -0
  216. package/dist/queries/similar-chains.js.map +1 -0
  217. package/dist/queries/similar-files.d.ts +19 -0
  218. package/dist/queries/similar-files.js +8 -0
  219. package/dist/queries/similar-files.js.map +1 -0
  220. package/dist/queries/similar-signatures.d.ts +21 -0
  221. package/dist/queries/similar-signatures.js +8 -0
  222. package/dist/queries/similar-signatures.js.map +1 -0
  223. package/dist/queries/similar.d.ts +34 -0
  224. package/dist/queries/similar.js +11 -0
  225. package/dist/queries/similar.js.map +1 -0
  226. package/dist/queries/slice.d.ts +21 -0
  227. package/dist/queries/slice.js +9 -0
  228. package/dist/queries/slice.js.map +1 -0
  229. package/dist/queries/stale-abstractions.d.ts +18 -0
  230. package/dist/queries/stale-abstractions.js +9 -0
  231. package/dist/queries/stale-abstractions.js.map +1 -0
  232. package/dist/queries/stats.d.ts +6 -0
  233. package/dist/queries/stats.js +7 -0
  234. package/dist/queries/stats.js.map +1 -0
  235. package/dist/queries/surface.d.ts +7 -0
  236. package/dist/queries/surface.js +8 -0
  237. package/dist/queries/surface.js.map +1 -0
  238. package/dist/queries/symbols.d.ts +6 -0
  239. package/dist/queries/symbols.js +9 -0
  240. package/dist/queries/symbols.js.map +1 -0
  241. package/dist/queries/system.d.ts +7 -0
  242. package/dist/queries/system.js +9 -0
  243. package/dist/queries/system.js.map +1 -0
  244. package/dist/queries/test-coverage.d.ts +22 -0
  245. package/dist/queries/test-coverage.js +11 -0
  246. package/dist/queries/test-coverage.js.map +1 -0
  247. package/dist/queries/trace.d.ts +6 -0
  248. package/dist/queries/trace.js +8 -0
  249. package/dist/queries/trace.js.map +1 -0
  250. package/dist/queries/wrapper-candidates.d.ts +17 -0
  251. package/dist/queries/wrapper-candidates.js +9 -0
  252. package/dist/queries/wrapper-candidates.js.map +1 -0
  253. package/dist/reindex-worker.js +368 -0
  254. package/dist/reindex-worker.js.map +1 -0
  255. package/docs/AGENT_GUIDE.md +359 -0
  256. package/package.json +70 -0
  257. package/reports/debloat/2026-04-10-scip-query-self-audit.md +161 -0
  258. package/skills/concrete-plan/SKILL.md +318 -0
  259. package/skills/scip-debloat/SKILL.md +413 -0
  260. package/skills/scip-explore/SKILL.md +235 -0
  261. package/skills/scip-verify/SKILL.md +323 -0
  262. package/src/cli.ts +1480 -0
  263. package/src/config.ts +117 -0
  264. package/src/db.ts +127 -0
  265. package/src/gitignore-filter.ts +143 -0
  266. package/src/index.ts +11 -0
  267. package/src/postinstall.ts +8 -0
  268. package/src/queries/affected.ts +86 -0
  269. package/src/queries/bottlenecks.ts +67 -0
  270. package/src/queries/by-kind.ts +204 -0
  271. package/src/queries/call-graph.ts +66 -0
  272. package/src/queries/change-surface.ts +110 -0
  273. package/src/queries/clean-signature.ts +22 -0
  274. package/src/queries/code.ts +101 -0
  275. package/src/queries/complexity-hotspots.ts +119 -0
  276. package/src/queries/complexity.ts +152 -0
  277. package/src/queries/convergence.ts +82 -0
  278. package/src/queries/coupling.ts +99 -0
  279. package/src/queries/cycles.ts +78 -0
  280. package/src/queries/dataflow.ts +128 -0
  281. package/src/queries/dead.ts +122 -0
  282. package/src/queries/deep-chains.ts +59 -0
  283. package/src/queries/deps.ts +46 -0
  284. package/src/queries/diff-impact.ts +204 -0
  285. package/src/queries/doc-coverage.ts +86 -0
  286. package/src/queries/drift.ts +224 -0
  287. package/src/queries/extract-candidates.ts +167 -0
  288. package/src/queries/fan.ts +148 -0
  289. package/src/queries/files.ts +16 -0
  290. package/src/queries/health.ts +324 -0
  291. package/src/queries/hierarchy.ts +49 -0
  292. package/src/queries/hotspots.ts +53 -0
  293. package/src/queries/imports.ts +95 -0
  294. package/src/queries/index.ts +45 -0
  295. package/src/queries/isolated.ts +67 -0
  296. package/src/queries/members.ts +54 -0
  297. package/src/queries/methods.ts +27 -0
  298. package/src/queries/outline.ts +52 -0
  299. package/src/queries/passthrough-candidates.ts +94 -0
  300. package/src/queries/redundant-reexports.ts +170 -0
  301. package/src/queries/refs.ts +27 -0
  302. package/src/queries/similar-chains.ts +314 -0
  303. package/src/queries/similar-files.ts +140 -0
  304. package/src/queries/similar-signatures.ts +151 -0
  305. package/src/queries/similar.ts +305 -0
  306. package/src/queries/slice.ts +154 -0
  307. package/src/queries/stale-abstractions.ts +82 -0
  308. package/src/queries/stats.ts +22 -0
  309. package/src/queries/surface.ts +34 -0
  310. package/src/queries/symbols.ts +39 -0
  311. package/src/queries/system.ts +86 -0
  312. package/src/queries/test-coverage.ts +106 -0
  313. package/src/queries/trace.ts +55 -0
  314. package/src/queries/wrapper-candidates.ts +112 -0
  315. package/src/query-support.ts +226 -0
  316. package/src/reindex/detect.ts +58 -0
  317. package/src/reindex/index.ts +153 -0
  318. package/src/reindex/indexers.ts +220 -0
  319. package/src/reindex/install.ts +125 -0
  320. package/src/reindex-worker.ts +35 -0
  321. package/src/setup.ts +202 -0
  322. package/src/symbol-parser.ts +278 -0
  323. package/src/types.ts +654 -0
  324. package/src/watch.ts +274 -0
  325. package/tests/gitignore-filter.test.ts +48 -0
  326. package/tests/queries.test.ts +300 -0
  327. package/tests/symbol-parser.test.ts +157 -0
  328. package/tsconfig.json +20 -0
  329. package/tsup.config.ts +40 -0
  330. package/vitest.config.ts +7 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts","../src/db.ts","../src/gitignore-filter.ts","../src/config.ts","../src/reindex/index.ts","../src/reindex/detect.ts","../src/reindex/indexers.ts","../src/reindex/install.ts","../src/watch.ts","../src/queries/stats.ts","../src/queries/files.ts","../src/symbol-parser.ts","../src/queries/clean-signature.ts","../src/queries/symbols.ts","../src/queries/methods.ts","../src/queries/refs.ts","../src/queries/trace.ts","../src/queries/deps.ts","../src/queries/system.ts","../src/queries/surface.ts","../src/query-support.ts","../src/queries/dead.ts","../src/queries/hotspots.ts","../src/queries/imports.ts","../src/queries/outline.ts","../src/queries/members.ts","../src/queries/fan.ts","../src/queries/coupling.ts","../src/queries/cycles.ts","../src/queries/bottlenecks.ts","../src/queries/isolated.ts","../src/queries/by-kind.ts","../src/queries/test-coverage.ts","../src/queries/doc-coverage.ts","../src/queries/deep-chains.ts","../src/queries/hierarchy.ts","../src/queries/call-graph.ts","../src/queries/similar.ts","../src/queries/similar-files.ts","../src/queries/similar-chains.ts","../src/queries/extract-candidates.ts","../src/queries/affected.ts","../src/queries/change-surface.ts","../src/queries/diff-impact.ts","../src/queries/drift.ts","../src/queries/wrapper-candidates.ts","../src/queries/passthrough-candidates.ts","../src/queries/stale-abstractions.ts","../src/queries/complexity-hotspots.ts","../src/queries/health.ts","../src/queries/convergence.ts","../src/queries/code.ts","../src/queries/complexity.ts","../src/queries/dataflow.ts","../src/queries/slice.ts","../src/queries/redundant-reexports.ts","../src/queries/similar-signatures.ts","../src/setup.ts"],"sourcesContent":["import { program } from 'commander';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { ScipDatabase } from './db.js';\nimport { createGitignoreFilter } from './gitignore-filter.js';\nimport { loadProjectConfig, resolveIndexPaths, initProjectConfig } from './config.js';\nimport { reindex, detectLanguages } from './reindex/index.js';\nimport { Watcher } from './watch.js';\nimport * as queries from './queries/index.js';\nimport type { ScipQueryConfig, DeadOptions, WatcherStatus } from './types.js';\nimport { installSkills, isScipInstalled, printScipInstallInstructions } from './setup.js';\n\n// ── Helpers ────────────────────────────────────────────────\n\nfunction resolveProjectRoot(): string {\n return process.env['SCIP_QUERY_PROJECT_ROOT'] ?? process.cwd();\n}\n\nfunction openDb(): ScipDatabase {\n const projectRoot = resolveProjectRoot();\n const config = loadProjectConfig(projectRoot);\n const paths = resolveIndexPaths(projectRoot, config);\n\n // Also check legacy location (project root) for backwards compat\n const dbPath = process.env['SCIP_QUERY_INDEX_DB']\n ?? (existsSync(paths.dbPath) ? paths.dbPath : join(projectRoot, 'index.db'));\n\n if (!existsSync(dbPath)) {\n console.error(`error: No index.db found. Run: scip-query reindex`);\n process.exit(1);\n }\n\n const dbConfig: ScipQueryConfig = {\n dbPath,\n indexPath: process.env['SCIP_QUERY_INDEX_SCIP'] ?? paths.indexPath,\n projectRoot,\n };\n\n const filter = createGitignoreFilter(projectRoot);\n return new ScipDatabase(dbConfig, filter);\n}\n\nfunction withDb(run: (db: ScipDatabase) => void): void {\n const db = openDb();\n try {\n run(db);\n } finally {\n db.close();\n }\n}\n\nfunction runQuery<T>(\n query: (db: ScipDatabase) => T,\n render: (result: T) => void,\n): void {\n withDb((db) => {\n render(query(db));\n });\n}\n\n// ── CLI Definition ─────────────────────────────────────────\n\nprogram\n .name('scip-query')\n .description('Language-agnostic code intelligence CLI powered by SCIP indexes')\n .version('0.1.0');\n\n// reindex\nprogram\n .command('reindex')\n .description('Index the codebase and convert to SQLite')\n .option('-l, --language <lang>', 'Index only this language (can be repeated)', collect, [])\n .option('--pnpm-workspaces', 'Enable pnpm workspace support (TypeScript)')\n .action(async (opts) => {\n const projectRoot = resolveProjectRoot();\n try {\n const result = await reindex({\n projectRoot,\n languages: opts.language.length > 0 ? opts.language : undefined,\n pnpmWorkspaces: opts.pnpmWorkspaces,\n });\n console.log(`Indexed ${result.languages.join(', ')} in ${(result.durationMs / 1000).toFixed(1)}s`);\n } catch (err) {\n console.error(`error: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n }\n });\n\n// stats\nprogram\n .command('stats')\n .description('Show index statistics')\n .action(() => {\n runQuery(\n (db) => queries.stats(db),\n (s) => {\n console.log(`Documents: ${s.documents}`);\n console.log(`Symbols: ${s.symbols}`);\n console.log(`Definitions: ${s.definitions}`);\n console.log(`References: ${s.references}`);\n console.log(`Index size: ${formatBytes(s.indexSizeBytes)}`);\n if (s.lastBuilt) {\n console.log(`Last built: ${s.lastBuilt.toISOString().replace('T', ' ').slice(0, 19)}`);\n }\n },\n );\n });\n\n// files\nprogram\n .command('files <pattern>')\n .description('Find files matching a pattern')\n .action((pattern) => {\n runQuery(\n (db) => queries.files(db, pattern),\n (results) => {\n for (const r of results) console.log(r.relativePath);\n },\n );\n });\n\n// symbols\nprogram\n .command('symbols <file>')\n .description('List symbols defined in a file (with line ranges + signatures)')\n .action((file) => {\n runQuery(\n (db) => queries.symbols(db, file),\n (results) => {\n for (const r of results) {\n const sig = r.signature ? ` — ${r.signature}` : '';\n console.log(` ${r.startLine}-${r.endLine} ${r.shortName}${sig}`);\n }\n },\n );\n });\n\n// methods\nprogram\n .command('methods <className>')\n .description('List methods of a class (with line ranges)')\n .action((className) => {\n runQuery(\n (db) => queries.methods(db, className),\n (results) => {\n for (const r of results) {\n console.log(` ${r.startLine}-${r.endLine} ${r.name}`);\n }\n },\n );\n });\n\n// refs\nprogram\n .command('refs <symbol>')\n .description('Find all files referencing a symbol')\n .action((symbol) => {\n runQuery(\n (db) => queries.refs(db, symbol),\n (results) => {\n let prevFile = '';\n for (const r of results) {\n if (r.relativePath !== prevFile) {\n if (prevFile) console.log('');\n console.log(r.relativePath);\n prevFile = r.relativePath;\n }\n console.log(` line ${r.line}`);\n }\n },\n );\n });\n\n// trace\nprogram\n .command('trace <symbol>')\n .description('Trace a symbol: definition + all references')\n .action((symbol) => {\n runQuery(\n (db) => queries.trace(db, symbol),\n (result) => {\n console.log('═══ DEFINITION ═══');\n for (const d of result.definitions) {\n const sig = d.signature ? ` — ${d.signature}` : '';\n console.log(` ${d.relativePath}:${d.startLine}-${d.endLine}${sig}`);\n }\n\n console.log('\\n═══ REFERENCED BY ═══');\n for (const ref of result.referencedBy) {\n console.log(` ${ref}`);\n }\n },\n );\n });\n\n// deps\nprogram\n .command('deps <file>')\n .description('Files this file depends on (internal)')\n .action((file) => {\n runQuery(\n (db) => queries.deps(db, file),\n (results) => {\n for (const r of results) console.log(r.relativePath);\n },\n );\n });\n\n// rdeps\nprogram\n .command('rdeps <file>')\n .description('Files that depend on this file/module')\n .action((file) => {\n runQuery(\n (db) => queries.rdeps(db, file),\n (results) => {\n for (const r of results) console.log(r.relativePath);\n },\n );\n });\n\n// system\nprogram\n .command('system <module>')\n .description('Full module map: files, symbols, deps in/out')\n .action((module) => {\n runQuery(\n (db) => queries.system(db, module),\n (result) => {\n console.log('═══ FILES ═══');\n for (const f of result.files) console.log(f);\n\n console.log('\\n═══ EXPORTED SYMBOLS ═══');\n for (const s of result.symbols) {\n console.log(` ${s.startLine}-${s.endLine} ${s.shortName}`);\n }\n\n console.log('\\n═══ DEPENDS ON (internal) ═══');\n for (const d of result.dependsOn) console.log(` ${d}`);\n\n console.log('\\n═══ DEPENDED ON BY ═══');\n for (const d of result.dependedOnBy) console.log(` ${d}`);\n },\n );\n });\n\n// surface\nprogram\n .command('surface <module>')\n .description('What symbols consumers actually use from this module')\n .action((module) => {\n runQuery(\n (db) => queries.surface(db, module),\n (results) => {\n for (const r of results) {\n console.log(` ${r.consumer} → ${r.shortName}`);\n }\n },\n );\n });\n\n// dead\nprogram\n .command('dead [scope]')\n .description('Find dead code and file-internal symbols (no cross-file consumers)')\n .option('--min-loc <n>', 'Only show symbols >= N lines', parseIntSafe, 1)\n .option('--include-tests', 'Include test files')\n .option('--skip-barrels', 'Ignore refs from barrel re-export files')\n .option('--include-members', 'Include class members')\n .action((scope, opts) => {\n withDb((db) => {\n const deadOpts: DeadOptions = {\n scope: scope || undefined,\n minLoc: opts.minLoc,\n includeTests: opts.includeTests,\n skipBarrels: opts.skipBarrels,\n includeMembers: opts.includeMembers,\n };\n\n const result = queries.dead(db, deadOpts);\n\n if (result.symbols.length === 0) {\n console.log('No dead code found.');\n return;\n }\n\n let prevFile = '';\n for (const s of result.symbols) {\n if (s.relativePath !== prevFile) {\n if (prevFile) console.log('');\n console.log(s.relativePath);\n prevFile = s.relativePath;\n }\n const tag = s.kind === 'dead-code' ? '[dead code]' : '[file-internal only]';\n console.log(` ${s.startLine}-${s.endLine} (${s.loc} LOC) ${s.shortName} ${tag}`);\n }\n\n console.log('\\n───────────────────────────');\n console.log(\n `Total: ${result.totalCount} symbols (${result.deadCodeCount} dead code, ` +\n `${result.fileInternalCount} file-internal), ${result.totalLoc} LOC`,\n );\n });\n });\n\n// hotspots\nprogram\n .command('hotspots')\n .description('Most-referenced symbols in the codebase (choke points)')\n .option('-n, --limit <n>', 'Number of results', parseIntSafe, 30)\n .option('-s, --scope <path>', 'Limit to files matching path')\n .action((opts) => {\n runQuery(\n (db) => queries.hotspots(db, { limit: opts.limit, scope: opts.scope }),\n (results) => {\n console.log(' refs files symbol');\n console.log(' ──── ───── ──────');\n for (const r of results) {\n console.log(` ${String(r.refCount).padStart(4)} ${String(r.fileCount).padStart(5)} ${r.shortName}`);\n }\n },\n );\n });\n\n// imports\nprogram\n .command('imports <file>')\n .description('What symbols does this file import?')\n .action((file) => {\n runQuery(\n (db) => queries.imports(db, file),\n (results) => {\n if (results.length === 0) {\n console.log('No imports found (indexer may not emit role=2 for this language).');\n }\n for (const r of results) {\n console.log(` ${r.shortName} ← ${r.fromFile}`);\n }\n },\n );\n });\n\n// imported-by\nprogram\n .command('imported-by <symbol>')\n .description('Which files import this symbol?')\n .action((symbol) => {\n runQuery(\n (db) => queries.importedBy(db, symbol),\n (results) => {\n for (const r of results) {\n console.log(` ${r.fromFile}`);\n }\n },\n );\n });\n\n// unused-imports\nprogram\n .command('unused-imports <file>')\n .description('Find imports not referenced in the same file')\n .action((file) => {\n runQuery(\n (db) => queries.unusedImports(db, file),\n (results) => {\n if (results.length === 0) {\n console.log('No unused imports found.');\n } else {\n for (const r of results) {\n console.log(` ${r.shortName} in ${r.importedIn}`);\n }\n console.log(`\\n${results.length} unused import(s)`);\n }\n },\n );\n });\n\n// outline\nprogram\n .command('outline <file>')\n .description('Tree view of symbols in a file (using nesting hierarchy)')\n .action((file) => {\n runQuery(\n (db) => queries.outline(db, file),\n (roots) => {\n function printTree(nodes: typeof roots, indent: number): void {\n for (const n of nodes) {\n const prefix = ' '.repeat(indent);\n console.log(`${prefix}${n.startLine}-${n.endLine} ${n.shortName}`);\n printTree(n.children, indent + 1);\n }\n }\n printTree(roots, 0);\n },\n );\n });\n\n// members\nprogram\n .command('members <symbol>')\n .description('All children of a symbol (methods, fields, nested types)')\n .action((symbol) => {\n runQuery(\n (db) => queries.members(db, symbol),\n (results) => {\n for (const r of results) {\n console.log(` ${r.startLine}-${r.endLine} [${r.kind}] ${r.shortName}`);\n }\n },\n );\n });\n\n// fan-in\nprogram\n .command('fan-in [symbol]')\n .description('How many files reference a symbol (or top fan-in across codebase)')\n .option('-n, --limit <n>', 'Number of results for top mode', parseIntSafe, 30)\n .option('-s, --scope <path>', 'Limit to files matching path')\n .action((symbol, opts) => {\n withDb((db) => {\n if (symbol) {\n const results = queries.fanIn(db, symbol);\n for (const r of results) {\n console.log(` ${String(r.count).padStart(4)} files ${r.name}`);\n }\n } else {\n const results = queries.topFanIn(db, { limit: opts.limit, scope: opts.scope });\n console.log(' files symbol');\n console.log(' ───── ──────');\n for (const r of results) {\n console.log(` ${String(r.count).padStart(5)} ${r.name}`);\n }\n }\n });\n });\n\n// fan-out\nprogram\n .command('fan-out [file]')\n .description('How many external symbols a file uses (or top fan-out across codebase)')\n .option('-n, --limit <n>', 'Number of results for top mode', parseIntSafe, 30)\n .option('-s, --scope <path>', 'Limit to files matching path')\n .action((file, opts) => {\n withDb((db) => {\n if (file) {\n const results = queries.fanOut(db, file);\n for (const r of results) {\n console.log(` ${String(r.count).padStart(4)} symbols ${r.name}`);\n }\n } else {\n const results = queries.topFanOut(db, { limit: opts.limit, scope: opts.scope });\n console.log(' symbols file');\n console.log(' ─────── ────');\n for (const r of results) {\n console.log(` ${String(r.count).padStart(7)} ${r.name}`);\n }\n }\n });\n });\n\n// coupling\nprogram\n .command('coupling [file1] [file2]')\n .description('Coupling between two files, or top coupled pairs in codebase')\n .option('-n, --limit <n>', 'Number of results for top mode', parseIntSafe, 20)\n .option('-s, --scope <path>', 'Limit to files matching path')\n .action((file1, file2, opts) => {\n withDb((db) => {\n if (file1 && file2) {\n const result = queries.coupling(db, file1, file2);\n console.log(`${result.file1} ↔ ${result.file2}: ${result.sharedSymbols} shared symbols`);\n } else {\n const results = queries.topCoupling(db, { limit: opts.limit, scope: opts.scope });\n console.log(' shared file1 → file2');\n console.log(' ────── ─────────────');\n for (const r of results) {\n console.log(` ${String(r.sharedSymbols).padStart(6)} ${r.file1} → ${r.file2}`);\n }\n }\n });\n });\n\n// cycles\nprogram\n .command('cycles')\n .description('Detect circular dependency chains between files')\n .option('-s, --scope <path>', 'Limit to files matching path')\n .option('--max-depth <n>', 'Maximum cycle depth', parseIntSafe, 10)\n .action((opts) => {\n runQuery(\n (db) => queries.cycles(db, { scope: opts.scope, maxDepth: opts.maxDepth }),\n (results) => {\n if (results.length === 0) {\n console.log('No circular dependencies found.');\n } else {\n for (let i = 0; i < results.length; i++) {\n console.log(`\\nCycle ${i + 1} (${results[i]!.path.length - 1} files):`);\n for (let j = 0; j < results[i]!.path.length; j++) {\n const arrow = j < results[i]!.path.length - 1 ? ' →' : ' (cycle)';\n console.log(` ${results[i]!.path[j]}${arrow}`);\n }\n }\n console.log(`\\n${results.length} cycle(s) found.`);\n }\n },\n );\n });\n\n// bottlenecks\nprogram\n .command('bottlenecks')\n .description('Find coupling hubs: high fan-in AND high fan-out')\n .option('-n, --limit <n>', 'Number of results', parseIntSafe, 20)\n .option('-s, --scope <path>', 'Limit to files matching path')\n .option('--min-fan-in <n>', 'Minimum fan-in', parseIntSafe, 2)\n .option('--min-fan-out <n>', 'Minimum fan-out', parseIntSafe, 2)\n .action((opts) => {\n runQuery(\n (db) => queries.bottlenecks(db, {\n limit: opts.limit,\n scope: opts.scope,\n minFanIn: opts.minFanIn,\n minFanOut: opts.minFanOut,\n }),\n (results) => {\n if (results.length === 0) {\n console.log('No bottlenecks found.');\n } else {\n console.log(' score fan-in fan-out symbol');\n console.log(' ───── ────── ─────── ──────');\n for (const r of results) {\n console.log(` ${String(r.score).padStart(5)} ${String(r.fanIn).padStart(6)} ${String(r.fanOut).padStart(7)} ${r.shortName}`);\n }\n }\n },\n );\n });\n\n// isolated\nprogram\n .command('isolated')\n .description('Find completely orphaned symbols (no references at all)')\n .option('-s, --scope <path>', 'Limit to files matching path')\n .option('--min-loc <n>', 'Minimum lines of code', parseIntSafe, 3)\n .action((opts) => {\n runQuery(\n (db) => queries.isolated(db, { scope: opts.scope, minLoc: opts.minLoc }),\n (results) => {\n if (results.length === 0) {\n console.log('No isolated symbols found.');\n } else {\n let prevFile = '';\n for (const r of results) {\n if (r.relativePath !== prevFile) {\n if (prevFile) console.log('');\n console.log(r.relativePath);\n prevFile = r.relativePath;\n }\n console.log(` ${r.startLine}-${r.endLine} (${r.loc} LOC) ${r.shortName}`);\n }\n console.log(`\\n${results.length} isolated symbol(s)`);\n }\n },\n );\n });\n\n// by-kind\nprogram\n .command('by-kind <kind>')\n .description('Find symbols by SCIP kind (class, interface, enum, function, etc.)')\n .option('-s, --scope <path>', 'Limit to files matching path')\n .option('-n, --limit <n>', 'Number of results', parseIntSafe, 100)\n .action((kind, opts) => {\n runQuery(\n (db) => queries.byKind(db, kind, { scope: opts.scope, limit: opts.limit }),\n (results) => {\n if (results.length === 0) {\n console.log(`No symbols found for kind \"${kind}\". Use \"kind-counts\" to see available kinds.`);\n } else {\n for (const r of results) {\n console.log(` ${r.relativePath}:${r.startLine}-${r.endLine} [${r.kindName}] ${r.shortName}`);\n }\n console.log(`\\n${results.length} symbol(s)`);\n }\n },\n );\n });\n\n// kind-counts\nprogram\n .command('kind-counts')\n .description('Histogram of symbol kinds in the codebase')\n .option('-s, --scope <path>', 'Limit to files matching path')\n .action((opts) => {\n runQuery(\n (db) => queries.kindCounts(db, { scope: opts.scope }),\n (results) => {\n console.log(' count kind');\n console.log(' ───── ────');\n for (const r of results) {\n console.log(` ${String(r.count).padStart(5)} ${r.kindName} (${r.kind})`);\n }\n },\n );\n });\n\n// test-coverage\nprogram\n .command('test-coverage [symbol]')\n .description('Check if symbols are referenced by test files')\n .option('-s, --scope <path>', 'Limit to files matching path')\n .option('--min-loc <n>', 'Minimum LOC for summary mode', parseIntSafe, 3)\n .action((symbol, opts) => {\n withDb((db) => {\n if (symbol) {\n const results = queries.testCoverage(db, symbol);\n for (const r of results) {\n const status = r.covered ? 'covered' : 'NOT COVERED';\n console.log(` [${status}] ${r.shortName} (${r.definedIn})`);\n for (const tf of r.testFiles) {\n console.log(` ← ${tf}`);\n }\n }\n } else {\n const summary = queries.testCoverageSummary(db, { scope: opts.scope, minLoc: opts.minLoc });\n console.log(`Test coverage: ${summary.percent}%`);\n console.log(` Total symbols: ${summary.total}`);\n console.log(` Covered: ${summary.covered}`);\n console.log(` Not covered: ${summary.uncovered}`);\n }\n });\n });\n\n// doc-coverage\nprogram\n .command('doc-coverage')\n .description('Check documentation coverage across symbols')\n .option('-s, --scope <path>', 'Limit to files matching path')\n .option('--min-loc <n>', 'Minimum LOC to consider', parseIntSafe, 3)\n .option('-n, --limit <n>', 'Max undocumented symbols to show', parseIntSafe, 50)\n .action((opts) => {\n runQuery(\n (db) => queries.docCoverage(db, {\n scope: opts.scope,\n minLoc: opts.minLoc,\n limit: opts.limit,\n }),\n (result) => {\n console.log(`Documentation coverage: ${result.coveragePercent}%`);\n console.log(` Total symbols: ${result.totalSymbols}`);\n console.log(` Documented: ${result.documented}`);\n console.log(` Undocumented: ${result.undocumented}`);\n if (result.undocumentedSymbols.length > 0) {\n console.log('\\nUndocumented:');\n for (const s of result.undocumentedSymbols) {\n console.log(` ${s.relativePath}:${s.startLine} ${s.shortName}`);\n }\n }\n },\n );\n });\n\n// deep-chains\nprogram\n .command('deep-chains')\n .description('Find the longest transitive dependency chains')\n .option('-n, --limit <n>', 'Number of chains to show', parseIntSafe, 10)\n .option('-s, --scope <path>', 'Limit to files matching path')\n .option('--min-depth <n>', 'Minimum chain depth', parseIntSafe, 3)\n .action((opts) => {\n runQuery(\n (db) => queries.deepChains(db, {\n limit: opts.limit,\n scope: opts.scope,\n minDepth: opts.minDepth,\n }),\n (results) => {\n if (results.length === 0) {\n console.log('No deep chains found.');\n } else {\n for (let i = 0; i < results.length; i++) {\n console.log(`\\nChain ${i + 1} (depth ${results[i]!.depth}):`);\n for (const file of results[i]!.chain) {\n console.log(` → ${file}`);\n }\n }\n }\n },\n );\n });\n\n// hierarchy\nprogram\n .command('hierarchy <symbol>')\n .description('Show a symbol\\'s ancestry chain (method → class → module)')\n .action((symbol) => {\n runQuery(\n (db) => queries.hierarchy(db, symbol),\n (chain) => {\n if (chain.length === 0) {\n console.log('Symbol not found.');\n } else {\n for (const node of chain) {\n const indent = ' '.repeat(node.depth);\n console.log(`${indent}${node.shortName}`);\n }\n }\n },\n );\n });\n\n// call-graph\nprogram\n .command('call-graph <symbol>')\n .description('Show incoming callers and outgoing callees for a symbol')\n .action((symbol) => {\n runQuery(\n (db) => queries.callGraph(db, symbol),\n (result) => {\n if (!result) {\n console.log('Symbol not found.');\n return;\n }\n console.log(`Symbol: ${result.shortName}\\n`);\n console.log(`═══ CALLERS (${result.callers.length}) ═══`);\n for (const c of result.callers) {\n console.log(` ${c.file} ${c.shortName}`);\n }\n console.log(`\\n═══ CALLEES (${result.callees.length}) ═══`);\n for (const c of result.callees) {\n console.log(` ${c.file} ${c.shortName}`);\n }\n },\n );\n });\n\n// similar\nprogram\n .command('similar [symbol]')\n .description('Find functions with similar callee fingerprints (consolidation candidates)')\n .option('--min-similarity <n>', 'Minimum Jaccard similarity (0-1)', parseFloat, 0.4)\n .option('-n, --limit <n>', 'Number of results', parseIntSafe, 20)\n .option('-s, --scope <path>', 'Limit to files matching path')\n .option('--min-callees <n>', 'Minimum callees to consider', parseIntSafe, 4)\n .action((symbol, opts) => {\n withDb((db) => {\n if (symbol) {\n const results = queries.similar(db, symbol, {\n minSimilarity: opts.minSimilarity,\n limit: opts.limit,\n });\n if (results.length === 0) {\n console.log('No similar symbols found.');\n } else {\n for (const r of results) {\n console.log(`\\n${Math.round(r.similarity * 100)}% similar:`);\n console.log(` A: ${r.shortNameA} (${r.fileA})`);\n console.log(` B: ${r.shortNameB} (${r.fileB})`);\n console.log(` Shared callees: ${r.sharedCallees.join(', ')}`);\n if (r.uniqueToA.length) console.log(` Only in A: ${r.uniqueToA.join(', ')}`);\n if (r.uniqueToB.length) console.log(` Only in B: ${r.uniqueToB.join(', ')}`);\n }\n }\n } else {\n const results = queries.similarAll(db, {\n minSimilarity: opts.minSimilarity,\n limit: opts.limit,\n scope: opts.scope,\n minCallees: opts.minCallees,\n });\n if (results.length === 0) {\n console.log('No similar symbol pairs found.');\n } else {\n for (const r of results) {\n console.log(`\\n${Math.round(r.similarity * 100)}% similar:`);\n console.log(` A: ${r.shortNameA} (${r.fileA})`);\n console.log(` B: ${r.shortNameB} (${r.fileB})`);\n console.log(` Shared: ${r.sharedCallees.join(', ')}`);\n }\n console.log(`\\n${results.length} similar pair(s) found.`);\n }\n }\n });\n });\n\n// similar-files\nprogram\n .command('similar-files [file]')\n .description('Find files with similar dependency profiles')\n .option('--min-similarity <n>', 'Minimum Jaccard similarity (0-1)', parseFloat, 0.5)\n .option('-n, --limit <n>', 'Number of results', parseIntSafe, 20)\n .option('-s, --scope <path>', 'Limit to files matching path')\n .option('--min-deps <n>', 'Minimum dependencies to consider', parseIntSafe, 3)\n .action((file, opts) => {\n runQuery(\n (db) => queries.similarFiles(db, {\n minSimilarity: opts.minSimilarity,\n limit: opts.limit,\n scope: opts.scope,\n minDeps: opts.minDeps,\n filePattern: file,\n }),\n (results) => {\n if (results.length === 0) {\n console.log('No similar file pairs found.');\n } else {\n for (const r of results) {\n console.log(`\\n${Math.round(r.similarity * 100)}% similar:`);\n console.log(` ${r.fileA}`);\n console.log(` ${r.fileB}`);\n console.log(` Shared deps (${r.sharedDeps.length}): ${r.sharedDeps.join(', ')}`);\n if (r.uniqueToA.length) console.log(` Only in first: ${r.uniqueToA.join(', ')}`);\n if (r.uniqueToB.length) console.log(` Only in second: ${r.uniqueToB.join(', ')}`);\n }\n console.log(`\\n${results.length} similar pair(s) found.`);\n }\n },\n );\n });\n\n// similar-chains\nprogram\n .command('similar-chains')\n .description('Find end-to-end dependency flows that diverge at few points')\n .option('--min-similarity <n>', 'Minimum chain similarity (0-1)', parseFloat, 0.5)\n .option('-n, --limit <n>', 'Number of results', parseIntSafe, 15)\n .option('-s, --scope <path>', 'Limit to files matching path')\n .option('--min-length <n>', 'Minimum chain length', parseIntSafe, 3)\n .option('--max-length <n>', 'Maximum chain length', parseIntSafe, 8)\n .action((opts) => {\n runQuery(\n (db) => queries.similarChains(db, {\n minSimilarity: opts.minSimilarity,\n limit: opts.limit,\n scope: opts.scope,\n minChainLength: opts.minLength,\n maxChainLength: opts.maxLength,\n }),\n (results) => {\n if (results.length === 0) {\n console.log('No similar chains found.');\n } else {\n for (let i = 0; i < results.length; i++) {\n const r = results[i]!;\n console.log(`\\n── Chain pair ${i + 1} (${Math.round(r.similarity * 100)}% similar, ${r.divergencePoints.length} divergence point(s)) ──`);\n console.log(` Chain A: ${r.chainA.join(' → ')}`);\n console.log(` Chain B: ${r.chainB.join(' → ')}`);\n if (r.commonPrefix.length) console.log(` Common prefix: ${r.commonPrefix.join(' → ')}`);\n if (r.commonSuffix.length) console.log(` Common suffix: ${r.commonSuffix.join(' → ')}`);\n console.log(' Divergence points (consolidation targets):');\n for (const d of r.divergencePoints) {\n console.log(` [${d.index}] ${d.nodeA} ↔ ${d.nodeB}`);\n }\n }\n console.log(`\\n${results.length} similar chain pair(s) found.`);\n }\n },\n );\n });\n\n// extract-candidates\nprogram\n .command('extract-candidates')\n .description('Find functions with natural extraction seams (isolated callee clusters)')\n .option('-s, --scope <path>', 'Limit to files matching path')\n .option('--min-loc <n>', 'Minimum function LOC', parseIntSafe, 10)\n .option('--min-callees <n>', 'Minimum callees to analyze', parseIntSafe, 6)\n .option('-n, --limit <n>', 'Number of results', parseIntSafe, 20)\n .action((opts) => {\n runQuery(\n (db) => queries.extractCandidates(db, {\n scope: opts.scope,\n minLoc: opts.minLoc,\n minCallees: opts.minCallees,\n limit: opts.limit,\n }),\n (results) => {\n if (results.length === 0) {\n console.log('No extraction candidates found.');\n } else {\n for (const r of results) {\n console.log(`\\n${r.relativePath}:${r.startLine}-${r.endLine} ${r.shortName} (${r.loc} LOC, ${r.totalCallees} callees)`);\n for (let i = 0; i < r.clusters.length; i++) {\n const c = r.clusters[i]!;\n console.log(` Cluster ${i + 1} (${Math.round(c.isolation * 100)}% isolated, ${c.callees.length} callees):`);\n for (const callee of c.callees) {\n console.log(` ${callee}`);\n }\n }\n }\n console.log(`\\n${results.length} extraction candidate(s) found.`);\n }\n },\n );\n });\n\n// affected\nprogram\n .command('affected <symbol>')\n .description('Transitive closure of symbols that could break if this symbol changes')\n .option('--max-depth <n>', 'Maximum traversal depth', parseIntSafe, 5)\n .option('-s, --scope <path>', 'Limit to files matching path')\n .action((symbol, opts) => {\n const db = openDb();\n const results = queries.affected(db, symbol, { maxDepth: opts.maxDepth, scope: opts.scope });\n if (results.length === 0) {\n console.log('No affected symbols found.');\n } else {\n let prevDepth = -1;\n for (const r of results) {\n if (r.depth !== prevDepth) {\n console.log(`\\n ── Depth ${r.depth} ──`);\n prevDepth = r.depth;\n }\n console.log(` ${r.file} ${r.shortName}`);\n }\n console.log(`\\n${results.length} affected symbol(s) across ${new Set(results.map((r) => r.file)).size} files.`);\n }\n db.close();\n });\n\n// change-surface\nprogram\n .command('change-surface <file>')\n .description('Pre-change briefing: exports, consumers, test coverage, risk')\n .action((file) => {\n const db = openDb();\n const result = queries.changeSurface(db, file);\n if (!result) {\n console.log('File not found in index.');\n db.close();\n return;\n }\n console.log(`File: ${result.file}`);\n console.log(`Test coverage: ${result.testCoveragePercent}% | External consumers: ${result.totalExternalConsumers}\\n`);\n for (const s of result.symbols) {\n const risk = s.riskLevel === 'high' ? ' *** HIGH RISK ***' : s.riskLevel === 'medium' ? ' * medium risk *' : '';\n const tests = s.testFiles.length > 0 ? ` (${s.testFiles.length} test file(s))` : ' (no tests)';\n console.log(` ${s.startLine}-${s.endLine} ${s.shortName} [${s.externalConsumers} consumers]${tests}${risk}`);\n }\n db.close();\n });\n\n// diff-impact\nprogram\n .command('diff-impact')\n .description('Compute affected symbols from current git diff')\n .option('--base <ref>', 'Git ref to diff against (default: HEAD)')\n .action((opts) => {\n const db = openDb();\n const result = queries.diffImpact(db, { base: opts.base });\n console.log(`Changed files: ${result.summary.totalChangedFiles}`);\n console.log(`Changed symbols: ${result.summary.totalChangedSymbols}`);\n console.log(`Affected consumer files: ${result.summary.totalAffectedFiles}`);\n console.log(`Test coverage: ${result.summary.testCoveragePercent}%\\n`);\n if (result.changedSymbols.length > 0) {\n console.log('Changed symbols:');\n for (const s of result.changedSymbols) {\n console.log(` ${s.file} ${s.shortName} (fan-in: ${s.fanIn})`);\n }\n }\n if (result.uncoveredSymbols.length > 0) {\n console.log('\\nUncovered (no test references):');\n for (const s of result.uncoveredSymbols) {\n console.log(` ${s.file} ${s.shortName}`);\n }\n }\n if (result.affectedConsumers.length > 0) {\n console.log('\\nAffected consumer files:');\n for (const c of result.affectedConsumers) {\n console.log(` ${c.file} (${c.consumedSymbols} symbol(s))`);\n }\n }\n db.close();\n });\n\n// drift\nprogram\n .command('drift [module]')\n .description('Detect unused imports, layer violations, and pattern deviations')\n .action((module) => {\n const db = openDb();\n const summary = queries.drift(db, { scope: module });\n if (summary.results.length === 0) {\n console.log('No drift detected.');\n } else {\n const grouped = new Map<string, typeof summary.results>();\n for (const r of summary.results) {\n if (!grouped.has(r.file)) grouped.set(r.file, []);\n grouped.get(r.file)!.push(r);\n }\n for (const [file, items] of grouped) {\n console.log(`\\n${file}`);\n for (const r of items) {\n const tag = r.kind === 'unused-import' ? 'UNUSED' : r.kind === 'layer-violation' ? 'LAYER' : 'UNIQUE';\n console.log(` [${tag}] ${r.description}`);\n if (r.detail) console.log(` ${r.detail}`);\n }\n }\n console.log(`\\n${summary.unusedImports} unused import(s), ${summary.layerViolations} layer violation(s), ${summary.patternDeviations} pattern deviation(s)`);\n }\n db.close();\n });\n\n// wrapper-candidates\nprogram\n .command('wrapper-candidates')\n .description('Find symbols only called by one consumer (premature abstractions)')\n .option('-s, --scope <path>', 'Limit to files matching path')\n .option('--max-loc <n>', 'Maximum LOC for candidates', parseIntSafe, 15)\n .option('-n, --limit <n>', 'Number of results', parseIntSafe, 30)\n .action((opts) => {\n const db = openDb();\n const results = queries.wrapperCandidates(db, { scope: opts.scope, maxLoc: opts.maxLoc, limit: opts.limit });\n if (results.length === 0) {\n console.log('No wrapper candidates found.');\n } else {\n for (const r of results) {\n console.log(` ${r.file}:${r.startLine}-${r.endLine} ${r.shortName} (${r.loc} LOC)`);\n console.log(` Only called by: ${r.singleCallerShort} (fan-in: ${r.callerFanIn})`);\n }\n console.log(`\\n${results.length} wrapper candidate(s).`);\n }\n db.close();\n });\n\n// passthrough-candidates\nprogram\n .command('passthrough-candidates')\n .description('Find functions that just forward to one other function')\n .option('-s, --scope <path>', 'Limit to files matching path')\n .option('--max-loc <n>', 'Maximum LOC for candidates', parseIntSafe, 15)\n .option('-n, --limit <n>', 'Number of results', parseIntSafe, 30)\n .action((opts) => {\n const db = openDb();\n const results = queries.passthroughCandidates(db, { scope: opts.scope, maxLoc: opts.maxLoc, limit: opts.limit });\n if (results.length === 0) {\n console.log('No passthrough candidates found.');\n } else {\n for (const r of results) {\n console.log(` ${r.file}:${r.startLine}-${r.endLine} ${r.shortName} (${r.loc} LOC)`);\n console.log(` Forwards to: ${r.forwardsToShort} (${r.forwardsToFile})`);\n }\n console.log(`\\n${results.length} passthrough candidate(s).`);\n }\n db.close();\n });\n\n// stale-abstractions\nprogram\n .command('stale-abstractions')\n .description('Find types/interfaces with 0-1 consumers (premature abstractions)')\n .option('-s, --scope <path>', 'Limit to files matching path')\n .option('--min-loc <n>', 'Minimum LOC', parseIntSafe, 3)\n .option('-n, --limit <n>', 'Number of results', parseIntSafe, 30)\n .action((opts) => {\n const db = openDb();\n const results = queries.staleAbstractions(db, { scope: opts.scope, minLoc: opts.minLoc, limit: opts.limit });\n if (results.length === 0) {\n console.log('No stale abstractions found.');\n } else {\n for (const r of results) {\n const label = r.consumers === 0 ? 'unused' : '1 consumer';\n console.log(` ${r.file}:${r.startLine}-${r.endLine} ${r.shortName} (${r.loc} LOC, ${label})`);\n }\n console.log(`\\n${results.length} stale abstraction(s).`);\n }\n db.close();\n });\n\n// complexity-hotspots\nprogram\n .command('complexity-hotspots')\n .description('Composite complexity score: LOC x fan-in x fan-out')\n .option('-s, --scope <path>', 'Limit to files matching path')\n .option('--min-loc <n>', 'Minimum LOC', parseIntSafe, 10)\n .option('-n, --limit <n>', 'Number of results', parseIntSafe, 20)\n .action((opts) => {\n const db = openDb();\n const results = queries.complexityHotspots(db, { scope: opts.scope, minLoc: opts.minLoc, limit: opts.limit });\n if (results.length === 0) {\n console.log('No complexity hotspots found.');\n } else {\n console.log(' score LOC fan-in fan-out callees symbol');\n console.log(' ───── ──── ────── ─────── ─────── ──────');\n for (const r of results) {\n console.log(` ${r.score.toFixed(1).padStart(5)} ${String(r.loc).padStart(4)} ${String(r.fanIn).padStart(6)} ${String(r.fanOut).padStart(7)} ${String(r.calleeCount).padStart(7)} ${r.shortName}`);\n }\n }\n db.close();\n });\n\n// health\nprogram\n .command('health')\n .description('Composite codebase health report with prioritized action list')\n .option('-s, --scope <path>', 'Limit to files matching path')\n .option('--json', 'Output as JSON for programmatic consumption')\n .action((opts) => {\n const db = openDb();\n const report = queries.health(db, { scope: opts.scope });\n if (opts.json) {\n console.log(JSON.stringify(report, null, 2));\n } else {\n console.log(`\\n Codebase Health Score: ${report.score}/100\\n`);\n console.log(` ${report.overview.documents} files | ${report.overview.symbols} symbols | ${formatBytes(report.overview.indexSizeBytes)}\\n`);\n\n console.log(' Findings:');\n const f = report.findings;\n if (f.deadSymbols > 0) console.log(` Dead code: ${f.deadSymbols} symbols (${f.deadLoc} LOC)`);\n if (f.isolatedSymbols > 0) console.log(` Isolated symbols: ${f.isolatedSymbols} (${f.isolatedLoc} LOC)`);\n if (f.cycles > 0) console.log(` Circular deps: ${f.cycles}`);\n if (f.similarPairs > 0) console.log(` Similar pairs: ${f.similarPairs}`);\n if (f.extractionCandidates > 0) console.log(` Extract candidates: ${f.extractionCandidates}`);\n if (f.wrappers > 0) console.log(` Wrapper functions: ${f.wrappers}`);\n if (f.passthroughs > 0) console.log(` Passthroughs: ${f.passthroughs}`);\n if (f.staleTypes > 0) console.log(` Stale abstractions: ${f.staleTypes}`);\n if (f.driftedFiles > 0) console.log(` Pattern drift: ${f.driftedFiles} files`);\n if (f.complexityHotspotCount > 0) console.log(` Complexity hotspots: ${f.complexityHotspotCount}`);\n console.log(` Test coverage: ${f.testCoveragePercent}%`);\n\n if (report.actions.length > 0) {\n console.log('\\n Prioritized Actions (highest impact + lowest effort first):');\n for (let i = 0; i < report.actions.length; i++) {\n const a = report.actions[i]!;\n const loc = a.locRecoverable > 0 ? ` (~${a.locRecoverable} LOC recoverable)` : '';\n console.log(` ${i + 1}. [${a.effort} effort / ${a.impact} impact] ${a.description}${loc}`);\n }\n }\n\n if (report.topComplexity.length > 0) {\n console.log('\\n Top Complexity Hotspots:');\n for (const c of report.topComplexity) {\n console.log(` ${c.score.toFixed(1).padStart(6)} ${c.symbol}`);\n }\n }\n\n if (report.actions.length === 0) {\n console.log('\\n No issues found. Codebase is clean.');\n }\n }\n db.close();\n });\n\n// convergence\nprogram\n .command('convergence <symbol1> <symbol2>')\n .description('Show what a consolidated version of two similar functions would look like')\n .action((symbol1, symbol2) => {\n const db = openDb();\n const result = queries.convergence(db, symbol1, symbol2);\n if (!result) {\n console.log('One or both symbols not found.');\n db.close();\n return;\n }\n console.log(`\\n${Math.round(result.similarity * 100)}% callee overlap\\n`);\n console.log(` A: ${result.symbolA.shortName} (${result.symbolA.file}, ${result.symbolA.loc} LOC)`);\n console.log(` B: ${result.symbolB.shortName} (${result.symbolB.file}, ${result.symbolB.loc} LOC)\\n`);\n console.log(` Shared callees (${result.sharedCallees.length}):`);\n for (const c of result.sharedCallees) console.log(` ${c}`);\n if (result.uniqueToA.length > 0) {\n console.log(`\\n Unique to A (${result.uniqueToA.length}):`);\n for (const c of result.uniqueToA) console.log(` ${c}`);\n }\n if (result.uniqueToB.length > 0) {\n console.log(`\\n Unique to B (${result.uniqueToB.length}):`);\n for (const c of result.uniqueToB) console.log(` ${c}`);\n }\n console.log(`\\n Strategy: ${result.consolidationStrategy}`);\n db.close();\n });\n\n// code\nprogram\n .command('code <symbol>')\n .description('Read the source code for a symbol (bounded to its definition range)')\n .option('-C, --context <n>', 'Extra lines of context above/below', parseIntSafe, 0)\n .action((symbol, opts) => {\n const db = openDb();\n const result = queries.code(db, symbol, { context: opts.context });\n if (!result) {\n console.log('Symbol not found or file unreadable.');\n db.close();\n return;\n }\n console.log(`${result.relativePath}:${result.startLine}-${result.endLine} ${result.shortName} [${result.language ?? 'unknown'}]\\n`);\n const lines = result.source.split('\\n');\n for (let i = 0; i < lines.length; i++) {\n console.log(` ${String(result.startLine + i).padStart(4)} ${lines[i]}`);\n }\n db.close();\n });\n\n// complexity\nprogram\n .command('complexity <symbol>')\n .description('Per-symbol complexity: branches, cyclomatic estimate, fan-in/out, callees')\n .action((symbol) => {\n const db = openDb();\n const result = queries.complexity(db, symbol);\n if (!result) {\n console.log('Symbol not found.');\n db.close();\n return;\n }\n console.log(`${result.relativePath}:${result.startLine}-${result.endLine} ${result.shortName}\\n`);\n console.log(` LOC: ${result.loc}`);\n console.log(` Branches: ${result.branches}`);\n console.log(` Cyclomatic estimate: ${result.cyclomaticEstimate}`);\n console.log(` Callees: ${result.calleeCount}`);\n console.log(` Fan-in: ${result.fanIn}`);\n console.log(` Fan-out: ${result.fanOut}`);\n db.close();\n });\n\n// dataflow\nprogram\n .command('dataflow <symbol>')\n .description('Reference-level dataflow: definition sites, usage sites, producers, consumers')\n .action((symbol) => {\n const db = openDb();\n const result = queries.dataflow(db, symbol);\n if (!result) {\n console.log('Symbol not found.');\n db.close();\n return;\n }\n console.log(`${result.shortName} (${result.relativePath})\\n`);\n\n if (result.definitionSites.length > 0) {\n console.log(' ═══ DEFINED AT ═══');\n for (const s of result.definitionSites) {\n console.log(` ${s.file}:${s.line}`);\n }\n }\n\n if (result.usageSites.length > 0) {\n console.log('\\n ═══ USED AT ═══');\n for (const s of result.usageSites) {\n console.log(` ${s.file}:${s.line} in ${s.enclosingShort}`);\n }\n }\n\n if (result.producers.length > 0) {\n console.log('\\n ═══ PRODUCERS (feeds into this) ═══');\n for (const p of result.producers) {\n console.log(` ${p.file} ${p.shortName}`);\n }\n }\n\n if (result.consumers.length > 0) {\n console.log('\\n ═══ CONSUMERS (this feeds into) ═══');\n for (const c of result.consumers) {\n console.log(` ${c.file} ${c.shortName}`);\n }\n }\n db.close();\n });\n\n// slice\nprogram\n .command('slice <symbol>')\n .description('Reference-level program slice: what affects this (backward) or what this affects (forward)')\n .option('--forward', 'Forward slice (what does this affect). Default is backward.')\n .action((symbol, opts) => {\n const db = openDb();\n const direction = opts.forward ? 'forward' : 'backward';\n const result = queries.slice(db, symbol, { direction });\n if (!result) {\n console.log('Symbol not found.');\n db.close();\n return;\n }\n console.log(`${result.direction} slice of ${result.shortName}\\n`);\n if (result.connectedSymbols.length === 0) {\n console.log(' No connected symbols found.');\n } else {\n for (const s of result.connectedSymbols) {\n console.log(` ${s.file} ${s.shortName}`);\n console.log(` ${s.relationship}`);\n }\n console.log(`\\n${result.connectedSymbols.length} connected symbol(s).`);\n }\n db.close();\n });\n\n// install-skills\nprogram\n .command('install-skills')\n .description('Install skills (concrete-plan, scip-explore, scip-debloat, scip-verify) into Claude Code and Codex')\n .action(() => {\n const result = installSkills();\n const total = result.installed.length + result.alreadyLinked.length;\n console.log(`\\n${result.installed.length} installed, ${result.alreadyLinked.length} already linked, ${result.skipped.length} skipped.`);\n if (total > 0) {\n console.log('Skills will be available in your next Claude Code / Codex session.');\n }\n });\n\n// check-deps\nprogram\n .command('check-deps')\n .description('Check if required dependencies (scip CLI) are installed')\n .action(() => {\n if (isScipInstalled()) {\n console.log('scip CLI: installed');\n } else {\n printScipInstallInstructions();\n }\n });\n\n// redundant-reexports\nprogram\n .command('redundant-reexports')\n .description('Find barrel re-exports that nobody imports through')\n .option('-s, --scope <path>', 'Limit to files matching path')\n .option('-n, --limit <n>', 'Number of results', parseIntSafe, 30)\n .action((opts) => {\n const db = openDb();\n const results = queries.redundantReexports(db, { scope: opts.scope, limit: opts.limit });\n if (results.length === 0) {\n console.log('No redundant re-exports found.');\n } else {\n let prevBarrel = '';\n for (const r of results) {\n if (r.barrelFile !== prevBarrel) {\n if (prevBarrel) console.log('');\n console.log(r.barrelFile);\n prevBarrel = r.barrelFile;\n }\n console.log(` ${r.shortName} (from ${r.originalFile})`);\n console.log(` barrel: ${r.barrelConsumers} consumer(s) | direct: ${r.directConsumers} consumer(s)`);\n }\n console.log(`\\n${results.length} redundant re-export(s).`);\n }\n db.close();\n });\n\n// similar-signatures\nprogram\n .command('similar-signatures')\n .description('Find functions with near-identical type signatures (same shape)')\n .option('-s, --scope <path>', 'Limit to files matching path')\n .option('--min-loc <n>', 'Minimum LOC per function', parseIntSafe, 3)\n .option('-n, --limit <n>', 'Number of groups', parseIntSafe, 20)\n .action((opts) => {\n const db = openDb();\n const groups = queries.similarSignatures(db, { scope: opts.scope, minLoc: opts.minLoc, limit: opts.limit });\n if (groups.length === 0) {\n console.log('No same-shape function groups found.');\n } else {\n for (const g of groups) {\n console.log(`\\nSignature: ${g.signature} (${g.functions.length} functions)`);\n for (const f of g.functions) {\n console.log(` ${f.file}:${f.startLine}-${f.endLine} ${f.shortName} (${f.loc} LOC)`);\n }\n }\n console.log(`\\n${groups.length} group(s) found.`);\n }\n db.close();\n });\n\n// init\nprogram\n .command('init')\n .description('Create a .scipquery.json config file for this project')\n .action(() => {\n const projectRoot = resolveProjectRoot();\n const languages = detectLanguages(projectRoot);\n const configPath = initProjectConfig(projectRoot, languages);\n console.log(`Config written to ${configPath}`);\n console.log(`Detected languages: ${languages.join(', ') || '(none)'}`);\n });\n\n// watch\nprogram\n .command('watch')\n .description('Watch for file changes and reindex automatically')\n .option('--debounce <ms>', 'Ms to wait after last change (default: 30000)', parseInt)\n .option('--cooldown <ms>', 'Min ms between reindexes (default: 60000)', parseInt)\n .action((opts) => {\n const projectRoot = resolveProjectRoot();\n const config = loadProjectConfig(projectRoot);\n\n // CLI flags override config\n if (opts.debounce) (config.watch ??= {}).debounceMs = opts.debounce;\n if (opts.cooldown) (config.watch ??= {}).cooldownMs = opts.cooldown;\n\n const watcher = new Watcher({\n projectRoot,\n config,\n onStatus: (status) => {\n process.stdout.write(`\\r\\x1b[K${formatStatus(status)}`);\n },\n onReindexComplete: (durationMs) => {\n console.log(`\\nReindex complete in ${(durationMs / 1000).toFixed(1)}s`);\n },\n onError: (err) => {\n console.error(`\\nWatch error: ${err.message}`);\n },\n });\n\n console.log(`Watching ${projectRoot}`);\n console.log(`Debounce: ${config.watch?.debounceMs ?? 30000}ms | Cooldown: ${config.watch?.cooldownMs ?? 60000}ms`);\n console.log('Press Ctrl+C to stop.\\n');\n watcher.start();\n\n process.on('SIGINT', () => {\n watcher.stop();\n console.log('\\nStopped.');\n process.exit(0);\n });\n });\n\n// status\nprogram\n .command('status')\n .description('Show index status for this project')\n .action(() => {\n const projectRoot = resolveProjectRoot();\n const config = loadProjectConfig(projectRoot);\n const paths = resolveIndexPaths(projectRoot, config);\n\n console.log(`Project: ${projectRoot}`);\n console.log(`DB path: ${paths.dbPath}`);\n console.log(`Exists: ${existsSync(paths.dbPath) ? 'yes' : 'no'}`);\n\n if (existsSync(paths.dbPath)) {\n withDb((db) => {\n const s = queries.stats(db);\n console.log(`Symbols: ${s.symbols}`);\n console.log(`Files: ${s.documents}`);\n console.log(`Size: ${formatBytes(s.indexSizeBytes)}`);\n if (s.lastBuilt) {\n const ago = Math.round((Date.now() - s.lastBuilt.getTime()) / 1000);\n console.log(`Built: ${ago}s ago`);\n }\n });\n }\n });\n\n// ── Parse & Run ────────────────────────────────────────────\n\nprogram.parse();\n\n// ── Utility ────────────────────────────────────────────────\n\nfunction collect(value: string, prev: string[]): string[] {\n return prev.concat([value]);\n}\n\n/** parseInt wrapper safe for commander (which passes default as 2nd arg = radix) */\nfunction parseIntSafe(value: string): number {\n return parseInt(value, 10);\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB`;\n if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;\n}\n\nfunction formatStatus(status: WatcherStatus): string {\n switch (status.state) {\n case 'idle':\n return 'Watching (idle)';\n case 'waiting': {\n const secs = Math.round((status.reindexAt - Date.now()) / 1000);\n return `${status.changedFiles} file(s) changed, reindexing in ${secs}s...`;\n }\n case 'indexing':\n return `Reindexing... (${Math.round((Date.now() - status.startedAt) / 1000)}s)`;\n case 'cooldown': {\n const secs = Math.round((status.until - Date.now()) / 1000);\n return `Cooldown (${secs}s)${status.dirty ? ' — changes pending' : ''}`;\n }\n }\n}\n","import Database from 'better-sqlite3';\nimport { statSync } from 'node:fs';\nimport type { PathFilter } from './gitignore-filter.js';\nimport type { ScipQueryConfig } from './types.js';\n\n/**\n * Thin wrapper around better-sqlite3 with a pre-configured connection\n * and helper methods for the SCIP SQLite schema.\n *\n * The schema is produced by `scip expt-convert` and is identical\n * regardless of source language (TypeScript, Rust, Python, etc.).\n *\n * Tables:\n * documents — indexed files (id, language, relative_path)\n * global_symbols — all symbols (id, symbol, display_name, kind, documentation)\n * defn_enclosing_ranges — definition locations (document_id, symbol_id, start/end line/char)\n * mentions — references & definitions (chunk_id, symbol_id, role)\n * chunks — code segments (document_id, chunk_index, start/end line, occurrences)\n */\nexport class ScipDatabase {\n readonly db: Database.Database;\n readonly config: ScipQueryConfig;\n private pathFilter: PathFilter | null;\n\n constructor(config: ScipQueryConfig, pathFilter?: PathFilter) {\n this.config = config;\n this.pathFilter = pathFilter ?? null;\n this.db = new Database(config.dbPath, { readonly: true });\n this.db.pragma('busy_timeout = 5000');\n }\n\n /** Attach a gitignore-based path filter for query results */\n setPathFilter(filter: PathFilter): void {\n this.pathFilter = filter;\n }\n\n /** Check if a path should be excluded based on .gitignore rules */\n isIgnored(relativePath: string): boolean {\n return this.pathFilter?.isIgnored(relativePath) ?? false;\n }\n\n /** Filter an array of paths using the gitignore filter */\n filterPaths(paths: string[]): string[] {\n return this.pathFilter?.filter(paths) ?? paths;\n }\n\n /**\n * The local-symbol predicate: only match symbols that are defined\n * in files NOT excluded by gitignore. This replaces the old hardcoded\n * `NOT LIKE 'node_modules/%'` check.\n *\n * Since SQLite can't evaluate JS gitignore rules inline, we use a\n * simpler approach: query broadly, then filter in JS. For queries\n * that need SQL-level filtering, use excludedPathPatterns().\n */\n get localSymbolPredicate(): string {\n // Basic SQL-level exclusions for the most common cases.\n // JS-level gitignore filtering handles the rest post-query.\n return `EXISTS (\n SELECT 1\n FROM defn_enclosing_ranges local_der\n JOIN documents local_d ON local_der.document_id = local_d.id\n WHERE local_der.symbol_id = gs.id\n ${this.pathExclusionsFor('local_d').trimStart()}\n )`;\n }\n\n /**\n * SQL WHERE clause fragments to exclude common build/dependency paths.\n * Complements the JS-level gitignore filtering for performance.\n */\n get pathExclusions(): string {\n return this.pathExclusionsFor('d');\n }\n\n /** Reusable SQL fragment: filter out synthetic/internal symbol noise */\n get symbolNoise(): string {\n return this.symbolNoiseFor('gs');\n }\n\n /** Build SQL path exclusions for one or more document table aliases */\n pathExclusionsFor(...aliases: string[]): string {\n return aliases\n .flatMap((alias) => [\n `AND ${alias}.relative_path NOT LIKE 'node_modules/%'`,\n `AND ${alias}.relative_path NOT LIKE '.git/%'`,\n ])\n .join('\\n ');\n }\n\n /** Build SQL symbol exclusions for the given global_symbols alias */\n symbolNoiseFor(alias: string): string {\n return `AND ${alias}.symbol NOT LIKE '%().(%' AND ${alias}.symbol NOT LIKE '%typeLiteral%'`;\n }\n\n /** Run a raw SQL query and return all rows */\n all<T = Record<string, unknown>>(sql: string, ...params: unknown[]): T[] {\n return this.db.prepare(sql).all(...params) as T[];\n }\n\n /** Run a raw SQL query and return the first row */\n get<T = Record<string, unknown>>(sql: string, ...params: unknown[]): T | undefined {\n return this.db.prepare(sql).get(...params) as T | undefined;\n }\n\n /** Get the database file size in bytes */\n sizeBytes(): number {\n try {\n return statSync(this.config.dbPath).size;\n } catch {\n return 0;\n }\n }\n\n /** Get the last modification time of the database file */\n lastModified(): Date | null {\n try {\n return statSync(this.config.dbPath).mtime;\n } catch {\n return null;\n }\n }\n\n close(): void {\n this.db.close();\n }\n}\n","import ignore, { type Ignore } from 'ignore';\nimport { readFileSync, existsSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\n\n/**\n * Builds a gitignore-based path filter from .gitignore files found\n * in the project directory tree. This replaces hardcoded path exclusions\n * like \"node_modules/\", \"dist/\", \"target/\", \"__pycache__/\" — instead,\n * we respect whatever the project already ignores.\n *\n * Falls back to sensible defaults if no .gitignore is found.\n */\nexport function createGitignoreFilter(projectRoot: string): PathFilter {\n const ig = ignore();\n let loaded = false;\n\n // Walk up from project root looking for .gitignore files\n // (nested .gitignore files apply to their subdirectory)\n const gitignorePaths = findGitignoreFiles(projectRoot);\n\n for (const gitignorePath of gitignorePaths) {\n try {\n const content = readFileSync(gitignorePath, 'utf-8');\n ig.add(content);\n loaded = true;\n } catch {\n // Skip unreadable files\n }\n }\n\n // If no .gitignore found, use universal defaults\n if (!loaded) {\n ig.add(DEFAULT_IGNORES);\n }\n\n return {\n isIgnored: (relativePath: string) => ig.ignores(relativePath),\n filter: (paths: string[]) => paths.filter((p) => !ig.ignores(p)),\n };\n}\n\nexport interface PathFilter {\n /** Returns true if this path should be excluded from results */\n isIgnored: (relativePath: string) => boolean;\n /** Filter an array of paths, keeping only non-ignored ones */\n filter: (paths: string[]) => string[];\n}\n\n/**\n * Find all .gitignore files from project root (including nested ones).\n * We look at the root .gitignore and any in immediate subdirectories\n * but don't recursively walk the entire tree (too expensive for large repos).\n */\nfunction findGitignoreFiles(projectRoot: string): string[] {\n const files: string[] = [];\n\n // Root .gitignore\n const rootGitignore = join(projectRoot, '.gitignore');\n if (existsSync(rootGitignore)) {\n files.push(rootGitignore);\n }\n\n // Also check parent directories (for monorepo setups where .gitignore\n // is at the repo root but the project is in a subdirectory)\n let dir = dirname(projectRoot);\n let depth = 0;\n while (dir !== dirname(dir) && depth < 5) {\n const parentGitignore = join(dir, '.gitignore');\n if (existsSync(parentGitignore)) {\n files.push(parentGitignore);\n }\n // Stop if we find a .git directory — that's the repo root\n if (existsSync(join(dir, '.git'))) break;\n dir = dirname(dir);\n depth++;\n }\n\n return files;\n}\n\n/**\n * Universal defaults when no .gitignore exists.\n * Covers build artifacts, dependency directories, and virtual environments\n * across all SCIP-supported languages.\n */\nconst DEFAULT_IGNORES = `\n# Dependencies\nnode_modules/\nvendor/\n.bundle/\n\n# Build output\ndist/\nbuild/\nout/\ntarget/\nbin/\nobj/\n\n# Python\n__pycache__/\n*.pyc\n*.pyo\n.venv/\nvenv/\n.env/\nenv/\n*.egg-info/\n\n# Rust\ntarget/\n\n# Java / Kotlin / Scala\n*.class\n.gradle/\n.mvn/\n\n# C# / .NET\nbin/\nobj/\npackages/\n\n# Go\nvendor/\n\n# Dart\n.dart_tool/\nbuild/\n\n# PHP\nvendor/\n\n# IDE / OS\n.idea/\n.vscode/\n*.swp\n*.swo\n.DS_Store\nThumbs.db\n\n# Type definitions (often noise in queries)\n*.d.ts\n`;\n","import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport { createHash } from 'node:crypto';\nimport { homedir } from 'node:os';\nimport type { ProjectConfig, WatchConfig } from './types.js';\n\nconst CONFIG_FILENAME = '.scipquery.json';\n\nconst DEFAULT_WATCH: Required<WatchConfig> = {\n enabled: false,\n debounceMs: 30_000,\n cooldownMs: 60_000,\n ignore: [],\n};\n\n/**\n * Load project config from .scipquery.json in the project root.\n * Returns defaults for anything not specified.\n */\nexport function loadProjectConfig(projectRoot: string): ProjectConfig {\n const configPath = join(projectRoot, CONFIG_FILENAME);\n\n if (!existsSync(configPath)) {\n return {};\n }\n\n try {\n const raw = readFileSync(configPath, 'utf-8');\n return JSON.parse(raw) as ProjectConfig;\n } catch {\n return {};\n }\n}\n\n/** Resolve watch config with defaults applied */\nexport function resolveWatchConfig(config: ProjectConfig): Required<WatchConfig> {\n return {\n ...DEFAULT_WATCH,\n ...config.watch,\n };\n}\n\n/**\n * Resolve the cache directory for a project's SCIP index.\n *\n * Default: ~/.cache/scip-query/projects/<hash>/\n * Override: project config dbPath, or SCIP_QUERY_DB_PATH env var\n *\n * The hash is derived from the absolute project path so each\n * project gets its own isolated index storage.\n */\nexport function resolveCacheDir(projectRoot: string, config?: ProjectConfig): string {\n // CLI/env override\n const envOverride = process.env['SCIP_QUERY_CACHE_DIR'];\n if (envOverride) return ensureDir(envOverride);\n\n // Project config override\n if (config?.dbPath) return ensureDir(resolve(projectRoot, config.dbPath));\n\n // Default: XDG cache dir / fallback to ~/.cache\n const xdgCache = process.env['XDG_CACHE_HOME'];\n const cacheBase = xdgCache || join(homedir(), '.cache');\n const projectHash = createHash('sha256')\n .update(resolve(projectRoot))\n .digest('hex')\n .slice(0, 12);\n\n const dir = join(cacheBase, 'scip-query', 'projects', projectHash);\n return ensureDir(dir);\n}\n\n/**\n * Resolve all paths for a project's index files.\n */\nexport function resolveIndexPaths(projectRoot: string, config?: ProjectConfig): {\n cacheDir: string;\n dbPath: string;\n indexPath: string;\n metaPath: string;\n} {\n const cacheDir = resolveCacheDir(projectRoot, config);\n return {\n cacheDir,\n dbPath: join(cacheDir, 'index.db'),\n indexPath: join(cacheDir, 'index.scip'),\n metaPath: join(cacheDir, 'meta.json'),\n };\n}\n\n/**\n * Scaffold a default .scipquery.json in the project root.\n * Does not overwrite an existing config.\n */\nexport function initProjectConfig(projectRoot: string, languages: string[]): string {\n const configPath = join(projectRoot, CONFIG_FILENAME);\n\n if (existsSync(configPath)) {\n return configPath;\n }\n\n const config: ProjectConfig = {\n languages: languages as ProjectConfig['languages'],\n watch: {\n enabled: false,\n debounceMs: 30_000,\n cooldownMs: 60_000,\n },\n };\n\n writeFileSync(configPath, JSON.stringify(config, null, 2) + '\\n');\n return configPath;\n}\n\nfunction ensureDir(dir: string): string {\n mkdirSync(dir, { recursive: true });\n return dir;\n}\n","import { execFileSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { SupportedLanguage } from '../types.js';\nimport { detectLanguages } from './detect.js';\nimport { getIndexerConfig } from './indexers.js';\nimport { isBinaryAvailable, isIndexerInstalled, tryInstallIndexer, tryInstallScipCli } from './install.js';\n\nexport interface ReindexOptions {\n projectRoot: string;\n /** Override language detection — index only these languages */\n languages?: SupportedLanguage[];\n /** Path for the SCIP protobuf output (default: <projectRoot>/index.scip) */\n outputScip?: string;\n /** Path for the SQLite output (default: <projectRoot>/index.db) */\n outputDb?: string;\n /** Max Node.js heap size in MB (default: 8192) */\n maxHeapMb?: number;\n /** Callback for status updates */\n onStatus?: (message: string) => void;\n /** Extra flags for pnpm-workspace-aware TS indexing */\n pnpmWorkspaces?: boolean;\n /** Skip auto-install prompts */\n skipAutoInstall?: boolean;\n}\n\nexport interface ReindexResult {\n languages: SupportedLanguage[];\n indexPath: string;\n dbPath: string;\n durationMs: number;\n}\n\n/**\n * Reindex a project: detect languages, run the appropriate SCIP indexer(s),\n * and convert the output to SQLite.\n */\nexport async function reindex(opts: ReindexOptions): Promise<ReindexResult> {\n const {\n projectRoot,\n maxHeapMb = 8192,\n onStatus = console.log,\n skipAutoInstall = false,\n } = opts;\n\n const outputScip = opts.outputScip ?? join(projectRoot, 'index.scip');\n const outputDb = opts.outputDb ?? join(projectRoot, 'index.db');\n const start = Date.now();\n\n // Detect or use provided languages\n const languages = opts.languages ?? detectLanguages(projectRoot);\n if (languages.length === 0) {\n throw new Error(\n 'No supported languages detected in this project. ' +\n 'Looked for: tsconfig.json, Cargo.toml, go.mod, pyproject.toml, etc.',\n );\n }\n\n onStatus(`Detected languages: ${languages.join(', ')}`);\n\n // Check that the scip CLI is available, auto-install if needed\n if (!isBinaryAvailable('scip')) {\n if (skipAutoInstall) {\n throw new Error(\n 'The scip CLI is required but not found on PATH.\\n' +\n 'Install from: https://github.com/sourcegraph/scip/releases',\n );\n }\n onStatus('scip CLI not found on PATH. Attempting auto-install...');\n if (!tryInstallScipCli(onStatus)) {\n throw new Error(\n 'The scip CLI is required but could not be installed.\\n' +\n 'Install manually from: https://github.com/sourcegraph/scip/releases',\n );\n }\n }\n\n const env = {\n ...process.env,\n NODE_OPTIONS: `--max-old-space-size=${maxHeapMb}`,\n };\n\n // Index each language\n for (const lang of languages) {\n const config = getIndexerConfig(lang);\n\n // Check if indexer is installed, auto-install if needed\n if (!isIndexerInstalled(config)) {\n if (skipAutoInstall) {\n throw new Error(\n `${config.indexerBinary} is required to index ${lang} but not found on PATH.\\n` +\n (config.installUrl ? `Install from: ${config.installUrl}` : `Make sure ${config.indexerBinary} is installed and available on PATH.`),\n );\n }\n onStatus(`${config.indexerBinary} not found. Attempting auto-install...`);\n if (!tryInstallIndexer(config, onStatus)) {\n throw new Error(\n `${config.indexerBinary} is required to index ${lang} but could not be installed.\\n` +\n (config.installUrl ? `Install manually from: ${config.installUrl}` : `Make sure ${config.indexerBinary} is installed and available on PATH.`),\n );\n }\n }\n\n onStatus(`Indexing ${lang} with ${config.indexerBinary}...`);\n\n const { binary, args } = config.indexArgs({\n projectRoot,\n outputPath: outputScip,\n pnpmWorkspaces: opts.pnpmWorkspaces,\n });\n\n try {\n execFileSync(binary, args, {\n cwd: projectRoot,\n env,\n stdio: 'pipe',\n maxBuffer: 50 * 1024 * 1024,\n });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new Error(\n `Failed to index ${lang} with ${config.indexerBinary}: ${msg}\\n` +\n `Make sure ${config.indexerBinary} is installed and available on PATH.`,\n );\n }\n }\n\n // Convert SCIP protobuf to SQLite\n onStatus('Converting to SQLite...');\n if (!existsSync(outputScip)) {\n throw new Error(`SCIP index not found at ${outputScip} after indexing`);\n }\n\n try {\n execFileSync('scip', ['expt-convert', '--output', outputDb, outputScip], {\n env,\n stdio: 'pipe',\n maxBuffer: 50 * 1024 * 1024,\n });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new Error(`Failed to convert SCIP index to SQLite: ${msg}`);\n }\n\n const durationMs = Date.now() - start;\n onStatus(`Done in ${(durationMs / 1000).toFixed(1)}s`);\n\n return { languages, indexPath: outputScip, dbPath: outputDb, durationMs };\n}\n\nexport { detectLanguages } from './detect.js';\nexport { getIndexerConfig, INDEXER_CONFIGS } from './indexers.js';\nexport { isBinaryAvailable, isIndexerInstalled, tryInstallIndexer, tryInstallScipCli } from './install.js';\n","import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { SupportedLanguage } from '../types.js';\n\ninterface LanguageMarker {\n language: SupportedLanguage;\n files: string[];\n}\n\n/**\n * Marker files that indicate a language is present in a project.\n * Ordered roughly by specificity — more specific markers first.\n */\nconst LANGUAGE_MARKERS: LanguageMarker[] = [\n { language: 'typescript', files: ['tsconfig.json', 'tsconfig.base.json'] },\n { language: 'rust', files: ['Cargo.toml'] },\n { language: 'go', files: ['go.mod'] },\n { language: 'java', files: ['pom.xml', 'build.gradle', 'build.gradle.kts'] },\n { language: 'kotlin', files: ['build.gradle.kts'] },\n { language: 'scala', files: ['build.sbt'] },\n { language: 'python', files: ['pyproject.toml', 'setup.py', 'setup.cfg', 'Pipfile'] },\n { language: 'ruby', files: ['Gemfile'] },\n { language: 'csharp', files: ['*.csproj', '*.sln'] },\n { language: 'dart', files: ['pubspec.yaml'] },\n { language: 'php', files: ['composer.json'] },\n { language: 'javascript', files: ['package.json'] }, // Last — very common, low specificity\n];\n\n/**\n * Detect which languages are present in a project directory\n * by checking for marker files.\n */\nexport function detectLanguages(projectRoot: string): SupportedLanguage[] {\n const detected: SupportedLanguage[] = [];\n\n for (const marker of LANGUAGE_MARKERS) {\n for (const file of marker.files) {\n if (file.includes('*')) {\n // Glob patterns — skip for now, basic detection only\n continue;\n }\n if (existsSync(join(projectRoot, file))) {\n if (!detected.includes(marker.language)) {\n detected.push(marker.language);\n }\n break;\n }\n }\n }\n\n // If we found TypeScript, don't also report JavaScript (it's implied)\n if (detected.includes('typescript')) {\n const jsIdx = detected.indexOf('javascript');\n if (jsIdx !== -1) detected.splice(jsIdx, 1);\n }\n\n return detected;\n}\n","import type { SupportedLanguage, IndexerConfig } from '../types.js';\n\n/**\n * Indexer configurations for each supported language.\n * Each entry describes how to produce a SCIP index for that language.\n *\n * The `scip` CLI binary is required for all languages (to convert protobuf -> SQLite).\n * Each language also needs its own SCIP indexer installed.\n */\nexport const INDEXER_CONFIGS: Record<SupportedLanguage, IndexerConfig> = {\n typescript: {\n language: 'typescript',\n indexerBinary: 'scip-typescript',\n checkCommand: 'npx scip-typescript --version',\n indexArgs: ({ outputPath, pnpmWorkspaces }) => {\n const args = ['scip-typescript', 'index', '--infer-tsconfig', '--output', outputPath, '--no-progress-bar'];\n if (pnpmWorkspaces) args.splice(2, 0, '--pnpm-workspaces');\n return { binary: 'npx', args };\n },\n markerFiles: ['tsconfig.json'],\n installMethods: [\n { label: 'npm', prerequisite: 'npm', binary: 'npm', args: ['install', '-g', '@sourcegraph/scip-typescript'] },\n ],\n installUrl: 'https://github.com/sourcegraph/scip-typescript',\n },\n\n javascript: {\n language: 'javascript',\n indexerBinary: 'scip-typescript',\n checkCommand: 'npx scip-typescript --version',\n indexArgs: ({ outputPath }) => ({\n binary: 'npx',\n args: ['scip-typescript', 'index', '--infer-tsconfig', '--output', outputPath, '--no-progress-bar'],\n }),\n markerFiles: ['package.json'],\n installMethods: [\n { label: 'npm', prerequisite: 'npm', binary: 'npm', args: ['install', '-g', '@sourcegraph/scip-typescript'] },\n ],\n installUrl: 'https://github.com/sourcegraph/scip-typescript',\n },\n\n java: {\n language: 'java',\n indexerBinary: 'scip-java',\n checkCommand: 'scip-java --version',\n indexArgs: ({ outputPath }) => ({\n binary: 'scip-java',\n args: ['index', '--output', outputPath],\n }),\n markerFiles: ['pom.xml', 'build.gradle'],\n installMethods: [\n { label: 'coursier', prerequisite: 'cs', binary: 'cs', args: ['install', 'scip-java'] },\n ],\n installUrl: 'https://github.com/sourcegraph/scip-java/releases',\n },\n\n scala: {\n language: 'scala',\n indexerBinary: 'scip-java',\n checkCommand: 'scip-java --version',\n indexArgs: ({ outputPath }) => ({\n binary: 'scip-java',\n args: ['index', '--output', outputPath],\n }),\n markerFiles: ['build.sbt'],\n installMethods: [\n { label: 'coursier', prerequisite: 'cs', binary: 'cs', args: ['install', 'scip-java'] },\n ],\n installUrl: 'https://github.com/sourcegraph/scip-java/releases',\n },\n\n kotlin: {\n language: 'kotlin',\n indexerBinary: 'scip-java',\n checkCommand: 'scip-java --version',\n indexArgs: ({ outputPath }) => ({\n binary: 'scip-java',\n args: ['index', '--output', outputPath],\n }),\n markerFiles: ['build.gradle.kts'],\n installMethods: [\n { label: 'coursier', prerequisite: 'cs', binary: 'cs', args: ['install', 'scip-java'] },\n ],\n installUrl: 'https://github.com/sourcegraph/scip-java/releases',\n },\n\n rust: {\n language: 'rust',\n indexerBinary: 'rust-analyzer',\n checkCommand: 'rust-analyzer --version',\n indexArgs: ({ outputPath }) => ({\n binary: 'rust-analyzer',\n args: ['scip', '.', '--output', outputPath],\n }),\n markerFiles: ['Cargo.toml'],\n installMethods: [\n { label: 'rustup', prerequisite: 'rustup', binary: 'rustup', args: ['component', 'add', 'rust-analyzer'] },\n ],\n installUrl: 'https://github.com/rust-lang/rust-analyzer',\n },\n\n python: {\n language: 'python',\n indexerBinary: 'scip-python',\n checkCommand: 'scip-python --version',\n indexArgs: ({ outputPath }) => ({\n binary: 'scip-python',\n args: ['index', '--output', outputPath, '--project-name', 'project'],\n }),\n markerFiles: ['pyproject.toml', 'setup.py'],\n installMethods: [\n { label: 'npm', prerequisite: 'npm', binary: 'npm', args: ['install', '-g', 'scip-python-plus'] },\n ],\n installUrl: 'https://github.com/PlunderStruck/scip-python',\n },\n\n ruby: {\n language: 'ruby',\n indexerBinary: 'scip-ruby',\n checkCommand: 'scip-ruby --version',\n indexArgs: ({ outputPath }) => ({\n binary: 'scip-ruby',\n args: ['--output', outputPath],\n }),\n markerFiles: ['Gemfile'],\n installMethods: [],\n installUrl: 'https://github.com/sourcegraph/scip-ruby/releases',\n },\n\n go: {\n language: 'go',\n indexerBinary: 'scip-go',\n checkCommand: 'scip-go --version',\n indexArgs: ({ outputPath }) => ({\n binary: 'scip-go',\n args: ['--output', outputPath],\n }),\n markerFiles: ['go.mod'],\n installMethods: [\n { label: 'go install', prerequisite: 'go', binary: 'go', args: ['install', 'github.com/sourcegraph/scip-go@latest'] },\n ],\n installUrl: 'https://github.com/sourcegraph/scip-go',\n },\n\n cpp: {\n language: 'cpp',\n indexerBinary: 'scip-clang',\n checkCommand: 'scip-clang --version',\n indexArgs: ({ outputPath }) => ({\n binary: 'scip-clang',\n args: ['--output', outputPath],\n }),\n markerFiles: ['CMakeLists.txt', 'Makefile'],\n installMethods: [],\n installUrl: 'https://github.com/sourcegraph/scip-clang/releases',\n },\n\n c: {\n language: 'c',\n indexerBinary: 'scip-clang',\n checkCommand: 'scip-clang --version',\n indexArgs: ({ outputPath }) => ({\n binary: 'scip-clang',\n args: ['--output', outputPath],\n }),\n markerFiles: ['CMakeLists.txt', 'Makefile'],\n installMethods: [],\n installUrl: 'https://github.com/sourcegraph/scip-clang/releases',\n },\n\n csharp: {\n language: 'csharp',\n indexerBinary: 'scip-dotnet',\n checkCommand: 'scip-dotnet --version',\n indexArgs: ({ outputPath }) => ({\n binary: 'scip-dotnet',\n args: ['index', '--output', outputPath],\n }),\n markerFiles: [],\n installMethods: [\n { label: 'dotnet', prerequisite: 'dotnet', binary: 'dotnet', args: ['tool', 'install', '--global', 'scip-dotnet'] },\n ],\n installUrl: 'https://github.com/sourcegraph/scip-dotnet/releases',\n },\n\n dart: {\n language: 'dart',\n indexerBinary: 'scip-dart',\n checkCommand: 'scip-dart --version',\n indexArgs: ({ outputPath }) => ({\n binary: 'scip-dart',\n args: ['index', '--output', outputPath],\n }),\n markerFiles: ['pubspec.yaml'],\n installMethods: [\n { label: 'dart pub', prerequisite: 'dart', binary: 'dart', args: ['pub', 'global', 'activate', 'scip_dart'] },\n ],\n installUrl: 'https://github.com/Workiva/scip-dart/releases',\n },\n\n php: {\n language: 'php',\n indexerBinary: 'scip-php',\n checkCommand: 'scip-php --version',\n indexArgs: ({ outputPath }) => ({\n binary: 'scip-php',\n args: ['index', '--output', outputPath],\n }),\n markerFiles: ['composer.json'],\n installMethods: [\n { label: 'composer', prerequisite: 'composer', binary: 'composer', args: ['global', 'require', 'davidrjenni/scip-php'] },\n ],\n installUrl: 'https://github.com/davidrjenni/scip-php/releases',\n },\n};\n\n/** Get the indexer config for a language */\nexport function getIndexerConfig(language: SupportedLanguage): IndexerConfig {\n return INDEXER_CONFIGS[language];\n}\n","import { execFileSync } from 'node:child_process';\nimport { platform } from 'node:os';\nimport type { IndexerConfig } from '../types.js';\n\nconst IS_WINDOWS = platform() === 'win32';\n\n/**\n * Check if a binary is available on PATH.\n */\nexport function isBinaryAvailable(name: string): boolean {\n const cmd = IS_WINDOWS ? 'where' : 'which';\n try {\n execFileSync(cmd, [name], { stdio: 'pipe' });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Check if an indexer's binary is available on PATH.\n */\nexport function isIndexerInstalled(config: IndexerConfig): boolean {\n return isBinaryAvailable(config.indexerBinary);\n}\n\n/**\n * Attempt to auto-install an indexer using its configured install methods.\n * Tries each method in order, checking prerequisites first.\n * Returns true if installation succeeded.\n */\nexport function tryInstallIndexer(\n config: IndexerConfig,\n onStatus: (msg: string) => void,\n): boolean {\n const methods = config.installMethods;\n if (!methods?.length) {\n onStatus(`No auto-install method available for ${config.indexerBinary}.`);\n if (config.installUrl) {\n onStatus(`Install manually from: ${config.installUrl}`);\n }\n return false;\n }\n\n for (const method of methods) {\n if (!isBinaryAvailable(method.prerequisite)) {\n continue;\n }\n\n onStatus(`Installing ${config.indexerBinary} via ${method.label}...`);\n try {\n execFileSync(method.binary, method.args, {\n stdio: 'inherit',\n timeout: 300_000,\n env: process.env,\n });\n\n if (isIndexerInstalled(config)) {\n onStatus(`Successfully installed ${config.indexerBinary} via ${method.label}`);\n return true;\n }\n onStatus(`${method.label} command completed but ${config.indexerBinary} not found on PATH`);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n onStatus(`${method.label} install failed: ${msg}`);\n }\n }\n\n onStatus(`Could not auto-install ${config.indexerBinary}.`);\n if (config.installUrl) {\n onStatus(`Install manually from: ${config.installUrl}`);\n }\n return false;\n}\n\n/**\n * Attempt to auto-install the `scip` CLI binary.\n * Tries brew (macOS), then go install, then prints manual instructions.\n * Returns true if installation succeeded.\n */\nexport function tryInstallScipCli(\n onStatus: (msg: string) => void,\n): boolean {\n // macOS: try Homebrew first\n if (platform() === 'darwin' && isBinaryAvailable('brew')) {\n onStatus('Installing scip CLI via Homebrew...');\n try {\n execFileSync('brew', ['install', 'sourcegraph/scip/scip'], {\n stdio: 'inherit',\n timeout: 300_000,\n env: process.env,\n });\n if (isBinaryAvailable('scip')) {\n onStatus('Successfully installed scip CLI via Homebrew');\n return true;\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n onStatus(`Homebrew install failed: ${msg}`);\n }\n }\n\n // Any platform: try go install\n if (isBinaryAvailable('go')) {\n onStatus('Installing scip CLI via go install...');\n try {\n execFileSync('go', ['install', 'github.com/sourcegraph/scip/cmd/scip@latest'], {\n stdio: 'inherit',\n timeout: 300_000,\n env: process.env,\n });\n if (isBinaryAvailable('scip')) {\n onStatus('Successfully installed scip CLI via go install');\n return true;\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n onStatus(`go install failed: ${msg}`);\n }\n }\n\n onStatus('Could not auto-install scip CLI.');\n onStatus('Install manually from: https://github.com/sourcegraph/scip/releases');\n return false;\n}\n","import { watch } from 'node:fs';\nimport { readFileSync, existsSync, renameSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport { fork } from 'node:child_process';\nimport ignore from 'ignore';\nimport type { WatcherStatus, ProjectConfig, SupportedLanguage } from './types.js';\nimport { resolveWatchConfig, resolveIndexPaths } from './config.js';\nimport { createGitignoreFilter } from './gitignore-filter.js';\n\nexport interface WatcherOptions {\n projectRoot: string;\n config: ProjectConfig;\n languages?: SupportedLanguage[];\n onStatus?: (status: WatcherStatus) => void;\n onReindexComplete?: (durationMs: number) => void;\n onError?: (error: Error) => void;\n}\n\n/**\n * File watcher that triggers single-flight background reindexing.\n *\n * Design:\n * - Debounce: waits 30s (configurable) after the last file change\n * - Single-flight: only one reindex runs at a time, never queued\n * - Dirty flag: changes during reindex schedule ONE follow-up\n * - Cooldown: minimum interval between reindex completions\n * - Atomic swap: writes to index.db.tmp, renames on success\n */\nexport class Watcher {\n private projectRoot: string;\n private watchConfig: Required<NonNullable<ProjectConfig['watch']>>;\n private indexPaths: ReturnType<typeof resolveIndexPaths>;\n private languages?: SupportedLanguage[];\n private pnpmWorkspaces: boolean;\n\n private onStatus: (status: WatcherStatus) => void;\n private onReindexComplete: (durationMs: number) => void;\n private onError: (error: Error) => void;\n\n // State machine\n private status: WatcherStatus = { state: 'idle' };\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private cooldownTimer: ReturnType<typeof setTimeout> | null = null;\n private dirty = false;\n private changedFiles = 0;\n private reindexInFlight = false;\n private lastReindexEnd = 0;\n\n // fs.watch watchers (one per watched directory)\n private fsWatchers: ReturnType<typeof watch>[] = [];\n private gitignoreFilter: ReturnType<typeof createGitignoreFilter>;\n private extraIgnore: ReturnType<typeof ignore>;\n private stopped = false;\n\n constructor(opts: WatcherOptions) {\n this.projectRoot = opts.projectRoot;\n this.watchConfig = resolveWatchConfig(opts.config);\n this.indexPaths = resolveIndexPaths(opts.projectRoot, opts.config);\n this.languages = opts.languages;\n this.pnpmWorkspaces = opts.config.indexer?.typescript?.pnpmWorkspaces ?? false;\n\n this.onStatus = opts.onStatus ?? (() => {});\n this.onReindexComplete = opts.onReindexComplete ?? (() => {});\n this.onError = opts.onError ?? ((e) => console.error(e.message));\n\n this.gitignoreFilter = createGitignoreFilter(opts.projectRoot);\n this.extraIgnore = ignore();\n if (this.watchConfig.ignore.length > 0) {\n this.extraIgnore.add(this.watchConfig.ignore);\n }\n }\n\n /** Start watching for file changes */\n start(): void {\n this.stopped = false;\n this.setStatus({ state: 'idle' });\n\n // Use recursive fs.watch on the project root\n // This is supported on macOS (FSEvents) and Windows\n // On Linux, falls back to inotify (may need per-directory watchers for large trees)\n try {\n const watcher = watch(\n this.projectRoot,\n { recursive: true },\n (_event, filename) => {\n if (filename && !this.stopped) {\n this.handleFileChange(filename);\n }\n },\n );\n this.fsWatchers.push(watcher);\n } catch {\n this.onError(new Error(\n 'Failed to start file watcher. On Linux, you may need to increase inotify limits: ' +\n 'sysctl -w fs.inotify.max_user_watches=524288',\n ));\n }\n }\n\n /** Stop watching and clean up */\n stop(): void {\n this.stopped = true;\n for (const w of this.fsWatchers) w.close();\n this.fsWatchers = [];\n if (this.debounceTimer) clearTimeout(this.debounceTimer);\n if (this.cooldownTimer) clearTimeout(this.cooldownTimer);\n this.setStatus({ state: 'idle' });\n }\n\n /** Get current watcher status */\n getStatus(): WatcherStatus {\n return this.status;\n }\n\n // ── Internal ─────────────────────────────────────────────\n\n private handleFileChange(filename: string): void {\n // Filter: skip gitignored files and extra ignore patterns\n const rel = relative(this.projectRoot, join(this.projectRoot, filename));\n if (this.gitignoreFilter.isIgnored(rel)) return;\n if (this.extraIgnore.ignores(rel)) return;\n\n // Skip the index files themselves\n if (filename.endsWith('index.db') || filename.endsWith('index.scip') ||\n filename.endsWith('index.db.tmp') || filename.endsWith('.scipquery.json')) {\n return;\n }\n\n this.changedFiles++;\n\n if (this.reindexInFlight) {\n // Reindex is running — just mark dirty, don't schedule anything\n this.dirty = true;\n this.setStatus({\n state: 'indexing',\n startedAt: (this.status as { startedAt: number }).startedAt,\n });\n return;\n }\n\n if (this.status.state === 'cooldown') {\n // In cooldown — mark dirty, the cooldown handler will pick it up\n this.dirty = true;\n this.setStatus({ state: 'cooldown', until: (this.status as { until: number }).until, dirty: true });\n return;\n }\n\n // Reset the debounce timer — every new change pushes the trigger out\n if (this.debounceTimer) clearTimeout(this.debounceTimer);\n\n const reindexAt = Date.now() + this.watchConfig.debounceMs;\n this.setStatus({ state: 'waiting', changedFiles: this.changedFiles, reindexAt });\n\n this.debounceTimer = setTimeout(() => {\n this.debounceTimer = null;\n this.triggerReindex();\n }, this.watchConfig.debounceMs);\n }\n\n private triggerReindex(): void {\n if (this.reindexInFlight || this.stopped) return;\n\n // Check cooldown\n const timeSinceLastReindex = Date.now() - this.lastReindexEnd;\n if (this.lastReindexEnd > 0 && timeSinceLastReindex < this.watchConfig.cooldownMs) {\n const remaining = this.watchConfig.cooldownMs - timeSinceLastReindex;\n this.dirty = true;\n const until = Date.now() + remaining;\n this.setStatus({ state: 'cooldown', until, dirty: true });\n\n this.cooldownTimer = setTimeout(() => {\n this.cooldownTimer = null;\n if (this.dirty && !this.stopped) {\n this.dirty = false;\n this.triggerReindex();\n }\n }, remaining);\n return;\n }\n\n this.reindexInFlight = true;\n this.dirty = false;\n this.changedFiles = 0;\n const startedAt = Date.now();\n this.setStatus({ state: 'indexing', startedAt });\n\n // Run reindex in a child process so it doesn't block the watcher\n this.runReindex()\n .then((durationMs) => {\n this.reindexInFlight = false;\n this.lastReindexEnd = Date.now();\n this.onReindexComplete(durationMs);\n\n if (this.dirty && !this.stopped) {\n // Changes arrived during reindex — enter cooldown then reindex again\n const until = Date.now() + this.watchConfig.cooldownMs;\n this.setStatus({ state: 'cooldown', until, dirty: true });\n\n this.cooldownTimer = setTimeout(() => {\n this.cooldownTimer = null;\n if (this.dirty && !this.stopped) {\n this.dirty = false;\n this.triggerReindex();\n } else {\n this.setStatus({ state: 'idle' });\n }\n }, this.watchConfig.cooldownMs);\n } else {\n this.setStatus({ state: 'idle' });\n }\n })\n .catch((err) => {\n this.reindexInFlight = false;\n this.lastReindexEnd = Date.now();\n this.onError(err instanceof Error ? err : new Error(String(err)));\n this.setStatus({ state: 'idle' });\n });\n }\n\n /**\n * Run the reindex in a forked child process.\n * Writes to index.db.tmp, then atomically renames to index.db.\n */\n private runReindex(): Promise<number> {\n return new Promise((resolve, reject) => {\n const start = Date.now();\n const tmpDb = this.indexPaths.dbPath + '.tmp';\n const tmpScip = this.indexPaths.indexPath + '.tmp';\n\n // Fork a child that runs the reindex\n const child = fork(\n new URL('./reindex-worker.js', import.meta.url).pathname,\n [],\n {\n env: {\n ...process.env,\n SCIP_REINDEX_PROJECT_ROOT: this.projectRoot,\n SCIP_REINDEX_OUTPUT_SCIP: tmpScip,\n SCIP_REINDEX_OUTPUT_DB: tmpDb,\n SCIP_REINDEX_LANGUAGES: this.languages?.join(',') ?? '',\n SCIP_REINDEX_PNPM_WORKSPACES: this.pnpmWorkspaces ? '1' : '',\n },\n stdio: 'pipe',\n },\n );\n\n child.on('exit', (code) => {\n if (code === 0) {\n // Atomic swap\n try {\n if (existsSync(tmpDb)) {\n renameSync(tmpDb, this.indexPaths.dbPath);\n }\n if (existsSync(tmpScip)) {\n renameSync(tmpScip, this.indexPaths.indexPath);\n }\n resolve(Date.now() - start);\n } catch (err) {\n reject(new Error(`Atomic swap failed: ${err}`));\n }\n } else {\n reject(new Error(`Reindex worker exited with code ${code}`));\n }\n });\n\n child.on('error', reject);\n });\n }\n\n private setStatus(status: WatcherStatus): void {\n this.status = status;\n this.onStatus(status);\n }\n}\n","import type { ScipDatabase } from '../db.js';\nimport type { StatsResult } from '../types.js';\n\nexport function stats(db: ScipDatabase): StatsResult {\n const documents = db.get<{ c: number }>('SELECT COUNT(*) as c FROM documents')!.c;\n const symbols = db.get<{ c: number }>('SELECT COUNT(*) as c FROM global_symbols')!.c;\n const definitions = db.get<{ c: number }>(\n 'SELECT COUNT(*) as c FROM mentions WHERE role = 1',\n )!.c;\n const references = db.get<{ c: number }>(\n 'SELECT COUNT(*) as c FROM mentions WHERE role = 0',\n )!.c;\n\n return {\n documents,\n symbols,\n definitions,\n references,\n indexSizeBytes: db.sizeBytes(),\n lastBuilt: db.lastModified(),\n };\n}\n","import type { ScipDatabase } from '../db.js';\nimport type { FileResult } from '../types.js';\n\nexport function files(db: ScipDatabase, pattern: string): FileResult[] {\n const rows = db.all<{ relative_path: string }>(\n `SELECT relative_path FROM documents\n WHERE relative_path LIKE ?\n ORDER BY relative_path`,\n `%${pattern}%`,\n );\n\n // Apply gitignore filtering\n return rows\n .filter((r) => !db.isIgnored(r.relative_path))\n .map((r) => ({ relativePath: r.relative_path }));\n}\n","import type { ScipSymbol, ScipDescriptor, ScipLocalSymbol, DescriptorSuffix } from './types.js';\n\n/**\n * SCIP Symbol Grammar (from the SCIP spec):\n *\n * <symbol> ::= <scheme> ' ' <package> ' ' <descriptor>+ | 'local ' <local-id>\n * <package> ::= <manager> ' ' <package-name> ' ' <version> ' '\n * <descriptor> ::= <name> <suffix>\n *\n * Suffix characters:\n * / namespace\n * # type (class, interface, enum)\n * . term (variable, field, property)\n * (). method\n * [ type parameter\n * () parameter\n * : meta\n * ! macro\n *\n * Names may be backtick-escaped: `some.weird/name`\n */\n\nconst SUFFIX_MAP: Record<string, DescriptorSuffix> = {\n '/': 'namespace',\n '#': 'type',\n '.': 'term',\n '[': 'type-param',\n ':': 'meta',\n '!': 'macro',\n};\n\n/**\n * Parse a SCIP symbol string into its structured components.\n * Works for any SCIP-indexed language (TypeScript, Java, Rust, Python, etc.)\n */\nexport function parseSymbol(raw: string): ScipSymbol | ScipLocalSymbol {\n if (raw.startsWith('local ')) {\n return { kind: 'local', id: raw.slice(6), raw };\n }\n\n // Split: <scheme> <manager> <package-name> <version> <descriptors...>\n // The tricky part: package-name can contain spaces if backtick-escaped\n const parts = raw.split(' ');\n if (parts.length < 4) {\n // Malformed — return a best-effort parse\n return {\n scheme: parts[0] ?? '',\n manager: parts[1] ?? '',\n packageName: parts[2] ?? '',\n version: '',\n descriptors: [],\n raw,\n };\n }\n\n const scheme = parts[0]!;\n const manager = parts[1]!;\n\n // Package name and version: package name might be backtick-escaped\n // After scheme + manager, we need to find package + version + descriptor string\n let restAfterManager = raw.slice(scheme.length + 1 + manager.length + 1);\n\n // Parse package name (may be backtick-escaped)\n let packageName: string;\n if (restAfterManager.startsWith('`')) {\n const closingTick = restAfterManager.indexOf('`', 1);\n if (closingTick === -1) {\n packageName = restAfterManager.slice(1);\n restAfterManager = '';\n } else {\n packageName = restAfterManager.slice(1, closingTick);\n restAfterManager = restAfterManager.slice(closingTick + 2); // skip ` and space\n }\n } else {\n const spaceIdx = restAfterManager.indexOf(' ');\n if (spaceIdx === -1) {\n packageName = restAfterManager;\n restAfterManager = '';\n } else {\n packageName = restAfterManager.slice(0, spaceIdx);\n restAfterManager = restAfterManager.slice(spaceIdx + 1);\n }\n }\n\n // Parse version\n let version: string;\n const versionSpaceIdx = restAfterManager.indexOf(' ');\n if (versionSpaceIdx === -1) {\n version = restAfterManager;\n restAfterManager = '';\n } else {\n version = restAfterManager.slice(0, versionSpaceIdx);\n restAfterManager = restAfterManager.slice(versionSpaceIdx + 1);\n }\n\n // Parse descriptors from the remaining string\n const descriptors = parseDescriptors(restAfterManager);\n\n return { scheme, manager, packageName, version, descriptors, raw };\n}\n\n/**\n * Parse the descriptor chain from a SCIP symbol.\n *\n * SCIP descriptor grammar:\n * namespace: name/\n * type: name#\n * term: name.\n * method: name(disambiguator).\n * type-param: [name] (bracket-wrapped, prefix syntax)\n * parameter: (name) (paren-wrapped, prefix syntax)\n * meta: name:\n * macro: name!\n *\n * Names can be backtick-escaped: `some/name.with.dots`\n */\nfunction parseDescriptors(input: string): ScipDescriptor[] {\n const descriptors: ScipDescriptor[] = [];\n let i = 0;\n\n while (i < input.length) {\n // Type parameter: [name]\n if (input[i] === '[') {\n const closeBracket = input.indexOf(']', i + 1);\n if (closeBracket === -1) {\n descriptors.push({ name: input.slice(i + 1), suffix: 'type-param' });\n break;\n }\n descriptors.push({ name: input.slice(i + 1, closeBracket), suffix: 'type-param' });\n i = closeBracket + 1;\n continue;\n }\n\n // Parameter: (name) — only when ( appears at descriptor start with no preceding name\n if (input[i] === '(' && (descriptors.length === 0 || i === 0 || isSuffixChar(input[i - 1]!))) {\n const closeParen = input.indexOf(')', i + 1);\n if (closeParen !== -1 && input[closeParen + 1] !== '.') {\n // This is a parameter (name), not a method disambiguator\n descriptors.push({ name: input.slice(i + 1, closeParen), suffix: 'parameter' });\n i = closeParen + 1;\n continue;\n }\n }\n\n let name: string;\n\n // Backtick-escaped name\n if (input[i] === '`') {\n const closingTick = input.indexOf('`', i + 1);\n if (closingTick === -1) {\n name = input.slice(i + 1);\n i = input.length;\n descriptors.push({ name, suffix: 'term' });\n break;\n }\n name = input.slice(i + 1, closingTick);\n i = closingTick + 1;\n } else {\n // Read name until we hit a suffix character\n const start = i;\n while (i < input.length && !isSuffixChar(input[i]!)) {\n i++;\n }\n name = input.slice(start, i);\n }\n\n // Parse suffix after name\n if (i >= input.length) {\n if (name) descriptors.push({ name, suffix: 'term' });\n break;\n }\n\n const char = input[i]!;\n\n // Method: name(disambiguator).\n if (char === '(') {\n const closeParen = input.indexOf(')', i + 1);\n if (closeParen !== -1 && input[closeParen + 1] === '.') {\n descriptors.push({ name, suffix: 'method' });\n i = closeParen + 2; // skip past ).\n } else if (closeParen !== -1) {\n // Bare (disambiguator) without . — treat as method anyway (common in practice)\n descriptors.push({ name, suffix: 'method' });\n i = closeParen + 1;\n } else {\n descriptors.push({ name, suffix: 'term' });\n i++;\n }\n } else {\n const suffix = SUFFIX_MAP[char];\n if (suffix) {\n descriptors.push({ name, suffix });\n i += 1;\n } else {\n i += 1; // Unknown suffix — skip\n }\n }\n }\n\n return descriptors;\n}\n\nfunction isSuffixChar(c: string): boolean {\n return c === '/' || c === '#' || c === '.' || c === '(' || c === '[' || c === ':' || c === '!';\n}\n\n/**\n * Convert a parsed SCIP symbol to a short, human-readable name.\n * Language-agnostic: works for any SCIP-indexed language.\n *\n * Examples:\n * \"scip-typescript npm @vega/api 0.1.3 src/modules/auth/auth.service.ts/AuthService#login().\"\n * → \"auth.service:AuthService:login()\"\n *\n * \"scip-java maven com.example/mylib 1.0.0 com/example/MyClass#doStuff().\"\n * → \"MyClass:doStuff()\"\n *\n * \"rust-analyzer cargo my-crate 0.1.0 src/lib.rs/MyStruct#new().\"\n * → \"lib:MyStruct:new()\"\n */\nexport function shortenSymbol(raw: string): string {\n const parsed = parseSymbol(raw);\n if ('kind' in parsed && parsed.kind === 'local') {\n return `local:${parsed.id}`;\n }\n\n const sym = parsed as ScipSymbol;\n if (sym.descriptors.length === 0) return sym.raw;\n\n const parts: string[] = [];\n for (const desc of sym.descriptors) {\n // Strip file extensions from namespace descriptors (the file path parts)\n let name = desc.name;\n if (desc.suffix === 'namespace') {\n // Remove common file extensions\n name = name\n .replace(/\\.(ts|tsx|js|jsx|mjs|cjs)$/, '')\n .replace(/\\.(py|pyi)$/, '')\n .replace(/\\.(rs)$/, '')\n .replace(/\\.(java|scala|kt|kts)$/, '')\n .replace(/\\.(rb)$/, '')\n .replace(/\\.(go)$/, '')\n .replace(/\\.(cs|vb)$/, '')\n .replace(/\\.(dart)$/, '')\n .replace(/\\.(php)$/, '')\n .replace(/\\.(c|cc|cpp|cxx|h|hpp)$/, '');\n }\n\n // Skip empty names (can happen with trailing suffixes)\n if (!name) continue;\n\n // For methods, append () for clarity\n if (desc.suffix === 'method') {\n parts.push(`${name}()`);\n } else {\n parts.push(name);\n }\n }\n\n return parts.join(':');\n}\n\n/**\n * Extract just the leaf name from a SCIP symbol.\n * Useful when you only need the function/class/variable name without path context.\n */\nexport function leafName(raw: string): string {\n const parsed = parseSymbol(raw);\n if ('kind' in parsed && parsed.kind === 'local') {\n return parsed.id;\n }\n\n const sym = parsed as ScipSymbol;\n if (sym.descriptors.length === 0) return '';\n\n const last = sym.descriptors[sym.descriptors.length - 1]!;\n return last.name;\n}\n","/**\n * Clean up the raw doc/signature string from the SCIP index.\n *\n * Shared across symbols, trace, and system queries.\n * Previously duplicated as cleanSig/cleanSignature in three files.\n */\nexport function cleanSignature(sig: string | null): string | null {\n if (!sig || !sig.trim()) return null;\n return sig\n .replace(/^```\\w*\\s*/, '')\n .replace(/\\s*```$/, '')\n .replace(/^\\(method\\)\\s*/, '')\n .replace(/^\\(property\\)\\s*/, '')\n .replace(/^\\(function\\)\\s*/, '')\n .replace(/^\\(class\\)\\s*/, '')\n .replace(/^\\(interface\\)\\s*/, '')\n .replace(/^\\(enum\\)\\s*/, '')\n .replace(/^\\(type alias\\)\\s*/, '')\n .replace(/^\\(const\\)\\s*/, '')\n .replace(/^\\(var\\)\\s*/, '')\n .trim() || null;\n}\n","import type { ScipDatabase } from '../db.js';\nimport type { SymbolResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\nimport { cleanSignature } from './clean-signature.js';\n\nexport function symbols(db: ScipDatabase, filePattern: string): SymbolResult[] {\n const rows = db.all<{\n start_line: number;\n end_line: number;\n sig: string | null;\n symbol: string;\n relative_path: string;\n }>(\n `SELECT\n der.start_line,\n der.end_line,\n REPLACE(SUBSTR(gs.documentation, INSTR(gs.documentation, '|') + 1), char(10), ' ') AS sig,\n gs.symbol,\n d.relative_path\n FROM defn_enclosing_ranges der\n JOIN global_symbols gs ON der.symbol_id = gs.id\n JOIN documents d ON der.document_id = d.id\n WHERE d.relative_path LIKE ?\n AND ${db.localSymbolPredicate}\n ${db.symbolNoise}\n ORDER BY der.start_line`,\n `%${filePattern}%`,\n );\n\n return rows\n .filter((r) => !db.isIgnored(r.relative_path))\n .map((r) => ({\n startLine: r.start_line,\n endLine: r.end_line,\n symbol: r.symbol,\n shortName: shortenSymbol(r.symbol),\n signature: cleanSignature(r.sig),\n }));\n}\n","import type { ScipDatabase } from '../db.js';\nimport type { MethodResult } from '../types.js';\nimport { leafName } from '../symbol-parser.js';\n\nexport function methods(db: ScipDatabase, className: string): MethodResult[] {\n const rows = db.all<{\n start_line: number;\n end_line: number;\n symbol: string;\n }>(\n `SELECT der.start_line, der.end_line, gs.symbol\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n WHERE gs.symbol LIKE ?\n AND ${db.localSymbolPredicate}\n AND gs.symbol LIKE '%().%'\n ${db.symbolNoise}\n ORDER BY der.start_line`,\n `%${className}#%`,\n );\n\n return rows.map((r) => ({\n startLine: r.start_line,\n endLine: r.end_line,\n name: leafName(r.symbol),\n }));\n}\n","import type { ScipDatabase } from '../db.js';\nimport type { RefResult } from '../types.js';\n\nexport function refs(db: ScipDatabase, symbolPattern: string): RefResult[] {\n const rows = db.all<{\n relative_path: string;\n start_line: number;\n }>(\n `SELECT DISTINCT d.relative_path, c.start_line\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d ON c.document_id = d.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n WHERE gs.symbol LIKE ?\n AND ${db.localSymbolPredicate}\n AND m.role = 0\n ORDER BY d.relative_path, c.start_line`,\n `%${symbolPattern}%`,\n );\n\n return rows\n .filter((r) => !db.isIgnored(r.relative_path))\n .map((r) => ({\n relativePath: r.relative_path,\n line: r.start_line,\n }));\n}\n","import type { ScipDatabase } from '../db.js';\nimport type { TraceResult } from '../types.js';\nimport { cleanSignature } from './clean-signature.js';\n\nexport function trace(db: ScipDatabase, symbolPattern: string): TraceResult {\n // Definitions\n const defRows = db.all<{\n relative_path: string;\n start_line: number;\n end_line: number;\n sig: string | null;\n }>(\n `SELECT d.relative_path, der.start_line, der.end_line,\n REPLACE(SUBSTR(gs.documentation, INSTR(gs.documentation, '|') + 1), char(10), ' ') AS sig\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE gs.symbol LIKE ?\n AND ${db.localSymbolPredicate}\n ${db.symbolNoise}\n ORDER BY d.relative_path, der.start_line\n LIMIT 10`,\n `%${symbolPattern}%`,\n );\n\n const definitions = defRows\n .filter((r) => !db.isIgnored(r.relative_path))\n .map((r) => ({\n relativePath: r.relative_path,\n startLine: r.start_line,\n endLine: r.end_line,\n signature: cleanSignature(r.sig),\n }));\n\n // References\n const refRows = db.all<{ relative_path: string }>(\n `SELECT DISTINCT d.relative_path\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d ON c.document_id = d.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n WHERE gs.symbol LIKE ?\n AND ${db.localSymbolPredicate}\n ${db.symbolNoise}\n AND m.role = 0\n ORDER BY d.relative_path`,\n `%${symbolPattern}%`,\n );\n\n const referencedBy = refRows\n .map((r) => r.relative_path)\n .filter((p) => !db.isIgnored(p));\n\n return { definitions, referencedBy };\n}\n","import type { ScipDatabase } from '../db.js';\nimport type { DepResult } from '../types.js';\n\n/** What internal files does this file depend on? (forward dependencies) */\nexport function deps(db: ScipDatabase, filePattern: string): DepResult[] {\n const rows = db.all<{ relative_path: string }>(\n `SELECT DISTINCT d2.relative_path\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d1 ON c.document_id = d1.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d2 ON der.document_id = d2.id\n WHERE d1.relative_path LIKE ?\n AND d2.relative_path <> d1.relative_path\n AND ${db.localSymbolPredicate}\n ORDER BY d2.relative_path`,\n `%${filePattern}%`,\n );\n\n return rows\n .filter((r) => !db.isIgnored(r.relative_path))\n .map((r) => ({ relativePath: r.relative_path }));\n}\n\n/** What files depend on this file/module? (reverse dependencies) */\nexport function rdeps(db: ScipDatabase, filePattern: string): DepResult[] {\n const rows = db.all<{ relative_path: string }>(\n `SELECT DISTINCT d1.relative_path\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d1 ON c.document_id = d1.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d2 ON der.document_id = d2.id\n WHERE d2.relative_path LIKE ?\n AND d1.relative_path NOT LIKE ?\n ORDER BY d1.relative_path`,\n `%${filePattern}%`,\n `%${filePattern}%`,\n );\n\n return rows\n .filter((r) => !db.isIgnored(r.relative_path))\n .map((r) => ({ relativePath: r.relative_path }));\n}\n","import type { ScipDatabase } from '../db.js';\nimport type { SystemResult, SymbolResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\nimport { cleanSignature } from './clean-signature.js';\n\n/** Full system map for a module path: files, symbols, deps in/out */\nexport function system(db: ScipDatabase, modulePattern: string): SystemResult {\n // Files in this module\n const fileRows = db.all<{ relative_path: string }>(\n `SELECT relative_path FROM documents\n WHERE relative_path LIKE ?\n ORDER BY relative_path`,\n `%${modulePattern}%`,\n );\n const files = fileRows\n .map((r) => r.relative_path)\n .filter((p) => !db.isIgnored(p));\n\n // Exported symbols\n const symbolRows = db.all<{\n start_line: number;\n end_line: number;\n symbol: string;\n sig: string | null;\n }>(\n `SELECT der.start_line, der.end_line, gs.symbol,\n REPLACE(SUBSTR(gs.documentation, INSTR(gs.documentation, '|') + 1), char(10), ' ') AS sig\n FROM defn_enclosing_ranges der\n JOIN global_symbols gs ON der.symbol_id = gs.id\n JOIN documents d ON der.document_id = d.id\n WHERE d.relative_path LIKE ?\n AND ${db.localSymbolPredicate}\n ${db.symbolNoise}\n AND gs.documentation IS NOT NULL\n ORDER BY d.relative_path, der.start_line`,\n `%${modulePattern}%`,\n );\n const symbols: SymbolResult[] = symbolRows.map((r) => ({\n startLine: r.start_line,\n endLine: r.end_line,\n symbol: r.symbol,\n shortName: shortenSymbol(r.symbol),\n signature: cleanSignature(r.sig),\n }));\n\n // Internal dependencies (what this module depends on)\n const depRows = db.all<{ relative_path: string }>(\n `SELECT DISTINCT d2.relative_path\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d1 ON c.document_id = d1.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d2 ON der.document_id = d2.id\n WHERE d1.relative_path LIKE ?\n AND d2.relative_path NOT LIKE ?\n AND ${db.localSymbolPredicate}\n ORDER BY d2.relative_path`,\n `%${modulePattern}%`,\n `%${modulePattern}%`,\n );\n const dependsOn = depRows\n .map((r) => r.relative_path)\n .filter((p) => !db.isIgnored(p));\n\n // Reverse dependencies (who depends on this module)\n const rdepRows = db.all<{ relative_path: string }>(\n `SELECT DISTINCT d1.relative_path\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d1 ON c.document_id = d1.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d2 ON der.document_id = d2.id\n WHERE d2.relative_path LIKE ?\n AND d1.relative_path NOT LIKE ?\n ORDER BY d1.relative_path`,\n `%${modulePattern}%`,\n `%${modulePattern}%`,\n );\n const dependedOnBy = rdepRows\n .map((r) => r.relative_path)\n .filter((p) => !db.isIgnored(p));\n\n return { files, symbols, dependsOn, dependedOnBy };\n}\n","import type { ScipDatabase } from '../db.js';\nimport type { SurfaceResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/** Public API surface: what symbols do external consumers actually use from this module? */\nexport function surface(db: ScipDatabase, modulePattern: string): SurfaceResult[] {\n const rows = db.all<{\n relative_path: string;\n symbol: string;\n }>(\n `SELECT DISTINCT d1.relative_path, gs.symbol\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d1 ON c.document_id = d1.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d2 ON der.document_id = d2.id\n WHERE d2.relative_path LIKE ?\n AND d1.relative_path NOT LIKE ?\n AND ${db.localSymbolPredicate}\n AND m.role = 0\n ORDER BY d1.relative_path`,\n `%${modulePattern}%`,\n `%${modulePattern}%`,\n );\n\n return rows\n .filter((r) => !db.isIgnored(r.relative_path))\n .map((r) => ({\n consumer: r.relative_path,\n symbol: r.symbol,\n shortName: shortenSymbol(r.symbol),\n }));\n}\n","import type { ScipDatabase } from './db.js';\n\nexport interface SymbolLocation {\n documentId: number;\n startLine: number;\n endLine: number;\n symbolId: number;\n}\n\nexport interface SymbolMatch extends SymbolLocation {\n symbol: string;\n relativePath: string;\n}\n\nexport interface CalleeRow {\n symbol: string;\n file: string;\n chunkId: number;\n}\n\nexport const TEST_FILE_PATTERNS = [\n '%/__tests__/%',\n '%.test.%',\n '%.spec.%',\n '%/test/%',\n '%/tests/%',\n '%_test.%',\n '%_spec.%',\n '%/test_%.%',\n '%/spec_%.%',\n] as const;\n\nexport const TEST_SUPPORT_PATH_PATTERNS = [\n '%/test-utils/%',\n] as const;\n\nexport function testFileMatchSql(\n alias: string,\n patterns: readonly string[] = TEST_FILE_PATTERNS,\n): string {\n return `(${patterns.map((pattern) => `${alias}.relative_path LIKE '${pattern}'`).join(' OR ')})`;\n}\n\nexport function testFileExclusionSql(\n alias: string,\n extraPatterns: readonly string[] = [],\n): string {\n const patterns = uniquePatterns([...TEST_FILE_PATTERNS, ...extraPatterns]);\n return patterns\n .map((pattern) => `${alias}.relative_path NOT LIKE '${pattern}'`)\n .join('\\n AND ');\n}\n\nexport function buildFileDepGraph(\n db: ScipDatabase,\n scope?: string,\n): Map<string, Set<string>> {\n const scopeFilter = scope ? `AND d1.relative_path LIKE '%${scope}%'` : '';\n\n const edges = db.all<{ from_file: string; to_file: string }>(\n `SELECT DISTINCT\n d1.relative_path AS from_file,\n d2.relative_path AS to_file\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d1 ON c.document_id = d1.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d2 ON der.document_id = d2.id\n WHERE d1.id != d2.id\n AND m.role = 0\n ${db.pathExclusionsFor('d1', 'd2')}\n ${scopeFilter}`,\n );\n\n const graph = new Map<string, Set<string>>();\n for (const edge of edges) {\n if (db.isIgnored(edge.from_file) || db.isIgnored(edge.to_file)) continue;\n if (!graph.has(edge.from_file)) graph.set(edge.from_file, new Set());\n graph.get(edge.from_file)!.add(edge.to_file);\n }\n\n return graph;\n}\n\nexport function findFirstSymbolMatch(\n db: ScipDatabase,\n symbolPattern: string,\n): SymbolMatch | null {\n // Handle file:line-line syntax (e.g., \"src/foo.ts:10-50\")\n const fileLineMatch = symbolPattern.match(/^(.+):(\\d+)-(\\d+)$/);\n if (fileLineMatch) {\n const [, filePath, startStr, endStr] = fileLineMatch;\n const row = db.get<{\n id: number;\n symbol: string;\n document_id: number;\n start_line: number;\n end_line: number;\n relative_path: string;\n }>(\n `SELECT gs.id, gs.symbol, der.document_id, der.start_line, der.end_line, d.relative_path\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE d.relative_path LIKE ?\n AND der.start_line <= ? AND der.end_line >= ?\n ${db.pathExclusionsFor('d')}\n ORDER BY (der.end_line - der.start_line) ASC\n LIMIT 1`,\n `%${filePath}%`, parseInt(startStr!, 10), parseInt(endStr!, 10),\n );\n if (row && !db.isIgnored(row.relative_path)) {\n return {\n symbolId: row.id,\n symbol: row.symbol,\n documentId: row.document_id,\n startLine: row.start_line,\n endLine: row.end_line,\n relativePath: row.relative_path,\n };\n }\n }\n\n // Strip parentheses from the pattern to avoid shell escaping issues.\n // Agents often pass \"functionName()\" — strip the () for matching.\n const cleaned = symbolPattern.replace(/\\(\\)$/, '').replace(/\\(.*$/, '');\n\n // Try exact-ish match first (with noise filter), then fallback without noise filter.\n // The noise filter excludes %().(% which can incorrectly match some symbols.\n for (const useNoiseFilter of [true, false]) {\n const noiseClause = useNoiseFilter ? db.symbolNoiseFor('gs') : '';\n const row = db.get<{\n id: number;\n symbol: string;\n document_id: number;\n start_line: number;\n end_line: number;\n relative_path: string;\n }>(\n `SELECT gs.id, gs.symbol, der.document_id, der.start_line, der.end_line, d.relative_path\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE gs.symbol LIKE ?\n ${db.pathExclusionsFor('d')}\n ${noiseClause}\n ORDER BY (der.end_line - der.start_line) DESC\n LIMIT 1`,\n `%${cleaned}%`,\n );\n\n if (row && !db.isIgnored(row.relative_path)) {\n return {\n symbolId: row.id,\n symbol: row.symbol,\n documentId: row.document_id,\n startLine: row.start_line,\n endLine: row.end_line,\n relativePath: row.relative_path,\n };\n }\n }\n\n return null;\n}\n\nexport function getCalleeRowsForSymbol(\n db: ScipDatabase,\n symbol: SymbolLocation,\n opts: { limit?: number } = {},\n): CalleeRow[] {\n const rows = db.all<{\n symbol: string;\n file: string;\n chunk_id: number;\n }>(\n `SELECT DISTINCT\n callee_gs.symbol AS symbol,\n callee_d.relative_path AS file,\n c.id AS chunk_id\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN global_symbols callee_gs ON m.symbol_id = callee_gs.id\n JOIN defn_enclosing_ranges callee_der ON callee_gs.id = callee_der.symbol_id\n JOIN documents callee_d ON callee_der.document_id = callee_d.id\n WHERE c.document_id = ?\n AND c.start_line >= ?\n AND c.end_line <= ?\n AND m.role = 0\n AND callee_gs.id != ?\n ${db.symbolNoiseFor('callee_gs')}\n ${db.pathExclusionsFor('callee_d')}\n ORDER BY callee_d.relative_path\n ${opts.limit ? 'LIMIT ?' : ''}`,\n ...calleeQueryParams(symbol, opts.limit),\n );\n\n return rows.filter((row) => !db.isIgnored(row.file)).map((row) => ({\n symbol: row.symbol,\n file: row.file,\n chunkId: row.chunk_id,\n }));\n}\n\nfunction calleeQueryParams(\n symbol: SymbolLocation,\n limit?: number,\n): number[] {\n const params = [\n symbol.documentId,\n symbol.startLine,\n symbol.endLine,\n symbol.symbolId,\n ];\n\n if (typeof limit === 'number') {\n params.push(limit);\n }\n\n return params;\n}\n\nfunction uniquePatterns(patterns: readonly string[]): string[] {\n return [...new Set(patterns)];\n}\n","import type { ScipDatabase } from '../db.js';\nimport { TEST_SUPPORT_PATH_PATTERNS, testFileExclusionSql } from '../query-support.js';\nimport type { DeadOptions, DeadSymbolResult, DeadSummary } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Find dead exports: symbols defined locally with no cross-file references.\n * Language-agnostic — works with any SCIP index.\n */\nexport function dead(db: ScipDatabase, opts: DeadOptions = {}): DeadSummary {\n const {\n scope,\n minLoc = 1,\n includeTests = false,\n skipBarrels = false,\n includeMembers = false,\n } = opts;\n\n const params: unknown[] = [minLoc];\n let testFileExclusions = '';\n let memberExclusion = '';\n\n if (scope) {\n params.push(`%${scope}%`);\n }\n\n if (!includeTests) {\n testFileExclusions = `\n AND ${testFileExclusionSql('d', TEST_SUPPORT_PATH_PATTERNS)}\n `;\n }\n\n if (!includeMembers) {\n memberExclusion = `AND gs.symbol NOT LIKE '%#%'`;\n }\n\n // Barrel file exclusion for the NOT EXISTS subquery\n const barrelExclusions = skipBarrels\n ? `AND ref_d.relative_path NOT LIKE '%/index.ts'\n AND ref_d.relative_path NOT LIKE '%/index.js'\n AND ref_d.relative_path NOT LIKE '%/mod.rs'\n AND ref_d.relative_path NOT LIKE '%/__init__.py'`\n : '';\n\n const sql = `\n SELECT\n d.relative_path,\n der.start_line,\n der.end_line,\n (der.end_line - der.start_line + 1) AS loc,\n gs.symbol,\n (SELECT COUNT(*) FROM mentions m2\n JOIN chunks c2 ON m2.chunk_id = c2.id\n WHERE m2.symbol_id = gs.id AND m2.role = 0 AND c2.document_id = d.id\n ) AS same_file_refs\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE 1 = 1\n ${db.pathExclusionsFor('d')}\n ${db.symbolNoiseFor('gs')}\n AND (der.end_line - der.start_line + 1) >= ?\n ${scope ? 'AND d.relative_path LIKE ?' : ''}\n ${testFileExclusions}\n ${memberExclusion}\n AND NOT EXISTS (\n SELECT 1\n FROM mentions ref_m\n JOIN chunks ref_c ON ref_m.chunk_id = ref_c.id\n JOIN documents ref_d ON ref_c.document_id = ref_d.id\n WHERE ref_m.symbol_id = gs.id\n AND ref_m.role = 0\n AND ref_d.id != d.id\n ${barrelExclusions}\n )\n ORDER BY (der.end_line - der.start_line + 1) DESC, d.relative_path, der.start_line\n `;\n\n const rows = db.all<{\n relative_path: string;\n start_line: number;\n end_line: number;\n loc: number;\n symbol: string;\n same_file_refs: number;\n }>(sql, ...params);\n\n let deadCodeCount = 0;\n let fileInternalCount = 0;\n let totalLoc = 0;\n\n const symbols: DeadSymbolResult[] = rows\n .filter((r) => !db.isIgnored(r.relative_path))\n .map((r) => {\n // dead-code: zero references anywhere (not even in same file) — safe to delete\n // file-internal: referenced within same file but never cross-file —\n // may be a private helper (fine) or a forgotten export (needs review)\n const kind = r.same_file_refs === 0 ? 'dead-code' : 'file-internal';\n if (kind === 'dead-code') deadCodeCount++;\n else fileInternalCount++;\n totalLoc += r.loc;\n\n return {\n relativePath: r.relative_path,\n startLine: r.start_line,\n endLine: r.end_line,\n loc: r.loc,\n symbol: r.symbol,\n shortName: shortenSymbol(r.symbol),\n sameFileRefs: r.same_file_refs,\n kind,\n };\n });\n\n return {\n symbols,\n totalCount: symbols.length,\n deadCodeCount,\n fileInternalCount,\n totalLoc,\n };\n}\n","import type { ScipDatabase } from '../db.js';\nimport type { HotspotResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Find the most-referenced symbols in the codebase — the choke points\n * where changes have the widest blast radius.\n */\nexport function hotspots(\n db: ScipDatabase,\n opts: { limit?: number; scope?: string } = {},\n): HotspotResult[] {\n const { limit = 30, scope } = opts;\n\n const scopeFilter = scope ? `AND def_d.relative_path LIKE '%${scope}%'` : '';\n\n const rows = db.all<{\n symbol: string;\n ref_count: number;\n file_count: number;\n defined_in: string;\n }>(\n `SELECT\n gs.symbol,\n COUNT(*) AS ref_count,\n COUNT(DISTINCT ref_d.id) AS file_count,\n def_d.relative_path AS defined_in\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents ref_d ON c.document_id = ref_d.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents def_d ON der.document_id = def_d.id\n WHERE m.role = 0\n ${db.pathExclusionsFor('def_d')}\n ${db.symbolNoiseFor('gs')}\n ${scopeFilter}\n GROUP BY gs.id\n ORDER BY ref_count DESC\n LIMIT ?`,\n limit,\n );\n\n return rows\n .filter((r) => !db.isIgnored(r.defined_in))\n .map((r) => ({\n symbol: r.symbol,\n shortName: shortenSymbol(r.symbol),\n refCount: r.ref_count,\n fileCount: r.file_count,\n definedIn: r.defined_in,\n }));\n}\n","import type { ScipDatabase } from '../db.js';\nimport type { ImportResult, UnusedImportResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * What symbols does this file import?\n * Uses role=2 (import) from the SCIP mentions table.\n */\nexport function imports(db: ScipDatabase, filePattern: string): ImportResult[] {\n const rows = db.all<{\n symbol: string;\n from_file: string;\n }>(\n `SELECT DISTINCT gs.symbol, def_d.relative_path AS from_file\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents imp_d ON c.document_id = imp_d.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n LEFT JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n LEFT JOIN documents def_d ON der.document_id = def_d.id\n WHERE imp_d.relative_path LIKE ?\n AND m.role = 2\n ORDER BY def_d.relative_path, gs.symbol`,\n `%${filePattern}%`,\n );\n\n return rows.map((r) => ({\n symbol: r.symbol,\n shortName: shortenSymbol(r.symbol),\n fromFile: r.from_file ?? '(external)',\n }));\n}\n\n/**\n * Which files import this symbol?\n */\nexport function importedBy(db: ScipDatabase, symbolPattern: string): ImportResult[] {\n const rows = db.all<{\n symbol: string;\n importer: string;\n }>(\n `SELECT DISTINCT gs.symbol, d.relative_path AS importer\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d ON c.document_id = d.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n WHERE gs.symbol LIKE ?\n AND m.role = 2\n ORDER BY d.relative_path`,\n `%${symbolPattern}%`,\n );\n\n return rows\n .filter((r) => !db.isIgnored(r.importer))\n .map((r) => ({\n symbol: r.symbol,\n shortName: shortenSymbol(r.symbol),\n fromFile: r.importer,\n }));\n}\n\n/**\n * Find imports in a file that are never referenced (role=0) in the same file.\n * These are likely unused imports.\n */\nexport function unusedImports(db: ScipDatabase, filePattern: string): UnusedImportResult[] {\n const rows = db.all<{\n symbol: string;\n imported_in: string;\n }>(\n `SELECT gs.symbol, d.relative_path AS imported_in\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d ON c.document_id = d.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n WHERE d.relative_path LIKE ?\n AND m.role = 2\n AND NOT EXISTS (\n SELECT 1\n FROM mentions ref_m\n JOIN chunks ref_c ON ref_m.chunk_id = ref_c.id\n WHERE ref_m.symbol_id = gs.id\n AND ref_m.role = 0\n AND ref_c.document_id = d.id\n )\n ORDER BY d.relative_path, gs.symbol`,\n `%${filePattern}%`,\n );\n\n return rows.map((r) => ({\n symbol: r.symbol,\n shortName: shortenSymbol(r.symbol),\n importedIn: r.imported_in,\n }));\n}\n","import type { ScipDatabase } from '../db.js';\nimport type { OutlineNode } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Build a tree-structured outline of symbols in a file,\n * using the enclosing_symbol field to establish parent-child relationships.\n */\nexport function outline(db: ScipDatabase, filePattern: string): OutlineNode[] {\n const rows = db.all<{\n symbol: string;\n enclosing_symbol: string | null;\n start_line: number;\n end_line: number;\n }>(\n `SELECT gs.symbol, gs.enclosing_symbol, der.start_line, der.end_line\n FROM defn_enclosing_ranges der\n JOIN global_symbols gs ON der.symbol_id = gs.id\n JOIN documents d ON der.document_id = d.id\n WHERE d.relative_path LIKE ?\n ${db.symbolNoise}\n ORDER BY der.start_line`,\n `%${filePattern}%`,\n );\n\n // Build a map of symbol -> node\n const nodeMap = new Map<string, OutlineNode>();\n const roots: OutlineNode[] = [];\n\n for (const r of rows) {\n const node: OutlineNode = {\n symbol: r.symbol,\n shortName: shortenSymbol(r.symbol),\n startLine: r.start_line,\n endLine: r.end_line,\n children: [],\n };\n nodeMap.set(r.symbol, node);\n }\n\n // Wire up parent-child via enclosing_symbol\n for (const r of rows) {\n const node = nodeMap.get(r.symbol)!;\n if (r.enclosing_symbol && nodeMap.has(r.enclosing_symbol)) {\n nodeMap.get(r.enclosing_symbol)!.children.push(node);\n } else {\n roots.push(node);\n }\n }\n\n return roots;\n}\n","import type { ScipDatabase } from '../db.js';\nimport type { MemberResult } from '../types.js';\nimport { shortenSymbol, parseSymbol } from '../symbol-parser.js';\nimport type { ScipSymbol } from '../types.js';\n\n/**\n * Find all direct children of a symbol (methods, fields, nested types).\n * Uses the enclosing_symbol relationship in global_symbols.\n */\nexport function members(db: ScipDatabase, symbolPattern: string): MemberResult[] {\n // First find the parent symbol(s)\n const parents = db.all<{ symbol: string }>(\n `SELECT symbol FROM global_symbols WHERE symbol LIKE ?`,\n `%${symbolPattern}%`,\n );\n\n if (parents.length === 0) return [];\n\n // Find children whose enclosing_symbol matches any parent\n const placeholders = parents.map(() => '?').join(',');\n const parentSymbols = parents.map((p) => p.symbol);\n\n const rows = db.all<{\n symbol: string;\n start_line: number;\n end_line: number;\n }>(\n `SELECT gs.symbol, der.start_line, der.end_line\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n WHERE gs.enclosing_symbol IN (${placeholders})\n ${db.symbolNoise}\n ORDER BY der.start_line`,\n ...parentSymbols,\n );\n\n return rows.map((r) => {\n const parsed = parseSymbol(r.symbol);\n let kind = 'unknown';\n if (!('kind' in parsed)) {\n const sym = parsed as ScipSymbol;\n const last = sym.descriptors[sym.descriptors.length - 1];\n if (last) kind = last.suffix;\n }\n\n return {\n symbol: r.symbol,\n shortName: shortenSymbol(r.symbol),\n startLine: r.start_line,\n endLine: r.end_line,\n kind,\n };\n });\n}\n","import type { ScipDatabase } from '../db.js';\nimport type { FanResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Fan-in: how many distinct files reference this symbol.\n * High fan-in = widely depended upon = high blast radius for changes.\n */\nexport function fanIn(\n db: ScipDatabase,\n symbolPattern: string,\n): FanResult[] {\n const rows = db.all<{\n symbol: string;\n file_count: number;\n }>(\n `SELECT gs.symbol, COUNT(DISTINCT c.document_id) AS file_count\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n WHERE gs.symbol LIKE ?\n AND m.role = 0\n GROUP BY gs.id\n ORDER BY file_count DESC`,\n `%${symbolPattern}%`,\n );\n\n return rows.map((r) => ({\n name: shortenSymbol(r.symbol),\n count: r.file_count,\n }));\n}\n\n/**\n * Fan-out: how many external symbols does this file reference.\n * High fan-out = depends on many things = fragile to upstream changes.\n */\nexport function fanOut(\n db: ScipDatabase,\n filePattern: string,\n): FanResult[] {\n const rows = db.all<{\n relative_path: string;\n symbol_count: number;\n }>(\n `SELECT d.relative_path, COUNT(DISTINCT gs.id) AS symbol_count\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d ON c.document_id = d.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents def_d ON der.document_id = def_d.id\n WHERE d.relative_path LIKE ?\n AND m.role = 0\n AND def_d.id != d.id\n GROUP BY d.id\n ORDER BY symbol_count DESC`,\n `%${filePattern}%`,\n );\n\n return rows\n .filter((r) => !db.isIgnored(r.relative_path))\n .map((r) => ({\n name: r.relative_path,\n count: r.symbol_count,\n }));\n}\n\n/**\n * Top fan-in across the whole codebase — the most depended-on symbols.\n */\nexport function topFanIn(\n db: ScipDatabase,\n opts: { limit?: number; scope?: string } = {},\n): FanResult[] {\n const { limit = 30, scope } = opts;\n const scopeFilter = scope\n ? `AND def_d.relative_path LIKE '%${scope}%'`\n : '';\n\n const rows = db.all<{\n symbol: string;\n file_count: number;\n }>(\n `SELECT gs.symbol, COUNT(DISTINCT c.document_id) AS file_count\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents def_d ON der.document_id = def_d.id\n WHERE m.role = 0\n ${db.pathExclusionsFor('def_d')}\n ${db.symbolNoiseFor('gs')}\n ${scopeFilter}\n GROUP BY gs.id\n HAVING file_count > 1\n ORDER BY file_count DESC\n LIMIT ?`,\n limit,\n );\n\n return rows.map((r) => ({\n name: shortenSymbol(r.symbol),\n count: r.file_count,\n }));\n}\n\n/**\n * Top fan-out across the whole codebase — files that depend on the most external symbols.\n */\nexport function topFanOut(\n db: ScipDatabase,\n opts: { limit?: number; scope?: string } = {},\n): FanResult[] {\n const { limit = 30, scope } = opts;\n const scopeFilter = scope\n ? `AND d.relative_path LIKE '%${scope}%'`\n : '';\n\n const rows = db.all<{\n relative_path: string;\n symbol_count: number;\n }>(\n `SELECT d.relative_path, COUNT(DISTINCT gs.id) AS symbol_count\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d ON c.document_id = d.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents def_d ON der.document_id = def_d.id\n WHERE m.role = 0\n AND def_d.id != d.id\n ${db.pathExclusionsFor('d')}\n ${db.symbolNoiseFor('gs')}\n ${scopeFilter}\n GROUP BY d.id\n ORDER BY symbol_count DESC\n LIMIT ?`,\n limit,\n );\n\n return rows\n .filter((r) => !db.isIgnored(r.relative_path))\n .map((r) => ({\n name: r.relative_path,\n count: r.symbol_count,\n }));\n}\n","import type { ScipDatabase } from '../db.js';\nimport type { CouplingResult } from '../types.js';\n\n/**\n * Measure coupling between two files: how many symbols do they share\n * (symbols defined in one and referenced in the other, or vice versa).\n */\nexport function coupling(\n db: ScipDatabase,\n file1: string,\n file2: string,\n): CouplingResult {\n const row = db.get<{ shared: number }>(\n `SELECT COUNT(DISTINCT gs.id) AS shared\n FROM global_symbols gs\n WHERE (\n -- Defined in file1, referenced in file2\n EXISTS (\n SELECT 1 FROM defn_enclosing_ranges der\n JOIN documents d ON der.document_id = d.id\n WHERE der.symbol_id = gs.id AND d.relative_path LIKE ?\n )\n AND EXISTS (\n SELECT 1 FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d ON c.document_id = d.id\n WHERE m.symbol_id = gs.id AND m.role = 0 AND d.relative_path LIKE ?\n )\n ) OR (\n -- Defined in file2, referenced in file1\n EXISTS (\n SELECT 1 FROM defn_enclosing_ranges der\n JOIN documents d ON der.document_id = d.id\n WHERE der.symbol_id = gs.id AND d.relative_path LIKE ?\n )\n AND EXISTS (\n SELECT 1 FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d ON c.document_id = d.id\n WHERE m.symbol_id = gs.id AND m.role = 0 AND d.relative_path LIKE ?\n )\n )`,\n `%${file1}%`, `%${file2}%`,\n `%${file2}%`, `%${file1}%`,\n );\n\n return {\n file1,\n file2,\n sharedSymbols: row?.shared ?? 0,\n };\n}\n\n/**\n * Find the most coupled file pairs in the codebase.\n */\nexport function topCoupling(\n db: ScipDatabase,\n opts: { limit?: number; scope?: string } = {},\n): CouplingResult[] {\n const { limit = 20, scope } = opts;\n const scopeFilter = scope\n ? `AND d1.relative_path LIKE '%${scope}%' AND d2.relative_path LIKE '%${scope}%'`\n : '';\n\n // Find file pairs that share the most symbols (one defines, other references)\n const rows = db.all<{\n file1: string;\n file2: string;\n shared: number;\n }>(\n `SELECT\n def_d.relative_path AS file1,\n ref_d.relative_path AS file2,\n COUNT(DISTINCT gs.id) AS shared\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents ref_d ON c.document_id = ref_d.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents def_d ON der.document_id = def_d.id\n WHERE m.role = 0\n AND def_d.id != ref_d.id\n ${db.pathExclusionsFor('def_d', 'ref_d')}\n ${scopeFilter}\n GROUP BY def_d.id, ref_d.id\n ORDER BY shared DESC\n LIMIT ?`,\n limit,\n );\n\n return rows\n .filter((r) => !db.isIgnored(r.file1) && !db.isIgnored(r.file2))\n .map((r) => ({\n file1: r.file1,\n file2: r.file2,\n sharedSymbols: r.shared,\n }));\n}\n","import type { ScipDatabase } from '../db.js';\nimport { buildFileDepGraph } from '../query-support.js';\nimport type { CycleResult } from '../types.js';\n\n/**\n * Detect circular dependency chains between files.\n * A cycle exists when file A depends on B, B depends on C, and C depends on A.\n *\n * Uses the same dependency edges as the `deps` command (symbol definitions\n * referenced across files), then runs DFS cycle detection.\n */\nexport function cycles(\n db: ScipDatabase,\n opts: { scope?: string; maxDepth?: number } = {},\n): CycleResult[] {\n const { scope, maxDepth = 10 } = opts;\n const graph = buildFileDepGraph(db, scope);\n\n // DFS cycle detection\n const allCycles: CycleResult[] = [];\n const visited = new Set<string>();\n const inStack = new Set<string>();\n const stack: string[] = [];\n\n function dfs(node: string, depth: number): void {\n if (depth > maxDepth) return;\n if (inStack.has(node)) {\n // Found a cycle — extract it from the stack\n const cycleStart = stack.indexOf(node);\n if (cycleStart !== -1) {\n const cyclePath = stack.slice(cycleStart).concat(node);\n // Normalize: start from the lexicographically smallest file\n const minIdx = cyclePath.indexOf(\n cyclePath.reduce((a, b) => (a < b ? a : b)),\n );\n const normalized = [\n ...cyclePath.slice(minIdx, -1),\n ...cyclePath.slice(0, minIdx),\n cyclePath[minIdx]!,\n ];\n // Deduplicate\n const key = normalized.join(' -> ');\n if (!seenCycles.has(key)) {\n seenCycles.add(key);\n allCycles.push({ path: normalized });\n }\n }\n return;\n }\n if (visited.has(node)) return;\n\n visited.add(node);\n inStack.add(node);\n stack.push(node);\n\n const neighbors = graph.get(node);\n if (neighbors) {\n for (const neighbor of neighbors) {\n dfs(neighbor, depth + 1);\n }\n }\n\n stack.pop();\n inStack.delete(node);\n }\n\n const seenCycles = new Set<string>();\n for (const node of graph.keys()) {\n if (!visited.has(node)) {\n dfs(node, 0);\n }\n }\n\n // Sort by cycle length (shorter cycles are more actionable)\n allCycles.sort((a, b) => a.path.length - b.path.length);\n\n return allCycles;\n}\n","import type { ScipDatabase } from '../db.js';\nimport type { BottleneckResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Find coupling hubs: symbols with both high fan-in (many consumers)\n * AND high fan-out (references many other symbols).\n *\n * These are the most dangerous symbols to change — they sit at the\n * intersection of many dependency paths. Score = fanIn * fanOut.\n */\nexport function bottlenecks(\n db: ScipDatabase,\n opts: { limit?: number; scope?: string; minFanIn?: number; minFanOut?: number } = {},\n): BottleneckResult[] {\n const { limit = 20, scope, minFanIn = 2, minFanOut = 2 } = opts;\n const scopeFilter = scope ? `AND def_d.relative_path LIKE '%${scope}%'` : '';\n\n // Use a wrapping query to filter on computed columns\n const rows = db.all<{\n symbol: string;\n defined_in: string;\n fan_in: number;\n fan_out: number;\n }>(\n `SELECT * FROM (\n SELECT\n gs.symbol,\n def_d.relative_path AS defined_in,\n (SELECT COUNT(DISTINCT ref_c.document_id)\n FROM mentions ref_m\n JOIN chunks ref_c ON ref_m.chunk_id = ref_c.id\n WHERE ref_m.symbol_id = gs.id AND ref_m.role = 0\n ) AS fan_in,\n (SELECT COUNT(DISTINCT ref_gs.id)\n FROM mentions ref_m\n JOIN chunks ref_c ON ref_m.chunk_id = ref_c.id\n JOIN global_symbols ref_gs ON ref_m.symbol_id = ref_gs.id\n JOIN defn_enclosing_ranges ref_der ON ref_gs.id = ref_der.symbol_id\n WHERE ref_c.document_id = def_d.id\n AND ref_m.role = 0\n AND ref_der.document_id != def_d.id\n ) AS fan_out\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents def_d ON der.document_id = def_d.id\n WHERE 1 = 1\n ${db.pathExclusionsFor('def_d')}\n ${db.symbolNoiseFor('gs')}\n ${scopeFilter}\n ) WHERE fan_in >= ? AND fan_out >= ?\n ORDER BY (fan_in * fan_out) DESC\n LIMIT ?`,\n minFanIn, minFanOut, limit,\n );\n\n return rows\n .filter((r) => !db.isIgnored(r.defined_in))\n .map((r) => ({\n symbol: r.symbol,\n shortName: shortenSymbol(r.symbol),\n fanIn: r.fan_in,\n fanOut: r.fan_out,\n score: r.fan_in * r.fan_out,\n definedIn: r.defined_in,\n }));\n}\n","import type { ScipDatabase } from '../db.js';\nimport { testFileExclusionSql } from '../query-support.js';\nimport type { IsolatedResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Find isolated symbols: defined locally, referenced by nothing,\n * and referencing nothing external. These are truly orphaned code —\n * not just unused exports, but completely disconnected from the graph.\n */\nexport function isolated(\n db: ScipDatabase,\n opts: { scope?: string; minLoc?: number } = {},\n): IsolatedResult[] {\n const { scope, minLoc = 3 } = opts;\n const scopeFilter = scope ? `AND d.relative_path LIKE '%${scope}%'` : '';\n\n const rows = db.all<{\n symbol: string;\n relative_path: string;\n start_line: number;\n end_line: number;\n loc: number;\n }>(\n `SELECT\n gs.symbol,\n d.relative_path,\n der.start_line,\n der.end_line,\n (der.end_line - der.start_line + 1) AS loc\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE 1 = 1\n ${db.pathExclusionsFor('d')}\n AND ${testFileExclusionSql('d')}\n ${db.symbolNoiseFor('gs')}\n AND gs.symbol NOT LIKE '%#%'\n AND (der.end_line - der.start_line + 1) >= ?\n ${scopeFilter}\n -- No cross-file references TO this symbol\n AND NOT EXISTS (\n SELECT 1 FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n WHERE m.symbol_id = gs.id AND m.role = 0 AND c.document_id != d.id\n )\n -- No same-file references either\n AND NOT EXISTS (\n SELECT 1 FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n WHERE m.symbol_id = gs.id AND m.role = 0 AND c.document_id = d.id\n )\n ORDER BY loc DESC, d.relative_path`,\n minLoc,\n );\n\n return rows\n .filter((r) => !db.isIgnored(r.relative_path))\n .map((r) => ({\n symbol: r.symbol,\n shortName: shortenSymbol(r.symbol),\n relativePath: r.relative_path,\n startLine: r.start_line,\n endLine: r.end_line,\n loc: r.loc,\n }));\n}\n","import type { ScipDatabase } from '../db.js';\nimport type { ByKindResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * SCIP SymbolInformation.Kind enum values.\n * From: https://github.com/sourcegraph/scip/blob/main/scip.proto\n */\nconst KIND_NAMES: Record<number, string> = {\n 0: 'UnspecifiedKind',\n 1: 'AbstractMethod',\n 2: 'Accessor',\n 3: 'Array',\n 4: 'Assertion',\n 5: 'AssociatedType',\n 6: 'Attribute',\n 7: 'Axiom',\n 8: 'Boolean',\n 9: 'Class',\n 10: 'Constant',\n 11: 'Constructor',\n 12: 'Contract',\n 13: 'DataFamily',\n 14: 'DefinitionMacro',\n 15: 'Delegate',\n 16: 'Enum',\n 17: 'EnumMember',\n 18: 'Error',\n 19: 'Event',\n 20: 'Fact',\n 21: 'Field',\n 22: 'File',\n 23: 'Function',\n 24: 'Getter',\n 25: 'Grammar',\n 26: 'Instance',\n 27: 'Interface',\n 28: 'Key',\n 29: 'Lang',\n 30: 'Lemma',\n 31: 'Library',\n 32: 'Macro',\n 33: 'Method',\n 34: 'MethodAlias',\n 35: 'MethodReceiver',\n 36: 'MethodSpecification',\n 37: 'Message',\n 38: 'Modifier',\n 39: 'Module',\n 40: 'Namespace',\n 41: 'Null',\n 42: 'Number',\n 43: 'Object',\n 44: 'Operator',\n 45: 'Package',\n 46: 'PackageObject',\n 47: 'Parameter',\n 48: 'ParameterLabel',\n 49: 'Pattern',\n 50: 'Predicate',\n 51: 'Property',\n 52: 'Protocol',\n 53: 'ProtocolMethod',\n 54: 'PureVirtualMethod',\n 55: 'Quasiquoter',\n 56: 'SelfParameter',\n 57: 'Setter',\n 58: 'Signature',\n 59: 'SingletonClass',\n 60: 'SingletonMethod',\n 61: 'StaticDataMember',\n 62: 'StaticEvent',\n 63: 'StaticField',\n 64: 'StaticMethod',\n 65: 'StaticProperty',\n 66: 'StaticVariable',\n 67: 'String',\n 68: 'Struct',\n 69: 'Subscript',\n 70: 'Tactic',\n 71: 'Theorem',\n 72: 'ThisParameter',\n 73: 'Trait',\n 74: 'TraitMethod',\n 75: 'Type',\n 76: 'TypeAlias',\n 77: 'TypeClass',\n 78: 'TypeClassMethod',\n 79: 'TypeFamily',\n 80: 'TypeParameter',\n 81: 'Union',\n 82: 'Value',\n 83: 'Variable',\n};\n\n/** Reverse lookup: name -> kind number */\nconst KIND_BY_NAME = new Map<string, number>();\nfor (const [k, v] of Object.entries(KIND_NAMES)) {\n KIND_BY_NAME.set(v.toLowerCase(), Number(k));\n}\n\n/**\n * Find symbols by SCIP kind (class, interface, enum, function, etc.)\n */\nexport function byKind(\n db: ScipDatabase,\n kindQuery: string,\n opts: { scope?: string; limit?: number } = {},\n): ByKindResult[] {\n const { scope, limit = 100 } = opts;\n\n // Resolve kind: accept number or name\n let kindNum: number | null = null;\n const asNum = parseInt(kindQuery, 10);\n if (!isNaN(asNum)) {\n kindNum = asNum;\n } else {\n kindNum = KIND_BY_NAME.get(kindQuery.toLowerCase()) ?? null;\n // Fuzzy match: try partial name\n if (kindNum === null) {\n for (const [name, num] of KIND_BY_NAME) {\n if (name.includes(kindQuery.toLowerCase())) {\n kindNum = num;\n break;\n }\n }\n }\n }\n\n if (kindNum === null) {\n return [];\n }\n\n const scopeFilter = scope ? `AND d.relative_path LIKE '%${scope}%'` : '';\n\n // Check if the index actually has kind data populated\n const hasKinds = db.get<{ c: number }>(\n `SELECT COUNT(*) AS c FROM global_symbols WHERE kind IS NOT NULL`,\n );\n if (!hasKinds || hasKinds.c === 0) {\n return []; // Indexer doesn't populate kind field\n }\n\n const rows = db.all<{\n symbol: string;\n kind: number;\n relative_path: string;\n start_line: number;\n end_line: number;\n }>(\n `SELECT gs.symbol, gs.kind, d.relative_path, der.start_line, der.end_line\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE gs.kind = ?\n ${db.pathExclusionsFor('d')}\n ${scopeFilter}\n ORDER BY d.relative_path, der.start_line\n LIMIT ?`,\n kindNum, limit,\n );\n\n return rows\n .filter((r) => !db.isIgnored(r.relative_path))\n .map((r) => ({\n symbol: r.symbol,\n shortName: shortenSymbol(r.symbol),\n kind: r.kind,\n kindName: KIND_NAMES[r.kind] ?? 'Unknown',\n relativePath: r.relative_path,\n startLine: r.start_line,\n endLine: r.end_line,\n }));\n}\n\n/** List all symbol kinds present in the index with counts */\nexport function kindCounts(\n db: ScipDatabase,\n opts: { scope?: string } = {},\n): Array<{ kind: number; kindName: string; count: number }> {\n const scopeFilter = opts.scope\n ? `AND d.relative_path LIKE '%${opts.scope}%'`\n : '';\n\n const rows = db.all<{ kind: number; cnt: number }>(\n `SELECT gs.kind, COUNT(*) AS cnt\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE 1 = 1\n ${db.pathExclusionsFor('d')}\n AND gs.kind IS NOT NULL\n AND gs.kind != 0\n ${scopeFilter}\n GROUP BY gs.kind\n ORDER BY cnt DESC`,\n );\n\n return rows.map((r) => ({\n kind: r.kind,\n kindName: KIND_NAMES[r.kind] ?? 'Unknown',\n count: r.cnt,\n }));\n}\n","import type { ScipDatabase } from '../db.js';\nimport { TEST_FILE_PATTERNS, testFileExclusionSql, testFileMatchSql } from '../query-support.js';\nimport type { TestCoverageResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Check if a symbol is referenced by any test file.\n * Reports which test files cover (reference) each matching symbol.\n */\nexport function testCoverage(\n db: ScipDatabase,\n symbolPattern: string,\n): TestCoverageResult[] {\n // Find matching symbols\n const syms = db.all<{\n id: number;\n symbol: string;\n relative_path: string;\n }>(\n `SELECT gs.id, gs.symbol, d.relative_path\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE gs.symbol LIKE ?\n ${db.pathExclusionsFor('d')}\n ${db.symbolNoiseFor('gs')}\n ORDER BY d.relative_path`,\n `%${symbolPattern}%`,\n );\n\n const testPatternSql = testFileMatchSql('ref_d', TEST_FILE_PATTERNS);\n\n return syms\n .filter((s) => !db.isIgnored(s.relative_path))\n .map((s) => {\n // Find test files that reference this symbol\n const testFiles = db.all<{ relative_path: string }>(\n `SELECT DISTINCT ref_d.relative_path\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents ref_d ON c.document_id = ref_d.id\n WHERE m.symbol_id = ?\n AND m.role = 0\n AND (${testPatternSql})\n ORDER BY ref_d.relative_path`,\n s.id,\n ).map((r) => r.relative_path);\n\n return {\n symbol: s.symbol,\n shortName: shortenSymbol(s.symbol),\n definedIn: s.relative_path,\n testFiles,\n covered: testFiles.length > 0,\n };\n });\n}\n\n/**\n * Summary: what percentage of symbols in scope are referenced by test files?\n */\nexport function testCoverageSummary(\n db: ScipDatabase,\n opts: { scope?: string; minLoc?: number } = {},\n): { total: number; covered: number; uncovered: number; percent: number } {\n const { scope, minLoc = 3 } = opts;\n const scopeFilter = scope ? `AND d.relative_path LIKE '%${scope}%'` : '';\n const testPatternSql = testFileExclusionSql('d');\n\n const symbols = db.all<{ id: number }>(\n `SELECT gs.id\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE 1 = 1\n ${db.pathExclusionsFor('d')}\n AND ${testPatternSql}\n ${db.symbolNoiseFor('gs')}\n AND gs.symbol NOT LIKE '%#%'\n AND (der.end_line - der.start_line + 1) >= ?\n ${scopeFilter}`,\n minLoc,\n );\n\n const testRefSql = testFileMatchSql('ref_d', TEST_FILE_PATTERNS);\n\n let covered = 0;\n for (const s of symbols) {\n const hasTest = db.get<{ c: number }>(\n `SELECT COUNT(*) AS c FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents ref_d ON c.document_id = ref_d.id\n WHERE m.symbol_id = ? AND m.role = 0 AND (${testRefSql})`,\n s.id,\n );\n if (hasTest && hasTest.c > 0) covered++;\n }\n\n const total = symbols.length;\n return {\n total,\n covered,\n uncovered: total - covered,\n percent: total > 0 ? Math.round((covered / total) * 100) : 0,\n };\n}\n","import type { ScipDatabase } from '../db.js';\nimport type { DocCoverageResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Check documentation coverage: what percentage of symbols have doc strings?\n * Reports overall stats and lists undocumented symbols.\n */\nexport function docCoverage(\n db: ScipDatabase,\n opts: { scope?: string; minLoc?: number; limit?: number } = {},\n): DocCoverageResult {\n const { scope, minLoc = 3, limit = 50 } = opts;\n const scopeFilter = scope ? `AND d.relative_path LIKE '%${scope}%'` : '';\n\n // Count all local symbols meeting the threshold\n const totalRow = db.get<{ c: number }>(\n `SELECT COUNT(*) AS c\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE 1 = 1\n ${db.pathExclusionsFor('d')}\n ${db.symbolNoiseFor('gs')}\n AND gs.symbol NOT LIKE '%#%'\n AND (der.end_line - der.start_line + 1) >= ?\n ${scopeFilter}`,\n minLoc,\n );\n\n const docRow = db.get<{ c: number }>(\n `SELECT COUNT(*) AS c\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE 1 = 1\n ${db.pathExclusionsFor('d')}\n ${db.symbolNoiseFor('gs')}\n AND gs.symbol NOT LIKE '%#%'\n AND (der.end_line - der.start_line + 1) >= ?\n AND gs.documentation IS NOT NULL\n AND gs.documentation != ''\n ${scopeFilter}`,\n minLoc,\n );\n\n const total = totalRow?.c ?? 0;\n const documented = docRow?.c ?? 0;\n\n // Get undocumented symbols\n const undocRows = db.all<{\n symbol: string;\n relative_path: string;\n start_line: number;\n }>(\n `SELECT gs.symbol, d.relative_path, der.start_line\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE 1 = 1\n ${db.pathExclusionsFor('d')}\n ${db.symbolNoiseFor('gs')}\n AND gs.symbol NOT LIKE '%#%'\n AND (der.end_line - der.start_line + 1) >= ?\n AND (gs.documentation IS NULL OR gs.documentation = '')\n ${scopeFilter}\n ORDER BY d.relative_path, der.start_line\n LIMIT ?`,\n minLoc, limit,\n );\n\n return {\n totalSymbols: total,\n documented,\n undocumented: total - documented,\n coveragePercent: total > 0 ? Math.round((documented / total) * 100) : 0,\n undocumentedSymbols: undocRows\n .filter((r) => !db.isIgnored(r.relative_path))\n .map((r) => ({\n symbol: r.symbol,\n shortName: shortenSymbol(r.symbol),\n relativePath: r.relative_path,\n startLine: r.start_line,\n })),\n };\n}\n","import type { ScipDatabase } from '../db.js';\nimport { buildFileDepGraph } from '../query-support.js';\nimport type { DeepChainResult } from '../types.js';\n\n/**\n * Find the longest transitive dependency chains between files.\n * A chain A → B → C → D means A depends on B, B on C, C on D.\n *\n * Long chains = high coupling depth = changes at the end ripple through many layers.\n */\nexport function deepChains(\n db: ScipDatabase,\n opts: { limit?: number; scope?: string; minDepth?: number } = {},\n): DeepChainResult[] {\n const { limit = 10, scope, minDepth = 3 } = opts;\n const graph = buildFileDepGraph(db, scope);\n\n // DFS to find longest paths (with cycle detection)\n const results: DeepChainResult[] = [];\n\n function dfs(node: string, path: string[], visited: Set<string>): void {\n const neighbors = graph.get(node);\n if (!neighbors || neighbors.size === 0) {\n if (path.length >= minDepth) {\n results.push({ chain: [...path], depth: path.length });\n }\n return;\n }\n\n let extended = false;\n for (const next of neighbors) {\n if (visited.has(next)) continue; // skip cycles\n visited.add(next);\n path.push(next);\n dfs(next, path, visited);\n path.pop();\n visited.delete(next);\n extended = true;\n }\n\n // If no unvisited neighbors, this is a leaf in this path\n if (!extended && path.length >= minDepth) {\n results.push({ chain: [...path], depth: path.length });\n }\n }\n\n // Start DFS from each node\n for (const startNode of graph.keys()) {\n const visited = new Set<string>([startNode]);\n dfs(startNode, [startNode], visited);\n\n // Early termination if we have enough results\n if (results.length > limit * 10) break;\n }\n\n // Sort by depth descending, take top N\n results.sort((a, b) => b.depth - a.depth);\n return results.slice(0, limit);\n}\n","import type { ScipDatabase } from '../db.js';\nimport type { HierarchyNode } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Walk the enclosing_symbol chain upward to show a symbol's ancestry.\n * e.g., method → class → module → file\n *\n * Falls back to parsing the SCIP symbol descriptor chain when\n * enclosing_symbol is not populated by the indexer.\n */\nexport function hierarchy(db: ScipDatabase, symbolPattern: string): HierarchyNode[] {\n // Find the symbol\n const sym = db.get<{ symbol: string; enclosing_symbol: string | null }>(\n `SELECT symbol, enclosing_symbol FROM global_symbols\n WHERE symbol LIKE ? LIMIT 1`,\n `%${symbolPattern}%`,\n );\n\n if (!sym) return [];\n\n const chain: HierarchyNode[] = [\n { symbol: sym.symbol, shortName: shortenSymbol(sym.symbol), depth: 0 },\n ];\n\n // Walk enclosing_symbol chain if available\n let current = sym.enclosing_symbol;\n let depth = 1;\n const seen = new Set<string>([sym.symbol]);\n\n while (current && !seen.has(current) && depth < 20) {\n seen.add(current);\n const parent = db.get<{ symbol: string; enclosing_symbol: string | null }>(\n `SELECT symbol, enclosing_symbol FROM global_symbols WHERE symbol = ?`,\n current,\n );\n if (!parent) break;\n\n chain.push({\n symbol: parent.symbol,\n shortName: shortenSymbol(parent.symbol),\n depth,\n });\n current = parent.enclosing_symbol;\n depth++;\n }\n\n return chain;\n}\n","import type { ScipDatabase } from '../db.js';\nimport { findFirstSymbolMatch, getCalleeRowsForSymbol } from '../query-support.js';\nimport type { CallGraphResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Build a call graph for a symbol: who calls it (incoming) and\n * what it calls (outgoing).\n *\n * Incoming: other symbols whose definition ranges contain a reference to this symbol.\n * Outgoing: symbols referenced within this symbol's definition range.\n */\nexport function callGraph(db: ScipDatabase, symbolPattern: string): CallGraphResult | null {\n // Find the target symbol and its definition range\n const target = findFirstSymbolMatch(db, symbolPattern);\n\n if (!target) return null;\n\n // CALLERS: symbols whose definition ranges contain a reference to our target.\n // Find chunks that reference our symbol, then find which symbol's definition encloses that chunk.\n const callerRows = db.all<{\n caller_symbol: string;\n caller_file: string;\n }>(\n `SELECT DISTINCT caller_gs.symbol AS caller_symbol, caller_d.relative_path AS caller_file\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents ref_d ON c.document_id = ref_d.id\n -- Find the enclosing symbol for where the reference appears\n JOIN defn_enclosing_ranges caller_der\n ON caller_der.document_id = ref_d.id\n AND c.start_line >= caller_der.start_line\n AND c.end_line <= caller_der.end_line\n JOIN global_symbols caller_gs ON caller_der.symbol_id = caller_gs.id\n JOIN documents caller_d ON caller_der.document_id = caller_d.id\n WHERE m.symbol_id = ?\n AND m.role = 0\n AND caller_gs.id != ?\n ${db.symbolNoiseFor('caller_gs')}\n ${db.pathExclusionsFor('caller_d')}\n ORDER BY caller_d.relative_path\n LIMIT 50`,\n target.symbolId, target.symbolId,\n );\n\n // CALLEES: symbols referenced within our target's definition range.\n const calleeRows = getCalleeRowsForSymbol(db, target, { limit: 50 });\n\n return {\n symbol: target.symbol,\n shortName: shortenSymbol(target.symbol),\n callers: callerRows\n .filter((r) => !db.isIgnored(r.caller_file))\n .map((r) => ({\n symbol: r.caller_symbol,\n shortName: shortenSymbol(r.caller_symbol),\n file: r.caller_file,\n })),\n callees: calleeRows\n .map((r) => ({\n symbol: r.symbol,\n shortName: shortenSymbol(r.symbol),\n file: r.file,\n })),\n };\n}\n","import type { ScipDatabase } from '../db.js';\nimport { findFirstSymbolMatch, getCalleeRowsForSymbol } from '../query-support.js';\nimport type { SimilarSymbolResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Find functions with similar callee fingerprints using TF-IDF weighted\n * cosine similarity.\n *\n * Plain Jaccard similarity inflates scores when functions share ubiquitous\n * infrastructure imports (db, types, shortenSymbol). TF-IDF fixes this by\n * weighting each shared callee by how rare it is:\n *\n * - A callee used by 2 functions (rare) gets high weight → strong signal\n * - A callee used by 30 functions (common) gets low weight → noise\n *\n * This means two functions sharing `sendWelcomeEmail()` (rare) score\n * much higher than two functions sharing `db.all()` (ubiquitous), even\n * though both are \"shared callees.\"\n */\nexport function similar(\n db: ScipDatabase,\n symbolPattern: string,\n opts: { minSimilarity?: number; limit?: number } = {},\n): SimilarSymbolResult[] {\n const { minSimilarity = 0.4, limit = 20 } = opts;\n\n const target = findCallees(db, symbolPattern);\n if (!target || target.callees.size === 0) return [];\n\n const candidates = getAllCalleeFingerprints(db, {\n minCallees: 3,\n excludeSymbol: target.symbol,\n });\n\n // Compute IDF weights across all fingerprints + target\n const allFingerprints = [target, ...candidates];\n const idfWeights = computeIdf(allFingerprints);\n\n const results: SimilarSymbolResult[] = [];\n\n for (const candidate of candidates) {\n if (candidate.callees.size < 3) continue;\n\n const { similarity, significantShared, trivialShared } = weightedSimilarity(\n target.callees, candidate.callees, idfWeights,\n );\n\n if (similarity < minSimilarity) continue;\n if (significantShared.length < 1) continue; // no real overlap\n\n results.push({\n symbolA: target.symbol,\n shortNameA: shortenSymbol(target.symbol),\n fileA: target.file,\n symbolB: candidate.symbol,\n shortNameB: shortenSymbol(candidate.symbol),\n fileB: candidate.file,\n similarity,\n sharedCallees: significantShared.map(shortenSymbol),\n uniqueToA: [...difference(target.callees, candidate.callees)].map(shortenSymbol),\n uniqueToB: [...difference(candidate.callees, target.callees)].map(shortenSymbol),\n });\n }\n\n results.sort((a, b) => b.similarity - a.similarity);\n return results.slice(0, limit);\n}\n\n/**\n * Find similar symbols across the entire codebase.\n * Uses TF-IDF weighted similarity to filter out infrastructure noise.\n */\nexport function similarAll(\n db: ScipDatabase,\n opts: { minSimilarity?: number; limit?: number; scope?: string; minCallees?: number } = {},\n): SimilarSymbolResult[] {\n const { minSimilarity = 0.5, limit = 20, scope, minCallees = 4 } = opts;\n\n const all = getAllCalleeFingerprints(db, { minCallees, scope });\n const idfWeights = computeIdf(all);\n\n const results: SimilarSymbolResult[] = [];\n\n for (let i = 0; i < all.length; i++) {\n for (let j = i + 1; j < all.length; j++) {\n const a = all[i]!;\n const b = all[j]!;\n\n if (a.file === b.file) continue;\n\n const { similarity, significantShared } = weightedSimilarity(\n a.callees, b.callees, idfWeights,\n );\n\n if (similarity < minSimilarity) continue;\n if (significantShared.length < 2) continue;\n\n results.push({\n symbolA: a.symbol,\n shortNameA: shortenSymbol(a.symbol),\n fileA: a.file,\n symbolB: b.symbol,\n shortNameB: shortenSymbol(b.symbol),\n fileB: b.file,\n similarity,\n sharedCallees: significantShared.map(shortenSymbol),\n uniqueToA: [...difference(a.callees, b.callees)].map(shortenSymbol),\n uniqueToB: [...difference(b.callees, a.callees)].map(shortenSymbol),\n });\n }\n\n if (results.length > limit * 5) break;\n }\n\n results.sort((a, b) => b.similarity - a.similarity);\n return results.slice(0, limit);\n}\n\n// ── TF-IDF Engine ──────────────────────────────────────────\n\n/**\n * Compute inverse document frequency for each callee.\n * IDF(callee) = log(N / df(callee)) where N is total functions\n * and df is how many functions reference that callee.\n *\n * High IDF = rare callee = strong similarity signal.\n * Low IDF = ubiquitous callee = noise.\n */\nfunction computeIdf(fingerprints: SymbolFingerprint[]): Map<string, number> {\n const n = fingerprints.length;\n if (n === 0) return new Map();\n\n // Count how many functions reference each callee\n const docFreq = new Map<string, number>();\n for (const fp of fingerprints) {\n for (const callee of fp.callees) {\n docFreq.set(callee, (docFreq.get(callee) ?? 0) + 1);\n }\n }\n\n // Compute IDF\n const idf = new Map<string, number>();\n for (const [callee, df] of docFreq) {\n idf.set(callee, Math.log(n / df));\n }\n\n return idf;\n}\n\n/**\n * Compute TF-IDF weighted cosine similarity between two callee sets.\n *\n * Each callee is a dimension. Its weight is its IDF score.\n * Cosine similarity of the weighted vectors gives a similarity\n * that ignores ubiquitous callees and emphasizes rare shared ones.\n *\n * Also returns which shared callees are \"significant\" (above-median IDF)\n * vs \"trivial\" (below-median IDF, i.e., infrastructure).\n */\nfunction weightedSimilarity(\n a: Set<string>,\n b: Set<string>,\n idf: Map<string, number>,\n): { similarity: number; significantShared: string[]; trivialShared: string[] } {\n const shared = intersection(a, b);\n if (shared.size === 0) return { similarity: 0, significantShared: [], trivialShared: [] };\n\n // Compute weighted dot product and magnitudes\n let dotProduct = 0;\n let magA = 0;\n let magB = 0;\n\n const allCallees = new Set([...a, ...b]);\n for (const callee of allCallees) {\n const weight = idf.get(callee) ?? 0;\n const inA = a.has(callee) ? weight : 0;\n const inB = b.has(callee) ? weight : 0;\n dotProduct += inA * inB;\n magA += inA * inA;\n magB += inB * inB;\n }\n\n const magnitude = Math.sqrt(magA) * Math.sqrt(magB);\n const similarity = magnitude > 0 ? dotProduct / magnitude : 0;\n\n // Split shared callees into significant (high IDF) and trivial (low IDF)\n const medianIdf = getMedianIdf(idf);\n const significantShared: string[] = [];\n const trivialShared: string[] = [];\n\n for (const callee of shared) {\n const weight = idf.get(callee) ?? 0;\n if (weight >= medianIdf) {\n significantShared.push(callee);\n } else {\n trivialShared.push(callee);\n }\n }\n\n // Sort significant callees by IDF descending (most distinctive first)\n significantShared.sort((x, y) => (idf.get(y) ?? 0) - (idf.get(x) ?? 0));\n\n return { similarity, significantShared, trivialShared };\n}\n\nfunction getMedianIdf(idf: Map<string, number>): number {\n const values = [...idf.values()].sort((a, b) => a - b);\n if (values.length === 0) return 0;\n const mid = Math.floor(values.length / 2);\n return values.length % 2 === 0\n ? (values[mid - 1]! + values[mid]!) / 2\n : values[mid]!;\n}\n\n// ── Internal helpers ───────────────────────────────────────\n\ninterface SymbolFingerprint {\n symbol: string;\n file: string;\n callees: Set<string>;\n}\n\nfunction findCallees(\n db: ScipDatabase,\n symbolPattern: string,\n): SymbolFingerprint | null {\n const target = findFirstSymbolMatch(db, symbolPattern);\n\n if (!target) return null;\n\n const calleeRows = getCalleeRowsForSymbol(db, target);\n\n return {\n symbol: target.symbol,\n file: target.relativePath,\n callees: new Set(calleeRows.map((r) => r.symbol)),\n };\n}\n\nfunction getAllCalleeFingerprints(\n db: ScipDatabase,\n opts: { minCallees: number; scope?: string; excludeSymbol?: string },\n): SymbolFingerprint[] {\n const { minCallees, scope, excludeSymbol } = opts;\n const scopeFilter = scope ? `AND d.relative_path LIKE '%${scope}%'` : '';\n const excludeFilter = excludeSymbol ? `AND gs.symbol != '${excludeSymbol.replace(/'/g, \"''\")}'` : '';\n\n const symbols = db.all<{\n id: number;\n symbol: string;\n document_id: number;\n start_line: number;\n end_line: number;\n relative_path: string;\n }>(\n `SELECT gs.id, gs.symbol, der.document_id, der.start_line, der.end_line, d.relative_path\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE 1 = 1\n ${db.pathExclusionsFor('d')}\n ${db.symbolNoiseFor('gs')}\n AND (der.end_line - der.start_line + 1) >= 5\n ${scopeFilter}\n ${excludeFilter}\n ORDER BY d.relative_path`,\n );\n\n const fingerprints: SymbolFingerprint[] = [];\n\n for (const sym of symbols) {\n if (db.isIgnored(sym.relative_path)) continue;\n\n const calleeRows = getCalleeRowsForSymbol(db, {\n documentId: sym.document_id,\n startLine: sym.start_line,\n endLine: sym.end_line,\n symbolId: sym.id,\n });\n\n const callees = new Set(calleeRows.map((r) => r.symbol));\n if (callees.size >= minCallees) {\n fingerprints.push({ symbol: sym.symbol, file: sym.relative_path, callees });\n }\n }\n\n return fingerprints;\n}\n\nfunction intersection<T>(a: Set<T>, b: Set<T>): Set<T> {\n const result = new Set<T>();\n for (const item of a) {\n if (b.has(item)) result.add(item);\n }\n return result;\n}\n\nfunction difference<T>(a: Set<T>, b: Set<T>): Set<T> {\n const result = new Set<T>();\n for (const item of a) {\n if (!b.has(item)) result.add(item);\n }\n return result;\n}\n","import type { ScipDatabase } from '../db.js';\nimport { buildFileDepGraph } from '../query-support.js';\nimport type { SimilarFileResult } from '../types.js';\n\n/**\n * Find files with similar dependency profiles.\n *\n * Two files that depend on (import from) the same set of other files\n * are structurally doing similar work. High Jaccard similarity between\n * their dependency sets = likely copy-paste variants or consolidation candidates.\n */\nexport function similarFiles(\n db: ScipDatabase,\n opts: {\n minSimilarity?: number;\n limit?: number;\n scope?: string;\n minDeps?: number;\n filePattern?: string;\n } = {},\n): SimilarFileResult[] {\n const { minSimilarity = 0.5, limit = 20, scope, minDeps = 3, filePattern } = opts;\n\n // Build dependency profile for each file\n const profiles = buildFileProfiles(db, { scope, minDeps });\n\n const results: SimilarFileResult[] = [];\n\n if (filePattern) {\n // Compare one file against all others\n const target = profiles.find((p) => p.file.includes(filePattern));\n if (!target) return [];\n\n for (const candidate of profiles) {\n if (candidate.file === target.file) continue;\n const result = compareProfiles(target, candidate, minSimilarity);\n if (result) results.push(result);\n }\n } else {\n // Pairwise comparison across all files\n for (let i = 0; i < profiles.length; i++) {\n for (let j = i + 1; j < profiles.length; j++) {\n const result = compareProfiles(profiles[i]!, profiles[j]!, minSimilarity);\n if (result) results.push(result);\n }\n if (results.length > limit * 5) break;\n }\n }\n\n results.sort((a, b) => b.similarity - a.similarity);\n return results.slice(0, limit);\n}\n\n// ── Internal ───────────────────────────────────────────────\n\ninterface FileProfile {\n file: string;\n deps: Set<string>;\n}\n\nfunction buildFileProfiles(\n db: ScipDatabase,\n opts: { scope?: string; minDeps: number },\n): FileProfile[] {\n const { scope, minDeps } = opts;\n const depMap = buildFileDepGraph(db, scope);\n const universalDeps = findUniversalDependencies(depMap);\n\n // Filter to files with enough deps\n const profiles: FileProfile[] = [];\n for (const [file, deps] of depMap) {\n if (deps.size >= minDeps) {\n profiles.push({\n file,\n deps: new Set([...deps].filter((dep) => !universalDeps.has(dep))),\n });\n }\n }\n\n return profiles;\n}\n\nfunction findUniversalDependencies(\n depMap: Map<string, Set<string>>,\n): Set<string> {\n const universalDeps = new Set<string>();\n const fileCount = depMap.size;\n if (fileCount === 0) return universalDeps;\n\n const depCounts = new Map<string, number>();\n for (const deps of depMap.values()) {\n for (const dep of deps) {\n depCounts.set(dep, (depCounts.get(dep) ?? 0) + 1);\n }\n }\n\n for (const [dep, count] of depCounts) {\n if (count / fileCount > 0.5) {\n universalDeps.add(dep);\n }\n }\n\n return universalDeps;\n}\n\nfunction compareProfiles(\n a: FileProfile,\n b: FileProfile,\n minSimilarity: number,\n): SimilarFileResult | null {\n const shared = new Set<string>();\n for (const dep of a.deps) {\n if (b.deps.has(dep)) shared.add(dep);\n }\n\n if (shared.size === 0) return null;\n\n const unionSize = new Set([...a.deps, ...b.deps]).size;\n const similarity = shared.size / unionSize;\n\n if (similarity < minSimilarity) return null;\n\n const uniqueA: string[] = [];\n for (const dep of a.deps) {\n if (!b.deps.has(dep)) uniqueA.push(dep);\n }\n const uniqueB: string[] = [];\n for (const dep of b.deps) {\n if (!a.deps.has(dep)) uniqueB.push(dep);\n }\n\n return {\n fileA: a.file,\n fileB: b.file,\n similarity,\n sharedDeps: [...shared],\n uniqueToA: uniqueA,\n uniqueToB: uniqueB,\n };\n}\n","import type { ScipDatabase } from '../db.js';\nimport { buildFileDepGraph } from '../query-support.js';\nimport type { SimilarChainResult } from '../types.js';\n\n/**\n * Find end-to-end dependency flows that are structurally similar\n * but diverge at a few points — indicating duplicated pipelines\n * that could be consolidated.\n *\n * Uses infrastructure-filtered chain comparison:\n *\n * 1. Build all dependency chains via DFS\n * 2. Compute node frequency across all chains\n * 3. Filter out infrastructure nodes (appearing in >50% of chains)\n * 4. Compare the filtered chains — what's left is the unique pipeline\n * 5. Edit distance on filtered chains finds real structural duplicates\n *\n * Two chains that both pass through db.ts → types.ts is meaningless.\n * Two chains that both pass through userValidation → userRepo → emailService\n * after filtering is a strong consolidation signal.\n */\nexport function similarChains(\n db: ScipDatabase,\n opts: {\n minSimilarity?: number;\n limit?: number;\n scope?: string;\n minChainLength?: number;\n maxChainLength?: number;\n } = {},\n): SimilarChainResult[] {\n const {\n minSimilarity = 0.5,\n limit = 15,\n scope,\n minChainLength = 3,\n maxChainLength = 8,\n } = opts;\n\n const graph = buildFileDepGraph(db, scope);\n const rawChains = generateChains(graph, minChainLength, maxChainLength);\n\n if (rawChains.length === 0) return [];\n\n // Compute node frequency to identify infrastructure.\n // Count both general frequency (appears anywhere in chain) and\n // tail frequency (appears as one of the last 2 nodes). Shared\n // tails like \"→ db.ts → types.ts\" are infrastructure even if\n // they don't appear in >50% of chains overall.\n const nodeFreq = new Map<string, number>();\n const tailFreq = new Map<string, number>();\n for (const chain of rawChains) {\n const seen = new Set<string>();\n for (const node of chain) {\n if (!seen.has(node)) {\n nodeFreq.set(node, (nodeFreq.get(node) ?? 0) + 1);\n seen.add(node);\n }\n }\n // Track tail nodes (last 2)\n for (let t = Math.max(0, chain.length - 2); t < chain.length; t++) {\n tailFreq.set(chain[t]!, (tailFreq.get(chain[t]!) ?? 0) + 1);\n }\n }\n\n // Infrastructure: nodes in >40% of chains OR tail nodes in >30% of chains\n const infraThreshold = rawChains.length * 0.4;\n const tailThreshold = rawChains.length * 0.3;\n const infraNodes = new Set<string>();\n for (const [node, freq] of nodeFreq) {\n if (freq > infraThreshold) infraNodes.add(node);\n }\n for (const [node, freq] of tailFreq) {\n if (freq > tailThreshold) infraNodes.add(node);\n }\n\n // Also treat structural role files as infrastructure — entry points,\n // barrels, and orchestrators are not meaningful pipeline nodes.\n const structuralNames = ['index.ts', 'index.js', 'cli.ts', 'main.ts', 'health.ts', 'health.js'];\n for (const node of nodeFreq.keys()) {\n const basename = node.split('/').pop() ?? '';\n if (structuralNames.includes(basename)) infraNodes.add(node);\n }\n\n // Filter chains: remove infrastructure nodes, keep the \"unique pipeline\"\n const filteredChains: { original: string[]; filtered: string[] }[] = [];\n for (const chain of rawChains) {\n const filtered = chain.filter((n) => !infraNodes.has(n));\n // Only keep chains that have at least 3 non-infrastructure nodes.\n // Chains with 1-2 unique nodes are just \"query → infra\" which is\n // the expected pattern, not a consolidation opportunity.\n if (filtered.length >= 3) {\n filteredChains.push({ original: chain, filtered });\n }\n }\n\n if (filteredChains.length < 2) return [];\n\n // Pairwise comparison on filtered chains\n const results: SimilarChainResult[] = [];\n\n for (let i = 0; i < filteredChains.length; i++) {\n for (let j = i + 1; j < filteredChains.length; j++) {\n const a = filteredChains[i]!;\n const b = filteredChains[j]!;\n\n // Quick reject: filtered chains must share at least one non-infra node\n const setA = new Set(a.filtered);\n let hasShared = false;\n for (const node of b.filtered) {\n if (setA.has(node)) { hasShared = true; break; }\n }\n if (!hasShared) continue;\n\n // Edit distance on the FILTERED chains (infrastructure stripped)\n const { distance, ops } = editDistance(a.filtered, b.filtered);\n const maxLen = Math.max(a.filtered.length, b.filtered.length);\n if (maxLen === 0) continue;\n\n const similarity = 1 - distance / maxLen;\n if (similarity < minSimilarity) continue;\n if (distance === 0) continue; // identical filtered chains = not interesting\n\n // Divergence points from the filtered comparison\n const divergencePoints = ops\n .filter((op) => op.type === 'substitute')\n .map((op) => ({\n index: op.indexA,\n nodeA: a.filtered[op.indexA]!,\n nodeB: b.filtered[op.indexB]!,\n }));\n\n if (divergencePoints.length === 0) continue;\n\n // Require at least 2 matching (non-divergent) filtered nodes.\n // A chain pair with 1 match and 1 divergence is just \"two things\n // that share one dependency\" — not a duplicated pipeline.\n const matchCount = ops.filter((op) => op.type === 'match').length;\n if (matchCount < 2) continue;\n\n // Report using original chains for context, but similarity is from filtered\n const commonPrefix = getCommonPrefix(a.original, b.original);\n const commonSuffix = getCommonSuffix(a.original, b.original);\n\n results.push({\n chainA: a.original,\n chainB: b.original,\n similarity,\n editDistance: distance,\n divergencePoints,\n commonPrefix,\n commonSuffix,\n });\n }\n\n if (results.length > limit * 10) break;\n }\n\n // Sort by similarity desc, then fewest divergence points\n results.sort((a, b) => {\n if (Math.abs(b.similarity - a.similarity) > 0.01) return b.similarity - a.similarity;\n return a.divergencePoints.length - b.divergencePoints.length;\n });\n\n // Deduplicate sub-chains\n const deduped: SimilarChainResult[] = [];\n for (const r of results) {\n const isDuplicate = deduped.some(\n (existing) =>\n isSubChain(r.chainA, existing.chainA) && isSubChain(r.chainB, existing.chainB),\n );\n if (!isDuplicate) deduped.push(r);\n if (deduped.length >= limit) break;\n }\n\n return deduped;\n}\n\n// ── Chain generation ───────────────────────────────────────\n\nfunction generateChains(\n graph: Map<string, Set<string>>,\n minLen: number,\n maxLen: number,\n): string[][] {\n const chains: string[][] = [];\n const maxChains = 500;\n\n for (const startNode of graph.keys()) {\n if (chains.length >= maxChains) break;\n dfsChains(graph, startNode, [startNode], new Set([startNode]), minLen, maxLen, chains, maxChains);\n }\n\n return chains;\n}\n\nfunction dfsChains(\n graph: Map<string, Set<string>>,\n node: string,\n path: string[],\n visited: Set<string>,\n minLen: number,\n maxLen: number,\n results: string[][],\n maxResults: number,\n): void {\n if (results.length >= maxResults) return;\n if (path.length >= maxLen) {\n if (path.length >= minLen) results.push([...path]);\n return;\n }\n\n const neighbors = graph.get(node);\n if (!neighbors || neighbors.size === 0) {\n if (path.length >= minLen) results.push([...path]);\n return;\n }\n\n let extended = false;\n for (const next of neighbors) {\n if (visited.has(next)) continue;\n visited.add(next);\n path.push(next);\n dfsChains(graph, next, path, visited, minLen, maxLen, results, maxResults);\n path.pop();\n visited.delete(next);\n extended = true;\n if (results.length >= maxResults) return;\n }\n\n if (!extended && path.length >= minLen) {\n results.push([...path]);\n }\n}\n\n// ── Edit distance ──────────────────────────────────────────\n\ninterface EditOp {\n type: 'match' | 'substitute' | 'insert' | 'delete';\n indexA: number;\n indexB: number;\n}\n\nfunction editDistance(a: string[], b: string[]): { distance: number; ops: EditOp[] } {\n const m = a.length;\n const n = b.length;\n\n const dp: number[][] = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));\n for (let i = 0; i <= m; i++) dp[i]![0] = i;\n for (let j = 0; j <= n; j++) dp[0]![j] = j;\n\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n if (a[i - 1] === b[j - 1]) {\n dp[i]![j] = dp[i - 1]![j - 1]!;\n } else {\n dp[i]![j] = 1 + Math.min(\n dp[i - 1]![j]!,\n dp[i]![j - 1]!,\n dp[i - 1]![j - 1]!,\n );\n }\n }\n }\n\n const ops: EditOp[] = [];\n let i = m, j = n;\n while (i > 0 || j > 0) {\n if (i > 0 && j > 0 && a[i - 1] === b[j - 1]) {\n ops.unshift({ type: 'match', indexA: i - 1, indexB: j - 1 });\n i--; j--;\n } else if (i > 0 && j > 0 && dp[i]![j] === dp[i - 1]![j - 1]! + 1) {\n ops.unshift({ type: 'substitute', indexA: i - 1, indexB: j - 1 });\n i--; j--;\n } else if (j > 0 && dp[i]![j] === dp[i]![j - 1]! + 1) {\n ops.unshift({ type: 'insert', indexA: i, indexB: j - 1 });\n j--;\n } else {\n ops.unshift({ type: 'delete', indexA: i - 1, indexB: j });\n i--;\n }\n }\n\n return { distance: dp[m]![n]!, ops };\n}\n\n// ── Utility ────────────────────────────────────────────────\n\nfunction getCommonPrefix(a: string[], b: string[]): string[] {\n const prefix: string[] = [];\n for (let i = 0; i < Math.min(a.length, b.length); i++) {\n if (a[i] === b[i]) prefix.push(a[i]!);\n else break;\n }\n return prefix;\n}\n\nfunction getCommonSuffix(a: string[], b: string[]): string[] {\n const suffix: string[] = [];\n let ai = a.length - 1;\n let bi = b.length - 1;\n while (ai >= 0 && bi >= 0 && a[ai] === b[bi]) {\n suffix.unshift(a[ai]!);\n ai--; bi--;\n }\n return suffix;\n}\n\nfunction isSubChain(sub: string[], full: string[]): boolean {\n if (sub.length > full.length) return false;\n const fullStr = full.join('→');\n const subStr = sub.join('→');\n return fullStr.includes(subStr);\n}\n","import type { ScipDatabase } from '../db.js';\nimport { getCalleeRowsForSymbol } from '../query-support.js';\nimport type { ExtractCandidate } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Find functions with natural extraction seams.\n *\n * A large function that references two distinct groups of symbols —\n * where group A's symbols are never co-referenced with group B's —\n * has a natural extraction boundary. The isolated cluster can likely\n * be pulled into its own function.\n *\n * We detect this by:\n * 1. Finding all callees of a function\n * 2. Building a co-occurrence graph (which callees appear in the same chunk)\n * 3. Finding connected components — disconnected components = extraction seams\n * 4. Scoring each cluster by how isolated it is from the rest\n */\nexport function extractCandidates(\n db: ScipDatabase,\n opts: { scope?: string; minLoc?: number; minCallees?: number; limit?: number } = {},\n): ExtractCandidate[] {\n const { scope, minLoc = 10, minCallees = 6, limit = 20 } = opts;\n const scopeFilter = scope ? `AND d.relative_path LIKE '%${scope}%'` : '';\n\n // Find functions large enough to consider\n const symbols = db.all<{\n id: number;\n symbol: string;\n document_id: number;\n start_line: number;\n end_line: number;\n relative_path: string;\n }>(\n `SELECT gs.id, gs.symbol, der.document_id, der.start_line, der.end_line, d.relative_path\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE 1 = 1\n ${db.pathExclusionsFor('d')}\n ${db.symbolNoiseFor('gs')}\n AND (der.end_line - der.start_line + 1) >= ?\n ${scopeFilter}\n ORDER BY (der.end_line - der.start_line + 1) DESC`,\n minLoc,\n );\n\n const results: ExtractCandidate[] = [];\n\n for (const sym of symbols) {\n if (db.isIgnored(sym.relative_path)) continue;\n\n // Skip pure type files — \"callees\" in a type file are just type references,\n // not function calls. Splitting type files is a cosmetic choice, not an\n // extraction opportunity.\n const basename = sym.relative_path.split('/').pop() ?? '';\n if (basename.includes('types')) continue;\n\n // Get callees with their chunk locations (to build co-occurrence)\n const calleeChunks = getCalleeRowsForSymbol(db, {\n documentId: sym.document_id,\n startLine: sym.start_line,\n endLine: sym.end_line,\n symbolId: sym.id,\n });\n\n // Collect unique callees\n const calleeSet = new Set(calleeChunks.map((c) => c.symbol));\n if (calleeSet.size < minCallees) continue;\n\n // Build co-occurrence graph: two callees are connected if they\n // appear in the same chunk (meaning they're used in proximity)\n const cooccurrence = new Map<string, Set<string>>();\n for (const callee of calleeSet) {\n cooccurrence.set(callee, new Set());\n }\n\n // Group by chunk\n const chunkToCallees = new Map<number, Set<string>>();\n for (const cc of calleeChunks) {\n if (!chunkToCallees.has(cc.chunkId)) chunkToCallees.set(cc.chunkId, new Set());\n chunkToCallees.get(cc.chunkId)!.add(cc.symbol);\n }\n\n // Callees in the same chunk are co-occurring\n for (const callees of chunkToCallees.values()) {\n const arr = [...callees];\n for (let i = 0; i < arr.length; i++) {\n for (let j = i + 1; j < arr.length; j++) {\n cooccurrence.get(arr[i]!)!.add(arr[j]!);\n cooccurrence.get(arr[j]!)!.add(arr[i]!);\n }\n }\n }\n\n // Find connected components via BFS\n const visited = new Set<string>();\n const clusters: Set<string>[] = [];\n\n for (const callee of calleeSet) {\n if (visited.has(callee)) continue;\n const cluster = new Set<string>();\n const queue = [callee];\n while (queue.length > 0) {\n const current = queue.pop()!;\n if (visited.has(current)) continue;\n visited.add(current);\n cluster.add(current);\n for (const neighbor of cooccurrence.get(current) ?? []) {\n if (!visited.has(neighbor)) queue.push(neighbor);\n }\n }\n clusters.push(cluster);\n }\n\n // Only interesting if there are multiple clusters (= extraction seams exist)\n if (clusters.length < 2) continue;\n\n // Score each cluster by isolation:\n // isolation = 1 - (edges to other clusters / total possible edges to other clusters)\n const scoredClusters = clusters\n .filter((c) => c.size >= 2) // single-callee clusters aren't interesting\n .map((cluster) => {\n const otherCallees = new Set<string>();\n for (const c of clusters) {\n if (c !== cluster) {\n for (const s of c) otherCallees.add(s);\n }\n }\n\n // Count cross-cluster edges\n let crossEdges = 0;\n for (const callee of cluster) {\n for (const neighbor of cooccurrence.get(callee) ?? []) {\n if (otherCallees.has(neighbor)) crossEdges++;\n }\n }\n\n const maxCrossEdges = cluster.size * otherCallees.size;\n const isolation = maxCrossEdges > 0 ? 1 - crossEdges / maxCrossEdges : 1;\n\n return {\n callees: [...cluster].map(shortenSymbol),\n isolation,\n };\n })\n .filter((c) => c.isolation > 0.5) // Only report well-isolated clusters\n .sort((a, b) => b.isolation - a.isolation);\n\n if (scoredClusters.length > 0) {\n results.push({\n symbol: sym.symbol,\n shortName: shortenSymbol(sym.symbol),\n relativePath: sym.relative_path,\n startLine: sym.start_line,\n endLine: sym.end_line,\n loc: sym.end_line - sym.start_line + 1,\n totalCallees: calleeSet.size,\n clusters: scoredClusters,\n });\n }\n }\n\n results.sort((a, b) => b.clusters.length - a.clusters.length || b.loc - a.loc);\n return results.slice(0, limit);\n}\n","import type { ScipDatabase } from '../db.js';\nimport { findFirstSymbolMatch } from '../query-support.js';\nimport type { AffectedResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Full transitive closure of symbols that could break if a given symbol changes.\n * BFS from the target through the mention graph: depth 1 = direct consumers,\n * depth 2 = consumers of consumers, etc.\n */\nexport function affected(\n db: ScipDatabase,\n symbolPattern: string,\n opts: { maxDepth?: number; scope?: string } = {},\n): AffectedResult[] {\n const { maxDepth = 5, scope } = opts;\n\n const target = findFirstSymbolMatch(db, symbolPattern);\n if (!target) return [];\n\n const scopeFilter = scope\n ? `AND enc_d.relative_path LIKE '%${scope}%'`\n : '';\n\n const results: AffectedResult[] = [];\n const visited = new Set<number>([target.symbolId]);\n let frontier = new Set<number>([target.symbolId]);\n\n for (let depth = 1; depth <= maxDepth; depth++) {\n if (frontier.size === 0) break;\n\n const placeholders = [...frontier].map(() => '?').join(',');\n const nextFrontier = new Set<number>();\n\n // For each symbol in the frontier, find enclosing symbols whose\n // definition ranges contain a reference (role=0) to that frontier symbol.\n const rows = db.all<{\n symbol_id: number;\n symbol: string;\n relative_path: string;\n }>(\n `SELECT DISTINCT\n enc_gs.id AS symbol_id,\n enc_gs.symbol AS symbol,\n enc_d.relative_path AS relative_path\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents ref_d ON c.document_id = ref_d.id\n JOIN defn_enclosing_ranges enc_der\n ON enc_der.document_id = ref_d.id\n AND c.start_line >= enc_der.start_line\n AND c.end_line <= enc_der.end_line\n JOIN global_symbols enc_gs ON enc_der.symbol_id = enc_gs.id\n JOIN documents enc_d ON enc_der.document_id = enc_d.id\n WHERE m.symbol_id IN (${placeholders})\n AND m.role = 0\n AND enc_gs.id NOT IN (${placeholders})\n ${db.symbolNoiseFor('enc_gs')}\n ${db.pathExclusionsFor('enc_d')}\n ${scopeFilter}`,\n ...[...frontier],\n ...[...frontier],\n );\n\n for (const row of rows) {\n if (visited.has(row.symbol_id)) continue;\n if (db.isIgnored(row.relative_path)) continue;\n\n visited.add(row.symbol_id);\n nextFrontier.add(row.symbol_id);\n\n results.push({\n symbol: row.symbol,\n shortName: shortenSymbol(row.symbol),\n file: row.relative_path,\n depth,\n });\n }\n\n frontier = nextFrontier;\n }\n\n // Sort by depth then file path\n results.sort((a, b) => a.depth - b.depth || a.file.localeCompare(b.file));\n return results;\n}\n","import type { ScipDatabase } from '../db.js';\nimport { TEST_FILE_PATTERNS, testFileMatchSql } from '../query-support.js';\nimport type { ChangeSurfaceEntry, ChangeSurfaceResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Pre-change briefing for a file. For each symbol defined in the file,\n * reports external consumer count, test coverage, and risk level.\n */\nexport function changeSurface(\n db: ScipDatabase,\n filePattern: string,\n): ChangeSurfaceResult | null {\n // Find the file\n const doc = db.get<{ id: number; relative_path: string }>(\n `SELECT id, relative_path FROM documents\n WHERE relative_path LIKE ?\n ${db.pathExclusionsFor('documents')}\n LIMIT 1`,\n `%${filePattern}%`,\n );\n\n if (!doc || db.isIgnored(doc.relative_path)) return null;\n\n // Get all symbols defined in this file, excluding typeLiterals\n const syms = db.all<{\n symbol_id: number;\n symbol: string;\n start_line: number;\n end_line: number;\n }>(\n `SELECT DISTINCT gs.id AS symbol_id, gs.symbol, der.start_line, der.end_line\n FROM defn_enclosing_ranges der\n JOIN global_symbols gs ON der.symbol_id = gs.id\n WHERE der.document_id = ?\n ${db.symbolNoiseFor('gs')}\n ORDER BY der.start_line`,\n doc.id,\n );\n\n const testPatternSql = testFileMatchSql('ref_d', TEST_FILE_PATTERNS);\n\n const symbols: ChangeSurfaceEntry[] = [];\n let totalExternalConsumers = 0;\n let coveredCount = 0;\n\n for (const sym of syms) {\n // Count external consumers: mentions with role=0 from different documents\n const consumerRow = db.get<{ consumer_count: number }>(\n `SELECT COUNT(DISTINCT c.document_id) AS consumer_count\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n WHERE m.symbol_id = ?\n AND m.role = 0\n AND c.document_id != ?`,\n sym.symbol_id,\n doc.id,\n );\n\n const externalConsumers = consumerRow?.consumer_count ?? 0;\n\n // Find test files that reference this symbol\n const testFiles = db.all<{ relative_path: string }>(\n `SELECT DISTINCT ref_d.relative_path\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents ref_d ON c.document_id = ref_d.id\n WHERE m.symbol_id = ?\n AND m.role = 0\n AND (${testPatternSql})\n ORDER BY ref_d.relative_path`,\n sym.symbol_id,\n ).map((r) => r.relative_path);\n\n const hasTests = testFiles.length > 0;\n if (hasTests) coveredCount++;\n\n // Risk level determination\n let riskLevel: 'low' | 'medium' | 'high';\n if (externalConsumers > 10 && !hasTests) {\n riskLevel = 'high';\n } else if (externalConsumers > 5 || !hasTests) {\n riskLevel = 'medium';\n } else {\n riskLevel = 'low';\n }\n\n totalExternalConsumers += externalConsumers;\n\n symbols.push({\n symbol: sym.symbol,\n shortName: shortenSymbol(sym.symbol),\n startLine: sym.start_line,\n endLine: sym.end_line,\n externalConsumers,\n testFiles,\n riskLevel,\n });\n }\n\n const testCoveragePercent =\n symbols.length > 0 ? Math.round((coveredCount / symbols.length) * 100) : 0;\n\n return {\n file: doc.relative_path,\n symbols,\n totalExternalConsumers,\n testCoveragePercent,\n };\n}\n","import { execFileSync } from 'node:child_process';\nimport type { ScipDatabase } from '../db.js';\nimport { TEST_FILE_PATTERNS, testFileMatchSql } from '../query-support.js';\nimport type { DiffImpactResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Given a git diff, compute the affected symbol set.\n * Finds all symbols defined in changed files, their fan-in,\n * the files that consume them, and test coverage gaps.\n */\nexport function diffImpact(\n db: ScipDatabase,\n opts: { base?: string } = {},\n): DiffImpactResult {\n const { base = 'HEAD' } = opts;\n\n // Get changed files from git\n let changedFileLines: string[];\n try {\n const stdout = execFileSync('git', ['diff', '--name-only', base], {\n encoding: 'utf-8',\n cwd: db.config.projectRoot,\n timeout: 10_000,\n });\n changedFileLines = stdout\n .split('\\n')\n .map((l) => l.trim())\n .filter((l) => l.length > 0);\n } catch {\n // Not in a git repo or git not available — return empty result\n return {\n changedFiles: [],\n changedSymbols: [],\n affectedConsumers: [],\n uncoveredSymbols: [],\n summary: {\n totalChangedFiles: 0,\n totalChangedSymbols: 0,\n totalAffectedFiles: 0,\n testCoveragePercent: 0,\n },\n };\n }\n\n if (changedFileLines.length === 0) {\n return {\n changedFiles: [],\n changedSymbols: [],\n affectedConsumers: [],\n uncoveredSymbols: [],\n summary: {\n totalChangedFiles: 0,\n totalChangedSymbols: 0,\n totalAffectedFiles: 0,\n testCoveragePercent: 0,\n },\n };\n }\n\n // Match changed files against the index\n const changedFiles: string[] = [];\n const changedDocIds: number[] = [];\n\n for (const file of changedFileLines) {\n const doc = db.get<{ id: number; relative_path: string }>(\n `SELECT id, relative_path FROM documents\n WHERE relative_path LIKE ?\n LIMIT 1`,\n `%${file}`,\n );\n if (doc && !db.isIgnored(doc.relative_path)) {\n changedFiles.push(doc.relative_path);\n changedDocIds.push(doc.id);\n }\n }\n\n if (changedDocIds.length === 0) {\n return {\n changedFiles: changedFileLines,\n changedSymbols: [],\n affectedConsumers: [],\n uncoveredSymbols: [],\n summary: {\n totalChangedFiles: changedFileLines.length,\n totalChangedSymbols: 0,\n totalAffectedFiles: 0,\n testCoveragePercent: 0,\n },\n };\n }\n\n // Get all symbols defined in changed files\n const docPlaceholders = changedDocIds.map(() => '?').join(',');\n const syms = db.all<{\n symbol_id: number;\n symbol: string;\n relative_path: string;\n }>(\n `SELECT DISTINCT gs.id AS symbol_id, gs.symbol, d.relative_path\n FROM defn_enclosing_ranges der\n JOIN global_symbols gs ON der.symbol_id = gs.id\n JOIN documents d ON der.document_id = d.id\n WHERE der.document_id IN (${docPlaceholders})\n ${db.symbolNoiseFor('gs')}\n ORDER BY d.relative_path`,\n ...changedDocIds,\n );\n\n // For each symbol, compute fan-in (distinct referencing documents)\n const testPatternSql = testFileMatchSql('ref_d', TEST_FILE_PATTERNS);\n const changedSymbols: DiffImpactResult['changedSymbols'] = [];\n const consumerMap = new Map<string, Set<string>>(); // file -> set of consumed symbol shortNames\n const uncoveredSymbols: DiffImpactResult['uncoveredSymbols'] = [];\n let coveredCount = 0;\n\n for (const sym of syms) {\n // Fan-in: distinct files that reference this symbol\n const fanInRow = db.get<{ fan_in: number }>(\n `SELECT COUNT(DISTINCT c.document_id) AS fan_in\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n WHERE m.symbol_id = ?\n AND m.role = 0`,\n sym.symbol_id,\n );\n\n const fanIn = fanInRow?.fan_in ?? 0;\n const shortName = shortenSymbol(sym.symbol);\n\n changedSymbols.push({\n symbol: sym.symbol,\n shortName,\n file: sym.relative_path,\n fanIn,\n });\n\n // Collect consumer files (excluding the changed files themselves)\n const consumers = db.all<{ relative_path: string }>(\n `SELECT DISTINCT ref_d.relative_path\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents ref_d ON c.document_id = ref_d.id\n WHERE m.symbol_id = ?\n AND m.role = 0\n AND ref_d.relative_path NOT IN (${changedFiles.map(() => '?').join(',')})\n ${db.pathExclusionsFor('ref_d')}`,\n sym.symbol_id,\n ...changedFiles,\n );\n\n for (const consumer of consumers) {\n if (db.isIgnored(consumer.relative_path)) continue;\n if (!consumerMap.has(consumer.relative_path)) {\n consumerMap.set(consumer.relative_path, new Set());\n }\n consumerMap.get(consumer.relative_path)!.add(shortName);\n }\n\n // Check test coverage\n const hasTest = db.get<{ c: number }>(\n `SELECT COUNT(*) AS c\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents ref_d ON c.document_id = ref_d.id\n WHERE m.symbol_id = ?\n AND m.role = 0\n AND (${testPatternSql})`,\n sym.symbol_id,\n );\n\n if (hasTest && hasTest.c > 0) {\n coveredCount++;\n } else {\n uncoveredSymbols.push({\n symbol: sym.symbol,\n shortName,\n file: sym.relative_path,\n });\n }\n }\n\n // Build affected consumers list\n const affectedConsumers = [...consumerMap.entries()]\n .map(([file, symbols]) => ({ file, consumedSymbols: symbols.size }))\n .sort((a, b) => b.consumedSymbols - a.consumedSymbols);\n\n const totalSymbols = changedSymbols.length;\n const testCoveragePercent =\n totalSymbols > 0 ? Math.round((coveredCount / totalSymbols) * 100) : 0;\n\n return {\n changedFiles,\n changedSymbols,\n affectedConsumers,\n uncoveredSymbols,\n summary: {\n totalChangedFiles: changedFiles.length,\n totalChangedSymbols: totalSymbols,\n totalAffectedFiles: affectedConsumers.length,\n testCoveragePercent,\n },\n };\n}\n","import path from 'node:path';\nimport type { ScipDatabase } from '../db.js';\nimport { buildFileDepGraph } from '../query-support.js';\nimport type { DriftResult, DriftSummary } from '../types.js';\n\n/**\n * Detect structural drift using the reference graph, not just import patterns.\n *\n * Three types of drift, each detecting a real problem:\n *\n * 1. **Unused imports** — file depends on a module but never references\n * any of its symbols. Dead dependency, safe to remove.\n *\n * 2. **Layer violations** — file imports from a directory it shouldn't\n * based on the project's directory structure (e.g., a query importing\n * from reindex, a helper importing from CLI). Architectural decay.\n *\n * 3. **Pattern deviations** — file imports something no sibling does,\n * suggesting it's reaching outside its expected scope. Only flagged\n * when the file is the ONLY one in its directory with that dep.\n */\nexport function drift(\n db: ScipDatabase,\n opts?: { scope?: string; minDeviation?: number },\n): DriftSummary {\n const { scope } = opts ?? {};\n\n // Build file dep graph (which files depend on which)\n const depGraph = buildFileDepGraph(db, scope);\n\n // Build symbol-level reference graph: for each file, which other files'\n // symbols does it actually reference?\n const symbolRefs = buildSymbolRefGraph(db, scope);\n\n const results: DriftResult[] = [];\n\n // ── Angle 1: Unused imports ──────────────────────────────\n // File depends on module B (via dep graph) but never references\n // any symbol defined in B (via symbol ref graph).\n for (const [file, deps] of depGraph) {\n if (isStructuralRole(path.basename(file))) continue;\n\n const referencedFiles = symbolRefs.get(file) ?? new Set<string>();\n\n for (const dep of deps) {\n if (!referencedFiles.has(dep)) {\n // This file \"depends on\" dep but never references its symbols.\n // This can happen when the dep is imported for types only\n // (which don't appear in the mention graph). Skip type-heavy deps.\n if (isLikelyTypeOnlyDep(dep)) continue;\n\n results.push({\n file,\n kind: 'unused-import',\n description: `Depends on ${dep} but references none of its symbols`,\n dep,\n });\n }\n }\n }\n\n // ── Angle 2: Layer violations ────────────────────────────\n // Detect when a file imports from a directory that represents\n // a different architectural layer. We infer layers from the\n // directory structure: files in the same top-level dir are peers,\n // files in different top-level dirs crossing inward is a violation.\n const layerRules = inferLayerRules(depGraph);\n\n for (const [file, deps] of depGraph) {\n if (isStructuralRole(path.basename(file))) continue;\n\n const fileLayer = getTopDir(file);\n for (const dep of deps) {\n const depLayer = getTopDir(dep);\n if (fileLayer === depLayer) continue; // same layer, fine\n\n const violation = layerRules.get(`${fileLayer}->${depLayer}`);\n if (violation === 'violation') {\n results.push({\n file,\n kind: 'layer-violation',\n description: `Imports from ${depLayer}/ (${dep}) — may cross architectural boundary`,\n dep,\n detail: `${fileLayer}/ should not depend on ${depLayer}/`,\n });\n }\n }\n }\n\n // ── Angle 3: Unique deps (pattern deviation) ─────────────\n // If a file is the ONLY one in its directory that depends on a\n // particular module, that dependency is unusual and worth flagging.\n const dirToFiles = new Map<string, string[]>();\n for (const file of depGraph.keys()) {\n const dir = path.dirname(file);\n if (!dirToFiles.has(dir)) dirToFiles.set(dir, []);\n dirToFiles.get(dir)!.push(file);\n }\n\n for (const [dir, files] of dirToFiles) {\n if (files.length < 3) continue;\n\n // Count dep frequency across siblings\n const depFreq = new Map<string, number>();\n for (const file of files) {\n if (isStructuralRole(path.basename(file))) continue;\n for (const dep of depGraph.get(file) ?? []) {\n depFreq.set(dep, (depFreq.get(dep) ?? 0) + 1);\n }\n }\n\n for (const file of files) {\n if (isStructuralRole(path.basename(file))) continue;\n for (const dep of depGraph.get(file) ?? []) {\n if ((depFreq.get(dep) ?? 0) === 1) {\n // This file is the only one in its dir that depends on this module\n // Skip if dep is in the same directory (sibling imports are normal)\n if (path.dirname(dep) === dir) continue;\n\n results.push({\n file,\n kind: 'pattern-deviation',\n description: `Only file in ${dir}/ that depends on ${dep}`,\n dep,\n });\n }\n }\n }\n }\n\n return {\n results,\n unusedImports: results.filter((r) => r.kind === 'unused-import').length,\n layerViolations: results.filter((r) => r.kind === 'layer-violation').length,\n patternDeviations: results.filter((r) => r.kind === 'pattern-deviation').length,\n };\n}\n\n// ── Helpers ────────────────────────────────────────────────\n\n/**\n * Build a map of file → set of files whose symbols it references.\n * This is more precise than the dep graph because it uses actual\n * symbol mentions, not just import statements.\n */\nfunction buildSymbolRefGraph(\n db: ScipDatabase,\n scope?: string,\n): Map<string, Set<string>> {\n const scopeFilter = scope ? `AND d1.relative_path LIKE '%${scope}%'` : '';\n\n const rows = db.all<{ from_file: string; to_file: string }>(\n `SELECT DISTINCT d1.relative_path AS from_file, d2.relative_path AS to_file\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d1 ON c.document_id = d1.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d2 ON der.document_id = d2.id\n WHERE d1.id != d2.id\n AND m.role = 0\n ${db.pathExclusionsFor('d1', 'd2')}\n ${scopeFilter}`,\n );\n\n const graph = new Map<string, Set<string>>();\n for (const r of rows) {\n if (db.isIgnored(r.from_file) || db.isIgnored(r.to_file)) continue;\n if (!graph.has(r.from_file)) graph.set(r.from_file, new Set());\n graph.get(r.from_file)!.add(r.to_file);\n }\n return graph;\n}\n\n/**\n * Infer layer boundary rules from the dependency graph.\n * If directory A never depends on directory B across the entire codebase,\n * then a new A→B dependency is a violation.\n */\nfunction inferLayerRules(\n depGraph: Map<string, Set<string>>,\n): Map<string, 'ok' | 'violation'> {\n const layerEdges = new Map<string, number>();\n const layerSet = new Set<string>();\n\n for (const [file, deps] of depGraph) {\n const fromLayer = getTopDir(file);\n layerSet.add(fromLayer);\n for (const dep of deps) {\n const toLayer = getTopDir(dep);\n if (fromLayer === toLayer) continue;\n layerSet.add(toLayer);\n const key = `${fromLayer}->${toLayer}`;\n layerEdges.set(key, (layerEdges.get(key) ?? 0) + 1);\n }\n }\n\n // An edge that appears only 1-2 times across the whole codebase\n // is likely a violation (anomalous cross-layer dep).\n // Edges that appear many times are established patterns.\n const rules = new Map<string, 'ok' | 'violation'>();\n for (const [edge, count] of layerEdges) {\n rules.set(edge, count <= 2 ? 'violation' : 'ok');\n }\n\n return rules;\n}\n\nfunction getTopDir(filePath: string): string {\n const parts = filePath.split('/');\n return parts[0] ?? filePath;\n}\n\nfunction isLikelyTypeOnlyDep(dep: string): boolean {\n return dep.includes('types') || dep.endsWith('.d.ts');\n}\n\nfunction isStructuralRole(basename: string): boolean {\n if (basename === 'index.ts' || basename === 'index.js') return true;\n if (basename === 'cli.ts' || basename === 'main.ts' || basename === 'main.rs') return true;\n if (basename.includes('worker.') || basename.includes('postinstall.')) return true;\n if (basename === 'health.ts' || basename === 'health.js') return true;\n return false;\n}\n","import type { ScipDatabase } from '../db.js';\nimport { testFileExclusionSql } from '../query-support.js';\nimport type { WrapperCandidate } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Find wrapper candidates: symbols called by only one other symbol.\n *\n * These are premature abstractions that add indirection without\n * providing reuse. A function with fan-in = 1 whose sole caller\n * is widely used is a strong signal of unnecessary wrapping.\n */\nexport function wrapperCandidates(\n db: ScipDatabase,\n opts?: { scope?: string; maxLoc?: number; limit?: number },\n): WrapperCandidate[] {\n const { scope, maxLoc = 15, limit = 30 } = opts ?? {};\n const scopeFilter = scope ? `AND d.relative_path LIKE '%${scope}%'` : '';\n\n // Find all symbols with exactly 1 cross-file consumer (fan-in = 1),\n // along with who that single caller is and the caller's own fan-in.\n const rows = db.all<{\n symbol: string;\n file: string;\n start_line: number;\n end_line: number;\n loc: number;\n caller_symbol: string;\n caller_fan_in: number;\n }>(\n `SELECT * FROM (\n SELECT\n gs.symbol,\n d.relative_path AS file,\n der.start_line,\n der.end_line,\n (der.end_line - der.start_line + 1) AS loc,\n -- The single caller: the symbol whose definition range contains\n -- the chunk that references our target\n (SELECT caller_gs.symbol\n FROM mentions ref_m\n JOIN chunks ref_c ON ref_m.chunk_id = ref_c.id\n JOIN defn_enclosing_ranges caller_der\n ON caller_der.document_id = ref_c.document_id\n AND ref_c.start_line >= caller_der.start_line\n AND ref_c.end_line <= caller_der.end_line\n JOIN global_symbols caller_gs ON caller_der.symbol_id = caller_gs.id\n WHERE ref_m.symbol_id = gs.id\n AND ref_m.role = 0\n AND ref_c.document_id != der.document_id\n LIMIT 1\n ) AS caller_symbol,\n -- Fan-in of that single caller\n (SELECT COUNT(DISTINCT caller_ref_c.document_id)\n FROM mentions caller_ref_m\n JOIN chunks caller_ref_c ON caller_ref_m.chunk_id = caller_ref_c.id\n WHERE caller_ref_m.symbol_id = (\n SELECT caller_der2.symbol_id\n FROM mentions ref_m2\n JOIN chunks ref_c2 ON ref_m2.chunk_id = ref_c2.id\n JOIN defn_enclosing_ranges caller_der2\n ON caller_der2.document_id = ref_c2.document_id\n AND ref_c2.start_line >= caller_der2.start_line\n AND ref_c2.end_line <= caller_der2.end_line\n WHERE ref_m2.symbol_id = gs.id\n AND ref_m2.role = 0\n AND ref_c2.document_id != der.document_id\n LIMIT 1\n )\n AND caller_ref_m.role = 0\n ) AS caller_fan_in\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE 1 = 1\n ${db.pathExclusionsFor('d')}\n AND ${testFileExclusionSql('d')}\n ${db.symbolNoiseFor('gs')}\n -- Only functions/terms, not type definitions (types with # are not wrappers)\n AND gs.symbol NOT LIKE '%#'\n AND (der.end_line - der.start_line + 1) <= ?\n AND (der.end_line - der.start_line + 1) >= 2\n ${scopeFilter}\n -- Exactly 1 cross-file consumer\n AND (\n SELECT COUNT(DISTINCT ref_c.document_id)\n FROM mentions ref_m\n JOIN chunks ref_c ON ref_m.chunk_id = ref_c.id\n WHERE ref_m.symbol_id = gs.id\n AND ref_m.role = 0\n AND ref_c.document_id != der.document_id\n ) = 1\n ) WHERE caller_symbol IS NOT NULL AND caller_fan_in > 3\n ORDER BY caller_fan_in DESC, loc DESC\n LIMIT ?`,\n maxLoc, limit,\n );\n\n return rows\n .filter((r) => !db.isIgnored(r.file))\n .map((r) => ({\n symbol: r.symbol,\n shortName: shortenSymbol(r.symbol),\n file: r.file,\n startLine: r.start_line,\n endLine: r.end_line,\n loc: r.loc,\n singleCaller: r.caller_symbol,\n singleCallerShort: shortenSymbol(r.caller_symbol),\n callerFanIn: r.caller_fan_in,\n }));\n}\n","import type { ScipDatabase } from '../db.js';\nimport { getCalleeRowsForSymbol, testFileExclusionSql } from '../query-support.js';\nimport type { PassthroughCandidate } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Find passthrough candidates: functions that just forward to one\n * other function.\n *\n * A function with exactly 1 callee and small LOC is likely a thin\n * wrapper that adds no value — it just passes arguments through to\n * the real implementation.\n */\nexport function passthroughCandidates(\n db: ScipDatabase,\n opts?: { scope?: string; maxLoc?: number; limit?: number },\n): PassthroughCandidate[] {\n const { scope, maxLoc = 15, limit = 30 } = opts ?? {};\n const scopeFilter = scope ? `AND d.relative_path LIKE '%${scope}%'` : '';\n\n // 1. Find all non-trivial symbols with definition ranges (>= 3 LOC)\n const symbols = db.all<{\n id: number;\n symbol: string;\n document_id: number;\n start_line: number;\n end_line: number;\n loc: number;\n relative_path: string;\n }>(\n `SELECT\n gs.id,\n gs.symbol,\n der.document_id,\n der.start_line,\n der.end_line,\n (der.end_line - der.start_line + 1) AS loc,\n d.relative_path\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE 1 = 1\n ${db.pathExclusionsFor('d')}\n AND ${testFileExclusionSql('d')}\n ${db.symbolNoiseFor('gs')}\n AND (der.end_line - der.start_line + 1) >= 3\n AND (der.end_line - der.start_line + 1) <= ?\n ${scopeFilter}\n ORDER BY d.relative_path`,\n maxLoc,\n );\n\n const results: PassthroughCandidate[] = [];\n\n for (const sym of symbols) {\n if (db.isIgnored(sym.relative_path)) continue;\n\n // 2. Count callees for this symbol\n const callees = getCalleeRowsForSymbol(db, {\n documentId: sym.document_id,\n startLine: sym.start_line,\n endLine: sym.end_line,\n symbolId: sym.id,\n });\n\n // Deduplicate by symbol (same callee may appear in multiple chunks)\n const uniqueCallees = new Map<string, { symbol: string; file: string }>();\n for (const c of callees) {\n if (!uniqueCallees.has(c.symbol)) {\n uniqueCallees.set(c.symbol, { symbol: c.symbol, file: c.file });\n }\n }\n\n // 3. Passthrough = exactly 1 unique callee\n if (uniqueCallees.size !== 1) continue;\n\n const [, callee] = [...uniqueCallees.entries()][0]!;\n\n results.push({\n symbol: sym.symbol,\n shortName: shortenSymbol(sym.symbol),\n file: sym.relative_path,\n startLine: sym.start_line,\n endLine: sym.end_line,\n loc: sym.loc,\n forwardsTo: callee.symbol,\n forwardsToShort: shortenSymbol(callee.symbol),\n forwardsToFile: callee.file,\n });\n }\n\n results.sort((a, b) => a.loc - b.loc || a.file.localeCompare(b.file));\n return results.slice(0, limit);\n}\n","import type { ScipDatabase } from '../db.js';\nimport { testFileExclusionSql } from '../query-support.js';\nimport type { StaleAbstraction } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Find stale abstractions: type-level symbols (classes, interfaces, type\n * aliases) that have 0 or 1 cross-file consumers.\n *\n * A type that only one file uses is over-abstracted — it was designed\n * for reuse that never materialized. Large single-consumer types are\n * the strongest signal of wasted abstraction.\n */\nexport function staleAbstractions(\n db: ScipDatabase,\n opts?: { scope?: string; minLoc?: number; limit?: number },\n): StaleAbstraction[] {\n const { scope, minLoc = 3, limit = 30 } = opts ?? {};\n const scopeFilter = scope ? `AND d.relative_path LIKE '%${scope}%'` : '';\n\n const rows = db.all<{\n symbol: string;\n file: string;\n start_line: number;\n end_line: number;\n loc: number;\n consumers: number;\n }>(\n `SELECT * FROM (\n SELECT\n gs.symbol,\n d.relative_path AS file,\n der.start_line,\n der.end_line,\n (der.end_line - der.start_line + 1) AS loc,\n (SELECT COUNT(DISTINCT ref_c.document_id)\n FROM mentions ref_m\n JOIN chunks ref_c ON ref_m.chunk_id = ref_c.id\n WHERE ref_m.symbol_id = gs.id\n AND ref_m.role = 0\n AND ref_c.document_id != der.document_id\n ) AS consumers\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE 1 = 1\n ${db.pathExclusionsFor('d')}\n AND ${testFileExclusionSql('d')}\n ${db.symbolNoiseFor('gs')}\n -- Top-level type symbols: ends with # but does not contain nested #\n AND gs.symbol LIKE '%#'\n AND gs.symbol NOT LIKE '%#%#%'\n AND (der.end_line - der.start_line + 1) >= ?\n ${scopeFilter}\n ) WHERE consumers <= 1\n ORDER BY loc DESC\n LIMIT ?`,\n minLoc, limit,\n );\n\n return rows\n .filter((r) => !db.isIgnored(r.file))\n // Exclude types defined in dedicated type files (types.ts, types/, etc.)\n // These are intentional public API types, not premature abstractions.\n .filter((r) => {\n const basename = r.file.split('/').pop() ?? '';\n const isTypeFile = basename.includes('types') || r.file.includes('/types/');\n // Types in type files with 1 consumer are normal API types — skip them.\n // Types in type files with 0 consumers are genuinely unused — keep them.\n if (isTypeFile && r.consumers > 0) return false;\n return true;\n })\n .map((r) => ({\n symbol: r.symbol,\n shortName: shortenSymbol(r.symbol),\n file: r.file,\n startLine: r.start_line,\n endLine: r.end_line,\n loc: r.loc,\n consumers: r.consumers,\n }));\n}\n","import type { ScipDatabase } from '../db.js';\nimport { testFileExclusionSql } from '../query-support.js';\nimport type { ComplexityHotspot } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Find complexity hotspots: symbols with a composite score based on\n * LOC, fan-in, fan-out, and callee count.\n *\n * Score = (loc / 50) * (fanIn / 5) * max(fanOut / 5, 1)\n *\n * High scores indicate symbols that are large, widely depended upon,\n * AND reach out to many other modules — the riskiest code to change.\n */\nexport function complexityHotspots(\n db: ScipDatabase,\n opts?: { scope?: string; minLoc?: number; limit?: number },\n): ComplexityHotspot[] {\n const { scope, minLoc = 10, limit = 30 } = opts ?? {};\n const scopeFilter = scope ? `AND d.relative_path LIKE '%${scope}%'` : '';\n\n const rows = db.all<{\n symbol: string;\n file: string;\n start_line: number;\n end_line: number;\n loc: number;\n fan_in: number;\n fan_out: number;\n callee_count: number;\n }>(\n `SELECT\n gs.symbol,\n d.relative_path AS file,\n der.start_line,\n der.end_line,\n (der.end_line - der.start_line + 1) AS loc,\n -- fanIn: distinct files that reference this symbol\n (SELECT COUNT(DISTINCT ref_c.document_id)\n FROM mentions ref_m\n JOIN chunks ref_c ON ref_m.chunk_id = ref_c.id\n WHERE ref_m.symbol_id = gs.id AND ref_m.role = 0\n ) AS fan_in,\n -- fanOut: distinct symbols referenced within this definition range\n -- that are defined in different files\n (SELECT COUNT(DISTINCT out_gs.id)\n FROM mentions out_m\n JOIN chunks out_c ON out_m.chunk_id = out_c.id\n JOIN global_symbols out_gs ON out_m.symbol_id = out_gs.id\n JOIN defn_enclosing_ranges out_der ON out_gs.id = out_der.symbol_id\n WHERE out_c.document_id = der.document_id\n AND out_c.start_line >= der.start_line\n AND out_c.end_line <= der.end_line\n AND out_m.role = 0\n AND out_gs.id != gs.id\n AND out_der.document_id != der.document_id\n ) AS fan_out,\n -- calleeCount: total distinct callees within definition range\n (SELECT COUNT(DISTINCT callee_gs.id)\n FROM mentions callee_m\n JOIN chunks callee_c ON callee_m.chunk_id = callee_c.id\n JOIN global_symbols callee_gs ON callee_m.symbol_id = callee_gs.id\n WHERE callee_c.document_id = der.document_id\n AND callee_c.start_line >= der.start_line\n AND callee_c.end_line <= der.end_line\n AND callee_m.role = 0\n AND callee_gs.id != gs.id\n ) AS callee_count\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE 1 = 1\n ${db.pathExclusionsFor('d')}\n AND ${testFileExclusionSql('d')}\n ${db.symbolNoiseFor('gs')}\n AND (der.end_line - der.start_line + 1) >= ?\n ${scopeFilter}\n ORDER BY (\n CAST((der.end_line - der.start_line + 1) AS REAL) / 50.0\n * CAST((SELECT COUNT(DISTINCT ref_c2.document_id)\n FROM mentions ref_m2\n JOIN chunks ref_c2 ON ref_m2.chunk_id = ref_c2.id\n WHERE ref_m2.symbol_id = gs.id AND ref_m2.role = 0\n ) AS REAL) / 5.0\n * MAX(CAST((SELECT COUNT(DISTINCT out_gs2.id)\n FROM mentions out_m2\n JOIN chunks out_c2 ON out_m2.chunk_id = out_c2.id\n JOIN global_symbols out_gs2 ON out_m2.symbol_id = out_gs2.id\n JOIN defn_enclosing_ranges out_der2 ON out_gs2.id = out_der2.symbol_id\n WHERE out_c2.document_id = der.document_id\n AND out_c2.start_line >= der.start_line\n AND out_c2.end_line <= der.end_line\n AND out_m2.role = 0\n AND out_gs2.id != gs.id\n AND out_der2.document_id != der.document_id\n ) AS REAL) / 5.0, 1.0)\n ) DESC\n LIMIT ?`,\n minLoc, limit,\n );\n\n return rows\n .filter((r) => !db.isIgnored(r.file))\n .map((r) => ({\n symbol: r.symbol,\n shortName: shortenSymbol(r.symbol),\n file: r.file,\n startLine: r.start_line,\n endLine: r.end_line,\n loc: r.loc,\n fanIn: r.fan_in,\n fanOut: r.fan_out,\n calleeCount: r.callee_count,\n score:\n Math.round(\n (r.loc / 50) * (r.fan_in / 5) * Math.max(r.fan_out / 5, 1) * 100,\n ) / 100,\n }));\n}\n","import type { ScipDatabase } from '../db.js';\nimport { dead } from './dead.js';\nimport { isolated } from './isolated.js';\nimport { cycles } from './cycles.js';\nimport { similarAll } from './similar.js';\nimport { extractCandidates } from './extract-candidates.js';\nimport { wrapperCandidates } from './wrapper-candidates.js';\nimport { passthroughCandidates } from './passthrough-candidates.js';\nimport { staleAbstractions } from './stale-abstractions.js';\nimport { drift } from './drift.js';\nimport { complexityHotspots } from './complexity-hotspots.js';\nimport { testCoverageSummary } from './test-coverage.js';\nimport { stats } from './stats.js';\nimport type { HealthAction, HealthReport } from '../types.js';\n\n/**\n * Single composite health report that runs all de-bloat analyses\n * and produces a prioritized action list.\n *\n * The scoring formula accounts for common false positives:\n * - Entry points (CLI, workers, barrels) appearing as \"dead code\"\n * - Typed result interfaces with 1 consumer (normal for APIs)\n * - Consistent import patterns across sibling modules (not duplication)\n * - Barrel and orchestrator files deviating from sibling patterns (expected)\n */\nexport function health(\n db: ScipDatabase,\n opts: { scope?: string } = {},\n): HealthReport {\n const { scope } = opts;\n\n // Run all analyses\n const s = stats(db);\n const deadResult = dead(db, { scope, minLoc: 3, skipBarrels: false });\n const isolatedResult = isolated(db, { scope, minLoc: 3 });\n const cycleResult = cycles(db, { scope });\n const similarResult = similarAll(db, { scope, minSimilarity: 0.6, limit: 50, minCallees: 4 });\n const extractResult = extractCandidates(db, { scope, minLoc: 15, minCallees: 5, limit: 50 });\n const wrapperResult = wrapperCandidates(db, { scope, maxLoc: 15, limit: 50 });\n const passthroughResult = passthroughCandidates(db, { scope, maxLoc: 15, limit: 50 });\n const staleResult = staleAbstractions(db, { scope, minLoc: 3, limit: 50 });\n const driftResult = drift(db, { scope });\n const complexResult = complexityHotspots(db, { scope, minLoc: 10, limit: 10 });\n const testResult = testCoverageSummary(db, { scope, minLoc: 3 });\n\n const isolatedLoc = isolatedResult.reduce((sum, r) => sum + r.loc, 0);\n\n // ── False-positive filtering ─────────────────────────────\n\n // Entry points and barrels appear as dead/isolated because nothing imports them.\n // Filter them out of the scoring (but still report them with a note).\n const entryPointPatterns = ['/index.ts', '/index.js', 'cli.ts', 'worker.ts', 'postinstall.ts', '/mod.rs', '__init__.py', 'main.ts', 'main.rs', 'main.go', 'main.py'];\n const isEntryPoint = (path: string) => entryPointPatterns.some((p) => path.endsWith(p));\n\n // Dead code: only count truly dead symbols (zero refs anywhere),\n // excluding entry points AND file-internal helpers (which are fine).\n const trueDeadSymbols = deadResult.symbols.filter(\n (s) => !isEntryPoint(s.relativePath) && s.kind === 'dead-code',\n );\n const trueDeadCount = trueDeadSymbols.length;\n const trueDeadLoc = trueDeadSymbols.reduce((sum, s) => sum + s.loc, 0);\n const fileInternalCount = deadResult.symbols.filter(\n (s) => !isEntryPoint(s.relativePath) && s.kind === 'file-internal',\n ).length;\n\n // Isolated: same entry-point filtering\n const trueIsolatedCount = isolatedResult.filter(\n (s) => !isEntryPoint(s.relativePath),\n ).length;\n\n // Stale abstractions: the command filters out types.ts single-consumer types.\n // Also filter out 0-consumer types in files that export functions — these are\n // likely parameter/return types consumed through function signatures, which\n // the SCIP index can't track as direct mentions.\n const filesWithFunctions = new Set(\n db.all<{ relative_path: string }>(\n `SELECT DISTINCT d.relative_path\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE gs.symbol LIKE '%().'\n ${db.pathExclusionsFor('d')}`,\n ).map((r) => r.relative_path),\n );\n const trueStaleCount = staleResult.filter((s) => {\n // 0-consumer types in files with functions are likely param/return types\n if (s.consumers === 0 && filesWithFunctions.has(s.file)) return false;\n return true;\n }).length;\n\n // Drift: now uses usage-based detection (unused imports, layer violations, pattern deviations)\n // The drift command already filters structural roles internally.\n const trueDriftCount = driftResult.results.length;\n\n // Similar pairs: the similar command now uses TF-IDF weighted cosine\n // similarity which automatically discounts infrastructure callees.\n // The sharedCallees list only contains significant (above-median IDF) callees.\n // We can trust the count directly.\n const trueSimilarCount = similarResult.length;\n\n // ── Build prioritized action list ────────────────────────\n\n const actions: HealthAction[] = [];\n\n if (trueDeadCount > 0) {\n actions.push({\n category: 'Dead code',\n description: `${trueDeadCount} symbols with zero references anywhere — safe to delete`,\n effort: 'low',\n impact: 'high',\n count: trueDeadCount,\n locRecoverable: trueDeadLoc,\n });\n }\n\n if (testResult.percent < 50) {\n actions.push({\n category: 'Test coverage',\n description: `${testResult.percent}% of symbols referenced by tests (${testResult.uncovered} uncovered)`,\n effort: 'high',\n impact: 'high',\n count: testResult.uncovered,\n locRecoverable: 0,\n });\n }\n\n if (trueIsolatedCount > 0) {\n actions.push({\n category: 'Isolated symbols',\n description: `${trueIsolatedCount} symbols completely disconnected from the codebase graph`,\n effort: 'low',\n impact: 'medium',\n count: trueIsolatedCount,\n locRecoverable: isolatedResult\n .filter((s) => !isEntryPoint(s.relativePath))\n .reduce((sum, s) => sum + s.loc, 0),\n });\n }\n\n if (cycleResult.length > 0) {\n actions.push({\n category: 'Circular dependencies',\n description: `${cycleResult.length} cycle(s) — break with dependency inversion or module restructuring`,\n effort: 'medium',\n impact: 'high',\n count: cycleResult.length,\n locRecoverable: 0,\n });\n }\n\n if (trueSimilarCount > 0) {\n actions.push({\n category: 'Similar functions',\n description: `${trueSimilarCount} pairs with real logic overlap (beyond shared imports) — consolidation candidates`,\n effort: 'medium',\n impact: 'medium',\n count: trueSimilarCount,\n locRecoverable: 0,\n });\n }\n\n if (extractResult.length > 0) {\n actions.push({\n category: 'Extraction candidates',\n description: `${extractResult.length} large functions with isolated callee clusters — extract method opportunities`,\n effort: 'medium',\n impact: 'medium',\n count: extractResult.length,\n locRecoverable: 0,\n });\n }\n\n if (wrapperResult.length > 0) {\n actions.push({\n category: 'Wrapper functions',\n description: `${wrapperResult.length} single-consumer symbols that could be inlined`,\n effort: 'low',\n impact: 'low',\n count: wrapperResult.length,\n locRecoverable: wrapperResult.reduce((sum, r) => sum + r.loc, 0),\n });\n }\n\n if (passthroughResult.length > 0) {\n actions.push({\n category: 'Passthrough functions',\n description: `${passthroughResult.length} functions that just forward to one callee — unnecessary indirection`,\n effort: 'low',\n impact: 'low',\n count: passthroughResult.length,\n locRecoverable: passthroughResult.reduce((sum, r) => sum + r.loc, 0),\n });\n }\n\n if (trueStaleCount > 0) {\n // Count from the filtered set, not the raw result\n const trueStaleSymbols = staleResult.filter((s) => {\n if (s.consumers === 0 && filesWithFunctions.has(s.file)) return false;\n return true;\n });\n const unused = trueStaleSymbols.filter((s) => s.consumers === 0).length;\n const singleUse = trueStaleCount - unused;\n const parts: string[] = [];\n if (unused > 0) parts.push(`${unused} unused`);\n if (singleUse > 0) parts.push(`${singleUse} single-consumer (not in types file)`);\n actions.push({\n category: 'Stale abstractions',\n description: `${parts.join(', ')} — premature abstraction`,\n effort: 'low',\n impact: 'medium',\n count: trueStaleCount,\n locRecoverable: staleResult\n .filter((s) => s.consumers === 0 || !s.file.includes('types'))\n .reduce((sum, r) => sum + r.loc, 0),\n });\n }\n\n if (trueDriftCount > 0) {\n const parts: string[] = [];\n if (driftResult.unusedImports > 0) parts.push(`${driftResult.unusedImports} unused imports`);\n if (driftResult.layerViolations > 0) parts.push(`${driftResult.layerViolations} layer violations`);\n if (driftResult.patternDeviations > 0) parts.push(`${driftResult.patternDeviations} unique deps`);\n actions.push({\n category: 'Structural drift',\n description: parts.join(', '),\n effort: driftResult.layerViolations > 0 ? 'medium' : 'low',\n impact: driftResult.layerViolations > 0 ? 'medium' : 'low',\n count: trueDriftCount,\n locRecoverable: 0,\n });\n }\n\n // Sort: high impact + low effort first\n const impactWeight = { high: 3, medium: 2, low: 1 };\n const effortWeight = { low: 3, medium: 2, high: 1 };\n actions.sort((a, b) => {\n const scoreA = impactWeight[a.impact] * effortWeight[a.effort];\n const scoreB = impactWeight[b.impact] * effortWeight[b.effort];\n return scoreB - scoreA;\n });\n\n // ── Compute health score (0-100) ─────────────────────────\n //\n // Uses filtered counts (false positives removed).\n // Deductions scale with codebase size so a 10-file project\n // and a 1000-file project aren't penalized the same way.\n const fileCount = Math.max(s.documents, 1);\n const symbolCount = Math.max(s.symbols, 1);\n\n let score = 100;\n\n // Dead code: deduct based on % of symbols that are dead, not raw count\n const deadPercent = trueDeadCount / symbolCount;\n score -= Math.min(20, Math.round(deadPercent * 200));\n\n // Isolated: same percentage-based\n const isolatedPercent = trueIsolatedCount / symbolCount;\n score -= Math.min(10, Math.round(isolatedPercent * 200));\n\n // Cycles: these are always bad, flat penalty\n score -= Math.min(15, cycleResult.length * 5);\n\n // Similar pairs: only count true logic overlap, not boilerplate\n score -= Math.min(10, trueSimilarCount * 2);\n\n // Extract candidates: mild penalty\n score -= Math.min(5, extractResult.length * 2);\n\n // Wrappers: mild\n score -= Math.min(3, wrapperResult.length);\n\n // Passthroughs: mild\n score -= Math.min(3, passthroughResult.length);\n\n // Stale abstractions: percentage-based with filtered count\n const stalePercent = trueStaleCount / Math.max(symbolCount * 0.1, 1);\n score -= Math.min(8, Math.round(stalePercent * 10));\n\n // Drift: percentage of files that deviate\n const driftPercent = trueDriftCount / fileCount;\n score -= Math.min(5, Math.round(driftPercent * 50));\n\n // Complexity: only penalize extreme outliers\n const extremeComplexity = complexResult.filter((r) => r.score > 50).length;\n score -= Math.min(5, extremeComplexity * 2);\n\n // Test coverage: significant penalty for low coverage\n // 0% = -15, 25% = -11, 50% = -7, 75% = -4, 100% = 0\n const coverageDeduction = Math.round(15 * (1 - testResult.percent / 100));\n score -= coverageDeduction;\n\n score = Math.max(0, Math.min(100, score));\n\n return {\n score,\n overview: {\n documents: s.documents,\n symbols: s.symbols,\n indexSizeBytes: s.indexSizeBytes,\n },\n findings: {\n deadSymbols: trueDeadCount,\n deadLoc: trueDeadLoc,\n isolatedSymbols: trueIsolatedCount,\n isolatedLoc: isolatedResult\n .filter((s) => !isEntryPoint(s.relativePath))\n .reduce((sum, s) => sum + s.loc, 0),\n cycles: cycleResult.length,\n similarPairs: trueSimilarCount,\n extractionCandidates: extractResult.length,\n wrappers: wrapperResult.length,\n passthroughs: passthroughResult.length,\n staleTypes: trueStaleCount,\n driftedFiles: trueDriftCount,\n complexityHotspotCount: complexResult.length,\n testCoveragePercent: testResult.percent,\n },\n actions,\n topComplexity: complexResult.slice(0, 5).map((r) => ({\n symbol: r.shortName,\n score: r.score,\n })),\n };\n}\n","import type { ScipDatabase } from '../db.js';\nimport { findFirstSymbolMatch, getCalleeRowsForSymbol } from '../query-support.js';\nimport type { ConvergenceResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Given two similar symbols, show what a consolidated version would look like.\n * The shared callee set becomes the common body. The unique callees become\n * the parameterization points.\n */\nexport function convergence(\n db: ScipDatabase,\n symbolPatternA: string,\n symbolPatternB: string,\n): ConvergenceResult | null {\n const matchA = findFirstSymbolMatch(db, symbolPatternA);\n const matchB = findFirstSymbolMatch(db, symbolPatternB);\n\n if (!matchA || !matchB) return null;\n\n const calleesA = new Set(\n getCalleeRowsForSymbol(db, matchA).map((r) => r.symbol),\n );\n const calleesB = new Set(\n getCalleeRowsForSymbol(db, matchB).map((r) => r.symbol),\n );\n\n const shared: string[] = [];\n for (const c of calleesA) {\n if (calleesB.has(c)) shared.push(c);\n }\n\n const uniqueA: string[] = [];\n for (const c of calleesA) {\n if (!calleesB.has(c)) uniqueA.push(c);\n }\n\n const uniqueB: string[] = [];\n for (const c of calleesB) {\n if (!calleesA.has(c)) uniqueB.push(c);\n }\n\n const union = new Set([...calleesA, ...calleesB]);\n const similarity = union.size > 0 ? shared.length / union.size : 0;\n\n // Generate a consolidation strategy description\n let strategy: string;\n if (uniqueA.length === 0 && uniqueB.length === 0) {\n strategy = 'These functions have identical callee sets. One can replace the other directly.';\n } else if (uniqueA.length === 0) {\n strategy = `A is a subset of B. A can be replaced by calling B (B does everything A does plus more).`;\n } else if (uniqueB.length === 0) {\n strategy = `B is a subset of A. B can be replaced by calling A (A does everything B does plus more).`;\n } else if (uniqueA.length <= 2 && uniqueB.length <= 2) {\n strategy = `Create a shared function with the ${shared.length} common callees. Pass the ${uniqueA.length + uniqueB.length} divergent callees as parameters or strategy callbacks.`;\n } else {\n strategy = `Extract the ${shared.length} shared callees into a common helper. Each function calls the helper plus its own unique logic (${uniqueA.length} callees in A, ${uniqueB.length} in B).`;\n }\n\n const locA = matchA.endLine - matchA.startLine + 1;\n const locB = matchB.endLine - matchB.startLine + 1;\n\n return {\n symbolA: {\n symbol: matchA.symbol,\n shortName: shortenSymbol(matchA.symbol),\n file: matchA.relativePath,\n loc: locA,\n },\n symbolB: {\n symbol: matchB.symbol,\n shortName: shortenSymbol(matchB.symbol),\n file: matchB.relativePath,\n loc: locB,\n },\n similarity,\n sharedCallees: shared.map(shortenSymbol),\n uniqueToA: uniqueA.map(shortenSymbol),\n uniqueToB: uniqueB.map(shortenSymbol),\n consolidationStrategy: strategy,\n };\n}\n","import { readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { ScipDatabase } from '../db.js';\nimport { findFirstSymbolMatch } from '../query-support.js';\nimport type { CodeResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Read the source code for a symbol, bounded to its definition range.\n * Language-agnostic: just reads the file and extracts the relevant lines.\n *\n * Accepts:\n * - Symbol name pattern: \"processVegaMention\"\n * - Full short name: \"src:modules:chat:processVegaMention\"\n * - File:line-line syntax: \"src/chat/service.ts:100-200\"\n */\nexport function code(\n db: ScipDatabase,\n symbolPattern: string,\n opts: { context?: number } = {},\n): CodeResult | null {\n const { context = 0 } = opts;\n\n // Handle direct file:line-line syntax (bypass symbol lookup)\n const fileLineMatch = symbolPattern.match(/^(.+\\.\\w+):(\\d+)-(\\d+)$/);\n if (fileLineMatch) {\n return readFileRange(db, fileLineMatch[1]!, parseInt(fileLineMatch[2]!, 10), parseInt(fileLineMatch[3]!, 10), context);\n }\n\n const match = findFirstSymbolMatch(db, symbolPattern);\n if (!match) return null;\n\n // Get the language from the documents table\n const doc = db.get<{ language: string | null }>(\n `SELECT language FROM documents WHERE relative_path = ?`,\n match.relativePath,\n );\n\n // Read the file\n const filePath = join(db.config.projectRoot, match.relativePath);\n let fileContent: string;\n try {\n fileContent = readFileSync(filePath, 'utf-8');\n } catch {\n return null;\n }\n\n const lines = fileContent.split('\\n');\n const startLine = Math.max(0, match.startLine - context);\n const endLine = Math.min(lines.length - 1, match.endLine + context);\n const source = lines.slice(startLine, endLine + 1).join('\\n');\n\n return {\n symbol: match.symbol,\n shortName: shortenSymbol(match.symbol),\n relativePath: match.relativePath,\n startLine: startLine + 1, // 1-indexed for display\n endLine: endLine + 1,\n language: doc?.language ?? null,\n source,\n };\n}\n\n/** Read source by file path and line range directly (no symbol lookup) */\nfunction readFileRange(\n db: ScipDatabase,\n filePath: string,\n startLine: number,\n endLine: number,\n context: number,\n): CodeResult | null {\n // Find the file in the index\n const doc = db.get<{ relative_path: string; language: string | null }>(\n `SELECT relative_path, language FROM documents WHERE relative_path LIKE ?`,\n `%${filePath}%`,\n );\n if (!doc) return null;\n\n const fullPath = join(db.config.projectRoot, doc.relative_path);\n let fileContent: string;\n try {\n fileContent = readFileSync(fullPath, 'utf-8');\n } catch {\n return null;\n }\n\n const lines = fileContent.split('\\n');\n const start = Math.max(0, startLine - 1 - context); // convert to 0-indexed\n const end = Math.min(lines.length - 1, endLine - 1 + context);\n const source = lines.slice(start, end + 1).join('\\n');\n\n return {\n symbol: `${doc.relative_path}:${startLine}-${endLine}`,\n shortName: `${doc.relative_path}:${startLine}-${endLine}`,\n relativePath: doc.relative_path,\n startLine: start + 1,\n endLine: end + 1,\n language: doc.language,\n source,\n };\n}\n","import { readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { ScipDatabase } from '../db.js';\nimport { findFirstSymbolMatch, getCalleeRowsForSymbol } from '../query-support.js';\nimport type { ComplexityResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Per-symbol complexity analysis combining source-level branch counting\n * with index-level metrics (fan-in, fan-out, callee count).\n *\n * Branch counting uses language-aware regex. The language is read from\n * the SCIP documents table, so it works for any indexed language.\n */\nexport function complexity(\n db: ScipDatabase,\n symbolPattern: string,\n): ComplexityResult | null {\n const match = findFirstSymbolMatch(db, symbolPattern);\n if (!match) return null;\n\n // Get language\n const doc = db.get<{ language: string | null }>(\n `SELECT language FROM documents WHERE relative_path = ?`,\n match.relativePath,\n );\n const language = doc?.language ?? 'unknown';\n\n // Read source for branch counting\n const filePath = join(db.config.projectRoot, match.relativePath);\n let source = '';\n try {\n const lines = readFileSync(filePath, 'utf-8').split('\\n');\n source = lines.slice(match.startLine, match.endLine + 1).join('\\n');\n } catch {\n // If we can't read the file, just skip branch counting\n }\n\n const branches = countBranches(source, language);\n const loc = match.endLine - match.startLine + 1;\n\n // Callee count\n const callees = getCalleeRowsForSymbol(db, match);\n const uniqueCallees = new Set(callees.map((c) => c.symbol));\n\n // Fan-in\n const fanInRow = db.get<{ c: number }>(\n `SELECT COUNT(DISTINCT c.document_id) AS c\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n WHERE m.symbol_id = ? AND m.role = 0`,\n match.symbolId,\n );\n\n // Fan-out (callees in other files)\n const fanOut = new Set(\n callees.filter((c) => c.file !== match.relativePath).map((c) => c.symbol),\n ).size;\n\n return {\n symbol: match.symbol,\n shortName: shortenSymbol(match.symbol),\n relativePath: match.relativePath,\n startLine: match.startLine,\n endLine: match.endLine,\n loc,\n branches,\n cyclomaticEstimate: branches + 1,\n calleeCount: uniqueCallees.size,\n fanIn: fanInRow?.c ?? 0,\n fanOut,\n };\n}\n\n/**\n * Count branch points in source code using language-aware regex.\n * Works across all SCIP-supported languages.\n */\nfunction countBranches(source: string, language: string): number {\n // Strip comments and strings to avoid false positives\n const stripped = stripCommentsAndStrings(source);\n let count = 0;\n\n // Universal branch keywords (work across most C-family languages)\n const universalPatterns = [\n /\\bif\\b/g,\n /\\belse\\s+if\\b/g,\n /\\belse\\b/g,\n /\\bfor\\b/g,\n /\\bwhile\\b/g,\n /\\bswitch\\b/g,\n /\\bcase\\b/g,\n /\\bcatch\\b/g,\n /\\?\\s*[^?]/g, // ternary (but not ??)\n /&&/g,\n /\\|\\|/g,\n ];\n\n for (const pattern of universalPatterns) {\n const matches = stripped.match(pattern);\n if (matches) count += matches.length;\n }\n\n // Language-specific patterns\n if (language === 'python') {\n const pyPatterns = [/\\belif\\b/g, /\\bexcept\\b/g, /\\bfinally\\b/g];\n for (const p of pyPatterns) {\n const m = stripped.match(p);\n if (m) count += m.length;\n }\n } else if (language === 'rust') {\n const rustPatterns = [/\\bmatch\\b/g, /=>/g, /\\bloop\\b/g];\n for (const p of rustPatterns) {\n const m = stripped.match(p);\n if (m) count += m.length;\n }\n } else if (language === 'ruby') {\n const rubyPatterns = [/\\belsif\\b/g, /\\bunless\\b/g, /\\brescue\\b/g, /\\bwhen\\b/g];\n for (const p of rubyPatterns) {\n const m = stripped.match(p);\n if (m) count += m.length;\n }\n } else if (language === 'go') {\n const goPatterns = [/\\bselect\\b/g, /\\bdefer\\b/g];\n for (const p of goPatterns) {\n const m = stripped.match(p);\n if (m) count += m.length;\n }\n }\n\n return count;\n}\n\n/**\n * Rough strip of comments and string literals to reduce false positives\n * in branch counting. Not perfect but good enough for estimation.\n */\nfunction stripCommentsAndStrings(source: string): string {\n return source\n // Block comments\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n // Line comments\n .replace(/\\/\\/.*/g, '')\n // Python/Ruby line comments\n .replace(/#.*/g, '')\n // Double-quoted strings\n .replace(/\"(?:[^\"\\\\]|\\\\.)*\"/g, '\"\"')\n // Single-quoted strings\n .replace(/'(?:[^'\\\\]|\\\\.)*'/g, \"''\")\n // Template literals\n .replace(/`(?:[^`\\\\]|\\\\.)*`/g, '``');\n}\n","import type { ScipDatabase } from '../db.js';\nimport { findFirstSymbolMatch } from '../query-support.js';\nimport type { DataflowResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Reference-level dataflow analysis: where does data around this symbol\n * come from and where does it go?\n *\n * This is not value-level dataflow (we can't trace x = foo(); bar(x);\n * as a chain). Instead it shows:\n * - Where the symbol is defined and used\n * - What other symbols appear in the same enclosing scope (co-occurring data)\n * - What feeds into the function that defines it (producers)\n * - What consumes the function that uses it (consumers)\n *\n * Language-agnostic: works with any SCIP index.\n */\nexport function dataflow(\n db: ScipDatabase,\n symbolPattern: string,\n): DataflowResult | null {\n const match = findFirstSymbolMatch(db, symbolPattern);\n if (!match) return null;\n\n // Definition sites (role=1)\n const defSites = db.all<{ file: string; line: number }>(\n `SELECT d.relative_path AS file, c.start_line AS line\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d ON c.document_id = d.id\n WHERE m.symbol_id = ? AND m.role = 1\n ORDER BY d.relative_path, c.start_line`,\n match.symbolId,\n );\n\n // Usage sites (role=0) with enclosing symbol\n const usageSites = db.all<{\n file: string;\n line: number;\n enclosing_symbol: string | null;\n }>(\n `SELECT d.relative_path AS file, c.start_line AS line,\n (SELECT enc_gs.symbol\n FROM defn_enclosing_ranges enc_der\n JOIN global_symbols enc_gs ON enc_der.symbol_id = enc_gs.id\n WHERE enc_der.document_id = d.id\n AND enc_der.start_line <= c.start_line\n AND enc_der.end_line >= c.end_line\n ORDER BY (enc_der.end_line - enc_der.start_line) ASC\n LIMIT 1\n ) AS enclosing_symbol\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d ON c.document_id = d.id\n WHERE m.symbol_id = ? AND m.role = 0\n ${db.pathExclusionsFor('d')}\n ORDER BY d.relative_path, c.start_line`,\n match.symbolId,\n );\n\n // Producers: other symbols referenced within the same function that defines our target\n const producers = db.all<{ symbol: string; file: string }>(\n `SELECT DISTINCT other_gs.symbol, other_d.relative_path AS file\n FROM mentions other_m\n JOIN chunks other_c ON other_m.chunk_id = other_c.id\n JOIN global_symbols other_gs ON other_m.symbol_id = other_gs.id\n JOIN defn_enclosing_ranges other_der ON other_gs.id = other_der.symbol_id\n JOIN documents other_d ON other_der.document_id = other_d.id\n WHERE other_c.document_id = ?\n AND other_c.start_line >= ? AND other_c.end_line <= ?\n AND other_m.role = 0\n AND other_gs.id != ?\n ${db.symbolNoiseFor('other_gs')}\n ${db.pathExclusionsFor('other_d')}\n ORDER BY other_d.relative_path\n LIMIT 30`,\n match.documentId, match.startLine, match.endLine, match.symbolId,\n );\n\n // Consumers: symbols exported/defined by functions that reference our target\n // (what does the data flow into after being used)\n const consumers = db.all<{ symbol: string; file: string }>(\n `SELECT DISTINCT consumer_gs.symbol, consumer_d.relative_path AS file\n FROM mentions ref_m\n JOIN chunks ref_c ON ref_m.chunk_id = ref_c.id\n JOIN documents ref_d ON ref_c.document_id = ref_d.id\n -- Find the enclosing function at each usage site\n JOIN defn_enclosing_ranges enc_der\n ON enc_der.document_id = ref_d.id\n AND enc_der.start_line <= ref_c.start_line\n AND enc_der.end_line >= ref_c.end_line\n JOIN global_symbols enc_gs ON enc_der.symbol_id = enc_gs.id\n -- Find other symbols defined by that enclosing function's file\n JOIN mentions consumer_m ON consumer_m.symbol_id = enc_gs.id AND consumer_m.role = 0\n JOIN chunks consumer_c ON consumer_m.chunk_id = consumer_c.id\n JOIN documents consumer_d ON consumer_c.document_id = consumer_d.id\n JOIN global_symbols consumer_gs ON consumer_m.symbol_id = consumer_gs.id\n WHERE ref_m.symbol_id = ? AND ref_m.role = 0\n AND consumer_d.id != ref_d.id\n ${db.symbolNoiseFor('consumer_gs')}\n ${db.pathExclusionsFor('consumer_d')}\n ORDER BY consumer_d.relative_path\n LIMIT 30`,\n match.symbolId,\n );\n\n return {\n symbol: match.symbol,\n shortName: shortenSymbol(match.symbol),\n relativePath: match.relativePath,\n definitionSites: defSites.filter((s) => !db.isIgnored(s.file)),\n usageSites: usageSites\n .filter((s) => !db.isIgnored(s.file))\n .map((s) => ({\n file: s.file,\n line: s.line,\n enclosingSymbol: s.enclosing_symbol ?? '(top-level)',\n enclosingShort: s.enclosing_symbol ? shortenSymbol(s.enclosing_symbol) : '(top-level)',\n })),\n producers: producers\n .filter((p) => !db.isIgnored(p.file))\n .map((p) => ({ symbol: p.symbol, shortName: shortenSymbol(p.symbol), file: p.file })),\n consumers: consumers\n .filter((c) => !db.isIgnored(c.file))\n .map((c) => ({ symbol: c.symbol, shortName: shortenSymbol(c.symbol), file: c.file })),\n };\n}\n","import type { ScipDatabase } from '../db.js';\nimport { findFirstSymbolMatch, getCalleeRowsForSymbol, type SymbolMatch } from '../query-support.js';\nimport type { SliceResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Reference-level program slicing: track what affects a symbol (backward)\n * or what a symbol affects (forward).\n *\n * Backward slice: \"What feeds into this?\" — symbols referenced in the same\n * function that defines the target. These are the inputs/dependencies.\n *\n * Forward slice: \"What does this feed into?\" — at each site where the target\n * is referenced, find the enclosing function, then find what that function\n * exports/defines. These are the outputs/consumers.\n *\n * Language-agnostic: works with any SCIP index.\n */\nexport function slice(\n db: ScipDatabase,\n symbolPattern: string,\n opts: { direction?: 'backward' | 'forward' } = {},\n): SliceResult | null {\n const { direction = 'backward' } = opts;\n\n const match = findFirstSymbolMatch(db, symbolPattern);\n if (!match) return null;\n\n if (direction === 'backward') {\n return backwardSlice(db, match);\n } else {\n return forwardSlice(db, match);\n }\n}\n\n\nfunction backwardSlice(db: ScipDatabase, match: SymbolMatch): SliceResult {\n // Find all symbols referenced within the definition range of the target.\n // These are what \"feeds into\" the target — the inputs.\n const callees = getCalleeRowsForSymbol(db, match);\n\n // Also find symbols whose definitions are in the same file and whose\n // ranges overlap or precede the target — local variables, parameters, etc.\n const localPredecessors = db.all<{ symbol: string; file: string }>(\n `SELECT DISTINCT gs.symbol, d.relative_path AS file\n FROM defn_enclosing_ranges der\n JOIN global_symbols gs ON der.symbol_id = gs.id\n JOIN documents d ON der.document_id = d.id\n WHERE der.document_id = ?\n AND der.end_line < ?\n AND gs.id != ?\n ${db.symbolNoiseFor('gs')}\n ORDER BY der.start_line DESC\n LIMIT 15`,\n match.documentId, match.startLine, match.symbolId,\n );\n\n const seen = new Set<string>();\n const connected: SliceResult['connectedSymbols'] = [];\n\n for (const c of callees) {\n if (seen.has(c.symbol)) continue;\n seen.add(c.symbol);\n connected.push({\n symbol: c.symbol,\n shortName: shortenSymbol(c.symbol),\n file: c.file,\n relationship: 'referenced within definition (callee)',\n });\n }\n\n for (const p of localPredecessors) {\n if (seen.has(p.symbol) || db.isIgnored(p.file)) continue;\n seen.add(p.symbol);\n connected.push({\n symbol: p.symbol,\n shortName: shortenSymbol(p.symbol),\n file: p.file,\n relationship: 'defined before target in same file (local predecessor)',\n });\n }\n\n return {\n symbol: match.symbol,\n shortName: shortenSymbol(match.symbol),\n direction: 'backward',\n connectedSymbols: connected,\n };\n}\n\nfunction forwardSlice(db: ScipDatabase, match: SymbolMatch): SliceResult {\n // Find where the target is referenced, then at each reference site,\n // find what else the enclosing function defines/exports.\n const rows = db.all<{\n enclosing_symbol: string;\n enclosing_file: string;\n output_symbol: string;\n output_file: string;\n }>(\n `SELECT DISTINCT\n enc_gs.symbol AS enclosing_symbol,\n enc_d.relative_path AS enclosing_file,\n out_gs.symbol AS output_symbol,\n out_d.relative_path AS output_file\n FROM mentions ref_m\n JOIN chunks ref_c ON ref_m.chunk_id = ref_c.id\n JOIN documents ref_d ON ref_c.document_id = ref_d.id\n -- Find enclosing function at each reference site\n JOIN defn_enclosing_ranges enc_der\n ON enc_der.document_id = ref_d.id\n AND enc_der.start_line <= ref_c.start_line\n AND enc_der.end_line >= ref_c.end_line\n JOIN global_symbols enc_gs ON enc_der.symbol_id = enc_gs.id\n JOIN documents enc_d ON enc_der.document_id = enc_d.id\n -- Find other symbols referenced within that enclosing function\n JOIN mentions out_m ON out_m.role = 0\n JOIN chunks out_c ON out_m.chunk_id = out_c.id\n AND out_c.document_id = enc_der.document_id\n AND out_c.start_line >= enc_der.start_line\n AND out_c.end_line <= enc_der.end_line\n JOIN global_symbols out_gs ON out_m.symbol_id = out_gs.id\n JOIN defn_enclosing_ranges out_der ON out_gs.id = out_der.symbol_id\n JOIN documents out_d ON out_der.document_id = out_d.id\n WHERE ref_m.symbol_id = ? AND ref_m.role = 0\n AND out_gs.id != ? AND out_gs.id != enc_gs.id\n AND out_d.id != ref_d.id\n ${db.symbolNoiseFor('out_gs')}\n ${db.pathExclusionsFor('out_d')}\n ORDER BY out_d.relative_path\n LIMIT 30`,\n match.symbolId, match.symbolId,\n );\n\n const seen = new Set<string>();\n const connected: SliceResult['connectedSymbols'] = [];\n\n for (const r of rows) {\n if (seen.has(r.output_symbol) || db.isIgnored(r.output_file)) continue;\n seen.add(r.output_symbol);\n connected.push({\n symbol: r.output_symbol,\n shortName: shortenSymbol(r.output_symbol),\n file: r.output_file,\n relationship: `used alongside target in ${shortenSymbol(r.enclosing_symbol)}`,\n });\n }\n\n return {\n symbol: match.symbol,\n shortName: shortenSymbol(match.symbol),\n direction: 'forward',\n connectedSymbols: connected,\n };\n}\n","import type { ScipDatabase } from '../db.js';\nimport type { RedundantReexport } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Find barrel re-exports that no consumer actually imports through.\n *\n * If `queries/index.ts` re-exports `byKind` from `by-kind.ts`, but every\n * consumer of `byKind` imports it directly from `by-kind.ts` (not through\n * `index.ts`), the re-export in the barrel is dead weight.\n *\n * Algorithm:\n * 1. Find all barrel files (index.ts / index.js)\n * 2. For each barrel, find symbols it re-exports (defined elsewhere, referenced in barrel with role=0)\n * 3. For each re-exported symbol, count consumers through the barrel vs direct from the source\n * 4. If zero consumers go through the barrel, the re-export is redundant\n */\nexport function redundantReexports(\n db: ScipDatabase,\n opts: { scope?: string; limit?: number } = {},\n): RedundantReexport[] {\n const { scope, limit } = opts;\n\n const scopeFilter = scope ? `AND barrel_d.relative_path LIKE '%${scope}%'` : '';\n\n // Step 1 + 2: Find all barrel files and symbols they re-export.\n // A re-export is a symbol that:\n // - is mentioned in a barrel file with role=0 (reference/import)\n // - has its definition (defn_enclosing_ranges) in a DIFFERENT file\n const reexportRows = db.all<{\n barrel_doc_id: number;\n barrel_path: string;\n symbol_id: number;\n symbol: string;\n original_doc_id: number;\n original_path: string;\n }>(\n `SELECT DISTINCT\n barrel_d.id AS barrel_doc_id,\n barrel_d.relative_path AS barrel_path,\n gs.id AS symbol_id,\n gs.symbol AS symbol,\n orig_d.id AS original_doc_id,\n orig_d.relative_path AS original_path\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents barrel_d ON c.document_id = barrel_d.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents orig_d ON der.document_id = orig_d.id\n WHERE m.role = 0\n AND (barrel_d.relative_path LIKE '%/index.ts'\n OR barrel_d.relative_path LIKE '%/index.js'\n OR barrel_d.relative_path = 'index.ts'\n OR barrel_d.relative_path = 'index.js')\n AND orig_d.id != barrel_d.id\n ${db.pathExclusionsFor('barrel_d', 'orig_d')}\n ${db.symbolNoiseFor('gs')}\n -- Only function-level symbols (ending with ().), not module-level\n AND gs.symbol LIKE '%().'\n ${scopeFilter}\n ORDER BY barrel_d.relative_path, gs.symbol`,\n );\n\n const results: RedundantReexport[] = [];\n\n for (const row of reexportRows) {\n if (db.isIgnored(row.barrel_path) || db.isIgnored(row.original_path)) continue;\n\n // Step 3: Count consumers that reference this symbol through the barrel\n // A \"barrel consumer\" is a file (other than the barrel itself and the original file)\n // that mentions this symbol AND also mentions something from the barrel document.\n // More precisely: count distinct files that reference this symbol AND whose\n // chunk is in a document that also has a role=0 mention pointing to the barrel file's symbols.\n //\n // Simpler approach: count distinct documents that reference this symbol (role=0)\n // grouped by whether the reference chunk is in a file that imports from the barrel\n // or from the original.\n //\n // Actually, the most reliable approach with SCIP data: count how many distinct\n // consumer documents reference this symbol_id with role=0, excluding the barrel\n // and the original file themselves. Then check if those consumers also reference\n // ANY symbol through a mention in the barrel doc vs the original doc.\n //\n // Simplest correct approach: In SCIP, when file A does `import { foo } from './bar/index'`,\n // the mention of `foo` in file A points to the same global symbol regardless of import path.\n // SCIP doesn't track import provenance. BUT the barrel file itself contains mentions\n // (role=0 references) of the re-exported symbols. So we can check:\n // - barrelConsumers: files that mention both this symbol AND any symbol whose definition\n // is in the barrel (i.e., they import the barrel)\n // - directConsumers: files that mention this symbol but don't import the barrel\n //\n // Even simpler: check if the barrel document is in the deps of the consumer.\n // A consumer \"goes through the barrel\" if it has ANY role=0 mention pointing to a\n // chunk in the barrel file. Otherwise it goes direct.\n\n const consumerCounts = db.get<{\n barrel_consumers: number;\n direct_consumers: number;\n }>(\n `SELECT\n SUM(CASE WHEN uses_barrel = 1 THEN 1 ELSE 0 END) AS barrel_consumers,\n SUM(CASE WHEN uses_barrel = 0 THEN 1 ELSE 0 END) AS direct_consumers\n FROM (\n SELECT\n consumer_d.id AS consumer_doc_id,\n MAX(CASE WHEN EXISTS (\n SELECT 1\n FROM mentions barrel_m\n JOIN chunks barrel_c ON barrel_m.chunk_id = barrel_c.id\n WHERE barrel_c.document_id = consumer_d.id\n AND barrel_m.role = 0\n AND barrel_m.symbol_id IN (\n SELECT m2.symbol_id\n FROM mentions m2\n JOIN chunks c2 ON m2.chunk_id = c2.id\n WHERE c2.document_id = ?\n AND m2.role = 0\n )\n ) THEN 1 ELSE 0 END) AS uses_barrel\n FROM mentions ref_m\n JOIN chunks ref_c ON ref_m.chunk_id = ref_c.id\n JOIN documents consumer_d ON ref_c.document_id = consumer_d.id\n WHERE ref_m.symbol_id = ?\n AND ref_m.role = 0\n AND consumer_d.id != ?\n AND consumer_d.id != ?\n ${db.pathExclusionsFor('consumer_d')}\n GROUP BY consumer_d.id\n )`,\n row.barrel_doc_id, // for the inner subquery checking barrel mentions\n row.symbol_id, // the re-exported symbol\n row.barrel_doc_id, // exclude the barrel itself\n row.original_doc_id, // exclude the original file\n );\n\n const barrelConsumers = consumerCounts?.barrel_consumers ?? 0;\n const directConsumers = consumerCounts?.direct_consumers ?? 0;\n\n // In TypeScript, `import * as X from './barrel'` resolves all references\n // directly to the source file — the barrel is transparent to SCIP.\n // This means barrelConsumers is always 0 for namespace imports.\n //\n // We can only confidently report symbols with 0 consumers EVERYWHERE\n // (both barrel and direct). These are truly dead re-exports.\n //\n // Symbols with directConsumers > 0 but barrelConsumers === 0 might be\n // consumed through a namespace import — we can't tell, so we skip them.\n if (barrelConsumers === 0 && directConsumers === 0) {\n results.push({\n barrelFile: row.barrel_path,\n symbol: row.symbol,\n shortName: shortenSymbol(row.symbol),\n originalFile: row.original_path,\n barrelConsumers,\n directConsumers,\n });\n }\n }\n\n // Sort: symbols with the most direct consumers first (biggest cleanup wins),\n // then by barrel file path for stable output\n results.sort((a, b) =>\n b.directConsumers - a.directConsumers\n || a.barrelFile.localeCompare(b.barrelFile)\n || a.shortName.localeCompare(b.shortName),\n );\n\n return limit ? results.slice(0, limit) : results;\n}\n","import type { ScipDatabase } from '../db.js';\nimport type { SimilarSignatureGroup } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Find functions with near-identical type signatures (same parameter types\n * and return type) but different names. These are \"same shape\" functions\n * that may be doing similar work even if their internal implementation differs.\n *\n * The SCIP `documentation` field often contains the full type signature\n * after a `|` delimiter. We parse it, normalize it (strip the function name,\n * whitespace, and case), then group by normalized signature.\n *\n * Groups with 2+ functions = same-shape candidates.\n */\nexport function similarSignatures(\n db: ScipDatabase,\n opts: { scope?: string; minLoc?: number; limit?: number } = {},\n): SimilarSignatureGroup[] {\n const { scope, minLoc = 1, limit } = opts;\n\n const scopeFilter = scope ? `AND d.relative_path LIKE '%${scope}%'` : '';\n\n // Get all function-level symbols with their documentation/signature strings.\n // We use the same signature extraction pattern as symbols.ts / trace.ts.\n // Filter to symbols that have a documentation field containing '|' (the sig delimiter)\n // and whose signature contains '(' (indicating a callable).\n const rows = db.all<{\n symbol: string;\n relative_path: string;\n start_line: number;\n end_line: number;\n loc: number;\n sig: string;\n }>(\n `SELECT\n gs.symbol,\n d.relative_path,\n der.start_line,\n der.end_line,\n (der.end_line - der.start_line + 1) AS loc,\n REPLACE(SUBSTR(gs.documentation, INSTR(gs.documentation, '|') + 1), char(10), ' ') AS sig\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE gs.documentation IS NOT NULL\n AND gs.documentation != ''\n AND INSTR(gs.documentation, '|') > 0\n AND (der.end_line - der.start_line + 1) >= ?\n ${db.pathExclusionsFor('d')}\n ${db.symbolNoiseFor('gs')}\n ${scopeFilter}\n ORDER BY d.relative_path, der.start_line`,\n minLoc,\n );\n\n // Group by normalized signature\n const sigGroups = new Map<string, Array<{\n symbol: string;\n shortName: string;\n file: string;\n startLine: number;\n endLine: number;\n loc: number;\n }>>();\n\n for (const row of rows) {\n if (db.isIgnored(row.relative_path)) continue;\n\n const normalized = normalizeSignature(row.sig);\n if (!normalized) continue;\n\n const entry = {\n symbol: row.symbol,\n shortName: shortenSymbol(row.symbol),\n file: row.relative_path,\n startLine: row.start_line,\n endLine: row.end_line,\n loc: row.loc,\n };\n\n const existing = sigGroups.get(normalized);\n if (existing) {\n existing.push(entry);\n } else {\n sigGroups.set(normalized, [entry]);\n }\n }\n\n // Collect groups with 2+ functions\n const results: SimilarSignatureGroup[] = [];\n\n for (const [signature, functions] of sigGroups) {\n if (functions.length < 2) continue;\n\n results.push({ signature, functions });\n }\n\n // Sort by group size descending (largest groups = most duplication),\n // then by total LOC in the group\n results.sort((a, b) => {\n const sizeDiff = b.functions.length - a.functions.length;\n if (sizeDiff !== 0) return sizeDiff;\n const locA = a.functions.reduce((sum, f) => sum + f.loc, 0);\n const locB = b.functions.reduce((sum, f) => sum + f.loc, 0);\n return locB - locA;\n });\n\n return limit ? results.slice(0, limit) : results;\n}\n\n/**\n * Normalize a signature for comparison:\n * 1. Clean markdown fences and SCIP prefixes\n * 2. Strip everything before the first '(' (removes the function name)\n * 3. Strip whitespace and lowercase\n *\n * Returns null if the signature doesn't contain a callable form.\n */\nfunction normalizeSignature(raw: string): string | null {\n if (!raw || !raw.trim()) return null;\n\n // Clean markdown and SCIP decoration (same as cleanSignature)\n let sig = raw\n .replace(/^```\\w*\\s*/, '')\n .replace(/\\s*```$/, '')\n .replace(/^\\(method\\)\\s*/, '')\n .replace(/^\\(property\\)\\s*/, '')\n .replace(/^\\(function\\)\\s*/, '')\n .replace(/^\\(class\\)\\s*/, '')\n .replace(/^\\(interface\\)\\s*/, '')\n .replace(/^\\(enum\\)\\s*/, '')\n .replace(/^\\(type alias\\)\\s*/, '')\n .replace(/^\\(const\\)\\s*/, '')\n .replace(/^\\(var\\)\\s*/, '')\n .trim();\n\n // Find the first '(' — everything from there is the parameter/return signature\n const parenIdx = sig.indexOf('(');\n if (parenIdx === -1) return null;\n\n sig = sig.slice(parenIdx);\n\n // Normalize: strip all whitespace, lowercase\n sig = sig.replace(/\\s+/g, '').toLowerCase();\n\n // Must have meaningful content after normalization\n if (sig.length < 3) return null; // e.g. \"()\" alone is too generic\n\n return sig;\n}\n","import {\n existsSync, mkdirSync, symlinkSync, readlinkSync,\n unlinkSync, chmodSync, createWriteStream,\n} from 'node:fs';\nimport { join, dirname, resolve } from 'node:path';\nimport { homedir, platform, arch } from 'node:os';\nimport { execFileSync } from 'node:child_process';\nimport { fileURLToPath } from 'node:url';\nimport { get as httpsGet } from 'node:https';\nimport { tryInstallScipCli } from './reindex/install.js';\n\nconst IS_WINDOWS = platform() === 'win32';\nconst SKILLS = ['concrete-plan', 'scip-explore', 'scip-debloat', 'scip-verify'];\nconst SCIP_VERSION = 'v0.7.0';\n\n// ── Skills Installation ────────────────────────────────────\n\nexport interface InstallSkillsResult {\n installed: string[];\n skipped: string[];\n alreadyLinked: string[];\n}\n\n/**\n * Install scip-query skills into both Claude Code (~/.claude/skills/)\n * and Codex (~/.codex/skills/). Uses symlinks (junctions on Windows)\n * so skills auto-update when the package updates.\n */\nexport function installSkills(\n opts: { quiet?: boolean } = {},\n): InstallSkillsResult {\n const log = opts.quiet ? () => {} : console.log;\n const thisFile = fileURLToPath(import.meta.url);\n const skillsSource = resolve(dirname(thisFile), '..', 'skills');\n\n const targets = [\n join(homedir(), '.claude', 'skills'),\n join(homedir(), '.codex', 'skills'),\n ];\n\n const result: InstallSkillsResult = {\n installed: [],\n skipped: [],\n alreadyLinked: [],\n };\n\n for (const targetDir of targets) {\n // Only install if the parent directory exists (tool is installed)\n const parentDir = dirname(targetDir);\n if (!existsSync(parentDir)) {\n continue;\n }\n\n mkdirSync(targetDir, { recursive: true });\n const toolName = targetDir.includes('.codex') ? 'Codex' : 'Claude';\n\n for (const skill of SKILLS) {\n const source = join(skillsSource, skill);\n const target = join(targetDir, skill);\n\n if (!existsSync(source)) {\n result.skipped.push(`${toolName}/${skill}`);\n continue;\n }\n\n if (existsSync(target)) {\n try {\n const existing = readlinkSync(target);\n if (resolve(existing) === resolve(source)) {\n result.alreadyLinked.push(`${toolName}/${skill}`);\n log(` ok: ${skill} → ${toolName} (already linked)`);\n continue;\n }\n } catch {\n // Not a symlink — don't overwrite user's custom skill\n result.skipped.push(`${toolName}/${skill}`);\n log(` skip: ${skill} → ${toolName} (exists, not a symlink)`);\n continue;\n }\n unlinkSync(target);\n }\n\n // Use 'junction' on Windows (doesn't need admin), 'dir' elsewhere\n symlinkSync(source, target, IS_WINDOWS ? 'junction' : 'dir');\n result.installed.push(`${toolName}/${skill}`);\n log(` done: ${skill} → ${toolName}`);\n }\n }\n\n return result;\n}\n\n// ── SCIP CLI Binary Detection & Installation ───────────────\n\n/**\n * Check if the `scip` CLI binary is available on PATH.\n */\nexport function isScipInstalled(): boolean {\n try {\n const cmd = IS_WINDOWS ? 'where' : 'which';\n execFileSync(cmd, ['scip'], { stdio: 'pipe' });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get the scip CLI version if installed.\n */\nexport function getScipVersion(): string | null {\n try {\n const output = execFileSync('scip', ['--version'], { stdio: 'pipe' }).toString().trim();\n return output;\n } catch {\n return null;\n }\n}\n\n/**\n * Resolve the download URL for the scip CLI binary for this platform.\n */\nfunction getScipDownloadUrl(): { url: string; filename: string } | null {\n const os = platform();\n const cpu = arch();\n\n let osName: string;\n let archName: string;\n let ext: string;\n\n switch (os) {\n case 'darwin': osName = 'darwin'; ext = 'tar.gz'; break;\n case 'linux': osName = 'linux'; ext = 'tar.gz'; break;\n case 'win32': osName = 'windows'; ext = 'zip'; break;\n default: return null;\n }\n\n switch (cpu) {\n case 'arm64': archName = 'arm64'; break;\n case 'x64': archName = 'amd64'; break;\n default: return null;\n }\n\n const filename = `scip-${osName}-${archName}.${ext}`;\n const url = `https://github.com/sourcegraph/scip/releases/download/${SCIP_VERSION}/${filename}`;\n return { url, filename };\n}\n\n/**\n * Print instructions for installing the scip CLI binary.\n */\nexport function printScipInstallInstructions(): void {\n const download = getScipDownloadUrl();\n\n console.log('\\nThe `scip` CLI is required but not found on PATH.\\n');\n\n if (platform() === 'darwin') {\n console.log('Install via Homebrew:');\n console.log(' brew install sourcegraph/scip/scip\\n');\n console.log('Or download manually:');\n } else {\n console.log('Download from:');\n }\n\n if (download) {\n console.log(` ${download.url}\\n`);\n } else {\n console.log(` https://github.com/sourcegraph/scip/releases/tag/${SCIP_VERSION}\\n`);\n }\n\n console.log('After installing, ensure `scip` is on your PATH and run `scip-query reindex`.');\n}\n\n// ── First-Run Setup ────────────────────────────────────────\n\n/**\n * Run first-time setup: install skills and check for scip binary.\n * Called from the postinstall script.\n */\nexport function postinstall(): void {\n console.log('scip-query: installing skills...');\n const result = installSkills({ quiet: false });\n\n const total = result.installed.length + result.alreadyLinked.length;\n if (total > 0) {\n console.log(`\\n${result.installed.length} skill(s) installed, ${result.alreadyLinked.length} already linked.`);\n }\n\n // Check for scip binary — auto-install if missing\n if (!isScipInstalled()) {\n console.log('\\nscip CLI not found on PATH. Attempting auto-install...');\n const installed = tryInstallScipCli(console.log);\n if (!installed) {\n printScipInstallInstructions();\n }\n } else {\n const version = getScipVersion();\n console.log(`\\nscip CLI: ${version ?? 'installed'}`);\n }\n\n console.log('');\n}\n"],"mappings":"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","names":["existsSync","join","files","readFileSync","existsSync","join","execFileSync","existsSync","join","existsSync","join","methods","join","execFileSync","existsSync","existsSync","join","ignore","ignore","join","resolve","code","existsSync","symbols","files","symbols","symbols","symbols","path","symbols","deps","path","i","j","symbols","symbols","execFileSync","execFileSync","fanIn","symbols","deps","files","symbols","path","s","readFileSync","join","join","readFileSync","readFileSync","join","join","readFileSync","fanOut","existsSync","mkdirSync","join","dirname","resolve","homedir","platform","execFileSync","IS_WINDOWS","platform","resolve","dirname","join","homedir","existsSync","mkdirSync","execFileSync","platform","existsSync","join"]}