@vibgrate/cli 2026.817.2 → 2026.818.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/dist/activity-MF2GNYAI.js +5 -0
  2. package/dist/activity-MF2GNYAI.js.map +1 -0
  3. package/dist/agent-X6VYCE63.js +30 -0
  4. package/dist/{agent-UQC7QN77.js.map → agent-X6VYCE63.js.map} +1 -1
  5. package/dist/{approvals-ASPJQUZK.js → approvals-TPQFQSWG.js} +5 -5
  6. package/dist/{approvals-ASPJQUZK.js.map → approvals-TPQFQSWG.js.map} +1 -1
  7. package/dist/attach-G5JUIWIT.js +10 -0
  8. package/dist/attach-G5JUIWIT.js.map +1 -0
  9. package/dist/baseline-DXI64VLW.js +9 -0
  10. package/dist/{baseline-FIV6PR2M.js.map → baseline-DXI64VLW.js.map} +1 -1
  11. package/dist/{chunk-AXZZ5CCG.js → chunk-2C33WR5O.js} +38 -19
  12. package/dist/chunk-2C33WR5O.js.map +1 -0
  13. package/dist/chunk-4NTNMT6T.js +6 -0
  14. package/dist/{chunk-PRG2ULPK.js.map → chunk-4NTNMT6T.js.map} +1 -1
  15. package/dist/chunk-5IQBIXHS.js +23 -0
  16. package/dist/chunk-5IQBIXHS.js.map +1 -0
  17. package/dist/{chunk-6K3XK7C5.js → chunk-6ABMV74F.js} +6 -3
  18. package/dist/chunk-6ABMV74F.js.map +1 -0
  19. package/dist/chunk-6BEBJCK4.js +467 -0
  20. package/dist/chunk-6BEBJCK4.js.map +1 -0
  21. package/dist/{chunk-E2FAQREZ.js → chunk-6PFHDHOL.js} +174 -401
  22. package/dist/chunk-6PFHDHOL.js.map +1 -0
  23. package/dist/chunk-6WRG7VDO.js +118 -0
  24. package/dist/chunk-6WRG7VDO.js.map +1 -0
  25. package/dist/{chunk-3NJUOIZQ.js → chunk-AEJYA6HZ.js} +5 -5
  26. package/dist/{chunk-3NJUOIZQ.js.map → chunk-AEJYA6HZ.js.map} +1 -1
  27. package/dist/{chunk-O2DL2Q55.js → chunk-B4EXD5LK.js} +5 -5
  28. package/dist/{chunk-O2DL2Q55.js.map → chunk-B4EXD5LK.js.map} +1 -1
  29. package/dist/{chunk-EXV4QSAD.js → chunk-BMOFJIMG.js} +3 -3
  30. package/dist/{chunk-EXV4QSAD.js.map → chunk-BMOFJIMG.js.map} +1 -1
  31. package/dist/chunk-DBX3DL27.js +26 -0
  32. package/dist/chunk-DBX3DL27.js.map +1 -0
  33. package/dist/{chunk-KNGAZDGF.js → chunk-E3O5UKNA.js} +151 -42
  34. package/dist/chunk-E3O5UKNA.js.map +1 -0
  35. package/dist/{chunk-RBIRXQR6.js → chunk-E53WBVUQ.js} +7 -14
  36. package/dist/chunk-E53WBVUQ.js.map +1 -0
  37. package/dist/{chunk-C3LMWZKF.js → chunk-FFXGWFAE.js} +4 -4
  38. package/dist/{chunk-C3LMWZKF.js.map → chunk-FFXGWFAE.js.map} +1 -1
  39. package/dist/chunk-H5Q4JUY4.js +47 -0
  40. package/dist/chunk-H5Q4JUY4.js.map +1 -0
  41. package/dist/{chunk-LHKQGVRF.js → chunk-HF6R73UC.js} +100 -11
  42. package/dist/chunk-HF6R73UC.js.map +1 -0
  43. package/dist/{chunk-K6DXETMC.js → chunk-JGA63RGF.js} +13 -12
  44. package/dist/chunk-JGA63RGF.js.map +1 -0
  45. package/dist/{chunk-3FMRFECC.js → chunk-KU7FI5EV.js} +3 -3
  46. package/dist/{chunk-3FMRFECC.js.map → chunk-KU7FI5EV.js.map} +1 -1
  47. package/dist/{chunk-5OL2TSHK.js → chunk-L2OS4WHT.js} +4 -4
  48. package/dist/{chunk-5OL2TSHK.js.map → chunk-L2OS4WHT.js.map} +1 -1
  49. package/dist/chunk-LJSJX6U4.js +38 -0
  50. package/dist/chunk-LJSJX6U4.js.map +1 -0
  51. package/dist/{chunk-Q4G2BWE3.js → chunk-MRZHNUN7.js} +12 -6
  52. package/dist/chunk-MRZHNUN7.js.map +1 -0
  53. package/dist/chunk-NDNNOAS6.js +16 -0
  54. package/dist/chunk-NDNNOAS6.js.map +1 -0
  55. package/dist/chunk-NJQZRM55.js +100 -0
  56. package/dist/chunk-NJQZRM55.js.map +1 -0
  57. package/dist/{chunk-DVW3SVCW.js → chunk-NKLYDSB7.js} +29 -9
  58. package/dist/chunk-NKLYDSB7.js.map +1 -0
  59. package/dist/{chunk-TVDMNIUT.js → chunk-O5IJDMTB.js} +4 -4
  60. package/dist/{chunk-TVDMNIUT.js.map → chunk-O5IJDMTB.js.map} +1 -1
  61. package/dist/chunk-POOL355F.js +237 -0
  62. package/dist/chunk-POOL355F.js.map +1 -0
  63. package/dist/{chunk-XLXJC7H3.js → chunk-PRHH4DVO.js} +5 -118
  64. package/dist/chunk-PRHH4DVO.js.map +1 -0
  65. package/dist/{chunk-3H3SVJUY.js → chunk-RHKOUPWT.js} +107 -542
  66. package/dist/chunk-RHKOUPWT.js.map +1 -0
  67. package/dist/{chunk-WAKP7SK7.js → chunk-V2UGRUTL.js} +225 -48
  68. package/dist/chunk-V2UGRUTL.js.map +1 -0
  69. package/dist/{chunk-2FEB5KJS.js → chunk-V6WONSIK.js} +5 -4
  70. package/dist/chunk-V6WONSIK.js.map +1 -0
  71. package/dist/{chunk-WVMOGIPC.js → chunk-VMAIDM4K.js} +3 -3
  72. package/dist/{chunk-WVMOGIPC.js.map → chunk-VMAIDM4K.js.map} +1 -1
  73. package/dist/{chunk-GOGMS3ST.js → chunk-VQ5KMHW6.js} +860 -65
  74. package/dist/chunk-VQ5KMHW6.js.map +1 -0
  75. package/dist/{chunk-M7IO3DXH.js → chunk-X2MQ7UFL.js} +250 -30
  76. package/dist/chunk-X2MQ7UFL.js.map +1 -0
  77. package/dist/{chunk-OZ3IFXRD.js → chunk-YENM3HT7.js} +5 -4
  78. package/dist/chunk-YENM3HT7.js.map +1 -0
  79. package/dist/{chunk-KJT2R6WW.js → chunk-YF54UMOU.js} +3 -3
  80. package/dist/{chunk-KJT2R6WW.js.map → chunk-YF54UMOU.js.map} +1 -1
  81. package/dist/{chunk-Q3M6K3HY.js → chunk-ZUOBPKVK.js} +3 -3
  82. package/dist/{chunk-Q3M6K3HY.js.map → chunk-ZUOBPKVK.js.map} +1 -1
  83. package/dist/cli.d.ts +6 -0
  84. package/dist/cli.js +711 -463
  85. package/dist/cli.js.map +1 -1
  86. package/dist/client-UQIELEEZ.js +8 -0
  87. package/dist/client-UQIELEEZ.js.map +1 -0
  88. package/dist/daemon-GUMWMKCA.js +31 -0
  89. package/dist/{daemon-FPTRHO5N.js.map → daemon-GUMWMKCA.js.map} +1 -1
  90. package/dist/embed-worker-main.js +3 -3
  91. package/dist/ensure-map-FHDJTO7Y.js +41 -0
  92. package/dist/{ensure-map-342G2IV3.js.map → ensure-map-FHDJTO7Y.js.map} +1 -1
  93. package/dist/graph-backend-W2D3HRRD.js +16 -0
  94. package/dist/{graph-backend-RNWQBT3P.js.map → graph-backend-W2D3HRRD.js.map} +1 -1
  95. package/dist/index.d.ts +633 -4
  96. package/dist/index.js +26 -17
  97. package/dist/index.js.map +1 -1
  98. package/dist/{interactive-SR7TMF6M.js → interactive-2MK4TLRD.js} +42 -34
  99. package/dist/interactive-2MK4TLRD.js.map +1 -0
  100. package/dist/load-4R4HYMBB.js +11 -0
  101. package/dist/{load-AYFECIQB.js.map → load-4R4HYMBB.js.map} +1 -1
  102. package/dist/parse-worker.js +3 -2
  103. package/dist/parse-worker.js.map +1 -1
  104. package/dist/publish-7YHRTBRA.js +9 -0
  105. package/dist/publish-7YHRTBRA.js.map +1 -0
  106. package/dist/{run-outcome-YQQJG3LW.js → run-outcome-H5GVDDZJ.js} +5 -5
  107. package/dist/{run-outcome-YQQJG3LW.js.map → run-outcome-H5GVDDZJ.js.map} +1 -1
  108. package/dist/runtime-session-JBIHHH5N.js +27 -0
  109. package/dist/{runtime-session-CNJ4DAV5.js.map → runtime-session-JBIHHH5N.js.map} +1 -1
  110. package/dist/semantic-status-2JFLIQQJ.js +4 -0
  111. package/dist/semantic-status-2JFLIQQJ.js.map +1 -0
  112. package/dist/{session-H34HUV2Y.js → session-N5IU4K5Q.js} +8 -8
  113. package/dist/{session-H34HUV2Y.js.map → session-N5IU4K5Q.js.map} +1 -1
  114. package/dist/slot-subscription-25GOARW5.js +95 -0
  115. package/dist/slot-subscription-25GOARW5.js.map +1 -0
  116. package/dist/{stream-json-55YDNAFX.js → stream-json-4WLSUF6I.js} +18 -15
  117. package/dist/stream-json-4WLSUF6I.js.map +1 -0
  118. package/dist/version-DTEU3SQD.js +4 -0
  119. package/dist/{version-WSE3QOPK.js.map → version-DTEU3SQD.js.map} +1 -1
  120. package/dist/{vg-mcp-bridge-2CNLHNEL.js → vg-mcp-bridge-KDVYIMFX.js} +12 -11
  121. package/dist/vg-mcp-bridge-KDVYIMFX.js.map +1 -0
  122. package/dist/{vgd-URUZQORN.js → vgd-M7UOPWLB.js} +15 -10
  123. package/dist/vgd-M7UOPWLB.js.map +1 -0
  124. package/package.json +1 -1
  125. package/dist/agent-UQC7QN77.js +0 -27
  126. package/dist/baseline-FIV6PR2M.js +0 -9
  127. package/dist/chunk-2FEB5KJS.js.map +0 -1
  128. package/dist/chunk-3H3SVJUY.js.map +0 -1
  129. package/dist/chunk-6K3XK7C5.js.map +0 -1
  130. package/dist/chunk-AXZZ5CCG.js.map +0 -1
  131. package/dist/chunk-DVW3SVCW.js.map +0 -1
  132. package/dist/chunk-E2FAQREZ.js.map +0 -1
  133. package/dist/chunk-GOGMS3ST.js.map +0 -1
  134. package/dist/chunk-K6DXETMC.js.map +0 -1
  135. package/dist/chunk-KNGAZDGF.js.map +0 -1
  136. package/dist/chunk-LHKQGVRF.js.map +0 -1
  137. package/dist/chunk-M7IO3DXH.js.map +0 -1
  138. package/dist/chunk-OZ3IFXRD.js.map +0 -1
  139. package/dist/chunk-PRG2ULPK.js +0 -6
  140. package/dist/chunk-Q4G2BWE3.js.map +0 -1
  141. package/dist/chunk-RBIRXQR6.js.map +0 -1
  142. package/dist/chunk-WAKP7SK7.js.map +0 -1
  143. package/dist/chunk-XLXJC7H3.js.map +0 -1
  144. package/dist/daemon-FPTRHO5N.js +0 -26
  145. package/dist/ensure-map-342G2IV3.js +0 -33
  146. package/dist/graph-backend-RNWQBT3P.js +0 -15
  147. package/dist/interactive-SR7TMF6M.js.map +0 -1
  148. package/dist/load-AYFECIQB.js +0 -11
  149. package/dist/runtime-session-CNJ4DAV5.js +0 -22
  150. package/dist/stream-json-55YDNAFX.js.map +0 -1
  151. package/dist/version-WSE3QOPK.js +0 -4
  152. package/dist/vg-mcp-bridge-2CNLHNEL.js.map +0 -1
  153. package/dist/vgd-URUZQORN.js.map +0 -1
package/dist/cli.js CHANGED
@@ -1,63 +1,72 @@
1
1
  #!/usr/bin/env node
2
- import { fetchCatalog, resolveProviders } from './chunk-C3LMWZKF.js';
3
- import { telemetryOptOut, StatsSharer, statsEndpoint, isCI } from './chunk-EXV4QSAD.js';
4
- import { loadAdvancedScanHook, baselineCommand } from './chunk-6K3XK7C5.js';
5
- import { sha256Hex, generateKeypair, dssePae, DSSE_PAYLOAD_TYPE, keyId, registerBuild, ProgressBar, printLogo, runBuild } from './chunk-LHKQGVRF.js';
6
- export { runBuild } from './chunk-LHKQGVRF.js';
7
- import { restartVgdIfRunning, stopVgd, registerDaemon, rootOf, requireGraph } from './chunk-KNGAZDGF.js';
8
- import { readGlobal, applyGlobalOptions } from './chunk-OZ3IFXRD.js';
9
- import { disableColor, info, c, json, out } from './chunk-CT5BS56U.js';
10
- import './chunk-GOGMS3ST.js';
11
- import './chunk-IS7VTH2Q.js';
2
+ import { fetchCatalog, resolveProviders } from './chunk-FFXGWFAE.js';
3
+ import { telemetryOptOut, StatsSharer, statsEndpoint, isCI } from './chunk-BMOFJIMG.js';
4
+ import { loadAdvancedScanHook, baselineCommand } from './chunk-6ABMV74F.js';
5
+ import { sha256Hex, generateKeypair, dssePae, DSSE_PAYLOAD_TYPE, keyId, registerBuild, LiveStatus, ProgressBar, printLogo, runBuild } from './chunk-HF6R73UC.js';
6
+ export { runBuild } from './chunk-HF6R73UC.js';
7
+ import { readOrchestratorState, writeOrchestratorState, parseMode, setDefaultMode, recommendMode, activePin, resolveMode, providerForBackend, QUALIFIED_PACKS, pinPack, unpinPack, buildOrchestratorStatus } from './chunk-NZELMYT4.js';
12
8
  import { defaultProcessEndpoint, startProcessHostServer, resolveInferenceIsolation } from './chunk-JFE7XCAE.js';
13
- import { clearHostSessionPool, acquireHostSession, generateOnSession, listHostSessions, hostSessionPoolSize } from './chunk-3LOWJSAF.js';
14
- import { runCodeSession } from './chunk-3NJUOIZQ.js';
15
- import { CONTEXT_POLICY_VERSION, computeFcsReport, renderFcsReportMarkdown, createTrajectoryCollector, runAgent } from './chunk-K6DXETMC.js';
9
+ import { runCodeSession } from './chunk-AEJYA6HZ.js';
10
+ import { CONTEXT_POLICY_VERSION, computeFcsReport, renderFcsReportMarkdown, createTrajectoryCollector, runAgent } from './chunk-JGA63RGF.js';
16
11
  import './chunk-543E6WDJ.js';
17
- import './chunk-Q3M6K3HY.js';
18
- import './chunk-TVDMNIUT.js';
19
- import './chunk-RBIRXQR6.js';
20
- import { buildIdentifierTrieFromGraph } from './chunk-5HYCB55P.js';
12
+ import './chunk-ZUOBPKVK.js';
13
+ import './chunk-O5IJDMTB.js';
21
14
  import { parseReasoningEffort, summarizeDiffs, ScriptedProvider } from './chunk-74UBGF4P.js';
22
15
  import './chunk-7AVYKZEM.js';
23
16
  import { buildModelInstallPlan } from './chunk-I5LP55B6.js';
24
17
  import { ensurePackage, ensureUnavailableMessage } from './chunk-3HNPVXUK.js';
18
+ import { vgdVersionSkew, restartVgdIfRunning, stopVgd, registerDaemon, rootOf, requireGraph } from './chunk-E3O5UKNA.js';
19
+ import { readGlobal, applyGlobalOptions } from './chunk-YENM3HT7.js';
20
+ import { ActivityLog } from './chunk-H5Q4JUY4.js';
21
+ import { disableColor, info, c, json, out } from './chunk-CT5BS56U.js';
25
22
  import { init_resolve_ollama, gatherSystemMemory, resolveOllamaBinary, hasOllamaBinary, resolve_ollama_exports } from './chunk-FJG5AXKZ.js';
26
- import { readOrchestratorState, writeOrchestratorState, parseMode, setDefaultMode, recommendMode, activePin, resolveMode, providerForBackend, QUALIFIED_PACKS, pinPack, unpinPack, buildOrchestratorStatus } from './chunk-NZELMYT4.js';
27
23
  import { fmt, estimateModelBytes } from './chunk-7N4Y3E47.js';
24
+ import { isManifest, isDependencyFile, manifestHash, loadScanCache, writeScanCache, manifestKind, findPackageLine, endOfLine, findRuntimeLine } from './chunk-VQ5KMHW6.js';
25
+ import { clearHostSessionPool, acquireHostSession, generateOnSession, listHostSessions, hostSessionPoolSize } from './chunk-3LOWJSAF.js';
26
+ import { buildIdentifierTrieFromGraph } from './chunk-5HYCB55P.js';
27
+ import './chunk-IS7VTH2Q.js';
28
28
  import './chunk-IZDH67DX.js';
29
- import { serveStdio, isRelevantChange, exportGraph, GraphSource, createServer, formatForExt, RefreshScheduler } from './chunk-M7IO3DXH.js';
30
- import { refreshIfStale } from './chunk-O2DL2Q55.js';
31
- import { driftCount, ASSISTANTS, detectAssistants, isAssistantInstalled, detectServeLaunch, installAssistant, writeNavigationConfig, uninstallAssistant, buildGraph, writeSnapshot, probeFreshness, discover, assistantById, SMALL_REPO_FILES, isSkippedDirName, SKIP_FILES, SKIP_DIRS } from './chunk-E2FAQREZ.js';
32
- 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-DVW3SVCW.js';
29
+ import { DaemonSemanticSession, serveStdio, exportGraph, GraphSource, createServer, formatForExt, RefreshScheduler } from './chunk-X2MQ7UFL.js';
30
+ import { refreshIfStale } from './chunk-B4EXD5LK.js';
31
+ import { driftCount, ASSISTANTS, detectAssistants, isAssistantInstalled, detectServeLaunch, installAssistant, writeNavigationConfig, uninstallAssistant, buildGraph, writeSnapshot, probeFreshness, assistantById, SMALL_REPO_FILES } from './chunk-6PFHDHOL.js';
32
+ 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-NKLYDSB7.js';
33
33
  import { resolveIngestHost, dashHostForIngestHost, availableRegionIds, ingestHostForRegionId } from './chunk-HTLDXEHW.js';
