@vibgrate/cli 2026.730.2 → 2026.731.2

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 (74) hide show
  1. package/dist/{agent-33BMKWJC.js → agent-6PPW5GIV.js} +4 -4
  2. package/dist/{agent-33BMKWJC.js.map → agent-6PPW5GIV.js.map} +1 -1
  3. package/dist/baseline-ZMHL6DXF.js +9 -0
  4. package/dist/{baseline-536TQZIB.js.map → baseline-ZMHL6DXF.js.map} +1 -1
  5. package/dist/{chunk-EGCB5K3P.js → chunk-4CGLQXSI.js} +3 -3
  6. package/dist/{chunk-EGCB5K3P.js.map → chunk-4CGLQXSI.js.map} +1 -1
  7. package/dist/chunk-4DZC3ADC.js +42 -0
  8. package/dist/chunk-4DZC3ADC.js.map +1 -0
  9. package/dist/chunk-4TC6RJ7U.js +326 -0
  10. package/dist/chunk-4TC6RJ7U.js.map +1 -0
  11. package/dist/{chunk-ZW5W627G.js → chunk-5J45MN3K.js} +13 -328
  12. package/dist/chunk-5J45MN3K.js.map +1 -0
  13. package/dist/{chunk-IDAQV3NQ.js → chunk-DT4KIVRI.js} +57 -17
  14. package/dist/chunk-DT4KIVRI.js.map +1 -0
  15. package/dist/{chunk-NSK25UT2.js → chunk-EX2SH5CT.js} +3 -3
  16. package/dist/{chunk-NSK25UT2.js.map → chunk-EX2SH5CT.js.map} +1 -1
  17. package/dist/{chunk-UPH2RJ7L.js → chunk-FF5ZQ6KI.js} +23 -6
  18. package/dist/chunk-FF5ZQ6KI.js.map +1 -0
  19. package/dist/{chunk-HWN4P64B.js → chunk-IZNOMGR6.js} +3 -3
  20. package/dist/{chunk-HWN4P64B.js.map → chunk-IZNOMGR6.js.map} +1 -1
  21. package/dist/chunk-L6BRBFBP.js +65 -0
  22. package/dist/chunk-L6BRBFBP.js.map +1 -0
  23. package/dist/{chunk-WHXVU23K.js → chunk-LZX5NH4V.js} +7 -7
  24. package/dist/{chunk-WHXVU23K.js.map → chunk-LZX5NH4V.js.map} +1 -1
  25. package/dist/chunk-NNB2H4BA.js +6 -0
  26. package/dist/{chunk-BZPZ3OM6.js.map → chunk-NNB2H4BA.js.map} +1 -1
  27. package/dist/{chunk-KGWEBM2J.js → chunk-Q7HUXIUF.js} +3 -3
  28. package/dist/{chunk-KGWEBM2J.js.map → chunk-Q7HUXIUF.js.map} +1 -1
  29. package/dist/{chunk-PHVVVOW7.js → chunk-QWOJO32H.js} +3 -3
  30. package/dist/{chunk-PHVVVOW7.js.map → chunk-QWOJO32H.js.map} +1 -1
  31. package/dist/{chunk-RV5DTGYT.js → chunk-RIWLXMMT.js} +3 -3
  32. package/dist/{chunk-RV5DTGYT.js.map → chunk-RIWLXMMT.js.map} +1 -1
  33. package/dist/{chunk-LCQILWQL.js → chunk-TNCD5VFX.js} +3 -3
  34. package/dist/{chunk-LCQILWQL.js.map → chunk-TNCD5VFX.js.map} +1 -1
  35. package/dist/{chunk-CPX7XP3O.js → chunk-XRN7DQGR.js} +11 -11
  36. package/dist/{chunk-CPX7XP3O.js.map → chunk-XRN7DQGR.js.map} +1 -1
  37. package/dist/{chunk-A5LF4VS4.js → chunk-Y44GPOBL.js} +41 -65
  38. package/dist/chunk-Y44GPOBL.js.map +1 -0
  39. package/dist/cli.d.ts +5 -1
  40. package/dist/cli.js +467 -86
  41. package/dist/cli.js.map +1 -1
  42. package/dist/ensure-map-C3NEC2GI.js +28 -0
  43. package/dist/ensure-map-C3NEC2GI.js.map +1 -0
  44. package/dist/fs-NTQUFCXV.js +4 -0
  45. package/dist/fs-NTQUFCXV.js.map +1 -0
  46. package/dist/index.d.ts +1 -1
  47. package/dist/index.js +10 -9
  48. package/dist/index.js.map +1 -1
  49. package/dist/{interactive-MR7DTVYS.js → interactive-2TAYVEHE.js} +19 -16
  50. package/dist/interactive-2TAYVEHE.js.map +1 -0
  51. package/dist/load-A5BGEQWP.js +10 -0
  52. package/dist/{load-RFQFTTIT.js.map → load-A5BGEQWP.js.map} +1 -1
  53. package/dist/{run-outcome-EKB6YQIK.js → run-outcome-OSIVMVT7.js} +5 -5
  54. package/dist/{run-outcome-EKB6YQIK.js.map → run-outcome-OSIVMVT7.js.map} +1 -1
  55. package/dist/{runtime-session-23RZLEA4.js → runtime-session-UPTC3E6N.js} +7 -7
  56. package/dist/{runtime-session-23RZLEA4.js.map → runtime-session-UPTC3E6N.js.map} +1 -1
  57. package/dist/{stream-json-3YOPU3LF.js → stream-json-CFKBL3MR.js} +4 -4
  58. package/dist/{stream-json-3YOPU3LF.js.map → stream-json-CFKBL3MR.js.map} +1 -1
  59. package/dist/{vg-mcp-bridge-UZFHPP2Q.js → vg-mcp-bridge-JHRKJBVT.js} +6 -6
  60. package/dist/{vg-mcp-bridge-UZFHPP2Q.js.map → vg-mcp-bridge-JHRKJBVT.js.map} +1 -1
  61. package/dist/{vgd-VIPBL7W4.js → vgd-HNPOSXKZ.js} +6 -6
  62. package/dist/vgd-HNPOSXKZ.js.map +1 -0
  63. package/package.json +1 -1
  64. package/dist/baseline-536TQZIB.js +0 -9
  65. package/dist/chunk-A5LF4VS4.js.map +0 -1
  66. package/dist/chunk-BZPZ3OM6.js +0 -6
  67. package/dist/chunk-IDAQV3NQ.js.map +0 -1
  68. package/dist/chunk-UPH2RJ7L.js.map +0 -1
  69. package/dist/chunk-ZW5W627G.js.map +0 -1
  70. package/dist/fs-HNR6LAI7.js +0 -4
  71. package/dist/fs-HNR6LAI7.js.map +0 -1
  72. package/dist/interactive-MR7DTVYS.js.map +0 -1
  73. package/dist/load-RFQFTTIT.js +0 -10
  74. package/dist/vgd-VIPBL7W4.js.map +0 -1
package/dist/cli.js CHANGED
@@ -1,12 +1,13 @@
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 { loadAdvancedScanHook, baselineCommand } from './chunk-FF5ZQ6KI.js';
3
+ import { fetchCatalog, resolveProviders } from './chunk-4TC6RJ7U.js';
4
+ import { VGD_PROTOCOL_VERSION, startVgdServer } from './chunk-EX2SH5CT.js';
5
+ import { telemetryOptOut, StatsSharer, statsEndpoint, isCI } from './chunk-TNCD5VFX.js';
6
6
  import { buildModelInstallPlan } from './chunk-WHJMS7XC.js';
