@vibgrate/cli 2026.730.1 → 2026.731.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/baseline-4FBHW2X2.js +9 -0
  2. package/dist/{baseline-V6MYDEMS.js.map → baseline-4FBHW2X2.js.map} +1 -1
  3. package/dist/chunk-2XTPGYR2.js +6 -0
  4. package/dist/{chunk-Q4UQ73NA.js.map → chunk-2XTPGYR2.js.map} +1 -1
  5. package/dist/{chunk-CQDCZQFV.js → chunk-3NP2DO4G.js} +3 -3
  6. package/dist/{chunk-CQDCZQFV.js.map → chunk-3NP2DO4G.js.map} +1 -1
  7. package/dist/{chunk-VOEYUAER.js → chunk-476KWSFM.js} +3 -3
  8. package/dist/{chunk-VOEYUAER.js.map → chunk-476KWSFM.js.map} +1 -1
  9. package/dist/{chunk-6D4BCGRQ.js → chunk-C22ZY3FV.js} +3 -3
  10. package/dist/{chunk-6D4BCGRQ.js.map → chunk-C22ZY3FV.js.map} +1 -1
  11. package/dist/{chunk-TJ3WIJ7H.js → chunk-CWB6H553.js} +3 -3
  12. package/dist/{chunk-TJ3WIJ7H.js.map → chunk-CWB6H553.js.map} +1 -1
  13. package/dist/{chunk-5G7C6H2G.js → chunk-DXSEG6SZ.js} +3 -3
  14. package/dist/{chunk-5G7C6H2G.js.map → chunk-DXSEG6SZ.js.map} +1 -1
  15. package/dist/{chunk-6WNJJXFY.js → chunk-GPDJOCUI.js} +23 -6
  16. package/dist/chunk-GPDJOCUI.js.map +1 -0
  17. package/dist/{chunk-CFL3QQQZ.js → chunk-J3BQ7FIT.js} +7 -7
  18. package/dist/{chunk-CFL3QQQZ.js.map → chunk-J3BQ7FIT.js.map} +1 -1
  19. package/dist/{chunk-IDAQV3NQ.js → chunk-NJT4CA6K.js} +42 -11
  20. package/dist/chunk-NJT4CA6K.js.map +1 -0
  21. package/dist/{chunk-DBMYWNLC.js → chunk-SE4JMB4W.js} +3 -3
  22. package/dist/{chunk-DBMYWNLC.js.map → chunk-SE4JMB4W.js.map} +1 -1
  23. package/dist/{chunk-GLT3N7T2.js → chunk-SKIMUFCI.js} +6 -6
  24. package/dist/{chunk-GLT3N7T2.js.map → chunk-SKIMUFCI.js.map} +1 -1
  25. package/dist/{chunk-EKCNSRNJ.js → chunk-T7OFJS3X.js} +7 -7
  26. package/dist/{chunk-EKCNSRNJ.js.map → chunk-T7OFJS3X.js.map} +1 -1
  27. package/dist/{chunk-ON7PZNYV.js → chunk-UVMP7DFF.js} +12 -12
  28. package/dist/{chunk-ON7PZNYV.js.map → chunk-UVMP7DFF.js.map} +1 -1
  29. package/dist/cli.js +354 -88
  30. package/dist/cli.js.map +1 -1
  31. package/dist/{fs-HNR6LAI7.js → fs-HF5DOHYR.js} +3 -3
  32. package/dist/fs-HF5DOHYR.js.map +1 -0
  33. package/dist/index.d.ts +1 -1
  34. package/dist/index.js +8 -8
  35. package/dist/{interactive-NJG6467J.js → interactive-V6IRYZTA.js} +13 -13
  36. package/dist/{interactive-NJG6467J.js.map → interactive-V6IRYZTA.js.map} +1 -1
  37. package/dist/load-KPHH26ND.js +10 -0
  38. package/dist/{load-YPSEDYIW.js.map → load-KPHH26ND.js.map} +1 -1
  39. package/dist/{run-outcome-5FQWHWYK.js → run-outcome-TZ53G67B.js} +5 -5
  40. package/dist/{run-outcome-5FQWHWYK.js.map → run-outcome-TZ53G67B.js.map} +1 -1
  41. package/dist/{runtime-session-Y4ZD3QDO.js → runtime-session-PZKXBDJT.js} +7 -7
  42. package/dist/{runtime-session-Y4ZD3QDO.js.map → runtime-session-PZKXBDJT.js.map} +1 -1
  43. package/dist/{vg-mcp-bridge-PZFGTZSA.js → vg-mcp-bridge-7NNVIVO7.js} +6 -6
  44. package/dist/{vg-mcp-bridge-PZFGTZSA.js.map → vg-mcp-bridge-7NNVIVO7.js.map} +1 -1
  45. package/dist/{vgd-DH7AHQ23.js → vgd-Y2YCN75V.js} +6 -6
  46. package/dist/vgd-Y2YCN75V.js.map +1 -0
  47. package/package.json +1 -1
  48. package/dist/baseline-V6MYDEMS.js +0 -9
  49. package/dist/chunk-6WNJJXFY.js.map +0 -1
  50. package/dist/chunk-IDAQV3NQ.js.map +0 -1
  51. package/dist/chunk-Q4UQ73NA.js +0 -6
  52. package/dist/fs-HNR6LAI7.js.map +0 -1
  53. package/dist/load-YPSEDYIW.js +0 -10
  54. package/dist/vgd-DH7AHQ23.js.map +0 -1
package/dist/cli.js CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import { sha256Hex, generateKeypair, dssePae, DSSE_PAYLOAD_TYPE, keyId, registerBuild, readGlobal, applyGlobalOptions, ProgressBar, printLogo, fetchCatalog, resolveProviders, runBuild } from './chunk-EKCNSRNJ.js';
3
- export { runBuild } from './chunk-EKCNSRNJ.js';
4
- import { telemetryOptOut, StatsSharer, statsEndpoint, isCI } from './chunk-TJ3WIJ7H.js';
5
- import { loadAdvancedScanHook, baselineCommand } from './chunk-6WNJJXFY.js';
2
+ import { sha256Hex, generateKeypair, dssePae, DSSE_PAYLOAD_TYPE, keyId, registerBuild, readGlobal, applyGlobalOptions, ProgressBar, printLogo, fetchCatalog, resolveProviders, runBuild } from './chunk-T7OFJS3X.js';
3
+ export { runBuild } from './chunk-T7OFJS3X.js';
4
+ import { telemetryOptOut, StatsSharer, statsEndpoint, isCI } from './chunk-CWB6H553.js';
5
+ import { loadAdvancedScanHook, baselineCommand } from './chunk-GPDJOCUI.js';
6
6
  import { buildModelInstallPlan } from './chunk-WHJMS7XC.js';
