@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,235 @@
1
+ // src/brain/freshness.ts
2
+ import { createHash } from "crypto";
3
+ import { readFileSync, existsSync, statSync } from "fs";
4
+ function hashFileContent(content) {
5
+ return createHash("sha256").update(content).digest("hex").slice(0, 16);
6
+ }
7
+ function fileUnchangedSince(path, indexedHash, indexedSize, indexedMtime) {
8
+ try {
9
+ const stat = statSync(path);
10
+ if (indexedSize !== null && indexedSize !== void 0 && indexedMtime !== null && indexedMtime !== void 0 && stat.size === indexedSize && Math.floor(stat.mtimeMs) === Math.floor(indexedMtime)) return true;
11
+ const content = readFileSync(path);
12
+ return hashFileContent(content) === indexedHash;
13
+ } catch {
14
+ return false;
15
+ }
16
+ }
17
+ function checkFileFreshness(raw, fileId) {
18
+ try {
19
+ const row = raw.prepare("SELECT path, file_hash, size_bytes, last_modified FROM brain_file WHERE id = ?").get(fileId);
20
+ if (!row) return null;
21
+ if (!existsSync(row.path)) return { fileId, path: row.path, indexedHash: row.file_hash, status: "missing" };
22
+ const fresh = fileUnchangedSince(row.path, row.file_hash, row.size_bytes, row.last_modified);
23
+ return { fileId, path: row.path, indexedHash: row.file_hash, status: fresh ? "fresh" : "stale" };
24
+ } catch {
25
+ return null;
26
+ }
27
+ }
28
+ function checkResultsFreshness(raw, rows) {
29
+ const result = /* @__PURE__ */ new Map();
30
+ const seen = /* @__PURE__ */ new Set();
31
+ for (const r of rows) {
32
+ if (!r.fileId || seen.has(r.fileId)) continue;
33
+ seen.add(r.fileId);
34
+ const f = checkFileFreshness(raw, r.fileId);
35
+ if (f) result.set(r.fileId, f.status);
36
+ }
37
+ return result;
38
+ }
39
+ function checkSymbolFreshness(raw, symbolId) {
40
+ try {
41
+ const row = raw.prepare("SELECT file_id FROM brain_symbol WHERE id = ?").get(symbolId);
42
+ if (!row) return null;
43
+ return checkFileFreshness(raw, row.file_id);
44
+ } catch {
45
+ return null;
46
+ }
47
+ }
48
+ function stableFileHash(id) {
49
+ let h = 2166136261;
50
+ for (let i = 0; i < id.length; i++) {
51
+ h ^= id.charCodeAt(i);
52
+ h = Math.imul(h, 16777619);
53
+ }
54
+ h ^= h >>> 16;
55
+ h = Math.imul(h, 2246822507);
56
+ h ^= h >>> 13;
57
+ h = Math.imul(h, 3266489909);
58
+ h ^= h >>> 16;
59
+ return h >>> 0;
60
+ }
61
+ function selectSampleFiles(rows, limit) {
62
+ const k = Math.min(limit, rows.length);
63
+ if (k <= 0) return [];
64
+ if (k >= rows.length) {
65
+ return [...rows].sort((a, b) => cmpPath(a.relative_path, b.relative_path) || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
66
+ }
67
+ const kept = [];
68
+ const precedes = (ah, aid, ai, bh, bid, bi) => ah < bh || ah === bh && (aid < bid || aid === bid && ai < bi);
69
+ for (let i = 0; i < rows.length; i++) {
70
+ const r = rows[i];
71
+ const h = stableFileHash(r.id);
72
+ if (kept.length === k) {
73
+ const worst = kept[k - 1];
74
+ if (!precedes(h, r.id, i, worst.h, worst.r.id, worst.i)) continue;
75
+ }
76
+ let lo = 0, hi = kept.length;
77
+ while (lo < hi) {
78
+ const mid = lo + hi >> 1;
79
+ if (precedes(kept[mid].h, kept[mid].r.id, kept[mid].i, h, r.id, i)) lo = mid + 1;
80
+ else hi = mid;
81
+ }
82
+ kept.splice(lo, 0, { r, h, i });
83
+ if (kept.length > k) kept.pop();
84
+ }
85
+ return kept.map((x) => x.r).sort((a, b) => cmpPath(a.relative_path, b.relative_path) || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
86
+ }
87
+ function cmpPath(a, b) {
88
+ if (a === b) return 0;
89
+ return a < b ? -1 : 1;
90
+ }
91
+ var freshnessStats = { statCalls: 0, hashReads: 0 };
92
+ function rawStat(p) {
93
+ freshnessStats.statCalls++;
94
+ try {
95
+ const s = statSync(p);
96
+ return { exists: true, size: s.size, mtime: Math.floor(s.mtimeMs) };
97
+ } catch {
98
+ return { exists: false, size: null, mtime: null };
99
+ }
100
+ }
101
+ function chunk(arr, n) {
102
+ const out = [];
103
+ for (let i = 0; i < arr.length; i += n) out.push(arr.slice(i, i + n));
104
+ return out;
105
+ }
106
+ function batchLoadRows(raw, ids, paths) {
107
+ const rows = /* @__PURE__ */ new Map();
108
+ const COLS = "id, path, file_hash, size_bytes, last_modified";
109
+ for (const c of chunk(ids, 500)) {
110
+ const rs = raw.prepare(`SELECT ${COLS} FROM brain_file WHERE id IN (${c.map(() => "?").join(",")})`).all(...c);
111
+ for (const r of rs) rows.set(r.id, r);
112
+ }
113
+ for (const c of chunk(paths, 500)) {
114
+ const rs = raw.prepare(`SELECT ${COLS} FROM brain_file WHERE path IN (${c.map(() => "?").join(",")})`).all(...c);
115
+ for (const r of rs) if (!rows.has(r.id)) rows.set(r.id, r);
116
+ }
117
+ return rows;
118
+ }
119
+ function classifyRow(row, statFor) {
120
+ const stat = statFor(row.path);
121
+ if (!stat.exists) return { status: "missing", reason: "file-gone" };
122
+ if (row.size_bytes !== null && row.size_bytes !== void 0 && row.last_modified !== null && row.last_modified !== void 0 && stat.size === row.size_bytes && stat.mtime === Math.floor(row.last_modified)) {
123
+ return { status: "fresh", reason: "metadata-fast-path" };
124
+ }
125
+ freshnessStats.hashReads++;
126
+ try {
127
+ const content = readFileSync(row.path);
128
+ return hashFileContent(content) === row.file_hash ? { status: "fresh", reason: "hash-match" } : { status: "stale", reason: "hash-differs" };
129
+ } catch {
130
+ return { status: "missing", reason: "unreadable" };
131
+ }
132
+ }
133
+ function resolveRowsFreshnessDetailed(raw, projectId, rows, opts = {}) {
134
+ void projectId;
135
+ freshnessStats.statCalls = 0;
136
+ freshnessStats.hashReads = 0;
137
+ const statCache = /* @__PURE__ */ new Map();
138
+ function memoStat(p) {
139
+ const hit = statCache.get(p);
140
+ if (hit) return hit;
141
+ const s = rawStat(p);
142
+ statCache.set(p, s);
143
+ return s;
144
+ }
145
+ function statFor(p) {
146
+ return memoStat(p);
147
+ }
148
+ const uniqueIds = /* @__PURE__ */ new Set();
149
+ const uniquePaths = /* @__PURE__ */ new Set();
150
+ for (const r of rows) {
151
+ if (r.fileId) uniqueIds.add(r.fileId);
152
+ else if (r.filePath) uniquePaths.add(r.filePath);
153
+ }
154
+ const byId = batchLoadRows(raw, [...uniqueIds], [...uniquePaths]);
155
+ const statuses = /* @__PURE__ */ new Map();
156
+ const reasons = /* @__PURE__ */ new Map();
157
+ for (const id of uniqueIds) {
158
+ const row = byId.get(id);
159
+ if (!row) {
160
+ statuses.set(id, "missing");
161
+ reasons.set(id, "no-row");
162
+ continue;
163
+ }
164
+ const c = classifyRow(row, statFor);
165
+ statuses.set(id, c.status);
166
+ reasons.set(id, c.reason);
167
+ }
168
+ const byPath = /* @__PURE__ */ new Map();
169
+ for (const r of byId.values()) if (!byPath.has(r.path)) byPath.set(r.path, r);
170
+ for (const p of uniquePaths) {
171
+ const row = byPath.get(p);
172
+ if (!row) {
173
+ statuses.set(p, "missing");
174
+ reasons.set(p, "no-row");
175
+ continue;
176
+ }
177
+ const c = classifyRow(row, statFor);
178
+ statuses.set(p, c.status);
179
+ reasons.set(p, c.reason);
180
+ }
181
+ let fresh = 0, stale = 0, missing = 0;
182
+ for (const s of statuses.values()) {
183
+ if (s === "fresh") fresh++;
184
+ else if (s === "stale") stale++;
185
+ else missing++;
186
+ }
187
+ const checked = fresh + stale + missing;
188
+ const summary = {
189
+ fresh,
190
+ stale,
191
+ missing,
192
+ staleRatio: checked === 0 ? 0 : (stale + missing) / checked,
193
+ freshnessMode: opts.freshnessMode ?? "complete"
194
+ };
195
+ return { statuses, reasons, summary };
196
+ }
197
+ var FRESHNESS_REMEDIATION = {
198
+ // M43.A1/A2: read tools now AUTO-refresh stale files within budget before
199
+ // answering and declare it; the strings name that automatic behavior and
200
+ // keep the manual interface for opt-out/over-budget cases. Substring
201
+ // contract (asserted by the M35 envelope gate): dir names "bb index
202
+ // --changed" and "bb_index"; file matches /bb index "/ and names bb_index.
203
+ dir: "reads auto-refresh stale files within budget when enabled \u2014 disable with BB_NO_AUTO_REFRESH=1 or refresh=false; manual repair: run: bb index --changed (or the bb_index tool with the project path \u2014 incremental, changed files only)",
204
+ file: 'reads auto-refresh this file within budget when enabled \u2014 disable with BB_NO_AUTO_REFRESH=1 or refresh=false; manual repair: run: bb index "<file>" (or the bb_index tool with that file path)'
205
+ };
206
+ var FRESHNESS_REMEDIATION_MANUAL_ONLY = {
207
+ dir: "this read does NOT auto-refresh \u2014 the rows describe the index as it stands; manual repair: run: bb index --changed (or the bb_index tool with the project path \u2014 incremental, changed files only)",
208
+ file: 'this read does NOT auto-refresh this file \u2014 the rows describe the index as it stands; manual repair: run: bb index "<file>" (or the bb_index tool with that file path)'
209
+ };
210
+ function buildStalenessEnvelope(summary, scope) {
211
+ const staleish = summary.stale + summary.missing;
212
+ const registered = scope.autoRefresh === false ? FRESHNESS_REMEDIATION_MANUAL_ONLY : FRESHNESS_REMEDIATION;
213
+ const remediation = staleish === 0 ? "" : scope.kind === "file" ? `${staleish} stale in this file \u2014 ${registered.file.replace("<file>", scope.path ?? "this file")}` : `${staleish} stale/missing \u2014 ${registered.dir}`;
214
+ return {
215
+ fresh: summary.fresh,
216
+ stale: summary.stale,
217
+ missing: summary.missing,
218
+ staleRatio: summary.staleRatio,
219
+ mode: summary.freshnessMode === "sampled" ? "sampled" : "complete",
220
+ remediation
221
+ };
222
+ }
223
+
224
+ export {
225
+ hashFileContent,
226
+ fileUnchangedSince,
227
+ checkFileFreshness,
228
+ checkResultsFreshness,
229
+ checkSymbolFreshness,
230
+ selectSampleFiles,
231
+ resolveRowsFreshnessDetailed,
232
+ FRESHNESS_REMEDIATION,
233
+ FRESHNESS_REMEDIATION_MANUAL_ONLY,
234
+ buildStalenessEnvelope
235
+ };
@@ -0,0 +1,19 @@
1
+ // src/ast/node-walk.ts
2
+ function treeContainsNodeType(root, type) {
3
+ if (!root) return false;
4
+ const stack = [root];
5
+ while (stack.length > 0) {
6
+ const n = stack.pop();
7
+ if (!n) continue;
8
+ if (n.type === type) return true;
9
+ for (let i = 0; i < n.namedChildCount; i++) {
10
+ const c = n.namedChild(i);
11
+ if (c) stack.push(c);
12
+ }
13
+ }
14
+ return false;
15
+ }
16
+
17
+ export {
18
+ treeContainsNodeType
19
+ };
@@ -0,0 +1,87 @@
1
+ // src/lsp/evidence_tier.ts
2
+ var EVIDENCE_TIERS = [
3
+ "structural",
4
+ "import_based",
5
+ "usage_contextual",
6
+ "reference_qualified",
7
+ "inferred"
8
+ ];
9
+ var TIER_RANK = {
10
+ structural: 0,
11
+ import_based: 1,
12
+ usage_contextual: 2,
13
+ reference_qualified: 3,
14
+ inferred: 4,
15
+ unknown: 5
16
+ };
17
+ var STRUCTURAL_KINDS = /* @__PURE__ */ new Set([
18
+ "call",
19
+ "calls",
20
+ "extends",
21
+ "inherits",
22
+ "implements",
23
+ "overrides",
24
+ "override",
25
+ "contains",
26
+ "exports",
27
+ "instantiates",
28
+ // EXTENDED 2026-10-18 (canonical vocabulary). These three are PARSER-DETERMINISTIC by the same
29
+ // argument the set already carries for extends/implements: `mixes_in` reads the `with` clause,
30
+ // `renders` reads a JSX element's tag, `decorates` reads a decorator node attached to a
31
+ // declaration. Leaving them out is not neutral — every tier reader falls through to `inferred`,
32
+ // so an edge the analyzer read straight off the grammar would be presented as a guess.
33
+ "mixes_in",
34
+ "renders",
35
+ "decorates"
36
+ ]);
37
+ var STRUCTURAL_FLOOR = 0.7;
38
+ var IMPORT_KINDS = /* @__PURE__ */ new Set(["import", "imports", "part_of"]);
39
+ var USAGE_CONTEXT_KINDS = /* @__PURE__ */ new Set(["reference", "references", "use", "uses", "usage"]);
40
+ var REFERENCE_QUALIFIED_KINDS = /* @__PURE__ */ new Set(["references_qualified", "reference_qualified"]);
41
+ function isDeclaredTier(value) {
42
+ return EVIDENCE_TIERS.includes(value);
43
+ }
44
+ function classifyTier(row) {
45
+ const stored = row.evidenceClass;
46
+ if (stored !== null && isDeclaredTier(stored)) return stored;
47
+ const t = row.relationshipType.trim().toLowerCase();
48
+ if (STRUCTURAL_KINDS.has(t)) return (row.confidence ?? 0) >= STRUCTURAL_FLOOR ? "structural" : "inferred";
49
+ if (IMPORT_KINDS.has(t)) return "import_based";
50
+ if (USAGE_CONTEXT_KINDS.has(t)) return "usage_contextual";
51
+ if (REFERENCE_QUALIFIED_KINDS.has(t)) return "reference_qualified";
52
+ return "inferred";
53
+ }
54
+ function evidenceClassOf(metadata) {
55
+ if (!metadata) return null;
56
+ try {
57
+ const parsed = JSON.parse(metadata);
58
+ if (typeof parsed !== "object" || parsed === null) return null;
59
+ const cls = parsed.evidenceClass;
60
+ return typeof cls === "string" ? cls : null;
61
+ } catch {
62
+ return null;
63
+ }
64
+ }
65
+ function classifyStoredRow(row) {
66
+ return classifyTier({
67
+ relationshipType: row.relationship_type,
68
+ confidence: row.confidence,
69
+ evidenceClass: evidenceClassOf(row.metadata)
70
+ });
71
+ }
72
+ function orderTiers(tiers) {
73
+ const set = /* @__PURE__ */ new Set();
74
+ for (const t of tiers) set.add(t);
75
+ return [...set].sort((a, b) => TIER_RANK[a] - TIER_RANK[b]);
76
+ }
77
+ function primaryTier(tiers) {
78
+ if (tiers.length === 0) return "unknown";
79
+ return orderTiers(tiers)[0];
80
+ }
81
+
82
+ export {
83
+ classifyTier,
84
+ classifyStoredRow,
85
+ orderTiers,
86
+ primaryTier
87
+ };