@backbencher/brain 0.0.0-stage → 0.1.1

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-Q5APTJQL.js +17 -0
  8. package/dist/brain-relationship-enrichment-MYR2AM4F.js +558 -0
  9. package/dist/brain.sql-EIM4WS4D.js +29 -0
  10. package/dist/chunk-22V37YTK.js +1758 -0
  11. package/dist/chunk-2BSKD7O3.js +40 -0
  12. package/dist/chunk-2DE27DVC.js +1314 -0
  13. package/dist/chunk-2RRBMNBQ.js +322 -0
  14. package/dist/chunk-2WXYNLBA.js +29 -0
  15. package/dist/chunk-3CTFIJJB.js +17 -0
  16. package/dist/chunk-3ZTOHHSW.js +2104 -0
  17. package/dist/chunk-4H22TLOT.js +543 -0
  18. package/dist/chunk-5BVAH26D.js +340 -0
  19. package/dist/chunk-62DHLYW6.js +3427 -0
  20. package/dist/chunk-7AN7U5IZ.js +371 -0
  21. package/dist/chunk-7DRPNVIN.js +782 -0
  22. package/dist/chunk-7MBYT777.js +174 -0
  23. package/dist/chunk-AHDWGM7Q.js +236 -0
  24. package/dist/chunk-B5GEAAYF.js +818 -0
  25. package/dist/chunk-BEIZZ73B.js +1479 -0
  26. package/dist/chunk-BQ3OVQ3P.js +125 -0
  27. package/dist/chunk-D2Q4Y47A.js +53 -0
  28. package/dist/chunk-DIYAGQJL.js +34 -0
  29. package/dist/chunk-DWKXZ6IF.js +336 -0
  30. package/dist/chunk-DYM4FQEE.js +90 -0
  31. package/dist/chunk-ENW4BTBA.js +930 -0
  32. package/dist/chunk-EWMWK7WN.js +75 -0
  33. package/dist/chunk-EY5ZZUUA.js +626 -0
  34. package/dist/chunk-GBI7V7KY.js +69 -0
  35. package/dist/chunk-GEFFO6O2.js +152 -0
  36. package/dist/chunk-HJEWO5EV.js +247 -0
  37. package/dist/chunk-HQSPJDHI.js +613 -0
  38. package/dist/chunk-KAET47ZL.js +125 -0
  39. package/dist/chunk-KCDECRJY.js +440 -0
  40. package/dist/chunk-L5TDYKYK.js +76 -0
  41. package/dist/chunk-MLKGABMK.js +9 -0
  42. package/dist/chunk-NO3U3FJQ.js +201 -0
  43. package/dist/chunk-OWISBAOF.js +61 -0
  44. package/dist/chunk-QKTRECYS.js +1119 -0
  45. package/dist/chunk-QLK6ED4Q.js +235 -0
  46. package/dist/chunk-R2GW4F6R.js +19 -0
  47. package/dist/chunk-RCMTFSEF.js +87 -0
  48. package/dist/chunk-RM3PY6TG.js +376 -0
  49. package/dist/chunk-ROMM6KMC.js +433 -0
  50. package/dist/chunk-SGGCSHAX.js +12050 -0
  51. package/dist/chunk-SK6YVHFZ.js +211 -0
  52. package/dist/chunk-SM7RFQRO.js +214 -0
  53. package/dist/chunk-UGR4QIGS.js +67 -0
  54. package/dist/chunk-UQNQZXHY.js +711 -0
  55. package/dist/chunk-UUNHHX4M.js +13 -0
  56. package/dist/chunk-VL52PL2T.js +71 -0
  57. package/dist/chunk-WIG36E67.js +196 -0
  58. package/dist/chunk-XHK3WWGB.js +7436 -0
  59. package/dist/chunk-XTQM2IP3.js +2863 -0
  60. package/dist/chunk-ZE2LG76D.js +1296 -0
  61. package/dist/chunk-ZETTGPAW.js +6950 -0
  62. package/dist/cli/index.js +37 -0
  63. package/dist/config-HZAAYDP3.js +10 -0
  64. package/dist/content-search-7XIP555Q.js +593 -0
  65. package/dist/database-76RP44JG.js +9 -0
  66. package/dist/doctor-ANGETYMN.js +395 -0
  67. package/dist/edit-engine-CG72LDZD.js +51 -0
  68. package/dist/engine-BKEOGN7N.js +11 -0
  69. package/dist/engine-VIW6NSKO.js +18 -0
  70. package/dist/fingerprint-OBLIMZLP.js +33 -0
  71. package/dist/framework-intelligence-3LORTPOX.js +860 -0
  72. package/dist/freshness-3K6VU5OT.js +174 -0
  73. package/dist/graph-engine-HBSQNPTB.js +21 -0
  74. package/dist/graph_request-Q6NKB6N2.js +350 -0
  75. package/dist/impact_request-LYP672WE.js +68 -0
  76. package/dist/index-space-IUUN5WYV.js +15 -0
  77. package/dist/index-status-7OVGYSGW.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-FK2XKZXY.js +88 -0
  86. package/dist/pool-worker.js +1153 -0
  87. package/dist/project-health-6XPENVAA.js +94 -0
  88. package/dist/project-index-5SDPHITE.js +57 -0
  89. package/dist/project-registry-ZJ3DVUGO.js +355 -0
  90. package/dist/real-bash-analyzer-EJAU5LW5.js +2201 -0
  91. package/dist/real-c-analyzer-HBD3FNNH.js +5942 -0
  92. package/dist/real-clean-analyzer-4EEZLPV5.js +3470 -0
  93. package/dist/real-clojure-analyzer-Q55EBOO2.js +2818 -0
  94. package/dist/real-cpp-analyzer-IVVOD25R.js +4101 -0
  95. package/dist/real-csharp-analyzer-ZBNLNJZJ.js +3298 -0
  96. package/dist/real-css-analyzer-6XRQLUN7.js +15 -0
  97. package/dist/real-dart-analyzer-OLR72EFW.js +3944 -0
  98. package/dist/real-elixir-analyzer-MQWGAH2I.js +2192 -0
  99. package/dist/real-erlang-analyzer-7BVPQEHO.js +1731 -0
  100. package/dist/real-fsharp-analyzer-C2UPFNOA.js +2390 -0
  101. package/dist/real-go-analyzer-UKGI43YS.js +4126 -0
  102. package/dist/real-graphql-analyzer-VE2EEFII.js +1442 -0
  103. package/dist/real-groovy-analyzer-W26VACFW.js +2285 -0
  104. package/dist/real-haskell-analyzer-5CVVAJRX.js +2533 -0
  105. package/dist/real-hcl-analyzer-5ZT4U43N.js +725 -0
  106. package/dist/real-html-analyzer-JWNX3C6I.js +1759 -0
  107. package/dist/real-java-analyzer-GU42VBGQ.js +4677 -0
  108. package/dist/real-javascript-analyzer-QA4QOJ6W.js +14 -0
  109. package/dist/real-json-analyzer-MPA6PRXL.js +1640 -0
  110. package/dist/real-julia-analyzer-22CWYQMN.js +2085 -0
  111. package/dist/real-kotlin-analyzer-QDZJLXXU.js +3956 -0
  112. package/dist/real-lua-analyzer-G7NHLYKS.js +1957 -0
  113. package/dist/real-makefile-analyzer-OCY3GT5N.js +920 -0
  114. package/dist/real-markdown-analyzer-TEJK2JXJ.js +1215 -0
  115. package/dist/real-matlab-analyzer-Q5SWLN7Z.js +480 -0
  116. package/dist/real-nim-analyzer-YLXSK563.js +3603 -0
  117. package/dist/real-objective-c-analyzer-D23ACC2R.js +1518 -0
  118. package/dist/real-perl-analyzer-WWTRHYDT.js +1865 -0
  119. package/dist/real-php-analyzer-JNKJHTCL.js +9368 -0
  120. package/dist/real-powershell-analyzer-XRSNQERV.js +2915 -0
  121. package/dist/real-protobuf-analyzer-3OKUCZ7T.js +867 -0
  122. package/dist/real-python-analyzer-VXAFWI72.js +4880 -0
  123. package/dist/real-r-analyzer-ZGAIDVI4.js +2596 -0
  124. package/dist/real-ruby-analyzer-X2KTLVBH.js +2429 -0
  125. package/dist/real-rust-analyzer-OFFHPL2A.js +3359 -0
  126. package/dist/real-scala-analyzer-TSTW27J6.js +3293 -0
  127. package/dist/real-scss-analyzer-AVWYPSOQ.js +1515 -0
  128. package/dist/real-solidity-analyzer-UCI2KWUB.js +2608 -0
  129. package/dist/real-sql-analyzer-F77ZMQXR.js +3840 -0
  130. package/dist/real-svelte-analyzer-SF7NRUO5.js +2532 -0
  131. package/dist/real-swift-analyzer-MN5QT3QN.js +2311 -0
  132. package/dist/real-toml-analyzer-66L7BDCQ.js +929 -0
  133. package/dist/real-typescript-analyzer-6KEMVDWQ.js +14 -0
  134. package/dist/real-vb-analyzer-VICVPOP7.js +3145 -0
  135. package/dist/real-vba-analyzer-HXLTTHKM.js +466 -0
  136. package/dist/real-vue-analyzer-QXR56CFV.js +2680 -0
  137. package/dist/real-xml-analyzer-YL465ZJW.js +2405 -0
  138. package/dist/real-yaml-analyzer-SUBCBNSI.js +3528 -0
  139. package/dist/real-zig-analyzer-HIQLZMGY.js +2430 -0
  140. package/dist/regex-search-NJKHMZNO.js +239 -0
  141. package/dist/rules-ACHPB7QU.js +152 -0
  142. package/dist/scoped-path-MJYWJZQX.js +11 -0
  143. package/dist/setup-show-NT5ZHYNE.js +15 -0
  144. package/dist/setup-wizard-G5YYR5T6.js +24 -0
  145. package/dist/symbol-search-GZJIM2J2.js +16 -0
  146. package/dist/taint-KXUHHPIE.js +202 -0
  147. package/dist/taint-analyzer-N7YLZU3N.js +163 -0
  148. package/dist/tool-handlers-OJDC35DI.js +72 -0
  149. package/dist/tool-registry-BPEJNSZG.js +17 -0
  150. package/dist/tool-validation-Q57YMMBX.js +32 -0
  151. package/dist/type-inference-QMT2RMLV.js +13 -0
  152. package/dist/vector-binary-LMY4QGAN.js +19 -0
  153. package/dist/version-ABP2TUL2.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,325 @@
