@duckmind/dm-darwin-x64 0.66.5 → 0.66.6

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 (1115) hide show
  1. package/README.md +4 -0
  2. package/dm +2 -2
  3. package/extensions/.dm-extensions.json +755 -37
  4. package/extensions/dm-lens/clients/actionable-warnings.js +63 -11
  5. package/extensions/dm-lens/clients/advisory-provenance.js +5 -3
  6. package/extensions/dm-lens/clients/agent-nudge.js +106 -2
  7. package/extensions/dm-lens/clients/analysis-root.js +103 -0
  8. package/extensions/dm-lens/clients/ast-grep-client.js +18 -7
  9. package/extensions/dm-lens/clients/ast-grep-rule-manager.js +35 -12
  10. package/extensions/dm-lens/clients/biome-client.js +18 -12
  11. package/extensions/dm-lens/clients/blocker-freshness.js +1 -9
  12. package/extensions/dm-lens/clients/bounded-pid-file-lock.js +141 -30
  13. package/extensions/dm-lens/clients/bounded-telemetry.js +3 -0
  14. package/extensions/dm-lens/clients/cache/rule-cache.js +2 -17
  15. package/extensions/dm-lens/clients/cache-manager.js +105 -17
  16. package/extensions/dm-lens/clients/cargo-manifest.js +23 -3
  17. package/extensions/dm-lens/clients/complexity-client.js +1 -1
  18. package/extensions/dm-lens/clients/config-core/normalize.js +9 -0
  19. package/extensions/dm-lens/clients/config-core/schema.js +3 -0
  20. package/extensions/dm-lens/clients/config-schema.js +105 -2
  21. package/extensions/dm-lens/clients/confirmed-delete.js +11 -0
  22. package/extensions/dm-lens/clients/custom-rule-locations.js +28 -0
  23. package/extensions/dm-lens/clients/dead-code-client.js +81 -12
  24. package/extensions/dm-lens/clients/deferred-runner-blockers.js +108 -0
  25. package/extensions/dm-lens/clients/deferred-test-targets.js +31 -0
  26. package/extensions/dm-lens/clients/degradation-ledger.js +21 -3
  27. package/extensions/dm-lens/clients/demoted-finding-render.js +5 -2
  28. package/extensions/dm-lens/clients/dependency-checker.js +13 -4
  29. package/extensions/dm-lens/clients/diagnostic-line-freshness.js +3 -5
  30. package/extensions/dm-lens/clients/dispatch/adopted-root-runners.js +22 -0
  31. package/extensions/dm-lens/clients/dispatch/dispatcher.js +105 -27
  32. package/extensions/dm-lens/clients/dispatch/facts/comment-facts.js +5 -2
  33. package/extensions/dm-lens/clients/dispatch/facts/function-facts.js +1 -1
  34. package/extensions/dm-lens/clients/dispatch/facts/import-facts.js +2 -2
  35. package/extensions/dm-lens/clients/dispatch/facts/tree-sitter-facts.js +2 -2
  36. package/extensions/dm-lens/clients/dispatch/facts/try-catch-facts.js +1 -1
  37. package/extensions/dm-lens/clients/dispatch/finding-policy.js +12 -4
  38. package/extensions/dm-lens/clients/dispatch/integration.js +60 -15
  39. package/extensions/dm-lens/clients/dispatch/known-runner-ids.js +13 -0
  40. package/extensions/dm-lens/clients/dispatch/pending-runner-findings.js +66 -11
  41. package/extensions/dm-lens/clients/dispatch/plan.js +6 -0
  42. package/extensions/dm-lens/clients/dispatch/rule-id-normalize.js +9 -2
  43. package/extensions/dm-lens/clients/dispatch/rule-policy.js +33 -4
  44. package/extensions/dm-lens/clients/dispatch/runners/ast-grep-napi.js +9 -5
  45. package/extensions/dm-lens/clients/dispatch/runners/biome-check.js +5 -2
  46. package/extensions/dm-lens/clients/dispatch/runners/cue-vet.js +7 -3
  47. package/extensions/dm-lens/clients/dispatch/runners/detekt.js +3 -3
  48. package/extensions/dm-lens/clients/dispatch/runners/fact-rules.js +3 -3
  49. package/extensions/dm-lens/clients/dispatch/runners/fish-indent.js +10 -6
  50. package/extensions/dm-lens/clients/dispatch/runners/gleam-check.js +8 -5
  51. package/extensions/dm-lens/clients/dispatch/runners/go-vet.js +2 -1
  52. package/extensions/dm-lens/clients/dispatch/runners/lsp.js +28 -8
  53. package/extensions/dm-lens/clients/dispatch/runners/oxlint.js +2 -2
  54. package/extensions/dm-lens/clients/dispatch/runners/php-lint.js +6 -7
  55. package/extensions/dm-lens/clients/dispatch/runners/prisma-validate.js +18 -8
  56. package/extensions/dm-lens/clients/dispatch/runners/psscriptanalyzer.js +3 -3
  57. package/extensions/dm-lens/clients/dispatch/runners/pyright.js +1 -1
  58. package/extensions/dm-lens/clients/dispatch/runners/rust-clippy.js +25 -6
  59. package/extensions/dm-lens/clients/dispatch/runners/shellcheck.js +71 -4
  60. package/extensions/dm-lens/clients/dispatch/runners/shfmt.js +5 -1
  61. package/extensions/dm-lens/clients/dispatch/runners/spellcheck.js +3 -3
  62. package/extensions/dm-lens/clients/dispatch/runners/swiftlint.js +3 -3
  63. package/extensions/dm-lens/clients/dispatch/runners/taplo.js +17 -5
  64. package/extensions/dm-lens/clients/dispatch/runners/tree-sitter.js +12 -5
  65. package/extensions/dm-lens/clients/dispatch/runners/trivy-config.js +3 -3
  66. package/extensions/dm-lens/clients/dispatch/runners/utils/runner-helpers.js +127 -46
  67. package/extensions/dm-lens/clients/dispatch/runners/utils/tool-failure.js +11 -6
  68. package/extensions/dm-lens/clients/dispatch/runners/vale.js +3 -3
  69. package/extensions/dm-lens/clients/dispatch/runners/yaml-rule-parser.js +8 -1
  70. package/extensions/dm-lens/clients/dispatch/types.js +21 -1
  71. package/extensions/dm-lens/clients/dispatch/utils/format-utils.js +13 -0
  72. package/extensions/dm-lens/clients/effective-config.js +14 -3
  73. package/extensions/dm-lens/clients/ephemeral-root.js +71 -0
  74. package/extensions/dm-lens/clients/file-kinds.js +9 -0
  75. package/extensions/dm-lens/clients/file-mutation-queue.js +95 -0
  76. package/extensions/dm-lens/clients/file-utils.js +87 -8
  77. package/extensions/dm-lens/clients/finding-delivery-gate.js +5 -2
  78. package/extensions/dm-lens/clients/fix-run-restore.js +416 -0
  79. package/extensions/dm-lens/clients/format-events-publish.js +82 -2
  80. package/extensions/dm-lens/clients/format-service.js +10 -5
  81. package/extensions/dm-lens/clients/formatters.js +29 -12
  82. package/extensions/dm-lens/clients/generation-guard.js +50 -8
  83. package/extensions/dm-lens/clients/generation-lock.js +184 -0
  84. package/extensions/dm-lens/clients/git-guard.js +19 -1
  85. package/extensions/dm-lens/clients/gitleaks-client.js +13 -4
  86. package/extensions/dm-lens/clients/grammar-source.js +5 -0
  87. package/extensions/dm-lens/clients/grammar-wasm-imports.js +48 -0
  88. package/extensions/dm-lens/clients/gzip-stage-write.js +15 -7
  89. package/extensions/dm-lens/clients/hard-failure-summary.js +28 -0
  90. package/extensions/dm-lens/clients/hook-budgets.js +1 -0
  91. package/extensions/dm-lens/clients/inline-blocker-fields.js +8 -0
  92. package/extensions/dm-lens/clients/install-diagnostics.js +31 -16
  93. package/extensions/dm-lens/clients/installer/index.js +238 -58
  94. package/extensions/dm-lens/clients/instance-reaper.js +164 -52
  95. package/extensions/dm-lens/clients/instance-registry-lock.js +117 -76
  96. package/extensions/dm-lens/clients/instance-registry-tail.js +17 -0
  97. package/extensions/dm-lens/clients/instance-registry.js +248 -91
  98. package/extensions/dm-lens/clients/io-bridge-contract.js +7 -0
  99. package/extensions/dm-lens/clients/io-bridge.js +372 -0
  100. package/extensions/dm-lens/clients/jscpd-client.js +83 -35
  101. package/extensions/dm-lens/clients/knip-client.js +75 -6
  102. package/extensions/dm-lens/clients/knip-scan-roots.js +29 -0
  103. package/extensions/dm-lens/clients/language-policy.js +2 -0
  104. package/extensions/dm-lens/clients/language-profile.js +4 -1
  105. package/extensions/dm-lens/clients/language-registry.js +4 -1
  106. package/extensions/dm-lens/clients/latency-logger.js +11 -1
  107. package/extensions/dm-lens/clients/lens-config.js +10 -1
  108. package/extensions/dm-lens/clients/lens-engine.js +1 -1
  109. package/extensions/dm-lens/clients/lens-flag-registry.js +14 -24
  110. package/extensions/dm-lens/clients/lsp/aggregation.js +9 -8
  111. package/extensions/dm-lens/clients/lsp/auxiliary-lifecycle.js +23 -0
  112. package/extensions/dm-lens/clients/lsp/capabilities.js +98 -0
  113. package/extensions/dm-lens/clients/lsp/cascade-tier.js +8 -3
  114. package/extensions/dm-lens/clients/lsp/client.js +282 -48
  115. package/extensions/dm-lens/clients/lsp/config.js +247 -15
  116. package/extensions/dm-lens/clients/lsp/document-drift.js +23 -11
  117. package/extensions/dm-lens/clients/lsp/edits.js +137 -85
  118. package/extensions/dm-lens/clients/lsp/grouping.js +38 -0
  119. package/extensions/dm-lens/clients/lsp/index.js +484 -275
  120. package/extensions/dm-lens/clients/lsp/launch.js +106 -6
  121. package/extensions/dm-lens/clients/lsp/pending-aux-coverage.js +37 -7
  122. package/extensions/dm-lens/clients/lsp/resolved-config.js +188 -0
  123. package/extensions/dm-lens/clients/lsp/server-covers.js +8 -0
  124. package/extensions/dm-lens/clients/lsp/server-traits.js +39 -0
  125. package/extensions/dm-lens/clients/lsp/server.js +259 -34
  126. package/extensions/dm-lens/clients/lsp/service-singleton.js +59 -0
  127. package/extensions/dm-lens/clients/lsp/session-roots.js +1 -1
  128. package/extensions/dm-lens/clients/lsp/wait-policy/classification.js +2 -1
  129. package/extensions/dm-lens/clients/lsp/wait-policy/strategies.js +25 -4
  130. package/extensions/dm-lens/clients/lsp/workspace-diagnostics-cache.js +6 -3
  131. package/extensions/dm-lens/clients/lsp-budget.js +9 -5
  132. package/extensions/dm-lens/clients/lsp-document-symbols.js +1 -1
  133. package/extensions/dm-lens/clients/lsp-lazy.js +1 -1
  134. package/extensions/dm-lens/clients/lsp-mutation.js +44 -8
  135. package/extensions/dm-lens/clients/lsp-status.js +5 -7
  136. package/extensions/dm-lens/clients/mcp/analyze.js +24 -11
  137. package/extensions/dm-lens/clients/mcp/ipc.js +26 -7
  138. package/extensions/dm-lens/clients/mcp/session.js +1 -1
  139. package/extensions/dm-lens/clients/memory-sampler.js +48 -3
  140. package/extensions/dm-lens/clients/module-report-lsp.js +1 -1
  141. package/extensions/dm-lens/clients/module-report.js +9 -3
  142. package/extensions/dm-lens/clients/mutating-tool.js +12 -3
  143. package/extensions/dm-lens/clients/mutation-attribution.js +8 -0
  144. package/extensions/dm-lens/clients/mutation-bridge.js +181 -48
  145. package/extensions/dm-lens/clients/ndjson-logger.js +33 -0
  146. package/extensions/dm-lens/clients/observed-mutation-sources.js +1 -1
  147. package/extensions/dm-lens/clients/observed-mutation.js +40 -20
  148. package/extensions/dm-lens/clients/opaque-mutation-scan.js +40 -13
  149. package/extensions/dm-lens/clients/opengrep-client.js +6 -3
  150. package/extensions/dm-lens/clients/package-manager.js +61 -6
  151. package/extensions/dm-lens/clients/path-utils.js +77 -18
  152. package/extensions/dm-lens/clients/performance-report.js +1 -1
  153. package/extensions/dm-lens/clients/persist-worker-stats.js +8 -0
  154. package/extensions/dm-lens/clients/persistent-reverify.js +5 -1
  155. package/extensions/dm-lens/clients/pipeline.js +310 -114
  156. package/extensions/dm-lens/clients/probe-home-state.js +6 -1
  157. package/extensions/dm-lens/clients/process-bridge.js +28 -0
  158. package/extensions/dm-lens/clients/process-snapshot.js +115 -2
  159. package/extensions/dm-lens/clients/project-changes.js +81 -19
  160. package/extensions/dm-lens/clients/project-diagnostics/fresh-fetch.js +18 -13
  161. package/extensions/dm-lens/clients/project-lens-config.js +32 -5
  162. package/extensions/dm-lens/clients/project-scale.js +1 -1
  163. package/extensions/dm-lens/clients/project-snapshot-fingerprint.js +17 -12
  164. package/extensions/dm-lens/clients/project-snapshot-persist-worker.js +2 -3
  165. package/extensions/dm-lens/clients/project-snapshot.js +229 -64
  166. package/extensions/dm-lens/clients/python-environment.js +44 -2
  167. package/extensions/dm-lens/clients/quiet-window.js +6 -3
  168. package/extensions/dm-lens/clients/read-bridge.js +28 -20
  169. package/extensions/dm-lens/clients/read-expansion.js +1 -1
  170. package/extensions/dm-lens/clients/read-guard-branch.js +129 -0
  171. package/extensions/dm-lens/clients/read-guard-logger.js +11 -3
  172. package/extensions/dm-lens/clients/read-guard-tool-lines.js +16 -8
  173. package/extensions/dm-lens/clients/read-guard.js +516 -176
  174. package/extensions/dm-lens/clients/review-graph/builder.js +132 -54
  175. package/extensions/dm-lens/clients/review-graph/git-identity.js +59 -1
  176. package/extensions/dm-lens/clients/review-graph/import-resolvers.js +6 -8
  177. package/extensions/dm-lens/clients/runtime-agent-end.js +271 -68
  178. package/extensions/dm-lens/clients/runtime-coordinator.js +386 -74
  179. package/extensions/dm-lens/clients/runtime-session.js +174 -31
  180. package/extensions/dm-lens/clients/runtime-tool-call.js +92 -17
  181. package/extensions/dm-lens/clients/runtime-tool-result.js +477 -137
  182. package/extensions/dm-lens/clients/runtime-turn.js +949 -355
  183. package/extensions/dm-lens/clients/safe-spawn.js +12 -4
  184. package/extensions/dm-lens/clients/scanner-temp-root.js +8 -0
  185. package/extensions/dm-lens/clients/scratch-tree-policy.js +9 -0
  186. package/extensions/dm-lens/clients/search-read-registration.js +2 -1
  187. package/extensions/dm-lens/clients/session-lifecycle.js +120 -18
  188. package/extensions/dm-lens/clients/session-scope.js +456 -0
  189. package/extensions/dm-lens/clients/session-state-store.js +23 -20
  190. package/extensions/dm-lens/clients/sg-runner.js +24 -6
  191. package/extensions/dm-lens/clients/sgconfig.js +35 -5
  192. package/extensions/dm-lens/clients/startup-scan.js +10 -2
  193. package/extensions/dm-lens/clients/test-runner-client.js +258 -48
  194. package/extensions/dm-lens/clients/test-runner-delivery.js +46 -9
  195. package/extensions/dm-lens/clients/test-target-roots.js +20 -0
  196. package/extensions/dm-lens/clients/tool-agreement.js +282 -19
  197. package/extensions/dm-lens/clients/tool-config.js +1 -0
  198. package/extensions/dm-lens/clients/tool-event.js +6 -0
  199. package/extensions/dm-lens/clients/tool-probe.js +8 -0
  200. package/extensions/dm-lens/clients/tool-set-policy.js +36 -26
  201. package/extensions/dm-lens/clients/tree-sitter-client.js +304 -34
  202. package/extensions/dm-lens/clients/tree-sitter-query-loader.js +76 -2
  203. package/extensions/dm-lens/clients/tree-sitter-shared.js +2 -2
  204. package/extensions/dm-lens/clients/tree-sitter-symbol-extractor.js +3 -1
  205. package/extensions/dm-lens/clients/trivy-client.js +40 -7
  206. package/extensions/dm-lens/clients/turn-end/delivery-holds.js +59 -0
  207. package/extensions/dm-lens/clients/widget-state.js +36 -2
  208. package/extensions/dm-lens/clients/word-index.js +73 -5
  209. package/extensions/dm-lens/clients/workspace-topology.js +11 -4
  210. package/extensions/dm-lens/clients/write-ordering-guard.js +4 -0
  211. package/extensions/dm-lens/config/dependency-cruiser-eager-allowlist.json +9 -3
  212. package/extensions/dm-lens/dist/clients/actionable-warnings-logger.js +24 -0
  213. package/extensions/dm-lens/dist/clients/actionable-warnings.js +1062 -0
  214. package/extensions/dm-lens/dist/clients/advisory-provenance.js +387 -0
  215. package/extensions/dm-lens/dist/clients/agent-behavior-client.js +94 -0
  216. package/extensions/dm-lens/dist/clients/agent-nudge.js +253 -0
  217. package/extensions/dm-lens/dist/clients/analysed-root.js +1 -0
  218. package/extensions/dm-lens/dist/clients/analysis-root.js +100 -0
  219. package/extensions/dm-lens/dist/clients/ast-grep-client.js +587 -0
  220. package/extensions/dm-lens/dist/clients/ast-grep-rule-manager.js +137 -0
  221. package/extensions/dm-lens/dist/clients/ast-grep-tool-logger.js +85 -0
  222. package/extensions/dm-lens/dist/clients/ast-grep-types.js +1 -0
  223. package/extensions/dm-lens/dist/clients/ast-grep-yaml-synth.js +109 -0
  224. package/extensions/dm-lens/dist/clients/atomic-write-staging.js +66 -0
  225. package/extensions/dm-lens/dist/clients/atomic-write.js +37 -0
  226. package/extensions/dm-lens/dist/clients/availability-probe-flight.js +11 -0
  227. package/extensions/dm-lens/dist/clients/bash-file-access.js +830 -0
  228. package/extensions/dm-lens/dist/clients/biome-client.js +223 -0
  229. package/extensions/dm-lens/dist/clients/blocker-freshness.js +377 -0
  230. package/extensions/dm-lens/dist/clients/blocker-past-eof.js +49 -0
  231. package/extensions/dm-lens/dist/clients/bootstrap.js +246 -0
  232. package/extensions/dm-lens/dist/clients/bounded-cache.js +105 -0
  233. package/extensions/dm-lens/dist/clients/bounded-pid-file-lock.js +275 -0
  234. package/extensions/dm-lens/dist/clients/bounded-telemetry.js +107 -0
  235. package/extensions/dm-lens/dist/clients/build-identity.js +45 -0
  236. package/extensions/dm-lens/dist/clients/bundled-resource-health.js +41 -0
  237. package/extensions/dm-lens/dist/clients/bus-events-logger.js +48 -0
  238. package/extensions/dm-lens/dist/clients/bus-publish.js +117 -0
  239. package/extensions/dm-lens/dist/clients/cache/rule-cache.js +87 -0
  240. package/extensions/dm-lens/dist/clients/cache-manager.js +428 -0
  241. package/extensions/dm-lens/dist/clients/cache-observability.js +847 -0
  242. package/extensions/dm-lens/dist/clients/call-graph.js +628 -0
  243. package/extensions/dm-lens/dist/clients/cargo-manifest.js +171 -0
  244. package/extensions/dm-lens/dist/clients/cascade-budget.js +52 -0
  245. package/extensions/dm-lens/dist/clients/cascade-format.js +160 -0
  246. package/extensions/dm-lens/dist/clients/cascade-logger.js +22 -0
  247. package/extensions/dm-lens/dist/clients/cascade-types.js +1 -0
  248. package/extensions/dm-lens/dist/clients/child-unref.js +59 -0
  249. package/extensions/dm-lens/dist/clients/code-quality-warnings.js +192 -0
  250. package/extensions/dm-lens/dist/clients/codebase-model.js +110 -0
  251. package/extensions/dm-lens/dist/clients/collateral-test-role.js +8 -0
  252. package/extensions/dm-lens/dist/clients/complexity-client.js +398 -0
  253. package/extensions/dm-lens/dist/clients/config-core/deny.js +117 -0
  254. package/extensions/dm-lens/dist/clients/config-core/index.js +2 -0
  255. package/extensions/dm-lens/dist/clients/config-core/merge.js +228 -0
  256. package/extensions/dm-lens/dist/clients/config-core/normalize.js +226 -0
  257. package/extensions/dm-lens/dist/clients/config-core/process-spec.js +147 -0
  258. package/extensions/dm-lens/dist/clients/config-core/provenance.js +54 -0
  259. package/extensions/dm-lens/dist/clients/config-core/records.js +79 -0
  260. package/extensions/dm-lens/dist/clients/config-core/resolve.js +48 -0
  261. package/extensions/dm-lens/dist/clients/config-core/safe-object.js +22 -0
  262. package/extensions/dm-lens/dist/clients/config-core/schema.js +93 -0
  263. package/extensions/dm-lens/dist/clients/config-diagnostic-codes.js +90 -0
  264. package/extensions/dm-lens/dist/clients/config-locations.js +175 -0
  265. package/extensions/dm-lens/dist/clients/config-resolve.js +359 -0
  266. package/extensions/dm-lens/dist/clients/config-schema.js +230 -0
  267. package/extensions/dm-lens/dist/clients/config-warn.js +146 -0
  268. package/extensions/dm-lens/dist/clients/confirmed-delete.js +11 -0
  269. package/extensions/dm-lens/dist/clients/console-guard-install.js +4 -0
  270. package/extensions/dm-lens/dist/clients/cooperative-budget.js +36 -0
  271. package/extensions/dm-lens/dist/clients/custom-rule-locations.js +28 -0
  272. package/extensions/dm-lens/dist/clients/dead-code-client.js +408 -0
  273. package/extensions/dm-lens/dist/clients/dead-code-logger.js +18 -0
  274. package/extensions/dm-lens/dist/clients/deadline-utils.js +117 -0
  275. package/extensions/dm-lens/dist/clients/debug-handles.js +121 -0
  276. package/extensions/dm-lens/dist/clients/debug-heap.js +80 -0
  277. package/extensions/dm-lens/dist/clients/deferred-lsp-work.js +33 -0
  278. package/extensions/dm-lens/dist/clients/deferred-runner-blockers.js +106 -0
  279. package/extensions/dm-lens/dist/clients/deferred-test-targets.js +31 -0
  280. package/extensions/dm-lens/dist/clients/degradation-ledger.js +289 -0
  281. package/extensions/dm-lens/dist/clients/demoted-finding-render.js +64 -0
  282. package/extensions/dm-lens/dist/clients/dependency-checker.js +534 -0
  283. package/extensions/dm-lens/dist/clients/deps/ast-grep-napi.js +17 -0
  284. package/extensions/dm-lens/dist/clients/deps/dm-host-deps.js +10 -0
  285. package/extensions/dm-lens/dist/clients/deps/dm-tui-compat.js +58 -0
  286. package/extensions/dm-lens/dist/clients/deps/js-yaml.js +7 -0
  287. package/extensions/dm-lens/dist/clients/deps/minimatch.js +6 -0
  288. package/extensions/dm-lens/dist/clients/deps/pidusage.js +5 -0
  289. package/extensions/dm-lens/dist/clients/deps/typebox.js +5 -0
  290. package/extensions/dm-lens/dist/clients/deps/vscode-jsonrpc.js +8 -0
  291. package/extensions/dm-lens/dist/clients/deps/web-tree-sitter.js +11 -0
  292. package/extensions/dm-lens/dist/clients/diagnostic-dispositions.js +318 -0
  293. package/extensions/dm-lens/dist/clients/diagnostic-line-freshness.js +142 -0
  294. package/extensions/dm-lens/dist/clients/diagnostic-logger.js +60 -0
  295. package/extensions/dm-lens/dist/clients/diagnostic-tracker.js +89 -0
  296. package/extensions/dm-lens/dist/clients/diagnostics-publish.js +134 -0
  297. package/extensions/dm-lens/dist/clients/dispatch/adopted-root-runners.js +22 -0
  298. package/extensions/dm-lens/dist/clients/dispatch/ast-grep-catalog.js +16 -0
  299. package/extensions/dm-lens/dist/clients/dispatch/auxiliary-lsp.js +158 -0
  300. package/extensions/dm-lens/dist/clients/dispatch/collect-later-tier.js +25 -0
  301. package/extensions/dm-lens/dist/clients/dispatch/diagnostic-taxonomy.js +58 -0
  302. package/extensions/dm-lens/dist/clients/dispatch/dispatcher.js +1017 -0
  303. package/extensions/dm-lens/dist/clients/dispatch/fact-provider-types.js +1 -0
  304. package/extensions/dm-lens/dist/clients/dispatch/fact-rule-runner.js +17 -0
  305. package/extensions/dm-lens/dist/clients/dispatch/fact-runner.js +18 -0
  306. package/extensions/dm-lens/dist/clients/dispatch/fact-scheduler.js +52 -0
  307. package/extensions/dm-lens/dist/clients/dispatch/fact-store.js +199 -0
  308. package/extensions/dm-lens/dist/clients/dispatch/facts/comment-facts.js +23 -0
  309. package/extensions/dm-lens/dist/clients/dispatch/facts/file-content.js +18 -0
  310. package/extensions/dm-lens/dist/clients/dispatch/facts/function-facts.js +281 -0
  311. package/extensions/dm-lens/dist/clients/dispatch/facts/import-facts.js +169 -0
  312. package/extensions/dm-lens/dist/clients/dispatch/facts/tree-sitter-facts.js +19 -0
  313. package/extensions/dm-lens/dist/clients/dispatch/facts/try-catch-facts.js +95 -0
  314. package/extensions/dm-lens/dist/clients/dispatch/finding-policy.js +164 -0
  315. package/extensions/dm-lens/dist/clients/dispatch/indent-detect.js +227 -0
  316. package/extensions/dm-lens/dist/clients/dispatch/inline-suppressions.js +52 -0
  317. package/extensions/dm-lens/dist/clients/dispatch/integration.js +1502 -0
  318. package/extensions/dm-lens/dist/clients/dispatch/known-runner-ids.js +13 -0
  319. package/extensions/dm-lens/dist/clients/dispatch/lazy.js +8 -0
  320. package/extensions/dm-lens/dist/clients/dispatch/pending-runner-findings.js +130 -0
  321. package/extensions/dm-lens/dist/clients/dispatch/plan.js +284 -0
  322. package/extensions/dm-lens/dist/clients/dispatch/priorities.js +14 -0
  323. package/extensions/dm-lens/dist/clients/dispatch/rule-id-normalize.js +49 -0
  324. package/extensions/dm-lens/dist/clients/dispatch/rule-ignores.js +21 -0
  325. package/extensions/dm-lens/dist/clients/dispatch/rule-policy.js +102 -0
  326. package/extensions/dm-lens/dist/clients/dispatch/rules/async-noise.js +31 -0
  327. package/extensions/dm-lens/dist/clients/dispatch/rules/async-unnecessary-wrapper.js +27 -0
  328. package/extensions/dm-lens/dist/clients/dispatch/rules/cors-wildcard.js +35 -0
  329. package/extensions/dm-lens/dist/clients/dispatch/rules/error-obscuring.js +29 -0
  330. package/extensions/dm-lens/dist/clients/dispatch/rules/error-swallowing.js +29 -0
  331. package/extensions/dm-lens/dist/clients/dispatch/rules/framework-call-noise.js +31 -0
  332. package/extensions/dm-lens/dist/clients/dispatch/rules/high-complexity.js +56 -0
  333. package/extensions/dm-lens/dist/clients/dispatch/rules/high-fan-out.js +45 -0
  334. package/extensions/dm-lens/dist/clients/dispatch/rules/high-import-coupling.js +31 -0
  335. package/extensions/dm-lens/dist/clients/dispatch/rules/missing-error-propagation.js +45 -0
  336. package/extensions/dm-lens/dist/clients/dispatch/rules/no-commented-credentials.js +46 -0
  337. package/extensions/dm-lens/dist/clients/dispatch/rules/pass-through-wrappers.js +38 -0
  338. package/extensions/dm-lens/dist/clients/dispatch/rules/placeholder-comments.js +40 -0
  339. package/extensions/dm-lens/dist/clients/dispatch/rules/unsafe-boundary.js +101 -0
  340. package/extensions/dm-lens/dist/clients/dispatch/runner-context.js +46 -0
  341. package/extensions/dm-lens/dist/clients/dispatch/runners/actionlint.js +98 -0
  342. package/extensions/dm-lens/dist/clients/dispatch/runners/ast-grep-napi.js +694 -0
  343. package/extensions/dm-lens/dist/clients/dispatch/runners/biome-check.js +205 -0
  344. package/extensions/dm-lens/dist/clients/dispatch/runners/cpp-check.js +190 -0
  345. package/extensions/dm-lens/dist/clients/dispatch/runners/credo.js +66 -0
  346. package/extensions/dm-lens/dist/clients/dispatch/runners/cue-vet.js +171 -0
  347. package/extensions/dm-lens/dist/clients/dispatch/runners/dart-analyze.js +151 -0
  348. package/extensions/dm-lens/dist/clients/dispatch/runners/detekt.js +157 -0
  349. package/extensions/dm-lens/dist/clients/dispatch/runners/dotnet-build.js +157 -0
  350. package/extensions/dm-lens/dist/clients/dispatch/runners/elixir-check.js +153 -0
  351. package/extensions/dm-lens/dist/clients/dispatch/runners/eslint.js +99 -0
  352. package/extensions/dm-lens/dist/clients/dispatch/runners/fact-rules.js +20 -0
  353. package/extensions/dm-lens/dist/clients/dispatch/runners/fish-indent.js +66 -0
  354. package/extensions/dm-lens/dist/clients/dispatch/runners/gleam-check.js +110 -0
  355. package/extensions/dm-lens/dist/clients/dispatch/runners/go-vet.js +52 -0
  356. package/extensions/dm-lens/dist/clients/dispatch/runners/golangci-lint.js +89 -0
  357. package/extensions/dm-lens/dist/clients/dispatch/runners/hadolint.js +83 -0
  358. package/extensions/dm-lens/dist/clients/dispatch/runners/helm-lint.js +144 -0
  359. package/extensions/dm-lens/dist/clients/dispatch/runners/helm-render.js +593 -0
  360. package/extensions/dm-lens/dist/clients/dispatch/runners/htmlhint.js +103 -0
  361. package/extensions/dm-lens/dist/clients/dispatch/runners/index.js +100 -0
  362. package/extensions/dm-lens/dist/clients/dispatch/runners/javac.js +82 -0
  363. package/extensions/dm-lens/dist/clients/dispatch/runners/ktlint.js +93 -0
  364. package/extensions/dm-lens/dist/clients/dispatch/runners/lsp.js +226 -0
  365. package/extensions/dm-lens/dist/clients/dispatch/runners/markdownlint.js +129 -0
  366. package/extensions/dm-lens/dist/clients/dispatch/runners/mypy.js +70 -0
  367. package/extensions/dm-lens/dist/clients/dispatch/runners/oxlint.js +305 -0
  368. package/extensions/dm-lens/dist/clients/dispatch/runners/php-lint.js +66 -0
  369. package/extensions/dm-lens/dist/clients/dispatch/runners/phpstan.js +90 -0
  370. package/extensions/dm-lens/dist/clients/dispatch/runners/prisma-validate.js +66 -0
  371. package/extensions/dm-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +307 -0
  372. package/extensions/dm-lens/dist/clients/dispatch/runners/pyright.js +118 -0
  373. package/extensions/dm-lens/dist/clients/dispatch/runners/rubocop.js +79 -0
  374. package/extensions/dm-lens/dist/clients/dispatch/runners/ruff.js +69 -0
  375. package/extensions/dm-lens/dist/clients/dispatch/runners/rust-clippy.js +166 -0
  376. package/extensions/dm-lens/dist/clients/dispatch/runners/shellcheck.js +177 -0
  377. package/extensions/dm-lens/dist/clients/dispatch/runners/shfmt.js +85 -0
  378. package/extensions/dm-lens/dist/clients/dispatch/runners/spellcheck.js +74 -0
  379. package/extensions/dm-lens/dist/clients/dispatch/runners/spotbugs.js +208 -0
  380. package/extensions/dm-lens/dist/clients/dispatch/runners/sqlfluff.js +136 -0
  381. package/extensions/dm-lens/dist/clients/dispatch/runners/stylelint.js +118 -0
  382. package/extensions/dm-lens/dist/clients/dispatch/runners/swiftlint.js +143 -0
  383. package/extensions/dm-lens/dist/clients/dispatch/runners/taplo.js +108 -0
  384. package/extensions/dm-lens/dist/clients/dispatch/runners/terragrunt.js +110 -0
  385. package/extensions/dm-lens/dist/clients/dispatch/runners/tflint.js +104 -0
  386. package/extensions/dm-lens/dist/clients/dispatch/runners/tree-sitter.js +521 -0
  387. package/extensions/dm-lens/dist/clients/dispatch/runners/trivy-config.js +155 -0
  388. package/extensions/dm-lens/dist/clients/dispatch/runners/utils/availability-policy.js +285 -0
  389. package/extensions/dm-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +61 -0
  390. package/extensions/dm-lens/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +61 -0
  391. package/extensions/dm-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +130 -0
  392. package/extensions/dm-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +1143 -0
  393. package/extensions/dm-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +40 -0
  394. package/extensions/dm-lens/dist/clients/dispatch/runners/utils/tool-failure.js +120 -0
  395. package/extensions/dm-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +88 -0
  396. package/extensions/dm-lens/dist/clients/dispatch/runners/utils.js +8 -0
  397. package/extensions/dm-lens/dist/clients/dispatch/runners/vale.js +106 -0
  398. package/extensions/dm-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +170 -0
  399. package/extensions/dm-lens/dist/clients/dispatch/runners/yamllint.js +83 -0
  400. package/extensions/dm-lens/dist/clients/dispatch/runners/zig-check.js +72 -0
  401. package/extensions/dm-lens/dist/clients/dispatch/suppress-writer.js +57 -0
  402. package/extensions/dm-lens/dist/clients/dispatch/tool-profile.js +30 -0
  403. package/extensions/dm-lens/dist/clients/dispatch/types.js +27 -0
  404. package/extensions/dm-lens/dist/clients/dispatch/utils/format-utils.js +58 -0
  405. package/extensions/dm-lens/dist/clients/dispatch/utils/lsp-diagnostics.js +31 -0
  406. package/extensions/dm-lens/dist/clients/disposition-logger.js +19 -0
  407. package/extensions/dm-lens/dist/clients/disposition-publish.js +88 -0
  408. package/extensions/dm-lens/dist/clients/durable-store.js +77 -0
  409. package/extensions/dm-lens/dist/clients/effective-config.js +170 -0
  410. package/extensions/dm-lens/dist/clients/env-utils.js +26 -0
  411. package/extensions/dm-lens/dist/clients/ephemeral-root.js +67 -0
  412. package/extensions/dm-lens/dist/clients/error-class.js +3 -0
  413. package/extensions/dm-lens/dist/clients/eval-timestamp.js +2 -0
  414. package/extensions/dm-lens/dist/clients/event-loop-hold.js +119 -0
  415. package/extensions/dm-lens/dist/clients/event-loop-monitor.js +84 -0
  416. package/extensions/dm-lens/dist/clients/extension-log.js +230 -0
  417. package/extensions/dm-lens/dist/clients/extension-mode.js +20 -0
  418. package/extensions/dm-lens/dist/clients/feature-hints.js +88 -0
  419. package/extensions/dm-lens/dist/clients/file-kinds.js +313 -0
  420. package/extensions/dm-lens/dist/clients/file-mutation-queue.js +95 -0
  421. package/extensions/dm-lens/dist/clients/file-role.js +50 -0
  422. package/extensions/dm-lens/dist/clients/file-time.js +112 -0
  423. package/extensions/dm-lens/dist/clients/file-utils.js +706 -0
  424. package/extensions/dm-lens/dist/clients/finding-delivery-gate.js +132 -0
  425. package/extensions/dm-lens/dist/clients/finding-identity.js +23 -0
  426. package/extensions/dm-lens/dist/clients/fix-run-restore.js +413 -0
  427. package/extensions/dm-lens/dist/clients/fix-worklog.js +75 -0
  428. package/extensions/dm-lens/dist/clients/format-events-publish.js +310 -0
  429. package/extensions/dm-lens/dist/clients/format-service.js +159 -0
  430. package/extensions/dm-lens/dist/clients/formatters-lazy.js +8 -0
  431. package/extensions/dm-lens/dist/clients/formatters.js +1367 -0
  432. package/extensions/dm-lens/dist/clients/freshness-cadence.js +1 -0
  433. package/extensions/dm-lens/dist/clients/freshness.js +8 -0
  434. package/extensions/dm-lens/dist/clients/generated-artifacts.js +209 -0
  435. package/extensions/dm-lens/dist/clients/generation-guard.js +147 -0
  436. package/extensions/dm-lens/dist/clients/generation-lock.js +181 -0
  437. package/extensions/dm-lens/dist/clients/git-guard.js +786 -0
  438. package/extensions/dm-lens/dist/clients/git-tracked-ignore.js +120 -0
  439. package/extensions/dm-lens/dist/clients/gitleaks-client.js +290 -0
  440. package/extensions/dm-lens/dist/clients/go-client.js +47 -0
  441. package/extensions/dm-lens/dist/clients/govulncheck-client.js +411 -0
  442. package/extensions/dm-lens/dist/clients/gradle-ktfmt-style.js +177 -0
  443. package/extensions/dm-lens/dist/clients/grammar-source.js +229 -0
  444. package/extensions/dm-lens/dist/clients/grammar-wasm-imports.js +48 -0
  445. package/extensions/dm-lens/dist/clients/gzip-stage-write.js +93 -0
  446. package/extensions/dm-lens/dist/clients/hard-failure-summary.js +28 -0
  447. package/extensions/dm-lens/dist/clients/hashline-anchor.js +222 -0
  448. package/extensions/dm-lens/dist/clients/hook-budgets.js +17 -0
  449. package/extensions/dm-lens/dist/clients/host-edit-normalize.js +87 -0
  450. package/extensions/dm-lens/dist/clients/host-ports.js +35 -0
  451. package/extensions/dm-lens/dist/clients/indent-retarget.js +102 -0
  452. package/extensions/dm-lens/dist/clients/inline-blocker-dispositions.js +103 -0
  453. package/extensions/dm-lens/dist/clients/inline-blocker-fields.js +8 -0
  454. package/extensions/dm-lens/dist/clients/install-diagnostics.js +135 -0
  455. package/extensions/dm-lens/dist/clients/installer/index.js +3935 -0
  456. package/extensions/dm-lens/dist/clients/installer/managed-tool-refresh-session.js +17 -0
  457. package/extensions/dm-lens/dist/clients/installer/managed-tool-refresh.js +522 -0
  458. package/extensions/dm-lens/dist/clients/instance-reaper-state.js +3 -0
  459. package/extensions/dm-lens/dist/clients/instance-reaper.js +682 -0
  460. package/extensions/dm-lens/dist/clients/instance-registry-lock.js +166 -0
  461. package/extensions/dm-lens/dist/clients/instance-registry-tail.js +17 -0
  462. package/extensions/dm-lens/dist/clients/instance-registry.js +595 -0
  463. package/extensions/dm-lens/dist/clients/io-bridge-contract.js +7 -0
  464. package/extensions/dm-lens/dist/clients/io-bridge.js +357 -0
  465. package/extensions/dm-lens/dist/clients/jscpd-client.js +300 -0
  466. package/extensions/dm-lens/dist/clients/json-cache-read.js +25 -0
  467. package/extensions/dm-lens/dist/clients/knip-client.js +534 -0
  468. package/extensions/dm-lens/dist/clients/knip-scan-roots.js +26 -0
  469. package/extensions/dm-lens/dist/clients/language-policy.js +244 -0
  470. package/extensions/dm-lens/dist/clients/language-profile.js +263 -0
  471. package/extensions/dm-lens/dist/clients/language-registry.js +427 -0
  472. package/extensions/dm-lens/dist/clients/latency-logger.js +202 -0
  473. package/extensions/dm-lens/dist/clients/lazy-import.js +14 -0
  474. package/extensions/dm-lens/dist/clients/ledger-bounds.js +21 -0
  475. package/extensions/dm-lens/dist/clients/lens-config.js +246 -0
  476. package/extensions/dm-lens/dist/clients/lens-engine.js +181 -0
  477. package/extensions/dm-lens/dist/clients/lens-events.js +105 -0
  478. package/extensions/dm-lens/dist/clients/lens-flag-registry.js +292 -0
  479. package/extensions/dm-lens/dist/clients/lens-map.js +980 -0
  480. package/extensions/dm-lens/dist/clients/live-bus-emitter.js +53 -0
  481. package/extensions/dm-lens/dist/clients/log-cleanup.js +138 -0
  482. package/extensions/dm-lens/dist/clients/lsp/aggregation.js +89 -0
  483. package/extensions/dm-lens/dist/clients/lsp/auxiliary-lifecycle.js +23 -0
  484. package/extensions/dm-lens/dist/clients/lsp/capabilities.js +94 -0
  485. package/extensions/dm-lens/dist/clients/lsp/cascade-tier.js +208 -0
  486. package/extensions/dm-lens/dist/clients/lsp/client.js +2943 -0
  487. package/extensions/dm-lens/dist/clients/lsp/config.js +471 -0
  488. package/extensions/dm-lens/dist/clients/lsp/content-limits.js +21 -0
  489. package/extensions/dm-lens/dist/clients/lsp/diagnostic-binding.js +79 -0
  490. package/extensions/dm-lens/dist/clients/lsp/document-drift.js +324 -0
  491. package/extensions/dm-lens/dist/clients/lsp/edits.js +982 -0
  492. package/extensions/dm-lens/dist/clients/lsp/grouping.js +38 -0
  493. package/extensions/dm-lens/dist/clients/lsp/index.js +4639 -0
  494. package/extensions/dm-lens/dist/clients/lsp/inferred-project.js +121 -0
  495. package/extensions/dm-lens/dist/clients/lsp/jvm-runtime.js +194 -0
  496. package/extensions/dm-lens/dist/clients/lsp/language.js +23 -0
  497. package/extensions/dm-lens/dist/clients/lsp/launch.js +564 -0
  498. package/extensions/dm-lens/dist/clients/lsp/lombok.js +146 -0
  499. package/extensions/dm-lens/dist/clients/lsp/path-utils.js +1 -0
  500. package/extensions/dm-lens/dist/clients/lsp/pending-aux-coverage.js +120 -0
  501. package/extensions/dm-lens/dist/clients/lsp/position-encoding.js +28 -0
  502. package/extensions/dm-lens/dist/clients/lsp/resolved-config.js +183 -0
  503. package/extensions/dm-lens/dist/clients/lsp/ruby-drive-dirs.js +42 -0
  504. package/extensions/dm-lens/dist/clients/lsp/server-covers.js +8 -0
  505. package/extensions/dm-lens/dist/clients/lsp/server-traits.js +39 -0
  506. package/extensions/dm-lens/dist/clients/lsp/server.js +2640 -0
  507. package/extensions/dm-lens/dist/clients/lsp/service-singleton.js +59 -0
  508. package/extensions/dm-lens/dist/clients/lsp/session-roots.js +52 -0
  509. package/extensions/dm-lens/dist/clients/lsp/spawn-history.js +15 -0
  510. package/extensions/dm-lens/dist/clients/lsp/sync-kind.js +30 -0
  511. package/extensions/dm-lens/dist/clients/lsp/tsserver-sync.js +156 -0
  512. package/extensions/dm-lens/dist/clients/lsp/wait-policy/capability-snapshot.js +1 -0
  513. package/extensions/dm-lens/dist/clients/lsp/wait-policy/classification.js +37 -0
  514. package/extensions/dm-lens/dist/clients/lsp/wait-policy/index.js +3 -0
  515. package/extensions/dm-lens/dist/clients/lsp/wait-policy/strategies.js +196 -0
  516. package/extensions/dm-lens/dist/clients/lsp/watch-queue.js +40 -0
  517. package/extensions/dm-lens/dist/clients/lsp/workspace-diagnostics-cache.js +270 -0
  518. package/extensions/dm-lens/dist/clients/lsp/workspace-diagnostics-session.js +7 -0
  519. package/extensions/dm-lens/dist/clients/lsp/workspace-sweep-hold.js +93 -0
  520. package/extensions/dm-lens/dist/clients/lsp-budget.js +87 -0
  521. package/extensions/dm-lens/dist/clients/lsp-document-symbols.js +93 -0
  522. package/extensions/dm-lens/dist/clients/lsp-lazy.js +8 -0
  523. package/extensions/dm-lens/dist/clients/lsp-mutation.js +309 -0
  524. package/extensions/dm-lens/dist/clients/lsp-status.js +35 -0
  525. package/extensions/dm-lens/dist/clients/map-with-concurrency.js +20 -0
  526. package/extensions/dm-lens/dist/clients/mcp/analyze.js +265 -0
  527. package/extensions/dm-lens/dist/clients/mcp/host-shim.js +14 -0
  528. package/extensions/dm-lens/dist/clients/mcp/ipc.js +321 -0
  529. package/extensions/dm-lens/dist/clients/mcp/review.js +137 -0
  530. package/extensions/dm-lens/dist/clients/mcp/session.js +305 -0
  531. package/extensions/dm-lens/dist/clients/memory-sampler.js +145 -0
  532. package/extensions/dm-lens/dist/clients/message-end-attribution.js +18 -0
  533. package/extensions/dm-lens/dist/clients/metrics-client.js +80 -0
  534. package/extensions/dm-lens/dist/clients/metrics-history.js +255 -0
  535. package/extensions/dm-lens/dist/clients/middle-man-analysis.js +161 -0
  536. package/extensions/dm-lens/dist/clients/model-provider.js +31 -0
  537. package/extensions/dm-lens/dist/clients/module-report-lsp.js +140 -0
  538. package/extensions/dm-lens/dist/clients/module-report.js +1648 -0
  539. package/extensions/dm-lens/dist/clients/mutating-tool.js +386 -0
  540. package/extensions/dm-lens/dist/clients/mutation-attribution.js +176 -0
  541. package/extensions/dm-lens/dist/clients/mutation-bridge.js +231 -0
  542. package/extensions/dm-lens/dist/clients/ndjson-logger.js +504 -0
  543. package/extensions/dm-lens/dist/clients/observed-mutation-sources.js +43 -0
  544. package/extensions/dm-lens/dist/clients/observed-mutation.js +729 -0
  545. package/extensions/dm-lens/dist/clients/oldtext-autopatch.js +100 -0
  546. package/extensions/dm-lens/dist/clients/opaque-mutation-scan.js +340 -0
  547. package/extensions/dm-lens/dist/clients/opengrep-client.js +219 -0
  548. package/extensions/dm-lens/dist/clients/opengrep-config.js +52 -0
  549. package/extensions/dm-lens/dist/clients/package-manager.js +358 -0
  550. package/extensions/dm-lens/dist/clients/package-root.js +25 -0
  551. package/extensions/dm-lens/dist/clients/partial-edit-apply.js +337 -0
  552. package/extensions/dm-lens/dist/clients/path-attribution-telemetry.js +31 -0
  553. package/extensions/dm-lens/dist/clients/path-keyed-map.js +57 -0
  554. package/extensions/dm-lens/dist/clients/path-utils.js +535 -0
  555. package/extensions/dm-lens/dist/clients/performance-report.js +291 -0
  556. package/extensions/dm-lens/dist/clients/persist-debounce.js +37 -0
  557. package/extensions/dm-lens/dist/clients/persist-worker-stats.js +8 -0
  558. package/extensions/dm-lens/dist/clients/persistent-reverify.js +166 -0
  559. package/extensions/dm-lens/dist/clients/php-cs-fixer-config.js +15 -0
  560. package/extensions/dm-lens/dist/clients/pipeline.js +1279 -0
  561. package/extensions/dm-lens/dist/clients/post-autofix-notice.js +19 -0
  562. package/extensions/dm-lens/dist/clients/print-mode.js +3 -0
  563. package/extensions/dm-lens/dist/clients/probe-home-state.js +67 -0
  564. package/extensions/dm-lens/dist/clients/process-bridge.js +48 -0
  565. package/extensions/dm-lens/dist/clients/process-singletons.js +69 -0
  566. package/extensions/dm-lens/dist/clients/process-snapshot.js +130 -0
  567. package/extensions/dm-lens/dist/clients/project-changes.js +174 -0
  568. package/extensions/dm-lens/dist/clients/project-conventions.js +152 -0
  569. package/extensions/dm-lens/dist/clients/project-diagnostics/cache.js +91 -0
  570. package/extensions/dm-lens/dist/clients/project-diagnostics/extractors.js +53 -0
  571. package/extensions/dm-lens/dist/clients/project-diagnostics/fresh-fetch.js +413 -0
  572. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +64 -0
  573. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/dead-code.js +38 -0
  574. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +21 -0
  575. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/govulncheck.js +23 -0
  576. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/jscpd.js +28 -0
  577. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/knip.js +45 -0
  578. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/madge.js +34 -0
  579. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/opengrep.js +32 -0
  580. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +79 -0
  581. package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +41 -0
  582. package/extensions/dm-lens/dist/clients/project-diagnostics/scanner.js +349 -0
  583. package/extensions/dm-lens/dist/clients/project-diagnostics/types.js +1 -0
  584. package/extensions/dm-lens/dist/clients/project-lens-config.js +464 -0
  585. package/extensions/dm-lens/dist/clients/project-report.js +527 -0
  586. package/extensions/dm-lens/dist/clients/project-scale.js +60 -0
  587. package/extensions/dm-lens/dist/clients/project-scan-policy.js +4 -0
  588. package/extensions/dm-lens/dist/clients/project-snapshot-fingerprint.js +44 -0
  589. package/extensions/dm-lens/dist/clients/project-snapshot-persist-worker.js +13 -0
  590. package/extensions/dm-lens/dist/clients/project-snapshot.js +1333 -0
  591. package/extensions/dm-lens/dist/clients/project-trust.js +104 -0
  592. package/extensions/dm-lens/dist/clients/python-environment.js +162 -0
  593. package/extensions/dm-lens/dist/clients/python-provenance.js +551 -0
  594. package/extensions/dm-lens/dist/clients/quiet-window-config.js +16 -0
  595. package/extensions/dm-lens/dist/clients/quiet-window.js +129 -0
  596. package/extensions/dm-lens/dist/clients/read-bridge.js +53 -0
  597. package/extensions/dm-lens/dist/clients/read-expansion.js +218 -0
  598. package/extensions/dm-lens/dist/clients/read-guard-branch.js +126 -0
  599. package/extensions/dm-lens/dist/clients/read-guard-logger.js +186 -0
  600. package/extensions/dm-lens/dist/clients/read-guard-tool-lines.js +1050 -0
  601. package/extensions/dm-lens/dist/clients/read-guard.js +1429 -0
  602. package/extensions/dm-lens/dist/clients/recent-touches.js +126 -0
  603. package/extensions/dm-lens/dist/clients/redact/secrets.js +386 -0
  604. package/extensions/dm-lens/dist/clients/resource-sampler.js +344 -0
  605. package/extensions/dm-lens/dist/clients/reverse-deps.js +227 -0
  606. package/extensions/dm-lens/dist/clients/review-graph/builder.js +3708 -0
  607. package/extensions/dm-lens/dist/clients/review-graph/format.js +30 -0
  608. package/extensions/dm-lens/dist/clients/review-graph/git-identity.js +168 -0
  609. package/extensions/dm-lens/dist/clients/review-graph/import-resolvers.js +323 -0
  610. package/extensions/dm-lens/dist/clients/review-graph/persist-worker.js +8 -0
  611. package/extensions/dm-lens/dist/clients/review-graph/query.js +195 -0
  612. package/extensions/dm-lens/dist/clients/review-graph/revision-drift.js +3 -0
  613. package/extensions/dm-lens/dist/clients/review-graph/service.js +60 -0
  614. package/extensions/dm-lens/dist/clients/review-graph/shared-extraction-ir.js +54 -0
  615. package/extensions/dm-lens/dist/clients/review-graph/symbol-id.js +29 -0
  616. package/extensions/dm-lens/dist/clients/review-graph/tsconfig-paths.js +253 -0
  617. package/extensions/dm-lens/dist/clients/review-graph/types.js +1 -0
  618. package/extensions/dm-lens/dist/clients/review-graph/workspace-modules.js +374 -0
  619. package/extensions/dm-lens/dist/clients/review-graph-logger.js +51 -0
  620. package/extensions/dm-lens/dist/clients/ruff-client.js +109 -0
  621. package/extensions/dm-lens/dist/clients/rules-scanner.js +113 -0
  622. package/extensions/dm-lens/dist/clients/run-duration.js +9 -0
  623. package/extensions/dm-lens/dist/clients/runtime-agent-end.js +800 -0
  624. package/extensions/dm-lens/dist/clients/runtime-config.js +39 -0
  625. package/extensions/dm-lens/dist/clients/runtime-context.js +155 -0
  626. package/extensions/dm-lens/dist/clients/runtime-coordinator.js +1117 -0
  627. package/extensions/dm-lens/dist/clients/runtime-session.js +1768 -0
  628. package/extensions/dm-lens/dist/clients/runtime-tool-call.js +935 -0
  629. package/extensions/dm-lens/dist/clients/runtime-tool-result.js +1630 -0
  630. package/extensions/dm-lens/dist/clients/runtime-turn.js +2900 -0
  631. package/extensions/dm-lens/dist/clients/rust-client.js +48 -0
  632. package/extensions/dm-lens/dist/clients/safe-spawn.js +1275 -0
  633. package/extensions/dm-lens/dist/clients/sanitize.js +174 -0
  634. package/extensions/dm-lens/dist/clients/scan-utils.js +7 -0
  635. package/extensions/dm-lens/dist/clients/scanner-temp-root.js +8 -0
  636. package/extensions/dm-lens/dist/clients/scratch-tree-policy.js +63 -0
  637. package/extensions/dm-lens/dist/clients/search-read-registration.js +60 -0
  638. package/extensions/dm-lens/dist/clients/secret-findings.js +69 -0
  639. package/extensions/dm-lens/dist/clients/security-scan-client.js +208 -0
  640. package/extensions/dm-lens/dist/clients/session-event-guard.js +111 -0
  641. package/extensions/dm-lens/dist/clients/session-lifecycle.js +269 -0
  642. package/extensions/dm-lens/dist/clients/session-scope.js +451 -0
  643. package/extensions/dm-lens/dist/clients/session-start-observability.js +47 -0
  644. package/extensions/dm-lens/dist/clients/session-state-store.js +66 -0
  645. package/extensions/dm-lens/dist/clients/session-summary.js +8 -0
  646. package/extensions/dm-lens/dist/clients/sessionstart-logger.js +22 -0
  647. package/extensions/dm-lens/dist/clients/sg-runner.js +645 -0
  648. package/extensions/dm-lens/dist/clients/sgconfig.js +306 -0
  649. package/extensions/dm-lens/dist/clients/shared-checkout-guard.js +177 -0
  650. package/extensions/dm-lens/dist/clients/single-flight.js +52 -0
  651. package/extensions/dm-lens/dist/clients/situational-tool-telemetry.js +85 -0
  652. package/extensions/dm-lens/dist/clients/skills-resolver.js +38 -0
  653. package/extensions/dm-lens/dist/clients/slow-fs.js +77 -0
  654. package/extensions/dm-lens/dist/clients/smells-rollup.js +118 -0
  655. package/extensions/dm-lens/dist/clients/source-filter.js +320 -0
  656. package/extensions/dm-lens/dist/clients/source-walker.js +96 -0
  657. package/extensions/dm-lens/dist/clients/spawn-output-cap.js +35 -0
  658. package/extensions/dm-lens/dist/clients/spawn-timeout-cooldown.js +51 -0
  659. package/extensions/dm-lens/dist/clients/stale-marker.js +1 -0
  660. package/extensions/dm-lens/dist/clients/startup-scan.js +230 -0
  661. package/extensions/dm-lens/dist/clients/startup-timing.js +67 -0
  662. package/extensions/dm-lens/dist/clients/string-utils.js +6 -0
  663. package/extensions/dm-lens/dist/clients/subagent-mode.js +40 -0
  664. package/extensions/dm-lens/dist/clients/symbol-containment.js +16 -0
  665. package/extensions/dm-lens/dist/clients/symbol-types.js +1 -0
  666. package/extensions/dm-lens/dist/clients/test-runner-client.js +1697 -0
  667. package/extensions/dm-lens/dist/clients/test-runner-delivery.js +293 -0
  668. package/extensions/dm-lens/dist/clients/test-target-roots.js +17 -0
  669. package/extensions/dm-lens/dist/clients/todo-scanner.js +164 -0
  670. package/extensions/dm-lens/dist/clients/tool-agreement.js +640 -0
  671. package/extensions/dm-lens/dist/clients/tool-config.js +219 -0
  672. package/extensions/dm-lens/dist/clients/tool-cwd.js +235 -0
  673. package/extensions/dm-lens/dist/clients/tool-definition.js +22 -0
  674. package/extensions/dm-lens/dist/clients/tool-event.js +24 -0
  675. package/extensions/dm-lens/dist/clients/tool-policy.js +2393 -0
  676. package/extensions/dm-lens/dist/clients/tool-probe.js +13 -0
  677. package/extensions/dm-lens/dist/clients/tool-render.js +79 -0
  678. package/extensions/dm-lens/dist/clients/tool-set-policy.js +77 -0
  679. package/extensions/dm-lens/dist/clients/tree-sitter-cache.js +206 -0
  680. package/extensions/dm-lens/dist/clients/tree-sitter-client.js +3057 -0
  681. package/extensions/dm-lens/dist/clients/tree-sitter-logger.js +77 -0
  682. package/extensions/dm-lens/dist/clients/tree-sitter-navigator.js +198 -0
  683. package/extensions/dm-lens/dist/clients/tree-sitter-query-loader.js +389 -0
  684. package/extensions/dm-lens/dist/clients/tree-sitter-shared.js +87 -0
  685. package/extensions/dm-lens/dist/clients/tree-sitter-symbol-extractor.js +959 -0
  686. package/extensions/dm-lens/dist/clients/trivy-client.js +335 -0
  687. package/extensions/dm-lens/dist/clients/tui-fit.js +26 -0
  688. package/extensions/dm-lens/dist/clients/turn-context.js +48 -0
  689. package/extensions/dm-lens/dist/clients/turn-end/delivery-holds.js +59 -0
  690. package/extensions/dm-lens/dist/clients/turn-end/lane.js +1 -0
  691. package/extensions/dm-lens/dist/clients/turn-end/lanes/govulncheck.js +54 -0
  692. package/extensions/dm-lens/dist/clients/turn-end/lanes/secrets.js +131 -0
  693. package/extensions/dm-lens/dist/clients/turn-summary-render.js +56 -0
  694. package/extensions/dm-lens/dist/clients/turn-summary.js +84 -0
  695. package/extensions/dm-lens/dist/clients/typos-config.js +9 -0
  696. package/extensions/dm-lens/dist/clients/user-notify.js +15 -0
  697. package/extensions/dm-lens/dist/clients/vanished-instance-marker.js +18 -0
  698. package/extensions/dm-lens/dist/clients/warm-attach.js +210 -0
  699. package/extensions/dm-lens/dist/clients/widget-state.js +997 -0
  700. package/extensions/dm-lens/dist/clients/word-index-logger.js +21 -0
  701. package/extensions/dm-lens/dist/clients/word-index-store.js +222 -0
  702. package/extensions/dm-lens/dist/clients/word-index.js +1494 -0
  703. package/extensions/dm-lens/dist/clients/workspace-topology.js +268 -0
  704. package/extensions/dm-lens/dist/clients/write-ordering-guard.js +28 -0
  705. package/extensions/dm-lens/dist/clients/zizmor-config.js +160 -0
  706. package/extensions/dm-lens/dist/i18n.js +67 -0
  707. package/extensions/dm-lens/dist/index.js +1973 -0
  708. package/extensions/dm-lens/dist/mcp/analyze-cli.js +205 -0
  709. package/extensions/dm-lens/dist/mcp/build-staleness.js +55 -0
  710. package/extensions/dm-lens/dist/mcp/cli.js +96 -0
  711. package/extensions/dm-lens/dist/mcp/server.js +1239 -0
  712. package/extensions/dm-lens/dist/mcp/tool-arguments.js +134 -0
  713. package/extensions/dm-lens/dist/mcp/worker.js +41 -0
  714. package/extensions/dm-lens/dist/scripts/lib/process-scan.mjs +375 -0
  715. package/extensions/dm-lens/dist/scripts/lib/skills-predicate.mjs +53 -0
  716. package/extensions/dm-lens/dist/scripts/lib/web-tree-sitter-dir.mjs +51 -0
  717. package/extensions/dm-lens/dist/tools/activate-tools.js +62 -0
  718. package/extensions/dm-lens/dist/tools/ast-grep-outline.js +126 -0
  719. package/extensions/dm-lens/dist/tools/ast-grep-replace.js +227 -0
  720. package/extensions/dm-lens/dist/tools/ast-grep-search.js +687 -0
  721. package/extensions/dm-lens/dist/tools/effective-config.js +59 -0
  722. package/extensions/dm-lens/dist/tools/lens-diagnostic-mark.js +251 -0
  723. package/extensions/dm-lens/dist/tools/lens-diagnostics.js +1518 -0
  724. package/extensions/dm-lens/dist/tools/lsp-diagnostics.js +1198 -0
  725. package/extensions/dm-lens/dist/tools/lsp-navigation.js +1249 -0
  726. package/extensions/dm-lens/dist/tools/lsp-structured-output.js +277 -0
  727. package/extensions/dm-lens/dist/tools/module-report.js +332 -0
  728. package/extensions/dm-lens/dist/tools/project-report.js +72 -0
  729. package/extensions/dm-lens/dist/tools/render-compact.js +272 -0
  730. package/extensions/dm-lens/dist/tools/scan-progress.js +31 -0
  731. package/extensions/dm-lens/dist/tools/shared.js +32 -0
  732. package/extensions/dm-lens/dist/tools/symbol-search.js +133 -0
  733. package/extensions/dm-lens/i18n.js +3 -3
  734. package/extensions/dm-lens/index.js +431 -214
  735. package/extensions/dm-lens/mcp/analyze-cli.js +63 -36
  736. package/extensions/dm-lens/mcp/cli.js +20 -0
  737. package/extensions/dm-lens/mcp/server.js +40 -3
  738. package/extensions/dm-lens/mcp/tool-arguments.js +134 -0
  739. package/extensions/dm-lens/mcp/worker.js +8 -0
  740. package/extensions/dm-lens/package.json +1 -1
  741. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/advisory-registry-subset-test.yml +41 -0
  742. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/no-identity-operator-on-literals-test.yml +12 -2
  743. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/throw-new-error-js-test.yml +2 -0
  744. package/extensions/dm-lens/rules/ast-grep-rules/rule-tests/throw-new-error-test.yml +2 -0
  745. package/extensions/dm-lens/rules/ast-grep-rules/rules/advisory-registry-subset.yml +50 -0
  746. package/extensions/dm-lens/rules/ast-grep-rules/rules/no-identity-operator-on-literals.yml +20 -12
  747. package/extensions/dm-lens/rules/ast-grep-rules/rules/throw-new-error-js.yml +2 -2
  748. package/extensions/dm-lens/rules/ast-grep-rules/rules/throw-new-error.yml +2 -2
  749. package/extensions/dm-lens/scripts/lib/process-scan.mjs +126 -7
  750. package/extensions/dm-lens/scripts/lib/web-tree-sitter-dir.mjs +6 -0
  751. package/extensions/dm-lens/tools/activate-tools.js +3 -2
  752. package/extensions/dm-lens/tools/ast-grep-outline.js +2 -3
  753. package/extensions/dm-lens/tools/ast-grep-replace.js +6 -5
  754. package/extensions/dm-lens/tools/ast-grep-search.js +2 -2
  755. package/extensions/dm-lens/tools/lens-diagnostic-mark.js +12 -1
  756. package/extensions/dm-lens/tools/lens-diagnostics.js +74 -37
  757. package/extensions/dm-lens/tools/lsp-diagnostics.js +140 -25
  758. package/extensions/dm-lens/tools/lsp-navigation.js +64 -7
  759. package/extensions/dm-lens/tools/module-report.js +6 -6
  760. package/extensions/dm-lens/tools/shared.js +6 -0
  761. package/extensions/dm-mcp-adapter/THIRD_PARTY_NOTICES.md +1 -1
  762. package/extensions/dm-mcp-adapter/cli.js +265 -23
  763. package/extensions/dm-mcp-adapter/commands.js +83 -17
  764. package/extensions/dm-mcp-adapter/config.js +517 -92
  765. package/extensions/dm-mcp-adapter/direct-tool-surface.js +10 -8
  766. package/extensions/dm-mcp-adapter/direct-tools.js +54 -36
  767. package/extensions/dm-mcp-adapter/dist/abort.js +35 -0
  768. package/extensions/dm-mcp-adapter/dist/agent-dir.js +45 -0
  769. package/extensions/dm-mcp-adapter/dist/agent-plugin-loader.js +392 -0
  770. package/extensions/dm-mcp-adapter/dist/agent-plugin-provenance.js +26 -0
  771. package/extensions/dm-mcp-adapter/dist/bearer-command-resolver.js +182 -0
  772. package/extensions/dm-mcp-adapter/dist/claude-plugin-loader.js +350 -0
  773. package/extensions/dm-mcp-adapter/dist/config.js +1735 -0
  774. package/extensions/dm-mcp-adapter/dist/consent-manager.js +84 -0
  775. package/extensions/dm-mcp-adapter/dist/elicitation-handler.js +370 -0
  776. package/extensions/dm-mcp-adapter/dist/errors.js +225 -0
  777. package/extensions/dm-mcp-adapter/dist/http-ca.js +75 -0
  778. package/extensions/dm-mcp-adapter/dist/jev-client.js +359 -0
  779. package/extensions/dm-mcp-adapter/dist/jev-contracts.js +1 -0
  780. package/extensions/dm-mcp-adapter/dist/jev-key-store.js +189 -0
  781. package/extensions/dm-mcp-adapter/dist/json-schema-validator.js +70 -0
  782. package/extensions/dm-mcp-adapter/dist/lifecycle.js +387 -0
  783. package/extensions/dm-mcp-adapter/dist/logger.js +115 -0
  784. package/extensions/dm-mcp-adapter/dist/mcp-auth-fetch.js +86 -0
  785. package/extensions/dm-mcp-adapter/dist/mcp-auth-flow.js +956 -0
  786. package/extensions/dm-mcp-adapter/dist/mcp-auth.js +998 -0
  787. package/extensions/dm-mcp-adapter/dist/mcp-bearer-store.js +182 -0
  788. package/extensions/dm-mcp-adapter/dist/mcp-callback-server.js +380 -0
  789. package/extensions/dm-mcp-adapter/dist/mcp-oauth-provider.js +525 -0
  790. package/extensions/dm-mcp-adapter/dist/mcp-probe.js +151 -0
  791. package/extensions/dm-mcp-adapter/dist/mcp-tasks.js +300 -0
  792. package/extensions/dm-mcp-adapter/dist/mcp-trace.js +220 -0
  793. package/extensions/dm-mcp-adapter/dist/metadata-cache.js +323 -0
  794. package/extensions/dm-mcp-adapter/dist/npx-resolver.js +465 -0
  795. package/extensions/dm-mcp-adapter/dist/output-shape.js +312 -0
  796. package/extensions/dm-mcp-adapter/dist/package-mcp-loader.js +144 -0
  797. package/extensions/dm-mcp-adapter/dist/project-server-trust.js +186 -0
  798. package/extensions/dm-mcp-adapter/dist/request-headers-command.js +294 -0
  799. package/extensions/dm-mcp-adapter/dist/resource-tools.js +7 -0
  800. package/extensions/dm-mcp-adapter/dist/runtime-owner.js +94 -0
  801. package/extensions/dm-mcp-adapter/dist/sampling-handler.js +213 -0
  802. package/extensions/dm-mcp-adapter/dist/secure-keyring.js +191 -0
  803. package/extensions/dm-mcp-adapter/dist/server-manager.js +1594 -0
  804. package/extensions/dm-mcp-adapter/dist/session-approvals.js +127 -0
  805. package/extensions/dm-mcp-adapter/dist/session-recovery.js +83 -0
  806. package/extensions/dm-mcp-adapter/dist/state.js +1 -0
  807. package/extensions/dm-mcp-adapter/dist/ts-shape.js +157 -0
  808. package/extensions/dm-mcp-adapter/dist/types.js +286 -0
  809. package/extensions/dm-mcp-adapter/dist/ui-app-bridge-helpers.js +36 -0
  810. package/extensions/dm-mcp-adapter/dist/ui-resource-handler.js +204 -0
  811. package/extensions/dm-mcp-adapter/dist/ui-stream-types.js +58 -0
  812. package/extensions/dm-mcp-adapter/dist/ui-tool-visibility.js +26 -0
  813. package/extensions/dm-mcp-adapter/dist/unix-socket-transport.js +83 -0
  814. package/extensions/dm-mcp-adapter/dist/utils.js +418 -0
  815. package/extensions/dm-mcp-adapter/elicitation-handler.js +67 -2
  816. package/extensions/dm-mcp-adapter/failure-backoff.js +9 -0
  817. package/extensions/dm-mcp-adapter/host-managed.js +400 -0
  818. package/extensions/dm-mcp-adapter/http-ca.js +4 -0
  819. package/extensions/dm-mcp-adapter/index.js +347 -57
  820. package/extensions/dm-mcp-adapter/init.js +92 -44
  821. package/extensions/dm-mcp-adapter/jev-client.js +5 -5
  822. package/extensions/dm-mcp-adapter/jev-key-store.js +15 -2
  823. package/extensions/dm-mcp-adapter/mcp-auth-flow.js +10 -2
  824. package/extensions/dm-mcp-adapter/mcp-auth.js +2 -1
  825. package/extensions/dm-mcp-adapter/mcp-callback-server.js +1 -1
  826. package/extensions/dm-mcp-adapter/mcp-code.js +174 -87
  827. package/extensions/dm-mcp-adapter/mcp-keyring-helper.cjs +1 -1
  828. package/extensions/dm-mcp-adapter/mcp-oauth-provider.js +3 -2
  829. package/extensions/dm-mcp-adapter/mcp-output-guard.js +19 -5
  830. package/extensions/dm-mcp-adapter/mcp-panel.js +59 -12
  831. package/extensions/dm-mcp-adapter/mcp-script-wasm.js +22 -0
  832. package/extensions/dm-mcp-adapter/mcp-script-worker.mjs +227 -111
  833. package/extensions/dm-mcp-adapter/mcp-setup-panel.js +500 -258
  834. package/extensions/dm-mcp-adapter/mcp-status.js +9 -2
  835. package/extensions/dm-mcp-adapter/mcp-trace.js +5 -0
  836. package/extensions/dm-mcp-adapter/metadata-cache.js +68 -11
  837. package/extensions/dm-mcp-adapter/namespace-tools.js +20 -5
  838. package/extensions/dm-mcp-adapter/onboarding-state.js +11 -1
  839. package/extensions/dm-mcp-adapter/output-shape.js +312 -0
  840. package/extensions/dm-mcp-adapter/package-mcp-loader.js +15 -6
  841. package/extensions/dm-mcp-adapter/package.json +6 -15
  842. package/extensions/dm-mcp-adapter/panel-keys.js +13 -0
  843. package/extensions/dm-mcp-adapter/pi-builtin-mcp.js +26 -0
  844. package/extensions/dm-mcp-adapter/pi-signin-import.js +121 -0
  845. package/extensions/dm-mcp-adapter/project-server-trust.js +186 -0
  846. package/extensions/dm-mcp-adapter/prompts.js +80 -7
  847. package/extensions/dm-mcp-adapter/proxy-modes.js +219 -158
  848. package/extensions/dm-mcp-adapter/runtime-protocol.js +342 -0
  849. package/extensions/dm-mcp-adapter/search-ranking.js +8 -6
  850. package/extensions/dm-mcp-adapter/semantic-search.js +5 -4
  851. package/extensions/dm-mcp-adapter/server-manager.js +108 -26
  852. package/extensions/dm-mcp-adapter/session-recovery.js +3 -2
  853. package/extensions/dm-mcp-adapter/skills/mcp-scripting/SKILL.md +24 -28
  854. package/extensions/dm-mcp-adapter/skills/mcp-scripting/references/jev.md +3 -0
  855. package/extensions/dm-mcp-adapter/test-runner.mjs +1 -1
  856. package/extensions/dm-mcp-adapter/tool-approval.js +17 -7
  857. package/extensions/dm-mcp-adapter/tool-metadata.js +4 -2
  858. package/extensions/dm-mcp-adapter/tool-parameters.js +4 -0
  859. package/extensions/dm-mcp-adapter/tool-result-renderer.js +68 -7
  860. package/extensions/dm-mcp-adapter/ts-shape.js +1 -1
  861. package/extensions/dm-mcp-adapter/ui-server.js +24 -20
  862. package/extensions/dm-mcp-adapter/unix-socket-transport.js +1 -1
  863. package/extensions/dm-mcp-adapter/utils.js +37 -1
  864. package/extensions/dm-ponytail/extensions/ponytail.mjs +37 -17
  865. package/extensions/dm-ponytail/hooks/claude-codex-hooks.json +3 -3
  866. package/extensions/dm-ponytail/hooks/copilot-hooks.json +4 -4
  867. package/extensions/dm-ponytail/hooks/ponytail-activate.js +46 -13
  868. package/extensions/dm-ponytail/hooks/ponytail-config.js +6 -5
  869. package/extensions/dm-ponytail/hooks/ponytail-instructions.js +29 -33
  870. package/extensions/dm-ponytail/hooks/ponytail-map.js +116 -0
  871. package/extensions/dm-ponytail/hooks/ponytail-mode-tracker.js +26 -13
  872. package/extensions/dm-ponytail/hooks/ponytail-runtime.js +23 -9
  873. package/extensions/dm-ponytail/hooks/ponytail-subagent.js +15 -3
  874. package/extensions/dm-ponytail/hooks/qoder-hooks.json +3 -3
  875. package/extensions/dm-ponytail/package.json +1 -1
  876. package/extensions/dm-ponytail/pi-extension/index.js +37 -17
  877. package/extensions/dm-ponytail/pi-extension/package.json +1 -1
  878. package/extensions/dm-ponytail/skills/plugin.json +5 -0
  879. package/extensions/dm-ponytail/skills/ponytail/SKILL.md +33 -101
  880. package/extensions/dm-ponytail/skills/ponytail-audit/SKILL.md +89 -27
  881. package/extensions/dm-ponytail/skills/ponytail-debt/SKILL.md +13 -12
  882. package/extensions/dm-ponytail/skills/ponytail-gain/SKILL.md +21 -18
  883. package/extensions/dm-ponytail/skills/ponytail-help/SKILL.md +13 -14
  884. package/extensions/dm-ponytail/skills/ponytail-review/SKILL.md +96 -52
  885. package/extensions/dm-subagents/agents/oracle.md +8 -19
  886. package/extensions/dm-subagents/agents/researcher.md +0 -3
  887. package/extensions/dm-subagents/agents/reviewer.md +17 -61
  888. package/extensions/dm-subagents/agents/scout.md +1 -4
  889. package/extensions/dm-subagents/agents/worker.md +8 -25
  890. package/extensions/dm-subagents/index.js +5 -0
  891. package/extensions/dm-subagents/install.mjs +47 -62
  892. package/extensions/dm-subagents/package.json +6 -5
  893. package/extensions/dm-subagents/prompts/council.md +1 -1
  894. package/extensions/dm-subagents/prompts/review-loop.md +1 -1
  895. package/extensions/dm-subagents/skills/council-mode/SKILL.md +1 -1
  896. package/extensions/dm-subagents/skills/dm-subagents/SKILL.md +13 -6
  897. package/extensions/dm-subagents/skills/dm-subagents/references/constraints-and-recipes.md +3 -3
  898. package/extensions/dm-subagents/skills/dm-subagents/references/execution-controls.md +79 -78
  899. package/extensions/dm-subagents/skills/dm-subagents/references/management-authoring-rpc.md +18 -14
  900. package/extensions/dm-subagents/skills/dm-subagents/references/multi-lane-orchestration.md +1 -1
  901. package/extensions/dm-subagents/skills/dm-subagents/references/prompting-and-roles.md +46 -49
  902. package/extensions/dm-subagents/src/agents/advertised-agent-prompt.js +18 -32
  903. package/extensions/dm-subagents/src/agents/agent-management.js +7 -2
  904. package/extensions/dm-subagents/src/agents/agent-memory.js +3 -3
  905. package/extensions/dm-subagents/src/agents/agent-scope.js +3 -0
  906. package/extensions/dm-subagents/src/agents/agent-serializer.js +12 -1
  907. package/extensions/dm-subagents/src/agents/agents.js +217 -120
  908. package/extensions/dm-subagents/src/api/inspectors.js +10 -0
  909. package/extensions/dm-subagents/src/api/preflight.js +43 -6
  910. package/extensions/dm-subagents/src/extension/config.js +35 -2
  911. package/extensions/dm-subagents/src/extension/control-notices.js +3 -7
  912. package/extensions/dm-subagents/src/extension/declaration-pinning.js +127 -0
  913. package/extensions/dm-subagents/src/extension/doctor.js +4 -7
  914. package/extensions/dm-subagents/src/extension/fanout-child.js +15 -7
  915. package/extensions/dm-subagents/src/extension/herdr-dm-bridge.js +2 -0
  916. package/extensions/dm-subagents/src/extension/index.js +231 -332
  917. package/extensions/dm-subagents/src/extension/public-execution.js +63 -33
  918. package/extensions/dm-subagents/src/extension/reply-workflow-script.js +65 -0
  919. package/extensions/dm-subagents/src/extension/rpc.js +42 -16
  920. package/extensions/dm-subagents/src/extension/schemas.js +73 -152
  921. package/extensions/dm-subagents/src/extension/subagent-guide.js +92 -7
  922. package/extensions/dm-subagents/src/extension/subagent-options.js +47 -0
  923. package/extensions/dm-subagents/src/extension/tool-activation.js +57 -89
  924. package/extensions/dm-subagents/src/extension/tool-description.js +56 -47
  925. package/extensions/dm-subagents/src/extension/upgrade-notice.js +36 -0
  926. package/extensions/dm-subagents/src/inspectors/actions.js +34 -11
  927. package/extensions/dm-subagents/src/inspectors/plugins.js +71 -2
  928. package/extensions/dm-subagents/src/inspectors/tmux/actions.js +173 -0
  929. package/extensions/dm-subagents/src/inspectors/tmux/client.js +63 -0
  930. package/extensions/dm-subagents/src/inspectors/tmux/plugin.js +14 -0
  931. package/extensions/dm-subagents/src/integrations/herdr-status.js +26 -49
  932. package/extensions/dm-subagents/src/integrations/program-status.js +179 -0
  933. package/extensions/dm-subagents/src/intercom/native-supervisor-channel.js +77 -4
  934. package/extensions/dm-subagents/src/intercom/result-intercom.js +3 -2
  935. package/extensions/dm-subagents/src/intercom/supervisor-ui.js +2 -152
  936. package/extensions/dm-subagents/src/missions/goal-driver.js +47 -34
  937. package/extensions/dm-subagents/src/missions/store.js +33 -4
  938. package/extensions/dm-subagents/src/profiles/profiles.js +22 -15
  939. package/extensions/dm-subagents/src/runs/background/active-async-capacity.js +49 -6
  940. package/extensions/dm-subagents/src/runs/background/async-execution.js +301 -139
  941. package/extensions/dm-subagents/src/runs/background/async-job-tracker.js +65 -24
  942. package/extensions/dm-subagents/src/runs/background/async-resume.js +9 -3
  943. package/extensions/dm-subagents/src/runs/background/async-retention.js +40 -15
  944. package/extensions/dm-subagents/src/runs/background/await-async-run.js +68 -0
  945. package/extensions/dm-subagents/src/runs/background/binary-bootstrap.js +2 -1
  946. package/extensions/dm-subagents/src/runs/background/calendar-schedule.js +90 -0
  947. package/extensions/dm-subagents/src/runs/background/chain-root-attachment.js +11 -8
  948. package/extensions/dm-subagents/src/runs/background/control-channel.js +89 -5
  949. package/extensions/dm-subagents/src/runs/background/fleet-view.js +5 -5
  950. package/extensions/dm-subagents/src/runs/background/notify.js +170 -11
  951. package/extensions/dm-subagents/src/runs/background/pid-namespace.js +17 -0
  952. package/extensions/dm-subagents/src/runs/background/result-files.js +80 -6
  953. package/extensions/dm-subagents/src/runs/background/result-watcher.js +92 -65
  954. package/extensions/dm-subagents/src/runs/background/resume-guidance.js +2 -2
  955. package/extensions/dm-subagents/src/runs/background/run-child-session.js +34 -10
  956. package/extensions/dm-subagents/src/runs/background/run-id-resolver.js +8 -6
  957. package/extensions/dm-subagents/src/runs/background/run-status.js +25 -15
  958. package/extensions/dm-subagents/src/runs/background/runner-aliases.js +4 -2
  959. package/extensions/dm-subagents/src/runs/background/runner-child-launch.js +3 -0
  960. package/extensions/dm-subagents/src/runs/background/runner-http-dispatcher.js +2 -1
  961. package/extensions/dm-subagents/src/runs/background/scheduled-runs.js +270 -79
  962. package/extensions/dm-subagents/src/runs/background/stale-run-reconciler.js +18 -3
  963. package/extensions/dm-subagents/src/runs/background/subagent-runner-bootstrap.js +4 -1
  964. package/extensions/dm-subagents/src/runs/background/subagent-runner.js +123 -33
  965. package/extensions/dm-subagents/src/runs/background/subagent-wait.js +33 -20
  966. package/extensions/dm-subagents/src/runs/background/terminal-run-index.js +42 -1
  967. package/extensions/dm-subagents/src/runs/background/wait-completions.js +1 -0
  968. package/extensions/dm-subagents/src/runs/background/wait-tool.js +36 -26
  969. package/extensions/dm-subagents/src/runs/background/workflow-terminal-proof.js +39 -26
  970. package/extensions/dm-subagents/src/runs/foreground/async-stop-action.js +58 -26
  971. package/extensions/dm-subagents/src/runs/foreground/command-action.js +37 -0
  972. package/extensions/dm-subagents/src/runs/foreground/execution.js +132 -32
  973. package/extensions/dm-subagents/src/runs/foreground/foreground-history.js +1 -0
  974. package/extensions/dm-subagents/src/runs/foreground/prompt-audit.js +5 -5
  975. package/extensions/dm-subagents/src/runs/foreground/subagent-executor.js +683 -325
  976. package/extensions/dm-subagents/src/runs/shared/async-status-projection.js +3 -0
  977. package/extensions/dm-subagents/src/runs/shared/child-commands.js +252 -0
  978. package/extensions/dm-subagents/src/runs/shared/child-hooks.js +6 -5
  979. package/extensions/dm-subagents/src/runs/shared/child-launch.js +13 -1
  980. package/extensions/dm-subagents/src/runs/shared/child-session.js +183 -34
  981. package/extensions/dm-subagents/src/runs/shared/child-tool-plan.js +17 -14
  982. package/extensions/dm-subagents/src/runs/shared/claude-code-adapter.js +87 -1
  983. package/extensions/dm-subagents/src/runs/shared/dm-spawn.js +11 -85
  984. package/extensions/dm-subagents/src/runs/shared/dynamic-fanout.js +3 -0
  985. package/extensions/dm-subagents/src/runs/shared/effective-system-prompt.js +1 -2
  986. package/extensions/dm-subagents/src/runs/shared/external-cli-preflight.js +57 -6
  987. package/extensions/dm-subagents/src/runs/shared/external-cli-runner.js +6 -3
  988. package/extensions/dm-subagents/src/runs/shared/herdr-placed-run.js +13 -6
  989. package/extensions/dm-subagents/src/runs/shared/mcp-config-sources.js +1 -1
  990. package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-allowlist.js +66 -14
  991. package/extensions/dm-subagents/src/runs/shared/model-resolution-diagnostic.js +25 -5
  992. package/extensions/dm-subagents/src/runs/shared/model-resolution.js +55 -11
  993. package/extensions/dm-subagents/src/runs/shared/model-scope.js +23 -10
  994. package/extensions/dm-subagents/src/runs/shared/nested-events.js +3 -0
  995. package/extensions/dm-subagents/src/runs/shared/parallel-handoff.js +55 -7
  996. package/extensions/dm-subagents/src/runs/shared/partial-output.js +26 -0
  997. package/extensions/dm-subagents/src/runs/shared/run-history.js +41 -0
  998. package/extensions/dm-subagents/src/runs/shared/runner-launcher.js +21 -0
  999. package/extensions/dm-subagents/src/runs/shared/single-output.js +67 -26
  1000. package/extensions/dm-subagents/src/runs/shared/structured-output.js +24 -7
  1001. package/extensions/dm-subagents/src/runs/shared/subagent-control.js +32 -20
  1002. package/extensions/dm-subagents/src/runs/shared/subagent-prompt-runtime.js +68 -29
  1003. package/extensions/dm-subagents/src/runs/shared/tool-availability.js +1 -1
  1004. package/extensions/dm-subagents/src/runs/shared/workflow-async-child-guidance.js +1 -1
  1005. package/extensions/dm-subagents/src/runs/shared/worktree-cleanup-apply.js +169 -0
  1006. package/extensions/dm-subagents/src/runs/shared/worktree-cleanup-plan.js +41 -20
  1007. package/extensions/dm-subagents/src/runs/shared/worktree-lock.js +38 -0
  1008. package/extensions/dm-subagents/src/runs/shared/worktree.js +10 -1
  1009. package/extensions/dm-subagents/src/shared/atomic-json.js +2 -1
  1010. package/extensions/dm-subagents/src/shared/disabled-features.js +101 -0
  1011. package/extensions/dm-subagents/src/shared/dm-declarations.js +14 -0
  1012. package/extensions/dm-subagents/src/shared/dm-safeguards.js +41 -0
  1013. package/extensions/dm-subagents/src/shared/dm-settlement.js +48 -0
  1014. package/extensions/dm-subagents/src/shared/edit-distance.js +23 -0
  1015. package/extensions/dm-subagents/src/shared/extension-context.js +4 -0
  1016. package/extensions/dm-subagents/src/shared/file-lease.js +89 -0
  1017. package/extensions/dm-subagents/src/shared/fork-context.js +0 -1
  1018. package/extensions/dm-subagents/src/shared/formatters.js +1 -6
  1019. package/extensions/dm-subagents/src/shared/model-info.js +23 -0
  1020. package/extensions/dm-subagents/src/shared/package-version.js +12 -0
  1021. package/extensions/dm-subagents/src/shared/parent-wake.js +67 -0
  1022. package/extensions/dm-subagents/src/shared/pruned-fork.js +6 -2
  1023. package/extensions/dm-subagents/src/shared/required-child-extensions.js +35 -5
  1024. package/extensions/dm-subagents/src/shared/runtime-module-path.js +9 -0
  1025. package/extensions/dm-subagents/src/shared/settings-file-lease.js +31 -0
  1026. package/extensions/dm-subagents/src/shared/types.js +3 -1
  1027. package/extensions/dm-subagents/src/shared/utils.js +7 -7
  1028. package/extensions/dm-subagents/src/slash/prompt-template-bridge.js +2 -2
  1029. package/extensions/dm-subagents/src/slash/slash-commands.js +25 -15
  1030. package/extensions/dm-subagents/src/slash/subagent-cost.js +38 -7
  1031. package/extensions/dm-subagents/src/slash/subagents-admin.js +1 -1
  1032. package/extensions/dm-subagents/src/tui/dm-mouse-region.js +12 -0
  1033. package/extensions/dm-subagents/src/tui/fleet-status.js +12 -6
  1034. package/extensions/dm-subagents/src/tui/fleet-transcript.js +6 -2
  1035. package/extensions/dm-subagents/src/tui/fleet.js +20 -6
  1036. package/extensions/dm-subagents/src/tui/render.js +126 -72
  1037. package/extensions/dm-subagents/src/tui/running-tone.js +20 -0
  1038. package/extensions/dm-subagents/src/tui/subagent-messages.js +249 -0
  1039. package/extensions/dm-subagents/src/watchdog/diff-tool.js +19 -11
  1040. package/extensions/dm-subagents/src/watchdog/permission-arbiter.js +2 -2
  1041. package/extensions/dm-subagents/src/watchdog/register-child.js +2 -2
  1042. package/extensions/dm-subagents/src/watchdog/register-main.js +4 -24
  1043. package/extensions/dm-subagents/src/watchdog/render.js +1 -19
  1044. package/extensions/dm-subagents/src/watchdog/review.js +3 -3
  1045. package/extensions/dm-subagents/src/watchdog/runtime.js +6 -2
  1046. package/extensions/dm-subagents/src/watchdog/settings.js +22 -17
  1047. package/extensions/dm-subagents/src/watchdog/tool-actions.js +2 -2
  1048. package/extensions/dm-subagents/src/watchdog/turn-delta.js +1 -1
  1049. package/extensions/dm-subagents/src/workflows/chat-progress.js +2 -2
  1050. package/extensions/dm-subagents/src/workflows/scripted-workflow.js +116 -45
  1051. package/extensions/dm-subagents/src/workflows/structured-workflow-scripts.js +154 -0
  1052. package/extensions/dm-subagents/src/workflows/workflow-checklist.js +3 -0
  1053. package/extensions/dm-subagents/src/workflows/workflow-receipt.js +7 -4
  1054. package/extensions/dm-subagents/src/workflows/workflow-resources.js +52 -17
  1055. package/extensions/dm-subagents/src/workflows/workflow-reuse.js +87 -0
  1056. package/extensions/dm-subagents/src/workflows/workflow-revival.js +80 -0
  1057. package/extensions/dm-tty/control.js +150 -0
  1058. package/extensions/dm-tty/index.js +122 -0
  1059. package/extensions/dm-tty/package.json +20 -0
  1060. package/extensions/dm-tty/pty.js +213 -0
  1061. package/extensions/dm-tty/pty_bridge.py +266 -0
  1062. package/extensions/dm-tty/server.js +438 -0
  1063. package/extensions/dm-tty/sessions.js +97 -0
  1064. package/extensions/dm-tty/standalone.js +75 -0
  1065. package/extensions/dm-tty/web/client.js +1141 -0
  1066. package/extensions/dm-tty/web/index.html +117 -0
  1067. package/extensions/dm-tty/web/style.css +73 -0
  1068. package/extensions/dm-web-access/brave-rate-limit.js +160 -0
  1069. package/extensions/dm-web-access/brave.js +62 -11
  1070. package/extensions/dm-web-access/ceramic.js +197 -0
  1071. package/extensions/dm-web-access/chrome-cookies.js +69 -21
  1072. package/extensions/dm-web-access/curator-page.js +12 -2
  1073. package/extensions/dm-web-access/curator-server.js +10 -0
  1074. package/extensions/dm-web-access/declared-web-links.js +1 -1
  1075. package/extensions/dm-web-access/degoog.js +288 -0
  1076. package/extensions/dm-web-access/dist/index.js +28404 -0
  1077. package/extensions/dm-web-access/dist/mcp-cli.js +28186 -0
  1078. package/extensions/dm-web-access/duckduckgo.js +6 -3
  1079. package/extensions/dm-web-access/endpoint-pdf-extract.js +210 -0
  1080. package/extensions/dm-web-access/exa.js +17 -35
  1081. package/extensions/dm-web-access/extract.js +63 -10
  1082. package/extensions/dm-web-access/firecrawl.js +30 -4
  1083. package/extensions/dm-web-access/gemini-search.js +117 -37
  1084. package/extensions/dm-web-access/gemini-web.js +7 -7
  1085. package/extensions/dm-web-access/github-extract.js +28 -2
  1086. package/extensions/dm-web-access/github-issue-pr.js +88 -73
  1087. package/extensions/dm-web-access/index.js +230 -1161
  1088. package/extensions/dm-web-access/keenable.js +197 -0
  1089. package/extensions/dm-web-access/mcp-cli.js +30 -0
  1090. package/extensions/dm-web-access/mcp-server.js +51 -0
  1091. package/extensions/dm-web-access/mcp-tool-definitions.js +93 -0
  1092. package/extensions/dm-web-access/openai-search.js +70 -20
  1093. package/extensions/dm-web-access/opencode-session-headers.js +1 -1
  1094. package/extensions/dm-web-access/package.json +4 -1
  1095. package/extensions/dm-web-access/page-query.js +5 -10
  1096. package/extensions/dm-web-access/parallel-mcp.js +2 -1
  1097. package/extensions/dm-web-access/pdf-extract.js +34 -1
  1098. package/extensions/dm-web-access/perplexity.js +68 -51
  1099. package/extensions/dm-web-access/query-rewrite.js +3 -4
  1100. package/extensions/dm-web-access/scripts/build.js +8 -0
  1101. package/extensions/dm-web-access/ssrf-protection.js +10 -8
  1102. package/extensions/dm-web-access/storage.js +79 -76
  1103. package/extensions/dm-web-access/summary-model-scope.js +5 -64
  1104. package/extensions/dm-web-access/summary-review.js +35 -9
  1105. package/extensions/dm-web-access/tavily.js +69 -22
  1106. package/extensions/dm-web-access/tool-activation.js +44 -26
  1107. package/extensions/dm-web-access/tool-arguments.js +21 -0
  1108. package/extensions/dm-web-access/utils.js +17 -7
  1109. package/extensions/dm-web-access/video-extract.js +1 -1
  1110. package/extensions/dm-web-access/web-tool-contract.js +0 -0
  1111. package/extensions/dm-web-access/web-tool-core.js +1312 -0
  1112. package/extensions/dm-web-access/you.js +155 -0
  1113. package/extensions/dm-web-access/youtube-extract.js +2 -2
  1114. package/extensions/dm-web-access/zai.js +159 -0
  1115. package/package.json +13 -9
