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
package/dist/index.js ADDED
@@ -0,0 +1,1271 @@
1
+ import "./chunk-JJP7KQND.js";
2
+ import {
3
+ surface
4
+ } from "./chunk-FFSWWE5O.js";
5
+ import {
6
+ symbols
7
+ } from "./chunk-KCBMVQL5.js";
8
+ import {
9
+ system
10
+ } from "./chunk-DCKMSTJ4.js";
11
+ import {
12
+ trace
13
+ } from "./chunk-TBP6BICL.js";
14
+ import {
15
+ redundantReexports
16
+ } from "./chunk-3E2X7RIE.js";
17
+ import {
18
+ refs
19
+ } from "./chunk-6NBLIDF4.js";
20
+ import {
21
+ similarChains
22
+ } from "./chunk-JKP5GH6T.js";
23
+ import {
24
+ similarFiles
25
+ } from "./chunk-Z73NYSBZ.js";
26
+ import {
27
+ similarSignatures
28
+ } from "./chunk-SEFSL2GF.js";
29
+ import {
30
+ slice
31
+ } from "./chunk-ZJRYBOEE.js";
32
+ import {
33
+ hierarchy
34
+ } from "./chunk-DEZKCZXD.js";
35
+ import {
36
+ hotspots
37
+ } from "./chunk-BFSCMC22.js";
38
+ import {
39
+ importedBy,
40
+ imports,
41
+ unusedImports
42
+ } from "./chunk-BEPIEVLR.js";
43
+ import {
44
+ members
45
+ } from "./chunk-3UOUTZQT.js";
46
+ import {
47
+ methods
48
+ } from "./chunk-NUZ4OMU3.js";
49
+ import {
50
+ outline
51
+ } from "./chunk-6SXADWLW.js";
52
+ import {
53
+ deps,
54
+ rdeps
55
+ } from "./chunk-N5KEREIA.js";
56
+ import {
57
+ diffImpact
58
+ } from "./chunk-YZAA4LYG.js";
59
+ import {
60
+ docCoverage
61
+ } from "./chunk-FGXRVW7G.js";
62
+ import {
63
+ fanIn,
64
+ fanOut,
65
+ topFanIn,
66
+ topFanOut
67
+ } from "./chunk-GTILYBH6.js";
68
+ import {
69
+ files
70
+ } from "./chunk-MGNMHKX3.js";
71
+ import {
72
+ health
73
+ } from "./chunk-7OZPA5OO.js";
74
+ import {
75
+ staleAbstractions
76
+ } from "./chunk-GJFURBEW.js";
77
+ import {
78
+ stats
79
+ } from "./chunk-XFXDXEUN.js";
80
+ import {
81
+ testCoverage,
82
+ testCoverageSummary
83
+ } from "./chunk-3ZZJVBIO.js";
84
+ import {
85
+ wrapperCandidates
86
+ } from "./chunk-TDNNOR6D.js";
87
+ import {
88
+ passthroughCandidates
89
+ } from "./chunk-NDSQYIWT.js";
90
+ import {
91
+ similar,
92
+ similarAll
93
+ } from "./chunk-TSPZOMHC.js";
94
+ import {
95
+ isolated
96
+ } from "./chunk-LUSIFBXO.js";
97
+ import {
98
+ drift
99
+ } from "./chunk-36OMT7ZJ.js";
100
+ import {
101
+ extractCandidates
102
+ } from "./chunk-CM454WL3.js";
103
+ import {
104
+ complexityHotspots
105
+ } from "./chunk-EMDQWNYR.js";
106
+ import {
107
+ complexity
108
+ } from "./chunk-BP2ATLK2.js";
109
+ import {
110
+ convergence
111
+ } from "./chunk-LB7OS35Q.js";
112
+ import {
113
+ coupling,
114
+ topCoupling
115
+ } from "./chunk-KVSW5KYP.js";
116
+ import {
117
+ cycles
118
+ } from "./chunk-5WTJAXY2.js";
119
+ import {
120
+ dataflow
121
+ } from "./chunk-T6ARFSBZ.js";
122
+ import {
123
+ dead
124
+ } from "./chunk-5FGUEU7N.js";
125
+ import {
126
+ deepChains
127
+ } from "./chunk-MBVNHJVN.js";
128
+ import {
129
+ affected
130
+ } from "./chunk-6VJ6Q7IE.js";
131
+ import {
132
+ bottlenecks
133
+ } from "./chunk-2QZ23IBN.js";
134
+ import {
135
+ byKind,
136
+ kindCounts
137
+ } from "./chunk-LAWMH22O.js";
138
+ import {
139
+ callGraph
140
+ } from "./chunk-UNTPVD36.js";
141
+ import {
142
+ changeSurface
143
+ } from "./chunk-VRUJH4BO.js";
144
+ import "./chunk-4TYLS5XX.js";
145
+ import {
146
+ code
147
+ } from "./chunk-VZ7AMAFL.js";
148
+ import "./chunk-FUHJCHS4.js";
149
+ import {
150
+ leafName,
151
+ parseSymbol,
152
+ shortenSymbol
153
+ } from "./chunk-QOV2R2WT.js";
154
+
155
+ // src/db.ts
156
+ import Database from "better-sqlite3";
157
+ import { statSync } from "fs";
158
+ var ScipDatabase = class {
159
+ db;
160
+ config;
161
+ pathFilter;
162
+ constructor(config, pathFilter) {
163
+ this.config = config;
164
+ this.pathFilter = pathFilter ?? null;
165
+ this.db = new Database(config.dbPath, { readonly: true });
166
+ this.db.pragma("busy_timeout = 5000");
167
+ }
168
+ /** Attach a gitignore-based path filter for query results */
169
+ setPathFilter(filter) {
170
+ this.pathFilter = filter;
171
+ }
172
+ /** Check if a path should be excluded based on .gitignore rules */
173
+ isIgnored(relativePath) {
174
+ return this.pathFilter?.isIgnored(relativePath) ?? false;
175
+ }
176
+ /** Filter an array of paths using the gitignore filter */
177
+ filterPaths(paths) {
178
+ return this.pathFilter?.filter(paths) ?? paths;
179
+ }
180
+ /**
181
+ * The local-symbol predicate: only match symbols that are defined
182
+ * in files NOT excluded by gitignore. This replaces the old hardcoded
183
+ * `NOT LIKE 'node_modules/%'` check.
184
+ *
185
+ * Since SQLite can't evaluate JS gitignore rules inline, we use a
186
+ * simpler approach: query broadly, then filter in JS. For queries
187
+ * that need SQL-level filtering, use excludedPathPatterns().
188
+ */
189
+ get localSymbolPredicate() {
190
+ return `EXISTS (
191
+ SELECT 1
192
+ FROM defn_enclosing_ranges local_der
193
+ JOIN documents local_d ON local_der.document_id = local_d.id
194
+ WHERE local_der.symbol_id = gs.id
195
+ ${this.pathExclusionsFor("local_d").trimStart()}
196
+ )`;
197
+ }
198
+ /**
199
+ * SQL WHERE clause fragments to exclude common build/dependency paths.
200
+ * Complements the JS-level gitignore filtering for performance.
201
+ */
202
+ get pathExclusions() {
203
+ return this.pathExclusionsFor("d");
204
+ }
205
+ /** Reusable SQL fragment: filter out synthetic/internal symbol noise */
206
+ get symbolNoise() {
207
+ return this.symbolNoiseFor("gs");
208
+ }
209
+ /** Build SQL path exclusions for one or more document table aliases */
210
+ pathExclusionsFor(...aliases) {
211
+ return aliases.flatMap((alias) => [
212
+ `AND ${alias}.relative_path NOT LIKE 'node_modules/%'`,
213
+ `AND ${alias}.relative_path NOT LIKE '.git/%'`
214
+ ]).join("\n ");
215
+ }
216
+ /** Build SQL symbol exclusions for the given global_symbols alias */
217
+ symbolNoiseFor(alias) {
218
+ return `AND ${alias}.symbol NOT LIKE '%().(%' AND ${alias}.symbol NOT LIKE '%typeLiteral%'`;
219
+ }
220
+ /** Run a raw SQL query and return all rows */
221
+ all(sql, ...params) {
222
+ return this.db.prepare(sql).all(...params);
223
+ }
224
+ /** Run a raw SQL query and return the first row */
225
+ get(sql, ...params) {
226
+ return this.db.prepare(sql).get(...params);
227
+ }
228
+ /** Get the database file size in bytes */
229
+ sizeBytes() {
230
+ try {
231
+ return statSync(this.config.dbPath).size;
232
+ } catch {
233
+ return 0;
234
+ }
235
+ }
236
+ /** Get the last modification time of the database file */
237
+ lastModified() {
238
+ try {
239
+ return statSync(this.config.dbPath).mtime;
240
+ } catch {
241
+ return null;
242
+ }
243
+ }
244
+ close() {
245
+ this.db.close();
246
+ }
247
+ };
248
+
249
+ // src/gitignore-filter.ts
250
+ import ignore from "ignore";
251
+ import { readFileSync, existsSync } from "fs";
252
+ import { join, dirname } from "path";
253
+ function createGitignoreFilter(projectRoot) {
254
+ const ig = ignore();
255
+ let loaded = false;
256
+ const gitignorePaths = findGitignoreFiles(projectRoot);
257
+ for (const gitignorePath of gitignorePaths) {
258
+ try {
259
+ const content = readFileSync(gitignorePath, "utf-8");
260
+ ig.add(content);
261
+ loaded = true;
262
+ } catch {
263
+ }
264
+ }
265
+ if (!loaded) {
266
+ ig.add(DEFAULT_IGNORES);
267
+ }
268
+ return {
269
+ isIgnored: (relativePath) => ig.ignores(relativePath),
270
+ filter: (paths) => paths.filter((p) => !ig.ignores(p))
271
+ };
272
+ }
273
+ function findGitignoreFiles(projectRoot) {
274
+ const files2 = [];
275
+ const rootGitignore = join(projectRoot, ".gitignore");
276
+ if (existsSync(rootGitignore)) {
277
+ files2.push(rootGitignore);
278
+ }
279
+ let dir = dirname(projectRoot);
280
+ let depth = 0;
281
+ while (dir !== dirname(dir) && depth < 5) {
282
+ const parentGitignore = join(dir, ".gitignore");
283
+ if (existsSync(parentGitignore)) {
284
+ files2.push(parentGitignore);
285
+ }
286
+ if (existsSync(join(dir, ".git"))) break;
287
+ dir = dirname(dir);
288
+ depth++;
289
+ }
290
+ return files2;
291
+ }
292
+ var DEFAULT_IGNORES = `
293
+ # Dependencies
294
+ node_modules/
295
+ vendor/
296
+ .bundle/
297
+
298
+ # Build output
299
+ dist/
300
+ build/
301
+ out/
302
+ target/
303
+ bin/
304
+ obj/
305
+
306
+ # Python
307
+ __pycache__/
308
+ *.pyc
309
+ *.pyo
310
+ .venv/
311
+ venv/
312
+ .env/
313
+ env/
314
+ *.egg-info/
315
+
316
+ # Rust
317
+ target/
318
+
319
+ # Java / Kotlin / Scala
320
+ *.class
321
+ .gradle/
322
+ .mvn/
323
+
324
+ # C# / .NET
325
+ bin/
326
+ obj/
327
+ packages/
328
+
329
+ # Go
330
+ vendor/
331
+
332
+ # Dart
333
+ .dart_tool/
334
+ build/
335
+
336
+ # PHP
337
+ vendor/
338
+
339
+ # IDE / OS
340
+ .idea/
341
+ .vscode/
342
+ *.swp
343
+ *.swo
344
+ .DS_Store
345
+ Thumbs.db
346
+
347
+ # Type definitions (often noise in queries)
348
+ *.d.ts
349
+ `;
350
+
351
+ // src/reindex/index.ts
352
+ import { execFileSync as execFileSync2 } from "child_process";
353
+ import { existsSync as existsSync3 } from "fs";
354
+ import { join as join3 } from "path";
355
+
356
+ // src/reindex/detect.ts
357
+ import { existsSync as existsSync2 } from "fs";
358
+ import { join as join2 } from "path";
359
+ var LANGUAGE_MARKERS = [
360
+ { language: "typescript", files: ["tsconfig.json", "tsconfig.base.json"] },
361
+ { language: "rust", files: ["Cargo.toml"] },
362
+ { language: "go", files: ["go.mod"] },
363
+ { language: "java", files: ["pom.xml", "build.gradle", "build.gradle.kts"] },
364
+ { language: "kotlin", files: ["build.gradle.kts"] },
365
+ { language: "scala", files: ["build.sbt"] },
366
+ { language: "python", files: ["pyproject.toml", "setup.py", "setup.cfg", "Pipfile"] },
367
+ { language: "ruby", files: ["Gemfile"] },
368
+ { language: "csharp", files: ["*.csproj", "*.sln"] },
369
+ { language: "dart", files: ["pubspec.yaml"] },
370
+ { language: "php", files: ["composer.json"] },
371
+ { language: "javascript", files: ["package.json"] }
372
+ // Last — very common, low specificity
373
+ ];
374
+ function detectLanguages(projectRoot) {
375
+ const detected = [];
376
+ for (const marker of LANGUAGE_MARKERS) {
377
+ for (const file of marker.files) {
378
+ if (file.includes("*")) {
379
+ continue;
380
+ }
381
+ if (existsSync2(join2(projectRoot, file))) {
382
+ if (!detected.includes(marker.language)) {
383
+ detected.push(marker.language);
384
+ }
385
+ break;
386
+ }
387
+ }
388
+ }
389
+ if (detected.includes("typescript")) {
390
+ const jsIdx = detected.indexOf("javascript");
391
+ if (jsIdx !== -1) detected.splice(jsIdx, 1);
392
+ }
393
+ return detected;
394
+ }
395
+
396
+ // src/reindex/indexers.ts
397
+ var INDEXER_CONFIGS = {
398
+ typescript: {
399
+ language: "typescript",
400
+ indexerBinary: "scip-typescript",
401
+ checkCommand: "npx scip-typescript --version",
402
+ indexArgs: ({ outputPath, pnpmWorkspaces }) => {
403
+ const args = ["scip-typescript", "index", "--infer-tsconfig", "--output", outputPath, "--no-progress-bar"];
404
+ if (pnpmWorkspaces) args.splice(2, 0, "--pnpm-workspaces");
405
+ return { binary: "npx", args };
406
+ },
407
+ markerFiles: ["tsconfig.json"],
408
+ installMethods: [
409
+ { label: "npm", prerequisite: "npm", binary: "npm", args: ["install", "-g", "@sourcegraph/scip-typescript"] }
410
+ ],
411
+ installUrl: "https://github.com/sourcegraph/scip-typescript"
412
+ },
413
+ javascript: {
414
+ language: "javascript",
415
+ indexerBinary: "scip-typescript",
416
+ checkCommand: "npx scip-typescript --version",
417
+ indexArgs: ({ outputPath }) => ({
418
+ binary: "npx",
419
+ args: ["scip-typescript", "index", "--infer-tsconfig", "--output", outputPath, "--no-progress-bar"]
420
+ }),
421
+ markerFiles: ["package.json"],
422
+ installMethods: [
423
+ { label: "npm", prerequisite: "npm", binary: "npm", args: ["install", "-g", "@sourcegraph/scip-typescript"] }
424
+ ],
425
+ installUrl: "https://github.com/sourcegraph/scip-typescript"
426
+ },
427
+ java: {
428
+ language: "java",
429
+ indexerBinary: "scip-java",
430
+ checkCommand: "scip-java --version",
431
+ indexArgs: ({ outputPath }) => ({
432
+ binary: "scip-java",
433
+ args: ["index", "--output", outputPath]
434
+ }),
435
+ markerFiles: ["pom.xml", "build.gradle"],
436
+ installMethods: [
437
+ { label: "coursier", prerequisite: "cs", binary: "cs", args: ["install", "scip-java"] }
438
+ ],
439
+ installUrl: "https://github.com/sourcegraph/scip-java/releases"
440
+ },
441
+ scala: {
442
+ language: "scala",
443
+ indexerBinary: "scip-java",
444
+ checkCommand: "scip-java --version",
445
+ indexArgs: ({ outputPath }) => ({
446
+ binary: "scip-java",
447
+ args: ["index", "--output", outputPath]
448
+ }),
449
+ markerFiles: ["build.sbt"],
450
+ installMethods: [
451
+ { label: "coursier", prerequisite: "cs", binary: "cs", args: ["install", "scip-java"] }
452
+ ],
453
+ installUrl: "https://github.com/sourcegraph/scip-java/releases"
454
+ },
455
+ kotlin: {
456
+ language: "kotlin",
457
+ indexerBinary: "scip-java",
458
+ checkCommand: "scip-java --version",
459
+ indexArgs: ({ outputPath }) => ({
460
+ binary: "scip-java",
461
+ args: ["index", "--output", outputPath]
462
+ }),
463
+ markerFiles: ["build.gradle.kts"],
464
+ installMethods: [
465
+ { label: "coursier", prerequisite: "cs", binary: "cs", args: ["install", "scip-java"] }
466
+ ],
467
+ installUrl: "https://github.com/sourcegraph/scip-java/releases"
468
+ },
469
+ rust: {
470
+ language: "rust",
471
+ indexerBinary: "rust-analyzer",
472
+ checkCommand: "rust-analyzer --version",
473
+ indexArgs: ({ outputPath }) => ({
474
+ binary: "rust-analyzer",
475
+ args: ["scip", ".", "--output", outputPath]
476
+ }),
477
+ markerFiles: ["Cargo.toml"],
478
+ installMethods: [
479
+ { label: "rustup", prerequisite: "rustup", binary: "rustup", args: ["component", "add", "rust-analyzer"] }
480
+ ],
481
+ installUrl: "https://github.com/rust-lang/rust-analyzer"
482
+ },
483
+ python: {
484
+ language: "python",
485
+ indexerBinary: "scip-python",
486
+ checkCommand: "scip-python --version",
487
+ indexArgs: ({ outputPath }) => ({
488
+ binary: "scip-python",
489
+ args: ["index", "--output", outputPath, "--project-name", "project"]
490
+ }),
491
+ markerFiles: ["pyproject.toml", "setup.py"],
492
+ installMethods: [
493
+ { label: "npm", prerequisite: "npm", binary: "npm", args: ["install", "-g", "scip-python-plus"] }
494
+ ],
495
+ installUrl: "https://github.com/PlunderStruck/scip-python"
496
+ },
497
+ ruby: {
498
+ language: "ruby",
499
+ indexerBinary: "scip-ruby",
500
+ checkCommand: "scip-ruby --version",
501
+ indexArgs: ({ outputPath }) => ({
502
+ binary: "scip-ruby",
503
+ args: ["--output", outputPath]
504
+ }),
505
+ markerFiles: ["Gemfile"],
506
+ installMethods: [],
507
+ installUrl: "https://github.com/sourcegraph/scip-ruby/releases"
508
+ },
509
+ go: {
510
+ language: "go",
511
+ indexerBinary: "scip-go",
512
+ checkCommand: "scip-go --version",
513
+ indexArgs: ({ outputPath }) => ({
514
+ binary: "scip-go",
515
+ args: ["--output", outputPath]
516
+ }),
517
+ markerFiles: ["go.mod"],
518
+ installMethods: [
519
+ { label: "go install", prerequisite: "go", binary: "go", args: ["install", "github.com/sourcegraph/scip-go@latest"] }
520
+ ],
521
+ installUrl: "https://github.com/sourcegraph/scip-go"
522
+ },
523
+ cpp: {
524
+ language: "cpp",
525
+ indexerBinary: "scip-clang",
526
+ checkCommand: "scip-clang --version",
527
+ indexArgs: ({ outputPath }) => ({
528
+ binary: "scip-clang",
529
+ args: ["--output", outputPath]
530
+ }),
531
+ markerFiles: ["CMakeLists.txt", "Makefile"],
532
+ installMethods: [],
533
+ installUrl: "https://github.com/sourcegraph/scip-clang/releases"
534
+ },
535
+ c: {
536
+ language: "c",
537
+ indexerBinary: "scip-clang",
538
+ checkCommand: "scip-clang --version",
539
+ indexArgs: ({ outputPath }) => ({
540
+ binary: "scip-clang",
541
+ args: ["--output", outputPath]
542
+ }),
543
+ markerFiles: ["CMakeLists.txt", "Makefile"],
544
+ installMethods: [],
545
+ installUrl: "https://github.com/sourcegraph/scip-clang/releases"
546
+ },
547
+ csharp: {
548
+ language: "csharp",
549
+ indexerBinary: "scip-dotnet",
550
+ checkCommand: "scip-dotnet --version",
551
+ indexArgs: ({ outputPath }) => ({
552
+ binary: "scip-dotnet",
553
+ args: ["index", "--output", outputPath]
554
+ }),
555
+ markerFiles: [],
556
+ installMethods: [
557
+ { label: "dotnet", prerequisite: "dotnet", binary: "dotnet", args: ["tool", "install", "--global", "scip-dotnet"] }
558
+ ],
559
+ installUrl: "https://github.com/sourcegraph/scip-dotnet/releases"
560
+ },
561
+ dart: {
562
+ language: "dart",
563
+ indexerBinary: "scip-dart",
564
+ checkCommand: "scip-dart --version",
565
+ indexArgs: ({ outputPath }) => ({
566
+ binary: "scip-dart",
567
+ args: ["index", "--output", outputPath]
568
+ }),
569
+ markerFiles: ["pubspec.yaml"],
570
+ installMethods: [
571
+ { label: "dart pub", prerequisite: "dart", binary: "dart", args: ["pub", "global", "activate", "scip_dart"] }
572
+ ],
573
+ installUrl: "https://github.com/Workiva/scip-dart/releases"
574
+ },
575
+ php: {
576
+ language: "php",
577
+ indexerBinary: "scip-php",
578
+ checkCommand: "scip-php --version",
579
+ indexArgs: ({ outputPath }) => ({
580
+ binary: "scip-php",
581
+ args: ["index", "--output", outputPath]
582
+ }),
583
+ markerFiles: ["composer.json"],
584
+ installMethods: [
585
+ { label: "composer", prerequisite: "composer", binary: "composer", args: ["global", "require", "davidrjenni/scip-php"] }
586
+ ],
587
+ installUrl: "https://github.com/davidrjenni/scip-php/releases"
588
+ }
589
+ };
590
+ function getIndexerConfig(language) {
591
+ return INDEXER_CONFIGS[language];
592
+ }
593
+
594
+ // src/reindex/install.ts
595
+ import { execFileSync } from "child_process";
596
+ import { platform } from "os";
597
+ var IS_WINDOWS = platform() === "win32";
598
+ function isBinaryAvailable(name) {
599
+ const cmd = IS_WINDOWS ? "where" : "which";
600
+ try {
601
+ execFileSync(cmd, [name], { stdio: "pipe" });
602
+ return true;
603
+ } catch {
604
+ return false;
605
+ }
606
+ }
607
+ function isIndexerInstalled(config) {
608
+ return isBinaryAvailable(config.indexerBinary);
609
+ }
610
+ function tryInstallIndexer(config, onStatus) {
611
+ const methods2 = config.installMethods;
612
+ if (!methods2?.length) {
613
+ onStatus(`No auto-install method available for ${config.indexerBinary}.`);
614
+ if (config.installUrl) {
615
+ onStatus(`Install manually from: ${config.installUrl}`);
616
+ }
617
+ return false;
618
+ }
619
+ for (const method of methods2) {
620
+ if (!isBinaryAvailable(method.prerequisite)) {
621
+ continue;
622
+ }
623
+ onStatus(`Installing ${config.indexerBinary} via ${method.label}...`);
624
+ try {
625
+ execFileSync(method.binary, method.args, {
626
+ stdio: "inherit",
627
+ timeout: 3e5,
628
+ env: process.env
629
+ });
630
+ if (isIndexerInstalled(config)) {
631
+ onStatus(`Successfully installed ${config.indexerBinary} via ${method.label}`);
632
+ return true;
633
+ }
634
+ onStatus(`${method.label} command completed but ${config.indexerBinary} not found on PATH`);
635
+ } catch (err) {
636
+ const msg = err instanceof Error ? err.message : String(err);
637
+ onStatus(`${method.label} install failed: ${msg}`);
638
+ }
639
+ }
640
+ onStatus(`Could not auto-install ${config.indexerBinary}.`);
641
+ if (config.installUrl) {
642
+ onStatus(`Install manually from: ${config.installUrl}`);
643
+ }
644
+ return false;
645
+ }
646
+ function tryInstallScipCli(onStatus) {
647
+ if (platform() === "darwin" && isBinaryAvailable("brew")) {
648
+ onStatus("Installing scip CLI via Homebrew...");
649
+ try {
650
+ execFileSync("brew", ["install", "sourcegraph/scip/scip"], {
651
+ stdio: "inherit",
652
+ timeout: 3e5,
653
+ env: process.env
654
+ });
655
+ if (isBinaryAvailable("scip")) {
656
+ onStatus("Successfully installed scip CLI via Homebrew");
657
+ return true;
658
+ }
659
+ } catch (err) {
660
+ const msg = err instanceof Error ? err.message : String(err);
661
+ onStatus(`Homebrew install failed: ${msg}`);
662
+ }
663
+ }
664
+ if (isBinaryAvailable("go")) {
665
+ onStatus("Installing scip CLI via go install...");
666
+ try {
667
+ execFileSync("go", ["install", "github.com/sourcegraph/scip/cmd/scip@latest"], {
668
+ stdio: "inherit",
669
+ timeout: 3e5,
670
+ env: process.env
671
+ });
672
+ if (isBinaryAvailable("scip")) {
673
+ onStatus("Successfully installed scip CLI via go install");
674
+ return true;
675
+ }
676
+ } catch (err) {
677
+ const msg = err instanceof Error ? err.message : String(err);
678
+ onStatus(`go install failed: ${msg}`);
679
+ }
680
+ }
681
+ onStatus("Could not auto-install scip CLI.");
682
+ onStatus("Install manually from: https://github.com/sourcegraph/scip/releases");
683
+ return false;
684
+ }
685
+
686
+ // src/reindex/index.ts
687
+ async function reindex(opts) {
688
+ const {
689
+ projectRoot,
690
+ maxHeapMb = 8192,
691
+ onStatus = console.log,
692
+ skipAutoInstall = false
693
+ } = opts;
694
+ const outputScip = opts.outputScip ?? join3(projectRoot, "index.scip");
695
+ const outputDb = opts.outputDb ?? join3(projectRoot, "index.db");
696
+ const start = Date.now();
697
+ const languages = opts.languages ?? detectLanguages(projectRoot);
698
+ if (languages.length === 0) {
699
+ throw new Error(
700
+ "No supported languages detected in this project. Looked for: tsconfig.json, Cargo.toml, go.mod, pyproject.toml, etc."
701
+ );
702
+ }
703
+ onStatus(`Detected languages: ${languages.join(", ")}`);
704
+ if (!isBinaryAvailable("scip")) {
705
+ if (skipAutoInstall) {
706
+ throw new Error(
707
+ "The scip CLI is required but not found on PATH.\nInstall from: https://github.com/sourcegraph/scip/releases"
708
+ );
709
+ }
710
+ onStatus("scip CLI not found on PATH. Attempting auto-install...");
711
+ if (!tryInstallScipCli(onStatus)) {
712
+ throw new Error(
713
+ "The scip CLI is required but could not be installed.\nInstall manually from: https://github.com/sourcegraph/scip/releases"
714
+ );
715
+ }
716
+ }
717
+ const env = {
718
+ ...process.env,
719
+ NODE_OPTIONS: `--max-old-space-size=${maxHeapMb}`
720
+ };
721
+ for (const lang of languages) {
722
+ const config = getIndexerConfig(lang);
723
+ if (!isIndexerInstalled(config)) {
724
+ if (skipAutoInstall) {
725
+ throw new Error(
726
+ `${config.indexerBinary} is required to index ${lang} but not found on PATH.
727
+ ` + (config.installUrl ? `Install from: ${config.installUrl}` : `Make sure ${config.indexerBinary} is installed and available on PATH.`)
728
+ );
729
+ }
730
+ onStatus(`${config.indexerBinary} not found. Attempting auto-install...`);
731
+ if (!tryInstallIndexer(config, onStatus)) {
732
+ throw new Error(
733
+ `${config.indexerBinary} is required to index ${lang} but could not be installed.
734
+ ` + (config.installUrl ? `Install manually from: ${config.installUrl}` : `Make sure ${config.indexerBinary} is installed and available on PATH.`)
735
+ );
736
+ }
737
+ }
738
+ onStatus(`Indexing ${lang} with ${config.indexerBinary}...`);
739
+ const { binary, args } = config.indexArgs({
740
+ projectRoot,
741
+ outputPath: outputScip,
742
+ pnpmWorkspaces: opts.pnpmWorkspaces
743
+ });
744
+ try {
745
+ execFileSync2(binary, args, {
746
+ cwd: projectRoot,
747
+ env,
748
+ stdio: "pipe",
749
+ maxBuffer: 50 * 1024 * 1024
750
+ });
751
+ } catch (err) {
752
+ const msg = err instanceof Error ? err.message : String(err);
753
+ throw new Error(
754
+ `Failed to index ${lang} with ${config.indexerBinary}: ${msg}
755
+ Make sure ${config.indexerBinary} is installed and available on PATH.`
756
+ );
757
+ }
758
+ }
759
+ onStatus("Converting to SQLite...");
760
+ if (!existsSync3(outputScip)) {
761
+ throw new Error(`SCIP index not found at ${outputScip} after indexing`);
762
+ }
763
+ try {
764
+ execFileSync2("scip", ["expt-convert", "--output", outputDb, outputScip], {
765
+ env,
766
+ stdio: "pipe",
767
+ maxBuffer: 50 * 1024 * 1024
768
+ });
769
+ } catch (err) {
770
+ const msg = err instanceof Error ? err.message : String(err);
771
+ throw new Error(`Failed to convert SCIP index to SQLite: ${msg}`);
772
+ }
773
+ const durationMs = Date.now() - start;
774
+ onStatus(`Done in ${(durationMs / 1e3).toFixed(1)}s`);
775
+ return { languages, indexPath: outputScip, dbPath: outputDb, durationMs };
776
+ }
777
+
778
+ // src/config.ts
779
+ import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync4, mkdirSync } from "fs";
780
+ import { join as join4, resolve } from "path";
781
+ import { createHash } from "crypto";
782
+ import { homedir } from "os";
783
+ var CONFIG_FILENAME = ".scipquery.json";
784
+ var DEFAULT_WATCH = {
785
+ enabled: false,
786
+ debounceMs: 3e4,
787
+ cooldownMs: 6e4,
788
+ ignore: []
789
+ };
790
+ function loadProjectConfig(projectRoot) {
791
+ const configPath = join4(projectRoot, CONFIG_FILENAME);
792
+ if (!existsSync4(configPath)) {
793
+ return {};
794
+ }
795
+ try {
796
+ const raw = readFileSync2(configPath, "utf-8");
797
+ return JSON.parse(raw);
798
+ } catch {
799
+ return {};
800
+ }
801
+ }
802
+ function resolveWatchConfig(config) {
803
+ return {
804
+ ...DEFAULT_WATCH,
805
+ ...config.watch
806
+ };
807
+ }
808
+ function resolveCacheDir(projectRoot, config) {
809
+ const envOverride = process.env["SCIP_QUERY_CACHE_DIR"];
810
+ if (envOverride) return ensureDir(envOverride);
811
+ if (config?.dbPath) return ensureDir(resolve(projectRoot, config.dbPath));
812
+ const xdgCache = process.env["XDG_CACHE_HOME"];
813
+ const cacheBase = xdgCache || join4(homedir(), ".cache");
814
+ const projectHash = createHash("sha256").update(resolve(projectRoot)).digest("hex").slice(0, 12);
815
+ const dir = join4(cacheBase, "scip-query", "projects", projectHash);
816
+ return ensureDir(dir);
817
+ }
818
+ function resolveIndexPaths(projectRoot, config) {
819
+ const cacheDir = resolveCacheDir(projectRoot, config);
820
+ return {
821
+ cacheDir,
822
+ dbPath: join4(cacheDir, "index.db"),
823
+ indexPath: join4(cacheDir, "index.scip"),
824
+ metaPath: join4(cacheDir, "meta.json")
825
+ };
826
+ }
827
+ function initProjectConfig(projectRoot, languages) {
828
+ const configPath = join4(projectRoot, CONFIG_FILENAME);
829
+ if (existsSync4(configPath)) {
830
+ return configPath;
831
+ }
832
+ const config = {
833
+ languages,
834
+ watch: {
835
+ enabled: false,
836
+ debounceMs: 3e4,
837
+ cooldownMs: 6e4
838
+ }
839
+ };
840
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
841
+ return configPath;
842
+ }
843
+ function ensureDir(dir) {
844
+ mkdirSync(dir, { recursive: true });
845
+ return dir;
846
+ }
847
+
848
+ // src/watch.ts
849
+ import { watch } from "fs";
850
+ import { existsSync as existsSync5, renameSync } from "fs";
851
+ import { join as join5, relative } from "path";
852
+ import { fork } from "child_process";
853
+ import ignore2 from "ignore";
854
+ var Watcher = class {
855
+ projectRoot;
856
+ watchConfig;
857
+ indexPaths;
858
+ languages;
859
+ pnpmWorkspaces;
860
+ onStatus;
861
+ onReindexComplete;
862
+ onError;
863
+ // State machine
864
+ status = { state: "idle" };
865
+ debounceTimer = null;
866
+ cooldownTimer = null;
867
+ dirty = false;
868
+ changedFiles = 0;
869
+ reindexInFlight = false;
870
+ lastReindexEnd = 0;
871
+ // fs.watch watchers (one per watched directory)
872
+ fsWatchers = [];
873
+ gitignoreFilter;
874
+ extraIgnore;
875
+ stopped = false;
876
+ constructor(opts) {
877
+ this.projectRoot = opts.projectRoot;
878
+ this.watchConfig = resolveWatchConfig(opts.config);
879
+ this.indexPaths = resolveIndexPaths(opts.projectRoot, opts.config);
880
+ this.languages = opts.languages;
881
+ this.pnpmWorkspaces = opts.config.indexer?.typescript?.pnpmWorkspaces ?? false;
882
+ this.onStatus = opts.onStatus ?? (() => {
883
+ });
884
+ this.onReindexComplete = opts.onReindexComplete ?? (() => {
885
+ });
886
+ this.onError = opts.onError ?? ((e) => console.error(e.message));
887
+ this.gitignoreFilter = createGitignoreFilter(opts.projectRoot);
888
+ this.extraIgnore = ignore2();
889
+ if (this.watchConfig.ignore.length > 0) {
890
+ this.extraIgnore.add(this.watchConfig.ignore);
891
+ }
892
+ }
893
+ /** Start watching for file changes */
894
+ start() {
895
+ this.stopped = false;
896
+ this.setStatus({ state: "idle" });
897
+ try {
898
+ const watcher = watch(
899
+ this.projectRoot,
900
+ { recursive: true },
901
+ (_event, filename) => {
902
+ if (filename && !this.stopped) {
903
+ this.handleFileChange(filename);
904
+ }
905
+ }
906
+ );
907
+ this.fsWatchers.push(watcher);
908
+ } catch {
909
+ this.onError(new Error(
910
+ "Failed to start file watcher. On Linux, you may need to increase inotify limits: sysctl -w fs.inotify.max_user_watches=524288"
911
+ ));
912
+ }
913
+ }
914
+ /** Stop watching and clean up */
915
+ stop() {
916
+ this.stopped = true;
917
+ for (const w of this.fsWatchers) w.close();
918
+ this.fsWatchers = [];
919
+ if (this.debounceTimer) clearTimeout(this.debounceTimer);
920
+ if (this.cooldownTimer) clearTimeout(this.cooldownTimer);
921
+ this.setStatus({ state: "idle" });
922
+ }
923
+ /** Get current watcher status */
924
+ getStatus() {
925
+ return this.status;
926
+ }
927
+ // ── Internal ─────────────────────────────────────────────
928
+ handleFileChange(filename) {
929
+ const rel = relative(this.projectRoot, join5(this.projectRoot, filename));
930
+ if (this.gitignoreFilter.isIgnored(rel)) return;
931
+ if (this.extraIgnore.ignores(rel)) return;
932
+ if (filename.endsWith("index.db") || filename.endsWith("index.scip") || filename.endsWith("index.db.tmp") || filename.endsWith(".scipquery.json")) {
933
+ return;
934
+ }
935
+ this.changedFiles++;
936
+ if (this.reindexInFlight) {
937
+ this.dirty = true;
938
+ this.setStatus({
939
+ state: "indexing",
940
+ startedAt: this.status.startedAt
941
+ });
942
+ return;
943
+ }
944
+ if (this.status.state === "cooldown") {
945
+ this.dirty = true;
946
+ this.setStatus({ state: "cooldown", until: this.status.until, dirty: true });
947
+ return;
948
+ }
949
+ if (this.debounceTimer) clearTimeout(this.debounceTimer);
950
+ const reindexAt = Date.now() + this.watchConfig.debounceMs;
951
+ this.setStatus({ state: "waiting", changedFiles: this.changedFiles, reindexAt });
952
+ this.debounceTimer = setTimeout(() => {
953
+ this.debounceTimer = null;
954
+ this.triggerReindex();
955
+ }, this.watchConfig.debounceMs);
956
+ }
957
+ triggerReindex() {
958
+ if (this.reindexInFlight || this.stopped) return;
959
+ const timeSinceLastReindex = Date.now() - this.lastReindexEnd;
960
+ if (this.lastReindexEnd > 0 && timeSinceLastReindex < this.watchConfig.cooldownMs) {
961
+ const remaining = this.watchConfig.cooldownMs - timeSinceLastReindex;
962
+ this.dirty = true;
963
+ const until = Date.now() + remaining;
964
+ this.setStatus({ state: "cooldown", until, dirty: true });
965
+ this.cooldownTimer = setTimeout(() => {
966
+ this.cooldownTimer = null;
967
+ if (this.dirty && !this.stopped) {
968
+ this.dirty = false;
969
+ this.triggerReindex();
970
+ }
971
+ }, remaining);
972
+ return;
973
+ }
974
+ this.reindexInFlight = true;
975
+ this.dirty = false;
976
+ this.changedFiles = 0;
977
+ const startedAt = Date.now();
978
+ this.setStatus({ state: "indexing", startedAt });
979
+ this.runReindex().then((durationMs) => {
980
+ this.reindexInFlight = false;
981
+ this.lastReindexEnd = Date.now();
982
+ this.onReindexComplete(durationMs);
983
+ if (this.dirty && !this.stopped) {
984
+ const until = Date.now() + this.watchConfig.cooldownMs;
985
+ this.setStatus({ state: "cooldown", until, dirty: true });
986
+ this.cooldownTimer = setTimeout(() => {
987
+ this.cooldownTimer = null;
988
+ if (this.dirty && !this.stopped) {
989
+ this.dirty = false;
990
+ this.triggerReindex();
991
+ } else {
992
+ this.setStatus({ state: "idle" });
993
+ }
994
+ }, this.watchConfig.cooldownMs);
995
+ } else {
996
+ this.setStatus({ state: "idle" });
997
+ }
998
+ }).catch((err) => {
999
+ this.reindexInFlight = false;
1000
+ this.lastReindexEnd = Date.now();
1001
+ this.onError(err instanceof Error ? err : new Error(String(err)));
1002
+ this.setStatus({ state: "idle" });
1003
+ });
1004
+ }
1005
+ /**
1006
+ * Run the reindex in a forked child process.
1007
+ * Writes to index.db.tmp, then atomically renames to index.db.
1008
+ */
1009
+ runReindex() {
1010
+ return new Promise((resolve3, reject) => {
1011
+ const start = Date.now();
1012
+ const tmpDb = this.indexPaths.dbPath + ".tmp";
1013
+ const tmpScip = this.indexPaths.indexPath + ".tmp";
1014
+ const child = fork(
1015
+ new URL("./reindex-worker.js", import.meta.url).pathname,
1016
+ [],
1017
+ {
1018
+ env: {
1019
+ ...process.env,
1020
+ SCIP_REINDEX_PROJECT_ROOT: this.projectRoot,
1021
+ SCIP_REINDEX_OUTPUT_SCIP: tmpScip,
1022
+ SCIP_REINDEX_OUTPUT_DB: tmpDb,
1023
+ SCIP_REINDEX_LANGUAGES: this.languages?.join(",") ?? "",
1024
+ SCIP_REINDEX_PNPM_WORKSPACES: this.pnpmWorkspaces ? "1" : ""
1025
+ },
1026
+ stdio: "pipe"
1027
+ }
1028
+ );
1029
+ child.on("exit", (code2) => {
1030
+ if (code2 === 0) {
1031
+ try {
1032
+ if (existsSync5(tmpDb)) {
1033
+ renameSync(tmpDb, this.indexPaths.dbPath);
1034
+ }
1035
+ if (existsSync5(tmpScip)) {
1036
+ renameSync(tmpScip, this.indexPaths.indexPath);
1037
+ }
1038
+ resolve3(Date.now() - start);
1039
+ } catch (err) {
1040
+ reject(new Error(`Atomic swap failed: ${err}`));
1041
+ }
1042
+ } else {
1043
+ reject(new Error(`Reindex worker exited with code ${code2}`));
1044
+ }
1045
+ });
1046
+ child.on("error", reject);
1047
+ });
1048
+ }
1049
+ setStatus(status) {
1050
+ this.status = status;
1051
+ this.onStatus(status);
1052
+ }
1053
+ };
1054
+
1055
+ // src/setup.ts
1056
+ import {
1057
+ existsSync as existsSync6,
1058
+ mkdirSync as mkdirSync2,
1059
+ symlinkSync,
1060
+ readlinkSync,
1061
+ unlinkSync
1062
+ } from "fs";
1063
+ import { join as join6, dirname as dirname2, resolve as resolve2 } from "path";
1064
+ import { homedir as homedir2, platform as platform2, arch } from "os";
1065
+ import { execFileSync as execFileSync3 } from "child_process";
1066
+ import { fileURLToPath } from "url";
1067
+ var IS_WINDOWS2 = platform2() === "win32";
1068
+ var SKILLS = ["concrete-plan", "scip-explore", "scip-debloat", "scip-verify"];
1069
+ var SCIP_VERSION = "v0.7.0";
1070
+ function installSkills(opts = {}) {
1071
+ const log = opts.quiet ? () => {
1072
+ } : console.log;
1073
+ const thisFile = fileURLToPath(import.meta.url);
1074
+ const skillsSource = resolve2(dirname2(thisFile), "..", "skills");
1075
+ const targets = [
1076
+ join6(homedir2(), ".claude", "skills"),
1077
+ join6(homedir2(), ".codex", "skills")
1078
+ ];
1079
+ const result = {
1080
+ installed: [],
1081
+ skipped: [],
1082
+ alreadyLinked: []
1083
+ };
1084
+ for (const targetDir of targets) {
1085
+ const parentDir = dirname2(targetDir);
1086
+ if (!existsSync6(parentDir)) {
1087
+ continue;
1088
+ }
1089
+ mkdirSync2(targetDir, { recursive: true });
1090
+ const toolName = targetDir.includes(".codex") ? "Codex" : "Claude";
1091
+ for (const skill of SKILLS) {
1092
+ const source = join6(skillsSource, skill);
1093
+ const target = join6(targetDir, skill);
1094
+ if (!existsSync6(source)) {
1095
+ result.skipped.push(`${toolName}/${skill}`);
1096
+ continue;
1097
+ }
1098
+ if (existsSync6(target)) {
1099
+ try {
1100
+ const existing = readlinkSync(target);
1101
+ if (resolve2(existing) === resolve2(source)) {
1102
+ result.alreadyLinked.push(`${toolName}/${skill}`);
1103
+ log(` ok: ${skill} \u2192 ${toolName} (already linked)`);
1104
+ continue;
1105
+ }
1106
+ } catch {
1107
+ result.skipped.push(`${toolName}/${skill}`);
1108
+ log(` skip: ${skill} \u2192 ${toolName} (exists, not a symlink)`);
1109
+ continue;
1110
+ }
1111
+ unlinkSync(target);
1112
+ }
1113
+ symlinkSync(source, target, IS_WINDOWS2 ? "junction" : "dir");
1114
+ result.installed.push(`${toolName}/${skill}`);
1115
+ log(` done: ${skill} \u2192 ${toolName}`);
1116
+ }
1117
+ }
1118
+ return result;
1119
+ }
1120
+ function isScipInstalled() {
1121
+ try {
1122
+ const cmd = IS_WINDOWS2 ? "where" : "which";
1123
+ execFileSync3(cmd, ["scip"], { stdio: "pipe" });
1124
+ return true;
1125
+ } catch {
1126
+ return false;
1127
+ }
1128
+ }
1129
+ function getScipVersion() {
1130
+ try {
1131
+ const output = execFileSync3("scip", ["--version"], { stdio: "pipe" }).toString().trim();
1132
+ return output;
1133
+ } catch {
1134
+ return null;
1135
+ }
1136
+ }
1137
+ function getScipDownloadUrl() {
1138
+ const os = platform2();
1139
+ const cpu = arch();
1140
+ let osName;
1141
+ let archName;
1142
+ let ext;
1143
+ switch (os) {
1144
+ case "darwin":
1145
+ osName = "darwin";
1146
+ ext = "tar.gz";
1147
+ break;
1148
+ case "linux":
1149
+ osName = "linux";
1150
+ ext = "tar.gz";
1151
+ break;
1152
+ case "win32":
1153
+ osName = "windows";
1154
+ ext = "zip";
1155
+ break;
1156
+ default:
1157
+ return null;
1158
+ }
1159
+ switch (cpu) {
1160
+ case "arm64":
1161
+ archName = "arm64";
1162
+ break;
1163
+ case "x64":
1164
+ archName = "amd64";
1165
+ break;
1166
+ default:
1167
+ return null;
1168
+ }
1169
+ const filename = `scip-${osName}-${archName}.${ext}`;
1170
+ const url = `https://github.com/sourcegraph/scip/releases/download/${SCIP_VERSION}/${filename}`;
1171
+ return { url, filename };
1172
+ }
1173
+ function printScipInstallInstructions() {
1174
+ const download = getScipDownloadUrl();
1175
+ console.log("\nThe `scip` CLI is required but not found on PATH.\n");
1176
+ if (platform2() === "darwin") {
1177
+ console.log("Install via Homebrew:");
1178
+ console.log(" brew install sourcegraph/scip/scip\n");
1179
+ console.log("Or download manually:");
1180
+ } else {
1181
+ console.log("Download from:");
1182
+ }
1183
+ if (download) {
1184
+ console.log(` ${download.url}
1185
+ `);
1186
+ } else {
1187
+ console.log(` https://github.com/sourcegraph/scip/releases/tag/${SCIP_VERSION}
1188
+ `);
1189
+ }
1190
+ console.log("After installing, ensure `scip` is on your PATH and run `scip-query reindex`.");
1191
+ }
1192
+ export {
1193
+ INDEXER_CONFIGS,
1194
+ ScipDatabase,
1195
+ Watcher,
1196
+ affected,
1197
+ bottlenecks,
1198
+ byKind,
1199
+ callGraph,
1200
+ changeSurface,
1201
+ code,
1202
+ complexity,
1203
+ complexityHotspots,
1204
+ convergence,
1205
+ coupling,
1206
+ createGitignoreFilter,
1207
+ cycles,
1208
+ dataflow,
1209
+ dead,
1210
+ deepChains,
1211
+ deps,
1212
+ detectLanguages,
1213
+ diffImpact,
1214
+ docCoverage,
1215
+ drift,
1216
+ extractCandidates,
1217
+ fanIn,
1218
+ fanOut,
1219
+ files,
1220
+ getIndexerConfig,
1221
+ getScipVersion,
1222
+ health,
1223
+ hierarchy,
1224
+ hotspots,
1225
+ importedBy,
1226
+ imports,
1227
+ initProjectConfig,
1228
+ installSkills,
1229
+ isBinaryAvailable,
1230
+ isIndexerInstalled,
1231
+ isScipInstalled,
1232
+ isolated,
1233
+ kindCounts,
1234
+ leafName,
1235
+ loadProjectConfig,
1236
+ members,
1237
+ methods,
1238
+ outline,
1239
+ parseSymbol,
1240
+ passthroughCandidates,
1241
+ printScipInstallInstructions,
1242
+ rdeps,
1243
+ redundantReexports,
1244
+ refs,
1245
+ reindex,
1246
+ resolveCacheDir,
1247
+ resolveIndexPaths,
1248
+ shortenSymbol,
1249
+ similar,
1250
+ similarAll,
1251
+ similarChains,
1252
+ similarFiles,
1253
+ similarSignatures,
1254
+ slice,
1255
+ staleAbstractions,
1256
+ stats,
1257
+ surface,
1258
+ symbols,
1259
+ system,
1260
+ testCoverage,
1261
+ testCoverageSummary,
1262
+ topCoupling,
1263
+ topFanIn,
1264
+ topFanOut,
1265
+ trace,
1266
+ tryInstallIndexer,
1267
+ tryInstallScipCli,
1268
+ unusedImports,
1269
+ wrapperCandidates
1270
+ };
1271
+ //# sourceMappingURL=index.js.map