7
7
  import { runCodeSession } from './chunk-WBMMRERH.js';
8
+ import { sha256Hex, generateKeypair, dssePae, DSSE_PAYLOAD_TYPE, keyId, registerBuild, readGlobal, applyGlobalOptions, ProgressBar, printLogo, runBuild } from './chunk-5J45MN3K.js';
9
+ export { runBuild } from './chunk-5J45MN3K.js';
8
10
  import { disableColor, info, c, json, out } from './chunk-CT5BS56U.js';
9
- import { VGD_PROTOCOL_VERSION, startVgdServer } from './chunk-NSK25UT2.js';
10
11
  import './chunk-5I4VSBWQ.js';
11
12
  import './chunk-IS7VTH2Q.js';
12
13
  import { init_resolve_ollama, gatherSystemMemory, resolveOllamaBinary, hasOllamaBinary, resolve_ollama_exports } from './chunk-OWSFZQOP.js';
@@ -15,7 +16,7 @@ import { fmt, estimateModelBytes } from './chunk-7N4Y3E47.js';
15
16
  import './chunk-IZDH67DX.js';
16
17
  import { defaultProcessEndpoint, startProcessHostServer, resolveInferenceIsolation } from './chunk-EVLS2M5G.js';
17
18
  import { clearHostSessionPool, acquireHostSession, generateOnSession, listHostSessions, hostSessionPoolSize } from './chunk-X634FZVG.js';
18
- import { CONTEXT_POLICY_VERSION, computeFcsReport, renderFcsReportMarkdown, createTrajectoryCollector, runAgent } from './chunk-KGWEBM2J.js';
19
+ import { CONTEXT_POLICY_VERSION, computeFcsReport, renderFcsReportMarkdown, createTrajectoryCollector, runAgent } from './chunk-Q7HUXIUF.js';
19
20
  import './chunk-543E6WDJ.js';
20
21
  import { summarizeDiffs, ScriptedProvider } from './chunk-MYM5VIJ4.js';
21
22
  import { ensurePackage, ensureUnavailableMessage } from './chunk-REIGWTTH.js';
@@ -23,15 +24,16 @@ import './chunk-RGEVBSLK.js';
23
24
  import { vgdSocketPath, vgdIsRunning, vgdRequest, vgdPidPath } from './chunk-RBIRXQR6.js';
24
25
  import { buildIdentifierTrieFromGraph } from './chunk-5HYCB55P.js';
25
26
  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';
27
+ import { serveStdio, exportGraph, GraphSource, createServer, formatForExt } from './chunk-LZX5NH4V.js';
28
+ import { refreshIfStale } from './chunk-L6BRBFBP.js';
29
+ import { CliError, ExitCode, driftCount, ASSISTANTS, detectAssistants, isAssistantInstalled, usageError, detectServeLaunch, installAssistant, writeNavigationConfig, uninstallAssistant, buildGraph, writeSnapshot, probeFreshness, discover, assistantById, SMALL_REPO_FILES, isSkippedDirName, SKIP_FILES, SKIP_DIRS } from './chunk-Y44GPOBL.js';
30
+ 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-RIWLXMMT.js';
31
+ 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-XRN7DQGR.js';
29
32
  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';
31
33
  import { ensureDir, pathExists, readJsonFile, writeTextFile, writeJsonFile } from './chunk-CRAMOEBE.js';
34
+ import { recordCliCall, CLI_TOOL_ALIASES, savingsLedgerPath, clearSavings, readSavings, readUsage, readModelSavings, CAPSULE_RANKING_VERSION, SAVINGS_TOOLS, sanitizeClient } from './chunk-US2DAKCM.js';
32
35
  import './chunk-IPICO2RV.js';
33
36
  import { inventory, enrichOnline, ECOSYSTEMS, catalogPath, libDir, loadCatalog, driftFor, addLibrary, resolveLib, libId, resolveVersion, readDoc, localPackageDocs, localApiSurface } from './chunk-FHJBGPJZ.js';
34
- import { recordCliCall, CLI_TOOL_ALIASES, savingsLedgerPath, clearSavings, readSavings, readUsage, readModelSavings, CAPSULE_RANKING_VERSION, SAVINGS_TOOLS, sanitizeClient } from './chunk-US2DAKCM.js';
35
37
  import { init_cli_invocation, resolveCliInvocation, NPX_INVOCATION } from './chunk-3LSG7Z4I.js';
36
38
  import { resolveOne } from './chunk-J7LKEB2R.js';
37
39
  import { embeddingsCached, resolveEmbedModel, loadEmbedder, getNodeEmbeddings, queryGraphSemantic, queryGraph, unavailableMessage, countPending, indexFor, impactOf, modelCacheInfo, clearModelCache } from './chunk-EETK7S43.js';
@@ -39,14 +41,14 @@ import { discoverModels } from './chunk-CQDUBAQY.js';
39
41
  import { freeBytesOnVolume, weightStoreDir, listCachedWeights, ensureWeightCached, catalogIntegrityReport } from './chunk-OV4KGXPD.js';
40
42
  import { resolvedGrammarFiles, grammarSetVersion } from './chunk-UTNNGKKX.js';
41
43
  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';
44
+ import { loadGraph, SCHEMA_VERSION } from './chunk-IZNOMGR6.js';
45
+ import { resolveGraphPath, renderReport, loadGraphFileWithSnapshot, writeArtifacts, vibgrateDir, mapFileExists, ensureVibgrateGitignore } from './chunk-QWOJO32H.js';
46
+ import { VERSION } from './chunk-NNB2H4BA.js';
45
47
  import { cacheDir, serializeGraph, stableStringify } from './chunk-ZKNB4YH4.js';
46
48
  import './chunk-BWPBB45M.js';
47
49
  import { canonicalize, hashString, hashBytes } from './chunk-JFGYT6BI.js';
48
50
  import './chunk-BPF3YX2U.js';
49
- import { pathExists as pathExists$1, parseExcludePatterns } from './chunk-IDAQV3NQ.js';
51
+ import { pathExists as pathExists$1, parseExcludePatterns } from './chunk-DT4KIVRI.js';
50
52
  import { __toCommonJS } from './chunk-Z6ZWNWWR.js';
51
53
  import * as fs7 from 'fs';
52
54
  import fs7__default, { realpathSync } from 'fs';