@@ -16,9 +16,9 @@ import {
16
16
  recordDegradation,
17
17
  recordDegradationOnce
18
18
  } from "../degradation-ledger.js";
19
+ import { assertInstallAllowed } from "../project-trust.js";
19
20
  import {
20
21
  isLspSpawnAllowedByTrust,
21
- assertInstallAllowed,
22
22
  projectTrustDenialReason
23
23
  } from "../project-trust.js";
24
24
  import { shouldPreferPullOnlyDiagnostics } from "../lsp-budget.js";
@@ -36,6 +36,7 @@ import {
36
36
  fingerprintDocumentContent
37
37
  } from "./document-drift.js";
38
38
  import {
39
+ captureAuxPublicationBacklog,
39
40
  markPendingAuxiliaryCoverage,
40
41
  napiFallbackCoveredSince
41
42
  } from "./pending-aux-coverage.js";
@@ -65,31 +66,68 @@ import {
65
66
  getSessionRootsForTelemetry,
66
67
  isOutsideAllSessionRoots
67
68
  } from "./session-roots.js";
68
- import { getProcessSingleton } from "../process-singletons.js";
69
+ import {
70
+ findLocalBinUpwards,
71
+ isProjectLocalBinPath
72
+ } from "../package-manager.js";
73
+ import {
74
+ resolveAnalysisRoot,
75
+ resolveAnalysisRootPath
76
+ } from "../analysis-root.js";
77
+ import {
78
+ configureLspServiceLifecycle,
79
+ getOwnedLspService,
80
+ peekOwnedLspService,
81
+ resetOwnedLspService
82
+ } from "./service-singleton.js";
83
+ import { groupFilesByPrimaryServer, runPerServerGroups } from "./grouping.js";
84
+ export { groupFilesByPrimaryServer, runPerServerGroups } from "./grouping.js";
85
+ import { isEphemeralCheckoutRoot } from "../ephemeral-root.js";
69
86
  import { getLanguageId } from "./language.js";