34
- import { writeDefaultConfig, parseDsn, detectVcs, computeRepoFingerprint, resolveRepositoryName, fetchScanPreflight, runCoreScan, loadConfig, prepareCompressedUpload, computeDriftScore, titleBox, projectTypeToVulnEcosystem, driftBar, gitHistoryAvailable, buildVersionTimelines, findPackageAnyEcosystem, normalizeConstraint, findVersionCrossings, versionSatisfies, refineArchitectureWithGraph, refineArchitectureWithAstRoles, PROJECT_TYPE_TO_OSV_ECOSYSTEM, fetchRiskySymbols, perDependencyDrift } from './chunk-WAKP7SK7.js';
35
- import { CliError, ExitCode, usageError, engineUnavailable } from './chunk-MS6V5XKB.js';
34
+ import { writeDefaultConfig, parseDsn, detectVcs, computeRepoFingerprint, resolveRepositoryName, fetchScanPreflight, runCoreScan, loadConfig, prepareCompressedUpload, computeDriftScore, titleBox, projectTypeToVulnEcosystem, driftBar, gitHistoryAvailable, buildVersionTimelines, findPackageAnyEcosystem, normalizeConstraint, findVersionCrossings, versionSatisfies, refineArchitectureWithAstRoles, refineArchitectureWithGraph, PROJECT_TYPE_TO_OSV_ECOSYSTEM, fetchRiskySymbols, perDependencyDrift, boundaryProfileRules } from './chunk-V2UGRUTL.js';
36
35
  import './chunk-VIWZ4QT7.js';
37
- import { inventory, enrichOnline, ECOSYSTEMS, catalogPath, libDir, loadCatalog, driftFor, addLibrary, resolveLib, libId, resolveVersion, readDoc, localPackageDocs, localApiSurface } from './chunk-3H3SVJUY.js';
38
- import { resolveOne } from './chunk-J7LKEB2R.js';
39
- import { recordCliCall, CLI_TOOL_ALIASES, savingsLedgerPath, clearSavings, readSavings, readUsage, readModelSavings, CAPSULE_RANKING_VERSION, SAVINGS_TOOLS, sanitizeClient } from './chunk-KJT2R6WW.js';
40
- import { queryGraphSemantic, queryGraph, indexFor, impactOf } from './chunk-Q4G2BWE3.js';
36
+ import { catalogPath, libDir, loadCatalog, driftFor, addLibrary, resolveLib, libId, resolveVersion, readDoc, localPackageDocs, localApiSurface } from './chunk-RHKOUPWT.js';
37
+ import { recordCliCall, CLI_TOOL_ALIASES, savingsLedgerPath, clearSavings, readSavings, readUsage, readModelSavings, CAPSULE_RANKING_VERSION, SAVINGS_TOOLS, sanitizeClient } from './chunk-YF54UMOU.js';
41
38
  import { discoverModels } from './chunk-CQDUBAQY.js';
42
39
  import { freeBytesOnVolume, weightStoreDir, listCachedWeights, ensureWeightCached, catalogIntegrityReport } from './chunk-OV4KGXPD.js';
43
- import { loadGraph, loadGraphPreferIndex, SCHEMA_VERSION } from './chunk-3FMRFECC.js';
44
- import './chunk-5I4VSBWQ.js';
40
+ import { CliError, ExitCode, usageError, engineUnavailable } from './chunk-MS6V5XKB.js';
41
+ import { attachVgd } from './chunk-NJQZRM55.js';
45
42
  import { pathExists as pathExists$1, parseExcludePatterns } from './chunk-NG4KIJW6.js';
46
43
  import { ensureDir, pathExists, readJsonFile, writeTextFile, writeJsonFile } from './chunk-CRAMOEBE.js';
44
+ import './chunk-5IQBIXHS.js';
47
45
  import { init_cli_invocation, resolveCliInvocation, NPX_INVOCATION } from './chunk-EZ7UC5Y5.js';
48
- import { resolvedGrammarFiles, TOOLCHAIN_GRAMMARS, resolveToolchainGrammar, grammarSetVersion, fileRolesFromParseCache } from './chunk-XLXJC7H3.js';
46
+ import { publishGraphToVgd } from './chunk-LJSJX6U4.js';
47
+ import { isRelevantChange } from './chunk-DBX3DL27.js';
48
+ import { discover, SKIP_DIRS } from './chunk-POOL355F.js';
49
+ import { inventory, enrichOnline, ECOSYSTEMS } from './chunk-6BEBJCK4.js';
50
+ import { resolveOne } from './chunk-J7LKEB2R.js';
51
+ import { queryGraphSemantic, queryGraph, indexFor, impactOf } from './chunk-MRZHNUN7.js';
52
+ import { loadGraph, loadGraphPreferIndex, SCHEMA_VERSION } from './chunk-KU7FI5EV.js';
53
+ import './chunk-E53WBVUQ.js';
54
+ import './chunk-NDNNOAS6.js';
55
+ import './chunk-5I4VSBWQ.js';
56
+ import { resolvedGrammarFiles, TOOLCHAIN_GRAMMARS, resolveToolchainGrammar, grammarSetVersion, fileRolesFromParseCache } from './chunk-PRHH4DVO.js';
49
57
  import './chunk-T7RSQ5WD.js';
50
- import { embeddingsCached, resolveEmbedModel, loadEmbedder, getNodeEmbeddings, unavailableMessage, countPending, modelCacheInfo, embeddingsPath, clearModelCache, withTimeout } from './chunk-AXZZ5CCG.js';
51
- import { resetRelevanceProviderCache, loadRelevanceProvider, relevanceModuleDir, resolveGraphPath, analyzeQuestion, loadTopicTags, renderReport, loadGraphFileWithSnapshot, writeArtifacts, vibgrateDir, mapFileExists, ensureVibgrateGitignore } from './chunk-WVMOGIPC.js';
58
+ import './chunk-6WRG7VDO.js';
59
+ import { embeddingsCached, resolveEmbedModel, loadEmbedder, getNodeEmbeddings, unavailableMessage, countPending, modelCacheInfo, embeddingsPath, clearModelCache, withTimeout } from './chunk-2C33WR5O.js';
60
+ import { resetRelevanceProviderCache, loadRelevanceProvider, relevanceModuleDir, resolveGraphPath, analyzeQuestion, loadTopicTags, renderReport, loadGraphFileWithSnapshot, writeArtifacts, vibgrateDir, mapFileExists, ensureVibgrateGitignore } from './chunk-VMAIDM4K.js';
52
61
  import { cacheDir } from './chunk-MVPRPSXU.js';
53
62
  import { serializeGraph, stableStringify, parseGraph } from './chunk-O3LABX6I.js';
54
- import { VERSION } from './chunk-PRG2ULPK.js';
63
+ import { VERSION } from './chunk-4NTNMT6T.js';
55
64
  import './chunk-BWPBB45M.js';
56
- import { canonicalize, hashString, hashBytes } from './chunk-JFGYT6BI.js';
65
+ import { canonicalize, hashString } from './chunk-JFGYT6BI.js';
57
66
  import './chunk-BPF3YX2U.js';
58
67
  import { __toCommonJS } from './chunk-Z6ZWNWWR.js';
59
- import * as fs14 from 'fs';
60
- import fs14__default, { realpathSync } from 'fs';
68
+ import * as fs13 from 'fs';
69
+ import fs13__default, { realpathSync } from 'fs';
61
70
  import * as path46 from 'path';
62
71
  import path46__default from 'path';
63
72
  import { fileURLToPath, pathToFileURL } from 'url';
@@ -71,7 +80,7 @@ import * as zlib from 'zlib';
71
80
  import * as crypto3 from 'crypto';
72
81
  import { randomUUID, createHash } from 'crypto';
73
82
  import chalk7 from 'chalk';
74
- import * as fs28 from 'fs/promises';
83
+ import * as fs27 from 'fs/promises';
75
84
  import { parse, stringify } from 'yaml';
76
85
 
77
86
  init_cli_invocation();
