@herbertgao/pi-extensions 2026.9.1 → 2026.9.3

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 (341) hide show
  1. package/README.md +3 -2
  2. package/THIRD_PARTY_NOTICES.md +24 -0
  3. package/node_modules/@herbertgao/sol-pi/LICENSE +19 -0
  4. package/node_modules/@herbertgao/sol-pi/README.md +159 -0
  5. package/node_modules/@herbertgao/sol-pi/SECURITY.md +26 -0
  6. package/node_modules/@herbertgao/sol-pi/THIRD_PARTY_NOTICES.md +19 -0
  7. package/node_modules/@herbertgao/sol-pi/agents-install.md +150 -0
  8. package/node_modules/@herbertgao/sol-pi/assets/sol-pi-hero.png +0 -0
  9. package/node_modules/@herbertgao/sol-pi/docs/compatibility.md +69 -0
  10. package/node_modules/@herbertgao/sol-pi/docs/configuration.md +75 -0
  11. package/node_modules/@herbertgao/sol-pi/package.json +76 -0
  12. package/node_modules/@herbertgao/sol-pi/scripts/check-pi-compat.mjs +32 -0
  13. package/node_modules/@herbertgao/sol-pi/scripts/check-sol-pi-config.mjs +120 -0
  14. package/node_modules/@herbertgao/sol-pi/sol-pi.example.json +10 -0
  15. package/node_modules/@herbertgao/sol-pi/src/sol-pi/config.ts +135 -0
  16. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/file-queue.ts +74 -0
  17. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/index.ts +185 -0
  18. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/then-run.ts +128 -0
  19. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/archive.ts +53 -0
  20. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/candidate.ts +101 -0
  21. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/config.ts +71 -0
  22. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/index.ts +220 -0
  23. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/journal.ts +25 -0
  24. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/provider.ts +164 -0
  25. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/receipt.ts +177 -0
  26. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/observation-pack/index.ts +227 -0
  27. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/observation-pack/ledger.ts +20 -0
  28. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/observation-pack/observation.ts +252 -0
  29. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/economics.ts +237 -0
  30. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/extension.ts +455 -0
  31. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/index.ts +49 -0
  32. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/plan.ts +79 -0
  33. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/state.ts +208 -0
  34. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/tools.ts +100 -0
  35. package/node_modules/@herbertgao/sol-pi/src/sol-pi/index.ts +42 -0
  36. package/node_modules/@herbertgao/sol-pi/src/sol-pi/runtime-paths.ts +17 -0
  37. package/node_modules/@herbertgao/sol-pi/src/sol-pi/tui.ts +71 -0
  38. package/node_modules/@narumitw/pi-btw/README.md +57 -141
  39. package/node_modules/@narumitw/pi-btw/dist/index.ts +478 -43
  40. package/node_modules/@narumitw/pi-btw/dist/index.ts.map +4 -4
  41. package/node_modules/@narumitw/pi-btw/docs/workflows.md +74 -0
  42. package/node_modules/@narumitw/pi-btw/package.json +2 -1
  43. package/node_modules/@narumitw/pi-btw/src/btw.ts +28 -3
  44. package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +32 -2
  45. package/node_modules/@narumitw/pi-btw/src/keybindings.ts +330 -0
  46. package/node_modules/@narumitw/pi-btw/src/menu.ts +136 -19
  47. package/node_modules/@narumitw/pi-btw/src/settings.ts +32 -0
  48. package/node_modules/@narumitw/pi-btw/src/side-thread.ts +57 -5
  49. package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +52 -30
  50. package/node_modules/pi-lens/CHANGELOG.md +260 -0
  51. package/node_modules/pi-lens/README.md +13 -8
  52. package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +3 -1
  53. package/node_modules/pi-lens/dist/clients/actionable-warnings-logger.js +0 -7
  54. package/node_modules/pi-lens/dist/clients/advisory-provenance.js +1 -1
  55. package/node_modules/pi-lens/dist/clients/analysed-root.js +1 -0
  56. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +1 -1
  57. package/node_modules/pi-lens/dist/clients/ast-grep-tool-logger.js +1 -8
  58. package/node_modules/pi-lens/dist/clients/ast-grep-types.js +2 -0
  59. package/node_modules/pi-lens/dist/clients/bash-file-access.js +133 -1
  60. package/node_modules/pi-lens/dist/clients/biome-client.js +13 -2
  61. package/node_modules/pi-lens/dist/clients/blocker-freshness.js +0 -6
  62. package/node_modules/pi-lens/dist/clients/bootstrap.js +4 -4
  63. package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +1 -1
  64. package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +2 -5
  65. package/node_modules/pi-lens/dist/clients/bus-events-logger.js +1 -9
  66. package/node_modules/pi-lens/dist/clients/cache-observability.js +122 -6
  67. package/node_modules/pi-lens/dist/clients/cargo-manifest.js +2 -2
  68. package/node_modules/pi-lens/dist/clients/cascade-logger.js +0 -7
  69. package/node_modules/pi-lens/dist/clients/child-unref.js +1 -19
  70. package/node_modules/pi-lens/dist/clients/complexity-client.js +5 -0
  71. package/node_modules/pi-lens/dist/clients/config-core/index.js +11 -8
  72. package/node_modules/pi-lens/dist/clients/config-core/process-spec.js +1 -1
  73. package/node_modules/pi-lens/dist/clients/config-core/provenance.js +2 -9
  74. package/node_modules/pi-lens/dist/clients/config-core/records.js +1 -1
  75. package/node_modules/pi-lens/dist/clients/config-core/schema.js +3 -5
  76. package/node_modules/pi-lens/dist/clients/config-diagnostic-codes.js +3 -1
  77. package/node_modules/pi-lens/dist/clients/config-resolve.js +10 -7
  78. package/node_modules/pi-lens/dist/clients/config-schema.js +56 -2
  79. package/node_modules/pi-lens/dist/clients/config-warn.js +2 -2
  80. package/node_modules/pi-lens/dist/clients/dead-code-client.js +8 -1
  81. package/node_modules/pi-lens/dist/clients/dead-code-logger.js +0 -4
  82. package/node_modules/pi-lens/dist/clients/dependency-checker.js +5 -1
  83. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +1 -1
  84. package/node_modules/pi-lens/dist/clients/diagnostic-logger.js +1 -1
  85. package/node_modules/pi-lens/dist/clients/dispatch/collect-later-tier.js +0 -4
  86. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +38 -41
  87. package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +1 -1
  88. package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +5 -1
  89. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +18 -1
  90. package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +0 -6
  91. package/node_modules/pi-lens/dist/clients/dispatch/pending-runner-findings.js +1 -1
  92. package/node_modules/pi-lens/dist/clients/dispatch/plan.js +0 -3
  93. package/node_modules/pi-lens/dist/clients/dispatch/rules/high-complexity.js +2 -2
  94. package/node_modules/pi-lens/dist/clients/dispatch/rules/high-fan-out.js +1 -1
  95. package/node_modules/pi-lens/dist/clients/dispatch/runners/actionlint.js +2 -1
  96. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +3 -1
  97. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +2 -3
  98. package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +7 -2
  99. package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +2 -1
  100. package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +2 -1
  101. package/node_modules/pi-lens/dist/clients/dispatch/runners/dart-analyze.js +2 -1
  102. package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +2 -1
  103. package/node_modules/pi-lens/dist/clients/dispatch/runners/dotnet-build.js +2 -1
  104. package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +2 -1
  105. package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +2 -1
  106. package/node_modules/pi-lens/dist/clients/dispatch/runners/fish-indent.js +2 -1
  107. package/node_modules/pi-lens/dist/clients/dispatch/runners/gleam-check.js +2 -1
  108. package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +2 -1
  109. package/node_modules/pi-lens/dist/clients/dispatch/runners/golangci-lint.js +2 -1
  110. package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +2 -1
  111. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +3 -1
  112. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +3 -2
  113. package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +2 -1
  114. package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +2 -1
  115. package/node_modules/pi-lens/dist/clients/dispatch/runners/ktlint.js +2 -1
  116. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +19 -1
  117. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +3 -2
  118. package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +2 -1
  119. package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +3 -1
  120. package/node_modules/pi-lens/dist/clients/dispatch/runners/php-lint.js +2 -1
  121. package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +2 -1
  122. package/node_modules/pi-lens/dist/clients/dispatch/runners/prisma-validate.js +2 -1
  123. package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +15 -11
  124. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +2 -1
  125. package/node_modules/pi-lens/dist/clients/dispatch/runners/rubocop.js +2 -1
  126. package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +3 -3
  127. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +12 -11
  128. package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +3 -2
  129. package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +2 -1
  130. package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +5 -3
  131. package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +2 -1
  132. package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +3 -2
  133. package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +3 -2
  134. package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +2 -1
  135. package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +2 -1
  136. package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +2 -1
  137. package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +2 -1
  138. package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +2 -1
  139. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +5 -0
  140. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +2 -2
  141. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +1 -64
  142. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +8 -2
  143. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils.js +0 -21
  144. package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +2 -1
  145. package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +2 -20
  146. package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +5 -3
  147. package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +2 -1
  148. package/node_modules/pi-lens/dist/clients/dispatch/utils/format-utils.js +2 -2
  149. package/node_modules/pi-lens/dist/clients/disposition-logger.js +0 -7
  150. package/node_modules/pi-lens/dist/clients/effective-config.js +12 -2
  151. package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +2 -2
  152. package/node_modules/pi-lens/dist/clients/extension-log.js +2 -0
  153. package/node_modules/pi-lens/dist/clients/file-kinds.js +1 -38
  154. package/node_modules/pi-lens/dist/clients/file-role.js +18 -1
  155. package/node_modules/pi-lens/dist/clients/file-time.js +1 -1
  156. package/node_modules/pi-lens/dist/clients/file-utils.js +5 -1
  157. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +4 -0
  158. package/node_modules/pi-lens/dist/clients/format-service.js +0 -1
  159. package/node_modules/pi-lens/dist/clients/formatters.js +66 -93
  160. package/node_modules/pi-lens/dist/clients/generated-artifacts.js +3 -4
  161. package/node_modules/pi-lens/dist/clients/generation-guard.js +4 -0
  162. package/node_modules/pi-lens/dist/clients/git-guard.js +5 -0
  163. package/node_modules/pi-lens/dist/clients/gitleaks-client.js +42 -6
  164. package/node_modules/pi-lens/dist/clients/govulncheck-client.js +48 -7
  165. package/node_modules/pi-lens/dist/clients/grammar-source.js +3 -3
  166. package/node_modules/pi-lens/dist/clients/installer/index.js +416 -61
  167. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +84 -18
  168. package/node_modules/pi-lens/dist/clients/instance-reaper.js +6 -6
  169. package/node_modules/pi-lens/dist/clients/jscpd-client.js +9 -1
  170. package/node_modules/pi-lens/dist/clients/knip-client.js +9 -2
  171. package/node_modules/pi-lens/dist/clients/language-profile.js +12 -11
  172. package/node_modules/pi-lens/dist/clients/language-registry.js +5 -1
  173. package/node_modules/pi-lens/dist/clients/latency-logger.js +7 -7
  174. package/node_modules/pi-lens/dist/clients/ledger-bounds.js +21 -1
  175. package/node_modules/pi-lens/dist/clients/lens-config.js +23 -0
  176. package/node_modules/pi-lens/dist/clients/lens-engine.js +3 -4
  177. package/node_modules/pi-lens/dist/clients/lens-events.js +1 -1
  178. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +18 -0
  179. package/node_modules/pi-lens/dist/clients/lens-map.js +1 -1
  180. package/node_modules/pi-lens/dist/clients/log-cleanup.js +0 -36
  181. package/node_modules/pi-lens/dist/clients/lsp/client.js +4 -3
  182. package/node_modules/pi-lens/dist/clients/lsp/config.js +37 -7
  183. package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +24 -1
  184. package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +79 -1
  185. package/node_modules/pi-lens/dist/clients/lsp/edits.js +3 -3
  186. package/node_modules/pi-lens/dist/clients/lsp/index.js +491 -64
  187. package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +1 -1
  188. package/node_modules/pi-lens/dist/clients/lsp/language.js +0 -8
  189. package/node_modules/pi-lens/dist/clients/lsp/path-utils.js +1 -1
  190. package/node_modules/pi-lens/dist/clients/lsp/pending-aux-coverage.js +0 -2
  191. package/node_modules/pi-lens/dist/clients/lsp/server.js +62 -15
  192. package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +0 -1
  193. package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +5 -5
  194. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +6 -0
  195. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +2 -1
  196. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +37 -4
  197. package/node_modules/pi-lens/dist/clients/lsp-document-symbols.js +1 -1
  198. package/node_modules/pi-lens/dist/clients/mcp/analyze.js +3 -0
  199. package/node_modules/pi-lens/dist/clients/mcp/session.js +2 -0
  200. package/node_modules/pi-lens/dist/clients/metrics-history.js +28 -107
  201. package/node_modules/pi-lens/dist/clients/middle-man-analysis.js +1 -1
  202. package/node_modules/pi-lens/dist/clients/module-report.js +1 -1
  203. package/node_modules/pi-lens/dist/clients/mutating-tool.js +3 -3
  204. package/node_modules/pi-lens/dist/clients/mutation-attribution.js +3 -3
  205. package/node_modules/pi-lens/dist/clients/ndjson-logger.js +0 -4
  206. package/node_modules/pi-lens/dist/clients/observed-mutation.js +9 -9
  207. package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +2 -6
  208. package/node_modules/pi-lens/dist/clients/opengrep-client.js +2 -0
  209. package/node_modules/pi-lens/dist/clients/opengrep-config.js +1 -1
  210. package/node_modules/pi-lens/dist/clients/package-manager.js +2 -1
  211. package/node_modules/pi-lens/dist/clients/path-utils.js +23 -2
  212. package/node_modules/pi-lens/dist/clients/performance-report.js +2 -2
  213. package/node_modules/pi-lens/dist/clients/php-cs-fixer-config.js +9 -4
  214. package/node_modules/pi-lens/dist/clients/pipeline.js +5 -4
  215. package/node_modules/pi-lens/dist/clients/project-changes.js +1 -1
  216. package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +1 -1
  217. package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +38 -10
  218. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +10 -9
  219. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/jscpd.js +1 -1
  220. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/knip.js +1 -1
  221. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/madge.js +1 -1
  222. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/opengrep.js +1 -1
  223. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +1 -1
  224. package/node_modules/pi-lens/dist/clients/project-lens-config.js +49 -1
  225. package/node_modules/pi-lens/dist/clients/project-scan-policy.js +3 -51
  226. package/node_modules/pi-lens/dist/clients/python-provenance.js +1 -1
  227. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +3 -1
  228. package/node_modules/pi-lens/dist/clients/read-guard.js +5 -2
  229. package/node_modules/pi-lens/dist/clients/recent-touches.js +2 -2
  230. package/node_modules/pi-lens/dist/clients/review-graph/builder.js +3 -5
  231. package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +1 -1
  232. package/node_modules/pi-lens/dist/clients/review-graph-logger.js +2 -0
  233. package/node_modules/pi-lens/dist/clients/ruff-client.js +18 -9
  234. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +10 -1
  235. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +5 -0
  236. package/node_modules/pi-lens/dist/clients/runtime-session.js +58 -14
  237. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +11 -1
  238. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +4 -1
  239. package/node_modules/pi-lens/dist/clients/runtime-turn.js +48 -1
  240. package/node_modules/pi-lens/dist/clients/sanitize.js +0 -11
  241. package/node_modules/pi-lens/dist/clients/scan-utils.js +1 -56
  242. package/node_modules/pi-lens/dist/clients/security-scan-client.js +2 -2
  243. package/node_modules/pi-lens/dist/clients/session-event-guard.js +69 -1
  244. package/node_modules/pi-lens/dist/clients/session-summary.js +0 -24
  245. package/node_modules/pi-lens/dist/clients/sg-runner.js +2 -1
  246. package/node_modules/pi-lens/dist/clients/sgconfig.js +1 -5
  247. package/node_modules/pi-lens/dist/clients/shared-checkout-guard.js +1 -1
  248. package/node_modules/pi-lens/dist/clients/situational-tool-telemetry.js +108 -0
  249. package/node_modules/pi-lens/dist/clients/smells-rollup.js +2 -2
  250. package/node_modules/pi-lens/dist/clients/startup-scan.js +2 -10
  251. package/node_modules/pi-lens/dist/clients/test-runner-client.js +291 -76
  252. package/node_modules/pi-lens/dist/clients/test-runner-delivery.js +77 -72
  253. package/node_modules/pi-lens/dist/clients/tool-config.js +199 -0
  254. package/node_modules/pi-lens/dist/clients/tool-cwd.js +299 -0
  255. package/node_modules/pi-lens/dist/clients/tool-policy.js +1 -1
  256. package/node_modules/pi-lens/dist/clients/tool-probe.js +53 -0
  257. package/node_modules/pi-lens/dist/clients/tool-set-policy.js +42 -0
  258. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +1 -52
  259. package/node_modules/pi-lens/dist/clients/trivy-client.js +9 -1
  260. package/node_modules/pi-lens/dist/clients/tui-fit.js +0 -4
  261. package/node_modules/pi-lens/dist/clients/turn-context.js +52 -0
  262. package/node_modules/pi-lens/dist/clients/user-notify.js +0 -4
  263. package/node_modules/pi-lens/dist/clients/widget-state.js +4 -3
  264. package/node_modules/pi-lens/dist/clients/word-index-logger.js +0 -7
  265. package/node_modules/pi-lens/dist/clients/word-index-store.js +3 -7
  266. package/node_modules/pi-lens/dist/clients/word-index.js +9 -16
  267. package/node_modules/pi-lens/dist/clients/zizmor-config.js +1 -1
  268. package/node_modules/pi-lens/dist/index.js +19969 -17481
  269. package/node_modules/pi-lens/dist/mcp/analyze-cli.js +3 -2
  270. package/node_modules/pi-lens/dist/mcp/build-staleness.js +1 -1
  271. package/node_modules/pi-lens/dist/mcp/server.js +135 -159
  272. package/node_modules/pi-lens/dist/scripts/lib/process-scan.mjs +1 -1
  273. package/node_modules/pi-lens/dist/scripts/lib/skills-predicate.mjs +1 -1
  274. package/node_modules/pi-lens/dist/tools/activate-tools.js +10 -7
  275. package/node_modules/pi-lens/dist/tools/ast-grep-outline.js +2 -13
  276. package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +8 -13
  277. package/node_modules/pi-lens/dist/tools/ast-grep-search.js +83 -39
  278. package/node_modules/pi-lens/dist/tools/effective-config.js +4 -3
  279. package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +1 -10
  280. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +354 -86
  281. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +54 -112
  282. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +20 -44
  283. package/node_modules/pi-lens/dist/tools/lsp-structured-output.js +3 -3
  284. package/node_modules/pi-lens/dist/tools/module-report.js +5 -9
  285. package/node_modules/pi-lens/dist/tools/project-report.js +9 -17
  286. package/node_modules/pi-lens/dist/tools/render-compact.js +281 -2
  287. package/node_modules/pi-lens/dist/tools/symbol-search.js +3 -4
  288. package/node_modules/pi-lens/docs/agent-guide.md +3 -4
  289. package/node_modules/pi-lens/docs/agent-tools.md +46 -22
  290. package/node_modules/pi-lens/docs/configuration.md +9 -0
  291. package/node_modules/pi-lens/docs/environment-variables.md +0 -5
  292. package/node_modules/pi-lens/docs/features.md +5 -5
  293. package/node_modules/pi-lens/docs/globalconfig.md +31 -1
  294. package/node_modules/pi-lens/docs/lsp-capability-matrix.md +9 -1
  295. package/node_modules/pi-lens/docs/mcp.md +13 -1
  296. package/node_modules/pi-lens/docs/pi-lens-fixer.md +71 -0
  297. package/node_modules/pi-lens/docs/pi-lens-investigator.md +15 -0
  298. package/node_modules/pi-lens/docs/pi-lens-monitor.md +88 -0
  299. package/node_modules/pi-lens/docs/pi-lens-reviewer.md +41 -0
  300. package/node_modules/pi-lens/docs/pi-lens-subagent.md +21 -2
  301. package/node_modules/pi-lens/docs/public-api-stability.md +1 -0
  302. package/node_modules/pi-lens/docs/real-harness.md +46 -0
  303. package/node_modules/pi-lens/docs/release-qa-baseline.md +17 -5
  304. package/node_modules/pi-lens/docs/servercapabilities.md +2 -3
  305. package/node_modules/pi-lens/docs/settings.md +37 -2
  306. package/node_modules/pi-lens/docs/tools_improvement2.md +4 -4
  307. package/node_modules/pi-lens/docs/tree-sitter_rules_catalog.md +1 -1
  308. package/node_modules/pi-lens/docs/usage.md +13 -3
  309. package/node_modules/pi-lens/docs/word-index.md +1 -1
  310. package/node_modules/pi-lens/package.json +15 -15
  311. package/node_modules/pi-lens/rules/tree-sitter-queries/typescript/sql-injection.yml +7 -3
  312. package/node_modules/pi-lens/rules/typos/_typos.toml +4 -2
  313. package/node_modules/pi-lens/scripts/lib/skills-predicate.mjs +1 -1
  314. package/node_modules/pi-lens/scripts/lib/warm-loader-cache.mjs +1 -1
  315. package/node_modules/pi-lens/scripts/warm-loader-cache.mjs +4 -2
  316. package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +8 -6
  317. package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +19 -9
  318. package/node_modules/pi-web-access/CHANGELOG.md +29 -0
  319. package/node_modules/pi-web-access/README.md +33 -22
  320. package/node_modules/pi-web-access/abortable.ts +17 -0
  321. package/node_modules/pi-web-access/crawl4ai.ts +204 -0
  322. package/node_modules/pi-web-access/credential-source.ts +1 -0
  323. package/node_modules/pi-web-access/curator-page.ts +20 -2
  324. package/node_modules/pi-web-access/curator-run.ts +44 -0
  325. package/node_modules/pi-web-access/curator-server.ts +3 -1
  326. package/node_modules/pi-web-access/duckduckgo.ts +1 -1
  327. package/node_modules/pi-web-access/extract.ts +57 -12
  328. package/node_modules/pi-web-access/fetch-params.ts +1 -1
  329. package/node_modules/pi-web-access/gemini-search.ts +9 -5
  330. package/node_modules/pi-web-access/index.ts +25 -18
  331. package/node_modules/pi-web-access/openai-search.ts +35 -13
  332. package/node_modules/pi-web-access/package.json +2 -2
  333. package/node_modules/pi-web-access/page-query.ts +5 -2
  334. package/node_modules/pi-web-access/query-rewrite.ts +5 -2
  335. package/node_modules/pi-web-access/serpapi.ts +220 -0
  336. package/node_modules/pi-web-access/ssrf-protection.ts +5 -1
  337. package/node_modules/pi-web-access/storage.ts +10 -0
  338. package/node_modules/pi-web-access/summary-review.ts +34 -21
  339. package/node_modules/pi-web-access/utils.ts +6 -4
  340. package/package.json +7 -4
  341. package/node_modules/pi-lens/dist/tools/ast-dump.js +0 -103
