@vibgrate/cli 2026.731.3 → 2026.803.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 (116) hide show
  1. package/dist/agent-HNV2VUCO.js +24 -0
  2. package/dist/{agent-6XOI7RVW.js.map → agent-HNV2VUCO.js.map} +1 -1
  3. package/dist/baseline-6WTULHM5.js +9 -0
  4. package/dist/{baseline-PY6TETA5.js.map → baseline-6WTULHM5.js.map} +1 -1
  5. package/dist/{chunk-B6S2DSBS.js → chunk-2TLQDF6C.js} +129 -20
  6. package/dist/chunk-2TLQDF6C.js.map +1 -0
  7. package/dist/{chunk-X634FZVG.js → chunk-3LOWJSAF.js} +11 -16
  8. package/dist/{chunk-X634FZVG.js.map → chunk-3LOWJSAF.js.map} +1 -1
  9. package/dist/{chunk-BMUTNUB7.js → chunk-4HFSUIIN.js} +117 -6
  10. package/dist/chunk-4HFSUIIN.js.map +1 -0
  11. package/dist/{chunk-3VSU7G75.js → chunk-536J6HUR.js} +235 -13
  12. package/dist/chunk-536J6HUR.js.map +1 -0
  13. package/dist/{chunk-EETK7S43.js → chunk-5VH3Y4QC.js} +111 -33
  14. package/dist/chunk-5VH3Y4QC.js.map +1 -0
  15. package/dist/{chunk-PHGAUWWF.js → chunk-6I4TXAI6.js} +3 -3
  16. package/dist/{chunk-PHGAUWWF.js.map → chunk-6I4TXAI6.js.map} +1 -1
  17. package/dist/{chunk-FF5ZQ6KI.js → chunk-6JP7HGIF.js} +4 -4
  18. package/dist/{chunk-FF5ZQ6KI.js.map → chunk-6JP7HGIF.js.map} +1 -1
  19. package/dist/chunk-AJ2KE3NT.js +446 -0
  20. package/dist/chunk-AJ2KE3NT.js.map +1 -0
  21. package/dist/{chunk-WK52LWRX.js → chunk-B2KLJPFY.js} +5 -5
  22. package/dist/{chunk-WK52LWRX.js.map → chunk-B2KLJPFY.js.map} +1 -1
  23. package/dist/{chunk-Z7VH4RPO.js → chunk-BBFQZ7CA.js} +4 -4
  24. package/dist/{chunk-Z7VH4RPO.js.map → chunk-BBFQZ7CA.js.map} +1 -1
  25. package/dist/{chunk-FHJBGPJZ.js → chunk-BWMMR5XA.js} +4 -4
  26. package/dist/{chunk-FHJBGPJZ.js.map → chunk-BWMMR5XA.js.map} +1 -1
  27. package/dist/{chunk-KLO2XBUX.js → chunk-CC6F75GI.js} +14 -7
  28. package/dist/chunk-CC6F75GI.js.map +1 -0
  29. package/dist/{chunk-SCTLOFNH.js → chunk-CE45STY5.js} +4 -4
  30. package/dist/{chunk-SCTLOFNH.js.map → chunk-CE45STY5.js.map} +1 -1
  31. package/dist/{chunk-MOLBANFB.js → chunk-DIU3MXB3.js} +4 -4
  32. package/dist/{chunk-MOLBANFB.js.map → chunk-DIU3MXB3.js.map} +1 -1
  33. package/dist/{chunk-5IA2TA57.js → chunk-FKFRASAB.js} +323 -152
  34. package/dist/chunk-FKFRASAB.js.map +1 -0
  35. package/dist/{chunk-EVLS2M5G.js → chunk-JFE7XCAE.js} +3 -3
  36. package/dist/{chunk-EVLS2M5G.js.map → chunk-JFE7XCAE.js.map} +1 -1
  37. package/dist/{chunk-RGEVBSLK.js → chunk-JUSXLCSE.js} +3 -3
  38. package/dist/{chunk-RGEVBSLK.js.map → chunk-JUSXLCSE.js.map} +1 -1
  39. package/dist/{chunk-7G5S5KZN.js → chunk-KUZLILN3.js} +16 -3
  40. package/dist/chunk-KUZLILN3.js.map +1 -0
  41. package/dist/{chunk-AVCBKQKA.js → chunk-N4IDP2M2.js} +218 -51
  42. package/dist/chunk-N4IDP2M2.js.map +1 -0
  43. package/dist/{chunk-XRN7DQGR.js → chunk-NJFQCDGA.js} +3 -3
  44. package/dist/{chunk-XRN7DQGR.js.map → chunk-NJFQCDGA.js.map} +1 -1
  45. package/dist/{chunk-LTTVCI5C.js → chunk-O7MTBC52.js} +134 -9
  46. package/dist/chunk-O7MTBC52.js.map +1 -0
  47. package/dist/chunk-QT2PMGN3.js +6 -0
  48. package/dist/{chunk-DEKGSQHL.js.map → chunk-QT2PMGN3.js.map} +1 -1
  49. package/dist/{chunk-5XIEVZLW.js → chunk-S4NSF5AZ.js} +6 -6
  50. package/dist/{chunk-5XIEVZLW.js.map → chunk-S4NSF5AZ.js.map} +1 -1
  51. package/dist/{chunk-TRKRRX2S.js → chunk-SJFBXCII.js} +35 -6
  52. package/dist/chunk-SJFBXCII.js.map +1 -0
  53. package/dist/{chunk-RIWLXMMT.js → chunk-SNKTD23L.js} +109 -10
  54. package/dist/chunk-SNKTD23L.js.map +1 -0
  55. package/dist/{chunk-IPICO2RV.js → chunk-VIWZ4QT7.js} +14 -3
  56. package/dist/chunk-VIWZ4QT7.js.map +1 -0
  57. package/dist/{chunk-US2DAKCM.js → chunk-Y7YKUZ3T.js} +8 -7
  58. package/dist/chunk-Y7YKUZ3T.js.map +1 -0
  59. package/dist/cli.js +732 -347
  60. package/dist/cli.js.map +1 -1
  61. package/dist/ensure-map-5YEI7R7V.js +29 -0
  62. package/dist/{ensure-map-UQL7SM34.js.map → ensure-map-5YEI7R7V.js.map} +1 -1
  63. package/dist/{graph-backend-G5Y6QQV4.js → graph-backend-CPHLUKUC.js} +5 -5
  64. package/dist/{graph-backend-G5Y6QQV4.js.map → graph-backend-CPHLUKUC.js.map} +1 -1
  65. package/dist/index.d.ts +127 -9
  66. package/dist/index.js +17 -16
  67. package/dist/index.js.map +1 -1
  68. package/dist/{interactive-QWT7ERXJ.js → interactive-TNRE4OEK.js} +46 -33
  69. package/dist/interactive-TNRE4OEK.js.map +1 -0
  70. package/dist/{llm-host-DZBD5D36.js → llm-host-XFYFOAAX.js} +4 -4
  71. package/dist/{llm-host-DZBD5D36.js.map → llm-host-XFYFOAAX.js.map} +1 -1
  72. package/dist/load-MWG6WZTK.js +10 -0
  73. package/dist/{load-WA53B3GW.js.map → load-MWG6WZTK.js.map} +1 -1
  74. package/dist/model-manager-GJ2YSTSK.js +1 -1
  75. package/dist/{run-outcome-J2IDIVYI.js → run-outcome-375HMSQG.js} +6 -6
  76. package/dist/{run-outcome-J2IDIVYI.js.map → run-outcome-375HMSQG.js.map} +1 -1
  77. package/dist/runtime-session-3MPWXNRL.js +20 -0
  78. package/dist/{runtime-session-52P2Y5LX.js.map → runtime-session-3MPWXNRL.js.map} +1 -1
  79. package/dist/session-2NGJLI5Y.js +15 -0
  80. package/dist/{session-L7SJNE55.js.map → session-2NGJLI5Y.js.map} +1 -1
  81. package/dist/session-store-F7NX7SZN.js +4 -0
  82. package/dist/{session-store-SQECEXUU.js.map → session-store-F7NX7SZN.js.map} +1 -1
  83. package/dist/{stream-json-TSGYC2MQ.js → stream-json-AUMU3NLV.js} +48 -16
  84. package/dist/stream-json-AUMU3NLV.js.map +1 -0
  85. package/dist/{vg-mcp-bridge-IFAXEQMZ.js → vg-mcp-bridge-D463EHQI.js} +13 -11
  86. package/dist/vg-mcp-bridge-D463EHQI.js.map +1 -0
  87. package/dist/{vgd-PNR7UKLL.js → vgd-Z23PXSP4.js} +10 -10
  88. package/dist/vgd-Z23PXSP4.js.map +1 -0
  89. package/package.json +4 -2
  90. package/dist/agent-6XOI7RVW.js +0 -22
  91. package/dist/baseline-PY6TETA5.js +0 -9
  92. package/dist/chunk-3VSU7G75.js.map +0 -1
  93. package/dist/chunk-5IA2TA57.js.map +0 -1
  94. package/dist/chunk-7G5S5KZN.js.map +0 -1
  95. package/dist/chunk-AVCBKQKA.js.map +0 -1
  96. package/dist/chunk-B6S2DSBS.js.map +0 -1
  97. package/dist/chunk-BMUTNUB7.js.map +0 -1
  98. package/dist/chunk-DEKGSQHL.js +0 -6
  99. package/dist/chunk-EETK7S43.js.map +0 -1
  100. package/dist/chunk-IPICO2RV.js.map +0 -1
  101. package/dist/chunk-KLO2XBUX.js.map +0 -1
  102. package/dist/chunk-LTTVCI5C.js.map +0 -1
  103. package/dist/chunk-RIWLXMMT.js.map +0 -1
  104. package/dist/chunk-TRKRRX2S.js.map +0 -1
  105. package/dist/chunk-US2DAKCM.js.map +0 -1
  106. package/dist/chunk-ZKNB4YH4.js +0 -102
  107. package/dist/chunk-ZKNB4YH4.js.map +0 -1
  108. package/dist/ensure-map-UQL7SM34.js +0 -28
  109. package/dist/interactive-QWT7ERXJ.js.map +0 -1
  110. package/dist/load-WA53B3GW.js +0 -10
  111. package/dist/runtime-session-52P2Y5LX.js +0 -20
  112. package/dist/session-L7SJNE55.js +0 -13
  113. package/dist/session-store-SQECEXUU.js +0 -4
  114. package/dist/stream-json-TSGYC2MQ.js.map +0 -1
  115. package/dist/vg-mcp-bridge-IFAXEQMZ.js.map +0 -1
  116. package/dist/vgd-PNR7UKLL.js.map +0 -1
package/dist/cli.js CHANGED
@@ -1,69 +1,70 @@
1
1
  #!/usr/bin/env node
2
- import { loadAdvancedScanHook, baselineCommand } from './chunk-FF5ZQ6KI.js';
3
- import { fetchCatalog, resolveProviders } from './chunk-BMUTNUB7.js';
4
- import { VGD_PROTOCOL_VERSION, startVgdServer } from './chunk-WK52LWRX.js';
5
- import { telemetryOptOut, StatsSharer, statsEndpoint, isCI } from './chunk-Z7VH4RPO.js';
2
+ import { loadAdvancedScanHook, baselineCommand } from './chunk-6JP7HGIF.js';
3
+ import { fetchCatalog, resolveProviders } from './chunk-4HFSUIIN.js';
4
+ import { VGD_PROTOCOL_VERSION, startVgdServer } from './chunk-B2KLJPFY.js';
5
+ import { telemetryOptOut, StatsSharer, statsEndpoint, isCI } from './chunk-BBFQZ7CA.js';
6
+ import './chunk-7AVYKZEM.js';
6
7
  import { buildModelInstallPlan } from './chunk-WHJMS7XC.js';
7
- import { runCodeSession } from './chunk-KLO2XBUX.js';
8
- import { sha256Hex, generateKeypair, dssePae, DSSE_PAYLOAD_TYPE, keyId, registerBuild, readGlobal, applyGlobalOptions, ProgressBar, printLogo, runBuild } from './chunk-LTTVCI5C.js';
9
- export { runBuild } from './chunk-LTTVCI5C.js';
8
+ import { runCodeSession } from './chunk-CC6F75GI.js';
9
+ import { sha256Hex, generateKeypair, dssePae, DSSE_PAYLOAD_TYPE, keyId, registerBuild, readGlobal, applyGlobalOptions, ProgressBar, printLogo, runBuild } from './chunk-O7MTBC52.js';
10
+ export { runBuild } from './chunk-O7MTBC52.js';
10
11
  import { disableColor, info, c, json, out } from './chunk-CT5BS56U.js';
11
- import './chunk-5I4VSBWQ.js';
12
12
  import './chunk-IS7VTH2Q.js';
13
13
  import { init_resolve_ollama, gatherSystemMemory, resolveOllamaBinary, hasOllamaBinary, resolve_ollama_exports } from './chunk-OWSFZQOP.js';
14
14
  import { readOrchestratorState, writeOrchestratorState, parseMode, setDefaultMode, recommendMode, activePin, resolveMode, providerForBackend, QUALIFIED_PACKS, pinPack, unpinPack, buildOrchestratorStatus } from './chunk-NZELMYT4.js';
15
15
  import { fmt, estimateModelBytes } from './chunk-7N4Y3E47.js';
16
16
  import './chunk-IZDH67DX.js';
17
- import { defaultProcessEndpoint, startProcessHostServer, resolveInferenceIsolation } from './chunk-EVLS2M5G.js';
18
- import { clearHostSessionPool, acquireHostSession, generateOnSession, listHostSessions, hostSessionPoolSize } from './chunk-X634FZVG.js';
19
- import { CONTEXT_POLICY_VERSION, computeFcsReport, renderFcsReportMarkdown, createTrajectoryCollector, runAgent } from './chunk-3VSU7G75.js';
17
+ import { defaultProcessEndpoint, startProcessHostServer, resolveInferenceIsolation } from './chunk-JFE7XCAE.js';
18
+ import { clearHostSessionPool, acquireHostSession, generateOnSession, listHostSessions, hostSessionPoolSize } from './chunk-3LOWJSAF.js';
19
+ import { CONTEXT_POLICY_VERSION, computeFcsReport, renderFcsReportMarkdown, createTrajectoryCollector, runAgent } from './chunk-536J6HUR.js';
20
20
  import './chunk-543E6WDJ.js';
21
- import { summarizeDiffs, ScriptedProvider } from './chunk-TRKRRX2S.js';
21
+ import { summarizeDiffs, ScriptedProvider } from './chunk-SJFBXCII.js';
22
22
  import { ensurePackage, ensureUnavailableMessage } from './chunk-REIGWTTH.js';
23
- import './chunk-RGEVBSLK.js';
23
+ import './chunk-JUSXLCSE.js';
24
24
  import { vgdSocketPath, vgdIsRunning, vgdRequest, vgdPidPath } from './chunk-RBIRXQR6.js';
25
25
  import { buildIdentifierTrieFromGraph } from './chunk-5HYCB55P.js';
26
- import './chunk-7AVYKZEM.js';
27
- import { serveStdio, exportGraph, GraphSource, createServer, formatForExt } from './chunk-B6S2DSBS.js';
28
- import { refreshIfStale } from './chunk-5XIEVZLW.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-5IA2TA57.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';
26
+ import { serveStdio, isRelevantChange, exportGraph, GraphSource, createServer, formatForExt } from './chunk-2TLQDF6C.js';
27
+ import { refreshIfStale } from './chunk-S4NSF5AZ.js';
28
+ 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-FKFRASAB.js';
29
+ 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-SNKTD23L.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-NJFQCDGA.js';
32
31
  import { resolveIngestHost, dashHostForIngestHost, availableRegionIds, ingestHostForRegionId } from './chunk-HTLDXEHW.js';
32
+ import { discoverModels } from './chunk-CQDUBAQY.js';
33
+ import { freeBytesOnVolume, weightStoreDir, listCachedWeights, ensureWeightCached, catalogIntegrityReport } from './chunk-OV4KGXPD.js';
34
+ import { pathExists as pathExists$1, parseExcludePatterns } from './chunk-DT4KIVRI.js';
33
35
  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';
35
- import './chunk-IPICO2RV.js';
36
- import { inventory, enrichOnline, ECOSYSTEMS, catalogPath, libDir, loadCatalog, driftFor, addLibrary, resolveLib, libId, resolveVersion, readDoc, localPackageDocs, localApiSurface } from './chunk-FHJBGPJZ.js';
36
+ import { recordCliCall, CLI_TOOL_ALIASES, savingsLedgerPath, clearSavings, readSavings, readUsage, readModelSavings, CAPSULE_RANKING_VERSION, SAVINGS_TOOLS, sanitizeClient } from './chunk-Y7YKUZ3T.js';
37
+ import './chunk-VIWZ4QT7.js';
38
+ import { inventory, enrichOnline, ECOSYSTEMS, catalogPath, libDir, loadCatalog, driftFor, addLibrary, resolveLib, libId, resolveVersion, readDoc, localPackageDocs, localApiSurface } from './chunk-BWMMR5XA.js';
37
39
  import { init_cli_invocation, resolveCliInvocation, NPX_INVOCATION } from './chunk-3LSG7Z4I.js';
38
40
  import { resolveOne } from './chunk-J7LKEB2R.js';
39
- import { embeddingsCached, resolveEmbedModel, loadEmbedder, getNodeEmbeddings, queryGraphSemantic, queryGraph, unavailableMessage, countPending, indexFor, impactOf, modelCacheInfo, clearModelCache } from './chunk-EETK7S43.js';
40
- import { discoverModels } from './chunk-CQDUBAQY.js';
41
- import { freeBytesOnVolume, weightStoreDir, listCachedWeights, ensureWeightCached, catalogIntegrityReport } from './chunk-OV4KGXPD.js';
41
+ import { embeddingsCached, resolveEmbedModel, loadEmbedder, getNodeEmbeddings, queryGraphSemantic, queryGraph, unavailableMessage, countPending, indexFor, impactOf, modelCacheInfo, clearModelCache } from './chunk-5VH3Y4QC.js';
42
42
  import { resolvedGrammarFiles, grammarSetVersion } from './chunk-UTNNGKKX.js';
43
43
  import './chunk-RXP66R2E.js';
44
- import { loadGraph, SCHEMA_VERSION } from './chunk-MOLBANFB.js';
45
- import { resolveGraphPath, renderReport, loadGraphFileWithSnapshot, writeArtifacts, vibgrateDir, mapFileExists, ensureVibgrateGitignore } from './chunk-AVCBKQKA.js';
46
- import { VERSION } from './chunk-DEKGSQHL.js';
47
- import { cacheDir, serializeGraph, stableStringify } from './chunk-ZKNB4YH4.js';
44
+ import { loadGraph, loadGraphPreferIndex, SCHEMA_VERSION } from './chunk-DIU3MXB3.js';
45
+ import { resolveGraphPath, analyzeQuestion, loadTopicTags, renderReport, resetRelevanceProviderCache, loadRelevanceProvider, loadGraphFileWithSnapshot, writeArtifacts, vibgrateDir, mapFileExists, relevanceModuleDir, ensureVibgrateGitignore } from './chunk-N4IDP2M2.js';
46
+ import { VERSION } from './chunk-QT2PMGN3.js';
47
+ import { cacheDir, serializeGraph, stableStringify, parseGraph } from './chunk-AJ2KE3NT.js';
48
+ import './chunk-5I4VSBWQ.js';
48
49
  import './chunk-BWPBB45M.js';
49
50
  import { canonicalize, hashString, hashBytes } from './chunk-JFGYT6BI.js';
50
51
  import './chunk-BPF3YX2U.js';
51
- import { pathExists as pathExists$1, parseExcludePatterns } from './chunk-DT4KIVRI.js';
52
52
  import { __toCommonJS } from './chunk-Z6ZWNWWR.js';
53
- import * as fs7 from 'fs';
54
- import fs7__default, { realpathSync } from 'fs';
55
- import * as path37 from 'path';
56
- import path37__default from 'path';
53
+ import * as fs10 from 'fs';
54
+ import fs10__default, { realpathSync } from 'fs';
55
+ import * as path39 from 'path';
56
+ import path39__default from 'path';
57
57
  import { fileURLToPath, pathToFileURL } from 'url';
58
58
  import { Command, CommanderError, Option } from 'commander';
59
59
  import * as semver3 from 'semver';
60
60
  import semver3__default from 'semver';
61
- import { execSync, spawn, spawnSync, execFileSync } from 'child_process';
62
61
  import * as readline from 'readline';
62
+ import * as zlib from 'zlib';
63
63
  import * as crypto3 from 'crypto';
64
- import { randomUUID } from 'crypto';
64
+ import { randomUUID, createHash } from 'crypto';
65
+ import { execSync, spawn, spawnSync, execFileSync } from 'child_process';
65
66
  import chalk7 from 'chalk';