7
7
  import { runCodeSession } from './chunk-WBMMRERH.js';
8
8
  import { disableColor, info, c, json, out } from './chunk-CT5BS56U.js';
9
- import { VGD_PROTOCOL_VERSION, startVgdServer } from './chunk-CQDCZQFV.js';
9
+ import { VGD_PROTOCOL_VERSION, startVgdServer } from './chunk-3NP2DO4G.js';
10
10
  import './chunk-5I4VSBWQ.js';
11
11
  import './chunk-IS7VTH2Q.js';
12
12
  import { init_resolve_ollama, gatherSystemMemory, resolveOllamaBinary, hasOllamaBinary, resolve_ollama_exports } from './chunk-OWSFZQOP.js';
@@ -23,11 +23,11 @@ import './chunk-RGEVBSLK.js';
23
23
  import { vgdSocketPath, vgdIsRunning, vgdRequest, vgdPidPath } from './chunk-RBIRXQR6.js';
24
24
  import { buildIdentifierTrieFromGraph } from './chunk-5HYCB55P.js';
25
25
  import './chunk-7AVYKZEM.js';
26
- import { serveStdio, exportGraph, GraphSource, createServer, formatForExt } from './chunk-CFL3QQQZ.js';
27
- import { CliError, ExitCode, refreshIfStale, driftCount, ASSISTANTS, detectAssistants, usageError, detectServeLaunch, installAssistant, writeNavigationConfig, uninstallAssistant, buildGraph, writeSnapshot, probeFreshness, discover, assistantById, SMALL_REPO_FILES, SKIP_DIRS, SKIP_FILES } from './chunk-GLT3N7T2.js';
28
- import { resolveDsn, createWorkspaceDsn, writeStoredCredentials, credentialsPath, findGitRoot, ensureGitignored, gitignoreEntryForCredentials, clearStoredCredentials, parseDsn as parseDsn$1, uploadScanArtifact, dsnCommand, pushCommand, countTokens, shortestPath, pathDisconnect, testsToRun, detectRunner, coveringTests, FREE_PACK, readScanArtifact, publishPrivateLibrary, assessDocQuality, symbolsFromApi, fetchHostedDocsCached, selectForBudget, hostedBase, readStoredCredentials, projectCredentialsPath, homeCredentialsPath } from './chunk-6D4BCGRQ.js';
26
+ import { serveStdio, exportGraph, GraphSource, createServer, formatForExt } from './chunk-J3BQ7FIT.js';
27
+ import { CliError, ExitCode, refreshIfStale, driftCount, ASSISTANTS, detectAssistants, usageError, detectServeLaunch, installAssistant, writeNavigationConfig, uninstallAssistant, buildGraph, writeSnapshot, probeFreshness, discover, assistantById, SMALL_REPO_FILES, SKIP_DIRS, SKIP_FILES } from './chunk-SKIMUFCI.js';
28
+ import { resolveDsn, createWorkspaceDsn, writeStoredCredentials, credentialsPath, findGitRoot, ensureGitignored, gitignoreEntryForCredentials, clearStoredCredentials, parseDsn as parseDsn$1, uploadScanArtifact, dsnCommand, pushCommand, countTokens, shortestPath, pathDisconnect, testsToRun, detectRunner, coveringTests, FREE_PACK, readScanArtifact, publishPrivateLibrary, assessDocQuality, symbolsFromApi, fetchHostedDocsCached, selectForBudget, hostedBase, readStoredCredentials, projectCredentialsPath, homeCredentialsPath } from './chunk-C22ZY3FV.js';
29
29
  import { resolveIngestHost, dashHostForIngestHost, availableRegionIds, ingestHostForRegionId } from './chunk-HTLDXEHW.js';
30
- import { writeDefaultConfig, parseDsn, detectVcs, computeRepoFingerprint, resolveRepositoryName, fetchScanPreflight, runCoreScan, loadConfig, prepareCompressedUpload, computeDriftScore, titleBox, projectTypeToVulnEcosystem, driftBar, gitHistoryAvailable, buildVersionTimelines, findPackageAnyEcosystem, normalizeConstraint, findVersionCrossings, versionSatisfies, PROJECT_TYPE_TO_OSV_ECOSYSTEM, fetchRiskySymbols } from './chunk-ON7PZNYV.js';
30
+ import { writeDefaultConfig, parseDsn, detectVcs, computeRepoFingerprint, resolveRepositoryName, fetchScanPreflight, runCoreScan, loadConfig, prepareCompressedUpload, computeDriftScore, titleBox, projectTypeToVulnEcosystem, driftBar, gitHistoryAvailable, buildVersionTimelines, findPackageAnyEcosystem, normalizeConstraint, findVersionCrossings, versionSatisfies, PROJECT_TYPE_TO_OSV_ECOSYSTEM, fetchRiskySymbols, perDependencyDrift } from './chunk-UVMP7DFF.js';
31
31
  import { ensureDir, pathExists, readJsonFile, writeTextFile, writeJsonFile } from './chunk-CRAMOEBE.js';
32
32
  import './chunk-IPICO2RV.js';
33
33
  import { inventory, enrichOnline, ECOSYSTEMS, catalogPath, libDir, loadCatalog, driftFor, addLibrary, resolveLib, libId, resolveVersion, readDoc, localPackageDocs, localApiSurface } from './chunk-FHJBGPJZ.js';
@@ -39,14 +39,14 @@ import { discoverModels } from './chunk-CQDUBAQY.js';
39
39
  import { freeBytesOnVolume, weightStoreDir, listCachedWeights, ensureWeightCached, catalogIntegrityReport } from './chunk-OV4KGXPD.js';
40
40
  import { resolvedGrammarFiles, grammarSetVersion } from './chunk-UTNNGKKX.js';
41
41
  import './chunk-RXP66R2E.js';