@@ -42,8 +42,9 @@ import { LEGACY_ROOT_LSP_KEYS, LSP_NAMESPACE_KEY } from "./config-locations.js";
42
42
  // every config loader's import graph for one type alias.
43
43
  import { DENY_KEY, } from "./config-core/schema.js";
44
44
  import { flagConfigSectionKeys, GLOBAL_NON_FLAG_CONFIG_SECTIONS, LENS_FLAGS, PROJECT_FOREIGN_CONFIG_NAMESPACES, PROJECT_NON_FLAG_CONFIG_SECTIONS, } from "./lens-flag-registry.js";
45
+ import { LENS_TOOL_NAMES } from "./tool-config.js";
45
46
  /** The JSON Schema dialect the published artifact declares. */
46
- export const CONFIG_SCHEMA_DIALECT = "https://json-schema.org/draft/2020-12/schema";
47
+ const CONFIG_SCHEMA_DIALECT = "https://json-schema.org/draft/2020-12/schema";
47
48
  /**
48
49
  * A node the schema says nothing else about. `config-core` treats a node with
49
50
  * no `type` as opaque and walks its children OPEN, so an undeclared section
@@ -109,7 +110,6 @@ export { LSP_KEY_TYPES };
109
110
  const LSP_KEY_DENY = {
110
111
  disabledServers: "array-union",
111
112
  };
112
- export { LSP_KEY_DENY };
113
113
  /** The `x-deny` annotation for a key, or nothing when it carries no denial. */
