@vibgrate/cli 2026.730.2 → 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-536TQZIB.js.map → baseline-4FBHW2X2.js.map} +1 -1
  3. package/dist/chunk-2XTPGYR2.js +6 -0
  4. package/dist/{chunk-BZPZ3OM6.js.map → chunk-2XTPGYR2.js.map} +1 -1
  5. package/dist/{chunk-NSK25UT2.js → chunk-3NP2DO4G.js} +3 -3
  6. package/dist/{chunk-NSK25UT2.js.map → chunk-3NP2DO4G.js.map} +1 -1
  7. package/dist/{chunk-HWN4P64B.js → chunk-476KWSFM.js} +3 -3
  8. package/dist/{chunk-HWN4P64B.js.map → chunk-476KWSFM.js.map} +1 -1
  9. package/dist/{chunk-RV5DTGYT.js → chunk-C22ZY3FV.js} +3 -3
  10. package/dist/{chunk-RV5DTGYT.js.map → chunk-C22ZY3FV.js.map} +1 -1
  11. package/dist/{chunk-LCQILWQL.js → chunk-CWB6H553.js} +3 -3
  12. package/dist/{chunk-LCQILWQL.js.map → chunk-CWB6H553.js.map} +1 -1
  13. package/dist/{chunk-PHVVVOW7.js → chunk-DXSEG6SZ.js} +3 -3
  14. package/dist/{chunk-PHVVVOW7.js.map → chunk-DXSEG6SZ.js.map} +1 -1
  15. package/dist/{chunk-UPH2RJ7L.js → chunk-GPDJOCUI.js} +23 -6
  16. package/dist/chunk-GPDJOCUI.js.map +1 -0
  17. package/dist/{chunk-WHXVU23K.js → chunk-J3BQ7FIT.js} +7 -7
  18. package/dist/{chunk-WHXVU23K.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-EGCB5K3P.js → chunk-SE4JMB4W.js} +3 -3
  22. package/dist/{chunk-EGCB5K3P.js.map → chunk-SE4JMB4W.js.map} +1 -1
  23. package/dist/{chunk-A5LF4VS4.js → chunk-SKIMUFCI.js} +6 -6
  24. package/dist/{chunk-A5LF4VS4.js.map → chunk-SKIMUFCI.js.map} +1 -1
  25. package/dist/{chunk-ZW5W627G.js → chunk-T7OFJS3X.js} +7 -7
  26. package/dist/{chunk-ZW5W627G.js.map → chunk-T7OFJS3X.js.map} +1 -1
  27. package/dist/{chunk-CPX7XP3O.js → chunk-UVMP7DFF.js} +11 -11
  28. package/dist/{chunk-CPX7XP3O.js.map → chunk-UVMP7DFF.js.map} +1 -1
  29. package/dist/cli.js +287 -65
  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-MR7DTVYS.js → interactive-V6IRYZTA.js} +13 -13
  36. package/dist/{interactive-MR7DTVYS.js.map → interactive-V6IRYZTA.js.map} +1 -1
  37. package/dist/load-KPHH26ND.js +10 -0
  38. package/dist/{load-RFQFTTIT.js.map → load-KPHH26ND.js.map} +1 -1
  39. package/dist/{run-outcome-EKB6YQIK.js → run-outcome-TZ53G67B.js} +5 -5
  40. package/dist/{run-outcome-EKB6YQIK.js.map → run-outcome-TZ53G67B.js.map} +1 -1
  41. package/dist/{runtime-session-23RZLEA4.js → runtime-session-PZKXBDJT.js} +7 -7
  42. package/dist/{runtime-session-23RZLEA4.js.map → runtime-session-PZKXBDJT.js.map} +1 -1
  43. package/dist/{vg-mcp-bridge-UZFHPP2Q.js → vg-mcp-bridge-7NNVIVO7.js} +6 -6
  44. package/dist/{vg-mcp-bridge-UZFHPP2Q.js.map → vg-mcp-bridge-7NNVIVO7.js.map} +1 -1
  45. package/dist/{vgd-VIPBL7W4.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-536TQZIB.js +0 -9
  49. package/dist/chunk-BZPZ3OM6.js +0 -6
  50. package/dist/chunk-IDAQV3NQ.js.map +0 -1
  51. package/dist/chunk-UPH2RJ7L.js.map +0 -1
  52. package/dist/fs-HNR6LAI7.js.map +0 -1
  53. package/dist/load-RFQFTTIT.js +0 -10
  54. package/dist/vgd-VIPBL7W4.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-ZW5W627G.js';
3
- export { runBuild } from './chunk-ZW5W627G.js';
4
- import { telemetryOptOut, StatsSharer, statsEndpoint, isCI } from './chunk-LCQILWQL.js';
5
- import { loadAdvancedScanHook, baselineCommand } from './chunk-UPH2RJ7L.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-NSK25UT2.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-WHXVU23K.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-A5LF4VS4.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-RV5DTGYT.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, perDependencyDrift } from './chunk-CPX7XP3O.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-HWN4P64B.js';
43
- import { resolveGraphPath, renderReport, loadGraphFileWithSnapshot, writeArtifacts, vibgrateDir, mapFileExists, ensureVibgrateGitignore } from './chunk-PHVVVOW7.js';
44
- import { VERSION } from './chunk-BZPZ3OM6.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,
@@ -2335,6 +2362,7 @@ var VibgrateLanguageServer = class {
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));
2337
2364
  this.conn.onRequest("vibgrate/score/forProject", (_m, params) => this.onScoreForProject(params));