42
- import { loadGraph, SCHEMA_VERSION } from './chunk-VOEYUAER.js';
43
- import { resolveGraphPath, renderReport, loadGraphFileWithSnapshot, writeArtifacts, vibgrateDir, mapFileExists, ensureVibgrateGitignore } from './chunk-5G7C6H2G.js';
44
- import { VERSION } from './chunk-Q4UQ73NA.js';
42
+ import { loadGraph, SCHEMA_VERSION } from './chunk-476KWSFM.js';
43
+ import { resolveGraphPath, renderReport, loadGraphFileWithSnapshot, writeArtifacts, vibgrateDir, mapFileExists, ensureVibgrateGitignore } from './chunk-DXSEG6SZ.js';
44
+ import { VERSION } from './chunk-2XTPGYR2.js';
45
45
  import { cacheDir, serializeGraph, stableStringify } from './chunk-ZKNB4YH4.js';
46
46
  import './chunk-BWPBB45M.js';
47
47
  import { canonicalize, hashString, hashBytes } from './chunk-JFGYT6BI.js';
48
48
  import './chunk-BPF3YX2U.js';
49
- import { pathExists as pathExists$1, parseExcludePatterns } from './chunk-IDAQV3NQ.js';
49
+ import { pathExists as pathExists$1, parseExcludePatterns } from './chunk-NJT4CA6K.js';
50
50
  import { __toCommonJS } from './chunk-Z6ZWNWWR.js';
51
51
  import * as fs7 from 'fs';
52
52
  import fs7__default, { realpathSync } from 'fs';
@@ -2009,6 +2009,30 @@ function runTree(graph, params) {
2009
2009
  }
2010
2010
 
2011
2011
  // src/lsp/enrich.ts
2012
+ var REACH_RANK = {
2013
+ reached: 3,
2014
+ potentially_reachable: 2,
2015
+ unknown: 1,
2016
+ "not-observed": 0
2017
+ };
2018
+ function mergeReachability(a, b) {
2019
+ const left = a ?? "unknown";
2020
+ const right = b ?? "unknown";
2021
+ return REACH_RANK[right] > REACH_RANK[left] ? right : left;
2022
+ }
2023
+ function mergeReachSites(a, b) {
2024
+ const out2 = [];
2025
+ const seen = /* @__PURE__ */ new Set();
2026
+ for (const site of [...a ?? [], ...b ?? []]) {
2027
+ if (!site?.file) continue;
2028
+ const k = `${site.file}::${site.line ?? ""}::${site.symbol ?? ""}`;
2029
+ if (seen.has(k)) continue;
2030
+ seen.add(k);
2031
+ out2.push(site);
2032
+ if (out2.length >= 10) break;
2033
+ }
2034
+ return out2;
2035
+ }
2012
2036
  var OSV_QUERY_URL = "https://api.osv.dev/v1/query";
2013
2037
  var KEV_URL = "https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json";
2014
2038
  var cache = /* @__PURE__ */ new Map();
@@ -2171,10 +2195,11 @@ async function scanWorkspaceVulns(targets, opts = { offline: false }) {
2171
2195
  existing.locations.push(loc);
2172
2196
  }
2173
2197
  }
2174
- if (t.reachability === "reached") existing.reachability = "reached";
2175
- else if (t.reachability === "not-observed" && existing.reachability === "unknown") {
2176
- existing.reachability = "not-observed";
2198
+ existing.reachability = mergeReachability(existing.reachability, t.reachability);
2199
+ if (t.reachSites?.length) {
2200
+ existing.reachSites = mergeReachSites(existing.reachSites, t.reachSites);
2177
2201
  }
2202
+ if (!existing.reachEvidence && t.reachEvidence) existing.reachEvidence = t.reachEvidence;
2178
2203
  if (!existing.latestStable && t.latestStable) existing.latestStable = t.latestStable;
2179
2204
  if (!existing.section && t.section) existing.section = t.section;
2180
2205
  }
