pi-lens 3.8.73 → 4.0.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 (346) hide show
  1. package/CHANGELOG.md +2614 -12
  2. package/README.md +50 -21
  3. package/dist/clients/actionable-warnings.js +73 -18
  4. package/dist/clients/agent-behavior-client.js +21 -4
  5. package/dist/clients/ast-grep-client.js +68 -16
  6. package/dist/clients/ast-grep-types.js +0 -1
  7. package/dist/clients/ast-grep-yaml-synth.js +37 -10
  8. package/dist/clients/atomic-write-staging.js +63 -0
  9. package/dist/clients/atomic-write.js +116 -16
  10. package/dist/clients/bash-file-access.js +193 -23
  11. package/dist/clients/biome-client.js +29 -25
  12. package/dist/clients/bootstrap.js +11 -2
  13. package/dist/clients/bounded-cache.js +34 -0
  14. package/dist/clients/bounded-pid-file-lock.js +192 -0
  15. package/dist/clients/bus-events-logger.js +5 -1
  16. package/dist/clients/bus-publish.js +10 -3
  17. package/dist/clients/cache/rule-cache.js +89 -6
  18. package/dist/clients/cache-manager.js +97 -9
  19. package/dist/clients/cache-observability.js +498 -0
  20. package/dist/clients/call-graph.js +460 -108
  21. package/dist/clients/cascade-logger.js +5 -1
  22. package/dist/clients/child-unref.js +85 -0
  23. package/dist/clients/codebase-model.js +52 -23
  24. package/dist/clients/collateral-test-role.js +40 -0
  25. package/dist/clients/complexity-client.js +6 -8
  26. package/dist/clients/console-guard-install.js +14 -0
  27. package/dist/clients/cooperative-budget.js +42 -0
  28. package/dist/clients/dead-code-client.js +2 -1
  29. package/dist/clients/debug-handles.js +206 -0
  30. package/dist/clients/debug-heap.js +167 -0
  31. package/dist/clients/degradation-ledger.js +153 -0
  32. package/dist/clients/dependency-checker.js +466 -63
  33. package/dist/clients/diagnostic-dispositions.js +83 -13
  34. package/dist/clients/diagnostics-publish.js +10 -3
  35. package/dist/clients/dispatch/auxiliary-lsp.js +34 -0
  36. package/dist/clients/dispatch/dispatcher.js +71 -13
  37. package/dist/clients/dispatch/fact-store.js +11 -0
  38. package/dist/clients/dispatch/facts/function-facts.js +37 -7
  39. package/dist/clients/dispatch/facts/import-facts.js +108 -119
  40. package/dist/clients/dispatch/facts/tree-sitter-facts.js +12 -12
  41. package/dist/clients/dispatch/facts/try-catch-facts.js +13 -0
  42. package/dist/clients/dispatch/indent-detect.js +35 -0
  43. package/dist/clients/dispatch/inline-suppressions.js +17 -8
  44. package/dist/clients/dispatch/integration.js +1094 -611
  45. package/dist/clients/dispatch/lazy.js +14 -0
  46. package/dist/clients/dispatch/plan.js +11 -1
  47. package/dist/clients/dispatch/rule-id-normalize.js +50 -0
  48. package/dist/clients/dispatch/rule-policy.js +135 -0
  49. package/dist/clients/dispatch/rules/async-noise.js +1 -0
  50. package/dist/clients/dispatch/rules/unsafe-boundary.js +7 -0
  51. package/dist/clients/dispatch/runners/ast-grep-napi.js +47 -6
  52. package/dist/clients/dispatch/runners/biome-check.js +5 -9
  53. package/dist/clients/dispatch/runners/detekt.js +3 -2
  54. package/dist/clients/dispatch/runners/hadolint.js +2 -1
  55. package/dist/clients/dispatch/runners/helm-lint.js +154 -0
  56. package/dist/clients/dispatch/runners/htmlhint.js +3 -2
  57. package/dist/clients/dispatch/runners/index.js +5 -1
  58. package/dist/clients/dispatch/runners/lsp.js +14 -6
  59. package/dist/clients/dispatch/runners/markdownlint.js +4 -9
  60. package/dist/clients/dispatch/runners/psscriptanalyzer.js +10 -1
  61. package/dist/clients/dispatch/runners/pyright.js +9 -5
  62. package/dist/clients/dispatch/runners/ruff.js +4 -8
  63. package/dist/clients/dispatch/runners/shellcheck.js +2 -3
  64. package/dist/clients/dispatch/runners/shfmt.js +2 -3
  65. package/dist/clients/dispatch/runners/spotbugs.js +2 -1
  66. package/dist/clients/dispatch/runners/taplo.js +2 -1
  67. package/dist/clients/dispatch/runners/terragrunt.js +163 -0
  68. package/dist/clients/dispatch/runners/tflint.js +37 -5
  69. package/dist/clients/dispatch/runners/tree-sitter.js +155 -166
  70. package/dist/clients/dispatch/runners/trivy-config.js +13 -7
  71. package/dist/clients/dispatch/runners/utils/lazy-installer.js +3 -0
  72. package/dist/clients/dispatch/runners/utils/runner-helpers.js +284 -34
  73. package/dist/clients/dispatch/runners/utils/spawn-outcome.js +22 -0
  74. package/dist/clients/dispatch/runners/yaml-rule-parser.js +5 -4
  75. package/dist/clients/disposition-publish.js +10 -3
  76. package/dist/clients/durable-store.js +97 -0
  77. package/dist/clients/event-loop-monitor.js +94 -3
  78. package/dist/clients/extension-log.js +139 -0
  79. package/dist/clients/extension-mode.js +73 -0
  80. package/dist/clients/feature-hints.js +53 -7
  81. package/dist/clients/file-kinds.js +143 -31
  82. package/dist/clients/file-role.js +18 -3
  83. package/dist/clients/file-utils.js +56 -34
  84. package/dist/clients/fix-worklog.js +14 -2
  85. package/dist/clients/format-events-publish.js +16 -3
  86. package/dist/clients/format-service.js +24 -8
  87. package/dist/clients/formatters-lazy.js +8 -0
  88. package/dist/clients/formatters.js +358 -61
  89. package/dist/clients/generated-artifacts.js +169 -15
  90. package/dist/clients/git-guard.js +681 -11
  91. package/dist/clients/git-tracked-ignore.js +4 -0
  92. package/dist/clients/go-client.js +2 -1
  93. package/dist/clients/govulncheck-client.js +8 -0
  94. package/dist/clients/grammar-source.js +12 -4
  95. package/dist/clients/gzip-stage-write.js +102 -0
  96. package/dist/clients/host-ports.js +31 -0
  97. package/dist/clients/installer/index.js +733 -213
  98. package/dist/clients/instance-reaper.js +142 -172
  99. package/dist/clients/jscpd-client.js +31 -54
  100. package/dist/clients/knip-client.js +78 -36
  101. package/dist/clients/language-policy.js +14 -2
  102. package/dist/clients/language-profile.js +72 -77
  103. package/dist/clients/latency-logger.js +28 -16
  104. package/dist/clients/lens-config.js +140 -166
  105. package/dist/clients/lens-engine.js +124 -21
  106. package/dist/clients/lens-events.js +27 -4
  107. package/dist/clients/lens-flag-registry.js +293 -0
  108. package/dist/clients/lens-map.js +96 -26
  109. package/dist/clients/live-bus-emitter.js +30 -0
  110. package/dist/clients/log-cleanup.js +8 -18
  111. package/dist/clients/lsp/cascade-tier.js +23 -3
  112. package/dist/clients/lsp/client.js +566 -57
  113. package/dist/clients/lsp/config.js +74 -10
  114. package/dist/clients/lsp/diagnostic-binding.js +86 -0
  115. package/dist/clients/lsp/edits.js +1012 -121
  116. package/dist/clients/lsp/index.js +1840 -803
  117. package/dist/clients/lsp/language.js +4 -1
  118. package/dist/clients/lsp/launch.js +40 -32
  119. package/dist/clients/lsp/path-utils.js +1 -1
  120. package/dist/clients/lsp/ruby-drive-dirs.js +83 -0
  121. package/dist/clients/lsp/server.js +279 -60
  122. package/dist/clients/lsp/workspace-diagnostics-cache.js +28 -4
  123. package/dist/clients/lsp-document-symbols.js +112 -0
  124. package/dist/clients/lsp-lazy.js +8 -0
  125. package/dist/clients/lsp-mutation.js +248 -0
  126. package/dist/clients/mcp/analyze.js +128 -36
  127. package/dist/clients/mcp/ipc.js +157 -24
  128. package/dist/clients/mcp/review.js +36 -3
  129. package/dist/clients/mcp/session.js +216 -8
  130. package/dist/clients/memory-sampler.js +115 -0
  131. package/dist/clients/metrics-client.js +2 -1
  132. package/dist/clients/metrics-history.js +2 -1
  133. package/dist/clients/module-report-lsp.js +5 -0
  134. package/dist/clients/module-report.js +267 -82
  135. package/dist/clients/ndjson-logger.js +334 -103
  136. package/dist/clients/opengrep-client.js +1 -1
  137. package/dist/clients/partial-edit-apply.js +120 -5
  138. package/dist/clients/path-keyed-map.js +76 -0
  139. package/dist/clients/path-utils.js +141 -5
  140. package/dist/clients/performance-report.js +327 -0
  141. package/dist/clients/pipeline.js +54 -13
  142. package/dist/clients/print-mode.js +21 -0
  143. package/dist/clients/project-changes.js +117 -4
  144. package/dist/clients/project-diagnostics/cache.js +3 -2
  145. package/dist/clients/project-diagnostics/extractors.js +26 -115
  146. package/dist/clients/project-diagnostics/fresh-fetch.js +149 -19
  147. package/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +117 -0
  148. package/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +37 -5
  149. package/dist/clients/project-diagnostics/scanner.js +268 -128
  150. package/dist/clients/project-lens-config.js +138 -34
  151. package/dist/clients/project-report.js +64 -25
  152. package/dist/clients/project-scale.js +8 -10
  153. package/dist/clients/project-snapshot-persist-worker.js +6 -0
  154. package/dist/clients/project-snapshot.js +767 -8
  155. package/dist/clients/project-trust.js +181 -0
  156. package/dist/clients/quiet-window.js +27 -5
  157. package/dist/clients/read-bridge.js +147 -0
  158. package/dist/clients/read-expansion.js +22 -12
  159. package/dist/clients/read-guard-logger.js +159 -1
  160. package/dist/clients/read-guard-tool-lines.js +150 -29
  161. package/dist/clients/read-guard.js +262 -3
  162. package/dist/clients/redact/secrets.js +449 -0
  163. package/dist/clients/resource-sampler.js +144 -39
  164. package/dist/clients/reverse-deps.js +48 -0
  165. package/dist/clients/review-graph/builder.js +2570 -326
  166. package/dist/clients/review-graph/git-identity.js +2 -1
  167. package/dist/clients/review-graph/import-resolvers.js +21 -10
  168. package/dist/clients/review-graph/persist-worker.js +10 -0
  169. package/dist/clients/review-graph/query.js +5 -0
  170. package/dist/clients/review-graph/shared-extraction-ir.js +90 -0
  171. package/dist/clients/review-graph/symbol-id.js +46 -0
  172. package/dist/clients/review-graph/tsconfig-paths.js +57 -6
  173. package/dist/clients/review-graph/workspace-modules.js +51 -3
  174. package/dist/clients/review-graph-logger.js +53 -0
  175. package/dist/clients/ruff-client.js +27 -44
  176. package/dist/clients/runtime-agent-end.js +111 -75
  177. package/dist/clients/runtime-context.js +36 -12
  178. package/dist/clients/runtime-coordinator.js +76 -8
  179. package/dist/clients/runtime-session.js +799 -137
  180. package/dist/clients/runtime-tool-call.js +117 -62
  181. package/dist/clients/runtime-tool-result.js +218 -23
  182. package/dist/clients/runtime-turn.js +284 -40
  183. package/dist/clients/rust-client.js +2 -1
  184. package/dist/clients/safe-spawn.js +873 -71
  185. package/dist/clients/security-scan-client.js +2 -1
  186. package/dist/clients/session-start-observability.js +15 -0
  187. package/dist/clients/session-state-store.js +5 -3
  188. package/dist/clients/sessionstart-logger.js +18 -0
  189. package/dist/clients/sg-runner.js +284 -159
  190. package/dist/clients/slow-fs.js +2 -1
  191. package/dist/clients/smells-rollup.js +224 -0
  192. package/dist/clients/source-filter.js +231 -43
  193. package/dist/clients/source-walker.js +66 -10
  194. package/dist/clients/startup-scan.js +15 -16
  195. package/dist/clients/startup-timing.js +9 -0
  196. package/dist/clients/test-runner-client.js +38 -8
  197. package/dist/clients/todo-scanner.js +30 -3
  198. package/dist/clients/tool-event.js +35 -0
  199. package/dist/clients/tool-policy.js +388 -39
  200. package/dist/clients/tool-render.js +155 -0
  201. package/dist/clients/tree-sitter-cache.js +153 -140
  202. package/dist/clients/tree-sitter-client.js +1722 -80
  203. package/dist/clients/tree-sitter-logger.js +64 -1
  204. package/dist/clients/tree-sitter-query-loader.js +117 -12
  205. package/dist/clients/tree-sitter-shared.js +48 -19
  206. package/dist/clients/tree-sitter-symbol-extractor.js +115 -11
  207. package/dist/clients/user-notify.js +51 -0
  208. package/dist/clients/vanished-instance-marker.js +57 -0
  209. package/dist/clients/warm-attach.js +33 -13
  210. package/dist/clients/widget-state.js +342 -49
  211. package/dist/clients/word-index-logger.js +44 -0
  212. package/dist/clients/word-index.js +612 -68
  213. package/dist/clients/workspace-topology.js +100 -7
  214. package/dist/index.js +65923 -47161
  215. package/dist/mcp/analyze-cli.js +185 -29
  216. package/dist/mcp/cli.js +110 -0
  217. package/dist/mcp/server.js +272 -50
  218. package/dist/tools/ast-grep-search.js +93 -27
  219. package/dist/tools/lens-diagnostics.js +247 -41
  220. package/dist/tools/lsp-diagnostics.js +153 -40
  221. package/dist/tools/lsp-navigation.js +51 -31
  222. package/dist/tools/module-report.js +9 -0
  223. package/dist/tools/symbol-search.js +21 -2
  224. package/docs/agent-guide.md +247 -0
  225. package/docs/agent-tools.md +21 -10
  226. package/docs/analysisall.md +192 -0
  227. package/docs/api-ports-inventory.md +165 -0
  228. package/docs/ast-grep_rules_catalog.md +5 -2
  229. package/docs/astplayground.md +3 -4
  230. package/docs/audit1.md +5 -5
  231. package/docs/durable-store-audit-1202.md +32 -0
  232. package/docs/environment-variables.md +197 -11
  233. package/docs/fable.md +27 -0
  234. package/docs/features.md +35 -5
  235. package/docs/globalconfig.md +101 -5
  236. package/docs/language-coverage.md +6 -5
  237. package/docs/lsp-capability-matrix.md +2 -2
  238. package/docs/mcp.md +54 -20
  239. package/docs/servercapabilities.md +7 -4
  240. package/docs/settings.md +192 -0
  241. package/docs/tools.md +18 -1
  242. package/docs/tree-sitter_rules_catalog.md +11 -31
  243. package/docs/usage.md +31 -0
  244. package/package.json +139 -138
  245. package/rules/ast-grep-rules/rule-tests/hardcoded-url-js-test.yml +1 -0
  246. package/rules/ast-grep-rules/rule-tests/hardcoded-url-test.yml +2 -0
  247. package/rules/ast-grep-rules/rule-tests/no-bare-except-test.yml +49 -0
  248. package/rules/ast-grep-rules/rule-tests/no-bare-host-path-in-win32-branch-test.yml +87 -0
  249. package/rules/ast-grep-rules/rule-tests/no-case-declarations-js-test.yml +10 -0
  250. package/rules/ast-grep-rules/rule-tests/no-case-declarations-test.yml +10 -0
  251. package/rules/ast-grep-rules/rule-tests/no-javascript-url-js-test.yml +10 -0
  252. package/rules/ast-grep-rules/rule-tests/no-javascript-url-test.yml +10 -0
  253. package/rules/ast-grep-rules/rule-tests/no-nested-links-test.yml +11 -1
  254. package/rules/ast-grep-rules/rule-tests/no-raw-json-store-write-test.yml +17 -0
  255. package/rules/ast-grep-rules/rule-tests/no-win32-isabsolute-for-qualification-test.yml +16 -0
  256. package/rules/ast-grep-rules/rule-tests/strict-equality-js-test.yml +3 -0
  257. package/rules/ast-grep-rules/rule-tests/strict-equality-test.yml +3 -0
  258. package/rules/ast-grep-rules/rule-tests/strict-inequality-js-test.yml +3 -0
  259. package/rules/ast-grep-rules/rule-tests/strict-inequality-test.yml +4 -0
  260. package/rules/ast-grep-rules/rules/hardcoded-url-js.yml +22 -4
  261. package/rules/ast-grep-rules/rules/hardcoded-url.yml +22 -4
  262. package/rules/ast-grep-rules/rules/no-bare-except.yml +3 -15
  263. package/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +25 -0
  264. package/rules/ast-grep-rules/rules/no-case-declarations-js.yml +4 -3
  265. package/rules/ast-grep-rules/rules/no-case-declarations.yml +4 -3
  266. package/rules/ast-grep-rules/rules/no-console-except-error-js.yml +10 -0
  267. package/rules/ast-grep-rules/rules/no-console-except-error.yml +10 -0
  268. package/rules/ast-grep-rules/rules/no-javascript-url-js.yml +42 -6
  269. package/rules/ast-grep-rules/rules/no-javascript-url.yml +42 -6
  270. package/rules/ast-grep-rules/rules/no-nested-links.yml +7 -0
  271. package/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +30 -0
  272. package/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +23 -0
  273. package/rules/ast-grep-rules/rules/strict-equality-js.yml +14 -1
  274. package/rules/ast-grep-rules/rules/strict-equality.yml +14 -1
  275. package/rules/ast-grep-rules/rules/strict-inequality-js.yml +14 -1
  276. package/rules/ast-grep-rules/rules/strict-inequality.yml +14 -1
  277. package/rules/tree-sitter-queries/cpp/no-memset-sensitive-data.yml +9 -3
  278. package/rules/tree-sitter-queries/cpp/no-scoped-lock-without-args.yml +6 -6
  279. package/rules/tree-sitter-queries/css/calc-spacing.yml +8 -6
  280. package/rules/tree-sitter-queries/go/go-mutex-copy.yml +21 -18
  281. package/rules/tree-sitter-queries/go/go-shared-map-write-goroutine.yml +3 -3
  282. package/rules/tree-sitter-queries/java/infinite-loop-java.yml +3 -3
  283. package/rules/tree-sitter-queries/java/junit-call-super.yml +6 -4
  284. package/rules/tree-sitter-queries/java/no-double-checked-locking.yml +10 -8
  285. package/rules/tree-sitter-queries/java/no-field-shadowing.yml +1 -1
  286. package/rules/tree-sitter-queries/java/prepared-statement-valid-indices.yml +2 -3
  287. package/rules/tree-sitter-queries/java/resources-closed.yml +2 -2
  288. package/rules/tree-sitter-queries/java/springboot-default-package.yml +6 -3
  289. package/rules/tree-sitter-queries/java/switch-fall-through.yml +6 -4
  290. package/rules/tree-sitter-queries/java/switch-non-case-labels.yml +4 -3
  291. package/rules/tree-sitter-queries/java/tests-include-assertions.yml +6 -5
  292. package/rules/tree-sitter-queries/javascript/switch-case-termination-js.yml +5 -8
  293. package/rules/tree-sitter-queries/javascript/switch-non-case-labels.yml +3 -2
  294. package/rules/tree-sitter-queries/kotlin/prepared-statement-indices.yml +9 -5
  295. package/rules/tree-sitter-queries/php/this-in-static-context.yml +5 -5
  296. package/rules/tree-sitter-queries/python/exit-signature-check.yml +2 -9
  297. package/rules/tree-sitter-queries/python/in-operator-unsupported.yml +3 -4
  298. package/rules/tree-sitter-queries/python/no-super-torchscript.yml +4 -8
  299. package/rules/tree-sitter-queries/python/notimplemented-boolean-context.yml +1 -5
  300. package/rules/tree-sitter-queries/python/python-empty-except.yml +1 -1
  301. package/rules/tree-sitter-queries/python/return-in-init.yml +0 -2
  302. package/rules/tree-sitter-queries/python/yield-return-outside-function.yml +0 -3
  303. package/rules/tree-sitter-queries/ruby/ruby-command-injection.yml +1 -12
  304. package/rules/tree-sitter-queries/ruby/ruby-eval.yml +1 -1
  305. package/rules/tree-sitter-queries/ruby/ruby-insecure-deserialization.yml +4 -4
  306. package/rules/tree-sitter-queries/ruby/ruby-insecure-random.yml +4 -11
  307. package/rules/tree-sitter-queries/ruby/ruby-open-struct.yml +1 -1
  308. package/rules/tree-sitter-queries/ruby/ruby-string-eval.yml +2 -3
  309. package/rules/tree-sitter-queries/ruby/ruby-weak-hash.yml +4 -4
  310. package/rules/tree-sitter-queries/rust/rust-lock-held-across-await.yml +4 -3
  311. package/rules/tree-sitter-queries/tsx/no-nested-links.yml +4 -6
  312. package/rules/tree-sitter-queries/typescript/console-statement.yml +11 -0
  313. package/rules/tree-sitter-queries/typescript/duplicate-function-arg.yml +4 -9
  314. package/rules/tree-sitter-queries/typescript/empty-switch-case.yml +13 -9
  315. package/rules/tree-sitter-queries/typescript/infinite-loop.yml +2 -2
  316. package/rules/tree-sitter-queries/typescript/mixed-async-styles.yml +10 -1
  317. package/rules/tree-sitter-queries/typescript/switch-case-termination.yml +5 -8
  318. package/rules/tree-sitter-queries/typescript/ts-insecure-random.yml +7 -10
  319. package/rules/tree-sitter-queries/typescript/unsafe-regex.yml +4 -2
  320. package/rules/typos/_typos.toml +17 -0
  321. package/scripts/analyze-pi-lens-logs.mjs +55 -2
  322. package/skills/pi-lens-write-tree-sitter-rule/SKILL.md +5 -0
  323. package/dist/clients/ast-grep-parser.js +0 -86
  324. package/dist/clients/config-enabled-shape.js +0 -39
  325. package/dist/clients/lsp/interactive-install.js +0 -367
  326. package/dist/clients/lsp/lsp-index.js +0 -10
  327. package/dist/clients/lsp/server-strategies.js +0 -5
  328. package/dist/clients/project-metadata.js +0 -690
  329. package/dist/clients/source-groups.js +0 -96
  330. package/dist/clients/types.js +0 -11
  331. package/docs/env_variables.md +0 -10
  332. package/rules/tree-sitter-queries/abap-disabled/delete-where.yml +0 -46
  333. package/rules/tree-sitter-queries/cpp/no-confused-move-forward.yml +0 -59
  334. package/rules/tree-sitter-queries/cpp/noexcept-functions.yml +0 -58
  335. package/rules/tree-sitter-queries/java/mockito-initialized.yml +0 -66
  336. package/rules/tree-sitter-queries/java/no-wait-notify-on-thread.yml +0 -58
  337. package/rules/tree-sitter-queries/java/short-circuit-logic.yml +0 -57
  338. package/rules/tree-sitter-queries/java/spring-session-attributes-setcomplete.yml +0 -75
  339. package/rules/tree-sitter-queries/plsql-disabled/delete-update-where.yml +0 -56
  340. package/rules/tree-sitter-queries/plsql-disabled/end-loop-semicolon.yml +0 -51
  341. package/rules/tree-sitter-queries/plsql-disabled/fetch-bulk-collect-limit.yml +0 -47
  342. package/rules/tree-sitter-queries/plsql-disabled/forallsave-exceptions.yml +0 -51
  343. package/rules/tree-sitter-queries/plsql-disabled/nchar-nvarchar2-bytes.yml +0 -54
  344. package/rules/tree-sitter-queries/plsql-disabled/not-null-initialization.yml +0 -59
  345. package/rules/tree-sitter-queries/plsql-disabled/raise-application-error-codes.yml +0 -50
  346. package/rules/tree-sitter-queries/typescript-disabled/ts-path-traversal.yml +0 -71