2365
+ this.conn.onRequest("vibgrate/architecture", (_m, params) => this.onArchitecture(params));
2338
2366
  this.conn.onRequest("vibgrate/score/history", (_m, params) => {
2339
2367
  const p = params;
2340
2368
  const days = typeof p?.days === "number" && p.days > 0 && p.days <= 365 ? p.days : 90;
@@ -2456,7 +2484,7 @@ var VibgrateLanguageServer = class {
2456
2484
  ...delta !== void 0 ? { delta } : {},
2457
2485
  ...buildBreakdown(a.drift, a.projects ?? []) ? { breakdown: buildBreakdown(a.drift, a.projects ?? []) } : {},
2458
2486
  ...buildEolHorizon(a.projects ?? []) ? { eolHorizon: buildEolHorizon(a.projects ?? []) } : {},
2459
- ...buildProjectRefs(a.projects ?? []) ? { projects: buildProjectRefs(a.projects ?? []) } : {}
2487
+ ...buildProjectRefs(this.opts.root, a.projects ?? []) ? { projects: buildProjectRefs(this.opts.root, a.projects ?? []) } : {}
2460
2488
  };
2461
2489
  this.conn.notify("vibgrate/score", payload);
2462
2490
  }
@@ -2639,7 +2667,7 @@ var VibgrateLanguageServer = class {
2639
2667
  kevSource: "skipped"
2640
2668
  };
2641
2669
  }
2642
- const reachedPkgs = packageReachSet(this.graph);
2670
+ const importMap = packageImportMap(this.graph);
2643
2671
  const targets = [];
2644
2672
  for (const proj of a.projects ?? []) {
2645
2673
  if (isPrunedWorkspacePath(proj.path) || isPrunedWorkspacePath(manifestRelativePath(proj))) {
@@ -2664,8 +2692,22 @@ var VibgrateLanguageServer = class {
2664
2692
  if (l >= 0) line = l + 1;
2665
2693
  }
2666
2694
  let reachability = "unknown";
2667
- if (reachedPkgs) {
2668
- 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
+ }
2669
2711
  }
2670
2712
  targets.push({
2671
2713
  ecosystem,
@@ -2675,7 +2717,9 @@ var VibgrateLanguageServer = class {
2675
2717
  line,
2676
2718
  section: dep.section ?? null,
2677
2719
  latestStable: dep.latestStable ?? null,
2678
- reachability
2720
+ reachability,
2721
+ reachSites,
2722
+ reachEvidence
2679
2723
  });
2680
2724
  }
2681
2725
  }