@@ -2211,6 +2236,8 @@ async function scanWorkspaceVulns(targets, opts = { offline: false }) {
2211
2236
  published: v.published,
2212
2237
  kev: kevHit,
2213
2238
  reachability: t.reachability ?? "unknown",
2239
+ reachSites: t.reachSites ?? [],
2240
+ reachEvidence: t.reachEvidence ?? null,
2214
2241
  file: locations[0]?.file ?? t.file ?? null,
2215
2242
  line: locations[0]?.line ?? t.line ?? null,
2216
2243
  locations,
@@ -2334,6 +2361,8 @@ var VibgrateLanguageServer = class {
2334
2361
  this.conn.onRequest("textDocument/codeLens", (_m, params) => this.onCodeLens(params));
2335
2362
  this.conn.onRequest("vibgrate/graph/query", (_m, params) => this.onGraphQuery(params));
2336
2363
  this.conn.onRequest("vibgrate/score/forFile", (_m, params) => this.onScoreForFile(params));
2364
+ this.conn.onRequest("vibgrate/score/forProject", (_m, params) => this.onScoreForProject(params));
2365
+ this.conn.onRequest("vibgrate/architecture", (_m, params) => this.onArchitecture(params));
2337
2366
  this.conn.onRequest("vibgrate/score/history", (_m, params) => {
2338
2367
  const p = params;
2339
2368
  const days = typeof p?.days === "number" && p.days > 0 && p.days <= 365 ? p.days : 90;
@@ -2454,7 +2483,8 @@ var VibgrateLanguageServer = class {
2454
2483
  scannedAt: a.timestamp,
2455
2484
  ...delta !== void 0 ? { delta } : {},
2456
2485
  ...buildBreakdown(a.drift, a.projects ?? []) ? { breakdown: buildBreakdown(a.drift, a.projects ?? []) } : {},
2457
- ...buildEolHorizon(a.projects ?? []) ? { eolHorizon: buildEolHorizon(a.projects ?? []) } : {}
2486
+ ...buildEolHorizon(a.projects ?? []) ? { eolHorizon: buildEolHorizon(a.projects ?? []) } : {},
2487
+ ...buildProjectRefs(this.opts.root, a.projects ?? []) ? { projects: buildProjectRefs(this.opts.root, a.projects ?? []) } : {}
2458
2488
  };
2459
2489
  this.conn.notify("vibgrate/score", payload);
2460
2490
  }
@@ -2637,7 +2667,7 @@ var VibgrateLanguageServer = class {
2637
2667
  kevSource: "skipped"
2638
2668
  };
2639
2669
  }
2640
- const reachedPkgs = packageReachSet(this.graph);
2670
+ const importMap = packageImportMap(this.graph);
2641
2671
  const targets = [];
2642
2672
  for (const proj of a.projects ?? []) {
2643
2673
  if (isPrunedWorkspacePath(proj.path) || isPrunedWorkspacePath(manifestRelativePath(proj))) {
@@ -2662,8 +2692,22 @@ var VibgrateLanguageServer = class {
2662
2692
  if (l >= 0) line = l + 1;
2663
2693
  }
2664
2694
  let reachability = "unknown";
2665
- if (reachedPkgs) {
2666
- reachability = packageReached(reachedPkgs, dep.package) ? "reached" : "not-observed";
2695
+ let reachSites = [];
2696
+ let reachEvidence = null;
2697
+ if (importMap) {
2698
+ const files = lookupImportFiles(importMap, dep.package);
2699
+ if (files.length > 0) {
2700
+ reachability = "reached";
2701
+ reachSites = files.slice(0, 10).map((file) => ({
2702
+ file,
2703
+ // Best-effort first line that mentions the package name (import site).
2704
+ line: firstPackageMentionLine(this.opts.root, file, dep.package)
2705
+ }));
2706
+ reachEvidence = `${dep.package} is imported by ${files.length} file${files.length === 1 ? "" : "s"} in the code map`;
2707
+ } else {
2708
+ reachability = "not-observed";
2709
+ reachEvidence = `no import of ${dep.package} was found in the code map`;
2710
+ }
2667
2711
  }
2668
2712
  targets.push({
2669
2713
  ecosystem,
@@ -2673,7 +2717,9 @@ var VibgrateLanguageServer = class {
2673
2717
  line,
2674
2718
  section: dep.section ?? null,
2675
2719
  latestStable: dep.latestStable ?? null,
2676
- reachability
2720
+ reachability,
2721
+ reachSites,
2722
+ reachEvidence
2677
2723
  });
2678
2724
  }
2679
2725
  }
@@ -2684,7 +2730,53 @@ var VibgrateLanguageServer = class {
2684
2730
  const a = this.artifact;
2685
2731
  if (!a || !p.uri) return null;
2686
2732
  const project = projectForFile(this.opts.root, a, uriToPath(p.uri));
2687
- return project ? scoreForProject(a, project) : null;
2733
+ return project ? scoreForProject(this.opts.root, a, project) : null;
2734
+ }
2735
+ /**
2736
+ * `vibgrate/score/forProject` — monorepo scope picker. Returns the same
2737
+ * shape as the whole-repo score, scoped to one scanned project path.
2738
+ */
2739
+ onScoreForProject(params) {
2740
+ const p = params;
2741
+ const a = this.artifact;
2742
+ if (!a || typeof p.path !== "string") return null;
2743
+ const project = projectByPath(a, p.path);
2744
+ return project ? scoreForProject(this.opts.root, a, project) : null;
2745
+ }
2746
+ /**
2747
+ * `vibgrate/architecture` — the Architecture panel. `path` absent or
2748
+ * `'__repo__'` returns the whole-workspace aggregate (`extended.architecture`);
2749
+ * a project path returns that project's own detection (`ProjectScan.architecture`).
2750
+ * Returns `null` when the scanner hasn't produced architecture data yet (still
2751
+ * scanning, or the archetype/layer scanner is disabled) rather than an empty
2752
+ * shape a client might mistake for "no layers detected".
2753
+ */
2754
+ onArchitecture(params) {
2755
+ const p = params;
2756
+ const a = this.artifact;
2757
+ if (!a) return null;
2758
+ if (!p?.path || p.path === "__repo__") {
2759
+ const arch = a.extended?.architecture;
2760
+ if (!arch) return null;
2761
+ return {
2762
+ archetype: arch.archetype,
2763
+ archetypeConfidence: arch.archetypeConfidence,
2764
+ layers: arch.layers,
2765
+ totalClassified: arch.totalClassified,
2766
+ unclassified: arch.unclassified
2767
+ };
2768
+ }
2769
+ const project = projectByPath(a, p.path);
2770
+ if (!project?.architecture) return null;
2771
+ return {
2772
+ archetype: project.architecture.archetype,
2773
+ archetypeConfidence: project.architecture.archetypeConfidence,
2774
+ layers: project.architecture.layers,
2775
+ totalClassified: project.architecture.totalClassified,
2776
+ unclassified: project.architecture.unclassified,
2777
+ manifestPath: manifestRelativePath(project),
2778
+ lockfilePath: lockfileRelativePath(this.opts.root, project)
2779
+ };
2688
2780
  }
2689
2781
  };
2690
2782
  function uriToPath(uri) {
@@ -2712,6 +2804,33 @@ function pruneArtifactProjects(a) {
2712
2804
  const findings = (a.findings ?? []).filter((f) => !isPrunedWorkspacePath(f.location));
2713
2805
  return { ...a, projects, findings };
2714
2806
  }
2807
+ function projectByPath(a, projectPath) {
2808
+ const want = path37.normalize(projectPath === "" ? "." : projectPath);
2809
+ for (const proj of a.projects ?? []) {
2810
+ const got = path37.normalize(proj.path === "" ? "." : proj.path);
2811
+ if (got === want) return proj;
2812
+ }
2813
+ return void 0;
2814
+ }
2815
+ function buildProjectRefs(rootDir, projects) {
2816
+ if (projects.length === 0) return void 0;
2817
+ return projects.map((p) => {
2818
+ const rel = p.path === "" ? "." : p.path;
2819
+ const base = rel === "." ? "." : path37.basename(rel);
2820
+ const lockfilePath = lockfileRelativePath(rootDir, p);
2821
+ return {
2822
+ path: rel,
2823
+ name: p.name || base,
2824
+ manifestPath: manifestRelativePath(p),
2825
+ ...lockfilePath ? { lockfilePath } : {},
2826
+ ...p.drift ? {
2827
+ score: p.drift.score,
2828
+ band: p.drift.riskLevel ?? "low",
2829
+ mode: p.drift.mode ?? "verified"
2830
+ } : {}
2831
+ };
2832
+ }).sort((a, b) => a.path.localeCompare(b.path));
2833
+ }
2715
2834
  function projectForFile(root2, a, filePath) {
2716
2835
  const dir = path37.dirname(path37.resolve(filePath));
2717
2836
  let best;
@@ -2736,7 +2855,7 @@ function hasReleaseDates(a) {
2736
2855
  }
2737
2856
  return false;
2738
2857
  }
2739
- function scoreForProject(a, proj) {
2858
+ function scoreForProject(rootDir, a, proj) {
2740
2859
  if (!proj.drift) return null;
2741
2860
  let behind = 0;
2742
2861
  let total = 0;
@@ -2757,10 +2876,11 @@ function scoreForProject(a, proj) {
2757
2876
  methodology: proj.drift.methodologyVersion ?? a.drift.methodologyVersion ?? "unknown",
2758
2877
  scale: "0 best, 100 worst",
2759
2878
  counts: { behind, eol, unmaintained, total },
2760
- rootPath: proj.path,
2879
+ rootPath: proj.path === "" ? "." : proj.path,
2761
2880
  scannedAt: a.timestamp,
2762
2881
  ...buildBreakdown(proj.drift, [proj]) ? { breakdown: buildBreakdown(proj.drift, [proj]) } : {},
2763
- ...buildEolHorizon([proj]) ? { eolHorizon: buildEolHorizon([proj]) } : {}
2882
+ ...buildEolHorizon([proj]) ? { eolHorizon: buildEolHorizon([proj]) } : {},
2883
+ ...buildProjectRefs(rootDir, a.projects ?? []) ? { projects: buildProjectRefs(rootDir, a.projects ?? []) } : {}
2764
2884
  };
2765
2885
  }
2766
2886
  function runtimeHorizonLabel(project) {
@@ -2789,34 +2909,40 @@ function bandForScore(n) {
2789
2909
  if (n <= 60) return "moderate";
2790
2910
  return "high";
2791
2911
  }
2792
- function buildBreakdown(drift, projects) {
2793
- const top = drift.dependencyDrift?.top;
2794
- if (!top || top.length === 0) return void 0;
2912
+ function buildBreakdown(_drift, projects) {
2795
2913
  const byPkg = /* @__PURE__ */ new Map();
2796
2914
  for (const p of projects) {
2797
2915
  const ecosystem = osvEcosystem(p.type);
2798
- for (const d of p.dependencies ?? []) if (!byPkg.has(d.package)) byPkg.set(d.package, { row: d, ecosystem });
2916
+ for (const d of p.dependencies ?? []) {
2917
+ if (!byPkg.has(d.package)) byPkg.set(d.package, { row: d, ecosystem });
2918
+ }
2799
2919
  }
2800
- const items = top.filter((t) => t.drift > 0).map((t) => {
2801
- const found = byPkg.get(t.package);
2802
- const row = found?.row;
2803
- return {
2804
- package: t.package,
2805
- section: row?.section ?? "dependencies",
2806
- ecosystem: found?.ecosystem ?? null,
2807
- drift: t.drift,
2808
- band: bandForScore(t.drift),
2809
- currentSpec: row?.currentSpec ?? "",
2810
- resolvedVersion: row?.resolvedVersion ?? null,
2811
- latestStable: row?.latestStable ?? null,
2812
- majorsBehind: row?.majorsBehind ?? null,
2813
- ageDays: row?.ageDays ?? null,
2814
- mode: t.mode,
2815
- unsupported: t.unsupported,
2816
- abandoned: t.flags.includes("abandoned-floor"),
2817
- flags: t.flags
2818
- };
2819
- });
2920
+ if (byPkg.size === 0) return void 0;
2921
+ const items = [];
2922
+ for (const [, { row, ecosystem }] of byPkg) {
2923
+ const scored = perDependencyDrift(row, {
2924
+ unsupported: row.unsupported === true,
2925
+ abandoned: row.abandoned === true
2926
+ });
2927
+ if (scored.excluded) continue;
2928
+ items.push({
2929
+ package: row.package,
2930
+ section: row.section ?? "dependencies",
2931
+ ecosystem,
2932
+ drift: scored.drift,
2933
+ band: bandForScore(scored.drift),
2934
+ currentSpec: row.currentSpec ?? "",
2935
+ resolvedVersion: row.resolvedVersion ?? null,
2936
+ latestStable: row.latestStable ?? null,
2937
+ majorsBehind: row.majorsBehind ?? null,
2938
+ ageDays: row.ageDays ?? null,
2939
+ mode: scored.mode,
2940
+ unsupported: scored.unsupported || row.unsupported === true,
2941
+ abandoned: scored.flags.includes("abandoned-floor") || row.abandoned === true,
2942
+ flags: scored.flags
2943
+ });
2944
+ }
2945
+ items.sort((a, b) => b.drift - a.drift || a.package.localeCompare(b.package));
2820
2946
  return items.length > 0 ? items : void 0;
2821
2947
  }
2822
2948
  function manifestRelativePath(proj) {
@@ -2851,30 +2977,129 @@ function manifestRelativePath(proj) {
2851
2977
  return join27("package.json");
2852
2978
  }
2853
2979
  }
2854
- function packageReachSet(graph) {
2980
+ function lockfileRelativePath(rootDir, proj) {
2981
+ const base = proj.path === "." || proj.path === "" ? "" : proj.path;
2982
+ const candidateNames = (() => {
2983
+ switch (proj.type) {
2984
+ case "node":
2985
+ case "typescript":
2986
+ return ["pnpm-lock.yaml", "yarn.lock", "package-lock.json", "bun.lockb"];
2987
+ case "python":
2988
+ return ["poetry.lock", "uv.lock", "Pipfile.lock"];
2989
+ case "go":
2990
+ return ["go.sum"];
2991
+ case "rust":
2992
+ return ["Cargo.lock"];
2993
+ case "ruby":
2994
+ return ["Gemfile.lock"];
2995
+ case "php":
2996
+ return ["composer.lock"];
2997
+ case "dotnet":
2998
+ return ["packages.lock.json"];
2999
+ case "dart":
3000
+ return ["pubspec.lock"];
3001
+ default:
3002
+ return [];
3003
+ }
3004
+ })();
3005
+ const dirsToTry = base ? [base, ""] : [""];
3006
+ for (const dir of dirsToTry) {
3007
+ for (const name of candidateNames) {
3008
+ const rel = dir ? path37.join(dir, name) : name;
3009
+ try {
3010
+ if (fs7.existsSync(path37.join(rootDir, rel))) return rel;
3011
+ } catch {
3012
+ }
3013
+ }
3014
+ }
3015
+ return void 0;
3016
+ }
3017
+ function packageImportMap(graph) {
2855
3018
  if (!graph?.nodes?.length) return null;
2856
- const set = /* @__PURE__ */ new Set();
3019
+ const byId = new Map(graph.nodes.map((n) => [n.id, n]));
3020
+ const map = /* @__PURE__ */ new Map();
3021
+ const addPkg = (raw, file) => {
3022
+ if (!file) return;
3023
+ const cleaned = raw.replace(/^node_modules\//, "").replace(/\\/g, "/");
3024
+ const keys = /* @__PURE__ */ new Set();
3025
+ keys.add(cleaned.toLowerCase());
3026
+ if (cleaned.startsWith("@")) {
3027
+ const parts = cleaned.split("/");
3028
+ if (parts.length >= 2) keys.add(`${parts[0]}/${parts[1]}`.toLowerCase());
3029
+ } else {
3030
+ keys.add(cleaned.split("/")[0].toLowerCase());
3031
+ }
3032
+ for (const k of keys) {
3033
+ let set = map.get(k);
3034
+ if (!set) {
3035
+ set = /* @__PURE__ */ new Set();
3036
+ map.set(k, set);
3037
+ }
3038
+ set.add(file);
3039
+ }
3040
+ };
3041
+ for (const e of graph.edges ?? []) {
3042
+ if (e.kind !== "import") continue;
3043
+ const src = byId.get(e.src);
3044
+ const dst = byId.get(e.dst);
3045
+ if (!src?.file || !dst) continue;
3046
+ if (dst.kind !== "external" && dst.kind !== "package" && dst.kind !== "module") continue;
3047
+ for (const raw of [dst.name, dst.qualifiedName].filter(Boolean)) {
3048
+ addPkg(raw, src.file);
3049
+ }
3050
+ }
2857
3051
  for (const n of graph.nodes) {
2858
3052
  if (n.kind !== "external" && n.kind !== "package" && n.kind !== "module") continue;
2859
- const names = [n.name, n.qualifiedName].filter(Boolean);
2860
- for (const raw of names) {
2861
- const cleaned = raw.replace(/^node_modules\//, "").replace(/\\/g, "/");
3053
+ for (const raw of [n.name, n.qualifiedName].filter(Boolean)) {
3054
+ const cleaned = raw.replace(/^node_modules\//, "").replace(/\\/g, "/").toLowerCase();
3055
+ if (!map.has(cleaned)) map.set(cleaned, /* @__PURE__ */ new Set());
2862
3056
  if (cleaned.startsWith("@")) {
2863
3057
  const parts = cleaned.split("/");
2864
- if (parts.length >= 2) set.add(`${parts[0]}/${parts[1]}`.toLowerCase());
2865
- } else {
2866
- set.add(cleaned.split("/")[0].toLowerCase());
3058
+ if (parts.length >= 2 && !map.has(`${parts[0]}/${parts[1]}`)) {
3059
+ map.set(`${parts[0]}/${parts[1]}`, /* @__PURE__ */ new Set());
3060
+ }
2867
3061
  }
2868
- set.add(cleaned.toLowerCase());
2869
3062
  }
2870
3063
  }
2871
- return set;
3064
+ const out2 = /* @__PURE__ */ new Map();
3065
+ for (const [k, files] of map) {
3066
+ out2.set(k, [...files].sort());
3067
+ }
3068
+ return out2;
2872
3069
  }
2873
- function packageReached(set, pkg) {
3070
+ function lookupImportFiles(map, pkg) {
2874
3071
  const p = pkg.toLowerCase();
2875
- if (set.has(p)) return true;
2876
- if (!p.startsWith("@") && set.has(p.split("/")[0])) return true;
2877
- return false;
3072
+ if (map.has(p)) return map.get(p);
3073
+ if (!p.startsWith("@")) {
3074
+ const root2 = p.split("/")[0];
3075
+ if (map.has(root2)) return map.get(root2);
3076
+ }
3077
+ return [];
3078
+ }
3079
+ function firstPackageMentionLine(root2, relFile, pkg) {
3080
+ try {
3081
+ const abs = path37.resolve(root2, relFile);
3082
+ const stat2 = fs7.statSync(abs);
3083
+ if (!stat2.isFile() || stat2.size > 256 * 1024) return null;
3084
+ const text = fs7.readFileSync(abs, "utf8");
3085
+ const tokens = [pkg];
3086
+ if (pkg.startsWith("@")) {
3087
+ const parts = pkg.split("/");
3088
+ if (parts[1]) tokens.push(parts[1]);
3089
+ } else if (pkg.includes("/")) {
3090
+ tokens.push(pkg.split("/")[0]);
3091
+ }
3092
+ const lines = text.split(/\r?\n/);
3093
+ for (let i = 0; i < lines.length; i++) {
3094
+ const line = lines[i];
3095
+ if (!/import|require|from|use |include/.test(line) && !line.includes(pkg)) continue;
3096
+ for (const t of tokens) {
3097
+ if (t && line.includes(t)) return i + 1;
3098
+ }
3099
+ }
3100
+ } catch {
3101
+ }
3102
+ return null;
2878
3103
  }
2879
3104
  function osvEcosystem(type) {
2880
3105
  switch (type) {
@@ -6064,7 +6289,7 @@ function registerCode(program) {
6064
6289
  try {
6065
6290
  const { parseMode: parseMode2, resolveMode: resolveMode2, readOrchestratorState: readOrchestratorState2, activePin: activePin2 } = await import('./model-orchestrator-LHYPJBFH.js');
6066
6291
  const { gatherSystemMemory: gatherSystemMemory2 } = await import('./local-runtime-2ED33KK6.js');
6067
- const { loadGraph: loadGraph2 } = await import('./load-YPSEDYIW.js');
6292
+ const { loadGraph: loadGraph2 } = await import('./load-KPHH26ND.js');
6068
6293
  const state = readOrchestratorState2();
6069
6294
  const mode = parseMode2(modeFlag) ?? state.defaultMode ?? void 0;
6070
6295
  const pin = mode ? activePin2(mode, state) : null;
@@ -6148,7 +6373,7 @@ function registerCode(program) {
6148
6373
  if (!(process.stdin.isTTY && process.stdout.isTTY)) {
6149
6374
  throw usageError('say what to change, e.g. `vg code "add a --timeout flag to the scan command"` (guided mode needs an interactive terminal)');
6150
6375
  }
6151
- const { runInteractive } = await import('./interactive-NJG6467J.js');
6376
+ const { runInteractive } = await import('./interactive-V6IRYZTA.js');
6152
6377
  await runInteractive(
6153
6378
  rootOf(global),
6154
6379
  global,
@@ -6229,7 +6454,7 @@ function registerCode(program) {
6229
6454
  process.stdout.write(JSON.stringify(line) + "\n");
6230
6455
  };
6231
6456
  try {
6232
- const { RunOutcomeRecorder, newOneShotRunId, turnRunId } = await import('./run-outcome-5FQWHWYK.js');
6457
+ const { RunOutcomeRecorder, newOneShotRunId, turnRunId } = await import('./run-outcome-TZ53G67B.js');
6233
6458
  const primarySlug = route.providers[0]?.model.includes("/") ? route.providers[0].model.split("/")[0] : route.providers[0]?.id;
6234
6459
  const { runCodeStreamJson, parseHostMessage } = await import('./stream-json-3YOPU3LF.js');
6235
6460
  const { nodeCodeFs } = await import('./session-3OBIQLE4.js');
@@ -6238,11 +6463,11 @@ function registerCode(program) {
6238
6463
  const { loadOrDiscoverFederation } = await import('./federation-MDQPO3PW.js');
6239
6464
  const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
6240
6465
  const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
6241
- const { startCodeRuntimeSession } = await import('./runtime-session-Y4ZD3QDO.js');
6466
+ const { startCodeRuntimeSession } = await import('./runtime-session-PZKXBDJT.js');
6242
6467
  const { resolveGraphBackend } = await import('./graph-backend-G5Y6QQV4.js');
6243
6468
  const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
6244
6469
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
6245
- const { vgdRequest: vgdRequest2 } = await import('./vgd-DH7AHQ23.js');
6470
+ const { vgdRequest: vgdRequest2 } = await import('./vgd-Y2YCN75V.js');
6246
6471
  const federation = loadOrDiscoverFederation(root2);
6247
6472
  const modelProfile = mergeModelExecutionProfile(
6248
6473
  resolveModelExecutionProfile({
@@ -6300,7 +6525,7 @@ ${res.stderr}` : ""),
6300
6525
  exitCode: res.status ?? 1
6301
6526
  };
6302
6527
  };
6303
- const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-PZFGTZSA.js');
6528
+ const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-7NNVIVO7.js');
6304
6529
  const vgBuiltin = createVgBuiltinMcpTools({
6305
6530
  getGraph: () => graph,
6306
6531
  root: root2,
@@ -6536,7 +6761,7 @@ ${res.stderr}` : ""),
6536
6761
  if (!autonomous && !tty) {
6537
6762
  throw usageError("the agent approves each edit/command \u2014 run in a terminal to approve interactively, or pass --auto to run autonomously (or --single for a one-shot diff).");
6538
6763
  }
6539
- const { agentTask } = await import('./interactive-NJG6467J.js');
6764
+ const { agentTask } = await import('./interactive-V6IRYZTA.js');
6540
6765
  const { nodeCodeFs } = await import('./session-3OBIQLE4.js');
6541
6766
  const { TtyPrompter } = await import('./ui-K7D3BCHD.js');
6542
6767
  let priorSummary;
@@ -6546,7 +6771,7 @@ ${res.stderr}` : ""),
6546
6771
  if (prev) priorSummary = summarizeSession(prev);
6547
6772
  }
6548
6773
  const prompter = tty ? new TtyPrompter() : void 0;
6549
- const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-PZFGTZSA.js');
6774
+ const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-7NNVIVO7.js');
6550
6775
  const vgBuiltin = createVgBuiltinMcpTools({
6551
6776
  getGraph: () => graph,
6552
6777
  root: root2,
@@ -6570,11 +6795,11 @@ ${res.stderr}` : ""),
6570
6795
  const { loadFederation } = await import('./federation-MDQPO3PW.js');
6571
6796
  const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
6572
6797
  const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
6573
- const { startCodeRuntimeSession } = await import('./runtime-session-Y4ZD3QDO.js');
6798
+ const { startCodeRuntimeSession } = await import('./runtime-session-PZKXBDJT.js');
6574
6799
  const { resolveGraphBackend } = await import('./graph-backend-G5Y6QQV4.js');
6575
6800
  const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
6576
6801
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
6577
- const { vgdRequest: vgdRequest2 } = await import('./vgd-DH7AHQ23.js');
6802
+ const { vgdRequest: vgdRequest2 } = await import('./vgd-Y2YCN75V.js');
6578
6803
  const federation = loadFederation(root2);
6579
6804
  const modelProfile = mergeModelExecutionProfile(
6580
6805
  resolveModelExecutionProfile({
@@ -7464,7 +7689,7 @@ function registerDaemon(program) {
7464
7689
  throw new CliError(loaded.error, ExitCode.NOT_FOUND);
7465
7690
  }
7466
7691
  if (!loaded.ok) {
7467
- const { loadGraph: loadGraph2 } = await import('./load-YPSEDYIW.js');
7692
+ const { loadGraph: loadGraph2 } = await import('./load-KPHH26ND.js');
7468
7693
  const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
7469
7694
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
7470
7695
  const graph = loadGraph2(root2, global.graph);
@@ -7869,7 +8094,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
7869
8094
  console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold("vibgrate.config.ts")}`);
7870
8095
  }
7871
8096
  if (opts.baseline) {
7872
- const { runBaseline } = await import('./baseline-V6MYDEMS.js');
8097
+ const { runBaseline } = await import('./baseline-4FBHW2X2.js');
7873
8098
  await runBaseline(rootDir);
7874
8099
  }
7875
8100
  console.log("");
@@ -7971,11 +8196,42 @@ function collectPackageImports(graph, ecosystem, pkg) {
7971
8196
  importingFiles: [...files].sort()
7972
8197
  };
7973
8198
  }
7974
- async function fileReferencesIdentifier(rootDir, relFile, identifier, readFile3) {
8199
+ async function firstReferenceLine(rootDir, relFile, identifier, readFile3) {
7975
8200
  const content = await readFile3(path37.join(rootDir, relFile));
7976
- if (!content) return false;
8201
+ if (!content) return null;
7977
8202
  const escaped = identifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
7978
- return new RegExp(`\\b${escaped}\\b`).test(content);
8203
+ const re = new RegExp(`\\b${escaped}\\b`);
8204
+ const lines = content.split(/\r?\n/);
8205
+ for (let i = 0; i < lines.length; i++) {
8206
+ if (re.test(lines[i])) return i + 1;
8207
+ }
8208
+ return null;
8209
+ }
8210
+ function formatSitePath(site) {
8211
+ return site.line != null && site.line > 0 ? `${site.file}:${site.line}` : site.file;
8212
+ }
8213
+ function enclosingFunctionName(graph, relFile, line) {
8214
+ if (line == null || line < 1) return null;
8215
+ let best = null;
8216
+ let bestSpan = Number.POSITIVE_INFINITY;
8217
+ for (const node2 of graph.nodes) {
8218
+ if (node2.file !== relFile) continue;
8219
+ if (node2.kind !== "function" && node2.kind !== "method") continue;
8220
+ const start = node2.span?.start;
8221
+ const end = node2.span?.end;
8222
+ if (start == null || end == null) continue;
8223
+ if (line < start || line > end) continue;
8224
+ const span = end - start;
8225
+ if (span < bestSpan) {
8226
+ bestSpan = span;
8227
+ best = node2;
8228
+ }
8229
+ }
8230
+ return best?.name ?? null;
8231
+ }
8232
+ function sitesFromImportFiles(files, limit = 10) {
8233
+ const sites = files.slice(0, limit).map((file) => ({ file }));
8234
+ return { callPath: sites.map(formatSitePath), sites };
7979
8235
  }
7980
8236
  async function defaultReadFile(absPath) {
7981
8237
  try {
@@ -8058,6 +8314,7 @@ async function analyzeReachability(input) {
8058
8314
  }
8059
8315
  const matchableSymbols = entry.symbols.map((s) => ({ symbol: s.symbol, identifier: symbolIdentifier(s.symbol) })).filter((s) => isMatchableIdentifier(s.identifier));
8060
8316
  if (entry.symbolCoverage !== "function" || matchableSymbols.length === 0) {
8317
+ const { callPath, sites } = sitesFromImportFiles(evidence.importingFiles, 10);
8061
8318
  findings.push({
8062
8319
  advisoryId: entry.advisoryId,
8063
8320
  ecosystem: entry.ecosystem,
@@ -8065,7 +8322,8 @@ async function analyzeReachability(input) {
8065
8322
  version: entry.version,
8066
8323
  tier: "potentially_reachable",
8067
8324
  evidence: `${entry.package} is imported by ${evidence.importingFiles.length} file${evidence.importingFiles.length === 1 ? "" : "s"}; vulnerable symbols unresolved (coverage: ${entry.symbolCoverage})`,
8068
- callPath: evidence.importingFiles.slice(0, 10),
8325
+ callPath,
8326
+ sites,
8069
8327
  graphConfidence: Math.min(baseConfidence, 0.6)
8070
8328
  });
8071
8329
  continue;
@@ -8073,14 +8331,19 @@ async function analyzeReachability(input) {
8073
8331
  const filesToCheck = evidence.importingFiles.slice(0, MAX_FILES_PER_PACKAGE);
8074
8332
  let anySymbolFound = false;
8075
8333
  for (const { symbol, identifier } of matchableSymbols) {
8076
- const referencingFiles = [];
8334
+ const sites = [];
8077
8335
  for (const relFile of filesToCheck) {
8078
- if (await fileReferencesIdentifier(input.rootDir, relFile, identifier, readFile3)) {
8079
- referencingFiles.push(relFile);
8080
- if (referencingFiles.length >= 5) break;
8081
- }
8336
+ const line = await firstReferenceLine(input.rootDir, relFile, identifier, readFile3);
8337
+ if (line == null) continue;
8338
+ sites.push({
8339
+ file: relFile,
8340
+ line,
8341
+ symbol,
8342
+ function: enclosingFunctionName(input.graph, relFile, line)
8343
+ });
8344
+ if (sites.length >= 5) break;
8082
8345
  }
8083
- if (referencingFiles.length > 0) {
8346
+ if (sites.length > 0) {
8084
8347
  anySymbolFound = true;
8085
8348
  findings.push({
8086
8349
  advisoryId: entry.advisoryId,
@@ -8089,13 +8352,15 @@ async function analyzeReachability(input) {
8089
8352
  version: entry.version,
8090
8353
  symbol,
8091
8354
  tier: "reachable",
8092
- evidence: `vulnerable symbol \`${identifier}\` is referenced in ${referencingFiles.length} importing file${referencingFiles.length === 1 ? "" : "s"}`,
8093
- callPath: referencingFiles,
8355
+ evidence: `vulnerable symbol \`${identifier}\` is referenced in ${sites.length} importing file${sites.length === 1 ? "" : "s"}`,
8356
+ callPath: sites.map(formatSitePath),
8357
+ sites,
8094
8358
  graphConfidence: Math.min(baseConfidence, 0.75)
8095
8359
  });
8096
8360
  }
8097
8361
  }
8098
8362
  if (!anySymbolFound) {
8363
+ const { callPath, sites } = sitesFromImportFiles(evidence.importingFiles, 10);
8099
8364
  findings.push({
8100
8365
  advisoryId: entry.advisoryId,
8101
8366
  ecosystem: entry.ecosystem,
@@ -8103,7 +8368,8 @@ async function analyzeReachability(input) {
8103
8368
  version: entry.version,
8104
8369
  tier: "not_reached",
8105
8370
  evidence: `${entry.package} is imported, but none of its ${matchableSymbols.length} vulnerable symbol${matchableSymbols.length === 1 ? "" : "s"} is referenced in the ${filesToCheck.length} importing file${filesToCheck.length === 1 ? "" : "s"} checked`,
8106
- callPath: evidence.importingFiles.slice(0, 10),
8371
+ callPath,
8372
+ sites,
8107
8373
  graphConfidence: Math.min(baseConfidence, 0.55)
8108
8374
  });
8109
8375
  }