@@ -63,7 +63,10 @@ export const LANGUAGE_EXTENSIONS = {
63
63
  ".sh": "shellscript",
64
64
  ".bash": "shellscript",
65
65
  ".zsh": "shellscript",
66
- ".fish": "shellscript",
66
+ ".fish": "fish",
67
+ // CMake
68
+ ".cmake": "cmake",
69
+ "CMakeLists.txt": "cmake",
67
70
  // JSON/YAML
68
71
  ".json": "json",
69
72
  ".jsonc": "jsonc",
@@ -12,7 +12,11 @@ import os from "node:os";
12
12
  import path from "node:path";
13
13
  import { isTestMode } from "../env-utils.js";
14
14
  import { getGlobalPiLensDir } from "../file-utils.js";
15
+ import { isFullyQualified } from "../path-utils.js";
15
16
  import { findGlobalBinary } from "../package-manager.js";
17
+ import { redactSecrets } from "../redact/secrets.js";
18
+ import { classifySpawnFailure, SpawnFailureError, } from "../safe-spawn.js";
19
+ import { getRubyVersionDirNamesAsync } from "./ruby-drive-dirs.js";
16
20
  const isWindows = process.platform === "win32";
17
21
  /**
18
22
  * Whether a resolved command must be spawned through a shell on Windows.
@@ -35,7 +39,9 @@ function logSessionStart(msg) {
35
39
  if (isTestMode()) {
36
40
  return;
37
41
  }
38
- const line = `[${new Date().toISOString()}] ${msg}\n`;
42
+ // Crash-adjacent: keep this write synchronous so a hard launch failure
43
+ // cannot discard the final diagnostic from an async logger queue.
44
+ const line = redactSecrets(`[${new Date().toISOString()}] ${msg}\n`);
39
45
  try {
40
46
  fs.mkdirSync(SESSIONSTART_LOG_DIR, { recursive: true });
41
47
  fs.appendFileSync(SESSIONSTART_LOG, line);
@@ -106,7 +112,7 @@ function getLiveWindowsPath() {
106
112
  }
107
113
  return _liveWindowsPath;
108
114
  }
109
- function buildAugmentedPath(basePath) {
115
+ async function buildAugmentedPath(basePath) {
110
116
  const candidates = [];
111
117
  const nodeDir = path.dirname(process.execPath);
112
118
  if (nodeDir) {
@@ -122,16 +128,12 @@ function buildAugmentedPath(basePath) {
122
128
  candidates.push(PI_LENS_TOOLS_BIN_DIR);
123
129
  candidates.push(path.join(driveRoot, "Program Files", "Go", "bin"));
124
130
  candidates.push(path.join(driveRoot, "Go", "bin"));
125
- // Ruby installer drops versioned dirs (e.g. Ruby34-x64) on the drive root — scan dynamically
126
- try {
127
- for (const entry of fs.readdirSync(driveRoot)) {
128
- if (/^ruby\d/i.test(entry)) {
129
- candidates.push(path.join(driveRoot, entry, "bin"));
130
- }
131
- }
132
- }
133
- catch {
134
- // drive root not readable — skip
131
+ // Ruby installer drops versioned dirs (e.g. Ruby34-x64) on the drive root.
132
+ // Read off the event loop and memoized once per process (#1137): a
133
+ // synchronous drive-root enumeration on every LSP spawn blocked the loop
134
+ // for the whole stall on a slow cloud/network-backed drive root.
135
+ for (const entry of await getRubyVersionDirNamesAsync(driveRoot)) {
136
+ candidates.push(path.join(driveRoot, entry, "bin"));
135
137
  }
136
138
  }
137
139
  // On Windows, merge the live registry PATH so newly installed tools are visible
@@ -336,10 +338,12 @@ function _attachErrorHandler(proc, context, logContext, rejectOnImmediateError)
336
338
  err.message +
337
339
  (stderrPreview ? " stderr=" + compactLogValue(stderrPreview) : ""));
338
340
  }
339
- // If we have a reject function and this is an immediate spawn error, reject
340
- if (rejectOnImmediateError &&
341
- err.code === "ENOENT") {
342
- rejectOnImmediateError(err);
341
+ // Preserve intent at the boundary instead of leaking a raw errno check.
342
+ if (rejectOnImmediateError && logContext) {
343
+ void classifySpawnFailure(err, {
344
+ command: logContext.command,
345
+ cwd: logContext.cwd,
346
+ }).then(rejectOnImmediateError);
343
347
  }
344
348
  });
345
349
  proc.on("close", (code, signal) => {
@@ -399,7 +403,7 @@ function _attachErrorHandler(proc, context, logContext, rejectOnImmediateError)
399
403
  export async function launchLSP(command, args = [], options = {}) {
400
404
  const cwd = String(options.cwd ?? process.cwd());
401
405
  const mergedEnv = { ...process.env, ...options.env };
402
- const augmentedPath = buildAugmentedPath(resolvePathValue(mergedEnv));
406
+ const augmentedPath = await buildAugmentedPath(resolvePathValue(mergedEnv));
403
407
  const env = {
404
408
  ...mergedEnv,
405
409
  PATH: augmentedPath,
@@ -409,10 +413,10 @@ export async function launchLSP(command, args = [], options = {}) {
409
413
  // - If already absolute, use as-is
410
414
  // - If it's a simple command (no path separators), let system find it via PATH
411
415
  // - Otherwise, resolve relative to cwd
412
- const isRelativePath = !path.isAbsolute(command) &&
416
+ const isRelativePath = !isFullyQualified(command) &&
413
417
  (command.includes(path.sep) || command.includes("/"));
414
418
  const explicitCommand = isRelativePath ? path.resolve(cwd, command) : command;
415
- const resolvedCommand = !path.isAbsolute(command) &&
419
+ const resolvedCommand = !isFullyQualified(command) &&
416
420
  !command.includes(path.sep) &&
417
421
  !command.includes("/")
418
422
  ? (findBinaryOnPath(command, env) ?? explicitCommand)
@@ -425,7 +429,7 @@ export async function launchLSP(command, args = [], options = {}) {
425
429
  // If command not found, try npm global as fallback (handles PATH caching after install)
426
430
  let spawnCommand = resolvedCommand;
427
431
  // First, try to find in npm global if it's a simple command name
428
- if (!path.isAbsolute(command) &&
432
+ if (!isFullyQualified(command) &&
429
433
  !command.includes(path.sep) &&
430
434
  !command.includes("/")) {
431
435
  const globalBinPath = await findGlobalBinary(command);
@@ -441,7 +445,8 @@ export async function launchLSP(command, args = [], options = {}) {
441
445
  /\.(cmd|bat)$/i.test(spawnCommand) &&
442
446
  !isCmdShimValid(spawnCommand)) {
443
447
  logSessionStart(`lsp cmd-shim-invalid: ${spawnCommand} target missing — skipping candidate`);
444
- throw new Error(`LSP .cmd shim target not found: ${spawnCommand}. The npm package may not be installed.`);
448
+ const cause = Object.assign(new Error(`LSP .cmd shim target not found: ${spawnCommand}`), { code: "ENOENT" });
449
+ throw await classifySpawnFailure(cause, { command, cwd });
445
450
  }
446
451
  // P0 FIX: Never spawn .ps1 wrappers on Windows — they hang when PowerShell
447
452
  // execution policy is Restricted/AllSigned. Prefer .cmd or direct node.
@@ -463,7 +468,7 @@ export async function launchLSP(command, args = [], options = {}) {
463
468
  }
464
469
  catch (err) {
465
470
  // If spawn failed with simple command, try npm global
466
- if (!path.isAbsolute(command) &&
471
+ if (!isFullyQualified(command) &&
467
472
  !command.includes(path.sep) &&
468
473
  !command.includes("/")) {
469
474
  const globalBinPath = await findGlobalBinary(command);
@@ -473,11 +478,11 @@ export async function launchLSP(command, args = [], options = {}) {
473
478
  proc = trySpawn(globalBinPath, args, cwd, env, needsShellGlobal);
474
479
  }
475
480
  else {
476
- throw err;
481
+ throw await classifySpawnFailure(err, { command, cwd });
477
482
  }
478
483
  }
479
484
  else {
480
- throw err;
485
+ throw await classifySpawnFailure(err, { command, cwd });
481
486
  }
482
487
  }
483
488
  if (!proc.stdin || !proc.stdout || !proc.stderr) {
@@ -509,10 +514,14 @@ export async function launchLSP(command, args = [], options = {}) {
509
514
  let settled = false;
510
515
  // Attach error handler that can reject for immediate errors
511
516
  proc.on("error", (err) => {
512
- if (!settled && (err.code === "ENOENT" || err.code === "EINVAL")) {
517
+ if (!settled) {
513
518
  settled = true;
514
- reject(new Error(`LSP server binary not found: ${command}. ` +
515
- `Install it or check your PATH.${formatStartupStderr(startupStderr)}`));
519
+ void classifySpawnFailure(err, { command, cwd }).then((failure) => {
520
+ const detail = formatStartupStderr(startupStderr);
521
+ reject(detail
522
+ ? new SpawnFailureError(failure.kind, `${failure.message}${detail}`, failure.cause)
523
+ : failure);
524
+ });
516
525
  }
517
526
  });
518
527
  // Also listen for immediate exit
@@ -532,12 +541,10 @@ export async function launchLSP(command, args = [], options = {}) {
532
541
  if (options?.startupFailureWindowMs) {
533
542
  return options.startupFailureWindowMs;
534
543
  }
535
- else if (isWindows && needsShell) {
544
+ if (isWindows && needsShell) {
536
545
  return WINDOWS_NAV_STARTUP_FAILURE_WINDOW_MS;
537
546
  }
538
- else {
539
- return DEFAULT_STARTUP_FAILURE_WINDOW_MS;
540
- }
547
+ return DEFAULT_STARTUP_FAILURE_WINDOW_MS;
541
548
  })();
542
549
  // Give shell-backed Windows launches a slightly longer window because
543
550
  // npm/cmd shims can fail asynchronously after the initial spawn succeeds.
@@ -621,7 +628,8 @@ export async function stopLSP(handle) {
621
628
  // tree-kill a PID we no longer own — fall back to handle.process.kill(),
622
629
  // which on Windows signals via the retained process HANDLE (not the raw
623
630
  // PID), so it's a safe no-op on an already-exited child.
624
- if (handle.process.exitCode !== null || handle.process.signalCode !== null)
631
+ if (handle.process.exitCode !== null ||
632
+ handle.process.signalCode !== null)
625
633
  return false;
626
634
  try {
627
635
  // Absolute path avoids PATH-resolution substitution on Windows.
@@ -2,4 +2,4 @@
2
2
  * Re-export from shared path-utils.
3
3
  * Kept as a local module for LSP imports that use relative paths.
4
4
  */
5
- export { isUnderDir, normalizeFilePath, normalizeMapKey, pathsEqual, pathToUri, uriToPath, } from "../path-utils.js";
5
+ export { isUnderDir, normalizeFilePath, normalizeEphemeralMapKey, normalizeMapKey, pathsEqual, pathToUri, uriToDiskPath, uriToPath, } from "../path-utils.js";
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Windows Ruby-installer drive-root version-dir discovery (refs #1137).
3
+ *
4
+ * The Ruby installer drops versioned directories (e.g. `Ruby34-x64`) directly
5
+ * at a drive root, and the drive and version suffix vary — so both the LSP
6
+ * candidate builder (`rubyBinCandidates`) and the spawn PATH augmenter
7
+ * (`buildAugmentedPath`) scan the drive root for `ruby<N>...` directories.
8
+ *
9
+ * Enumerating a drive root **synchronously on every LSP spawn** was a genuine
10
+ * #1137 event-loop offender: a stalled cloud/network-backed drive-root
11
+ * `readdirSync` blocks the Node loop (and pi's TUI) for the entire stall. This
12
+ * module makes that enumeration:
13
+ * 1. **O(1) amortized** — the matching directory names are memoized for the
14
+ * process (the set is static for a session; the previous inline code
15
+ * equally required a restart to notice a new Ruby install on PATH), and
16
+ * 2. **non-blocking on the hot path** — `buildAugmentedPath` (called on every
17
+ * spawn) reads the drive root via `fs.promises.readdir` off the loop.
18
+ *
19
+ * Both readers share ONE cache keyed by `driveRoot`, so at most one drive-root
20
+ * read happens per drive per process regardless of which reader runs first.
21
+ * Callers derive their own paths from the returned directory NAMES (the two
22
+ * readers build different suffixes: `bin/<tool>` vs `bin`), so only the raw
23
+ * `ruby<N>` names are cached.
24
+ */
25
+ import { BoundedLruCache } from "../bounded-cache.js";
26
+ import { normalizeMapKey } from "../path-utils.js";
27
+ import * as fs from "node:fs";
28
+ /** Matches the Ruby installer's `Ruby34-x64`, `ruby3.3`, … drive-root dirs. */
29
+ const RUBY_VERSION_DIR = /^ruby\d/i;
30
+ /** Process-lifetime memo of matching dir names, keyed by drive root (e.g. `C:\`). */
31
+ const rubyDirNamesCache = new BoundedLruCache(16);
32
+ function rubyDriveKey(driveRoot) {
33
+ return normalizeMapKey(driveRoot);
34
+ }
35
+ function filterRubyDirNames(entries) {
36
+ return entries.filter((name) => RUBY_VERSION_DIR.test(name));
37
+ }
38
+ /**
39
+ * Memoized **synchronous** enumeration for sync callers (`rubyBinCandidates`).
40
+ * First call reads the drive root once (fail-open to `[]` on an unreadable
41
+ * root); every later call is a cache hit. If an async caller populated the
42
+ * cache first, this returns that result with no drive-root read at all.
43
+ */
44
+ export function getRubyVersionDirNamesSync(driveRoot) {
45
+ const key = rubyDriveKey(driveRoot);
46
+ const cached = rubyDirNamesCache.get(key);
47
+ if (cached !== undefined)
48
+ return cached;
49
+ let names;
50
+ try {
51
+ names = filterRubyDirNames(fs.readdirSync(driveRoot));
52
+ }
53
+ catch {
54
+ names = [];
55
+ }
56
+ rubyDirNamesCache.set(key, names);
57
+ return names;
58
+ }
59
+ /**
60
+ * Memoized **async** twin for the hot spawn path (`buildAugmentedPath`) — reads
61
+ * the drive root via `fs.promises.readdir` so a slow/stalled cloud-backed drive
62
+ * root never blocks the event loop. Shares the same process cache as the sync
63
+ * reader (identical content, so a benign sync/async populate race is fine).
64
+ */
65
+ export async function getRubyVersionDirNamesAsync(driveRoot) {
66
+ const key = rubyDriveKey(driveRoot);
67
+ const cached = rubyDirNamesCache.get(key);
68
+ if (cached !== undefined)
69
+ return cached;
70
+ let names;
71
+ try {
72
+ names = filterRubyDirNames(await fs.promises.readdir(driveRoot));
73
+ }
74
+ catch {
75
+ names = [];
76
+ }
77
+ rubyDirNamesCache.set(key, names);
78
+ return names;
79
+ }
80
+ /** Test-only: clear the process memo so each case starts cold. */
81
+ export function __resetRubyDriveDirsCacheForTest() {
82
+ rubyDirNamesCache.clear();
83
+ }