114
114
  function denyAnnotation(key) {
115
115
  const policy = LSP_KEY_DENY[key];
@@ -155,12 +155,66 @@ function buildConfigSchema() {
155
155
  ]) {
156
156
  properties[key] = opaque("stable");
157
157
  }
158
+ properties.tools = {
159
+ type: "object",
160
+ additionalProperties: true,
161
+ properties: Object.fromEntries(LENS_TOOL_NAMES.map((name) => [
162
+ name,
163
+ {
164
+ type: "object",
165
+ additionalProperties: true,
166
+ properties: {
167
+ enabled: { type: "boolean", [STABILITY_TIER_KEY]: "experimental" },
168
+ },
169
+ [STABILITY_TIER_KEY]: "experimental",
170
+ },
171
+ ])),
172
+ [STABILITY_TIER_KEY]: "stable",
173
+ };
158
174
  // Namespaces owned by another tool that ride in the same file (`trivy`,
159
175
  // `helm`). Reserved so they survive validation, `experimental` because their
160
176
  // shape belongs to those runners, not to this schema.
161
177
  for (const key of PROJECT_FOREIGN_CONFIG_NAMESPACES) {
162
178
  properties[key] ??= opaque("experimental");
163
179
  }
180
+ for (const key of [
181
+ "knip",
182
+ "jscpd",
183
+ "madge",
184
+ "gitleaks",
185
+ "govulncheck",
186
+ "deadCode",
187
+ "complexity",
188
+ ]) {
189
+ properties[key] = {
190
+ type: "object",
191
+ additionalProperties: true,
192
+ properties: {
193
+ enabled: { type: "boolean", [STABILITY_TIER_KEY]: "experimental" },
194
+ },
195
+ [STABILITY_TIER_KEY]: "stable",
196
+ };
197
+ }
198
+ properties.startup = {
199
+ type: "object",
200
+ additionalProperties: true,
201
+ properties: {
202
+ mode: {
203
+ type: "string",
204
+ enum: ["quick", "full", "minimal"],
205
+ [STABILITY_TIER_KEY]: "experimental",
206
+ },
207
+ scans: {
208
+ type: "object",
209
+ additionalProperties: true,
210
+ properties: {
211
+ enabled: { type: "boolean", [STABILITY_TIER_KEY]: "experimental" },
212
+ },
213
+ [STABILITY_TIER_KEY]: "experimental",
214
+ },
215
+ },
216
+ [STABILITY_TIER_KEY]: "stable",
217
+ };
164
218
  // The four legacy ROOT LSP keys. Still accepted for their deprecation window