70
87
  import {
71
88
  getReverseDepsFromIndex,
72
89
  loadReverseDependencyIndexFromSnapshot
73
90
  } from "../reverse-deps.js";
91
+ import { isSameOrWithin } from "./server.js";
92
+ import {
93
+ refuseUntrustedLspExecution,
94
+ withLspProjectCodePermission
95
+ } from "./launch.js";
74
96
  import {
75
- LSP_SERVERS,
76
97
  enforceLspRootCeiling,
98
+ getServerById,
77
99
  hasProjectBoundaryMarker,
78
100
  isDirectLspCommandTemporarilyUnavailable,
79
101
  resetClassicTsRepairGuard,
80
102
  resetLspLaunchAvailabilityGeneration,
81
103
  resolveLspServerCwd
82
104
  } from "./server.js";
105
+ import { isAuxiliary, serverTraits } from "./server-traits.js";
106
+ import {
107
+ auxWaitBudgetMs,
108
+ readEnvAuxGraceMs,
109
+ DEFAULT_AUX_GRACE_CEILING_MS
110
+ } from "./auxiliary-lifecycle.js";
83
111
  import {
84
112
  classifyCascadeWaitTier,
85
113
  classifyServerWaitTier,
86
114
  getStrategy
87
115
  } from "./wait-policy/index.js";
