@backbencher/brain 0.0.0-stage → 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 (319) hide show
  1. package/CHANGELOG.md +298 -0
  2. package/EMBEDDINGS.md +355 -0
  3. package/LICENSE +21 -0
  4. package/README.md +415 -2
  5. package/bin/bb +13 -0
  6. package/dist/analysis-exclusions-7ZJDXOVZ.js +35 -0
  7. package/dist/brain-index-health-KY7K552E.js +17 -0
  8. package/dist/brain-relationship-enrichment-QH7OOHUF.js +558 -0
  9. package/dist/brain.sql-EIM4WS4D.js +29 -0
  10. package/dist/chunk-2BSKD7O3.js +40 -0
  11. package/dist/chunk-2DE27DVC.js +1314 -0
  12. package/dist/chunk-2RRBMNBQ.js +322 -0
  13. package/dist/chunk-2RTN2DFU.js +711 -0
  14. package/dist/chunk-2WXYNLBA.js +29 -0
  15. package/dist/chunk-3CTFIJJB.js +17 -0
  16. package/dist/chunk-3LFTSMIV.js +174 -0
  17. package/dist/chunk-47HKX4AJ.js +930 -0
  18. package/dist/chunk-4H22TLOT.js +543 -0
  19. package/dist/chunk-5SD45FLC.js +818 -0
  20. package/dist/chunk-66A5ZFYA.js +1758 -0
  21. package/dist/chunk-6AIRWAO2.js +247 -0
  22. package/dist/chunk-6WNGD3NN.js +196 -0
  23. package/dist/chunk-7AN7U5IZ.js +371 -0
  24. package/dist/chunk-BHB7BYYI.js +626 -0
  25. package/dist/chunk-BQ3OVQ3P.js +125 -0
  26. package/dist/chunk-CW4XXSNN.js +1479 -0
  27. package/dist/chunk-D2Q4Y47A.js +53 -0
  28. package/dist/chunk-DIYAGQJL.js +34 -0
  29. package/dist/chunk-DYM4FQEE.js +90 -0
  30. package/dist/chunk-EWMWK7WN.js +75 -0
  31. package/dist/chunk-FVVQTSIM.js +3427 -0
  32. package/dist/chunk-FWSL4VG6.js +1290 -0
  33. package/dist/chunk-GBI7V7KY.js +69 -0
  34. package/dist/chunk-GEFFO6O2.js +152 -0
  35. package/dist/chunk-HOWAQXJO.js +236 -0
  36. package/dist/chunk-HQSPJDHI.js +613 -0
  37. package/dist/chunk-IFZNR5UJ.js +2863 -0
  38. package/dist/chunk-J4PMBXQQ.js +336 -0
  39. package/dist/chunk-KAET47ZL.js +125 -0
  40. package/dist/chunk-KCDECRJY.js +440 -0
  41. package/dist/chunk-KLK3PBTO.js +1119 -0
  42. package/dist/chunk-L5TDYKYK.js +76 -0
  43. package/dist/chunk-MLKGABMK.js +9 -0
  44. package/dist/chunk-OWISBAOF.js +61 -0
  45. package/dist/chunk-PJTNGD3Z.js +6924 -0
  46. package/dist/chunk-QLK6ED4Q.js +235 -0
  47. package/dist/chunk-R2GW4F6R.js +19 -0
  48. package/dist/chunk-RCMTFSEF.js +87 -0
  49. package/dist/chunk-RH7KC5HU.js +12050 -0
  50. package/dist/chunk-RM3PY6TG.js +376 -0
  51. package/dist/chunk-ROMM6KMC.js +433 -0
  52. package/dist/chunk-SK6YVHFZ.js +211 -0
  53. package/dist/chunk-SM7RFQRO.js +214 -0
  54. package/dist/chunk-UFE77L67.js +782 -0
  55. package/dist/chunk-UGR4QIGS.js +67 -0
  56. package/dist/chunk-UUNHHX4M.js +13 -0
  57. package/dist/chunk-V44PGPA6.js +2104 -0
  58. package/dist/chunk-VL52PL2T.js +71 -0
  59. package/dist/chunk-VURYFIHW.js +201 -0
  60. package/dist/chunk-XJKJYIPP.js +7436 -0
  61. package/dist/chunk-YI6FF2ZR.js +340 -0
  62. package/dist/cli/index.js +37 -0
  63. package/dist/config-HZAAYDP3.js +10 -0
  64. package/dist/content-search-642F7E5V.js +593 -0
  65. package/dist/database-TCTZDLE5.js +9 -0
  66. package/dist/doctor-GXCKSJOX.js +395 -0
  67. package/dist/edit-engine-KM7MPFEC.js +51 -0
  68. package/dist/engine-42TZFNIZ.js +11 -0
  69. package/dist/engine-LO6L4JLQ.js +18 -0
  70. package/dist/fingerprint-XDXFRWO6.js +33 -0
  71. package/dist/framework-intelligence-DWFCKV44.js +860 -0
  72. package/dist/freshness-3K6VU5OT.js +174 -0
  73. package/dist/graph-engine-PL5YA7BA.js +21 -0
  74. package/dist/graph_request-MM4REP6H.js +350 -0
  75. package/dist/impact_request-WDE47IZ5.js +68 -0
  76. package/dist/index-space-IUUN5WYV.js +15 -0
  77. package/dist/index-status-6BD7UBHR.js +34 -0
  78. package/dist/index.js +159 -0
  79. package/dist/instance-FO6QZRLH.js +19 -0
  80. package/dist/language-detection-DFCAU5DZ.js +11 -0
  81. package/dist/lsp/server.js +4301 -0
  82. package/dist/mcp/server.js +132 -0
  83. package/dist/onboard-DIQZV2NW.js +161 -0
  84. package/dist/override-companion-pass-XR7MHTP7.js +117 -0
  85. package/dist/parallel-indexer-4PW3AFXP.js +88 -0
  86. package/dist/pool-worker.js +1153 -0
  87. package/dist/project-health-ZS5TS2Z6.js +94 -0
  88. package/dist/project-index-5SDPHITE.js +57 -0
  89. package/dist/project-registry-DGZBIZS7.js +355 -0
  90. package/dist/real-bash-analyzer-SXSV67E2.js +2201 -0
  91. package/dist/real-c-analyzer-SY7FTZ6W.js +5942 -0
  92. package/dist/real-clean-analyzer-IGDHHLZK.js +3470 -0
  93. package/dist/real-clojure-analyzer-4OH7IWLB.js +2818 -0
  94. package/dist/real-cpp-analyzer-7LTDRJRJ.js +4101 -0
  95. package/dist/real-csharp-analyzer-KICU3TLH.js +3298 -0
  96. package/dist/real-css-analyzer-HPU277Q6.js +15 -0
  97. package/dist/real-dart-analyzer-7LZ5LCMW.js +3944 -0
  98. package/dist/real-elixir-analyzer-BE3MEVZO.js +2192 -0
  99. package/dist/real-erlang-analyzer-BZMAKYBK.js +1731 -0
  100. package/dist/real-fsharp-analyzer-5QLTOV3E.js +2390 -0
  101. package/dist/real-go-analyzer-POD7MZQR.js +4126 -0
  102. package/dist/real-graphql-analyzer-MAQRZ6QW.js +1442 -0
  103. package/dist/real-groovy-analyzer-MEWSUPMJ.js +2285 -0
  104. package/dist/real-haskell-analyzer-I5L2GR3Y.js +2533 -0
  105. package/dist/real-hcl-analyzer-DBOPXSWJ.js +725 -0
  106. package/dist/real-html-analyzer-O63XZLZD.js +1759 -0
  107. package/dist/real-java-analyzer-CHCW3EKA.js +4677 -0
  108. package/dist/real-javascript-analyzer-QAAJQYZE.js +14 -0
  109. package/dist/real-json-analyzer-UGBR7YQN.js +1640 -0
  110. package/dist/real-julia-analyzer-35Q4GHOZ.js +2085 -0
  111. package/dist/real-kotlin-analyzer-GRAYCWW2.js +3956 -0
  112. package/dist/real-lua-analyzer-5BAPDZDF.js +1957 -0
  113. package/dist/real-makefile-analyzer-YJKAHNAS.js +920 -0
  114. package/dist/real-markdown-analyzer-UKUQZO4F.js +1215 -0
  115. package/dist/real-matlab-analyzer-FVIKQZKG.js +480 -0
  116. package/dist/real-nim-analyzer-M7FAIABG.js +3603 -0
  117. package/dist/real-objective-c-analyzer-XMYQIGQI.js +1518 -0
  118. package/dist/real-perl-analyzer-ZLY6M2DZ.js +1865 -0
  119. package/dist/real-php-analyzer-KI2ZAM7X.js +9368 -0
  120. package/dist/real-powershell-analyzer-B3T5ZP6U.js +2915 -0
  121. package/dist/real-protobuf-analyzer-23OZ75XV.js +867 -0
  122. package/dist/real-python-analyzer-I4TIUB6D.js +4880 -0
  123. package/dist/real-r-analyzer-FJZJXXS6.js +2596 -0
  124. package/dist/real-ruby-analyzer-M3UFIVTQ.js +2429 -0
  125. package/dist/real-rust-analyzer-LVSONPAN.js +3359 -0
  126. package/dist/real-scala-analyzer-CWPI33Q2.js +3293 -0
  127. package/dist/real-scss-analyzer-TGRJQ7TH.js +1515 -0
  128. package/dist/real-solidity-analyzer-4P2VBVWA.js +2608 -0
  129. package/dist/real-sql-analyzer-J7DYZOZR.js +3840 -0
  130. package/dist/real-svelte-analyzer-NHEN2SX5.js +2532 -0
  131. package/dist/real-swift-analyzer-2NSYULWI.js +2311 -0
  132. package/dist/real-toml-analyzer-L3C66L7Q.js +929 -0
  133. package/dist/real-typescript-analyzer-FTC6ETRQ.js +14 -0
  134. package/dist/real-vb-analyzer-ORY7LAQS.js +3145 -0
  135. package/dist/real-vba-analyzer-JH2TTUFI.js +466 -0
  136. package/dist/real-vue-analyzer-OO4FUGBV.js +2680 -0
  137. package/dist/real-xml-analyzer-6CQVR477.js +2405 -0
  138. package/dist/real-yaml-analyzer-J6MQG3YX.js +3528 -0
  139. package/dist/real-zig-analyzer-EFKCPJNU.js +2430 -0
  140. package/dist/regex-search-OPTLKUN5.js +239 -0
  141. package/dist/rules-I453JTRC.js +152 -0
  142. package/dist/scoped-path-MJYWJZQX.js +11 -0
  143. package/dist/setup-show-Y5GB5KXA.js +15 -0
  144. package/dist/setup-wizard-G5YYR5T6.js +24 -0
  145. package/dist/symbol-search-KB4MU4SI.js +16 -0
  146. package/dist/taint-YOTN5X55.js +202 -0
  147. package/dist/taint-analyzer-N7YLZU3N.js +163 -0
  148. package/dist/tool-handlers-G4NAGJIH.js +72 -0
  149. package/dist/tool-registry-BPEJNSZG.js +17 -0
  150. package/dist/tool-validation-RF675A3C.js +32 -0
  151. package/dist/type-inference-4Y7WTMFE.js +13 -0
  152. package/dist/vector-binary-LMY4QGAN.js +19 -0
  153. package/dist/version-LXGNFO37.js +9 -0
  154. package/dist/wasm-NMWO3WXY.js +16 -0
  155. package/docs/EMBEDDINGS.md +132 -0
  156. package/docs/README.md +178 -0
  157. package/docs/data/m10-baseline.json +602 -0
  158. package/docs/data/m10-benchmark-baseline.json +57 -0
  159. package/docs/data/m10-benchmark-last-run.json +127 -0
  160. package/docs/data/m10-final-audit.json +215 -0
  161. package/docs/data/m12-final-audit.json +138 -0
  162. package/docs/data/m12-surface-matrix.json +50 -0
  163. package/docs/data/public-tools.json +1902 -0
  164. package/docs/indexing/DEAD-ASSETS.md +88 -0
  165. package/docs/indexing/INDEXER-REVIEW.md +634 -0
  166. package/docs/indexing/PERFORMANCE-FINDINGS.md +106 -0
  167. package/docs/indexing/README.md +427 -0
  168. package/docs/indexing/discovery-matrix.md +41 -0
  169. package/docs/indexing/embeddings.md +325 -0
  170. package/docs/indexing/environment-variables.md +77 -0
  171. package/docs/indexing/performance.md +323 -0
  172. package/docs/indexing/resume.md +345 -0
  173. package/docs/indexing/troubleshooting.md +391 -0
  174. package/docs/man/bb.1 +190 -0
  175. package/docs/tools/bb_analyze.md +147 -0
  176. package/docs/tools/bb_annotate.md +110 -0
  177. package/docs/tools/bb_annotations.md +106 -0
  178. package/docs/tools/bb_ask.md +101 -0
  179. package/docs/tools/bb_cross_language.md +103 -0
  180. package/docs/tools/bb_doc.md +169 -0
  181. package/docs/tools/bb_edit.md +185 -0
  182. package/docs/tools/bb_graph.md +169 -0
  183. package/docs/tools/bb_health.md +156 -0
  184. package/docs/tools/bb_impact.md +117 -0
  185. package/docs/tools/bb_index.md +108 -0
  186. package/docs/tools/bb_migrate.md +135 -0
  187. package/docs/tools/bb_patterns.md +140 -0
  188. package/docs/tools/bb_search.md +150 -0
  189. package/docs/tools/bb_security.md +100 -0
  190. package/docs/tools/bb_visualize.md +184 -0
  191. package/grammars/README.md +57 -0
  192. package/grammars/THIRD-PARTY-NOTICES.md +50 -0
  193. package/grammars/tree-sitter-c/LICENSE +21 -0
  194. package/grammars/tree-sitter-clojure/LICENSE.md +21 -0
  195. package/grammars/tree-sitter-cpp/LICENSE +21 -0
  196. package/grammars/tree-sitter-csharp/LICENSE +21 -0
  197. package/grammars/tree-sitter-css/LICENSE +21 -0
  198. package/grammars/tree-sitter-css/README.md +21 -0
  199. package/grammars/tree-sitter-dart/LICENSE +20 -0
  200. package/grammars/tree-sitter-dart-upstream/LICENSE +20 -0
  201. package/grammars/tree-sitter-dart-upstream/README.md +18 -0
  202. package/grammars/tree-sitter-elixir/LICENSE +176 -0
  203. package/grammars/tree-sitter-elixir/README.md +11 -0
  204. package/grammars/tree-sitter-fsharp/LICENSE +21 -0
  205. package/grammars/tree-sitter-fsharp/README.md +45 -0
  206. package/grammars/tree-sitter-graphql/LICENSE +21 -0
  207. package/grammars/tree-sitter-graphql/README.md +106 -0
  208. package/grammars/tree-sitter-groovy/LICENSE +21 -0
  209. package/grammars/tree-sitter-groovy/README.md +4 -0
  210. package/grammars/tree-sitter-haskell/LICENSE +21 -0
  211. package/grammars/tree-sitter-haskell/README.md +394 -0
  212. package/grammars/tree-sitter-hcl/CHANGELOG.md +102 -0
  213. package/grammars/tree-sitter-hcl/LICENSE +201 -0
  214. package/grammars/tree-sitter-hcl/README.md +39 -0
  215. package/grammars/tree-sitter-html/LICENSE +21 -0
  216. package/grammars/tree-sitter-html/README.md +21 -0
  217. package/grammars/tree-sitter-julia/LICENSE +21 -0
  218. package/grammars/tree-sitter-julia/README.md +24 -0
  219. package/grammars/tree-sitter-kotlin/LICENSE +9 -0
  220. package/grammars/tree-sitter-lua/LICENSE.md +21 -0
  221. package/grammars/tree-sitter-lua/README.md +29 -0
  222. package/grammars/tree-sitter-make/LICENSE +21 -0
  223. package/grammars/tree-sitter-matlab/LICENSE +19 -0
  224. package/grammars/tree-sitter-matlab/README.md +99 -0
  225. package/grammars/tree-sitter-nim/LICENSE +373 -0
  226. package/grammars/tree-sitter-nim/README.md +46 -0
  227. package/grammars/tree-sitter-objc/LICENSE +21 -0
  228. package/grammars/tree-sitter-objc/README.md +20 -0
  229. package/grammars/tree-sitter-perl/LICENSE +7 -0
  230. package/grammars/tree-sitter-perl/README.md +100 -0
  231. package/grammars/tree-sitter-powershell/LICENSE +21 -0
  232. package/grammars/tree-sitter-powershell/README.md +7 -0
  233. package/grammars/tree-sitter-proto/LICENSE +21 -0
  234. package/grammars/tree-sitter-proto/README.md +105 -0
  235. package/grammars/tree-sitter-r/LICENSE +9 -0
  236. package/grammars/tree-sitter-r/README.md +66 -0
  237. package/grammars/tree-sitter-ruby/LICENSE +22 -0
  238. package/grammars/tree-sitter-scss/LICENSE +21 -0
  239. package/grammars/tree-sitter-scss/README.md +17 -0
  240. package/grammars/tree-sitter-solidity/LICENSE +7 -0
  241. package/grammars/tree-sitter-sql/LICENSE +21 -0
  242. package/grammars/tree-sitter-typescript/LICENSE +21 -0
  243. package/grammars/tree-sitter-vba/LICENSE +21 -0
  244. package/grammars/tree-sitter-vba/README.md +738 -0
  245. package/grammars/tree-sitter-vbnet/LICENSE +21 -0
  246. package/grammars/tree-sitter-vbnet/README.md +322 -0
  247. package/grammars/tree-sitter-xml/LICENSE +19 -0
  248. package/grammars/tree-sitter-yaml/LICENSE +20 -0
  249. package/grammars/tree-sitter-yaml/README.md +21 -0
  250. package/package.json +184 -4
  251. package/wasm/dart.wasm +0 -0
  252. package/wasm/tree-sitter-bash.wasm +0 -0
  253. package/wasm/tree-sitter-c.wasm +0 -0
  254. package/wasm/tree-sitter-c_sharp.wasm +0 -0
  255. package/wasm/tree-sitter-clean.wasm +0 -0
  256. package/wasm/tree-sitter-clojure.wasm +0 -0
  257. package/wasm/tree-sitter-core_schema.wasm +0 -0
  258. package/wasm/tree-sitter-cpp.wasm +0 -0
  259. package/wasm/tree-sitter-css.wasm +0 -0
  260. package/wasm/tree-sitter-dart.wasm +0 -0
  261. package/wasm/tree-sitter-elisp.wasm +0 -0
  262. package/wasm/tree-sitter-elixir.wasm +0 -0
  263. package/wasm/tree-sitter-elm.wasm +0 -0
  264. package/wasm/tree-sitter-embedded_template.wasm +0 -0
  265. package/wasm/tree-sitter-erlang.wasm +0 -0
  266. package/wasm/tree-sitter-fsharp.wasm +0 -0
  267. package/wasm/tree-sitter-fsharp_signature.wasm +0 -0
  268. package/wasm/tree-sitter-go.wasm +0 -0
  269. package/wasm/tree-sitter-graphql.wasm +0 -0
  270. package/wasm/tree-sitter-groovy.wasm +0 -0
  271. package/wasm/tree-sitter-haskell.wasm +0 -0
  272. package/wasm/tree-sitter-hcl.wasm +0 -0
  273. package/wasm/tree-sitter-html.wasm +0 -0
  274. package/wasm/tree-sitter-java.wasm +0 -0
  275. package/wasm/tree-sitter-javascript.wasm +0 -0
  276. package/wasm/tree-sitter-json.wasm +0 -0
  277. package/wasm/tree-sitter-json_schema.wasm +0 -0
  278. package/wasm/tree-sitter-julia.wasm +0 -0
  279. package/wasm/tree-sitter-kotlin.wasm +0 -0
  280. package/wasm/tree-sitter-lua.wasm +0 -0
  281. package/wasm/tree-sitter-make.wasm +0 -0
  282. package/wasm/tree-sitter-markdown.wasm +0 -0
  283. package/wasm/tree-sitter-markdown_inline.wasm +0 -0
  284. package/wasm/tree-sitter-matlab.wasm +0 -0
  285. package/wasm/tree-sitter-nim.wasm +0 -0
  286. package/wasm/tree-sitter-objc.wasm +0 -0
  287. package/wasm/tree-sitter-ocaml.wasm +0 -0
  288. package/wasm/tree-sitter-perl.wasm +0 -0
  289. package/wasm/tree-sitter-php.wasm +0 -0
  290. package/wasm/tree-sitter-php_only.wasm +0 -0
  291. package/wasm/tree-sitter-powershell.wasm +0 -0
  292. package/wasm/tree-sitter-protobuf.wasm +0 -0
  293. package/wasm/tree-sitter-python.wasm +0 -0
  294. package/wasm/tree-sitter-ql.wasm +0 -0
  295. package/wasm/tree-sitter-r.wasm +0 -0
  296. package/wasm/tree-sitter-rescript.wasm +0 -0
  297. package/wasm/tree-sitter-ruby.wasm +0 -0
  298. package/wasm/tree-sitter-rust.wasm +0 -0
  299. package/wasm/tree-sitter-scala.wasm +0 -0
  300. package/wasm/tree-sitter-scss.wasm +0 -0
  301. package/wasm/tree-sitter-solidity.wasm +0 -0
  302. package/wasm/tree-sitter-sql.wasm +0 -0
  303. package/wasm/tree-sitter-svelte.wasm +0 -0
  304. package/wasm/tree-sitter-swift.wasm +0 -0
  305. package/wasm/tree-sitter-systemrdl.wasm +0 -0
  306. package/wasm/tree-sitter-terraform.wasm +0 -0
  307. package/wasm/tree-sitter-tlaplus.wasm +0 -0
  308. package/wasm/tree-sitter-toml.wasm +0 -0
  309. package/wasm/tree-sitter-tsx.wasm +0 -0
  310. package/wasm/tree-sitter-typescript.wasm +0 -0
  311. package/wasm/tree-sitter-vba.wasm +0 -0
  312. package/wasm/tree-sitter-vbnet.wasm +0 -0
  313. package/wasm/tree-sitter-vue.wasm +0 -0
  314. package/wasm/tree-sitter-xml.wasm +0 -0
  315. package/wasm/tree-sitter-yaml.wasm +0 -0
  316. package/wasm/tree-sitter-zig.wasm +0 -0
  317. package/wasm/tree-sitter.wasm +0 -0
  318. package/wasm/tsx.wasm +0 -0
  319. package/wasm/typescript.wasm +0 -0