66
- import * as fs21 from 'fs/promises';
67
+ import * as fs24 from 'fs/promises';
67
68
  import * as os from 'os';
68
69
 
69
70
  init_cli_invocation();
@@ -74,10 +75,10 @@ function registerStatus(program) {
74
75
  applyGlobalOptions(cmd);
75
76
  }
76
77
  async function runStatus(global) {
77
- const root2 = path37.resolve(global.cwd ?? ".");
78
+ const root2 = path39.resolve(global.cwd ?? ".");
78
79
  const graphPath = resolveGraphPath(root2, global.graph);
79
80
  const graph = loadGraph(root2, graphPath);
80
- const hasCache = fs7.existsSync(path37.join(cacheDir(root2), "parse-cache.json"));
81
+ const hasCache = fs10.existsSync(path39.join(cacheDir(root2), "parse-cache.json"));
81
82
  let stale = null;
82
83
  let staleExact = false;
83
84
  if (graph) {
@@ -97,8 +98,8 @@ async function runStatus(global) {
97
98
  }
98
99
  if (global.json) {
99
100
  json({
100
- root: path37.relative(process.cwd(), root2) || ".",
101
- graphPath: path37.relative(root2, graphPath),
101
+ root: path39.relative(process.cwd(), root2) || ".",
102
+ graphPath: path39.relative(root2, graphPath),
102
103
  built: graph !== null,
103
104
  generatedAt: graph?.generatedAt ?? null,
104
105
  counts: graph?.meta.counts ?? null,
@@ -113,11 +114,11 @@ async function runStatus(global) {
113
114
  return;
114
115
  }
115
116
  if (!graph) {
116
- info(`${c.cyan("vg")} \xB7 no map yet at ${c.dim(path37.relative(root2, graphPath))}`);
117
+ info(`${c.cyan("vg")} \xB7 no map yet at ${c.dim(path39.relative(root2, graphPath))}`);
117
118
  info(` run ${c.bold("vg")} to build one`);
118
119
  return;
119
120
  }
120
- info(`${c.cyan("vg")} \xB7 ${path37.relative(root2, graphPath)}`);
121
+ info(`${c.cyan("vg")} \xB7 ${path39.relative(root2, graphPath)}`);
121
122
  info(` generated ${graph.generatedAt}`);
122
123
  info(
123
124
  ` nodes ${c.bold(String(graph.meta.counts.nodes))} edges ${c.bold(
@@ -134,7 +135,7 @@ async function runStatus(global) {
134
135
  if (vibgrateDir(root2)) ;
135
136
  }
136
137
  function rootOf(global) {
137
- return path37.resolve(global.cwd ?? ".");
138
+ return path39.resolve(global.cwd ?? ".");
138
139
  }
139
140
  function requireGraph(global) {
140
141
  const root2 = rootOf(global);
@@ -170,6 +171,8 @@ function registerAsk(program) {
170
171
  let result;
171
172
  let mode = "lexical";
172
173
  let note = "";
174
+ const relevance = await analyzeQuestion(q);
175
+ const topicTags = relevance ? await loadTopicTags(graph, root2, resolveGraphPath(root2, global.graph)) : null;
173
176
  if (wantSemantic) {
174
177
  const firstRun = !embeddingsCached(root2, resolveEmbedModel());
175
178
  if (!global.json && firstRun) {
@@ -181,14 +184,14 @@ function registerAsk(program) {
181
184
  const bar = !global.json && firstRun ? new ProgressBar(c.dim("embedding")) : void 0;
182
185
  const vectors = await getNodeEmbeddings(graph, embedder, root2, bar ? (d, t) => bar.update(d, t) : void 0);
183
186
  bar?.done();
184
- result = await queryGraphSemantic(graph, q, { budget, embedder, nodeVectors: vectors });
187
+ result = await queryGraphSemantic(graph, q, { budget, embedder, nodeVectors: vectors, relevance, topicTags });
185
188
  mode = `semantic (${embedder.id})`;
186
189
  } else {
187
- result = queryGraph(graph, q, { budget });
190
+ result = queryGraph(graph, q, { budget, relevance, topicTags });
188
191
  note = reason ? unavailableMessage(reason) : "semantic unavailable; used lexical";
189
192
  }
190
193
  } else {
191
- result = queryGraph(graph, q, { budget });
194
+ result = queryGraph(graph, q, { budget, relevance, topicTags });
192
195
  if (global.local) note = "semantic skipped under --local; used lexical";
193
196
  }
194
197
  if (global.client) {
@@ -868,12 +871,12 @@ var PUBLISH_INTERVAL_MS = 2e3;
868
871
  var KEEPALIVE_MS = 1e4;
869
872
  var STALE_MS = 6e4;
870
873
  function liveStatsDir(root2) {
871
- return path37.join(cacheDir(root2), "serve-live");
874
+ return path39.join(cacheDir(root2), "serve-live");
872
875
  }
873
876
  function reapOtherVersionServers(dir, keepVersion, now = Date.now(), kill = (pid, signal) => process.kill(pid, signal), selfPid = process.pid) {
874
877
  let entries;
875
878
  try {
876
- entries = fs7.readdirSync(dir);
879
+ entries = fs10.readdirSync(dir);
877
880
  } catch {
878
881
  return [];
879
882
  }
@@ -882,7 +885,7 @@ function reapOtherVersionServers(dir, keepVersion, now = Date.now(), kill = (pid
882
885
  if (!/^serve-\d+\.json$/.test(name)) continue;
883
886
  let parsed;
884
887
  try {
885
- parsed = JSON.parse(fs7.readFileSync(path37.join(dir, name), "utf8"));
888
+ parsed = JSON.parse(fs10.readFileSync(path39.join(dir, name), "utf8"));
886
889
  } catch {
887
890
  continue;
888
891
  }
@@ -904,7 +907,7 @@ var LiveStatsBus = class {
904
907
  this.dir = dir;
905
908
  this.stats = stats;
906
909
  this.pid = pid;
907
- this.file = path37.join(dir, `serve-${this.pid}.json`);
910
+ this.file = path39.join(dir, `serve-${this.pid}.json`);
908
911
  }
909
912
  dir;
910
913
  stats;
@@ -936,10 +939,10 @@ var LiveStatsBus = class {
936
939
  this.lastWriteAt = now;
937
940
  const body = { pid: this.pid, updatedAt: now, version: VERSION, snapshot: snap };
938
941
  try {
939
- fs7.mkdirSync(this.dir, { recursive: true });
942
+ fs10.mkdirSync(this.dir, { recursive: true });
940
943
  const tmp = `${this.file}.tmp`;
941
- fs7.writeFileSync(tmp, JSON.stringify(body));
942
- fs7.renameSync(tmp, this.file);
944
+ fs10.writeFileSync(tmp, JSON.stringify(body));
945
+ fs10.renameSync(tmp, this.file);
943
946
  } catch {
944
947
  }
945
948
  }
@@ -950,24 +953,24 @@ var LiveStatsBus = class {
950
953
  siblings(now = Date.now()) {
951
954
  let entries;
952
955
  try {
953
- entries = fs7.readdirSync(this.dir);
956
+ entries = fs10.readdirSync(this.dir);
954
957
  } catch {
955
958
  return [];
956
959
  }
957
960
  const out2 = [];
958
961
  for (const name of entries.sort()) {
959
962
  if (!/^serve-\d+\.json$/.test(name)) continue;
960
- const file = path37.join(this.dir, name);
963
+ const file = path39.join(this.dir, name);
961
964
  let parsed;
962
965
  try {
963
- parsed = JSON.parse(fs7.readFileSync(file, "utf8"));
966
+ parsed = JSON.parse(fs10.readFileSync(file, "utf8"));
964
967
  } catch {
965
968
  continue;
966
969
  }
967
970
  if (typeof parsed?.pid !== "number" || typeof parsed.updatedAt !== "number" || !parsed.snapshot?.totals) continue;
968
971
  if (now - parsed.updatedAt > STALE_MS) {
969
972
  try {
970
- fs7.unlinkSync(file);
973
+ fs10.unlinkSync(file);
971
974
  } catch {
972
975
  }
973
976
  continue;
@@ -979,7 +982,7 @@ var LiveStatsBus = class {
979
982
  }
980
983
  unlinkOwn = () => {
981
984
  try {
982
- fs7.unlinkSync(this.file);
985
+ fs10.unlinkSync(this.file);
983
986
  } catch {
984
987
  }
985
988
  };
@@ -1292,12 +1295,12 @@ var LedgerTail = class {
1292
1295
  if (size === this.offset) return;
1293
1296
  let chunk;
1294
1297
  try {
1295
- const fd = fs7.openSync(this.file, "r");
1298
+ const fd = fs10.openSync(this.file, "r");
1296
1299
  try {
1297
1300
  chunk = Buffer.alloc(size - this.offset);
1298
- fs7.readSync(fd, chunk, 0, chunk.length, this.offset);
1301
+ fs10.readSync(fd, chunk, 0, chunk.length, this.offset);
1299
1302
  } finally {
1300
- fs7.closeSync(fd);
1303
+ fs10.closeSync(fd);
1301
1304
  }
1302
1305
  } catch {
1303
1306
  return;
@@ -1310,7 +1313,7 @@ var LedgerTail = class {
1310
1313
  }
1311
1314
  sizeOf() {
1312
1315
  try {
1313
- return fs7.statSync(this.file).size;
1316
+ return fs10.statSync(this.file).size;
1314
1317
  } catch {
1315
1318
  return 0;
1316
1319
  }
@@ -1342,7 +1345,7 @@ function ingestLedgerLine(stats, line, now) {
1342
1345
  // src/commands/serve.ts
1343
1346
  var SHARE_FLUSH_INTERVAL_MS = 5 * 60 * 1e3;
1344
1347
  function registerServe(program) {
1345
- const cmd = program.command("serve").description("start Vibgrate AI Context \u2014 local-first MCP serving your code map, drift & version-correct docs to your AI").option("--http", "serve over streamable HTTP instead of stdio").option("--port <n>", "port for --http", "7437").option("--host <h>", "host for --http", "127.0.0.1").option("--savings", "record local, counts-only usage savings (opt-in; off by default)").option("--share-stats", "ALSO upload the counts-only usage ledger to Vibgrate to improve the local MCP (opt-in; off by default; implies --savings; disabled under --local)").option("--dedup", "collapse a node's heavy relation lists on repeat reads within a session (opt-in; saves tokens)").option("--no-refresh", "serve the map as built \u2014 skip the auto-rebuild when files change").action(async function(opts) {
1348
+ const cmd = program.command("serve").description("start Vibgrate AI Context \u2014 local-first MCP serving your code map, drift & version-correct docs to your AI").option("--http", "serve over streamable HTTP instead of stdio").option("--port <n>", "port for --http", "7437").option("--host <h>", "host for --http", "127.0.0.1").option("--savings", "record local, counts-only usage savings (opt-in; off by default)").option("--share-stats", "ALSO upload the counts-only usage ledger to Vibgrate to improve the local MCP (opt-in; off by default; implies --savings; disabled under --local)").option("--dedup", "collapse a node's heavy relation lists on repeat reads within a session (opt-in; saves tokens)").option("--no-refresh", "serve the map as built \u2014 skip the auto-rebuild when files change").option("--no-watch", "disable the event-driven file watcher \u2014 freshness falls back to the periodic poll").option("--surface <mode>", 'tool listing surface: "hot" lists only the navigation core (orient/search_symbols/query_graph/get_node); "full" lists all tools. Every tool stays callable either way. Env: VG_MCP_SURFACE').option("--tools <names>", "comma-separated tool names to list (listing only \u2014 all tools remain callable). Env: VG_MCP_TOOLS").action(async function(opts) {
1346
1349
  const global = readGlobal(this);
1347
1350
  const root2 = rootOf(global);
1348
1351
  const graphPath = resolveGraphPath(root2, global.graph);
@@ -1365,8 +1368,15 @@ function registerServe(program) {
1365
1368
  local,
1366
1369
  dedup: opts.dedup === true,
1367
1370
  refresh,
1371
+ watch: opts.watch !== false,
1368
1372
  root: root2,
1369
- stats
1373
+ stats,
1374
+ // Listing surface: flags win over env; unknown values fall back to the
1375
+ // full surface inside listedToolNames (fail-open).
1376
+ toolSurface: {
1377
+ surface: (opts.surface ?? process.env.VG_MCP_SURFACE) === "hot" ? "hot" : "full",
1378
+ tools: (opts.tools ?? process.env.VG_MCP_TOOLS)?.split(",").map((s) => s.trim()).filter(Boolean)
1379
+ }
1370
1380
  };
1371
1381
  await ensureServableGraph(root2, graphPath, global, refresh);
1372
1382
  if (opts.shareStats === true && local) {
@@ -1455,6 +1465,7 @@ async function serveHttp(graphPath, host, port, opts, freshness, onReady) {
1455
1465
  const { createServer: createHttp } = await import('http');
1456
1466
  const { StreamableHTTPServerTransport } = await import('@modelcontextprotocol/sdk/server/streamableHttp.js');
1457
1467
  const source = new GraphSource(graphPath, opts.refresh !== false, { root: opts.root });
1468
+ if (opts.refresh !== false && opts.watch !== false) source.startWatching();
1458
1469
  const httpServer = createHttp(async (req, res) => {
1459
1470
  if (req.url !== "/mcp") {
1460
1471
  res.writeHead(404).end("not found");
@@ -1695,19 +1706,19 @@ function endOfLine(text, line) {
1695
1706
  }
1696
1707
  var CACHE_VERSION = "vg-lsp-scan-cache/2";
1697
1708
  function cachePath(root2) {
1698
- return path37.join(cacheDir(root2), "lsp-scan.json");
1709
+ return path39.join(cacheDir(root2), "lsp-scan.json");
1699
1710
  }
1700
1711
  function manifestHash(root2) {
1701
1712
  const files = [];
1702
1713
  const walk2 = (dir) => {
1703
1714
  let entries;
1704
1715
  try {
1705
- entries = fs7.readdirSync(dir, { withFileTypes: true });
1716
+ entries = fs10.readdirSync(dir, { withFileTypes: true });
1706
1717
  } catch {
1707
1718
  return;
1708
1719
  }
1709
1720
  for (const entry of entries) {
1710
- const abs = path37.join(dir, entry.name);
1721
+ const abs = path39.join(dir, entry.name);
1711
1722
  if (entry.isDirectory()) {
1712
1723
  if (isSkippedDirName(entry.name)) continue;
1713
1724
  walk2(abs);
@@ -1717,8 +1728,8 @@ function manifestHash(root2) {
1717
1728
  const base = entry.name.toLowerCase();
1718
1729
  if (!isManifest(abs) && !SKIP_FILES.has(base)) continue;
1719
1730
  try {
1720
- const rel = path37.relative(root2, abs).split(path37.sep).join("/");
1721
- files.push({ rel, hash: hashBytes(fs7.readFileSync(abs)) });
1731
+ const rel = path39.relative(root2, abs).split(path39.sep).join("/");
1732
+ files.push({ rel, hash: hashBytes(fs10.readFileSync(abs)) });
1722
1733
  } catch {
1723
1734
  }
1724
1735
  }
@@ -1728,16 +1739,16 @@ function manifestHash(root2) {
1728
1739
  return hashString(canonicalize(files));
1729
1740
  }
1730
1741
  function isDependencyFile(root2, filePath) {
1731
- const rel = path37.relative(path37.resolve(root2), path37.resolve(filePath));
1732
- if (rel === "" || rel.startsWith("..") || path37.isAbsolute(rel)) return false;
1733
- const parts = rel.split(path37.sep);
1742
+ const rel = path39.relative(path39.resolve(root2), path39.resolve(filePath));
1743
+ if (rel === "" || rel.startsWith("..") || path39.isAbsolute(rel)) return false;
1744
+ const parts = rel.split(path39.sep);
1734
1745
  if (parts.slice(0, -1).some((dir) => isSkippedDirName(dir))) return false;
1735
1746
  const base = parts[parts.length - 1].toLowerCase();
1736
1747
  return isManifest(filePath) || SKIP_FILES.has(base);
1737
1748
  }
1738
1749
  function loadScanCache(root2, key2) {
1739
1750
  try {
1740
- const raw = JSON.parse(fs7.readFileSync(cachePath(root2), "utf8"));
1751
+ const raw = JSON.parse(fs10.readFileSync(cachePath(root2), "utf8"));
1741
1752
  if (raw.version === CACHE_VERSION && raw.manifestHash === key2.manifestHash && raw.toolVersion === key2.toolVersion && raw.offline === key2.offline && raw.artifact) {
1742
1753
  return { manifestHash: raw.manifestHash, artifact: raw.artifact };
1743
1754
  }
@@ -1747,8 +1758,8 @@ function loadScanCache(root2, key2) {
1747
1758
  }
1748
1759
  function writeScanCache(root2, key2, artifact) {
1749
1760
  try {
1750
- fs7.mkdirSync(cacheDir(root2), { recursive: true });
1751
- fs7.writeFileSync(
1761
+ fs10.mkdirSync(cacheDir(root2), { recursive: true });
1762
+ fs10.writeFileSync(
1752
1763
  cachePath(root2),
1753
1764
  stableStringify(
1754
1765
  { version: CACHE_VERSION, manifestHash: key2.manifestHash, toolVersion: key2.toolVersion, offline: key2.offline, artifact },
@@ -1761,7 +1772,7 @@ function writeScanCache(root2, key2, artifact) {
1761
1772
  var MAX_ENTRIES = 1e3;
1762
1773
  var KEEP_ENTRIES = 500;
1763
1774
  function historyPath(root2) {
1764
- return path37.join(root2, ".vibgrate", "score-history.jsonl");
1775
+ return path39.join(root2, ".vibgrate", "score-history.jsonl");
1765
1776
  }
1766
1777
  function parseLine(line) {
1767
1778
  try {
@@ -1775,7 +1786,7 @@ function parseLine(line) {
1775
1786
  }
1776
1787
  function readHistory(root2) {
1777
1788
  try {
1778
- return fs7.readFileSync(historyPath(root2), "utf8").split("\n").filter((l) => l.trim()).map(parseLine).filter((e) => e !== null);
1789
+ return fs10.readFileSync(historyPath(root2), "utf8").split("\n").filter((l) => l.trim()).map(parseLine).filter((e) => e !== null);
1779
1790
  } catch {
1780
1791
  return [];
1781
1792
  }
@@ -1802,14 +1813,14 @@ function recordScore(root2, entry) {
1802
1813
  }
1803
1814
  }
1804
1815
  const file = historyPath(root2);
1805
- fs7.mkdirSync(path37.dirname(file), { recursive: true });
1816
+ fs10.mkdirSync(path39.dirname(file), { recursive: true });
1806
1817
  ensureVibgrateGitignore(root2);
1807
- fs7.appendFileSync(file, `${JSON.stringify(entry)}
1818
+ fs10.appendFileSync(file, `${JSON.stringify(entry)}
1808
1819
  `);
1809
1820
  const all = readHistory(root2);
1810
1821
  if (all.length > MAX_ENTRIES) {
1811
1822
  const kept = all.slice(-KEEP_ENTRIES);
1812
- fs7.writeFileSync(file, kept.map((e) => JSON.stringify(e)).join("\n") + "\n");
1823
+ fs10.writeFileSync(file, kept.map((e) => JSON.stringify(e)).join("\n") + "\n");
1813
1824
  }
1814
1825
  } catch {
1815
1826
  }
@@ -2682,10 +2693,10 @@ var VibgrateLanguageServer = class {
2682
2693
  const ecosystem = osvEcosystem(proj.type);
2683
2694
  if (!ecosystem) continue;
2684
2695
  const relManifest = manifestRelativePath(proj);
2685
- const absManifest = path37.resolve(this.opts.root, relManifest);
2696
+ const absManifest = path39.resolve(this.opts.root, relManifest);
2686
2697
  let text = null;
2687
2698
  try {
2688
- if (fs7.existsSync(absManifest)) text = fs7.readFileSync(absManifest, "utf8");
2699
+ if (fs10.existsSync(absManifest)) text = fs10.readFileSync(absManifest, "utf8");
2689
2700
  } catch {
2690
2701
  text = null;
2691
2702
  }
@@ -2815,9 +2826,9 @@ function pruneArtifactProjects(a) {
2815
2826
  return { ...a, projects, findings };
2816
2827
  }
2817
2828
  function projectByPath(a, projectPath) {
2818
- const want = path37.normalize(projectPath === "" ? "." : projectPath);
2829
+ const want = path39.normalize(projectPath === "" ? "." : projectPath);
2819
2830
  for (const proj of a.projects ?? []) {
2820
- const got = path37.normalize(proj.path === "" ? "." : proj.path);
2831
+ const got = path39.normalize(proj.path === "" ? "." : proj.path);
2821
2832
  if (got === want) return proj;
2822
2833
  }
2823
2834
  return void 0;
@@ -2854,12 +2865,12 @@ function buildProjectRefs(rootDir, projects) {
2854
2865
  return refs.length > 0 ? refs : void 0;
2855
2866
  }
2856
2867
  function projectForFile(root2, a, filePath) {
2857
- const dir = path37.dirname(path37.resolve(filePath));
2868
+ const dir = path39.dirname(path39.resolve(filePath));
2858
2869
  let best;
2859
2870
  let bestLen = -1;
2860
2871
  for (const proj of a.projects ?? []) {
2861
- const projDir = path37.resolve(root2, proj.path);
2862
- if ((dir === projDir || dir.startsWith(projDir + path37.sep)) && projDir.length > bestLen) {
2872
+ const projDir = path39.resolve(root2, proj.path);
2873
+ if ((dir === projDir || dir.startsWith(projDir + path39.sep)) && projDir.length > bestLen) {
2863
2874
  best = proj;
2864
2875
  bestLen = projDir.length;
2865
2876
  }
@@ -2867,7 +2878,7 @@ function projectForFile(root2, a, filePath) {
2867
2878
  return best;
2868
2879
  }
2869
2880
  function sameProject(location, projectPath) {
2870
- return path37.normalize(location) === path37.normalize(projectPath);
2881
+ return path39.normalize(location) === path39.normalize(projectPath);
2871
2882
  }
2872
2883
  function hasReleaseDates(a) {
2873
2884
  for (const proj of a.projects ?? []) {
@@ -2937,10 +2948,10 @@ function buildBreakdown(rootDir, projects) {
2937
2948
  const relManifest = manifestRelativePath(p);
2938
2949
  if (isPrunedWorkspacePath(p.path) || isPrunedWorkspacePath(relManifest)) continue;
2939
2950
  const ecosystem = osvEcosystem(p.type);
2940
- const absManifest = path37.resolve(rootDir, relManifest);
2951
+ const absManifest = path39.resolve(rootDir, relManifest);
2941
2952
  let text = null;
2942
2953
  try {
2943
- if (fs7.existsSync(absManifest)) text = fs7.readFileSync(absManifest, "utf8");
2954
+ if (fs10.existsSync(absManifest)) text = fs10.readFileSync(absManifest, "utf8");
2944
2955
  } catch {
2945
2956
  text = null;
2946
2957
  }
@@ -3005,34 +3016,34 @@ function buildBreakdown(rootDir, projects) {
3005
3016
  }
3006
3017
  function manifestRelativePath(proj) {
3007
3018
  const base = proj.path === "." || proj.path === "" ? "" : proj.path;
3008
- const join27 = (name) => base ? path37.join(base, name) : name;
3019
+ const join29 = (name) => base ? path39.join(base, name) : name;
3009
3020
  switch (proj.type) {
3010
3021
  case "node":
3011
3022
  case "typescript":
3012
- return join27("package.json");
3023
+ return join29("package.json");
3013
3024
  case "python":
3014
- return join27("pyproject.toml");
3025
+ return join29("pyproject.toml");
3015
3026
  case "go":
3016
- return join27("go.mod");
3027
+ return join29("go.mod");
3017
3028
  case "rust":
3018
- return join27("Cargo.toml");
3029
+ return join29("Cargo.toml");
3019
3030
  case "ruby":
3020
- return join27("Gemfile");
3031
+ return join29("Gemfile");
3021
3032
  case "php":
3022
- return join27("composer.json");
3033
+ return join29("composer.json");
3023
3034
  case "java":
3024
3035
  case "kotlin":
3025
3036
  case "scala":
3026
3037
  case "groovy":
3027
- return join27("pom.xml");
3038
+ return join29("pom.xml");
3028
3039
  case "dotnet":
3029
- return join27(proj.name ? `${proj.name}.csproj` : "Directory.Build.props");
3040
+ return join29(proj.name ? `${proj.name}.csproj` : "Directory.Build.props");
3030
3041
  case "dart":
3031
- return join27("pubspec.yaml");
3042
+ return join29("pubspec.yaml");
3032
3043
  case "elixir":
3033
- return join27("mix.exs");
3044
+ return join29("mix.exs");
3034
3045
  default:
3035
- return join27("package.json");
3046
+ return join29("package.json");
3036
3047
  }
3037
3048
  }
3038
3049
  function lockfileRelativePath(rootDir, proj) {
@@ -3063,9 +3074,9 @@ function lockfileRelativePath(rootDir, proj) {
3063
3074
  const dirsToTry = base ? [base, ""] : [""];
3064
3075
  for (const dir of dirsToTry) {
3065
3076
  for (const name of candidateNames) {
3066
- const rel = dir ? path37.join(dir, name) : name;
3077
+ const rel = dir ? path39.join(dir, name) : name;
3067
3078
  try {
3068
- if (fs7.existsSync(path37.join(rootDir, rel))) return rel;
3079
+ if (fs10.existsSync(path39.join(rootDir, rel))) return rel;
3069
3080
  } catch {
3070
3081
  }
3071
3082
  }
@@ -3136,10 +3147,10 @@ function lookupImportFiles(map, pkg) {
3136
3147
  }
3137
3148
  function firstPackageMentionLine(root2, relFile, pkg) {
3138
3149
  try {
3139
- const abs = path37.resolve(root2, relFile);
3140
- const stat2 = fs7.statSync(abs);
3150
+ const abs = path39.resolve(root2, relFile);
3151
+ const stat2 = fs10.statSync(abs);
3141
3152
  if (!stat2.isFile() || stat2.size > 256 * 1024) return null;
3142
- const text = fs7.readFileSync(abs, "utf8");
3153
+ const text = fs10.readFileSync(abs, "utf8");
3143
3154
  const tokens = [pkg];
3144
3155
  if (pkg.startsWith("@")) {
3145
3156
  const parts = pkg.split("/");
@@ -3291,7 +3302,7 @@ function hoverMarkdown(dep, contribution) {
3291
3302
  return lines.join("\n");
3292
3303
  }
3293
3304
  function startLanguageServer(opts) {
3294
- if (!fs7.existsSync(opts.root)) {
3305
+ if (!fs10.existsSync(opts.root)) {
3295
3306
  process.stderr.write(`vg lsp: root does not exist: ${opts.root}
3296
3307
  `);
3297
3308
  process.exit(1);
@@ -3333,10 +3344,90 @@ function registerLsp(program) {
3333
3344
  });
3334
3345
  applyGlobalOptions(cmd);
3335
3346
  }
3347
+ var HOOK_NEEDLE = "vg hook pre-tool-use";
3348
+ var MATCHER = "Grep|Glob";
3349
+ var HOOK_TIMEOUT_S = 10;
3350
+ function hookCommand(vgBin) {
3351
+ return `${vgBin} hook pre-tool-use`;
3352
+ }
3353
+ function installClaudeHooks(root2, vgBin = "vg") {
3354
+ const file = path39.join(root2, ".claude", "settings.json");
3355
+ const rel = path39.join(".claude", "settings.json");
3356
+ let settings = {};
3357
+ if (fs10.existsSync(file)) {
3358
+ try {
3359
+ const parsed = JSON.parse(fs10.readFileSync(file, "utf8"));
3360
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
3361
+ return { file: rel, status: "skipped", note: "settings.json is not a JSON object \u2014 left untouched" };
3362
+ }
3363
+ settings = parsed;
3364
+ } catch {
3365
+ return { file: rel, status: "skipped", note: "settings.json is not parseable JSON \u2014 left untouched (fix it and rerun)" };
3366
+ }
3367
+ }
3368
+ const hooks = settings.hooks ??= {};
3369
+ if (typeof hooks !== "object" || Array.isArray(hooks)) {
3370
+ return { file: rel, status: "skipped", note: '"hooks" is not an object \u2014 left untouched' };
3371
+ }
3372
+ const pre = hooks.PreToolUse ??= [];
3373
+ if (!Array.isArray(pre)) {
3374
+ return { file: rel, status: "skipped", note: '"hooks.PreToolUse" is not an array \u2014 left untouched' };
3375
+ }
3376
+ const desired = { type: "command", command: hookCommand(vgBin), timeout: HOOK_TIMEOUT_S };
3377
+ for (const group of pre) {
3378
+ for (const entry of group.hooks ?? []) {
3379
+ if (typeof entry.command === "string" && entry.command.includes(HOOK_NEEDLE)) {
3380
+ if (entry.command === desired.command && entry.timeout === desired.timeout && group.matcher === MATCHER) {
3381
+ return { file: rel, status: "unchanged" };
3382
+ }
3383
+ entry.command = desired.command;
3384
+ entry.timeout = desired.timeout;
3385
+ group.matcher = MATCHER;
3386
+ writeSettings(file, settings);
3387
+ return { file: rel, status: "written", note: "updated existing vg hook entry" };
3388
+ }
3389
+ }
3390
+ }
3391
+ pre.push({ matcher: MATCHER, hooks: [desired] });
3392
+ writeSettings(file, settings);
3393
+ return { file: rel, status: "written" };
3394
+ }
3395
+ function uninstallClaudeHooks(root2) {
3396
+ const file = path39.join(root2, ".claude", "settings.json");
3397
+ const rel = path39.join(".claude", "settings.json");
3398
+ if (!fs10.existsSync(file)) return { file: rel, status: "unchanged" };
3399
+ let settings;
3400
+ try {
3401
+ settings = JSON.parse(fs10.readFileSync(file, "utf8"));
3402
+ } catch {
3403
+ return { file: rel, status: "skipped", note: "settings.json is not parseable JSON \u2014 left untouched" };
3404
+ }
3405
+ const hooks = settings.hooks;
3406
+ const pre = hooks?.PreToolUse;
3407
+ if (!Array.isArray(pre)) return { file: rel, status: "unchanged" };
3408
+ let removed = false;
3409
+ for (const group of pre) {
3410
+ const before = group.hooks?.length ?? 0;
3411
+ group.hooks = (group.hooks ?? []).filter((e) => !(typeof e.command === "string" && e.command.includes(HOOK_NEEDLE)));
3412
+ if (group.hooks.length !== before) removed = true;
3413
+ }
3414
+ const kept = pre.filter((g) => (g.hooks?.length ?? 0) > 0);
3415
+ if (!removed) return { file: rel, status: "unchanged" };
3416
+ if (kept.length) hooks.PreToolUse = kept;
3417
+ else delete hooks.PreToolUse;
3418
+ if (hooks && Object.keys(hooks).length === 0) delete settings.hooks;
3419
+ writeSettings(file, settings);
3420
+ return { file: rel, status: "written" };
3421
+ }
3422
+ function writeSettings(file, settings) {
3423
+ fs10.mkdirSync(path39.dirname(file), { recursive: true });
3424
+ fs10.writeFileSync(file, `${JSON.stringify(settings, null, 2)}
3425
+ `);
3426
+ }
3336
3427
 
3337
3428
  // src/commands/install.ts
3338
3429
  function registerInstall(program) {
3339
- const install = program.command("install").description("add vg to your AI assistant(s): skill + MCP + advisory nudge").argument("[tools...]", `assistant ids: ${ASSISTANTS.map((a) => a.id).join(", ")}`).option("--all", "install for every supported assistant").option("--detect", "detect assistants in use (repo footprint, home config, PATH) and install for those; with --list, only report what was detected").option("--list", "show the support matrix and exit").option("--no-hook", "skip the advisory nudge").action(function(tools, opts) {
3430
+ const install = program.command("install").description("add vg to your AI assistant(s): skill + MCP + advisory nudge").argument("[tools...]", `assistant ids: ${ASSISTANTS.map((a) => a.id).join(", ")}`).option("--all", "install for every supported assistant").option("--detect", "detect assistants in use (repo footprint, home config, PATH) and install for those; with --list, only report what was detected").option("--list", "show the support matrix and exit").option("--no-hook", "skip the advisory nudge").option("--hooks", "also wire the PreToolUse enrichment hook (Claude Code): Grep/Glob calls get graph context via `vg hook pre-tool-use` (project .claude/settings.json; opt-in)").action(function(tools, opts) {
3340
3431
  const global = readGlobal(this);
3341
3432
  const root2 = rootOf(global);
3342
3433
  const detected = opts.detect ? detectAssistants(root2) : [];
@@ -3400,6 +3491,12 @@ function registerInstall(program) {
3400
3491
  for (const r of results) {
3401
3492
  info(`${c.green("\u2714")} ${c.bold(r.id)} \u2014 wrote ${r.wrote.join(", ")}${r.skipped.length ? c.dim(` (skipped ${r.skipped.join(", ")})`) : ""}`);
3402
3493
  }
3494
+ if (opts.hooks && targets.some((a) => a.id === "claude")) {
3495
+ const vgBin = launch.command === "npx" ? null : launch.command;
3496
+ const hooksResult = vgBin ? installClaudeHooks(root2, vgBin) : { file: ".claude/settings.json", status: "skipped", note: "vg is not installed on PATH \u2014 hooks need a fast binary (npm i -g @vibgrate/cli), rerun with --hooks after" };
3497
+ if (hooksResult.status === "written") info(`${c.green("\u2714")} ${c.bold("hooks")} \u2014 wrote PreToolUse enrichment into ${hooksResult.file}`);
3498
+ else if (hooksResult.note) info(`${c.yellow("!")} hooks \u2014 ${hooksResult.note}`);
3499
+ }
3403
3500
  if (launch.note && results.some((r) => r.note)) info(`${c.yellow("!")} ${launch.note}`);
3404
3501
  if (smallRepo) info(c.dim(` note: small repo (${fileCount} files) \u2014 nudge says searching is fine; vg is still used for impact/tests`));
3405
3502
  info(c.dim(` wrote ${navConfig} \u2014 deferred-loading config for Claude-API agents (lower per-step token cost)`));
@@ -3410,6 +3507,10 @@ function registerInstall(program) {
3410
3507
  const global = readGlobal(this);
3411
3508
  const root2 = rootOf(global);
3412
3509
  const results = tools.map(resolve5).map((a) => ({ id: a.id, removed: uninstallAssistant(a, root2, !!opts.purge) }));
3510
+ if (tools.map(resolve5).some((a) => a.id === "claude")) {
3511
+ const hooksResult = uninstallClaudeHooks(root2);
3512
+ if (hooksResult.status === "written") results.find((r) => r.id === "claude")?.removed.push(`${hooksResult.file} (vg hook entries)`);
3513
+ }
3413
3514
  if (global.json) {
3414
3515
  json({ root: root2, results });
3415
3516
  return;
@@ -3434,14 +3535,289 @@ function resolve5(id) {
3434
3535
  }
3435
3536
  return a;
3436
3537
  }
3538
+ var RELEVANCE_MODULE_NAME = "@vibgrate/relevance";
3539
+ var DEFAULT_REGISTRY = "https://registry.npmjs.org";
3540
+ function registryBase(opts) {
3541
+ return (process.env.VIBGRATE_MODULE_REGISTRY || opts.registry || DEFAULT_REGISTRY).replace(/\/+$/, "");
3542
+ }
3543
+ function stateFile() {
3544
+ return path39.join(path39.dirname(relevanceModuleDir()), "consent.json");
3545
+ }
3546
+ function readConsent() {
3547
+ try {
3548
+ return JSON.parse(fs10.readFileSync(stateFile(), "utf8"));
3549
+ } catch {
3550
+ return {};
3551
+ }
3552
+ }
3553
+ function writeConsent(state) {
3554
+ try {
3555
+ fs10.mkdirSync(path39.dirname(stateFile()), { recursive: true });
3556
+ fs10.writeFileSync(stateFile(), JSON.stringify(state));
3557
+ } catch {
3558
+ }
3559
+ }
3560
+ function kernelDisabled() {
3561
+ const v = process.env.VIBGRATE_NO_KERNEL;
3562
+ return v === "1" || v === "true";
3563
+ }
3564
+ function moduleInstalled() {
3565
+ try {
3566
+ const meta = JSON.parse(fs10.readFileSync(path39.join(relevanceModuleDir(), ".module.json"), "utf8"));
3567
+ if (fs10.existsSync(path39.join(relevanceModuleDir(), "index.js"))) {
3568
+ return { installed: true, version: meta.version };
3569
+ }
3570
+ } catch {
3571
+ }
3572
+ return { installed: false };
3573
+ }
3574
+ var DISCLOSURE = "vg can install the optional Vibgrate relevance module (proprietary license, runs fully locally, improves how questions find the code they mean). Disable any time with VIBGRATE_NO_KERNEL=1.";
3575
+ function verifyIntegrity(buf, integrity, shasum) {
3576
+ if (integrity) {
3577
+ const [algo, expected] = integrity.split("-", 2);
3578
+ if (!algo || !expected) throw new Error("malformed integrity metadata");
3579
+ const actual = createHash(algo).update(buf).digest("base64");
3580
+ if (actual !== expected) throw new Error(`integrity mismatch (${algo})`);
3581
+ return;
3582
+ }
3583
+ if (shasum) {
3584
+ const actual = createHash("sha1").update(buf).digest("hex");
3585
+ if (actual !== shasum) throw new Error("integrity mismatch (shasum)");
3586
+ return;
3587
+ }
3588
+ throw new Error("registry provided no integrity metadata");
3589
+ }
3590
+ function untar(data) {
3591
+ const out2 = [];
3592
+ let offset = 0;
3593
+ let pendingName = null;
3594
+ while (offset + 512 <= data.length) {
3595
+ const block = data.subarray(offset, offset + 512);
3596
+ offset += 512;
3597
+ if (block.every((b) => b === 0)) continue;
3598
+ const rawName = block.subarray(0, 100).toString("utf8").replace(/\0.*$/, "");
3599
+ const size = parseInt(block.subarray(124, 136).toString("utf8").replace(/\0.*$/, "").trim() || "0", 8);
3600
+ const type = String.fromCharCode(block[156]);
3601
+ const prefix = block.subarray(345, 500).toString("utf8").replace(/\0.*$/, "");
3602
+ const body = data.subarray(offset, offset + size);
3603
+ offset += Math.ceil(size / 512) * 512;
3604
+ if (type === "L") {
3605
+ pendingName = body.toString("utf8").replace(/\0.*$/, "");
3606
+ continue;
3607
+ }
3608
+ if (type === "x" || type === "g") {
3609
+ const m = /(?:^|\n)\d+ path=([^\n]+)\n/.exec(body.toString("utf8"));
3610
+ if (m) pendingName = m[1];
3611
+ continue;
3612
+ }
3613
+ if (type !== "0" && type !== "\0") continue;
3614
+ const name = pendingName ?? (prefix ? `${prefix}/${rawName}` : rawName);
3615
+ pendingName = null;
3616
+ if (name.split("/").includes("..") || path39.isAbsolute(name)) {
3617
+ throw new Error(`unsafe path in tarball: ${name}`);
3618
+ }
3619
+ out2.push({ name, body: Buffer.from(body) });
3620
+ }
3621
+ return out2;
3622
+ }
3623
+ async function installRelevanceModule(opts = {}) {
3624
+ if (kernelDisabled()) return { status: "disabled", detail: "VIBGRATE_NO_KERNEL is set" };
3625
+ const existing = moduleInstalled();
3626
+ if (existing.installed && !opts.force) return { status: "already-installed", version: existing.version };
3627
+ const doFetch = opts.fetchImpl ?? fetch;
3628
+ const base = registryBase(opts);
3629
+ try {
3630
+ const metaRes = await doFetch(`${base}/${RELEVANCE_MODULE_NAME.replace("/", "%2f")}`);
3631
+ if (!metaRes.ok) return { status: "unavailable", detail: `registry ${metaRes.status}` };
3632
+ const meta = await metaRes.json();
3633
+ const version = meta["dist-tags"]?.latest;
3634
+ const dist = version ? meta.versions?.[version]?.dist : void 0;
3635
+ if (!version || !dist?.tarball) return { status: "unavailable", detail: "no published version" };
3636
+ const tarRes = await doFetch(dist.tarball);
3637
+ if (!tarRes.ok) return { status: "unavailable", detail: `tarball ${tarRes.status}` };
3638
+ const gz = Buffer.from(await tarRes.arrayBuffer());
3639
+ verifyIntegrity(gz, dist.integrity, dist.shasum);
3640
+ const entries = untar(zlib.gunzipSync(gz));
3641
+ const dir = relevanceModuleDir();
3642
+ fs10.rmSync(dir, { recursive: true, force: true });
3643
+ fs10.mkdirSync(dir, { recursive: true });
3644
+ let wrote = 0;
3645
+ for (const e of entries) {
3646
+ let rel = null;
3647
+ if (e.name.startsWith("package/dist/")) rel = e.name.slice("package/dist/".length);
3648
+ else if (e.name === "package/LICENSE" || e.name === "package/README.md") rel = e.name.slice("package/".length);
3649
+ if (!rel) continue;
3650
+ const target = path39.join(dir, rel);
3651
+ if (!target.startsWith(dir + path39.sep) && target !== dir) throw new Error(`unsafe extract path: ${rel}`);
3652
+ fs10.mkdirSync(path39.dirname(target), { recursive: true });
3653
+ fs10.writeFileSync(target, e.body);
3654
+ wrote += 1;
3655
+ }
3656
+ if (!wrote || !fs10.existsSync(path39.join(dir, "index.js"))) {
3657
+ fs10.rmSync(dir, { recursive: true, force: true });
3658
+ return { status: "unavailable", detail: "package layout not recognized (no dist/index.js)" };
3659
+ }
3660
+ fs10.writeFileSync(path39.join(dir, ".module.json"), JSON.stringify({ name: RELEVANCE_MODULE_NAME, version }));
3661
+ resetRelevanceProviderCache();
3662
+ return { status: "installed", version };
3663
+ } catch (e) {
3664
+ return { status: "unavailable", detail: String(e.message ?? e).slice(0, 200) };
3665
+ }
3666
+ }
3667
+ function removeRelevanceModule() {
3668
+ fs10.rmSync(relevanceModuleDir(), { recursive: true, force: true });
3669
+ resetRelevanceProviderCache();
3670
+ }
3671
+ async function ensureRelevanceModule(io = {}) {
3672
+ try {
3673
+ if (kernelDisabled()) return { status: "disabled" };
3674
+ const existing = moduleInstalled();
3675
+ if (existing.installed) return { status: "already-installed", version: existing.version };
3676
+ if (readConsent().relevance === "denied") return { status: "declined" };
3677
+ return await installRelevanceModule({ fetchImpl: io.fetchImpl });
3678
+ } catch {
3679
+ return { status: "unavailable", detail: "auto-install failed" };
3680
+ }
3681
+ }
3682
+
3683
+ // src/commands/module.ts
3684
+ function registerModule(program) {
3685
+ const cmd = program.command("module").description("manage optional local modules (relevance)");
3686
+ cmd.command("install").description("install an optional module (fetches from the registry, integrity-checked)").argument("<name>", "module name (supported: relevance)").option("--yes", "skip the confirmation prompt").option("--force", "reinstall even when already present").action(async function(name, opts) {
3687
+ const global = readGlobal(this);
3688
+ requireRelevance(name);
3689
+ if (kernelDisabled()) {
3690
+ throw new CliError("VIBGRATE_NO_KERNEL is set \u2014 unset it to install the relevance module", ExitCode.USAGE_ERROR);
3691
+ }
3692
+ if (!opts.yes && process.stdin.isTTY && process.stdout.isTTY) {
3693
+ const ok = await confirm(`${DISCLOSURE}
3694
+ Install now? [Y/n] `);
3695
+ if (!ok) {
3696
+ writeConsent({ ...readConsent(), relevance: "denied" });
3697
+ info("not installed");
3698
+ return;
3699
+ }
3700
+ }
3701
+ writeConsent({ ...readConsent(), relevance: "granted" });
3702
+ const result = await installRelevanceModule({ force: opts.force });
3703
+ if (global.json) {
3704
+ json(result);
3705
+ if (result.status === "unavailable") process.exitCode = ExitCode.ERROR;
3706
+ return;
3707
+ }
3708
+ if (result.status === "installed") out(`installed ${RELEVANCE_MODULE_NAME}@${result.version}`);
3709
+ else if (result.status === "already-installed") out(`already installed (${result.version ?? "unknown"}) \u2014 use --force to reinstall`);
3710
+ else throw new CliError(`install failed: ${result.detail ?? result.status} \u2014 check network access to the registry, or retry later`, ExitCode.ERROR);
3711
+ });
3712
+ cmd.command("remove").description("remove an installed module").argument("<name>", "module name (supported: relevance)").action(async function(name) {
3713
+ requireRelevance(name);
3714
+ removeRelevanceModule();
3715
+ out("removed");
3716
+ });
3717
+ cmd.command("status").description("show installed modules and whether they load").action(async function() {
3718
+ const global = readGlobal(this);
3719
+ const installed = moduleInstalled();
3720
+ resetRelevanceProviderCache();
3721
+ const provider = installed.installed ? await loadRelevanceProvider() : null;
3722
+ const status = {
3723
+ relevance: {
3724
+ installed: installed.installed,
3725
+ version: installed.version ?? null,
3726
+ loadable: !!provider,
3727
+ providerVersion: provider ? provider.version() : null,
3728
+ disabled: kernelDisabled(),
3729
+ consent: readConsent().relevance ?? "unset"
3730
+ }
3731
+ };
3732
+ if (global.json) {
3733
+ json(status);
3734
+ return;
3735
+ }
3736
+ const r = status.relevance;
3737
+ out(`relevance: ${r.installed ? `installed ${r.version}` : "not installed"}${r.disabled ? " (disabled via VIBGRATE_NO_KERNEL)" : ""}`);
3738
+ if (r.installed) out(` loads: ${r.loadable ? `yes (${r.providerVersion})` : "no"}`);
3739
+ info(c.dim(` consent: ${r.consent}`));
3740
+ });
3741
+ applyGlobalOptions(cmd);
3742
+ }
3743
+ function requireRelevance(name) {
3744
+ if (name !== "relevance") {
3745
+ throw usageError(`unknown module '${name}' \u2014 supported modules: relevance`);
3746
+ }
3747
+ }
3748
+ function confirm(question) {
3749
+ return new Promise((resolve21) => {
3750
+ const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
3751
+ rl.question(question, (answer) => {
3752
+ rl.close();
3753
+ resolve21(answer.trim() === "" || /^y(es)?$/i.test(answer.trim()));
3754
+ });
3755
+ });
3756
+ }
3757
+ var MAX_HOOK_MATCHES = 5;
3758
+ var MIN_PATTERN_CHARS = 3;
3759
+ function patternToQuery(pattern) {
3760
+ return pattern.replace(/\\[dwsbDWSB]/g, " ").replace(/[\\^$.*+?()[\]{}|]/g, " ").replace(/\s+/g, " ").trim();
3761
+ }
3762
+ function hookContext(payloadText, root2, graphOverride) {
3763
+ let payload;
3764
+ try {
3765
+ payload = JSON.parse(payloadText);
3766
+ } catch {
3767
+ return null;
3768
+ }
3769
+ if (payload.tool_name !== "Grep" && payload.tool_name !== "Glob") return null;
3770
+ const raw = payload.tool_input?.pattern ?? payload.tool_input?.query ?? "";
3771
+ const query = patternToQuery(String(raw));
3772
+ if (query.length < MIN_PATTERN_CHARS) return null;
3773
+ const graphPath = resolveGraphPath(root2, graphOverride);
3774
+ let graph;
3775
+ try {
3776
+ const preferred = loadGraphPreferIndex(root2, graphPath);
3777
+ graph = preferred ? preferred.graph : parseGraph(fs10.readFileSync(graphPath, "utf8"));
3778
+ } catch {
3779
+ return null;
3780
+ }
3781
+ const result = queryGraph(graph, query, {});
3782
+ const matches = result.matches.slice(0, MAX_HOOK_MATCHES);
3783
+ if (!matches.length) return null;
3784
+ const lines = matches.map(
3785
+ (m) => `- \`${m.node.qualifiedName}\` (${m.node.kind}) \u2014 ${m.node.file}:${m.node.span.start}${m.node.isHub ? " [hub \u2014 check impact_of before changing]" : ""}`
3786
+ );
3787
+ return [
3788
+ `vg code map \u2014 symbols matching "${query}":`,
3789
+ ...lines,
3790
+ "These locations come from the deterministic code graph; prefer them over scanning the raw grep output."
3791
+ ].join("\n");
3792
+ }
3793
+ function registerHook(program) {
3794
+ const cmd = program.command("hook", { hidden: true }).description("assistant-host hook endpoints (wired by `vg install --hooks`)");
3795
+ const pre = cmd.command("pre-tool-use").description("PreToolUse enrichment: annotate Grep/Glob calls with graph context (stdin: host hook payload)").action(async function() {
3796
+ const global = readGlobal(this);
3797
+ const root2 = rootOf(global);
3798
+ try {
3799
+ const stdin = fs10.readFileSync(0, "utf8");
3800
+ const context = hookContext(stdin, root2, global.graph);
3801
+ if (context) {
3802
+ process.stdout.write(
3803
+ `${JSON.stringify({ hookSpecificOutput: { hookEventName: "PreToolUse", additionalContext: context } })}
3804
+ `
3805
+ );
3806
+ }
3807
+ } catch {
3808
+ }
3809
+ });
3810
+ applyGlobalOptions(pre);
3811
+ applyGlobalOptions(cmd);
3812
+ }
3437
3813
  var HOOK_BEGIN = "# vg:begin";
3438
3814
  var HOOK_END = "# vg:end";
3439
3815
  function registerShare(program) {
3440
3816
  const cmd = program.command("share").description("make the map committable + auto-updating for your team (git)").option("--undo", "reverse what `vg share` installed").option("--reports", "also commit graph.html / GRAPH_REPORT.md (default: gitignored)").action(function(opts) {
3441
3817
  const global = readGlobal(this);
3442
3818
  const root2 = rootOf(global);
3443
- const gitDir = path37.join(root2, ".git");
3444
- if (!fs7.existsSync(gitDir)) {
3819
+ const gitDir = path39.join(root2, ".git");
3820
+ if (!fs10.existsSync(gitDir)) {
3445
3821
  throw new CliError("not a git repository \u2014 run `vg share` inside a git repo", ExitCode.USAGE_ERROR);
3446
3822
  }
3447
3823
  if (opts.undo) {
@@ -3462,23 +3838,23 @@ function registerShare(program) {
3462
3838
  applyGlobalOptions(cmd);
3463
3839
  }
3464
3840
  function writeVibgrateGitignore(root2, reports) {
3465
- const dir = path37.join(root2, ".vibgrate");
3466
- fs7.mkdirSync(dir, { recursive: true });
3841
+ const dir = path39.join(root2, ".vibgrate");
3842
+ fs10.mkdirSync(dir, { recursive: true });
3467
3843
  const lines = ["# Managed by `vg share` \u2014 keep graph.json committed, ignore the rest", "cache/", "facts.jsonl", "graph.snap"];
3468
3844
  if (!reports) lines.push("graph.html", "GRAPH_REPORT.md");
3469
- fs7.writeFileSync(path37.join(dir, ".gitignore"), `${lines.join("\n")}
3845
+ fs10.writeFileSync(path39.join(dir, ".gitignore"), `${lines.join("\n")}
3470
3846
  `);
3471
3847
  }
3472
3848
  function writeGitAttributes(root2) {
3473
- const file = path37.join(root2, ".gitattributes");
3849
+ const file = path39.join(root2, ".gitattributes");
3474
3850
  const line = ".vibgrate/graph.json merge=vg";
3475
- let content = fs7.existsSync(file) ? fs7.readFileSync(file, "utf8") : "";
3851
+ let content = fs10.existsSync(file) ? fs10.readFileSync(file, "utf8") : "";
3476
3852
  if (!content.split("\n").some((l) => l.trim() === line)) {
3477
3853
  content = content.length ? `${content.replace(/\s*$/, "")}
3478
3854
  ${line}
3479
3855
  ` : `${line}
3480
3856
  `;
3481
- fs7.writeFileSync(file, content);
3857
+ fs10.writeFileSync(file, content);
3482
3858
  }
3483
3859
  }
3484
3860
  function configureMergeDriver(root2) {
@@ -3487,8 +3863,8 @@ function configureMergeDriver(root2) {
3487
3863
  }
3488
3864
  function installPreCommitHook(root2) {
3489
3865
  const hooksDir = hookDir(root2);
3490
- fs7.mkdirSync(hooksDir, { recursive: true });
3491
- const file = path37.join(hooksDir, "pre-commit");
3866
+ fs10.mkdirSync(hooksDir, { recursive: true });
3867
+ const file = path39.join(hooksDir, "pre-commit");
3492
3868
  const block = [
3493
3869
  HOOK_BEGIN,
3494
3870
  "if command -v vg >/dev/null 2>&1; then",
@@ -3497,7 +3873,7 @@ function installPreCommitHook(root2) {
3497
3873
  "fi",
3498
3874
  HOOK_END
3499
3875
  ].join("\n");
3500
- let content = fs7.existsSync(file) ? fs7.readFileSync(file, "utf8") : "#!/bin/sh\n";
3876
+ let content = fs10.existsSync(file) ? fs10.readFileSync(file, "utf8") : "#!/bin/sh\n";
3501
3877
  const re = new RegExp(`${escapeRe(HOOK_BEGIN)}[\\s\\S]*?${escapeRe(HOOK_END)}`);
3502
3878
  if (re.test(content)) content = content.replace(re, block);
3503
3879
  else content = `${content.replace(/\s*$/, "")}
@@ -3506,21 +3882,21 @@ ${block}
3506
3882
  `;
3507
3883
  if (!content.startsWith("#!")) content = `#!/bin/sh
3508
3884
  ${content}`;
3509
- fs7.writeFileSync(file, content);
3510
- fs7.chmodSync(file, 493);
3885
+ fs10.writeFileSync(file, content);
3886
+ fs10.chmodSync(file, 493);
3511
3887
  }
3512
3888
  function undo(root2) {
3513
- const hookFile = path37.join(hookDir(root2), "pre-commit");
3514
- if (fs7.existsSync(hookFile)) {
3889
+ const hookFile = path39.join(hookDir(root2), "pre-commit");
3890
+ if (fs10.existsSync(hookFile)) {
3515
3891
  const re = new RegExp(`\\n*${escapeRe(HOOK_BEGIN)}[\\s\\S]*?${escapeRe(HOOK_END)}\\n*`);
3516
- const next2 = fs7.readFileSync(hookFile, "utf8").replace(re, "\n");
3517
- if (next2.trim() === "#!/bin/sh") fs7.rmSync(hookFile);
3518
- else fs7.writeFileSync(hookFile, next2);
3892
+ const next2 = fs10.readFileSync(hookFile, "utf8").replace(re, "\n");
3893
+ if (next2.trim() === "#!/bin/sh") fs10.rmSync(hookFile);
3894
+ else fs10.writeFileSync(hookFile, next2);
3519
3895
  }
3520
- const attr = path37.join(root2, ".gitattributes");
3521
- if (fs7.existsSync(attr)) {
3522
- const next2 = fs7.readFileSync(attr, "utf8").split("\n").filter((l) => l.trim() !== ".vibgrate/graph.json merge=vg").join("\n");
3523
- fs7.writeFileSync(attr, next2);
3896
+ const attr = path39.join(root2, ".gitattributes");
3897
+ if (fs10.existsSync(attr)) {
3898
+ const next2 = fs10.readFileSync(attr, "utf8").split("\n").filter((l) => l.trim() !== ".vibgrate/graph.json merge=vg").join("\n");
3899
+ fs10.writeFileSync(attr, next2);
3524
3900
  }
3525
3901
  try {
3526
3902
  git(root2, ["config", "--remove-section", "merge.vg"]);
@@ -3530,10 +3906,10 @@ function undo(root2) {
3530
3906
  function hookDir(root2) {
3531
3907
  try {
3532
3908
  const configured = git(root2, ["config", "--get", "core.hooksPath"]).trim();
3533
- if (configured) return path37.resolve(root2, configured);
3909
+ if (configured) return path39.resolve(root2, configured);
3534
3910
  } catch {
3535
3911
  }
3536
- return path37.join(root2, ".git", "hooks");
3912
+ return path39.join(root2, ".git", "hooks");
3537
3913
  }
3538
3914
  function git(root2, args) {
3539
3915
  return execFileSync("git", args, { cwd: root2, encoding: "utf8" });
@@ -3542,28 +3918,14 @@ function escapeRe(s) {
3542
3918
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3543
3919
  }
3544
3920
  var DEFAULT_DEBOUNCE_MS = 400;
3545
- var SKIP_NAME = /* @__PURE__ */ new Set([
3546
- ".git",
3547
- "node_modules",
3548
- ".vibgrate",
3549
- "dist",
3550
- "build",
3551
- "out",
3552
- "coverage",
3553
- ".next",
3554
- "target",
3555
- "__pycache__",
3556
- ".venv",
3557
- "venv"
3558
- ]);
3559
3921
  function registerWatch(program) {
3560
3922
  const cmd = program.command("watch").description("rebuild the code map when files change (debounced)").argument("[paths...]", "folders to watch (default: current folder)").option("--debounce <ms>", "settle time after a change before rebuild", String(DEFAULT_DEBOUNCE_MS)).option("--no-html", "do not write graph.html on each rebuild").option("--no-report", "do not write GRAPH_REPORT.md on each rebuild").option("--fast", "skip precise tsc resolve on rebuilds (heuristic only)").action(async function(paths, opts) {
3561
3923
  const global = readGlobal(this);
3562
3924
  const root2 = rootOf(global);
3563
3925
  const debounceMs = Math.max(50, Number(opts.debounce) || DEFAULT_DEBOUNCE_MS);
3564
- const watchRoots = (paths.length ? paths : ["."]).map((p) => path37.resolve(root2, p));
3926
+ const watchRoots = (paths.length ? paths : ["."]).map((p) => path39.resolve(root2, p));
3565
3927
  for (const w of watchRoots) {
3566
- if (!fs7.existsSync(w)) {
3928
+ if (!fs10.existsSync(w)) {
3567
3929
  throw new CliError(`watch path not found: ${w}`, ExitCode.USAGE_ERROR);
3568
3930
  }
3569
3931
  }
@@ -3616,16 +3978,12 @@ function registerWatch(program) {
3616
3978
  const watchers = [];
3617
3979
  for (const w of watchRoots) {
3618
3980
  try {
3619
- const watcher = fs7.watch(w, { recursive: true }, (_event, filename) => {
3981
+ const watcher = fs10.watch(w, { recursive: true }, (_event, filename) => {
3620
3982
  if (!filename) {
3621
3983
  schedule("change");
3622
3984
  return;
3623
3985
  }
3624
- const parts = filename.split(path37.sep);
3625
- if (parts.some((p) => SKIP_NAME.has(p))) return;
3626
- if (filename.includes(`${path37.sep}.vibgrate${path37.sep}`) || filename.startsWith(".vibgrate")) {
3627
- return;
3628
- }
3986
+ if (!isRelevantChange(filename)) return;
3629
3987
  schedule(filename);
3630
3988
  });
3631
3989
  watchers.push(watcher);
@@ -3633,7 +3991,7 @@ function registerWatch(program) {
3633
3991
  throw new CliError(`cannot watch ${w}: ${err.message}`, ExitCode.ERROR);
3634
3992
  }
3635
3993
  }
3636
- info(c.dim(`vg watch \xB7 watching ${watchRoots.map((p) => path37.relative(root2, p) || ".").join(", ")} (debounce ${debounceMs}ms) \xB7 Ctrl+C to stop`));
3994
+ info(c.dim(`vg watch \xB7 watching ${watchRoots.map((p) => path39.relative(root2, p) || ".").join(", ")} (debounce ${debounceMs}ms) \xB7 Ctrl+C to stop`));
3637
3995
  await new Promise((resolve21) => {
3638
3996
  const stop = () => {
3639
3997
  for (const w of watchers) w.close();
@@ -3966,10 +4324,10 @@ function normalizeStandards(raw) {
3966
4324
  }
3967
4325
  function loadStandards(root2) {
3968
4326
  for (const rel of STANDARDS_FILES) {
3969
- const p = path37__default.join(root2, rel);
4327
+ const p = path39__default.join(root2, rel);
3970
4328
  let text;
3971
4329
  try {
3972
- text = fs7__default.readFileSync(p, "utf8");
4330
+ text = fs10__default.readFileSync(p, "utf8");
3973
4331
  } catch {
3974
4332
  continue;
3975
4333
  }
@@ -4687,8 +5045,8 @@ async function runHostBench(options = {}) {
4687
5045
  }
4688
5046
  async function runArmSimulate(input) {
4689
5047
  const { arm, lib, modelPath, turns, trie, env, live } = input;
4690
- const path39 = `${modelPath}#${arm.id}`;
4691
- const session = await acquireHostSession(lib, path39);
5048
+ const path41 = `${modelPath}#${arm.id}`;
5049
+ const session = await acquireHostSession(lib, path41);
4692
5050
  const system = "You are a coding agent with a Task Capsule.";
4693
5051
  const capsule = "function readConfig(): Config { return load(); }";
4694
5052
  let last = null;
@@ -5900,7 +6258,7 @@ function registerModels(program) {
5900
6258
  );
5901
6259
  }
5902
6260
  } else {
5903
- if (!target.path || !fs7.existsSync(target.path)) {
6261
+ if (!target.path || !fs10.existsSync(target.path)) {
5904
6262
  throw new CliError(
5905
6263
  `model file not found at ${target.path || "(unknown path)"} \u2014 it may already be removed.`,
5906
6264
  ExitCode.NOT_FOUND
@@ -5914,7 +6272,7 @@ function registerModels(program) {
5914
6272
  }
5915
6273
  if (!global.json) info(c.dim(` $ rm ${target.path}`));
5916
6274
  try {
5917
- fs7.unlinkSync(target.path);
6275
+ fs10.unlinkSync(target.path);
5918
6276
  } catch (e) {
5919
6277
  const msg = e instanceof Error ? e.message : String(e);
5920
6278
  throw new CliError(`could not delete ${target.path}: ${msg}`, ExitCode.ERROR);
@@ -6052,9 +6410,9 @@ function registerModels(program) {
6052
6410
  }
6053
6411
  });
6054
6412
  if (opts.out) {
6055
- const outPath = path37.resolve(opts.out);
6056
- fs7.mkdirSync(path37.dirname(outPath), { recursive: true });
6057
- fs7.writeFileSync(outPath, `${JSON.stringify(report, null, 2)}
6413
+ const outPath = path39.resolve(opts.out);
6414
+ fs10.mkdirSync(path39.dirname(outPath), { recursive: true });
6415
+ fs10.writeFileSync(outPath, `${JSON.stringify(report, null, 2)}
6058
6416
  `);
6059
6417
  if (!global.json) info(c.dim(` wrote ${outPath}`));
6060
6418
  }
@@ -6203,14 +6561,14 @@ function resolveUninstallTarget(name, runtimeOpt) {
6203
6561
  }
6204
6562
  return exact[0];
6205
6563
  }
6206
- const base = path37.basename(wantLc);
6564
+ const base = path39.basename(wantLc);
6207
6565
  const soft = fleet.filter((m) => {
6208
6566
  const n = m.name.toLowerCase();
6209
- return n === base || n.endsWith("/" + base) || n.endsWith(wantLc) || path37.basename(n) === base;
6567
+ return n === base || n.endsWith("/" + base) || n.endsWith(wantLc) || path39.basename(n) === base;
6210
6568
  });
6211
6569
  if (soft.length === 1) return soft[0];
6212
6570
  if (soft.length > 1) {
6213
- const baseHits = soft.filter((m) => path37.basename(m.name).toLowerCase() === base);
6571
+ const baseHits = soft.filter((m) => path39.basename(m.name).toLowerCase() === base);
6214
6572
  const pool = baseHits.length ? baseHits : soft;
6215
6573
  const order = ["ollama", "gguf", "lm-studio"];
6216
6574
  for (const rt of order) {
@@ -6248,11 +6606,11 @@ function printBackends(backends) {
6248
6606
  }
6249
6607
  }
6250
6608
  function codeConfigPath(root2) {
6251
- return path37.join(root2, ".vibgrate", "code.json");
6609
+ return path39.join(root2, ".vibgrate", "code.json");
6252
6610
  }
6253
6611
  function loadCodeConfig(root2) {
6254
6612
  try {
6255
- const raw = JSON.parse(fs7.readFileSync(codeConfigPath(root2), "utf8"));
6613
+ const raw = JSON.parse(fs10.readFileSync(codeConfigPath(root2), "utf8"));
6256
6614
  return sanitize(raw);
6257
6615
  } catch {
6258
6616
  return {};
@@ -6319,7 +6677,7 @@ function contextBudgetFor(config, modelContextWindow) {
6319
6677
  var MCP_CONFIG_FILES = [".cursor/mcp.json", ".vscode/mcp.json", ".mcp.json"];
6320
6678
  function readMcpServersFile(file) {
6321
6679
  try {
6322
- const raw = JSON.parse(fs7.readFileSync(file, "utf8"));
6680
+ const raw = JSON.parse(fs10.readFileSync(file, "utf8"));
6323
6681
  const map = raw.mcpServers ?? raw.servers;
6324
6682
  return map && typeof map === "object" ? parseMcpServers(map) : {};
6325
6683
  } catch {
@@ -6330,7 +6688,7 @@ function discoverMcpServers(root2, ownServers) {
6330
6688
  const servers = {};
6331
6689
  const sources = [];
6332
6690
  for (const rel of MCP_CONFIG_FILES) {
6333
- const found = readMcpServersFile(path37.join(root2, rel));
6691
+ const found = readMcpServersFile(path39.join(root2, rel));
6334
6692
  const names = Object.keys(found);
6335
6693
  if (names.length) {
6336
6694
  sources.push(rel);
@@ -6349,6 +6707,9 @@ function registerCode(program) {
6349
6707
  const cmd = program.command("code").description("propose a graph-grounded code edit (guided mode with no instruction; dry-run by default)").argument("[instruction...]", "what to change, in plain language (omit for guided interactive mode)").option("--provider <id>", "backend: vibgrate-relay (Vibgrate Relay), ollama, lmstudio, foundry-local, openrouter, litellm, openai, together, llama-cpp").option("--model <id>", "model id (or set VG_CODE_MODEL). No model is hard-coded \u2014 pick the current best.").option("--mode <mode>", "Code Mode: spark | flow | forge (preferred over raw model names; auto-fits when omitted and no --model)").option("--model-path <gguf>", "gguf path for --provider llama-cpp (weights are never auto-downloaded)").option("-f, --file <path>", "restrict the edit surface to this file (repeatable)", collect, []).option("-b, --budget <n>", "approx context token budget", "3000").option("--apply", "write the change (still requires --yes or an interactive confirm)").option("--yes", "consent to write / to a first-use package install, non-interactively").option("--auto", "autonomous agent: auto-approve every edit and command (use with care)").option("--max-steps <n>", "cap the number of agent steps", "24").option("--single", "one-shot planner (single edit) instead of the multi-step agent").option("--stream", "stream the model output live").option("--stream-json", "machine protocol: NDJSON agent events on stdout, approval decisions on stdin (for host UIs like the VS Code panel)").option("--session", "with --stream-json: stay open for further turns (warm graph and tools) instead of exiting after one").option("--verify [command]", "after the agent finishes, run tests and make it fix failures (uses the config testCommand if no command is given)").option("--continue", "resume the most recent session (recap + restore /undo)").option("--capsule", "use a source-bearing Task Capsule for first context (Fusion A/B; exact source ranges from the graph)").option("--no-capsule", "disable Task Capsule context even if enabled in .vibgrate/code.json").option("--security-tier <tier>", "shell isolation: L0 (host), L1 (Seatbelt/bubblewrap when available), L2/L3 reserved").option("--mock <file>", "use a scripted reply from <file> instead of a model (offline; for tests/CI)").option("-o, --out <file>", "write the JSON result to <file> (implies --json shape; for CI/benchmarks)").action(async function(instructionParts, opts) {
6350
6708
  const global = readGlobal(this);
6351
6709
  const instruction = (instructionParts ?? []).join(" ").trim();
6710
+ if (!global.local) {
6711
+ await ensureRelevanceModule();
6712
+ }
6352
6713
  const config = loadCodeConfig(rootOf(global));
6353
6714
  let provider = opts.provider ?? config.provider;
6354
6715
  let model = opts.model ?? config.model;
@@ -6359,7 +6720,7 @@ function registerCode(program) {
6359
6720
  try {
6360
6721
  const { parseMode: parseMode2, resolveMode: resolveMode2, readOrchestratorState: readOrchestratorState2, activePin: activePin2 } = await import('./model-orchestrator-LHYPJBFH.js');
6361
6722
  const { gatherSystemMemory: gatherSystemMemory2 } = await import('./local-runtime-2ED33KK6.js');
6362
- const { loadGraph: loadGraph2 } = await import('./load-WA53B3GW.js');
6723
+ const { loadGraph: loadGraph2 } = await import('./load-MWG6WZTK.js');
6363
6724
  const state = readOrchestratorState2();
6364
6725
  const mode = parseMode2(modeFlag) ?? state.defaultMode ?? void 0;
6365
6726
  const pin = mode ? activePin2(mode, state) : null;
@@ -6439,11 +6800,12 @@ function registerCode(program) {
6439
6800
  const verifyCommand = opts.verify === true ? config.testCommand : typeof opts.verify === "string" ? opts.verify : void 0;
6440
6801
  const verify3 = verifyCommand ? { command: verifyCommand } : void 0;
6441
6802
  const mcp = discoverMcpServers(rootOf(global), config.mcpServers);
6442
- if (!instruction && !opts.mock) {
6803
+ const stdinFirstTurn = !instruction && !!opts.streamJson && !!opts.session;
6804
+ if (!instruction && !opts.mock && !stdinFirstTurn) {
6443
6805
  if (!(process.stdin.isTTY && process.stdout.isTTY)) {
6444
6806
  throw usageError('say what to change, e.g. `vg code "add a --timeout flag to the scan command"` (guided mode needs an interactive terminal)');
6445
6807
  }
6446
- const { runInteractive } = await import('./interactive-QWT7ERXJ.js');
6808
+ const { runInteractive } = await import('./interactive-TNRE4OEK.js');
6447
6809
  await runInteractive(
6448
6810
  rootOf(global),
6449
6811
  global,
@@ -6471,9 +6833,9 @@ function registerCode(program) {
6471
6833
  );
6472
6834
  return;
6473
6835
  }
6474
- if (!instruction) throw usageError('say what to change, e.g. `vg code "add a --timeout flag to the scan command"`');
6836
+ if (!instruction && !stdinFirstTurn) throw usageError('say what to change, e.g. `vg code "add a --timeout flag to the scan command"`');
6475
6837
  {
6476
- const { ensureCodeMap } = await import('./ensure-map-UQL7SM34.js');
6838
+ const { ensureCodeMap } = await import('./ensure-map-5YEI7R7V.js');
6477
6839
  const mapRoot = rootOf(global);
6478
6840
  try {
6479
6841
  await ensureCodeMap(mapRoot, global, {
@@ -6510,7 +6872,7 @@ function registerCode(program) {
6510
6872
  let mockReply;
6511
6873
  if (opts.mock) {
6512
6874
  try {
6513
- mockReply = fs7.readFileSync(opts.mock, "utf8");
6875
+ mockReply = fs10.readFileSync(opts.mock, "utf8");
6514
6876
  } catch {
6515
6877
  throw new CliError(`couldn't read the --mock file: ${opts.mock}`, ExitCode.USAGE_ERROR);
6516
6878
  }
@@ -6558,20 +6920,20 @@ function registerCode(program) {
6558
6920
  process.stdout.write(JSON.stringify(line) + "\n");
6559
6921
  };
6560
6922
  try {
6561
- const { RunOutcomeRecorder, newOneShotRunId, turnRunId } = await import('./run-outcome-J2IDIVYI.js');
6923
+ const { RunOutcomeRecorder, newOneShotRunId, turnRunId } = await import('./run-outcome-375HMSQG.js');
6562
6924
  const primarySlug = route.providers[0]?.model.includes("/") ? route.providers[0].model.split("/")[0] : route.providers[0]?.id;
6563
- const { runCodeStreamJson, parseHostMessage } = await import('./stream-json-TSGYC2MQ.js');
6564
- const { nodeCodeFs } = await import('./session-L7SJNE55.js');
6565
- const readline5 = await import('readline');
6925
+ const { runCodeStreamJson, parseHostMessage } = await import('./stream-json-AUMU3NLV.js');
6926
+ const { nodeCodeFs } = await import('./session-2NGJLI5Y.js');
6927
+ const readline6 = await import('readline');
6566
6928
  const child = await import('child_process');
6567
6929
  const { loadOrDiscoverFederation } = await import('./federation-MDQPO3PW.js');
6568
6930
  const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
6569
6931
  const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
6570
- const { startCodeRuntimeSession } = await import('./runtime-session-52P2Y5LX.js');
6571
- const { resolveGraphBackend } = await import('./graph-backend-G5Y6QQV4.js');
6932
+ const { startCodeRuntimeSession } = await import('./runtime-session-3MPWXNRL.js');
6933
+ const { resolveGraphBackend } = await import('./graph-backend-CPHLUKUC.js');
6572
6934
  const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
6573
6935
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
6574
- const { vgdRequest: vgdRequest2 } = await import('./vgd-PNR7UKLL.js');
6936
+ const { vgdRequest: vgdRequest2 } = await import('./vgd-Z23PXSP4.js');
6575
6937
  const federation = loadOrDiscoverFederation(root2);
6576
6938
  const modelProfile = mergeModelExecutionProfile(
6577
6939
  resolveModelExecutionProfile({
@@ -6629,7 +6991,7 @@ ${res.stderr}` : ""),
6629
6991
  exitCode: res.status ?? 1
6630
6992
  };
6631
6993
  };
6632
- const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-IFAXEQMZ.js');
6994
+ const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-D463EHQI.js');
6633
6995
  const vgBuiltin = createVgBuiltinMcpTools({
6634
6996
  getGraph: () => graph,
6635
6997
  root: root2,
@@ -6653,7 +7015,7 @@ ${res.stderr}` : ""),
6653
7015
  const os4 = await import('os');
6654
7016
  const pathMod = await import('path');
6655
7017
  const checkpointIndex = pathMod.join(
6656
- fs7.mkdtempSync(pathMod.join(os4.tmpdir(), "vg-code-cp-")),
7018
+ fs10.mkdtempSync(pathMod.join(os4.tmpdir(), "vg-code-cp-")),
6657
7019
  "index"
6658
7020
  );
6659
7021
  const gitRunner = (gitArgs, gitEnv) => {
@@ -6703,6 +7065,8 @@ ${res.stderr}` : ""),
6703
7065
  capsule,
6704
7066
  files: opts.file.length ? opts.file : void 0,
6705
7067
  worktreeOverlay: true,
7068
+ // Real-model host: compaction writes a model checkpoint summary.
7069
+ llmCompaction: true,
6706
7070
  // Full coding agent: free discovery by default. Capsule is context only.
6707
7071
  advancedMode: true,
6708
7072
  externalTools,
@@ -6717,15 +7081,16 @@ ${res.stderr}` : ""),
6717
7081
  };
6718
7082
  try {
6719
7083
  if (opts.session) {
6720
- const { runCodeStreamJsonSession } = await import('./stream-json-TSGYC2MQ.js');
6721
- const { runAgent: runAgent2 } = await import('./agent-6XOI7RVW.js');
7084
+ const { runCodeStreamJsonSession } = await import('./stream-json-AUMU3NLV.js');
7085
+ const { runAgent: runAgent2 } = await import('./agent-HNV2VUCO.js');
6722
7086
  const {
7087
+ condenseSession,
6723
7088
  loadLatestSession,
6724
7089
  newSession,
6725
7090
  recordTask,
6726
7091
  saveSession,
6727
7092
  summarizeSession
6728
- } = await import('./session-store-SQECEXUU.js');
7093
+ } = await import('./session-store-F7NX7SZN.js');
6729
7094
  const resumedRecord = opts.continue ? loadLatestSession(root2) : void 0;
6730
7095
  let record = resumedRecord ?? newSession(
6731
7096
  `s${Date.now().toString(36)}`,
@@ -6736,13 +7101,13 @@ ${res.stderr}` : ""),
6736
7101
  const pendingTurns = [];
6737
7102
  let wakeTurn;
6738
7103
  let ended = false;
6739
- const pushTurn = (instruction2) => {
7104
+ const pushTurn = (turn) => {
6740
7105
  if (wakeTurn) {
6741
7106
  const wake = wakeTurn;
6742
7107
  wakeTurn = void 0;
6743
- wake(instruction2);
6744
- } else if (instruction2 !== null) {
6745
- pendingTurns.push(instruction2);
7108
+ wake(turn);
7109
+ } else if (turn !== null) {
7110
+ pendingTurns.push(turn);
6746
7111
  }
6747
7112
  };
6748
7113
  const nextTurn = () => {
@@ -6763,7 +7128,7 @@ ${res.stderr}` : ""),
6763
7128
  nextTurn,
6764
7129
  bindDecisions: (session) => {
6765
7130
  streamApprove = (action) => session.approve(action);
6766
- const rl = readline5.createInterface({ input: process.stdin });
7131
+ const rl = readline6.createInterface({ input: process.stdin });
6767
7132
  rl.on("line", (raw) => {
6768
7133
  const msg = parseHostMessage(raw);
6769
7134
  if (!msg) return;
@@ -6771,7 +7136,8 @@ ${res.stderr}` : ""),
6771
7136
  session.submitDecision(msg.id, msg.approve);
6772
7137
  runOutcome.noteDecision(msg.id, msg.approve);
6773
7138
  } else if (msg.kind === "answer") session.submitAnswer(msg.id, msg.answer);
6774
- else if (msg.kind === "submit") pushTurn(msg.instruction);
7139
+ else if (msg.kind === "submit")
7140
+ pushTurn({ instruction: msg.instruction, agentMode: msg.agentMode, images: msg.images });
6775
7141
  else if (msg.kind === "restore") {
6776
7142
  void import('./checkpoint-4WFZMKEO.js').then(({ restoreCheckpoint }) => {
6777
7143
  const outcome = restoreCheckpoint(gitRunner, {
@@ -6780,6 +7146,14 @@ ${res.stderr}` : ""),
6780
7146
  });
6781
7147
  emitStream({ event: "checkpoint-restored", commit: msg.commit, ...outcome });
6782
7148
  });
7149
+ } else if (msg.kind === "compact") {
7150
+ record = condenseSession(record, Date.now());
7151
+ saveSession(root2, record);
7152
+ emitStream({
7153
+ event: "event",
7154
+ type: "notice",
7155
+ text: "Conversation compacted \u2014 earlier turns condensed into a checkpoint."
7156
+ });
6783
7157
  } else if (msg.kind === "cancel") {
6784
7158
  session.cancelTurn();
6785
7159
  runOutcome.cancelPending();
@@ -6795,14 +7169,20 @@ ${res.stderr}` : ""),
6795
7169
  pushTurn(null);
6796
7170
  });
6797
7171
  },
6798
- runTurn: ({ instruction: turnInstruction, priorSummary, signal, session }) => {
7172
+ runTurn: ({ instruction: turnInstruction, signal, session, agentMode, auto: turnAuto, images }) => {
7173
+ const priorSummary = summarizeSession(record) || void 0;
6799
7174
  turnIndex++;
6800
7175
  runOutcome.beginRun(turnRunId(record.id, turnIndex), turnInstruction);
7176
+ const plan = agentMode === "plan";
7177
+ streamApprove = plan ? async () => false : (action) => session.approve(action);
6801
7178
  return runAgent2({
6802
7179
  ...baseAgentOptions,
6803
7180
  instruction: turnInstruction,
6804
7181
  priorSummary,
6805
7182
  signal,
7183
+ auto: turnAuto,
7184
+ plan,
7185
+ images,
6806
7186
  approve: session.approve,
6807
7187
  askUser: session.askUser,
6808
7188
  onEvent: session.onEvent
@@ -6831,7 +7211,7 @@ ${res.stderr}` : ""),
6831
7211
  emit: emitAndRecord,
6832
7212
  bindDecisions: (session) => {
6833
7213
  streamApprove = (action) => session.approve(action);
6834
- const rl = readline5.createInterface({ input: process.stdin });
7214
+ const rl = readline6.createInterface({ input: process.stdin });
6835
7215
  rl.on("line", (raw) => {
6836
7216
  const msg = parseHostMessage(raw);
6837
7217
  if (!msg) return;
@@ -6866,17 +7246,17 @@ ${res.stderr}` : ""),
6866
7246
  if (!autonomous && !tty) {
6867
7247
  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).");
6868
7248
  }
6869
- const { agentTask } = await import('./interactive-QWT7ERXJ.js');
6870
- const { nodeCodeFs } = await import('./session-L7SJNE55.js');
7249
+ const { agentTask } = await import('./interactive-TNRE4OEK.js');
7250
+ const { nodeCodeFs } = await import('./session-2NGJLI5Y.js');
6871
7251
  const { TtyPrompter } = await import('./ui-K7D3BCHD.js');
6872
7252
  let priorSummary;
6873
7253
  if (opts.continue) {
6874
- const { loadLatestSession, summarizeSession } = await import('./session-store-SQECEXUU.js');
7254
+ const { loadLatestSession, summarizeSession } = await import('./session-store-F7NX7SZN.js');
6875
7255
  const prev = loadLatestSession(root2);
6876
7256
  if (prev) priorSummary = summarizeSession(prev);
6877
7257
  }
6878
7258
  const prompter = tty ? new TtyPrompter() : void 0;
6879
- const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-IFAXEQMZ.js');
7259
+ const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-D463EHQI.js');
6880
7260
  const vgBuiltin = createVgBuiltinMcpTools({
6881
7261
  getGraph: () => graph,
6882
7262
  root: root2,
@@ -6900,11 +7280,11 @@ ${res.stderr}` : ""),
6900
7280
  const { loadFederation } = await import('./federation-MDQPO3PW.js');
6901
7281
  const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
6902
7282
  const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
6903
- const { startCodeRuntimeSession } = await import('./runtime-session-52P2Y5LX.js');
6904
- const { resolveGraphBackend } = await import('./graph-backend-G5Y6QQV4.js');
7283
+ const { startCodeRuntimeSession } = await import('./runtime-session-3MPWXNRL.js');
7284
+ const { resolveGraphBackend } = await import('./graph-backend-CPHLUKUC.js');
6905
7285
  const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
6906
7286
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
6907
- const { vgdRequest: vgdRequest2 } = await import('./vgd-PNR7UKLL.js');
7287
+ const { vgdRequest: vgdRequest2 } = await import('./vgd-Z23PXSP4.js');
6908
7288
  const federation = loadFederation(root2);
6909
7289
  const modelProfile = mergeModelExecutionProfile(
6910
7290
  resolveModelExecutionProfile({
@@ -6960,7 +7340,8 @@ ${res.stderr}` : ""),
6960
7340
  files: opts.file.length ? opts.file : void 0,
6961
7341
  executionEnv,
6962
7342
  graphBackend,
6963
- modelProfile
7343
+ modelProfile,
7344
+ llmCompaction: true
6964
7345
  });
6965
7346
  if (global.json) json(agentResult);
6966
7347
  if (agentResult.stopped === "error") process.exitCode = ExitCode.ERROR;
@@ -6974,7 +7355,7 @@ ${res.stderr}` : ""),
6974
7355
  }
6975
7356
  let consent = !!opts.yes;
6976
7357
  if (opts.apply && !consent && process.stdin.isTTY && process.stdout.isTTY) {
6977
- consent = await confirm(`Apply the proposed change to ${root2}?`);
7358
+ consent = await confirm2(`Apply the proposed change to ${root2}?`);
6978
7359
  }
6979
7360
  const onPhase = (phase, detail) => {
6980
7361
  if (!global.json && !global.quiet) info(c.dim(` ${phase}: ${detail}`));
@@ -6996,7 +7377,7 @@ ${res.stderr}` : ""),
6996
7377
  attribution: { client: "vg-code", provider: providerSlug, model: primary?.model }
6997
7378
  });
6998
7379
  if (opts.out) {
6999
- fs7.writeFileSync(opts.out, JSON.stringify(result, null, 2) + "\n");
7380
+ fs10.writeFileSync(opts.out, JSON.stringify(result, null, 2) + "\n");
7000
7381
  }
7001
7382
  if (global.json) {
7002
7383
  json(result);
@@ -7047,7 +7428,7 @@ function resolveSecurityTierFlag(flag, fromConfig, auto) {
7047
7428
  if (fromConfig) return fromConfig;
7048
7429
  return auto ? "L1" : "L0";
7049
7430
  }
7050
- function confirm(question) {
7431
+ function confirm2(question) {
7051
7432
  return new Promise((resolve21) => {
7052
7433
  const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
7053
7434
  rl.question(`${question} [y/N] `, (answer) => {
@@ -7209,7 +7590,7 @@ async function addCmd(root2, rest, opts, asJson) {
7209
7590
  }
7210
7591
  function readPackageVersion(root2) {
7211
7592
  try {
7212
- const pkg = JSON.parse(fs7__default.readFileSync(path37__default.join(root2, "package.json"), "utf8"));
7593
+ const pkg = JSON.parse(fs10__default.readFileSync(path39__default.join(root2, "package.json"), "utf8"));
7213
7594
  return typeof pkg.version === "string" ? pkg.version : void 0;
7214
7595
  } catch {
7215
7596
  return void 0;
@@ -7217,7 +7598,7 @@ function readPackageVersion(root2) {
7217
7598
  }
7218
7599
  function readOptionalFile(p) {
7219
7600
  try {
7220
- const t = fs7__default.readFileSync(p, "utf8");
7601
+ const t = fs10__default.readFileSync(p, "utf8");
7221
7602
  return t.trim() ? t : void 0;
7222
7603
  } catch {
7223
7604
  return void 0;
@@ -7232,8 +7613,8 @@ async function publishCmd(root2, rest, opts, global, asJson) {
7232
7613
  if (!parsed) throw new CliError("publishing a private library requires a DSN \u2014 run `vibgrate login` or set VIBGRATE_DSN", ExitCode.USAGE_ERROR);
7233
7614
  const version = (opts.version || readPackageVersion(root2) || "").trim();
7234
7615
  if (!version) throw usageError("a --version is required (or run from a package whose package.json has a version)");
7235
- const readme = readOptionalFile(opts.readme ? path37__default.resolve(opts.readme) : path37__default.join(root2, "README.md"));
7236
- const dts = opts.dts ? readOptionalFile(path37__default.resolve(opts.dts)) : void 0;
7616
+ const readme = readOptionalFile(opts.readme ? path39__default.resolve(opts.readme) : path39__default.join(root2, "README.md"));
7617
+ const dts = opts.dts ? readOptionalFile(path39__default.resolve(opts.dts)) : void 0;
7237
7618
  if (!readme && !dts) throw usageError("nothing to publish \u2014 no README.md found and no --dts given");
7238
7619
  const result = await publishPrivateLibrary(
7239
7620
  { name, version, readme, dts, language: opts.language },
@@ -7365,8 +7746,8 @@ function registerExport(program) {
7365
7746
  out(content.trimEnd());
7366
7747
  return;
7367
7748
  }
7368
- fs7.mkdirSync(path37.dirname(path37.resolve(file)), { recursive: true });
7369
- fs7.writeFileSync(file, content);
7749
+ fs10.mkdirSync(path39.dirname(path39.resolve(file)), { recursive: true });
7750
+ fs10.writeFileSync(file, content);
7370
7751
  info(`${c.green("\u2714")} wrote ${file} ${c.dim(`(${format})`)}`);
7371
7752
  });
7372
7753
  applyGlobalOptions(cmd);
@@ -7376,43 +7757,43 @@ function detectFormat(file) {
7376
7757
  if (lower.endsWith(".cdx.json")) return "cyclonedx";
7377
7758
  if (lower.endsWith(".spdx.json")) return "spdx";
7378
7759
  if (file === "-") return "json";
7379
- return formatForExt(path37.extname(file));
7760
+ return formatForExt(path39.extname(file));
7380
7761
  }
7381
7762
  function registerBundle(program) {
7382
7763
  const cmd = program.command("bundle").description("build an air-gapped bundle (grammars + graph + library catalog)").option("--offline", "offline bundle (default; present for clarity)").option("-o, --out <dir>", "output directory", "vg-bundle").action(function(opts) {
7383
7764
  const global = readGlobal(this);
7384
7765
  const root2 = rootOf(global);
7385
- const outDir = path37.resolve(root2, opts.out ?? "vg-bundle");
7766
+ const outDir = path39.resolve(root2, opts.out ?? "vg-bundle");
7386
7767
  let grammarFiles;
7387
7768
  try {
7388
7769
  grammarFiles = resolvedGrammarFiles();
7389
7770
  } catch {
7390
7771
  throw new CliError("no grammars found to bundle (run a build first)", ExitCode.ERROR);
7391
7772
  }
7392
- fs7.mkdirSync(path37.join(outDir, "grammars"), { recursive: true });
7773
+ fs10.mkdirSync(path39.join(outDir, "grammars"), { recursive: true });
7393
7774
  let grammarCount = 0;
7394
7775
  for (const { fileName, absPath } of grammarFiles) {
7395
- fs7.copyFileSync(absPath, path37.join(outDir, "grammars", fileName));
7776
+ fs10.copyFileSync(absPath, path39.join(outDir, "grammars", fileName));
7396
7777
  grammarCount++;
7397
7778
  }
7398
7779
  const included = [`grammars/ (${grammarCount} .wasm)`];
7399
7780
  const graphSrc = resolveGraphPath(root2, global.graph);
7400
- if (fs7.existsSync(graphSrc)) {
7401
- fs7.copyFileSync(graphSrc, path37.join(outDir, "graph.json"));
7781
+ if (fs10.existsSync(graphSrc)) {
7782
+ fs10.copyFileSync(graphSrc, path39.join(outDir, "graph.json"));
7402
7783
  included.push("graph.json");
7403
7784
  } else {
7404
7785
  const graph = loadGraphFileWithSnapshot(graphSrc);
7405
7786
  if (graph) {
7406
- fs7.writeFileSync(path37.join(outDir, "graph.json"), serializeGraph(graph));
7787
+ fs10.writeFileSync(path39.join(outDir, "graph.json"), serializeGraph(graph));
7407
7788
  included.push("graph.json");
7408
7789
  }
7409
7790
  }
7410
7791
  const cat = catalogPath(root2);
7411
- if (fs7.existsSync(cat)) {
7412
- fs7.copyFileSync(cat, path37.join(outDir, "vibgrate.lib.json"));
7792
+ if (fs10.existsSync(cat)) {
7793
+ fs10.copyFileSync(cat, path39.join(outDir, "vibgrate.lib.json"));
7413
7794
  included.push("vibgrate.lib.json");
7414
- if (fs7.existsSync(libDir(root2))) {
7415
- fs7.cpSync(libDir(root2), path37.join(outDir, "lib"), { recursive: true });
7795
+ if (fs10.existsSync(libDir(root2))) {
7796
+ fs10.cpSync(libDir(root2), path39.join(outDir, "lib"), { recursive: true });
7416
7797
  included.push("lib/");
7417
7798
  }
7418
7799
  }
@@ -7424,15 +7805,15 @@ function registerBundle(program) {
7424
7805
  included,
7425
7806
  usage: "Run `vg build --grammars <this dir>/grammars` to build fully offline."
7426
7807
  };
7427
- fs7.writeFileSync(path37.join(outDir, "MANIFEST.json"), `${stableStringify(manifest, 2)}
7808
+ fs10.writeFileSync(path39.join(outDir, "MANIFEST.json"), `${stableStringify(manifest, 2)}
7428
7809
  `);
7429
7810
  if (global.json) {
7430
- json({ out: path37.relative(root2, outDir), ...manifest });
7811
+ json({ out: path39.relative(root2, outDir), ...manifest });
7431
7812
  return;
7432
7813
  }
7433
- info(`${c.cyan("vg bundle")} \xB7 wrote ${path37.relative(root2, outDir)}/`);
7814
+ info(`${c.cyan("vg bundle")} \xB7 wrote ${path39.relative(root2, outDir)}/`);
7434
7815
  for (const i of included) info(` ${c.green("\u2714")} ${i}`);
7435
- info(c.dim(` offline: vg build --grammars "${path37.relative(root2, outDir)}/grammars"`));
7816
+ info(c.dim(` offline: vg build --grammars "${path39.relative(root2, outDir)}/grammars"`));
7436
7817
  });
7437
7818
  applyGlobalOptions(cmd);
7438
7819
  }
@@ -7450,7 +7831,7 @@ async function runDoctor(global) {
7450
7831
  const root2 = rootOf(global);
7451
7832
  const local = global.local === true;
7452
7833
  const graphPath = resolveGraphPath(root2, global.graph);
7453
- const configFile = CONFIG_BASENAMES.find((f) => fs7.existsSync(path37.join(root2, f))) ?? null;
7834
+ const configFile = CONFIG_BASENAMES.find((f) => fs10.existsSync(path39.join(root2, f))) ?? null;
7454
7835
  const graph = loadGraph(root2, graphPath);
7455
7836
  let staleFiles = null;
7456
7837
  if (graph) {
@@ -7476,14 +7857,14 @@ async function runDoctor(global) {
7476
7857
  root: root2,
7477
7858
  configFile,
7478
7859
  map: {
7479
- path: path37.relative(root2, graphPath),
7860
+ path: path39.relative(root2, graphPath),
7480
7861
  built: graph !== null,
7481
7862
  generatedAt: graph?.generatedAt ?? null,
7482
7863
  staleFiles
7483
7864
  },
7484
7865
  libCatalog: {
7485
- path: path37.relative(root2, catalogPath(root2)),
7486
- present: fs7.existsSync(catalogPath(root2)),
7866
+ path: path39.relative(root2, catalogPath(root2)),
7867
+ present: fs10.existsSync(catalogPath(root2)),
7487
7868
  libraries: libCount
7488
7869
  },
7489
7870
  credentials: creds,
@@ -7540,7 +7921,7 @@ async function runDoctor(global) {
7540
7921
  );
7541
7922
  info(
7542
7923
  ` host pool ${li.hostPool.size} warm session(s)` + (li.hostPool.sessions[0] ? c.dim(
7543
- ` \xB7 last ${path37.basename(li.hostPool.sessions[0].modelPath)} kv=${li.hostPool.sessions[0].kvBlocks}`
7924
+ ` \xB7 last ${path39.basename(li.hostPool.sessions[0].modelPath)} kv=${li.hostPool.sessions[0].kvBlocks}`
7544
7925
  ) : c.dim(" \xB7 none (load via vg code / vgd host-load)"))
7545
7926
  );
7546
7927
  if (li.dynamicOnToken || li.dynamicCustomSampler) {
@@ -7716,7 +8097,7 @@ function registerDaemon(program) {
7716
8097
  const register = cmd.command("register").description("register the current repository with a running vgd").argument("[root]", "repository root (default: cwd)").action(async function(rootArg) {
7717
8098
  const global = readGlobal(this);
7718
8099
  const socketPath = socketOf(this);
7719
- const root2 = path37.resolve(rootArg ?? rootOf(global));
8100
+ const root2 = path39.resolve(rootArg ?? rootOf(global));
7720
8101
  if (!await vgdIsRunning({ socketPath })) {
7721
8102
  throw new CliError(`vgd is not running \u2014 start it with \`vg daemon start\` (${socketPath})`, ExitCode.NOT_FOUND);
7722
8103
  }
@@ -7752,7 +8133,7 @@ function registerDaemon(program) {
7752
8133
  const federation = cmd.command("federation").description("register a multi-root federation from .vibgrate/federation.json (or primary cwd)").argument("[root]", "primary repository root (default: cwd)").action(async function(rootArg) {
7753
8134
  const global = readGlobal(this);
7754
8135
  const socketPath = socketOf(this);
7755
- const primary = path37.resolve(rootArg ?? rootOf(global));
8136
+ const primary = path39.resolve(rootArg ?? rootOf(global));
7756
8137
  if (!await vgdIsRunning({ socketPath })) {
7757
8138
  throw new CliError(`vgd is not running \u2014 start it with \`vg daemon start\` (${socketPath})`, ExitCode.NOT_FOUND);
7758
8139
  }
@@ -7780,7 +8161,7 @@ function registerDaemon(program) {
7780
8161
  const publish = cmd.command("publish").description("load the workspace code map into vgd ActiveGraph (from global/legacy store)").argument("[root]", "repository root (default: cwd)").option("--git-ref <ref>", "branch or SHA (default: detect HEAD)").action(async function(rootArg) {
7781
8162
  const global = readGlobal(this);
7782
8163
  const socketPath = socketOf(this);
7783
- const root2 = path37.resolve(rootArg ?? rootOf(global));
8164
+ const root2 = path39.resolve(rootArg ?? rootOf(global));
7784
8165
  if (!await vgdIsRunning({ socketPath })) {
7785
8166
  throw new CliError(`vgd is not running \u2014 start it with \`vg daemon ensure\` (${socketPath})`, ExitCode.NOT_FOUND);
7786
8167
  }
@@ -7794,7 +8175,7 @@ function registerDaemon(program) {
7794
8175
  throw new CliError(loaded.error, ExitCode.NOT_FOUND);
7795
8176
  }
7796
8177
  if (!loaded.ok) {
7797
- const { loadGraph: loadGraph2 } = await import('./load-WA53B3GW.js');
8178
+ const { loadGraph: loadGraph2 } = await import('./load-MWG6WZTK.js');
7798
8179
  const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
7799
8180
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
7800
8181
  const graph = loadGraph2(root2, global.graph);
@@ -7910,7 +8291,7 @@ function socketOf(cmd) {
7910
8291
  let c2 = cmd;
7911
8292
  while (c2) {
7912
8293
  const opts = c2.opts();
7913
- if (opts.socket) return path37.resolve(opts.socket);
8294
+ if (opts.socket) return path39.resolve(opts.socket);
7914
8295
  c2 = c2.parent;
7915
8296
  }
7916
8297
  return vgdSocketPath();
@@ -7982,7 +8363,7 @@ async function restartVgdIfRunning(socketPath = vgdSocketPath()) {
7982
8363
  }
7983
8364
  function readVgdPid() {
7984
8365
  try {
7985
- const raw = fs7.readFileSync(vgdPidPath(), "utf8").trim();
8366
+ const raw = fs10.readFileSync(vgdPidPath(), "utf8").trim();
7986
8367
  const pid = Number.parseInt(raw, 10);
7987
8368
  return Number.isInteger(pid) && pid > 0 ? pid : null;
7988
8369
  } catch {
@@ -8067,7 +8448,7 @@ function registerPolicy(program) {
8067
8448
  const global = readGlobal(this);
8068
8449
  let raw;
8069
8450
  try {
8070
- raw = fs7.readFileSync(file, "utf8");
8451
+ raw = fs10.readFileSync(file, "utf8");
8071
8452
  } catch {
8072
8453
  throw new CliError(`cannot read ${file}`, ExitCode.NOT_FOUND);
8073
8454
  }
@@ -8187,11 +8568,11 @@ function registerLlmHost(program) {
8187
8568
  applyGlobalOptions(cmd);
8188
8569
  }
8189
8570
  var initCommand = new Command("init").description("Initialize vibgrate in a project").argument("[path]", "Path to initialize", ".").option("--baseline", "Create initial baseline after init").option("--yes", "Skip confirmation prompts").action(async (targetPath, opts) => {
8190
- const rootDir = path37.resolve(targetPath);
8191
- const vibgrateDir2 = path37.join(rootDir, ".vibgrate");
8571
+ const rootDir = path39.resolve(targetPath);
8572
+ const vibgrateDir2 = path39.join(rootDir, ".vibgrate");
8192
8573
  await ensureDir(vibgrateDir2);
8193
8574
  console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold(".vibgrate/")} directory`);
8194
- const configPath = path37.join(rootDir, "vibgrate.config.ts");
8575
+ const configPath = path39.join(rootDir, "vibgrate.config.ts");
8195
8576
  if (await pathExists(configPath)) {
8196
8577
  console.log(chalk7.dim(" vibgrate.config.ts already exists, skipping"));
8197
8578
  } else {
@@ -8199,7 +8580,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
8199
8580
  console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold("vibgrate.config.ts")}`);
8200
8581
  }
8201
8582
  if (opts.baseline) {
8202
- const { runBaseline } = await import('./baseline-PY6TETA5.js');
8583
+ const { runBaseline } = await import('./baseline-6WTULHM5.js');
8203
8584
  await runBaseline(rootDir);
8204
8585
  }
8205
8586
  console.log("");
@@ -8302,7 +8683,7 @@ function collectPackageImports(graph, ecosystem, pkg) {
8302
8683
  };
8303
8684
  }
8304
8685
  async function firstReferenceLine(rootDir, relFile, identifier, readFile3) {
8305
- const content = await readFile3(path37.join(rootDir, relFile));
8686
+ const content = await readFile3(path39.join(rootDir, relFile));
8306
8687
  if (!content) return null;
8307
8688
  const escaped = identifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
8308
8689
  const re = new RegExp(`\\b${escaped}\\b`);
@@ -8340,9 +8721,9 @@ function sitesFromImportFiles(files, limit = 10) {
8340
8721
  }
8341
8722
  async function defaultReadFile(absPath) {
8342
8723
  try {
8343
- const stat2 = await fs21.stat(absPath);
8724
+ const stat2 = await fs24.stat(absPath);
8344
8725
  if (!stat2.isFile() || stat2.size > MAX_FILE_BYTES) return null;
8345
- return await fs21.readFile(absPath, "utf8");
8726
+ return await fs24.readFile(absPath, "utf8");
8346
8727
  } catch {
8347
8728
  return null;
8348
8729
  }
@@ -8538,7 +8919,7 @@ var AI_ASSISTANT_DETECTORS = [
8538
8919
  async function detectAiAssistant(rootDir) {
8539
8920
  for (const detector of AI_ASSISTANT_DETECTORS) {
8540
8921
  for (const file of detector.files) {
8541
- if (await pathExists$1(path37.join(rootDir, file))) {
8922
+ if (await pathExists$1(path39.join(rootDir, file))) {
8542
8923
  return detector.name;
8543
8924
  }
8544
8925
  }
@@ -8732,7 +9113,7 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
8732
9113
  collectExcludes,
8733
9114
  []
8734
9115
  ).option("--concurrency <n>", "Max concurrent npm calls", "8").option("--push", "Auto-push results to Vibgrate API after scan").option("--dsn <dsn>", "DSN token for push (or use VIBGRATE_DSN env)").option("--region <region>", "Override data residency region for push (us, eu)").option("--strict", "Fail on push errors").option("--ui-purpose", "Enable optional UI purpose evidence extraction (slower)").option("--no-local-artifacts", "Do not write .vibgrate JSON artifacts to disk").option("--max-privacy", "Enable strongest privacy mode (minimal scanners, no local artifacts)").option("--offline", "Run without network calls; do not upload results").option("--full", "Comprehensive scan: turns on known-vulnerability detection (= --vulns) and, when a standards policy exists, a banned-dependency report \u2014 on top of drift scoring and the code map").option("--vulns", "Also scan installed dependencies for known vulnerabilities (OSV online, or advisories from --package-manifest when offline)").option("--package-manifest <file>", "Use local package-version manifest JSON/ZIP (for offline mode)").option("--project-scan-timeout <seconds>", "Per-project scan timeout in seconds (default: 180)").option("--drift-budget <score>", "Fail if DriftScore is above budget (0-100)").option("--drift-worsening <percent>", "Fail if drift worsens by more than % since baseline").option("--repository-name <name>", "Override the repository name recorded for this scan (defaults to the directory or package.json name)").option("--force", "Always create a fresh scan ingest, even if the repository is unchanged since the last scan (skips the unchanged/reuse optimization). Used by scheduled and dashboard-triggered scans.").option("--no-graph", "Skip building the local code map (the AI/docs index) that scan produces after scoring drift").option("--quiet", "Suppress promotional output (the free-plan tracking panel and the AI Context install prompt); scan results are unaffected").action(async (targetPath, opts) => {
8735
- const rootDir = path37.resolve(targetPath);
9116
+ const rootDir = path39.resolve(targetPath);
8736
9117
  if (!await pathExists$1(rootDir)) {
8737
9118
  console.error(chalk7.red(`Path does not exist: ${rootDir}`));
8738
9119
  process.exit(1);
@@ -8740,7 +9121,7 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
8740
9121
  const hasDsn = !!resolveDsn(opts.dsn);
8741
9122
  const willPush = !opts.offline && (opts.push || hasDsn);
8742
9123
  const noLocalArtifacts = opts.localArtifacts === false;
8743
- const isFirstRun = !await pathExists$1(path37.join(rootDir, ".vibgrate", "scan_result.json"));
9124
+ const isFirstRun = !await pathExists$1(path39.join(rootDir, ".vibgrate", "scan_result.json"));
8744
9125
  let pinnedRegion;
8745
9126
  let planTier;
8746
9127
  let upgradeUrl;
@@ -8999,7 +9380,7 @@ var SKIP_DIRS2 = /* @__PURE__ */ new Set([
8999
9380
  function scanStaleness(rootDir, artifactPath) {
9000
9381
  let ref;
9001
9382
  try {
9002
- ref = fs7.statSync(artifactPath).mtimeMs;
9383
+ ref = fs10.statSync(artifactPath).mtimeMs;
9003
9384
  } catch {
9004
9385
  return { stale: false };
9005
9386
  }
@@ -9011,7 +9392,7 @@ function scanStaleness(rootDir, artifactPath) {
9011
9392
  if (depth > 8 || scanned > MAX_ENTRIES2) return;
9012
9393
  let entries;
9013
9394
  try {
9014
- entries = fs7.readdirSync(dir, { withFileTypes: true });
9395
+ entries = fs10.readdirSync(dir, { withFileTypes: true });
9015
9396
  } catch {
9016
9397
  return;
9017
9398
  }
@@ -9019,20 +9400,20 @@ function scanStaleness(rootDir, artifactPath) {
9019
9400
  scanned++;
9020
9401
  if (scanned > MAX_ENTRIES2) break;
9021
9402
  if (e.isDirectory()) {
9022
- if (!SKIP_DIRS2.has(e.name) && !e.name.startsWith(".")) walk2(path37.join(dir, e.name), depth + 1);
9403
+ if (!SKIP_DIRS2.has(e.name) && !e.name.startsWith(".")) walk2(path39.join(dir, e.name), depth + 1);
9023
9404
  continue;
9024
9405
  }
9025
9406
  if (!WATCHED_FILES.has(e.name) && !WATCHED_EXT.test(e.name)) continue;
9026
- const abs = path37.join(dir, e.name);
9407
+ const abs = path39.join(dir, e.name);
9027
9408
  let mtimeMs;
9028
9409
  try {
9029
- mtimeMs = fs7.statSync(abs).mtimeMs;
9410
+ mtimeMs = fs10.statSync(abs).mtimeMs;
9030
9411
  } catch {
9031
9412
  continue;
9032
9413
  }
9033
9414
  if (mtimeMs > newest) {
9034
9415
  newest = mtimeMs;
9035
- newestChanged = path37.relative(rootDir, abs) || e.name;
9416
+ newestChanged = path39.relative(rootDir, abs) || e.name;
9036
9417
  }
9037
9418
  }
9038
9419
  };
@@ -9163,7 +9544,7 @@ function analyzeTree(root2, packages) {
9163
9544
  if (depth > MAX_DEPTH || filesSeen >= MAX_FILES) return;
9164
9545
  let entries;
9165
9546
  try {
9166
- entries = fs7.readdirSync(dir, { withFileTypes: true });
9547
+ entries = fs10.readdirSync(dir, { withFileTypes: true });
9167
9548
  } catch {
9168
9549
  return;
9169
9550
  }
@@ -9172,17 +9553,17 @@ function analyzeTree(root2, packages) {
9172
9553
  if (filesSeen >= MAX_FILES) return;
9173
9554
  if (entry.isDirectory()) {
9174
9555
  if (SKIP_DIRS3.has(entry.name) || entry.name.startsWith(".")) continue;
9175
- walk2(path37.join(dir, entry.name), depth + 1);
9556
+ walk2(path39.join(dir, entry.name), depth + 1);
9176
9557
  continue;
9177
9558
  }
9178
- const fileEco = EXT_ECOSYSTEM[path37.extname(entry.name)];
9559
+ const fileEco = EXT_ECOSYSTEM[path39.extname(entry.name)];
9179
9560
  if (!fileEco || fileEco === "unknown") continue;
9180
9561
  filesSeen++;
9181
- const full = path37.join(dir, entry.name);
9562
+ const full = path39.join(dir, entry.name);
9182
9563
  let content;
9183
9564
  try {
9184
- if (fs7.statSync(full).size > MAX_FILE_BYTES2) continue;
9185
- content = fs7.readFileSync(full, "utf8");
9565
+ if (fs10.statSync(full).size > MAX_FILE_BYTES2) continue;
9566
+ content = fs10.readFileSync(full, "utf8");
9186
9567
  } catch {
9187
9568
  continue;
9188
9569
  }
@@ -9493,7 +9874,7 @@ function applyPlan(rootDir, upgrades, opts = {}) {
9493
9874
  }
9494
9875
  const outcomes = effective.map((t) => {
9495
9876
  const c2 = pmCommandFor(u.ecosystem, u.package, u.to, opts.packageManager, { workspaceRoot: t.isWorkspaceRoot });
9496
- return { t, res: run(c2, path37.join(rootDir, t.dir)) };
9877
+ return { t, res: run(c2, path39.join(rootDir, t.dir)) };
9497
9878
  });
9498
9879
  const failures = outcomes.filter((o) => !o.res.ok);
9499
9880
  if (failures.length === 0) {
@@ -9522,8 +9903,8 @@ function applyPlan(rootDir, upgrades, opts = {}) {
9522
9903
  return results;
9523
9904
  }
9524
9905
  var REGISTRY_URL = "https://registry.npmjs.org/@vibgrate%2fcli/latest";
9525
- var CACHE_DIR = path37.join(os.homedir(), ".vibgrate");
9526
- var CACHE_FILE = path37.join(CACHE_DIR, "update-check.json");
9906
+ var CACHE_DIR = path39.join(os.homedir(), ".vibgrate");
9907
+ var CACHE_FILE = path39.join(CACHE_DIR, "update-check.json");
9527
9908
  async function fetchLatestVersion() {
9528
9909
  try {
9529
9910
  const controller = new AbortController();
@@ -9550,8 +9931,8 @@ async function fetchLatestVersion() {
9550
9931
  }
9551
9932
  async function writeCache(data) {
9552
9933
  try {
9553
- await fs21.mkdir(CACHE_DIR, { recursive: true });
9554
- await fs21.writeFile(CACHE_FILE, JSON.stringify(data), "utf-8");
9934
+ await fs24.mkdir(CACHE_DIR, { recursive: true });
9935
+ await fs24.writeFile(CACHE_FILE, JSON.stringify(data), "utf-8");
9555
9936
  } catch {
9556
9937
  }
9557
9938
  }
@@ -9562,7 +9943,7 @@ function detectGlobalInstall(execPath = process.argv[1] || "", cwd = process.cwd
9562
9943
  if (!execPath) return null;
9563
9944
  let resolved = execPath;
9564
9945
  try {
9565
- resolved = fs7.realpathSync(execPath);
9946
+ resolved = fs10.realpathSync(execPath);
9566
9947
  } catch {
9567
9948
  }
9568
9949
  const p = resolved.replace(/\\/g, "/");
@@ -9592,14 +9973,14 @@ async function findGlobalInstall(pkg = PACKAGE_NAME, run = defaultRunner) {
9592
9973
  pm: "yarn",
9593
9974
  root: () => {
9594
9975
  const dir = tryRun("yarn global dir");
9595
- return dir ? path37.join(dir, "node_modules") : null;
9976
+ return dir ? path39.join(dir, "node_modules") : null;
9596
9977
  }
9597
9978
  },
9598
- { pm: "bun", root: () => path37.join(os.homedir(), ".bun", "install", "global", "node_modules") }
9979
+ { pm: "bun", root: () => path39.join(os.homedir(), ".bun", "install", "global", "node_modules") }
9599
9980
  ];
9600
9981
  for (const probe of probes) {
9601
9982
  const root2 = probe.root();
9602
- if (root2 && await pathExists(path37.join(root2, pkg))) return probe.pm;
9983
+ if (root2 && await pathExists(path39.join(root2, pkg))) return probe.pm;
9603
9984
  }
9604
9985
  return null;
9605
9986
  }
@@ -9618,15 +9999,15 @@ function getGlobalUpdateCommand(pm, pkg, version) {
9618
9999
  }
9619
10000
  }
9620
10001
  async function detectPackageManager(cwd) {
9621
- if (await pathExists(path37.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
9622
- if (await pathExists(path37.join(cwd, "bun.lockb"))) return "bun";
9623
- if (await pathExists(path37.join(cwd, "yarn.lock"))) return "yarn";
10002
+ if (await pathExists(path39.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
10003
+ if (await pathExists(path39.join(cwd, "bun.lockb"))) return "bun";
10004
+ if (await pathExists(path39.join(cwd, "yarn.lock"))) return "yarn";
9624
10005
  return "npm";
9625
10006
  }
9626
10007
  async function detectWorkspaceRoot(cwd) {
9627
- if (await pathExists(path37.join(cwd, "pnpm-workspace.yaml"))) return true;
10008
+ if (await pathExists(path39.join(cwd, "pnpm-workspace.yaml"))) return true;
9628
10009
  try {
9629
- const pkgPath = path37.join(cwd, "package.json");
10010
+ const pkgPath = path39.join(cwd, "package.json");
9630
10011
  const raw = await (await import('fs/promises')).readFile(pkgPath, "utf-8");
9631
10012
  const pkg = JSON.parse(raw);
9632
10013
  return pkg.workspaces != null;
@@ -9651,7 +10032,7 @@ function getInstallCommand(pm, pkg, version, isDev, opts = {}) {
9651
10032
  }
9652
10033
  async function getLocalDependencyState(cwd, pkg = PACKAGE_NAME) {
9653
10034
  try {
9654
- const pkgPath = path37.join(cwd, "package.json");
10035
+ const pkgPath = path39.join(cwd, "package.json");
9655
10036
  const raw = await (await import('fs/promises')).readFile(pkgPath, "utf-8");
9656
10037
  const parsed = JSON.parse(raw);
9657
10038
  if (parsed.devDependencies?.[pkg]) return "dev";
@@ -9820,13 +10201,13 @@ function collectCandidates(artifact) {
9820
10201
  return out2;
9821
10202
  }
9822
10203
  var defaultFixScanner = async (rootDir) => {
9823
- const scratch = path37.join(os.tmpdir(), `vg-fix-scan-${process.pid}.json`);
10204
+ const scratch = path39.join(os.tmpdir(), `vg-fix-scan-${process.pid}.json`);
9824
10205
  const scanOpts = { vibgrateVersion: VERSION, format: "json", out: scratch, quiet: true, concurrency: 8 };
9825
10206
  const advanced = await loadAdvancedScanHook();
9826
10207
  return runCoreScan(rootDir, scanOpts, advanced);
9827
10208
  };
9828
10209
  async function loadArtifact(rootDir, inFile, scan = defaultFixScanner) {
9829
- const artifactPath = path37.isAbsolute(inFile) ? inFile : path37.join(rootDir, inFile);
10210
+ const artifactPath = path39.isAbsolute(inFile) ? inFile : path39.join(rootDir, inFile);
9830
10211
  if (await pathExists(artifactPath)) {
9831
10212
  const staleness = scanStaleness(rootDir, artifactPath);
9832
10213
  if (!staleness.stale) {
@@ -9853,7 +10234,7 @@ async function repositoryIdentity(rootDir, override) {
9853
10234
  }
9854
10235
  }
9855
10236
  var fixCommand = new Command("fix").description("Get ranked, risk-tiered upgrade plans from the hosted planner and optionally apply them (prompts before changing files; --yes applies non-interactively, --dry-run previews, --no-apply only prints). Requires login/DSN.").argument("[path]", "Path to analyse", ".").option("--in <file>", "Scan artifact to read", ".vibgrate/scan_result.json").option("--format <format>", "Output format (text|json|md)", "text").option("--dsn <dsn>", 'DSN token (or use VIBGRATE_DSN env / "vg login")').option("--region <region>", "Override data residency region (us, eu)").option("--repository-name <name>", "Override the repository name recorded for this plan").option("--plan <tier>", "Apply a specific plan non-interactively (safe|balanced|aggressive)").option("--yes", "Apply the recommended plan without prompting").option("--dry-run", "Show what would change without applying").option("--no-apply", "Only print the plans; never modify the project").option("--fail-on-vulns <severity>", "Exit non-zero if the recommended plan leaves an advisory at/above this severity unresolved (low|moderate|high|critical)").action(async (targetPath, opts) => {
9856
- const rootDir = path37.resolve(targetPath);
10237
+ const rootDir = path39.resolve(targetPath);
9857
10238
  if (!await pathExists(rootDir)) {
9858
10239
  console.error(chalk7.red(`Path does not exist: ${rootDir}`));
9859
10240
  process.exit(1);
@@ -10014,7 +10395,7 @@ function emit(report, format) {
10014
10395
  }
10015
10396
  }
10016
10397
  function relProjectDir(rootDir, projectPath) {
10017
- const rel = path37.isAbsolute(projectPath) ? path37.relative(rootDir, projectPath) : projectPath;
10398
+ const rel = path39.isAbsolute(projectPath) ? path39.relative(rootDir, projectPath) : projectPath;
10018
10399
  return rel === "" ? "." : rel;
10019
10400
  }
10020
10401
  async function buildTargetResolver(rootDir, artifact) {
@@ -10849,7 +11230,7 @@ function formatMarkdown(artifact) {
10849
11230
 
10850
11231
  // src/reporting/commands/report.ts
10851
11232
  var reportCommand = new Command("report").description("Generate a drift report from a scan artifact").option("--in <file>", "Input artifact file", ".vibgrate/scan_result.json").option("--format <format>", "Output format (md|text|json)", "text").action(async (opts) => {
10852
- const artifactPath = path37.resolve(opts.in);
11233
+ const artifactPath = path39.resolve(opts.in);
10853
11234
  if (!await pathExists(artifactPath)) {
10854
11235
  console.error(chalk7.red(`Artifact not found: ${artifactPath}`));
10855
11236
  console.error(chalk7.dim('Run "vibgrate scan" first to generate a scan artifact.'));
@@ -10898,8 +11279,8 @@ function openUrl(url) {
10898
11279
  // src/reporting/commands/login.ts
10899
11280
  var delay = (ms) => new Promise((resolve21) => setTimeout(resolve21, ms));
10900
11281
  function isInside(dir, file) {
10901
- const rel = path37.relative(dir, file);
10902
- return !!rel && !rel.startsWith("..") && !path37.isAbsolute(rel);
11282
+ const rel = path39.relative(dir, file);
11283
+ return !!rel && !rel.startsWith("..") && !path39.isAbsolute(rel);
10903
11284
  }
10904
11285
  var loginCommand = new Command("login").description("Authenticate the CLI with your Vibgrate workspace via the browser").option("--ingest <url>", "Ingest API URL (overrides --region)").option("--region <region>", `Data residency region (${availableRegionIds().join(", ")})`, "us").option("--no-browser", "Do not attempt to open a browser automatically").option(
10905
11286
  "--local",
@@ -11154,7 +11535,7 @@ var vexCommand = new Command("vex").description("Generate an OpenVEX document (e
11154
11535
  try {
11155
11536
  const statements = [];
11156
11537
  if (opts.from) {
11157
- const fromPath = path37.resolve(opts.from);
11538
+ const fromPath = path39.resolve(opts.from);
11158
11539
  if (!await pathExists(fromPath)) {
11159
11540
  process.stderr.write(chalk7.red(`Statements file not found: ${fromPath}
11160
11541
  `));
@@ -11172,9 +11553,9 @@ var vexCommand = new Command("vex").description("Generate an OpenVEX document (e
11172
11553
  });
11173
11554
  const json2 = JSON.stringify(doc, null, 2);
11174
11555
  if (opts.out) {
11175
- await writeTextFile(path37.resolve(opts.out), json2 + "\n");
11556
+ await writeTextFile(path39.resolve(opts.out), json2 + "\n");
11176
11557
  process.stderr.write(
11177
- chalk7.green("\u2714") + ` Wrote OpenVEX document (${doc.statements.length} statement(s)) to ${path37.resolve(opts.out)}
11558
+ chalk7.green("\u2714") + ` Wrote OpenVEX document (${doc.statements.length} statement(s)) to ${path39.resolve(opts.out)}
11178
11559
  `
11179
11560
  );
11180
11561
  } else {
@@ -11357,7 +11738,7 @@ function formatDeltaText(base, current) {
11357
11738
  return lines.join("\n");
11358
11739
  }
11359
11740
  async function readArtifactOrExit(filePath) {
11360
- const absolutePath = path37.resolve(filePath);
11741
+ const absolutePath = path39.resolve(filePath);
11361
11742
  if (!await pathExists(absolutePath)) {
11362
11743
  console.error(chalk7.red(`Artifact not found: ${absolutePath}`));
11363
11744
  process.exit(1);
@@ -11374,7 +11755,7 @@ var exportCommand = new Command("export").description("Export scan artifact as S
11374
11755
  const sbom = format === "cyclonedx" ? toCycloneDx(artifact) : toSpdx(artifact);
11375
11756
  const body = JSON.stringify(sbom, null, 2);
11376
11757
  if (opts.out) {
11377
- await writeTextFile(path37.resolve(opts.out), body);
11758
+ await writeTextFile(path39.resolve(opts.out), body);
11378
11759
  console.log(chalk7.green("\u2714") + ` SBOM written to ${opts.out}`);
11379
11760
  } else {
11380
11761
  console.log(body);
@@ -11385,7 +11766,7 @@ var deltaCommand = new Command("delta").description("Show SBOM delta between two
11385
11766
  const current = await readArtifactOrExit(opts.to);
11386
11767
  const report = formatDeltaText(base, current);
11387
11768
  if (opts.out) {
11388
- await writeTextFile(path37.resolve(opts.out), report);
11769
+ await writeTextFile(path39.resolve(opts.out), report);
11389
11770
  console.log(chalk7.green("\u2714") + ` SBOM delta report written to ${opts.out}`);
11390
11771
  } else {
11391
11772
  console.log(report);
@@ -11516,20 +11897,20 @@ function resolveRegime(id) {
11516
11897
  return regime;
11517
11898
  }
11518
11899
  function evidenceDir(root2) {
11519
- return path37.join(root2, ".vibgrate", "evidence");
11900
+ return path39.join(root2, ".vibgrate", "evidence");
11520
11901
  }
11521
11902
  function orgPath(root2) {
11522
- return path37.join(evidenceDir(root2), "org.json");
11903
+ return path39.join(evidenceDir(root2), "org.json");
11523
11904
  }
11524
11905
  function productsPath(root2) {
11525
- return path37.join(evidenceDir(root2), "products.json");
11906
+ return path39.join(evidenceDir(root2), "products.json");
11526
11907
  }
11527
11908
  function releasesDir(root2) {
11528
- return path37.join(evidenceDir(root2), "releases");
11909
+ return path39.join(evidenceDir(root2), "releases");
11529
11910
  }
11530
11911
  function releasePath(root2, productId, version) {
11531
11912
  const safe = `${productId}@${version}`.replace(/[^A-Za-z0-9._@-]/g, "_");
11532
- return path37.join(releasesDir(root2), `${safe}.json`);
11913
+ return path39.join(releasesDir(root2), `${safe}.json`);
11533
11914
  }
11534
11915
  var DEFAULT_ORG = {
11535
11916
  responsiblePersons: [],
@@ -11560,7 +11941,7 @@ async function freezeRelease(root2, release) {
11560
11941
  const p = releasePath(root2, release.productId, release.version);
11561
11942
  if (await pathExists(p)) {
11562
11943
  throw new CliError(
11563
- `release ${release.productId}@${release.version} is already frozen and manifests are immutable \u2014 delete ${path37.relative(root2, p)} only if it was frozen in error`,
11944
+ `release ${release.productId}@${release.version} is already frozen and manifests are immutable \u2014 delete ${path39.relative(root2, p)} only if it was frozen in error`,
11564
11945
  ExitCode.USAGE_ERROR
11565
11946
  );
11566
11947
  }
@@ -11574,7 +11955,7 @@ async function loadReleases(root2, productId) {
11574
11955
  const files = (await readdir(dir)).filter((f) => f.endsWith(".json")).sort();
11575
11956
  const releases = [];
11576
11957
  for (const f of files) {
11577
- const rel = await readJsonFile(path37.join(dir, f));
11958
+ const rel = await readJsonFile(path39.join(dir, f));
11578
11959
  if (!productId || rel.productId === productId) releases.push(rel);
11579
11960
  }
11580
11961
  return releases;
@@ -12269,19 +12650,19 @@ function verifyEvidenceEnvelope(env, opts = {}) {
12269
12650
  var DEFAULT_KEY = "attest-key.pem";
12270
12651
  function resolveSigningKey(root2, explicit) {
12271
12652
  const chosen = process.env.VG_ATTEST_KEY;
12272
- const keyPath = chosen ? path37.resolve(chosen) : path37.join(root2, ".vibgrate", DEFAULT_KEY);
12653
+ const keyPath = chosen ? path39.resolve(chosen) : path39.join(root2, ".vibgrate", DEFAULT_KEY);
12273
12654
  let minted = false;
12274
- if (!fs7.existsSync(keyPath)) {
12655
+ if (!fs10.existsSync(keyPath)) {
12275
12656
  if (chosen) throw new CliError(`signing key not found: ${chosen}`, ExitCode.USAGE_ERROR);
12276
12657
  const kp = generateKeypair();
12277
- fs7.mkdirSync(path37.dirname(keyPath), { recursive: true });
12278
- fs7.writeFileSync(keyPath, kp.privatePem, { mode: 384 });
12279
- fs7.writeFileSync(`${keyPath}.pub`, kp.publicPem);
12658
+ fs10.mkdirSync(path39.dirname(keyPath), { recursive: true });
12659
+ fs10.writeFileSync(keyPath, kp.privatePem, { mode: 384 });
12660
+ fs10.writeFileSync(`${keyPath}.pub`, kp.publicPem);
12280
12661
  minted = true;
12281
12662
  }
12282
12663
  let key2;
12283
12664
  try {
12284
- key2 = crypto3.createPrivateKey(fs7.readFileSync(keyPath, "utf8"));
12665
+ key2 = crypto3.createPrivateKey(fs10.readFileSync(keyPath, "utf8"));
12285
12666
  } catch {
12286
12667
  throw new CliError(`could not read an Ed25519 private key from ${keyPath}`, ExitCode.USAGE_ERROR);
12287
12668
  }
@@ -12292,16 +12673,16 @@ function resolveSigningKey(root2, explicit) {
12292
12673
  }
12293
12674
  function writeBundle(input) {
12294
12675
  const dir = input.outDir;
12295
- fs7.mkdirSync(path37.join(dir, "inputs", "releases"), { recursive: true });
12296
- const write = (rel, data) => fs7.writeFileSync(path37.join(dir, rel), `${JSON.stringify(data, null, 2)}
12676
+ fs10.mkdirSync(path39.join(dir, "inputs", "releases"), { recursive: true });
12677
+ const write = (rel, data) => fs10.writeFileSync(path39.join(dir, rel), `${JSON.stringify(data, null, 2)}
12297
12678
  `);
12298
12679
  write("result.json", input.result);
12299
- write(path37.join("inputs", "advisory.json"), input.advisory);
12680
+ write(path39.join("inputs", "advisory.json"), input.advisory);
12300
12681
  for (const rel of input.releases) {
12301
12682
  const safe = `${rel.productId}@${rel.version}`.replace(/[^A-Za-z0-9._@-]/g, "_");
12302
- write(path37.join("inputs", "releases", `${safe}.json`), rel);
12683
+ write(path39.join("inputs", "releases", `${safe}.json`), rel);
12303
12684
  }
12304
- write(path37.join("inputs", "datapack.lock"), { dataPackVersion: input.result.meta.dataPackVersion, kernelVersion: input.result.meta.kernelVersion });
12685
+ write(path39.join("inputs", "datapack.lock"), { dataPackVersion: input.result.meta.dataPackVersion, kernelVersion: input.result.meta.kernelVersion });
12305
12686
  write("provenance.json", {
12306
12687
  method: "deterministic",
12307
12688
  modelDrafted: [],
@@ -12317,13 +12698,13 @@ function writeBundle(input) {
12317
12698
  disclaimer: input.regime.disclaimer
12318
12699
  });
12319
12700
  if (input.envelope) {
12320
- fs7.writeFileSync(path37.join(dir, "evidence.intoto.jsonl"), `${JSON.stringify(input.envelope)}
12701
+ fs10.writeFileSync(path39.join(dir, "evidence.intoto.jsonl"), `${JSON.stringify(input.envelope)}
12321
12702
  `);
12322
12703
  }
12323
12704
  if (input.timestampToken) {
12324
- fs7.writeFileSync(path37.join(dir, "timestamp.tsr"), input.timestampToken);
12705
+ fs10.writeFileSync(path39.join(dir, "timestamp.tsr"), input.timestampToken);
12325
12706
  }
12326
- fs7.writeFileSync(path37.join(dir, "VERIFY.md"), verifyDoc(input));
12707
+ fs10.writeFileSync(path39.join(dir, "VERIFY.md"), verifyDoc(input));
12327
12708
  return dir;
12328
12709
  }
12329
12710
  function verifyDoc(input) {
@@ -12384,13 +12765,13 @@ function undeterminedFields(result, regime) {
12384
12765
  return gaps.filter((g) => regime.submission.requires.some((r) => g.startsWith(r)) || g.startsWith("exposure") || g.startsWith("member"));
12385
12766
  }
12386
12767
  async function recordDrill(root2, record) {
12387
- const dir = path37.join(evidenceDir(root2), "drills");
12388
- const p = path37.join(dir, `${record.drillId}.json`);
12768
+ const dir = path39.join(evidenceDir(root2), "drills");
12769
+ const p = path39.join(dir, `${record.drillId}.json`);
12389
12770
  await writeJsonFile(p, record);
12390
12771
  return p;
12391
12772
  }
12392
12773
  async function hasRecentDrill(root2, asOf) {
12393
- const dir = path37.join(evidenceDir(root2), "drills");
12774
+ const dir = path39.join(evidenceDir(root2), "drills");
12394
12775
  if (!await pathExists(dir)) return void 0;
12395
12776
  const { readdir } = await import('fs/promises');
12396
12777
  const { readJsonFile: readJsonFile2 } = await import('./fs-4G5A65KS.js');
@@ -12398,7 +12779,7 @@ async function hasRecentDrill(root2, asOf) {
12398
12779
  if (files.length === 0) return void 0;
12399
12780
  const cutoff = new Date(new Date(asOf).getTime() - 90 * 24 * 3600 * 1e3).toISOString();
12400
12781
  for (const f of files) {
12401
- const rec = await readJsonFile2(path37.join(dir, f));
12782
+ const rec = await readJsonFile2(path39.join(dir, f));
12402
12783
  if (rec.ranAt >= cutoff) return true;
12403
12784
  }
12404
12785
  return false;
@@ -12478,7 +12859,7 @@ function formatRegimeList() {
12478
12859
 
12479
12860
  // src/reporting/commands/evidence/index.ts
12480
12861
  function root(opts) {
12481
- return path37.resolve(opts.cwd ?? process.cwd());
12862
+ return path39.resolve(opts.cwd ?? process.cwd());
12482
12863
  }
12483
12864
  function slug(name) {
12484
12865
  return name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "product";
@@ -12566,7 +12947,7 @@ var releaseCmd = new Command("release").description("Freeze a shipped release in
12566
12947
  const release = await buildRelease({
12567
12948
  productId: product.id,
12568
12949
  version,
12569
- from: path37.resolve(rootDir, opts.from),
12950
+ from: path39.resolve(rootDir, opts.from),
12570
12951
  shipDate: opts.shipDate,
12571
12952
  buildId: opts.buildId,
12572
12953
  artefactDigest: opts.digest,
@@ -12574,7 +12955,7 @@ var releaseCmd = new Command("release").description("Freeze a shipped release in
12574
12955
  frozenAt: nowIso()
12575
12956
  });
12576
12957
  const p = await freezeRelease(rootDir, release);
12577
- console.log(chalk7.green("\u2714") + ` froze ${chalk7.bold(`${product.id}@${version}`)} \u2014 ${release.components.length} components, immutable at ${path37.relative(rootDir, p)}`);
12958
+ console.log(chalk7.green("\u2714") + ` froze ${chalk7.bold(`${product.id}@${version}`)} \u2014 ${release.components.length} components, immutable at ${path39.relative(rootDir, p)}`);
12578
12959
  });
12579
12960
  async function runExposure(rootDir, vuln, opts) {
12580
12961
  const org = await loadOrg(rootDir);
@@ -12626,7 +13007,7 @@ var exposureCmd = new Command("exposure").description("Which shipped products co
12626
13007
  console.log("\n" + buildPack(result, regime, org, stage));
12627
13008
  }
12628
13009
  if (opts.bundle) {
12629
- const dir = path37.resolve(rootDir, opts.bundle, `evidence-${result.meta.evidenceId}`);
13010
+ const dir = path39.resolve(rootDir, opts.bundle, `evidence-${result.meta.evidenceId}`);
12630
13011
  let envelope;
12631
13012
  if (opts.sign !== false) {
12632
13013
  const { key: key2, minted } = resolveSigningKey(rootDir);
@@ -12634,7 +13015,7 @@ var exposureCmd = new Command("exposure").description("Which shipped products co
12634
13015
  envelope = signEvidenceStatement(buildEvidenceStatement(result, VERSION), key2);
12635
13016
  }
12636
13017
  writeBundle({ outDir: dir, result, advisory, releases, regime, envelope, timestampToken, cliVersion: VERSION });
12637
- console.error(chalk7.green("\u2714") + ` evidence bundle written to ${path37.relative(rootDir, dir)}${envelope ? " (signed)" : " (unsigned)"}${timestampToken ? " \xB7 RFC 3161" : ""}`);
13018
+ console.error(chalk7.green("\u2714") + ` evidence bundle written to ${path39.relative(rootDir, dir)}${envelope ? " (signed)" : " (unsigned)"}${timestampToken ? " \xB7 RFC 3161" : ""}`);
12638
13019
  }
12639
13020
  process.exitCode = exposureExit(result.overallStatus);
12640
13021
  });
@@ -12666,7 +13047,7 @@ var packCmd = new Command("pack").description("Build the submission pack a human
12666
13047
  const stage = opts.stage ?? regime.clocks[0]?.stage ?? "early-warning";
12667
13048
  const md = buildPack(result, regime, org, stage);
12668
13049
  if (opts.out) {
12669
- fs7.writeFileSync(path37.resolve(rootDir, opts.out), md);
13050
+ fs10.writeFileSync(path39.resolve(rootDir, opts.out), md);
12670
13051
  console.error(chalk7.green("\u2714") + ` pack written to ${opts.out}`);
12671
13052
  } else {
12672
13053
  console.log(md);
@@ -12708,20 +13089,20 @@ var drillCmd = new Command("drill").description("Timed dry-run of the determinat
12708
13089
  }
12709
13090
  });
12710
13091
  var verifyCmd = new Command("verify").description("Verify an evidence bundle offline (no Vibgrate needed)").argument("<bundle>", "Path to an evidence bundle directory or evidence.intoto.jsonl").option("--pub <file>", "Public key PEM to pin the signer (establish trust)").action((bundlePath, opts) => {
12711
- const abs = path37.resolve(bundlePath);
12712
- const envPath = fs7.statSync(abs).isDirectory() ? path37.join(abs, "evidence.intoto.jsonl") : abs;
12713
- if (!fs7.existsSync(envPath)) throw new CliError(`no evidence.intoto.jsonl at ${bundlePath}`, ExitCode.NOT_FOUND);
12714
- const envelope = JSON.parse(fs7.readFileSync(envPath, "utf8").trim().split("\n")[0]);
12715
- const resultPath = path37.join(path37.dirname(envPath), "result.json");
12716
- const result = fs7.existsSync(resultPath) ? JSON.parse(fs7.readFileSync(resultPath, "utf8")) : void 0;
12717
- const publicKeyPem = opts.pub ? fs7.readFileSync(path37.resolve(opts.pub), "utf8") : void 0;
13092
+ const abs = path39.resolve(bundlePath);
13093
+ const envPath = fs10.statSync(abs).isDirectory() ? path39.join(abs, "evidence.intoto.jsonl") : abs;
13094
+ if (!fs10.existsSync(envPath)) throw new CliError(`no evidence.intoto.jsonl at ${bundlePath}`, ExitCode.NOT_FOUND);
13095
+ const envelope = JSON.parse(fs10.readFileSync(envPath, "utf8").trim().split("\n")[0]);
13096
+ const resultPath = path39.join(path39.dirname(envPath), "result.json");
13097
+ const result = fs10.existsSync(resultPath) ? JSON.parse(fs10.readFileSync(resultPath, "utf8")) : void 0;
13098
+ const publicKeyPem = opts.pub ? fs10.readFileSync(path39.resolve(opts.pub), "utf8") : void 0;
12718
13099
  const v = verifyEvidenceEnvelope(envelope, { publicKeyPem, result });
12719
13100
  const color = v.status === "verified" ? chalk7.green : v.status === "failed" ? chalk7.red : chalk7.yellow;
12720
13101
  console.log(" " + color(v.status.toUpperCase()) + ` ${v.reason}`);
12721
13102
  if (v.evidenceId) console.log(" " + chalk7.dim(`evidence ${v.evidenceId} \xB7 regime ${v.regime} \xB7 advisory ${v.advisoryId} \xB7 ${v.overallStatus}`));
12722
- const tsrPath = path37.join(path37.dirname(envPath), "timestamp.tsr");
12723
- if (fs7.existsSync(tsrPath) && result) {
12724
- const t = verifyTimestamp(fs7.readFileSync(tsrPath), exposureSubjectDigest(result));
13103
+ const tsrPath = path39.join(path39.dirname(envPath), "timestamp.tsr");
13104
+ if (fs10.existsSync(tsrPath) && result) {
13105
+ const t = verifyTimestamp(fs10.readFileSync(tsrPath), exposureSubjectDigest(result));
12725
13106
  const tcolor = t.imprintMatches ? chalk7.green : chalk7.red;
12726
13107
  console.log(" " + tcolor("TIMESTAMP") + ` ${t.reason}`);
12727
13108
  }
@@ -12788,12 +13169,12 @@ var exportCmd = new Command("export").description("Air-gap bundle of all evidenc
12788
13169
  const releases = [];
12789
13170
  for (const list of releasesByProduct.values()) releases.push(...list);
12790
13171
  const report = computeReadiness({ regime, org, products, releasesByProduct, recentDrill: await hasRecentDrill(rootDir, today()) });
12791
- const dir = path37.resolve(rootDir, opts.out);
12792
- await writeJsonFile(path37.join(dir, "org.json"), org);
12793
- await writeJsonFile(path37.join(dir, "products.json"), products);
12794
- for (const r of releases) await writeJsonFile(path37.join(dir, "releases", `${r.productId}@${r.version}.json`.replace(/[^A-Za-z0-9._@-]/g, "_")), r);
12795
- await writeJsonFile(path37.join(dir, "readiness.json"), report);
12796
- console.error(chalk7.green("\u2714") + ` exported evidence state to ${path37.relative(rootDir, dir)} (${products.length} products, ${releases.length} frozen releases)`);
13172
+ const dir = path39.resolve(rootDir, opts.out);
13173
+ await writeJsonFile(path39.join(dir, "org.json"), org);
13174
+ await writeJsonFile(path39.join(dir, "products.json"), products);
13175
+ for (const r of releases) await writeJsonFile(path39.join(dir, "releases", `${r.productId}@${r.version}.json`.replace(/[^A-Za-z0-9._@-]/g, "_")), r);
13176
+ await writeJsonFile(path39.join(dir, "readiness.json"), report);
13177
+ console.error(chalk7.green("\u2714") + ` exported evidence state to ${path39.relative(rootDir, dir)} (${products.length} products, ${releases.length} frozen releases)`);
12797
13178
  });
12798
13179
  var pushCmd = new Command("push").description("Push the product registry (and an optional exposure result) to Vibgrate Cloud").option(...cwdOption).option("--dsn <dsn>", "DSN token (or use VIBGRATE_DSN env / `vg login`)").option("--regime <id>", "Reporting regime").option("--result <file>", "An exposure result.json (or a bundle dir) to include").option("--signed", "Mark the included exposure result as signed").option("--strict", "Fail on push errors").action(async (opts) => {
12799
13180
  const rootDir = root(opts);
@@ -12819,10 +13200,10 @@ var pushCmd = new Command("push").description("Push the product registry (and an
12819
13200
  }));
12820
13201
  let exposure;
12821
13202
  if (opts.result) {
12822
- const raw = path37.resolve(rootDir, opts.result);
12823
- const resultPath = fs7.existsSync(raw) && fs7.statSync(raw).isDirectory() ? path37.join(raw, "result.json") : raw;
12824
- if (!fs7.existsSync(resultPath)) throw new CliError(`no result.json at ${opts.result}`, ExitCode.NOT_FOUND);
12825
- exposure = JSON.parse(fs7.readFileSync(resultPath, "utf8"));
13203
+ const raw = path39.resolve(rootDir, opts.result);
13204
+ const resultPath = fs10.existsSync(raw) && fs10.statSync(raw).isDirectory() ? path39.join(raw, "result.json") : raw;
13205
+ if (!fs10.existsSync(resultPath)) throw new CliError(`no result.json at ${opts.result}`, ExitCode.NOT_FOUND);
13206
+ exposure = JSON.parse(fs10.readFileSync(resultPath, "utf8"));
12826
13207
  }
12827
13208
  const payload = { schemaVersion: "evidence-push-1", regime: regime.id, generatedAt: nowIso(), signed: Boolean(opts.signed), products: productPayload, exposure };
12828
13209
  const body = JSON.stringify(payload);
@@ -12880,6 +13261,7 @@ var KNOWN_COMMANDS = /* @__PURE__ */ new Set([
12880
13261
  "serve",
12881
13262
  "lsp",
12882
13263
  "doctor",
13264
+ "module",
12883
13265
  "daemon",
12884
13266
  "policy",
12885
13267
  "llm-host",
@@ -12887,6 +13269,7 @@ var KNOWN_COMMANDS = /* @__PURE__ */ new Set([
12887
13269
  "uninstall",
12888
13270
  "share",
12889
13271
  "watch",
13272
+ "hook",
12890
13273
  "help",
12891
13274
  // Drift-reporting verbs (merged from the Vibgrate CLI).
12892
13275
  "init",
@@ -12926,6 +13309,8 @@ ${aliasNote}Docs: https://vibgrate.com/help`;
12926
13309
  registerServe(program);
12927
13310
  registerLsp(program);
12928
13311
  registerInstall(program);
13312
+ registerModule(program);
13313
+ registerHook(program);
12929
13314
  registerShare(program);
12930
13315
  registerWatch(program);
12931
13316
  registerTests(program);
@@ -13012,7 +13397,7 @@ function dispatch(argv, cwd) {
13012
13397
  }
13013
13398
  const looksLikeQuestion = /\s/.test(first) || first.endsWith("?");
13014
13399
  if (looksLikeQuestion) return ["ask", ...args];
13015
- if (fs7.existsSync(path37.resolve(cwd, first))) {
13400
+ if (fs10.existsSync(path39.resolve(cwd, first))) {
13016
13401
  return [hasBuildOnlyFlag(args) ? "build" : "scan", ...args];
13017
13402
  }
13018
13403
  const moved = MOVED_COMMANDS[first];
@@ -13057,9 +13442,9 @@ async function main(argv = process.argv) {
13057
13442
  }
13058
13443
  function readCwd(raw) {
13059
13444
  const i = raw.findIndex((a) => a === "-C" || a === "--cwd");
13060
- if (i >= 0 && raw[i + 1]) return path37.resolve(raw[i + 1]);
13445
+ if (i >= 0 && raw[i + 1]) return path39.resolve(raw[i + 1]);
13061
13446
  const eq = raw.find((a) => a.startsWith("--cwd="));
13062
- if (eq) return path37.resolve(eq.slice("--cwd=".length));
13447
+ if (eq) return path39.resolve(eq.slice("--cwd=".length));
13063
13448
  return process.cwd();
13064
13449
  }
13065
13450
  function handleError(err) {