@@ -85,7 +94,7 @@ async function runStatus(global) {
85
94
  const root3 = path46.resolve(global.cwd ?? ".");
86
95
  const graphPath = resolveGraphPath(root3, global.graph);
87
96
  const graph = loadGraph(root3, graphPath);
88
- const hasCache = fs14.existsSync(path46.join(cacheDir(root3), "parse-cache.json"));
97
+ const hasCache = fs13.existsSync(path46.join(cacheDir(root3), "parse-cache.json"));
89
98
  let stale = null;
90
99
  let staleExact = false;
91
100
  if (graph) {
@@ -158,6 +167,21 @@ function registerAsk(program) {
158
167
  }
159
168
  }
160
169
  const { graph } = requireGraph(global);
170
+ const activity = new ActivityLog();
171
+ const live = !global.json ? new LiveStatus() : null;
172
+ live?.start("attaching to vgd\u2026");
173
+ const attached = await activity.time(
174
+ "attach",
175
+ () => attachVgd(root3, {
176
+ graphPath: global.graph,
177
+ disabled: global.daemon === false,
178
+ // Skip the republish when the daemon already holds this exact map:
179
+ // a publish drops the slot's vectors, so doing it on every ask
180
+ // churned the index for nothing.
181
+ corpusHash: graph.provenance?.corpusHash
182
+ }),
183
+ (a) => describeAttach(a)
184
+ );
161
185
  const budget = Number(opts.budget) || 2e3;
162
186
  const q = question.join(" ");
163
187
  const wantSemantic = opts.semantic !== false && !global.local;
@@ -166,34 +190,64 @@ function registerAsk(program) {
166
190
  let note = "";
167
191
  const relevance = await analyzeQuestion(q);
168
192
  const topicTags = relevance ? await loadTopicTags(graph, root3, resolveGraphPath(root3, global.graph)) : null;
169
- if (wantSemantic) {
170
- const firstRun = !embeddingsCached(root3, resolveEmbedModel());
171
- if (!global.json && firstRun) {
172
- info(c.dim(" preparing semantic search (first use embeds the map; cached, resumable & offline after)\u2026"));
173
- }
174
- let reason;
175
- let detail;
176
- const embedder = await loadEmbedder({
177
- local: global.local,
178
- onUnavailable: (r, d) => {
179
- reason = r;
180
- detail = d;
193
+ try {
194
+ if (wantSemantic) {
195
+ live?.set("asking the daemon\u2026");
196
+ const ranked = attached.status === "attached" && attached.repositoryId ? await activity.time(
197
+ "semantic",
198
+ // The attach above already resolved (and, if needed, published)
199
+ // the slot — this session only sends the question.
200
+ () => new DaemonSemanticSession(root3, { socketPath: attached.socketPath, publish: false }).rank(q, void 0, {
201
+ onProgress: (p) => live?.set(p.detail)
202
+ }),
203
+ (r) => r ? { outcome: "ok", detail: `ranked in the daemon \xB7 ${r.ranked.length} of ${r.vectors} vector(s)${r.model ? ` \xB7 ${r.model}` : ""}` } : { outcome: "skip", detail: "daemon index unavailable \u2014 embedding in this process" }
204
+ ) : null;
205
+ if (ranked) {
206
+ live?.set("answering from the daemon index\u2026");
207
+ result = await queryGraphSemantic(graph, q, {
208
+ budget,
209
+ semanticRanked: ranked.ranked,
210
+ relevance,
211
+ topicTags
212
+ });
213
+ mode = `semantic (vgd${ranked.model ? `, ${ranked.model}` : ""})`;
214
+ activity.add("answer", "ok", "answered from the daemon index \u2014 no local model load");
215
+ } else {
216
+ const firstRun = !embeddingsCached(root3, resolveEmbedModel());
217
+ live?.set(
218
+ firstRun ? "loading the embedding model (first use; then cached and offline)\u2026" : "embedding the map in this process\u2026"
219
+ );
220
+ let reason;
221
+ let detail;
222
+ const embedder = await loadEmbedder({
223
+ local: global.local,
224
+ onUnavailable: (r, d) => {
225
+ reason = r;
226
+ detail = d;
227
+ }
228
+ });
229
+ if (embedder) {
230
+ live?.stop();
231
+ const bar = !global.json ? new ProgressBar(c.dim("embedding")) : void 0;
232
+ const vectors = await getNodeEmbeddings(graph, embedder, root3, bar ? (d, t) => bar.update(d, t) : void 0);
233
+ bar?.done();
234
+ result = await queryGraphSemantic(graph, q, { budget, embedder, nodeVectors: vectors, relevance, topicTags });
235
+ mode = `semantic (${embedder.id})`;
236
+ activity.add("answer", "ok", `answered in this process \xB7 ${embedder.id} \xB7 ${vectors.size} vector(s)`);
237
+ } else {
238
+ result = queryGraph(graph, q, { budget, relevance, topicTags });
239
+ note = reason ? unavailableMessage(reason) : "semantic unavailable; used lexical";
240
+ if (detail) note += ` (${detail})`;
241
+ activity.add("answer", "warn", `lexical only \u2014 ${note}`);
242
+ }
181
243
  }
182
- });
183
- if (embedder) {
184
- const bar = !global.json && firstRun ? new ProgressBar(c.dim("embedding")) : void 0;
185
- const vectors = await getNodeEmbeddings(graph, embedder, root3, bar ? (d, t) => bar.update(d, t) : void 0);
186
- bar?.done();
187
- result = await queryGraphSemantic(graph, q, { budget, embedder, nodeVectors: vectors, relevance, topicTags });
188
- mode = `semantic (${embedder.id})`;
189
244
  } else {
190
245
  result = queryGraph(graph, q, { budget, relevance, topicTags });
191
- note = reason ? unavailableMessage(reason) : "semantic unavailable; used lexical";
192
- if (detail) note += ` (${detail})`;
246
+ if (global.local) note = "semantic skipped under --local; used lexical";
247
+ activity.add("answer", "skip", global.local ? "lexical only (--local)" : "lexical only (--no-semantic)");
193
248
  }
194
- } else {
195
- result = queryGraph(graph, q, { budget, relevance, topicTags });
196
- if (global.local) note = "semantic skipped under --local; used lexical";
249
+ } finally {
250
+ live?.stop();
197
251
  }
198
252
  if (global.client) {
199
253
  const files = new Set(result.matches.map((m) => m.node.file).filter(Boolean));
@@ -214,6 +268,7 @@ function registerAsk(program) {
214
268
  question: result.question,
215
269
  mode,
216
270
  note: note || void 0,
271
+ activity: activity.toJSON(),
217
272
  tokensEstimate: result.tokensEstimate,
218
273
  matches: result.matches.map((m) => ({
219
274
  name: m.node.qualifiedName,
@@ -231,9 +286,25 @@ function registerAsk(program) {
231
286
  info("");
232
287
  info(c.dim(`vg \xB7 ${result.matches.length} match(es) \xB7 ~${result.tokensEstimate} tokens (budget ${budget}) \xB7 ${mode}`));
233
288
  if (note) info(c.yellow(` ${note}`));
289
+ for (const line of activity.render()) info(line);
234
290
  });
235
291
  applyGlobalOptions(cmd);
236
292
  }
293
+ function describeAttach(a) {
294
+ if (a.status === "disabled") return { outcome: "skip", detail: `${a.reason} \u2014 running in this process` };
295
+ if (a.status === "unavailable") return { outcome: "skip", detail: `${a.reason} \u2014 running in this process` };
296
+ const started = a.started ? "started vgd" : "attached to vgd";
297
+ if (a.published?.status === "current") {
298
+ return { outcome: "ok", detail: `${started} \xB7 already holds this map (${a.published.gitRef})` };
299
+ }
300
+ if (a.published?.status === "published") {
301
+ return { outcome: "ok", detail: `${started} \xB7 map published ${a.published.gitRef} \xB7 ${a.published.nodeCount} nodes` };
302
+ }
303
+ if (a.published?.status === "failed") {
304
+ return { outcome: "warn", detail: `${started} \xB7 map not published (${a.published.error})` };
305
+ }
306
+ return { outcome: "ok", detail: started };
307
+ }
237
308
  function crashedMessage(signal) {
238
309
  const envPrefix = process.platform === "linux" ? "ONNXRUNTIME_NODE_INSTALL=skip " : "";
239
310
  return `semantic search is disabled: its native backend (onnxruntime-node, via the vendored fastembed path) crashed with ${signal} \u2014 using fast lexical search instead. This usually means the installed native binaries are broken (an interrupted install, or a platform without prebuilt CPU binaries). Reinstall to repair \u2014 ${envPrefix}npm install -g --allow-scripts=@vibgrate/cli,onnxruntime-node,msgpackr-extract @vibgrate/cli \u2014 or run with --local to stay lexical quietly.`;
@@ -247,7 +318,7 @@ function verdictPath(dir) {
247
318
  }
248
319
  function readVerdict(dir) {
249
320
  try {
250
- const raw = JSON.parse(fs14.readFileSync(verdictPath(dir), "utf8"));
321
+ const raw = JSON.parse(fs13.readFileSync(verdictPath(dir), "utf8"));
251
322
  if (raw?.status !== "ok" && raw?.status !== "crashed") return null;
252
323
  if (raw.version !== VERSION) return null;
253
324
  return raw;
@@ -257,8 +328,8 @@ function readVerdict(dir) {
257
328
  }
258
329
  function writeVerdict(dir, verdict) {
259
330
  try {
260
- fs14.mkdirSync(dir, { recursive: true });
261
- fs14.writeFileSync(verdictPath(dir), JSON.stringify(verdict, null, 2) + "\n", "utf8");
331
+ fs13.mkdirSync(dir, { recursive: true });
332
+ fs13.writeFileSync(verdictPath(dir), JSON.stringify(verdict, null, 2) + "\n", "utf8");
262
333
  } catch {
263
334
  }
264
335
  }
@@ -266,7 +337,7 @@ function probeModuleUrl(from = import.meta.url) {
266
337
  const dir = path46.dirname(fileURLToPath(from));
267
338
  for (const name of ["embeddings.js", "index.js"]) {
268
339
  const candidate = path46.join(dir, name);
269
- if (fs14.existsSync(candidate)) return pathToFileURL(candidate).href;
340
+ if (fs13.existsSync(candidate)) return pathToFileURL(candidate).href;
270
341
  }
271
342
  return pathToFileURL(path46.join(dir, "index.js")).href;
272
343
  }
@@ -343,7 +414,7 @@ async function embedderHealth(options = {}) {
343
414
  }
344
415
  function clearEmbedderHealth(cacheDir2) {
345
416
  try {
346
- fs14.unlinkSync(verdictPath(cacheDir2 ?? defaultCacheDir()));
417
+ fs13.unlinkSync(verdictPath(cacheDir2 ?? defaultCacheDir()));
347
418
  } catch {
348
419
  }
349
420
  }
@@ -370,6 +441,7 @@ function registerEmbed(program) {
370
441
  return;
371
442
  }
372
443
  if (countPending(graph, root3, modelId) === 0) {
444
+ await warmDaemonIndex(root3, global.graph);
373
445
  if (global.json) json({ embedded: 0, pending: 0, upToDate: true, model: modelId, semantic: true });
374
446
  else if (speak) info(`${c.cyan("vg embed")} \xB7 semantic index already up to date`);
375
447
  return;
@@ -406,11 +478,15 @@ function registerEmbed(program) {
406
478
  const bar = speak ? new ProgressBar(c.dim("embedding")) : void 0;
407
479
  await getNodeEmbeddings(graph, embedder, root3, bar ? (d, t) => bar.update(d, t) : void 0);
408
480
  bar?.done();
481
+ await warmDaemonIndex(root3, global.graph);
409
482
  if (global.json) json({ embedded: pending, model: modelId, semantic: true });
410
483
  else if (speak) info(`${c.green("\u2714")} vg embed \xB7 semantic index ready (~${pending} node(s) \xB7 model ${modelId})`);
411
484
  });
412
485
  applyGlobalOptions(cmd);
413
486
  }
487
+ async function warmDaemonIndex(root3, graphPath) {
488
+ await publishGraphToVgd(root3, { graphPath, warmSemantic: true });
489
+ }
414
490
  function showWhere(root3, modelId, asJson) {
415
491
  const m = modelCacheInfo(modelId);
416
492
  const repoCached = embeddingsCached(root3, modelId);
@@ -1018,7 +1094,7 @@ function liveStatsDir(root3) {
1018
1094
  function reapOtherVersionServers(dir, keepVersion, now = Date.now(), kill = (pid, signal) => process.kill(pid, signal), selfPid = process.pid) {
1019
1095
  let entries;
1020
1096
  try {
1021
- entries = fs14.readdirSync(dir);
1097
+ entries = fs13.readdirSync(dir);
1022
1098
  } catch {
1023
1099
  return [];
1024
1100
  }
@@ -1027,7 +1103,7 @@ function reapOtherVersionServers(dir, keepVersion, now = Date.now(), kill = (pid
1027
1103
  if (!/^serve-\d+\.json$/.test(name)) continue;
1028
1104
  let parsed;
1029
1105
  try {
1030
- parsed = JSON.parse(fs14.readFileSync(path46.join(dir, name), "utf8"));
1106
+ parsed = JSON.parse(fs13.readFileSync(path46.join(dir, name), "utf8"));
1031
1107
  } catch {
1032
1108
  continue;
1033
1109
  }
@@ -1081,10 +1157,10 @@ var LiveStatsBus = class {
1081
1157
  this.lastWriteAt = now;
1082
1158
  const body = { pid: this.pid, updatedAt: now, version: VERSION, snapshot: snap };
1083
1159
  try {
1084
- fs14.mkdirSync(this.dir, { recursive: true });
1160
+ fs13.mkdirSync(this.dir, { recursive: true });
1085
1161
  const tmp = `${this.file}.tmp`;
1086
- fs14.writeFileSync(tmp, JSON.stringify(body));
1087
- fs14.renameSync(tmp, this.file);
1162
+ fs13.writeFileSync(tmp, JSON.stringify(body));
1163
+ fs13.renameSync(tmp, this.file);
1088
1164
  } catch {
1089
1165
  }
1090
1166
  }
@@ -1095,7 +1171,7 @@ var LiveStatsBus = class {
1095
1171
  siblings(now = Date.now()) {
1096
1172
  let entries;
1097
1173
  try {
1098
- entries = fs14.readdirSync(this.dir);
1174
+ entries = fs13.readdirSync(this.dir);
1099
1175
  } catch {
1100
1176
  return [];
1101
1177
  }
@@ -1105,14 +1181,14 @@ var LiveStatsBus = class {
1105
1181
  const file = path46.join(this.dir, name);
1106
1182
  let parsed;
1107
1183
  try {
1108
- parsed = JSON.parse(fs14.readFileSync(file, "utf8"));
1184
+ parsed = JSON.parse(fs13.readFileSync(file, "utf8"));
1109
1185
  } catch {
1110
1186
  continue;
1111
1187
  }
1112
1188
  if (typeof parsed?.pid !== "number" || typeof parsed.updatedAt !== "number" || !parsed.snapshot?.totals) continue;
1113
1189
  if (now - parsed.updatedAt > STALE_MS) {
1114
1190
  try {
1115
- fs14.unlinkSync(file);
1191
+ fs13.unlinkSync(file);
1116
1192
  } catch {
1117
1193
  }
1118
1194
  continue;
@@ -1124,7 +1200,7 @@ var LiveStatsBus = class {
1124
1200
  }
1125
1201
  unlinkOwn = () => {
1126
1202
  try {
1127
- fs14.unlinkSync(this.file);
1203
+ fs13.unlinkSync(this.file);
1128
1204
  } catch {
1129
1205
  }
1130
1206
  };
@@ -1437,12 +1513,12 @@ var LedgerTail = class {
1437
1513
  if (size === this.offset) return;
1438
1514
  let chunk;
1439
1515
  try {
1440
- const fd = fs14.openSync(this.file, "r");
1516
+ const fd = fs13.openSync(this.file, "r");
1441
1517
  try {
1442
1518
  chunk = Buffer.alloc(size - this.offset);
1443
- fs14.readSync(fd, chunk, 0, chunk.length, this.offset);
1519
+ fs13.readSync(fd, chunk, 0, chunk.length, this.offset);
1444
1520
  } finally {
1445
- fs14.closeSync(fd);
1521
+ fs13.closeSync(fd);
1446
1522
  }
1447
1523
  } catch {
1448
1524
  return;
@@ -1455,7 +1531,7 @@ var LedgerTail = class {
1455
1531
  }
1456
1532
  sizeOf() {
1457
1533
  try {
1458
- return fs14.statSync(this.file).size;
1534
+ return fs13.statSync(this.file).size;
1459
1535
  } catch {
1460
1536
  return 0;
1461
1537
  }
@@ -1511,6 +1587,7 @@ function registerServe(program) {
1511
1587
  dedup: opts.dedup === true,
1512
1588
  refresh,
1513
1589
  watch: opts.watch !== false,
1590
+ daemon: global.daemon,
1514
1591
  root: root3,
1515
1592
  stats,
1516
1593
  // Listing surface: flags win over env; unknown values fall back to the
@@ -1745,171 +1822,26 @@ var Connection = class {
1745
1822
  }
1746
1823
  }
1747
1824
  };
1748
-
1749
- // src/lsp/manifest-positions.ts
1750
- function manifestKind(filePath) {
1751
- const base = (filePath.split(/[\\/]/).pop() ?? "").toLowerCase();
1752
- if (base === "package.json") return "package.json";
1753
- if (base === "go.mod") return "go.mod";
1754
- if (base === "requirements.txt" || /^requirements.*\.txt$/.test(base)) return "requirements.txt";
1755
- if (base === "pyproject.toml") return "pyproject.toml";
1756
- if (base === "cargo.toml") return "Cargo.toml";
1757
- if (base === "pom.xml") return "pom.xml";
1758
- if (base === "build.gradle" || base === "build.gradle.kts") return "build.gradle";
1759
- if (base === "gemfile") return "Gemfile";
1760
- if (base === "composer.json") return "composer.json";
1761
- if (base === "pubspec.yaml") return "pubspec.yaml";
1762
- if (base === "mix.exs") return "mix.exs";
1763
- if (base.endsWith(".csproj") || base.endsWith(".fsproj") || base.endsWith(".vbproj")) return "csproj";
1764
- if (base === "dockerfile" || base.startsWith("dockerfile.")) return "Dockerfile";
1765
- return "unknown";
1825
+ function projectDir(root3, projectPath) {
1826
+ const rel = projectPath === "" || projectPath === "." ? "" : projectPath;
1827
+ return rel ? path46.resolve(root3, rel) : path46.resolve(root3);
1766
1828
  }
1767
- function isManifest(filePath) {
1768
- return manifestKind(filePath) !== "unknown";
1769
- }
1770
- function esc(s) {
1771
- return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1772
- }
1773
- function findPackageLine(text, pkg, kind) {
1774
- const lines = text.split(/\r?\n/);
1775
- const p = esc(pkg);
1776
- const patterns = (() => {
1777
- switch (kind) {
1778
- case "package.json":
1779
- case "composer.json":
1780
- return [new RegExp(`^\\s*"${p}"\\s*:`)];
1781
- case "go.mod":
1782
- return [new RegExp(`^\\s*(?:require\\s+)?${p}\\s+v?\\d`)];
1783
- case "requirements.txt":
1784
- return [new RegExp(`^\\s*${p}\\s*(?:\\[[^\\]]*\\])?\\s*(?:[=<>!~]|$)`, "i")];
1785
- case "pyproject.toml":
1786
- case "Cargo.toml":
1787
- return [
1788
- new RegExp(`^\\s*${p}\\s*=`),
1789
- new RegExp(`^\\s*"${p}\\s*(?:[=<>!~\\[]|")`)
1790
- ];
1791
- case "pom.xml":
1792
- return [new RegExp(`<artifactId>\\s*${p}\\s*</artifactId>`)];
1793
- case "build.gradle":
1794
- return [new RegExp(`["']${p}(?:["':])`)];
1795
- case "Gemfile":
1796
- return [new RegExp(`^\\s*gem\\s+["']${p}["']`)];
1797
- case "pubspec.yaml":
1798
- return [new RegExp(`^\\s*${p}\\s*:`)];
1799
- case "mix.exs":
1800
- return [new RegExp(`\\{\\s*:${p}\\s*,`)];
1801
- case "csproj":
1802
- return [new RegExp(`Include\\s*=\\s*"${p}"`, "i")];
1803
- case "Dockerfile":
1804
- return [new RegExp(`^\\s*FROM\\s+.*${p}`, "i")];
1805
- default:
1806
- return [];
1807
- }
1808
- })();
1809
- for (const re of patterns) {
1810
- for (let i = 0; i < lines.length; i++) {
1811
- if (re.test(lines[i])) return i;
1812
- }
1813
- }
1814
- return -1;
1815
- }
1816
- function findRuntimeLine(text, kind) {
1817
- const lines = text.split(/\r?\n/);
1818
- const patterns = (() => {
1819
- switch (kind) {
1820
- case "package.json":
1821
- return [/^\s*"node"\s*:/, /^\s*"engines"\s*:/];
1822
- case "go.mod":
1823
- return [/^\s*go\s+\d/];
1824
- case "pyproject.toml":
1825
- return [/^\s*(?:requires-python|python)\s*=/];
1826
- case "pom.xml":
1827
- return [/<(?:java\.version|maven\.compiler\.(?:source|target|release))>/];
1828
- case "build.gradle":
1829
- return [/(?:sourceCompatibility|targetCompatibility|JavaVersion)/];
1830
- case "csproj":
1831
- return [/<TargetFrameworks?>/i];
1832
- case "Dockerfile":
1833
- return [/^\s*FROM\s+/i];
1834
- default:
1835
- return [];
1836
- }
1837
- })();
1838
- for (const re of patterns) {
1839
- for (let i = 0; i < lines.length; i++) {
1840
- if (re.test(lines[i])) return i;
1841
- }
1829
+ function projectForFile(root3, projects, filePath) {
1830
+ const dir = path46.dirname(path46.resolve(filePath));
1831
+ for (const proj of projects) {
1832
+ if (projectDir(root3, proj.path) === dir) return proj;
1842
1833
  }
1843
- return -1;
1844
- }
1845
- function endOfLine(text, line) {
1846
- const lines = text.split(/\r?\n/);
1847
- return (lines[line] ?? "").length;
1848
- }
1849
- var CACHE_VERSION = "vg-lsp-scan-cache/2";
1850
- function cachePath(root3) {
1851
- return path46.join(cacheDir(root3), "lsp-scan.json");
1852
- }
1853
- function manifestHash(root3) {
1854
- const files = [];
1855
- const walk2 = (dir) => {
1856
- let entries;
1857
- try {
1858
- entries = fs14.readdirSync(dir, { withFileTypes: true });
1859
- } catch {
1860
- return;
1861
- }
1862
- for (const entry of entries) {
1863
- const abs = path46.join(dir, entry.name);
1864
- if (entry.isDirectory()) {
1865
- if (isSkippedDirName(entry.name)) continue;
1866
- walk2(abs);
1867
- continue;
1868
- }
1869
- if (!entry.isFile()) continue;
1870
- const base = entry.name.toLowerCase();
1871
- if (!isManifest(abs) && !SKIP_FILES.has(base)) continue;
1872
- try {
1873
- const rel = path46.relative(root3, abs).split(path46.sep).join("/");
1874
- files.push({ rel, hash: hashBytes(fs14.readFileSync(abs)) });
1875
- } catch {
1876
- }
1877
- }
1878
- };
1879
- walk2(root3);
1880
- files.sort((a, b) => a.rel < b.rel ? -1 : a.rel > b.rel ? 1 : 0);
1881
- return hashString(canonicalize(files));
1882
- }
1883
- function isDependencyFile(root3, filePath) {
1884
- const rel = path46.relative(path46.resolve(root3), path46.resolve(filePath));
1885
- if (rel === "" || rel.startsWith("..") || path46.isAbsolute(rel)) return false;
1886
- const parts = rel.split(path46.sep);
1887
- if (parts.slice(0, -1).some((dir) => isSkippedDirName(dir))) return false;
1888
- const base = parts[parts.length - 1].toLowerCase();
1889
- return isManifest(filePath) || SKIP_FILES.has(base);
1890
- }
1891
- function loadScanCache(root3, key2) {
1892
- try {
1893
- const raw = JSON.parse(fs14.readFileSync(cachePath(root3), "utf8"));
1894
- if (raw.version === CACHE_VERSION && raw.manifestHash === key2.manifestHash && raw.toolVersion === key2.toolVersion && raw.offline === key2.offline && raw.artifact) {
1895
- return { manifestHash: raw.manifestHash, artifact: raw.artifact };
1834
+ if (isManifest(filePath)) return void 0;
1835
+ let best;
1836
+ let bestLen = -1;
1837
+ for (const proj of projects) {
1838
+ const projDir = projectDir(root3, proj.path);
1839
+ if ((dir === projDir || dir.startsWith(projDir + path46.sep)) && projDir.length > bestLen) {
1840
+ best = proj;
1841
+ bestLen = projDir.length;
1896
1842
  }
1897
- } catch {
1898
- }
1899
- return null;
1900
- }
1901
- function writeScanCache(root3, key2, artifact) {
1902
- try {
1903
- fs14.mkdirSync(cacheDir(root3), { recursive: true });
1904
- fs14.writeFileSync(
1905
- cachePath(root3),
1906
- stableStringify(
1907
- { version: CACHE_VERSION, manifestHash: key2.manifestHash, toolVersion: key2.toolVersion, offline: key2.offline, artifact },
1908
- 0
1909
- )
1910
- );
1911
- } catch {
1912
1843
  }
1844
+ return best;
1913
1845
  }
1914
1846
  var MAX_ENTRIES = 1e3;
1915
1847
  var KEEP_ENTRIES = 500;
@@ -1928,7 +1860,7 @@ function parseLine(line) {
1928
1860
  }
1929
1861
  function readHistory(root3) {
1930
1862
  try {
1931
- return fs14.readFileSync(historyPath(root3), "utf8").split("\n").filter((l) => l.trim()).map(parseLine).filter((e) => e !== null);
1863
+ return fs13.readFileSync(historyPath(root3), "utf8").split("\n").filter((l) => l.trim()).map(parseLine).filter((e) => e !== null);
1932
1864
  } catch {
1933
1865
  return [];
1934
1866
  }
@@ -1955,14 +1887,14 @@ function recordScore(root3, entry) {
1955
1887
  }
1956
1888
  }
1957
1889
  const file = historyPath(root3);
1958
- fs14.mkdirSync(path46.dirname(file), { recursive: true });
1890
+ fs13.mkdirSync(path46.dirname(file), { recursive: true });
1959
1891
  ensureVibgrateGitignore(root3);
1960
- fs14.appendFileSync(file, `${JSON.stringify(entry)}
1892
+ fs13.appendFileSync(file, `${JSON.stringify(entry)}
1961
1893
  `);
1962
1894
  const all = readHistory(root3);
1963
1895
  if (all.length > MAX_ENTRIES) {
1964
1896
  const kept = all.slice(-KEEP_ENTRIES);
1965
- fs14.writeFileSync(file, kept.map((e) => JSON.stringify(e)).join("\n") + "\n");
1897
+ fs13.writeFileSync(file, kept.map((e) => JSON.stringify(e)).join("\n") + "\n");
1966
1898
  }
1967
1899
  } catch {
1968
1900
  }
@@ -1985,7 +1917,7 @@ function readIgnores(root3, now = Date.now()) {
1985
1917
  const out2 = /* @__PURE__ */ new Map();
1986
1918
  let raw;
1987
1919
  try {
1988
- raw = fs14.readFileSync(ignoreFilePath(root3), "utf8");
1920
+ raw = fs13.readFileSync(ignoreFilePath(root3), "utf8");
1989
1921
  } catch {
1990
1922
  return out2;
1991
1923
  }
@@ -2012,7 +1944,7 @@ function inventoryKey(projectPath, pkg) {
2012
1944
  }
2013
1945
  function readInventory(root3) {
2014
1946
  try {
2015
- const parsed = JSON.parse(fs14.readFileSync(inventoryPath(root3), "utf8"));
1947
+ const parsed = JSON.parse(fs13.readFileSync(inventoryPath(root3), "utf8"));
2016
1948
  if (typeof parsed.ts === "string" && typeof parsed.methodology === "string" && Array.isArray(parsed.drifted) && parsed.drifted.every((d) => typeof d === "string")) {
2017
1949
  return parsed;
2018
1950
  }
@@ -2023,7 +1955,7 @@ function readInventory(root3) {
2023
1955
  function recordInventory(root3, snap) {
2024
1956
  try {
2025
1957
  ensureVibgrateGitignore(root3);
2026
- fs14.writeFileSync(inventoryPath(root3), `${JSON.stringify(snap)}
1958
+ fs13.writeFileSync(inventoryPath(root3), `${JSON.stringify(snap)}
2027
1959
  `);
2028
1960
  } catch {
2029
1961
  }
@@ -2075,7 +2007,23 @@ async function runAsk(graph, params, ctx) {
2075
2007
  let result = null;
2076
2008
  let mode = "lexical";
2077
2009
  let note;
2078
- if (wantSemantic) {
2010
+ if (wantSemantic && ctx.semanticSession) {
2011
+ try {
2012
+ const ranked = await withTimeout(
2013
+ ctx.semanticSession.rank(question, graph.provenance?.corpusHash),
2014
+ semanticBudgetMs(),
2015
+ "daemon ranking over budget"
2016
+ );
2017
+ if (ranked) {
2018
+ log(`ask: ranked by vgd against ${ranked.vectors} vector(s) \u2014 no local model load`);
2019
+ result = await queryGraphSemantic(graph, question, { budget, semanticRanked: ranked.ranked });
2020
+ mode = `semantic (vgd${ranked.model ? `, ${ranked.model}` : ""})`;
2021
+ }
2022
+ } catch {
2023
+ log("ask: vgd ranking unavailable \u2014 trying the in-process semantic path");
2024
+ }
2025
+ }
2026
+ if (wantSemantic && !result) {
2079
2027
  const budgetMs = semanticBudgetMs();
2080
2028
  log(`ask: trying the semantic path (budget ${Math.round(budgetMs / 1e3)}s)`);
2081
2029
  let reason;
@@ -2556,7 +2504,11 @@ function architectureWire(arch) {
2556
2504
  if (arch.workspaceEdgesCapped) out2.workspaceEdgesCapped = true;
2557
2505
  if (arch.violations) out2.violations = arch.violations;
2558
2506
  if (arch.violationsCapped) out2.violationsCapped = true;
2559
- if (arch.boundaryProfile) out2.boundaryProfile = arch.boundaryProfile;
2507
+ if (arch.boundaryProfile) {
2508
+ out2.boundaryProfile = arch.boundaryProfile;
2509
+ const rules = boundaryProfileRules(arch.boundaryProfile);
2510
+ if (rules.length > 0) out2.boundaryRules = rules;
2511
+ }
2560
2512
  if (arch.structure) out2.structure = arch.structure;
2561
2513
  if (arch.generated) out2.generated = true;
2562
2514
  if (arch.generatedBy) out2.generatedBy = arch.generatedBy;
@@ -2586,6 +2538,7 @@ var VibgrateLanguageServer = class {
2586
2538
  constructor(opts, output = process.stdout) {
2587
2539
  this.opts = opts;
2588
2540
  this.conn = new Connection(process.stdin, output);
2541
+ this.semanticSession = new DaemonSemanticSession(opts.root, { disabled: opts.daemon === false });
2589
2542
  this.refresher = new RefreshScheduler({
2590
2543
  root: opts.root,
2591
2544
  graphPath: () => resolveGraphPath(opts.root),
@@ -2623,6 +2576,32 @@ var VibgrateLanguageServer = class {
2623
2576
  * single Ask block for over a minute. See engine/refresh-scheduler.ts.
2624
2577
  */
2625
2578
  refresher;
2579
+ /**
2580
+ * Open while the daemon is pushing map changes for this workspace. Closing
2581
+ * it (or losing it) puts this server back in charge of its own freshness.
2582
+ */
2583
+ slotSubscription = null;
2584
+ /**
2585
+ * True only while the daemon is confirmed to hold *this* map and to be
2586
+ * pushing changes for it. While set, `graphForQuery` stops probing: the
2587
+ * daemon already watches the tree and rebuilds, and two processes doing it
2588
+ * means two stat-walks over one corpus and two rebuilds racing for one lock.
2589
+ *
2590
+ * Never assumed — see `deferFreshnessToDaemon`. A daemon that dies degrades
2591
+ * this server to watching for itself, never to nothing watching.
2592
+ */
2593
+ daemonOwnsFreshness = false;
2594
+ /**
2595
+ * The local runtime's semantic index, held for the life of the server.
2596
+ * Ranking there means the native embedding backend is never loaded into this
2597
+ * process — the failure this server has the least tolerance for, since a
2598
+ * SIGTRAP from the addon kills it outright mid-request.
2599
+ */
2600
+ semanticSession;
2601
+ /** In-flight on-demand scans of open manifests the workspace scan skipped. */
2602
+ openManifestScans = /* @__PURE__ */ new Set();
2603
+ /** Failed on-demand scans — retry only after the next workspace scan. */
2604
+ openManifestFailed = /* @__PURE__ */ new Set();
2626
2605
  register() {
2627
2606
  this.conn.onRequest("initialize", () => ({
2628
2607
  capabilities: {
@@ -2680,6 +2659,7 @@ var VibgrateLanguageServer = class {
2680
2659
  this.conn.onRequest("vibgrate/score/forFile", (_m, params) => this.onScoreForFile(params));
2681
2660
  this.conn.onRequest("vibgrate/score/forProject", (_m, params) => this.onScoreForProject(params));
2682
2661
  this.conn.onRequest("vibgrate/architecture", (_m, params) => this.onArchitecture(params));
2662
+ this.conn.onRequest("vibgrate/architecture/projects", () => this.onArchitectureProjects());
2683
2663
  this.conn.onRequest("vibgrate/score/history", (_m, params) => {
2684
2664
  const p = params;
2685
2665
  const days = typeof p?.days === "number" && p.days > 0 && p.days <= 365 ? p.days : 90;
@@ -2698,6 +2678,9 @@ var VibgrateLanguageServer = class {
2698
2678
  this.conn.onRequest("shutdown", () => {
2699
2679
  this.shuttingDown = true;
2700
2680
  if (this.debounce) clearTimeout(this.debounce);
2681
+ this.slotSubscription?.close();
2682
+ this.slotSubscription = null;
2683
+ this.daemonOwnsFreshness = false;
2701
2684
  return null;
2702
2685
  });
2703
2686
  this.conn.onNotification("exit", () => {
@@ -2718,8 +2701,13 @@ var VibgrateLanguageServer = class {
2718
2701
  this.scanning = true;
2719
2702
  const force = this.forceNextScan;
2720
2703
  this.forceNextScan = false;
2704
+ this.openManifestFailed.clear();
2721
2705
  try {
2722
- const cacheKey = { manifestHash: manifestHash(this.opts.root), toolVersion: VERSION, offline: this.opts.offline };
2706
+ const cacheKey = {
2707
+ manifestHash: await this.sharedManifestHash() ?? manifestHash(this.opts.root),
2708
+ toolVersion: VERSION,
2709
+ offline: this.opts.offline
2710
+ };
2723
2711
  const cached2 = force ? null : loadScanCache(this.opts.root, cacheKey);
2724
2712
  let fromCache = false;
2725
2713
  if (cached2) {
@@ -2845,7 +2833,10 @@ var VibgrateLanguageServer = class {
2845
2833
  if (!a || text === void 0) return;
2846
2834
  const filePath = uriToPath(uri);
2847
2835
  const kind = manifestKind(filePath);
2848
- const project = projectForFile(this.opts.root, a, filePath);
2836
+ const project = projectForFile2(this.opts.root, a, filePath);
2837
+ if (!project && isManifest(filePath)) {
2838
+ void this.scanOpenManifest(uri, filePath);
2839
+ }
2849
2840
  const items = [];
2850
2841
  for (const dep of project?.dependencies ?? []) {
2851
2842
  if (dep.drift === "current" || dep.drift === "unknown") continue;
@@ -2890,6 +2881,58 @@ var VibgrateLanguageServer = class {
2890
2881
  });
2891
2882
  this.conn.notify("textDocument/publishDiagnostics", { uri, diagnostics });
2892
2883
  }
2884
+ /**
2885
+ * Workspace scan skipped this package (auto-exclude / timeout). Score it
2886
+ * alone so the open editor can show overlays; do not write the result into
2887
+ * the workspace scan cache (billing / repo score stay on the official scan).
2888
+ */
2889
+ async scanOpenManifest(uri, filePath) {
2890
+ const relDir = path46.relative(this.opts.root, path46.dirname(path46.resolve(filePath)));
2891
+ const key2 = relDir === "" ? "." : relDir;
2892
+ if (this.openManifestScans.has(key2) || this.openManifestFailed.has(key2)) return;
2893
+ if (key2 === "." || key2.startsWith("..")) return;
2894
+ this.openManifestScans.add(key2);
2895
+ try {
2896
+ this.conn.notify("window/logMessage", {
2897
+ type: 3,
2898
+ message: `Vibgrate: scoring open package ${key2} (not in the workspace scan) so editor overlays can render.`
2899
+ });
2900
+ const advanced = await loadAdvancedScanHook();
2901
+ const scanOpts = {
2902
+ format: "json",
2903
+ concurrency: 8,
2904
+ offline: this.opts.offline,
2905
+ noLocalArtifacts: true,
2906
+ noGraph: true,
2907
+ quiet: true,
2908
+ vibgrateVersion: VERSION
2909
+ };
2910
+ const sub = await runCoreScanSilently(path46.dirname(filePath), scanOpts, advanced);
2911
+ const proj = (sub.projects ?? []).find((p) => p.path === "." || p.path === "") ?? sub.projects?.[0];
2912
+ if (!proj || !this.artifact) {
2913
+ this.openManifestFailed.add(key2);
2914
+ return;
2915
+ }
2916
+ proj.path = key2;
2917
+ this.artifact.projects = [...(this.artifact.projects ?? []).filter((p) => p.path !== key2), proj];
2918
+ for (const f of sub.findings ?? []) {
2919
+ if (f.location === "." || f.location === "" || f.location === key2) {
2920
+ this.artifact.findings = [...(this.artifact.findings ?? []).filter((x) => !(x.ruleId === f.ruleId && x.location === key2)), { ...f, location: key2 }];
2921
+ }
2922
+ }
2923
+ this.publishScore();
2924
+ this.publishForDoc(uri);
2925
+ } catch (err) {
2926
+ this.openManifestFailed.add(key2);
2927
+ const message = err instanceof Error ? err.message : String(err);
2928
+ this.conn.notify("window/logMessage", {
2929
+ type: 3,
2930
+ message: `Vibgrate: could not score open package ${key2}: ${message}`
2931
+ });
2932
+ } finally {
2933
+ this.openManifestScans.delete(key2);
2934
+ }
2935
+ }
2893
2936
  // ── Requests ─────────────────────────────────────────────────────────────
2894
2937
  onHover(params) {
2895
2938
  const p = params;
@@ -2900,7 +2943,7 @@ var VibgrateLanguageServer = class {
2900
2943
  if (!uri || line === void 0 || !a || text === void 0) return null;
2901
2944
  const filePath = uriToPath(uri);
2902
2945
  const kind = manifestKind(filePath);
2903
- const project = projectForFile(this.opts.root, a, filePath);
2946
+ const project = projectForFile2(this.opts.root, a, filePath);
2904
2947
  const dep = (project?.dependencies ?? []).find(
2905
2948
  (d) => findPackageLine(text, d.package, kind) === line
2906
2949
  );
@@ -2923,18 +2966,31 @@ var VibgrateLanguageServer = class {
2923
2966
  const uri = p.textDocument?.uri;
2924
2967
  const a = this.artifact;
2925
2968
  if (!uri || !a || !this.docs.has(uri)) return [];
2926
- const behind = (a.projects ?? []).reduce(
2927
- (n, proj) => n + (proj.dependencies ?? []).filter(
2928
- (d) => d.drift === "major-behind" || d.drift === "minor-behind"
2929
- ).length,
2930
- 0
2931
- );
2969
+ const filePath = uriToPath(uri);
2970
+ const project = projectForFile2(this.opts.root, a, filePath);
2971
+ if (!project) {
2972
+ return [
2973
+ {
2974
+ range: { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } },
2975
+ command: {
2976
+ title: "Vibgrate \xB7 this package is not in the workspace scan",
2977
+ command: "vibgrate.openPanel",
2978
+ arguments: []
2979
+ }
2980
+ }
2981
+ ];
2982
+ }
2983
+ const behind = (project.dependencies ?? []).filter(
2984
+ (d) => d.drift === "major-behind" || d.drift === "minor-behind"
2985
+ ).length;
2932
2986
  const eol = (a.findings ?? []).filter(
2933
- (f) => f.ruleId === "vibgrate/runtime-eol" || f.ruleId === "vibgrate/eol"
2987
+ (f) => sameProject(f.location, project.path) && (f.ruleId === "vibgrate/runtime-eol" || f.ruleId === "vibgrate/eol")
2934
2988
  ).length;
2935
- const estimated = (a.drift.mode ?? (hasReleaseDates(a) ? "verified" : "estimated")) === "estimated";
2989
+ const estimated = (project.drift?.mode ?? a.drift.mode ?? (hasReleaseDates(a) ? "verified" : "estimated")) === "estimated";
2936
2990
  const mode = estimated ? "~" : "";
2937
- const title = `Vibgrate \xB7 drift ${mode}${a.drift.score} (${a.drift.riskLevel}) \xB7 ${behind} behind \xB7 ${eol} EOL`;
2991
+ const score = project.drift?.score ?? a.drift.score;
2992
+ const band = project.drift?.riskLevel ?? a.drift.riskLevel;
2993
+ const title = `Vibgrate \xB7 drift ${mode}${score} (${band}) \xB7 ${behind} behind \xB7 ${eol} EOL`;
2938
2994
  return [
2939
2995
  {
2940
2996
  range: { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } },
@@ -2963,6 +3019,7 @@ var VibgrateLanguageServer = class {
2963
3019
  this.fileRoles = fileRolesFromParseCache(this.opts.root);
2964
3020
  this.refineAndPublishArchitecture();
2965
3021
  this.conn.notify("vibgrate/graph/status", { state: "ready" });
3022
+ void this.deferFreshnessToDaemon();
2966
3023
  return;
2967
3024
  }
2968
3025
  this.conn.notify("vibgrate/graph/status", { state: "building" });
@@ -2973,6 +3030,7 @@ var VibgrateLanguageServer = class {
2973
3030
  this.fileRoles = result.fileRoles;
2974
3031
  this.refineAndPublishArchitecture();
2975
3032
  this.conn.notify("vibgrate/graph/status", { state: "ready" });
3033
+ void this.deferFreshnessToDaemon();
2976
3034
  } catch (err) {
2977
3035
  const message = err instanceof Error ? err.message : String(err);
2978
3036
  this.conn.notify("window/logMessage", { type: 3, message: `Vibgrate graph build failed: ${message}` });
@@ -2981,6 +3039,55 @@ var VibgrateLanguageServer = class {
2981
3039
  this.graphBuilding = false;
2982
3040
  }
2983
3041
  }
3042
+ /**
3043
+ * Hand freshness to the daemon, but only once it is actually holding this
3044
+ * map and pushing changes for it.
3045
+ *
3046
+ * The daemon watches a repository the moment it holds its slot — and not
3047
+ * before. Registration is not enough; this server has historically been one
3048
+ * of the roots vgd knew about but never had a map for. So the order matters:
3049
+ * publish the map we just loaded or built, take the repository id the daemon
3050
+ * answers with, and subscribe to *that* repository. Only a confirmed
3051
+ * subscription retires the local probe.
3052
+ *
3053
+ * Every failure mode lands on "keep watching for ourselves": no daemon, a
3054
+ * daemon that will not take the map, a subscription it does not confirm, or
3055
+ * a connection that later drops. None of them are errors — a machine with no
3056
+ * vgd is a supported configuration.
3057
+ */
3058
+ async deferFreshnessToDaemon() {
3059
+ if (this.opts.daemon === false || !this.opts.graph) return;
3060
+ if (this.daemonOwnsFreshness || this.slotSubscription || this.shuttingDown) return;
3061
+ try {
3062
+ const [{ publishGraphToVgd: publishGraphToVgd2 }, { subscribeToSlots }] = await Promise.all([
3063
+ import('./publish-7YHRTBRA.js'),
3064
+ import('./slot-subscription-25GOARW5.js')
3065
+ ]);
3066
+ const published = await publishGraphToVgd2(this.opts.root);
3067
+ if (published.status !== "published" && published.status !== "current") return;
3068
+ const { repositoryId } = published;
3069
+ const subscription = await subscribeToSlots({
3070
+ repositoryId,
3071
+ onChange: () => this.reloadGraphFromDisk(),
3072
+ onDetach: () => {
3073
+ this.daemonOwnsFreshness = false;
3074
+ this.slotSubscription = null;
3075
+ }
3076
+ });
3077
+ if (!subscription.active) return;
3078
+ if (this.shuttingDown) {
3079
+ subscription.close();
3080
+ return;
3081
+ }
3082
+ this.slotSubscription = subscription;
3083
+ this.daemonOwnsFreshness = true;
3084
+ this.conn.notify("window/logMessage", {
3085
+ type: 3,
3086
+ message: `Vibgrate graph: freshness deferred to the local runtime (${repositoryId}).`
3087
+ });
3088
+ } catch {
3089
+ }
3090
+ }
2984
3091
  /**
2985
3092
  * The graph for a query. The first call still builds the map (there is
2986
3093
  * nothing to answer from otherwise), but a *refresh* is only ever kicked off
@@ -2991,7 +3098,7 @@ var VibgrateLanguageServer = class {
2991
3098
  async graphForQuery() {
2992
3099
  await this.ensureGraph();
2993
3100
  if (!this.graph) return null;
2994
- await this.refresher.maybeRefresh();
3101
+ if (!this.daemonOwnsFreshness) await this.refresher.maybeRefresh();
2995
3102
  return this.graph;
2996
3103
  }
2997
3104
  /**
@@ -3001,13 +3108,20 @@ var VibgrateLanguageServer = class {
3001
3108
  */
3002
3109
  onRefreshSettled(outcome) {
3003
3110
  if (outcome?.status !== "refreshed" || !outcome.wrote) return;
3111
+ this.reloadGraphFromDisk();
3112
+ }
3113
+ /**
3114
+ * Re-read the map we already have on disk. Shared by the local refresher and
3115
+ * by the daemon's `slot-changed` push, which are the only two things that
3116
+ * ever rewrite it — and never both at once.
3117
+ */
3118
+ reloadGraphFromDisk() {
3004
3119
  const graphPath = resolveGraphPath(this.opts.root);
3005
3120
  const reloaded = loadGraphPreferIndex(this.opts.root, graphPath)?.graph ?? loadGraph(this.opts.root);
3006
- if (reloaded) {
3007
- this.graph = reloaded;
3008
- this.fileRoles = fileRolesFromParseCache(this.opts.root);
3009
- this.refineAndPublishArchitecture();
3010
- }
3121
+ if (!reloaded) return;
3122
+ this.graph = reloaded;
3123
+ this.fileRoles = fileRolesFromParseCache(this.opts.root);
3124
+ this.refineAndPublishArchitecture();
3011
3125
  }
3012
3126
  /**
3013
3127
  * Graph / AST-role refine can land after the first `publishScore()`. The
@@ -3040,9 +3154,23 @@ var VibgrateLanguageServer = class {
3040
3154
  root: this.opts.root,
3041
3155
  offline: this.opts.offline,
3042
3156
  semantic: this.opts.semantic,
3157
+ semanticSession: this.semanticSession,
3043
3158
  log: trace
3044
3159
  });
3045
3160
  }
3161
+ /**
3162
+ * The daemon's manifest digest for this workspace, or null when there is no
3163
+ * daemon (or it has not been told about this repo yet) — in which case the
3164
+ * caller computes it locally, exactly as before.
3165
+ */
3166
+ async sharedManifestHash() {
3167
+ try {
3168
+ const deps = await this.semanticSession.depContext();
3169
+ return deps?.manifestHash ?? null;
3170
+ } catch {
3171
+ return null;
3172
+ }
3173
+ }
3046
3174
  /**
3047
3175
  * `vibgrate/enrich` — lazy vulnerability enrichment for one expanded package,
3048
3176
  * straight from OSV.dev (never our API). Honours the server's offline flag.
@@ -3090,7 +3218,7 @@ var VibgrateLanguageServer = class {
3090
3218
  const absManifest = path46.resolve(this.opts.root, relManifest);
3091
3219
  let text = null;
3092
3220
  try {
3093
- if (fs14.existsSync(absManifest)) text = fs14.readFileSync(absManifest, "utf8");
3221
+ if (fs13.existsSync(absManifest)) text = fs13.readFileSync(absManifest, "utf8");
3094
3222
  } catch {
3095
3223
  text = null;
3096
3224
  }
@@ -3140,7 +3268,7 @@ var VibgrateLanguageServer = class {
3140
3268
  const p = params;
3141
3269
  const a = this.artifact;
3142
3270
  if (!a || !p.uri) return null;
3143
- const project = projectForFile(this.opts.root, a, uriToPath(p.uri));
3271
+ const project = projectForFile2(this.opts.root, a, uriToPath(p.uri));
3144
3272
  return project ? scoreForProject(this.opts.root, a, project) : null;
3145
3273
  }
3146
3274
  /**
@@ -3181,6 +3309,37 @@ var VibgrateLanguageServer = class {
3181
3309
  lockfilePath: lockfileRelativePath(this.opts.root, project)
3182
3310
  };
3183
3311
  }
3312
+ /**
3313
+ * `vibgrate/architecture/projects` — the workspace-scope Projects view.
3314
+ * One row per scanned project that produced architecture data, so a client
3315
+ * can render the whole portfolio without N round trips. Projects the
3316
+ * scanner never classified are omitted rather than shown as empty rows.
3317
+ */
3318
+ onArchitectureProjects() {
3319
+ const a = this.artifact;
3320
+ if (!a) return null;
3321
+ const rows = [];
3322
+ for (const project of a.projects ?? []) {
3323
+ const arch = project.architecture;
3324
+ if (!arch) continue;
3325
+ const row = {
3326
+ path: project.path,
3327
+ name: project.name,
3328
+ // `violations` absent means "no graph was available to check against",
3329
+ // which is not the same as "checked and clean" — keep them distinct.
3330
+ violations: arch.violations ? arch.violations.length : null,
3331
+ layerCount: arch.layers.filter((l) => l.fileCount > 0).length,
3332
+ fileCount: arch.totalClassified
3333
+ };
3334
+ if (arch.projectKind) row.projectKind = arch.projectKind;
3335
+ if (arch.artifactKind) row.artifactKind = arch.artifactKind;
3336
+ if (arch.structure) row.structure = arch.structure.primary;
3337
+ if (arch.supportLevel !== void 0) row.supportLevel = arch.supportLevel;
3338
+ if (arch.packIds && arch.packIds.length > 0) row.packIds = arch.packIds;
3339
+ rows.push(row);
3340
+ }
3341
+ return rows;
3342
+ }
3184
3343
  };
3185
3344
  function uriToPath(uri) {
3186
3345
  try {
@@ -3292,18 +3451,8 @@ function buildProjectRefs(rootDir, projects) {
3292
3451
  refs.sort((a, b) => a.path.localeCompare(b.path));
3293
3452
  return refs.length > 0 ? refs : void 0;
3294
3453
  }
3295
- function projectForFile(root3, a, filePath) {
3296
- const dir = path46.dirname(path46.resolve(filePath));
3297
- let best;
3298
- let bestLen = -1;
3299
- for (const proj of a.projects ?? []) {
3300
- const projDir = path46.resolve(root3, proj.path);
3301
- if ((dir === projDir || dir.startsWith(projDir + path46.sep)) && projDir.length > bestLen) {
3302
- best = proj;
3303
- bestLen = projDir.length;
3304
- }
3305
- }
3306
- return best;
3454
+ function projectForFile2(root3, a, filePath) {
3455
+ return projectForFile(root3, a.projects ?? [], filePath);
3307
3456
  }
3308
3457
  function sameProject(location, projectPath) {
3309
3458
  return path46.normalize(location) === path46.normalize(projectPath);
@@ -3379,7 +3528,7 @@ function buildBreakdown(rootDir, projects) {
3379
3528
  const absManifest = path46.resolve(rootDir, relManifest);
3380
3529
  let text = null;
3381
3530
  try {
3382
- if (fs14.existsSync(absManifest)) text = fs14.readFileSync(absManifest, "utf8");
3531
+ if (fs13.existsSync(absManifest)) text = fs13.readFileSync(absManifest, "utf8");
3383
3532
  } catch {
3384
3533
  text = null;
3385
3534
  }
@@ -3444,34 +3593,34 @@ function buildBreakdown(rootDir, projects) {
3444
3593
  }
3445
3594
  function manifestRelativePath(proj) {
3446
3595
  const base = proj.path === "." || proj.path === "" ? "" : proj.path;
3447
- const join36 = (name) => base ? path46.join(base, name) : name;
3596
+ const join35 = (name) => base ? path46.join(base, name) : name;
3448
3597
  switch (proj.type) {
3449
3598
  case "node":
3450
3599
  case "typescript":
3451
- return join36("package.json");
3600
+ return join35("package.json");
3452
3601
  case "python":
3453
- return join36("pyproject.toml");
3602
+ return join35("pyproject.toml");
3454
3603
  case "go":
3455
- return join36("go.mod");
3604
+ return join35("go.mod");
3456
3605
  case "rust":
3457
- return join36("Cargo.toml");
3606
+ return join35("Cargo.toml");
3458
3607
  case "ruby":
3459
- return join36("Gemfile");
3608
+ return join35("Gemfile");
3460
3609
  case "php":
3461
- return join36("composer.json");
3610
+ return join35("composer.json");
3462
3611
  case "java":
3463
3612
  case "kotlin":
3464
3613
  case "scala":
3465
3614
  case "groovy":
3466
- return join36("pom.xml");
3615
+ return join35("pom.xml");
3467
3616
  case "dotnet":
3468
- return join36(proj.name ? `${proj.name}.csproj` : "Directory.Build.props");
3617
+ return join35(proj.name ? `${proj.name}.csproj` : "Directory.Build.props");
3469
3618
  case "dart":
3470
- return join36("pubspec.yaml");
3619
+ return join35("pubspec.yaml");
3471
3620
  case "elixir":
3472
- return join36("mix.exs");
3621
+ return join35("mix.exs");
3473
3622
  default:
3474
- return join36("package.json");
3623
+ return join35("package.json");
3475
3624
  }
3476
3625
  }
3477
3626
  function lockfileRelativePath(rootDir, proj) {
@@ -3504,7 +3653,7 @@ function lockfileRelativePath(rootDir, proj) {
3504
3653
  for (const name of candidateNames) {
3505
3654
  const rel = dir ? path46.join(dir, name) : name;
3506
3655
  try {
3507
- if (fs14.existsSync(path46.join(rootDir, rel))) return rel;
3656
+ if (fs13.existsSync(path46.join(rootDir, rel))) return rel;
3508
3657
  } catch {
3509
3658
  }
3510
3659
  }
@@ -3576,9 +3725,9 @@ function lookupImportFiles(map, pkg) {
3576
3725
  function firstPackageMentionLine(root3, relFile, pkg) {
3577
3726
  try {
3578
3727
  const abs = path46.resolve(root3, relFile);
3579
- const stat2 = fs14.statSync(abs);
3728
+ const stat2 = fs13.statSync(abs);
3580
3729
  if (!stat2.isFile() || stat2.size > 256 * 1024) return null;
3581
- const text = fs14.readFileSync(abs, "utf8");
3730
+ const text = fs13.readFileSync(abs, "utf8");
3582
3731
  const tokens = [pkg];
3583
3732
  if (pkg.startsWith("@")) {
3584
3733
  const parts = pkg.split("/");
@@ -3774,7 +3923,7 @@ function hoverMarkdown(dep, contribution, state) {
3774
3923
  return lines.join("\n");
3775
3924
  }
3776
3925
  function startLanguageServer(opts) {
3777
- if (!fs14.existsSync(opts.root)) {
3926
+ if (!fs13.existsSync(opts.root)) {
3778
3927
  process.stderr.write(`vg lsp: root does not exist: ${opts.root}
3779
3928
  `);
3780
3929
  process.exit(1);
@@ -3809,7 +3958,8 @@ function registerLsp(program) {
3809
3958
  offline: global.local === true,
3810
3959
  diagnostics: opts.diagnostics === true,
3811
3960
  graph: opts.graph !== false,
3812
- semantic: opts.semantic !== false
3961
+ semantic: opts.semantic !== false,
3962
+ daemon: global.daemon
3813
3963
  });
3814
3964
  await new Promise(() => {
3815
3965
  });
@@ -3826,9 +3976,9 @@ function installClaudeHooks(root3, vgBin = "vg") {
3826
3976
  const file = path46.join(root3, ".claude", "settings.json");
3827
3977
  const rel = path46.join(".claude", "settings.json");
3828
3978
  let settings = {};
3829
- if (fs14.existsSync(file)) {
3979
+ if (fs13.existsSync(file)) {
3830
3980
  try {
3831
- const parsed = JSON.parse(fs14.readFileSync(file, "utf8"));
3981
+ const parsed = JSON.parse(fs13.readFileSync(file, "utf8"));
3832
3982
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
3833
3983
  return { file: rel, status: "skipped", note: "settings.json is not a JSON object \u2014 left untouched" };
3834
3984
  }
@@ -3867,10 +4017,10 @@ function installClaudeHooks(root3, vgBin = "vg") {
3867
4017
  function uninstallClaudeHooks(root3) {
3868
4018
  const file = path46.join(root3, ".claude", "settings.json");
3869
4019
  const rel = path46.join(".claude", "settings.json");
3870
- if (!fs14.existsSync(file)) return { file: rel, status: "unchanged" };
4020
+ if (!fs13.existsSync(file)) return { file: rel, status: "unchanged" };
3871
4021
  let settings;
3872
4022
  try {
3873
- settings = JSON.parse(fs14.readFileSync(file, "utf8"));
4023
+ settings = JSON.parse(fs13.readFileSync(file, "utf8"));
3874
4024
  } catch {
3875
4025
  return { file: rel, status: "skipped", note: "settings.json is not parseable JSON \u2014 left untouched" };
3876
4026
  }
@@ -3892,8 +4042,8 @@ function uninstallClaudeHooks(root3) {
3892
4042
  return { file: rel, status: "written" };
3893
4043
  }
3894
4044
  function writeSettings(file, settings) {
3895
- fs14.mkdirSync(path46.dirname(file), { recursive: true });
3896
- fs14.writeFileSync(file, `${JSON.stringify(settings, null, 2)}
4045
+ fs13.mkdirSync(path46.dirname(file), { recursive: true });
4046
+ fs13.writeFileSync(file, `${JSON.stringify(settings, null, 2)}
3897
4047
  `);
3898
4048
  }
3899
4049
 
@@ -4020,15 +4170,15 @@ function stateFile() {
4020
4170
  }
4021
4171
  function readConsent() {
4022
4172
  try {
4023
- return JSON.parse(fs14.readFileSync(stateFile(), "utf8"));
4173
+ return JSON.parse(fs13.readFileSync(stateFile(), "utf8"));
4024
4174
  } catch {
4025
4175
  return {};
4026
4176
  }
4027
4177
  }
4028
4178
  function writeConsent(state) {
4029
4179
  try {
4030
- fs14.mkdirSync(path46.dirname(stateFile()), { recursive: true });
4031
- fs14.writeFileSync(stateFile(), JSON.stringify(state));
4180
+ fs13.mkdirSync(path46.dirname(stateFile()), { recursive: true });
4181
+ fs13.writeFileSync(stateFile(), JSON.stringify(state));
4032
4182
  } catch {
4033
4183
  }
4034
4184
  }
@@ -4038,8 +4188,8 @@ function kernelDisabled() {
4038
4188
  }
4039
4189
  function moduleInstalledAt(dir) {
4040
4190
  try {
4041
- const meta = JSON.parse(fs14.readFileSync(path46.join(dir, ".module.json"), "utf8"));
4042
- if (fs14.existsSync(path46.join(dir, "index.js"))) {
4191
+ const meta = JSON.parse(fs13.readFileSync(path46.join(dir, ".module.json"), "utf8"));
4192
+ if (fs13.existsSync(path46.join(dir, "index.js"))) {
4043
4193
  return { installed: true, version: meta.version };
4044
4194
  }
4045
4195
  } catch {
@@ -4113,8 +4263,8 @@ async function installModule(mod, opts = {}) {
4113
4263
  verifyIntegrity(gz, dist.integrity, dist.shasum);
4114
4264
  const entries = untar(zlib.gunzipSync(gz));
4115
4265
  const dir = mod.dir();
4116
- fs14.rmSync(dir, { recursive: true, force: true });
4117
- fs14.mkdirSync(dir, { recursive: true });
4266
+ fs13.rmSync(dir, { recursive: true, force: true });
4267
+ fs13.mkdirSync(dir, { recursive: true });
4118
4268
  let wrote = 0;
4119
4269
  for (const e of entries) {
4120
4270
  let rel = null;
@@ -4123,15 +4273,15 @@ async function installModule(mod, opts = {}) {
4123
4273
  if (!rel) continue;
4124
4274
  const target = path46.join(dir, rel);
4125
4275
  if (!target.startsWith(dir + path46.sep) && target !== dir) throw new Error(`unsafe extract path: ${rel}`);
4126
- fs14.mkdirSync(path46.dirname(target), { recursive: true });
4127
- fs14.writeFileSync(target, e.body);
4276
+ fs13.mkdirSync(path46.dirname(target), { recursive: true });
4277
+ fs13.writeFileSync(target, e.body);
4128
4278
  wrote += 1;
4129
4279
  }
4130
- if (!wrote || !fs14.existsSync(path46.join(dir, "index.js"))) {
4131
- fs14.rmSync(dir, { recursive: true, force: true });
4280
+ if (!wrote || !fs13.existsSync(path46.join(dir, "index.js"))) {
4281
+ fs13.rmSync(dir, { recursive: true, force: true });
4132
4282
  return { status: "unavailable", detail: "package layout not recognized (no dist/index.js)" };
4133
4283
  }
4134
- fs14.writeFileSync(path46.join(dir, ".module.json"), JSON.stringify({ name: mod.npmName, version }));
4284
+ fs13.writeFileSync(path46.join(dir, ".module.json"), JSON.stringify({ name: mod.npmName, version }));
4135
4285
  mod.onChanged?.();
4136
4286
  return { status: "installed", version };
4137
4287
  } catch (e) {
@@ -4139,7 +4289,7 @@ async function installModule(mod, opts = {}) {
4139
4289
  }
4140
4290
  }
4141
4291
  function removeModule(mod) {
4142
- fs14.rmSync(mod.dir(), { recursive: true, force: true });
4292
+ fs13.rmSync(mod.dir(), { recursive: true, force: true });
4143
4293
  mod.onChanged?.();
4144
4294
  }
4145
4295
 
@@ -4184,7 +4334,7 @@ function candidatePaths() {
4184
4334
  if (custom) {
4185
4335
  const p = path46.resolve(custom);
4186
4336
  try {
4187
- if (fs14.statSync(p).isDirectory()) return [path46.join(p, "index.js")];
4337
+ if (fs13.statSync(p).isDirectory()) return [path46.join(p, "index.js")];
4188
4338
  } catch {
4189
4339
  }
4190
4340
  return [p];
@@ -4200,7 +4350,7 @@ async function loadHcsEngine() {
4200
4350
  cached = null;
4201
4351
  if (disabled()) return cached;
4202
4352
  for (const p of candidatePaths()) {
4203
- if (!fs14.existsSync(p)) continue;
4353
+ if (!fs13.existsSync(p)) continue;
4204
4354
  try {
4205
4355
  const mod = await import(pathToFileURL(p).href);
4206
4356
  const engine = await mod.createHcsEngine?.();
@@ -4367,7 +4517,7 @@ function hookContext(payloadText, root3, graphOverride) {
4367
4517
  let graph;
4368
4518
  try {
4369
4519
  const preferred = loadGraphPreferIndex(root3, graphPath);
4370
- graph = preferred ? preferred.graph : parseGraph(fs14.readFileSync(graphPath, "utf8"));
4520
+ graph = preferred ? preferred.graph : parseGraph(fs13.readFileSync(graphPath, "utf8"));
4371
4521
  } catch {
4372
4522
  return null;
4373
4523
  }
@@ -4389,7 +4539,7 @@ function registerHook(program) {
4389
4539
  const global = readGlobal(this);
4390
4540
  const root3 = rootOf(global);
4391
4541
  try {
4392
- const stdin = fs14.readFileSync(0, "utf8");
4542
+ const stdin = fs13.readFileSync(0, "utf8");
4393
4543
  const context = hookContext(stdin, root3, global.graph);
4394
4544
  if (context) {
4395
4545
  process.stdout.write(
@@ -4410,7 +4560,7 @@ function registerShare(program) {
4410
4560
  const global = readGlobal(this);
4411
4561
  const root3 = rootOf(global);
4412
4562
  const gitDir = path46.join(root3, ".git");
4413
- if (!fs14.existsSync(gitDir)) {
4563
+ if (!fs13.existsSync(gitDir)) {
4414
4564
  throw new CliError("not a git repository \u2014 run `vg share` inside a git repo", ExitCode.USAGE_ERROR);
4415
4565
  }
4416
4566
  if (opts.undo) {
@@ -4432,22 +4582,22 @@ function registerShare(program) {
4432
4582
  }
4433
4583
  function writeVibgrateGitignore(root3, reports) {
4434
4584
  const dir = path46.join(root3, ".vibgrate");
4435
- fs14.mkdirSync(dir, { recursive: true });
4585
+ fs13.mkdirSync(dir, { recursive: true });
4436
4586
  const lines = ["# Managed by `vg share` \u2014 keep graph.json committed, ignore the rest", "cache/", "facts.jsonl", "graph.snap"];
4437
4587
  if (!reports) lines.push("graph.html", "GRAPH_REPORT.md");
4438
- fs14.writeFileSync(path46.join(dir, ".gitignore"), `${lines.join("\n")}
4588
+ fs13.writeFileSync(path46.join(dir, ".gitignore"), `${lines.join("\n")}
4439
4589
  `);
4440
4590
  }
4441
4591
  function writeGitAttributes(root3) {
4442
4592
  const file = path46.join(root3, ".gitattributes");
4443
4593
  const line = ".vibgrate/graph.json merge=vg";
4444
- let content = fs14.existsSync(file) ? fs14.readFileSync(file, "utf8") : "";
4594
+ let content = fs13.existsSync(file) ? fs13.readFileSync(file, "utf8") : "";
4445
4595
  if (!content.split("\n").some((l) => l.trim() === line)) {
4446
4596
  content = content.length ? `${content.replace(/\s*$/, "")}
4447
4597
  ${line}
4448
4598
  ` : `${line}
4449
4599
  `;
4450
- fs14.writeFileSync(file, content);
4600
+ fs13.writeFileSync(file, content);
4451
4601
  }
4452
4602
  }
4453
4603
  function configureMergeDriver(root3) {
@@ -4456,7 +4606,7 @@ function configureMergeDriver(root3) {
4456
4606
  }
4457
4607
  function installPreCommitHook(root3) {
4458
4608
  const hooksDir = hookDir(root3);
4459
- fs14.mkdirSync(hooksDir, { recursive: true });
4609
+ fs13.mkdirSync(hooksDir, { recursive: true });
4460
4610
  const file = path46.join(hooksDir, "pre-commit");
4461
4611
  const block = [
4462
4612
  HOOK_BEGIN,
@@ -4466,7 +4616,7 @@ function installPreCommitHook(root3) {
4466
4616
  "fi",
4467
4617
  HOOK_END
4468
4618
  ].join("\n");
4469
- let content = fs14.existsSync(file) ? fs14.readFileSync(file, "utf8") : "#!/bin/sh\n";
4619
+ let content = fs13.existsSync(file) ? fs13.readFileSync(file, "utf8") : "#!/bin/sh\n";
4470
4620
  const re = new RegExp(`${escapeRe(HOOK_BEGIN)}[\\s\\S]*?${escapeRe(HOOK_END)}`);
4471
4621
  if (re.test(content)) content = content.replace(re, block);
4472
4622
  else content = `${content.replace(/\s*$/, "")}
@@ -4475,21 +4625,21 @@ ${block}
4475
4625
  `;
4476
4626
  if (!content.startsWith("#!")) content = `#!/bin/sh
4477
4627
  ${content}`;
4478
- fs14.writeFileSync(file, content);
4479
- fs14.chmodSync(file, 493);
4628
+ fs13.writeFileSync(file, content);
4629
+ fs13.chmodSync(file, 493);
4480
4630
  }
4481
4631
  function undo(root3) {
4482
4632
  const hookFile = path46.join(hookDir(root3), "pre-commit");
4483
- if (fs14.existsSync(hookFile)) {
4633
+ if (fs13.existsSync(hookFile)) {
4484
4634
  const re = new RegExp(`\\n*${escapeRe(HOOK_BEGIN)}[\\s\\S]*?${escapeRe(HOOK_END)}\\n*`);
4485
- const next2 = fs14.readFileSync(hookFile, "utf8").replace(re, "\n");
4486
- if (next2.trim() === "#!/bin/sh") fs14.rmSync(hookFile);
4487
- else fs14.writeFileSync(hookFile, next2);
4635
+ const next2 = fs13.readFileSync(hookFile, "utf8").replace(re, "\n");
4636
+ if (next2.trim() === "#!/bin/sh") fs13.rmSync(hookFile);
4637
+ else fs13.writeFileSync(hookFile, next2);
4488
4638
  }
4489
4639
  const attr = path46.join(root3, ".gitattributes");
4490
- if (fs14.existsSync(attr)) {
4491
- const next2 = fs14.readFileSync(attr, "utf8").split("\n").filter((l) => l.trim() !== ".vibgrate/graph.json merge=vg").join("\n");
4492
- fs14.writeFileSync(attr, next2);
4640
+ if (fs13.existsSync(attr)) {
4641
+ const next2 = fs13.readFileSync(attr, "utf8").split("\n").filter((l) => l.trim() !== ".vibgrate/graph.json merge=vg").join("\n");
4642
+ fs13.writeFileSync(attr, next2);
4493
4643
  }
4494
4644
  try {
4495
4645
  git(root3, ["config", "--remove-section", "merge.vg"]);
@@ -4518,7 +4668,7 @@ function registerWatch(program) {
4518
4668
  const debounceMs = Math.max(50, Number(opts.debounce) || DEFAULT_DEBOUNCE_MS);
4519
4669
  const watchRoots = (paths.length ? paths : ["."]).map((p) => path46.resolve(root3, p));
4520
4670
  for (const w of watchRoots) {
4521
- if (!fs14.existsSync(w)) {
4671
+ if (!fs13.existsSync(w)) {
4522
4672
  throw new CliError(`watch path not found: ${w}`, ExitCode.USAGE_ERROR);
4523
4673
  }
4524
4674
  }
@@ -4571,7 +4721,7 @@ function registerWatch(program) {
4571
4721
  const watchers = [];
4572
4722
  for (const w of watchRoots) {
4573
4723
  try {
4574
- const watcher = fs14.watch(w, { recursive: true }, (_event, filename) => {
4724
+ const watcher = fs13.watch(w, { recursive: true }, (_event, filename) => {
4575
4725
  if (!filename) {
4576
4726
  schedule("change");
4577
4727
  return;
@@ -4920,7 +5070,7 @@ function loadStandards(root3) {
4920
5070
  const p = path46__default.join(root3, rel);
4921
5071
  let text;
4922
5072
  try {
4923
- text = fs14__default.readFileSync(p, "utf8");
5073
+ text = fs13__default.readFileSync(p, "utf8");
4924
5074
  } catch {
4925
5075
  continue;
4926
5076
  }
@@ -6851,7 +7001,7 @@ function registerModels(program) {
6851
7001
  );
6852
7002
  }
6853
7003
  } else {
6854
- if (!target.path || !fs14.existsSync(target.path)) {
7004
+ if (!target.path || !fs13.existsSync(target.path)) {
6855
7005
  throw new CliError(
6856
7006
  `model file not found at ${target.path || "(unknown path)"} \u2014 it may already be removed.`,
6857
7007
  ExitCode.NOT_FOUND
@@ -6865,7 +7015,7 @@ function registerModels(program) {
6865
7015
  }
6866
7016
  if (!global.json) info(c.dim(` $ rm ${target.path}`));
6867
7017
  try {
6868
- fs14.unlinkSync(target.path);
7018
+ fs13.unlinkSync(target.path);
6869
7019
  } catch (e) {
6870
7020
  const msg = e instanceof Error ? e.message : String(e);
6871
7021
  throw new CliError(`could not delete ${target.path}: ${msg}`, ExitCode.ERROR);
@@ -7004,8 +7154,8 @@ function registerModels(program) {
7004
7154
  });
7005
7155
  if (opts.out) {
7006
7156
  const outPath = path46.resolve(opts.out);
7007
- fs14.mkdirSync(path46.dirname(outPath), { recursive: true });
7008
- fs14.writeFileSync(outPath, `${JSON.stringify(report, null, 2)}
7157
+ fs13.mkdirSync(path46.dirname(outPath), { recursive: true });
7158
+ fs13.writeFileSync(outPath, `${JSON.stringify(report, null, 2)}
7009
7159
  `);
7010
7160
  if (!global.json) info(c.dim(` wrote ${outPath}`));
7011
7161
  }
@@ -7203,7 +7353,7 @@ function codeConfigPath(root3) {
7203
7353
  }
7204
7354
  function loadCodeConfig(root3) {
7205
7355
  try {
7206
- const raw = JSON.parse(fs14.readFileSync(codeConfigPath(root3), "utf8"));
7356
+ const raw = JSON.parse(fs13.readFileSync(codeConfigPath(root3), "utf8"));
7207
7357
  return sanitize(raw);
7208
7358
  } catch {
7209
7359
  return {};
@@ -7270,7 +7420,7 @@ function contextBudgetFor(config, modelContextWindow) {
7270
7420
  var MCP_CONFIG_FILES = [".cursor/mcp.json", ".vscode/mcp.json", ".mcp.json"];
7271
7421
  function readMcpServersFile(file) {
7272
7422
  try {
7273
- const raw = JSON.parse(fs14.readFileSync(file, "utf8"));
7423
+ const raw = JSON.parse(fs13.readFileSync(file, "utf8"));
7274
7424
  const map = raw.mcpServers ?? raw.servers;
7275
7425
  return map && typeof map === "object" ? parseMcpServers(map) : {};
7276
7426
  } catch {
@@ -7395,10 +7545,10 @@ function registerCode(program) {
7395
7545
  return;
7396
7546
  }
7397
7547
  const patchFile = pathMod.join(
7398
- fs14.mkdtempSync(pathMod.join(os7.tmpdir(), "vg-wt-")),
7548
+ fs13.mkdtempSync(pathMod.join(os7.tmpdir(), "vg-wt-")),
7399
7549
  "delta.patch"
7400
7550
  );
7401
- fs14.writeFileSync(patchFile, diff2.patch);
7551
+ fs13.writeFileSync(patchFile, diff2.patch);
7402
7552
  const outcome = wt.applyWorktreePatch(gitRunner, root4, patchFile, diff2.files);
7403
7553
  emitLine({ event: "worktree-applied", id: target.id, ...outcome });
7404
7554
  if (!opts.streamJson && !global.json) {
@@ -7464,7 +7614,7 @@ function registerCode(program) {
7464
7614
  try {
7465
7615
  const { parseMode: parseMode2, resolveMode: resolveMode2, readOrchestratorState: readOrchestratorState2, activePin: activePin2 } = await import('./model-orchestrator-LHYPJBFH.js');
7466
7616
  const { gatherSystemMemory: gatherSystemMemory2 } = await import('./local-runtime-6SNWKSA7.js');
7467
- const { loadGraph: loadGraph2 } = await import('./load-AYFECIQB.js');
7617
+ const { loadGraph: loadGraph2 } = await import('./load-4R4HYMBB.js');
7468
7618
  const state = readOrchestratorState2();
7469
7619
  const mode = parseMode2(modeFlag) ?? state.defaultMode ?? void 0;
7470
7620
  const pin = mode ? activePin2(mode, state) : null;
@@ -7549,7 +7699,7 @@ function registerCode(program) {
7549
7699
  if (!(process.stdin.isTTY && process.stdout.isTTY)) {
7550
7700
  throw usageError('say what to change, e.g. `vg code "add a --timeout flag to the scan command"` (guided mode needs an interactive terminal)');
7551
7701
  }
7552
- const { runInteractive } = await import('./interactive-SR7TMF6M.js');
7702
+ const { runInteractive } = await import('./interactive-2MK4TLRD.js');
7553
7703
  await runInteractive(
7554
7704
  rootOf(global),
7555
7705
  global,
@@ -7579,7 +7729,7 @@ function registerCode(program) {
7579
7729
  }
7580
7730
  if (!instruction && !stdinFirstTurn) throw usageError('say what to change, e.g. `vg code "add a --timeout flag to the scan command"`');
7581
7731
  {
7582
- const { ensureCodeMap } = await import('./ensure-map-342G2IV3.js');
7732
+ const { ensureCodeMap } = await import('./ensure-map-FHDJTO7Y.js');
7583
7733
  const mapRoot = rootOf(global);
7584
7734
  try {
7585
7735
  await ensureCodeMap(mapRoot, global, {
@@ -7616,7 +7766,7 @@ function registerCode(program) {
7616
7766
  let mockReply;
7617
7767
  if (opts.mock) {
7618
7768
  try {
7619
- mockReply = fs14.readFileSync(opts.mock, "utf8");
7769
+ mockReply = fs13.readFileSync(opts.mock, "utf8");
7620
7770
  } catch {
7621
7771
  throw new CliError(`couldn't read the --mock file: ${opts.mock}`, ExitCode.USAGE_ERROR);
7622
7772
  }
@@ -7664,20 +7814,20 @@ function registerCode(program) {
7664
7814
  process.stdout.write(JSON.stringify(line) + "\n");
7665
7815
  };
7666
7816
  try {
7667
- const { RunOutcomeRecorder, newOneShotRunId, turnRunId } = await import('./run-outcome-YQQJG3LW.js');
7817
+ const { RunOutcomeRecorder, newOneShotRunId, turnRunId } = await import('./run-outcome-H5GVDDZJ.js');
7668
7818
  const primarySlug = route.providers[0]?.model.includes("/") ? route.providers[0].model.split("/")[0] : route.providers[0]?.id;
7669
- const { runCodeStreamJson, parseHostMessage } = await import('./stream-json-55YDNAFX.js');
7670
- const { nodeCodeFs } = await import('./session-H34HUV2Y.js');
7819
+ const { runCodeStreamJson, parseHostMessage } = await import('./stream-json-4WLSUF6I.js');
7820
+ const { nodeCodeFs } = await import('./session-N5IU4K5Q.js');
7671
7821
  const readline6 = await import('readline');
7672
7822
  const child = await import('child_process');
7673
7823
  const { loadOrDiscoverFederation } = await import('./federation-MDQPO3PW.js');
7674
7824
  const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
7675
7825
  const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
7676
- const { startCodeRuntimeSession } = await import('./runtime-session-CNJ4DAV5.js');
7677
- const { resolveGraphBackend } = await import('./graph-backend-RNWQBT3P.js');
7826
+ const { startCodeRuntimeSession } = await import('./runtime-session-JBIHHH5N.js');
7827
+ const { resolveGraphBackend } = await import('./graph-backend-W2D3HRRD.js');
7678
7828
  const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
7679
7829
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
7680
- const { vgdRequest } = await import('./vgd-URUZQORN.js');
7830
+ const { vgdRequest } = await import('./vgd-M7UOPWLB.js');
7681
7831
  const federation = loadOrDiscoverFederation(root3);
7682
7832
  const modelProfile = mergeModelExecutionProfile(
7683
7833
  resolveModelExecutionProfile({
@@ -7735,7 +7885,7 @@ ${res.stderr}` : ""),
7735
7885
  exitCode: res.status ?? 1
7736
7886
  };
7737
7887
  };
7738
- const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-2CNLHNEL.js');
7888
+ const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-KDVYIMFX.js');
7739
7889
  const vgBuiltin = createVgBuiltinMcpTools({
7740
7890
  getGraph: () => graph,
7741
7891
  root: root3,
@@ -7759,7 +7909,7 @@ ${res.stderr}` : ""),
7759
7909
  const os7 = await import('os');
7760
7910
  const pathMod = await import('path');
7761
7911
  const checkpointIndex = pathMod.join(
7762
- fs14.mkdtempSync(pathMod.join(os7.tmpdir(), "vg-code-cp-")),
7912
+ fs13.mkdtempSync(pathMod.join(os7.tmpdir(), "vg-code-cp-")),
7763
7913
  "index"
7764
7914
  );
7765
7915
  const gitRunner = (gitArgs, gitEnv) => {
@@ -7780,7 +7930,7 @@ ${res.stderr}` : ""),
7780
7930
  files,
7781
7931
  indexFile: checkpointIndex
7782
7932
  });
7783
- const { loadApprovalRules, addApprovalRule, ruleForAction, ruleLabel } = await import('./approvals-ASPJQUZK.js');
7933
+ const { loadApprovalRules, addApprovalRule, ruleForAction, ruleLabel } = await import('./approvals-TPQFQSWG.js');
7784
7934
  const { loadProjectRules, nodeRulesReader } = await import('./rules-ASYEUNB5.js');
7785
7935
  const projectRules = loadProjectRules(nodeRulesReader(root3));
7786
7936
  if (projectRules.sources.length && !global.quiet) {
@@ -7838,8 +7988,8 @@ ${res.stderr}` : ""),
7838
7988
  };
7839
7989
  try {
7840
7990
  if (opts.session) {
7841
- const { runCodeStreamJsonSession, STREAM_JSON_PROTOCOL_VERSION } = await import('./stream-json-55YDNAFX.js');
7842
- const { runAgent: runAgent2 } = await import('./agent-UQC7QN77.js');
7991
+ const { runCodeStreamJsonSession, STREAM_JSON_PROTOCOL_VERSION } = await import('./stream-json-4WLSUF6I.js');
7992
+ const { runAgent: runAgent2 } = await import('./agent-X6VYCE63.js');
7843
7993
  const {
7844
7994
  condenseSession,
7845
7995
  loadLatestSession,
@@ -7850,7 +8000,7 @@ ${res.stderr}` : ""),
7850
8000
  sessionsDir,
7851
8001
  summarizeSession
7852
8002
  } = await import('./session-store-AQUORKWB.js');
7853
- const { VERSION: VERSION2 } = await import('./version-WSE3QOPK.js');
8003
+ const { VERSION: VERSION2 } = await import('./version-DTEU3SQD.js');
7854
8004
  const resumedRecord = typeof opts.continue === "string" ? loadSession(mainRoot, opts.continue) : opts.continue ? loadLatestSession(mainRoot) : void 0;
7855
8005
  if (typeof opts.continue === "string" && !resumedRecord) {
7856
8006
  emitStream({
@@ -8062,8 +8212,8 @@ ${res.stderr}` : ""),
8062
8212
  if (!autonomous && !tty) {
8063
8213
  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).");
8064
8214
  }
8065
- const { agentTask } = await import('./interactive-SR7TMF6M.js');
8066
- const { nodeCodeFs } = await import('./session-H34HUV2Y.js');
8215
+ const { agentTask } = await import('./interactive-2MK4TLRD.js');
8216
+ const { nodeCodeFs } = await import('./session-N5IU4K5Q.js');
8067
8217
  const { TtyPrompter } = await import('./ui-K7D3BCHD.js');
8068
8218
  let priorSummary;
8069
8219
  let priorInstruction;
@@ -8078,7 +8228,7 @@ ${res.stderr}` : ""),
8078
8228
  }
8079
8229
  }
8080
8230
  const prompter = tty ? new TtyPrompter() : void 0;
8081
- const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-2CNLHNEL.js');
8231
+ const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-KDVYIMFX.js');
8082
8232
  const vgBuiltin = createVgBuiltinMcpTools({
8083
8233
  getGraph: () => graph,
8084
8234
  root: root3,
@@ -8102,11 +8252,11 @@ ${res.stderr}` : ""),
8102
8252
  const { loadFederation } = await import('./federation-MDQPO3PW.js');
8103
8253
  const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
8104
8254
  const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
8105
- const { startCodeRuntimeSession } = await import('./runtime-session-CNJ4DAV5.js');
8106
- const { resolveGraphBackend } = await import('./graph-backend-RNWQBT3P.js');
8255
+ const { startCodeRuntimeSession } = await import('./runtime-session-JBIHHH5N.js');
8256
+ const { resolveGraphBackend } = await import('./graph-backend-W2D3HRRD.js');
8107
8257
  const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
8108
8258
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
8109
- const { vgdRequest } = await import('./vgd-URUZQORN.js');
8259
+ const { vgdRequest } = await import('./vgd-M7UOPWLB.js');
8110
8260
  const federation = loadFederation(root3);
8111
8261
  const modelProfile = mergeModelExecutionProfile(
8112
8262
  resolveModelExecutionProfile({
@@ -8200,7 +8350,7 @@ ${res.stderr}` : ""),
8200
8350
  attribution: { client: "vg-code", provider: providerSlug, model: primary?.model }
8201
8351
  });
8202
8352
  if (opts.out) {
8203
- fs14.writeFileSync(opts.out, JSON.stringify(result, null, 2) + "\n");
8353
+ fs13.writeFileSync(opts.out, JSON.stringify(result, null, 2) + "\n");
8204
8354
  }
8205
8355
  if (global.json) {
8206
8356
  json(result);
@@ -8389,8 +8539,9 @@ function listCatalog(root3, asJson) {
8389
8539
  return;
8390
8540
  }
8391
8541
  info(`${c.cyan("vg lib")} \xB7 ${libs.length} library(ies) in the catalog`);
8542
+ const inv = inventory(root3);
8392
8543
  for (const l of libs) {
8393
- const d = driftFor(root3, l);
8544
+ const d = driftFor(root3, l, inv);
8394
8545
  const tag = d.drift === "behind" ? c.yellow(" (docs behind your version)") : d.drift === "ahead" ? c.dim(" (docs ahead)") : "";
8395
8546
  info(` ${c.bold(l.name)} ${c.dim(`@${l.version}`)} ${c.dim(`[${l.source.type}]`)}${tag}`);
8396
8547
  }
@@ -8413,7 +8564,7 @@ async function addCmd(root3, rest, opts, asJson) {
8413
8564
  }
8414
8565
  function readPackageVersion(root3) {
8415
8566
  try {
8416
- const pkg = JSON.parse(fs14__default.readFileSync(path46__default.join(root3, "package.json"), "utf8"));
8567
+ const pkg = JSON.parse(fs13__default.readFileSync(path46__default.join(root3, "package.json"), "utf8"));
8417
8568
  return typeof pkg.version === "string" ? pkg.version : void 0;
8418
8569
  } catch {
8419
8570
  return void 0;
@@ -8421,7 +8572,7 @@ function readPackageVersion(root3) {
8421
8572
  }
8422
8573
  function readOptionalFile(p) {
8423
8574
  try {
8424
- const t = fs14__default.readFileSync(p, "utf8");
8575
+ const t = fs13__default.readFileSync(p, "utf8");
8425
8576
  return t.trim() ? t : void 0;
8426
8577
  } catch {
8427
8578
  return void 0;
@@ -8569,8 +8720,8 @@ function registerExport(program) {
8569
8720
  out(content.trimEnd());
8570
8721
  return;
8571
8722
  }
8572
- fs14.mkdirSync(path46.dirname(path46.resolve(file)), { recursive: true });
8573
- fs14.writeFileSync(file, content);
8723
+ fs13.mkdirSync(path46.dirname(path46.resolve(file)), { recursive: true });
8724
+ fs13.writeFileSync(file, content);
8574
8725
  info(`${c.green("\u2714")} wrote ${file} ${c.dim(`(${format})`)}`);
8575
8726
  });
8576
8727
  applyGlobalOptions(cmd);
@@ -8593,36 +8744,36 @@ function registerBundle(program) {
8593
8744
  } catch {
8594
8745
  throw new CliError("no grammars found to bundle (run a build first)", ExitCode.ERROR);
8595
8746
  }
8596
- fs14.mkdirSync(path46.join(outDir, "grammars"), { recursive: true });
8747
+ fs13.mkdirSync(path46.join(outDir, "grammars"), { recursive: true });
8597
8748
  let grammarCount = 0;
8598
8749
  for (const { fileName, absPath } of grammarFiles) {
8599
- fs14.copyFileSync(absPath, path46.join(outDir, "grammars", fileName));
8750
+ fs13.copyFileSync(absPath, path46.join(outDir, "grammars", fileName));
8600
8751
  grammarCount++;
8601
8752
  }
8602
8753
  for (const id of Object.keys(TOOLCHAIN_GRAMMARS).sort()) {
8603
8754
  const absPath = resolveToolchainGrammar(id);
8604
8755
  if (!absPath) continue;
8605
- fs14.copyFileSync(absPath, path46.join(outDir, "grammars", path46.basename(absPath)));
8756
+ fs13.copyFileSync(absPath, path46.join(outDir, "grammars", path46.basename(absPath)));
8606
8757
  grammarCount++;
8607
8758
  }
8608
8759
  const included = [`grammars/ (${grammarCount} .wasm)`];
8609
8760
  const graphSrc = resolveGraphPath(root3, global.graph);
8610
- if (fs14.existsSync(graphSrc)) {
8611
- fs14.copyFileSync(graphSrc, path46.join(outDir, "graph.json"));
8761
+ if (fs13.existsSync(graphSrc)) {
8762
+ fs13.copyFileSync(graphSrc, path46.join(outDir, "graph.json"));
8612
8763
  included.push("graph.json");
8613
8764
  } else {
8614
8765
  const graph = loadGraphFileWithSnapshot(graphSrc);
8615
8766
  if (graph) {
8616
- fs14.writeFileSync(path46.join(outDir, "graph.json"), serializeGraph(graph));
8767
+ fs13.writeFileSync(path46.join(outDir, "graph.json"), serializeGraph(graph));
8617
8768
  included.push("graph.json");
8618
8769
  }
8619
8770
  }
8620
8771
  const cat = catalogPath(root3);
8621
- if (fs14.existsSync(cat)) {
8622
- fs14.copyFileSync(cat, path46.join(outDir, "vibgrate.lib.json"));
8772
+ if (fs13.existsSync(cat)) {
8773
+ fs13.copyFileSync(cat, path46.join(outDir, "vibgrate.lib.json"));
8623
8774
  included.push("vibgrate.lib.json");
8624
- if (fs14.existsSync(libDir(root3))) {
8625
- fs14.cpSync(libDir(root3), path46.join(outDir, "lib"), { recursive: true });
8775
+ if (fs13.existsSync(libDir(root3))) {
8776
+ fs13.cpSync(libDir(root3), path46.join(outDir, "lib"), { recursive: true });
8626
8777
  included.push("lib/");
8627
8778
  }
8628
8779
  }
@@ -8634,7 +8785,7 @@ function registerBundle(program) {
8634
8785
  included,
8635
8786
  usage: "Run `vg build --grammars <this dir>/grammars` to build fully offline."
8636
8787
  };
8637
- fs14.writeFileSync(path46.join(outDir, "MANIFEST.json"), `${stableStringify(manifest, 2)}
8788
+ fs13.writeFileSync(path46.join(outDir, "MANIFEST.json"), `${stableStringify(manifest, 2)}
8638
8789
  `);
8639
8790
  if (global.json) {
8640
8791
  json({ out: path46.relative(root3, outDir), ...manifest });
@@ -8660,7 +8811,7 @@ async function runDoctor(global) {
8660
8811
  const root3 = rootOf(global);
8661
8812
  const local = global.local === true;
8662
8813
  const graphPath = resolveGraphPath(root3, global.graph);
8663
- const configFile = CONFIG_BASENAMES.find((f) => fs14.existsSync(path46.join(root3, f))) ?? null;
8814
+ const configFile = CONFIG_BASENAMES.find((f) => fs13.existsSync(path46.join(root3, f))) ?? null;
8664
8815
  const graph = loadGraph(root3, graphPath);
8665
8816
  let staleFiles = null;
8666
8817
  if (graph) {
@@ -8693,7 +8844,7 @@ async function runDoctor(global) {
8693
8844
  },
8694
8845
  libCatalog: {
8695
8846
  path: path46.relative(root3, catalogPath(root3)),
8696
- present: fs14.existsSync(catalogPath(root3)),
8847
+ present: fs13.existsSync(catalogPath(root3)),
8697
8848
  libraries: libCount
8698
8849
  },
8699
8850
  credentials: creds,
@@ -8870,7 +9021,7 @@ function registerPolicy(program) {
8870
9021
  const global = readGlobal(this);
8871
9022
  let raw;
8872
9023
  try {
8873
- raw = fs14.readFileSync(file, "utf8");
9024
+ raw = fs13.readFileSync(file, "utf8");
8874
9025
  } catch {
8875
9026
  throw new CliError(`cannot read ${file}`, ExitCode.NOT_FOUND);
8876
9027
  }
@@ -9058,8 +9209,8 @@ async function readStdin() {
9058
9209
  }
9059
9210
  function readFileOrThrow(file, label) {
9060
9211
  const p = path46.resolve(file);
9061
- if (!fs14.existsSync(p)) throw usageError(`${label} file not found: ${p}`);
9062
- return fs14.readFileSync(p, "utf-8");
9212
+ if (!fs13.existsSync(p)) throw usageError(`${label} file not found: ${p}`);
9213
+ return fs13.readFileSync(p, "utf-8");
9063
9214
  }
9064
9215
  async function readInput(file, label) {
9065
9216
  return file ? readFileOrThrow(file, label) : readStdin();
@@ -9071,8 +9222,8 @@ function writeOutput(outFile, content) {
9071
9222
  }
9072
9223
  const outPath = path46.resolve(outFile);
9073
9224
  const dir = path46.dirname(outPath);
9074
- if (!fs14.existsSync(dir)) throw usageError(`output directory does not exist: ${dir}`);
9075
- fs14.writeFileSync(outPath, content.endsWith("\n") ? content : content + "\n", "utf-8");
9225
+ if (!fs13.existsSync(dir)) throw usageError(`output directory does not exist: ${dir}`);
9226
+ fs13.writeFileSync(outPath, content.endsWith("\n") ? content : content + "\n", "utf-8");
9076
9227
  info(c.dim(`wrote ${outPath}`));
9077
9228
  }
9078
9229
  function requireChoice(value, valid2, flag) {
@@ -9106,7 +9257,7 @@ function registerHcs(program) {
9106
9257
  const statePath = opts.previous ?? opts.out;
9107
9258
  const useIncremental = canIncremental && statePath !== void 0;
9108
9259
  const root3 = path46.resolve(dir);
9109
- if (!fs14.existsSync(root3) || !fs14.statSync(root3).isDirectory()) {
9260
+ if (!fs13.existsSync(root3) || !fs13.statSync(root3).isDirectory()) {
9110
9261
  throw usageError(`not a directory: ${root3}`);
9111
9262
  }
9112
9263
  const supported = new Set(
@@ -9124,7 +9275,7 @@ function registerHcs(program) {
9124
9275
  const walk2 = (abs, rel) => {
9125
9276
  let entries;
9126
9277
  try {
9127
- entries = fs14.readdirSync(abs, { withFileTypes: true });
9278
+ entries = fs13.readdirSync(abs, { withFileTypes: true });
9128
9279
  } catch {
9129
9280
  return;
9130
9281
  }
@@ -9141,8 +9292,8 @@ function registerHcs(program) {
9141
9292
  const lang = extToLang.get(path46.extname(entry.name).toLowerCase());
9142
9293
  if (!lang) continue;
9143
9294
  try {
9144
- if (fs14.statSync(absChild).size > MAX_EXTRACT_FILE_BYTES) continue;
9145
- const content = fs14.readFileSync(absChild, "utf-8");
9295
+ if (fs13.statSync(absChild).size > MAX_EXTRACT_FILE_BYTES) continue;
9296
+ const content = fs13.readFileSync(absChild, "utf-8");
9146
9297
  let bucket = byLanguage.get(lang);
9147
9298
  if (!bucket) byLanguage.set(lang, bucket = []);
9148
9299
  bucket.push({ path: relChild, content });
@@ -9173,7 +9324,7 @@ function registerHcs(program) {
9173
9324
  return;
9174
9325
  }
9175
9326
  const previousPath = path46.resolve(statePath);
9176
- const previousNdjson = !opts.full && fs14.existsSync(previousPath) ? fs14.readFileSync(previousPath, "utf-8") : "";
9327
+ const previousNdjson = !opts.full && fs13.existsSync(previousPath) ? fs13.readFileSync(previousPath, "utf-8") : "";
9177
9328
  if (opts.full) info(c.dim("running a full re-extraction (--full)"));
9178
9329
  else if (!previousNdjson) info(c.dim(`previous stream not found at ${previousPath} \u2014 running a full extraction`));
9179
9330
  const currentFilesJson = JSON.stringify(
@@ -9289,7 +9440,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
9289
9440
  console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold("vibgrate.config.ts")}`);
9290
9441
  }
9291
9442
  if (opts.baseline) {
9292
- const { runBaseline } = await import('./baseline-FIV6PR2M.js');
9443
+ const { runBaseline } = await import('./baseline-DXI64VLW.js');
9293
9444
  await runBaseline(rootDir);
9294
9445
  }
9295
9446
  console.log("");
@@ -9430,9 +9581,9 @@ function sitesFromImportFiles(files, limit = 10) {
9430
9581
  }
9431
9582
  async function defaultReadFile(absPath) {
9432
9583
  try {
9433
- const stat2 = await fs28.stat(absPath);
9584
+ const stat2 = await fs27.stat(absPath);
9434
9585
  if (!stat2.isFile() || stat2.size > MAX_FILE_BYTES) return null;
9435
- return await fs28.readFile(absPath, "utf8");
9586
+ return await fs27.readFile(absPath, "utf8");
9436
9587
  } catch {
9437
9588
  return null;
9438
9589
  }
@@ -9820,6 +9971,36 @@ function reportStandards(rootDir) {
9820
9971
  console.log(` ${chalk7.red("banned")} ${v.ecosystem}:${v.name}${v.installed ? chalk7.dim(` ${v.installed}`) : ""}${fix}${why}`);
9821
9972
  }
9822
9973
  }
9974
+ async function printRuntimeSnapshot(rootDir, opts, already) {
9975
+ try {
9976
+ const { attachVgd: attachVgd2 } = await import('./attach-G5JUIWIT.js');
9977
+ const { vgdRequest } = await import('./client-UQIELEEZ.js');
9978
+ const { formatSemanticProgress } = await import('./semantic-status-2JFLIQQJ.js');
9979
+ let repositoryId = already?.repositoryId;
9980
+ let socketPath = already?.socketPath;
9981
+ if (!repositoryId || !socketPath) {
9982
+ const attached = await attachVgd2(rootDir, {
9983
+ disabled: opts.daemon === false,
9984
+ autoStart: false,
9985
+ publish: false
9986
+ });
9987
+ if (attached.status !== "attached" || !attached.repositoryId || !attached.socketPath) return;
9988
+ repositoryId = attached.repositoryId;
9989
+ socketPath = attached.socketPath;
9990
+ }
9991
+ const semantic = await vgdRequest({ op: "embed-status", repositoryId }, { socketPath });
9992
+ if (!semantic.ok || !("semantic" in semantic)) return;
9993
+ const slot = semantic.semantic.slots.find((s) => s.repositoryId === repositoryId) ?? semantic.semantic.slots[0];
9994
+ if (!slot) {
9995
+ if (semantic.semantic.worker === "unavailable" && semantic.semantic.reason) {
9996
+ console.error(chalk7.dim(` \xB7 semantic \xB7 ${semantic.semantic.reason}`));
9997
+ }
9998
+ return;
9999
+ }
10000
+ console.error(chalk7.dim(` \xB7 ${formatSemanticProgress(slot)}`));
10001
+ } catch {
10002
+ }
10003
+ }
9823
10004
  function parseNonNegativeNumber(value, label) {
9824
10005
  if (value === void 0) return void 0;
9825
10006
  const parsed = Number(value);
@@ -9833,7 +10014,7 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
9833
10014
  'Exclude paths matching a glob pattern. Repeatable, and a single value may list several patterns separated by commas or semicolons (e.g. --exclude "legacy/**,vendor/**"). Merged with excludes from the config file.',
9834
10015
  collectExcludes,
9835
10016
  []
9836
- ).option("--concurrency <n>", "Max concurrent registry lookups", "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) => {
10017
+ ).option("--concurrency <n>", "Max concurrent registry lookups", "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("--no-daemon", "Never auto-start or use the local runtime (vgd) \u2014 run everything in this process").option("--quiet", "Suppress promotional output (the free-plan tracking panel and the AI Context install prompt); scan results are unaffected").action(async (targetPath, opts) => {
9837
10018
  const rootDir = path46.resolve(targetPath);
9838
10019
  if (!await pathExists$1(rootDir)) {
9839
10020
  console.error(chalk7.red(`Path does not exist: ${rootDir}`));
@@ -9918,6 +10099,7 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
9918
10099
  console.error(chalk7.red("Repository unchanged but no previous ingest id available."));
9919
10100
  process.exit(1);
9920
10101
  }
10102
+ await printRuntimeSnapshot(rootDir, opts);
9921
10103
  return;
9922
10104
  }
9923
10105
  }
@@ -9985,20 +10167,49 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
9985
10167
  writeSnapshot(rootDir, result.graph.provenance.corpusHash, result.fileStats, {
9986
10168
  exclude: opts.exclude
9987
10169
  });
9988
- refineArchitectureWithGraph(
9989
- { projects: ctx.projects, solutions: ctx.solutions, extended: ctx.extended },
9990
- architectureGraphView2(result.graph)
9991
- );
9992
10170
  refineArchitectureWithAstRoles(
9993
10171
  { projects: ctx.projects, solutions: ctx.solutions, extended: ctx.extended },
9994
10172
  result.fileRoles
9995
10173
  );
10174
+ refineArchitectureWithGraph(
10175
+ { projects: ctx.projects, solutions: ctx.solutions, extended: ctx.extended },
10176
+ architectureGraphView2(result.graph)
10177
+ );
9996
10178
  const { counts } = result.graph.meta;
9997
10179
  return `${counts.nodes.toLocaleString()} nodes \xB7 ${counts.edges.toLocaleString()} edges`;
9998
10180
  };
9999
10181
  }
10000
10182
  const advanced = await loadAdvancedScanHook();
10001
10183
  const artifact = await runCoreScan(rootDir, scanOpts, advanced);
10184
+ if (wantGraph && builtGraph) {
10185
+ const { attachVgd: attachVgd2 } = await import('./attach-G5JUIWIT.js');
10186
+ const { ActivityLog: ActivityLog2 } = await import('./activity-MF2GNYAI.js');
10187
+ const activity = new ActivityLog2();
10188
+ const attached = await activity.time(
10189
+ "attach",
10190
+ () => attachVgd2(rootDir, { disabled: opts.daemon === false }),
10191
+ (a) => {
10192
+ if (a.status !== "attached") return { outcome: "skip", detail: `${a.reason} \u2014 the map stays on disk only` };
10193
+ const started = a.started ? "started vgd" : "attached to vgd";
10194
+ if (a.published?.status === "published") {
10195
+ return {
10196
+ outcome: "ok",
10197
+ detail: `${started} \xB7 map published ${a.published.gitRef} \xB7 ${a.published.nodeCount} nodes`
10198
+ };
10199
+ }
10200
+ return { outcome: "ok", detail: started };
10201
+ }
10202
+ );
10203
+ if (!opts.quiet && opts.format !== "json") {
10204
+ for (const line of activity.render()) console.error(line);
10205
+ if (attached.status === "attached") {
10206
+ await printRuntimeSnapshot(rootDir, opts, {
10207
+ repositoryId: attached.repositoryId,
10208
+ socketPath: attached.socketPath
10209
+ });
10210
+ }
10211
+ }
10212
+ }
10002
10213
  emitDriftScoreLine(artifact.drift.score);
10003
10214
  if (opts.full) {
10004
10215
  reportStandards(rootDir);
@@ -10119,7 +10330,7 @@ var SKIP_DIRS3 = /* @__PURE__ */ new Set([
10119
10330
  function scanStaleness(rootDir, artifactPath) {
10120
10331
  let ref;
10121
10332
  try {
10122
- ref = fs14.statSync(artifactPath).mtimeMs;
10333
+ ref = fs13.statSync(artifactPath).mtimeMs;
10123
10334
  } catch {
10124
10335
  return { stale: false };
10125
10336
  }
@@ -10131,7 +10342,7 @@ function scanStaleness(rootDir, artifactPath) {
10131
10342
  if (depth > 8 || scanned > MAX_ENTRIES2) return;
10132
10343
  let entries;
10133
10344
  try {
10134
- entries = fs14.readdirSync(dir, { withFileTypes: true });
10345
+ entries = fs13.readdirSync(dir, { withFileTypes: true });
10135
10346
  } catch {
10136
10347
  return;
10137
10348
  }
@@ -10146,7 +10357,7 @@ function scanStaleness(rootDir, artifactPath) {
10146
10357
  const abs = path46.join(dir, e.name);
10147
10358
  let mtimeMs;
10148
10359
  try {
10149
- mtimeMs = fs14.statSync(abs).mtimeMs;
10360
+ mtimeMs = fs13.statSync(abs).mtimeMs;
10150
10361
  } catch {
10151
10362
  continue;
10152
10363
  }
@@ -10283,7 +10494,7 @@ function analyzeTree(root3, packages) {
10283
10494
  if (depth > MAX_DEPTH || filesSeen >= MAX_FILES) return;
10284
10495
  let entries;
10285
10496
  try {
10286
- entries = fs14.readdirSync(dir, { withFileTypes: true });
10497
+ entries = fs13.readdirSync(dir, { withFileTypes: true });
10287
10498
  } catch {
10288
10499
  return;
10289
10500
  }
@@ -10301,8 +10512,8 @@ function analyzeTree(root3, packages) {
10301
10512
  const full = path46.join(dir, entry.name);
10302
10513
  let content;
10303
10514
  try {
10304
- if (fs14.statSync(full).size > MAX_FILE_BYTES2) continue;
10305
- content = fs14.readFileSync(full, "utf8");
10515
+ if (fs13.statSync(full).size > MAX_FILE_BYTES2) continue;
10516
+ content = fs13.readFileSync(full, "utf8");
10306
10517
  } catch {
10307
10518
  continue;
10308
10519
  }
@@ -10670,8 +10881,8 @@ async function fetchLatestVersion() {
10670
10881
  }
10671
10882
  async function writeCache(data) {
10672
10883
  try {
10673
- await fs28.mkdir(CACHE_DIR, { recursive: true });
10674
- await fs28.writeFile(CACHE_FILE, JSON.stringify(data), "utf-8");
10884
+ await fs27.mkdir(CACHE_DIR, { recursive: true });
10885
+ await fs27.writeFile(CACHE_FILE, JSON.stringify(data), "utf-8");
10675
10886
  } catch {
10676
10887
  }
10677
10888
  }
@@ -10709,7 +10920,7 @@ function scheduleDeferredUpdate(command, pid = process.pid, dir = os.tmpdir()) {
10709
10920
  const scriptPath = path46.join(dir, `vg-update-${stamp}.cmd`);
10710
10921
  const logPath = path46.join(dir, `vg-update-${stamp}.log`);
10711
10922
  try {
10712
- fs14.writeFileSync(scriptPath, buildDeferredUpdateScript({ pid, command, logPath }), "utf8");
10923
+ fs13.writeFileSync(scriptPath, buildDeferredUpdateScript({ pid, command, logPath }), "utf8");
10713
10924
  const child = spawn(process.env.ComSpec || "cmd.exe", ["/d", "/s", "/c", scriptPath], {
10714
10925
  detached: true,
10715
10926
  stdio: "ignore",
@@ -10733,7 +10944,7 @@ function detectGlobalInstall(execPath = process.argv[1] || "", cwd = process.cwd
10733
10944
  if (!execPath) return null;
10734
10945
  let resolved = execPath;
10735
10946
  try {
10736
- resolved = fs14.realpathSync(execPath);
10947
+ resolved = fs13.realpathSync(execPath);
10737
10948
  } catch {
10738
10949
  }
10739
10950
  const p = resolved.replace(/\\/g, "/");
@@ -10877,7 +11088,7 @@ ${String(err)}` }));
10877
11088
  async function releaseWindowsFileLocks(cwd, keepVersion) {
10878
11089
  reapAndReport(cwd, keepVersion);
10879
11090
  try {
10880
- const { vgdSocketPath } = await import('./vgd-URUZQORN.js');
11091
+ const { vgdSocketPath } = await import('./vgd-M7UOPWLB.js');
10881
11092
  const result = await stopVgd(vgdSocketPath());
10882
11093
  if (result === "stopped") {
10883
11094
  console.log(chalk7.dim("Stopped the vgd daemon so its files can be replaced \u2014 it restarts on the next command."));
@@ -10930,6 +11141,7 @@ var updateCommand = new Command("update").description("Update vibgrate to the la
10930
11141
  if (!semver4.gt(latest, VERSION)) {
10931
11142
  console.log(chalk7.green("\u2714") + ` You are on the latest version (${VERSION}).`);
10932
11143
  if (opts.reap !== false) reapAndReport(process.cwd(), VERSION);
11144
+ if (opts.reap !== false) await reconcileVgdAndReport(process.cwd());
10933
11145
  return;
10934
11146
  }
10935
11147
  console.log(chalk7.yellow(`Update available: ${VERSION} \u2192 ${latest}`));
@@ -10992,7 +11204,7 @@ var updateCommand = new Command("update").description("Update vibgrate to the la
10992
11204
  process.exit(1);
10993
11205
  }
10994
11206
  if (opts.reap !== false) reapAndReport(cwd, latest);
10995
- if (opts.reap !== false) await restartVgdAndReport();
11207
+ if (opts.reap !== false) await restartVgdAndReport({ force: true });
10996
11208
  try {
10997
11209
  clearEmbedderHealth();
10998
11210
  } catch {
@@ -11002,10 +11214,10 @@ var updateCommand = new Command("update").description("Update vibgrate to the la
11002
11214
  );
11003
11215
  async function rewarmVgdAndReport(cwd) {
11004
11216
  try {
11005
- const { vgdIsRunning, vgdRequest } = await import('./vgd-URUZQORN.js');
11217
+ const { vgdIsRunning, vgdRequest } = await import('./vgd-M7UOPWLB.js');
11006
11218
  if (!await vgdIsRunning()) return;
11007
11219
  const loaded = await vgdRequest({ op: "load-graph", root: cwd });
11008
- if (!loaded.ok || !("repositoryId" in loaded)) return;
11220
+ if (!loaded.ok || !("stored" in loaded)) return;
11009
11221
  console.log(chalk7.dim("Re-published the code map into the restarted daemon."));
11010
11222
  const indexed = await vgdRequest({ op: "embed-index", repositoryId: loaded.repositoryId });
11011
11223
  if (indexed.ok && "vectors" in indexed && indexed.state === "ready") {
@@ -11014,10 +11226,30 @@ async function rewarmVgdAndReport(cwd) {
11014
11226
  } catch {
11015
11227
  }
11016
11228
  }
11017
- async function restartVgdAndReport() {
11229
+ async function reconcileVgdAndReport(cwd) {
11230
+ let skew;
11231
+ try {
11232
+ skew = await vgdVersionSkew();
11233
+ } catch {
11234
+ return;
11235
+ }
11236
+ if (!skew.running || skew.state === "match") return;
11237
+ if (skew.state === "newer") {
11238
+ console.log(chalk7.dim(`A newer vgd (${skew.version}) is running \u2014 left alone.`));
11239
+ return;
11240
+ }
11241
+ console.log(
11242
+ chalk7.yellow("Stale daemon: ") + chalk7.dim(
11243
+ `vgd is running ${skew.version ?? "a build older than 2026.817"}, not ${VERSION} \u2014 restarting it on this build.`
11244
+ )
11245
+ );
11246
+ await restartVgdAndReport({ force: true });
11247
+ await rewarmVgdAndReport(cwd);
11248
+ }
11249
+ async function restartVgdAndReport(opts = {}) {
11018
11250
  let result;
11019
11251
  try {
11020
- result = await restartVgdIfRunning();
11252
+ result = await restartVgdIfRunning(void 0, opts);
11021
11253
  } catch {
11022
11254
  return;
11023
11255
  }
@@ -11771,6 +12003,7 @@ function formatArchitectureDiagram(arch) {
11771
12003
  lines.push("");
11772
12004
  if (arch.layers.length > 0) {
11773
12005
  for (const layer of arch.layers) {
12006
+ if (layer.fileCount === 0) continue;
11774
12007
  const risk = layer.riskLevel === "none" ? chalk7.dim("none") : layer.riskLevel === "low" ? chalk7.green("low") : layer.riskLevel === "moderate" ? chalk7.yellow("moderate") : chalk7.red("high");
11775
12008
  lines.push(` ${chalk7.bold(layer.layer)} ${layer.fileCount} file${layer.fileCount !== 1 ? "s" : ""} drift ${scoreBar(layer.driftScore)} risk ${risk}`);
11776
12009
  }
@@ -11778,12 +12011,27 @@ function formatArchitectureDiagram(arch) {
11778
12011
  }
11779
12012
  if (arch.violations && arch.violations.length > 0) {
11780
12013
  const extra = arch.violationsCapped ? "+" : "";
11781
- lines.push(` Boundary violations (${arch.violations.length}${extra})`);
11782
- for (const v of arch.violations.slice(0, 8)) {
11783
- lines.push(` ${v.fromFile} \u2192 ${v.toFile} ${v.rule}`);
12014
+ const boundary = arch.violations.filter((v) => !v.rule.startsWith("graph-conflict:"));
12015
+ const conflicts = arch.violations.filter((v) => v.rule.startsWith("graph-conflict:"));
12016
+ if (boundary.length > 0) {
12017
+ const cap = extra && conflicts.length === 0 ? extra : "";
12018
+ lines.push(` Boundary violations (${boundary.length}${cap})`);
12019
+ for (const v of boundary.slice(0, 8)) {
12020
+ lines.push(` ${v.fromFile} \u2192 ${v.toFile} ${v.rule}`);
12021
+ }
12022
+ if (boundary.length > 8) {
12023
+ lines.push(chalk7.dim(` + ${boundary.length - 8} more`));
12024
+ }
11784
12025
  }
11785
- if (arch.violations.length > 8) {
11786
- lines.push(chalk7.dim(` + ${arch.violations.length - 8} more`));
12026
+ if (conflicts.length > 0) {
12027
+ const cap = extra ? extra : "";
12028
+ lines.push(` Layer conflicts (${conflicts.length}${cap})`);
12029
+ for (const v of conflicts.slice(0, 8)) {
12030
+ lines.push(` ${v.fromFile} \u2192 ${v.toFile} ${v.rule}`);
12031
+ }
12032
+ if (conflicts.length > 8) {
12033
+ lines.push(chalk7.dim(` + ${conflicts.length - 8} more`));
12034
+ }
11787
12035
  }
11788
12036
  lines.push("");
11789
12037
  }
@@ -12446,7 +12694,7 @@ var LOCALE_CONFIG_FILENAMES = ["vibgrate.locale.yaml", ".vibgrate/locale.yaml"];
12446
12694
  function findLocaleConfig(cwd) {
12447
12695
  for (const name of LOCALE_CONFIG_FILENAMES) {
12448
12696
  const candidate = path46.join(cwd, name);
12449
- if (fs14.existsSync(candidate)) return candidate;
12697
+ if (fs13.existsSync(candidate)) return candidate;
12450
12698
  }
12451
12699
  return null;
12452
12700
  }
@@ -12474,7 +12722,7 @@ function loadLocaleConfig(cwd) {
12474
12722
  const file = findLocaleConfig(cwd);
12475
12723
  if (!file) return { config: {}, file: null };
12476
12724
  try {
12477
- return { config: parseLocaleConfig(fs14.readFileSync(file, "utf8")), file };
12725
+ return { config: parseLocaleConfig(fs13.readFileSync(file, "utf8")), file };
12478
12726
  } catch (error) {
12479
12727
  throw new Error(
12480
12728
  `Could not parse ${path46.relative(cwd, file)}: ${error instanceof Error ? error.message : String(error)}`
@@ -12493,8 +12741,8 @@ function serializeLocaleConfig(config) {
12493
12741
  }
12494
12742
  function writeLocaleConfig(cwd, config, filename) {
12495
12743
  const target = filename ?? path46.join(cwd, LOCALE_CONFIG_FILENAMES[0]);
12496
- fs14.mkdirSync(path46.dirname(target), { recursive: true });
12497
- fs14.writeFileSync(target, serializeLocaleConfig(config), "utf8");
12744
+ fs13.mkdirSync(path46.dirname(target), { recursive: true });
12745
+ fs13.writeFileSync(target, serializeLocaleConfig(config), "utf8");
12498
12746
  return target;
12499
12747
  }
12500
12748
  function resolveLocaleSettings(config, flags) {
@@ -12652,14 +12900,14 @@ function resolveLocaleFiles(cwd, template, languages, namespaces) {
12652
12900
  for (const namespace of namespaces) {
12653
12901
  const relative13 = renderPath(template, language, namespace);
12654
12902
  const file = path46.resolve(cwd, relative13);
12655
- out2.push({ language, namespace, file, relative: relative13, exists: fs14.existsSync(file) });
12903
+ out2.push({ language, namespace, file, relative: relative13, exists: fs13.existsSync(file) });
12656
12904
  }
12657
12905
  }
12658
12906
  return out2;
12659
12907
  }
12660
12908
  function readCatalog(file, format) {
12661
- if (!fs14.existsSync(file)) return {};
12662
- const text = fs14.readFileSync(file, "utf8");
12909
+ if (!fs13.existsSync(file)) return {};
12910
+ const text = fs13.readFileSync(file, "utf8");
12663
12911
  try {
12664
12912
  return codecFor(format).decode(text);
12665
12913
  } catch (error) {
@@ -12670,11 +12918,11 @@ function readCatalog(file, format) {
12670
12918
  }
12671
12919
  function writeCatalog(file, format, catalog, opts = {}) {
12672
12920
  const encoded = codecFor(format).encode(sortKeys(catalog));
12673
- const existing = fs14.existsSync(file) ? fs14.readFileSync(file, "utf8") : null;
12921
+ const existing = fs13.existsSync(file) ? fs13.readFileSync(file, "utf8") : null;
12674
12922
  const changed = existing !== encoded;
12675
12923
  if (changed && !opts.dryRun) {
12676
- fs14.mkdirSync(path46.dirname(file), { recursive: true });
12677
- fs14.writeFileSync(file, encoded, "utf8");
12924
+ fs13.mkdirSync(path46.dirname(file), { recursive: true });
12925
+ fs13.writeFileSync(file, encoded, "utf8");
12678
12926
  }
12679
12927
  return { file, changed, bytes: Buffer.byteLength(encoded, "utf8") };
12680
12928
  }
@@ -14357,17 +14605,17 @@ function resolveSigningKey(root3, explicit) {
14357
14605
  const chosen = process.env.VG_ATTEST_KEY;
14358
14606
  const keyPath = chosen ? path46.resolve(chosen) : path46.join(root3, ".vibgrate", DEFAULT_KEY);
14359
14607
  let minted = false;
14360
- if (!fs14.existsSync(keyPath)) {
14608
+ if (!fs13.existsSync(keyPath)) {
14361
14609
  if (chosen) throw new CliError(`signing key not found: ${chosen}`, ExitCode.USAGE_ERROR);
14362
14610
  const kp = generateKeypair();
14363
- fs14.mkdirSync(path46.dirname(keyPath), { recursive: true });
14364
- fs14.writeFileSync(keyPath, kp.privatePem, { mode: 384 });
14365
- fs14.writeFileSync(`${keyPath}.pub`, kp.publicPem);
14611
+ fs13.mkdirSync(path46.dirname(keyPath), { recursive: true });
14612
+ fs13.writeFileSync(keyPath, kp.privatePem, { mode: 384 });
14613
+ fs13.writeFileSync(`${keyPath}.pub`, kp.publicPem);
14366
14614
  minted = true;
14367
14615
  }
14368
14616
  let key2;
14369
14617
  try {
14370
- key2 = crypto3.createPrivateKey(fs14.readFileSync(keyPath, "utf8"));
14618
+ key2 = crypto3.createPrivateKey(fs13.readFileSync(keyPath, "utf8"));
14371
14619
  } catch {
14372
14620
  throw new CliError(`could not read an Ed25519 private key from ${keyPath}`, ExitCode.USAGE_ERROR);
14373
14621
  }
@@ -14378,8 +14626,8 @@ function resolveSigningKey(root3, explicit) {
14378
14626
  }
14379
14627
  function writeBundle(input) {
14380
14628
  const dir = input.outDir;
14381
- fs14.mkdirSync(path46.join(dir, "inputs", "releases"), { recursive: true });
14382
- const write = (rel, data) => fs14.writeFileSync(path46.join(dir, rel), `${JSON.stringify(data, null, 2)}
14629
+ fs13.mkdirSync(path46.join(dir, "inputs", "releases"), { recursive: true });
14630
+ const write = (rel, data) => fs13.writeFileSync(path46.join(dir, rel), `${JSON.stringify(data, null, 2)}
14383
14631
  `);
14384
14632
  write("result.json", input.result);
14385
14633
  write(path46.join("inputs", "advisory.json"), input.advisory);
@@ -14403,13 +14651,13 @@ function writeBundle(input) {
14403
14651
  disclaimer: input.regime.disclaimer
14404
14652
  });
14405
14653
  if (input.envelope) {
14406
- fs14.writeFileSync(path46.join(dir, "evidence.intoto.jsonl"), `${JSON.stringify(input.envelope)}
14654
+ fs13.writeFileSync(path46.join(dir, "evidence.intoto.jsonl"), `${JSON.stringify(input.envelope)}
14407
14655
  `);
14408
14656
  }
14409
14657
  if (input.timestampToken) {
14410
- fs14.writeFileSync(path46.join(dir, "timestamp.tsr"), input.timestampToken);
14658
+ fs13.writeFileSync(path46.join(dir, "timestamp.tsr"), input.timestampToken);
14411
14659
  }
14412
- fs14.writeFileSync(path46.join(dir, "VERIFY.md"), verifyDoc(input));
14660
+ fs13.writeFileSync(path46.join(dir, "VERIFY.md"), verifyDoc(input));
14413
14661
  return dir;
14414
14662
  }
14415
14663
  function verifyDoc(input) {
@@ -14752,7 +15000,7 @@ var packCmd = new Command("pack").description("Build the submission pack a human
14752
15000
  const stage = opts.stage ?? regime.clocks[0]?.stage ?? "early-warning";
14753
15001
  const md = buildPack(result, regime, org, stage);
14754
15002
  if (opts.out) {
14755
- fs14.writeFileSync(path46.resolve(rootDir, opts.out), md);
15003
+ fs13.writeFileSync(path46.resolve(rootDir, opts.out), md);
14756
15004
  console.error(chalk7.green("\u2714") + ` pack written to ${opts.out}`);
14757
15005
  } else {
14758
15006
  console.log(md);
@@ -14795,19 +15043,19 @@ var drillCmd = new Command("drill").description("Timed dry-run of the determinat
14795
15043
  });
14796
15044
  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) => {
14797
15045
  const abs = path46.resolve(bundlePath);
14798
- const envPath = fs14.statSync(abs).isDirectory() ? path46.join(abs, "evidence.intoto.jsonl") : abs;
14799
- if (!fs14.existsSync(envPath)) throw new CliError(`no evidence.intoto.jsonl at ${bundlePath}`, ExitCode.NOT_FOUND);
14800
- const envelope = JSON.parse(fs14.readFileSync(envPath, "utf8").trim().split("\n")[0]);
15046
+ const envPath = fs13.statSync(abs).isDirectory() ? path46.join(abs, "evidence.intoto.jsonl") : abs;
15047
+ if (!fs13.existsSync(envPath)) throw new CliError(`no evidence.intoto.jsonl at ${bundlePath}`, ExitCode.NOT_FOUND);
15048
+ const envelope = JSON.parse(fs13.readFileSync(envPath, "utf8").trim().split("\n")[0]);
14801
15049
  const resultPath = path46.join(path46.dirname(envPath), "result.json");
14802
- const result = fs14.existsSync(resultPath) ? JSON.parse(fs14.readFileSync(resultPath, "utf8")) : void 0;
14803
- const publicKeyPem = opts.pub ? fs14.readFileSync(path46.resolve(opts.pub), "utf8") : void 0;
15050
+ const result = fs13.existsSync(resultPath) ? JSON.parse(fs13.readFileSync(resultPath, "utf8")) : void 0;
15051
+ const publicKeyPem = opts.pub ? fs13.readFileSync(path46.resolve(opts.pub), "utf8") : void 0;
14804
15052
  const v = verifyEvidenceEnvelope(envelope, { publicKeyPem, result });
14805
15053
  const color = v.status === "verified" ? chalk7.green : v.status === "failed" ? chalk7.red : chalk7.yellow;
14806
15054
  console.log(" " + color(v.status.toUpperCase()) + ` ${v.reason}`);
14807
15055
  if (v.evidenceId) console.log(" " + chalk7.dim(`evidence ${v.evidenceId} \xB7 regime ${v.regime} \xB7 advisory ${v.advisoryId} \xB7 ${v.overallStatus}`));
14808
15056
  const tsrPath = path46.join(path46.dirname(envPath), "timestamp.tsr");
14809
- if (fs14.existsSync(tsrPath) && result) {
14810
- const t = verifyTimestamp(fs14.readFileSync(tsrPath), exposureSubjectDigest(result));
15057
+ if (fs13.existsSync(tsrPath) && result) {
15058
+ const t = verifyTimestamp(fs13.readFileSync(tsrPath), exposureSubjectDigest(result));
14811
15059
  const tcolor = t.imprintMatches ? chalk7.green : chalk7.red;
14812
15060
  console.log(" " + tcolor("TIMESTAMP") + ` ${t.reason}`);
14813
15061
  }
@@ -14906,9 +15154,9 @@ var pushCmd = new Command("push").description("Push the product registry (and an
14906
15154
  let exposure;
14907
15155
  if (opts.result) {
14908
15156
  const raw = path46.resolve(rootDir, opts.result);
14909
- const resultPath = fs14.existsSync(raw) && fs14.statSync(raw).isDirectory() ? path46.join(raw, "result.json") : raw;
14910
- if (!fs14.existsSync(resultPath)) throw new CliError(`no result.json at ${opts.result}`, ExitCode.NOT_FOUND);
14911
- exposure = JSON.parse(fs14.readFileSync(resultPath, "utf8"));
15157
+ const resultPath = fs13.existsSync(raw) && fs13.statSync(raw).isDirectory() ? path46.join(raw, "result.json") : raw;
15158
+ if (!fs13.existsSync(resultPath)) throw new CliError(`no result.json at ${opts.result}`, ExitCode.NOT_FOUND);
15159
+ exposure = JSON.parse(fs13.readFileSync(resultPath, "utf8"));
14912
15160
  }
14913
15161
  const payload = { schemaVersion: "evidence-push-1", regime: regime.id, generatedAt: nowIso(), signed: Boolean(opts.signed), products: productPayload, exposure };
14914
15162
  const body = JSON.stringify(payload);
@@ -15107,7 +15355,7 @@ function dispatch(argv, cwd) {
15107
15355
  }
15108
15356
  const looksLikeQuestion = /\s/.test(first) || first.endsWith("?");
15109
15357
  if (looksLikeQuestion) return ["ask", ...args];
15110
- if (fs14.existsSync(path46.resolve(cwd, first))) {
15358
+ if (fs13.existsSync(path46.resolve(cwd, first))) {
15111
15359
  return [hasBuildOnlyFlag(args) ? "build" : "scan", ...args];
15112
15360
  }
15113
15361
  const moved = MOVED_COMMANDS[first];