@@ -0,0 +1,1153 @@
1
+ #!/usr/bin/env bun
2
+ import {
3
+ BINDING_SEP,
4
+ decodeSourceText
5
+ } from "./chunk-KAET47ZL.js";
6
+ import {
7
+ detectLanguageFromPath
8
+ } from "./chunk-KCDECRJY.js";
9
+ import "./chunk-MLKGABMK.js";
10
+
11
+ // src/ast/pool-worker.ts
12
+ import { createHash } from "crypto";
13
+ import { createRequire } from "module";
14
+ import path from "path";
15
+ import fs from "fs";
16
+ var require2 = createRequire(import.meta.url);
17
+ if (!process.env.BB_LOG_LEVEL) {
18
+ process.env.BB_LOG_LEVEL = "error";
19
+ }
20
+ function bbDiagnosticsLogPath(name) {
21
+ const dataDir = process.env.BB_DATA_DIR || path.join(process.env.HOME || process.env.USERPROFILE || "/tmp", ".bb");
22
+ const logsDir = path.join(dataDir, "logs");
23
+ try {
24
+ fs.mkdirSync(logsDir, { recursive: true });
25
+ } catch {
26
+ }
27
+ return path.join(logsDir, name);
28
+ }
29
+ function log(..._args) {
30
+ }
31
+ var startupDiagnostics = [];
32
+ var reportedStartupProblems = /* @__PURE__ */ new Set();
33
+ function reportStartupProblem(what, error) {
34
+ const message = error instanceof Error ? error.message : String(error);
35
+ const line = `${what}: ${message}`;
36
+ if (reportedStartupProblems.has(line)) return;
37
+ reportedStartupProblems.add(line);
38
+ process.stderr.write(`[BB-WORKER-STARTUP] ${line}
39
+ `);
40
+ startupDiagnostics.push(line.slice(0, 300));
41
+ }
42
+ function safeSend(message) {
43
+ try {
44
+ if (typeof process.send !== "function") return false;
45
+ if (process.connected === false) return false;
46
+ process.send(message);
47
+ return true;
48
+ } catch {
49
+ return false;
50
+ }
51
+ }
52
+ function extractBasicSymbols(content, language) {
53
+ const symbols = [];
54
+ const lines = content.split("\n");
55
+ const patterns = {
56
+ typescript: [
57
+ /^(?:export\s+)?(?:async\s+)?function\s+(\w+)/,
58
+ /^(?:export\s+)?class\s+(\w+)/,
59
+ /^(?:export\s+)?interface\s+(\w+)/,
60
+ /^(?:export\s+)?type\s+(\w+)/,
61
+ /^(?:export\s+)?(?:const|let|var)\s+(\w+)/,
62
+ /^\s*(?:public|private|protected)?\s*(?:async\s+)?(\w+)\s*\(/
63
+ ],
64
+ javascript: [
65
+ /^(?:export\s+)?(?:async\s+)?function\s+(\w+)/,
66
+ /^(?:export\s+)?class\s+(\w+)/,
67
+ /^(?:export\s+)?(?:const|let|var)\s+(\w+)/
68
+ ],
69
+ python: [/^(?:async\s+)?def\s+(\w+)/, /^class\s+(\w+)/],
70
+ svelte: [
71
+ /^\s*export\s+let\s+(\w+)/,
72
+ /^\s*\$:.*?\s*=\s*(.+)/,
73
+ /^\s*const\s+(\w+)\s*=\s*\$state/,
74
+ /^\s*const\s+(\w+)\s*=\s*\$derived/,
75
+ /^\s*\$effect\s*\(/,
76
+ /^\s*\$props\s*\(/,
77
+ /^\s*function\s+(\w+)/,
78
+ /^\s*class\s+(\w+)/
79
+ ],
80
+ go: [/^func\s+(?:\([^)]+\)\s+)?(\w+)/, /^type\s+(\w+)\s+struct/, /^type\s+(\w+)\s+interface/],
81
+ rust: [
82
+ /^(?:pub\s+)?(?:async\s+)?fn\s+(\w+)/,
83
+ /^(?:pub\s+)?struct\s+(\w+)/,
84
+ /^(?:pub\s+)?trait\s+(\w+)/,
85
+ /^(?:pub\s+)?impl(?:\s+\w+)?\s+(?:for\s+)?(\w+)/
86
+ ],
87
+ java: [
88
+ /^(?:public|private|protected)?\s*(?:static\s+)?(?:final\s+)?class\s+(\w+)/,
89
+ /^(?:public|private|protected)?\s*(?:static\s+)?(?:final\s+)?interface\s+(\w+)/,
90
+ /^(?:public|private|protected)?\s*(?:static\s+)?(?:\w+\s+)+(\w+)\s*\(/
91
+ ],
92
+ kotlin: [
93
+ /^(?:fun|suspend\s+fun)\s+(\w+)/,
94
+ /^(?:class|data\s+class|sealed\s+class|object)\s+(\w+)/,
95
+ /^interface\s+(\w+)/
96
+ ],
97
+ swift: [/^(?:func|class\s+func|static\s+func)\s+(\w+)/, /^(?:class|struct|protocol|enum)\s+(\w+)/],
98
+ ruby: [/^def\s+(\w+)/, /^class\s+(\w+)/, /^module\s+(\w+)/],
99
+ php: [
100
+ /^(?:public|private|protected)?\s*function\s+(\w+)/,
101
+ /^class\s+(\w+)/,
102
+ /^interface\s+(\w+)/,
103
+ /^trait\s+(\w+)/
104
+ ],
105
+ csharp: [
106
+ /^(?:public|private|protected|internal)?\s*(?:static\s+)?(?:async\s+)?(?:\w+\s+)+(\w+)\s*\(/,
107
+ /^(?:public|private|protected|internal)?\s*(?:partial\s+)?class\s+(\w+)/,
108
+ /^(?:public|private|protected|internal)?\s*interface\s+(\w+)/
109
+ ]
110
+ };
111
+ const langPatterns = patterns[language] || patterns.javascript || [];
112
+ for (let i = 0; i < lines.length; i++) {
113
+ const line = lines[i].trim();
114
+ for (const pattern of langPatterns) {
115
+ const match = line.match(pattern);
116
+ if (match && match[1]) {
117
+ const name = match[1];
118
+ if (["if", "for", "while", "switch", "catch", "return", "new", "this", "super"].includes(name)) continue;
119
+ let type = "function";
120
+ if (/class\s/.test(line)) type = "class";
121
+ else if (/interface\s/.test(line)) type = "interface";
122
+ else if (/struct\s/.test(line)) type = "class";
123
+ else if (/trait\s/.test(line) || /protocol\s/.test(line)) type = "interface";
124
+ else if (/type\s/.test(line)) type = "type";
125
+ else if (/const\s|let\s|var\s/.test(line)) type = "variable";
126
+ else if (/module\s/.test(line) || /namespace\s/.test(line)) type = "module";
127
+ else if (language === "svelte") {
128
+ if (/export\s+let/.test(line)) type = "prop";
129
+ else if (/^\$:\s/.test(line)) type = "reactive";
130
+ else if (/\$state/.test(line)) type = "rune";
131
+ else if (/\$derived/.test(line)) type = "rune";
132
+ else if (/\$effect\(/.test(line)) type = "rune";
133
+ else if (/\$props\(/.test(line)) type = "rune";
134
+ }
135
+ let byteOffset = 0;
136
+ for (let j = 0; j < i; j++) byteOffset += lines[j].length + 1;
137
+ const lineLen = lines[i].length;
138
+ symbols.push({
139
+ name,
140
+ type,
141
+ startLine: i + 1,
142
+ endLine: i + 1
143
+ });
144
+ break;
145
+ }
146
+ }
147
+ }
148
+ return symbols;
149
+ }
150
+ function extractBasicImports(content, language) {
151
+ const imports = [];
152
+ const lines = content.split("\n");
153
+ const patterns = {
154
+ typescript: [
155
+ /import\s+(?:{([^}]+)}|(\w+))\s+from\s+['"]([^'"]+)['"]/,
156
+ /import\s+\*\s+as\s+(\w+)\s+from\s+['"]([^'"]+)['"]/
157
+ ],
158
+ javascript: [/import\s+(?:{([^}]+)}|(\w+))\s+from\s+['"]([^'"]+)['"]/, /require\s*\(\s*['"]([^'"]+)['"]\s*\)/],
159
+ python: [/^from\s+([\w.]+)\s+import\s+(.+)$/, /^import\s+([\w.]+)/],
160
+ go: [/import\s+(?:"([^"]+)"|(\w+)\s+"([^"]+)")/],
161
+ rust: [/use\s+([\w:]+)(?:::\{([^}]+)\})?/],
162
+ java: [/import\s+(?:static\s+)?([\w.]+)/]
163
+ };
164
+ const GROUP_ROLES = {
165
+ typescript: { module: 3, items: 1 },
166
+ javascript: { module: 3, items: 1 },
167
+ python: { module: 1, items: 2 },
168
+ go: { module: 3, items: 1 },
169
+ rust: { module: 1, items: 2 },
170
+ java: { module: 1, items: 1 }
171
+ };
172
+ const langPatterns = patterns[language] || patterns.javascript || [];
173
+ for (let i = 0; i < lines.length; i++) {
174
+ const line = lines[i].trim();
175
+ for (const pattern of langPatterns) {
176
+ const match = line.match(pattern);
177
+ if (match) {
178
+ const roles = GROUP_ROLES[language] ?? GROUP_ROLES.javascript;
179
+ const path2 = String(match[roles.module] ?? "");
180
+ const names = String(match[roles.items] ?? "");
181
+ if (!path2) continue;
182
+ const isExternal = !path2.startsWith(".") && !path2.startsWith("/");
183
+ const items = names.split(",").map((s) => s.trim()).filter(Boolean);
184
+ if (items.length === 0) items.push(path2.split("/").pop() || path2);
185
+ for (const name of items) {
186
+ const asMatch = name.match(/^(\S+)\s+as\s+(\S+)$/);
187
+ imports.push({
188
+ name: asMatch ? asMatch[1] : name,
189
+ alias: asMatch ? asMatch[2] : void 0,
190
+ path: path2,
191
+ type: "named",
192
+ isExternal,
193
+ line: i + 1
194
+ });
195
+ }
196
+ break;
197
+ }
198
+ }
199
+ }
200
+ return imports;
201
+ }
202
+ function extractBasicRelationships(content, _language, symbols, imports = []) {
203
+ const rels = [];
204
+ const knownNames = new Set(symbols.map((s) => s.name));
205
+ for (const imp of imports) {
206
+ knownNames.add(imp.name);
207
+ }
208
+ const knownFunctions = new Set(
209
+ symbols.filter((s) => s.type === "function" || s.type === "method").map((s) => s.name)
210
+ );
211
+ const lines = content.split("\n");
212
+ const callPattern = /(\w+)\s*\(/g;
213
+ const methodCallPattern = /(\w+)\.(\w+)\s*\(/g;
214
+ const newPattern = /new\s+(\w+)\s*[\(<]/g;
215
+ for (let i = 0; i < lines.length; i++) {
216
+ const line = lines[i];
217
+ let nmatch;
218
+ while ((nmatch = newPattern.exec(line)) !== null) {
219
+ const className = nmatch[1];
220
+ if (className.length < 2) continue;
221
+ if (className === className.toUpperCase()) continue;
222
+ if (knownNames.has(className)) {
223
+ rels.push({
224
+ source: "this",
225
+ target: className,
226
+ type: "instantiates",
227
+ confidence: 0.6,
228
+ metadata: { line: i + 1, method: "regex", isNew: true }
229
+ });
230
+ }
231
+ }
232
+ newPattern.lastIndex = 0;
233
+ let match;
234
+ while ((match = methodCallPattern.exec(line)) !== null) {
235
+ const target = match[2];
236
+ if (knownFunctions.has(target) || knownNames.has(target)) {
237
+ rels.push({
238
+ source: match[1],
239
+ // object name (approximate)
240
+ target,
241
+ type: "calls",
242
+ confidence: 0.4,
243
+ // Lower confidence: regex-based, may have false positives
244
+ metadata: { line: i + 1, method: "regex" }
245
+ });
246
+ }
247
+ }
248
+ methodCallPattern.lastIndex = 0;
249
+ while ((match = callPattern.exec(line)) !== null) {
250
+ const target = match[1];
251
+ if ([
252
+ "if",
253
+ "for",
254
+ "while",
255
+ "switch",
256
+ "catch",
257
+ "return",
258
+ "new",
259
+ "this",
260
+ "super",
261
+ "function",
262
+ "class",
263
+ "import",
264
+ "export",
265
+ "const",
266
+ "let",
267
+ "var",
268
+ "typeof",
269
+ "instanceof",
270
+ "throw",
271
+ "else",
272
+ "case",
273
+ "default",
274
+ "break",
275
+ "continue",
276
+ "delete",
277
+ "void"
278
+ ].includes(target)) continue;
279
+ if (target.length < 2) continue;
280
+ if (target === target.toUpperCase() && target.length > 3) continue;
281
+ if (target.startsWith("_") && target.length < 3) continue;
282
+ if (knownFunctions.has(target) || knownNames.has(target)) {
283
+ rels.push({
284
+ source: "this",
285
+ target,
286
+ type: "calls",
287
+ confidence: 0.5,
288
+ metadata: { line: i + 1, method: "regex" }
289
+ });
290
+ }
291
+ }
292
+ callPattern.lastIndex = 0;
293
+ }
294
+ const seen = /* @__PURE__ */ new Set();
295
+ return rels.filter((r) => {
296
+ const key = `${r.source}:${r.target}:${r.type}`;
297
+ if (seen.has(key)) return false;
298
+ seen.add(key);
299
+ return true;
300
+ });
301
+ }
302
+ function extractFallback(content, language, hash, sizeBytes, lastModified) {
303
+ const symbols = extractBasicSymbols(content, language);
304
+ const imports = extractBasicImports(content, language);
305
+ const relationships = filterNoiseRelationships(
306
+ extractBasicRelationships(content, language, symbols, imports),
307
+ language,
308
+ new Set(symbols.map((s) => String(s?.name ?? "")).filter(Boolean))
309
+ );
310
+ return {
311
+ success: true,
312
+ language,
313
+ framework: null,
314
+ fileHash: hash,
315
+ sizeBytes,
316
+ lastModified,
317
+ symbols,
318
+ imports,
319
+ relationships,
320
+ errors: [],
321
+ fallback: true
322
+ };
323
+ }
324
+ var NOISE_TARGETS = /* @__PURE__ */ new Set([
325
+ // Tree-sitter AST internals
326
+ "namedChild",
327
+ "childForFieldName",
328
+ "namedChildren",
329
+ "childCount",
330
+ "namedChildCount",
331
+ "type",
332
+ "text",
333
+ "startIndex",
334
+ "endIndex",
335
+ "startPosition",
336
+ "endPosition",
337
+ "nextSibling",
338
+ "previousSibling",
339
+ "firstChild",
340
+ "lastChild",
341
+ "parent",
342
+ // CSS properties that leak into relationships (hyphenated names)
343
+ "font-size",
344
+ "background-color",
345
+ "align-items",
346
+ "justify-content",
347
+ "flex-direction",
348
+ "border-radius",
349
+ "font-weight",
350
+ "line-height",
351
+ "margin-bottom",
352
+ "min-width",
353
+ // Test-framework boilerplate (NOT valid production targets)
354
+ "setUp",
355
+ "tearDown",
356
+ "setUpBeforeClass",
357
+ "tearDownAfterClass",
358
+ "beforeEach",
359
+ "afterEach"
360
+ ]);
361
+ function isDeclarationShaped(s) {
362
+ const r = s?.range ?? {};
363
+ const st = Number(r.startIndex ?? s?.startIndex);
364
+ const en = Number(r.endIndex ?? s?.endIndex);
365
+ const sl = Number(r.startLine ?? s?.startLine);
366
+ const el = Number(r.endLine ?? s?.endLine);
367
+ return Number.isFinite(st) && Number.isFinite(en) && en > st && Number.isFinite(sl) && sl >= 1 && Number.isFinite(el) && el >= sl;
368
+ }
369
+ function keepSymbol(s, lang) {
370
+ const name = s.name || "";
371
+ if (s.qualifiedName?.startsWith("__global__")) return false;
372
+ if (lang === "json" || lang === "yaml" || lang === "xml" || lang === "make" || lang === "markdown") return true;
373
+ const JS_FAMILY = /* @__PURE__ */ new Set(["javascript", "typescript", "tsx", "vue", "svelte"]);
374
+ const JS_GLOBALS = /* @__PURE__ */ new Set([
375
+ "window",
376
+ "document",
377
+ "console",
378
+ "process",
379
+ "global",
380
+ "__dirname",
381
+ "__filename",
382
+ "module",
383
+ "exports",
384
+ "default",
385
+ "globalThis"
386
+ ]);
387
+ if (JS_FAMILY.has(lang) && JS_GLOBALS.has(name)) return isDeclarationShaped(s);
388
+ const UNIVERSAL = /* @__PURE__ */ new Set([
389
+ // Reserved in essentially every language parsed here. Kept unconditionally
390
+ // because no lane produced a legitimate declaration of any of them.
391
+ "this",
392
+ "super",
393
+ // Synthetic artifact names the analyzers themselves mint. These are OURS, not
394
+ // the language's, so no user program can declare them.
395
+ "SCSS_FILE_SCOPE",
396
+ "GlobalScope",
397
+ "module_declaration",
398
+ "package_manifest"
399
+ // REMOVED, each with a lane and a count — see the comment above:
400
+ // self, Self deleted R/Python/Zig `self`; lua declares `local this`
401
+ // me, My legitimate in every language (graphql `me`, lua `me`)
402
+ // destructor a real method name in C++/Rust/Go
403
+ // root lua `local root` at lazy.nvim/lua/lazy/core/loader.lua:497
404
+ // program a legal SQL column name
405
+ // source_file an ordinary R function
406
+ // unknown hcl files declare a variable literally named `unknown`
407
+ //
408
+ // `unknown` is the one that cannot simply be deleted: R7 counts it as a
409
+ // PLACEHOLDER, and 46 registered placeholder sites depend on that. It now moves
410
+ // to RESERVED below rather than being dropped, so a placeholder is still refused
411
+ // while a declared `unknown` survives.
412
+ ]);
413
+ if (lang === "julia" && name === "this") return true;
414
+ if (UNIVERSAL.has(name)) return false;
415
+ const RESERVED = {
416
+ // `self` is reserved in PHP and Python 2-style declarations but a LEGAL variable
417
+ // in Lua, Python 3, Rust and Zig, all of which are parsed here.
418
+ php: /* @__PURE__ */ new Set(["self", "parent"]),
419
+ // `program` is reserved in Haskell/Elm-ish contexts; it is a SQL column name.
420
+ sql: /* @__PURE__ */ new Set(["program"])
421
+ };
422
+ if (RESERVED[lang]?.has(name)) {
423
+ const PHP_MEMBER_KINDS = /* @__PURE__ */ new Set(["method", "property", "constant", "enum_member"]);
424
+ const isPhpMember = lang === "php" && PHP_MEMBER_KINDS.has(String(s.kind)) && Boolean(s.ownerName);
425
+ if (!isPhpMember) return false;
426
+ }
427
+ return true;
428
+ }
429
+ function nameTheSymbolRule(s, lang) {
430
+ const name = s.name || "";
431
+ if (s.qualifiedName?.startsWith("__global__")) return "qualifiedName is the __global__ sentinel";
432
+ if (["json", "yaml", "xml", "make", "markdown"].includes(lang)) return "language-exempt (kept)";
433
+ if ((/* @__PURE__ */ new Set(["javascript", "typescript", "tsx", "vue", "svelte"])).has(lang) && (/* @__PURE__ */ new Set([
434
+ "window",
435
+ "document",
436
+ "console",
437
+ "process",
438
+ "global",
439
+ "__dirname",
440
+ "__filename",
441
+ "module",
442
+ "exports",
443
+ "default",
444
+ "globalThis"
445
+ ])).has(name)) return "JS-family global name";
446
+ return "UNIVERSAL denylist (a keyword or a synthetic tree-sitter artifact name)";
447
+ }
448
+ var JS_FAMILY_LANGUAGES = /* @__PURE__ */ new Set(["javascript", "typescript", "tsx", "vue", "svelte"]);
449
+ var CSS_FAMILY_LANGUAGES = /* @__PURE__ */ new Set(["css", "scss", "sass", "less"]);
450
+ var NOISE_TARGET_FAMILIES = {};
451
+ for (const n of [
452
+ "namedChild",
453
+ "childForFieldName",
454
+ "namedChildren",
455
+ "childCount",
456
+ "namedChildCount",
457
+ "type",
458
+ "text",
459
+ "startIndex",
460
+ "endIndex",
461
+ "startPosition",
462
+ "endPosition",
463
+ "nextSibling",
464
+ "previousSibling",
465
+ "firstChild",
466
+ "lastChild",
467
+ "parent"
468
+ ]) {
469
+ NOISE_TARGET_FAMILIES[n] = JS_FAMILY_LANGUAGES;
470
+ }
471
+ for (const n of [
472
+ "font-size",
473
+ "background-color",
474
+ "align-items",
475
+ "justify-content",
476
+ "flex-direction",
477
+ "border-radius",
478
+ "font-weight",
479
+ "line-height",
480
+ "margin-bottom",
481
+ "min-width"
482
+ ]) {
483
+ NOISE_TARGET_FAMILIES[n] = CSS_FAMILY_LANGUAGES;
484
+ }
485
+ function importBindingNames(imports) {
486
+ const names = /* @__PURE__ */ new Set();
487
+ const add = (raw) => {
488
+ if (typeof raw !== "string") return;
489
+ let s = raw.trim();
490
+ if (!s) return;
491
+ const colon = s.lastIndexOf(":");
492
+ if (colon >= 0) s = s.slice(colon + 1).trim();
493
+ const slash = s.lastIndexOf("/");
494
+ if (slash >= 0) s = s.slice(slash + 1).trim();
495
+ if (!s) return;
496
+ const asAt = s.indexOf(" as ");
497
+ if (asAt > 0) {
498
+ const imported = s.slice(0, asAt).trim();
499
+ const local = s.slice(asAt + 4).trim();
500
+ if (imported) names.add(imported);
501
+ if (local) names.add(local);
502
+ return;
503
+ }
504
+ names.add(s);
505
+ };
506
+ for (const i of imports ?? []) {
507
+ if (!i || typeof i !== "object") continue;
508
+ if (Array.isArray(i.items)) for (const it of i.items) add(it);
509
+ add(i.localName);
510
+ add(i.defaultName);
511
+ add(i.alias);
512
+ add(i.namespaceName);
513
+ }
514
+ return names;
515
+ }
516
+ function filterNoiseRelationships(rels, language, declaredNames, boundNames) {
517
+ if (!rels || rels.length === 0) return rels;
518
+ const extractLeaf = (name) => {
519
+ const afterSep = BINDING_SEP.length > 0 && name.includes(BINDING_SEP) ? name.slice(name.lastIndexOf(BINDING_SEP) + BINDING_SEP.length) : name;
520
+ const noLine = afterSep.replace(/:\d+$/, "");
521
+ const segments = noLine.split(":").filter((s) => s.length > 0);
522
+ const last = segments[segments.length - 1] ?? "";
523
+ const dotParts = last.split(".");
524
+ return dotParts[dotParts.length - 1];
525
+ };
526
+ return rels.filter((r) => {
527
+ const target = r.target || r.targetId || r.to || r.toSymbol || "";
528
+ if (!target) return true;
529
+ if (language === "json" || language === "yaml" || language === "hcl" || language === "terraform" || language === "graphql" || language === "toml") return true;
530
+ if ((language === "bash" || language === "toml") && (r.type === "imports" || r.type === "references" || r.relationshipType === "imports" || r.relationshipType === "references")) {
531
+ if (target.length > 200 || target.includes("\n")) return false;
532
+ return true;
533
+ }
534
+ if (language === "julia" && target.includes('var"') && (r.type === "contains" || r.type === "calls" || r.type === "references" || r.relationshipType === "contains" || r.relationshipType === "calls" || r.relationshipType === "references")) {
535
+ if (target.includes("\n") || target.includes(" ") || target.includes(" ")) return false;
536
+ return true;
537
+ }
538
+ if (language === "julia" && target.trim() === ":" && (r.type === "calls" || r.relationshipType === "calls")) return true;
539
+ if (target.includes("\n")) return false;
540
+ const leaf = extractLeaf(target);
541
+ const lower = leaf.toLowerCase();
542
+ if (leaf.length < 1) return false;
543
+ const SETTER_NAME = /^[A-Za-z_$][A-Za-z0-9_$]*=$/;
544
+ const OPERATOR_NAME = /^[<>=!+\-*/%^&|~\[\]]+$/;
545
+ const CALLABLE_REF = /^@(?:mixin|function)\s+[A-Za-z_$][\w$-]*$/;
546
+ const DERIVED_TEMPLATE_ID = /xsl:template\[[^\]]*\](?:#\d+)?$/;
547
+ const DECLARED_SIGNATURE = /^[A-Za-z_$][A-Za-z0-9_$]*\(\)$/;
548
+ const isDeclaredSignature = DECLARED_SIGNATURE.test(leaf) && ((declaredNames?.has(leaf) ?? false) || (declaredNames?.has(target) ?? false));
549
+ const isDeclaredName = (declaredNames?.has(leaf) ?? false) || (declaredNames?.has(target) ?? false);
550
+ if (/[\s'"(),=]/.test(leaf) && !OPERATOR_NAME.test(leaf) && !SETTER_NAME.test(leaf) && !CALLABLE_REF.test(leaf) && !DERIVED_TEMPLATE_ID.test(target) && !isDeclaredSignature && !isDeclaredName) return false;
551
+ const isOperatorName = /^[<>=!+\-*/%^&|~\[\]]+$/.test(leaf);
552
+ if (!isOperatorName && /[{}`<>\n\r\t]/.test(leaf)) return false;
553
+ if (leaf.startsWith(" ") || leaf.includes(" ")) return false;
554
+ const declaredTarget = !!declaredNames && (declaredNames.has(String(r.target ?? r.to ?? "")) || declaredNames.has(leaf));
555
+ if (NOISE_TARGETS.has(leaf) && !declaredTarget && // UNION: main's second hatch — a name the file BINDS without declaring (an imported binding is
556
+ // not framework noise). Absent here, present there, and the probe taken from main depends on it.
557
+ !(boundNames && boundNames.has(leaf))) {
558
+ const family = NOISE_TARGET_FAMILIES[leaf];
559
+ if (family && !family.has(language)) return true;
560
+ return false;
561
+ }
562
+ return true;
563
+ });
564
+ }
565
+ var SNIPPET_KINDS = /* @__PURE__ */ new Set(["function", "class", "method", "interface", "impl", "struct"]);
566
+ var engineModule = null;
567
+ async function parseFile(filePath, projectPath, context) {
568
+ const stat = await import("fs/promises").then((fs2) => fs2.stat(filePath));
569
+ const sizeBytes = stat.size;
570
+ const lastModified = stat.mtimeMs;
571
+ const ext = path.extname(filePath).toLowerCase();
572
+ const language = detectLanguageFromPath(filePath) ?? "unknown";
573
+ const STRUCTURAL_LIMIT = 5 * 1024 * 1024;
574
+ if (sizeBytes > STRUCTURAL_LIMIT) {
575
+ log(`Skipping file over 5MB: ${filePath} (${sizeBytes} bytes)`);
576
+ return {
577
+ success: true,
578
+ language,
579
+ fileHash: createHash("sha256").update("").digest("hex").slice(0, 16),
580
+ sizeBytes,
581
+ lastModified,
582
+ symbols: [],
583
+ imports: [],
584
+ relationships: [],
585
+ errors: [],
586
+ fallback: true
587
+ };
588
+ }
589
+ const FULL_AST_LIMIT = 1 * 1024 * 1024;
590
+ if (sizeBytes > FULL_AST_LIMIT) {
591
+ const fsModule = await import("fs/promises");
592
+ const fd = await fsModule.open(filePath, "r");
593
+ const buffer = Buffer.alloc(Math.min(sizeBytes, 256 * 1024));
594
+ await fd.read(buffer, 0, buffer.length, 0);
595
+ await fd.close();
596
+ const content2 = decodeSourceText(buffer).text;
597
+ const hash2 = createHash("sha256").update(content2).digest("hex").slice(0, 16);
598
+ log(`Using structural extraction for large file: ${filePath} (${sizeBytes} bytes)`);
599
+ return extractFallback(content2, language, hash2, sizeBytes, lastModified);
600
+ }
601
+ const decoded = decodeSourceText(await import("fs/promises").then((fs2) => fs2.readFile(filePath)));
602
+ const content = decoded.text;
603
+ const hash = createHash("sha256").update(content).digest("hex").slice(0, 16);
604
+ if (decoded.encoding !== "utf8" || decoded.inferred) {
605
+ log(`Decoded ${filePath} as ${decoded.encoding}${decoded.inferred ? " (inferred from a NUL pattern, no BOM)" : decoded.hadBom ? " (BOM)" : ""}`);
606
+ }
607
+ try {
608
+ if (!engineModule) {
609
+ engineModule = await import("./engine-LO6L4JLQ.js");
610
+ }
611
+ const parsed = await engineModule.ASTEngine.parseFile(filePath, content, context);
612
+ if ((parsed?.symbols?.length || 0) === 0 && (parsed?.errors?.length || 0) > 0) {
613
+ try {
614
+ const errSample = parsed.errors.slice(0, 3).map((e) => e.message).join(" | ");
615
+ fs.appendFileSync(
616
+ bbDiagnosticsLogPath("parse-errors.log"),
617
+ `${(/* @__PURE__ */ new Date()).toISOString()} | ${language} | ${sizeBytes}B | ${filePath} | ENGINE_EMPTY: ${errSample.substring(0, 200)}
618
+ `
619
+ );
620
+ } catch {
621
+ }
622
+ }
623
+ if (ext === ".dart") {
624
+ try {
625
+ fs.appendFileSync(
626
+ bbDiagnosticsLogPath("worker-debug.log"),
627
+ `[Worker] ASTEngine.parseFile returned ${parsed?.relationships?.length || 0} relationships for ${filePath}
628
+ `
629
+ );
630
+ } catch {
631
+ }
632
+ }
633
+ const TAINT_ELIGIBLE_LANGUAGES = /* @__PURE__ */ new Set([
634
+ // The languages the engine dispatches to a REAL analyzer AND for which
635
+ // the taint rules are written against a language API (`db.query`,
636
+ // `child_process`, `PreparedStatement`, `cursor.execute`, …).
637
+ "typescript",
638
+ "tsx",
639
+ "javascript",
640
+ "java",
641
+ "kotlin",
642
+ "scala",
643
+ "groovy",
644
+ "python",
645
+ "ruby",
646
+ "php",
647
+ "go",
648
+ "rust",
649
+ "swift",
650
+ "dart",
651
+ "c",
652
+ "cpp",
653
+ "csharp",
654
+ "perl",
655
+ "lua",
656
+ "r",
657
+ "elixir",
658
+ "erlang",
659
+ "clojure",
660
+ "haskell",
661
+ "zig",
662
+ "nim",
663
+ "fsharp",
664
+ "vb",
665
+ "powershell",
666
+ "bash",
667
+ "objective-c"
668
+ // Explicitly EXCLUDED, and each exclusion is load-bearing:
669
+ // markdown json yaml toml xml html css sass scss graphql protobuf
670
+ // make clean hcl terraform svelte vue sql
671
+ // Markdown/JSON/YAML/TOML/XML/HTML/CSS carry prose and data, not code —
672
+ // measured at 326 of 3,190 bb_security findings (10.2%). The rest are
673
+ // schema, query, build and markup formats whose tokens ("select", "exec",
674
+ // "query") collide with the sink rules without ever being a sink.
675
+ ]);
676
+ const taintEligible = TAINT_ELIGIBLE_LANGUAGES.has((language || "").toLowerCase());
677
+ try {
678
+ if (taintEligible) {
679
+ const { TaintAnalyzer } = await import("./taint-analyzer-N7YLZU3N.js");
680
+ TaintAnalyzer.enrichSymbols(parsed.symbols, content, language);
681
+ }
682
+ } catch (e) {
683
+ log("Taint extraction failed:", e);
684
+ }
685
+ let snippetLines;
686
+ const identityOf = (s) => {
687
+ const out = [];
688
+ if (s?.name) out.push(String(s.name));
689
+ if (s?.qualifiedName) out.push(String(s.qualifiedName));
690
+ if (typeof s?.metadata?.fqn === "string" && s.metadata.fqn) out.push(String(s.metadata.fqn));
691
+ if (s?.name) {
692
+ out.push(
693
+ s.qualifiedName || s.metadata?.fqn || (s.scope ? `${s.scope}.${s.name}` : String(s.name))
694
+ );
695
+ }
696
+ return out;
697
+ };
698
+ const keptSymbols = [];
699
+ const keptNames = /* @__PURE__ */ new Set();
700
+ const notKept = [];
701
+ for (const s of parsed.symbols ?? []) {
702
+ if (keepSymbol(s, parsed.language || language)) {
703
+ keptSymbols.push(s);
704
+ for (const id of identityOf(s)) keptNames.add(id);
705
+ } else {
706
+ notKept.push(s);
707
+ }
708
+ }
709
+ const droppedNames = /* @__PURE__ */ new Set();
710
+ for (const s of notKept) {
711
+ for (const id of identityOf(s)) {
712
+ if (!keptNames.has(id)) droppedNames.add(id);
713
+ }
714
+ }
715
+ const ret = {
716
+ success: true,
717
+ language: parsed.language || language,
718
+ framework: parsed.metadata?.framework,
719
+ fileHash: hash,
720
+ sizeBytes,
721
+ lastModified,
722
+ symbols: keptSymbols.map((s) => {
723
+ let snippet = "";
724
+ if (SNIPPET_KINDS.has(s.kind)) {
725
+ const lines = snippetLines ?? (snippetLines = content.split("\n"));
726
+ snippet = lines.slice(Math.max(0, s.range.startLine - 1), s.range.endLine).join("\n");
727
+ if (snippet.length > 1e4) snippet = snippet.substring(0, 1e4);
728
+ }
729
+ return {
730
+ name: s.name,
731
+ type: s.kind,
732
+ kind: s.kind,
733
+ qualifiedName: s.qualifiedName || s.metadata?.fqn || (s.scope ? `${s.scope}.${s.name}` : s.name),
734
+ startLine: s.range.startLine,
735
+ endLine: s.range.endLine,
736
+ startIndex: s.range.startIndex,
737
+ endIndex: s.range.endIndex,
738
+ visibility: s.visibility || "public",
739
+ parameters: s.parameters,
740
+ returnType: s.returnType,
741
+ qualifiedCalls: s.qualified_calls,
742
+ complexity: s.complexity || s.metadata?.complexity || 1,
743
+ ownerName: s.ownerName || s.scope,
744
+ ownerKind: s.ownerKind || s.metadata?.ownerKind,
745
+ scope: s.scope,
746
+ taintSources: s.taintSources,
747
+ taintSinks: s.taintSinks,
748
+ decorators: s.decorators,
749
+ genericParameters: s.genericParameters,
750
+ isStatic: s.isStatic,
751
+ isAsync: s.isAsync,
752
+ isAbstract: s.isAbstract,
753
+ // M35 pre-work: carry the analyzer-extracted docstring across the
754
+ // worker boundary. It was dropped here AND never bound in the
755
+ // brain_symbol INSERT, so brain_symbol.docstring was always NULL.
756
+ docstring: s.docstring ?? null,
757
+ // SOL-16. `docstring` alone cannot answer "is this NatSpec, or a stray
758
+ // `//` remark?" — and Solidity's documentation system has THREE forms
759
+ // (`///`, the slash-star block, and a plain line comment), so the kind is
760
+ // the difference between documented code and a comment that happened to sit
761
+ // above a declaration. `docTags` is the structured half: the tags are inside
762
+ // `docstring` already, but a consumer that wants `@param` names should not
763
+ // have to re-parse prose, and `comments` is the per-comment array the
764
+ // TypeScript lane populates for the same job, so a reader of Solidity
765
+ // documentation should not have to learn a second shape.
766
+ //
767
+ // Purely additive, on the same terms as the CSS forwarding above: nothing
768
+ // read these before, so no consumer changes behaviour.
769
+ // SOL-22. A LICENCE is a file-level fact and the module symbol is the only
770
+ // symbol that can carry it, so without this key a Solidity file's licence was
771
+ // in the analyzer's payload and in no consumer's hands — the same seam as
772
+ // `docstring` above, and the same terms: additive, nothing read it before.
773
+ license: s.license ?? s.metadata?.license ?? null,
774
+ // SOL-23: the NatSpec-vs-signature findings, per symbol. Additive on the same
775
+ // terms as the rest of this block.
776
+ undocumentedParameters: s.undocumentedParameters ?? null,
777
+ // Data location (`transient` / `storage` / `memory` / `calldata`). Read by the
778
+ // analyzer from the declaration's `location:` field, and invisible until it is
779
+ // whitelisted here. The CORPUS cannot exercise it — this grammar reports
780
+ // `transient` on the state-variable field rather than as a `layout_specifier`
781
+ // node, and no OpenZeppelin contract at 5.5.0 declares one — so the fixture is
782
+ // the only place this can be gated, which is worth knowing before anyone reads
783
+ // a zero here as a broken path.
784
+ stateLocation: s.stateLocation ?? s.metadata?.stateLocation ?? null,
785
+ overDocumentedParameters: s.overDocumentedParameters ?? null,
786
+ returnDocumentedWithoutReturn: s.returnDocumentedWithoutReturn ?? false,
787
+ docstringKind: s.docstringKind ?? s.metadata?.docstringKind ?? null,
788
+ docTags: s.docTags ?? s.metadata?.docTags ?? null,
789
+ comments: s.comments ?? s.metadata?.comments ?? null,
790
+ // #612 store-phase (same seam class as docstring above and scope_kind
791
+ // below): the declaration/definition fact. c has published
792
+ // `metadata.isDeclaration` since the HC1 review, and cpp/rust/zig
793
+ // publish it as of #612 — but the whole `metadata` object was dropped
794
+ // HERE, so brain_symbol.annotations was NULL for every analyzer
795
+ // symbol and the store had nothing but the NAME to resolve with. The
796
+ // narrow key is carried rather than all of metadata: it is the one
797
+ // metadata fact the store phase reads (a schema column of its own,
798
+ // `is_declaration`), and widening `annotations` for every symbol in
799
+ // every language is a separate, larger change that would need its own
800
+ // measurement round.
801
+ isDeclaration: s.metadata?.isDeclaration === true || void 0,
802
+ // CSS lane (2026-09-26). The same seam as `isDeclaration` above, met
803
+ // from the other side: the store DOES read `symbol.metadata` and
804
+ // serialise it into `brain_symbol.annotations`, but the whole
805
+ // `metadata` object is dropped HERE, so nothing an analyzer puts in it
806
+ // survives the worker boundary. For CSS that silently deleted a
807
+ // payload the lane's own ruling depends on — `declaresProperties`,
808
+ // which replaced 32,654 relationships to CSS property names that are
809
+ // not graph nodes (measured: `uses` resolved at both ends 6.0% of the
810
+ // time, and the production filter then discarded the class outright).
811
+ // Trading a wrong edge for a dead field is not a fix, so the payload is
812
+ // carried.
813
+ //
814
+ // Deliberately NARROW, and deliberately CSS-only, for the reason the
815
+ // comment above gives: widening `annotations` for every symbol in every
816
+ // language is a separate, larger change that needs its own measurement
817
+ // round. The keys below are the ones the CSS lane's F6/F8/CC1 checks
818
+ // read, so the channel carries facts that are consumed rather than
819
+ // facts that are merely produced.
820
+ // Emitted under the name the indexer already reads, so the existing
821
+ // `symbol.metadata -> annotations` INSERT path carries it with no
822
+ // change on the store side.
823
+ metadata: (() => {
824
+ const m = s.metadata;
825
+ if (!m) return void 0;
826
+ const out = {};
827
+ if (Array.isArray(m.declaresProperties)) out.declaresProperties = m.declaresProperties;
828
+ if (typeof m.declaredPropertyCount === "number") out.declaredPropertyCount = m.declaredPropertyCount;
829
+ if (typeof m.isSelector === "boolean") out.isSelector = m.isSelector;
830
+ if (typeof m.isComplex === "boolean") out.isComplex = m.isComplex;
831
+ if (typeof m.isUtility === "boolean") out.isUtility = m.isUtility;
832
+ if (typeof m.isCustomProperty === "boolean") out.isCustomProperty = m.isCustomProperty;
833
+ if (typeof m.isKeyframes === "boolean") out.isKeyframes = m.isKeyframes;
834
+ if (typeof m.isSupports === "boolean") out.isSupports = m.isSupports;
835
+ if (typeof m.isAtRule === "boolean") out.isAtRule = m.isAtRule;
836
+ if (typeof m.isCssModule === "boolean") out.isCssModule = m.isCssModule;
837
+ if (Array.isArray(m.specificity)) out.specificity = m.specificity;
838
+ if (Array.isArray(m.classNames)) out.classNames = m.classNames;
839
+ if (m.selectorComposition) out.selectorComposition = m.selectorComposition;
840
+ if (typeof m.supportsCondition === "string") out.supportsCondition = m.supportsCondition;
841
+ if (typeof m.atKeyword === "string") out.atKeyword = m.atKeyword;
842
+ if (Array.isArray(m.selectorChain)) out.selectorChain = m.selectorChain;
843
+ if (typeof m.nodeType === "string") out.nodeType = m.nodeType;
844
+ if (typeof m.headingLevel === "number") out.headingLevel = m.headingLevel;
845
+ if (typeof m.language === "string") out.language = m.language;
846
+ if (m.isMarkdownHeading === true) out.isMarkdownHeading = m.isMarkdownHeading;
847
+ if (m.isMarkdownTable === true) out.isMarkdownTable = m.isMarkdownTable;
848
+ if (m.isMarkdownTableColumn === true) out.isMarkdownTableColumn = m.isMarkdownTableColumn;
849
+ if (m.isMarkdownCodeBlock === true) out.isMarkdownCodeBlock = m.isMarkdownCodeBlock;
850
+ if (m.isMarkdownFrontMatter === true) out.isMarkdownFrontMatter = m.isMarkdownFrontMatter;
851
+ if (m.isRepeatedSite === true) out.isRepeatedSite = m.isRepeatedSite;
852
+ if (m.isExported === true) out.isExported = m.isExported;
853
+ if (m.isImplicitBinding === true) out.isImplicitBinding = m.isImplicitBinding;
854
+ if (typeof m.bindingSite === "string") out.bindingSite = m.bindingSite;
855
+ if (typeof m.isArray === "boolean") out.isArray = m.isArray;
856
+ if (Array.isArray(m.superTypes) && m.superTypes.length > 0) out.superTypes = m.superTypes;
857
+ return Object.keys(out).length > 0 ? out : void 0;
858
+ })(),
859
+ snippet
860
+ };
861
+ }),
862
+ imports: (parsed.imports || []).flatMap((i) => {
863
+ const items = Array.isArray(i.items) && i.items.length > 0 ? i.items : [i.localName || i.module || ""];
864
+ const baseType = i.isDefault || i.isDefaultImport ? "default" : i.isNamespace || i.isNamespaceImport ? "namespace" : "named";
865
+ const declared = i.metadata ?? {};
866
+ const external = declared.isSystemInclude === true || declared.isExternal === true || i.isExternal === true ? true : declared.isSystemInclude === false || declared.isExternal === false ? false : typeof i.module === "string" ? !i.module.startsWith(".") && !i.module.startsWith("/") : !!i.isExternal;
867
+ const line = i.range?.startLine ?? i.line ?? i.line_number ?? i.lineNumber ?? 0;
868
+ const bindings = /* @__PURE__ */ new Map();
869
+ for (const b of Array.isArray(i.itemBindings) ? i.itemBindings : []) {
870
+ if (b && typeof b.name === "string" && typeof b.as === "string" && b.name && b.as) {
871
+ bindings.set(b.name, b.as);
872
+ }
873
+ }
874
+ const itemCount = items.length;
875
+ const statementAlias = itemCount === 1 && typeof i.alias === "string" && i.alias ? i.alias : itemCount === 1 && typeof i.localName === "string" && i.localName ? i.localName : void 0;
876
+ return items.filter((name) => typeof name === "string" && name.length > 0).map((name) => {
877
+ const asMatch = name.match(/^(\S+)\s+as\s+(\S+)$/);
878
+ const importedName = asMatch ? asMatch[1] : name;
879
+ const cleanName = importedName.replace(/^type\s+/, "").trim();
880
+ const boundName = asMatch ? asMatch[2] : bindings.get(name) ?? statementAlias;
881
+ return {
882
+ name: cleanName,
883
+ path: i.module || i.path || "",
884
+ ...boundName ? { alias: boundName } : {},
885
+ // The analyzer's OWN classification, when it declares one. Five lanes do:
886
+ // makefile `make_include`, objective-c `include`, sql `sql_import`, xml
887
+ // `xml-doctype`, yaml `yaml_tag_include` / `yaml_keyword_include` /
888
+ // `github_action`. The fallback below is the JS/TS idiom
889
+ // (named/default/namespace), and applying it to every language made all
890
+ // 442 of this lane's corpus imports read `named` — so an Ansible
891
+ // `include_tasks: tasks.yml` PROJECT file dependency and a GitHub Actions
892
+ // `uses: actions/checkout@v4` EXTERNAL tool invocation became
893
+ // indistinguishable in the row the file-dependency engine reads. The
894
+ // relationships always carried the distinction; the row did not.
895
+ //
896
+ // Safe to prefer: the stored column is `import_type`, no fixture in the
897
+ // tree pins this field, and the only consumer that branches on an import's
898
+ // `type` (import-pruner.ts) reads JS/TS AST SPECIFIERS — a different
899
+ // structure entirely, not these rows. A lane that sets no `importType`
900
+ // keeps the historical value unchanged.
901
+ type: i.importType ?? (asMatch ? "alias" : baseType),
902
+ isExternal: external,
903
+ line
904
+ };
905
+ });
906
+ }),
907
+ // THE DROPPED-SYMBOL INVARIANT — see `droppedNames` above. An edge that names a symbol
908
+ // this call filtered out is not a weaker edge, it is an edge to nothing, so it goes with
909
+ // the symbol. Applied BEFORE the noise filter so the two are independent and either can
910
+ // be measured alone.
911
+ relationships: filterNoiseRelationships(
912
+ droppedNames.size ? (parsed.relationships ?? []).filter((r) => {
913
+ const type = String(r?.type ?? r?.relationshipType ?? "");
914
+ const src = String(r?.source ?? r?.from ?? "");
915
+ const tgt = String(r?.target ?? r?.to ?? "");
916
+ if ((type === "imports" || type === "exports") && droppedNames.has(src)) return true;
917
+ return !droppedNames.has(src) && !droppedNames.has(tgt);
918
+ }) : parsed.relationships,
919
+ language,
920
+ new Set((parsed.symbols ?? []).map((s) => String(s?.name ?? "")).filter(Boolean))
921
+ ),
922
+ // M60 LUA-14: the analyzer's `exports` were never forwarded here, so the
923
+ // entire export surface of every language was invisible to the index. This
924
+ // is the same defect the `metadata` line below already documents for
925
+ // metadata — two entry points that disagreed, with the worker the lossy one
926
+ // — except that nobody had measured the size of it. Now measured, over
927
+ // every Lua file of two pinned corpora: 1,587 exports on kong and 187 on
928
+ // luvit, emitted by the analyzer and returned by nobody. Zero of 1,774
929
+ // reached the product.
930
+ //
931
+ // `ParseResult.exports` was already declared optional and `engine.ts`
932
+ // already forwards it, so this adds no new contract: it makes the worker
933
+ // agree with the engine it wraps. `?? []` rather than a bare field, because
934
+ // `extractFallback` and the size/extension early-returns build their own
935
+ // objects and a consumer must not have to distinguish "no exports" from
936
+ // "this path never set the key".
937
+ exports: parsed.exports ?? [],
938
+ errors: parsed.errors || [],
939
+ // <-- Stage 4: propagate syntax errors from the AST Engine
940
+ // The analyzer's WHOLE `metadata` object was being dropped here, and this
941
+ // is the function `parallel-indexer.ts:889` uses — the production indexing
942
+ // path. `engine.ts` carries it (its own result type is
943
+ // `Omit<ParseResult, "language" | "metadata"> & { metadata?: ... }`), so the
944
+ // two entry points disagreed and the worker was the lossy one. Found by
945
+ // running the bash contract probe through `parseFile` rather than through
946
+ // the analyzer directly: the analyzer reported 10 patterns for
947
+ // `Deploy.sh` — Strict Error Handling, Insecure Pipe Execution, Privilege
948
+ // Escalation, Destructive File Operation — and `parseFile` returned none.
949
+ // Every pattern-based signal in every language was invisible to the index.
950
+ // Purely additive: nothing read this before, so no consumer changes
951
+ // behaviour, and the fields that WERE forwarded (`framework` above) are
952
+ // left exactly as they were.
953
+ metadata: parsed.metadata
954
+ };
955
+ if (ext === ".dart") {
956
+ try {
957
+ fs.appendFileSync(
958
+ bbDiagnosticsLogPath("worker-debug.log"),
959
+ `[Worker] Returning object with ${ret.relationships?.length || 0} relationships for ${filePath}
960
+ `
961
+ );
962
+ } catch {
963
+ }
964
+ }
965
+ return ret;
966
+ } catch (parseError) {
967
+ const errMsg = parseError?.message || String(parseError);
968
+ const isExpected = errMsg.includes("Unsupported file type") || errMsg.includes("Failed to determine WASM path") || errMsg.includes("not yet implemented");
969
+ const lang = detectLanguageFromPath(filePath) ?? "unknown";
970
+ if (!isExpected) {
971
+ process.stderr.write(`[BB-PARSE-ERR] ${lang} | ${filePath} | ${errMsg.substring(0, 300)}
972
+ `);
973
+ }
974
+ return extractFallback(content, lang, hash, sizeBytes, lastModified);
975
+ }
976
+ }
977
+ async function warmUpWorker() {
978
+ let wasm = "ok";
979
+ try {
980
+ const { ensureWasmRegistry } = await import("./wasm-NMWO3WXY.js");
981
+ await ensureWasmRegistry();
982
+ } catch (e) {
983
+ wasm = "unavailable";
984
+ reportStartupProblem("wasm registry unavailable \u2014 tree-sitter grammars may not load", e);
985
+ }
986
+ let engine = "ok";
987
+ try {
988
+ engineModule = await import("./engine-LO6L4JLQ.js");
989
+ if (!engineModule?.ASTEngine) {
990
+ engine = "unavailable";
991
+ reportStartupProblem("engine module loaded but exports no ASTEngine", new Error("ASTEngine missing"));
992
+ }
993
+ } catch (e) {
994
+ engine = "unavailable";
995
+ reportStartupProblem("engine module failed to load \u2014 falling back to regex extraction for EVERY file", e);
996
+ }
997
+ return { engine, wasm };
998
+ }
999
+ function persistStartupDiagnostics() {
1000
+ if (startupDiagnostics.length === 0) return;
1001
+ try {
1002
+ fs.appendFileSync(
1003
+ bbDiagnosticsLogPath("worker-startup.log"),
1004
+ `${(/* @__PURE__ */ new Date()).toISOString()} | pid=${process.pid} | node=${process.version} | ${startupDiagnostics.join(" | ")}
1005
+ `
1006
+ );
1007
+ } catch {
1008
+ }
1009
+ }
1010
+ async function runSelfTest() {
1011
+ const { engine, wasm } = await warmUpWorker();
1012
+ persistStartupDiagnostics();
1013
+ const report = {
1014
+ ok: engine === "ok" && wasm === "ok",
1015
+ engine,
1016
+ wasm,
1017
+ node: process.version,
1018
+ pid: process.pid,
1019
+ execPath: process.execPath,
1020
+ diagnostics: startupDiagnostics.slice(0, 5)
1021
+ };
1022
+ process.stdout.write(`[BB-WORKER-SELFTEST] ${JSON.stringify(report)}
1023
+ `);
1024
+ return report.ok ? 0 : 1;
1025
+ }
1026
+ process.on("message", async (msg) => {
1027
+ if (msg.type === "warmup") {
1028
+ const watchdogMs = Number(process.env.BB_WORKER_STARTUP_TIMEOUT_MS || 0) || 3e4;
1029
+ const slowWarmNote = setTimeout(() => {
1030
+ process.stderr.write(
1031
+ `[BB-WORKER-STARTUP] still warming after ${Math.round(watchdogMs / 2)}ms (loading tree-sitter grammars); the parent's watchdog is ${watchdogMs}ms
1032
+ `
1033
+ );
1034
+ }, Math.max(1, Math.round(watchdogMs / 2)));
1035
+ slowWarmNote.unref?.();
1036
+ const { engine: engineStatus, wasm: wasmStatus } = await warmUpWorker();
1037
+ if (engineStatus === "unavailable") {
1038
+ safeSend({ type: "engine_fail", workerId: msg.workerId, error: startupDiagnostics.join(" | ") });
1039
+ }
1040
+ if (process.env.BB_TEST_HOOKS === "1") {
1041
+ const delayReady = Number(process.env.BB_WORKER_DELAY_READY_MS || 0);
1042
+ if (delayReady > 0) await new Promise((r) => setTimeout(r, delayReady));
1043
+ }
1044
+ clearTimeout(slowWarmNote);
1045
+ safeSend({
1046
+ type: "ready",
1047
+ workerId: msg.workerId,
1048
+ pid: process.pid,
1049
+ node: process.version,
1050
+ execPath: process.execPath,
1051
+ engine: engineStatus,
1052
+ wasm: wasmStatus,
1053
+ diagnostics: startupDiagnostics.slice(0, 5)
1054
+ });
1055
+ persistStartupDiagnostics();
1056
+ } else if (msg.type === "parse_batch") {
1057
+ const { batchId, files, projectPath, projectIndexes } = msg;
1058
+ let indexCache = null;
1059
+ if (projectIndexes !== void 0 && projectIndexes !== null) {
1060
+ try {
1061
+ const mod = await import("./project-index-5SDPHITE.js");
1062
+ indexCache = /* @__PURE__ */ new Map();
1063
+ for (const [lang, raw] of Object.entries(projectIndexes)) {
1064
+ const built = mod.deserializeProjectIndex(raw);
1065
+ if (built !== null) {
1066
+ mod.buildResolutionTables(built);
1067
+ indexCache.set(lang, built);
1068
+ }
1069
+ }
1070
+ } catch (e) {
1071
+ log(`[Worker] project index unavailable, continuing per-file: ${e?.message ?? e}`);
1072
+ reportStartupProblem("project index unavailable, indexing per-file", e);
1073
+ indexCache = null;
1074
+ }
1075
+ }
1076
+ const extnameOf = (p) => {
1077
+ const base = p.slice(p.lastIndexOf("/") + 1);
1078
+ const dot = base.lastIndexOf(".");
1079
+ return dot <= 0 ? "" : base.slice(dot).toLowerCase();
1080
+ };
1081
+ const contextFor = (filePath) => {
1082
+ const root = String(projectPath ?? "") || void 0;
1083
+ if (indexCache === null) return root === void 0 ? void 0 : { projectRoot: root };
1084
+ const ext = extnameOf(filePath);
1085
+ const built = indexCache.get(ext);
1086
+ if (built === void 0) return root === void 0 ? void 0 : { projectRoot: root };
1087
+ return { projectIndex: built, projectRoot: root };
1088
+ };
1089
+ const FILE_TIMEOUT_MS = Number(process.env.BB_FILE_TIMEOUT_MS || 45e3);
1090
+ let delayParse = 0;
1091
+ if (process.env.BB_TEST_HOOKS === "1") {
1092
+ if (process.env.BB_WORKER_CRASH_ON_BATCH === "1") {
1093
+ process.stderr.write(`[BB-WORKER-FIXTURE] crashing on parse_batch (batch ${batchId})
1094
+ `);
1095
+ process.exit(1);
1096
+ }
1097
+ delayParse = Number(process.env.BB_WORKER_DELAY_PARSE_MS || 0);
1098
+ }
1099
+ for (const filePath of files) {
1100
+ try {
1101
+ safeSend({ type: "file_start", batchId, filePath });
1102
+ await new Promise((r) => setTimeout(r, 0));
1103
+ if (delayParse > 0) await new Promise((r) => setTimeout(r, delayParse));
1104
+ const fileTimer = setTimeout(() => {
1105
+ log(`Worker self-timeout: killing process after ${FILE_TIMEOUT_MS}ms on ${filePath}`);
1106
+ process.exit(1);
1107
+ }, FILE_TIMEOUT_MS);
1108
+ const result = await parseFile(filePath, projectPath, contextFor(filePath));
1109
+ clearTimeout(fileTimer);
1110
+ safeSend({ type: "file_done", batchId, filePath, result });
1111
+ } catch (err) {
1112
+ safeSend({
1113
+ type: "file_error",
1114
+ batchId,
1115
+ filePath,
1116
+ error: err instanceof Error ? err.message : String(err)
1117
+ });
1118
+ }
1119
+ }
1120
+ safeSend({ type: "batch_done", batchId });
1121
+ }
1122
+ });
1123
+ process.on("disconnect", () => process.exit(0));
1124
+ if (process.connected) {
1125
+ if (process.env.BB_POOL_WORKER !== "1") {
1126
+ process.stderr.write(
1127
+ `[BB-WORKER-STARTUP] forked with BB_POOL_WORKER=${JSON.stringify(process.env.BB_POOL_WORKER ?? null)} rather than "1"; serving anyway \u2014 unset BB_POOL_WORKER to use in-process indexing
1128
+ `
1129
+ );
1130
+ }
1131
+ setInterval(() => {
1132
+ }, 1 << 30);
1133
+ }
1134
+ if (process.env.BB_POOL_WORKER_SELFTEST === "1" && !process.connected) {
1135
+ runSelfTest().then(
1136
+ (code) => {
1137
+ process.exitCode = code;
1138
+ },
1139
+ (e) => {
1140
+ process.stderr.write(`[BB-WORKER-SELFTEST] failed: ${e?.message ?? String(e)}
1141
+ `);
1142
+ process.exitCode = 1;
1143
+ }
1144
+ );
1145
+ }
1146
+ export {
1147
+ extractFallback,
1148
+ filterNoiseRelationships,
1149
+ importBindingNames,
1150
+ keepSymbol,
1151
+ nameTheSymbolRule,
1152
+ parseFile
1153
+ };