165
219
  // (#2418 registry), and `experimental` because they are scheduled for
166
220
  // removal — a `stable` tier on a key with a `removeNotBefore` would be two
@@ -22,7 +22,7 @@
22
22
  * extraction — the prose is not API (the code is), but silently rewording a
23
23
  * warning inside a refactor is still not a thing this PR does.
24
24
  */
25
- import { DEPRECATED_CONFIG_SURFACES, } from "./config-diagnostic-codes.js";
25
+ import { DEPRECATED_CONFIG_SURFACES, withConfigDiagnosticCode, } from "./config-diagnostic-codes.js";
26
26
  import { recordDegradationOnce } from "./degradation-ledger.js";
27
27
  import { errorClassName } from "./error-class.js";
28
28
  import { logExtension } from "./extension-log.js";
@@ -378,7 +378,7 @@ export function warnIgnoredConfigOnce(options) {
378
378
  logExtension({
379
379
  subsystem,
380
380
  level: "warn",
381
- message,
381
+ message: withConfigDiagnosticCode(message, code),
382
382
  metadata: { configPath: file, reason, code, ...(key ? { key } : {}) },
383
383
  });
384
384
  // HUMAN-audience too: a config the user wrote is being ignored. Routed
@@ -19,6 +19,7 @@ import { findLocalBinsAt, VENV_BIN_DIRS } from "./package-manager.js";
19
19
  import { findNearestMarkerRoot } from "./path-utils.js";
20
20
  import { getScratchTreeFnmatchPatterns } from "./scratch-tree-policy.js";
21
21
  import { safeSpawnAsync } from "./safe-spawn.js";
22
+ import { probeToolAsync } from "./tool-probe.js";
22
23
  import { classifyProbeFailure, createAvailabilityLatch, logAvailabilityDecision, startHostStallSampler, } from "./dispatch/runners/utils/availability-policy.js";
23
24
  import { firstOutputLine, spawnFailedWithNoOutput, } from "./dispatch/runners/utils/spawn-outcome.js";
24
25
  import { formatToolFailure } from "./dispatch/runners/utils/tool-failure.js";
@@ -229,7 +230,7 @@ export class PythonDeadCodeClient {
229
230
  let probe;
230
231
  let hostStallMs;
231
232
  try {
232
- probe = await safeSpawnAsync(c.cmd, [...c.prefix, "--version"], {
233
+ probe = await probeToolAsync(c.cmd, [...c.prefix, "--version"], {
233
234
  timeout: 5000,
234
235
  });
235
236
  }
@@ -415,9 +416,13 @@ export class PythonDeadCodeClient {
415
416
  durationMs,
416
417
  };
417
418
  }
419
+ // vulture's verified exit-code table (above): exit 0 with empty
420
+ // stdout IS the clean-run signal, so this ran over the root
421
+ // (#2154) — unlike knip, whose clean run always prints JSON.
418
422
  return {
419
423
  ...emptyResult(this.language),
420
424
  success: true,
425
+ analyzed: true,
421
426
  summary: "No dead code found",
422
427
  durationMs,
423
428
  };
@@ -430,6 +435,8 @@ export class PythonDeadCodeClient {
430
435
  return {
431
436
  ...emptyResult(this.language),
432
437
  success: true,
438
+ // #2154: parsed vulture output for this root.
439
+ analyzed: true,
433
440
  unusedExports,
434
441
  summary: total === 0
435
442
  ? "No dead code found"
@@ -28,7 +28,3 @@ export function logDeadCodeScan(event) {
28
28
  return;
29
29
  writer.log({ ts: new Date().toISOString(), ...event });
30
30
  }
31
- /** Resolve once all enqueued dead-code writes are on disk (tests/shutdown). */
32
- export function flushDeadCodeLog() {
33
- return writer.flush();
34
- }
@@ -815,7 +815,11 @@ export class DependencyChecker {
815
815
  }
816
816
  }
817
817
  this.publishState(gen, circular, circularFiles);
818
- return { circular, count: circular.length };
818
+ // #2154: the one madge site that parsed a graph for this root. Every
819
+ // other return here (missing root, no top-level source file, madge
820
+ // unavailable, spawn error, parse throw) is the SAME empty shape and
821
+ // must not be read as "no cycles in this project".
822
+ return { circular, count: circular.length, analyzed: true };
819
823
  }
820
824
  catch (err) {
821
825
  this.log(`Scan error: ${err.message}`);
@@ -128,7 +128,7 @@ export function computeStrictAnchor(args) {
128
128
  });
129
129
  }
130
130
  /** Intent-level anchor — see module doc. Used for defer/flagged/suppress. */
131
- export function computeWeakAnchor(args) {
131
+ function computeWeakAnchor(args) {
132
132
  return stableFindingId("ddw:", {
133
133
  cwd: args.cwd,
134
134
  filePath: args.filePath,
@@ -23,7 +23,7 @@ export function getDiagnosticLogger() {
23
23
  }
24
24
  return _logger;
25
25
  }
26
- export function createDiagnosticLogger() {
26
+ function createDiagnosticLogger() {
27
27
  // Lazy filePath: the log file is keyed on the current date, resolved per
28
28
  // drain so a long-lived logger rolls over at midnight. A daily rollover
29
29
  // is NOT a size bound (#2505): one very busy day, or a long-lived
@@ -33,7 +33,3 @@ export function observeRunnerLatency(options) {
33
33
  export function resetObservedRunnerLatency() {
34
34
  slowRunners.clear();
35
35
  }
36
- /** Test-only inspection without exposing mutable state. */
37
- export function observedRunnerTierForTests(projectRoot, runnerId) {
38
- return classifyObservedRunner(projectRoot, runnerId);
39
- }
@@ -29,7 +29,7 @@ import { isSpawnableCommand } from "../installer/index.js";
29
29
  import { isAbsoluteFilePath, normalizeEphemeralMapKey, normalizeMapKey, } from "../path-utils.js";
30
30
  import { loadPiLensProjectConfig } from "../project-lens-config.js";
31
31
  import { RUNTIME_CONFIG, getRunnerTimeoutFloorMs } from "../runtime-config.js";
32
- import { safeSpawnAsync } from "../safe-spawn.js";
32
+ import { probeToolAsync } from "../tool-probe.js";
33
33
  import { classifyDiagnostic } from "./diagnostic-taxonomy.js";
34
34
  import { classifyProbeFailure, logAvailabilityDecision, startHostStallSampler, transientRetryDelayMs, } from "./runners/utils/availability-policy.js";
35
35
  import { recordAvailabilityProbeOverrun, getDispatchAvailabilityGeneration, } from "./runners/utils/runner-helpers.js";
@@ -147,7 +147,7 @@ export async function checkToolAvailability(command, facts) {
147
147
  let hostStallMs;
148
148
  let probeJoined = false;
149
149
  try {
150
- const shared = dispatcherProbeFlights.run(`dispatcher:${key}`, () => safeSpawnAsync(command, ["--version"], {
150
+ const shared = dispatcherProbeFlights.run(`dispatcher:${key}`, () => probeToolAsync(command, ["--version"], {
151
151
  timeout: TOOL_PROBE_TIMEOUT_MS,
152
152
  }));
153
153
  probeJoined = shared.joined;
@@ -285,11 +285,13 @@ telemetryModel, telemetryProvider) {
285
285
  async hasTool(command) {
286
286
  return checkToolAvailability(command, facts);
287
287
  },
288
- log(message) {
288
+ log(message, level) {
289
289
  // #1333: pi owns the terminal — a runner advisory must never be a raw
290
290
  // write. Every DispatchContext.log line lands in extension.log instead.
291
291
  logExtension({
292
292
  subsystem: "dispatch",
293
+ // exactOptionalPropertyTypes: an omitted level must stay omitted.
294
+ ...(level !== undefined && { level }),
293
295
  message,
294
296
  metadata: { filePath: normalizedFilePath, kind },
295
297
  });
@@ -446,31 +448,49 @@ function buildCoverageNotice(ctx, runnerLatencies) {
446
448
  ...new Set(relevant.flatMap((r) => r.unconfirmedServerIds ?? [])),
447
449
  ];
448
450
  if (unconfirmedServerIds.length > 0) {
449
- // The marker describes this exact silent-scanner set. A scanner can
450
- // recover while another goes dark on the same file, so the set belongs
451
- // in the session dedupe identity rather than only kind and path.
451
+ const deferredIds = new Set(relevant.flatMap((r) => r.deferredServerIds ?? []));
452
+ const markerFor = (ids) => {
453
+ const shown = ids.slice(0, 4);
454
+ const remainder = ids.length - shown.length;
455
+ return `${shown.join(", ")}${remainder > 0 ? ` +${remainder}` : ""}`;
456
+ };
457
+ const deferredServerIds = unconfirmedServerIds.filter((id) => deferredIds.has(id));
458
+ const silentServerIds = unconfirmedServerIds.filter((id) => !deferredIds.has(id));
459
+ // The marker describes this exact scanner set. A scanner can recover
460
+ // while another goes dark on the same file, so the set belongs in the
461
+ // session dedupe identity rather than only kind and path.
452
462
  // #2016: these are SCANNER IDS, not filesystem paths. `normalizeMapKey`
453
463
  // would realpath each one; on Windows that fails, falls through to
454
464
  // `resolveNonExisting`, and resolves the id against the CURRENT process
455
465
  // cwd, so the dedupe key differed by platform and by cwd (the #2219
456
466
  // non-path-sentinel class). The cheap syntactic fold is what this
457
- // session-scoped dedupe key actually needs.
458
- const silentScannerSet = [...new Set(unconfirmedServerIds)]
467
+ // session-scoped dedupe key actually needs. Code-unit comparator: the
468
+ // sorted set is a KEY, so ordering must be deterministic across locales
469
+ // — localeCompare is not.
470
+ const dedupeSet = (ids) => [...new Set(ids)]
459
471
  .map(normalizeEphemeralMapKey)
460
- // Code-unit comparator: the sorted set is a dedupe KEY, so ordering
461
- // must be deterministic across locales — localeCompare is not.
462
472
  .sort((a, b) => Number(a > b) - Number(a < b))
463
473
  .join(",");
464
- const onceKey = `${ctx.kind}:${ctx.filePath}:${silentScannerSet}`;
474
+ // #2810 round 4: the PARTITION is part of the identity, not just the
475
+ // scanner set. The same scanner can be silent on one edit and marked for
476
+ // late delivery on the next; keying on the unconfirmed set alone showed
477
+ // the session whichever message came first and suppressed the other, so a
478
+ // scanner that recovered a delivery path (or lost one) kept the stale
479
+ // wording for the rest of the session.
480
+ const onceKey = `${ctx.kind}:${ctx.filePath}:${dedupeSet(silentServerIds)}|${dedupeSet(deferredServerIds)}`;
465
481
  if (coverageNoticeSeen.has(onceKey))
466
482
  return undefined;
467
483
  coverageNoticeSeen.add(onceKey);
468
- const shown = unconfirmedServerIds.slice(0, 4);
469
- const remainder = unconfirmedServerIds.length - shown.length;
470
- const marker = `${shown.join(", ")}${remainder > 0 ? ` +${remainder}` : ""}`;
484
+ const coverageParts = [];
485
+ if (deferredServerIds.length > 0) {
486
+ coverageParts.push(`coverage: ${markerFor(deferredServerIds)} deferred — diagnostics are incomplete; findings arrive at turn end if the scan lands.`);
487
+ }
488
+ if (silentServerIds.length > 0) {
489
+ coverageParts.push(`coverage: ${markerFor(silentServerIds)} silent — diagnostics are incomplete (not a clean result).`);
490
+ }
471
491
  return {
472
492
  id: `coverage-partial:${ctx.kind}:${path.basename(ctx.filePath)}`,
473
- message: `coverage: ${marker} silent — diagnostics are incomplete (not a clean result).`,
493
+ message: coverageParts.join("\n"),
474
494
  filePath: ctx.filePath,
475
495
  severity: "warning",
476
496
  semantic: "warning",
@@ -837,6 +857,9 @@ async function runGroup(ctx, group, registry, onRunnerResult) {
837
857
  ...(result.unconfirmedServerIds !== undefined && {
838
858
  unconfirmedServerIds: result.unconfirmedServerIds,
839
859
  }),
860
+ ...(result.deferredServerIds !== undefined && {
861
+ deferredServerIds: result.deferredServerIds,
862
+ }),
840
863
  });
841
864
  logLatency({
842
865
  type: "runner",
@@ -1237,29 +1260,3 @@ async function runRunner(ctx, runner, defaultSemantic) {
1237
1260
  }
1238
1261
  }
1239
1262
  // --- Simple Integration Helper ---
1240
- /**
1241
- * @internal
1242
- * Low-level dispatch entry point. Use `dispatchLint` from `./integration.js` instead —
1243
- * that version provides session-persistent baselines and FactStore.
1244
- * This function creates an ephemeral FactStore per call; facts do not persist across calls.
1245
- */
1246
- export async function dispatchLint(filePath, cwd, pi, facts, registry) {
1247
- // By default, only run BLOCKING rules for fast feedback on file write
1248
- const ctx = createDispatchContext(filePath, cwd, pi, facts, true);
1249
- // Get runners for this file kind
1250
- if (!ctx.kind)
1251
- return "";
1252
- const runners = registry.getForKind(ctx.kind, ctx.filePath);
1253
- if (runners.length === 0) {
1254
- return "";
1255
- }
1256
- // Create groups from registered runners (all in fallback mode)
1257
- const groups = [
1258
- {
1259
- mode: "fallback",
1260
- runnerIds: runners.map((r) => r.id),
1261
- },
1262
- ];
1263
- const result = await dispatchForFile(ctx, groups, registry);
1264
- return result.output;
1265
- }
@@ -135,7 +135,7 @@ function isCallPassThrough(stmt, paramNames) {
135
135
  }
136
136
  return { pass: true, target: (expr.children ?? [])[0]?.text };
137
137
  }
138
- function calcCyclomaticComplexity(body) {
138
+ export function calcCyclomaticComplexity(body) {
139
139
  let cc = 1;
140
140
  walk(body, (node) => {
141
141
  if (COMPLEXITY_TYPES.has(node.type)) {
@@ -1,6 +1,10 @@
1
1
  import { logLatency } from "../../latency-logger.js";
2
2
  import { isJstsFactFile } from "../../file-kinds.js";
3
3
  import { childrenOfType, firstChildOfType, withFactTree, walk, } from "./tree-sitter-facts.js";
4
+ /** Whether the import-facts provider applies to a source path. */
5
+ export function importFactsApplyTo(filePath) {
6
+ return isJstsFactFile(filePath);
7
+ }
4
8
  function stripQuotes(raw) {
5
9
  return raw.replace(/^["'`]+|["'`]+$/g, "");
6
10
  }
@@ -69,7 +73,7 @@ export const importFactProvider = {
69
73
  provides: ["file.imports", "file.reexports", "file.importFactsCoverage"],
70
74
  requires: ["file.content"],
71
75
  appliesTo(ctx) {
72
- return isJstsFactFile(ctx.filePath);
76
+ return importFactsApplyTo(ctx.filePath);
73
77
  },
74
78
  async run(ctx, store) {
75
79
  const content = store.getFileFact(ctx.filePath, "file.content");
@@ -1489,7 +1489,9 @@ export async function computeCascadeForFile(filePath, cwd, options = {}) {
1489
1489
  try {
1490
1490
  const snapshots = (await lspService.getCapabilitySnapshots?.(neighborPath)) ?? [];
1491
1491
  const tier = classifyCascadeWaitTier(lspService, neighborPath, snapshots);
1492
- if (tier === "tier3-silent" || tier === "collect-later") {
1492
+ if (tier === "tier3-silent" ||
1493
+ tier === "collect-later" ||
1494
+ tier === "diagnostics-unsupported") {
1493
1495
  const spawnedForTouch = await lspService.getClientForFile(neighborPath);
1494
1496
  if (spawnedForTouch) {
1495
1497
  // Sampled BEFORE the touchFile notify: a publish landing
@@ -1505,6 +1507,21 @@ export async function computeCascadeForFile(filePath, cwd, options = {}) {
1505
1507
  source: "cascade",
1506
1508
  clientScope: "primary",
1507
1509
  });
1510
+ if (tier === "diagnostics-unsupported") {
1511
+ logCascade({
1512
+ phase: "cascade_skip",
1513
+ filePath,
1514
+ neighborFile: neighborPath,
1515
+ durationMs: Date.now() - neighborStart,
1516
+ lspServerCount: configuredServerCount,
1517
+ coldSnapshot: isColdSnapshot,
1518
+ metadata: {
1519
+ serverId: spawnedForTouch.client.serverId,
1520
+ waitTier: tier,
1521
+ },
1522
+ });
1523
+ return undefined;
1524
+ }
1508
1525
  recordOutstandingCascadeTouch({
1509
1526
  filePath: neighborPath,
1510
1527
  serverId: spawnedForTouch.client.serverId,
@@ -9,9 +9,3 @@ export function warmDispatchIntegration() {
9
9
  export function loadDispatchIntegration() {
10
10
  return warmDispatchIntegration();
11
11
  }
12
- /** Test-only reset; production sessions intentionally retain the promise
13
- * across successful loads (a rejection already evicts itself — see
14
- * `createLazyImport`). */
15
- export function resetDispatchIntegrationForTests() {
16
- lazyIntegration.resetForTests();
17
- }
@@ -1,7 +1,7 @@
1
1
  /** Turn-end handoff for runners moved off the post-write critical path. */
2
2
  import { incrementDegradationCount } from "../degradation-ledger.js";
3
3
  const pending = [];
4
- export const MAX_PENDING_RUNNER_FINDINGS = 50;
4
+ const MAX_PENDING_RUNNER_FINDINGS = 50;
5
5
  export function deferRunnerFindings(entry) {
6
6
  const tracked = { ...entry, settled: false };
7
7
  // Attach exactly once at ownership time. Re-attaching at every turn end
@@ -276,6 +276,3 @@ export const TOOL_PLANS = Object.fromEntries(Object.entries(LANGUAGE_CAPABILITY_
276
276
  export function getToolPlan(kind) {
277
277
  return TOOL_PLANS[kind];
278
278
  }
279
- export function getAllToolPlans() {
280
- return TOOL_PLANS;
281
- }
@@ -3,8 +3,8 @@ import { isTestSuiteOrganizer } from "./framework-call-noise.js";
3
3
  // projects without a config. Project-specific overrides are read from the
4
4
  // per-dispatch context; these mutable fallbacks exist for tests/legacy direct
5
5
  // rule evaluation only.
6
- export const DEFAULT_HIGH_COMPLEXITY_THRESHOLD = 15;
7
- export const DEFAULT_HIGH_COMPLEXITY_DEPTH_THRESHOLD = 6;
6
+ const DEFAULT_HIGH_COMPLEXITY_THRESHOLD = 15;
7
+ const DEFAULT_HIGH_COMPLEXITY_DEPTH_THRESHOLD = 6;
8
8
  let ccThreshold = DEFAULT_HIGH_COMPLEXITY_THRESHOLD;
9
9
  let depthThreshold = DEFAULT_HIGH_COMPLEXITY_DEPTH_THRESHOLD;
10
10
  function isPositiveFiniteThreshold(value) {
@@ -3,7 +3,7 @@ import { isTestFrameworkNoiseCall, isTestSuiteOrganizer, } from "./framework-cal
3
3
  // projects without a config. Project-specific overrides are read from the
4
4
  // per-dispatch context; this mutable fallback exists for tests/legacy direct
5
5
  // rule evaluation only.
6
- export const DEFAULT_HIGH_FAN_OUT_THRESHOLD = 20;
6
+ const DEFAULT_HIGH_FAN_OUT_THRESHOLD = 20;
7
7
  let fanOutThreshold = DEFAULT_HIGH_FAN_OUT_THRESHOLD;
8
8
  /** Override fallback threshold for tests/legacy direct rule evaluation. */
9
9
  export function setHighFanOutThreshold(n) {
@@ -1,5 +1,6 @@
1
1
  import path from "node:path";
2
2
  import { safeSpawnAsync } from "../../safe-spawn.js";
3
+ import { resolveRunnerCwd } from "../../tool-cwd.js";
3
4
  import { PRIORITY } from "../priorities.js";
4
5
  import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
5
6
  const actionlint = createAvailabilityChecker("actionlint", ".exe");
@@ -66,7 +67,7 @@ const actionlintRunner = {
66
67
  return isGitHubWorkflowFile(ctx.filePath);
67
68
  },
68
69
  async run(ctx) {
69
- const cwd = ctx.cwd || process.cwd();
70
+ const cwd = resolveRunnerCwd(ctx, "actionlint");
70
71
  let cmd = null;
71
72
  if (await actionlint.isAvailableAsync(cwd)) {
72
73
  cmd = actionlint.getCommand(cwd);
@@ -184,7 +184,9 @@ export async function loadSg() {
184
184
  }
185
185
  })();
186
186
  sgLoadPromise = task;
187
- task.finally(() => {
187
+ // `task` never rejects (the IIFE catches), so the derived promise is inert;
188
+ // `void` records that no consumer awaits it (oxlint no-floating-promises).
189
+ void task.finally(() => {
188
190
  if (sgLoadPromise === task)
189
191
  sgLoadPromise = undefined;
190
192
  });
@@ -5,13 +5,12 @@
5
5
  * Autofix is handled earlier by the post-write pipeline to avoid
6
6
  * mutating files mid-dispatch after LSP sync has already happened.
7
7
  */
8
- import * as path from "node:path";
9
8
  import { incrementDegradationCount } from "../../degradation-ledger.js";
10
9
  import { mapWithConcurrency } from "../../dependency-checker.js";
11
10
  import { safeSpawnAsync } from "../../safe-spawn.js";
12
11
  import { biomeConfigArgs, getAutofixCapability, getJstsLintPolicyForCwd, } from "../../tool-policy.js";
13
12
  import { PRIORITY } from "../priorities.js";
14
- import { resolveToolCommandWithInstallFallback } from "./utils/runner-helpers.js";
13
+ import { resolveRunnerCwd, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
15
14
  import { finishParsedRun } from "./utils/tool-failure.js";
16
15
  /**
17
16
  * Map biome's own severity vocabulary onto the four-tier `Diagnostic.severity`
@@ -198,7 +197,7 @@ const biomeCheckJsonRunner = {
198
197
  appliesTo: ["jsts"],
199
198
  priority: PRIORITY.FORMAT_AND_LINT_PRIMARY,
200
199
  async run(ctx) {
201
- const cwd = ctx.cwd || path.dirname(ctx.filePath);
200
+ const cwd = resolveRunnerCwd(ctx, "biome");
202
201
  const policy = getJstsLintPolicyForCwd(cwd);
203
202
  // Defer to ESLint/oxlint if the project has explicitly configured one —
204
203
  // biome runs as the default linter only when no alternative is present.
@@ -1,6 +1,8 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
3
  import { safeSpawnAsync } from "../../safe-spawn.js";
4
+ import { probeToolAsync } from "../../tool-probe.js";
5
+ import { resolveRunnerCwd } from "../../tool-cwd.js";
4
6
  import { PRIORITY } from "../priorities.js";
5
7
  import { createAvailabilityChecker } from "./utils/runner-helpers.js";
6
8
  // Per-compiler availability checkers — each one caches per-cwd and
@@ -97,7 +99,10 @@ async function resolveCompiler(absPath, cwd) {
97
99
  flavor: "msvc",
98
100
  };
99
101
  }
100
- const clProbe = await safeSpawnAsync("cl", [], { timeout: 5000 });
102
+ // Mirrors the deliberate global-PATH probes in utils/runner-helpers.ts:
103
+ // this never resolves a config file or a target path, so there is no cwd
104
+ // for it to get wrong.
105
+ const clProbe = await probeToolAsync("cl", [], { timeout: 5000 });
101
106
  if (!clProbe.error && clProbe.status !== null) {
102
107
  return {
103
108
  command: "cl",
@@ -177,7 +182,7 @@ const cppCheckRunner = {
177
182
  priority: PRIORITY.GENERAL_ANALYSIS,
178
183
  skipTestFiles: false,
179
184
  async run(ctx) {
180
- const cwd = ctx.cwd || process.cwd();
185
+ const cwd = resolveRunnerCwd(ctx, "cpp-check");
181
186
  const absPath = path.resolve(cwd, ctx.filePath);
182
187
  const compiler = await resolveCompiler(absPath, cwd);
183
188
  if (!compiler) {
@@ -1,6 +1,7 @@
1
1
  import * as path from "node:path";
2
2
  import * as fs from "node:fs";
3
3
  import { safeSpawnAsync } from "../../safe-spawn.js";
4
+ import { resolveRunnerCwd } from "../../tool-cwd.js";
4
5
  import { PRIORITY } from "../priorities.js";
5
6
  import { createCwdCachedProbe } from "./utils/runner-helpers.js";
6
7
  const CREDO_PROBE_BUDGET_MS = 10_000;
@@ -50,7 +51,7 @@ const credoRunner = {
50
51
  priority: PRIORITY.GENERAL_ANALYSIS,
51
52
  skipTestFiles: false,
52
53
  async run(ctx) {
53
- const cwd = ctx.cwd || process.cwd();
54
+ const cwd = resolveRunnerCwd(ctx, "credo");
54
55
  if (!hasMixExs(cwd)) {
55
56
  return { status: "skipped", diagnostics: [], semantic: "none" };
56
57
  }
@@ -104,6 +104,7 @@
104
104
  import * as fs from "node:fs";
105
105
  import * as path from "node:path";
106
106
  import { safeSpawnAsync } from "../../safe-spawn.js";
107
+ import { resolveRunnerCwd } from "../../tool-cwd.js";
107
108
  import { createAvailabilityChecker, resolveAvailableOrInstall, } from "./utils/runner-helpers.js";
108
109
  import { spawnFailedWithNoOutput } from "./utils/spawn-outcome.js";
109
110
  import { PRIORITY } from "../priorities.js";
@@ -281,7 +282,7 @@ const cueVetRunner = {
281
282
  skipTestFiles: false,
282
283
  timeoutMs: 30_000,
283
284
  async run(ctx) {
284
- const cwd = ctx.cwd || process.cwd();
285
+ const cwd = resolveRunnerCwd(ctx, "cue-vet");
285
286
  let cmd = null;
286
287
  if (await cue.isAvailableAsync(cwd)) {
287
288
  cmd = cue.getCommand(cwd);
@@ -1,5 +1,6 @@
1
1
  import * as path from "node:path";
2
2
  import { safeSpawnAsync } from "../../safe-spawn.js";
3
+ import { resolveRunnerCwd } from "../../tool-cwd.js";
3
4
  import { createAvailabilityChecker } from "./utils/runner-helpers.js";
4
5
  import { PRIORITY } from "../priorities.js";
5
6
  const dart = createAvailabilityChecker("dart", ".exe");
@@ -147,7 +148,7 @@ const dartAnalyzeRunner = {
147
148
  priority: PRIORITY.GENERAL_ANALYSIS,
148
149
  skipTestFiles: false,
149
150
  async run(ctx) {
150
- const cwd = ctx.cwd || process.cwd();
151
+ const cwd = resolveRunnerCwd(ctx, "dart-analyze");
151
152
  const absPath = path.resolve(cwd, ctx.filePath);
152
153
  const dartAvailable = await dart.isAvailableAsync(cwd);
153
154
  const flutterAvailable = !dartAvailable && (await flutter.isAvailableAsync(cwd));
@@ -1,6 +1,7 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
3
  import { safeSpawnAsync } from "../../safe-spawn.js";
4
+ import { resolveRunnerCwd } from "../../tool-cwd.js";
4
5
  import { getLinterPolicyForCwd } from "../../tool-policy.js";
5
6
  import { PRIORITY } from "../priorities.js";
6
7
  import { createAvailabilityChecker } from "./utils/runner-helpers.js";
@@ -129,7 +130,7 @@ const detektRunner = {
129
130
  timeoutMs: 90_000,
130
131
  skipTestFiles: false,
131
132
  async run(ctx) {
132
- const cwd = ctx.cwd || process.cwd();
133
+ const cwd = resolveRunnerCwd(ctx, "detekt");
133
134
  const policy = getLinterPolicyForCwd(ctx.filePath, cwd);
134
135
  if (policy && !policy.preferredRunners.includes("detekt")) {
135
136
  return { status: "skipped", diagnostics: [], semantic: "none" };
@@ -1,6 +1,7 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
3
  import { safeSpawnAsync } from "../../safe-spawn.js";
4
+ import { resolveRunnerCwd } from "../../tool-cwd.js";
4
5
  import { PRIORITY } from "../priorities.js";
5
6
  import { createAvailabilityChecker } from "./utils/runner-helpers.js";
6
7
  const dotnet = createAvailabilityChecker("dotnet", ".exe");
@@ -118,7 +119,7 @@ const dotnetBuildRunner = {
118
119
  timeoutMs: 90_000,
119
120
  skipTestFiles: false,
120
121
  async run(ctx) {
121
- const cwd = ctx.cwd || process.cwd();
122
+ const cwd = resolveRunnerCwd(ctx, "dotnet-build");
122
123
  if (!(await dotnet.isAvailableAsync(cwd))) {
123
124
  return { status: "skipped", diagnostics: [], semantic: "none" };
124
125
  }
@@ -2,6 +2,7 @@ import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
3
  import { getProjectDataDir } from "../../file-utils.js";
4
4
  import { safeSpawnAsync } from "../../safe-spawn.js";
5
+ import { resolveRunnerCwd } from "../../tool-cwd.js";
5
6
  import { PRIORITY } from "../priorities.js";
6
7
  import { createAvailabilityChecker } from "./utils/runner-helpers.js";
7
8
  // Per-cwd cached `--version` probes (#120). Before this, each dispatch
@@ -141,7 +142,7 @@ const elixirCheckRunner = {
141
142
  priority: PRIORITY.GENERAL_ANALYSIS,
142
143
  skipTestFiles: false,
143
144
  async run(ctx) {
144
- const cwd = ctx.cwd || process.cwd();
145
+ const cwd = resolveRunnerCwd(ctx, "elixir-check");
145
146
  const absPath = path.resolve(cwd, ctx.filePath);
146
147
  let command;
147
148
  let args = [];