@selvakumaresra/specship 0.1.1 → 0.1.3

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 (575) hide show
  1. package/package.json +8 -7
  2. package/scripts/sync-shim-version.mjs +64 -0
  3. package/dist/bin/node-version-check.d.ts +0 -37
  4. package/dist/bin/node-version-check.d.ts.map +0 -1
  5. package/dist/bin/node-version-check.js +0 -79
  6. package/dist/bin/node-version-check.js.map +0 -1
  7. package/dist/bin/specship.d.ts +0 -25
  8. package/dist/bin/specship.d.ts.map +0 -1
  9. package/dist/bin/specship.js +0 -2018
  10. package/dist/bin/specship.js.map +0 -1
  11. package/dist/bin/uninstall.d.ts +0 -13
  12. package/dist/bin/uninstall.d.ts.map +0 -1
  13. package/dist/bin/uninstall.js +0 -35
  14. package/dist/bin/uninstall.js.map +0 -1
  15. package/dist/context/formatter.d.ts +0 -30
  16. package/dist/context/formatter.d.ts.map +0 -1
  17. package/dist/context/formatter.js +0 -263
  18. package/dist/context/formatter.js.map +0 -1
  19. package/dist/context/index.d.ts +0 -119
  20. package/dist/context/index.d.ts.map +0 -1
  21. package/dist/context/index.js +0 -1289
  22. package/dist/context/index.js.map +0 -1
  23. package/dist/context/markers.d.ts +0 -19
  24. package/dist/context/markers.d.ts.map +0 -1
  25. package/dist/context/markers.js +0 -22
  26. package/dist/context/markers.js.map +0 -1
  27. package/dist/db/index.d.ts +0 -101
  28. package/dist/db/index.d.ts.map +0 -1
  29. package/dist/db/index.js +0 -276
  30. package/dist/db/index.js.map +0 -1
  31. package/dist/db/migrations.d.ts +0 -44
  32. package/dist/db/migrations.d.ts.map +0 -1
  33. package/dist/db/migrations.js +0 -427
  34. package/dist/db/migrations.js.map +0 -1
  35. package/dist/db/queries.d.ts +0 -357
  36. package/dist/db/queries.d.ts.map +0 -1
  37. package/dist/db/queries.js +0 -1504
  38. package/dist/db/queries.js.map +0 -1
  39. package/dist/db/schema.sql +0 -410
  40. package/dist/db/spec-queries.d.ts +0 -101
  41. package/dist/db/spec-queries.d.ts.map +0 -1
  42. package/dist/db/spec-queries.js +0 -675
  43. package/dist/db/spec-queries.js.map +0 -1
  44. package/dist/db/sqlite-adapter.d.ts +0 -65
  45. package/dist/db/sqlite-adapter.d.ts.map +0 -1
  46. package/dist/db/sqlite-adapter.js +0 -214
  47. package/dist/db/sqlite-adapter.js.map +0 -1
  48. package/dist/directory.d.ts +0 -57
  49. package/dist/directory.d.ts.map +0 -1
  50. package/dist/directory.js +0 -253
  51. package/dist/directory.js.map +0 -1
  52. package/dist/errors.d.ts +0 -136
  53. package/dist/errors.d.ts.map +0 -1
  54. package/dist/errors.js +0 -219
  55. package/dist/errors.js.map +0 -1
  56. package/dist/extraction/dfm-extractor.d.ts +0 -31
  57. package/dist/extraction/dfm-extractor.d.ts.map +0 -1
  58. package/dist/extraction/dfm-extractor.js +0 -151
  59. package/dist/extraction/dfm-extractor.js.map +0 -1
  60. package/dist/extraction/generated-detection.d.ts +0 -30
  61. package/dist/extraction/generated-detection.d.ts.map +0 -1
  62. package/dist/extraction/generated-detection.js +0 -80
  63. package/dist/extraction/generated-detection.js.map +0 -1
  64. package/dist/extraction/grammars.d.ts +0 -100
  65. package/dist/extraction/grammars.d.ts.map +0 -1
  66. package/dist/extraction/grammars.js +0 -426
  67. package/dist/extraction/grammars.js.map +0 -1
  68. package/dist/extraction/index.d.ts +0 -138
  69. package/dist/extraction/index.d.ts.map +0 -1
  70. package/dist/extraction/index.js +0 -1394
  71. package/dist/extraction/index.js.map +0 -1
  72. package/dist/extraction/languages/c-cpp.d.ts +0 -4
  73. package/dist/extraction/languages/c-cpp.d.ts.map +0 -1
  74. package/dist/extraction/languages/c-cpp.js +0 -171
  75. package/dist/extraction/languages/c-cpp.js.map +0 -1
  76. package/dist/extraction/languages/csharp.d.ts +0 -3
  77. package/dist/extraction/languages/csharp.d.ts.map +0 -1
  78. package/dist/extraction/languages/csharp.js +0 -73
  79. package/dist/extraction/languages/csharp.js.map +0 -1
  80. package/dist/extraction/languages/dart.d.ts +0 -3
  81. package/dist/extraction/languages/dart.d.ts.map +0 -1
  82. package/dist/extraction/languages/dart.js +0 -192
  83. package/dist/extraction/languages/dart.js.map +0 -1
  84. package/dist/extraction/languages/go.d.ts +0 -3
  85. package/dist/extraction/languages/go.d.ts.map +0 -1
  86. package/dist/extraction/languages/go.js +0 -74
  87. package/dist/extraction/languages/go.js.map +0 -1
  88. package/dist/extraction/languages/index.d.ts +0 -10
  89. package/dist/extraction/languages/index.d.ts.map +0 -1
  90. package/dist/extraction/languages/index.js +0 -51
  91. package/dist/extraction/languages/index.js.map +0 -1
  92. package/dist/extraction/languages/java.d.ts +0 -3
  93. package/dist/extraction/languages/java.d.ts.map +0 -1
  94. package/dist/extraction/languages/java.js +0 -70
  95. package/dist/extraction/languages/java.js.map +0 -1
  96. package/dist/extraction/languages/javascript.d.ts +0 -3
  97. package/dist/extraction/languages/javascript.d.ts.map +0 -1
  98. package/dist/extraction/languages/javascript.js +0 -90
  99. package/dist/extraction/languages/javascript.js.map +0 -1
  100. package/dist/extraction/languages/kotlin.d.ts +0 -3
  101. package/dist/extraction/languages/kotlin.d.ts.map +0 -1
  102. package/dist/extraction/languages/kotlin.js +0 -259
  103. package/dist/extraction/languages/kotlin.js.map +0 -1
  104. package/dist/extraction/languages/lua.d.ts +0 -3
  105. package/dist/extraction/languages/lua.d.ts.map +0 -1
  106. package/dist/extraction/languages/lua.js +0 -150
  107. package/dist/extraction/languages/lua.js.map +0 -1
  108. package/dist/extraction/languages/luau.d.ts +0 -3
  109. package/dist/extraction/languages/luau.d.ts.map +0 -1
  110. package/dist/extraction/languages/luau.js +0 -37
  111. package/dist/extraction/languages/luau.js.map +0 -1
  112. package/dist/extraction/languages/objc.d.ts +0 -3
  113. package/dist/extraction/languages/objc.d.ts.map +0 -1
  114. package/dist/extraction/languages/objc.js +0 -133
  115. package/dist/extraction/languages/objc.js.map +0 -1
  116. package/dist/extraction/languages/pascal.d.ts +0 -3
  117. package/dist/extraction/languages/pascal.d.ts.map +0 -1
  118. package/dist/extraction/languages/pascal.js +0 -66
  119. package/dist/extraction/languages/pascal.js.map +0 -1
  120. package/dist/extraction/languages/php.d.ts +0 -3
  121. package/dist/extraction/languages/php.d.ts.map +0 -1
  122. package/dist/extraction/languages/php.js +0 -107
  123. package/dist/extraction/languages/php.js.map +0 -1
  124. package/dist/extraction/languages/python.d.ts +0 -3
  125. package/dist/extraction/languages/python.d.ts.map +0 -1
  126. package/dist/extraction/languages/python.js +0 -56
  127. package/dist/extraction/languages/python.js.map +0 -1
  128. package/dist/extraction/languages/ruby.d.ts +0 -3
  129. package/dist/extraction/languages/ruby.d.ts.map +0 -1
  130. package/dist/extraction/languages/ruby.js +0 -114
  131. package/dist/extraction/languages/ruby.js.map +0 -1
  132. package/dist/extraction/languages/rust.d.ts +0 -3
  133. package/dist/extraction/languages/rust.d.ts.map +0 -1
  134. package/dist/extraction/languages/rust.js +0 -109
  135. package/dist/extraction/languages/rust.js.map +0 -1
  136. package/dist/extraction/languages/scala.d.ts +0 -3
  137. package/dist/extraction/languages/scala.d.ts.map +0 -1
  138. package/dist/extraction/languages/scala.js +0 -139
  139. package/dist/extraction/languages/scala.js.map +0 -1
  140. package/dist/extraction/languages/swift.d.ts +0 -3
  141. package/dist/extraction/languages/swift.d.ts.map +0 -1
  142. package/dist/extraction/languages/swift.js +0 -91
  143. package/dist/extraction/languages/swift.js.map +0 -1
  144. package/dist/extraction/languages/typescript.d.ts +0 -3
  145. package/dist/extraction/languages/typescript.d.ts.map +0 -1
  146. package/dist/extraction/languages/typescript.js +0 -129
  147. package/dist/extraction/languages/typescript.js.map +0 -1
  148. package/dist/extraction/liquid-extractor.d.ts +0 -52
  149. package/dist/extraction/liquid-extractor.d.ts.map +0 -1
  150. package/dist/extraction/liquid-extractor.js +0 -313
  151. package/dist/extraction/liquid-extractor.js.map +0 -1
  152. package/dist/extraction/mybatis-extractor.d.ts +0 -48
  153. package/dist/extraction/mybatis-extractor.d.ts.map +0 -1
  154. package/dist/extraction/mybatis-extractor.js +0 -198
  155. package/dist/extraction/mybatis-extractor.js.map +0 -1
  156. package/dist/extraction/parse-worker.d.ts +0 -8
  157. package/dist/extraction/parse-worker.d.ts.map +0 -1
  158. package/dist/extraction/parse-worker.js +0 -94
  159. package/dist/extraction/parse-worker.js.map +0 -1
  160. package/dist/extraction/specs/markdown-spec-extractor.d.ts +0 -59
  161. package/dist/extraction/specs/markdown-spec-extractor.d.ts.map +0 -1
  162. package/dist/extraction/specs/markdown-spec-extractor.js +0 -327
  163. package/dist/extraction/specs/markdown-spec-extractor.js.map +0 -1
  164. package/dist/extraction/specs/types.d.ts +0 -39
  165. package/dist/extraction/specs/types.d.ts.map +0 -1
  166. package/dist/extraction/specs/types.js +0 -8
  167. package/dist/extraction/specs/types.js.map +0 -1
  168. package/dist/extraction/svelte-extractor.d.ts +0 -56
  169. package/dist/extraction/svelte-extractor.d.ts.map +0 -1
  170. package/dist/extraction/svelte-extractor.js +0 -272
  171. package/dist/extraction/svelte-extractor.js.map +0 -1
  172. package/dist/extraction/tree-sitter-helpers.d.ts +0 -28
  173. package/dist/extraction/tree-sitter-helpers.d.ts.map +0 -1
  174. package/dist/extraction/tree-sitter-helpers.js +0 -103
  175. package/dist/extraction/tree-sitter-helpers.js.map +0 -1
  176. package/dist/extraction/tree-sitter-types.d.ts +0 -193
  177. package/dist/extraction/tree-sitter-types.d.ts.map +0 -1
  178. package/dist/extraction/tree-sitter-types.js +0 -10
  179. package/dist/extraction/tree-sitter-types.js.map +0 -1
  180. package/dist/extraction/tree-sitter.d.ts +0 -317
  181. package/dist/extraction/tree-sitter.d.ts.map +0 -1
  182. package/dist/extraction/tree-sitter.js +0 -3092
  183. package/dist/extraction/tree-sitter.js.map +0 -1
  184. package/dist/extraction/vue-extractor.d.ts +0 -51
  185. package/dist/extraction/vue-extractor.d.ts.map +0 -1
  186. package/dist/extraction/vue-extractor.js +0 -251
  187. package/dist/extraction/vue-extractor.js.map +0 -1
  188. package/dist/extraction/wasm/tree-sitter-lua.wasm +0 -0
  189. package/dist/extraction/wasm/tree-sitter-luau.wasm +0 -0
  190. package/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
  191. package/dist/extraction/wasm/tree-sitter-scala.wasm +0 -0
  192. package/dist/extraction/wasm-runtime-flags.d.ts +0 -38
  193. package/dist/extraction/wasm-runtime-flags.d.ts.map +0 -1
  194. package/dist/extraction/wasm-runtime-flags.js +0 -106
  195. package/dist/extraction/wasm-runtime-flags.js.map +0 -1
  196. package/dist/graph/index.d.ts +0 -8
  197. package/dist/graph/index.d.ts.map +0 -1
  198. package/dist/graph/index.js +0 -13
  199. package/dist/graph/index.js.map +0 -1
  200. package/dist/graph/queries.d.ts +0 -106
  201. package/dist/graph/queries.d.ts.map +0 -1
  202. package/dist/graph/queries.js +0 -366
  203. package/dist/graph/queries.js.map +0 -1
  204. package/dist/graph/traversal.d.ts +0 -127
  205. package/dist/graph/traversal.d.ts.map +0 -1
  206. package/dist/graph/traversal.js +0 -531
  207. package/dist/graph/traversal.js.map +0 -1
  208. package/dist/index.d.ts +0 -551
  209. package/dist/index.d.ts.map +0 -1
  210. package/dist/index.js +0 -1165
  211. package/dist/index.js.map +0 -1
  212. package/dist/installer/config-writer.d.ts +0 -28
  213. package/dist/installer/config-writer.d.ts.map +0 -1
  214. package/dist/installer/config-writer.js +0 -91
  215. package/dist/installer/config-writer.js.map +0 -1
  216. package/dist/installer/index.d.ts +0 -87
  217. package/dist/installer/index.d.ts.map +0 -1
  218. package/dist/installer/index.js +0 -409
  219. package/dist/installer/index.js.map +0 -1
  220. package/dist/installer/instructions-template.d.ts +0 -18
  221. package/dist/installer/instructions-template.d.ts.map +0 -1
  222. package/dist/installer/instructions-template.js +0 -21
  223. package/dist/installer/instructions-template.js.map +0 -1
  224. package/dist/installer/targets/claude.d.ts +0 -88
  225. package/dist/installer/targets/claude.d.ts.map +0 -1
  226. package/dist/installer/targets/claude.js +0 -582
  227. package/dist/installer/targets/claude.js.map +0 -1
  228. package/dist/installer/targets/registry.d.ts +0 -19
  229. package/dist/installer/targets/registry.d.ts.map +0 -1
  230. package/dist/installer/targets/registry.js +0 -31
  231. package/dist/installer/targets/registry.js.map +0 -1
  232. package/dist/installer/targets/shared.d.ts +0 -62
  233. package/dist/installer/targets/shared.d.ts.map +0 -1
  234. package/dist/installer/targets/shared.js +0 -207
  235. package/dist/installer/targets/shared.js.map +0 -1
  236. package/dist/installer/targets/types.d.ts +0 -76
  237. package/dist/installer/targets/types.d.ts.map +0 -1
  238. package/dist/installer/targets/types.js +0 -12
  239. package/dist/installer/targets/types.js.map +0 -1
  240. package/dist/isolation/worktree.d.ts +0 -65
  241. package/dist/isolation/worktree.d.ts.map +0 -1
  242. package/dist/isolation/worktree.js +0 -231
  243. package/dist/isolation/worktree.js.map +0 -1
  244. package/dist/mcp/daemon-paths.d.ts +0 -46
  245. package/dist/mcp/daemon-paths.d.ts.map +0 -1
  246. package/dist/mcp/daemon-paths.js +0 -125
  247. package/dist/mcp/daemon-paths.js.map +0 -1
  248. package/dist/mcp/daemon.d.ts +0 -161
  249. package/dist/mcp/daemon.d.ts.map +0 -1
  250. package/dist/mcp/daemon.js +0 -403
  251. package/dist/mcp/daemon.js.map +0 -1
  252. package/dist/mcp/engine.d.ts +0 -105
  253. package/dist/mcp/engine.d.ts.map +0 -1
  254. package/dist/mcp/engine.js +0 -270
  255. package/dist/mcp/engine.js.map +0 -1
  256. package/dist/mcp/index.d.ts +0 -112
  257. package/dist/mcp/index.d.ts.map +0 -1
  258. package/dist/mcp/index.js +0 -477
  259. package/dist/mcp/index.js.map +0 -1
  260. package/dist/mcp/proxy.d.ts +0 -81
  261. package/dist/mcp/proxy.d.ts.map +0 -1
  262. package/dist/mcp/proxy.js +0 -510
  263. package/dist/mcp/proxy.js.map +0 -1
  264. package/dist/mcp/server-instructions.d.ts +0 -18
  265. package/dist/mcp/server-instructions.d.ts.map +0 -1
  266. package/dist/mcp/server-instructions.js +0 -77
  267. package/dist/mcp/server-instructions.js.map +0 -1
  268. package/dist/mcp/session.d.ts +0 -77
  269. package/dist/mcp/session.d.ts.map +0 -1
  270. package/dist/mcp/session.js +0 -294
  271. package/dist/mcp/session.js.map +0 -1
  272. package/dist/mcp/spec-tools.d.ts +0 -39
  273. package/dist/mcp/spec-tools.d.ts.map +0 -1
  274. package/dist/mcp/spec-tools.js +0 -326
  275. package/dist/mcp/spec-tools.js.map +0 -1
  276. package/dist/mcp/tools.d.ts +0 -404
  277. package/dist/mcp/tools.d.ts.map +0 -1
  278. package/dist/mcp/tools.js +0 -3066
  279. package/dist/mcp/tools.js.map +0 -1
  280. package/dist/mcp/transport.d.ts +0 -188
  281. package/dist/mcp/transport.d.ts.map +0 -1
  282. package/dist/mcp/transport.js +0 -343
  283. package/dist/mcp/transport.js.map +0 -1
  284. package/dist/mcp/version.d.ts +0 -19
  285. package/dist/mcp/version.d.ts.map +0 -1
  286. package/dist/mcp/version.js +0 -71
  287. package/dist/mcp/version.js.map +0 -1
  288. package/dist/resolution/callback-synthesizer.d.ts +0 -10
  289. package/dist/resolution/callback-synthesizer.d.ts.map +0 -1
  290. package/dist/resolution/callback-synthesizer.js +0 -1300
  291. package/dist/resolution/callback-synthesizer.js.map +0 -1
  292. package/dist/resolution/frameworks/cargo-workspace.d.ts +0 -18
  293. package/dist/resolution/frameworks/cargo-workspace.d.ts.map +0 -1
  294. package/dist/resolution/frameworks/cargo-workspace.js +0 -225
  295. package/dist/resolution/frameworks/cargo-workspace.js.map +0 -1
  296. package/dist/resolution/frameworks/csharp.d.ts +0 -8
  297. package/dist/resolution/frameworks/csharp.d.ts.map +0 -1
  298. package/dist/resolution/frameworks/csharp.js +0 -241
  299. package/dist/resolution/frameworks/csharp.js.map +0 -1
  300. package/dist/resolution/frameworks/drupal.d.ts +0 -51
  301. package/dist/resolution/frameworks/drupal.d.ts.map +0 -1
  302. package/dist/resolution/frameworks/drupal.js +0 -367
  303. package/dist/resolution/frameworks/drupal.js.map +0 -1
  304. package/dist/resolution/frameworks/expo-modules.d.ts +0 -3
  305. package/dist/resolution/frameworks/expo-modules.d.ts.map +0 -1
  306. package/dist/resolution/frameworks/expo-modules.js +0 -143
  307. package/dist/resolution/frameworks/expo-modules.js.map +0 -1
  308. package/dist/resolution/frameworks/express.d.ts +0 -8
  309. package/dist/resolution/frameworks/express.d.ts.map +0 -1
  310. package/dist/resolution/frameworks/express.js +0 -308
  311. package/dist/resolution/frameworks/express.js.map +0 -1
  312. package/dist/resolution/frameworks/fabric.d.ts +0 -3
  313. package/dist/resolution/frameworks/fabric.d.ts.map +0 -1
  314. package/dist/resolution/frameworks/fabric.js +0 -354
  315. package/dist/resolution/frameworks/fabric.js.map +0 -1
  316. package/dist/resolution/frameworks/go.d.ts +0 -8
  317. package/dist/resolution/frameworks/go.d.ts.map +0 -1
  318. package/dist/resolution/frameworks/go.js +0 -161
  319. package/dist/resolution/frameworks/go.js.map +0 -1
  320. package/dist/resolution/frameworks/index.d.ts +0 -48
  321. package/dist/resolution/frameworks/index.d.ts.map +0 -1
  322. package/dist/resolution/frameworks/index.js +0 -161
  323. package/dist/resolution/frameworks/index.js.map +0 -1
  324. package/dist/resolution/frameworks/java.d.ts +0 -8
  325. package/dist/resolution/frameworks/java.d.ts.map +0 -1
  326. package/dist/resolution/frameworks/java.js +0 -504
  327. package/dist/resolution/frameworks/java.js.map +0 -1
  328. package/dist/resolution/frameworks/laravel.d.ts +0 -13
  329. package/dist/resolution/frameworks/laravel.d.ts.map +0 -1
  330. package/dist/resolution/frameworks/laravel.js +0 -257
  331. package/dist/resolution/frameworks/laravel.js.map +0 -1
  332. package/dist/resolution/frameworks/nestjs.d.ts +0 -26
  333. package/dist/resolution/frameworks/nestjs.d.ts.map +0 -1
  334. package/dist/resolution/frameworks/nestjs.js +0 -698
  335. package/dist/resolution/frameworks/nestjs.js.map +0 -1
  336. package/dist/resolution/frameworks/play.d.ts +0 -19
  337. package/dist/resolution/frameworks/play.d.ts.map +0 -1
  338. package/dist/resolution/frameworks/play.js +0 -111
  339. package/dist/resolution/frameworks/play.js.map +0 -1
  340. package/dist/resolution/frameworks/python.d.ts +0 -10
  341. package/dist/resolution/frameworks/python.d.ts.map +0 -1
  342. package/dist/resolution/frameworks/python.js +0 -396
  343. package/dist/resolution/frameworks/python.js.map +0 -1
  344. package/dist/resolution/frameworks/react-native.d.ts +0 -3
  345. package/dist/resolution/frameworks/react-native.d.ts.map +0 -1
  346. package/dist/resolution/frameworks/react-native.js +0 -360
  347. package/dist/resolution/frameworks/react-native.js.map +0 -1
  348. package/dist/resolution/frameworks/react.d.ts +0 -8
  349. package/dist/resolution/frameworks/react.d.ts.map +0 -1
  350. package/dist/resolution/frameworks/react.js +0 -365
  351. package/dist/resolution/frameworks/react.js.map +0 -1
  352. package/dist/resolution/frameworks/ruby.d.ts +0 -8
  353. package/dist/resolution/frameworks/ruby.d.ts.map +0 -1
  354. package/dist/resolution/frameworks/ruby.js +0 -302
  355. package/dist/resolution/frameworks/ruby.js.map +0 -1
  356. package/dist/resolution/frameworks/rust.d.ts +0 -8
  357. package/dist/resolution/frameworks/rust.d.ts.map +0 -1
  358. package/dist/resolution/frameworks/rust.js +0 -304
  359. package/dist/resolution/frameworks/rust.js.map +0 -1
  360. package/dist/resolution/frameworks/svelte.d.ts +0 -9
  361. package/dist/resolution/frameworks/svelte.d.ts.map +0 -1
  362. package/dist/resolution/frameworks/svelte.js +0 -249
  363. package/dist/resolution/frameworks/svelte.js.map +0 -1
  364. package/dist/resolution/frameworks/swift-objc.d.ts +0 -37
  365. package/dist/resolution/frameworks/swift-objc.d.ts.map +0 -1
  366. package/dist/resolution/frameworks/swift-objc.js +0 -252
  367. package/dist/resolution/frameworks/swift-objc.js.map +0 -1
  368. package/dist/resolution/frameworks/swift.d.ts +0 -10
  369. package/dist/resolution/frameworks/swift.d.ts.map +0 -1
  370. package/dist/resolution/frameworks/swift.js +0 -400
  371. package/dist/resolution/frameworks/swift.js.map +0 -1
  372. package/dist/resolution/frameworks/vue.d.ts +0 -9
  373. package/dist/resolution/frameworks/vue.d.ts.map +0 -1
  374. package/dist/resolution/frameworks/vue.js +0 -306
  375. package/dist/resolution/frameworks/vue.js.map +0 -1
  376. package/dist/resolution/go-module.d.ts +0 -26
  377. package/dist/resolution/go-module.d.ts.map +0 -1
  378. package/dist/resolution/go-module.js +0 -78
  379. package/dist/resolution/go-module.js.map +0 -1
  380. package/dist/resolution/import-resolver.d.ts +0 -68
  381. package/dist/resolution/import-resolver.d.ts.map +0 -1
  382. package/dist/resolution/import-resolver.js +0 -1275
  383. package/dist/resolution/import-resolver.js.map +0 -1
  384. package/dist/resolution/index.d.ts +0 -117
  385. package/dist/resolution/index.d.ts.map +0 -1
  386. package/dist/resolution/index.js +0 -895
  387. package/dist/resolution/index.js.map +0 -1
  388. package/dist/resolution/lru-cache.d.ts +0 -24
  389. package/dist/resolution/lru-cache.d.ts.map +0 -1
  390. package/dist/resolution/lru-cache.js +0 -62
  391. package/dist/resolution/lru-cache.js.map +0 -1
  392. package/dist/resolution/name-matcher.d.ts +0 -32
  393. package/dist/resolution/name-matcher.d.ts.map +0 -1
  394. package/dist/resolution/name-matcher.js +0 -596
  395. package/dist/resolution/name-matcher.js.map +0 -1
  396. package/dist/resolution/path-aliases.d.ts +0 -68
  397. package/dist/resolution/path-aliases.d.ts.map +0 -1
  398. package/dist/resolution/path-aliases.js +0 -238
  399. package/dist/resolution/path-aliases.js.map +0 -1
  400. package/dist/resolution/spec-link-resolver.d.ts +0 -103
  401. package/dist/resolution/spec-link-resolver.d.ts.map +0 -1
  402. package/dist/resolution/spec-link-resolver.js +0 -259
  403. package/dist/resolution/spec-link-resolver.js.map +0 -1
  404. package/dist/resolution/strip-comments.d.ts +0 -27
  405. package/dist/resolution/strip-comments.d.ts.map +0 -1
  406. package/dist/resolution/strip-comments.js +0 -441
  407. package/dist/resolution/strip-comments.js.map +0 -1
  408. package/dist/resolution/swift-objc-bridge.d.ts +0 -134
  409. package/dist/resolution/swift-objc-bridge.d.ts.map +0 -1
  410. package/dist/resolution/swift-objc-bridge.js +0 -256
  411. package/dist/resolution/swift-objc-bridge.js.map +0 -1
  412. package/dist/resolution/types.d.ts +0 -216
  413. package/dist/resolution/types.d.ts.map +0 -1
  414. package/dist/resolution/types.js +0 -8
  415. package/dist/resolution/types.js.map +0 -1
  416. package/dist/resolution/workspace-packages.d.ts +0 -48
  417. package/dist/resolution/workspace-packages.d.ts.map +0 -1
  418. package/dist/resolution/workspace-packages.js +0 -208
  419. package/dist/resolution/workspace-packages.js.map +0 -1
  420. package/dist/search/query-parser.d.ts +0 -57
  421. package/dist/search/query-parser.d.ts.map +0 -1
  422. package/dist/search/query-parser.js +0 -177
  423. package/dist/search/query-parser.js.map +0 -1
  424. package/dist/search/query-utils.d.ts +0 -71
  425. package/dist/search/query-utils.d.ts.map +0 -1
  426. package/dist/search/query-utils.js +0 -380
  427. package/dist/search/query-utils.js.map +0 -1
  428. package/dist/server/cli.js +0 -152
  429. package/dist/server/index.js +0 -12
  430. package/dist/server/ingest/index.js +0 -18
  431. package/dist/server/ingest/ingestor.js +0 -406
  432. package/dist/server/ingest/parser.js +0 -104
  433. package/dist/server/ingest/pricing.js +0 -78
  434. package/dist/server/ingest/types.js +0 -9
  435. package/dist/server/ingest/watcher.js +0 -77
  436. package/dist/server/package.json +0 -3
  437. package/dist/server/project-registry.js +0 -101
  438. package/dist/server/routes/claude.js +0 -480
  439. package/dist/server/routes/graph.js +0 -149
  440. package/dist/server/routes/memory.js +0 -272
  441. package/dist/server/routes/projects.js +0 -197
  442. package/dist/server/routes/spec.js +0 -105
  443. package/dist/server/routes/status.js +0 -35
  444. package/dist/server/routes/workflow.js +0 -184
  445. package/dist/server/server.js +0 -202
  446. package/dist/sync/git-hooks.d.ts +0 -45
  447. package/dist/sync/git-hooks.d.ts.map +0 -1
  448. package/dist/sync/git-hooks.js +0 -225
  449. package/dist/sync/git-hooks.js.map +0 -1
  450. package/dist/sync/index.d.ts +0 -19
  451. package/dist/sync/index.d.ts.map +0 -1
  452. package/dist/sync/index.js +0 -35
  453. package/dist/sync/index.js.map +0 -1
  454. package/dist/sync/watch-policy.d.ts +0 -48
  455. package/dist/sync/watch-policy.d.ts.map +0 -1
  456. package/dist/sync/watch-policy.js +0 -124
  457. package/dist/sync/watch-policy.js.map +0 -1
  458. package/dist/sync/watcher.d.ts +0 -283
  459. package/dist/sync/watcher.d.ts.map +0 -1
  460. package/dist/sync/watcher.js +0 -606
  461. package/dist/sync/watcher.js.map +0 -1
  462. package/dist/sync/worktree.d.ts +0 -54
  463. package/dist/sync/worktree.d.ts.map +0 -1
  464. package/dist/sync/worktree.js +0 -137
  465. package/dist/sync/worktree.js.map +0 -1
  466. package/dist/types.d.ts +0 -623
  467. package/dist/types.d.ts.map +0 -1
  468. package/dist/types.js +0 -108
  469. package/dist/types.js.map +0 -1
  470. package/dist/ui/glyphs.d.ts +0 -42
  471. package/dist/ui/glyphs.d.ts.map +0 -1
  472. package/dist/ui/glyphs.js +0 -78
  473. package/dist/ui/glyphs.js.map +0 -1
  474. package/dist/ui/shimmer-progress.d.ts +0 -11
  475. package/dist/ui/shimmer-progress.d.ts.map +0 -1
  476. package/dist/ui/shimmer-progress.js +0 -90
  477. package/dist/ui/shimmer-progress.js.map +0 -1
  478. package/dist/ui/shimmer-worker.d.ts +0 -2
  479. package/dist/ui/shimmer-worker.d.ts.map +0 -1
  480. package/dist/ui/shimmer-worker.js +0 -118
  481. package/dist/ui/shimmer-worker.js.map +0 -1
  482. package/dist/ui/types.d.ts +0 -17
  483. package/dist/ui/types.d.ts.map +0 -1
  484. package/dist/ui/types.js +0 -3
  485. package/dist/ui/types.js.map +0 -1
  486. package/dist/utils.d.ts +0 -205
  487. package/dist/utils.d.ts.map +0 -1
  488. package/dist/utils.js +0 -549
  489. package/dist/utils.js.map +0 -1
  490. package/dist/web/chunk-2YZXEHZ2.js +0 -1
  491. package/dist/web/chunk-3GIC555L.js +0 -18
  492. package/dist/web/chunk-3IIIGRMT.js +0 -1
  493. package/dist/web/chunk-47QYKLE5.js +0 -1
  494. package/dist/web/chunk-4LHBWWP7.js +0 -1
  495. package/dist/web/chunk-4OAZLD5W.js +0 -1
  496. package/dist/web/chunk-5OQKAJAE.js +0 -1
  497. package/dist/web/chunk-7B525GKQ.js +0 -1
  498. package/dist/web/chunk-BPDXCOOZ.js +0 -1
  499. package/dist/web/chunk-DT37HTZB.js +0 -1
  500. package/dist/web/chunk-EIMUHJND.js +0 -1
  501. package/dist/web/chunk-FTESTUEO.js +0 -1
  502. package/dist/web/chunk-GLJZV6MU.js +0 -1
  503. package/dist/web/chunk-I7LS67U5.js +0 -1
  504. package/dist/web/chunk-L4TVIPSR.js +0 -1
  505. package/dist/web/chunk-MASCULC2.js +0 -1
  506. package/dist/web/chunk-MW7ICSRM.js +0 -1
  507. package/dist/web/chunk-OI5VP2A3.js +0 -1
  508. package/dist/web/chunk-RA6EBF6I.js +0 -1
  509. package/dist/web/chunk-RP3WU5Y6.js +0 -1
  510. package/dist/web/chunk-RQDRMTXN.js +0 -1
  511. package/dist/web/chunk-TQMT6UDU.js +0 -1
  512. package/dist/web/chunk-U7IYOV7T.js +0 -1
  513. package/dist/web/chunk-UE227MWF.js +0 -1
  514. package/dist/web/chunk-WV573J4K.js +0 -1
  515. package/dist/web/chunk-WVCKOJZL.js +0 -4
  516. package/dist/web/chunk-XZKLVPHE.js +0 -1
  517. package/dist/web/chunk-ZABKKHJ3.js +0 -1
  518. package/dist/web/favicon-16.png +0 -0
  519. package/dist/web/favicon-180.png +0 -0
  520. package/dist/web/favicon-32.png +0 -0
  521. package/dist/web/favicon-512.png +0 -0
  522. package/dist/web/favicon-small.svg +0 -15
  523. package/dist/web/favicon.ico +0 -0
  524. package/dist/web/favicon.svg +0 -20
  525. package/dist/web/index.html +0 -145
  526. package/dist/web/main-RI5CO5Z4.js +0 -1
  527. package/dist/web/styles-CYN7IKT4.css +0 -1
  528. package/dist/workflows/condition-evaluator.d.ts +0 -75
  529. package/dist/workflows/condition-evaluator.d.ts.map +0 -1
  530. package/dist/workflows/condition-evaluator.js +0 -282
  531. package/dist/workflows/condition-evaluator.js.map +0 -1
  532. package/dist/workflows/defaults/index.d.ts +0 -26
  533. package/dist/workflows/defaults/index.d.ts.map +0 -1
  534. package/dist/workflows/defaults/index.js +0 -94
  535. package/dist/workflows/defaults/index.js.map +0 -1
  536. package/dist/workflows/defaults/spec-fix.yaml +0 -110
  537. package/dist/workflows/defaults/spec-implement.yaml +0 -150
  538. package/dist/workflows/defaults/spec-relink.yaml +0 -81
  539. package/dist/workflows/defaults/spec-verify.yaml +0 -51
  540. package/dist/workflows/discovery.d.ts +0 -46
  541. package/dist/workflows/discovery.d.ts.map +0 -1
  542. package/dist/workflows/discovery.js +0 -193
  543. package/dist/workflows/discovery.js.map +0 -1
  544. package/dist/workflows/executor.d.ts +0 -83
  545. package/dist/workflows/executor.d.ts.map +0 -1
  546. package/dist/workflows/executor.js +0 -623
  547. package/dist/workflows/executor.js.map +0 -1
  548. package/dist/workflows/runners/approval.d.ts +0 -18
  549. package/dist/workflows/runners/approval.d.ts.map +0 -1
  550. package/dist/workflows/runners/approval.js +0 -34
  551. package/dist/workflows/runners/approval.js.map +0 -1
  552. package/dist/workflows/runners/bash.d.ts +0 -13
  553. package/dist/workflows/runners/bash.d.ts.map +0 -1
  554. package/dist/workflows/runners/bash.js +0 -143
  555. package/dist/workflows/runners/bash.js.map +0 -1
  556. package/dist/workflows/runners/cancel.d.ts +0 -10
  557. package/dist/workflows/runners/cancel.d.ts.map +0 -1
  558. package/dist/workflows/runners/cancel.js +0 -19
  559. package/dist/workflows/runners/cancel.js.map +0 -1
  560. package/dist/workflows/runners/prompt.d.ts +0 -28
  561. package/dist/workflows/runners/prompt.d.ts.map +0 -1
  562. package/dist/workflows/runners/prompt.js +0 -212
  563. package/dist/workflows/runners/prompt.js.map +0 -1
  564. package/dist/workflows/runners/script.d.ts +0 -17
  565. package/dist/workflows/runners/script.d.ts.map +0 -1
  566. package/dist/workflows/runners/script.js +0 -155
  567. package/dist/workflows/runners/script.js.map +0 -1
  568. package/dist/workflows/runners/types.d.ts +0 -51
  569. package/dist/workflows/runners/types.d.ts.map +0 -1
  570. package/dist/workflows/runners/types.js +0 -13
  571. package/dist/workflows/runners/types.js.map +0 -1
  572. package/dist/workflows/schemas/workflow.d.ts +0 -166
  573. package/dist/workflows/schemas/workflow.d.ts.map +0 -1
  574. package/dist/workflows/schemas/workflow.js +0 -437
  575. package/dist/workflows/schemas/workflow.js.map +0 -1
