@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,106 @@
1
+ # Indexing performance — measured findings
2
+
3
+ > **Read the provenance warning.** Every number on this page was measured on a
4
+ > developer machine and **no evidence file for any of it exists in this
5
+ > repository** — there is nothing under `validation/` recording the 9.9 s /
6
+ > 455.4 s pair, and nothing recording the 3,850 s real-repo run. Every other
7
+ > timings page in this directory
8
+ > ([`performance.md`](performance.md)) cites a specific evidence file and line
9
+ > for each number, precisely so a reader can check it. This page cannot be
10
+ > checked that way, so treat it as a set of observations to re-derive, not as
11
+ > citable evidence. `script/verify-docs-indexing.ts` cannot verify it either:
12
+ > the gate checks claims against `src/` and against a live run, and there is
13
+ > nothing here for either to check.
14
+ >
15
+ > Host for all figures: 12 cores, effective pool concurrency 11, node v22.23.3.
16
+
17
+ ## The worker pool was worth ~46× on one machine. Losing it is the real perf cliff.
18
+
19
+ Same 300-file TypeScript fixture, identical flags, warm cache, back to back
20
+ (**unverified — no evidence file recorded**):
21
+
22
+ | Mode | Wall clock |
23
+ |---|---|
24
+ | Worker pool | **9.9 s** |
25
+ | In-process (serial) | **455.4 s** |
26
+
27
+ **46× slower.** The *direction* is not in doubt and is corroborated by the
28
+ measured bottleneck classification in [`performance.md`](performance.md) — the
29
+ pool is where the parallelism lives, and losing it is single-threaded. The
30
+ *magnitude* is one machine, one fixture, one run, unrecorded. Do not quote 46×.
31
+
32
+ This reframes the "pool workers don't start" bug: it is not a cosmetic warning.
33
+ This is why the pool diagnosis work matters more than its line count suggests.
34
+ Before this change the failure printed one generic line and the run continued
35
+ looking fine.
36
+
37
+ ## Where the 1 h 4 m on the real repo went
38
+
39
+ Measured on `backbencher-brain` itself (**unverified — no evidence file
40
+ recorded**): 7,220 files, 386,336 symbols, 543,762 relationships, 79,649
41
+ embeddings in 3,850 s.
42
+
43
+ Composition of the work:
44
+
45
+ - 3,478 TypeScript + 2,522 JSON files are 83% of the file count. JSON is parsed
46
+ by tree-sitter like everything else, which is far more expensive per byte than
47
+ a line-oriented format warrants.
48
+ - 141 files were flagged with parse errors, 11 hit the worker file timeout
49
+ (`BB_FILE_TIMEOUT_MS`, default 45 s).
50
+ - 5 files exceed the 1 MB `FULL_AST_LIMIT` and get structural extraction instead
51
+ of a full parse (`src/ast/parallel-indexer.ts:850-877`) — correct, and cheap.
52
+ - Only 352 files were newly parsed on the run that reported 1 h 4 m; the other
53
+ 6,146 were unchanged. So the headline number was dominated by the incremental
54
+ check plus the **full derived pass** — relationship resolution, enrichment,
55
+ gravity, taint and health over 386k symbols — not by parsing.
56
+
57
+ Note what that last bullet rests on: the run parsed *something*, so it took the
58
+ `full` derived path. A run that parses nothing reports
59
+ `derived: skipped-unchanged` and runs no derived pass at all — that is the
60
+ common case on a second run, and it is verified live by
61
+ `script/verify-docs-indexing.ts --live`.
62
+
63
+ ## The honest conclusion
64
+
65
+ The parse phase is not the bottleneck on a large index; the derived-data pass
66
+ over hundreds of thousands of symbols is. Two consequences:
67
+
68
+ 1. A faster pool does not make the derived pass faster. Raising concurrency
69
+ further has a ceiling and will not move the 3,850 s much.
70
+ 2. `bb index --skip-post-processing` followed by `bb index --post` is the
71
+ documented way to split that work, and `--changed` should be preferred over a
72
+ full run when files have not changed. Both are already implemented; the CLI
73
+ help and docs now describe them.
74
+
75
+ Not yet measured: whether the derived pass is memory-bound or CPU-bound, and
76
+ where inside it the time goes. That is the next profiling step before any
77
+ optimisation attempt — guessing at it would be how the previous duplicate-VALUES
78
+ bug shipped.
79
+
80
+ ## Reproducing the pool comparison
81
+
82
+ ```bash
83
+ # pool
84
+ node bin/bb index <fixture> --force
85
+
86
+ # serial, same fixture
87
+ BB_POOL_WORKER=0 node bin/bb index <fixture> --force
88
+ ```
89
+
90
+ `BB_POOL_WORKER=0` is honoured by `resolvePoolWorkerForkSafe`, which returns the
91
+ `pool-disabled-by-env` failure reason rather than failing opaquely
92
+ (`src/ast/pool-diagnostics.ts:80`, `:190-201`). `0` is one of five disabling
93
+ values: `0`, `false`, `off`, `no`, `none`.
94
+
95
+ This is the one mechanism on this page that **is** gated: the reason string, the
96
+ value set, and the "the env var is not a supported opt-out" rule are all asserted
97
+ by `script/verify-docs-indexing.ts` against `src/`, and the env-var behaviour is
98
+ described in [`troubleshooting.md`](troubleshooting.md#cause-5--bb_pool_worker-is-set-in-your-environment).
99
+ The timings are not.
100
+
101
+ ## To make this page citable
102
+
103
+ Each number above needs a `validation/<milestone>/results/<id>.json` recording
104
+ the command, the host, and the parsed counts — the shape
105
+ `performance.md` cites throughout. Until that exists, this page is a note to
106
+ self.
@@ -0,0 +1,427 @@
1
+ # Indexing
2
+
3
+ > **These pages are gated against the code.** `script/verify-docs-indexing.ts`
4
+ > asserts that every env var, flag, default and quoted output line below exists
5
+ > in `src/`, and (`--live`) that the behavioural claims hold when `bb index` is
6
+ > actually run. Run it after touching anything here:
7
+ >
8
+ > ```bash
9
+ > npx tsx script/verify-docs-indexing.ts # static claims
10
+ > npx tsx script/verify-docs-indexing.ts --live # + run bb index on a fixture
11
+ > ```
12
+ >
13
+ > A claim that cannot be verified is not in these pages. Source of truth:
14
+ > `bb index --help` (`src/cli/index.ts:743-772`), the executable semantics matrix
15
+ > at `src/cli/index.ts:89-104`, and `indexProjectParallel`
16
+ > (`src/ast/parallel-indexer.ts`). Everything quoted below is quoted from code
17
+ > or from a real run, not described from memory.
18
+
19
+ `bb index` reads a project, parses every file it decides to index, stores the
20
+ structural result in a per-project SQLite database, and then derives the
21
+ expensive cross-file data from it. This directory explains what each mode
22
+ actually does, how to resume an interrupted run, what the timings look like,
23
+ what to do when the worker pool does not start, and how embeddings are
24
+ configured.
25
+
26
+ | Document | Use it when |
27
+ | --- | --- |
28
+ | [`resume.md`](resume.md) | a run was interrupted, or you want to know what survives an interrupt |
29
+ | [`performance.md`](performance.md) | the run is taking longer than you expect |
30
+ | [`troubleshooting.md`](troubleshooting.md) | "the workers don't start" / "it says it parsed in-process" |
31
+ | [`embeddings.md`](embeddings.md) | you want semantic search, or `bb setup` / `bb doctor` confused you |
32
+
33
+ ## The command
34
+
35
+ ```
36
+ bb index [dir] [flags]
37
+ ```
38
+
39
+ `dir` defaults to the current working directory (`src/cli/index.ts:67`), so
40
+ `cd my-project && bb index` and `bb index ../my-project` are equivalent.
41
+
42
+ ## What a full index actually does
43
+
44
+ `bb index` with no flags is a single run with six phases. The boundaries matter
45
+ because almost every confusion below comes from attributing a symptom to the
46
+ wrong phase.
47
+
48
+ 1. **Discovery.** Walk the project and decide what is a file worth indexing.
49
+ `.gitignore` is always respected; a project-level `.bbignore` (same syntax)
50
+ is loaded on top of it and wins (`src/ast/parallel-indexer.ts:799-812`,
51
+ `:915-932`). Built-in skip patterns exclude `node_modules`,
52
+ `bower_components`, `dist`, `build`, `out`, `target`, `coverage`,
53
+ `__pycache__`, `.venv`/`venv`, `.next`, `.nuxt`, `.svelte-kit` and friends
54
+ (`src/ast/parallel-indexer.ts:253-300`).
55
+ 2. **Size tiering.** Files over **5 MB** are skipped entirely. Files over
56
+ **1 MB** get structural extraction instead of a full AST
57
+ (`src/ast/parallel-indexer.ts:850-877`). A file over the limit is counted in
58
+ `skipped`, not in `errors` — that is expected, not a failure.
59
+ 3. **Worker-pool fork test.** One worker is forked and asked to say `ready`. If
60
+ it cannot, the whole run degrades to serial in-process parsing
61
+ (`src/ast/parallel-indexer.ts:4770-4825`). See
62
+ [`troubleshooting.md`](troubleshooting.md).
63
+ 4. **Parse + store.** Files are parsed in parallel workers and flushed to the
64
+ database in batches of 20, to avoid blocking the event loop
65
+ (`src/ast/parallel-indexer.ts:1674-1678`).
66
+ 5. **Derived phases.** `runPostProcessing` runs **eight** recorded phases —
67
+ `relationships`, `enrichment`, `gravity`, `taint`, `health`, `integrity`,
68
+ `vectorBlobs`, `analyze`
69
+ (`src/ast/parallel-indexer.ts:576`, `:5561-5680`). Measured by running
70
+ `bb index --post`:
71
+
72
+ ```
73
+ ✓ post-processing complete in 0.1s
74
+ ✓ relationships 2ms
75
+ ✓ enrichment 10ms
76
+ ✓ gravity 3ms
77
+ ✓ taint 2ms
78
+ ✓ health 56ms
79
+ ✓ integrity 10ms
80
+ ✓ vectorBlobs 3ms
81
+ ✓ analyze 3ms
82
+ ```
83
+
84
+ The first five are the derived data; `integrity`, `vectorBlobs` and
85
+ `analyze` are checks/maintenance that run with them. This whole phase is the
86
+ expensive half on a large project.
87
+ 6. **Background embeddings.** Vectors are queued and drained after the parse,
88
+ not during it. Coverage is therefore always a per-run measurement, never a
89
+ fixed product number (`docs/EMBEDDINGS.md` §3).
90
+
91
+ ## The eight legal flag combinations
92
+
93
+ The CLI holds an explicit whitelist of legal combinations
94
+ (`src/cli/index.ts:89-98`). **Any combination not on the list is rejected
95
+ before any work starts**, with exit code 1 (`src/cli/index.ts:99-104`). Real
96
+ output:
97
+
98
+ ```
99
+ ✗ conflicting bb index options: --force --changed
100
+ This combination has no defined behavior. See the semantics matrix: bb index --help, docs/m40/PLAN.md
101
+ Remediations: --force alone rebuilds everything; --post alone re-runs derived-data phases; --changed/--resume alone run the bounded pass.
102
+ ```
103
+
104
+ Note the flag names carry their `--` prefix; they are built from the flags you
105
+ actually passed (`src/cli/index.ts` legal-combination matrix).
106
+
107
+ | Flags | Defined behavior |
108
+ | --- | --- |
109
+ | *(none)* | full index + all post-processing |
110
+ | `--changed` | incremental parse + bounded post-pass |
111
+ | `--resume` | incremental from checkpoint + bounded post-pass |
112
+ | `--post` | no parse; re-run the derived phases only |
113
+ | `--skip-post-processing` | parse+store only; derived data deferred |
114
+ | `--file <path>` | single-file reindex + scoped post-pass |
115
+ | `--import <db>` | adopt DB, then incremental top-up |
116
+ | `--force` | wipe + full index + full post-processing |
117
+
118
+ `--no-setup` is **not** part of this matrix. It is orthogonal — it only skips the
119
+ first-run embedding prompt (`src/cli/index.ts`, the `--no-setup` option) — so it may be combined
120
+ with any of the eight rows above. `--exclude` and `--concurrency` are orthogonal too: they change
121
+ which files are discovered and how many parse workers are used, not which mode runs.
122
+
123
+ `bb index --exclude <globs>` skips files matching comma-separated globs while discovering. It is
124
+ **non-destructive**: a file that an earlier run indexed keeps its rows when it is now excluded
125
+ (only a file that no longer exists is purged), so `--exclude fixtures/**` is a scoping decision,
126
+ not a delete. `bb index --concurrency <n>` (1–64) overrides the worker count for one run; the same
127
+ number can be set for a shell with `BB_INDEX_CONCURRENCY` (see `environment-variables.md`).
128
+
129
+ ## `bb index` — full
130
+
131
+ ```
132
+ bb index
133
+ ```
134
+
135
+ **Does:** discovers, parses every eligible file, stores symbols/imports, then
136
+ runs all eight derived phases.
137
+
138
+ **Use when:** first index of a project, or after a large structural change.
139
+
140
+ **Does NOT:** save you the derived pass on a re-run. Discovery *does* skip files
141
+ whose `mtime` and `size` both match what is stored — that filter is not gated on
142
+ any flag (`src/ast/parallel-indexer.ts:887-894`) — so a re-run of an unchanged
143
+ project parses nothing. When a re-run *does* parse something, it then pays for
144
+ the **full** derived pass over the whole project, where `--changed` would have
145
+ paid for a bounded one. That is the whole difference between the two modes.
146
+
147
+ Measured, second bare run with nothing changed:
148
+
149
+ ```
150
+ ✓ nothing to index — already up to date (7 unchanged, 0 skipped, 0.3s)
151
+ stats: {"totalFiles":7,"processed":7,"errors":0}
152
+ breakdown: 0 newly parsed | 7 unchanged | 0 skipped | 0 symbol-loss (parsed 0 symbols) | 0 errors | 0 timeouts
153
+ parsed nothing — no files needed parsing, so no parse mode was used
154
+ derived: skipped-unchanged (no files parsed, so no derived pass ran)
155
+ consistency: every internal relationship is attached to a symbol (external references are attached to an external identity, which is correct)
156
+ ```
157
+
158
+ Note the first line is not the `✓ indexed N files` form. A run that parsed nothing
159
+ says so in words rather than printing a zero-file success
160
+ (`src/cli/index.ts:298-304`).
161
+
162
+ Read those lines carefully; they are the run's own report on itself.
163
+
164
+ - `breakdown:` — `newly parsed | unchanged | skipped | symbol-loss | errors |
165
+ timeouts`, plus `| N cancelled` on an interrupted run
166
+ (`src/cli/index.ts:356`).
167
+ - `parsed with the worker pool` / `parsed in-process …` — which parse path ran
168
+ (`src/cli/index.ts:376-384`). `in-process` means the run was **serial** and is
169
+ correspondingly slower, even though every other number on the line looks
170
+ pristine. A fourth value exists: `parsed nothing — no files needed parsing, so
171
+ no parse mode was used`, which is what a run that parsed nothing reports.
172
+ - `derived:` — one of `full`, `bounded`, `deferred`, `skipped-unchanged`,
173
+ `partial`, with its own note (`src/cli/index.ts:388-418`). **`deferred` means
174
+ the relationships/enrichment/gravity/taints/health data in your index is
175
+ stale.** Finish it with `bb index --post`.
176
+ - `consistency:` — a measurement taken from the store after the run, not an
177
+ inference from the `derived:` label (`src/cli/index.ts:426-449`). At zero it
178
+ prints a sentence; **non-zero means some internal edges are counted in the
179
+ relationship total above and traversed by nothing**, and it names the
180
+ remediation. A third form, `not measured for this run`, means the run predates
181
+ the measurement — that is *not* an all-clear.
182
+
183
+ ## `bb index --changed` — incremental
184
+
185
+ ```
186
+ bb index --changed
187
+ ```
188
+
189
+ **Does:** sets the run to incremental mode (`src/cli/index.ts:206`). Discovery
190
+ compares each file against the stored record and **skips files whose mtime and
191
+ size both match** (`src/ast/parallel-indexer.ts:887-894`); the rest are parsed.
192
+ Then it runs a **bounded** derived pass scoped to what this run touched, plus a
193
+ purge of files that no longer exist on disk. Measured:
194
+
195
+ ```
196
+ ✓ indexed 8 files, 24 symbols, 22 relationships, 6 embeddings in 4.8s
197
+ breakdown: 1 newly parsed | 7 unchanged | 0 skipped | 0 symbol-loss (parsed 0 symbols) | 0 errors | 0 timeouts
198
+ derived: bounded (derived data re-processed for touched files (bounded pass))
199
+ bounded: 10 symbols touched
200
+ ```
201
+
202
+ **Use when:** this is the daily driver after editing code.
203
+
204
+ **Does NOT:** re-parse unchanged files, and does not do a whole-project derived
205
+ pass. Write cost is proportional to what changed, not to the size of the
206
+ project.
207
+
208
+ Expect `derived: bounded (derived data re-processed for touched files (bounded pass))`.
209
+
210
+ ## `bb index --resume` — continue an interrupted run
211
+
212
+ ```
213
+ bb index --resume
214
+ ```
215
+
216
+ **Does:** reads the run's checkpoint, reports whether it found one, and runs
217
+ incrementally (`src/cli/index.ts:216-229`). Because resume is incremental, the
218
+ mtime/size skip means strictly fewer files are processed than a fresh run.
219
+ Measured with no checkpoint present:
220
+
221
+ ```
222
+ no in-progress checkpoint; running incremental (only missing/changed files)
223
+ ```
224
+
225
+ and then, after changing one file:
226
+
227
+ ```
228
+ ✓ indexed 8 files, 24 symbols, 22 relationships, 6 embeddings in 2.9s
229
+ breakdown: 2 newly parsed | 6 unchanged | 0 skipped | 0 symbol-loss (parsed 0 symbols) | 0 errors | 0 timeouts
230
+ derived: bounded (derived data re-processed for touched files (bounded pass))
231
+ bounded: 11 symbols touched
232
+ ```
233
+
234
+ When there is nothing left to parse, it reports `derived: skipped-unchanged`
235
+ instead — see the trap in
236
+ [`resume.md`](resume.md#verify-the-resume-was-correct).
237
+
238
+ **Use when:** a run was cancelled with Ctrl+C, or the machine died mid-index.
239
+
240
+ **Does NOT:** rewind anything, and does not re-run derived phases for work a
241
+ previous run already did — see the measured caveat in
242
+ [`resume.md`](resume.md#verify-the-resume-was-correct) before you trust it.
243
+
244
+ Full detail in [`resume.md`](resume.md).
245
+
246
+ ## `bb index --file <path>` — one file
247
+
248
+ ```
249
+ bb index --file src/services/auth.ts
250
+ ```
251
+
252
+ **Does:** restricts the run to that one path **and** sets incremental mode so
253
+ the derived pass is scoped to it (`src/cli/index.ts:198-205`).
254
+
255
+ **Use when:** an agent just created or edited a function and you want it
256
+ queryable immediately.
257
+
258
+ **Does NOT:** reindex neighbours. If the edit changed an import or a call site
259
+ elsewhere, that other file is stale too — use `--changed` instead. Note the
260
+ mtime/size check applies to `--file` as well, so a file whose mtime and size did
261
+ not change is not parsed and the run reports `derived: skipped-unchanged`.
262
+
263
+ ## `bb index --post` — derived phases only
264
+
265
+ ```
266
+ bb index --post
267
+ ```
268
+
269
+ **Does:** parses nothing. Re-runs all eight derived phases over the existing
270
+ index (`src/cli/index.ts:109-127`), printing a per-phase timing and outcome for
271
+ each. Real output, in the exact column alignment the CLI prints
272
+ (`p.name.padEnd(14)`):
273
+
274
+ ```
275
+ ✓ post-processing complete in 0.1s
276
+ ✓ relationships 2ms
277
+ ✓ enrichment 10ms
278
+ ✓ gravity 3ms
279
+ ✓ taint 2ms
280
+ ✓ health 56ms
281
+ ✓ integrity 10ms
282
+ ✓ vectorBlobs 3ms
283
+ ✓ analyze 3ms
284
+ ```
285
+
286
+ Exits 1 if any phase failed, and the index is marked `partial`
287
+ (`src/cli/index.ts:117-121`). If the project has no index at all it refuses with
288
+ `no index for project … — post-processing derives from indexed symbols; run bb
289
+ index first` (`src/ast/parallel-indexer.ts:5539-5541`).
290
+
291
+ **Use when:** `derived: deferred`, or `consistency:` reported unattached
292
+ internal relationships. This is the documented remediation for both.
293
+
294
+ **Does NOT:** parse, so it cannot fix a file whose symbols were never extracted.
295
+
296
+ ## `bb index --force` — wipe and rebuild
297
+
298
+ ```
299
+ bb index --force
300
+ ```
301
+
302
+ **Does:** takes the project's index lock first, then wipes the project's data
303
+ **in place — the `brain.db` file itself is kept** so a running MCP server's open
304
+ handle is not orphaned onto a stale view (`src/cli/index.ts:168-193`), then
305
+ does a full parse and all derived phases.
306
+
307
+ **Use when:** the index is genuinely corrupt, or you changed analyzer settings.
308
+
309
+ **Does NOT:** preserve anything. This is the most expensive mode there is — every
310
+ eligible file is re-parsed from scratch and every derived phase is recomputed.
311
+ See the measured costs in [`performance.md`](performance.md).
312
+
313
+ The functional cost of the in-place wipe is real: a concurrent reader sees an
314
+ empty database until the rebuild finishes (`src/cli/index.ts:181-184`).
315
+
316
+ ## `bb index --skip-post-processing` — parse and stop
317
+
318
+ ```
319
+ bb index --skip-post-processing
320
+ ```
321
+
322
+ **Does:** parses and stores, then stops. The run reports
323
+ `derived: deferred (derived data deferred — run: bb index --post)`
324
+ (`src/cli/index.ts:410`). Verified by running it.
325
+
326
+ **Use when:** you want symbols searchable immediately and do not need
327
+ relationships, enrichment, gravity, taints or health yet.
328
+
329
+ **Does NOT:** update any derived data. Until you run `bb index --post`, the
330
+ cross-file layer of the index is stale, and anything that reads it will be
331
+ reading stale data. This is the fastest route to "my new symbol is in the
332
+ index", not a way to skip work permanently.
333
+
334
+ ## Other flags
335
+
336
+ | Flag | Does |
337
+ | --- | --- |
338
+ | `--import <db>` | Adopt an existing `brain.db` onto this checkout's project id, then top up incrementally. For a project you moved or copied to another machine (`src/cli/index.ts:130-140`, `:144-164`). |
339
+ | `--no-setup` | Skip the first-run embedding prompt. Orthogonal to the semantics matrix. |
340
+ | `--verbose` | Raise log level to `debug` (`src/cli/index.ts:713`, `:720-723`). This is how you see worker-pool and WASM diagnostics — workers default to `error` and swallow everything below it. **There is no short form.** |
341
+ | `--quiet` | Raise log level to `warn` (`src/cli/index.ts:724-727`). **There is no short form.** |
342
+
343
+ There is deliberately no `-v` for verbose: `-v` is bound to `--version`
344
+ (`src/cli/index.ts:710`), so `bb index -v` prints a version number. `bb index -q`
345
+ is an error — `unknown option '-q'`.
346
+
347
+ `--import` deserves a caveat: adoption matches on the **codebase fingerprint**.
348
+ If no adopted index matches, `bb index` just builds a new one. Adoption also
349
+ implies incremental mode, because a move preserves mtimes and a full re-parse
350
+ would duplicate symbol rows (`src/cli/index.ts:210`).
351
+
352
+ ## Watching a run
353
+
354
+ The progress line goes to **stderr** so stdout stays clean for anything
355
+ consuming it (`src/cli/index.ts:236-254`). Shape, not a captured run — the
356
+ renderer adapts to TTY vs pipe (`src/cli/index-progress.ts`):
357
+
358
+ ```
359
+ 312/2580 files (12%) 18.4/s ETA 2m 9s — src/components/button.ts
360
+ ```
361
+
362
+ From another shell, `bb status` reports the in-flight run, and afterwards the
363
+ last run's per-phase breakdown — total, parse, dbFlush, discovery, worker
364
+ startup, worker count, and any post-processing timings the run recorded
365
+ (`src/cli/index.ts:630-662`):
366
+
367
+ ```
368
+ ✓ last index of /proj: 8 files, 24 symbols, 22 relationships
369
+ total n/a | parse 1218ms | dbFlush 27ms | discovery 77ms | startup 990ms
370
+ mode worker-pool | workers 1 | noop no
371
+ db: <data-dir>/projects/<projectId>/brain.db
372
+ ```
373
+
374
+ Real output from a fixture. Two things to know when reading it: `workers 1` on a
375
+ small project is correct (see
376
+ [`troubleshooting.md`](troubleshooting.md#cause-6--only-one-worker-and-that-is-correct)),
377
+ and `n/a` appears for any timing the recorded run did not persist.
378
+
379
+ `bb stats` gives the committed counts at any time, including during a run, and
380
+ prints the database path.
381
+
382
+ ## One index run at a time
383
+
384
+ Indexing takes a single-flight per-project lock (`src/ast/index-lock.ts`). A
385
+ second concurrent run refuses rather than interleaving writes, and names the
386
+ holder:
387
+
388
+ ```
389
+ ✗ another index run is already active for this project (pid 4821, started 2026-10-02T17:41:03.000Z, kind=index); wait for it to finish, or if it crashed the stale lock at .index.lock is reclaimed automatically on the next run
390
+ ```
391
+
392
+ A lock left behind by a crashed process is reclaimed automatically; you do not
393
+ need to delete it by hand.
394
+
395
+ ## Related
396
+
397
+ - `website/index-commands.md` — the user-facing command reference, same flags
398
+ - [`docs/EMBEDDINGS.md`](../EMBEDDINGS.md) — what the vector layer is and is not
399
+ - [`docs/TROUBLESHOOTING.md`](../TROUBLESHOOTING.md) — general `bb` troubleshooting
400
+ ## Reading the output
401
+
402
+ `bb index` writes live progress and logs to **stderr** and the final report to **stdout**, so a script can
403
+ capture the report without the live line. What you should see, in order:
404
+
405
+ 1. **The banner** — `indexing <path> (project <id>…)` before any side effect, so the first line says what is
406
+ being indexed (a `--force` wipe prints its reclaim lines after it, not before).
407
+ 2. **The expectation** — `Indexing <n> files — a moment — this is a tiny project` / `this will take a few
408
+ minutes` / `large project — this takes a while…`. The band scales with the discovered file count, so a
409
+ small project is never told to grab a coffee.
410
+ 3. **Progress + ETA** — on a terminal this is one redrawing bar: percentage, files done, rate, elapsed, and
411
+ `ETA <time>`. In a pipe or CI log the same information arrives as rate-limited `[index] NN% … eta=<time>`
412
+ milestone lines (one per 5% plus the final one), never a `\r` smear. The ETA is computed from the recent
413
+ window, not the lifetime average; it shows `…` until there is enough signal, and `finishing` once all
414
+ files are processed but the derived phases are still running (it never claims `0s` while work remains).
415
+ 4. **Encouragement / slow-run notes** — occasional lines like `halfway there` for long runs only (never on
416
+ tiny projects); a run slower than its size allows says so and names the support address.
417
+ 5. **Embeddings wait** — if the background embedding queue still has work, the run says it is finishing
418
+ vectors, bounds the wait, and reports how it ended; the counts printed afterwards are read from the
419
+ database after that wait, so they match `bb stats`.
420
+ 6. **The final report** — `✓ indexed …` (or `✓ nothing to index — already up to date`), the authoritative
421
+ `index health (after embeddings)` verdict, and the run's footprint.
422
+
423
+ **Noise is opt-in.** Per-file traces (the `[STORE] file: Ns Nr` lines for unusually large stores) are
424
+ debug-level: they appear only with `--verbose` and are silent by default, so the progress/ETA line, the
425
+ warnings and the final verdict are not buried in a wall of same-looking lines. Warnings/errors are visually
426
+ distinct when the destination is a terminal; `NO_COLOR` disables colour, `FORCE_COLOR=1` forces it in a pipe.
427
+ In a non-terminal destination the output is plain text and contains no ANSI escapes by default.
@@ -0,0 +1,41 @@
1
+ # What `bb index` actually scans
2
+
3
+ This page is the written form of the discovery matrix. It is verified by
4
+ `script/verify-index-discovery-matrix.ts`, which builds one fixture per case and asks the product's own
5
+ discovery function (`discoverIndexableFiles`, the same eligible-only walk behind `bb_health`) what it would
6
+ index. If a rule here changes without the doc and the gate moving together, the gate fails; the page cannot
7
+ silently drift from the walk.
8
+
9
+ The rules are enforced in this order (an explicit un-ignore is consulted first, so a user can always escape
10
+ a default with `.bbignore`):
11
+
12
+ | Case | Verdict | Rule |
13
+ | --- | --- | --- |
14
+ | A file whose extension maps to a supported language | **scanned** | `hasValidExtension` → `detectLanguageFromPath` (the language registry: TypeScript/JavaScript incl. `.mts`/`.cts`, Python, Go, Ruby, Rust, Java, Kotlin, Swift, C/C++, C#, PHP, Dart, Julia, R, Scala, Lua, shell, SQL, proto, GraphQL, and the structured-data/README extensions such as `.json`, `.yaml`, `.md`) |
15
+ | An extensionless file whose first 256 bytes are a shell `#!` line | **scanned** | bounded shebang read (`admitsShellShebang`); recognised extensions skip the read |
16
+ | A data file between 1 MB and 5 MB (e.g. `.json`) | **scanned** with structural extraction | size tier: full AST up to 1 MB; structural-only to 5 MB |
17
+ | A file over 5 MB | **skipped** | `> STRUCTURAL_LIMIT` skip in discovery; the file stays on disk, it is simply not indexed |
18
+ | A hidden directory (`.github`, `.vscode`, `.devcontainer`, `.hidden`, …) | **scanned** | hidden dirs are not skipped by default |
19
+ | Metadata/cache hidden dirs: `.git`, `.svn`, `.hg`, `.cache`, `.nyc_output`, `.venv`, `.next`, `.nuxt`, `.svelte-kit`, `.turbo` | **skipped** | fixed directory skip list |
20
+ | Default skip path segments: `Microbenchmarks/`, `wwwroot/`, `testassets/`, `benchmarkapps/`, `coverage/`, `testData/`, `node_modules/`, `dist/`, `build/`, `.git/`, `obj/`, `bin/` | **skipped** | built-in ignore globs + walk filter; `bin/` means the index does not re-index the launcher or build output |
21
+ | `vendor/`, `third_party/` | **scanned** | not on any skip list; vendored code is ordinary source |
22
+ | A file ignored by a `.gitignore` (root or nested) | **skipped** | `.gitignore` is respected at every directory level |
23
+ | A file ignored by `.gitignore` but re-included by a `.bbignore` `!pattern` | **scanned** | `.bbignore` is added after the gitignore layer; last match wins, so `!` un-ignores |
24
+ | A file listed in `.bbignore` | **skipped** | user-controlled exclusion, higher priority than `.gitignore` |
25
+ | A subdirectory containing its own `.git` (submodule / nested checkout / linked worktree) | **not walked** | nested project boundary; the subtree belongs to another index |
26
+ | A symlink | **not followed** | the walk admits regular files only; a symlinked file/dir is neither `isFile()` nor `isDirectory()` |
27
+ | A file deeper than 50 directory levels | **not walked** | depth cap 50 |
28
+ | A path matching `bb index --exclude <glob>` | **skipped for that run** | discovery exclusion, non-destructive: rows an earlier run stored are kept unless the file is genuinely gone |
29
+ | Anything else (binary, unknown extension, no shebang) | **skipped** | no language route |
30
+
31
+ Two consequences worth stating plainly:
32
+
33
+ - **The index is source plus structured text, not "everything".** A README, a `package.json` and a YAML
34
+ config are indexed because a language route exists for them; a PNG, a lockfile of unknown type or a
35
+ minified >5 MB bundle is not.
36
+ - **A nested repository is a boundary.** If a directory contains its own `.git`, its files belong to the
37
+ index of that checkout, not this one. Worktrees and submodules behave the same way.
38
+
39
+ To see what the rules admit for a project without indexing it, use the same walk via
40
+ `discoverIndexableFiles(projectPath)` (the gate does exactly this). `bb_health`'s completeness question also
41
+ uses this function, so "missing from the index" and "not eligible" are the same rule set.