@@ -2686,7 +2730,7 @@ var VibgrateLanguageServer = class {
2686
2730
  const a = this.artifact;
2687
2731
  if (!a || !p.uri) return null;
2688
2732
  const project = projectForFile(this.opts.root, a, uriToPath(p.uri));
2689
- return project ? scoreForProject(a, project) : null;
2733
+ return project ? scoreForProject(this.opts.root, a, project) : null;
2690
2734
  }
2691
2735
  /**
2692
2736
  * `vibgrate/score/forProject` — monorepo scope picker. Returns the same
@@ -2697,7 +2741,42 @@ var VibgrateLanguageServer = class {
2697
2741
  const a = this.artifact;
2698
2742
  if (!a || typeof p.path !== "string") return null;
2699
2743
  const project = projectByPath(a, p.path);
2700
- return project ? scoreForProject(a, project) : null;
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
+ };
2701
2780
  }
2702
2781
  };
2703
2782
  function uriToPath(uri) {
@@ -2733,14 +2812,17 @@ function projectByPath(a, projectPath) {
2733
2812
  }
2734
2813
  return void 0;
2735
2814
  }
2736
- function buildProjectRefs(projects) {
2815
+ function buildProjectRefs(rootDir, projects) {
2737
2816
  if (projects.length === 0) return void 0;
2738
2817
  return projects.map((p) => {
2739
2818
  const rel = p.path === "" ? "." : p.path;
2740
2819
  const base = rel === "." ? "." : path37.basename(rel);
2820
+ const lockfilePath = lockfileRelativePath(rootDir, p);
2741
2821
  return {
2742
2822
  path: rel,
2743
2823
  name: p.name || base,
2824
+ manifestPath: manifestRelativePath(p),
2825
+ ...lockfilePath ? { lockfilePath } : {},
2744
2826
  ...p.drift ? {
2745
2827
  score: p.drift.score,
2746
2828
  band: p.drift.riskLevel ?? "low",
@@ -2773,7 +2855,7 @@ function hasReleaseDates(a) {
2773
2855
  }
2774
2856
  return false;
2775
2857
  }
2776
- function scoreForProject(a, proj) {
2858
+ function scoreForProject(rootDir, a, proj) {
2777
2859
  if (!proj.drift) return null;
2778
2860
  let behind = 0;
2779
2861
  let total = 0;
@@ -2798,7 +2880,7 @@ function scoreForProject(a, proj) {
2798
2880
  scannedAt: a.timestamp,
2799
2881
  ...buildBreakdown(proj.drift, [proj]) ? { breakdown: buildBreakdown(proj.drift, [proj]) } : {},
2800
2882
  ...buildEolHorizon([proj]) ? { eolHorizon: buildEolHorizon([proj]) } : {},
2801
- ...buildProjectRefs(a.projects ?? []) ? { projects: buildProjectRefs(a.projects ?? []) } : {}
2883
+ ...buildProjectRefs(rootDir, a.projects ?? []) ? { projects: buildProjectRefs(rootDir, a.projects ?? []) } : {}
2802
2884
  };
2803
2885
  }
2804
2886
  function runtimeHorizonLabel(project) {
@@ -2895,30 +2977,129 @@ function manifestRelativePath(proj) {
2895
2977
  return join27("package.json");
2896
2978
  }
2897
2979
  }
2898
- 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) {
2899
3018
  if (!graph?.nodes?.length) return null;
2900
- 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
+ }
2901
3051
  for (const n of graph.nodes) {
2902
3052
  if (n.kind !== "external" && n.kind !== "package" && n.kind !== "module") continue;
2903
- const names = [n.name, n.qualifiedName].filter(Boolean);
2904
- for (const raw of names) {
2905
- 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());
2906
3056
  if (cleaned.startsWith("@")) {
2907
3057
  const parts = cleaned.split("/");
2908
- if (parts.length >= 2) set.add(`${parts[0]}/${parts[1]}`.toLowerCase());
2909
- } else {
2910
- 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
+ }
2911
3061
  }
2912
- set.add(cleaned.toLowerCase());
2913
3062
  }
2914
3063
  }
2915
- 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;
2916
3069
  }
2917
- function packageReached(set, pkg) {
3070
+ function lookupImportFiles(map, pkg) {
2918
3071
  const p = pkg.toLowerCase();
2919
- if (set.has(p)) return true;
2920
- if (!p.startsWith("@") && set.has(p.split("/")[0])) return true;
2921
- 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;
2922
3103
  }
2923
3104
  function osvEcosystem(type) {
2924
3105
  switch (type) {
@@ -6108,7 +6289,7 @@ function registerCode(program) {
6108
6289
  try {
6109
6290
  const { parseMode: parseMode2, resolveMode: resolveMode2, readOrchestratorState: readOrchestratorState2, activePin: activePin2 } = await import('./model-orchestrator-LHYPJBFH.js');
6110
6291
  const { gatherSystemMemory: gatherSystemMemory2 } = await import('./local-runtime-2ED33KK6.js');
6111
- const { loadGraph: loadGraph2 } = await import('./load-RFQFTTIT.js');
6292
+ const { loadGraph: loadGraph2 } = await import('./load-KPHH26ND.js');
6112
6293
  const state = readOrchestratorState2();
6113
6294
  const mode = parseMode2(modeFlag) ?? state.defaultMode ?? void 0;
6114
6295
  const pin = mode ? activePin2(mode, state) : null;
@@ -6192,7 +6373,7 @@ function registerCode(program) {
6192
6373
  if (!(process.stdin.isTTY && process.stdout.isTTY)) {
6193
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)');
6194
6375
  }
6195
- const { runInteractive } = await import('./interactive-MR7DTVYS.js');
6376
+ const { runInteractive } = await import('./interactive-V6IRYZTA.js');
6196
6377
  await runInteractive(
6197
6378
  rootOf(global),
6198
6379
  global,
@@ -6273,7 +6454,7 @@ function registerCode(program) {
6273
6454
  process.stdout.write(JSON.stringify(line) + "\n");
6274
6455
  };
6275
6456
  try {
6276
- const { RunOutcomeRecorder, newOneShotRunId, turnRunId } = await import('./run-outcome-EKB6YQIK.js');
6457
+ const { RunOutcomeRecorder, newOneShotRunId, turnRunId } = await import('./run-outcome-TZ53G67B.js');
6277
6458
  const primarySlug = route.providers[0]?.model.includes("/") ? route.providers[0].model.split("/")[0] : route.providers[0]?.id;
6278
6459
  const { runCodeStreamJson, parseHostMessage } = await import('./stream-json-3YOPU3LF.js');
6279
6460
  const { nodeCodeFs } = await import('./session-3OBIQLE4.js');
@@ -6282,11 +6463,11 @@ function registerCode(program) {
6282
6463
  const { loadOrDiscoverFederation } = await import('./federation-MDQPO3PW.js');
6283
6464
  const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
6284
6465
  const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
6285
- const { startCodeRuntimeSession } = await import('./runtime-session-23RZLEA4.js');
6466
+ const { startCodeRuntimeSession } = await import('./runtime-session-PZKXBDJT.js');
6286
6467
  const { resolveGraphBackend } = await import('./graph-backend-G5Y6QQV4.js');
6287
6468
  const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
6288
6469
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
6289
- const { vgdRequest: vgdRequest2 } = await import('./vgd-VIPBL7W4.js');
6470
+ const { vgdRequest: vgdRequest2 } = await import('./vgd-Y2YCN75V.js');
6290
6471
  const federation = loadOrDiscoverFederation(root2);
6291
6472
  const modelProfile = mergeModelExecutionProfile(
6292
6473
  resolveModelExecutionProfile({
@@ -6344,7 +6525,7 @@ ${res.stderr}` : ""),
6344
6525
  exitCode: res.status ?? 1
6345
6526
  };
6346
6527
  };
6347
- const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-UZFHPP2Q.js');
6528
+ const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-7NNVIVO7.js');
6348
6529
  const vgBuiltin = createVgBuiltinMcpTools({
6349
6530
  getGraph: () => graph,
6350
6531
  root: root2,
@@ -6580,7 +6761,7 @@ ${res.stderr}` : ""),
6580
6761
  if (!autonomous && !tty) {
6581
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).");
6582
6763
  }
6583
- const { agentTask } = await import('./interactive-MR7DTVYS.js');
6764
+ const { agentTask } = await import('./interactive-V6IRYZTA.js');
6584
6765
  const { nodeCodeFs } = await import('./session-3OBIQLE4.js');
6585
6766
  const { TtyPrompter } = await import('./ui-K7D3BCHD.js');
6586
6767
  let priorSummary;
@@ -6590,7 +6771,7 @@ ${res.stderr}` : ""),
6590
6771
  if (prev) priorSummary = summarizeSession(prev);
6591
6772
  }
6592
6773
  const prompter = tty ? new TtyPrompter() : void 0;
6593
- const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-UZFHPP2Q.js');
6774
+ const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-7NNVIVO7.js');
6594
6775
  const vgBuiltin = createVgBuiltinMcpTools({
6595
6776
  getGraph: () => graph,
6596
6777
  root: root2,
@@ -6614,11 +6795,11 @@ ${res.stderr}` : ""),
6614
6795
  const { loadFederation } = await import('./federation-MDQPO3PW.js');
6615
6796
  const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
6616
6797
  const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
6617
- const { startCodeRuntimeSession } = await import('./runtime-session-23RZLEA4.js');
6798
+ const { startCodeRuntimeSession } = await import('./runtime-session-PZKXBDJT.js');
6618
6799
  const { resolveGraphBackend } = await import('./graph-backend-G5Y6QQV4.js');
6619
6800
  const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
6620
6801
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
6621
- const { vgdRequest: vgdRequest2 } = await import('./vgd-VIPBL7W4.js');
6802
+ const { vgdRequest: vgdRequest2 } = await import('./vgd-Y2YCN75V.js');
6622
6803
  const federation = loadFederation(root2);
6623
6804
  const modelProfile = mergeModelExecutionProfile(
6624
6805
  resolveModelExecutionProfile({
@@ -7508,7 +7689,7 @@ function registerDaemon(program) {
7508
7689
  throw new CliError(loaded.error, ExitCode.NOT_FOUND);
7509
7690
  }
7510
7691
  if (!loaded.ok) {
7511
- const { loadGraph: loadGraph2 } = await import('./load-RFQFTTIT.js');
7692
+ const { loadGraph: loadGraph2 } = await import('./load-KPHH26ND.js');
7512
7693
  const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
7513
7694
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
7514
7695
  const graph = loadGraph2(root2, global.graph);
@@ -7913,7 +8094,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
7913
8094
  console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold("vibgrate.config.ts")}`);
7914
8095
  }
7915
8096
  if (opts.baseline) {
7916
- const { runBaseline } = await import('./baseline-536TQZIB.js');
8097
+ const { runBaseline } = await import('./baseline-4FBHW2X2.js');
7917
8098
  await runBaseline(rootDir);
7918
8099
  }
7919
8100
  console.log("");
@@ -8015,11 +8196,42 @@ function collectPackageImports(graph, ecosystem, pkg) {
8015
8196
  importingFiles: [...files].sort()
8016
8197
  };
8017
8198
  }
8018
- async function fileReferencesIdentifier(rootDir, relFile, identifier, readFile3) {
8199
+ async function firstReferenceLine(rootDir, relFile, identifier, readFile3) {
8019
8200
  const content = await readFile3(path37.join(rootDir, relFile));
8020
- if (!content) return false;
8201
+ if (!content) return null;
8021
8202
  const escaped = identifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
8022
- 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 };
8023
8235
  }
8024
8236
  async function defaultReadFile(absPath) {
8025
8237
  try {
@@ -8102,6 +8314,7 @@ async function analyzeReachability(input) {
8102
8314
  }
8103
8315
  const matchableSymbols = entry.symbols.map((s) => ({ symbol: s.symbol, identifier: symbolIdentifier(s.symbol) })).filter((s) => isMatchableIdentifier(s.identifier));
8104
8316
  if (entry.symbolCoverage !== "function" || matchableSymbols.length === 0) {
8317
+ const { callPath, sites } = sitesFromImportFiles(evidence.importingFiles, 10);
8105
8318
  findings.push({
8106
8319
  advisoryId: entry.advisoryId,
8107
8320
  ecosystem: entry.ecosystem,
@@ -8109,7 +8322,8 @@ async function analyzeReachability(input) {
8109
8322
  version: entry.version,
8110
8323
  tier: "potentially_reachable",
8111
8324
  evidence: `${entry.package} is imported by ${evidence.importingFiles.length} file${evidence.importingFiles.length === 1 ? "" : "s"}; vulnerable symbols unresolved (coverage: ${entry.symbolCoverage})`,
8112
- callPath: evidence.importingFiles.slice(0, 10),
8325
+ callPath,
8326
+ sites,
8113
8327
  graphConfidence: Math.min(baseConfidence, 0.6)
8114
8328
  });
8115
8329
  continue;
@@ -8117,14 +8331,19 @@ async function analyzeReachability(input) {
8117
8331
  const filesToCheck = evidence.importingFiles.slice(0, MAX_FILES_PER_PACKAGE);
8118
8332
  let anySymbolFound = false;
8119
8333
  for (const { symbol, identifier } of matchableSymbols) {
8120
- const referencingFiles = [];
8334
+ const sites = [];
8121
8335
  for (const relFile of filesToCheck) {
8122
- if (await fileReferencesIdentifier(input.rootDir, relFile, identifier, readFile3)) {
8123
- referencingFiles.push(relFile);
8124
- if (referencingFiles.length >= 5) break;
8125
- }
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;
8126
8345
  }
8127
- if (referencingFiles.length > 0) {
8346
+ if (sites.length > 0) {
8128
8347
  anySymbolFound = true;
8129
8348
  findings.push({
8130
8349
  advisoryId: entry.advisoryId,
@@ -8133,13 +8352,15 @@ async function analyzeReachability(input) {
8133
8352
  version: entry.version,
8134
8353
  symbol,
8135
8354
  tier: "reachable",
8136
- evidence: `vulnerable symbol \`${identifier}\` is referenced in ${referencingFiles.length} importing file${referencingFiles.length === 1 ? "" : "s"}`,
8137
- 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,
8138
8358
  graphConfidence: Math.min(baseConfidence, 0.75)
8139
8359
  });
8140
8360
  }
8141
8361
  }
8142
8362
  if (!anySymbolFound) {
8363
+ const { callPath, sites } = sitesFromImportFiles(evidence.importingFiles, 10);
8143
8364
  findings.push({
8144
8365
  advisoryId: entry.advisoryId,
8145
8366
  ecosystem: entry.ecosystem,
@@ -8147,7 +8368,8 @@ async function analyzeReachability(input) {
8147
8368
  version: entry.version,
8148
8369
  tier: "not_reached",
8149
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`,
8150
- callPath: evidence.importingFiles.slice(0, 10),
8371
+ callPath,
8372
+ sites,
8151
8373
  graphConfidence: Math.min(baseConfidence, 0.55)
8152
8374
  });
8153
8375
  }