@vibgrate/cli 2026.711.2 → 2026.715.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.
@@ -1,5 +1,5 @@
1
- import { hashString, langById, shortId, canonicalize, grammarSetVersion, hashBytes, langForExtension, setGrammarsOverride, parseSource } from './chunk-X5YT263H.js';
2
- import { writeTextFile, pathExists, readJsonFile, computeUpgradeImpact, getChangelogSignals, gitHistoryAvailable, buildVersionTimelines, findPackageTimeline, severityRank, projectTypeToVulnEcosystem, VERSION } from './chunk-NNU2PW2H.js';
1
+ import { hashString, langById, shortId, canonicalize, grammarSetVersion, hashBytes, langForExtension, setGrammarsOverride, parseSource } from './chunk-VFO5UDAT.js';
2
+ import { writeTextFile, pathExists, readJsonFile, loadConfig, computeUpgradeImpact, getChangelogSignals, gitHistoryAvailable, buildVersionTimelines, findPackageTimeline, severityRank, projectTypeToVulnEcosystem, VERSION } from './chunk-C5AVF7PT.js';
3
3
  import * as fs19 from 'fs';
4
4
  import { spawnSync, execFileSync } from 'child_process';
5
5
  import * as path19 from 'path';
@@ -703,6 +703,73 @@ function edgeId(kind, src, dst) {
703
703
  return shortId(canonicalize({ t: "edge", kind, src, dst }));
704
704
  }
705
705
 