116
+ function textDocumentSaveOf(client) {
117
+ if (typeof client.getSaveOptions !== "function")
118
+ return;
119
+ const save = client.getSaveOptions();
120
+ if (!save)
121
+ return "none";
122
+ return save.includeText ? "save+text" : "save";
123
+ }
88
124
  const WORKSPACE_ATTRIBUTION_CLIENT_CAP = 16;
89
125
  const AUX_WAIT_DEMOTION_THRESHOLD = 5;
90
126
  const AUX_WAIT_DEMOTION_RATIO = 0.9;
91
127
  const AUX_WAIT_REPROMOTION_THRESHOLD = 5;
92
128
  const AUX_WAIT_REPROMOTION_RATIO = 0.5;
129
+ const ADOPTED_ROOT_CAP = 2;
130
+ const ADOPTED_ROOT_IDLE_EVICT_MS = 60000;
93
131
  import { raceToCompletion } from "./aggregation.js";
94
132
  import {
95
133
  applyWorkspaceEdit,
@@ -187,10 +225,25 @@ async function runRenameNotify(send, timeoutMs) {
187
225
  }
188
226
  }
189
227
  const DEFAULT_LSP_CLIENT_CEILING = 24;
190
- const DEFAULT_TS_IDLE_EVICT_MS = 20 * 60000;
191
- export function getTypeScriptIdleEvictMs() {
192
- const parsed = Number.parseInt(process.env.DM_LENS_TS_IDLE_EVICT_MS ?? "", 10);
193
- return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : DEFAULT_TS_IDLE_EVICT_MS;
228
+ const DEFAULT_IDLE_EVICT_MS = 20 * 60000;
229
+ const DEFAULT_EPHEMERAL_IDLE_EVICT_MS = 60000;
230
+ export function getLspIdleEvictMs() {
231
+ for (const name of [
232
+ "DM_LENS_LSP_IDLE_EVICT_MS",
233
+ "DM_LENS_TS_IDLE_EVICT_MS"
234
+ ]) {
235
+ const parsed = Number.parseInt(process.env[name] ?? "", 10);
236
+ if (Number.isSafeInteger(parsed) && parsed > 0)
237
+ return parsed;
238
+ }
239
+ return DEFAULT_IDLE_EVICT_MS;
240
+ }
241
+ function getEphemeralLspIdleEvictMs() {
242
+ const parsed = Number.parseInt(process.env.DM_LENS_EPHEMERAL_LSP_IDLE_EVICT_MS ?? "", 10);
243
+ return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : DEFAULT_EPHEMERAL_IDLE_EVICT_MS;
244
+ }
245
+ export function getLspIdleEvictMsForRoot(root) {
246
+ return isEphemeralCheckoutRoot(root) ? getEphemeralLspIdleEvictMs() : getLspIdleEvictMs();
194
247
  }
195
248
  export function getLspClientCeiling() {
196
249
  const parsed = Number.parseInt(process.env.DM_LENS_LSP_CLIENT_CEILING ?? "", 10);
@@ -206,6 +259,12 @@ function documentIsOpenOn(client, filePath) {
206
259
  return false;
207
260
  }
208
261
  }
262
+ function tsserverSyncChannel(client) {
263
+ return {
264
+ getAdvertisedCommands: async () => client.getAdvertisedCommands(),
265
+ executeCommand: (_filePath, command, args) => client.executeCommand(command, args)
266
+ };
267
+ }
209
268
  function warmupTimeoutMs() {
210
269
  const raw = Number.parseInt(process.env.DM_LENS_LSP_WARMUP_TIMEOUT_MS ?? "", 10);
211
270
  return Number.isFinite(raw) && raw > 0 ? raw : 20000;
@@ -232,28 +291,7 @@ function readTsserverSyncGraceMs() {
232
291
  return 300;
233
292
  return parsed;
234
293
  }
235
- function readEnvAuxGraceMs() {
236
- const raw = process.env.DM_LENS_AUX_GRACE_MS;
237
- if (raw === undefined)
238
- return;
239
- const parsed = Number.parseInt(raw, 10);
240
- if (!Number.isFinite(parsed) || parsed < 0)
241
- return;
242
- return parsed;
243
- }
244
- const DEFAULT_AUX_GRACE_CEILING_MS = 2000;
245
- const MAX_ADAPTIVE_AUX_GRACE_CEILING_MS = 8000;
246
- const ADAPTIVE_AUX_GRACE_MARGIN_MS = 500;
247
- export function auxWaitBudgetMs(serverId, isCold, configuredCeilingMs, declaredWaitMs) {
248
- if (configuredCeilingMs !== undefined || !isCold) {
249
- return Math.min(declaredWaitMs, configuredCeilingMs ?? DEFAULT_AUX_GRACE_CEILING_MS);
250
- }
251
- const observedSpawnMs = getSuccessfulLspSpawnDurationMs(serverId);
252
- if (observedSpawnMs === undefined || observedSpawnMs <= 0) {
253
- return Math.min(declaredWaitMs, DEFAULT_AUX_GRACE_CEILING_MS);
254
- }
255
- return Math.min(MAX_ADAPTIVE_AUX_GRACE_CEILING_MS, Math.max(declaredWaitMs, observedSpawnMs + ADAPTIVE_AUX_GRACE_MARGIN_MS));
256
- }
294
+ const MAX_TOUCH_CANDIDATES = 8;
257
295
  const DIAGNOSTICS_SEMANTIC_SETTLE_THRESHOLD_MS = Math.max(0, Number.parseInt(process.env.DM_LENS_LSP_DIAGNOSTICS_SEMANTIC_THRESHOLD_MS ?? "250", 10) || 250);
258
296
  const DIAGNOSTICS_SEMANTIC_SETTLE_WAIT_MS = Math.max(0, Number.parseInt(process.env.DM_LENS_LSP_DIAGNOSTICS_SEMANTIC_SETTLE_MS ?? "400", 10) || 400);
259
297
  const EARLY_UNBLOCK_GRACE_MS = Math.max(0, Number.parseInt(process.env.DM_LENS_LSP_EARLY_UNBLOCK_GRACE_MS ?? "400", 10) || 400);
@@ -276,25 +314,6 @@ function mergeLspDiagnostics(diagnostics) {
276
314
  function attributeDiagnostics(serverId, diagnostics) {
277
315
  return diagnostics.map((diagnostic) => ({ ...diagnostic, serverId }));
278
316
  }
279
- export function groupFilesByPrimaryServer(files) {
280
- const byServer = new Map;
281
- for (const filePath of files) {
282
- const servers = getServersForFileWithConfig(filePath);
283
- const primary = servers[0]?.id ?? "none";
284
- const group = byServer.get(primary);
285
- if (group) {
286
- group.files.push(filePath);
287
- if (servers.length > 1)
288
- group.multiServer = true;
289
- } else {
290
- byServer.set(primary, {
291
- files: [filePath],
292
- multiServer: servers.length > 1
293
- });
294
- }
295
- }
296
- return [...byServer.values()];
297
- }
298
317
  export function createSweepIndexGate() {
299
318
  const seen = new Set;
300
319
  return {
@@ -306,20 +325,6 @@ export function createSweepIndexGate() {
306
325
  }
307
326
  };
308
327
  }
309
- export async function runPerServerGroups(groups, concurrency, processGroup, signal) {
310
- let nextGroup = 0;
311
- const workers = Math.min(Math.max(1, concurrency), groups.length);
312
- await Promise.all(Array.from({ length: workers }, async () => {
313
- while (!signal?.aborted) {
314
- const gi = nextGroup;
315
- nextGroup += 1;
316
- if (gi >= groups.length)
317
- break;
318
- await processGroup(groups[gi]);
319
- }
320
- return true;
321
- }));
322
- }
323
328
  const WORKSPACE_DIAGNOSTICS_CONCURRENCY = 8;
324
329
  const WORKSPACE_SWEEP_PREOPEN_CHUNK_SIZE = (() => {
325
330
  const raw = Number(process.env.DM_LENS_LSP_WORKSPACE_PREOPEN_CHUNK);
@@ -333,7 +338,7 @@ function notifyWriteBudgetMs() {
333
338
  return Number.isFinite(raw) && raw > 0 ? raw : 2000;
334
339
  }
335
340
  function primaryServerWaitFloorMs(filePath, maxWaitMs) {
336
- const serverWaitOverrideMs = getServersForFileWithConfig(filePath).filter((s) => s.role !== "auxiliary").reduce((max, server) => Math.max(max, server.clientWaitTimeoutMs ?? 0), 0);
341
+ const serverWaitOverrideMs = getServersForFileWithConfig(filePath).filter((s) => !isAuxiliary(s)).reduce((max, server) => Math.max(max, server.clientWaitTimeoutMs ?? 0), 0);
337
342
  return Math.max(maxWaitMs ?? 0, serverWaitOverrideMs);
338
343
  }
339
344
  const NOTIFY_WEDGED_BUDGET_MULTIPLIER = 5;
@@ -351,15 +356,6 @@ function notifyStallCpuSampleMs() {
351
356
  return Number.isFinite(raw) && raw > 0 ? raw : 1200;
352
357
  }
353
358
  const NOTIFY_STALL_CPU_BUSY_FLOOR_PERCENT = 10;
354
- const AUX_NOTIFY_INFLIGHT_DEFAULT = 8;
355
- function auxNotifyInflightLimit(info) {
356
- const perServer = info.notifyInflightLimit;
357
- if (typeof perServer === "number" && Number.isFinite(perServer) && perServer > 0) {
358
- return Math.floor(perServer);
359
- }
360
- const raw = Number(process.env.DM_LENS_LSP_AUX_NOTIFY_INFLIGHT);
361
- return Number.isFinite(raw) && raw > 0 ? Math.floor(raw) : AUX_NOTIFY_INFLIGHT_DEFAULT;
362
- }
363
359
  function workspacePullBudgetMs() {
364
360
  const raw = Number(process.env.DM_LENS_LSP_WORKSPACE_PULL_MS);
365
361
  return Number.isFinite(raw) && raw > 0 ? raw : 30000;
@@ -408,8 +404,10 @@ async function collectWorkspaceDiagnosticFiles(root, maxFiles = getMaxWorkspaceD
408
404
  }
409
405
 
410
406
  export class LSPService {
407
+ static MAX_SIBLING_ANNOUNCEMENTS = 1024;
411
408
  sessionCwd;
412
409
  state;
410
+ siblingAnnouncementHashes = new BoundedFifoMap(LSPService.MAX_SIBLING_ANNOUNCEMENTS);
413
411
  workspaceProbeLogged = new Set;
414
412
  projectBoundaryCache = new Map;
415
413
  warmStartLogged = new Set;
@@ -439,8 +437,10 @@ export class LSPService {
439
437
  static MAX_NOTIFY_STALL_DEMOTIONS = 50;
440
438
  notifyStallDemotions = new BoundedFifoMap(LSPService.MAX_NOTIFY_STALL_DEMOTIONS);
441
439
  clientLastUsedAt = new Map;
440
+ adoptedRootLastUsedAt = new Map;
441
+ adoptedClientKeys = new Set;
442
442
  clientLeases = new Map;
443
- typeScriptIdleTimers = new Map;
443
+ idleEvictionTimers = new Map;
444
444
  clientSpawnGate = Promise.resolve();
445
445
  isDestroyed = false;
446
446
  shutdownController = new AbortController;
@@ -507,11 +507,77 @@ export class LSPService {
507
507
  reason: "auxiliary produced five consecutive late answers below half its declared wait budget"
508
508
  });
509
509
  }
510
+ analysisRootModeForFile(filePath) {
511
+ const roots = getSessionRootsForTelemetry(128);
512
+ if (this.sessionCwd)
513
+ roots.push(this.sessionCwd);
514
+ let adopted = false;
515
+ for (const root of new Set(roots)) {
516
+ const mode = resolveAnalysisRoot(filePath, root);
517
+ if (mode === "session" || mode === "linked-worktree")
518
+ return mode;
519
+ adopted ||= mode === "adopted";
520
+ }
521
+ return adopted ? "adopted" : "none";
522
+ }
523
+ fileIsOutsideRegisteredRoots(filePath) {
524
+ const roots = getSessionRootsForTelemetry(128);
525
+ if (roots.length === 0)
526
+ return isOutsideAllSessionRoots(filePath);
527
+ return !roots.some((root) => isSameOrWithin(root, filePath));
528
+ }
529
+ admitAdoptedRoot(root, filePath) {
530
+ if (this.analysisRootModeForFile(filePath) !== "adopted")
531
+ return false;
532
+ const normalized = normalizeMapKey(root);
533
+ const liveRoots = new Set;
534
+ for (const key of this.state.clients.keys()) {
535
+ if (this.adoptedClientKeys.has(key))
536
+ liveRoots.add(key.slice(key.indexOf(":") + 1));
537
+ }
538
+ for (const root of this.adoptedRootLastUsedAt.keys()) {
539
+ if (!liveRoots.has(root))
540
+ this.adoptedRootLastUsedAt.delete(root);
541
+ }
542
+ if (liveRoots.has(normalized)) {
543
+ this.adoptedRootLastUsedAt.set(normalized, Date.now());
544
+ return true;
545
+ }
546
+ if (this.adoptedRootLastUsedAt.size < ADOPTED_ROOT_CAP) {
547
+ this.adoptedRootLastUsedAt.set(normalized, Date.now());
548
+ return true;
549
+ }
550
+ this.adoptedRootLastUsedAt.set(normalized, Date.now());
551
+ const victim = [...this.adoptedRootLastUsedAt.keys()].sort((a, b) => (this.adoptedRootLastUsedAt.get(a) ?? 0) - (this.adoptedRootLastUsedAt.get(b) ?? 0)).find((candidate) => candidate !== normalized);
552
+ if (!victim)
553
+ return true;
554
+ this.adoptedRootLastUsedAt.delete(victim);
555
+ for (const [key, client] of this.state.clients) {
556
+ if (!this.adoptedClientKeys.has(key) || !key.endsWith(`:${victim}`))
557
+ continue;
558
+ if ((this.clientLeases.get(key) ?? 0) > 0)
559
+ continue;
560
+ this.retireClient(key);
561
+ client.shutdown({ reason: "adopted-root-lru" }).catch(() => {});
562
+ }
563
+ incrementDegradationCount({
564
+ kind: "lsp-adopted-root-evicted",
565
+ subject: victim,
566
+ reason: `adopted root cap ${ADOPTED_ROOT_CAP} evicted ${victim}`
567
+ });
568
+ return true;
569
+ }
510
570
  async resolveServerRoot(server, filePath, onRootFailure) {
511
571
  const candidate = await resolveLspServerCwd(server, filePath, this.sessionCwd ?? process.cwd(), onRootFailure);
512
572
  if (!candidate)
513
573
  return;
514
- if (isOutsideAllSessionRoots(filePath))
574
+ const mode = this.analysisRootModeForFile(filePath);
575
+ if (mode === "adopted") {
576
+ const classifierRoot = resolveAnalysisRootPath(filePath, this.sessionCwd ?? process.cwd());
577
+ if (!classifierRoot || normalizeMapKey(classifierRoot) !== normalizeMapKey(candidate))
578
+ return;
579
+ }
580
+ if (this.fileIsOutsideRegisteredRoots(filePath) && this.analysisRootModeForFile(filePath) !== "adopted")
515
581
  return;
516
582
  const root = enforceLspRootCeiling(candidate, process.cwd(), filePath);
517
583
  if (normalizeMapKey(root) === normalizeMapKey(process.cwd()))
@@ -549,6 +615,32 @@ export class LSPService {
549
615
  checkDestroyed() {
550
616
  return this.isDestroyed;
551
617
  }
618
+ announceToSiblings(filePath, content, contentHash = this.hashContent(content)) {
619
+ const normalizedPath = normalizeMapKey(filePath);
620
+ if (this.siblingAnnouncementHashes.get(normalizedPath) === contentHash) {
621
+ return Promise.resolve();
622
+ }
623
+ return Promise.all(getServersForFileWithConfig(filePath).map((server) => this.resolveServerRoot(server, filePath).then((root) => {
624
+ if (!root)
625
+ return false;
626
+ const ownKey = `${server.id}:${normalizeMapKey(root)}`;
627
+ return this.notifyLiveClientsForServer(server.id, filePath, 2, ownKey, false);
628
+ }))).then(() => {
629
+ this.siblingAnnouncementHashes.set(normalizedPath, contentHash);
630
+ });
631
+ }
632
+ notifyLiveClientsForServer(serverId, filePath, type, ownKey, includeOwn) {
633
+ let notified = false;
634
+ const prefix = `${serverId}:`;
635
+ for (const [key, client] of this.state.clients) {
636
+ if (!key.startsWith(prefix) || !includeOwn && key === ownKey || !client.isAlive()) {
637
+ continue;
638
+ }
639
+ client.notify.watchedFileChange(filePath, type);
640
+ notified = true;
641
+ }
642
+ return notified;
643
+ }
552
644
  async withClientSpawnGate(operation) {
553
645
  const previous = this.clientSpawnGate;
554
646
  let release;
@@ -590,10 +682,10 @@ export class LSPService {
590
682
  for (const [key] of keyed) {
591
683
  this.clientLeases.set(key, (this.clientLeases.get(key) ?? 0) + 1);
592
684
  }
593
- return keyed.map(([key]) => key);
685
+ return keyed.map(([key, entry]) => ({ key, server: entry.info }));
594
686
  });
595
687
  }
596
- releaseClientLease(key) {
688
+ releaseClientLease(key, server) {
597
689
  const remaining = (this.clientLeases.get(key) ?? 1) - 1;
598
690
  if (remaining > 0) {
599
691
  this.clientLeases.set(key, remaining);
@@ -602,7 +694,7 @@ export class LSPService {
602
694
  this.clientLeases.delete(key);
603
695
  if (this.state.clients.has(key)) {
604
696
  this.clientLastUsedAt.set(key, Date.now());
605
- this.scheduleTypeScriptIdleEviction(key);
697
+ this.scheduleIdleEviction(key, server);
606
698
  }
607
699
  }
608
700
  async withClientForFileUse(filePath, maxWaitMs, hardCapMs, use) {
@@ -616,7 +708,7 @@ export class LSPService {
616
708
  try {
617
709
  return await use(entry);
618
710
  } finally {
619
- this.releaseClientLease(leaseKey);
711
+ this.releaseClientLease(leaseKey, entry.info);
620
712
  }
621
713
  }
622
714
  return;
@@ -639,20 +731,30 @@ export class LSPService {
639
731
  const [victimKey, victimClient] = victim;
640
732
  this.releaseOutstandingAuxNotifyWrite(victimKey);
641
733
  await victimClient.shutdown({ reason: "client_ceiling_lru" });
642
- this.state.clients.delete(victimKey);
643
- this.state.clientSpawnedAt.delete(victimKey);
644
- this.state.demonstratedReady.delete(victimKey);
645
- this.state.demonstratedCold.delete(victimKey);
646
- this.clientLastUsedAt.delete(victimKey);
647
- this.clearTypeScriptIdleTimer(victimKey);
734
+ this.retireClient(victimKey);
648
735
  logSessionStart(`lsp client ceiling ${getLspClientCeiling()}: evicted idle LRU ${victimKey}`);
649
736
  return true;
650
737
  }
651
- clearTypeScriptIdleTimer(key) {
652
- const timer = this.typeScriptIdleTimers.get(key);
738
+ clearIdleEvictionTimer(key) {
739
+ const timer = this.idleEvictionTimers.get(key);
653
740
  if (timer)
654
741
  clearTimeout(timer);
655
- this.typeScriptIdleTimers.delete(key);
742
+ this.idleEvictionTimers.delete(key);
743
+ }
744
+ retireClient(key) {
745
+ this.releaseOutstandingAuxNotifyWrite(key);
746
+ this.state.clients.delete(key);
747
+ this.state.clientSpawnedAt.delete(key);
748
+ this.forgetReadiness(key);
749
+ this.clientLastUsedAt.delete(key);
750
+ if (this.adoptedClientKeys.delete(key)) {
751
+ const root = key.slice(key.indexOf(":") + 1);
752
+ if (![...this.adoptedClientKeys].some((candidate) => candidate.endsWith(`:${root}`)))
753
+ this.adoptedRootLastUsedAt.delete(root);
754
+ }
755
+ this.clearIdleEvictionTimer(key);
756
+ this.auxNotifyInflight.delete(key);
757
+ this.auxNotifyDrainLatencyEwma.delete(key);
656
758
  }
657
759
  releaseOutstandingAuxNotifyWrite(key, token) {
658
760
  const current = this.outstandingAuxNotifyWrites.get(key);
@@ -662,13 +764,15 @@ export class LSPService {
662
764
  this.outstandingAuxNotifyWrites.delete(key);
663
765
  current.resolveSettled();
664
766
  }
665
- scheduleTypeScriptIdleEviction(key) {
666
- if (!key.startsWith("typescript:"))
767
+ scheduleIdleEviction(key, server) {
768
+ if (server.idleEviction !== "transparent" && !this.adoptedClientKeys.has(key))
667
769
  return;
668
- this.clearTypeScriptIdleTimer(key);
770
+ this.clearIdleEvictionTimer(key);
669
771
  const lastUsedAt = this.clientLastUsedAt.get(key) ?? Date.now();
772
+ const root = key.slice(key.indexOf(":") + 1);
773
+ const idleMs = this.adoptedClientKeys.has(key) ? ADOPTED_ROOT_IDLE_EVICT_MS : getLspIdleEvictMsForRoot(root);
670
774
  const timer = setTimeout(() => {
671
- this.typeScriptIdleTimers.delete(key);
775
+ this.idleEvictionTimers.delete(key);
672
776
  this.withClientSpawnGate(async () => {
673
777
  if (this.isDestroyed)
674
778
  return;
@@ -676,43 +780,32 @@ export class LSPService {
676
780
  if (!client?.isAlive())
677
781
  return;
678
782
  if (client.isBusy?.() === true || (this.clientLeases.get(key) ?? 0) > 0 || (this.clientLastUsedAt.get(key) ?? 0) !== lastUsedAt) {
679
- this.scheduleTypeScriptIdleEviction(key);
783
+ this.scheduleIdleEviction(key, server);
680
784
  return;
681
785
  }
682
- this.releaseOutstandingAuxNotifyWrite(key);
683
- this.state.clients.delete(key);
684
- this.state.clientSpawnedAt.delete(key);
685
- this.state.demonstratedReady.delete(key);
686
- this.state.demonstratedCold.delete(key);
687
- this.clientLastUsedAt.delete(key);
786
+ this.retireClient(key);
688
787
  try {
689
- await client.shutdown({ reason: "typescript_idle_eviction" });
788
+ await client.shutdown({ reason: "idle_eviction" });
690
789
  } catch {}
691
- logSessionStart(`lsp typescript idle eviction: released ${key}`);
790
+ logSessionStart(`lsp idle eviction: released ${key}`);
692
791
  recordDegradation({
693
- kind: "ts-idle-eviction",
792
+ kind: "lsp-idle-eviction",
694
793
  subject: key,
695
- reason: "idle TypeScript client released to bound memory"
794
+ reason: "idle LSP client released to bound memory"
696
795
  });
697
796
  }).catch(() => {});
698
- }, getTypeScriptIdleEvictMs());
797
+ }, idleMs);
699
798
  timer.unref?.();
700
- this.typeScriptIdleTimers.set(key, timer);
799
+ this.idleEvictionTimers.set(key, timer);
701
800
  }
702
- fingerprintContent(content) {
703
- if (content.length <= 96) {
704
- return `${content.length}:${content}`;
705
- }
706
- return `${content.length}:${content.slice(0, 48)}:${content.slice(-48)}`;
707
- }
708
- shouldSkipTouch(filePath, content, clientScope, waitForDiagnostics, serverIds) {
801
+ shouldSkipTouch(filePath, contentFingerprint, clientScope, waitForDiagnostics, spawned) {
709
802
  if (waitForDiagnostics)
710
803
  return false;
711
- if (serverIds.length === 0)
804
+ if (spawned.length === 0)
712
805
  return false;
713
- return serverIds.every((serverId) => this.shouldSkipNotify(filePath, content, clientScope, serverId));
806
+ return spawned.every((entry) => this.shouldSkipNotify(filePath, contentFingerprint, clientScope, entry.info.id, entry.client));
714
807
  }
715
- shouldSkipNotify(filePath, content, clientScope, serverId) {
808
+ shouldSkipNotify(filePath, contentFingerprint, clientScope, serverId, client) {
716
809
  if (TOUCH_DEBOUNCE_MS <= 0)
717
810
  return false;
718
811
  const previous = this.recentTouches.get(this.recentTouchKey(filePath, clientScope, serverId));
@@ -721,18 +814,21 @@ export class LSPService {
721
814
  const now = Date.now();
722
815
  if (now - previous.touchedAt > TOUCH_DEBOUNCE_MS)
723
816
  return false;
724
- return previous.fingerprint === this.fingerprintContent(content);
817
+ if (previous.client.deref() !== client)
818
+ return false;
819
+ return previous.fingerprint === contentFingerprint();
725
820
  }
726
821
  recentTouchKey(filePath, clientScope, serverId) {
727
822
  return `${normalizeMapKey(filePath)}:${clientScope}:${serverId}`;
728
823
  }
729
- markTouched(filePath, content, clientScope, serverId) {
824
+ markTouched(filePath, contentFingerprint, clientScope, serverId, client) {
730
825
  const key = this.recentTouchKey(filePath, clientScope, serverId);
731
826
  const now = Date.now();
732
827
  this.recentTouches.set(key, {
733
- fingerprint: this.fingerprintContent(content),
828
+ fingerprint: contentFingerprint,
734
829
  touchedAt: now,
735
- clientScope
830
+ clientScope,
831
+ client: new WeakRef(client)
736
832
  });
737
833
  if (this.recentTouches.size > 800) {
738
834
  for (const [k, v] of this.recentTouches) {
@@ -748,6 +844,11 @@ export class LSPService {
748
844
  return;
749
845
  return `${server.id}:${normalizeMapKey(root)}`;
750
846
  }
847
+ forgetReadiness(key) {
848
+ this.state.demonstratedReady.delete(key);
849
+ this.state.demonstratedCold.delete(key);
850
+ this.notifyWriteBackpressureStreak.delete(key);
851
+ }
751
852
  markDemonstratedReadyKey(key) {
752
853
  this.state.demonstratedReady.add(key);
753
854
  this.state.demonstratedCold.delete(key);
@@ -758,6 +859,8 @@ export class LSPService {
758
859
  recordNotifyWriteBackpressure(key, entry, filePath) {
759
860
  if (!key)
760
861
  return;
862
+ if (this.state.clients.get(key) !== entry.client)
863
+ return;
761
864
  const streak = (this.notifyWriteBackpressureStreak.get(key) ?? 0) + 1;
762
865
  if (streak < NOTIFY_BACKPRESSURE_BROKEN_AFTER) {
763
866
  this.notifyWriteBackpressureStreak.set(key, streak);
@@ -771,11 +874,11 @@ export class LSPService {
771
874
  async demoteNotifyStallCpuGuarded(key, entry, filePath, reason) {
772
875
  if (this.state.clients.get(key) !== entry.client)
773
876
  return;
774
- this.clearTypeScriptIdleTimer(key);
877
+ this.clearIdleEvictionTimer(key);
775
878
  const verdict = await this.notifyStallCpuVerdict(entry);
776
879
  if (verdict.cpuVerdict === "busy") {
777
880
  if (this.state.clients.get(key) === entry.client) {
778
- this.scheduleTypeScriptIdleEviction(key);
881
+ this.scheduleIdleEviction(key, entry.info);
779
882
  }
780
883
  this.logNotifyStallCpuBusy(key, entry, filePath, 0, verdict);
781
884
  return;
@@ -830,17 +933,10 @@ export class LSPService {
830
933
  demoteForNotifyStall(key, entry, filePath, reason) {
831
934
  if (this.state.clients.get(key) !== entry.client)
832
935
  return;
833
- this.notifyWriteBackpressureStreak.delete(key);
834
- this.releaseOutstandingAuxNotifyWrite(key);
835
- this.auxNotifyInflight.delete(key);
836
936
  this.state.broken.set(key, Date.now() + BROKEN_BASE_COOLDOWN_MS);
837
937
  this.notifyStallDemotions.set(key, Date.now());
838
938
  entry.client.shutdown().catch(() => {});
839
- this.state.clients.delete(key);
840
- this.state.clientSpawnedAt.delete(key);
841
- this.state.demonstratedReady.delete(key);
842
- this.clientLastUsedAt.delete(key);
843
- this.clearTypeScriptIdleTimer(key);
939
+ this.retireClient(key);
844
940
  logLatency({
845
941
  type: "phase",
846
942
  phase: "lsp_notify_backpressure_broken",
@@ -934,7 +1030,7 @@ export class LSPService {
934
1030
  return false;
935
1031
  if (record.gateOpen)
936
1032
  return false;
937
- return record.unacked >= auxNotifyInflightLimit(entry.info);
1033
+ return record.unacked >= serverTraits(entry.info).notifyInflightLimit;
938
1034
  }
939
1035
  async paceAuxNotify(key, entry, filePath, waitMs, context) {
940
1036
  const record = this.auxNotifyInflight.get(key);
@@ -946,10 +1042,11 @@ export class LSPService {
946
1042
  }
947
1043
  if (record.gateOpen)
948
1044
  return;
949
- const limit = auxNotifyInflightLimit(entry.info);
1045
+ const traits = serverTraits(entry.info);
1046
+ const limit = traits.notifyInflightLimit;
950
1047
  if (record.unacked < limit)
951
1048
  return;
952
- const ping = entry.client.pingLiveness;
1049
+ const ping = traits.replyOrdering === "threaded" ? undefined : entry.client.pingLiveness;
953
1050
  if (!ping) {
954
1051
  record.unacked = 0;
955
1052
  return;
@@ -1134,7 +1231,7 @@ export class LSPService {
1134
1231
  const attached = new Set(spawned.map((entry) => entry.info.id));
1135
1232
  const skipped = [];
1136
1233
  for (const server of getServersForFileWithConfig(filePath)) {
1137
- if (server.role !== "auxiliary")
1234
+ if (!isAuxiliary(server))
1138
1235
  continue;
1139
1236
  if (attached.has(server.id))
1140
1237
  continue;
@@ -1179,10 +1276,19 @@ export class LSPService {
1179
1276
  }
1180
1277
  return [...paths];
1181
1278
  }
1279
+ getTrackedContent(filePath, cwd) {
1280
+ const priorityServerIds = getServersForFileWithConfig(filePath).map((server) => server.id);
1281
+ for (const { client } of this.activeClientsForCwd(cwd, priorityServerIds)) {
1282
+ const sent = client.getSentContent?.(filePath);
1283
+ if (sent !== undefined)
1284
+ return sent;
1285
+ }
1286
+ return;
1287
+ }
1182
1288
  async getClientForFile(filePath, maxWaitMs, hardCapMs, resolvedRoots, waitSkipReasons) {
1183
1289
  if (this.checkDestroyed())
1184
1290
  return;
1185
- const servers = getServersForFileWithConfig(filePath).filter((s) => s.role !== "auxiliary");
1291
+ const servers = getServersForFileWithConfig(filePath).filter((s) => !isAuxiliary(s));
1186
1292
  const rootMemo = new Map;
1187
1293
  const partitionCandidates = async () => {
1188
1294
  const resolved = await Promise.all(servers.map(async (server) => {
@@ -1378,7 +1484,7 @@ export class LSPService {
1378
1484
  }
1379
1485
  return waitResult;
1380
1486
  }
1381
- async getClientsForFile(filePath, excludeServerIds, resolvedRoots) {
1487
+ async getClientsForFile(filePath, excludeServerIds, resolvedRoots, auxiliaryRoots) {
1382
1488
  const allServers = getServersForFileWithConfig(filePath);
1383
1489
  const servers = excludeServerIds && excludeServerIds.size > 0 ? allServers.filter((s) => !excludeServerIds.has(s.id)) : allServers;
1384
1490
  if (servers.length === 0)
@@ -1387,6 +1493,9 @@ export class LSPService {
1387
1493
  server,
1388
1494
  root: await this.resolveServerRoot(server, filePath)
1389
1495
  })))).filter((entry) => entry.root !== undefined);
1496
+ for (const { server, root } of rootedServers)
1497
+ if (isAuxiliary(server))
1498
+ auxiliaryRoots?.set(server.id, normalizeMapKey(root));
1390
1499
  let serverCountAttempted = 0;
1391
1500
  const acquisitions = new Map;
1392
1501
  const acquire = (server) => {
@@ -1405,7 +1514,7 @@ export class LSPService {
1405
1514
  async getAuxiliaryClientsForFile(filePath, enabledIds, onOutcome, maxWaitMs, signal, hook) {
1406
1515
  if (this.checkDestroyed() || enabledIds.size === 0)
1407
1516
  return [];
1408
- const servers = getServersForFileWithConfig(filePath).filter((s) => s.role === "auxiliary" && enabledIds.has(s.id));
1517
+ const servers = getServersForFileWithConfig(filePath).filter((s) => isAuxiliary(s) && enabledIds.has(s.id));
1409
1518
  if (servers.length === 0)
1410
1519
  return [];
1411
1520
  const rootMemo = new Map;
@@ -1524,17 +1633,16 @@ export class LSPService {
1524
1633
  const root = await this.resolveServerRoot(server, filePath);
1525
1634
  if (!root)
1526
1635
  continue;
1527
- const key = `${server.id}:${normalizeMapKey(root)}`;
1528
- const existing = this.state.clients.get(key);
1529
- if (existing?.isAlive()) {
1530
- existing.notify.watchedFileChange(filePath, type);
1531
- }
1636
+ this.notifyLiveClientsForServer(server.id, filePath, type, `${server.id}:${normalizeMapKey(root)}`, true);
1532
1637
  }
1533
1638
  }
1534
- async resyncGitChangedFiles(changedPaths) {
1535
- if (this.checkDestroyed() || changedPaths.length === 0)
1536
- return;
1639
+ async resyncGitChangedFiles(changedPaths, options = {}) {
1640
+ const dispositions = new Map;
1641
+ if (this.checkDestroyed() || changedPaths.length === 0) {
1642
+ return dispositions;
1643
+ }
1537
1644
  const targets = new Set;
1645
+ const changed = new Map;
1538
1646
  for (const changedPath of changedPaths) {
1539
1647
  const resolved = path.resolve(changedPath);
1540
1648
  for (const server of getServersForFileWithConfig(resolved)) {
@@ -1547,9 +1655,12 @@ export class LSPService {
1547
1655
  }
1548
1656
  }
1549
1657
  targets.add(resolved);
1658
+ changed.set(changedPath, resolved);
1550
1659
  }
1551
1660
  const openTargets = [...targets].filter((filePath) => this.hasLiveClientHoldingDocument(filePath));
1552
- this.documentDrift.enqueueResync(openTargets);
1661
+ const written = new Set(changed.values());
1662
+ this.documentDrift.enqueueResync(openTargets.filter((filePath) => !written.has(filePath)));
1663
+ this.documentDrift.enqueueResync(openTargets.filter((filePath) => written.has(filePath)), { saved: options.saved === true });
1553
1664
  const pass = await this.sweepDocumentDrift({ force: true });
1554
1665
  logLatency({
1555
1666
  type: "phase",
@@ -1562,17 +1673,23 @@ export class LSPService {
1562
1673
  deferred: pass?.deferred ?? this.documentDrift.pendingResyncCount
1563
1674
  }
1564
1675
  });
1676
+ for (const [changedPath, resolved] of changed) {
1677
+ dispositions.set(changedPath, openTargets.includes(resolved) ? pass?.queued.get(normalizeMapKey(resolved)) ?? "deferred" : "unheld");
1678
+ }
1679
+ return dispositions;
1565
1680
  }
1566
1681
  async sweepDocumentDrift(options = {}) {
1567
1682
  if (this.checkDestroyed())
1568
1683
  return;
1569
1684
  return this.documentDrift.sweep({
1570
- resync: async (filePath, content) => {
1685
+ resync: async (filePath, content, _driftAgeMs, readStamp, saved) => {
1571
1686
  await this.touchFile(filePath, content, {
1572
1687
  diagnostics: "none",
1573
1688
  source: "drift_resync",
1574
1689
  clientScope: "all",
1575
- excludeServerIds: await this.serverIdsNotHoldingDocument(filePath)
1690
+ excludeServerIds: await this.serverIdsNotHoldingDocument(filePath),
1691
+ readStamp,
1692
+ saved: saved === true
1576
1693
  });
1577
1694
  return this.documentDrift.peek(filePath)?.fingerprint === fingerprintDocumentContent(content);
1578
1695
  },
@@ -1624,7 +1741,7 @@ export class LSPService {
1624
1741
  }
1625
1742
  return exclude;
1626
1743
  }
1627
- recordFullyCoveredSync(filePath, content, targeted, allWritesLanded, at) {
1744
+ recordFullyCoveredSync(filePath, content, targeted, allWritesLanded, at, contentFingerprint) {
1628
1745
  if (!allWritesLanded || targeted.length === 0)
1629
1746
  return;
1630
1747
  const targetedClients = new Set(targeted.map((entry) => entry.client));
@@ -1636,7 +1753,7 @@ export class LSPService {
1636
1753
  if (documentIsOpenOn(client, filePath))
1637
1754
  return;
1638
1755
  }
1639
- this.documentDrift.recordSynced(filePath, content, at);
1756
+ this.documentDrift.recordSynced(filePath, content, at, contentFingerprint?.() ?? fingerprintDocumentContent(content));
1640
1757
  }
1641
1758
  noteSpawnVerdict(key, verdict) {
1642
1759
  this.lastSpawnVerdict.set(key, verdict);
@@ -1664,12 +1781,28 @@ export class LSPService {
1664
1781
  const root = await this.resolveServerRootOnce(server, filePath, rootMemo);
1665
1782
  if (!root || this.checkDestroyed())
1666
1783
  return;
1667
- if (server.role !== "auxiliary") {
1784
+ if (!isAuxiliary(server)) {
1668
1785
  resolvedRoots?.set(server.id, normalizeMapKey(root));
1669
1786
  }
1670
1787
  const allowInstall = this.shouldAllowInstall(server.id);
1671
1788
  const normalizedRoot = normalizeMapKey(root);
1672
1789
  const key = `${server.id}:${normalizedRoot}`;
1790
+ const adopted = this.analysisRootModeForFile(filePath) === "adopted";
1791
+ if (adopted) {
1792
+ const localCommand = server.command ?? server.projectLocalCommand ?? server.availabilityKey;
1793
+ const localBinary = localCommand ? path.isAbsolute(localCommand) ? isProjectLocalBinPath(localCommand, root) ? localCommand : undefined : findLocalBinUpwards(localCommand, root) : undefined;
1794
+ if (localBinary) {
1795
+ recordDegradationOnce({
1796
+ kind: "lsp-registry-decision",
1797
+ subject: `${server.id}:${normalizeMapKey(root)}`,
1798
+ reason: "project-local LSP binary refused for adopted root"
1799
+ });
1800
+ return;
1801
+ }
1802
+ this.adoptedClientKeys.add(key);
1803
+ if (!this.admitAdoptedRoot(root, filePath))
1804
+ return;
1805
+ }
1673
1806
  const isOptionalServer = OPTIONAL_LSP_SERVER_IDS.has(server.id);
1674
1807
  if (server.availabilityKey && isDirectLspCommandTemporarilyUnavailable(server.availabilityKey)) {
1675
1808
  emitBounded("lsp_client_skipped_unavailable_command", `${server.availabilityKey}:${normalizeMapKey(filePath)}`, {
@@ -1709,7 +1842,7 @@ export class LSPService {
1709
1842
  if (existing.isAlive()) {
1710
1843
  this.unavailableLogged.delete(key);
1711
1844
  this.clientLastUsedAt.set(key, Date.now());
1712
- this.scheduleTypeScriptIdleEviction(key);
1845
+ this.scheduleIdleEviction(key, server);
1713
1846
  if (!this.warmStartLogged.has(key)) {
1714
1847
  logSessionStart(`lsp warm-start ${server.id}: reused root=${root} file=${filePath}`);
1715
1848
  this.warmStartLogged.add(key);
@@ -1737,10 +1870,7 @@ export class LSPService {
1737
1870
  try {
1738
1871
  await existing.shutdown();
1739
1872
  } catch {}
1740
- this.state.clients.delete(key);
1741
- this.state.clientSpawnedAt.delete(key);
1742
- this.clientLastUsedAt.delete(key);
1743
- this.clearTypeScriptIdleTimer(key);
1873
+ this.retireClient(key);
1744
1874
  this.state.broken.delete(key);
1745
1875
  if (wasIntentional) {} else {
1746
1876
  if (this.recordRuntimeExitWindow(key, exitedAt, uptimeMs)) {
@@ -1841,7 +1971,20 @@ export class LSPService {
1841
1971
  return process.env.DM_LENS_DISABLE_LSP_INSTALL !== "1";
1842
1972
  }
1843
1973
  async spawnClient(server, root, key, filePath, allowInstall) {
1844
- if (!isLspSpawnAllowedByTrust()) {
1974
+ try {
1975
+ if (server.executesProjectCode === true) {
1976
+ refuseUntrustedLspExecution({
1977
+ kind: "project-code-server",
1978
+ serverId: server.id,
1979
+ root
1980
+ });
1981
+ }
1982
+ } catch (error) {
1983
+ logSessionStart(`lsp spawn ${server.id}: refused — ${error instanceof Error ? error.message : String(error)}`);
1984
+ this.noteSpawnVerdict(key, "failed");
1985
+ return;
1986
+ }
1987
+ if (server.trustAllowed !== true && !isLspSpawnAllowedByTrust()) {
1845
1988
  logSessionStart(`lsp spawn ${server.id}: refused — ${projectTrustDenialReason()}`);
1846
1989
  this.noteSpawnVerdict(key, "declined");
1847
1990
  return;
@@ -1851,7 +1994,12 @@ export class LSPService {
1851
1994
  logSessionStart(`lsp spawn ${server.id}: start root=${root} install=${allowInstall ? "enabled" : "disabled"} file=${filePath}`);
1852
1995
  recordLsp(server.id, root, "spawn_start");
1853
1996
  try {
1854
- const spawned = await server.spawn(root, { allowInstall });
1997
+ const projectCodeAllowed = this.analysisRootModeForFile(filePath) !== "adopted";
1998
+ const spawned = await withLspProjectCodePermission(projectCodeAllowed, () => server.spawn(root, {
1999
+ allowInstall,
2000
+ projectCodeAllowed,
2001
+ sessionRoot: this.sessionCwd ?? process.cwd()
2002
+ }));
1855
2003
  if (this.isDestroyed) {
1856
2004
  try {
1857
2005
  spawned?.process?.process?.kill();
@@ -1882,7 +2030,7 @@ export class LSPService {
1882
2030
  return;
1883
2031
  }
1884
2032
  const override = getServerInitOverride(server.id, filePath);
1885
- const mergedInit = mergeInitializationOptions(spawned.initialization, override?.initializationOptions);
2033
+ const mergedInit = spawned.launchVariant === "classic" ? mergeInitializationOptions(override?.initializationOptions, spawned.initialization) : mergeInitializationOptions(spawned.initialization, override?.initializationOptions);
1886
2034
  this.state.diagnosticsPublished.delete(server.id);
1887
2035
  this.state.diagnosticsUnsupported.delete(server.id);
1888
2036
  this.firstContactWaits.delete(server.id);
@@ -1910,12 +2058,13 @@ export class LSPService {
1910
2058
  diagnosticProviderKind: "unavailable"
1911
2059
  };
1912
2060
  this.state.clients.set(key, client);
2061
+ this.forgetReadiness(key);
1913
2062
  this.notifyStallDemotions.delete(key);
1914
2063
  this.unavailableLogged.delete(key);
1915
2064
  this.lastSpawnVerdict.delete(key);
1916
2065
  this.state.clientSpawnedAt.set(key, Date.now());
1917
2066
  this.clientLastUsedAt.set(key, Date.now());
1918
- this.scheduleTypeScriptIdleEviction(key);
2067
+ this.scheduleIdleEviction(key, server);
1919
2068
  this.failureCounts.delete(key);
1920
2069
  if (isOptionalServer) {
1921
2070
  this.optionalDisabled.delete(key);
@@ -1972,8 +2121,8 @@ export class LSPService {
1972
2121
  const startedAt = Date.now();
1973
2122
  await this.withClientForFileUse(filePath, undefined, options?.spawnBudgetMs, async (spawned) => {
1974
2123
  const languageId = getLanguageId(filePath) ?? "plaintext";
1975
- await spawned.client.notify.open(filePath, content, languageId, options?.preserveDiagnostics);
1976
- this.recordFullyCoveredSync(filePath, content, [spawned], true, startedAt);
2124
+ const sent = await spawned.client.notify.open(filePath, content, languageId, options?.preserveDiagnostics);
2125
+ this.recordFullyCoveredSync(filePath, content, [spawned], sent !== false, startedAt);
1977
2126
  });
1978
2127
  }
1979
2128
  async updateFile(filePath, content) {
@@ -2000,7 +2149,19 @@ export class LSPService {
2000
2149
  });
2001
2150
  return;
2002
2151
  }
2152
+ const contentHash = this.hashContent(content);
2153
+ if (typeof content === "string") {
2154
+ this.announceToSiblings(filePath, content, contentHash).catch((cause) => {
2155
+ incrementDegradationCount({
2156
+ kind: "lsp-sibling-announcement",
2157
+ subject: normalizeMapKey(filePath),
2158
+ reason: `sibling notification failed: ${String(cause)}`
2159
+ });
2160
+ });
2161
+ }
2003
2162
  const startedAt = Date.now();
2163
+ let fingerprintMemo;
2164
+ const contentFingerprint = () => fingerprintMemo ??= fingerprintDocumentContent(content);
2004
2165
  const hookDeadlineAt = options.hook !== undefined && Object.hasOwn(HOOK_WALL_BUDGET_MS, options.hook) ? startedAt + HOOK_WALL_BUDGET_MS[options.hook] : undefined;
2005
2166
  const normalizedPath = normalizeMapKey(filePath);
2006
2167
  const outsideRoot = await this.findOutsideProjectRoot(filePath);
@@ -2014,6 +2175,7 @@ export class LSPService {
2014
2175
  const clientScope = options.clientScope ?? (diagnosticsMode === "full" ? "all" : "primary");
2015
2176
  const useAllClients = clientScope === "all";
2016
2177
  const resolvedPrimaryRoots = new Map;
2178
+ const attemptedAuxiliaryRoots = new Map;
2017
2179
  const waitSkipReasons = new Set;
2018
2180
  const coldAuxiliaryServerIds = new Set;
2019
2181
  const noteColdAuxiliary = (serverId, outcome) => {
@@ -2024,7 +2186,7 @@ export class LSPService {
2024
2186
  let spawned;
2025
2187
  let serverCountAttempted;
2026
2188
  if (useAllClients) {
2027
- const result = await this.getClientsForFile(filePath, options.excludeServerIds, resolvedPrimaryRoots);
2189
+ const result = await this.getClientsForFile(filePath, options.excludeServerIds, resolvedPrimaryRoots, attemptedAuxiliaryRoots);
2028
2190
  spawned = result.clients;
2029
2191
  serverCountAttempted = result.serverCountAttempted;
2030
2192
  } else if (clientScope === "with-auxiliary") {
@@ -2071,7 +2233,8 @@ export class LSPService {
2071
2233
  source,
2072
2234
  maxClientWaitMs: options.maxClientWaitMs,
2073
2235
  failureKind,
2074
- ...waitSkipReasons.size > 0 ? { reason: [...waitSkipReasons][0] } : {}
2236
+ ...waitSkipReasons.size > 0 ? { reason: [...waitSkipReasons][0] } : {},
2237
+ candidates: this.describeTouchCandidates(filePath, resolvedPrimaryRoots, attemptedAuxiliaryRoots)
2075
2238
  }
2076
2239
  });
2077
2240
  return;
@@ -2079,7 +2242,7 @@ export class LSPService {
2079
2242
  const leaseKeys = await this.acquireClientLeases(spawned, filePath);
2080
2243
  if (!leaseKeys) {
2081
2244
  if (this.checkDestroyed()) {
2082
- const primaryServerIds = spawned.filter((entry) => entry.info.role !== "auxiliary").map((entry) => entry.info.id);
2245
+ const primaryServerIds = spawned.filter((entry) => !isAuxiliary(entry.info)).map((entry) => entry.info.id);
2083
2246
  return {
2084
2247
  diags: [],
2085
2248
  inconclusive: true,
@@ -2092,8 +2255,7 @@ export class LSPService {
2092
2255
  return this.touchFile(filePath, content, options);
2093
2256
  }
2094
2257
  try {
2095
- const spawnedServerIds = spawned.map((entry) => entry.info.id);
2096
- if (this.shouldSkipTouch(filePath, content, clientScope, diagnosticsMode !== "none", spawnedServerIds)) {
2258
+ if (this.shouldSkipTouch(filePath, contentFingerprint, clientScope, diagnosticsMode !== "none", spawned)) {
2097
2259
  logLatency({
2098
2260
  type: "phase",
2099
2261
  phase: "lsp_touch_file",
@@ -2113,15 +2275,15 @@ export class LSPService {
2113
2275
  }
2114
2276
  const languageId = getLanguageId(filePath) ?? "plaintext";
2115
2277
  const silent = options.silent ?? false;
2116
- const notifySkippedServerIds = new Set(spawnedServerIds.filter((serverId) => this.shouldSkipNotify(filePath, content, clientScope, serverId)));
2278
+ const notifySkippedServerIds = new Set(spawned.filter((entry) => this.shouldSkipNotify(filePath, contentFingerprint, clientScope, entry.info.id, entry.client)).map((entry) => entry.info.id));
2117
2279
  const notifySkipped = spawned.length > 0 && notifySkippedServerIds.size === spawned.length;
2118
2280
  const readPathVersion = (client) => client.getDiagnosticsVersionForPath?.(filePath);
2119
2281
  const diagnosticBaselines = new Map(spawned.map((entry) => [entry.client, readPathVersion(entry.client)]));
2120
2282
  const markedAtMs = Date.now();
2121
- const touchContentHash = this.hashContent(content);
2283
+ const touchContentHash = contentHash;
2122
2284
  const bindingMatchesTouchContent = (binding) => binding?.contentHash === touchContentHash;
2123
2285
  const carriedAuxiliary = options.collectDiagnostics ? spawned.flatMap((entry) => {
2124
- if (entry.info.role !== "auxiliary")
2286
+ if (!isAuxiliary(entry.info))
2125
2287
  return [];
2126
2288
  const binding = entry.client.getDiagnosticBinding?.(filePath);
2127
2289
  if (!bindingMatchesTouchContent(binding))
@@ -2129,16 +2291,17 @@ export class LSPService {
2129
2291
  const diags = entry.client.getDiagnostics(filePath);
2130
2292
  return diags.length > 0 ? [{ serverId: entry.info.id, diags, binding }] : [];
2131
2293
  }) : [];
2132
- const auxPublishedThisContent = new Set(spawned.flatMap((entry) => entry.info.role === "auxiliary" && bindingMatchesTouchContent(entry.client.getDiagnosticBinding?.(filePath)) ? [entry.info.id] : []));
2294
+ const auxPublishedThisContent = new Set(spawned.flatMap((entry) => isAuxiliary(entry.info) && bindingMatchesTouchContent(entry.client.getDiagnosticBinding?.(filePath)) ? [entry.info.id] : []));
2133
2295
  const spawnedByServerId = new Map(spawned.map((entry) => [entry.info.id, entry]));
2134
2296
  const auxCoversThisContent = (serverId) => {
2135
2297
  const entry = spawnedByServerId.get(serverId);
2136
- if (entry?.info.role !== "auxiliary")
2298
+ if (!entry || !isAuxiliary(entry.info))
2137
2299
  return false;
2138
2300
  return auxPublishedThisContent.has(serverId) || bindingMatchesTouchContent(entry.client.getDiagnosticBinding?.(filePath));
2139
2301
  };
2140
2302
  const notifyWriteTimedOutServerIds = [];
2141
2303
  const notifyDeferredServerIds = [];
2304
+ const supersededServerIds = [];
2142
2305
  if (!notifySkipped) {
2143
2306
  const budget = notifyWriteBudgetMs();
2144
2307
  const queueWaitMs = options.maxClientWaitMs !== undefined ? Math.min(budget, Math.max(0, primaryServerWaitFloorMs(filePath, options.maxClientWaitMs) - (Date.now() - startedAt))) : budget;
@@ -2146,7 +2309,7 @@ export class LSPService {
2146
2309
  if (notifySkippedServerIds.has(entry.info.id))
2147
2310
  return;
2148
2311
  const clientKey = await this.demonstratedReadyKeyFor(entry.info, filePath);
2149
- const gated = entry.info.role === "auxiliary" && clientKey !== undefined;
2312
+ const gated = isAuxiliary(entry.info) && clientKey !== undefined;
2150
2313
  let slot;
2151
2314
  if (gated && clientKey) {
2152
2315
  const barrierStartedAt = Date.now();
@@ -2180,7 +2343,7 @@ export class LSPService {
2180
2343
  let rejected = false;
2181
2344
  try {
2182
2345
  const writeStartedAt = Date.now();
2183
- const writePromise = entry.client.notify.open(filePath, content, languageId, undefined, silent, options.saved === true).then(() => true);
2346
+ const writePromise = entry.client.notify.open(filePath, content, languageId, undefined, silent, options.saved === true, options.readStamp).then((sent) => sent !== false);
2184
2347
  if (gated && clientKey) {
2185
2348
  this.noteAuxNotifyIssued(clientKey, entry.client);
2186
2349
  }
@@ -2207,7 +2370,9 @@ export class LSPService {
2207
2370
  if (wrote === true) {
2208
2371
  if (clientKey)
2209
2372
  this.notifyWriteBackpressureStreak.delete(clientKey);
2210
- this.markTouched(filePath, content, clientScope, entry.info.id);
2373
+ this.markTouched(filePath, contentFingerprint(), clientScope, entry.info.id, entry.client);
2374
+ } else if (wrote === false) {
2375
+ supersededServerIds.push(entry.info.id);
2211
2376
  } else {
2212
2377
  notifyWriteTimedOutServerIds.push(entry.info.id);
2213
2378
  if (!rejected) {
@@ -2215,7 +2380,7 @@ export class LSPService {
2215
2380
  }
2216
2381
  }
2217
2382
  }));
2218
- this.recordFullyCoveredSync(filePath, content, spawned, notifyWriteTimedOutServerIds.length === 0 && notifyDeferredServerIds.length === 0, startedAt);
2383
+ this.recordFullyCoveredSync(filePath, content, spawned, notifyWriteTimedOutServerIds.length === 0 && notifyDeferredServerIds.length === 0 && supersededServerIds.length === 0, startedAt, contentFingerprint);
2219
2384
  if (notifyWriteTimedOutServerIds.length > 0) {
2220
2385
  logLatency({
2221
2386
  type: "phase",
@@ -2232,7 +2397,7 @@ export class LSPService {
2232
2397
  }
2233
2398
  }
2234
2399
  const notifyWriteTimedOut = notifyWriteTimedOutServerIds.length > 0;
2235
- const primaryEntries = spawned.filter((entry) => entry.info.role !== "auxiliary");
2400
+ const primaryEntries = spawned.filter((entry) => !isAuxiliary(entry.info));
2236
2401
  const primaryServerIds = new Set(primaryEntries.map((e) => e.info.id));
2237
2402
  const primaryNotifyWriteTimedOutServerIds = notifyWriteTimedOutServerIds.filter((id) => primaryServerIds.has(id));
2238
2403
  const primaryNotifyWriteTimedOut = primaryNotifyWriteTimedOutServerIds.length > 0;
@@ -2327,7 +2492,7 @@ export class LSPService {
2327
2492
  } catch {}
2328
2493
  }
2329
2494
  const waitStartedAt = Date.now();
2330
- const hasTouchAuxiliaries = clientScope === "with-auxiliary" && options.collectDiagnostics === true && spawned.some((e) => e.info.role === "auxiliary");
2495
+ const hasTouchAuxiliaries = clientScope === "with-auxiliary" && options.collectDiagnostics === true && spawned.some((e) => isAuxiliary(e.info));
2331
2496
  if (spawned.some((entry) => entry.info.custom === true)) {
2332
2497
  try {
2333
2498
  const snapshotHook = options.hook ?? "tool_result_edit";
@@ -2355,7 +2520,7 @@ export class LSPService {
2355
2520
  const perServerWaitTimeouts = spawned.map((entry, entryIndex) => {
2356
2521
  const declaredServerTimeout = perServerDeclaredTimeouts[entryIndex];
2357
2522
  const observedSpawnMs = getSuccessfulLspSpawnDurationMs(entry.client.serverId);
2358
- return hasTouchAuxiliaries && entry.info.role === "auxiliary" && coldAuxiliaryServerIds.has(entry.client.serverId) && (configuredAuxCeilingMs !== undefined || observedSpawnMs !== undefined && observedSpawnMs > 0) ? auxWaitBudgetMs(entry.client.serverId, true, configuredAuxCeilingMs, declaredServerTimeout) : perServerDeclaredTimeouts[entryIndex];
2523
+ return hasTouchAuxiliaries && isAuxiliary(entry.info) && coldAuxiliaryServerIds.has(entry.client.serverId) && (configuredAuxCeilingMs !== undefined || observedSpawnMs !== undefined && observedSpawnMs > 0) ? auxWaitBudgetMs(entry.client.serverId, true, configuredAuxCeilingMs, declaredServerTimeout) : perServerDeclaredTimeouts[entryIndex];
2359
2524
  });
2360
2525
  const firstContactCutOffServerIds = new Set;
2361
2526
  const firstContactErroredServerIds = new Set;
@@ -2376,10 +2541,10 @@ export class LSPService {
2376
2541
  }
2377
2542
  };
2378
2543
  const perServerRaceBudgets = spawned.map((entry, entryIndex) => {
2379
- return hasTouchAuxiliaries && entry.info.role === "auxiliary" ? auxWaitBudgetMs(entry.client.serverId, coldAuxiliaryServerIds.has(entry.client.serverId), configuredAuxCeilingMs, perServerDeclaredTimeouts[entryIndex]) : perServerDeclaredTimeouts[entryIndex];
2544
+ return hasTouchAuxiliaries && isAuxiliary(entry.info) ? auxWaitBudgetMs(entry.client.serverId, coldAuxiliaryServerIds.has(entry.client.serverId), configuredAuxCeilingMs, perServerDeclaredTimeouts[entryIndex]) : perServerDeclaredTimeouts[entryIndex];
2380
2545
  });
2381
2546
  const perServerWaits = spawned.map((entry, entryIndex) => {
2382
- if (hasTouchAuxiliaries && entry.info.role === "auxiliary" && this.isAuxiliaryWaitDemoted(entry.info.id, entry.client.root ?? filePath)) {
2547
+ if (hasTouchAuxiliaries && isAuxiliary(entry.info) && this.isAuxiliaryWaitDemoted(entry.info.id, entry.client.root ?? filePath)) {
2383
2548
  return Promise.resolve(undefined);
2384
2549
  }
2385
2550
  if (this.state.diagnosticsUnsupported.has(entry.info.id) || diagnosticsUnsupportedServerIds.includes(entry.info.id)) {
@@ -2464,8 +2629,8 @@ export class LSPService {
2464
2629
  });
2465
2630
  let pushWaitSettled = false;
2466
2631
  const pushWait = hasTouchAuxiliaries ? (() => {
2467
- const primaryWaits = perServerWaits.filter((_, i) => spawned[i].info.role !== "auxiliary");
2468
- const auxWaits = perServerWaits.map((p, i) => spawned[i].info.role === "auxiliary" ? {
2632
+ const primaryWaits = perServerWaits.filter((_, i) => !isAuxiliary(spawned[i].info));
2633
+ const auxWaits = perServerWaits.map((p, i) => isAuxiliary(spawned[i].info) ? {
2469
2634
  promise: p,
2470
2635
  serverId: spawned[i].info.id,
2471
2636
  client: spawned[i].client,
@@ -2537,7 +2702,9 @@ export class LSPService {
2537
2702
  const collectLaterServerIds = outcomes.filter((o) => !o.publishedThisContent && (o.outcome === "cut_off" || o.outcome === "silent" || o.outcome === "demoted") && !(o.serverId === "ast-grep" && napiFallbackCoveredSince(filePath, startedAt))).map((o) => o.serverId);
2538
2703
  if (collectLaterServerIds.length > 0) {
2539
2704
  lateDeliveryServerIds = collectLaterServerIds;
2540
- markPendingAuxiliaryCoverage(filePath, collectLaterServerIds, Date.now());
2705
+ for (const serverId of collectLaterServerIds) {
2706
+ markPendingAuxiliaryCoverage(filePath, [serverId], startedAt, undefined, undefined, captureAuxPublicationBacklog(auxWaits.find((aux) => aux.serverId === serverId)?.client, filePath));
2707
+ }
2541
2708
  }
2542
2709
  logLatency({
2543
2710
  type: "phase",
@@ -2565,7 +2732,7 @@ export class LSPService {
2565
2732
  return new Promise(() => {});
2566
2733
  }
2567
2734
  try {
2568
- const result = await attemptTsserverSyncDiagnostics(filePath, this);
2735
+ const result = await attemptTsserverSyncDiagnostics(filePath, tsserverSyncChannel(primaryClient));
2569
2736
  if (result === undefined || pushWaitSettled) {
2570
2737
  return new Promise(() => {});
2571
2738
  }
@@ -2609,7 +2776,7 @@ export class LSPService {
2609
2776
  ...new Set(diagnosticsUnsupportedServerIds)
2610
2777
  ];
2611
2778
  if (!hasTouchAuxiliaries && options.collectDiagnostics === true) {
2612
- const auxEntries = spawned.filter((entry) => entry.info.role === "auxiliary");
2779
+ const auxEntries = spawned.filter((entry) => isAuxiliary(entry.info));
2613
2780
  if (auxEntries.length > 0) {
2614
2781
  const outcomes = auxEntries.map((entry) => {
2615
2782
  const baseline = diagnosticBaselines.get(entry.client);
@@ -2661,9 +2828,9 @@ export class LSPService {
2661
2828
  const waited = spawned.filter((entry) => !deferredResyncServerIds.has(entry.info.id) && !diagnosticsUnsupportedServerIds.includes(entry.info.id));
2662
2829
  const unanswered = waited.filter((entry) => !answeredForThisTouch(entry));
2663
2830
  diagnosticsUnansweredServerIds = unanswered.map((e) => e.info.id);
2664
- diagnosticsUnansweredPrimaryServerIds = unanswered.filter((entry) => entry.info.role !== "auxiliary").map((e) => e.info.id);
2665
- const hasWaitedPrimary = waited.some((entry) => entry.info.role !== "auxiliary");
2666
- const hasUnsupportedPrimary = diagnosticsUnsupportedServerIds.some((serverId) => spawned.some((entry) => entry.info.id === serverId && entry.info.role !== "auxiliary"));
2831
+ diagnosticsUnansweredPrimaryServerIds = unanswered.filter((entry) => !isAuxiliary(entry.info)).map((e) => e.info.id);
2832
+ const hasWaitedPrimary = waited.some((entry) => !isAuxiliary(entry.info));
2833
+ const hasUnsupportedPrimary = diagnosticsUnsupportedServerIds.some((serverId) => spawned.some((entry) => entry.info.id === serverId && !isAuxiliary(entry.info)));
2667
2834
  diagnosticsTimedOut = !hasWaitedPrimary && !hasUnsupportedPrimary || diagnosticsUnansweredPrimaryServerIds.length > 0;
2668
2835
  for (const entry of unanswered) {
2669
2836
  incrementDegradationCount({
@@ -2720,7 +2887,7 @@ export class LSPService {
2720
2887
  }
2721
2888
  const auxCoveredAtMerge = new Set(spawned.filter((entry) => auxCoversThisContent(entry.info.id)).map((entry) => entry.info.id));
2722
2889
  const uncoveredDeferredServerIds = notifyDeferredServerIds.filter((serverId) => !auxCoveredAtMerge.has(serverId));
2723
- const staleWriteAuxiliaryServerIds = spawned.filter((entry) => entry.info.role === "auxiliary" && notifyWriteTimedOutServerIds.includes(entry.info.id) && !auxCoveredAtMerge.has(entry.info.id)).map((entry) => entry.info.id);
2890
+ const staleWriteAuxiliaryServerIds = spawned.filter((entry) => isAuxiliary(entry.info) && notifyWriteTimedOutServerIds.includes(entry.info.id) && !auxCoveredAtMerge.has(entry.info.id)).map((entry) => entry.info.id);
2724
2891
  const droppedAuxiliaryServerIds = new Set([
2725
2892
  ...uncoveredDeferredServerIds,
2726
2893
  ...staleWriteAuxiliaryServerIds
@@ -2730,9 +2897,10 @@ export class LSPService {
2730
2897
  ...carriedAuxiliary.flatMap((entry) => attributeDiagnostics(entry.serverId, entry.diags))
2731
2898
  ]) : undefined;
2732
2899
  let syncConfirmed = tsserverSyncConfirmed !== undefined;
2733
- if (diagnosticsTimedOut && tsserverSyncEligible && collected !== undefined && collected.length === 0) {
2900
+ const syncClient = spawned[0]?.client;
2901
+ if (diagnosticsTimedOut && tsserverSyncEligible && syncClient !== undefined && collected !== undefined && collected.length === 0) {
2734
2902
  try {
2735
- const syncResult = await attemptTsserverSyncDiagnostics(filePath, this);
2903
+ const syncResult = await attemptTsserverSyncDiagnostics(filePath, tsserverSyncChannel(syncClient));
2736
2904
  if (syncResult !== undefined) {
2737
2905
  diagnosticsTimedOut = false;
2738
2906
  retractPrimaryTimeoutAttribution();
@@ -2787,7 +2955,7 @@ export class LSPService {
2787
2955
  });
2788
2956
  const inconclusive = verdict.inconclusive;
2789
2957
  const brokenSkippedServerIds = collected !== undefined ? await this.brokenSkippedAuxiliaryServerIds(filePath, clientScope, options, spawned) : [];
2790
- const auxNoAnswerServerIds = spawned.filter((entry) => entry.info.role === "auxiliary" && (diagnosticsUnansweredServerIds.includes(entry.info.id) || notifyWriteTimedOutServerIds.includes(entry.info.id)) && !auxCoveredAtMerge.has(entry.info.id)).map((entry) => entry.info.id);
2958
+ const auxNoAnswerServerIds = spawned.filter((entry) => isAuxiliary(entry.info) && (diagnosticsUnansweredServerIds.includes(entry.info.id) || notifyWriteTimedOutServerIds.includes(entry.info.id)) && !auxCoveredAtMerge.has(entry.info.id)).map((entry) => entry.info.id);
2791
2959
  const unconfirmedServerIds = [
2792
2960
  ...new Set([
2793
2961
  ...auxUnconfirmedServerIds ?? [],
@@ -2835,7 +3003,7 @@ export class LSPService {
2835
3003
  if (uncoveredServerIds.has(entry.info.id))
2836
3004
  continue;
2837
3005
  const key = await this.demonstratedReadyKeyFor(entry.info, filePath);
2838
- if (key)
3006
+ if (key && this.state.clients.get(key) === entry.client)
2839
3007
  this.markDemonstratedReadyKey(key);
2840
3008
  }
2841
3009
  }
@@ -2850,7 +3018,7 @@ export class LSPService {
2850
3018
  }
2851
3019
  }
2852
3020
  const result = { diags: collected ?? [] };
2853
- const primaryDiagnosticsUnsupported = diagnosticsUnsupportedServerIds.some((serverId) => spawned.some((entry) => entry.info.id === serverId && entry.info.role !== "auxiliary"));
3021
+ const primaryDiagnosticsUnsupported = diagnosticsUnsupportedServerIds.some((serverId) => spawned.some((entry) => entry.info.id === serverId && !isAuxiliary(entry.info)));
2854
3022
  if (diagnosticsUnsupportedServerIds.length > 0) {
2855
3023
  result.diagnosticsUnsupportedServerIds = diagnosticsUnsupportedServerIds;
2856
3024
  }
@@ -2882,6 +3050,9 @@ export class LSPService {
2882
3050
  if (lateDeliveryPending.length > 0) {
2883
3051
  result.deferredServerIds = lateDeliveryPending;
2884
3052
  }
3053
+ if (supersededServerIds.length > 0) {
3054
+ result.supersededServerIds = supersededServerIds;
3055
+ }
2885
3056
  logLatency({
2886
3057
  type: "phase",
2887
3058
  phase: "lsp_touch_file",
@@ -2902,6 +3073,7 @@ export class LSPService {
2902
3073
  ...notifyWriteTimedOutServerIds.length > 0 && {
2903
3074
  notifyWriteTimedOutServerIds
2904
3075
  },
3076
+ ...supersededServerIds.length > 0 && { supersededServerIds },
2905
3077
  diagnosticsTimedOut,
2906
3078
  inconclusive,
2907
3079
  ...verdict.inconclusiveServerIds && {
@@ -2929,12 +3101,14 @@ export class LSPService {
2929
3101
  });
2930
3102
  return result;
2931
3103
  } finally {
2932
- for (const key of leaseKeys)
2933
- this.releaseClientLease(key);
3104
+ for (const lease of leaseKeys)
3105
+ this.releaseClientLease(lease.key, lease.server);
2934
3106
  }
2935
3107
  }
2936
3108
  async findOutsideProjectRoot(filePath) {
2937
- if (!isOutsideAllSessionRoots(filePath))
3109
+ if (!this.fileIsOutsideRegisteredRoots(filePath))
3110
+ return;
3111
+ if (this.analysisRootModeForFile(filePath) === "adopted")
2938
3112
  return;
2939
3113
  const candidates = await Promise.all(getServersForFileWithConfig(filePath).map((server) => server.root(filePath)));
2940
3114
  return candidates.find((candidate) => Boolean(candidate));
@@ -3044,16 +3218,16 @@ export class LSPService {
3044
3218
  });
3045
3219
  const graceMs = diagnosticsMode === "document" ? 0 : EARLY_UNBLOCK_GRACE_MS;
3046
3220
  const diagDescriptors = spawned.map((entry) => {
3047
- if (entry.info.role !== "auxiliary")
3048
- return { role: "primary" };
3221
+ if (!isAuxiliary(entry.info))
3222
+ return { role: entry.info.role };
3049
3223
  const strategy = getStrategy(entry.info.id, entry.client.getLaunchVariant?.());
3050
- return { role: "auxiliary", budgetMs: strategy.aggregateWaitMs };
3224
+ return { role: entry.info.role, budgetMs: strategy.aggregateWaitMs };
3051
3225
  });
3052
3226
  const perServer = await raceToCompletion(clientWaits, (results) => results.some((r) => r.diagnosticCount > 0 || getStrategy(r.serverId, r.launchVariant).seedFirstPush), {
3053
3227
  timeoutMs: Math.max(...spawned.map((entry) => getStrategy(entry.info.id, entry.client.getLaunchVariant?.()).aggregateWaitMs)),
3054
3228
  graceMs,
3055
3229
  descriptors: diagDescriptors,
3056
- auxGraceMs: readEnvAuxGraceMs() ?? 2000
3230
+ auxGraceMs: readEnvAuxGraceMs() ?? DEFAULT_AUX_GRACE_CEILING_MS
3057
3231
  });
3058
3232
  const earlyUnblockedCount = spawned.length - perServer.length;
3059
3233
  const perServerFull = spawned.map((entry) => {
@@ -3218,8 +3392,7 @@ export class LSPService {
3218
3392
  continue;
3219
3393
  const separator = key.indexOf(":");
3220
3394
  const serverId = separator >= 0 ? key.slice(0, separator) : key;
3221
- const role = LSP_SERVERS.find((s) => s.id === serverId)?.role;
3222
- if (role === "auxiliary") {
3395
+ if (isAuxiliary(getServerById(serverId))) {
3223
3396
  if (!auxFallback)
3224
3397
  auxFallback = { client, serverId };
3225
3398
  continue;
@@ -3349,6 +3522,7 @@ export class LSPService {
3349
3522
  diagnosticsUnsupported: this.state.diagnosticsUnsupported.has(server.id),
3350
3523
  advertisedCommands: client.getAdvertisedCommands(),
3351
3524
  rawCapabilityKeys: client.getRawCapabilityKeys?.() ?? [],
3525
+ textDocumentSave: textDocumentSaveOf(client),
3352
3526
  launchVariant: client.getLaunchVariant?.()
3353
3527
  });
3354
3528
  }
@@ -3369,6 +3543,7 @@ export class LSPService {
3369
3543
  diagnosticsUnsupported: this.state.diagnosticsUnsupported.has(serverId),
3370
3544
  advertisedCommands: client.getAdvertisedCommands(),
3371
3545
  rawCapabilityKeys: client.getRawCapabilityKeys?.() ?? [],
3546
+ textDocumentSave: textDocumentSaveOf(client),
3372
3547
  launchVariant: client.getLaunchVariant?.()
3373
3548
  });
3374
3549
  }
@@ -3499,7 +3674,7 @@ export class LSPService {
3499
3674
  oldUri: client.getDocumentUri(oldFilePath)
3500
3675
  }));
3501
3676
  const closeFailures = [];
3502
- await Promise.all(openDocuments.map(async ({ serverId, client }) => {
3677
+ await Promise.all(activeClients.map(async ({ serverId, client }) => {
3503
3678
  const result = await runRenameNotify(() => client.closeDocument(oldFilePath), RENAME_NOTIFY_TIMEOUT_MS);
3504
3679
  if (!result.ok) {
3505
3680
  closeFailures.push({
@@ -3520,7 +3695,11 @@ export class LSPService {
3520
3695
  const languageId = getLanguageId(oldFilePath) ?? "plaintext";
3521
3696
  const resyncFailures = [];
3522
3697
  await Promise.all(openDocuments.map(async ({ serverId, client }) => {
3523
- const resyncResult = await runRenameNotify(() => client.notify.open(oldFilePath, content, languageId, true, true), RENAME_NOTIFY_TIMEOUT_MS);
3698
+ const resyncResult = await runRenameNotify(() => client.notify.open(oldFilePath, content, languageId, true, true).then((sent) => {
3699
+ if (sent === false) {
3700
+ throw new Error(client.isAlive() ? "re-open not sent: the close is still queued" : "re-open not sent: the client is dead");
3701
+ }
3702
+ }), RENAME_NOTIFY_TIMEOUT_MS);
3524
3703
  if (!resyncResult.ok) {
3525
3704
  resyncFailures.push({
3526
3705
  serverId,
@@ -3665,19 +3844,36 @@ export class LSPService {
3665
3844
  if (this.checkDestroyed() || options.signal?.aborted) {
3666
3845
  return { performedWarmup: false, failedServerIds: [] };
3667
3846
  }
3668
- const servers = getServersForFileWithConfig(representativeFile).filter((s) => s.role !== "auxiliary");
3847
+ const servers = getServersForFileWithConfig(representativeFile).filter((s) => !isAuxiliary(s));
3669
3848
  if (servers.length === 0) {
3670
3849
  return { performedWarmup: false, failedServerIds: [] };
3671
3850
  }
3672
3851
  const keys = await Promise.all(servers.map((server) => this.demonstratedReadyKeyFor(server, representativeFile)));
3673
- const alreadyWarm = keys.every((key) => key === undefined || this.state.demonstratedReady.has(key));
3852
+ const headOf = new Map;
3853
+ const familyHead = servers.map((server) => {
3854
+ const preferredHead = server.fallbackFor === undefined ? undefined : headOf.get(server.fallbackFor);
3855
+ const head = preferredHead ?? server.id;
3856
+ headOf.set(server.id, head);
3857
+ return head;
3858
+ });
3859
+ const isColdAt = (i) => {
3860
+ const key = keys[i];
3861
+ if (key === undefined || this.state.demonstratedReady.has(key)) {
3862
+ return false;
3863
+ }
3864
+ return !servers.some((_, j) => {
3865
+ const peerKey = keys[j];
3866
+ return peerKey !== undefined && familyHead[j] === familyHead[i] && this.state.demonstratedReady.has(peerKey);
3867
+ });
3868
+ };
3869
+ const alreadyWarm = servers.every((_, i) => !isColdAt(i));
3674
3870
  if (alreadyWarm)
3675
3871
  return { performedWarmup: false, failedServerIds: [] };
3676
3872
  const cachedColdServerIds = [];
3677
3873
  let allNonWarmCached = true;
3678
3874
  for (let i = 0;i < servers.length; i++) {
3679
3875
  const key = keys[i];
3680
- if (key === undefined || this.state.demonstratedReady.has(key))
3876
+ if (key === undefined || !isColdAt(i))
3681
3877
  continue;
3682
3878
  if (this.state.demonstratedCold.has(key)) {
3683
3879
  cachedColdServerIds.push(servers[i].id);
@@ -3724,10 +3920,8 @@ export class LSPService {
3724
3920
  const stillColdServerIds = () => {
3725
3921
  const cold = [];
3726
3922
  for (let i = 0;i < servers.length; i++) {
3727
- const key = keys[i];
3728
- if (key !== undefined && !this.state.demonstratedReady.has(key)) {
3923
+ if (isColdAt(i))
3729
3924
  cold.push(servers[i].id);
3730
- }
3731
3925
  }
3732
3926
  return cold;
3733
3927
  };
@@ -3792,6 +3986,7 @@ export class LSPService {
3792
3986
  };
3793
3987
  await runWarmupTouch(1);
3794
3988
  let failedServerIds = stillColdServerIds();
3989
+ const warmedClients = keys.map((key) => key === undefined ? undefined : this.state.clients.get(key));
3795
3990
  if (failedServerIds.length > 0 && !options.signal?.aborted) {
3796
3991
  const backoffMs = warmupRetryBackoffMs();
3797
3992
  if (backoffMs > 0) {
@@ -3811,7 +4006,7 @@ export class LSPService {
3811
4006
  if (failedServerIds.length > 0) {
3812
4007
  for (let i = 0;i < servers.length; i++) {
3813
4008
  const key = keys[i];
3814
- if (key !== undefined && failedServerIds.includes(servers[i].id)) {
4009
+ if (key !== undefined && failedServerIds.includes(servers[i].id) && this.state.clients.get(key) === warmedClients[i]) {
3815
4010
  this.state.demonstratedCold.add(key);
3816
4011
  }
3817
4012
  }
@@ -3906,8 +4101,18 @@ export class LSPService {
3906
4101
  }
3907
4102
  const cacheServedKeys = new Set(cachedResults.map((result) => normalizeMapKey(result.filePath)));
3908
4103
  const supersededCacheKeys = new Set;
4104
+ const pullAnsweredFiles = new Set;
3909
4105
  const scannedMtimeByFile = new Map;
3910
4106
  const scannedSizeByFile = new Map;
4107
+ const scannedAtByFile = new Map;
4108
+ const noteScanStat = (filePath) => {
4109
+ scannedAtByFile.set(filePath, Date.now());
4110
+ try {
4111
+ const scanStat = nodeFs.statSync(filePath);
4112
+ scannedMtimeByFile.set(filePath, scanStat.mtimeMs);
4113
+ scannedSizeByFile.set(filePath, scanStat.size);
4114
+ } catch {}
4115
+ };
3911
4116
  const groups = groupFilesByPrimaryServer(filesToTouch);
3912
4117
  const sweepIndexGate = createSweepIndexGate();
3913
4118
  const workspacePullEnabled = process.env.DM_LENS_LSP_WORKSPACE_PULL === "1";
@@ -3933,6 +4138,7 @@ export class LSPService {
3933
4138
  if (signal?.aborted)
3934
4139
  return;
3935
4140
  let content;
4141
+ noteScanStat(filePath);
3936
4142
  try {
3937
4143
  content = await nodeFs.promises.readFile(filePath, "utf-8");
3938
4144
  } catch {
@@ -3944,16 +4150,17 @@ export class LSPService {
3944
4150
  const { clients } = await this.getClientsForFile(filePath, WORKSPACE_SWEEP_EXCLUDED_SERVER_IDS);
3945
4151
  for (const entry of clients) {
3946
4152
  let auxKey;
3947
- if (entry.info.role === "auxiliary") {
4153
+ if (isAuxiliary(entry.info)) {
3948
4154
  auxKey = await this.demonstratedReadyKeyFor(entry.info, filePath);
3949
4155
  if (auxKey && this.auxNotifyBacklogAtCeiling(auxKey, entry)) {
3950
4156
  continue;
3951
4157
  }
3952
4158
  }
3953
4159
  try {
3954
- await entry.client.notify.open(filePath, content, languageId);
3955
- if (auxKey)
4160
+ const sent = await entry.client.notify.open(filePath, content, languageId);
4161
+ if (auxKey && sent !== false) {
3956
4162
  this.noteAuxNotifyIssued(auxKey, entry.client);
4163
+ }
3957
4164
  } catch {}
3958
4165
  }
3959
4166
  })(), { ms: perFileMs, onTimeout: "undefined" });
@@ -3988,12 +4195,11 @@ export class LSPService {
3988
4195
  };
3989
4196
  const processFile = async (filePath) => {
3990
4197
  try {
3991
- const content = contentCache.get(filePath) ?? await nodeFs.promises.readFile(filePath, "utf-8");
3992
- try {
3993
- const scanStat = nodeFs.statSync(filePath);
3994
- scannedMtimeByFile.set(filePath, scanStat.mtimeMs);
3995
- scannedSizeByFile.set(filePath, scanStat.size);
3996
- } catch {}
4198
+ let content = contentCache.get(filePath);
4199
+ if (content === undefined) {
4200
+ noteScanStat(filePath);
4201
+ content = await nodeFs.promises.readFile(filePath, "utf-8");
4202
+ }
3997
4203
  const attached = isWarmAttached() ? await tryWarmAttachedDiagnostics(filePath, content, perFileMs, "sweep") : undefined;
3998
4204
  if (attached && !attached.available) {
3999
4205
  await this.ensureWarmForSweep(filePath, { signal });
@@ -4078,6 +4284,7 @@ export class LSPService {
4078
4284
  return;
4079
4285
  }
4080
4286
  if (!isWarmAttached() && workspacePullEnabled && !group.multiServer) {
4287
+ const pullStartedAt = Date.now();
4081
4288
  const pulled = await this.tryWorkspacePull(group.files, perFileMs, cacheServedKeys);
4082
4289
  if (pulled) {
4083
4290
  for (const clean of pulled.extraClean) {
@@ -4088,10 +4295,12 @@ export class LSPService {
4088
4295
  ...result,
4089
4296
  writeIndex: writeIndexByPath.get(normalizeMapKey(result.filePath))
4090
4297
  });
4298
+ pullAnsweredFiles.add(result.filePath);
4091
4299
  try {
4092
4300
  const pullStat = nodeFs.statSync(result.filePath);
4093
4301
  scannedMtimeByFile.set(result.filePath, pullStat.mtimeMs);
4094
4302
  scannedSizeByFile.set(result.filePath, pullStat.size);
4303
+ scannedAtByFile.set(result.filePath, pullStartedAt);
4095
4304
  } catch {}
4096
4305
  }
4097
4306
  completed += group.files.length;
@@ -4168,6 +4377,11 @@ export class LSPService {
4168
4377
  const unconfirmedServerIds = [
4169
4378
  ...new Set(results.flatMap((result) => result.unconfirmedServerIds ?? []))
4170
4379
  ].sort((a, b) => Number(a > b) - Number(a < b));
4380
+ let pullUnbound = 0;
4381
+ for (const result of results) {
4382
+ if (pullAnsweredFiles.has(result.filePath) && result.contentHash === undefined)
4383
+ pullUnbound += 1;
4384
+ }
4171
4385
  logLatency({
4172
4386
  type: "phase",
4173
4387
  phase: "lsp_workspace_diagnostics",
@@ -4183,6 +4397,7 @@ export class LSPService {
4183
4397
  timedOutFiles,
4184
4398
  unconfirmedByReason,
4185
4399
  partiallyCoveredFiles,
4400
+ pullUnbound,
4186
4401
  ...unconfirmedServerIds.length > 0 && { unconfirmedServerIds },
4187
4402
  aborted: signal?.aborted ?? false
4188
4403
  }
@@ -4192,11 +4407,19 @@ export class LSPService {
4192
4407
  if (result.error || result.timedOut || (result.unconfirmedServerIds?.length ?? 0) > 0 || scannedAt === undefined) {
4193
4408
  continue;
4194
4409
  }
4195
- workspaceDiagnosticsCacheCtx.record(result.filePath, workspaceSweepScopeKey, result.diagnostics, scannedAt, result.contentHash, scannedSizeByFile.get(result.filePath));
4410
+ if (pullAnsweredFiles.has(result.filePath) && result.contentHash === undefined) {
4411
+ workspaceDiagnosticsCacheCtx.forget(result.filePath);
4412
+ continue;
4413
+ }
4414
+ workspaceDiagnosticsCacheCtx.record(result.filePath, workspaceSweepScopeKey, result.diagnostics, scannedAt, result.contentHash, scannedSizeByFile.get(result.filePath), scannedAtByFile.get(result.filePath));
4196
4415
  }
4197
4416
  workspaceDiagnosticsCacheCtx.persist();
4198
4417
  const servedCacheResults = supersededCacheKeys.size === 0 ? cachedResults : cachedResults.filter((result) => !supersededCacheKeys.has(normalizeMapKey(result.filePath)));
4199
- return [...servedCacheResults, ...results].filter(Boolean);
4418
+ const freshResults = results.map((result) => ({
4419
+ ...result,
4420
+ observedAt: scannedAtByFile.get(result.filePath)
4421
+ }));
4422
+ return [...servedCacheResults, ...freshResults].filter(Boolean);
4200
4423
  }
4201
4424
  async tryWorkspacePull(groupFiles, perFileMs, reanswerFor) {
4202
4425
  try {
@@ -4309,6 +4532,26 @@ export class LSPService {
4309
4532
  }
4310
4533
  return false;
4311
4534
  }
4535
+ describeTouchCandidates(filePath, resolvedRoots, auxiliaryRoots = new Map) {
4536
+ const candidates = [];
4537
+ for (const server of getServersForFileWithConfig(filePath)) {
4538
+ const auxiliary = isAuxiliary(server);
4539
+ if (auxiliary && !auxiliaryRoots.has(server.id))
4540
+ continue;
4541
+ if (candidates.length >= MAX_TOUCH_CANDIDATES)
4542
+ break;
4543
+ const root = (auxiliary ? auxiliaryRoots : resolvedRoots).get(server.id);
4544
+ const key = root === undefined ? undefined : `${server.id}:${root}`;
4545
+ const client = key === undefined ? undefined : this.state.clients.get(key);
4546
+ candidates.push({
4547
+ serverId: server.id,
4548
+ rooted: root !== undefined,
4549
+ clientFound: client ? client.isAlive() ? "alive" : "dead" : "none",
4550
+ generation: key === undefined ? undefined : this.state.clientSpawnedAt.get(key)
4551
+ });
4552
+ }
4553
+ return candidates;
4554
+ }
4312
4555
  async hasWarmLSP(filePath) {
4313
4556
  const spawned = await this.getWarmClientForFile(filePath);
4314
4557
  return Boolean(spawned);
@@ -4326,8 +4569,8 @@ export class LSPService {
4326
4569
  for (const [key, token] of this.outstandingAuxNotifyWrites) {
4327
4570
  this.releaseOutstandingAuxNotifyWrite(key, token);
4328
4571
  }
4329
- for (const key of this.typeScriptIdleTimers.keys()) {
4330
- this.clearTypeScriptIdleTimer(key);
4572
+ for (const key of this.idleEvictionTimers.keys()) {
4573
+ this.clearIdleEvictionTimer(key);
4331
4574
  }
4332
4575
  if (!options.processExiting && this.state.inFlight.size > 0) {
4333
4576
  const pending = Array.from(this.state.inFlight.values());
@@ -4434,44 +4677,27 @@ export class LSPService {
4434
4677
  if (seen.has(id))
4435
4678
  continue;
4436
4679
  seen.add(id);
4437
- const role = LSP_SERVERS.find((s) => s.id === id)?.role;
4438
- (role === "auxiliary" ? aux : primary).push(id);
4680
+ (isAuxiliary(getServerById(id)) ? aux : primary).push(id);
4439
4681
  }
4440
4682
  return [...primary, ...aux];
4441
4683
  }
4442
4684
  }
4443
- const LSP_PROCESS_FAMILY = "lsp.service";
4444
- const LSP_PROCESS_VERSION = 1;
4445
- function lspProcessState() {
4446
- let incompatibleHandoff;
4447
- return getProcessSingleton(LSP_PROCESS_FAMILY, LSP_PROCESS_VERSION, () => ({ service: null, generationHandoff: incompatibleHandoff }), (value) => {
4448
- if (!value || typeof value !== "object")
4449
- return;
4450
- const candidate = value;
4451
- const previousHandoff = candidate.generationHandoff;
4452
- const teardown = candidate.service?.shutdown ? candidate.service.shutdown({ fast: true, reason: "process_singleton_reset" }).catch(() => {
4453
- return;
4454
- }) : undefined;
4455
- if (previousHandoff && teardown) {
4456
- incompatibleHandoff = Promise.allSettled([
4457
- previousHandoff,
4458
- teardown
4459
- ]).then(() => {
4460
- return;
4461
- });
4462
- } else {
4463
- incompatibleHandoff = previousHandoff ?? teardown;
4464
- }
4465
- });
4466
- }
4467
- function processService() {
4468
- const state = lspProcessState();
4469
- if (!state.service)
4470
- state.service = new LSPService(state.generationHandoff, process.cwd());
4471
- return state.service;
4472
- }
4685
+ configureLspServiceLifecycle({
4686
+ create: (generationHandoff) => new LSPService(generationHandoff, process.cwd()),
4687
+ beforeReset: (options) => {
4688
+ abortDeferredLspWork(`lsp service reset: ${options.reason ?? "unspecified"}`);
4689
+ resetLspLaunchAvailabilityGeneration();
4690
+ if (options.reason === "session_start") {
4691
+ resetClassicTsRepairGuard();
4692
+ }
4693
+ },
4694
+ destroy: (service, options) => service.shutdown(options)
4695
+ });
4473
4696
  export function getLSPService() {
4474
- return processService();
4697
+ return getOwnedLspService();
4698
+ }
4699
+ export function peekLSPService() {
4700
+ return peekOwnedLspService();
4475
4701
  }
4476
4702
  export async function hasAuxiliaryLspPublishedForRoot(serverId, filePath) {
4477
4703
  return getLSPService().hasServerPublishedForFileRoot(serverId, filePath);
@@ -4483,28 +4709,11 @@ export async function resyncGitChangedFiles(changedPaths) {
4483
4709
  return getLSPService().resyncGitChangedFiles(changedPaths);
4484
4710
  }
4485
4711
  export function resetLSPService(options = {}) {
4486
- abortDeferredLspWork(`lsp service reset: ${options.reason ?? "unspecified"}`);
4487
- resetLspLaunchAvailabilityGeneration();
4488
4712
  if (options.reason === "session_start") {
4489
4713
  resetClassicTsRepairGuard();
4490
4714
  clearWorkspaceSweepHoldForSessionStart();
4491
4715
  }
4492
- const state = lspProcessState();
4493
- const retiringService = state.service;
4494
- state.service = null;
4495
- if (!retiringService)
4496
- return;
4497
- const teardown = retiringService.shutdown(options);
4498
- const pending = state.generationHandoff ? [state.generationHandoff, teardown] : [teardown];
4499
- const handoff = Promise.allSettled(pending).then(() => {
4500
- return;
4501
- });
4502
- state.generationHandoff = handoff;
4503
- handoff.then(() => {
4504
- if (state.generationHandoff === handoff) {
4505
- state.generationHandoff = undefined;
4506
- }
4507
- });
4716
+ resetOwnedLspService(options);
4508
4717
  }
4509
4718
  export function __collectWorkspaceDiagnosticFilesForTest(root, maxFiles, signal, homeDir) {
4510
4719
  return collectWorkspaceDiagnosticFiles(path.resolve(root), maxFiles ?? getMaxWorkspaceDiagnosticFiles(), signal, homeDir);