@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.
- package/CHANGELOG.md +298 -0
- package/EMBEDDINGS.md +355 -0
- package/LICENSE +21 -0
- package/README.md +415 -2
- package/bin/bb +13 -0
- package/dist/analysis-exclusions-7ZJDXOVZ.js +35 -0
- package/dist/brain-index-health-KY7K552E.js +17 -0
- package/dist/brain-relationship-enrichment-QH7OOHUF.js +558 -0
- package/dist/brain.sql-EIM4WS4D.js +29 -0
- package/dist/chunk-2BSKD7O3.js +40 -0
- package/dist/chunk-2DE27DVC.js +1314 -0
- package/dist/chunk-2RRBMNBQ.js +322 -0
- package/dist/chunk-2RTN2DFU.js +711 -0
- package/dist/chunk-2WXYNLBA.js +29 -0
- package/dist/chunk-3CTFIJJB.js +17 -0
- package/dist/chunk-3LFTSMIV.js +174 -0
- package/dist/chunk-47HKX4AJ.js +930 -0
- package/dist/chunk-4H22TLOT.js +543 -0
- package/dist/chunk-5SD45FLC.js +818 -0
- package/dist/chunk-66A5ZFYA.js +1758 -0
- package/dist/chunk-6AIRWAO2.js +247 -0
- package/dist/chunk-6WNGD3NN.js +196 -0
- package/dist/chunk-7AN7U5IZ.js +371 -0
- package/dist/chunk-BHB7BYYI.js +626 -0
- package/dist/chunk-BQ3OVQ3P.js +125 -0
- package/dist/chunk-CW4XXSNN.js +1479 -0
- package/dist/chunk-D2Q4Y47A.js +53 -0
- package/dist/chunk-DIYAGQJL.js +34 -0
- package/dist/chunk-DYM4FQEE.js +90 -0
- package/dist/chunk-EWMWK7WN.js +75 -0
- package/dist/chunk-FVVQTSIM.js +3427 -0
- package/dist/chunk-FWSL4VG6.js +1290 -0
- package/dist/chunk-GBI7V7KY.js +69 -0
- package/dist/chunk-GEFFO6O2.js +152 -0
- package/dist/chunk-HOWAQXJO.js +236 -0
- package/dist/chunk-HQSPJDHI.js +613 -0
- package/dist/chunk-IFZNR5UJ.js +2863 -0
- package/dist/chunk-J4PMBXQQ.js +336 -0
- package/dist/chunk-KAET47ZL.js +125 -0
- package/dist/chunk-KCDECRJY.js +440 -0
- package/dist/chunk-KLK3PBTO.js +1119 -0
- package/dist/chunk-L5TDYKYK.js +76 -0
- package/dist/chunk-MLKGABMK.js +9 -0
- package/dist/chunk-OWISBAOF.js +61 -0
- package/dist/chunk-PJTNGD3Z.js +6924 -0
- package/dist/chunk-QLK6ED4Q.js +235 -0
- package/dist/chunk-R2GW4F6R.js +19 -0
- package/dist/chunk-RCMTFSEF.js +87 -0
- package/dist/chunk-RH7KC5HU.js +12050 -0
- package/dist/chunk-RM3PY6TG.js +376 -0
- package/dist/chunk-ROMM6KMC.js +433 -0
- package/dist/chunk-SK6YVHFZ.js +211 -0
- package/dist/chunk-SM7RFQRO.js +214 -0
- package/dist/chunk-UFE77L67.js +782 -0
- package/dist/chunk-UGR4QIGS.js +67 -0
- package/dist/chunk-UUNHHX4M.js +13 -0
- package/dist/chunk-V44PGPA6.js +2104 -0
- package/dist/chunk-VL52PL2T.js +71 -0
- package/dist/chunk-VURYFIHW.js +201 -0
- package/dist/chunk-XJKJYIPP.js +7436 -0
- package/dist/chunk-YI6FF2ZR.js +340 -0
- package/dist/cli/index.js +37 -0
- package/dist/config-HZAAYDP3.js +10 -0
- package/dist/content-search-642F7E5V.js +593 -0
- package/dist/database-TCTZDLE5.js +9 -0
- package/dist/doctor-GXCKSJOX.js +395 -0
- package/dist/edit-engine-KM7MPFEC.js +51 -0
- package/dist/engine-42TZFNIZ.js +11 -0
- package/dist/engine-LO6L4JLQ.js +18 -0
- package/dist/fingerprint-XDXFRWO6.js +33 -0
- package/dist/framework-intelligence-DWFCKV44.js +860 -0
- package/dist/freshness-3K6VU5OT.js +174 -0
- package/dist/graph-engine-PL5YA7BA.js +21 -0
- package/dist/graph_request-MM4REP6H.js +350 -0
- package/dist/impact_request-WDE47IZ5.js +68 -0
- package/dist/index-space-IUUN5WYV.js +15 -0
- package/dist/index-status-6BD7UBHR.js +34 -0
- package/dist/index.js +159 -0
- package/dist/instance-FO6QZRLH.js +19 -0
- package/dist/language-detection-DFCAU5DZ.js +11 -0
- package/dist/lsp/server.js +4301 -0
- package/dist/mcp/server.js +132 -0
- package/dist/onboard-DIQZV2NW.js +161 -0
- package/dist/override-companion-pass-XR7MHTP7.js +117 -0
- package/dist/parallel-indexer-4PW3AFXP.js +88 -0
- package/dist/pool-worker.js +1153 -0
- package/dist/project-health-ZS5TS2Z6.js +94 -0
- package/dist/project-index-5SDPHITE.js +57 -0
- package/dist/project-registry-DGZBIZS7.js +355 -0
- package/dist/real-bash-analyzer-SXSV67E2.js +2201 -0
- package/dist/real-c-analyzer-SY7FTZ6W.js +5942 -0
- package/dist/real-clean-analyzer-IGDHHLZK.js +3470 -0
- package/dist/real-clojure-analyzer-4OH7IWLB.js +2818 -0
- package/dist/real-cpp-analyzer-7LTDRJRJ.js +4101 -0
- package/dist/real-csharp-analyzer-KICU3TLH.js +3298 -0
- package/dist/real-css-analyzer-HPU277Q6.js +15 -0
- package/dist/real-dart-analyzer-7LZ5LCMW.js +3944 -0
- package/dist/real-elixir-analyzer-BE3MEVZO.js +2192 -0
- package/dist/real-erlang-analyzer-BZMAKYBK.js +1731 -0
- package/dist/real-fsharp-analyzer-5QLTOV3E.js +2390 -0
- package/dist/real-go-analyzer-POD7MZQR.js +4126 -0
- package/dist/real-graphql-analyzer-MAQRZ6QW.js +1442 -0
- package/dist/real-groovy-analyzer-MEWSUPMJ.js +2285 -0
- package/dist/real-haskell-analyzer-I5L2GR3Y.js +2533 -0
- package/dist/real-hcl-analyzer-DBOPXSWJ.js +725 -0
- package/dist/real-html-analyzer-O63XZLZD.js +1759 -0
- package/dist/real-java-analyzer-CHCW3EKA.js +4677 -0
- package/dist/real-javascript-analyzer-QAAJQYZE.js +14 -0
- package/dist/real-json-analyzer-UGBR7YQN.js +1640 -0
- package/dist/real-julia-analyzer-35Q4GHOZ.js +2085 -0
- package/dist/real-kotlin-analyzer-GRAYCWW2.js +3956 -0
- package/dist/real-lua-analyzer-5BAPDZDF.js +1957 -0
- package/dist/real-makefile-analyzer-YJKAHNAS.js +920 -0
- package/dist/real-markdown-analyzer-UKUQZO4F.js +1215 -0
- package/dist/real-matlab-analyzer-FVIKQZKG.js +480 -0
- package/dist/real-nim-analyzer-M7FAIABG.js +3603 -0
- package/dist/real-objective-c-analyzer-XMYQIGQI.js +1518 -0
- package/dist/real-perl-analyzer-ZLY6M2DZ.js +1865 -0
- package/dist/real-php-analyzer-KI2ZAM7X.js +9368 -0
- package/dist/real-powershell-analyzer-B3T5ZP6U.js +2915 -0
- package/dist/real-protobuf-analyzer-23OZ75XV.js +867 -0
- package/dist/real-python-analyzer-I4TIUB6D.js +4880 -0
- package/dist/real-r-analyzer-FJZJXXS6.js +2596 -0
- package/dist/real-ruby-analyzer-M3UFIVTQ.js +2429 -0
- package/dist/real-rust-analyzer-LVSONPAN.js +3359 -0
- package/dist/real-scala-analyzer-CWPI33Q2.js +3293 -0
- package/dist/real-scss-analyzer-TGRJQ7TH.js +1515 -0
- package/dist/real-solidity-analyzer-4P2VBVWA.js +2608 -0
- package/dist/real-sql-analyzer-J7DYZOZR.js +3840 -0
- package/dist/real-svelte-analyzer-NHEN2SX5.js +2532 -0
- package/dist/real-swift-analyzer-2NSYULWI.js +2311 -0
- package/dist/real-toml-analyzer-L3C66L7Q.js +929 -0
- package/dist/real-typescript-analyzer-FTC6ETRQ.js +14 -0
- package/dist/real-vb-analyzer-ORY7LAQS.js +3145 -0
- package/dist/real-vba-analyzer-JH2TTUFI.js +466 -0
- package/dist/real-vue-analyzer-OO4FUGBV.js +2680 -0
- package/dist/real-xml-analyzer-6CQVR477.js +2405 -0
- package/dist/real-yaml-analyzer-J6MQG3YX.js +3528 -0
- package/dist/real-zig-analyzer-EFKCPJNU.js +2430 -0
- package/dist/regex-search-OPTLKUN5.js +239 -0
- package/dist/rules-I453JTRC.js +152 -0
- package/dist/scoped-path-MJYWJZQX.js +11 -0
- package/dist/setup-show-Y5GB5KXA.js +15 -0
- package/dist/setup-wizard-G5YYR5T6.js +24 -0
- package/dist/symbol-search-KB4MU4SI.js +16 -0
- package/dist/taint-YOTN5X55.js +202 -0
- package/dist/taint-analyzer-N7YLZU3N.js +163 -0
- package/dist/tool-handlers-G4NAGJIH.js +72 -0
- package/dist/tool-registry-BPEJNSZG.js +17 -0
- package/dist/tool-validation-RF675A3C.js +32 -0
- package/dist/type-inference-4Y7WTMFE.js +13 -0
- package/dist/vector-binary-LMY4QGAN.js +19 -0
- package/dist/version-LXGNFO37.js +9 -0
- package/dist/wasm-NMWO3WXY.js +16 -0
- package/docs/EMBEDDINGS.md +132 -0
- package/docs/README.md +178 -0
- package/docs/data/m10-baseline.json +602 -0
- package/docs/data/m10-benchmark-baseline.json +57 -0
- package/docs/data/m10-benchmark-last-run.json +127 -0
- package/docs/data/m10-final-audit.json +215 -0
- package/docs/data/m12-final-audit.json +138 -0
- package/docs/data/m12-surface-matrix.json +50 -0
- package/docs/data/public-tools.json +1902 -0
- package/docs/indexing/DEAD-ASSETS.md +88 -0
- package/docs/indexing/INDEXER-REVIEW.md +634 -0
- package/docs/indexing/PERFORMANCE-FINDINGS.md +106 -0
- package/docs/indexing/README.md +427 -0
- package/docs/indexing/discovery-matrix.md +41 -0
- package/docs/indexing/embeddings.md +325 -0
- package/docs/indexing/environment-variables.md +77 -0
- package/docs/indexing/performance.md +323 -0
- package/docs/indexing/resume.md +345 -0
- package/docs/indexing/troubleshooting.md +391 -0
- package/docs/man/bb.1 +190 -0
- package/docs/tools/bb_analyze.md +147 -0
- package/docs/tools/bb_annotate.md +110 -0
- package/docs/tools/bb_annotations.md +106 -0
- package/docs/tools/bb_ask.md +101 -0
- package/docs/tools/bb_cross_language.md +103 -0
- package/docs/tools/bb_doc.md +169 -0
- package/docs/tools/bb_edit.md +185 -0
- package/docs/tools/bb_graph.md +169 -0
- package/docs/tools/bb_health.md +156 -0
- package/docs/tools/bb_impact.md +117 -0
- package/docs/tools/bb_index.md +108 -0
- package/docs/tools/bb_migrate.md +135 -0
- package/docs/tools/bb_patterns.md +140 -0
- package/docs/tools/bb_search.md +150 -0
- package/docs/tools/bb_security.md +100 -0
- package/docs/tools/bb_visualize.md +184 -0
- package/grammars/README.md +57 -0
- package/grammars/THIRD-PARTY-NOTICES.md +50 -0
- package/grammars/tree-sitter-c/LICENSE +21 -0
- package/grammars/tree-sitter-clojure/LICENSE.md +21 -0
- package/grammars/tree-sitter-cpp/LICENSE +21 -0
- package/grammars/tree-sitter-csharp/LICENSE +21 -0
- package/grammars/tree-sitter-css/LICENSE +21 -0
- package/grammars/tree-sitter-css/README.md +21 -0
- package/grammars/tree-sitter-dart/LICENSE +20 -0
- package/grammars/tree-sitter-dart-upstream/LICENSE +20 -0
- package/grammars/tree-sitter-dart-upstream/README.md +18 -0
- package/grammars/tree-sitter-elixir/LICENSE +176 -0
- package/grammars/tree-sitter-elixir/README.md +11 -0
- package/grammars/tree-sitter-fsharp/LICENSE +21 -0
- package/grammars/tree-sitter-fsharp/README.md +45 -0
- package/grammars/tree-sitter-graphql/LICENSE +21 -0
- package/grammars/tree-sitter-graphql/README.md +106 -0
- package/grammars/tree-sitter-groovy/LICENSE +21 -0
- package/grammars/tree-sitter-groovy/README.md +4 -0
- package/grammars/tree-sitter-haskell/LICENSE +21 -0
- package/grammars/tree-sitter-haskell/README.md +394 -0
- package/grammars/tree-sitter-hcl/CHANGELOG.md +102 -0
- package/grammars/tree-sitter-hcl/LICENSE +201 -0
- package/grammars/tree-sitter-hcl/README.md +39 -0
- package/grammars/tree-sitter-html/LICENSE +21 -0
- package/grammars/tree-sitter-html/README.md +21 -0
- package/grammars/tree-sitter-julia/LICENSE +21 -0
- package/grammars/tree-sitter-julia/README.md +24 -0
- package/grammars/tree-sitter-kotlin/LICENSE +9 -0
- package/grammars/tree-sitter-lua/LICENSE.md +21 -0
- package/grammars/tree-sitter-lua/README.md +29 -0
- package/grammars/tree-sitter-make/LICENSE +21 -0
- package/grammars/tree-sitter-matlab/LICENSE +19 -0
- package/grammars/tree-sitter-matlab/README.md +99 -0
- package/grammars/tree-sitter-nim/LICENSE +373 -0
- package/grammars/tree-sitter-nim/README.md +46 -0
- package/grammars/tree-sitter-objc/LICENSE +21 -0
- package/grammars/tree-sitter-objc/README.md +20 -0
- package/grammars/tree-sitter-perl/LICENSE +7 -0
- package/grammars/tree-sitter-perl/README.md +100 -0
- package/grammars/tree-sitter-powershell/LICENSE +21 -0
- package/grammars/tree-sitter-powershell/README.md +7 -0
- package/grammars/tree-sitter-proto/LICENSE +21 -0
- package/grammars/tree-sitter-proto/README.md +105 -0
- package/grammars/tree-sitter-r/LICENSE +9 -0
- package/grammars/tree-sitter-r/README.md +66 -0
- package/grammars/tree-sitter-ruby/LICENSE +22 -0
- package/grammars/tree-sitter-scss/LICENSE +21 -0
- package/grammars/tree-sitter-scss/README.md +17 -0
- package/grammars/tree-sitter-solidity/LICENSE +7 -0
- package/grammars/tree-sitter-sql/LICENSE +21 -0
- package/grammars/tree-sitter-typescript/LICENSE +21 -0
- package/grammars/tree-sitter-vba/LICENSE +21 -0
- package/grammars/tree-sitter-vba/README.md +738 -0
- package/grammars/tree-sitter-vbnet/LICENSE +21 -0
- package/grammars/tree-sitter-vbnet/README.md +322 -0
- package/grammars/tree-sitter-xml/LICENSE +19 -0
- package/grammars/tree-sitter-yaml/LICENSE +20 -0
- package/grammars/tree-sitter-yaml/README.md +21 -0
- package/package.json +184 -4
- package/wasm/dart.wasm +0 -0
- package/wasm/tree-sitter-bash.wasm +0 -0
- package/wasm/tree-sitter-c.wasm +0 -0
- package/wasm/tree-sitter-c_sharp.wasm +0 -0
- package/wasm/tree-sitter-clean.wasm +0 -0
- package/wasm/tree-sitter-clojure.wasm +0 -0
- package/wasm/tree-sitter-core_schema.wasm +0 -0
- package/wasm/tree-sitter-cpp.wasm +0 -0
- package/wasm/tree-sitter-css.wasm +0 -0
- package/wasm/tree-sitter-dart.wasm +0 -0
- package/wasm/tree-sitter-elisp.wasm +0 -0
- package/wasm/tree-sitter-elixir.wasm +0 -0
- package/wasm/tree-sitter-elm.wasm +0 -0
- package/wasm/tree-sitter-embedded_template.wasm +0 -0
- package/wasm/tree-sitter-erlang.wasm +0 -0
- package/wasm/tree-sitter-fsharp.wasm +0 -0
- package/wasm/tree-sitter-fsharp_signature.wasm +0 -0
- package/wasm/tree-sitter-go.wasm +0 -0
- package/wasm/tree-sitter-graphql.wasm +0 -0
- package/wasm/tree-sitter-groovy.wasm +0 -0
- package/wasm/tree-sitter-haskell.wasm +0 -0
- package/wasm/tree-sitter-hcl.wasm +0 -0
- package/wasm/tree-sitter-html.wasm +0 -0
- package/wasm/tree-sitter-java.wasm +0 -0
- package/wasm/tree-sitter-javascript.wasm +0 -0
- package/wasm/tree-sitter-json.wasm +0 -0
- package/wasm/tree-sitter-json_schema.wasm +0 -0
- package/wasm/tree-sitter-julia.wasm +0 -0
- package/wasm/tree-sitter-kotlin.wasm +0 -0
- package/wasm/tree-sitter-lua.wasm +0 -0
- package/wasm/tree-sitter-make.wasm +0 -0
- package/wasm/tree-sitter-markdown.wasm +0 -0
- package/wasm/tree-sitter-markdown_inline.wasm +0 -0
- package/wasm/tree-sitter-matlab.wasm +0 -0
- package/wasm/tree-sitter-nim.wasm +0 -0
- package/wasm/tree-sitter-objc.wasm +0 -0
- package/wasm/tree-sitter-ocaml.wasm +0 -0
- package/wasm/tree-sitter-perl.wasm +0 -0
- package/wasm/tree-sitter-php.wasm +0 -0
- package/wasm/tree-sitter-php_only.wasm +0 -0
- package/wasm/tree-sitter-powershell.wasm +0 -0
- package/wasm/tree-sitter-protobuf.wasm +0 -0
- package/wasm/tree-sitter-python.wasm +0 -0
- package/wasm/tree-sitter-ql.wasm +0 -0
- package/wasm/tree-sitter-r.wasm +0 -0
- package/wasm/tree-sitter-rescript.wasm +0 -0
- package/wasm/tree-sitter-ruby.wasm +0 -0
- package/wasm/tree-sitter-rust.wasm +0 -0
- package/wasm/tree-sitter-scala.wasm +0 -0
- package/wasm/tree-sitter-scss.wasm +0 -0
- package/wasm/tree-sitter-solidity.wasm +0 -0
- package/wasm/tree-sitter-sql.wasm +0 -0
- package/wasm/tree-sitter-svelte.wasm +0 -0
- package/wasm/tree-sitter-swift.wasm +0 -0
- package/wasm/tree-sitter-systemrdl.wasm +0 -0
- package/wasm/tree-sitter-terraform.wasm +0 -0
- package/wasm/tree-sitter-tlaplus.wasm +0 -0
- package/wasm/tree-sitter-toml.wasm +0 -0
- package/wasm/tree-sitter-tsx.wasm +0 -0
- package/wasm/tree-sitter-typescript.wasm +0 -0
- package/wasm/tree-sitter-vba.wasm +0 -0
- package/wasm/tree-sitter-vbnet.wasm +0 -0
- package/wasm/tree-sitter-vue.wasm +0 -0
- package/wasm/tree-sitter-xml.wasm +0 -0
- package/wasm/tree-sitter-yaml.wasm +0 -0
- package/wasm/tree-sitter-zig.wasm +0 -0
- package/wasm/tree-sitter.wasm +0 -0
- package/wasm/tsx.wasm +0 -0
- package/wasm/typescript.wasm +0 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Author: Muhammad Ishaq Khan
|
|
3
|
+
|
|
4
|
+
WHAT THIS DOCUMENT IS — the generated reference for bb_patterns: contract, input schema, returns, examples, errors, limitations, performance, safety and evidence semantics.
|
|
5
|
+
WHO IT IS FOR — callers of bb_patterns through any MCP host, the CLI (`bb tool bb_patterns`), or a library.
|
|
6
|
+
EDIT TOGETHER WHEN THIS CHANGES — src/mcp/tools/bb_patterns/descriptor.ts, src/mcp/tools/bb_patterns/handler.ts, script/tool-docs/curation/bb_patterns.ts; regenerate with `npx tsx script/verify-tool-docs.ts --only bb_patterns --write`.
|
|
7
|
+
-->
|
|
8
|
+
# `bb_patterns`
|
|
9
|
+
|
|
10
|
+
Detect orphaned code, framework patterns, and anti-patterns, ranked by confidence, with staleness markers when a finding's file changed after indexing. Use scope=orphaned for dead code; scope=all (default) for the full pattern scan with the optional class/confidence filters. Orphan confidence is derived from evidence (0.30-0.70); anti-pattern confidence is 0.60-0.90; framework findings carry a fixed 0.6. `limit` is one bounded page (maximum 500) and the answer names the full census. Architecture and code-quality analysis are planned, not yet executable.
|
|
11
|
+
|
|
12
|
+
## Contract
|
|
13
|
+
|
|
14
|
+
- Category: `analysis`
|
|
15
|
+
- Mutability: `read`
|
|
16
|
+
- Requires index: `true`
|
|
17
|
+
- Modes: `orphaned`, `all`
|
|
18
|
+
- Planned modes (roadmap, not executable): `quality`, `architecture`
|
|
19
|
+
- Defaults: `{"scope":"all","limit":20,"includeOrphaned":true,"includeFramework":true,"includeAntiPatterns":true,"confidenceThreshold":0,"history":false,"recordRun":false}`
|
|
20
|
+
|
|
21
|
+
## Input Schema
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"type": "object",
|
|
26
|
+
"properties": {
|
|
27
|
+
"scope": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"enum": [
|
|
30
|
+
"orphaned",
|
|
31
|
+
"all"
|
|
32
|
+
],
|
|
33
|
+
"default": "all",
|
|
34
|
+
"description": "orphaned only, or all pattern classes (default all)"
|
|
35
|
+
},
|
|
36
|
+
"limit": {
|
|
37
|
+
"type": "number",
|
|
38
|
+
"default": 20,
|
|
39
|
+
"minimum": 0,
|
|
40
|
+
"maximum": 500,
|
|
41
|
+
"description": "maximum findings displayed (default 20, maximum 500); the answer's census line reports the full count"
|
|
42
|
+
},
|
|
43
|
+
"includeOrphaned": {
|
|
44
|
+
"type": "boolean",
|
|
45
|
+
"default": true,
|
|
46
|
+
"description": "include orphaned-code patterns in an all scan (default true)"
|
|
47
|
+
},
|
|
48
|
+
"includeFramework": {
|
|
49
|
+
"type": "boolean",
|
|
50
|
+
"default": true,
|
|
51
|
+
"description": "include framework patterns (default true)"
|
|
52
|
+
},
|
|
53
|
+
"includeAntiPatterns": {
|
|
54
|
+
"type": "boolean",
|
|
55
|
+
"default": true,
|
|
56
|
+
"description": "include anti-patterns (default true)"
|
|
57
|
+
},
|
|
58
|
+
"confidenceThreshold": {
|
|
59
|
+
"type": "number",
|
|
60
|
+
"default": 0,
|
|
61
|
+
"minimum": 0,
|
|
62
|
+
"maximum": 1,
|
|
63
|
+
"description": "drop findings below this confidence (default 0 = report everything, ranked). Orphan confidence is evidence-derived and spans 0.30-0.70; anti-pattern confidence spans 0.60-0.90; framework findings are a fixed 0.6"
|
|
64
|
+
},
|
|
65
|
+
"history": {
|
|
66
|
+
"type": "boolean",
|
|
67
|
+
"default": false,
|
|
68
|
+
"description": "return persisted pattern history (runs bounded by limit; the findings window and its total are declared in the answer)"
|
|
69
|
+
},
|
|
70
|
+
"recordRun": {
|
|
71
|
+
"type": "boolean",
|
|
72
|
+
"default": false,
|
|
73
|
+
"description": "persist this scan as an analysis run (persists the whole census, not the displayed page; works in both scopes; capped at 50,000 findings with the cap disclosed)"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Returns
|
|
80
|
+
|
|
81
|
+
- A bounded page of findings (default 20, maximum 500): rule/type, file:line, symbol for orphan rules, confidence, and a per-finding [stale] marker when the finding's file changed after indexing
|
|
82
|
+
- A census line naming the full finding count and the per-rule breakdown, so the page never reads as the population
|
|
83
|
+
- scope=orphaned: suppression accounting (every candidate the scan discarded, by reason), refused-usage counts (selfLoop/inferred/lowConfidence), and import-resolution counts
|
|
84
|
+
- provenance line: evidence class, engine, symbols/files scanned, limitations count
|
|
85
|
+
- Explicit JSON when history=true: runs bounded by limit, a findings window (200) with findingsTotal/findingsReturned/findingsTruncated declared
|
|
86
|
+
|
|
87
|
+
## Examples
|
|
88
|
+
|
|
89
|
+
`{"scope":"orphaned"}`
|
|
90
|
+
|
|
91
|
+
`{"confidenceThreshold":0.6}`
|
|
92
|
+
|
|
93
|
+
`{"recordRun":true}`
|
|
94
|
+
|
|
95
|
+
## Errors
|
|
96
|
+
|
|
97
|
+
- scope must be one of: orphaned, all
|
|
98
|
+
- confidenceThreshold must be between 0 and 1
|
|
99
|
+
- limit must be a whole number >= 0; above 500 it is refused by name (the census line reports the full count)
|
|
100
|
+
- unknown or irrelevant options are refused and the accepted options are named
|
|
101
|
+
- No index found for <project>: run: bb index <project> — an unindexed project is a named refusal, never a clean zero
|
|
102
|
+
|
|
103
|
+
## Limitations
|
|
104
|
+
|
|
105
|
+
- A finding is not a deletion instruction. The tool reports what the index does and does not record; where the index is silent, the finding says so on its face rather than presenting absence of evidence as evidence of absence.
|
|
106
|
+
- The text answer does not include the engine's per-finding evidence array, limitations array or remediation text. Those travel on the engine report (PatternFinding) that the text is rendered from; the answer surface carries the aggregate disclosures listed under Returns.
|
|
107
|
+
- Confidence is derived from evidence classes, not assigned per rule. Orphans span 0.30-0.70 (0.30-0.55 for file findings); anti-patterns span 0.60-0.90. Name-unique orphan candidates measured a 0.0% false-positive rate against a source-text oracle; ambiguous names measured 14.4%; per-corpus rates are a lower bound because the oracle cannot see reflection or template indirection.
|
|
108
|
+
- Framework findings carry a FIXED confidence of 0.6 — that is the whole population of that rule, so a threshold above 0.6 removes every framework finding at once rather than discriminating among them.
|
|
109
|
+
- A relationship counts as usage evidence only when it is not a self-loop, its published evidenceClass is not "inferred", and its confidence is at least 0.7. Refused rows are counted in the orphaned answer's [usage-evidence] line and itemised on the findings they would have cleared.
|
|
110
|
+
- A finding whose symbol had no recorded incoming reference while its file did carries a coverage-gap indicator: that is the signature of an analyzer that reached the file and not the declaration, and such a finding may be a coverage gap rather than dead code.
|
|
111
|
+
- Dynamic dispatch, reflection and string-keyed lookups are invisible to the index; the engine never fabricates a resolved edge for them, so a symbol reached only that way is reported with the limitation stated on the finding.
|
|
112
|
+
- Lifecycle methods can look unreferenced because a framework invokes them by convention rather than by a recorded call: Ruby "initialize", constructors in Java/Kotlin/C#/Python, and similar framework entry points are known false-positive classes. Treat them as entry points when reviewing a report.
|
|
113
|
+
- Test files are excluded from candidates but not from evidence: a production symbol called only from a test is not reported, and a production file imported only by a test is not reported as orphaned. The engine option includeTests (true means "also report test symbols") is an engine API option, not a bb_patterns parameter.
|
|
114
|
+
- Framework and anti-pattern detection is heuristic and confidence-qualified; non-code languages (JSON, YAML, Markdown, ...) contribute no symbol candidates and no anti-pattern findings, though they are still indexed and checked as whole files.
|
|
115
|
+
|
|
116
|
+
## Performance
|
|
117
|
+
|
|
118
|
+
Warm in-process measurements (one excluded warm-up, five runs, wall clock and process CPU recorded): T0 (5 files / 13 symbols) p50 18.6 ms default-all and 11.2 ms orphaned; T1 (97 files / 3,512 symbols) p50 632 ms default-all and 773 ms orphaned at 404-607 ms process CPU. T2 (6,452 files / 310,423 symbols / 820,040 relationships): the common campaign baseline (validation/release/T2-BASELINE.json, in-process, shared reference index) is p50 3,504 / p95 3,506 ms — inside the 5,000 ms budget; this tool's warm confirmation on the same index measured p50 4,535 ms / p95 5,385 ms at load 4-8, with db+WAL unchanged by every call. The migration that builds the extended covering index and brain_symbol_type_cover_idx costs 28.8 s once per database. limit bounds the displayed page only; the census in the header is the full candidate count. Full data: validation/tools/bb_patterns/LATENCY.json.
|
|
119
|
+
|
|
120
|
+
## Safety
|
|
121
|
+
|
|
122
|
+
The read path is byte-read-only: db and WAL are unchanged by a call (the -shm read marks may move). A read never creates an index or a schema. recordRun is the one write and it is opt-in: it persists analysis-history records (never source), records the whole census up to a declared 50,000-finding cap rather than the displayed page, and reports the recorded count and any cap on the answer.
|
|
123
|
+
|
|
124
|
+
## Evidence Semantics
|
|
125
|
+
|
|
126
|
+
The wire answer is deliberately explicit about its own coverage: census and per-rule counts, suppression accounting by reason (orphaned scope), refused usage rows by reason and import-resolution counts (orphaned scope), provenance (evidence class, engine, symbols/files scanned), and per-finding staleness markers with a manual-repair footer. The engine report beneath it additionally carries a per-finding evidence array, limitations array and remediation text; those are engine-report fields, available through the library API rather than the MCP text surface.
|
|
127
|
+
|
|
128
|
+
## Relationship to other tools
|
|
129
|
+
|
|
130
|
+
For security-specific taint findings use `bb_security`; this tool covers orphans, framework patterns, and anti-patterns.
|
|
131
|
+
|
|
132
|
+
## Deep guides
|
|
133
|
+
|
|
134
|
+
- [Patterns: dead code, orphans, frameworks and anti-patterns](../BB_PATTERNS.md)
|
|
135
|
+
|
|
136
|
+
## Staleness
|
|
137
|
+
|
|
138
|
+
Freshness applies to the tool's read output (no registered per-mode split). Staleness surfaces as: per-finding `[stale]` markers + counts footer naming the remediation; silent when all fresh. This tool does NOT auto-refresh: the per-finding flags DESCRIBE the index as it stands, nothing is reindexed to make them stale or fresh, and there is no `refresh` option to opt out with. When findings name stale or missing files, repair them with the manual interface: run: `bb index --changed` (or the `bb_index` tool with the project path — incremental, changed files only). Nothing is stale → silence (no remediation text). Detection uses a mtime+size fast path with a content-hash fallback: an edit that leaves both size and mtime unchanged is reported fresh without hashing (same trade-off as git's index stat-cache; accepted, documented in `src/brain/freshness.ts`).
|
|
139
|
+
|
|
140
|
+
This page is generated from the executable registry and curated documentation. Run `npm run docs:generate` to update it, or `npx tsx script/verify-tool-docs.ts --only <tool> --write` for a single page.
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Author: Muhammad Ishaq Khan
|
|
3
|
+
|
|
4
|
+
WHAT THIS DOCUMENT IS — the generated reference for bb_search: contract, input schema, returns, examples, errors, limitations, performance, safety and evidence semantics.
|
|
5
|
+
WHO IT IS FOR — callers of bb_search through any MCP host, the CLI (`bb tool bb_search`), or a library.
|
|
6
|
+
EDIT TOGETHER WHEN THIS CHANGES — src/mcp/tools/bb_search/descriptor.ts, src/mcp/tools/bb_search/handler.ts, script/tool-docs/curation/bb_search.ts; regenerate with `npx tsx script/verify-tool-docs.ts --only bb_search --write`.
|
|
7
|
+
-->
|
|
8
|
+
# `bb_search`
|
|
9
|
+
|
|
10
|
+
Unified indexed retrieval for symbol lists, content, exact symbol source, or files. This is retrieval, not natural-language explanation or code analysis. `symbols` (default) searches indexed symbol NAMES with exact, prefix and substring phases, optional case folding (default: case-insensitive over every Unicode case pair), exact-name restriction, regex name matching (the query is then a JavaScript RegExp source, validated and bounded), language/symbolKind filters (case-insensitive against the indexed vocabulary), snippets and paging; it answers as text lines plus a final machine-readable match-set line (`[match-set] searchMode=symbols totalMatches=… returned=… truncated=… staleCount=…`) so a short page is never read as a complete one. `content` searches the indexed symbol corpus — name, qualified name, docstring and the stored bounded symbol body — case-insensitively, and answers as JSON declaring the match set (`total`, `returned`, `truncated`, `truncationReason`), HOW it matched (`matchMode` phrase when the query appeared verbatim, terms when nothing matched verbatim and the query's content words were matched instead, with `termMatch` naming which words carried the best hit), `bodyCoverage` ({ withBody, symbols, ratio }) so 'nothing matched' is distinguishable from 'nothing could match', and a freshness block. `symbol` returns the exact indexed symbol record(s) with byte bounds, language and per-match freshness, declaring `found` and `totalMatches` (the complete match set; this mode has no paging). `file` returns current source for one indexed project-relative file, bounded to 100,000 characters with `contentLength`/`truncated` and a file-scoped freshness block; it never auto-refreshes. `symbol`, `content` and `symbols` modes auto-refresh stale files they touch within a bounded budget and declare the decision in an `autoRefresh` field; `refresh:false` opts out. Stale rows carry `stale:true` and the freshness block's remediation names the manual reindex command (file scope names that exact file). `limit` is a page size and a work budget: 0 returns no rows, values above 2000 are refused rather than clamped, and `limit`/`offset` are accepted only by the modes that page (`symbols`, `content`). `language`/`symbolKind` values the index does not contain are errors naming the indexed vocabulary; options a mode cannot honour are refused naming that mode's accepted set; an invalid regex is a named error; a candidate cap, projection cap or time budget is reported as `truncated` with `truncationReason` instead of a complete-looking page.
|
|
11
|
+
|
|
12
|
+
## Contract
|
|
13
|
+
|
|
14
|
+
- Category: `search`
|
|
15
|
+
- Mutability: `read`
|
|
16
|
+
- Requires index: `true`
|
|
17
|
+
- Modes: `symbols`, `content`, `symbol`, `file`
|
|
18
|
+
- Planned modes (roadmap, not executable): (none)
|
|
19
|
+
- Defaults: `{"mode":"symbols","limit":15,"includeContent":false,"exact":false,"caseSensitive":false,"regex":false,"offset":0}`
|
|
20
|
+
|
|
21
|
+
## Input Schema
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"type": "object",
|
|
26
|
+
"properties": {
|
|
27
|
+
"mode": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"enum": [
|
|
30
|
+
"symbols",
|
|
31
|
+
"content",
|
|
32
|
+
"symbol",
|
|
33
|
+
"file"
|
|
34
|
+
],
|
|
35
|
+
"description": "retrieval mode (default symbols)"
|
|
36
|
+
},
|
|
37
|
+
"query": {
|
|
38
|
+
"type": "string",
|
|
39
|
+
"description": "symbol/content/regex query, trimmed before use; also accepted as the exact symbol name in symbol mode. Not accepted in file mode"
|
|
40
|
+
},
|
|
41
|
+
"symbolName": {
|
|
42
|
+
"type": "string",
|
|
43
|
+
"description": "exact symbol name for symbol mode; supplying it with a different query is an error"
|
|
44
|
+
},
|
|
45
|
+
"filePath": {
|
|
46
|
+
"type": "string",
|
|
47
|
+
"description": "file target for file mode, or symbol disambiguation in symbol mode. Not accepted in symbols/content modes"
|
|
48
|
+
},
|
|
49
|
+
"limit": {
|
|
50
|
+
"type": "number",
|
|
51
|
+
"description": "max results (default 15; 0 returns no rows; above 2000 is refused; whole number). symbols/content modes page; symbol mode returns the COMPLETE match set when omitted and pages when given (its `totalMatches` is always the complete set size)"
|
|
52
|
+
},
|
|
53
|
+
"language": {
|
|
54
|
+
"type": "string",
|
|
55
|
+
"description": "filter by language, case-insensitive (e.g. typescript, python, go); a language this project does not index is an error. symbols/content modes only"
|
|
56
|
+
},
|
|
57
|
+
"symbolKind": {
|
|
58
|
+
"type": "string",
|
|
59
|
+
"description": "filter by symbol kind, case-insensitive (function, class, variable, interface, enum, ...); a kind this project does not index is an error. symbols/content modes only"
|
|
60
|
+
},
|
|
61
|
+
"includeContent": {
|
|
62
|
+
"type": "boolean",
|
|
63
|
+
"description": "include a code snippet per result (default false). symbols mode only"
|
|
64
|
+
},
|
|
65
|
+
"exact": {
|
|
66
|
+
"type": "boolean",
|
|
67
|
+
"description": "only exact name matches (default false); obeys caseSensitive. symbols mode only"
|
|
68
|
+
},
|
|
69
|
+
"caseSensitive": {
|
|
70
|
+
"type": "boolean",
|
|
71
|
+
"description": "case-sensitive matching (default false); folds every Unicode case pair, not only ASCII. symbols mode only"
|
|
72
|
+
},
|
|
73
|
+
"regex": {
|
|
74
|
+
"type": "boolean",
|
|
75
|
+
"description": "treat query as a regex against symbol names (default false). symbols mode only"
|
|
76
|
+
},
|
|
77
|
+
"offset": {
|
|
78
|
+
"type": "number",
|
|
79
|
+
"description": "pagination offset (default 0). symbols/content modes, and symbol mode when `limit` is given"
|
|
80
|
+
},
|
|
81
|
+
"refresh": {
|
|
82
|
+
"type": "boolean",
|
|
83
|
+
"description": "false opts out of the inline auto-refresh of stale files (default: auto-refresh within budget before answering). Accepted by symbols/content/symbol; file mode never auto-refreshes and does not accept it"
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"required": []
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Returns
|
|
91
|
+
|
|
92
|
+
- `symbols` mode: one text line per match (name [kind] file:line (language), plus a snippet when includeContent is set) and a final machine-readable `[match-set] searchMode=symbols totalMatches=… returned=… truncated=… staleCount=…` line
|
|
93
|
+
- `content` mode: JSON with the match set (`total`, `returned`, `truncated`, optional `truncationReason`), the route (`matchMode` phrase/terms, `termMatch` on the terms route), `bodyCoverage`, page-local `staleCount`/`freshCount`/`pageStaleCount`, and a `freshness` block
|
|
94
|
+
- `symbol` mode: JSON `matches` of exact indexed symbol records (id, fileId, name, symbolType, lineStart, byteStart, byteEnd, language), `found`, `totalMatches`, `returned`/`truncated` when paged, per-match `stale`, and a `freshness` block
|
|
95
|
+
- `file` mode: JSON source envelope (`searchMode`, project-relative `file`, `fileId`, `language`, `content`, `contentLength`, `truncated` at 100,000 characters, `totalMatches: 1`, `stale`) plus a file-scoped `freshness` block
|
|
96
|
+
|
|
97
|
+
## Examples
|
|
98
|
+
|
|
99
|
+
`{"mode":"symbols","query":"handleRequest","limit":5}`
|
|
100
|
+
|
|
101
|
+
`{"mode":"content","query":"serialize cache entry"}`
|
|
102
|
+
|
|
103
|
+
`{"mode":"symbol","symbolName":"handleRequest"}`
|
|
104
|
+
|
|
105
|
+
`{"mode":"file","filePath":"src/app.ts"}`
|
|
106
|
+
|
|
107
|
+
## Errors
|
|
108
|
+
|
|
109
|
+
- Missing or blank mode-specific query, symbolName or filePath
|
|
110
|
+
- Invalid regular expression: a named error carrying the pattern and the engine's reason
|
|
111
|
+
- `exact` combined with `regex` in symbols mode (they ask for different things)
|
|
112
|
+
- `limit` above 2000: refused, never clamped
|
|
113
|
+
- `language`/`symbolKind` value the index does not contain: the message names the indexed vocabulary
|
|
114
|
+
- Option that the chosen mode cannot honour: the message names that mode's accepted set
|
|
115
|
+
- Project has no index: the message names the reindex command
|
|
116
|
+
- File mode: path escapes the project root, path is not a file, or the file is not indexed
|
|
117
|
+
|
|
118
|
+
## Limitations
|
|
119
|
+
|
|
120
|
+
- Content search is lexical over the indexed symbol corpus (name, qualified name, docstring and the stored bounded body). It is not full-text file search and it is not semantic — use bb_ask for semantic discovery.
|
|
121
|
+
- A body-only word is unreachable when the index was built by an analyzer that does not store symbol bodies. `bodyCoverage` reports how much of the corpus carries a searchable body so 'nothing matched' is distinguishable from 'nothing could match'.
|
|
122
|
+
- Regex matching scans at most 20,000 candidate symbol names under a 2,000 ms matching budget. A cut scan is reported as `truncated` with `truncationReason` and is never presented as a complete answer.
|
|
123
|
+
- `symbol` mode returns the complete match set unless `limit` is given; with `limit` it pages over that complete set (`totalMatches` always names the whole set).
|
|
124
|
+
- Results reflect the index and may be stale. Stale/missing files are flagged per row and in the freshness block, and the remediation names the manual reindex command.
|
|
125
|
+
|
|
126
|
+
## Performance
|
|
127
|
+
|
|
128
|
+
Indexed name lookup (symbols/symbol) is bounded by a candidate cap that scales with the page and answers in milliseconds on small projects and within seconds on a 310,423-symbol index. Content mode runs bounded candidate phases on projects large enough for them and a single ranked corpus pass otherwise; neither is a full-text file scan. Regex scans are hard-bounded by the candidate cap and the matching budget. Measured warm on a 6,452-file / 310,423-symbol index: symbols p95 3.6 s, content p95 3.3 s, symbol p95 29 ms, file p95 38 ms.
|
|
129
|
+
|
|
130
|
+
## Safety
|
|
131
|
+
|
|
132
|
+
No source file is ever modified. `symbols`/`content`/`symbol` reindex stale files they touch within a bounded budget unless BB_NO_AUTO_REFRESH=1 or refresh=false (declared in `autoRefresh`); `file` never auto-refreshes. A content read does not persist schema in the index database: the durable search index is built by maintenance, and the ranking table a query needs is created in the connection's temp schema.
|
|
133
|
+
|
|
134
|
+
## Evidence Semantics
|
|
135
|
+
|
|
136
|
+
Paths, line ranges, symbol kinds, byte bounds and snippets are indexed evidence; per-row `stale` flags plus the freshness block qualify it. In content mode `matchMode`/`termMatch` say whether a hit is a verbatim phrase or a keyword coincidence, and `bodyCoverage` says how much of the corpus could match at all.
|
|
137
|
+
|
|
138
|
+
## Relationship to other tools
|
|
139
|
+
|
|
140
|
+
For lexical/exact retrieval use this tool. For natural-language questions over the codebase use `bb_ask` (semantic, cited answers).
|
|
141
|
+
|
|
142
|
+
## Deep guides
|
|
143
|
+
|
|
144
|
+
- [Search semantics and modes](../BB_SEARCH.md)
|
|
145
|
+
|
|
146
|
+
## Staleness
|
|
147
|
+
|
|
148
|
+
Freshness modes (registered as `freshnessModes`): `symbol`, `content`, `file`. Staleness surfaces as: per-row `stale` flags + `freshness` block (`{ fresh, stale, missing, staleRatio, mode, remediation }`). When something is stale/missing, the remediation names the registered reindex interfaces: project scope → `reads auto-refresh stale files within budget when enabled — disable with BB_NO_AUTO_REFRESH=1 or refresh=false; manual repair: run: bb index --changed (or the bb_index tool with the project path — incremental, changed files only)`; file scope → `reads auto-refresh this file within budget when enabled — disable with BB_NO_AUTO_REFRESH=1 or refresh=false; manual repair: run: bb index "<file>" (or the bb_index tool with that file path)`. Nothing is stale → silence (no remediation text). Detection uses a mtime+size fast path with a content-hash fallback: an edit that leaves both size and mtime unchanged is reported fresh without hashing (same trade-off as git's index stat-cache; accepted, documented in `src/brain/freshness.ts`).
|
|
149
|
+
|
|
150
|
+
This page is generated from the executable registry and curated documentation. Run `npm run docs:generate` to update it, or `npx tsx script/verify-tool-docs.ts --only <tool> --write` for a single page.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Author: Muhammad Ishaq Khan
|
|
3
|
+
|
|
4
|
+
WHAT THIS DOCUMENT IS — the generated reference for bb_security: contract, input schema, returns, examples, errors, limitations, performance, safety and evidence semantics.
|
|
5
|
+
WHO IT IS FOR — callers of bb_security through any MCP host, the CLI (`bb tool bb_security`), or a library.
|
|
6
|
+
EDIT TOGETHER WHEN THIS CHANGES — src/mcp/tools/bb_security/descriptor.ts, src/mcp/tools/bb_security/handler.ts, script/tool-docs/curation/bb_security.ts; regenerate with `npx tsx script/verify-tool-docs.ts --only bb_security --write`.
|
|
7
|
+
-->
|
|
8
|
+
# `bb_security`
|
|
9
|
+
|
|
10
|
+
Taint-flow security scan over the indexed source-to-sink flows: SQL injection, XSS, command injection, path traversal, insecure deserialization, SSRF, open redirect and code execution. Flows whose endpoints both resolve to indexed symbols are findings; one-sided flows are reported separately as unvalidated observations, never as confirmed exploits. Reads are read-only against the index; an unindexed project is refused by name. Findings whose underlying file changed after indexing carry a staleness marker.
|
|
11
|
+
|
|
12
|
+
## Contract
|
|
13
|
+
|
|
14
|
+
- Category: `analysis`
|
|
15
|
+
- Mutability: `read`
|
|
16
|
+
- Requires index: `true`
|
|
17
|
+
- Modes: `findings`
|
|
18
|
+
- Planned modes (roadmap, not executable): `flow`, `summary`, `hotspots`
|
|
19
|
+
- Defaults: `{"history":false,"recordRun":false,"limit":20}`
|
|
20
|
+
|
|
21
|
+
## Input Schema
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"type": "object",
|
|
26
|
+
"properties": {
|
|
27
|
+
"history": {
|
|
28
|
+
"type": "boolean",
|
|
29
|
+
"description": "return persisted security history"
|
|
30
|
+
},
|
|
31
|
+
"recordRun": {
|
|
32
|
+
"type": "boolean",
|
|
33
|
+
"description": "persist this scan as an analysis run"
|
|
34
|
+
},
|
|
35
|
+
"limit": {
|
|
36
|
+
"type": "number",
|
|
37
|
+
"description": "history run limit (default 20)"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Returns
|
|
44
|
+
|
|
45
|
+
- A findings answer: one line per finding with severity, label, symbol, resolved `file:line`, source and sink type, and `[mitigated]` / `[stale]` flags when they apply — at most 20 findings are rendered per answer
|
|
46
|
+
- A `[scan: …]` census line stating how many taint flows were indexed, how many findings they deduplicated into, how many are shown, how many are beyond the scan cap, and — when the cap bites — the explicit `CAPPED at <cap>` sentence naming how many findings were not examined
|
|
47
|
+
- One-sided flows listed separately as unvalidated observations, each with its real severity, its location and the reason it is unvalidated (at most 5 rendered; the census names the total)
|
|
48
|
+
- A staleness footer only when a finding's file changed after indexing: `N stale, M missing of K finding file(s)` plus the manual repair command; silence when everything is fresh
|
|
49
|
+
- A history answer: a JSON page with the persisted runs (bounded by `limit`), the persisted findings (capped at 200 with `findingsTotal`/`findingsShown`/`findingsTruncated`), the finding-state summary, and a `census` object. Persisted findings carry the engine's evidence, calibrated confidence and per-finding limitations; unvalidated observations are never persisted
|
|
50
|
+
|
|
51
|
+
## Examples
|
|
52
|
+
|
|
53
|
+
`{}`
|
|
54
|
+
|
|
55
|
+
`{"recordRun":true}`
|
|
56
|
+
|
|
57
|
+
`{"history":true}`
|
|
58
|
+
|
|
59
|
+
## Errors
|
|
60
|
+
|
|
61
|
+
- Unavailable index — every door (MCP, CLI, library) refuses by name; a read never creates an index
|
|
62
|
+
- Invalid history limit (non-integer, or negative)
|
|
63
|
+
- Unknown option (rejected with the accepted set named)
|
|
64
|
+
- `limit` without `history: true` (refused: it would be accepted and then ignored)
|
|
65
|
+
- `history` together with `recordRun` (refused: they are different answers; pass one)
|
|
66
|
+
|
|
67
|
+
## Limitations
|
|
68
|
+
|
|
69
|
+
- Static taint analysis can produce false positives and false negatives
|
|
70
|
+
- It is not runtime testing or a penetration test
|
|
71
|
+
- `confirmed` means both flow endpoints are indexed symbols — it does **not** prove the values are connected. The indexer pairs every taint source with every taint sink in a symbol body, so two tokens in one function produce a confirmed flow whether or not one reaches the other
|
|
72
|
+
- **Not detected:** hardcoded secrets (no such finding type is emitted; that rule belongs to `bb_patterns`), genuine cross-*language* taint (the `crossLanguage` flag means the flow was stitched across symbols, not that languages differ), standalone weak-crypto use (emitted as a sink with no co-located source, so it remains an observation)
|
|
73
|
+
- Severity is normalized into exactly `critical|high|medium|low|unknown`; an unrecognised stored value becomes `unknown` rather than vanishing from the counts. Persisted history stores the normalized grade of a confirmed/mitigated flow, so an ungradeable resolved flow is recorded as `unknown`
|
|
74
|
+
- A parameterized or escaped sink may still be reported: the indexer matcher is token-based and does not track sanitizers, so validate a critical finding against the actual data flow before acting on it
|
|
75
|
+
|
|
76
|
+
## Performance
|
|
77
|
+
|
|
78
|
+
A findings answer is bounded by the engine's scan cap (500 flows) and renders at most 20 findings plus 5 observations; the census line states when the cap dropped findings. `recordRun` re-scans with a census-sized cap (50,000) so the persisted snapshot is the analysed set rather than the display window, and the same CAPPED sentence appears if even that cap bites. A history answer is bounded by `limit` on runs and by a 200-finding page with the true total declared. Reads open the index read-only and never reindex a file.
|
|
79
|
+
|
|
80
|
+
## Safety
|
|
81
|
+
|
|
82
|
+
Reads are read-only: the index is opened with the driver's read-only mode, so a read runs no migrations and moves no WAL. `recordRun` is the one write — it stores analysis-history rows — and, because it opens the database for writing, it may also run the additive open-path migrations every write path runs. No source file is ever modified.
|
|
83
|
+
|
|
84
|
+
## Evidence Semantics
|
|
85
|
+
|
|
86
|
+
A finding is supported by indexed source/sink locations and relationship paths; severity does not imply exploitability. The text answer renders the finding's location, source and sink type; the calibrated confidence (0.7 confirmed / 0.4 observation / 0.3 mitigated) and the taint-flow evidence are carried in the history JSON, which is the persisted evidence. Unvalidated observations are never persisted to history.
|
|
87
|
+
|
|
88
|
+
## Relationship to other tools
|
|
89
|
+
|
|
90
|
+
For general code-quality patterns use `bb_patterns`; this tool focuses on taint flows and security findings.
|
|
91
|
+
|
|
92
|
+
## Deep guides
|
|
93
|
+
|
|
94
|
+
- [Security: taint flows, tiers, and what is not detected](../BB_SECURITY.md)
|
|
95
|
+
|
|
96
|
+
## Staleness
|
|
97
|
+
|
|
98
|
+
Freshness applies to the tool's read output (no registered per-mode split). Staleness surfaces as: per-finding `[stale]` markers + counts footer naming the remediation; silent when all fresh. This tool does not auto-refresh and has no `refresh` option: a touched finding file is marked `[stale]` and the footer names the MANUAL repair — run: `bb index --changed` (or the `bb_index` tool with the project path — incremental, changed files only). Nothing is stale → silence (no remediation text). Detection uses a mtime+size fast path with a content-hash fallback: an edit that leaves both size and mtime unchanged is reported fresh without hashing (same trade-off as git's index stat-cache; accepted, documented in `src/brain/freshness.ts`).
|
|
99
|
+
|
|
100
|
+
This page is generated from the executable registry and curated documentation. Run `npm run docs:generate` to update it, or `npx tsx script/verify-tool-docs.ts --only <tool> --write` for a single page.
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Author: Muhammad Ishaq Khan
|
|
3
|
+
|
|
4
|
+
WHAT THIS DOCUMENT IS — the generated reference for bb_visualize: contract, input schema, returns, examples, errors, limitations, performance, safety and evidence semantics.
|
|
5
|
+
WHO IT IS FOR — callers of bb_visualize through any MCP host, the CLI (`bb tool bb_visualize`), or a library.
|
|
6
|
+
EDIT TOGETHER WHEN THIS CHANGES — src/mcp/tools/bb_visualize/descriptor.ts, src/mcp/tools/bb_visualize/handler.ts, script/tool-docs/curation/bb_visualize.ts; regenerate with `npx tsx script/verify-tool-docs.ts --only bb_visualize --write`.
|
|
7
|
+
-->
|
|
8
|
+
# `bb_visualize`
|
|
9
|
+
|
|
10
|
+
Scoped dependency and architecture visualization: one bounded projection over the index's stored symbol and relationship rows, with explicit filters, provenance, truncation, machine-readable JSON, and genuinely self-contained HTML (no network, no fonts, no build step — it renders offline, in an air-gapped editor, anywhere). The answer is an AUDITABLE projection of the index, not a picture: every link carries the stored relationship row it traces to (rowId) and its stored confidence, and every node carries its line, lineEnd and qualifiedName, so the graph is navigable and every edge can be checked against the row that justifies it. Distinct relationship types between the same pair are SEPARATE links, so a pair that is both contains and exports renders as both. Node size follows the index’s own gravity score. In the HTML, edge opacity encodes stored confidence, relationship type sets colour and a structural/behavioural dash, a CROSS-LANGUAGE edge gets its own wide dash and is drawn beneath the local edges so a polyglot project shows where one language hands off to another, and a stale endpoint (file changed since index) is drawn as a hollow ring; links inherit worst-of-endpoints. Nodes are grouped into the NAMED REGION they live in — a directory of the project, a directory with fewer than three matching symbols folded into its parent — each region placed at its own anchor inside a rounded pod and switchable from the sidebar like any other class, At overview zoom an edge BETWEEN two regions is drawn as one REGION LINK per region pair — dotted, because it is a summary and not a stored row; its width and alpha come from how many stored edges it stands for — while an edge INSIDE one region is always drawn as itself, and the individual cross-region edges return past ~1.15x zoom or when a link is opened (double-click frames both of its regions). Edges drawn individually are capped at a zoom-dependent count with the readout naming the cap, because an uncapped aggregate is a smear rather than a map; the frame's readout reconciles the picture with the census (how many cross-region edges the links stand for, how many pairs exist, how to open them), the sidebar's live line repeats it, and the links — with their regions, counts, stored rows, commonest relationship and screen geometry — are PUBLISHED on the view's API rather than only painted, because a summary that can only be seen cannot be checked. Moving the pointer across the map never changes the view: hover emphasises the node's own edges, and a CLICK is what focuses, so the map cannot dissolve under the reader's hand. The graph has TWO arrangements and the reader picks: `layout: "regions"` (the default) is the region map described above, and `layout: "force"` drops the directories entirely — one force layout, no region pods and no region links, every stored edge drawn as itself under the same zoom-dependent cap — which is the graph as it looked before the regions existed, and which is the honest shape for a project whose parts do not fall along directory lines. The layout is written onto the document itself (data-bb-layout) and both arrangements are offered as a switch in the generated page's sidebar, so `layout` sets the arrangement the page OPENS with and the reader can move between them without regenerating anything. The picked-item panel is deliberately not a modal: it docks to either side of the frame and collapses to its own heading — which always names what is picked — while KEEPING the selection, because hiding a panel to see the picture must not cost the reader the focus and the zoom they just asked for (its X is the control that clears). The layout runs in frame-sized slices with a progress readout, so the artifact stays interactive and visible at the maximum graph size and in a background tab. Every answer declares its bounds as three DISTINCT numbers — totalNodesAvailable (what the scope and filters actually match), truncation.originalNodes (what reached the projection) and nodes (what was returned) — and the HTML artifact carries the same declaration in its machine-readable payload (`declared`), so a short page can never be mistaken for a whole set in any format. `offset` walks that same order rather than re-reading the first page: the ranking carries a final `s.id` tiebreaker so page k+1 begins exactly where page k ended, and `considered.page` declares which page the answer is, of how many, and where the next one starts (null on the last) — a scope larger than one page can be walked, and an offset past the end is stated as an empty PAGE rather than as an empty project. Whatever the noise filter removes is counted onto excluded with the patterns responsible — always present, including when it is empty, so silence and zero are never confused — and an empty answer is declaredAbsent with a reason rather than an empty result that looks like a real project. `considered` declares what the answer actually READ: the relationship rows connecting the returned nodes (complete for that node set, not a slice of the relationship table), the selection order that chose the nodes, the applied filters, and the symbol-kind and language census of what was returned, plus the annotation overlay and the owner-cascade counts. `considered.overlays` carries the index's OTHER facts about the returned symbols — agent annotations from `bb_annotate`, matched by NAME AND PATH (never by name alone: two symbols can share a name, and a note is about one of them), with the notes themselves, the author class, and a count of notes that name a symbol of this scope at another path and are therefore NOT attached. The layer is declared even when it is empty, so "no agent has annotated these symbols" and "nobody looked" are different replies. Language filters are applied BEFORE the limit, so a rare language receives the same budget as a common one. The DEFAULT text format carries the same declared coverage, selection and exclusion as the JSON one, so the reply a caller gets without asking is the reply that can be audited. Member-level relationships are FOLDED onto the owner class, and every folded edge says so: when a class-like symbol is selected and a relationship is stored on one of its MEMBERS that is not itself in the node set, the row is attributed to the owner and the edge carries ownerCascade with matchedMembers naming the member it came through — so an attributed edge is never presented as one the index stored between the two drawn nodes. The fold is deliberately narrow (one level, class-like owners only, never for contains, an exact edge always preferred to an attributed one) and `considered.ownerCascade` declares whether it ran, how many members it scanned, how many rows it folded and whether a cap truncated it, so "nothing to fold" and "the fold never ran" are distinguishable. This is NOT bb_graph's depth-N traversal: the edge set is the relationships between the selected nodes, plus the folded member rows.
|
|
11
|
+
|
|
12
|
+
## Contract
|
|
13
|
+
|
|
14
|
+
- Category: `analysis`
|
|
15
|
+
- Mutability: `read`
|
|
16
|
+
- Requires index: `true`
|
|
17
|
+
- Modes: `project`, `file`, `module`, `symbol`, `feature`
|
|
18
|
+
- Planned modes (roadmap, not executable): (none)
|
|
19
|
+
- Defaults: `{"scope":"project","maxNodes":200,"maxLinks":5000,"offset":0,"format":"text"}`
|
|
20
|
+
|
|
21
|
+
## Input Schema
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"type": "object",
|
|
26
|
+
"properties": {
|
|
27
|
+
"scope": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"enum": [
|
|
30
|
+
"project",
|
|
31
|
+
"file",
|
|
32
|
+
"module",
|
|
33
|
+
"symbol",
|
|
34
|
+
"feature"
|
|
35
|
+
],
|
|
36
|
+
"description": "graph scope (default project)"
|
|
37
|
+
},
|
|
38
|
+
"target": {
|
|
39
|
+
"type": "string",
|
|
40
|
+
"description": "file, module, symbol, or feature target (`symbol` and `query` are accepted as aliases for `target`)"
|
|
41
|
+
},
|
|
42
|
+
"maxNodes": {
|
|
43
|
+
"type": "number",
|
|
44
|
+
"description": "max nodes (default 200, accepted range 1-2000); 0 and anything above the ceiling are REFUSED with the range named rather than clamped, because a returned page must mean the page that was asked for"
|
|
45
|
+
},
|
|
46
|
+
"maxLinks": {
|
|
47
|
+
"type": "number",
|
|
48
|
+
"description": "max links (default 5000, accepted range 1-20000); 0 and anything above the ceiling are REFUSED with the range named rather than clamped, because a returned page must mean the page that was asked for"
|
|
49
|
+
},
|
|
50
|
+
"offset": {
|
|
51
|
+
"type": "number",
|
|
52
|
+
"description": "how many symbols of the ranking to SKIP before this page starts (default 0; a whole number >= 0, refused rather than normalised). The order is the scope's own ranking with a final `s.id` tiebreaker, so page k+1 begins where page k ended and no symbol is repeated or lost. `considered.page` states the page number, the page count, the total matching the scope, and the next offset (null on the last page). Without this, a scope bigger than `maxNodes` had symbols that could not be asked for at all"
|
|
53
|
+
},
|
|
54
|
+
"relationshipTypes": {
|
|
55
|
+
"type": "array",
|
|
56
|
+
"items": {
|
|
57
|
+
"type": "string"
|
|
58
|
+
},
|
|
59
|
+
"description": "relationship type filter. Matched case-insensitively against the index's OWN stored spellings, and a type the index does not contain is REJECTED with the stored set named (never answered as zero links, which would read like a project with no calls). The applied filter is echoed in considered.relationshipTypesConsidered."
|
|
60
|
+
},
|
|
61
|
+
"symbolKinds": {
|
|
62
|
+
"type": "array",
|
|
63
|
+
"items": {
|
|
64
|
+
"type": "string"
|
|
65
|
+
},
|
|
66
|
+
"description": "symbol kinds to KEEP (class, interface, struct, enum, function, method, property, constant, variable, ...). Omitted = every kind, and on a real project gravity ranks files’ constants and properties first: the reply states the composition it returned in `considered.kindCensus`, so a graph of string constants is visible as one rather than mistaken for the architecture. Matched case-insensitively against the index’s own spellings, and a kind the index does not contain is REJECTED with the stored set named (never answered as zero nodes). The applied filter is echoed in considered.symbolKindsConsidered. The filter also scopes the symbols the owner cascade would add; removed additions are counted on considered.ownerCascade.nodesFiltered."
|
|
67
|
+
},
|
|
68
|
+
"languages": {
|
|
69
|
+
"type": "array",
|
|
70
|
+
"items": {
|
|
71
|
+
"type": "string"
|
|
72
|
+
},
|
|
73
|
+
"description": "language filter. Matched case-insensitively against the index's OWN stored spellings, and an unknown language is REJECTED with the stored set named (never answered as zero nodes). Applied BEFORE the node limit, so a rare language receives the same budget as a common one, and the applied filter is echoed in considered.languagesConsidered."
|
|
74
|
+
},
|
|
75
|
+
"excludePatterns": {
|
|
76
|
+
"type": "array",
|
|
77
|
+
"items": {
|
|
78
|
+
"type": "string"
|
|
79
|
+
},
|
|
80
|
+
"description": "path SEGMENTS treated as build noise and excluded. Matched on whole segments, never as substrings — a substring rule removed `src/util/edit_distance.rs` because `dist` is inside `edit_distance`, and `src/compiler/layout.rs` because `out` is inside `layout`. Omit to use the defaults (node_modules, .git, .next, .turbo, .cache, coverage, dist, build, out, target, vendor, __pycache__)"
|
|
81
|
+
},
|
|
82
|
+
"includeTests": {
|
|
83
|
+
"type": "boolean",
|
|
84
|
+
"description": "include test/spec sources. Default true: they are ordinary source. When false, test/spec/testdata directories and *_test.* / *spec.* files are excluded and counted"
|
|
85
|
+
},
|
|
86
|
+
"view": {
|
|
87
|
+
"type": "string",
|
|
88
|
+
"enum": [
|
|
89
|
+
"graph"
|
|
90
|
+
],
|
|
91
|
+
"default": "graph",
|
|
92
|
+
"description": "The dependency map (nodes are symbols, lines are relationships, sized by stored evidence). Accepts only `graph`; any other value is REFUSED rather than answered as the graph."
|
|
93
|
+
},
|
|
94
|
+
"layout": {
|
|
95
|
+
"type": "string",
|
|
96
|
+
"enum": [
|
|
97
|
+
"regions",
|
|
98
|
+
"force"
|
|
99
|
+
],
|
|
100
|
+
"default": "regions",
|
|
101
|
+
"description": "the GRAPH view's arrangement, and the only option here that shapes the picture without changing the data. `regions` (default) groups every node into the DIRECTORY it lives in, anchors and names each region, and summarises the edges between regions as one dotted region link per pair at the overview. `force` ignores directories entirely: one force layout, no pods and no region links, every stored edge drawn as itself under a zoom-dependent cap the readout names. The generated page carries BOTH as a switch in its sidebar, so this sets the arrangement the page OPENS with; the layout is declared on the document itself (data-bb-layout), so the file draws what it says it is."
|
|
102
|
+
},
|
|
103
|
+
"format": {
|
|
104
|
+
"type": "string",
|
|
105
|
+
"enum": [
|
|
106
|
+
"text",
|
|
107
|
+
"json",
|
|
108
|
+
"html"
|
|
109
|
+
],
|
|
110
|
+
"description": "output format (default text)"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Returns
|
|
117
|
+
|
|
118
|
+
- Nodes and links projected from the index's stored symbol and relationship rows. Every stored relationship type between a pair is kept as a separate link, each link carries the stored `rowId`, `rowIds` and `occurrences` behind it plus its stored confidence, and each node carries its `line`, `lineEnd`, `qualifiedName` and stored gravity, so every edge can be checked against the row that justifies it
|
|
119
|
+
- Three DISTINCT declared counts — `totalNodesAvailable` (what the scope and filters match), `truncation.originalNodes` (what reached the projection) and the returned `nodes` — plus the page cursor (`offset`, `nextOffset`, `considered.page`), so a short page is never mistaken for a whole set and an offset past the end is stated as an empty PAGE rather than an empty project
|
|
120
|
+
- `considered` — what the answer actually READ: the relationship rows connecting the returned nodes (complete for that node set, not a slice of the table), which selection order produced the nodes, the symbol-kind and language census of what was returned, the applied filters, the annotation overlay, and the owner-cascade fold with its caps
|
|
121
|
+
- `excluded` — what the noise filter removed, how many, and which path segment, build suffix or test rule removed it — always present, including when it is empty
|
|
122
|
+
- `declaredAbsent` with an `absenceNote` when the answer is empty, distinguishing a query that matched nothing from a page that walked past the end and from symbols that did not survive the projection
|
|
123
|
+
- A `freshness` envelope (fresh/stale/missing of the graph's files) and per-node `stale` flags, with links inheriting the worst of their endpoints; the read path never refreshes the index and says so
|
|
124
|
+
- Text, JSON, or a genuinely SELF-CONTAINED HTML artifact: one file with no network request, no webfont and no build step, carrying its own force-directed layout and canvas renderer. Both arrangements — `regions` (named directory pods and one dotted region link per region pair at the overview) and `force` (one force layout, every edge drawn as itself) — are in the page and switchable from its sidebar, and the document declares the one it opens with (`data-bb-layout`)
|
|
125
|
+
- The HTML payload carries the declared bounds and freshness under `declared`, so the artifact is auditable on its own rather than only next to a JSON call: totalNodesAvailable, originalNodes, returnedNodes, the limits, the page, the owner-cascade counts and the freshness totals
|
|
126
|
+
- In the HTML the evidence is ENCODED rather than decorated: edge opacity is stored confidence, relationship type sets colour and a structural/behavioural dash, a cross-language edge gets its own wide dash and is drawn beneath the local edges, a stale endpoint is a hollow ring, node size is the index's gravity, and any node or edge can be selected to read its stored facts
|
|
127
|
+
- The DEFAULT text format carries the same declared coverage, selection and exclusion as the JSON one, so the reply a caller gets without asking is the reply that can be audited
|
|
128
|
+
- `view` is `graph` and rides the result as `view`: the dependency map. Any other value is refused rather than answered as the graph
|
|
129
|
+
|
|
130
|
+
## Examples
|
|
131
|
+
|
|
132
|
+
`{"scope":"symbol","target":"handleRequest","format":"json"}`
|
|
133
|
+
|
|
134
|
+
`{"scope":"module","target":"src/api","format":"html"}`
|
|
135
|
+
|
|
136
|
+
## Errors
|
|
137
|
+
|
|
138
|
+
- A scoped call without a non-empty `target` — refused by name for file, module, symbol and feature scopes
|
|
139
|
+
- An unknown scope, view, format, layout or option — refused with the accepted set named, never silently defaulted
|
|
140
|
+
- A filter value the index does not contain (language, relationship type, symbol kind) — refused with the stored vocabulary named, never answered as zero results
|
|
141
|
+
- `maxNodes` outside 1..2000, `maxLinks` outside 1..20000, or an `offset` that is not a whole number >= 0 — refused rather than clamped, so a returned page means the page that was asked for
|
|
142
|
+
- An absent or uninitialised index — a loud error naming the project and the index command
|
|
143
|
+
|
|
144
|
+
## Limitations
|
|
145
|
+
|
|
146
|
+
- The graph is a projection of static indexed relationships; it does not observe runtime calls
|
|
147
|
+
- THE EDGE SET IS COMPLETE for the returned nodes and declared as such: relationships are fetched by joining the selected identities, not by slicing the relationship table. Several stored rows sharing one (source, target, type) are one drawn edge: `occurrences` and `rowIds` keep the evidence, and the readout totals the rows behind the drawn edges
|
|
148
|
+
- THE NODE SET IS A SELECTION, and says so in `considered.nodeSelection`: project and feature scope rank by the index's gravity (the busiest core rather than a sample); file, module and symbol scope use source order. `offset` walks that same total order — every ORDER BY ends with `s.id` — so page k+1 starts where page k ended
|
|
149
|
+
- `symbolKinds` and `languages` scope the whole answer, including the symbols the owner cascade would add. Cascade additions are filtered by the caller's kinds and languages; removed additions are counted on `considered.ownerCascade.nodesFiltered`, and folded rows whose counterpart cannot be drawn are counted on `foldedRowsWithoutDrawableCounterpart` rather than reported as drawn edges
|
|
150
|
+
- THE OWNER FOLD IS NARROW AND BOUNDED. Only class-like owners are folded, only one level, never for `contains`, and an exact edge always beats an attributed one. The scan caps are declared on `considered.ownerCascade.capped`: at most 500 class-like owners, 3,000 member rows and 20,000 rows on members per answer, which is a bounded sample of the member evidence on a very large hub graph rather than a claim of completeness
|
|
151
|
+
- NOISE FILTER (declared, and the caller's to change). Build output and VCS metadata are excluded by default, matched on whole path SEGMENTS; `.d.ts`, `.min.js` and `.map` are excluded by build-artifact rule and declared in `excluded.suffixes`; test and spec sources are ordinary source and are INCLUDED by default. `excludePatterns` and `includeTests` change all of it, and whatever is removed is counted onto `excluded` with the rule that removed it
|
|
152
|
+
- SCOPE TARGETS ARE VALUES, not patterns: `%`, `_` and `\` match themselves, and a directory prefix matches on a segment boundary, so `src/util` never reaches `src/utilities`
|
|
153
|
+
- LANGUAGE FILTERS ARE APPLIED BEFORE THE LIMIT. `relationshipTypes` deliberately filters EDGES rather than nodes: a caller narrowing edges must not change which nodes exist, and the applied filter is echoed in `considered.relationshipTypesConsidered`
|
|
154
|
+
- `feature` scope matches a symbol name or a docstring. The docstring half is thin in practice — 70 of 40,595 symbols carried one on the index measured here — so a feature query is usually a name match
|
|
155
|
+
- PAGE WINDOW: a page is cut from a fetch of `offset + 2 * maxNodes` symbols, so a deep `offset` reads a wider window than a first page. The returned page and its cursor are exact, but paging deep into a very large scope costs more than the first page
|
|
156
|
+
- PERFORMANCE on the reference index (6,452 files / 310,423 symbols / 820,040 relationships): the default text answer measured 372 ms p50 / 496 ms p95 warm, with a 723 ms first call in a fresh process; JSON and HTML at the same budget measured 380/392 ms and 357/373 ms p95; the largest accepted budget (`maxNodes: 2000`, JSON) measured 4.4 s p50 / 5.7 s p95 with a 15.9 MB payload. The HTML artifact for the default 200-node graph is about 0.84 MB. All of it is bounded by the output budget, not by a client timeout
|
|
157
|
+
- The HTML artifact is a single file with no network, no fonts and no build step; the view publishes its own state (`window.__bbView`) so the census, the region links and the layout can be checked rather than inferred from pixels
|
|
158
|
+
- THE DOCUMENT SAVES ITSELF: each artifact re-serialises its own live page through a Blob and an object URL and publishes that as `saveHtml`, because a reader who wants to keep the page has no other way to
|
|
159
|
+
|
|
160
|
+
## Performance
|
|
161
|
+
|
|
162
|
+
The default answer on the reference index measured 372 ms p50 / 496 ms p95 warm (723 ms first call in a fresh process); JSON and HTML at the same budget measured 380/392 ms and 357/373 ms p95. `maxNodes` and `maxLinks` bound the output and the edge fetch; the largest accepted budget (2000 nodes / 20000 links) measured 4.4 s p50 / 5.7 s p95 with a 15.9 MB JSON payload on that index, and is the declared slow case.
|
|
163
|
+
|
|
164
|
+
## Safety
|
|
165
|
+
|
|
166
|
+
Read-only, and byte-read-only: the tool opens the index with the driver's read-only mode, runs no migrations or healers, writes neither the database nor its WAL, and never writes the repositories it visualises. The HTML output contains the same bounded graph as JSON and makes no network request.
|
|
167
|
+
|
|
168
|
+
## Evidence Semantics
|
|
169
|
+
|
|
170
|
+
Nodes and links resolve to canonical indexed entities; links with an endpoint outside the returned node set are not emitted, and the two reasons an edge is absent (the node cut and the maxLinks budget) are counted apart in `provenance`. Folded edges state the member row they came through (`ownerCascade`, `matchedMembers`), and the stored row itself is never modified.
|
|
171
|
+
|
|
172
|
+
## Relationship to other tools
|
|
173
|
+
|
|
174
|
+
For one symbol's depth-bounded callers and callees with per-edge evidence tiers, use `bb_graph`; `bb_visualize` projects a whole scope — a project, file, module, symbol or feature — into one bounded graph and renders it as text, JSON or a self-contained HTML map.
|
|
175
|
+
|
|
176
|
+
## Deep guides
|
|
177
|
+
|
|
178
|
+
- [Bounded dependency maps and their declared bounds](../BB_VISUALIZE.md)
|
|
179
|
+
|
|
180
|
+
## Staleness
|
|
181
|
+
|
|
182
|
+
Freshness applies to the tool's read output (no registered per-mode split). Staleness surfaces as: per-node and per-link `stale` flags (links inherit worst-of-endpoints) + `freshness` envelope (`{ fresh, stale, missing, staleRatio, mode, remediation }`) on JSON; truncation composes with staleness. This tool does NOT auto-refresh: the flags and the envelope DESCRIBE the index as it stands, nothing is reindexed to make them stale or fresh, and there is no `refresh` option to opt out with. Project scope → run: `bb index --changed` (or the `bb_index` tool with the project path — incremental, changed files only). File scope → run: `bb index "<file>"` for the one file named in the answer. Nothing is stale → silence (no remediation text). Detection uses a mtime+size fast path with a content-hash fallback: an edit that leaves both size and mtime unchanged is reported fresh without hashing (same trade-off as git's index stat-cache; accepted, documented in `src/brain/freshness.ts`).
|
|
183
|
+
|
|
184
|
+
This page is generated from the executable registry and curated documentation. Run `npm run docs:generate` to update it, or `npx tsx script/verify-tool-docs.ts --only <tool> --write` for a single page.
|