pi-lens 4.3.0 → 4.4.0

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 (650) hide show
  1. package/CHANGELOG.md +1064 -0
  2. package/README.md +115 -25
  3. package/config/dependency-cruiser-eager-allowlist.json +6 -2
  4. package/dist/chunk-22AVIGXS.js +560 -0
  5. package/dist/chunk-27BBHSZC.js +106 -0
  6. package/dist/chunk-2BEMIWEW.js +51 -0
  7. package/dist/chunk-2EECBNC5.js +89 -0
  8. package/dist/chunk-34U7PLGE.js +23 -0
  9. package/dist/chunk-3I5QFT3N.js +181 -0
  10. package/dist/chunk-3MED75HT.js +37 -0
  11. package/dist/chunk-47D2BO4S.js +87 -0
  12. package/dist/chunk-4RERDEXR.js +348 -0
  13. package/dist/chunk-4W2PLC4J.js +27 -0
  14. package/dist/chunk-52H5B5TC.js +202 -0
  15. package/dist/chunk-54B42YRX.js +27 -0
  16. package/dist/chunk-5RXBNSW2.js +266 -0
  17. package/dist/chunk-5THXD6X5.js +201 -0
  18. package/dist/chunk-5W3R6LFT.js +24 -0
  19. package/dist/chunk-5ZEJHV35.js +341 -0
  20. package/dist/chunk-6P62QVEA.js +118 -0
  21. package/dist/chunk-6QIUX4EP.js +459 -0
  22. package/dist/chunk-6VCD4VKZ.js +78 -0
  23. package/dist/chunk-7F72PXY2.js +326 -0
  24. package/dist/chunk-7FBF7NPR.js +998 -0
  25. package/dist/chunk-7U2IDNXN.js +37 -0
  26. package/dist/chunk-ABBOA7UD.js +157 -0
  27. package/dist/chunk-AHDW3GPE.js +50 -0
  28. package/dist/chunk-AJ3QXTRQ.js +756 -0
  29. package/dist/chunk-AJVLWNFN.js +1610 -0
  30. package/dist/chunk-AJXODZY6.js +112 -0
  31. package/dist/chunk-ARFCXG7S.js +84 -0
  32. package/dist/chunk-AS44CFQ4.js +708 -0
  33. package/dist/chunk-AWE5TMPO.js +38 -0
  34. package/dist/chunk-B3I2UUT4.js +4692 -0
  35. package/dist/chunk-BRJKOBZP.js +331 -0
  36. package/dist/chunk-BW5KFIQC.js +59 -0
  37. package/dist/chunk-C2AUYXQH.js +149 -0
  38. package/dist/chunk-CGGAIP7J.js +29 -0
  39. package/dist/chunk-D6QS3U6M.js +30 -0
  40. package/dist/chunk-DFVMIKMQ.js +349 -0
  41. package/dist/chunk-DIULIWKU.js +169 -0
  42. package/dist/chunk-DQ2NZ7C4.js +2317 -0
  43. package/dist/chunk-E2WFBRHM.js +213 -0
  44. package/dist/chunk-E4MAEDPM.js +50 -0
  45. package/dist/chunk-EOKRQ3SA.js +30 -0
  46. package/dist/chunk-F3AU2TMM.js +2626 -0
  47. package/dist/chunk-F3P7VQ7H.js +170 -0
  48. package/dist/chunk-FC4RP4I2.js +12 -0
  49. package/dist/chunk-FJNKANOS.js +32 -0
  50. package/dist/chunk-GUOGVTCQ.js +146 -0
  51. package/dist/chunk-GVXA6CCE.js +18 -0
  52. package/dist/chunk-HHYAELLJ.js +2334 -0
  53. package/dist/chunk-HMFXILPV.js +83 -0
  54. package/dist/chunk-HVUZXSWK.js +421 -0
  55. package/dist/chunk-HWBZIGMJ.js +62 -0
  56. package/dist/chunk-I3R7GKDR.js +17 -0
  57. package/dist/chunk-I7SPGOWI.js +55 -0
  58. package/dist/chunk-IIXOAGHR.js +38 -0
  59. package/dist/chunk-IVP5KAB7.js +2250 -0
  60. package/dist/chunk-IXEBJSUE.js +22 -0
  61. package/dist/chunk-JOLITGCC.js +27 -0
  62. package/dist/chunk-K6VYLB2U.js +145 -0
  63. package/dist/chunk-LJDODBBZ.js +78 -0
  64. package/dist/chunk-LNAKEO63.js +78 -0
  65. package/dist/chunk-LSMJ6KBE.js +4139 -0
  66. package/dist/chunk-LW6XKDZQ.js +5565 -0
  67. package/dist/chunk-N3YQJI6O.js +899 -0
  68. package/dist/chunk-NABLC7W3.js +148 -0
  69. package/dist/chunk-NKOUFPQF.js +659 -0
  70. package/dist/chunk-NL5GLMFI.js +211 -0
  71. package/dist/chunk-NMABWBZN.js +327 -0
  72. package/dist/chunk-NTHH2J74.js +27 -0
  73. package/dist/chunk-NTUJEGDZ.js +59 -0
  74. package/dist/chunk-NXL4FFQQ.js +47 -0
  75. package/dist/chunk-NXPS2L6U.js +466 -0
  76. package/dist/chunk-O5WILGMI.js +42 -0
  77. package/dist/chunk-O6TQT6RI.js +48 -0
  78. package/dist/chunk-OAXNDZJ7.js +323 -0
  79. package/dist/chunk-ODEEOXPH.js +44 -0
  80. package/dist/chunk-OQGFCZJ4.js +4533 -0
  81. package/dist/chunk-ORTMY4Q4.js +282 -0
  82. package/dist/chunk-OS32RNR2.js +442 -0
  83. package/dist/chunk-PAK6IDME.js +189 -0
  84. package/dist/chunk-PWFHBTSF.js +406 -0
  85. package/dist/chunk-Q5U6FMDI.js +2352 -0
  86. package/dist/chunk-QOZXJ4NA.js +3364 -0
  87. package/dist/chunk-QYF5S6P6.js +45 -0
  88. package/dist/chunk-RIISMHKN.js +36 -0
  89. package/dist/chunk-RPD4ZSB7.js +25 -0
  90. package/dist/chunk-RPD5K5NC.js +79 -0
  91. package/dist/chunk-RUOG5D2C.js +262 -0
  92. package/dist/chunk-T4ERT73Y.js +599 -0
  93. package/dist/chunk-T6D4Q4AQ.js +54 -0
  94. package/dist/chunk-TGPXLY2J.js +391 -0
  95. package/dist/chunk-TLGFBM3F.js +12116 -0
  96. package/dist/chunk-TO6WL3GM.js +88 -0
  97. package/dist/chunk-TT22N74J.js +517 -0
  98. package/dist/chunk-TVN5N6GY.js +21216 -0
  99. package/dist/chunk-U3VGR4VU.js +308 -0
  100. package/dist/chunk-UK3CMEAL.js +1250 -0
  101. package/dist/chunk-UOPVJQ4N.js +103 -0
  102. package/dist/chunk-UXVNL3D7.js +23 -0
  103. package/dist/chunk-UY752QSN.js +45 -0
  104. package/dist/chunk-V5PXFSZK.js +188 -0
  105. package/dist/chunk-V7R425XG.js +398 -0
  106. package/dist/chunk-VCSRSYLF.js +81 -0
  107. package/dist/chunk-VD4JQCQC.js +162 -0
  108. package/dist/chunk-VDBPVIKD.js +62 -0
  109. package/dist/chunk-VHQLPIRJ.js +114 -0
  110. package/dist/chunk-VN2AXLEX.js +5414 -0
  111. package/dist/chunk-VNMT7C64.js +478 -0
  112. package/dist/chunk-WONERJTP.js +309 -0
  113. package/dist/chunk-XECLWQZN.js +85 -0
  114. package/dist/chunk-XIMYZ3JA.js +27 -0
  115. package/dist/chunk-XK4CIILI.js +144 -0
  116. package/dist/chunk-Y4T27COV.js +562 -0
  117. package/dist/chunk-YGVYKNSN.js +1860 -0
  118. package/dist/chunk-YLF3PPT5.js +308 -0
  119. package/dist/chunk-YSNFMJKN.js +14 -0
  120. package/dist/chunk-Z3CCVDUB.js +76 -0
  121. package/dist/chunk-Z54ZSOBZ.js +61 -0
  122. package/dist/chunk-ZAWW3AF6.js +97 -0
  123. package/dist/chunk-ZMOL6RQC.js +167 -0
  124. package/dist/index.js +16456 -8335
  125. package/dist/mcp/analyze-cli.js +186 -232
  126. package/dist/mcp/cli.js +137 -98
  127. package/dist/mcp/server.js +22589 -1573
  128. package/dist/mcp/worker.js +97 -38
  129. package/dist/probes/installer.js +135 -0
  130. package/dist/workers/project-snapshot-persist-worker.js +22 -0
  131. package/dist/workers/review-graph-persist-worker.js +15 -0
  132. package/docs/agent-guide.md +13 -4
  133. package/docs/agent-tools.md +42 -0
  134. package/docs/ast-grep_rules_catalog.md +3 -2
  135. package/docs/configuration.md +20 -1
  136. package/docs/environment-variables.md +52 -2
  137. package/docs/features.md +8 -4
  138. package/docs/globalconfig.md +1 -0
  139. package/docs/io-bridge-v2-migration.md +94 -0
  140. package/docs/lsp-capability-matrix.md +36 -4
  141. package/docs/lsp-idle-eviction.md +124 -0
  142. package/docs/mcp.md +21 -5
  143. package/docs/merge-queue-rollout.md +77 -0
  144. package/docs/pi-lens-fixer.md +156 -88
  145. package/docs/pi-lens-investigator.md +74 -26
  146. package/docs/pi-lens-merge-policy.md +694 -0
  147. package/docs/pi-lens-monitor.md +73 -7
  148. package/docs/pi-lens-retro.md +6 -4
  149. package/docs/pi-lens-reviewer.md +188 -48
  150. package/docs/pi-lens-subagent.md +246 -45
  151. package/docs/pi-lens-warden.md +18 -7
  152. package/docs/public-api-stability.md +55 -0
  153. package/docs/release-qa-baseline.md +84 -17
  154. package/docs/rfcs/3654-unified-io-bridge-v2.md +316 -0
  155. package/docs/servercapabilities.md +53 -49
  156. package/docs/settings.md +1 -0
  157. package/docs/usage.md +5 -1
  158. package/grammars/tree-sitter-bash.wasm +0 -0
  159. package/grammars/tree-sitter-bash.wasm.json +3 -3
  160. package/package.json +19 -7
  161. package/rules/ast-grep-rules/rule-tests/advisory-registry-subset-test.yml +41 -0
  162. package/rules/ast-grep-rules/rules/advisory-registry-subset.yml +50 -0
  163. package/scripts/analyze-pi-lens-logs.mjs +1275 -62
  164. package/scripts/download-grammars.js +5 -0
  165. package/scripts/grammars.lock.json +6 -1
  166. package/scripts/install-selftest.mjs +33 -34
  167. package/scripts/lib/host-provided-deps.mjs +13 -4
  168. package/scripts/lib/web-tree-sitter-dir.mjs +18 -0
  169. package/dist/clients/actionable-warnings-logger.js +0 -35
  170. package/dist/clients/actionable-warnings.js +0 -1610
  171. package/dist/clients/advisory-provenance.js +0 -593
  172. package/dist/clients/agent-behavior-client.js +0 -147
  173. package/dist/clients/agent-nudge.js +0 -325
  174. package/dist/clients/analysed-root.js +0 -1
  175. package/dist/clients/ast-grep-client.js +0 -731
  176. package/dist/clients/ast-grep-rule-manager.js +0 -146
  177. package/dist/clients/ast-grep-tool-logger.js +0 -118
  178. package/dist/clients/ast-grep-types.js +0 -10
  179. package/dist/clients/ast-grep-yaml-synth.js +0 -154
  180. package/dist/clients/atomic-write-staging.js +0 -75
  181. package/dist/clients/atomic-write.js +0 -189
  182. package/dist/clients/availability-probe-flight.js +0 -12
  183. package/dist/clients/bash-file-access.js +0 -1056
  184. package/dist/clients/biome-client.js +0 -357
  185. package/dist/clients/blocker-freshness.js +0 -837
  186. package/dist/clients/blocker-past-eof.js +0 -129
  187. package/dist/clients/bootstrap.js +0 -569
  188. package/dist/clients/bounded-cache.js +0 -190
  189. package/dist/clients/bounded-pid-file-lock.js +0 -202
  190. package/dist/clients/bounded-telemetry.js +0 -295
  191. package/dist/clients/build-identity.js +0 -95
  192. package/dist/clients/bundled-resource-health.js +0 -113
  193. package/dist/clients/bus-events-logger.js +0 -105
  194. package/dist/clients/bus-publish.js +0 -171
  195. package/dist/clients/cache/rule-cache.js +0 -190
  196. package/dist/clients/cache-manager.js +0 -524
  197. package/dist/clients/cache-observability.js +0 -1313
  198. package/dist/clients/call-graph.js +0 -852
  199. package/dist/clients/cargo-manifest.js +0 -422
  200. package/dist/clients/cascade-budget.js +0 -196
  201. package/dist/clients/cascade-format.js +0 -315
  202. package/dist/clients/cascade-logger.js +0 -31
  203. package/dist/clients/cascade-types.js +0 -9
  204. package/dist/clients/child-unref.js +0 -124
  205. package/dist/clients/code-quality-warnings.js +0 -286
  206. package/dist/clients/codebase-model.js +0 -173
  207. package/dist/clients/collateral-test-role.js +0 -40
  208. package/dist/clients/complexity-client.js +0 -462
  209. package/dist/clients/config-core/deny.js +0 -221
  210. package/dist/clients/config-core/index.js +0 -50
  211. package/dist/clients/config-core/merge.js +0 -357
  212. package/dist/clients/config-core/normalize.js +0 -340
  213. package/dist/clients/config-core/process-spec.js +0 -248
  214. package/dist/clients/config-core/provenance.js +0 -164
  215. package/dist/clients/config-core/records.js +0 -218
  216. package/dist/clients/config-core/resolve.js +0 -125
  217. package/dist/clients/config-core/safe-object.js +0 -78
  218. package/dist/clients/config-core/schema.js +0 -165
  219. package/dist/clients/config-diagnostic-codes.js +0 -285
  220. package/dist/clients/config-locations.js +0 -388
  221. package/dist/clients/config-resolve.js +0 -798
  222. package/dist/clients/config-schema.js +0 -251
  223. package/dist/clients/config-warn.js +0 -407
  224. package/dist/clients/console-guard-install.js +0 -26
  225. package/dist/clients/cooperative-budget.js +0 -42
  226. package/dist/clients/dead-code-client.js +0 -510
  227. package/dist/clients/dead-code-logger.js +0 -30
  228. package/dist/clients/deadline-utils.js +0 -280
  229. package/dist/clients/debug-handles.js +0 -211
  230. package/dist/clients/debug-heap.js +0 -174
  231. package/dist/clients/deferred-lsp-work.js +0 -106
  232. package/dist/clients/degradation-ledger.js +0 -426
  233. package/dist/clients/demoted-finding-render.js +0 -169
  234. package/dist/clients/dependency-checker.js +0 -885
  235. package/dist/clients/deps/ast-grep-napi.js +0 -22
  236. package/dist/clients/deps/js-yaml.js +0 -9
  237. package/dist/clients/deps/minimatch.js +0 -4
  238. package/dist/clients/deps/pi-tui.js +0 -14
  239. package/dist/clients/deps/typebox.js +0 -14
  240. package/dist/clients/deps/vscode-jsonrpc.js +0 -1
  241. package/dist/clients/deps/web-tree-sitter.js +0 -24
  242. package/dist/clients/diagnostic-dispositions.js +0 -630
  243. package/dist/clients/diagnostic-line-freshness.js +0 -305
  244. package/dist/clients/diagnostic-logger.js +0 -73
  245. package/dist/clients/diagnostic-tracker.js +0 -105
  246. package/dist/clients/diagnostics-publish.js +0 -230
  247. package/dist/clients/dispatch/ast-grep-catalog.js +0 -65
  248. package/dist/clients/dispatch/auxiliary-lsp.js +0 -343
  249. package/dist/clients/dispatch/collect-later-tier.js +0 -35
  250. package/dist/clients/dispatch/diagnostic-taxonomy.js +0 -66
  251. package/dist/clients/dispatch/dispatcher.js +0 -1269
  252. package/dist/clients/dispatch/fact-provider-types.js +0 -1
  253. package/dist/clients/dispatch/fact-rule-runner.js +0 -17
  254. package/dist/clients/dispatch/fact-runner.js +0 -30
  255. package/dist/clients/dispatch/fact-scheduler.js +0 -68
  256. package/dist/clients/dispatch/fact-store.js +0 -377
  257. package/dist/clients/dispatch/facts/comment-facts.js +0 -22
  258. package/dist/clients/dispatch/facts/file-content.js +0 -19
  259. package/dist/clients/dispatch/facts/function-facts.js +0 -348
  260. package/dist/clients/dispatch/facts/import-facts.js +0 -204
  261. package/dist/clients/dispatch/facts/tree-sitter-facts.js +0 -34
  262. package/dist/clients/dispatch/facts/try-catch-facts.js +0 -119
  263. package/dist/clients/dispatch/finding-policy.js +0 -339
  264. package/dist/clients/dispatch/indent-detect.js +0 -417
  265. package/dist/clients/dispatch/inline-suppressions.js +0 -89
  266. package/dist/clients/dispatch/integration.js +0 -2377
  267. package/dist/clients/dispatch/lazy.js +0 -11
  268. package/dist/clients/dispatch/pending-runner-findings.js +0 -87
  269. package/dist/clients/dispatch/plan.js +0 -278
  270. package/dist/clients/dispatch/priorities.js +0 -20
  271. package/dist/clients/dispatch/rule-id-normalize.js +0 -50
  272. package/dist/clients/dispatch/rule-ignores.js +0 -69
  273. package/dist/clients/dispatch/rule-policy.js +0 -135
  274. package/dist/clients/dispatch/rules/async-noise.js +0 -40
  275. package/dist/clients/dispatch/rules/async-unnecessary-wrapper.js +0 -27
  276. package/dist/clients/dispatch/rules/cors-wildcard.js +0 -54
  277. package/dist/clients/dispatch/rules/error-obscuring.js +0 -32
  278. package/dist/clients/dispatch/rules/error-swallowing.js +0 -31
  279. package/dist/clients/dispatch/rules/framework-call-noise.js +0 -67
  280. package/dist/clients/dispatch/rules/high-complexity.js +0 -72
  281. package/dist/clients/dispatch/rules/high-fan-out.js +0 -74
  282. package/dist/clients/dispatch/rules/high-import-coupling.js +0 -37
  283. package/dist/clients/dispatch/rules/missing-error-propagation.js +0 -62
  284. package/dist/clients/dispatch/rules/no-commented-credentials.js +0 -52
  285. package/dist/clients/dispatch/rules/pass-through-wrappers.js +0 -42
  286. package/dist/clients/dispatch/rules/placeholder-comments.js +0 -40
  287. package/dist/clients/dispatch/rules/unsafe-boundary.js +0 -126
  288. package/dist/clients/dispatch/runner-context.js +0 -52
  289. package/dist/clients/dispatch/runners/actionlint.js +0 -111
  290. package/dist/clients/dispatch/runners/ast-grep-napi.js +0 -1196
  291. package/dist/clients/dispatch/runners/biome-check.js +0 -296
  292. package/dist/clients/dispatch/runners/cpp-check.js +0 -219
  293. package/dist/clients/dispatch/runners/credo.js +0 -82
  294. package/dist/clients/dispatch/runners/cue-vet.js +0 -416
  295. package/dist/clients/dispatch/runners/dart-analyze.js +0 -183
  296. package/dist/clients/dispatch/runners/detekt.js +0 -176
  297. package/dist/clients/dispatch/runners/dotnet-build.js +0 -164
  298. package/dist/clients/dispatch/runners/elixir-check.js +0 -195
  299. package/dist/clients/dispatch/runners/eslint.js +0 -137
  300. package/dist/clients/dispatch/runners/fact-rules.js +0 -29
  301. package/dist/clients/dispatch/runners/fish-indent.js +0 -69
  302. package/dist/clients/dispatch/runners/gleam-check.js +0 -167
  303. package/dist/clients/dispatch/runners/go-vet.js +0 -104
  304. package/dist/clients/dispatch/runners/golangci-lint.js +0 -135
  305. package/dist/clients/dispatch/runners/hadolint.js +0 -91
  306. package/dist/clients/dispatch/runners/helm-lint.js +0 -171
  307. package/dist/clients/dispatch/runners/helm-render.js +0 -940
  308. package/dist/clients/dispatch/runners/htmlhint.js +0 -117
  309. package/dist/clients/dispatch/runners/index.js +0 -108
  310. package/dist/clients/dispatch/runners/javac.js +0 -99
  311. package/dist/clients/dispatch/runners/ktlint.js +0 -110
  312. package/dist/clients/dispatch/runners/lsp.js +0 -379
  313. package/dist/clients/dispatch/runners/markdownlint.js +0 -167
  314. package/dist/clients/dispatch/runners/mypy.js +0 -102
  315. package/dist/clients/dispatch/runners/oxlint.js +0 -414
  316. package/dist/clients/dispatch/runners/php-lint.js +0 -85
  317. package/dist/clients/dispatch/runners/phpstan.js +0 -120
  318. package/dist/clients/dispatch/runners/prisma-validate.js +0 -62
  319. package/dist/clients/dispatch/runners/psscriptanalyzer.js +0 -445
  320. package/dist/clients/dispatch/runners/pyright.js +0 -169
  321. package/dist/clients/dispatch/runners/rubocop.js +0 -99
  322. package/dist/clients/dispatch/runners/ruff.js +0 -88
  323. package/dist/clients/dispatch/runners/rust-clippy.js +0 -256
  324. package/dist/clients/dispatch/runners/shellcheck.js +0 -173
  325. package/dist/clients/dispatch/runners/shfmt.js +0 -102
  326. package/dist/clients/dispatch/runners/spellcheck.js +0 -128
  327. package/dist/clients/dispatch/runners/spotbugs.js +0 -259
  328. package/dist/clients/dispatch/runners/sqlfluff.js +0 -183
  329. package/dist/clients/dispatch/runners/stylelint.js +0 -166
  330. package/dist/clients/dispatch/runners/swiftlint.js +0 -163
  331. package/dist/clients/dispatch/runners/taplo.js +0 -174
  332. package/dist/clients/dispatch/runners/terragrunt.js +0 -168
  333. package/dist/clients/dispatch/runners/tflint.js +0 -125
  334. package/dist/clients/dispatch/runners/tree-sitter.js +0 -643
  335. package/dist/clients/dispatch/runners/trivy-config.js +0 -253
  336. package/dist/clients/dispatch/runners/utils/availability-policy.js +0 -496
  337. package/dist/clients/dispatch/runners/utils/candidate-probe.js +0 -90
  338. package/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +0 -95
  339. package/dist/clients/dispatch/runners/utils/lazy-installer.js +0 -274
  340. package/dist/clients/dispatch/runners/utils/runner-helpers.js +0 -1701
  341. package/dist/clients/dispatch/runners/utils/spawn-outcome.js +0 -101
  342. package/dist/clients/dispatch/runners/utils/tool-failure.js +0 -235
  343. package/dist/clients/dispatch/runners/utils/toolchain-availability.js +0 -169
  344. package/dist/clients/dispatch/runners/utils.js +0 -15
  345. package/dist/clients/dispatch/runners/vale.js +0 -128
  346. package/dist/clients/dispatch/runners/yaml-rule-parser.js +0 -242
  347. package/dist/clients/dispatch/runners/yamllint.js +0 -95
  348. package/dist/clients/dispatch/runners/zig-check.js +0 -79
  349. package/dist/clients/dispatch/suppress-writer.js +0 -79
  350. package/dist/clients/dispatch/tool-profile.js +0 -30
  351. package/dist/clients/dispatch/types.js +0 -21
  352. package/dist/clients/dispatch/utils/format-utils.js +0 -45
  353. package/dist/clients/dispatch/utils/lsp-diagnostics.js +0 -35
  354. package/dist/clients/disposition-logger.js +0 -32
  355. package/dist/clients/disposition-publish.js +0 -124
  356. package/dist/clients/durable-store.js +0 -97
  357. package/dist/clients/effective-config.js +0 -415
  358. package/dist/clients/env-utils.js +0 -83
  359. package/dist/clients/error-class.js +0 -23
  360. package/dist/clients/eval-timestamp.js +0 -17
  361. package/dist/clients/event-loop-hold.js +0 -274
  362. package/dist/clients/event-loop-monitor.js +0 -250
  363. package/dist/clients/extension-log.js +0 -504
  364. package/dist/clients/extension-mode.js +0 -73
  365. package/dist/clients/feature-hints.js +0 -103
  366. package/dist/clients/file-kinds.js +0 -412
  367. package/dist/clients/file-role.js +0 -134
  368. package/dist/clients/file-time.js +0 -160
  369. package/dist/clients/file-utils.js +0 -1032
  370. package/dist/clients/finding-delivery-gate.js +0 -494
  371. package/dist/clients/finding-identity.js +0 -88
  372. package/dist/clients/fix-worklog.js +0 -103
  373. package/dist/clients/format-events-publish.js +0 -343
  374. package/dist/clients/format-service.js +0 -222
  375. package/dist/clients/formatters-lazy.js +0 -9
  376. package/dist/clients/formatters.js +0 -2032
  377. package/dist/clients/freshness-cadence.js +0 -17
  378. package/dist/clients/freshness.js +0 -38
  379. package/dist/clients/generated-artifacts.js +0 -394
  380. package/dist/clients/generation-guard.js +0 -215
  381. package/dist/clients/git-guard.js +0 -1136
  382. package/dist/clients/git-tracked-ignore.js +0 -243
  383. package/dist/clients/gitleaks-client.js +0 -509
  384. package/dist/clients/go-client.js +0 -104
  385. package/dist/clients/govulncheck-client.js +0 -605
  386. package/dist/clients/gradle-ktfmt-style.js +0 -348
  387. package/dist/clients/grammar-source.js +0 -465
  388. package/dist/clients/gzip-stage-write.js +0 -135
  389. package/dist/clients/hashline-anchor.js +0 -424
  390. package/dist/clients/hook-budgets.js +0 -76
  391. package/dist/clients/host-edit-normalize.js +0 -140
  392. package/dist/clients/host-ports.js +0 -39
  393. package/dist/clients/indent-retarget.js +0 -154
  394. package/dist/clients/inline-blocker-dispositions.js +0 -186
  395. package/dist/clients/install-diagnostics.js +0 -156
  396. package/dist/clients/installer/index.js +0 -5416
  397. package/dist/clients/installer/managed-tool-refresh-session.js +0 -58
  398. package/dist/clients/installer/managed-tool-refresh.js +0 -783
  399. package/dist/clients/instance-reaper-state.js +0 -7
  400. package/dist/clients/instance-reaper.js +0 -1137
  401. package/dist/clients/instance-registry-lock.js +0 -145
  402. package/dist/clients/instance-registry.js +0 -773
  403. package/dist/clients/jscpd-client.js +0 -378
  404. package/dist/clients/json-cache-read.js +0 -65
  405. package/dist/clients/knip-client.js +0 -788
  406. package/dist/clients/language-policy.js +0 -252
  407. package/dist/clients/language-profile.js +0 -361
  408. package/dist/clients/language-registry.js +0 -603
  409. package/dist/clients/latency-logger.js +0 -727
  410. package/dist/clients/lazy-import.js +0 -21
  411. package/dist/clients/ledger-bounds.js +0 -54
  412. package/dist/clients/lens-config.js +0 -404
  413. package/dist/clients/lens-engine.js +0 -358
  414. package/dist/clients/lens-events.js +0 -125
  415. package/dist/clients/lens-flag-registry.js +0 -467
  416. package/dist/clients/lens-map.js +0 -1156
  417. package/dist/clients/live-bus-emitter.js +0 -74
  418. package/dist/clients/log-cleanup.js +0 -222
  419. package/dist/clients/lsp/aggregation.js +0 -178
  420. package/dist/clients/lsp/cascade-tier.js +0 -421
  421. package/dist/clients/lsp/client.js +0 -4593
  422. package/dist/clients/lsp/config.js +0 -691
  423. package/dist/clients/lsp/content-limits.js +0 -41
  424. package/dist/clients/lsp/diagnostic-binding.js +0 -225
  425. package/dist/clients/lsp/document-drift.js +0 -467
  426. package/dist/clients/lsp/edits.js +0 -1219
  427. package/dist/clients/lsp/index.js +0 -8305
  428. package/dist/clients/lsp/inferred-project.js +0 -216
  429. package/dist/clients/lsp/jvm-runtime.js +0 -298
  430. package/dist/clients/lsp/language.js +0 -63
  431. package/dist/clients/lsp/launch.js +0 -746
  432. package/dist/clients/lsp/lombok.js +0 -158
  433. package/dist/clients/lsp/path-utils.js +0 -5
  434. package/dist/clients/lsp/pending-aux-coverage.js +0 -251
  435. package/dist/clients/lsp/position-encoding.js +0 -61
  436. package/dist/clients/lsp/ruby-drive-dirs.js +0 -83
  437. package/dist/clients/lsp/server.js +0 -3290
  438. package/dist/clients/lsp/session-roots.js +0 -192
  439. package/dist/clients/lsp/spawn-history.js +0 -17
  440. package/dist/clients/lsp/sync-kind.js +0 -56
  441. package/dist/clients/lsp/tsserver-sync.js +0 -332
  442. package/dist/clients/lsp/wait-policy/capability-snapshot.js +0 -1
  443. package/dist/clients/lsp/wait-policy/classification.js +0 -85
  444. package/dist/clients/lsp/wait-policy/index.js +0 -10
  445. package/dist/clients/lsp/wait-policy/strategies.js +0 -392
  446. package/dist/clients/lsp/watch-queue.js +0 -61
  447. package/dist/clients/lsp/workspace-diagnostics-cache.js +0 -639
  448. package/dist/clients/lsp/workspace-diagnostics-session.js +0 -30
  449. package/dist/clients/lsp/workspace-sweep-hold.js +0 -184
  450. package/dist/clients/lsp-budget.js +0 -186
  451. package/dist/clients/lsp-document-symbols.js +0 -110
  452. package/dist/clients/lsp-lazy.js +0 -9
  453. package/dist/clients/lsp-mutation.js +0 -396
  454. package/dist/clients/lsp-status.js +0 -59
  455. package/dist/clients/map-with-concurrency.js +0 -40
  456. package/dist/clients/mcp/analyze.js +0 -420
  457. package/dist/clients/mcp/host-shim.js +0 -31
  458. package/dist/clients/mcp/ipc.js +0 -523
  459. package/dist/clients/mcp/review.js +0 -197
  460. package/dist/clients/mcp/session.js +0 -412
  461. package/dist/clients/memory-sampler.js +0 -208
  462. package/dist/clients/message-end-attribution.js +0 -30
  463. package/dist/clients/metrics-client.js +0 -107
  464. package/dist/clients/metrics-history.js +0 -327
  465. package/dist/clients/middle-man-analysis.js +0 -263
  466. package/dist/clients/model-provider.js +0 -53
  467. package/dist/clients/module-report-lsp.js +0 -189
  468. package/dist/clients/module-report.js +0 -2150
  469. package/dist/clients/mutating-tool.js +0 -651
  470. package/dist/clients/mutation-attribution.js +0 -368
  471. package/dist/clients/mutation-bridge.js +0 -240
  472. package/dist/clients/ndjson-logger.js +0 -734
  473. package/dist/clients/observed-mutation-sources.js +0 -101
  474. package/dist/clients/observed-mutation.js +0 -1253
  475. package/dist/clients/oldtext-autopatch.js +0 -128
  476. package/dist/clients/opaque-mutation-scan.js +0 -496
  477. package/dist/clients/opengrep-client.js +0 -333
  478. package/dist/clients/opengrep-config.js +0 -76
  479. package/dist/clients/package-manager.js +0 -607
  480. package/dist/clients/package-root.js +0 -38
  481. package/dist/clients/partial-edit-apply.js +0 -439
  482. package/dist/clients/path-attribution-telemetry.js +0 -43
  483. package/dist/clients/path-keyed-map.js +0 -108
  484. package/dist/clients/path-utils.js +0 -1244
  485. package/dist/clients/performance-report.js +0 -331
  486. package/dist/clients/persist-debounce.js +0 -70
  487. package/dist/clients/persistent-reverify.js +0 -271
  488. package/dist/clients/php-cs-fixer-config.js +0 -119
  489. package/dist/clients/pipeline.js +0 -1480
  490. package/dist/clients/post-autofix-notice.js +0 -37
  491. package/dist/clients/print-mode.js +0 -21
  492. package/dist/clients/probe-home-state.js +0 -228
  493. package/dist/clients/process-bridge.js +0 -66
  494. package/dist/clients/process-singletons.js +0 -210
  495. package/dist/clients/process-snapshot.js +0 -68
  496. package/dist/clients/project-changes.js +0 -181
  497. package/dist/clients/project-conventions.js +0 -171
  498. package/dist/clients/project-diagnostics/cache.js +0 -137
  499. package/dist/clients/project-diagnostics/extractors.js +0 -109
  500. package/dist/clients/project-diagnostics/fresh-fetch.js +0 -668
  501. package/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +0 -118
  502. package/dist/clients/project-diagnostics/runner-adapters/dead-code.js +0 -47
  503. package/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +0 -40
  504. package/dist/clients/project-diagnostics/runner-adapters/govulncheck.js +0 -34
  505. package/dist/clients/project-diagnostics/runner-adapters/jscpd.js +0 -38
  506. package/dist/clients/project-diagnostics/runner-adapters/knip.js +0 -47
  507. package/dist/clients/project-diagnostics/runner-adapters/madge.js +0 -48
  508. package/dist/clients/project-diagnostics/runner-adapters/opengrep.js +0 -40
  509. package/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +0 -127
  510. package/dist/clients/project-diagnostics/runner-adapters/trivy.js +0 -81
  511. package/dist/clients/project-diagnostics/scanner.js +0 -520
  512. package/dist/clients/project-diagnostics/types.js +0 -1
  513. package/dist/clients/project-lens-config.js +0 -807
  514. package/dist/clients/project-report.js +0 -701
  515. package/dist/clients/project-scale.js +0 -237
  516. package/dist/clients/project-scan-policy.js +0 -11
  517. package/dist/clients/project-snapshot-fingerprint.js +0 -48
  518. package/dist/clients/project-snapshot-persist-worker.js +0 -20
  519. package/dist/clients/project-snapshot.js +0 -1653
  520. package/dist/clients/project-trust.js +0 -181
  521. package/dist/clients/python-environment.js +0 -217
  522. package/dist/clients/python-provenance.js +0 -639
  523. package/dist/clients/quiet-window-config.js +0 -47
  524. package/dist/clients/quiet-window.js +0 -236
  525. package/dist/clients/read-bridge.js +0 -139
  526. package/dist/clients/read-expansion.js +0 -266
  527. package/dist/clients/read-guard-logger.js +0 -251
  528. package/dist/clients/read-guard-tool-lines.js +0 -1306
  529. package/dist/clients/read-guard.js +0 -1561
  530. package/dist/clients/recent-touches.js +0 -240
  531. package/dist/clients/redact/secrets.js +0 -449
  532. package/dist/clients/resource-sampler.js +0 -628
  533. package/dist/clients/reverse-deps.js +0 -270
  534. package/dist/clients/review-graph/builder.js +0 -5126
  535. package/dist/clients/review-graph/format.js +0 -33
  536. package/dist/clients/review-graph/git-identity.js +0 -163
  537. package/dist/clients/review-graph/import-resolvers.js +0 -481
  538. package/dist/clients/review-graph/persist-worker.js +0 -10
  539. package/dist/clients/review-graph/query.js +0 -244
  540. package/dist/clients/review-graph/revision-drift.js +0 -21
  541. package/dist/clients/review-graph/service.js +0 -96
  542. package/dist/clients/review-graph/shared-extraction-ir.js +0 -82
  543. package/dist/clients/review-graph/symbol-id.js +0 -103
  544. package/dist/clients/review-graph/tsconfig-paths.js +0 -299
  545. package/dist/clients/review-graph/types.js +0 -1
  546. package/dist/clients/review-graph/workspace-modules.js +0 -449
  547. package/dist/clients/review-graph-logger.js +0 -81
  548. package/dist/clients/ruff-client.js +0 -179
  549. package/dist/clients/rules-scanner.js +0 -131
  550. package/dist/clients/run-duration.js +0 -55
  551. package/dist/clients/runtime-agent-end.js +0 -746
  552. package/dist/clients/runtime-config.js +0 -77
  553. package/dist/clients/runtime-context.js +0 -211
  554. package/dist/clients/runtime-coordinator.js +0 -1324
  555. package/dist/clients/runtime-session.js +0 -2485
  556. package/dist/clients/runtime-tool-call.js +0 -1295
  557. package/dist/clients/runtime-tool-result.js +0 -2049
  558. package/dist/clients/runtime-turn.js +0 -3767
  559. package/dist/clients/rust-client.js +0 -97
  560. package/dist/clients/safe-spawn.js +0 -2357
  561. package/dist/clients/sanitize.js +0 -286
  562. package/dist/clients/scan-utils.js +0 -25
  563. package/dist/clients/scratch-tree-policy.js +0 -165
  564. package/dist/clients/search-read-registration.js +0 -94
  565. package/dist/clients/secret-findings.js +0 -114
  566. package/dist/clients/security-scan-client.js +0 -352
  567. package/dist/clients/session-event-guard.js +0 -297
  568. package/dist/clients/session-lifecycle.js +0 -484
  569. package/dist/clients/session-start-observability.js +0 -94
  570. package/dist/clients/session-state-store.js +0 -101
  571. package/dist/clients/session-summary.js +0 -15
  572. package/dist/clients/sessionstart-logger.js +0 -27
  573. package/dist/clients/sg-runner.js +0 -876
  574. package/dist/clients/sgconfig.js +0 -347
  575. package/dist/clients/shared-checkout-guard.js +0 -338
  576. package/dist/clients/single-flight.js +0 -158
  577. package/dist/clients/situational-tool-telemetry.js +0 -108
  578. package/dist/clients/skills-resolver.js +0 -141
  579. package/dist/clients/slow-fs.js +0 -138
  580. package/dist/clients/smells-rollup.js +0 -231
  581. package/dist/clients/source-filter.js +0 -596
  582. package/dist/clients/source-walker.js +0 -211
  583. package/dist/clients/spawn-output-cap.js +0 -120
  584. package/dist/clients/spawn-timeout-cooldown.js +0 -110
  585. package/dist/clients/stale-marker.js +0 -17
  586. package/dist/clients/startup-scan.js +0 -400
  587. package/dist/clients/startup-timing.js +0 -130
  588. package/dist/clients/string-utils.js +0 -33
  589. package/dist/clients/subagent-mode.js +0 -111
  590. package/dist/clients/symbol-containment.js +0 -24
  591. package/dist/clients/symbol-types.js +0 -5
  592. package/dist/clients/test-runner-client.js +0 -2507
  593. package/dist/clients/test-runner-delivery.js +0 -287
  594. package/dist/clients/todo-scanner.js +0 -229
  595. package/dist/clients/tool-agreement.js +0 -423
  596. package/dist/clients/tool-config.js +0 -249
  597. package/dist/clients/tool-cwd.js +0 -270
  598. package/dist/clients/tool-definition.js +0 -47
  599. package/dist/clients/tool-event.js +0 -105
  600. package/dist/clients/tool-policy.js +0 -2755
  601. package/dist/clients/tool-probe.js +0 -53
  602. package/dist/clients/tool-render.js +0 -156
  603. package/dist/clients/tool-set-policy.js +0 -118
  604. package/dist/clients/tree-sitter-cache.js +0 -364
  605. package/dist/clients/tree-sitter-client.js +0 -4195
  606. package/dist/clients/tree-sitter-logger.js +0 -100
  607. package/dist/clients/tree-sitter-navigator.js +0 -269
  608. package/dist/clients/tree-sitter-query-loader.js +0 -569
  609. package/dist/clients/tree-sitter-shared.js +0 -158
  610. package/dist/clients/tree-sitter-symbol-extractor.js +0 -1265
  611. package/dist/clients/trivy-client.js +0 -467
  612. package/dist/clients/tui-fit.js +0 -50
  613. package/dist/clients/turn-context.js +0 -52
  614. package/dist/clients/turn-end/lane.js +0 -51
  615. package/dist/clients/turn-end/lanes/govulncheck.js +0 -112
  616. package/dist/clients/turn-end/lanes/secrets.js +0 -204
  617. package/dist/clients/turn-summary-render.js +0 -72
  618. package/dist/clients/turn-summary.js +0 -132
  619. package/dist/clients/typos-config.js +0 -29
  620. package/dist/clients/user-notify.js +0 -51
  621. package/dist/clients/vanished-instance-marker.js +0 -57
  622. package/dist/clients/warm-attach.js +0 -305
  623. package/dist/clients/widget-state.js +0 -1808
  624. package/dist/clients/word-index-logger.js +0 -49
  625. package/dist/clients/word-index-store.js +0 -459
  626. package/dist/clients/word-index.js +0 -2080
  627. package/dist/clients/workspace-topology.js +0 -443
  628. package/dist/clients/write-ordering-guard.js +0 -65
  629. package/dist/clients/zizmor-config.js +0 -340
  630. package/dist/i18n.js +0 -69
  631. package/dist/mcp/build-staleness.js +0 -124
  632. package/dist/scripts/lib/process-scan.mjs +0 -583
  633. package/dist/scripts/lib/skills-predicate.mjs +0 -129
  634. package/dist/scripts/lib/web-tree-sitter-dir.mjs +0 -123
  635. package/dist/tools/activate-tools.js +0 -87
  636. package/dist/tools/ast-grep-outline.js +0 -137
  637. package/dist/tools/ast-grep-replace.js +0 -244
  638. package/dist/tools/ast-grep-search.js +0 -762
  639. package/dist/tools/effective-config.js +0 -90
  640. package/dist/tools/lens-diagnostic-mark.js +0 -375
  641. package/dist/tools/lens-diagnostics.js +0 -2571
  642. package/dist/tools/lsp-diagnostics.js +0 -1745
  643. package/dist/tools/lsp-navigation.js +0 -1367
  644. package/dist/tools/lsp-structured-output.js +0 -294
  645. package/dist/tools/module-report.js +0 -382
  646. package/dist/tools/project-report.js +0 -86
  647. package/dist/tools/render-compact.js +0 -374
  648. package/dist/tools/scan-progress.js +0 -53
  649. package/dist/tools/shared.js +0 -29
  650. package/dist/tools/symbol-search.js +0 -155