@@ -1,1394 +0,0 @@
1
- "use strict";
2
- /**
3
- * Extraction Orchestrator
4
- *
5
- * Coordinates file scanning, parsing, and database storage.
6
- */
7
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
- if (k2 === undefined) k2 = k;
9
- var desc = Object.getOwnPropertyDescriptor(m, k);
10
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
- desc = { enumerable: true, get: function() { return m[k]; } };
12
- }
13
- Object.defineProperty(o, k2, desc);
14
- }) : (function(o, m, k, k2) {
15
- if (k2 === undefined) k2 = k;
16
- o[k2] = m[k];
17
- }));
18
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
- Object.defineProperty(o, "default", { enumerable: true, value: v });
20
- }) : function(o, v) {
21
- o["default"] = v;
22
- });
23
- var __importStar = (this && this.__importStar) || (function () {
24
- var ownKeys = function(o) {
25
- ownKeys = Object.getOwnPropertyNames || function (o) {
26
- var ar = [];
27
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
- return ar;
29
- };
30
- return ownKeys(o);
31
- };
32
- return function (mod) {
33
- if (mod && mod.__esModule) return mod;
34
- var result = {};
35
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
- __setModuleDefault(result, mod);
37
- return result;
38
- };
39
- })();
40
- var __importDefault = (this && this.__importDefault) || function (mod) {
41
- return (mod && mod.__esModule) ? mod : { "default": mod };
42
- };
43
- Object.defineProperty(exports, "__esModule", { value: true });
44
- exports.loadAllGrammars = exports.loadGrammarsForLanguages = exports.initGrammars = exports.getSupportedLanguages = exports.isGrammarLoaded = exports.isLanguageSupported = exports.isSourceFile = exports.detectLanguage = exports.extractFromSource = exports.ExtractionOrchestrator = void 0;
45
- exports.hashContent = hashContent;
46
- exports.buildDefaultIgnore = buildDefaultIgnore;
47
- exports.scanDirectory = scanDirectory;
48
- exports.scanDirectoryAsync = scanDirectoryAsync;
49
- const fs = __importStar(require("fs"));
50
- const fsp = __importStar(require("fs/promises"));
51
- const path = __importStar(require("path"));
52
- const crypto = __importStar(require("crypto"));
53
- const child_process_1 = require("child_process");
54
- const tree_sitter_1 = require("./tree-sitter");
55
- const grammars_1 = require("./grammars");
56
- const errors_1 = require("../errors");
57
- const utils_1 = require("../utils");
58
- const ignore_1 = __importDefault(require("ignore"));
59
- const frameworks_1 = require("../resolution/frameworks");
60
- /**
61
- * Number of files to read in parallel during indexing.
62
- * File reads are I/O-bound; batching overlaps I/O wait with CPU parse work.
63
- */
64
- const FILE_IO_BATCH_SIZE = 10;
65
- // PARSER_RESET_INTERVAL moved to parse-worker.ts (runs in worker thread)
66
- /**
67
- * Maximum time (ms) to wait for a single file to parse in the worker thread.
68
- * If tree-sitter hangs or WASM runs out of memory, this prevents the entire
69
- * indexing run from freezing. The worker is restarted after a timeout.
70
- */
71
- const PARSE_TIMEOUT_MS = 10_000;
72
- /**
73
- * Number of files to parse before recycling the worker thread.
74
- * WASM linear memory can grow but NEVER shrink (WebAssembly spec limitation).
75
- * The only way to reclaim tree-sitter's WASM heap is to destroy the entire
76
- * V8 isolate by terminating the worker thread and spawning a fresh one.
77
- * This interval balances memory usage against the cost of reloading grammars.
78
- */
79
- const WORKER_RECYCLE_INTERVAL = 250;
80
- /**
81
- * Calculate SHA256 hash of file contents
82
- */
83
- function hashContent(content) {
84
- return crypto.createHash('sha256').update(content).digest('hex');
85
- }
86
- /**
87
- * Skip files larger than this (bytes). Generated bundles, minified JS, and
88
- * vendored blobs blow the WASM heap and the worker-recycle budget for no useful
89
- * symbols. 1 MB covers essentially all hand-written source.
90
- */
91
- const MAX_FILE_SIZE = 1024 * 1024;
92
- /**
93
- * Directory names that are dependency, build, cache, or tooling output across the
94
- * languages/frameworks SpecShip supports — curated from the canonical
95
- * github/gitignore templates. Excluded by default so the graph reflects your code,
96
- * not third-party noise, without requiring a `.gitignore` (issue #407). The
97
- * exclusion applies uniformly (git or not, tracked or not); the only opt-in is an
98
- * explicit `.gitignore` negation (e.g. `!vendor/`). First-party-prone or generic
99
- * names (`packages`, `lib`, `app`, `bin`, `src`, `deps`, `env`, `tmp`, `storage`,
100
- * `Library`) are deliberately NOT listed, to avoid ever hiding real source.
101
- *
102
- * Only dirs that actually contain *indexable source* (or are enormous) earn a slot
103
- * — IDE/state dirs like `.idea`/`.vs` are omitted because SpecShip indexes only
104
- * recognized source extensions, so they produce no symbols regardless.
105
- */
106
- const DEFAULT_IGNORE_DIRS = new Set([
107
- // JS / TS — dependency directories
108
- 'node_modules', 'bower_components', 'jspm_packages', 'web_modules',
109
- '.yarn', '.pnpm-store',
110
- // JS / TS — framework & bundler build / cache / deploy output
111
- '.next', '.nuxt', '.svelte-kit', '.turbo', '.vite', '.parcel-cache', '.angular',
112
- '.docusaurus', 'storybook-static', '.vinxi', '.nitro', 'out-tsc',
113
- '.vercel', '.netlify', '.wrangler',
114
- // Build output (common across ecosystems)
115
- 'dist', 'build', 'out', '.output',
116
- // Test / coverage
117
- 'coverage', '.nyc_output',
118
- // Python
119
- '__pycache__', '__pypackages__', '.venv', 'venv', '.pixi', '.pdm-build',
120
- '.mypy_cache', '.pytest_cache', '.ruff_cache', '.tox', '.nox', '.hypothesis',
121
- '.ipynb_checkpoints', '.eggs',
122
- // Rust / JVM (Maven, Gradle, Scala)
123
- 'target', '.gradle',
124
- // .NET
125
- 'obj',
126
- // Vendored deps (Go, PHP/Composer, Ruby/Bundler)
127
- 'vendor',
128
- // Swift / iOS
129
- '.build', 'Pods', 'Carthage', 'DerivedData', '.swiftpm',
130
- // Dart / Flutter
131
- '.dart_tool', '.pub-cache',
132
- // Native (Android NDK, C/C++ deps)
133
- '.cxx', '.externalNativeBuild', 'vcpkg_installed',
134
- // Scala tooling
135
- '.bloop', '.metals',
136
- // Lua / Luau (LuaRocks)
137
- 'lua_modules', '.luarocks',
138
- // Delphi / RAD Studio IDE backups (duplicate .pas source — would double-count)
139
- '__history', '__recovery',
140
- // Generic cache
141
- '.cache',
142
- ]);
143
- /** Gitignore-style patterns for the `ignore` matcher: the dirs above plus a few globs. */
144
- const DEFAULT_IGNORE_PATTERNS = [
145
- ...Array.from(DEFAULT_IGNORE_DIRS, (d) => `${d}/`),
146
- '*.egg-info/', // Python packaging metadata
147
- 'cmake-build-*/', // CLion / CMake build trees
148
- 'bazel-*/', // Bazel output symlink trees
149
- ];
150
- /**
151
- * An `ignore` matcher seeded with the built-in defaults, merged with the project's
152
- * root .gitignore so a negation there (e.g. `!vendor/`) overrides a default. Shared
153
- * by both enumeration paths so behavior is identical with or without git — and so
154
- * the defaults apply to tracked files too (committing a dependency dir doesn't make
155
- * it project code; the explicit `.gitignore` negation is the only opt-in).
156
- */
157
- function buildDefaultIgnore(rootDir) {
158
- const ig = (0, ignore_1.default)().add(DEFAULT_IGNORE_PATTERNS);
159
- try {
160
- const rootGitignore = path.join(rootDir, '.gitignore');
161
- if (fs.existsSync(rootGitignore))
162
- ig.add(fs.readFileSync(rootGitignore, 'utf-8'));
163
- }
164
- catch {
165
- // Unreadable root .gitignore — the built-in defaults still apply.
166
- }
167
- return ig;
168
- }
169
- /**
170
- * Collect git-visible files (tracked + untracked, .gitignore-respected) from the
171
- * git repository rooted at `repoDir`, adding each to `files` with `prefix`
172
- * prepended so paths stay relative to the original scan root.
173
- *
174
- * Recurses into embedded git repositories — nested repos that are NOT submodules
175
- * (independent clones living inside the workspace, common in CMake "super-repo"
176
- * layouts). The parent repo's `git ls-files` cannot see into them: tracked output
177
- * skips them entirely, and untracked output reports them only as an opaque
178
- * "subdir/" entry (trailing slash) rather than expanding their files. Each
179
- * embedded repo is its own git boundary, so we re-run `git ls-files` inside it.
180
- * (See issue #193.)
181
- */
182
- function collectGitFiles(repoDir, prefix, files) {
183
- const gitOpts = { cwd: repoDir, encoding: 'utf-8', timeout: 30000, maxBuffer: 50 * 1024 * 1024, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true };
184
- // Tracked files. --recurse-submodules pulls in files from active submodules,
185
- // which the index would otherwise represent only as a commit pointer.
186
- // Without this, monorepos using submodules index 0 files. (See issue #147.)
187
- // Note: --recurse-submodules only supports -c/--cached and --stage modes — it
188
- // can't be combined with -o, so untracked files are gathered separately below.
189
- // -z gives NUL-separated, unquoted output so non-ASCII (e.g. CJK) paths
190
- // survive verbatim. Without it git octal-escapes and double-quotes such paths
191
- // (the core.quotepath default), and the quoted form never matches a real file
192
- // on disk → those files are silently dropped from the index. (#541)
193
- const tracked = (0, child_process_1.execFileSync)('git', ['ls-files', '-z', '-c', '--recurse-submodules'], gitOpts);
194
- for (const rel of tracked.split('\0')) {
195
- if (rel)
196
- files.add((0, utils_1.normalizePath)(prefix + rel));
197
- }
198
- // Untracked files (submodules manage their own untracked state). Embedded git
199
- // repos surface here as a single "subdir/" entry that git refuses to descend
200
- // into — recurse into those as their own repos so their source gets indexed.
201
- const untracked = (0, child_process_1.execFileSync)('git', ['ls-files', '-z', '-o', '--exclude-standard'], gitOpts);
202
- for (const rel of untracked.split('\0')) {
203
- if (!rel)
204
- continue;
205
- if (rel.endsWith('/')) {
206
- // git only emits a trailing-slash directory entry for an embedded repo.
207
- // Guard with a .git check anyway, and skip anything else exactly as git
208
- // itself skips it (we never descend into a non-repo opaque dir).
209
- const childDir = path.join(repoDir, rel);
210
- if (fs.existsSync(path.join(childDir, '.git'))) {
211
- collectGitFiles(childDir, prefix + rel, files);
212
- }
213
- continue;
214
- }
215
- files.add((0, utils_1.normalizePath)(prefix + rel));
216
- }
217
- }
218
- /**
219
- * Get all files visible to git (tracked + untracked but not ignored).
220
- * Respects .gitignore at all levels (root, subdirectories) and descends into
221
- * embedded (nested, non-submodule) git repos. Returns null on failure
222
- * (non-git project) so callers can fall back to a filesystem walk.
223
- */
224
- function getGitVisibleFiles(rootDir) {
225
- try {
226
- // Check if the project directory is gitignored by a parent repo.
227
- // When rootDir lives inside a parent git repo that ignores it,
228
- // `git ls-files` returns nothing — fall back to filesystem walk.
229
- const gitRoot = (0, child_process_1.execFileSync)('git', ['rev-parse', '--show-toplevel'], { cwd: rootDir, encoding: 'utf-8', timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true }).trim();
230
- if (path.resolve(gitRoot) !== path.resolve(rootDir)) {
231
- try {
232
- // git check-ignore exits 0 if the path IS ignored, 1 if not
233
- (0, child_process_1.execFileSync)('git', ['check-ignore', '-q', path.resolve(rootDir)], { cwd: rootDir, encoding: 'utf-8', timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true });
234
- // Directory is gitignored by parent repo — fall back to filesystem walk
235
- return null;
236
- }
237
- catch {
238
- // Not ignored — safe to use git ls-files
239
- }
240
- }
241
- const files = new Set();
242
- collectGitFiles(rootDir, '', files);
243
- // Apply built-in default ignores uniformly — to tracked files too, since
244
- // committing a dependency/build dir doesn't make it project code. A
245
- // `.gitignore` negation (e.g. `!vendor/`) is the explicit opt-in. (issue #407)
246
- const ig = buildDefaultIgnore(rootDir);
247
- return new Set([...files].filter((f) => !ig.ignores(f)));
248
- }
249
- catch {
250
- return null;
251
- }
252
- }
253
- /**
254
- * Use `git status` to detect changed files instead of scanning every file.
255
- * Returns null on failure so callers fall back to full scan.
256
- */
257
- function getGitChangedFiles(rootDir) {
258
- try {
259
- const output = (0, child_process_1.execFileSync)('git', ['status', '--porcelain', '--no-renames'], { cwd: rootDir, encoding: 'utf-8', timeout: 10000, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true });
260
- const modified = [];
261
- const added = [];
262
- const deleted = [];
263
- for (const line of output.split('\n')) {
264
- if (line.length < 4)
265
- continue; // Minimum: "XY file"
266
- const statusCode = line.substring(0, 2);
267
- const filePath = (0, utils_1.normalizePath)(line.substring(3));
268
- // Skip non-source files (git status already omits .gitignored paths).
269
- if (!(0, grammars_1.isSourceFile)(filePath))
270
- continue;
271
- if (statusCode === '??') {
272
- added.push(filePath);
273
- }
274
- else if (statusCode.includes('D')) {
275
- deleted.push(filePath);
276
- }
277
- else {
278
- // M, MM, AM, A (staged), etc. — treat as modified
279
- modified.push(filePath);
280
- }
281
- }
282
- return { modified, added, deleted };
283
- }
284
- catch {
285
- return null;
286
- }
287
- }
288
- /**
289
- * Recursively scan a directory for source files.
290
- *
291
- * In git repos, uses `git ls-files` (inherently respects .gitignore at all
292
- * levels), then keeps files with a supported source extension. For non-git
293
- * projects, falls back to a filesystem walk that parses .gitignore itself.
294
- */
295
- function scanDirectory(rootDir, onProgress) {
296
- // Fast path: use git to get all visible files (respects .gitignore everywhere)
297
- const gitFiles = getGitVisibleFiles(rootDir);
298
- if (gitFiles) {
299
- const files = [];
300
- let count = 0;
301
- for (const filePath of gitFiles) {
302
- if ((0, grammars_1.isSourceFile)(filePath)) {
303
- files.push(filePath);
304
- count++;
305
- onProgress?.(count, filePath);
306
- }
307
- }
308
- return files;
309
- }
310
- // Fallback: walk filesystem for non-git projects
311
- return scanDirectoryWalk(rootDir, onProgress);
312
- }
313
- /**
314
- * Async variant of scanDirectory that yields to the event loop periodically,
315
- * allowing worker threads to receive and render progress messages.
316
- */
317
- async function scanDirectoryAsync(rootDir, onProgress) {
318
- const gitFiles = getGitVisibleFiles(rootDir);
319
- if (gitFiles) {
320
- const files = [];
321
- let count = 0;
322
- for (const filePath of gitFiles) {
323
- if ((0, grammars_1.isSourceFile)(filePath)) {
324
- files.push(filePath);
325
- count++;
326
- onProgress?.(count, filePath);
327
- // Yield every 100 files so worker threads can render progress
328
- if (count % 100 === 0) {
329
- await new Promise(r => setImmediate(r));
330
- }
331
- }
332
- }
333
- return files;
334
- }
335
- return scanDirectoryWalk(rootDir, onProgress);
336
- }
337
- /**
338
- * Filesystem walk fallback for non-git projects.
339
- */
340
- function scanDirectoryWalk(rootDir, onProgress) {
341
- const files = [];
342
- let count = 0;
343
- const visitedDirs = new Set();
344
- const loadIgnore = (dir) => {
345
- try {
346
- const giPath = path.join(dir, '.gitignore');
347
- if (fs.existsSync(giPath)) {
348
- return { dir, ig: (0, ignore_1.default)().add(fs.readFileSync(giPath, 'utf-8')) };
349
- }
350
- }
351
- catch {
352
- // Unreadable .gitignore — treat as absent.
353
- }
354
- return null;
355
- };
356
- const isIgnored = (fullPath, isDir, matchers) => {
357
- for (const { dir, ig } of matchers) {
358
- let rel = (0, utils_1.normalizePath)(path.relative(dir, fullPath));
359
- if (!rel || rel.startsWith('..'))
360
- continue; // not under this matcher's dir
361
- if (isDir)
362
- rel += '/'; // dir-only rules (e.g. `build/`) only match with the slash
363
- if (ig.ignores(rel))
364
- return true;
365
- }
366
- return false;
367
- };
368
- function walk(dir, matchers) {
369
- let realDir;
370
- try {
371
- realDir = fs.realpathSync(dir);
372
- }
373
- catch {
374
- (0, errors_1.logDebug)('Skipping unresolvable directory', { dir });
375
- return;
376
- }
377
- if (visitedDirs.has(realDir)) {
378
- (0, errors_1.logDebug)('Skipping already-visited directory (symlink cycle)', { dir, realDir });
379
- return;
380
- }
381
- visitedDirs.add(realDir);
382
- // This directory's own .gitignore (if present) applies to everything below it.
383
- // The root's .gitignore is already merged into the seeded base matcher (so a
384
- // negation there can override a built-in default), so skip it here.
385
- const own = dir === rootDir ? null : loadIgnore(dir);
386
- const active = own ? [...matchers, own] : matchers;
387
- let entries;
388
- try {
389
- entries = fs.readdirSync(dir, { withFileTypes: true });
390
- }
391
- catch (error) {
392
- (0, errors_1.logDebug)('Skipping unreadable directory', { dir, error: String(error) });
393
- return;
394
- }
395
- for (const entry of entries) {
396
- // Never descend into git internals or our own data directory.
397
- if (entry.name === '.git' || entry.name === '.specship')
398
- continue;
399
- const fullPath = path.join(dir, entry.name);
400
- const relativePath = (0, utils_1.normalizePath)(path.relative(rootDir, fullPath));
401
- if (entry.isSymbolicLink()) {
402
- try {
403
- const realTarget = fs.realpathSync(fullPath);
404
- const stat = fs.statSync(realTarget);
405
- if (stat.isDirectory()) {
406
- if (!isIgnored(fullPath, true, active)) {
407
- walk(fullPath, active);
408
- }
409
- }
410
- else if (stat.isFile()) {
411
- if (!isIgnored(fullPath, false, active) && (0, grammars_1.isSourceFile)(relativePath)) {
412
- files.push(relativePath);
413
- count++;
414
- onProgress?.(count, relativePath);
415
- }
416
- }
417
- }
418
- catch {
419
- (0, errors_1.logDebug)('Skipping broken symlink', { path: fullPath });
420
- }
421
- continue;
422
- }
423
- if (entry.isDirectory()) {
424
- if (!isIgnored(fullPath, true, active)) {
425
- walk(fullPath, active);
426
- }
427
- }
428
- else if (entry.isFile()) {
429
- if (!isIgnored(fullPath, false, active) && (0, grammars_1.isSourceFile)(relativePath)) {
430
- files.push(relativePath);
431
- count++;
432
- onProgress?.(count, relativePath);
433
- }
434
- }
435
- }
436
- }
437
- // Seed a base matcher with the built-in default ignores (merged with the root
438
- // .gitignore so a negation can override). Nested .gitignores still layer per-dir.
439
- walk(rootDir, [{ dir: rootDir, ig: buildDefaultIgnore(rootDir) }]);
440
- return files;
441
- }
442
- /**
443
- * Extraction orchestrator
444
- */
445
- class ExtractionOrchestrator {
446
- rootDir;
447
- queries;
448
- /**
449
- * Names of frameworks detected for this project, populated by indexAll().
450
- * Passed to extractFromSource so framework-specific extractors (route nodes,
451
- * middleware, etc.) run after the tree-sitter pass. Cleared if detection
452
- * hasn't run yet so single-file re-index paths can detect on the spot.
453
- */
454
- detectedFrameworkNames = null;
455
- constructor(rootDir, queries) {
456
- this.rootDir = rootDir;
457
- this.queries = queries;
458
- }
459
- /**
460
- * Build a filesystem-backed ResolutionContext sufficient for framework
461
- * detection. Graph-query methods (getNodesByName etc.) return empty because
462
- * the DB hasn't been populated yet, but detect() only uses readFile,
463
- * fileExists, and getAllFiles, so that's fine.
464
- */
465
- buildDetectionContext(files) {
466
- const rootDir = this.rootDir;
467
- return {
468
- getNodesInFile: () => [],
469
- getNodesByName: () => [],
470
- getNodesByQualifiedName: () => [],
471
- getNodesByKind: () => [],
472
- getNodesByLowerName: () => [],
473
- getImportMappings: () => [],
474
- getAllFiles: () => files,
475
- getProjectRoot: () => rootDir,
476
- fileExists: (relativePath) => {
477
- const full = (0, utils_1.validatePathWithinRoot)(rootDir, relativePath);
478
- if (!full)
479
- return false;
480
- try {
481
- return fs.existsSync(full);
482
- }
483
- catch {
484
- return false;
485
- }
486
- },
487
- readFile: (relativePath) => {
488
- const full = (0, utils_1.validatePathWithinRoot)(rootDir, relativePath);
489
- if (!full)
490
- return null;
491
- try {
492
- return fs.readFileSync(full, 'utf-8');
493
- }
494
- catch {
495
- return null;
496
- }
497
- },
498
- // Monorepo support — needed by framework detect()s that probe
499
- // subpackage manifests (e.g. fabric-view looking at
500
- // packages/<sub>/package.json when the root manifest is just a
501
- // workspace declaration). Matches the resolver-context shape.
502
- listDirectories: (relativePath) => {
503
- const target = relativePath === '.' || relativePath === ''
504
- ? rootDir
505
- : path.join(rootDir, relativePath);
506
- try {
507
- return fs
508
- .readdirSync(target, { withFileTypes: true })
509
- .filter((entry) => entry.isDirectory())
510
- .map((entry) => entry.name);
511
- }
512
- catch {
513
- return [];
514
- }
515
- },
516
- };
517
- }
518
- /**
519
- * Detect frameworks on demand using the current scanned files (or a fresh
520
- * scan if none are provided). Cached on the orchestrator so repeat calls
521
- * inside a single run don't re-scan.
522
- */
523
- ensureDetectedFrameworks(files) {
524
- if (this.detectedFrameworkNames !== null)
525
- return this.detectedFrameworkNames;
526
- const fileList = files ?? scanDirectory(this.rootDir);
527
- const context = this.buildDetectionContext(fileList);
528
- this.detectedFrameworkNames = (0, frameworks_1.detectFrameworks)(context).map((r) => r.name);
529
- return this.detectedFrameworkNames;
530
- }
531
- /**
532
- * Index all files in the project
533
- */
534
- async indexAll(onProgress, signal, verbose) {
535
- await (0, grammars_1.initGrammars)();
536
- const startTime = Date.now();
537
- const errors = [];
538
- let filesIndexed = 0;
539
- let filesSkipped = 0;
540
- let filesErrored = 0;
541
- let totalNodes = 0;
542
- let totalEdges = 0;
543
- const log = verbose
544
- ? (msg) => { console.log(`[worker] ${msg}`); }
545
- : (_msg) => { };
546
- // Phase 1: Scan for files
547
- onProgress?.({
548
- phase: 'scanning',
549
- current: 0,
550
- total: 0,
551
- });
552
- const files = await scanDirectoryAsync(this.rootDir, (current, file) => {
553
- onProgress?.({
554
- phase: 'scanning',
555
- current,
556
- total: 0,
557
- currentFile: file,
558
- });
559
- });
560
- // Detect frameworks once per indexAll run using the scanned file list.
561
- // Names are passed to each parse call so framework-specific extractors
562
- // (route nodes, middleware, etc.) run after the tree-sitter pass.
563
- // Framework detection is reset each run so adding e.g. requirements.txt
564
- // between runs is picked up without restarting the process.
565
- this.detectedFrameworkNames = null;
566
- const frameworkNames = this.ensureDetectedFrameworks(files);
567
- if (signal?.aborted) {
568
- return {
569
- success: false,
570
- filesIndexed: 0,
571
- filesSkipped: 0,
572
- filesErrored: 0,
573
- nodesCreated: 0,
574
- edgesCreated: 0,
575
- errors: [{ message: 'Aborted', severity: 'error' }],
576
- durationMs: Date.now() - startTime,
577
- };
578
- }
579
- // Phase 2: Parse files in a worker thread (keeps main thread unblocked for UI)
580
- const total = files.length;
581
- let processed = 0;
582
- // Emit parsing phase immediately so the progress bar appears during worker setup.
583
- // The yield lets the shimmer worker flush the phase transition to stdout before
584
- // the main thread starts synchronous grammar detection work.
585
- onProgress?.({
586
- phase: 'parsing',
587
- current: 0,
588
- total,
589
- });
590
- await new Promise(resolve => setImmediate(resolve));
591
- // Detect needed languages and load grammars in the parse worker
592
- const neededLanguages = [...new Set(files.map((f) => (0, grammars_1.detectLanguage)(f)))];
593
- // .h files default to 'c' but may be C++ — ensure cpp grammar is loaded when c is needed
594
- if (neededLanguages.includes('c') && !neededLanguages.includes('cpp')) {
595
- neededLanguages.push('cpp');
596
- }
597
- // Try to use a worker thread for parsing (keeps main thread unblocked for UI).
598
- // Falls back to in-process parsing if the compiled worker is unavailable (e.g. tests).
599
- const parseWorkerPath = path.join(__dirname, 'parse-worker.js');
600
- const useWorker = fs.existsSync(parseWorkerPath);
601
- let WorkerClass = null;
602
- if (useWorker) {
603
- const { Worker } = await Promise.resolve().then(() => __importStar(require('worker_threads')));
604
- WorkerClass = Worker;
605
- }
606
- else {
607
- // In-process fallback: load grammars locally
608
- await (0, grammars_1.loadGrammarsForLanguages)(neededLanguages);
609
- }
610
- // --- Worker lifecycle management ---
611
- // The worker can crash (OOM in WASM) or hang on pathological files.
612
- // We track pending parse promises and handle both cases:
613
- // - Timeout: terminate + restart the worker, reject the timed-out request
614
- // - Crash: reject all pending promises, restart for remaining files
615
- let parseWorker = null;
616
- let nextId = 0;
617
- let workerParseCount = 0;
618
- const pendingParses = new Map();
619
- function rejectAllPending(reason) {
620
- for (const [id, pending] of pendingParses) {
621
- clearTimeout(pending.timer);
622
- pendingParses.delete(id);
623
- pending.reject(new Error(reason));
624
- }
625
- }
626
- function attachWorkerHandlers(w) {
627
- w.on('message', (msg) => {
628
- if (msg.type === 'parse-result' && msg.id !== undefined) {
629
- const pending = pendingParses.get(msg.id);
630
- if (pending) {
631
- clearTimeout(pending.timer);
632
- pendingParses.delete(msg.id);
633
- pending.resolve(msg.result);
634
- }
635
- }
636
- });
637
- w.on('error', (err) => {
638
- (0, errors_1.logWarn)('Parse worker error', { error: err.message });
639
- rejectAllPending(`Worker error: ${err.message}`);
640
- });
641
- w.on('exit', (code) => {
642
- if (code !== 0 && pendingParses.size > 0) {
643
- (0, errors_1.logWarn)('Parse worker exited unexpectedly', { code });
644
- rejectAllPending(`Worker exited with code ${code}`);
645
- }
646
- // Clear reference so we know to respawn, reset count so
647
- // the fresh worker gets a full cycle before recycling.
648
- if (parseWorker === w) {
649
- parseWorker = null;
650
- workerParseCount = 0;
651
- }
652
- });
653
- }
654
- async function ensureWorker() {
655
- if (parseWorker)
656
- return parseWorker;
657
- log('Spawning new parse worker...');
658
- parseWorker = new WorkerClass(parseWorkerPath);
659
- attachWorkerHandlers(parseWorker);
660
- // Load grammars in the new worker
661
- await new Promise((resolve, reject) => {
662
- parseWorker.once('message', (msg) => {
663
- if (msg.type === 'grammars-loaded')
664
- resolve();
665
- else
666
- reject(new Error(`Unexpected message: ${msg.type}`));
667
- });
668
- parseWorker.postMessage({ type: 'load-grammars', languages: neededLanguages });
669
- });
670
- return parseWorker;
671
- }
672
- if (WorkerClass) {
673
- await ensureWorker();
674
- }
675
- /**
676
- * Recycle the worker thread to reclaim WASM memory.
677
- * Terminates the current worker and clears the reference so
678
- * ensureWorker() will spawn a fresh one on the next call.
679
- */
680
- function recycleWorker() {
681
- if (!parseWorker)
682
- return;
683
- log(`Recycling worker after ${workerParseCount} parses (heap: ${Math.round(process.memoryUsage().rss / 1024 / 1024)}MB RSS)`);
684
- const w = parseWorker;
685
- parseWorker = null;
686
- workerParseCount = 0;
687
- // Fire-and-forget: worker.terminate() can hang if WASM is stuck
688
- w.terminate().catch(() => { });
689
- }
690
- async function requestParse(filePath, content) {
691
- if (!WorkerClass) {
692
- // In-process fallback
693
- return (0, tree_sitter_1.extractFromSource)(filePath, content, (0, grammars_1.detectLanguage)(filePath, content), frameworkNames);
694
- }
695
- // Recycle the worker before the next parse if we've hit the threshold.
696
- // This destroys the WASM linear memory (which can grow but never shrink)
697
- // and starts a fresh worker with a clean heap.
698
- if (workerParseCount >= WORKER_RECYCLE_INTERVAL) {
699
- await recycleWorker();
700
- }
701
- const worker = await ensureWorker();
702
- const id = nextId++;
703
- workerParseCount++;
704
- // Scale timeout for large files: base 10s + 10s per 100KB
705
- const timeoutMs = PARSE_TIMEOUT_MS + Math.floor(content.length / 100_000) * 10_000;
706
- return new Promise((resolve, reject) => {
707
- const timer = setTimeout(() => {
708
- pendingParses.delete(id);
709
- log(`TIMEOUT: ${filePath} exceeded ${timeoutMs}ms — killing worker`);
710
- // Reject FIRST — worker.terminate() can hang if WASM is stuck
711
- parseWorker = null;
712
- workerParseCount = 0;
713
- reject(new Error(`Parse timed out after ${timeoutMs}ms`));
714
- // Fire-and-forget: kill the stuck worker in the background
715
- worker.terminate().catch(() => { });
716
- }, timeoutMs);
717
- pendingParses.set(id, { resolve, reject, timer });
718
- worker.postMessage({ type: 'parse', id, filePath, content, frameworkNames });
719
- });
720
- }
721
- for (let i = 0; i < files.length; i += FILE_IO_BATCH_SIZE) {
722
- if (signal?.aborted) {
723
- if (parseWorker)
724
- parseWorker.terminate().catch(() => { });
725
- return {
726
- success: false,
727
- filesIndexed,
728
- filesSkipped,
729
- filesErrored,
730
- nodesCreated: totalNodes,
731
- edgesCreated: totalEdges,
732
- errors: [{ message: 'Aborted', severity: 'error' }, ...errors],
733
- durationMs: Date.now() - startTime,
734
- };
735
- }
736
- const batch = files.slice(i, i + FILE_IO_BATCH_SIZE);
737
- // Read files in parallel (with path validation before any I/O)
738
- const fileContents = await Promise.all(batch.map(async (fp) => {
739
- try {
740
- const fullPath = (0, utils_1.validatePathWithinRoot)(this.rootDir, fp);
741
- if (!fullPath) {
742
- (0, errors_1.logWarn)('Path traversal blocked in batch reader', { filePath: fp });
743
- return { filePath: fp, content: null, stats: null, error: new Error('Path traversal blocked') };
744
- }
745
- const content = await fsp.readFile(fullPath, 'utf-8');
746
- const stats = await fsp.stat(fullPath);
747
- return { filePath: fp, content, stats, error: null };
748
- }
749
- catch (err) {
750
- return { filePath: fp, content: null, stats: null, error: err };
751
- }
752
- }));
753
- // Send to worker for parsing, store results on main thread
754
- for (const { filePath, content, stats, error } of fileContents) {
755
- if (signal?.aborted) {
756
- if (parseWorker)
757
- parseWorker.terminate().catch(() => { });
758
- return {
759
- success: false,
760
- filesIndexed,
761
- filesSkipped,
762
- filesErrored,
763
- nodesCreated: totalNodes,
764
- edgesCreated: totalEdges,
765
- errors: [{ message: 'Aborted', severity: 'error' }, ...errors],
766
- durationMs: Date.now() - startTime,
767
- };
768
- }
769
- // Report progress before parsing (show current file being worked on)
770
- onProgress?.({
771
- phase: 'parsing',
772
- current: processed,
773
- total,
774
- currentFile: filePath,
775
- });
776
- if (error || content === null || stats === null) {
777
- processed++;
778
- filesErrored++;
779
- errors.push({
780
- message: `Failed to read file: ${error instanceof Error ? error.message : String(error)}`,
781
- filePath,
782
- severity: 'error',
783
- code: 'read_error',
784
- });
785
- continue;
786
- }
787
- // Honour MAX_FILE_SIZE. Without this check, vendored generated
788
- // headers, minified bundles, and other multi-MB files get indexed,
789
- // wasting WASM heap and the worker recycle budget on inputs with no
790
- // useful symbols. The single-file extractFile path already enforces
791
- // this; the bulk path used to silently skip the check.
792
- if (stats.size > MAX_FILE_SIZE) {
793
- processed++;
794
- filesSkipped++;
795
- errors.push({
796
- message: `File exceeds max size (${stats.size} > ${MAX_FILE_SIZE})`,
797
- filePath,
798
- severity: 'warning',
799
- code: 'size_exceeded',
800
- });
801
- onProgress?.({ phase: 'parsing', current: processed, total });
802
- continue;
803
- }
804
- // Parse in worker thread (main thread stays unblocked).
805
- // Wrapped in try/catch to handle worker timeouts and crashes gracefully.
806
- let result;
807
- try {
808
- result = await requestParse(filePath, content);
809
- }
810
- catch (parseErr) {
811
- processed++;
812
- filesErrored++;
813
- errors.push({
814
- message: parseErr instanceof Error ? parseErr.message : String(parseErr),
815
- filePath,
816
- severity: 'error',
817
- code: 'parse_error',
818
- });
819
- continue;
820
- }
821
- processed++;
822
- // Store in database on main thread (SQLite is not thread-safe)
823
- if (result.nodes.length > 0 || result.errors.length === 0) {
824
- const language = (0, grammars_1.detectLanguage)(filePath, content);
825
- this.storeExtractionResult(filePath, content, language, stats, result);
826
- }
827
- if (result.errors.length > 0) {
828
- for (const err of result.errors) {
829
- if (!err.filePath)
830
- err.filePath = filePath;
831
- }
832
- errors.push(...result.errors);
833
- }
834
- if (result.nodes.length > 0) {
835
- filesIndexed++;
836
- totalNodes += result.nodes.length;
837
- totalEdges += result.edges.length;
838
- }
839
- else if (result.errors.some((e) => e.severity === 'error')) {
840
- filesErrored++;
841
- }
842
- else {
843
- // Files with no symbols but no errors (yaml, twig, properties) are
844
- // tracked at the file level — count them as indexed so the CLI
845
- // doesn't misleadingly report "No files found to index".
846
- const lang = (0, grammars_1.detectLanguage)(filePath, content);
847
- if ((0, grammars_1.isFileLevelOnlyLanguage)(lang)) {
848
- filesIndexed++;
849
- }
850
- else {
851
- filesSkipped++;
852
- }
853
- }
854
- }
855
- }
856
- // Report 100% so the progress bar doesn't hang at 99%
857
- onProgress?.({
858
- phase: 'parsing',
859
- current: total,
860
- total,
861
- });
862
- // Yield so the shimmer worker's buffered stdout writes can flush.
863
- // Worker thread stdout is proxied through the main thread's event loop,
864
- // so synchronous work here blocks the animation from rendering.
865
- await new Promise(resolve => setImmediate(resolve));
866
- // Retry pass: files that failed due to WASM memory corruption may succeed
867
- // on a fresh worker with a clean heap. Recycle before each attempt so
868
- // every file gets the absolute cleanest WASM state possible.
869
- const retryableErrors = errors.filter((e) => e.code === 'parse_error' && e.filePath &&
870
- (e.message.includes('Worker exited') || e.message.includes('memory access out of bounds')));
871
- if (retryableErrors.length > 0 && WorkerClass) {
872
- log(`Retrying ${retryableErrors.length} files that failed due to WASM memory errors...`);
873
- const stillFailing = [];
874
- for (const errEntry of retryableErrors) {
875
- const filePath = errEntry.filePath;
876
- if (signal?.aborted)
877
- break;
878
- // Fresh worker for every retry — maximum WASM headroom
879
- recycleWorker();
880
- let content;
881
- try {
882
- const fullPath = (0, utils_1.validatePathWithinRoot)(this.rootDir, filePath);
883
- if (!fullPath)
884
- continue;
885
- content = await fsp.readFile(fullPath, 'utf-8');
886
- }
887
- catch {
888
- continue;
889
- }
890
- let result;
891
- try {
892
- result = await requestParse(filePath, content);
893
- }
894
- catch {
895
- stillFailing.push(errEntry);
896
- continue;
897
- }
898
- if (result.nodes.length > 0 || result.errors.length === 0) {
899
- const language = (0, grammars_1.detectLanguage)(filePath, content);
900
- const stats = await fsp.stat(path.join(this.rootDir, filePath));
901
- this.storeExtractionResult(filePath, content, language, stats, result);
902
- const idx = errors.indexOf(errEntry);
903
- if (idx >= 0)
904
- errors.splice(idx, 1);
905
- filesErrored--;
906
- filesIndexed++;
907
- totalNodes += result.nodes.length;
908
- totalEdges += result.edges.length;
909
- log(`Retry OK: ${filePath} (${result.nodes.length} nodes)`);
910
- }
911
- }
912
- // Last resort: for files that still crash on a clean worker, strip
913
- // comment-only lines to reduce WASM memory pressure. Many compiler
914
- // test files are 90%+ comments (CHECK directives) that don't contribute
915
- // code nodes but consume parser memory.
916
- if (stillFailing.length > 0) {
917
- log(`${stillFailing.length} files still failing — retrying with comments stripped...`);
918
- for (const errEntry of stillFailing) {
919
- const filePath = errEntry.filePath;
920
- if (signal?.aborted)
921
- break;
922
- recycleWorker();
923
- let fullContent;
924
- try {
925
- const fullPath = (0, utils_1.validatePathWithinRoot)(this.rootDir, filePath);
926
- if (!fullPath)
927
- continue;
928
- fullContent = await fsp.readFile(fullPath, 'utf-8');
929
- }
930
- catch {
931
- continue;
932
- }
933
- // Strip lines that are entirely comments (preserving line numbers
934
- // by replacing with empty lines so node positions stay correct)
935
- const stripped = fullContent
936
- .split('\n')
937
- .map(line => /^\s*\/\//.test(line) ? '' : line)
938
- .join('\n');
939
- let result;
940
- try {
941
- result = await requestParse(filePath, stripped);
942
- }
943
- catch {
944
- continue;
945
- }
946
- if (result.nodes.length > 0 || result.errors.length === 0) {
947
- const language = (0, grammars_1.detectLanguage)(filePath, fullContent);
948
- const stats = await fsp.stat(path.join(this.rootDir, filePath));
949
- this.storeExtractionResult(filePath, fullContent, language, stats, result);
950
- const idx = errors.indexOf(errEntry);
951
- if (idx >= 0)
952
- errors.splice(idx, 1);
953
- filesErrored--;
954
- filesIndexed++;
955
- totalNodes += result.nodes.length;
956
- totalEdges += result.edges.length;
957
- log(`Retry (stripped) OK: ${filePath} (${result.nodes.length} nodes)`);
958
- }
959
- }
960
- }
961
- }
962
- // Shut down parse worker and clear any pending timers
963
- rejectAllPending('Indexing complete');
964
- if (parseWorker) {
965
- parseWorker.terminate().catch(() => { });
966
- }
967
- return {
968
- success: filesIndexed > 0 || errors.filter((e) => e.severity === 'error').length === 0,
969
- filesIndexed,
970
- filesSkipped,
971
- filesErrored,
972
- nodesCreated: totalNodes,
973
- edgesCreated: totalEdges,
974
- errors,
975
- durationMs: Date.now() - startTime,
976
- };
977
- }
978
- /**
979
- * Index specific files
980
- */
981
- async indexFiles(filePaths) {
982
- const startTime = Date.now();
983
- const errors = [];
984
- let filesIndexed = 0;
985
- let filesSkipped = 0;
986
- let filesErrored = 0;
987
- let totalNodes = 0;
988
- let totalEdges = 0;
989
- for (const filePath of filePaths) {
990
- const result = await this.indexFile(filePath);
991
- if (result.errors.length > 0) {
992
- errors.push(...result.errors);
993
- }
994
- if (result.nodes.length > 0) {
995
- filesIndexed++;
996
- totalNodes += result.nodes.length;
997
- totalEdges += result.edges.length;
998
- }
999
- else if (result.errors.some((e) => e.severity === 'error')) {
1000
- filesErrored++;
1001
- }
1002
- else {
1003
- const tracked = this.queries.getFileByPath(filePath);
1004
- if (tracked && (0, grammars_1.isFileLevelOnlyLanguage)(tracked.language)) {
1005
- filesIndexed++;
1006
- }
1007
- else {
1008
- filesSkipped++;
1009
- }
1010
- }
1011
- }
1012
- return {
1013
- success: filesIndexed > 0 || errors.filter((e) => e.severity === 'error').length === 0,
1014
- filesIndexed,
1015
- filesSkipped,
1016
- filesErrored,
1017
- nodesCreated: totalNodes,
1018
- edgesCreated: totalEdges,
1019
- errors,
1020
- durationMs: Date.now() - startTime,
1021
- };
1022
- }
1023
- /**
1024
- * Index a single file
1025
- */
1026
- async indexFile(relativePath) {
1027
- const fullPath = (0, utils_1.validatePathWithinRoot)(this.rootDir, relativePath);
1028
- if (!fullPath) {
1029
- return {
1030
- nodes: [],
1031
- edges: [],
1032
- unresolvedReferences: [],
1033
- errors: [{ message: `Path traversal blocked: ${relativePath}`, filePath: relativePath, severity: 'error', code: 'path_traversal' }],
1034
- durationMs: 0,
1035
- };
1036
- }
1037
- // Read file content and stats
1038
- let content;
1039
- let stats;
1040
- try {
1041
- stats = await fsp.stat(fullPath);
1042
- content = await fsp.readFile(fullPath, 'utf-8');
1043
- }
1044
- catch (error) {
1045
- return {
1046
- nodes: [],
1047
- edges: [],
1048
- unresolvedReferences: [],
1049
- errors: [
1050
- {
1051
- message: `Failed to read file: ${error instanceof Error ? error.message : String(error)}`,
1052
- filePath: relativePath,
1053
- severity: 'error',
1054
- code: 'read_error',
1055
- },
1056
- ],
1057
- durationMs: 0,
1058
- };
1059
- }
1060
- return this.indexFileWithContent(relativePath, content, stats);
1061
- }
1062
- /**
1063
- * Index a single file with pre-read content and stats.
1064
- * Used by the parallel batch reader to avoid redundant file I/O.
1065
- */
1066
- async indexFileWithContent(relativePath, content, stats) {
1067
- // Prevent path traversal
1068
- const fullPath = (0, utils_1.validatePathWithinRoot)(this.rootDir, relativePath);
1069
- if (!fullPath) {
1070
- (0, errors_1.logWarn)('Path traversal blocked in indexFileWithContent', { relativePath });
1071
- return {
1072
- nodes: [],
1073
- edges: [],
1074
- unresolvedReferences: [],
1075
- errors: [{ message: 'Path traversal blocked', filePath: relativePath, severity: 'error', code: 'path_traversal' }],
1076
- durationMs: 0,
1077
- };
1078
- }
1079
- // Check file size
1080
- if (stats.size > MAX_FILE_SIZE) {
1081
- return {
1082
- nodes: [],
1083
- edges: [],
1084
- unresolvedReferences: [],
1085
- errors: [
1086
- {
1087
- message: `File exceeds max size (${stats.size} > ${MAX_FILE_SIZE})`,
1088
- filePath: relativePath,
1089
- severity: 'warning',
1090
- code: 'size_exceeded',
1091
- },
1092
- ],
1093
- durationMs: 0,
1094
- };
1095
- }
1096
- // Detect language
1097
- const language = (0, grammars_1.detectLanguage)(relativePath, content);
1098
- if (!(0, grammars_1.isLanguageSupported)(language)) {
1099
- return {
1100
- nodes: [],
1101
- edges: [],
1102
- unresolvedReferences: [],
1103
- errors: [],
1104
- durationMs: 0,
1105
- };
1106
- }
1107
- // Extract from source. Use cached framework names if indexAll has run,
1108
- // otherwise detect on the spot so single-file re-index paths still emit
1109
- // route nodes / middleware / etc.
1110
- const frameworkNames = this.ensureDetectedFrameworks();
1111
- const result = (0, tree_sitter_1.extractFromSource)(relativePath, content, language, frameworkNames);
1112
- // Store in database
1113
- if (result.nodes.length > 0 || result.errors.length === 0) {
1114
- this.storeExtractionResult(relativePath, content, language, stats, result);
1115
- }
1116
- return result;
1117
- }
1118
- /**
1119
- * Store extraction result in database
1120
- */
1121
- storeExtractionResult(filePath, content, language, stats, result) {
1122
- const contentHash = hashContent(content);
1123
- // Check if file already exists and hasn't changed
1124
- const existingFile = this.queries.getFileByPath(filePath);
1125
- if (existingFile && existingFile.contentHash === contentHash) {
1126
- return; // No changes
1127
- }
1128
- // Delete existing data for this file
1129
- if (existingFile) {
1130
- this.queries.deleteFile(filePath);
1131
- }
1132
- // Filter out nodes with missing required fields before insertion.
1133
- // This prevents FK violations when edges reference nodes that would
1134
- // be silently skipped by insertNode() (see issue #42).
1135
- const validNodes = result.nodes.filter((n) => n.id && n.kind && n.name && n.filePath && n.language);
1136
- // Insert nodes
1137
- if (validNodes.length > 0) {
1138
- this.queries.insertNodes(validNodes);
1139
- }
1140
- // Filter edges to only reference nodes that were actually inserted
1141
- if (result.edges.length > 0) {
1142
- const insertedIds = new Set(validNodes.map((n) => n.id));
1143
- const validEdges = result.edges.filter((e) => insertedIds.has(e.source) && insertedIds.has(e.target));
1144
- if (validEdges.length > 0) {
1145
- this.queries.insertEdges(validEdges);
1146
- }
1147
- }
1148
- // Insert unresolved references in batch with denormalized filePath/language
1149
- if (result.unresolvedReferences.length > 0) {
1150
- const insertedIds = new Set(validNodes.map((n) => n.id));
1151
- const refsWithContext = result.unresolvedReferences
1152
- .filter((ref) => insertedIds.has(ref.fromNodeId))
1153
- .map((ref) => ({
1154
- ...ref,
1155
- filePath: ref.filePath ?? filePath,
1156
- language: ref.language ?? language,
1157
- }));
1158
- if (refsWithContext.length > 0) {
1159
- this.queries.insertUnresolvedRefsBatch(refsWithContext);
1160
- }
1161
- }
1162
- // Insert file record
1163
- const fileRecord = {
1164
- path: filePath,
1165
- contentHash,
1166
- language,
1167
- size: stats.size,
1168
- modifiedAt: stats.mtimeMs,
1169
- indexedAt: Date.now(),
1170
- nodeCount: result.nodes.length,
1171
- errors: result.errors.length > 0 ? result.errors : undefined,
1172
- };
1173
- this.queries.upsertFile(fileRecord);
1174
- }
1175
- /**
1176
- * Sync the index with the current file state.
1177
- *
1178
- * Change detection is filesystem-based, never git: a (size, mtime) stat
1179
- * pre-filter skips unchanged files, then a content-hash compare confirms real
1180
- * changes. This works in non-git projects and catches committed changes from
1181
- * `git pull`/`checkout`/`merge`/`rebase` that `git status` cannot see.
1182
- */
1183
- async sync(onProgress) {
1184
- await (0, grammars_1.initGrammars)(); // Initialize WASM runtime (grammars loaded lazily below)
1185
- const startTime = Date.now();
1186
- let filesChecked = 0;
1187
- let filesAdded = 0;
1188
- let filesModified = 0;
1189
- let filesRemoved = 0;
1190
- let nodesUpdated = 0;
1191
- const changedFilePaths = [];
1192
- onProgress?.({
1193
- phase: 'scanning',
1194
- current: 0,
1195
- total: 0,
1196
- });
1197
- const filesToIndex = [];
1198
- // === Filesystem reconcile (git-independent) ===
1199
- // The source of truth for "what changed" is the filesystem vs the indexed
1200
- // state — never git. We enumerate the current source files and reconcile
1201
- // each against the DB. A cheap (size, mtime) stat pre-filter skips unchanged
1202
- // files without reading or hashing them, so the expensive read+hash+parse
1203
- // only runs for files that actually changed. This catches edits/adds/deletes
1204
- // whether or not the project uses git, and crucially also catches committed
1205
- // changes from `git pull`/`checkout`/`merge`/`rebase` — which `git status`
1206
- // cannot see, because the working tree is clean afterward.
1207
- const currentFiles = scanDirectory(this.rootDir);
1208
- filesChecked = currentFiles.length;
1209
- const currentSet = new Set(currentFiles);
1210
- const trackedFiles = this.queries.getAllFiles();
1211
- const trackedMap = new Map();
1212
- for (const f of trackedFiles) {
1213
- trackedMap.set(f.path, f);
1214
- }
1215
- // Removals: tracked in the DB but no longer a present source file. Check the
1216
- // filesystem directly — `scanDirectory` (via `git ls-files`) still lists a
1217
- // file deleted from disk but not yet staged, so set membership alone misses it.
1218
- for (const tracked of trackedFiles) {
1219
- if (!currentSet.has(tracked.path) || !fs.existsSync(path.join(this.rootDir, tracked.path))) {
1220
- this.queries.deleteFile(tracked.path);
1221
- filesRemoved++;
1222
- }
1223
- }
1224
- // Adds / modifications.
1225
- for (const filePath of currentFiles) {
1226
- const fullPath = path.join(this.rootDir, filePath);
1227
- const tracked = trackedMap.get(filePath);
1228
- // Cheap pre-filter: an already-indexed file whose size AND mtime both match
1229
- // the DB is unchanged — skip it without reading or hashing. (A content
1230
- // change that preserves both exactly is the blind spot every mtime-based
1231
- // incremental tool accepts; `index --force` is the escape hatch. Git bumps
1232
- // mtime on every file it writes during checkout/merge, so pulls are caught.)
1233
- if (tracked) {
1234
- try {
1235
- const stat = fs.statSync(fullPath);
1236
- if (stat.size === tracked.size && Math.floor(stat.mtimeMs) === Math.floor(tracked.modifiedAt)) {
1237
- continue;
1238
- }
1239
- }
1240
- catch (error) {
1241
- (0, errors_1.logDebug)('Skipping unstattable file during sync', { filePath, error: String(error) });
1242
- continue;
1243
- }
1244
- }
1245
- // New, or size/mtime changed — read + hash to confirm a real content change.
1246
- let content;
1247
- try {
1248
- content = fs.readFileSync(fullPath, 'utf-8');
1249
- }
1250
- catch (error) {
1251
- (0, errors_1.logDebug)('Skipping unreadable file during sync', { filePath, error: String(error) });
1252
- continue;
1253
- }
1254
- const contentHash = hashContent(content);
1255
- if (!tracked) {
1256
- filesToIndex.push(filePath);
1257
- changedFilePaths.push(filePath);
1258
- filesAdded++;
1259
- }
1260
- else if (tracked.contentHash !== contentHash) {
1261
- filesToIndex.push(filePath);
1262
- changedFilePaths.push(filePath);
1263
- filesModified++;
1264
- }
1265
- }
1266
- // Load only grammars needed for changed files
1267
- if (filesToIndex.length > 0) {
1268
- const neededLanguages = [...new Set(filesToIndex.map((f) => (0, grammars_1.detectLanguage)(f)))];
1269
- // .h files default to 'c' but may be C++ — ensure cpp grammar is loaded
1270
- if (neededLanguages.includes('c') && !neededLanguages.includes('cpp')) {
1271
- neededLanguages.push('cpp');
1272
- }
1273
- await (0, grammars_1.loadGrammarsForLanguages)(neededLanguages);
1274
- }
1275
- // Index changed files
1276
- const total = filesToIndex.length;
1277
- for (let i = 0; i < filesToIndex.length; i++) {
1278
- const filePath = filesToIndex[i];
1279
- onProgress?.({
1280
- phase: 'parsing',
1281
- current: i + 1,
1282
- total,
1283
- currentFile: filePath,
1284
- });
1285
- const result = await this.indexFile(filePath);
1286
- nodesUpdated += result.nodes.length;
1287
- }
1288
- return {
1289
- filesChecked,
1290
- filesAdded,
1291
- filesModified,
1292
- filesRemoved,
1293
- nodesUpdated,
1294
- durationMs: Date.now() - startTime,
1295
- changedFilePaths: changedFilePaths.length > 0 ? changedFilePaths : undefined,
1296
- };
1297
- }
1298
- /**
1299
- * Get files that have changed since last index.
1300
- * Uses git status as a fast path when available, falling back to full scan.
1301
- */
1302
- getChangedFiles() {
1303
- const gitChanges = getGitChangedFiles(this.rootDir);
1304
- if (gitChanges) {
1305
- // === Git fast path ===
1306
- const added = [];
1307
- const modified = [];
1308
- const removed = [];
1309
- // Deleted files — only report if tracked in DB
1310
- for (const filePath of gitChanges.deleted) {
1311
- const tracked = this.queries.getFileByPath(filePath);
1312
- if (tracked) {
1313
- removed.push(filePath);
1314
- }
1315
- }
1316
- // Modified + added files — read + hash, compare with DB. Untracked (`??`)
1317
- // files stay untracked in git even after indexing, so they must be
1318
- // hash-compared like modified files instead of always counting as added —
1319
- // otherwise status reports them as pending forever. (See issue #206.)
1320
- for (const filePath of [...gitChanges.modified, ...gitChanges.added]) {
1321
- const fullPath = path.join(this.rootDir, filePath);
1322
- let content;
1323
- try {
1324
- content = fs.readFileSync(fullPath, 'utf-8');
1325
- }
1326
- catch (error) {
1327
- (0, errors_1.logDebug)('Skipping unreadable file while detecting changes', { filePath, error: String(error) });
1328
- continue;
1329
- }
1330
- const contentHash = hashContent(content);
1331
- const tracked = this.queries.getFileByPath(filePath);
1332
- if (!tracked) {
1333
- added.push(filePath);
1334
- }
1335
- else if (tracked.contentHash !== contentHash) {
1336
- modified.push(filePath);
1337
- }
1338
- }
1339
- return { added, modified, removed };
1340
- }
1341
- // === Fallback: full scan (non-git project or git failure) ===
1342
- const currentFiles = new Set(scanDirectory(this.rootDir));
1343
- const trackedFiles = this.queries.getAllFiles();
1344
- // Build Map for O(1) lookups
1345
- const trackedMap = new Map();
1346
- for (const f of trackedFiles) {
1347
- trackedMap.set(f.path, f);
1348
- }
1349
- const added = [];
1350
- const modified = [];
1351
- const removed = [];
1352
- // Find removed files
1353
- for (const tracked of trackedFiles) {
1354
- if (!currentFiles.has(tracked.path)) {
1355
- removed.push(tracked.path);
1356
- }
1357
- }
1358
- // Find added and modified files
1359
- for (const filePath of currentFiles) {
1360
- const fullPath = path.join(this.rootDir, filePath);
1361
- let content;
1362
- try {
1363
- content = fs.readFileSync(fullPath, 'utf-8');
1364
- }
1365
- catch (error) {
1366
- (0, errors_1.logDebug)('Skipping unreadable file while detecting changes', { filePath, error: String(error) });
1367
- continue;
1368
- }
1369
- const contentHash = hashContent(content);
1370
- const tracked = trackedMap.get(filePath);
1371
- if (!tracked) {
1372
- added.push(filePath);
1373
- }
1374
- else if (tracked.contentHash !== contentHash) {
1375
- modified.push(filePath);
1376
- }
1377
- }
1378
- return { added, modified, removed };
1379
- }
1380
- }
1381
- exports.ExtractionOrchestrator = ExtractionOrchestrator;
1382
- // Re-export useful types and functions
1383
- var tree_sitter_2 = require("./tree-sitter");
1384
- Object.defineProperty(exports, "extractFromSource", { enumerable: true, get: function () { return tree_sitter_2.extractFromSource; } });
1385
- var grammars_2 = require("./grammars");
1386
- Object.defineProperty(exports, "detectLanguage", { enumerable: true, get: function () { return grammars_2.detectLanguage; } });
1387
- Object.defineProperty(exports, "isSourceFile", { enumerable: true, get: function () { return grammars_2.isSourceFile; } });
1388
- Object.defineProperty(exports, "isLanguageSupported", { enumerable: true, get: function () { return grammars_2.isLanguageSupported; } });
1389
- Object.defineProperty(exports, "isGrammarLoaded", { enumerable: true, get: function () { return grammars_2.isGrammarLoaded; } });
1390
- Object.defineProperty(exports, "getSupportedLanguages", { enumerable: true, get: function () { return grammars_2.getSupportedLanguages; } });
1391
- Object.defineProperty(exports, "initGrammars", { enumerable: true, get: function () { return grammars_2.initGrammars; } });
1392
- Object.defineProperty(exports, "loadGrammarsForLanguages", { enumerable: true, get: function () { return grammars_2.loadGrammarsForLanguages; } });
1393
- Object.defineProperty(exports, "loadAllGrammars", { enumerable: true, get: function () { return grammars_2.loadAllGrammars; } });
1394
- //# sourceMappingURL=index.js.map