@@ -1707,7 +1709,7 @@ function manifestHash(root2) {
1707
1709
  for (const entry of entries) {
1708
1710
  const abs = path37.join(dir, entry.name);
1709
1711
  if (entry.isDirectory()) {
1710
- if (SKIP_DIRS.has(entry.name)) continue;
1712
+ if (isSkippedDirName(entry.name)) continue;
1711
1713
  walk2(abs);
1712
1714
  continue;
1713
1715
  }
@@ -1729,7 +1731,7 @@ function isDependencyFile(root2, filePath) {
1729
1731
  const rel = path37.relative(path37.resolve(root2), path37.resolve(filePath));
1730
1732
  if (rel === "" || rel.startsWith("..") || path37.isAbsolute(rel)) return false;
1731
1733
  const parts = rel.split(path37.sep);
1732
- if (parts.slice(0, -1).some((dir) => SKIP_DIRS.has(dir))) return false;
1734
+ if (parts.slice(0, -1).some((dir) => isSkippedDirName(dir))) return false;
1733
1735
  const base = parts[parts.length - 1].toLowerCase();
1734
1736
  return isManifest(filePath) || SKIP_FILES.has(base);
1735
1737
  }
@@ -2009,6 +2011,30 @@ function runTree(graph, params) {
2009
2011
  }
2010
2012
 
2011
2013
  // src/lsp/enrich.ts
2014
+ var REACH_RANK = {
2015
+ reached: 3,
2016
+ potentially_reachable: 2,
2017
+ unknown: 1,
2018
+ "not-observed": 0
2019
+ };
2020
+ function mergeReachability(a, b) {
2021
+ const left = a ?? "unknown";
2022
+ const right = b ?? "unknown";
2023
+ return REACH_RANK[right] > REACH_RANK[left] ? right : left;
2024
+ }
2025
+ function mergeReachSites(a, b) {
2026
+ const out2 = [];
2027
+ const seen = /* @__PURE__ */ new Set();
2028
+ for (const site of [...a ?? [], ...b ?? []]) {
2029
+ if (!site?.file) continue;
2030
+ const k = `${site.file}::${site.line ?? ""}::${site.symbol ?? ""}`;
2031
+ if (seen.has(k)) continue;
2032
+ seen.add(k);
2033
+ out2.push(site);
2034
+ if (out2.length >= 10) break;
2035
+ }
2036
+ return out2;
2037
+ }
2012
2038
  var OSV_QUERY_URL = "https://api.osv.dev/v1/query";
2013
2039
  var KEV_URL = "https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json";
2014
2040
  var cache = /* @__PURE__ */ new Map();
@@ -2171,10 +2197,11 @@ async function scanWorkspaceVulns(targets, opts = { offline: false }) {
2171
2197
  existing.locations.push(loc);
2172
2198
  }
2173
2199
  }
2174
- if (t.reachability === "reached") existing.reachability = "reached";
2175
- else if (t.reachability === "not-observed" && existing.reachability === "unknown") {
2176
- existing.reachability = "not-observed";
2200
+ existing.reachability = mergeReachability(existing.reachability, t.reachability);
2201
+ if (t.reachSites?.length) {
2202
+ existing.reachSites = mergeReachSites(existing.reachSites, t.reachSites);
2177
2203
  }
2204
+ if (!existing.reachEvidence && t.reachEvidence) existing.reachEvidence = t.reachEvidence;
2178
2205
  if (!existing.latestStable && t.latestStable) existing.latestStable = t.latestStable;
2179
2206
  if (!existing.section && t.section) existing.section = t.section;
2180
2207
  }
@@ -2195,10 +2222,14 @@ async function scanWorkspaceVulns(targets, opts = { offline: false }) {
2195
2222
  else if (r.source === "error") anyError = true;
2196
2223
  const locations = t.locations.length ? t.locations : t.file ? [{ file: t.file, line: t.line ?? null }] : [];
2197
2224
  const seenIds = /* @__PURE__ */ new Set();
2225
+ const seenCves = /* @__PURE__ */ new Set();
2198
2226
  for (const v of r.vulns) {
2199
2227
  if (seenIds.has(v.id)) continue;
2228
+ const cveKeys = (v.cves ?? []).map((c2) => c2.toUpperCase()).filter(Boolean);
2229
+ if (cveKeys.length && cveKeys.every((c2) => seenCves.has(c2))) continue;
2200
2230
  seenIds.add(v.id);
2201
- const kevHit = v.cves.some((c2) => kev.cves.has(c2.toUpperCase()));
2231
+ for (const c2 of cveKeys) seenCves.add(c2);
2232
+ const kevHit = cveKeys.some((c2) => kev.cves.has(c2));
2202
2233
  findings.push({
2203
2234
  package: t.package,
2204
2235
  version: t.version,
@@ -2211,6 +2242,8 @@ async function scanWorkspaceVulns(targets, opts = { offline: false }) {
2211
2242
  published: v.published,
2212
2243
  kev: kevHit,
2213
2244
  reachability: t.reachability ?? "unknown",
2245
+ reachSites: t.reachSites ?? [],
2246
+ reachEvidence: t.reachEvidence ?? null,
2214
2247
  file: locations[0]?.file ?? t.file ?? null,
2215
2248
  line: locations[0]?.line ?? t.line ?? null,
2216
2249
  locations,
@@ -2335,6 +2368,7 @@ var VibgrateLanguageServer = class {
2335
2368
  this.conn.onRequest("vibgrate/graph/query", (_m, params) => this.onGraphQuery(params));
2336
2369
  this.conn.onRequest("vibgrate/score/forFile", (_m, params) => this.onScoreForFile(params));
2337
2370
  this.conn.onRequest("vibgrate/score/forProject", (_m, params) => this.onScoreForProject(params));
2371
+ this.conn.onRequest("vibgrate/architecture", (_m, params) => this.onArchitecture(params));
2338
2372
  this.conn.onRequest("vibgrate/score/history", (_m, params) => {
2339
2373
  const p = params;
2340
2374
  const days = typeof p?.days === "number" && p.days > 0 && p.days <= 365 ? p.days : 90;
@@ -2454,9 +2488,9 @@ var VibgrateLanguageServer = class {
2454
2488
  rootPath: a.rootPath,
2455
2489
  scannedAt: a.timestamp,
2456
2490
  ...delta !== void 0 ? { delta } : {},
2457
- ...buildBreakdown(a.drift, a.projects ?? []) ? { breakdown: buildBreakdown(a.drift, a.projects ?? []) } : {},
2491
+ ...buildBreakdown(this.opts.root, a.projects ?? []) ? { breakdown: buildBreakdown(this.opts.root, a.projects ?? []) } : {},
2458
2492
  ...buildEolHorizon(a.projects ?? []) ? { eolHorizon: buildEolHorizon(a.projects ?? []) } : {},
2459
- ...buildProjectRefs(a.projects ?? []) ? { projects: buildProjectRefs(a.projects ?? []) } : {}
2493
+ ...buildProjectRefs(this.opts.root, a.projects ?? []) ? { projects: buildProjectRefs(this.opts.root, a.projects ?? []) } : {}
2460
2494
  };
2461
2495
  this.conn.notify("vibgrate/score", payload);
2462
2496
  }
@@ -2639,7 +2673,7 @@ var VibgrateLanguageServer = class {
2639
2673
  kevSource: "skipped"
2640
2674
  };
2641
2675
  }
2642
- const reachedPkgs = packageReachSet(this.graph);
2676
+ const importMap = packageImportMap(this.graph);
2643
2677
  const targets = [];
2644
2678
  for (const proj of a.projects ?? []) {
2645
2679
  if (isPrunedWorkspacePath(proj.path) || isPrunedWorkspacePath(manifestRelativePath(proj))) {
@@ -2664,8 +2698,22 @@ var VibgrateLanguageServer = class {
2664
2698
  if (l >= 0) line = l + 1;
2665
2699
  }
2666
2700
  let reachability = "unknown";
2667
- if (reachedPkgs) {
2668
- reachability = packageReached(reachedPkgs, dep.package) ? "reached" : "not-observed";
2701
+ let reachSites = [];
2702
+ let reachEvidence = null;
2703
+ if (importMap) {
2704
+ const files = lookupImportFiles(importMap, dep.package);
2705
+ if (files.length > 0) {
2706
+ reachability = "reached";
2707
+ reachSites = files.slice(0, 10).map((file) => ({
2708
+ file,
2709
+ // Best-effort first line that mentions the package name (import site).
2710
+ line: firstPackageMentionLine(this.opts.root, file, dep.package)
2711
+ }));
2712
+ reachEvidence = `${dep.package} is imported by ${files.length} file${files.length === 1 ? "" : "s"} in the code map`;
2713
+ } else {
2714
+ reachability = "not-observed";
2715
+ reachEvidence = `no import of ${dep.package} was found in the code map`;
2716
+ }
2669
2717
  }
2670
2718
  targets.push({
2671
2719
  ecosystem,
@@ -2675,7 +2723,9 @@ var VibgrateLanguageServer = class {
2675
2723
  line,
2676
2724
  section: dep.section ?? null,
2677
2725
  latestStable: dep.latestStable ?? null,
2678
- reachability
2726
+ reachability,
2727
+ reachSites,
2728
+ reachEvidence
2679
2729
  });
2680
2730
  }
2681
2731
  }
@@ -2686,7 +2736,7 @@ var VibgrateLanguageServer = class {
2686
2736
  const a = this.artifact;
2687
2737
  if (!a || !p.uri) return null;
2688
2738
  const project = projectForFile(this.opts.root, a, uriToPath(p.uri));
2689
- return project ? scoreForProject(a, project) : null;
2739
+ return project ? scoreForProject(this.opts.root, a, project) : null;
2690
2740
  }
2691
2741
  /**
2692
2742
  * `vibgrate/score/forProject` — monorepo scope picker. Returns the same
@@ -2697,7 +2747,42 @@ var VibgrateLanguageServer = class {
2697
2747
  const a = this.artifact;
2698
2748
  if (!a || typeof p.path !== "string") return null;
2699
2749
  const project = projectByPath(a, p.path);
2700
- return project ? scoreForProject(a, project) : null;
2750
+ return project ? scoreForProject(this.opts.root, a, project) : null;
2751
+ }
2752
+ /**
2753
+ * `vibgrate/architecture` — the Architecture panel. `path` absent or
2754
+ * `'__repo__'` returns the whole-workspace aggregate (`extended.architecture`);
2755
+ * a project path returns that project's own detection (`ProjectScan.architecture`).
2756
+ * Returns `null` when the scanner hasn't produced architecture data yet (still
2757
+ * scanning, or the archetype/layer scanner is disabled) rather than an empty
2758
+ * shape a client might mistake for "no layers detected".
2759
+ */
2760
+ onArchitecture(params) {
2761
+ const p = params;
2762
+ const a = this.artifact;
2763
+ if (!a) return null;
2764
+ if (!p?.path || p.path === "__repo__") {
2765
+ const arch = a.extended?.architecture;
2766
+ if (!arch) return null;
2767
+ return {
2768
+ archetype: arch.archetype,
2769
+ archetypeConfidence: arch.archetypeConfidence,
2770
+ layers: arch.layers,
2771
+ totalClassified: arch.totalClassified,
2772
+ unclassified: arch.unclassified
2773
+ };
2774
+ }
2775
+ const project = projectByPath(a, p.path);
2776
+ if (!project?.architecture) return null;
2777
+ return {
2778
+ archetype: project.architecture.archetype,
2779
+ archetypeConfidence: project.architecture.archetypeConfidence,
2780
+ layers: project.architecture.layers,
2781
+ totalClassified: project.architecture.totalClassified,
2782
+ unclassified: project.architecture.unclassified,
2783
+ manifestPath: manifestRelativePath(project),
2784
+ lockfilePath: lockfileRelativePath(this.opts.root, project)
2785
+ };
2701
2786
  }
2702
2787
  };
2703
2788
  function uriToPath(uri) {
@@ -2711,7 +2796,11 @@ function isPrunedWorkspacePath(relPath) {
2711
2796
  if (!relPath || relPath === "." || relPath === "") return false;
2712
2797
  const parts = relPath.split(/[/\\]/).filter(Boolean);
2713
2798
  if (parts.includes(".claude")) return true;
2714
- return parts.some((p) => SKIP_DIRS.has(p));
2799
+ return parts.some((p) => {
2800
+ if (SKIP_DIRS.has(p)) return true;
2801
+ if (p.startsWith(".venv") || p.startsWith("venv-") || p === "site-packages") return true;
2802
+ return false;
2803
+ });
2715
2804
  }
2716
2805
  function pruneArtifactProjects(a) {
2717
2806
  const projects = (a.projects ?? []).filter(
@@ -2733,14 +2822,83 @@ function projectByPath(a, projectPath) {
2733
2822
  }
2734
2823
  return void 0;
2735
2824
  }
2736
- function buildProjectRefs(projects) {
2825
+ function projectHasLocalLockOrCsproj(rootDir, proj) {
2826
+ const base = proj.path === "." || proj.path === "" ? "" : proj.path;
2827
+ const dirAbs = base ? path37.join(rootDir, base) : rootDir;
2828
+ const lockNames = (() => {
2829
+ switch (proj.type) {
2830
+ case "node":
2831
+ case "typescript":
2832
+ return ["pnpm-lock.yaml", "yarn.lock", "package-lock.json", "bun.lockb", "bun.lock"];
2833
+ case "python":
2834
+ return ["poetry.lock", "uv.lock", "Pipfile.lock"];
2835
+ case "go":
2836
+ return ["go.sum"];
2837
+ case "rust":
2838
+ return ["Cargo.lock"];
2839
+ case "ruby":
2840
+ return ["Gemfile.lock"];
2841
+ case "php":
2842
+ return ["composer.lock"];
2843
+ case "dotnet":
2844
+ return ["packages.lock.json"];
2845
+ case "dart":
2846
+ return ["pubspec.lock"];
2847
+ case "java":
2848
+ case "kotlin":
2849
+ case "scala":
2850
+ case "groovy":
2851
+ return ["gradle.lockfile"];
2852
+ default:
2853
+ return [
2854
+ "pnpm-lock.yaml",
2855
+ "yarn.lock",
2856
+ "package-lock.json",
2857
+ "bun.lockb",
2858
+ "poetry.lock",
2859
+ "uv.lock",
2860
+ "Cargo.lock",
2861
+ "go.sum",
2862
+ "Gemfile.lock",
2863
+ "composer.lock",
2864
+ "packages.lock.json",
2865
+ "pubspec.lock"
2866
+ ];
2867
+ }
2868
+ })();
2869
+ for (const name of lockNames) {
2870
+ try {
2871
+ if (fs7.existsSync(path37.join(dirAbs, name))) return true;
2872
+ } catch {
2873
+ }
2874
+ }
2875
+ try {
2876
+ if (fs7.existsSync(dirAbs)) {
2877
+ const entries = fs7.readdirSync(dirAbs);
2878
+ if (entries.some((e) => /\.(csproj|fsproj|vbproj)$/i.test(e))) return true;
2879
+ }
2880
+ } catch {
2881
+ }
2882
+ const manifest = manifestRelativePath(proj);
2883
+ if (/\.(csproj|fsproj|vbproj)$/i.test(manifest)) {
2884
+ try {
2885
+ if (fs7.existsSync(path37.join(rootDir, manifest))) return true;
2886
+ } catch {
2887
+ }
2888
+ }
2889
+ return false;
2890
+ }
2891
+ function buildProjectRefs(rootDir, projects) {
2737
2892
  if (projects.length === 0) return void 0;
2738
- return projects.map((p) => {
2893
+ const refs = projects.filter((p) => projectHasLocalLockOrCsproj(rootDir, p)).map((p) => {
2739
2894
  const rel = p.path === "" ? "." : p.path;
2740
- const base = rel === "." ? "." : path37.basename(rel);
2895
+ const base = rel === "." || rel === "" ? "root" : path37.basename(rel);
2896
+ const lockfilePath = lockfileRelativePath(rootDir, p);
2741
2897
  return {
2742
2898
  path: rel,
2743
- name: p.name || base,
2899
+ name: base,
2900
+ manifestPath: manifestRelativePath(p),
2901
+ ...lockfilePath ? { lockfilePath } : {},
2744
2902
  ...p.drift ? {
2745
2903
  score: p.drift.score,
2746
2904
  band: p.drift.riskLevel ?? "low",
@@ -2748,6 +2906,7 @@ function buildProjectRefs(projects) {
2748
2906
  } : {}
2749
2907
  };
2750
2908
  }).sort((a, b) => a.path.localeCompare(b.path));
2909
+ return refs.length > 0 ? refs : void 0;
2751
2910
  }
2752
2911
  function projectForFile(root2, a, filePath) {
2753
2912
  const dir = path37.dirname(path37.resolve(filePath));
@@ -2773,7 +2932,7 @@ function hasReleaseDates(a) {
2773
2932
  }
2774
2933
  return false;
2775
2934
  }
2776
- function scoreForProject(a, proj) {
2935
+ function scoreForProject(rootDir, a, proj) {
2777
2936
  if (!proj.drift) return null;
2778
2937
  let behind = 0;
2779
2938
  let total = 0;
@@ -2796,9 +2955,9 @@ function scoreForProject(a, proj) {
2796
2955
  counts: { behind, eol, unmaintained, total },
2797
2956
  rootPath: proj.path === "" ? "." : proj.path,
2798
2957
  scannedAt: a.timestamp,
2799
- ...buildBreakdown(proj.drift, [proj]) ? { breakdown: buildBreakdown(proj.drift, [proj]) } : {},
2958
+ ...buildBreakdown(rootDir, [proj]) ? { breakdown: buildBreakdown(rootDir, [proj]) } : {},
2800
2959
  ...buildEolHorizon([proj]) ? { eolHorizon: buildEolHorizon([proj]) } : {},
2801
- ...buildProjectRefs(a.projects ?? []) ? { projects: buildProjectRefs(a.projects ?? []) } : {}
2960
+ ...buildProjectRefs(rootDir, a.projects ?? []) ? { projects: buildProjectRefs(rootDir, a.projects ?? []) } : {}
2802
2961
  };
2803
2962
  }
2804
2963
  function runtimeHorizonLabel(project) {
@@ -2827,17 +2986,52 @@ function bandForScore(n) {
2827
2986
  if (n <= 60) return "moderate";
2828
2987
  return "high";
2829
2988
  }
2830
- function buildBreakdown(_drift, projects) {
2989
+ function buildBreakdown(rootDir, projects) {
2831
2990
  const byPkg = /* @__PURE__ */ new Map();
2832
2991
  for (const p of projects) {
2992
+ const relManifest = manifestRelativePath(p);
2993
+ if (isPrunedWorkspacePath(p.path) || isPrunedWorkspacePath(relManifest)) continue;
2833
2994
  const ecosystem = osvEcosystem(p.type);
2995
+ const absManifest = path37.resolve(rootDir, relManifest);
2996
+ let text = null;
2997
+ try {
2998
+ if (fs7.existsSync(absManifest)) text = fs7.readFileSync(absManifest, "utf8");
2999
+ } catch {
3000
+ text = null;
3001
+ }
3002
+ const kind = manifestKind(absManifest);
2834
3003
  for (const d of p.dependencies ?? []) {
2835
- if (!byPkg.has(d.package)) byPkg.set(d.package, { row: d, ecosystem });
3004
+ let line = null;
3005
+ if (text && kind !== "unknown") {
3006
+ const l = findPackageLine(text, d.package, kind);
3007
+ if (l >= 0) line = l + 1;
3008
+ }
3009
+ const loc = { file: relManifest, line };
3010
+ const existing = byPkg.get(d.package);
3011
+ if (!existing) {
3012
+ byPkg.set(d.package, { row: d, ecosystem, locations: [loc] });
3013
+ continue;
3014
+ }
3015
+ if (!existing.locations.some((x) => x.file === loc.file && x.line === loc.line)) {
3016
+ existing.locations.push(loc);
3017
+ }
3018
+ const prev = perDependencyDrift(existing.row, {
3019
+ unsupported: existing.row.unsupported === true,
3020
+ abandoned: existing.row.abandoned === true
3021
+ });
3022
+ const next2 = perDependencyDrift(d, {
3023
+ unsupported: d.unsupported === true,
3024
+ abandoned: d.abandoned === true
3025
+ });
3026
+ if (!next2.excluded && (prev.excluded || next2.drift > prev.drift)) {
3027
+ existing.row = d;
3028
+ if (ecosystem) existing.ecosystem = ecosystem;
3029
+ }
2836
3030
  }
2837
3031
  }
2838
3032
  if (byPkg.size === 0) return void 0;
2839
3033
  const items = [];
2840
- for (const [, { row, ecosystem }] of byPkg) {
3034
+ for (const [, { row, ecosystem, locations }] of byPkg) {
2841
3035
  const scored = perDependencyDrift(row, {
2842
3036
  unsupported: row.unsupported === true,
2843
3037
  abandoned: row.abandoned === true
@@ -2857,7 +3051,8 @@ function buildBreakdown(_drift, projects) {
2857
3051
  mode: scored.mode,
2858
3052
  unsupported: scored.unsupported || row.unsupported === true,
2859
3053
  abandoned: scored.flags.includes("abandoned-floor") || row.abandoned === true,
2860
- flags: scored.flags
3054
+ flags: scored.flags,
3055
+ locations
2861
3056
  });
2862
3057
  }
2863
3058
  items.sort((a, b) => b.drift - a.drift || a.package.localeCompare(b.package));
@@ -2895,30 +3090,129 @@ function manifestRelativePath(proj) {
2895
3090
  return join27("package.json");
2896
3091
  }
2897
3092
  }
2898
- function packageReachSet(graph) {
3093
+ function lockfileRelativePath(rootDir, proj) {
3094
+ const base = proj.path === "." || proj.path === "" ? "" : proj.path;
3095
+ const candidateNames = (() => {
3096
+ switch (proj.type) {
3097
+ case "node":
3098
+ case "typescript":
3099
+ return ["pnpm-lock.yaml", "yarn.lock", "package-lock.json", "bun.lockb"];
3100
+ case "python":
3101
+ return ["poetry.lock", "uv.lock", "Pipfile.lock"];
3102
+ case "go":
3103
+ return ["go.sum"];
3104
+ case "rust":
3105
+ return ["Cargo.lock"];
3106
+ case "ruby":
3107
+ return ["Gemfile.lock"];
3108
+ case "php":
3109
+ return ["composer.lock"];
3110
+ case "dotnet":
3111
+ return ["packages.lock.json"];
3112
+ case "dart":
3113
+ return ["pubspec.lock"];
3114
+ default:
3115
+ return [];
3116
+ }
3117
+ })();
3118
+ const dirsToTry = base ? [base, ""] : [""];
3119
+ for (const dir of dirsToTry) {
3120
+ for (const name of candidateNames) {
3121
+ const rel = dir ? path37.join(dir, name) : name;
3122
+ try {
3123
+ if (fs7.existsSync(path37.join(rootDir, rel))) return rel;
3124
+ } catch {
3125
+ }
3126
+ }
3127
+ }
3128
+ return void 0;
3129
+ }
3130
+ function packageImportMap(graph) {
2899
3131
  if (!graph?.nodes?.length) return null;
2900
- const set = /* @__PURE__ */ new Set();
3132
+ const byId = new Map(graph.nodes.map((n) => [n.id, n]));
3133
+ const map = /* @__PURE__ */ new Map();
3134
+ const addPkg = (raw, file) => {
3135
+ if (!file) return;
3136
+ const cleaned = raw.replace(/^node_modules\//, "").replace(/\\/g, "/");
3137
+ const keys = /* @__PURE__ */ new Set();
3138
+ keys.add(cleaned.toLowerCase());
3139
+ if (cleaned.startsWith("@")) {
3140
+ const parts = cleaned.split("/");
3141
+ if (parts.length >= 2) keys.add(`${parts[0]}/${parts[1]}`.toLowerCase());
3142
+ } else {
3143
+ keys.add(cleaned.split("/")[0].toLowerCase());
3144
+ }
3145
+ for (const k of keys) {
3146
+ let set = map.get(k);
3147
+ if (!set) {
3148
+ set = /* @__PURE__ */ new Set();
3149
+ map.set(k, set);
3150
+ }
3151
+ set.add(file);
3152
+ }
3153
+ };
3154
+ for (const e of graph.edges ?? []) {
3155
+ if (e.kind !== "import") continue;
3156
+ const src = byId.get(e.src);
3157
+ const dst = byId.get(e.dst);
3158
+ if (!src?.file || !dst) continue;
3159
+ if (dst.kind !== "external" && dst.kind !== "package" && dst.kind !== "module") continue;
3160
+ for (const raw of [dst.name, dst.qualifiedName].filter(Boolean)) {
3161
+ addPkg(raw, src.file);
3162
+ }
3163
+ }
2901
3164
  for (const n of graph.nodes) {
2902
3165
  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, "/");
3166
+ for (const raw of [n.name, n.qualifiedName].filter(Boolean)) {
3167
+ const cleaned = raw.replace(/^node_modules\//, "").replace(/\\/g, "/").toLowerCase();
3168
+ if (!map.has(cleaned)) map.set(cleaned, /* @__PURE__ */ new Set());
2906
3169
  if (cleaned.startsWith("@")) {
2907
3170
  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());
3171
+ if (parts.length >= 2 && !map.has(`${parts[0]}/${parts[1]}`)) {
3172
+ map.set(`${parts[0]}/${parts[1]}`, /* @__PURE__ */ new Set());
3173
+ }
2911
3174
  }
2912
- set.add(cleaned.toLowerCase());
2913
3175
  }
2914
3176
  }
2915
- return set;
3177
+ const out2 = /* @__PURE__ */ new Map();
3178
+ for (const [k, files] of map) {
3179
+ out2.set(k, [...files].sort());
3180
+ }
3181
+ return out2;
2916
3182
  }
2917
- function packageReached(set, pkg) {
3183
+ function lookupImportFiles(map, pkg) {
2918
3184
  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;
3185
+ if (map.has(p)) return map.get(p);
3186
+ if (!p.startsWith("@")) {
3187
+ const root2 = p.split("/")[0];
3188
+ if (map.has(root2)) return map.get(root2);
3189
+ }
3190
+ return [];
3191
+ }
3192
+ function firstPackageMentionLine(root2, relFile, pkg) {
3193
+ try {
3194
+ const abs = path37.resolve(root2, relFile);
3195
+ const stat2 = fs7.statSync(abs);
3196
+ if (!stat2.isFile() || stat2.size > 256 * 1024) return null;
3197
+ const text = fs7.readFileSync(abs, "utf8");
3198
+ const tokens = [pkg];
3199
+ if (pkg.startsWith("@")) {
3200
+ const parts = pkg.split("/");
3201
+ if (parts[1]) tokens.push(parts[1]);
3202
+ } else if (pkg.includes("/")) {
3203
+ tokens.push(pkg.split("/")[0]);
3204
+ }
3205
+ const lines = text.split(/\r?\n/);
3206
+ for (let i = 0; i < lines.length; i++) {
3207
+ const line = lines[i];
3208
+ if (!/import|require|from|use |include/.test(line) && !line.includes(pkg)) continue;
3209
+ for (const t of tokens) {
3210
+ if (t && line.includes(t)) return i + 1;
3211
+ }
3212
+ }
3213
+ } catch {
3214
+ }
3215
+ return null;
2922
3216
  }
2923
3217
  function osvEcosystem(type) {
2924
3218
  switch (type) {
@@ -3044,7 +3338,7 @@ function hoverMarkdown(dep, contribution) {
3044
3338
  majorsBehind: dep.majorsBehind ?? 0
3045
3339
  });
3046
3340
  const explainUri = commandUri("vibgrate.explain", { package: dep.package });
3047
- lines.push(`[Route this fix \u2192](${routeFixUri}) \xB7 [Explain this drift](${explainUri})`);
3341
+ lines.push(`[Fix \u2192](${routeFixUri}) \xB7 [Explain this drift](${explainUri})`);
3048
3342
  }
3049
3343
  lines.push("");
3050
3344
  lines.push("---");
@@ -3117,12 +3411,24 @@ function registerInstall(program) {
3117
3411
  return;
3118
3412
  }
3119
3413
  if (global.json) {
3120
- json(ASSISTANTS.map((a) => ({ id: a.id, label: a.label, mcp: !!a.mcp, skill: !!a.skill, nudge: !!a.nudge })));
3414
+ json(
3415
+ ASSISTANTS.map((a) => ({
3416
+ id: a.id,
3417
+ label: a.label,
3418
+ mcp: !!a.mcp,
3419
+ skill: !!a.skill,
3420
+ nudge: !!a.nudge,
3421
+ installed: isAssistantInstalled(a, root2)
3422
+ }))
3423
+ );
3121
3424
  } else {
3122
3425
  info(`${c.cyan("vg install")} \xB7 supported assistants`);
3123
3426
  const pad4 = Math.max(...ASSISTANTS.map((a) => a.id.length)) + 2;
3124
3427
  for (const a of ASSISTANTS) {
3125
- info(` ${c.bold(a.id.padEnd(pad4))} ${a.label} ${c.dim(`mcp:${a.mcp ? "\u2713" : "\u2014"} skill:${a.skill ? "\u2713" : "\u2014"} nudge:${a.nudge ? "\u2713" : "\u2014"}`)}`);
3428
+ const on = isAssistantInstalled(a, root2) ? c.green("on") : c.dim("off");
3429
+ info(
3430
+ ` ${c.bold(a.id.padEnd(pad4))} ${a.label} ${on} ${c.dim(`mcp:${a.mcp ? "\u2713" : "\u2014"} skill:${a.skill ? "\u2713" : "\u2014"} nudge:${a.nudge ? "\u2713" : "\u2014"}`)}`
3431
+ );
3126
3432
  }
3127
3433
  }
3128
3434
  return;
@@ -6108,7 +6414,7 @@ function registerCode(program) {
6108
6414
  try {
6109
6415
  const { parseMode: parseMode2, resolveMode: resolveMode2, readOrchestratorState: readOrchestratorState2, activePin: activePin2 } = await import('./model-orchestrator-LHYPJBFH.js');
6110
6416
  const { gatherSystemMemory: gatherSystemMemory2 } = await import('./local-runtime-2ED33KK6.js');
6111
- const { loadGraph: loadGraph2 } = await import('./load-RFQFTTIT.js');
6417
+ const { loadGraph: loadGraph2 } = await import('./load-A5BGEQWP.js');
6112
6418
  const state = readOrchestratorState2();
6113
6419
  const mode = parseMode2(modeFlag) ?? state.defaultMode ?? void 0;
6114
6420
  const pin = mode ? activePin2(mode, state) : null;
@@ -6192,7 +6498,7 @@ function registerCode(program) {
6192
6498
  if (!(process.stdin.isTTY && process.stdout.isTTY)) {
6193
6499
  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
6500
  }
6195
- const { runInteractive } = await import('./interactive-MR7DTVYS.js');
6501
+ const { runInteractive } = await import('./interactive-2TAYVEHE.js');
6196
6502
  await runInteractive(
6197
6503
  rootOf(global),
6198
6504
  global,
@@ -6221,6 +6527,40 @@ function registerCode(program) {
6221
6527
  return;
6222
6528
  }
6223
6529
  if (!instruction) throw usageError('say what to change, e.g. `vg code "add a --timeout flag to the scan command"`');
6530
+ {
6531
+ const { ensureCodeMap } = await import('./ensure-map-C3NEC2GI.js');
6532
+ const mapRoot = rootOf(global);
6533
+ try {
6534
+ await ensureCodeMap(mapRoot, global, {
6535
+ onProgress: (p) => {
6536
+ if (opts.streamJson) {
6537
+ process.stdout.write(
6538
+ JSON.stringify({
6539
+ event: "event",
6540
+ type: "map_build",
6541
+ phase: p.phase,
6542
+ message: p.message,
6543
+ ...p.pct != null ? { pct: p.pct } : {}
6544
+ }) + "\n"
6545
+ );
6546
+ return;
6547
+ }
6548
+ if (!global.json && !global.quiet && (p.phase === "start" || p.phase === "done")) {
6549
+ info(c.dim(`vg code \xB7 ${p.message}`));
6550
+ }
6551
+ }
6552
+ });
6553
+ } catch (e) {
6554
+ const msg = e instanceof Error ? e.message : String(e);
6555
+ if (opts.streamJson) {
6556
+ process.stdout.write(
6557
+ JSON.stringify({ event: "error", message: `Could not build the code map: ${msg}` }) + "\n"
6558
+ );
6559
+ return;
6560
+ }
6561
+ throw e;
6562
+ }
6563
+ }
6224
6564
  const { root: root2, graph } = requireGraph(global);
6225
6565
  let mockReply;
6226
6566
  if (opts.mock) {
@@ -6273,20 +6613,20 @@ function registerCode(program) {
6273
6613
  process.stdout.write(JSON.stringify(line) + "\n");
6274
6614
  };
6275
6615
  try {
6276
- const { RunOutcomeRecorder, newOneShotRunId, turnRunId } = await import('./run-outcome-EKB6YQIK.js');
6616
+ const { RunOutcomeRecorder, newOneShotRunId, turnRunId } = await import('./run-outcome-OSIVMVT7.js');
6277
6617
  const primarySlug = route.providers[0]?.model.includes("/") ? route.providers[0].model.split("/")[0] : route.providers[0]?.id;
6278
- const { runCodeStreamJson, parseHostMessage } = await import('./stream-json-3YOPU3LF.js');
6618
+ const { runCodeStreamJson, parseHostMessage } = await import('./stream-json-CFKBL3MR.js');
6279
6619
  const { nodeCodeFs } = await import('./session-3OBIQLE4.js');
6280
6620
  const readline5 = await import('readline');
6281
6621
  const child = await import('child_process');
6282
6622
  const { loadOrDiscoverFederation } = await import('./federation-MDQPO3PW.js');
6283
6623
  const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
6284
6624
  const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
6285
- const { startCodeRuntimeSession } = await import('./runtime-session-23RZLEA4.js');
6625
+ const { startCodeRuntimeSession } = await import('./runtime-session-UPTC3E6N.js');
6286
6626
  const { resolveGraphBackend } = await import('./graph-backend-G5Y6QQV4.js');
6287
6627
  const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
6288
6628
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
6289
- const { vgdRequest: vgdRequest2 } = await import('./vgd-VIPBL7W4.js');
6629
+ const { vgdRequest: vgdRequest2 } = await import('./vgd-HNPOSXKZ.js');
6290
6630
  const federation = loadOrDiscoverFederation(root2);
6291
6631
  const modelProfile = mergeModelExecutionProfile(
6292
6632
  resolveModelExecutionProfile({
@@ -6344,7 +6684,7 @@ ${res.stderr}` : ""),
6344
6684
  exitCode: res.status ?? 1
6345
6685
  };
6346
6686
  };
6347
- const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-UZFHPP2Q.js');
6687
+ const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-JHRKJBVT.js');
6348
6688
  const vgBuiltin = createVgBuiltinMcpTools({
6349
6689
  getGraph: () => graph,
6350
6690
  root: root2,
@@ -6431,8 +6771,8 @@ ${res.stderr}` : ""),
6431
6771
  };
6432
6772
  try {
6433
6773
  if (opts.session) {
6434
- const { runCodeStreamJsonSession } = await import('./stream-json-3YOPU3LF.js');
6435
- const { runAgent: runAgent2 } = await import('./agent-33BMKWJC.js');
6774
+ const { runCodeStreamJsonSession } = await import('./stream-json-CFKBL3MR.js');
6775
+ const { runAgent: runAgent2 } = await import('./agent-6PPW5GIV.js');
6436
6776
  const {
6437
6777
  loadLatestSession,
6438
6778
  newSession,
@@ -6580,7 +6920,7 @@ ${res.stderr}` : ""),
6580
6920
  if (!autonomous && !tty) {
6581
6921
  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
6922
  }
6583
- const { agentTask } = await import('./interactive-MR7DTVYS.js');
6923
+ const { agentTask } = await import('./interactive-2TAYVEHE.js');
6584
6924
  const { nodeCodeFs } = await import('./session-3OBIQLE4.js');
6585
6925
  const { TtyPrompter } = await import('./ui-K7D3BCHD.js');
6586
6926
  let priorSummary;
@@ -6590,7 +6930,7 @@ ${res.stderr}` : ""),
6590
6930
  if (prev) priorSummary = summarizeSession(prev);
6591
6931
  }
6592
6932
  const prompter = tty ? new TtyPrompter() : void 0;
6593
- const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-UZFHPP2Q.js');
6933
+ const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-JHRKJBVT.js');
6594
6934
  const vgBuiltin = createVgBuiltinMcpTools({
6595
6935
  getGraph: () => graph,
6596
6936
  root: root2,
@@ -6614,11 +6954,11 @@ ${res.stderr}` : ""),
6614
6954
  const { loadFederation } = await import('./federation-MDQPO3PW.js');
6615
6955
  const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
6616
6956
  const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
6617
- const { startCodeRuntimeSession } = await import('./runtime-session-23RZLEA4.js');
6957
+ const { startCodeRuntimeSession } = await import('./runtime-session-UPTC3E6N.js');
6618
6958
  const { resolveGraphBackend } = await import('./graph-backend-G5Y6QQV4.js');
6619
6959
  const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
6620
6960
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
6621
- const { vgdRequest: vgdRequest2 } = await import('./vgd-VIPBL7W4.js');
6961
+ const { vgdRequest: vgdRequest2 } = await import('./vgd-HNPOSXKZ.js');
6622
6962
  const federation = loadFederation(root2);
6623
6963
  const modelProfile = mergeModelExecutionProfile(
6624
6964
  resolveModelExecutionProfile({
@@ -7508,7 +7848,7 @@ function registerDaemon(program) {
7508
7848
  throw new CliError(loaded.error, ExitCode.NOT_FOUND);
7509
7849
  }
7510
7850
  if (!loaded.ok) {
7511
- const { loadGraph: loadGraph2 } = await import('./load-RFQFTTIT.js');
7851
+ const { loadGraph: loadGraph2 } = await import('./load-A5BGEQWP.js');
7512
7852
  const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
7513
7853
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
7514
7854
  const graph = loadGraph2(root2, global.graph);
@@ -7913,7 +8253,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
7913
8253
  console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold("vibgrate.config.ts")}`);
7914
8254
  }
7915
8255
  if (opts.baseline) {
7916
- const { runBaseline } = await import('./baseline-536TQZIB.js');
8256
+ const { runBaseline } = await import('./baseline-ZMHL6DXF.js');
7917
8257
  await runBaseline(rootDir);
7918
8258
  }
7919
8259
  console.log("");
@@ -8015,11 +8355,42 @@ function collectPackageImports(graph, ecosystem, pkg) {
8015
8355
  importingFiles: [...files].sort()
8016
8356
  };
8017
8357
  }
8018
- async function fileReferencesIdentifier(rootDir, relFile, identifier, readFile3) {
8358
+ async function firstReferenceLine(rootDir, relFile, identifier, readFile3) {
8019
8359
  const content = await readFile3(path37.join(rootDir, relFile));
8020
- if (!content) return false;
8360
+ if (!content) return null;
8021
8361
  const escaped = identifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
8022
- return new RegExp(`\\b${escaped}\\b`).test(content);
8362
+ const re = new RegExp(`\\b${escaped}\\b`);
8363
+ const lines = content.split(/\r?\n/);
8364
+ for (let i = 0; i < lines.length; i++) {
8365
+ if (re.test(lines[i])) return i + 1;
8366
+ }
8367
+ return null;
8368
+ }
8369
+ function formatSitePath(site) {
8370
+ return site.line != null && site.line > 0 ? `${site.file}:${site.line}` : site.file;
8371
+ }
8372
+ function enclosingFunctionName(graph, relFile, line) {
8373
+ if (line == null || line < 1) return null;
8374
+ let best = null;
8375
+ let bestSpan = Number.POSITIVE_INFINITY;
8376
+ for (const node2 of graph.nodes) {
8377
+ if (node2.file !== relFile) continue;
8378
+ if (node2.kind !== "function" && node2.kind !== "method") continue;
8379
+ const start = node2.span?.start;
8380
+ const end = node2.span?.end;
8381
+ if (start == null || end == null) continue;
8382
+ if (line < start || line > end) continue;
8383
+ const span = end - start;
8384
+ if (span < bestSpan) {
8385
+ bestSpan = span;
8386
+ best = node2;
8387
+ }
8388
+ }
8389
+ return best?.name ?? null;
8390
+ }
8391
+ function sitesFromImportFiles(files, limit = 10) {
8392
+ const sites = files.slice(0, limit).map((file) => ({ file }));
8393
+ return { callPath: sites.map(formatSitePath), sites };
8023
8394
  }
8024
8395
  async function defaultReadFile(absPath) {
8025
8396
  try {
@@ -8102,6 +8473,7 @@ async function analyzeReachability(input) {
8102
8473
  }
8103
8474
  const matchableSymbols = entry.symbols.map((s) => ({ symbol: s.symbol, identifier: symbolIdentifier(s.symbol) })).filter((s) => isMatchableIdentifier(s.identifier));
8104
8475
  if (entry.symbolCoverage !== "function" || matchableSymbols.length === 0) {
8476
+ const { callPath, sites } = sitesFromImportFiles(evidence.importingFiles, 10);
8105
8477
  findings.push({
8106
8478
  advisoryId: entry.advisoryId,
8107
8479
  ecosystem: entry.ecosystem,
@@ -8109,7 +8481,8 @@ async function analyzeReachability(input) {
8109
8481
  version: entry.version,
8110
8482
  tier: "potentially_reachable",
8111
8483
  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),
8484
+ callPath,
8485
+ sites,
8113
8486
  graphConfidence: Math.min(baseConfidence, 0.6)
8114
8487
  });
8115
8488
  continue;
@@ -8117,14 +8490,19 @@ async function analyzeReachability(input) {
8117
8490
  const filesToCheck = evidence.importingFiles.slice(0, MAX_FILES_PER_PACKAGE);
8118
8491
  let anySymbolFound = false;
8119
8492
  for (const { symbol, identifier } of matchableSymbols) {
8120
- const referencingFiles = [];
8493
+ const sites = [];
8121
8494
  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
- }
8495
+ const line = await firstReferenceLine(input.rootDir, relFile, identifier, readFile3);
8496
+ if (line == null) continue;
8497
+ sites.push({
8498
+ file: relFile,
8499
+ line,
8500
+ symbol,
8501
+ function: enclosingFunctionName(input.graph, relFile, line)
8502
+ });
8503
+ if (sites.length >= 5) break;
8126
8504
  }
8127
- if (referencingFiles.length > 0) {
8505
+ if (sites.length > 0) {
8128
8506
  anySymbolFound = true;
8129
8507
  findings.push({
8130
8508
  advisoryId: entry.advisoryId,
@@ -8133,13 +8511,15 @@ async function analyzeReachability(input) {
8133
8511
  version: entry.version,
8134
8512
  symbol,
8135
8513
  tier: "reachable",
8136
- evidence: `vulnerable symbol \`${identifier}\` is referenced in ${referencingFiles.length} importing file${referencingFiles.length === 1 ? "" : "s"}`,
8137
- callPath: referencingFiles,
8514
+ evidence: `vulnerable symbol \`${identifier}\` is referenced in ${sites.length} importing file${sites.length === 1 ? "" : "s"}`,
8515
+ callPath: sites.map(formatSitePath),
8516
+ sites,
8138
8517
  graphConfidence: Math.min(baseConfidence, 0.75)
8139
8518
  });
8140
8519
  }
8141
8520
  }
8142
8521
  if (!anySymbolFound) {
8522
+ const { callPath, sites } = sitesFromImportFiles(evidence.importingFiles, 10);
8143
8523
  findings.push({
8144
8524
  advisoryId: entry.advisoryId,
8145
8525
  ecosystem: entry.ecosystem,
@@ -8147,7 +8527,8 @@ async function analyzeReachability(input) {
8147
8527
  version: entry.version,
8148
8528
  tier: "not_reached",
8149
8529
  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),
8530
+ callPath,
8531
+ sites,
8151
8532
  graphConfidence: Math.min(baseConfidence, 0.55)
8152
8533
  });
8153
8534
  }