@@ -1,746 +0,0 @@
1
- /**
2
- * LSP Process Launch Utilities
3
- *
4
- * Handles spawning LSP servers via various methods:
5
- * - Direct binary execution (using absolute paths on Windows)
6
- * - Node.js scripts (npx/bun)
7
- * - Package manager execution
8
- */
9
- import { execFileSync, spawn as nodeSpawn, } from "node:child_process";
10
- import fs from "node:fs";
11
- import os from "node:os";
12
- import path from "node:path";
13
- import { isTestMode } from "../env-utils.js";
14
- import { getGlobalPiLensDir } from "../file-utils.js";
15
- import { getGlobalPiLensLogDir } from "../probe-home-state.js";
16
- import { isFullyQualified } from "../path-utils.js";
17
- import { findGlobalBinary } from "../package-manager.js";
18
- import { redactSecrets } from "../redact/secrets.js";
19
- import { classifySpawnFailure, holdOwnChildPid, isOwnLiveChild, SpawnFailureError, } from "../safe-spawn.js";
20
- import { getRubyVersionDirNamesAsync } from "./ruby-drive-dirs.js";
21
- const isWindows = process.platform === "win32";
22
- /**
23
- * Whether a resolved command must be spawned through a shell on Windows.
24
- * `.cmd`/`.bat` are scripts cmd.exe must interpret; extensionless or spaced-path
25
- * commands also go through the shell so cmd resolves/quotes them.
26
- */
27
- function computeNeedsShell(resolvedCommand) {
28
- return (isWindows &&
29
- (resolvedCommand.includes(" ") ||
30
- /\.(cmd|bat)$/i.test(resolvedCommand) ||
31
- !/\.(exe|cmd|bat)$/i.test(resolvedCommand)));
32
- }
33
- const DEFAULT_STARTUP_FAILURE_WINDOW_MS = 50;
34
- const WINDOWS_NAV_STARTUP_FAILURE_WINDOW_MS = 500;
35
- const SESSIONSTART_LOG_DIR = getGlobalPiLensLogDir();
36
- const SESSIONSTART_LOG = path.join(SESSIONSTART_LOG_DIR, "sessionstart.log");
37
- const PI_LENS_BIN_DIR = path.join(getGlobalPiLensDir(), "bin");
38
- const PI_LENS_TOOLS_BIN_DIR = path.join(getGlobalPiLensDir(), "tools", "node_modules", ".bin");
39
- function logSessionStart(msg) {
40
- if (isTestMode()) {
41
- return;
42
- }
43
- // Crash-adjacent: keep this write synchronous so a hard launch failure
44
- // cannot discard the final diagnostic from an async logger queue.
45
- const line = redactSecrets(`[${new Date().toISOString()}] ${msg}\n`);
46
- try {
47
- fs.mkdirSync(SESSIONSTART_LOG_DIR, { recursive: true });
48
- fs.appendFileSync(SESSIONSTART_LOG, line);
49
- }
50
- catch { }
51
- }
52
- function compactLogValue(value, max = 280) {
53
- const normalized = value.replace(/\s+/g, " ").trim();
54
- if (!normalized)
55
- return "";
56
- return normalized.length > max
57
- ? `${normalized.slice(0, max)}...`
58
- : normalized;
59
- }
60
- function delimiterForPlatform(platform) {
61
- return platform === "win32" ? ";" : ":";
62
- }
63
- function splitPathEntries(value, delimiter) {
64
- if (!value)
65
- return [];
66
- return value
67
- .split(delimiter)
68
- .map((entry) => entry.trim())
69
- .filter((entry) => entry.length > 0);
70
- }
71
- /**
72
- * Dedupe key for one PATH entry, under `platform`'s rules.
73
- *
74
- * #1193 P3: the body used the HOST-DEFAULT `path.normalize` inside a branch
75
- * already committed to `platform` (AGENTS.md defect shape 2), so on the ubuntu
76
- * lane the win32 arm lowercased without folding separators or dot segments and
77
- * `C:\Tools` / `C:/Tools` / `C:\x\..\Tools` were three keys for one directory.
78
- * Each arm now parses with its own `path` flavor. That is the whole fix: a
79
- * `toPosix` call on the win32 arm would be INERT — `win32.normalize` already
80
- * answers backslashes for either input separator (measured: adding it left
81
- * every case green) — and the POSIX arm must NOT fold separators at all,
82
- * because a backslash is a legal POSIX filename character and `/opt/a\b` and
83
- * `/opt/a/b` are two directories there.
84
- *
85
- * Ephemeral by construction: the key exists only inside one
86
- * `combinePathValuesForPlatform` call's `seen` set — the ORIGINAL entry string
87
- * is what survives into the joined PATH — so it never reaches a persisted or
88
- * cross-process record and `normalizeEphemeralMapKey`'s `process.platform` read
89
- * would defeat the explicit-`platform` seam these arms exist for.
90
- */
91
- function normalizePathEntry(entry, platform) {
92
- if (platform !== "win32")
93
- return path.posix.normalize(entry);
94
- return path.win32.normalize(entry).toLowerCase();
95
- }
96
- export function combinePathValuesForPlatform(values, platform = process.platform) {
97
- const unique = [];
98
- const seen = new Set();
99
- const delimiter = delimiterForPlatform(platform);
100
- for (const value of values) {
101
- for (const entry of splitPathEntries(value, delimiter)) {
102
- const key = normalizePathEntry(entry, platform);
103
- if (seen.has(key))
104
- continue;
105
- seen.add(key);
106
- unique.push(entry);
107
- }
108
- }
109
- return unique.join(delimiter);
110
- }
111
- function resolvePathValue(env) {
112
- return combinePathValuesForPlatform([env.PATH, env.Path, env.path]);
113
- }
114
- /**
115
- * Run an `execFileSync` probe with the #2095 stderr guard applied, returning
116
- * `""` on any failure. Exported as a small test seam: production always calls
117
- * it with the fixed `powershell.exe` command/args below, but a test can pass
118
- * a command guaranteed to fail with real stderr output (no real Windows or
119
- * powershell.exe required) to prove the guard is actually reached and not
120
- * vacuous.
121
- */
122
- export function runStderrGuardedProbe(command, args) {
123
- try {
124
- const { execFileSync } = require("node:child_process");
125
- const out = execFileSync(command, args, {
126
- timeout: 3000,
127
- encoding: "utf8",
128
- // #2095 sibling: execFileSync inherits stderr to the parent by
129
- // default (only stdout is captured into `out`), so a failed
130
- // powershell.exe launch would print raw diagnostics into the pi
131
- // TUI even though the surrounding catch already returns "" (read as
132
- // "unknown" PATH by every caller). Pipe stderr instead of inheriting it.
133
- stdio: ["ignore", "pipe", "ignore"],
134
- });
135
- return out.trim();
136
- }
137
- catch {
138
- return "";
139
- }
140
- }
141
- /** Read live system+user PATH from Windows registry (bypasses stale process.env.PATH). */
142
- function readWindowsRegistryPath() {
143
- return runStderrGuardedProbe("powershell.exe", [
144
- "-NoProfile",
145
- "-NonInteractive",
146
- "-Command",
147
- "[System.Environment]::GetEnvironmentVariable('Path','Machine') + ';' + [System.Environment]::GetEnvironmentVariable('Path','User')",
148
- ]);
149
- }
150
- let _liveWindowsPath = null;
151
- function getLiveWindowsPath() {
152
- if (_liveWindowsPath === null) {
153
- _liveWindowsPath = readWindowsRegistryPath();
154
- }
155
- return _liveWindowsPath;
156
- }
157
- async function buildAugmentedPath(basePath) {
158
- const candidates = [];
159
- const nodeDir = path.dirname(process.execPath);
160
- if (nodeDir) {
161
- candidates.push(nodeDir);
162
- }
163
- if (isWindows) {
164
- const home = os.homedir();
165
- const driveRoot = path.parse(home).root; // e.g. "C:\"
166
- candidates.push(path.join(home, ".cargo", "bin"));
167
- candidates.push(path.join(home, "go", "bin"));
168
- candidates.push(path.join(home, ".dotnet", "tools"));
169
- candidates.push(PI_LENS_BIN_DIR);
170
- candidates.push(PI_LENS_TOOLS_BIN_DIR);
171
- candidates.push(path.join(driveRoot, "Program Files", "Go", "bin"));
172
- candidates.push(path.join(driveRoot, "Go", "bin"));
173
- // Ruby installer drops versioned dirs (e.g. Ruby34-x64) on the drive root.
174
- // Read off the event loop and memoized once per process (#1137): a
175
- // synchronous drive-root enumeration on every LSP spawn blocked the loop
176
- // for the whole stall on a slow cloud/network-backed drive root.
177
- for (const entry of await getRubyVersionDirNamesAsync(driveRoot)) {
178
- candidates.push(path.join(driveRoot, entry, "bin"));
179
- }
180
- }
181
- // On Windows, merge the live registry PATH so newly installed tools are visible
182
- // even if the pi agent process started before they were installed.
183
- const effectiveBase = isWindows
184
- ? combinePathValuesForPlatform([basePath, getLiveWindowsPath()])
185
- : basePath;
186
- const existing = new Set();
187
- for (const entry of splitPathEntries(effectiveBase, path.delimiter)) {
188
- if (!entry)
189
- continue;
190
- existing.add(normalizePathEntry(entry, process.platform));
191
- }
192
- const toAppend = [];
193
- for (const candidate of candidates) {
194
- if (!candidate || !fs.existsSync(candidate))
195
- continue;
196
- const normalized = normalizePathEntry(candidate, process.platform);
197
- if (existing.has(normalized))
198
- continue;
199
- toAppend.push(candidate);
200
- existing.add(normalized);
201
- }
202
- if (toAppend.length === 0)
203
- return basePath ?? "";
204
- if (!basePath)
205
- return toAppend.join(path.delimiter);
206
- return `${basePath}${path.delimiter}${toAppend.join(path.delimiter)}`;
207
- }
208
- /**
209
- * Validate that a .cmd shim's target JS/script exists before attempting to
210
- * spawn it. npm-generated .cmd files reference the actual script via a path
211
- * like `"%~dp0\..\yaml-language-server\bin\yaml-language-server"`. If that
212
- * target is missing the shim will exit immediately with code 1 after a 500ms
213
- * startup window — pre-checking avoids the delay.
214
- * Returns true if the shim is valid (or we can't determine), false if the
215
- * target is definitively missing.
216
- */
217
- export function isCmdShimValid(cmdPath) {
218
- try {
219
- const content = fs.readFileSync(cmdPath, "utf-8");
220
- // npm cmd shim pattern: "%~dp0\..\<relpath>" or "%~dp0/<relpath>"
221
- // The `-` ends the char class, where it is a literal and needs no escape.
222
- // oxfmt formats this repository (#1844) and rewrites no regex literal, so
223
- // this line needs no suppression; the directive oxfmt honors, if one is
224
- // ever needed here, is `// prettier-ignore`.
225
- const match = content.match(/"%~dp0[/\\]\.\.[/\\]((?:[\w./@-]|\\)+\.(?:mjs|cjs|js))"/i);
226
- if (!match)
227
- return true; // non-npm shim — let it through
228
- const relPath = match[1].replace(/[/\\]/g, path.sep);
229
- const target = path.resolve(path.dirname(cmdPath), "..", relPath);
230
- return fs.existsSync(target);
231
- }
232
- catch {
233
- return true; // can't read — be permissive
234
- }
235
- }
236
- /**
237
- * On Windows, npm creates .ps1 wrappers that hang indefinitely when PowerShell
238
- * execution policy is Restricted or AllSigned. Bypass by preferring the .cmd
239
- * sibling (runs under cmd.exe, no execution policy) or falling back to direct
240
- * Node.js execution of the JS entry point extracted from the PS1 script.
241
- * Returns undefined if no safe bypass is found.
242
- */
243
- function bypassPs1OnWindows(ps1Path, args) {
244
- // 1. Prefer the .cmd sibling — cmd.exe handles it without execution policy issues
245
- const cmdPath = `${ps1Path.slice(0, -4)}.cmd`;
246
- if (fs.existsSync(cmdPath)) {
247
- return { command: cmdPath, args, needsShell: true };
248
- }
249
- // 2. Parse the .ps1 to find the JS entry point and invoke via node directly.
250
- // npm-generated PS1 pattern: "$basedir/../<package>/bin/cli.js"
251
- try {
252
- const content = fs.readFileSync(ps1Path, "utf-8");
253
- // Same char class as isCmdShimValid above, and the same note: the trailing
254
- // `-` is a literal, and oxfmt leaves regex literals alone.
255
- const match = content.match(/"\$basedir[/\\]\.\.[/\\]((?:[\w./@-]|\\)+\.(?:mjs|cjs|js))"/i);
256
- if (match) {
257
- const relPath = match[1].replace(/[/\\]/g, path.sep);
258
- const jsPath = path.resolve(path.dirname(ps1Path), "..", relPath);
259
- if (fs.existsSync(jsPath)) {
260
- return {
261
- command: process.execPath,
262
- args: [jsPath, ...args],
263
- needsShell: false,
264
- };
265
- }
266
- }
267
- }
268
- catch {
269
- // Can't read PS1 — no bypass available
270
- }
271
- return undefined;
272
- }
273
- function findBinaryOnPath(command, env) {
274
- try {
275
- const result = execFileSync(isWindows ? "where" : "which", [command], {
276
- encoding: "utf-8",
277
- stdio: ["ignore", "pipe", "ignore"],
278
- env,
279
- // #1980 population sweep: this was the one synchronous
280
- // child-process site in the repo with no bound at all. It runs on
281
- // the LSP server spawn path, so an unresponsive `where`/`which` — a
282
- // stale network PATH entry is the classic cause — parked the event
283
- // loop with no ceiling, and read as ordinary compute in
284
- // `loop_block`. 5s matches `isCommandAvailable`/`findCommand` in
285
- // clients/safe-spawn.ts, which run these same two binaries.
286
- timeout: 5000,
287
- })
288
- .split(/\r?\n/)
289
- .map((line) => line.trim())
290
- .filter(Boolean);
291
- for (const candidate of result) {
292
- if (fs.existsSync(candidate)) {
293
- return candidate;
294
- }
295
- }
296
- }
297
- catch {
298
- // ignore lookup failures
299
- }
300
- return undefined;
301
- }
302
- /**
303
- * Try to spawn a process, throwing immediately if it fails
304
- */
305
- function trySpawn(command, args, cwd, env, needsShell) {
306
- let proc;
307
- if (needsShell) {
308
- // Build a cmd.exe-safe command string: wrap in double quotes, escape internal
309
- // quotes by doubling them, and escape cmd metacharacters (& | < > ^ ( ) !) with ^
310
- const escapeCmdArg = (s) => {
311
- // Escape cmd.exe metacharacters first, then wrap in quotes if needed
312
- const escaped = s.replace(/([&|<>^()!])/g, "^$1");
313
- return /[\s"]/.test(escaped)
314
- ? `"${escaped.replace(/"/g, '""')}"`
315
- : escaped;
316
- };
317
- // shell:true justified: Windows .cmd/.bat LSP binaries (e.g. typescript-language-server.cmd)
318
- // cannot be spawned via execFile — cmd.exe must interpret the script wrapper.
319
- const shellCommand = `"${command}" ${args.map(escapeCmdArg).join(" ")}`;
320
- // #2015 class-sweep exemption: this is a LONG-LIVED language-server launch,
321
- // not a bounded probe - killing it on a timeout would be wrong, and its
322
- // lifetime is owned by the LSP lifecycle, not the spawner. Exempt from the
323
- // verifyToolBinary/probe tree-kill migration.
324
- proc = nodeSpawn(shellCommand, [], {
325
- cwd,
326
- env,
327
- stdio: ["pipe", "pipe", "pipe"],
328
- detached: !isWindows,
329
- windowsHide: true,
330
- shell: true,
331
- });
332
- }
333
- else {
334
- // Use normal spawn without shell
335
- proc = nodeSpawn(command, args, {
336
- cwd,
337
- env,
338
- stdio: ["pipe", "pipe", "pipe"],
339
- detached: !isWindows,
340
- windowsHide: isWindows,
341
- });
342
- }
343
- if (!proc.stdin || !proc.stdout || !proc.stderr) {
344
- throw new Error(`Failed to spawn LSP server: ${command}`);
345
- }
346
- // Check if process exited immediately (spawn failure - synchronous check)
347
- if (proc.exitCode !== null || proc.killed) {
348
- throw new Error(`LSP server ${command} exited immediately (code: ${proc.exitCode}). ` +
349
- `The binary may be missing or corrupted.`);
350
- }
351
- // #3091 F1-r2: take ownership HERE, while the child is provably alive. LSP
352
- // servers are the one long-lived child pi-lens spawns outside
353
- // `safeSpawnAsync`, so without this their first offer of verification is
354
- // `stopLSP`'s group kill — by which time, on the `processExiting` path, the
355
- // leader can already be dead, `/proc` is gone, and the group signal that
356
- // reaps surviving grandchildren (#2026) is refused. The verdict is released
357
- // by `killProcessTree` when the shutdown ladder is done with the pid.
358
- holdOwnChildPid(proc.pid, "lsp-spawn");
359
- return proc;
360
- }
361
- /**
362
- * Attach error handler to a spawned process to prevent ENOENT crashes
363
- * This catches "command not found" errors and other spawn failures
364
- * Returns a promise that rejects if an immediate error occurs
365
- */
366
- function unrefLspProcessHandles(proc) {
367
- try {
368
- proc.unref();
369
- }
370
- catch {
371
- // best-effort
372
- }
373
- for (const stream of [proc.stdin, proc.stdout, proc.stderr]) {
374
- try {
375
- stream?.unref?.();
376
- }
377
- catch {
378
- // best-effort
379
- }
380
- }
381
- }
382
- function _attachErrorHandler(proc, context, logContext, rejectOnImmediateError) {
383
- let stderrPreview = "";
384
- let closeLogged = false;
385
- const onStderr = (chunk) => {
386
- if (stderrPreview.length >= 4000)
387
- return;
388
- stderrPreview += chunk.toString();
389
- };
390
- proc.stderr?.on("data", onStderr);
391
- proc.on("error", (err) => {
392
- if (logContext) {
393
- logSessionStart("lsp process " +
394
- context +
395
- ": spawn-error command=" +
396
- logContext.command +
397
- " args=" +
398
- JSON.stringify(logContext.args) +
399
- " cwd=" +
400
- logContext.cwd +
401
- " pid=" +
402
- (logContext.pid ?? 0) +
403
- " error=" +
404
- err.message +
405
- (stderrPreview ? " stderr=" + compactLogValue(stderrPreview) : ""));
406
- }
407
- // Preserve intent at the boundary instead of leaking a raw errno check.
408
- if (rejectOnImmediateError && logContext) {
409
- void classifySpawnFailure(err, {
410
- command: logContext.command,
411
- cwd: logContext.cwd,
412
- }).then(rejectOnImmediateError);
413
- }
414
- });
415
- proc.on("close", (code, signal) => {
416
- if (closeLogged)
417
- return;
418
- closeLogged = true;
419
- proc.stderr?.off("data", onStderr);
420
- if (code !== 0 && code !== null) {
421
- if (logContext) {
422
- logSessionStart("lsp process " +
423
- context +
424
- ": closed code=" +
425
- code +
426
- (signal ? " signal=" + signal : "") +
427
- " command=" +
428
- logContext.command +
429
- " args=" +
430
- JSON.stringify(logContext.args) +
431
- " cwd=" +
432
- logContext.cwd +
433
- " pid=" +
434
- (logContext.pid ?? 0) +
435
- (stderrPreview ? " stderr=" + compactLogValue(stderrPreview) : ""));
436
- }
437
- }
438
- else if (signal && logContext) {
439
- logSessionStart("lsp process " +
440
- context +
441
- ": closed signal=" +
442
- signal +
443
- " command=" +
444
- logContext.command +
445
- " args=" +
446
- JSON.stringify(logContext.args) +
447
- " cwd=" +
448
- logContext.cwd +
449
- " pid=" +
450
- (logContext.pid ?? 0) +
451
- (stderrPreview ? " stderr=" + compactLogValue(stderrPreview) : ""));
452
- }
453
- });
454
- }
455
- /**
456
- * Spawn an LSP server process
457
- *
458
- * Key fixes for Windows:
459
- * - Uses absolute paths (relative paths fail in shell mode)
460
- * - Uses shell: true for .cmd files
461
- * - Uses windowsHide to prevent console window popup
462
- * - Detects immediate spawn failures (ENOENT) before returning
463
- *
464
- * @param command - Command to run (e.g., "typescript-language-server")
465
- * @param args - Arguments (e.g., ["--stdio"])
466
- * @param options - Spawn options including cwd, env
467
- * @returns LSPProcess handle
468
- */
469
- export async function launchLSP(command, args = [], options = {}) {
470
- const cwd = String(options.cwd ?? process.cwd());
471
- const mergedEnv = { ...process.env, ...options.env };
472
- const augmentedPath = await buildAugmentedPath(resolvePathValue(mergedEnv));
473
- const env = {
474
- ...mergedEnv,
475
- PATH: augmentedPath,
476
- ...(isWindows ? { Path: augmentedPath } : {}),
477
- };
478
- // Resolve command path
479
- // - If already absolute, use as-is
480
- // - If it's a simple command (no path separators), let system find it via PATH
481
- // - Otherwise, resolve relative to cwd
482
- const isRelativePath = !isFullyQualified(command) &&
483
- (command.includes(path.sep) || command.includes("/"));
484
- const explicitCommand = isRelativePath ? path.resolve(cwd, command) : command;
485
- const resolvedCommand = !isFullyQualified(command) &&
486
- !command.includes(path.sep) &&
487
- !command.includes("/")
488
- ? (findBinaryOnPath(command, env) ?? explicitCommand)
489
- : explicitCommand;
490
- // Compute needsShell based on command
491
- // On Windows, shell: true is needed for .cmd/.bat files and extensionless binaries
492
- // .exe files can be spawned directly, but .cmd/.bat require shell interpretation
493
- let needsShell = computeNeedsShell(resolvedCommand);
494
- // Try to spawn the process
495
- // If command not found, try npm global as fallback (handles PATH caching after install)
496
- let spawnCommand = resolvedCommand;
497
- // First, try to find in npm global if it's a simple command name
498
- if (!isFullyQualified(command) &&
499
- !command.includes(path.sep) &&
500
- !command.includes("/")) {
501
- const globalBinPath = await findGlobalBinary(command);
502
- if (globalBinPath) {
503
- spawnCommand = globalBinPath;
504
- // Recompute needsShell for the resolved global path
505
- needsShell = computeNeedsShell(spawnCommand);
506
- }
507
- }
508
- // Pre-validate .cmd shims: if the underlying script is missing the shim will
509
- // exit with code 1 after a 500ms wait. Catching this early avoids the delay.
510
- if (isWindows &&
511
- /\.(cmd|bat)$/i.test(spawnCommand) &&
512
- !isCmdShimValid(spawnCommand)) {
513
- logSessionStart(`lsp cmd-shim-invalid: ${spawnCommand} target missing — skipping candidate`);
514
- const cause = Object.assign(new Error(`LSP .cmd shim target not found: ${spawnCommand}`), { code: "ENOENT" });
515
- throw await classifySpawnFailure(cause, { command, cwd });
516
- }
517
- // P0 FIX: Never spawn .ps1 wrappers on Windows — they hang when PowerShell
518
- // execution policy is Restricted/AllSigned. Prefer .cmd or direct node.
519
- if (isWindows && /\.ps1$/i.test(spawnCommand)) {
520
- const bypass = bypassPs1OnWindows(spawnCommand, args);
521
- if (bypass) {
522
- logSessionStart(`lsp ps1-bypass: ${spawnCommand} → ${bypass.command} shell=${bypass.needsShell}`);
523
- spawnCommand = bypass.command;
524
- args = bypass.args;
525
- needsShell = bypass.needsShell;
526
- }
527
- else {
528
- logSessionStart(`lsp ps1-bypass: no .cmd or JS entry found for ${spawnCommand}, spawn may hang`);
529
- }
530
- }
531
- let proc;
532
- try {
533
- proc = trySpawn(spawnCommand, args, cwd, env, needsShell);
534
- }
535
- catch (err) {
536
- // If spawn failed with simple command, try npm global
537
- if (!isFullyQualified(command) &&
538
- !command.includes(path.sep) &&
539
- !command.includes("/")) {
540
- const globalBinPath = await findGlobalBinary(command);
541
- if (globalBinPath && globalBinPath !== spawnCommand) {
542
- // Recompute needsShell for the resolved global path
543
- const needsShellGlobal = computeNeedsShell(globalBinPath);
544
- proc = trySpawn(globalBinPath, args, cwd, env, needsShellGlobal);
545
- }
546
- else {
547
- throw await classifySpawnFailure(err, { command, cwd });
548
- }
549
- }
550
- else {
551
- throw await classifySpawnFailure(err, { command, cwd });
552
- }
553
- }
554
- if (!proc.stdin || !proc.stdout || !proc.stderr) {
555
- throw new Error(`Failed to spawn LSP server: ${command}`);
556
- }
557
- // Check if process exited immediately (spawn failure - synchronous check)
558
- if (proc.exitCode !== null || proc.killed) {
559
- throw new Error(`LSP server ${command} exited immediately (code: ${proc.exitCode}). ` +
560
- `The binary may be missing or corrupted.`);
561
- }
562
- logSessionStart(`lsp launch: command=${command} resolved=${spawnCommand} args=${JSON.stringify(args)} cwd=${cwd} shell=${needsShell ? "true" : "false"} pid=${proc.pid ?? 0}`);
563
- const formatStartupStderr = (stderr) => {
564
- const normalized = compactLogValue(stderr);
565
- if (!normalized)
566
- return "";
567
- return ` stderr=${normalized}`;
568
- };
569
- let startupStderr = "";
570
- const onStartupStderr = (chunk) => {
571
- if (startupStderr.length >= 4000)
572
- return;
573
- startupStderr += chunk.toString();
574
- };
575
- proc.stderr?.on("data", onStartupStderr);
576
- // For Windows and certain spawn failures, the error is async (ENOENT)
577
- // We need to wait a small tick to catch immediate spawn failures
578
- try {
579
- await new Promise((resolve, reject) => {
580
- let settled = false;
581
- // Attach error handler that can reject for immediate errors
582
- proc.on("error", (err) => {
583
- if (!settled) {
584
- settled = true;
585
- void classifySpawnFailure(err, { command, cwd }).then((failure) => {
586
- const detail = formatStartupStderr(startupStderr);
587
- reject(detail
588
- ? new SpawnFailureError(failure.kind, `${failure.message}${detail}`, failure.cause)
589
- : failure);
590
- });
591
- }
592
- });
593
- // Also listen for immediate exit
594
- proc.on("exit", (code) => {
595
- if (!settled && code !== null) {
596
- settled = true;
597
- // On Windows, .cmd shims fail with code 1 when the underlying binary isn't installed
598
- // This is different from ENOENT - the shim exists but can't find the binary
599
- const isWindowsCmd = isWindows && command.endsWith(".cmd");
600
- const errorMsg = isWindowsCmd && code === 1
601
- ? `npm .cmd shim failed (underlying binary not installed). Run 'npm install' in this project or use a global installation.`
602
- : `The binary may be missing or corrupted.`;
603
- reject(new Error(`LSP server ${command} exited immediately with code ${code}. ${errorMsg}${formatStartupStderr(startupStderr)}`));
604
- }
605
- });
606
- const startupFailureWindowMs = (() => {
607
- if (options?.startupFailureWindowMs) {
608
- return options.startupFailureWindowMs;
609
- }
610
- if (isWindows && needsShell) {
611
- return WINDOWS_NAV_STARTUP_FAILURE_WINDOW_MS;
612
- }
613
- return DEFAULT_STARTUP_FAILURE_WINDOW_MS;
614
- })();
615
- // Give shell-backed Windows launches a slightly longer window because
616
- // npm/cmd shims can fail asynchronously after the initial spawn succeeds.
617
- setTimeout(() => {
618
- if (!settled) {
619
- settled = true;
620
- resolve();
621
- }
622
- }, startupFailureWindowMs);
623
- });
624
- }
625
- finally {
626
- proc.stderr?.off("data", onStartupStderr);
627
- }
628
- // Re-attach the permanent error handler now that we've passed the danger zone
629
- _attachErrorHandler(proc, command, {
630
- command: spawnCommand,
631
- args,
632
- cwd,
633
- pid: proc.pid ?? 0,
634
- });
635
- unrefLspProcessHandles(proc);
636
- return {
637
- process: proc,
638
- stdin: proc.stdin,
639
- stdout: proc.stdout,
640
- stderr: proc.stderr,
641
- pid: proc.pid ?? 0,
642
- command: spawnCommand,
643
- args,
644
- };
645
- }
646
- /**
647
- * Spawn via Node.js directly
648
- */
649
- export async function launchViaNode(scriptPath, args = [], options = {}) {
650
- return launchLSP(process.execPath, [scriptPath, ...args], options);
651
- }
652
- /**
653
- * Spawn via Python module
654
- */
655
- export async function launchViaPython(moduleName, args = [], options = {}) {
656
- // On Windows, prefer 'py' launcher, fall back to 'python'
657
- const pythonCmd = process.platform === "win32" ? "py" : "python3";
658
- return launchLSP(pythonCmd, ["-m", moduleName, ...args], options);
659
- }
660
- /**
661
- * Stop an LSP process gracefully
662
- */
663
- export async function stopLSP(handle) {
664
- if (handle.process.exitCode !== null || handle.process.signalCode !== null) {
665
- return;
666
- }
667
- return new Promise((resolve) => {
668
- let settled = false;
669
- let forceTimeout;
670
- let giveUpTimeout;
671
- const done = () => {
672
- if (settled)
673
- return;
674
- settled = true;
675
- if (forceTimeout)
676
- clearTimeout(forceTimeout);
677
- if (giveUpTimeout)
678
- clearTimeout(giveUpTimeout);
679
- handle.process.off("exit", done);
680
- handle.process.off("error", done);
681
- resolve();
682
- };
683
- handle.process.once("exit", done);
684
- handle.process.once("error", done);
685
- const killWindowsTree = () => {
686
- if (!isWindows)
687
- return false;
688
- // If our child has already exited, its PID is dead and the OS may have
689
- // RECYCLED it to an unrelated process. `taskkill /F /T` on a recycled PID
690
- // force-kills that process AND its whole tree — in the test suite this
691
- // occasionally nuked a vitest worker fork ("Worker exited unexpectedly",
692
- // no fatal dump, e.g. via the "stopLSP after the process already exited"
693
- // path); in production it could kill an unrelated user process. Never
694
- // tree-kill a PID we no longer own — fall back to handle.process.kill(),
695
- // which on Windows signals via the retained process HANDLE (not the raw
696
- // PID), so it's a safe no-op on an already-exited child.
697
- //
698
- // #2042 folded the sign check and this exited check into the one
699
- // ownership predicate every kill-by-raw-pid now shares; the handle
700
- // arm below IS this paragraph, and on Windows it is the only
701
- // ownership evidence available (there is no /proc to read).
702
- if (!isOwnLiveChild(handle.pid, "lsp-stop-windows-tree", handle.process))
703
- return false;
704
- try {
705
- // Absolute path avoids PATH-resolution substitution on Windows.
706
- const taskkill = `${process.env.SystemRoot ?? "C:\\Windows"}\\System32\\taskkill.exe`;
707
- const killer = nodeSpawn(taskkill, ["/F", "/T", "/PID", String(handle.pid)], {
708
- shell: false,
709
- windowsHide: true,
710
- });
711
- killer.once("error", done);
712
- return true;
713
- }
714
- catch {
715
- return false;
716
- }
717
- };
718
- try {
719
- // On Windows, kill the tree first; killing the direct child can orphan
720
- // grandchildren (e.g. tsserver.js behind a cmd/npm shim).
721
- if (!killWindowsTree()) {
722
- handle.process.kill("SIGTERM");
723
- }
724
- }
725
- catch {
726
- done();
727
- return;
728
- }
729
- forceTimeout = setTimeout(() => {
730
- if (settled)
731
- return;
732
- try {
733
- if (!killWindowsTree()) {
734
- handle.process.kill("SIGKILL");
735
- }
736
- }
737
- catch {
738
- done();
739
- return;
740
- }
741
- // If the process had already exited before listeners were attached, no
742
- // exit event will arrive. Resolve rather than hanging test cleanup forever.
743
- giveUpTimeout = setTimeout(done, 500);
744
- }, 5000);
745
- });
746
- }