@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.
- 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-Q5APTJQL.js +17 -0
- package/dist/brain-relationship-enrichment-MYR2AM4F.js +558 -0
- package/dist/brain.sql-EIM4WS4D.js +29 -0
- package/dist/chunk-22V37YTK.js +1758 -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-2WXYNLBA.js +29 -0
- package/dist/chunk-3CTFIJJB.js +17 -0
- package/dist/chunk-3ZTOHHSW.js +2104 -0
- package/dist/chunk-4H22TLOT.js +543 -0
- package/dist/chunk-5BVAH26D.js +340 -0
- package/dist/chunk-62DHLYW6.js +3427 -0
- package/dist/chunk-7AN7U5IZ.js +371 -0
- package/dist/chunk-7DRPNVIN.js +782 -0
- package/dist/chunk-7MBYT777.js +174 -0
- package/dist/chunk-AHDWGM7Q.js +236 -0
- package/dist/chunk-B5GEAAYF.js +818 -0
- package/dist/chunk-BEIZZ73B.js +1479 -0
- package/dist/chunk-BQ3OVQ3P.js +125 -0
- package/dist/chunk-D2Q4Y47A.js +53 -0
- package/dist/chunk-DIYAGQJL.js +34 -0
- package/dist/chunk-DWKXZ6IF.js +336 -0
- package/dist/chunk-DYM4FQEE.js +90 -0
- package/dist/chunk-ENW4BTBA.js +930 -0
- package/dist/chunk-EWMWK7WN.js +75 -0
- package/dist/chunk-EY5ZZUUA.js +626 -0
- package/dist/chunk-GBI7V7KY.js +69 -0
- package/dist/chunk-GEFFO6O2.js +152 -0
- package/dist/chunk-HJEWO5EV.js +247 -0
- package/dist/chunk-HQSPJDHI.js +613 -0
- package/dist/chunk-KAET47ZL.js +125 -0
- package/dist/chunk-KCDECRJY.js +440 -0
- package/dist/chunk-L5TDYKYK.js +76 -0
- package/dist/chunk-MLKGABMK.js +9 -0
- package/dist/chunk-NO3U3FJQ.js +201 -0
- package/dist/chunk-OWISBAOF.js +61 -0
- package/dist/chunk-QKTRECYS.js +1119 -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-RM3PY6TG.js +376 -0
- package/dist/chunk-ROMM6KMC.js +433 -0
- package/dist/chunk-SGGCSHAX.js +12050 -0
- package/dist/chunk-SK6YVHFZ.js +211 -0
- package/dist/chunk-SM7RFQRO.js +214 -0
- package/dist/chunk-UGR4QIGS.js +67 -0
- package/dist/chunk-UQNQZXHY.js +711 -0
- package/dist/chunk-UUNHHX4M.js +13 -0
- package/dist/chunk-VL52PL2T.js +71 -0
- package/dist/chunk-WIG36E67.js +196 -0
- package/dist/chunk-XHK3WWGB.js +7436 -0
- package/dist/chunk-XTQM2IP3.js +2863 -0
- package/dist/chunk-ZE2LG76D.js +1296 -0
- package/dist/chunk-ZETTGPAW.js +6950 -0
- package/dist/cli/index.js +37 -0
- package/dist/config-HZAAYDP3.js +10 -0
- package/dist/content-search-7XIP555Q.js +593 -0
- package/dist/database-76RP44JG.js +9 -0
- package/dist/doctor-ANGETYMN.js +395 -0
- package/dist/edit-engine-CG72LDZD.js +51 -0
- package/dist/engine-BKEOGN7N.js +11 -0
- package/dist/engine-VIW6NSKO.js +18 -0
- package/dist/fingerprint-OBLIMZLP.js +33 -0
- package/dist/framework-intelligence-3LORTPOX.js +860 -0
- package/dist/freshness-3K6VU5OT.js +174 -0
- package/dist/graph-engine-HBSQNPTB.js +21 -0
- package/dist/graph_request-Q6NKB6N2.js +350 -0
- package/dist/impact_request-LYP672WE.js +68 -0
- package/dist/index-space-IUUN5WYV.js +15 -0
- package/dist/index-status-7OVGYSGW.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-FK2XKZXY.js +88 -0
- package/dist/pool-worker.js +1153 -0
- package/dist/project-health-6XPENVAA.js +94 -0
- package/dist/project-index-5SDPHITE.js +57 -0
- package/dist/project-registry-ZJ3DVUGO.js +355 -0
- package/dist/real-bash-analyzer-EJAU5LW5.js +2201 -0
- package/dist/real-c-analyzer-HBD3FNNH.js +5942 -0
- package/dist/real-clean-analyzer-4EEZLPV5.js +3470 -0
- package/dist/real-clojure-analyzer-Q55EBOO2.js +2818 -0
- package/dist/real-cpp-analyzer-IVVOD25R.js +4101 -0
- package/dist/real-csharp-analyzer-ZBNLNJZJ.js +3298 -0
- package/dist/real-css-analyzer-6XRQLUN7.js +15 -0
- package/dist/real-dart-analyzer-OLR72EFW.js +3944 -0
- package/dist/real-elixir-analyzer-MQWGAH2I.js +2192 -0
- package/dist/real-erlang-analyzer-7BVPQEHO.js +1731 -0
- package/dist/real-fsharp-analyzer-C2UPFNOA.js +2390 -0
- package/dist/real-go-analyzer-UKGI43YS.js +4126 -0
- package/dist/real-graphql-analyzer-VE2EEFII.js +1442 -0
- package/dist/real-groovy-analyzer-W26VACFW.js +2285 -0
- package/dist/real-haskell-analyzer-5CVVAJRX.js +2533 -0
- package/dist/real-hcl-analyzer-5ZT4U43N.js +725 -0
- package/dist/real-html-analyzer-JWNX3C6I.js +1759 -0
- package/dist/real-java-analyzer-GU42VBGQ.js +4677 -0
- package/dist/real-javascript-analyzer-QA4QOJ6W.js +14 -0
- package/dist/real-json-analyzer-MPA6PRXL.js +1640 -0
- package/dist/real-julia-analyzer-22CWYQMN.js +2085 -0
- package/dist/real-kotlin-analyzer-QDZJLXXU.js +3956 -0
- package/dist/real-lua-analyzer-G7NHLYKS.js +1957 -0
- package/dist/real-makefile-analyzer-OCY3GT5N.js +920 -0
- package/dist/real-markdown-analyzer-TEJK2JXJ.js +1215 -0
- package/dist/real-matlab-analyzer-Q5SWLN7Z.js +480 -0
- package/dist/real-nim-analyzer-YLXSK563.js +3603 -0
- package/dist/real-objective-c-analyzer-D23ACC2R.js +1518 -0
- package/dist/real-perl-analyzer-WWTRHYDT.js +1865 -0
- package/dist/real-php-analyzer-JNKJHTCL.js +9368 -0
- package/dist/real-powershell-analyzer-XRSNQERV.js +2915 -0
- package/dist/real-protobuf-analyzer-3OKUCZ7T.js +867 -0
- package/dist/real-python-analyzer-VXAFWI72.js +4880 -0
- package/dist/real-r-analyzer-ZGAIDVI4.js +2596 -0
- package/dist/real-ruby-analyzer-X2KTLVBH.js +2429 -0
- package/dist/real-rust-analyzer-OFFHPL2A.js +3359 -0
- package/dist/real-scala-analyzer-TSTW27J6.js +3293 -0
- package/dist/real-scss-analyzer-AVWYPSOQ.js +1515 -0
- package/dist/real-solidity-analyzer-UCI2KWUB.js +2608 -0
- package/dist/real-sql-analyzer-F77ZMQXR.js +3840 -0
- package/dist/real-svelte-analyzer-SF7NRUO5.js +2532 -0
- package/dist/real-swift-analyzer-MN5QT3QN.js +2311 -0
- package/dist/real-toml-analyzer-66L7BDCQ.js +929 -0
- package/dist/real-typescript-analyzer-6KEMVDWQ.js +14 -0
- package/dist/real-vb-analyzer-VICVPOP7.js +3145 -0
- package/dist/real-vba-analyzer-HXLTTHKM.js +466 -0
- package/dist/real-vue-analyzer-QXR56CFV.js +2680 -0
- package/dist/real-xml-analyzer-YL465ZJW.js +2405 -0
- package/dist/real-yaml-analyzer-SUBCBNSI.js +3528 -0
- package/dist/real-zig-analyzer-HIQLZMGY.js +2430 -0
- package/dist/regex-search-NJKHMZNO.js +239 -0
- package/dist/rules-ACHPB7QU.js +152 -0
- package/dist/scoped-path-MJYWJZQX.js +11 -0
- package/dist/setup-show-NT5ZHYNE.js +15 -0
- package/dist/setup-wizard-G5YYR5T6.js +24 -0
- package/dist/symbol-search-GZJIM2J2.js +16 -0
- package/dist/taint-KXUHHPIE.js +202 -0
- package/dist/taint-analyzer-N7YLZU3N.js +163 -0
- package/dist/tool-handlers-OJDC35DI.js +72 -0
- package/dist/tool-registry-BPEJNSZG.js +17 -0
- package/dist/tool-validation-Q57YMMBX.js +32 -0
- package/dist/type-inference-QMT2RMLV.js +13 -0
- package/dist/vector-binary-LMY4QGAN.js +19 -0
- package/dist/version-ABP2TUL2.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,558 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BrainDatabase
|
|
3
|
+
} from "./chunk-QKTRECYS.js";
|
|
4
|
+
import {
|
|
5
|
+
create
|
|
6
|
+
} from "./chunk-BQ3OVQ3P.js";
|
|
7
|
+
import "./chunk-2BSKD7O3.js";
|
|
8
|
+
import {
|
|
9
|
+
isTestFileCandidate
|
|
10
|
+
} from "./chunk-L5TDYKYK.js";
|
|
11
|
+
import "./chunk-ROMM6KMC.js";
|
|
12
|
+
import "./chunk-MLKGABMK.js";
|
|
13
|
+
|
|
14
|
+
// src/brain/brain-relationship-enrichment.ts
|
|
15
|
+
var log = create({ service: "relationship-enrichment" });
|
|
16
|
+
var ENRICHMENT_MAX_ROWS = 2e6;
|
|
17
|
+
var BATCH = 2e4;
|
|
18
|
+
var CRITICALITY_HIGH_MIN_IN_DEGREE = 50;
|
|
19
|
+
var CRITICALITY_MEDIUM_MIN_IN_DEGREE = 10;
|
|
20
|
+
var UNRESOLVED_TARGET = "unresolved";
|
|
21
|
+
function resolveMaxRows(explicit) {
|
|
22
|
+
if (explicit !== void 0 && explicit !== null) {
|
|
23
|
+
const n = Number(explicit);
|
|
24
|
+
if (n === Infinity) return Infinity;
|
|
25
|
+
if (Number.isFinite(n) && n > 0) return Math.trunc(n);
|
|
26
|
+
return ENRICHMENT_MAX_ROWS;
|
|
27
|
+
}
|
|
28
|
+
const raw = process.env.BB_ENRICHMENT_MAX_ROWS;
|
|
29
|
+
if (raw !== void 0 && raw !== "") {
|
|
30
|
+
const n = Number(raw);
|
|
31
|
+
if (n === Infinity) return Infinity;
|
|
32
|
+
if (Number.isFinite(n) && n > 0) return Math.trunc(n);
|
|
33
|
+
}
|
|
34
|
+
return ENRICHMENT_MAX_ROWS;
|
|
35
|
+
}
|
|
36
|
+
async function enrichRelationships(projectId, onProgress, opts = {}) {
|
|
37
|
+
const startTime = Date.now();
|
|
38
|
+
const rawDb = await BrainDatabase.getRawInstance(projectId);
|
|
39
|
+
const now = Date.now();
|
|
40
|
+
const maxRows = resolveMaxRows(opts.maxRows);
|
|
41
|
+
const report = (step, pct) => {
|
|
42
|
+
if (onProgress) onProgress(step, pct);
|
|
43
|
+
};
|
|
44
|
+
report("reading", 0);
|
|
45
|
+
const zero = (pagination2) => ({
|
|
46
|
+
enriched: 0,
|
|
47
|
+
patternsFound: 0,
|
|
48
|
+
durationMs: 0,
|
|
49
|
+
considered: 0,
|
|
50
|
+
unchanged: 0,
|
|
51
|
+
danglingSources: 0,
|
|
52
|
+
unresolvedTargets: 0,
|
|
53
|
+
danglingTargets: 0,
|
|
54
|
+
rowsWithoutParseableMetadata: 0,
|
|
55
|
+
failedPages: 0,
|
|
56
|
+
failedRows: 0,
|
|
57
|
+
firstError: null,
|
|
58
|
+
truncated: false,
|
|
59
|
+
skipped: 0,
|
|
60
|
+
cap: maxRows,
|
|
61
|
+
pagination: pagination2,
|
|
62
|
+
staleInScope: 0
|
|
63
|
+
});
|
|
64
|
+
const countRow = rawDb.prepare(`
|
|
65
|
+
SELECT COUNT(*) as c FROM brain_relationship WHERE project_id = ?
|
|
66
|
+
`).get(projectId);
|
|
67
|
+
const totalRels = countRow?.c ?? 0;
|
|
68
|
+
let rowidAvailable = true;
|
|
69
|
+
try {
|
|
70
|
+
rawDb.prepare(`SELECT rowid FROM brain_relationship LIMIT 1`).get();
|
|
71
|
+
} catch {
|
|
72
|
+
rowidAvailable = false;
|
|
73
|
+
}
|
|
74
|
+
const pagination = rowidAvailable ? "rowid" : "offset";
|
|
75
|
+
if (totalRels === 0) {
|
|
76
|
+
report("done", 100);
|
|
77
|
+
return { ...zero(pagination), durationMs: Date.now() - startTime };
|
|
78
|
+
}
|
|
79
|
+
report("counting", 0);
|
|
80
|
+
const inDegreeMap = /* @__PURE__ */ new Map();
|
|
81
|
+
const inDegreeRows = rawDb.prepare(`
|
|
82
|
+
SELECT target_symbol_id, COUNT(*) as c
|
|
83
|
+
FROM brain_relationship
|
|
84
|
+
WHERE project_id = ? AND target_symbol_id IS NOT NULL AND target_symbol_id != ''
|
|
85
|
+
GROUP BY target_symbol_id
|
|
86
|
+
`).all(projectId);
|
|
87
|
+
for (const r of inDegreeRows) {
|
|
88
|
+
inDegreeMap.set(r.target_symbol_id, r.c);
|
|
89
|
+
}
|
|
90
|
+
report("enriching", 5);
|
|
91
|
+
const scopeIds = opts.sourceSymbolIds;
|
|
92
|
+
const danglingRow = rawDb.prepare(`
|
|
93
|
+
SELECT COUNT(*) as c FROM brain_relationship r
|
|
94
|
+
WHERE r.project_id = ?
|
|
95
|
+
AND NOT EXISTS (SELECT 1 FROM brain_symbol s WHERE s.id = r.source_symbol_id)
|
|
96
|
+
`).get(projectId);
|
|
97
|
+
let danglingSources = danglingRow?.c ?? 0;
|
|
98
|
+
if (danglingSources > 0) {
|
|
99
|
+
log.warn("relationship enrichment: dangling source edges cannot be enriched", {
|
|
100
|
+
projectId: String(projectId).slice(0, 8),
|
|
101
|
+
danglingSources,
|
|
102
|
+
totalRelationships: totalRels
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
let danglingTargets = 0;
|
|
106
|
+
try {
|
|
107
|
+
const row = rawDb.prepare(`
|
|
108
|
+
SELECT COUNT(*) as c FROM brain_relationship r
|
|
109
|
+
WHERE r.project_id = ? AND r.target_symbol_id IS NOT NULL AND r.target_symbol_id != ''
|
|
110
|
+
AND NOT EXISTS (SELECT 1 FROM brain_symbol t WHERE t.id = r.target_symbol_id)
|
|
111
|
+
`).get(projectId);
|
|
112
|
+
danglingTargets = row?.c ?? 0;
|
|
113
|
+
} catch (e) {
|
|
114
|
+
log.warn("relationship enrichment: dangling-target count unavailable", { error: e?.message });
|
|
115
|
+
}
|
|
116
|
+
const updateStmt = rawDb.prepare(`
|
|
117
|
+
UPDATE brain_relationship SET metadata = ? WHERE id = ? AND project_id = ?
|
|
118
|
+
`);
|
|
119
|
+
const ENRICHMENT_OWNED_KEYS = /* @__PURE__ */ new Set([
|
|
120
|
+
"role",
|
|
121
|
+
"pattern",
|
|
122
|
+
"layerFlow",
|
|
123
|
+
"criticality",
|
|
124
|
+
"frequency",
|
|
125
|
+
"isTestCode",
|
|
126
|
+
"isGeneratedCode",
|
|
127
|
+
"isFrameworkContract",
|
|
128
|
+
"isDependencyInjection",
|
|
129
|
+
"inferredAt"
|
|
130
|
+
]);
|
|
131
|
+
let rowsWithoutParseableMetadata = 0;
|
|
132
|
+
let considered = 0;
|
|
133
|
+
let unchanged = 0;
|
|
134
|
+
let unresolvedTargets = 0;
|
|
135
|
+
let enriched = 0;
|
|
136
|
+
let patternsFound = 0;
|
|
137
|
+
let failedPages = 0;
|
|
138
|
+
let failedRows = 0;
|
|
139
|
+
let firstError = null;
|
|
140
|
+
let staleInScope = 0;
|
|
141
|
+
const sameMetadata = (a, b) => {
|
|
142
|
+
const strip = (m) => {
|
|
143
|
+
const out = {};
|
|
144
|
+
for (const k of Object.keys(m)) if (k !== "inferredAt") out[k] = m[k];
|
|
145
|
+
return out;
|
|
146
|
+
};
|
|
147
|
+
const ak = Object.keys(strip(a)).sort();
|
|
148
|
+
const bk = Object.keys(strip(b)).sort();
|
|
149
|
+
if (ak.length !== bk.length) return false;
|
|
150
|
+
for (let i = 0; i < ak.length; i++) {
|
|
151
|
+
if (ak[i] !== bk[i]) return false;
|
|
152
|
+
if (JSON.stringify(strip(a)[ak[i]]) !== JSON.stringify(strip(b)[bk[i]])) return false;
|
|
153
|
+
}
|
|
154
|
+
return true;
|
|
155
|
+
};
|
|
156
|
+
const mergeMetadata = (row, computed) => {
|
|
157
|
+
let existing = {};
|
|
158
|
+
if (typeof row.metadata === "string" && row.metadata.length > 0) {
|
|
159
|
+
try {
|
|
160
|
+
const parsed = JSON.parse(row.metadata);
|
|
161
|
+
if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) existing = parsed;
|
|
162
|
+
else rowsWithoutParseableMetadata++;
|
|
163
|
+
} catch {
|
|
164
|
+
rowsWithoutParseableMetadata++;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
const meta = { ...existing };
|
|
168
|
+
for (const k of Object.keys(meta)) if (ENRICHMENT_OWNED_KEYS.has(k)) delete meta[k];
|
|
169
|
+
meta.layerFlow = computed.layerFlow;
|
|
170
|
+
meta.criticality = computed.criticality;
|
|
171
|
+
meta.frequency = computed.frequency;
|
|
172
|
+
if (computed.isTestCode) meta.isTestCode = true;
|
|
173
|
+
if (computed.isGeneratedCode) meta.isGeneratedCode = true;
|
|
174
|
+
if (computed.isFrameworkContract) meta.isFrameworkContract = true;
|
|
175
|
+
if (computed.isDI) meta.isDependencyInjection = true;
|
|
176
|
+
if (computed.pattern) meta.pattern = computed.pattern;
|
|
177
|
+
if (computed.role) meta.role = computed.role;
|
|
178
|
+
meta.inferredAt = now;
|
|
179
|
+
return { meta, existing };
|
|
180
|
+
};
|
|
181
|
+
const processBatch = (batch) => {
|
|
182
|
+
if (batch.length === 0) return { written: 0, patterns: 0, failed: null };
|
|
183
|
+
let written = 0;
|
|
184
|
+
let patterns = 0;
|
|
185
|
+
let unresolvedHere = 0;
|
|
186
|
+
let failed = null;
|
|
187
|
+
const tx = rawDb.transaction((rows) => {
|
|
188
|
+
for (const row of rows) {
|
|
189
|
+
const sourceFile = row.source_file || "";
|
|
190
|
+
const sourceLanguage = row.source_language || null;
|
|
191
|
+
const isTestCode = sourceLanguage ? isTestFileCandidate(sourceFile, sourceLanguage) : isTestFileCandidate(sourceFile);
|
|
192
|
+
const isGeneratedCode = sourceFile.includes("/generated/") || sourceFile.includes("/build/generated/") || sourceFile.includes(".pb.") || sourceFile.includes(".g.dart") || sourceFile.includes(".g.cs") || sourceFile.includes("/gen/");
|
|
193
|
+
const isFrameworkContract = row.relationship_type === "extends" || row.relationship_type === "overrides" || row.relationship_type === "implements";
|
|
194
|
+
const isDI = row.relationship_type === "instantiates" && (row.target_type === "interface" || row.target_type === "trait" || row.target_type === "protocol" || row.target_type === "abstract");
|
|
195
|
+
const targetResolved = typeof row.target_resolved_id === "string" && row.target_resolved_id.length > 0;
|
|
196
|
+
if (!targetResolved) unresolvedHere++;
|
|
197
|
+
const layerFlow = `${row.source_layer || "core"}\u2192${targetResolved && row.target_layer ? row.target_layer : UNRESOLVED_TARGET}`;
|
|
198
|
+
const inDeg = inDegreeMap.get(row.target_symbol_id) ?? 0;
|
|
199
|
+
const criticality = inDeg >= CRITICALITY_HIGH_MIN_IN_DEGREE ? "high" : inDeg >= CRITICALITY_MEDIUM_MIN_IN_DEGREE ? "medium" : "low";
|
|
200
|
+
const frequency = `one_of_${inDeg}`;
|
|
201
|
+
const pattern = inferPattern({
|
|
202
|
+
relationship_type: row.relationship_type,
|
|
203
|
+
source_name: row.source_name || "",
|
|
204
|
+
source_type: row.source_type || "",
|
|
205
|
+
target_name: row.target_name || "",
|
|
206
|
+
target_type: row.target_type || "",
|
|
207
|
+
source_file: row.source_file || ""
|
|
208
|
+
});
|
|
209
|
+
const role = inferRole(row.relationship_type, row.source_type || "", row.target_type || "", pattern);
|
|
210
|
+
const { meta, existing } = mergeMetadata(row, {
|
|
211
|
+
layerFlow,
|
|
212
|
+
criticality,
|
|
213
|
+
frequency,
|
|
214
|
+
isTestCode,
|
|
215
|
+
isGeneratedCode,
|
|
216
|
+
isFrameworkContract,
|
|
217
|
+
isDI,
|
|
218
|
+
pattern,
|
|
219
|
+
role
|
|
220
|
+
});
|
|
221
|
+
if (sameMetadata(existing, meta)) continue;
|
|
222
|
+
updateStmt.run(JSON.stringify(meta), row.id, projectId);
|
|
223
|
+
written++;
|
|
224
|
+
if (pattern) patterns++;
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
try {
|
|
228
|
+
tx(batch);
|
|
229
|
+
} catch (e) {
|
|
230
|
+
failed = e?.message ? String(e.message) : String(e);
|
|
231
|
+
written = 0;
|
|
232
|
+
patterns = 0;
|
|
233
|
+
unresolvedHere = 0;
|
|
234
|
+
}
|
|
235
|
+
unresolvedTargets += unresolvedHere;
|
|
236
|
+
return { written, patterns, failed };
|
|
237
|
+
};
|
|
238
|
+
let truncated = false;
|
|
239
|
+
const processedSoFar = () => enriched + unchanged + failedRows;
|
|
240
|
+
const absorb = (batch, make) => {
|
|
241
|
+
let outcome = make();
|
|
242
|
+
if (outcome.failed !== null) outcome = make();
|
|
243
|
+
const rowsInPage = batch.length;
|
|
244
|
+
considered += rowsInPage;
|
|
245
|
+
if (outcome.failed === null) {
|
|
246
|
+
enriched += outcome.written;
|
|
247
|
+
patternsFound += outcome.patterns;
|
|
248
|
+
unchanged += rowsInPage - outcome.written;
|
|
249
|
+
return true;
|
|
250
|
+
}
|
|
251
|
+
failedPages++;
|
|
252
|
+
failedRows += rowsInPage;
|
|
253
|
+
if (firstError === null) firstError = outcome.failed;
|
|
254
|
+
log.warn("relationship enrichment: page failed, rows left un-enriched", {
|
|
255
|
+
projectId: String(projectId).slice(0, 8),
|
|
256
|
+
rows: rowsInPage,
|
|
257
|
+
error: outcome.failed
|
|
258
|
+
});
|
|
259
|
+
return false;
|
|
260
|
+
};
|
|
261
|
+
const PROJECTION = `
|
|
262
|
+
r.id, r.rowid AS rowid, r.relationship_type, r.source_symbol_id, r.target_symbol_id, r.metadata,
|
|
263
|
+
s.layer as source_layer, s.symbol_type as source_type, s.name as source_name,
|
|
264
|
+
t.id as target_resolved_id, t.layer as target_layer, t.symbol_type as target_type, t.name as target_name,
|
|
265
|
+
sf.relative_path as source_file, sf.language as source_language`;
|
|
266
|
+
const JOINS = `
|
|
267
|
+
JOIN brain_symbol s ON s.id = r.source_symbol_id AND s.project_id = r.project_id
|
|
268
|
+
LEFT JOIN brain_symbol t ON t.id = r.target_symbol_id AND t.project_id = r.project_id
|
|
269
|
+
LEFT JOIN brain_file sf ON sf.id = s.file_id`;
|
|
270
|
+
if (scopeIds?.length) {
|
|
271
|
+
const CHUNK = 500;
|
|
272
|
+
for (let i = 0; i < scopeIds.length; i += CHUNK) {
|
|
273
|
+
if (maxRows !== Infinity && processedSoFar() >= maxRows) {
|
|
274
|
+
truncated = true;
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
const chunk = scopeIds.slice(i, i + CHUNK);
|
|
278
|
+
const placeholders = chunk.map(() => "?").join(",");
|
|
279
|
+
const batch = rawDb.prepare(`
|
|
280
|
+
SELECT ${PROJECTION}
|
|
281
|
+
FROM brain_relationship r
|
|
282
|
+
${JOINS}
|
|
283
|
+
WHERE r.project_id = ? AND r.source_symbol_id IN (${placeholders})
|
|
284
|
+
`).all(projectId, ...chunk);
|
|
285
|
+
absorb(batch, () => processBatch(batch));
|
|
286
|
+
const pct = Math.min(95, 5 + Math.round(processedSoFar() / Math.max(1, scopeIds.length) * 90));
|
|
287
|
+
report("enriching", pct);
|
|
288
|
+
}
|
|
289
|
+
staleInScope = countStaleInScope(rawDb, projectId, scopeIds);
|
|
290
|
+
} else {
|
|
291
|
+
if (pagination === "rowid") {
|
|
292
|
+
let cursor = 0;
|
|
293
|
+
for (; ; ) {
|
|
294
|
+
const remaining = maxRows === Infinity ? BATCH : Math.min(BATCH, maxRows - processedSoFar());
|
|
295
|
+
if (remaining <= 0) {
|
|
296
|
+
truncated = true;
|
|
297
|
+
break;
|
|
298
|
+
}
|
|
299
|
+
const batch = rawDb.prepare(`
|
|
300
|
+
SELECT ${PROJECTION}
|
|
301
|
+
FROM brain_relationship r
|
|
302
|
+
${JOINS}
|
|
303
|
+
WHERE r.project_id = ? AND r.rowid > ?
|
|
304
|
+
ORDER BY r.rowid
|
|
305
|
+
LIMIT ${remaining}
|
|
306
|
+
`).all(projectId, cursor);
|
|
307
|
+
if (batch.length === 0) break;
|
|
308
|
+
const pageLast = batch[batch.length - 1].rowid;
|
|
309
|
+
absorb(batch, () => processBatch(batch));
|
|
310
|
+
cursor = pageLast;
|
|
311
|
+
const pct = Math.min(95, 5 + Math.round(processedSoFar() / Math.max(1, totalRels) * 90));
|
|
312
|
+
report("enriching", pct);
|
|
313
|
+
}
|
|
314
|
+
} else {
|
|
315
|
+
let offset = 0;
|
|
316
|
+
for (; ; ) {
|
|
317
|
+
const remaining = maxRows === Infinity ? BATCH : Math.min(BATCH, maxRows - processedSoFar());
|
|
318
|
+
if (remaining <= 0) {
|
|
319
|
+
truncated = true;
|
|
320
|
+
break;
|
|
321
|
+
}
|
|
322
|
+
const batch = rawDb.prepare(`
|
|
323
|
+
SELECT ${PROJECTION}
|
|
324
|
+
FROM brain_relationship r
|
|
325
|
+
${JOINS}
|
|
326
|
+
WHERE r.project_id = ?
|
|
327
|
+
LIMIT ${remaining} OFFSET ${offset}
|
|
328
|
+
`).all(projectId);
|
|
329
|
+
if (batch.length === 0) break;
|
|
330
|
+
absorb(batch, () => processBatch(batch));
|
|
331
|
+
offset += batch.length;
|
|
332
|
+
const pct = Math.min(95, 5 + Math.round(offset / Math.max(1, totalRels) * 90));
|
|
333
|
+
report("enriching", pct);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
const processed = processedSoFar();
|
|
338
|
+
const result = {
|
|
339
|
+
enriched,
|
|
340
|
+
patternsFound,
|
|
341
|
+
durationMs: Date.now() - startTime,
|
|
342
|
+
considered,
|
|
343
|
+
unchanged,
|
|
344
|
+
danglingSources,
|
|
345
|
+
unresolvedTargets,
|
|
346
|
+
danglingTargets,
|
|
347
|
+
rowsWithoutParseableMetadata,
|
|
348
|
+
failedPages,
|
|
349
|
+
failedRows,
|
|
350
|
+
firstError,
|
|
351
|
+
truncated,
|
|
352
|
+
// A floor, not an exact count: the source-side join drops `danglingSources`
|
|
353
|
+
// rows that this pass can never enrich, so the true unreached count is at
|
|
354
|
+
// most this number and is reported as an at-least.
|
|
355
|
+
skipped: truncated ? Math.max(0, totalRels - processed - danglingSources) : 0,
|
|
356
|
+
cap: maxRows,
|
|
357
|
+
pagination,
|
|
358
|
+
staleInScope
|
|
359
|
+
};
|
|
360
|
+
if (truncated) {
|
|
361
|
+
log.warn("relationship enrichment: work cap reached, pass is PARTIAL", {
|
|
362
|
+
projectId: String(projectId).slice(0, 8),
|
|
363
|
+
cap: maxRows,
|
|
364
|
+
processed,
|
|
365
|
+
totalRelationships: totalRels,
|
|
366
|
+
skipped: result.skipped
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
if (failedPages > 0) {
|
|
370
|
+
log.warn("relationship enrichment: PARTIAL \u2014 some pages failed and were left un-enriched", {
|
|
371
|
+
projectId: String(projectId).slice(0, 8),
|
|
372
|
+
failedPages,
|
|
373
|
+
failedRows,
|
|
374
|
+
firstError
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
if (rowsWithoutParseableMetadata > 0) {
|
|
378
|
+
log.warn("relationship enrichment: pre-existing metadata was unparseable and was replaced", {
|
|
379
|
+
projectId: String(projectId).slice(0, 8),
|
|
380
|
+
rows: rowsWithoutParseableMetadata
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
if (danglingTargets > 0) {
|
|
384
|
+
log.warn("relationship enrichment: dangling TARGET edges present (target_symbol_id names no symbol)", {
|
|
385
|
+
projectId: String(projectId).slice(0, 8),
|
|
386
|
+
danglingTargets
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
report(truncated ? "capped" : "done", 100);
|
|
390
|
+
return result;
|
|
391
|
+
}
|
|
392
|
+
function countStaleInScope(rawDb, projectId, scopeIds) {
|
|
393
|
+
const CHUNK = 500;
|
|
394
|
+
let total = 0;
|
|
395
|
+
for (let i = 0; i < scopeIds.length; i += CHUNK) {
|
|
396
|
+
const chunk = scopeIds.slice(i, i + CHUNK);
|
|
397
|
+
const placeholders = chunk.map(() => "?").join(",");
|
|
398
|
+
try {
|
|
399
|
+
const row = rawDb.prepare(`
|
|
400
|
+
SELECT COUNT(*) as c FROM brain_relationship r
|
|
401
|
+
WHERE r.project_id = ?
|
|
402
|
+
AND r.target_symbol_id IN (${placeholders})
|
|
403
|
+
AND r.metadata IS NOT NULL
|
|
404
|
+
AND json_valid(r.metadata)
|
|
405
|
+
AND json_extract(r.metadata, '$.inferredAt') IS NOT NULL
|
|
406
|
+
AND json_extract(r.metadata, '$.inferredAt') < r.time_updated
|
|
407
|
+
`).get(projectId, ...chunk);
|
|
408
|
+
total += row?.c ?? 0;
|
|
409
|
+
} catch (e) {
|
|
410
|
+
log.warn("relationship enrichment: stale-in-scope count unavailable", { error: e?.message });
|
|
411
|
+
return total;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
return total;
|
|
415
|
+
}
|
|
416
|
+
function inferPattern(row) {
|
|
417
|
+
const rt = row.relationship_type;
|
|
418
|
+
const sn = (row.source_name || "").toLowerCase();
|
|
419
|
+
const tn = (row.target_name || "").toLowerCase();
|
|
420
|
+
const st = (row.source_type || "").toLowerCase();
|
|
421
|
+
const tt = (row.target_type || "").toLowerCase();
|
|
422
|
+
if (rt === "calls" && (tn.includes("factory") || tn.includes("builder") || tn.includes("create") || tn.includes("build") || tn.includes("new"))) {
|
|
423
|
+
return "factory_consumer";
|
|
424
|
+
}
|
|
425
|
+
if (rt === "calls" && /^(on|handle|listen|notify|emit|fire|addListener|removeListener|subscribe|unsubscribe)/i.test(tn)) {
|
|
426
|
+
return "observer";
|
|
427
|
+
}
|
|
428
|
+
if (rt === "calls" && (sn.includes("callback") || sn.includes("handler") || tn.endsWith("callback"))) {
|
|
429
|
+
return "callback";
|
|
430
|
+
}
|
|
431
|
+
if (rt === "calls" && (sn.includes("event") || tn.includes("event"))) {
|
|
432
|
+
return "event_handler";
|
|
433
|
+
}
|
|
434
|
+
if (rt === "implements" && (tt === "interface" || tt === "trait" || tt === "protocol")) {
|
|
435
|
+
return "adapter";
|
|
436
|
+
}
|
|
437
|
+
if ((sn.includes("adapter") || sn.includes("wrapper") || sn.includes("decorator")) && rt === "calls") {
|
|
438
|
+
return "adapter";
|
|
439
|
+
}
|
|
440
|
+
if (rt === "instantiates" && (tt === "interface" || tt === "trait" || tt === "abstract" || tt === "protocol")) {
|
|
441
|
+
return "di_injection";
|
|
442
|
+
}
|
|
443
|
+
if (rt === "overrides") {
|
|
444
|
+
return "override";
|
|
445
|
+
}
|
|
446
|
+
if (rt === "calls" && (sn.includes("delegate") || tn.includes("delegate") || tn.includes("proxy"))) {
|
|
447
|
+
return "delegate";
|
|
448
|
+
}
|
|
449
|
+
return null;
|
|
450
|
+
}
|
|
451
|
+
function inferRole(relationshipType, sourceType, targetType, pattern) {
|
|
452
|
+
const st = (sourceType || "").toLowerCase();
|
|
453
|
+
const tt = (targetType || "").toLowerCase();
|
|
454
|
+
if (relationshipType === "extends") return "inheritor";
|
|
455
|
+
if (relationshipType === "implements") return "implementor";
|
|
456
|
+
if (relationshipType === "overrides") return "inheritor";
|
|
457
|
+
if (relationshipType === "instantiates") {
|
|
458
|
+
if (tt === "interface" || tt === "trait" || tt === "protocol") return "configurator";
|
|
459
|
+
return "producer";
|
|
460
|
+
}
|
|
461
|
+
if (relationshipType === "calls") {
|
|
462
|
+
if (pattern === "observer" || pattern === "callback" || pattern === "event_handler") return "consumer";
|
|
463
|
+
if (pattern === "adapter") return "decorator";
|
|
464
|
+
if (pattern === "di_injection") return "configurator";
|
|
465
|
+
return "consumer";
|
|
466
|
+
}
|
|
467
|
+
if (relationshipType === "uses" || relationshipType === "references" || relationshipType === "imports") {
|
|
468
|
+
return "consumer";
|
|
469
|
+
}
|
|
470
|
+
return void 0;
|
|
471
|
+
}
|
|
472
|
+
function formatEnrichedRelationship(row) {
|
|
473
|
+
let meta = {};
|
|
474
|
+
try {
|
|
475
|
+
meta = row.rel_metadata ? JSON.parse(row.rel_metadata) : row.metadata ? JSON.parse(row.metadata) : {};
|
|
476
|
+
} catch {
|
|
477
|
+
}
|
|
478
|
+
if (meta === null || typeof meta !== "object" || Array.isArray(meta)) meta = {};
|
|
479
|
+
const str = (v) => typeof v === "string" && v.length > 0 ? v : null;
|
|
480
|
+
const bool = (v) => v === true;
|
|
481
|
+
const parts = [];
|
|
482
|
+
const role = str(meta.role);
|
|
483
|
+
const pattern = str(meta.pattern);
|
|
484
|
+
if (role || pattern) {
|
|
485
|
+
const labels = [];
|
|
486
|
+
if (role) labels.push(role);
|
|
487
|
+
if (pattern) labels.push(pattern.replace(/_/g, " "));
|
|
488
|
+
parts.push(`[${labels.join(" \xB7 ")}]`);
|
|
489
|
+
}
|
|
490
|
+
const layerFlow = str(meta.layerFlow);
|
|
491
|
+
if (layerFlow && layerFlow !== "core\u2192core") {
|
|
492
|
+
parts.push(`(${layerFlow})`);
|
|
493
|
+
}
|
|
494
|
+
if (meta.criticality === "high") {
|
|
495
|
+
parts.push(`\u{1F534}`);
|
|
496
|
+
} else if (meta.criticality === "medium") {
|
|
497
|
+
parts.push(`\u{1F7E1}`);
|
|
498
|
+
}
|
|
499
|
+
const frequency = str(meta.frequency);
|
|
500
|
+
if (frequency && frequency !== "one_of_0") {
|
|
501
|
+
parts.push(`\xD7${frequency.replace("one_of_", "")}`);
|
|
502
|
+
}
|
|
503
|
+
const flags = [];
|
|
504
|
+
if (bool(meta.isTestCode)) flags.push("\u{1F9EA}");
|
|
505
|
+
if (bool(meta.isFrameworkContract)) flags.push("\u{1F4DC}");
|
|
506
|
+
if (bool(meta.isGeneratedCode)) flags.push("\u{1F916}");
|
|
507
|
+
if (bool(meta.isDependencyInjection)) flags.push("\u{1F489}");
|
|
508
|
+
if (flags.length > 0) parts.push(flags.join(""));
|
|
509
|
+
return parts.length > 0 ? parts.join(" ") : "";
|
|
510
|
+
}
|
|
511
|
+
function normalizeMaxResults(value) {
|
|
512
|
+
if (value === void 0 || value === null) return 100;
|
|
513
|
+
const n = Math.trunc(Number(value));
|
|
514
|
+
if (!Number.isFinite(n) || n < 0) return 100;
|
|
515
|
+
return n;
|
|
516
|
+
}
|
|
517
|
+
async function getEnrichedRelationships(projectId, options = {}) {
|
|
518
|
+
const rawDb = await BrainDatabase.getRawInstance(projectId);
|
|
519
|
+
const conditions = ["r.project_id = ?"];
|
|
520
|
+
const params = [projectId];
|
|
521
|
+
if (options.sourceSymbolId) {
|
|
522
|
+
conditions.push("r.source_symbol_id = ?");
|
|
523
|
+
params.push(options.sourceSymbolId);
|
|
524
|
+
}
|
|
525
|
+
if (options.targetSymbolId) {
|
|
526
|
+
conditions.push("r.target_symbol_id = ?");
|
|
527
|
+
params.push(options.targetSymbolId);
|
|
528
|
+
}
|
|
529
|
+
if (options.relationshipType) {
|
|
530
|
+
conditions.push("r.relationship_type = ?");
|
|
531
|
+
params.push(options.relationshipType);
|
|
532
|
+
}
|
|
533
|
+
const limit = normalizeMaxResults(options.maxResults);
|
|
534
|
+
const metadataColumn = options.includeEnrichment === false ? "NULL as metadata" : "r.metadata";
|
|
535
|
+
const where = conditions.join(" AND ");
|
|
536
|
+
return rawDb.prepare(`
|
|
537
|
+
SELECT r.id, r.relationship_type, ${metadataColumn},
|
|
538
|
+
s.name as source_name, s.symbol_type as source_type, s.layer as source_layer,
|
|
539
|
+
t.name as target_name, t.symbol_type as target_type, t.layer as target_layer,
|
|
540
|
+
sf.relative_path as source_file, sf.language as source_language,
|
|
541
|
+
tf.relative_path as target_file, tf.language as target_language,
|
|
542
|
+
r.is_cross_file, r.is_cross_language, r.bridge_mechanism
|
|
543
|
+
FROM brain_relationship r
|
|
544
|
+
JOIN brain_symbol s ON s.id = r.source_symbol_id AND s.project_id = r.project_id
|
|
545
|
+
JOIN brain_file sf ON sf.id = s.file_id
|
|
546
|
+
LEFT JOIN brain_symbol t ON t.id = r.target_symbol_id AND t.project_id = r.project_id
|
|
547
|
+
LEFT JOIN brain_file tf ON tf.id = t.file_id
|
|
548
|
+
WHERE ${where}
|
|
549
|
+
ORDER BY s.name, t.name
|
|
550
|
+
LIMIT ${limit}
|
|
551
|
+
`).all(...params);
|
|
552
|
+
}
|
|
553
|
+
export {
|
|
554
|
+
ENRICHMENT_MAX_ROWS,
|
|
555
|
+
enrichRelationships,
|
|
556
|
+
formatEnrichedRelationship,
|
|
557
|
+
getEnrichedRelationships
|
|
558
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BrainAnalysisFindingTable,
|
|
3
|
+
BrainAnalysisOccurrenceTable,
|
|
4
|
+
BrainAnalysisRunTable,
|
|
5
|
+
BrainFileTable,
|
|
6
|
+
BrainImportTable,
|
|
7
|
+
BrainIndexStatusTable,
|
|
8
|
+
BrainProjectHealthTable,
|
|
9
|
+
BrainQueryCacheTable,
|
|
10
|
+
BrainRelationshipTable,
|
|
11
|
+
BrainSemanticEmbeddingTable,
|
|
12
|
+
BrainSymbolTable,
|
|
13
|
+
BrainTaintFlowTable
|
|
14
|
+
} from "./chunk-ROMM6KMC.js";
|
|
15
|
+
import "./chunk-MLKGABMK.js";
|
|
16
|
+
export {
|
|
17
|
+
BrainAnalysisFindingTable,
|
|
18
|
+
BrainAnalysisOccurrenceTable,
|
|
19
|
+
BrainAnalysisRunTable,
|
|
20
|
+
BrainFileTable,
|
|
21
|
+
BrainImportTable,
|
|
22
|
+
BrainIndexStatusTable,
|
|
23
|
+
BrainProjectHealthTable,
|
|
24
|
+
BrainQueryCacheTable,
|
|
25
|
+
BrainRelationshipTable,
|
|
26
|
+
BrainSemanticEmbeddingTable,
|
|
27
|
+
BrainSymbolTable,
|
|
28
|
+
BrainTaintFlowTable
|
|
29
|
+
};
|