1
+ # Configuring embeddings
2
+
3
+ > Source of truth: the precedence resolver `resolveEmbeddingConfig`
4
+ > (`src/config/config.ts:35-53`), the client `src/brain/semantic/openai-embed.ts`,
5
+ > the local fallback in `src/brain/semantic/local-embed.ts`, the wizard and
6
+ > reporter in `src/setup/`, and `docs/EMBEDDINGS.md` for retrieval semantics.
7
+ >
8
+ > **This document contains no API key and never will.** It references environment
9
+ > variable *names* only. Do not commit a key to `bb.json`, to a docs file, to a
10
+ > test fixture, or to a log.
11
+
12
+ ## What embeddings are for
13
+
14
+ The brain stores one dense vector per indexed symbol in
15
+ `brain_semantic_embedding`. Those vectors power `bb_ask` — natural-language
16
+ questions. They do **not** power `bb_search`, which has no semantic mode
17
+ (`docs/EMBEDDINGS.md` §6).
18
+
19
+ Embeddings are generated **in the background after indexing**, in batches. `bb index`
20
+ waits for that whole pipeline (active job + queued jobs + queued items), announces the
21
+ wait, and only then reads the counts it prints — so the summary's embedding count,
22
+ `bb stats` and `bb health` agree with the database. Before 2026-11-01 the run read the
23
+ count first: a demo run printed `0 embeddings` over 12 stored rows and a real run
24
+ printed 568 over 1,117, with the same run printing an error-level "holds no vectors"
25
+ health claim. Coverage is still a per-run measurement, never a fixed product number
26
+ (`docs/EMBEDDINGS.md` §3).
27
+
28
+ ## How a vector is stored
29
+
30
+ Dense vectors are stored **once**, as a little-endian float32 blob
31
+ (`embedding_blob`: `vector_dimension * 4` bytes). The `embedding_vector` text column
32
+ holds an empty string for those rows. Storing both forms was measured on a real
33
+ 343-file repository: 28.9 MB of JSON digits beside 9.15 MB of float32 on an 84.5 MB
34
+ index — 34% of the whole database duplicated, plus a `JSON.stringify`/`parse` pair on
35
+ every write and read. Sparse token lists (`tfidf-v1`) keep their JSON form, and rows
36
+ written before 2026-11-01 keep JSON with a NULL blob until a background promotion
37
+ fills the blob; every read goes through one blob-first reader with that JSON fallback,
38
+ so an existing index keeps answering without being rebuilt. A rebuild
39
+ (`bb index --force`) reclaims the old JSON bytes (SQLite returns them to the file on
40
+ the next vacuum/rebuild, not in place).
41
+
42
+ ## The free/local fallback: you do not need a key
43
+
44
+ With no configuration at all, semantic search still works. It falls back to
45
+ built-in local word vectors:
46
+
47
+ | Property | Value |
48
+ | --- | --- |
49
+ | Model label | `local-word-vectors-v3` (`src/brain/semantic/engine.ts:49`) |
50
+ | Dimensions | 50 (`WORD_DIM`, `src/brain/semantic/local-embed.ts:7`) |
51
+ | Dependencies | none — no downloads, no model files |
52
+ | Strength | weaker than a real embedding model; lexical similarity over project vocabulary |
53
+
54
+ The label is **versioned** and the `-v3` is load-bearing: a tokenizer change makes
55
+ old and new vectors occupy different spaces even though both are 50-dimensional,
56
+ so the label is what lets the model-consistency guard refuse to compare them
57
+ (`src/brain/semantic/engine.ts:38-49`). If you see `local-word-vectors` without a
58
+ suffix anywhere in the docs, that is a bug — the constant is
59
+ `local-word-vectors-v3`. (`describeEmbeddingChain` reports the *provider role* as
60
+ `local word vectors` with model `local-word-vectors`, `src/brain/semantic/openai-embed.ts:514`;
61
+ that is a provider description, not the stored label. Do not confuse the two.)
62
+
63
+ `bb setup show` says so plainly when nothing is configured:
64
+
65
+ ```
66
+ Winner: none — semantic search will use local vectors (weaker). Setup: bb setup
67
+ ```
68
+
69
+ and `bb doctor` reports it as a warning, not a failure (`src/setup/doctor.ts:191-198`;
70
+ the `!` glyph is the warn severity, `src/setup/doctor.ts:213`):
71
+
72
+ ```
73
+ ! Semantic search will use local-word-vectors-v3 (weaker).
74
+ Fix: bb setup
75
+ ```
76
+
77
+ **This is a supported configuration, not a broken one.** It is also what CI and
78
+ MCP hosts get by default, because they have no TTY to prompt on
79
+ (`src/setup/setup-wizard.ts:355-370`). If you never configure anything, indexing
80
+ still runs, `bb_ask` still answers, and it reports its own degradation rather
81
+ than pretending.
82
+
83
+ ## Configure a provider
84
+
85
+ ### Option A — the wizard (recommended)
86
+
87
+ ```
88
+ bb setup
89
+ ```
90
+
91
+ It validates the endpoint with a real request before saving, maps failures to
92
+ actionable messages (a 401 means the key was rejected, a 429 means the key is
93
+ fine and you are rate-limited, a 404 means the model name is wrong), and writes
94
+ `~/.bb/config.json` with mode **0600** via a temp file and an atomic rename
95
+ (`src/setup/setup-wizard.ts:181-182`), and re-checks the mode afterwards
96
+ (`:191-192`).
97
+
98
+ `bb setup` requires an interactive terminal and exits with
99
+ `✗ bb setup requires an interactive terminal.` otherwise
100
+ (`src/cli/index.ts:783-786`). In a non-TTY, `bb index` never blocks: it prints a
101
+ one-line notice instead (`src/setup/setup-wizard.ts:363-368`).
102
+
103
+ ### Option B — environment variables
104
+
105
+ ```bash
106
+ export BB_EMBEDDING_BASE_URL="https://<your-endpoint>/v1"
107
+ export BB_EMBEDDING_MODEL="<your-embedding-model>"
108
+ export BB_EMBEDDING_API_KEY="<your-key>"
109
+ ```
110
+
111
+ Read the key from your secret store, your shell profile, or your CI secret
112
+ manager. Do not hardcode it.
113
+
114
+ ### Option C — a config file
115
+
116
+ `bb.json` in the project root, or `~/.bb/config.json` globally:
117
+
118
+ ```json
119
+ {
120
+ "embedding_base_url": "https://<your-endpoint>/v1",
121
+ "embedding_model": "<your-embedding-model>",
122
+ "embedding_api_key": "<your-key>"
123
+ }
124
+ ```
125
+
126
+ Prefer environment variables over `bb.json` for the key if the file is ever
127
+ going to be committed. `bb.json` at the project root is the tier most likely to
128
+ be shared with other people or checked into git.
129
+
130
+ ## Precedence
131
+
132
+ Highest tier wins, per field, independently (`src/config/config.ts:17-24`,
133
+ `:35-53`, `:70-81`):
134
+
135
+ 1. **Environment** — `BB_EMBEDDING_BASE_URL` / `BB_EMBEDDING_API_KEY` /
136
+ `BB_EMBEDDING_MODEL`
137
+ 2. **Config files** — explicit `BB_CONFIG_FILE` > `./bb.json` >
138
+ `<data-dir>/config.json` (`~/.bb/config.json` by default)
139
+ 3. **Built-in default** — `https://api.openai.com/v1` and
140
+ `text-embedding-3-small`
141
+
142
+ Two things that surprise people:
143
+
144
+ - The built-in defaults are **not** treated as "configured". A tier only counts
145
+ as configured when both a base URL and a model were set by env or file
146
+ (`configured: baseURLSrc !== "default" && modelSrc !== "default"`,
147
+ `src/config/config.ts:50`). Without that, an untouched install would look
148
+ remotely configured and would fail every request. An API key alone is not
149
+ enough either.
150
+ - **`BB_CONFIG_FILE` exists** so an MCP host can point at a workspace `bb.json`
151
+ regardless of the process's working directory
152
+ (`src/config/config.ts:77`).
153
+
154
+ Verify what is actually winning:
155
+
156
+ ```
157
+ bb setup show
158
+ ```
159
+
160
+ ```
161
+ bb — embedding configuration
162
+ Precedence: env > ~/.bb/config.json > bb.json
163
+
164
+ env: ✓ https://<endpoint>/v1 · <model> · key: ••••<last-4>
165
+ global: — (not set)
166
+ project: ✓ https://<other>/v1 · <other-model> · key: none · mode: 600
167
+
168
+ Winner: env
169
+ ```
170
+
171
+ Notes on that output:
172
+
173
+ - The key is printed as a **fingerprint only** — the last four characters. The
174
+ full key is structurally absent from the rendered output
175
+ (`src/setup/setup-show.ts:133-168`).
176
+ - An incomplete tier is shown with what's missing and can never win, even if it
177
+ appears first: the winner is the first *complete* tier in env → global →
178
+ project order (`src/setup/setup-show.ts:121-127`).
179
+ - A file mode other than `600` is flagged, because the file holds a key
180
+ (`src/setup/setup-show.ts:153-158`).
181
+ - `bb setup show` exits non-zero if nothing is configured
182
+ (`src/cli/index.ts:796`).
183
+
184
+ ## What is required
185
+
186
+ | Field | Required? | Notes |
187
+ | --- | --- | --- |
188
+ | base URL | **Yes**, together with the model | Must be a `/v1`-style OpenAI-compatible base; the client posts to `<baseURL>/embeddings` (`src/brain/semantic/openai-embed.ts:207`). Trailing slashes are stripped (`src/config/config.ts:47`). A base URL that is not a usable http(s) endpoint makes `getEmbeddingConfig()` return null, so remote embeddings turn off with a debug log rather than failing every batch (`src/brain/semantic/openai-embed.ts:60-64`). |
189
+ | model | **Yes** | Its name becomes the stored `embedding_model` label. |
190
+ | API key | Not for the tier to be *configured*; yes for most hosted providers | The `Authorization: Bearer` header is only sent when a key is present (`src/brain/semantic/openai-embed.ts:239`). Self-hosted servers that do not authenticate can omit it. |
191
+ | dimension | No | `embedding_dimension` in the config file, when your provider returns a fixed width (`src/brain/semantic/openai-embed.ts:56`). |
192
+
193
+ Any OpenAI-compatible `/embeddings` endpoint works — OpenAI, Google, NVIDIA
194
+ NIM, or a self-hosted vLLM / llama.cpp server. Loopback endpoints get
195
+ `NO_PROXY`/`no_proxy` handling so a local server behind a proxy configuration is
196
+ not unreachable: the loopback hosts `127.0.0.1`, `localhost` and `::1` are
197
+ appended to the no-proxy set (`src/brain/semantic/openai-embed.ts:215-226`).
198
+
199
+ ## Diagnose with `bb doctor`
200
+
201
+ ```
202
+ bb doctor
203
+ ```
204
+
205
+ Read-only by default. It checks configuration presence, tier completeness, file
206
+ permissions, model consistency against the vectors actually stored in the
207
+ project index, and semantic degradation (`src/setup/doctor.ts:104-202`):
208
+
209
+ | Finding | Severity | Glyph | Fix it prints |
210
+ | --- | --- | --- | --- |
211
+ | `no-config` | fail | `✗` | `bb setup` |
212
+ | `incomplete-{env,global,project}` | fail | `✗` | `bb setup` |
213
+ | `mode-{env,global,project}` | warn | `!` | `bb doctor --fix` |
214
+ | `model-mismatch` | fail | `✗` | `bb index --force` |
215
+ | `model-mixed` | warn | `!` | `bb index --force` |
216
+ | `no-index` | info | `·` | `bb index .` |
217
+ | `semantic-degraded` | warn | `!` | `bb setup` |
218
+
219
+ That is **seven** findings, not the "four things" an earlier draft of this page
220
+ claimed. `no-index` is informational, not a problem: it just means there are no
221
+ stored vectors to compare against yet. `bb doctor` exits 1 when a **fail**
222
+ finding exists (`src/setup/doctor.ts:200`, `src/cli/index.ts:815`).
223
+
224
+ `bb doctor --fix` applies exactly one repair: file permissions back to `0600`,
225
+ for at most 8 files per run (`MAX_FIX_ACTIONS`, `src/setup/doctor.ts:250`); a
226
+ file that changed between diagnosis and `chmod` becomes a printed refusal, never
227
+ a silent no-op (`:299-316`). It is read-only without the flag
228
+ (`src/cli/index.ts:804-816`).
229
+
230
+ ## When you change the model, you must re-embed
231
+
232
+ Vectors from different models occupy different vector spaces and are **never**
233
+ compared with each other, even at the same dimension
234
+ (`docs/EMBEDDINGS.md` §2). Changing `BB_EMBEDDING_MODEL` therefore does not
235
+ re-embed anything; it makes every previously stored vector unusable for search.
236
+
237
+ The symptom is that `bb doctor` reports (`src/setup/doctor.ts:163-168`; the
238
+ message is one line in the source — the counts are illustrative, not measured):
239
+
240
+ ```
241
+ ✗ Model mismatch: config has <new-model>, index has <old-model> (412 rows). Vectors from different models cannot be compared — the stored vectors are unusable.
242
+ Fix: bb index --force
243
+ ```
244
+
245
+ Note the `✗` glyph and the trailing `Fix:` line: the message text itself does not
246
+ contain the fix. A doc that quotes a doctor finding without the `Fix:` line is
247
+ quoting half of what you will see.
248
+
249
+ The fix is the one it names:
250
+
251
+ ```
252
+ bb index --force
253
+ ```
254
+
255
+ This is the correct and only fix — a full re-index is what re-embeds. The
256
+ storage query is what enforces the invariant: only rows whose `embedding_model`
257
+ equals the query model **and** whose `vector_dimension` equals the query vector
258
+ length are ever candidates.
259
+
260
+ ## Environment variables that control embedding behaviour
261
+
262
+ | Variable | Default | Effect |
263
+ | --- | --- | --- |
264
+ | `BB_EMBEDDING_BASE_URL` | — | OpenAI-compatible base URL. |
265
+ | `BB_EMBEDDING_MODEL` | — | Embedding model name; becomes the stored label. |
266
+ | `BB_EMBEDDING_API_KEY` | — | Sent as `Authorization: Bearer`. Read it from your secret store. |
267
+ | `BB_EMBEDDING_QUEUE_LIMIT` | `25000` | Cap on queued items for the background embedder (`src/ast/parallel-indexer.ts:1821`). Beyond it, work is dropped rather than queued forever. |
268
+ | `BB_EMBEDDING_CALL_TIMEOUT_MS` | `60000` | Bounds a single provider call, so a wedged or hanging server cannot permanently stall the drainer (`src/ast/parallel-indexer.ts:1832`). A timeout is treated as a provider failure and routed to the fallback. |
269
+ | `BB_EMBEDDING_BATCH_LIMIT` | `50000` | A batch at or above this size is not queued for embedding at all (`src/ast/parallel-indexer.ts:1897`). |
270
+ | `BB_EMBEDDING_CACHE_MAX` | `128` | LRU entry cap on the in-process embedding cache (`src/brain/semantic/engine.ts:157`). The cache key includes the effective model *and* endpoint, so a config change can never serve a vector from a different space. |
271
+ | `BB_VECTOR_SCAN_CAP` | `20000` | Cap on candidate rows loaded by a semantic query (`src/intelligence/search/semantic-search.ts:15`). When hit, `provenance.truncated` is `true` and `metadata.scannedRows` reports exactly how many were read. |
272
+ | `BB_DATA_DIR` | `~/.bb` | Where `config.json`, `status/`, `projects/` and `logs/` live (`src/util/bb-data-dir.ts:11-13`). |
273
+ | `BB_EMBEDDING_DISABLED` | unset | Kill switch. `1`/`true`/`yes`/`on` forces local word vectors with **zero** HTTP requests (`src/brain/semantic/embedding-config.ts:91-95`). An unrecognised value counts as OFF, so a typo cannot silently disable a paid provider. |
274
+ | `BB_EMBEDDING_TIMEOUT_MS` | `30000` | Bounds a single provider HTTP call (clamped 1 000–600 000) — `src/brain/semantic/embedding-config.ts:103`. Distinct from `BB_EMBEDDING_CALL_TIMEOUT_MS`, which bounds the indexer's drainer. |
275
+ | `BB_EMBEDDING_MAX_INPUTS` | `256` | Ceiling on inputs per `/embeddings` request (clamped 1–2048) — `src/brain/semantic/embedding-config.ts:117`. The default is load-bearing: the indexer already chunks to 100 snippets per call, so 256 keeps every real indexing request a **single** request. |
276
+ | `BB_EMBEDDING_DIMENSION` | unset | Declares the vector width you expect the provider to return. `src/brain/semantic/openai-embed.ts:452` REFUSES to store vectors whose width disagrees with this, because mixing widths in one index is the same defect as mixing models: search compares only one. Leave it unset unless you know the provider's real output width; if you set it wrongly, reindex with `bb index --force`. |
277
+ | `BB_EMBEDDING_FALLBACK_BASE_URL` | unset | Second provider used when the primary fails. Must be set together with `BB_EMBEDDING_FALLBACK_MODEL` — the fallback object is built only when both are non-empty (`src/brain/semantic/embedding-config.ts:126`), and setting one without the other is reported as an error by `describeEmbeddingSetup` (`:263-270`). |
278
+ | `BB_EMBEDDING_FALLBACK_MODEL` | unset | The fallback provider's model. See above. |
279
+ | `BB_EMBEDDING_FALLBACK_API_KEY` | unset | The fallback provider's key. |
280
+ | `BB_EMBEDDING_FALLBACK_RETRIES` | `2` | Retries **for the fallback provider only** (clamped 0–5) — `src/brain/semantic/embedding-config.ts:123`. See the retry-ownership note below before assuming your primary provider retries. |
281
+ | `BB_EMBEDDING_RETRY_BASE_MS` | `250` | Exponential backoff base for those retries (clamped 10–10 000) — `:124`. |
282
+ | `BB_EMBEDDING_RETRY_CAP_MS` | `4000` | Cap on that backoff (clamped 100–60 000) — `:125`. |
283
+
284
+ ### Who retries, precisely
285
+
286
+ This is worth stating because getting it wrong produces a confident, false
287
+ assurance about a provider outage:
288
+
289
+ | Provider | Retries? | Where |
290
+ | --- | --- | --- |
291
+ | **Primary** | **No client-side retry.** One attempt per call (`src/brain/semantic/openai-embed.ts:395` passes `maxAttempts = 1`). Its resilience is the *per-batch* path in `engine.ts` (`_apiRetryAt`): the failing batch degrades to local vectors, and **later batches** try the API again. On 429 specifically there is a bounded backoff honouring `Retry-After` (`src/brain/semantic/engine.ts:315-322`). | `src/brain/semantic/openai-embed.ts:361-379` states the ownership rule |
292
+ | **Fallback** | Yes, bounded exponential backoff, default 2 attempts. | `src/brain/semantic/openai-embed.ts:373-375`, `:441-483` |
293
+ | **401/403/404** | Never, on either. Latched per `(baseURL, model)` for the rest of the process — one 401 is enough to know retrying will not help (`src/brain/semantic/openai-embed.ts:391-392`, `:398-409`). | — |
294
+
295
+ So "indexing retries automatically" is true of a 429 and of later batches after
296
+ a transient 5xx. It is **not** true of the failed call itself, which is not
297
+ reissued — it degrades to local vectors, and the stored `embedding_model` for
298
+ those rows records the local label. That is why `bb index` prints the
299
+ `embeddings incomplete:` and multi-model warnings when it happens
300
+ (`src/cli/index.ts:318-340`), and why `bb doctor` reports `model-mixed`.
301
+
302
+ ## Honest limits
303
+
304
+ - **A key in a config file is a key on disk.** `bb setup` writes `0600` and
305
+ `bb doctor --fix` repairs the mode, but nothing stops you from committing a
306
+ `bb.json` to git. Use environment variables for anything shared.
307
+ - **Coverage is volatile.** The embedding API batches and rate-limits, so one
308
+ run may embed a different fraction of the same corpus than the next
309
+ (`docs/EMBEDDINGS.md` §3). `bb health` reports what was actually measured.
310
+ - **The query vector may not be the configured model.** The API layer can fall
311
+ back to local word vectors; the model that *actually produced* the last
312
+ vector is authoritative (`docs/EMBEDDINGS.md` §2). This is why the stored
313
+ label is written from the real producer.
314
+ - **`bb_search` does not use embeddings at all.** No semantic mode exists. Any
315
+ documentation or UI implying otherwise is wrong.
316
+ - **Embedding time as a share of index time is not measured.**
317
+ `docs/m20/PERFORMANCE-DIAGNOSTIC.md:24` explicitly declines to attribute a
318
+ slow run to embeddings for lack of evidence.
319
+
320
+ ## Related
321
+
322
+ - [`../EMBEDDINGS.md`](../EMBEDDINGS.md) — vector semantics, coverage, retrieval
323
+ measurements, fallback reasons
324
+ - [`README.md`](README.md) — flag semantics
325
+ - [`performance.md`](performance.md) — where index time actually goes
@@ -0,0 +1,77 @@
1
+ <!--
2
+ Author: Muhammad Ishaq Khan
3
+
4
+ WHAT THIS DOCUMENT IS — the environment variables that change query-index behaviour: operational knobs, test-only injection, and per-analyzer claim flags.
5
+ WHO IT IS FOR — an operator indexing a real project (or running the gates) who needs to know which knob is safe, which is diagnostics-only, and what each one changes.
6
+ EDIT TOGETHER WHEN THIS CHANGES — the `process.env.BB_*` reads in src/ast/index-lock.ts, src/ast/auto-refresh.ts, src/ast/index-status.ts, src/ast/parallel-indexer.ts and their gates (script/m43/verify-a3-flag-semantics.ts, script/m40/verify-a9-purge.ts).
7
+ -->
8
+
9
+ # Environment variables that change indexing
10
+
11
+ This page documents the `BB_*` knobs read by the indexer and by the language analyzers that the other
12
+ indexing pages do not cover. Precedence, defaults and the embedding resolver are documented in
13
+ `docs/indexing/embeddings.md`; worker/queue variables are in `docs/indexing/troubleshooting.md`; the
14
+ resume/checkpoint variables are in `docs/indexing/resume.md`. Everything here is read by `src/`.
15
+
16
+ There are three classes, and the class matters more than the name:
17
+
18
+ 1. **Operational knobs** — safe to set; they change cost/latency, not what the index claims.
19
+ 2. **Test-only injection** — only a gate sets these; they deliberately corrupt or freeze a run to prove
20
+ the failure path. Never export them in a shell that indexes a real project.
21
+ 3. **Analyzer claim flags** — default OFF and **byte-identical when off**. Each flag enables one
22
+ metadata claim inside one language analyzer; its lane's gate verifies the claim. Turning a flag on
23
+ without that gate's evidence is how a claim ships unverified.
24
+
25
+ ## Operational knobs
26
+
27
+ | Variable | Default | What it does |
28
+ | --- | --- | --- |
29
+ | `BB_DB_FLUSH_CHUNK` | `20` | Files per store-batch flush during indexing. Lowering it (e.g. `4`) bounds how long one store block can hold the event loop, at the cost of more commits; raising it amortizes commit overhead. This is a throughput/latency knob, not a correctness one. |
30
+ | `BB_EMBEDDING_DRAIN_WAIT_MS` | `300000` | How long `bb index` waits for the background embedding queue after the index itself is complete. The wait is announced before it starts; on timeout the remaining queue count is reported and semantic search is declared partial for those symbols. Raise it for slow providers, lower it for CI. |
31
+ | `BB_INDEX_VACUUM` | unset | `=0` disables the post-wipe `VACUUM` that `reclaimSpace` runs after a `--force` reindex. The index is correct either way; the file keeps the pages the wipe freed. Useful when a very large `--force` must finish quickly on a disk with room to spare. |
32
+ | `BB_DEBUG_DOTTED` | unset | `=1` prints the error when `resolveDottedTargets` (dotted import-path resolution) fails. Off by design: a dotted import that cannot be resolved is a data limitation, not a crash, and must not spam every run. |
33
+ | `BB_SQLITE_TEMP_STORE` | unset | Optional SQLite tuning: `MEMORY`/`FILE`/`DEFAULT` (or 0–2) sets the connection's `temp_store`. Off by default so a small install pays no extra memory. Measured on the apollo-server derived pass: temp_store=MEMORY + a 128 MB page cache reduced the pass 2.57 s → 2.46 s (relationships 1,449 → 1,287 ms, −11%); no full-index win was demonstrated at that corpus size, so the default is unchanged and the knob is for large databases. |
34
+ | `BB_SQLITE_CACHE_MB` | unset | Optional per-connection page cache in MiB (1–4096), applied as `cache_size = -<n*1024>` KiB. Same experiment as above; invalid/out-of-range values are ignored rather than guessed (`script/verify-sqlite-tuning.ts`). |
35
+ | `BB_INDEX_LOCK_GRACE_MS` | `10000` | How long an unreadable `.index.lock` (a 0-byte file from a kill between create and write, a corrupt payload, a full disk) is left alone before it is reclaimed. Inside the window nothing can prove a creator finished, so the acquire is refused; after it, no live creator can still be mid-write. |
36
+ | `BB_INDEX_LOCK_CROSS_HOST_TTL_MS` | `86400000` (24 h) | How long a lock written by ANOTHER host is honoured before it is reclaimed. A pid from another machine means nothing locally, so it is judged by age only; lower it only on a shared data directory whose writers are known to be short-lived. |
37
+ | `BB_STATUS_FSYNC` | unset | `=1` makes the live index-status checkpoint durable (fsync before rename) at the cost of a possible blocking fsync on every progress tick. The atomic rename already makes `kill -9` survivable; this is power-loss durability only. |
38
+ | `BB_NO_AUTO_REFRESH` | unset | `=1` disables the inline auto-refresh that a READ path runs when it finds stale files within budget. A measurement must set this so a read never takes the index lock or writes. |
39
+ | `BB_AUTO_REFRESH_MAX_FILES` | `25` | File-count budget for that inline repair; above it the read declines with the reason and answers from existing data with the staleness envelope. |
40
+ | `BB_AUTO_REFRESH_MAX_BYTES` | `2097152` (2 MiB) | Byte budget for the modified files of an inline repair; above it the read declines the repair rather than stalling. |
41
+ | `BB_INDEX_CONCURRENCY` | unset | Worker count for the parse pool, overriding the built-in plateau `max(2, min(cpus - 1, 12))`. Bounded 1–64; the CLI's `bb index --concurrency <n>` sets the same number for one run. Lower it to keep a machine responsive, raise it only when the index is truly CPU-bound. |
42
+
43
+ ## Test-only injection (gates only)
44
+
45
+ These exist so the failure paths are exercised on purpose. They are not production features.
46
+
47
+ | Variable | Used by | What it does |
48
+ | --- | --- | --- |
49
+ | `BB_TEST_FAIL_STORE_ONCE` | `script/perf/verify-store-failure-honesty.ts` | Makes the FIRST store batch throw. Proves a rolled-back batch is recovered, counted, and reported as an incomplete index rather than as a clean run. |
50
+ | `BB_TEST_FAIL_STORE_ALWAYS` | `script/perf/verify-store-failure-honesty.ts` | Makes EVERY store batch throw — the full-disk case. Proves the run exits non-zero and never claims `complete`. |
51
+ | `BB_TEST_FORCE_EDGE_RESOLVE` | edge-resolution A/B probes | Forces the legacy per-edge resolution arm of the bounded derived pass, for comparison against the current decider path. Changes derived rows by design; measurement only. |
52
+ | `BB_TEST_SKIP_EDGE_RESOLVE` | edge-resolution A/B probes | Skips the bounded edge-resolution pass entirely, for measurement. The index is left with unresolved edges it would otherwise re-point; never use it for an index you intend to query. |
53
+
54
+ Test-only variables are often read alongside `BB_TEST_HOOKS=1` (the umbrella switch documented in
55
+ `docs/indexing/troubleshooting.md`); a run with `BB_TEST_HOOKS=1` exported can take diagnostic
56
+ short-circuits inside MCP tool handlers and the worker fixtures.
57
+
58
+ ## Analyzer claim flags (default OFF, byte-identical when off)
59
+
60
+ Each of these enables one **metadata claim** in one language analyzer. The analyzer's accepted output
61
+ (the lane's D1–D6 verdict) was measured with the flag off, so off means "no change of any kind". With
62
+ the flag on, the analyzer attaches declaration facts it can verify — never a new or suppressed row —
63
+ and the lane's gate is responsible for checking the claim.
64
+
65
+ | Variable | Analyzer | Claim it enables |
66
+ | --- | --- | --- |
67
+ | `BB_CPP_CITATION` | C++ | `metadata.languageNamespace` (+ strict-absent policy) on calls whose bare target is an exact committed standard-library root. |
68
+ | `BB_CPP_PACKAGE_SCOPE` | C++ | Package-scope claims for qualified spellings, but ONLY when the caller supplies the governing manifest's package names in `context.cppPackageScopePackages`; with no package list it emits nothing. |
69
+ | `BB_CPP_INDEX_CONSUME` | C++ | Consumes the project index's declaration facts (call provenance, heritage kind, inheritance-closed declaring base for overrides) onto rows the analyzer already emits. Requires an index whose `complete` flag is strictly true; metadata only, never a row change. |
70
+ | `BB_DART_CITATION` | Dart | Namespace citation claims on rows whose bare target is an exact committed Dart SDK core-vocabulary name (`languageNamespace` + `"strict-absent"` policy on annotation rows and capitalized type-shaped targets). |
71
+ | `BB_KOTLIN_IMPORT_CLAIM` | Kotlin | Imported-binding claims derived from Kotlin import declarations. |
72
+ | `BB_PY_OWNER_MEMBER_ABSENT` | Python | Owner-member absence claims; fail-closed — without a COMPLETE project index it returns immediately, so the no-index arm is byte-identical. |
73
+ | `BB_RUBY_INDEX_CONSUME` | Ruby | Project-index consumption (overrides verification, declared constant paths for instantiates/extends/mixes_in). Fail-closed on an absent or incomplete index; calls are deliberately not touched. |
74
+ | `BB_JULIA_BIND_SHOW` | Julia (diagnostic) | An integer N: prints up to N one-binding key representatives while collapsing Julia bindings. This is read-only diagnostics; it does not change analyzer output. |
75
+
76
+ If you are not that analyzer's gate, leave these flags alone. A claim emitted without its gate's
77
+ evidence is exactly the failure mode these pages exist to prevent.