706
+ // src/engine/tests.ts
707
+ function isTestFile(rel2) {
708
+ const lower = rel2.toLowerCase();
709
+ const base = rel2.split("/").pop() ?? rel2;
710
+ const lbase = base.toLowerCase();
711
+ if (/(^|\/)(__tests__|__test__)\//.test(lower)) return true;
712
+ if (/(^|\/)(tests?|spec|specs)\//.test(lower)) return true;
713
+ if (/(^|\/)src\/test\//.test(lower)) return true;
714
+ if (/\.(test|spec)\.[cm]?[jt]sx?$/.test(lbase)) return true;
715
+ if (/^test_.*\.py$/.test(lbase) || /_test\.py$/.test(lbase)) return true;
716
+ if (/_test\.go$/.test(lbase)) return true;
717
+ if (/[A-Za-z0-9](Test|Tests|IT)\.java$/.test(base)) return true;
718
+ if (/_spec\.rb$/.test(lbase) || /_test\.rb$/.test(lbase)) return true;
719
+ if (/[A-Za-z0-9](Test|Tests)\.cs$/.test(base)) return true;
720
+ if (/[A-Za-z0-9](Test|Tests)\.swift$/.test(base)) return true;
721
+ return false;
722
+ }
723
+ function applyStaticTestLinkage(nodes, edges) {
724
+ const byId = new Map(nodes.map((n) => [n.id, n]));
725
+ const testFiles = /* @__PURE__ */ new Set();
726
+ for (const n of nodes) if (n.kind === "file" && isTestFile(n.file)) testFiles.add(n.file);
727
+ const fileNodeIdByRel = /* @__PURE__ */ new Map();
728
+ for (const n of nodes) if (n.kind === "file") fileNodeIdByRel.set(n.file, n.id);
729
+ const covered = /* @__PURE__ */ new Set();
730
+ const newEdges = /* @__PURE__ */ new Map();
731
+ for (const e of edges) {
732
+ if (e.kind !== "call") continue;
733
+ const src = byId.get(e.src);
734
+ const dst = byId.get(e.dst);
735
+ if (!src || !dst) continue;
736
+ if (testFiles.has(src.file) && !testFiles.has(dst.file) && dst.kind !== "external") {
737
+ const testFileId = fileNodeIdByRel.get(src.file);
738
+ if (!testFileId) continue;
739
+ const id = edgeId("test", testFileId, dst.id);
740
+ if (!newEdges.has(id)) {
741
+ newEdges.set(id, {
742
+ id,
743
+ kind: "test",
744
+ src: testFileId,
745
+ dst: dst.id,
746
+ resolution: e.resolution,
747
+ confidence: e.confidence
748
+ });
749
+ }
750
+ covered.add(dst.id);
751
+ }
752
+ }
753
+ const outNodes = nodes.map((n) => ({ ...n, tested: testedFlag(n, covered.has(n.id), testFiles) }));
754
+ const outEdges = [...edges, ...newEdges.values()].sort(
755
+ (a, b) => a.kind.localeCompare(b.kind) || a.src.localeCompare(b.src) || a.dst.localeCompare(b.dst)
756
+ );
757
+ return {
758
+ nodes: outNodes,
759
+ edges: outEdges,
760
+ testFiles: [...testFiles].sort(),
761
+ testEdgeCount: newEdges.size
762
+ };
763
+ }
764
+ function testedFlag(node, covered, testFiles) {
765
+ if (node.kind === "external" || node.kind === "file" || node.kind === "package" || node.kind === "module") {
766
+ return null;
767
+ }
768
+ if (testFiles.has(node.file)) return null;
769
+ if (node.kind === "function" || node.kind === "method") return covered;
770
+ return covered ? true : node.tested ?? null;
771
+ }
772
+
706
773
  // src/engine/scip.ts
707
774
  var ROLE_DEFINITION = 1;
708
775
  var Reader = class {
@@ -1065,72 +1132,6 @@ function round(x) {
1065
1132
  function pairKey(a, b) {
1066
1133
  return a < b ? `${a}|${b}` : `${b}|${a}`;
1067
1134
  }
1068
-
1069
- // src/engine/tests.ts
1070
- function isTestFile(rel2) {
1071
- const lower = rel2.toLowerCase();
1072
- const base = rel2.split("/").pop() ?? rel2;
1073
- const lbase = base.toLowerCase();
1074
- if (/(^|\/)(__tests__|__test__)\//.test(lower)) return true;
1075
- if (/(^|\/)(tests?|spec|specs)\//.test(lower)) return true;
1076
- if (/(^|\/)src\/test\//.test(lower)) return true;
1077
- if (/\.(test|spec)\.[cm]?[jt]sx?$/.test(lbase)) return true;
1078
- if (/^test_.*\.py$/.test(lbase) || /_test\.py$/.test(lbase)) return true;
1079
- if (/_test\.go$/.test(lbase)) return true;
1080
- if (/[A-Za-z0-9](Test|Tests|IT)\.java$/.test(base)) return true;
1081
- if (/_spec\.rb$/.test(lbase) || /_test\.rb$/.test(lbase)) return true;
1082
- if (/[A-Za-z0-9](Test|Tests)\.cs$/.test(base)) return true;
1083
- return false;
1084
- }
1085
- function applyStaticTestLinkage(nodes, edges) {
1086
- const byId = new Map(nodes.map((n) => [n.id, n]));
1087
- const testFiles = /* @__PURE__ */ new Set();
1088
- for (const n of nodes) if (n.kind === "file" && isTestFile(n.file)) testFiles.add(n.file);
1089
- const fileNodeIdByRel = /* @__PURE__ */ new Map();
1090
- for (const n of nodes) if (n.kind === "file") fileNodeIdByRel.set(n.file, n.id);
1091
- const covered = /* @__PURE__ */ new Set();
1092
- const newEdges = /* @__PURE__ */ new Map();
1093
- for (const e of edges) {
1094
- if (e.kind !== "call") continue;
1095
- const src = byId.get(e.src);
1096
- const dst = byId.get(e.dst);
1097
- if (!src || !dst) continue;
1098
- if (testFiles.has(src.file) && !testFiles.has(dst.file) && dst.kind !== "external") {
1099
- const testFileId = fileNodeIdByRel.get(src.file);
1100
- if (!testFileId) continue;
1101
- const id = edgeId("test", testFileId, dst.id);
1102
- if (!newEdges.has(id)) {
1103
- newEdges.set(id, {
1104
- id,
1105
- kind: "test",
1106
- src: testFileId,
1107
- dst: dst.id,
1108
- resolution: e.resolution,
1109
- confidence: e.confidence
1110
- });
1111
- }
1112
- covered.add(dst.id);
1113
- }
1114
- }
1115
- const outNodes = nodes.map((n) => ({ ...n, tested: testedFlag(n, covered.has(n.id), testFiles) }));
1116
- const outEdges = [...edges, ...newEdges.values()].sort(
1117
- (a, b) => a.kind.localeCompare(b.kind) || a.src.localeCompare(b.src) || a.dst.localeCompare(b.dst)
1118
- );
1119
- return {
1120
- nodes: outNodes,
1121
- edges: outEdges,
1122
- testFiles: [...testFiles].sort(),
1123
- testEdgeCount: newEdges.size
1124
- };
1125
- }
1126
- function testedFlag(node, covered, testFiles) {
1127
- if (node.kind === "external" || node.kind === "file" || node.kind === "package" || node.kind === "module") {
1128
- return null;
1129
- }
1130
- if (testFiles.has(node.file)) return null;
1131
- if (node.kind === "function" || node.kind === "method") return covered;
1132
- return covered ? true : node.tested ?? null;
1133
- }
1134
1135
  var DEFAULT_PATHS = [
1135
1136
  "coverage/lcov.info",
1136
1137
  "lcov.info",
@@ -1570,6 +1571,7 @@ function emptyParse(file, warning) {
1570
1571
  calls: [],
1571
1572
  imports: [],
1572
1573
  heritage: [],
1574
+ typeRefs: [],
1573
1575
  guards: [],
1574
1576
  warnings: [warning]
1575
1577
  };
@@ -1667,9 +1669,10 @@ function resolve4(parses, resolver) {
1667
1669
  const fileId = fileNodeIdByRel.get(p.rel);
1668
1670
  const localDefs = defsByFile.get(p.rel) ?? [];
1669
1671
  const imported = importedFilesByRel.get(p.rel) ?? /* @__PURE__ */ new Set();
1672
+ const testCaller = isTestFile(p.rel);
1670
1673
  for (const call of p.calls) {
1671
1674
  const srcId = enclosingDefId(localDefs, call.byte) ?? fileId;
1672
- const resolved = resolveCall(call, p.rel, p.lang, imported, defsByName, srcId);
1675
+ const resolved = resolveCall(call, p.rel, p.lang, imported, defsByName, srcId, testCaller);
1673
1676
  if (resolved) {
1674
1677
  edges.add("call", srcId, resolved.id, "heuristic", resolved.confidence);
1675
1678
  stats.callsResolved++;
@@ -1679,13 +1682,25 @@ function resolve4(parses, resolver) {
1679
1682
  }
1680
1683
  }
1681
1684
  }
1685
+ for (const p of parses) {
1686
+ const fileId = fileNodeIdByRel.get(p.rel);
1687
+ const localDefs = defsByFile.get(p.rel) ?? [];
1688
+ const imported = importedFilesByRel.get(p.rel) ?? /* @__PURE__ */ new Set();
1689
+ const testCaller = isTestFile(p.rel);
1690
+ for (const ref of p.typeRefs) {
1691
+ const srcId = enclosingDefId(localDefs, ref.byte) ?? fileId;
1692
+ const target = resolveType(ref.name, p.rel, p.lang, imported, defsByName, testCaller);
1693
+ if (target) edges.add("references", srcId, target.id, "heuristic", 0.7);
1694
+ }
1695
+ }
1682
1696
  for (const p of parses) {
1683
1697
  const localDefs = defsByFile.get(p.rel) ?? [];
1684
1698
  const imported = importedFilesByRel.get(p.rel) ?? /* @__PURE__ */ new Set();
1699
+ const testCaller = isTestFile(p.rel);
1685
1700
  for (const h of p.heritage) {
1686
1701
  const srcId = enclosingDefId(localDefs, h.byte);
1687
1702
  if (!srcId) continue;
1688
- const target = resolveType(h.superName, p.rel, p.lang, imported, defsByName);
1703
+ const target = resolveType(h.superName, p.rel, p.lang, imported, defsByName, testCaller);
1689
1704
  if (target) edges.add(h.kind, srcId, target.id, "heuristic", 0.85);
1690
1705
  else bumpUnresolved(unresolved2, srcId, h.superName, h.kind, p.rel);
1691
1706
  }
@@ -1750,7 +1765,7 @@ function dirOf(rel2) {
1750
1765
  const i = rel2.lastIndexOf("/");
1751
1766
  return i >= 0 ? rel2.slice(0, i) : "";
1752
1767
  }
1753
- function resolveCall(call, fromRel, fromLang, importedRels, defsByName, enclosingId) {
1768
+ function resolveCall(call, fromRel, fromLang, importedRels, defsByName, enclosingId, fromIsTestFile = false) {
1754
1769
  const candidates = defsByName.get(call.callee);
1755
1770
  if (!candidates || candidates.length === 0) return null;
1756
1771
  const callable = candidates.filter((c) => c.kind === "function" || c.kind === "method");
@@ -1771,9 +1786,12 @@ function resolveCall(call, fromRel, fromLang, importedRels, defsByName, enclosin
1771
1786
  if (call.qualified && enclosingId) samePkg = samePkg.filter((c) => c.id !== enclosingId);
1772
1787
  if (samePkg.length === 1) return { id: samePkg[0].id, confidence: 0.7 };
1773
1788
  }
1789
+ if (fromLang === "swift" && fromIsTestFile && pool.length === 1) {
1790
+ return { id: pool[0].id, confidence: 0.5 };
1791
+ }
1774
1792
  return null;
1775
1793
  }
1776
- function resolveType(name, fromRel, fromLang, importedRels, defsByName) {
1794
+ function resolveType(name, fromRel, fromLang, importedRels, defsByName, fromIsTestFile = false) {
1777
1795
  const candidates = (defsByName.get(name) ?? []).filter(
1778
1796
  (c) => c.kind === "class" || c.kind === "interface"
1779
1797
  );
@@ -1788,6 +1806,9 @@ function resolveType(name, fromRel, fromLang, importedRels, defsByName) {
1788
1806
  const samePkg = candidates.filter((c) => c.lang === fromLang && dirOf(c.rel) === dir);
1789
1807
  if (samePkg.length === 1) return { id: samePkg[0].id };
1790
1808
  }
1809
+ if (fromLang === "swift" && fromIsTestFile && candidates.length === 1) {
1810
+ return { id: candidates[0].id };
1811
+ }
1791
1812
  return null;
1792
1813
  }
1793
1814
  var EdgeSet = class {
@@ -2985,13 +3006,19 @@ var GraphIndex = class {
2985
3006
  node(id) {
2986
3007
  return this.nodeById.get(id);
2987
3008
  }
2988
- /** Resolved nodes called by `id`. */
3009
+ /**
3010
+ * Resolved nodes called by `id` — invocations (`call`) plus structural
3011
+ * dependency references (`references`, e.g. a constructor-injected field's
3012
+ * type), since both represent real usage a caller/impact question cares
3013
+ * about. `references` is otherwise only emitted by the precise SCIP/tsc
3014
+ * rungs and (for Java DI wiring) the heuristic rung — never a guess.
3015
+ */
2989
3016
  callees(id) {
2990
- return this.resolveTargets(this.out(id, "call"), "dst");
3017
+ return this.resolveTargets(this.out(id).filter(isUsageEdge), "dst");
2991
3018
  }
2992
- /** Resolved nodes that call `id`. */
3019
+ /** Resolved nodes that call or structurally reference `id`. */
2993
3020
  callers(id) {
2994
- return this.resolveTargets(this.in(id, "call"), "src");
3021
+ return this.resolveTargets(this.in(id).filter(isUsageEdge), "src");
2995
3022
  }
2996
3023
  resolveTargets(edges, end) {
2997
3024
  const out = [];
@@ -3002,6 +3029,10 @@ var GraphIndex = class {
3002
3029
  return out;
3003
3030
  }
3004
3031
  };
3032
+ var USAGE_KINDS = /* @__PURE__ */ new Set(["call", "references"]);
3033
+ function isUsageEdge(e) {
3034
+ return USAGE_KINDS.has(e.kind);
3035
+ }
3005
3036
  function push2(map, key, value) {
3006
3037
  const list = map.get(key);
3007
3038
  if (list) list.push(value);
@@ -3059,7 +3090,26 @@ var STOPWORDS = /* @__PURE__ */ new Set([
3059
3090
  "from",
3060
3091
  "by",
3061
3092
  "at",
3062
- "as"
3093
+ "as",
3094
+ // Discovery-question scaffolding: words a caller uses to FRAME the ask
3095
+ // ("find the code responsible for X", "I need to modify X, where do I
3096
+ // start?", "explain how X works in this codebase") rather than to name the
3097
+ // target. Left in, these compete on equal footing with the real identifier
3098
+ // terms and can outrank it outright — e.g. "find the code responsible for
3099
+ // deleteAsync" let "find" alone drag in every FindByIdAsync/FindAll method
3100
+ // in the repo, none of them the target (VG-LOCATE-FAILURE-ANALYSIS.md).
3101
+ "find",
3102
+ "code",
3103
+ "responsible",
3104
+ "need",
3105
+ "modify",
3106
+ "me",
3107
+ "implementation",
3108
+ "explain",
3109
+ "works",
3110
+ "codebase",
3111
+ "contains",
3112
+ "file"
3063
3113
  ]);
3064
3114
  function queryGraph(graph, question, options = {}) {
3065
3115
  const budget = options.budget ?? 2e3;
@@ -3115,7 +3165,7 @@ async function queryGraphSemantic(graph, question, options) {
3115
3165
  function tokenize(q2) {
3116
3166
  return [
3117
3167
  ...new Set(
3118
- q2.toLowerCase().split(/[^a-z0-9]+/).filter((t) => t.length >= 2 && !STOPWORDS.has(t))
3168
+ q2.toLowerCase().split(/[^\p{L}\p{N}]+/u).filter((t) => t.length >= 1 && !STOPWORDS.has(t))
3119
3169
  )
3120
3170
  ];
3121
3171
  }
@@ -3173,7 +3223,7 @@ function termWeights(graph, terms) {
3173
3223
  }
3174
3224
  function identifierParts(name) {
3175
3225
  return new Set(
3176
- name.split(/[^a-zA-Z0-9]+|(?<=[a-z0-9])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/).filter(Boolean).map((s) => s.toLowerCase())
3226
+ name.split(/[^\p{L}\p{N}]+|(?<=[a-z0-9])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/u).filter(Boolean).map((s) => s.toLowerCase())
3177
3227
  );
3178
3228
  }
3179
3229
  function fuzzyPartMatch(term, parts) {
@@ -4938,6 +4988,20 @@ function dedupeRoutes(routes) {
4938
4988
  // src/reporting/utils/compact-artifact.ts
4939
4989
  var gzip2 = promisify(zlib.gzip);
4940
4990
  var MAX_ITEMS = 50;
4991
+ var MAX_DB_MODELS = 300;
4992
+ var MAX_DB_FIELDS_PER_MODEL = 100;
4993
+ var MAX_DB_MODEL_FILES = 5;
4994
+ var MAX_DB_FILES_SCANNED = 500;
4995
+ var DB_UPLOAD_HARD_CEILING = {
4996
+ maxModels: 2e3,
4997
+ maxFieldsPerModel: 500,
4998
+ maxFilesPerModel: 20,
4999
+ maxFilesScanned: 5e3
5000
+ };
5001
+ function clampCap(configured, fallback, ceiling) {
5002
+ if (typeof configured !== "number" || !Number.isFinite(configured) || configured <= 0) return fallback;
5003
+ return Math.min(Math.floor(configured), ceiling);
5004
+ }
4941
5005
  function extractName(entry) {
4942
5006
  const match = entry.match(/^(.+?)\s*\(/);
4943
5007
  return match ? match[1].trim() : entry.trim();
@@ -5003,7 +5067,29 @@ function compactAssetBranding(result) {
5003
5067
  // Don't include logos
5004
5068
  };
5005
5069
  }
5006
- function prepareArtifactForUpload(artifact) {
5070
+ function compactDatabaseSchema(result, caps) {
5071
+ const maxModels = clampCap(caps?.maxModels, MAX_DB_MODELS, DB_UPLOAD_HARD_CEILING.maxModels);
5072
+ const maxFieldsPerModel = clampCap(caps?.maxFieldsPerModel, MAX_DB_FIELDS_PER_MODEL, DB_UPLOAD_HARD_CEILING.maxFieldsPerModel);
5073
+ const maxFilesPerModel = clampCap(caps?.maxFilesPerModel, MAX_DB_MODEL_FILES, DB_UPLOAD_HARD_CEILING.maxFilesPerModel);
5074
+ const maxFilesScanned = clampCap(caps?.maxFilesScanned, MAX_DB_FILES_SCANNED, DB_UPLOAD_HARD_CEILING.maxFilesScanned);
5075
+ return {
5076
+ providers: result.providers.slice(0, MAX_ITEMS),
5077
+ models: result.models.slice(0, maxModels).map((model) => ({
5078
+ ...model,
5079
+ fields: model.fields.slice(0, maxFieldsPerModel),
5080
+ files: model.files.slice(0, maxFilesPerModel)
5081
+ })),
5082
+ enums: result.enums.slice(0, MAX_ITEMS),
5083
+ filesScanned: result.filesScanned.slice(0, maxFilesScanned),
5084
+ projects: result.projects.slice(0, MAX_ITEMS).map((project) => ({
5085
+ project: project.project,
5086
+ filesScanned: project.filesScanned.slice(0, MAX_ITEMS),
5087
+ models: project.models.slice(0, MAX_ITEMS),
5088
+ enums: project.enums.slice(0, MAX_ITEMS)
5089
+ }))
5090
+ };
5091
+ }
5092
+ function prepareArtifactForUpload(artifact, opts) {
5007
5093
  const compacted = { ...artifact };
5008
5094
  if (compacted.extended) {
5009
5095
  const ext = { ...compacted.extended };
@@ -5079,6 +5165,9 @@ function prepareArtifactForUpload(artifact) {
5079
5165
  duplicatedPackages: ext.dependencyGraph.duplicatedPackages.slice(0, MAX_ITEMS)
5080
5166
  };
5081
5167
  }
5168
+ if (ext.databaseSchema) {
5169
+ ext.databaseSchema = compactDatabaseSchema(ext.databaseSchema, opts?.databaseSchemaCaps);
5170
+ }
5082
5171
  compacted.extended = ext;
5083
5172
  }
5084
5173
  return compacted;
@@ -5087,8 +5176,8 @@ async function compressArtifact(artifact) {
5087
5176
  const json = JSON.stringify(artifact);
5088
5177
  return gzip2(json, { level: 9 });
5089
5178
  }
5090
- async function prepareCompressedUpload(artifact) {
5091
- const compacted = prepareArtifactForUpload(artifact);
5179
+ async function prepareCompressedUpload(artifact, opts) {
5180
+ const compacted = prepareArtifactForUpload(artifact, opts);
5092
5181
  const compressed = await compressArtifact(compacted);
5093
5182
  return { body: compressed, contentEncoding: "gzip" };
5094
5183
  }
@@ -5101,8 +5190,9 @@ function postOnce(input, host) {
5101
5190
  "Content-Encoding": input.contentEncoding,
5102
5191
  "X-Vibgrate-Timestamp": input.timestamp,
5103
5192
  "Authorization": `VibgrateDSN ${input.keyId}:${input.secret}`,
5104
- "Connection": "close"
5193
+ "Connection": "close",
5105
5194
  // Prevent keep-alive delays on exit
5195
+ ...input.runId && input.runToken ? { "X-Vibgrate-Run-Id": input.runId, "X-Vibgrate-Run-Token": input.runToken } : {}
5106
5196
  },
5107
5197
  body: input.body
5108
5198
  });
@@ -5170,7 +5260,9 @@ var pushCommand = new Command("push").description("Push scan results to Vibgrate
5170
5260
  return;
5171
5261
  }
5172
5262
  const artifact = await readJsonFile(filePath);
5173
- const { body, contentEncoding } = await prepareCompressedUpload(artifact);
5263
+ const config = await loadConfig(process.cwd());
5264
+ const databaseSchemaCaps = config.scanners !== false ? config.scanners?.databaseSchema : void 0;
5265
+ const { body, contentEncoding } = await prepareCompressedUpload(artifact, { databaseSchemaCaps });
5174
5266
  const timestamp = String(Date.now());
5175
5267
  let host = parsed.host;
5176
5268
  if (opts.region) {
@@ -5194,7 +5286,11 @@ var pushCommand = new Command("push").description("Push scan results to Vibgrate
5194
5286
  secret: parsed.secret,
5195
5287
  body,
5196
5288
  contentEncoding,
5197
- timestamp
5289
+ timestamp,
5290
+ // Set only by an automated caller running the scan on the workspace's
5291
+ // behalf (e.g. a Vibgrate-hosted remediation run) — never a customer flag.
5292
+ runId: process.env.VIBGRATE_SCAN_RUN_ID,
5293
+ runToken: process.env.VIBGRATE_SCAN_RUN_TOKEN
5198
5294
  });
5199
5295
  host = uploadedHost;
5200
5296
  if (!response.ok) {
@@ -5885,6 +5981,9 @@ async function searchSymbols(graph, root, query, limit) {
5885
5981
  if (!q2) return { matches: [], moreAvailable: false, hint: "query is required" };
5886
5982
  const isPhrase = /\s/.test(q2);
5887
5983
  let nodes = findNodes(graph, q2).filter((n) => n.kind !== "file");
5984
+ if (nodes.length === 0 && isPhrase) {
5985
+ nodes = reconstructedIdentifierNodes(graph, q2);
5986
+ }
5888
5987
  if (nodes.length === 0) {
5889
5988
  const tokens = queryTokens(q2);
5890
5989
  if (tokens.length >= 2) nodes = multiTokenNodes(graph, tokens);
@@ -5927,6 +6026,14 @@ async function searchSymbols(graph, root, query, limit) {
5927
6026
  function queryTokens(q2) {
5928
6027
  return [...new Set(q2.toLowerCase().split(/[^a-z0-9]+/).filter((t) => t.length >= 2))];
5929
6028
  }
6029
+ function reconstructedIdentifierNodes(graph, q2) {
6030
+ const words = q2.trim().split(/\s+/).filter(Boolean);
6031
+ if (words.length < 2) return [];
6032
+ const concat = findNodes(graph, words.join(""));
6033
+ if (concat.length) return concat.filter((n) => n.kind !== "file");
6034
+ const snake = findNodes(graph, words.join("_"));
6035
+ return snake.filter((n) => n.kind !== "file");
6036
+ }
5930
6037
  function multiTokenNodes(graph, tokens) {
5931
6038
  const cov = /* @__PURE__ */ new Map();
5932
6039
  for (const t of tokens) {
@@ -7385,5 +7492,5 @@ function spdx(ctx) {
7385
7492
  }
7386
7493
 
7387
7494
  export { ASSISTANTS, CLI_TOOL_ALIASES, CliError, ECOSYSTEMS, ExitCode, FREE_PACK, GraphIndex, GraphSource, NPX_INVOCATION, ResourceLimitError, SCHEMA_VERSION, SKIP_DIRS, SKIP_FILES, TOOLS, UsageError, addLibrary, analyze, applyCoverage, applyStaticTestLinkage, assessDocQuality, assistantById, availableRegionIds, buildFacts, buildGraph, buildModuleResolver, cacheDir, catalogPath, clearModelCache, clearStoredCredentials, cosine, countPending, countTokens, coveringTests, createServer, createWorkspaceDsn, credentialsPath, dashHostForIngestHost, decodeScipIndex, defaultGraphPath, detectRunner, detectServeLaunch, discover, discoverModels, driftCount, driftFor, dsnCommand, embeddingsCached, enrichOnline, ensureGitignored, epistemicBreakdown, exportGraph, fetchHostedDocsCached, findGitRoot, findNodes, formatForExt, getNodeEmbeddings, gitignoreEntryForCredentials, groundGraph, hasDrift, identifierParts, impactOf, indexFor, ingestHostForRegionId, installAssistant, inventory, isModelReady, isTestFile, libDir, libId, loadCatalog, loadCoverage, loadEmbedder, loadGraph, loadSnapshot, localApiSurface, localPackageDocs, modelCacheInfo, nodeById, nodeEmbedText, parseDsn, parseGraph, parseJsonc, probeFreshness, publishPrivateLibrary, pushCommand, queryGraph, queryGraphSemantic, readDoc, readSavings, readScanArtifact, readUsage, recordCliCall, recordSaving, refreshIfStale, relativeResolver, renderHtml, renderReport, resolveCliInvocation, resolveDsn, resolveEmbedModel, resolveIngestHost, resolveLib, resolveLimits, resolveOne, resolveVersion, saveCatalog, savingsRecorded, scipEdges, selectForBudget, serializeGraph, serveStdio, shortestPath, stableStringify, symbolsFromApi, testsToRun, unavailableMessage, uninstallAssistant, uploadScanArtifact, usageError, verifyDeterminism, vibgrateDir, writeArtifacts, writeNavigationConfig, writeSnapshot, writeStoredCredentials };
7388
- //# sourceMappingURL=chunk-75ZJYYJE.js.map
7389
- //# sourceMappingURL=chunk-75ZJYYJE.js.map
7495
+ //# sourceMappingURL=chunk-D4BPWARI.js.map
7496
+ //# sourceMappingURL=chunk-D4BPWARI.js.map