@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
@@ -20,7 +20,7 @@
20
20
  */
21
21
  import { safeSpawnAsync } from "../../safe-spawn.js";
22
22
  import { PRIORITY } from "../priorities.js";
23
- import { createAvailabilityChecker } from "./utils/runner-helpers.js";
23
+ import { createAvailabilityChecker, resolveRunnerCwd, } from "./utils/runner-helpers.js";
24
24
  import { parseToolRun } from "./utils/tool-failure.js";
25
25
  const typos = createAvailabilityChecker("typos", ".exe");
26
26
  // typos-cli exit codes: 0 = no typos, 2 = typos found, 1 = an error that
@@ -82,15 +82,17 @@ const spellcheckRunner = {
82
82
  priority: PRIORITY.DOC_QUALITY,
83
83
  skipTestFiles: false, // Check docs in test files too
84
84
  async run(ctx) {
85
+ const cwd = resolveRunnerCwd(ctx, "spellcheck/typos");
85
86
  // Skip if typos-cli is not installed
86
- if (!(await typos.isAvailableAsync(ctx.cwd || process.cwd()))) {
87
+ if (!(await typos.isAvailableAsync(cwd))) {
87
88
  return { status: "skipped", diagnostics: [], semantic: "none" };
88
89
  }
89
90
  // Run typos-cli with JSON output
90
91
  // --format json: Output JSON Lines
91
92
  // --exclude <pattern>: Could be used to exclude code blocks if needed
92
93
  const args = ["--format", "json", ctx.filePath];
93
- const result = await safeSpawnAsync(typos.getCommand(ctx.cwd || process.cwd()), args, {
94
+ const result = await safeSpawnAsync(typos.getCommand(cwd), args, {
95
+ cwd,
94
96
  timeout: 15000,
95
97
  });
96
98
  // #1816: typos-cli exits 0 clean, 2 with typos found, and 1 on an ERROR
@@ -3,6 +3,7 @@ import * as os from "node:os";
3
3
  import * as path from "node:path";
4
4
  import { BoundedLruCache } from "../../bounded-cache.js";
5
5
  import { safeSpawnAsync } from "../../safe-spawn.js";
6
+ import { resolveRunnerCwd } from "../../tool-cwd.js";
6
7
  import { findCompiledClassesDir } from "../../tool-policy.js";
7
8
  import { PRIORITY } from "../priorities.js";
8
9
  import { createAvailabilityChecker, resolveAvailableOrInstall, } from "./utils/runner-helpers.js";
@@ -191,7 +192,7 @@ const spotbugsRunner = {
191
192
  appliesTo: ["java", "kotlin"],
192
193
  priority: PRIORITY.DEEP_LANGUAGE_ANALYSIS,
193
194
  async run(ctx) {
194
- const cwd = ctx.cwd || process.cwd();
195
+ const cwd = resolveRunnerCwd(ctx, "spotbugs");
195
196
  const classesDir = findCompiledClassesDir(cwd);
196
197
  if (!classesDir) {
197
198
  ctx.log?.("spotbugs: Java project detected but no compiled .class files found — run `mvn compile` / `gradle build` first");
@@ -1,4 +1,5 @@
1
1
  import { safeSpawnAsync } from "../../safe-spawn.js";
2
+ import { logRunnerAdvisoryOnce, resolveRunnerCwd } from "../../tool-cwd.js";
2
3
  import { getLinterPolicyForCwd, hasSqlfluffConfig } from "../../tool-policy.js";
3
4
  import { PRIORITY } from "../priorities.js";
4
5
  import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
@@ -117,14 +118,14 @@ const sqlfluffRunner = {
117
118
  priority: PRIORITY.SQL_LINT,
118
119
  skipTestFiles: false,
119
120
  async run(ctx) {
120
- const cwd = ctx.cwd || process.cwd();
121
+ const cwd = resolveRunnerCwd(ctx, "sqlfluff");
121
122
  const policy = getLinterPolicyForCwd(ctx.filePath, cwd);
122
123
  if (policy && !policy.preferredRunners.includes("sqlfluff")) {
123
124
  return { status: "skipped", diagnostics: [], semantic: "none" };
124
125
  }
125
126
  const hasConfig = hasSqlfluffConfig(cwd);
126
127
  if (!hasConfig) {
127
- ctx.log("sqlfluff: no config detected, using ANSI dialect defaults");
128
+ logRunnerAdvisoryOnce(ctx, "sqlfluff", cwd, "sqlfluff: no config detected, using ANSI dialect defaults");
128
129
  }
129
130
  let cmd = null;
130
131
  if (await sqlfluff.isAvailableAsync(cwd)) {
@@ -1,5 +1,6 @@
1
1
  import * as path from "node:path";
2
2
  import { safeSpawnAsync } from "../../safe-spawn.js";
3
+ import { logRunnerAdvisoryOnce, resolveRunnerCwd } from "../../tool-cwd.js";
3
4
  import { getLinterPolicyForCwd, hasStylelintConfig, } from "../../tool-policy.js";
4
5
  import { PRIORITY } from "../priorities.js";
5
6
  import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
@@ -116,7 +117,7 @@ const stylelintRunner = {
116
117
  priority: PRIORITY.FORMAT_AND_LINT_PRIMARY,
117
118
  skipTestFiles: false,
118
119
  async run(ctx) {
119
- const cwd = ctx.cwd || process.cwd();
120
+ const cwd = resolveRunnerCwd(ctx, "stylelint");
120
121
  const policy = getLinterPolicyForCwd(ctx.filePath, cwd);
121
122
  if (policy && !policy.preferredRunners.includes("stylelint")) {
122
123
  return { status: "skipped", diagnostics: [], semantic: "none" };
@@ -124,7 +125,7 @@ const stylelintRunner = {
124
125
  const fileDir = path.dirname(path.resolve(cwd, ctx.filePath));
125
126
  const hasConfig = hasStylelintConfig(fileDir) || hasStylelintConfig(cwd);
126
127
  if (!hasConfig) {
127
- ctx.log("stylelint: no config detected, running with default rules");
128
+ logRunnerAdvisoryOnce(ctx, "stylelint", cwd, "stylelint: no config detected, running with default rules");
128
129
  }
129
130
  let cmd = null;
130
131
  if (await stylelint.isAvailableAsync(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 { PRIORITY } from "../priorities.js";
4
5
  import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
5
6
  import { parseToolRun } from "./utils/tool-failure.js";
@@ -115,7 +116,7 @@ const swiftlintRunner = {
115
116
  priority: PRIORITY.GENERAL_ANALYSIS,
116
117
  skipTestFiles: false,
117
118
  async run(ctx) {
118
- const cwd = ctx.cwd || process.cwd();
119
+ const cwd = resolveRunnerCwd(ctx, "swiftlint");
119
120
  let cmd = null;
120
121
  if (await swiftlint.isAvailableAsync(cwd)) {
121
122
  cmd = swiftlint.getCommand(cwd);
@@ -1,6 +1,7 @@
1
1
  import * as path from "node:path";
2
2
  import { findLocalBinUpwards } from "../../package-manager.js";
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, lspPrimaryCoversFile, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
@@ -106,7 +107,7 @@ const taploRunner = {
106
107
  priority: PRIORITY.FORMAT_AND_LINT_PRIMARY,
107
108
  skipTestFiles: false,
108
109
  async run(ctx) {
109
- const cwd = ctx.cwd || process.cwd();
110
+ const cwd = resolveRunnerCwd(ctx, "taplo");
110
111
  const policy = getLinterPolicyForCwd(ctx.filePath, cwd);
111
112
  if (policy && !policy.preferredRunners.includes("taplo")) {
112
113
  return { status: "skipped", diagnostics: [], semantic: "none" };
@@ -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 { pathsEqual } from "../../path-utils.js";
4
5
  import { getLinterPolicyForCwd } from "../../tool-policy.js";
5
6
  import { PRIORITY } from "../priorities.js";
@@ -128,7 +129,7 @@ const terragruntRunner = {
128
129
  priority: PRIORITY.GENERAL_ANALYSIS,
129
130
  skipTestFiles: false,
130
131
  async run(ctx) {
131
- const cwd = ctx.cwd || process.cwd();
132
+ const cwd = resolveRunnerCwd(ctx, "terragrunt");
132
133
  const policy = getLinterPolicyForCwd(ctx.filePath, cwd);
133
134
  if (policy && !policy.preferredRunners.includes("terragrunt"))
134
135
  return SKIPPED;
@@ -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 { getLinterPolicyForCwd } from "../../tool-policy.js";
4
5
  import { findNearestDirWithAnyBasename } from "../../workspace-topology.js";
5
6
  import { PRIORITY } from "../priorities.js";
@@ -52,7 +53,7 @@ const tflintRunner = {
52
53
  priority: PRIORITY.GENERAL_ANALYSIS,
53
54
  skipTestFiles: false,
54
55
  async run(ctx) {
55
- const cwd = ctx.cwd || process.cwd();
56
+ const cwd = resolveRunnerCwd(ctx, "tflint");
56
57
  const policy = getLinterPolicyForCwd(ctx.filePath, cwd);
57
58
  if (policy && !policy.preferredRunners.includes("tflint")) {
58
59
  return { status: "skipped", diagnostics: [], semantic: "none" };
@@ -40,6 +40,7 @@ import * as fs from "node:fs";
40
40
  import * as path from "node:path";
41
41
  import { incrementDegradationCount } from "../../degradation-ledger.js";
42
42
  import { safeSpawnAsync } from "../../safe-spawn.js";
43
+ import { resolveRunnerCwd } from "../../tool-cwd.js";
43
44
  import { isTrivyEnabled, resolveSeverityFloor, } from "../../trivy-client.js";
44
45
  import { PRIORITY } from "../priorities.js";
45
46
  import { createAvailabilityChecker, resolveAvailableOrInstall, } from "./utils/runner-helpers.js";
@@ -148,7 +149,7 @@ const trivyConfigRunner = {
148
149
  priority: PRIORITY.GENERAL_ANALYSIS,
149
150
  skipTestFiles: false,
150
151
  async run(ctx) {
151
- const cwd = ctx.cwd || process.cwd();
152
+ const cwd = resolveRunnerCwd(ctx, "trivy-config");
152
153
  // Single opt-in switch — trivy is opt-in across all modes.
153
154
  if (!isTrivyEnabled(cwd)) {
154
155
  return { status: "skipped", diagnostics: [], semantic: "none" };
@@ -75,6 +75,11 @@ export function describeInstallAttempt(attempt, options = {}) {
75
75
  return { install: "succeeded", ...(reason && { installReason: reason }) };
76
76
  case "failed":
77
77
  return { install: "failed", ...(reason && { installReason: reason }) };
78
+ case "unavailable":
79
+ return {
80
+ install: "unavailable",
81
+ ...(reason && { installReason: reason }),
82
+ };
78
83
  default:
79
84
  return {
80
85
  install: "not-attempted",
@@ -11,7 +11,7 @@
11
11
  * Complexity limit. This is that sweep, written once.
12
12
  */
13
13
  import * as fs from "node:fs";
14
- import { safeSpawnAsync } from "../../../safe-spawn.js";
14
+ import { probeToolAsync } from "../../../tool-probe.js";
15
15
  import { classifyProbeFailure, startHostStallSampler, } from "./availability-policy.js";
16
16
  /**
17
17
  * Walk `candidates` in order. A candidate containing a path separator is
@@ -45,7 +45,7 @@ export async function probeAvailabilityCandidates(candidates, probeArgs, timeout
45
45
  let result;
46
46
  let stallMs;
47
47
  try {
48
- result = await safeSpawnAsync(candidate, [...probeArgs], {
48
+ result = await probeToolAsync(candidate, probeArgs, {
49
49
  timeout: timeoutMs,
50
50
  });
51
51
  }
@@ -5,13 +5,12 @@
5
5
  * Supports the common `file:line:col: message` format used by most linters.
6
6
  */
7
7
  import { stripAnsi } from "../../../sanitize.js";
8
- import { escapeRegExp } from "../../../string-utils.js";
9
8
  import { getAutofixCapability } from "../../../tool-policy.js";
10
9
  /**
11
10
  * Create a parser for line-based tool output.
12
11
  * Common format: file:line:col: message (with variations)
13
12
  */
14
- export function createLineParser(config) {
13
+ function createLineParser(config) {
15
14
  return (raw, filePath) => {
16
15
  const diagnostics = [];
17
16
  // Optionally strip ANSI codes (for tools that output colored text)
@@ -81,68 +80,6 @@ export const parseGoVetOutput = createLineParser({
81
80
  generateId: (m) => `go-vet-${m[2]}`,
82
81
  defectClass: "correctness",
83
82
  });
84
- /**
85
- * Parse Biome output: file:line:col message (category)
86
- * With autofix support for fix suggestions
87
- */
88
- export function createBiomeParser(_autofix = false) {
89
- const biomeAutofix = getAutofixCapability("biome");
90
- return createLineParser({
91
- tool: "biome",
92
- regex: /^(.+?):(\d+):(\d+)\s+(.+?)\s*\((.+?)\)/,
93
- extractMessage: (m) => `${m[5]}: ${m[4]}`, // category: message
94
- extractRule: (m) => m[5],
95
- generateId: (m) => `biome-${m[2]}-${m[5]}`,
96
- getSeverity: (line) => (line.includes("error") ? "error" : "warning"),
97
- fixable: true,
98
- autoFixAvailable: biomeAutofix?.safePipelineAutofix ?? false,
99
- fixKind: biomeAutofix?.fixKind === "none" ? undefined : biomeAutofix?.fixKind,
100
- });
101
- }
102
- // Backward-compatible default biome parser
103
- export const parseBiomeOutput = createBiomeParser(false);
104
83
  // =============================================================================
105
84
  // GENERIC PARSER FACTORY
106
85
  // =============================================================================
107
- /**
108
- * Create a simple parser for tools using standard file:line:col format.
109
- * Format variations: :line:col:, line:col, (line,col), etc.
110
- */
111
- export function createSimpleParser(tool, options = {}) {
112
- const sep = options.separator ?? ":";
113
- const severity = options.severity ?? "warning";
114
- const fixable = options.fixable ?? false;
115
- // Build regex based on separator type
116
- const escapedSep = sep === " " ? "\\s+" : escapeRegExp(sep);
117
- const regex = options.includesFileName
118
- ? new RegExp(`^(.+?)${escapedSep}(\\d+)${escapedSep}(\\d+)${escapedSep}(.+)`)
119
- : new RegExp(`^(\\d+)${escapedSep}(\\d+)${escapedSep}(.+)`);
120
- return (raw, filePath) => {
121
- const diagnostics = [];
122
- const lines = raw.split("\n").filter((l) => l.trim());
123
- for (const line of lines) {
124
- const match = line.match(regex);
125
- if (!match)
126
- continue;
127
- const lineNum = options.includesFileName
128
- ? parseInt(match[2], 10)
129
- : parseInt(match[1], 10);
130
- const colNum = options.includesFileName
131
- ? parseInt(match[3], 10)
132
- : parseInt(match[2], 10);
133
- const message = options.includesFileName ? match[4] : match[3];
134
- diagnostics.push({
135
- id: `${tool}-${lineNum}`,
136
- message: message.trim(),
137
- filePath,
138
- line: lineNum,
139
- column: colNum,
140
- severity,
141
- semantic: severity === "error" ? "blocking" : "warning",
142
- tool,
143
- fixable,
144
- });
145
- }
146
- return diagnostics;
147
- };
148
- }
@@ -20,9 +20,11 @@ import { getServersForFileWithConfig, isServerDisabled, } from "../../../lsp/con
20
20
  import { findGlobalBinary, findLocalBinAt, findLocalBinsUpwards, findLocalBinUpwards, VENDOR_BIN_DIRS, VENV_BIN_DIRS, } from "../../../package-manager.js";
21
21
  import { logLatency } from "../../../latency-logger.js";
22
22
  import { safeSpawnAsync } from "../../../safe-spawn.js";
23
+ import { probeToolAsync } from "../../../tool-probe.js";
23
24
  import { compareOrdinal } from "../../../string-utils.js";
24
25
  import { getToolCommandSpec, shouldAutoInstallTool, } from "../../../tool-policy.js";
25
26
  import { isInSpawnTimeoutCooldown } from "../../../spawn-timeout-cooldown.js";
27
+ import { resolveToolCwd } from "../../../tool-cwd.js";
26
28
  import { createAvailabilityProbeFlight } from "../../../availability-probe-flight.js";
27
29
  import { classifyProbeFailure, createAvailabilityLatch, describeInstallAttempt, describeProbeEvidence, isLatchingOutcome, logAvailabilityDecision, startHostStallSampler, transientRetryDelayMs, } from "./availability-policy.js";
28
30
  export { createAvailabilityLatch, classifyProbeFailure, describeProbeEvidence, describeUnavailability, isTransientDecision, logAvailabilityDecision, startHostStallSampler, } from "./availability-policy.js";
@@ -1390,7 +1392,7 @@ async function probeAstGrepCommandAsync(cmd, argsPrefix = []) {
1390
1392
  let check;
1391
1393
  let hostStallMs;
1392
1394
  try {
1393
- check = await safeSpawnAsync(cmd, [...argsPrefix, "--version"], {
1395
+ check = await probeToolAsync(cmd, [...argsPrefix, "--version"], {
1394
1396
  timeout: 5000,
1395
1397
  });
1396
1398
  }
@@ -1674,7 +1676,7 @@ export async function resolveLocalFirstAsync(toolName, cwd, windowsExt = ".cmd")
1674
1676
  if (globalBin)
1675
1677
  return { cmd: globalBin, args: [] };
1676
1678
  // 3. Global PATH (already installed system-wide, on PATH)
1677
- const globalCheck = await safeSpawnAsync(toolName, ["--version"], {
1679
+ const globalCheck = await probeToolAsync(toolName, ["--version"], {
1678
1680
  timeout: 3000,
1679
1681
  });
1680
1682
  if (!globalCheck.error && globalCheck.status === 0) {
@@ -1693,3 +1695,7 @@ export const sg = {
1693
1695
  isAvailableAsync: isSgAvailableAsync,
1694
1696
  getCommand: getSgCommand,
1695
1697
  };
1698
+ /** Shared cwd seam for runner probes and analysis children (#2777). */
1699
+ export function resolveRunnerCwd(ctx, tool) {
1700
+ return resolveToolCwd("runner", tool, ctx.filePath, ctx);
1701
+ }
@@ -13,24 +13,3 @@ export function readFileContent(filePath) {
13
13
  return undefined;
14
14
  }
15
15
  }
16
- /**
17
- * Parse common tool output line into a diagnostic
18
- * Format: file:line:col message (category)
19
- */
20
- export function parseToolLine(line, toolName, filePath) {
21
- const match = line.match(/^(.+?):(\d+):(\d+)\s+(.+?)\s*\((.+?)\)/);
22
- if (!match)
23
- return null;
24
- return {
25
- id: `${toolName}-${match[2]}-${match[5]}`,
26
- message: `${match[5]}: ${match[4]}`,
27
- filePath,
28
- line: parseInt(match[2], 10),
29
- column: parseInt(match[3], 10),
30
- severity: line.includes("error") ? "error" : "warning",
31
- semantic: "warning",
32
- tool: toolName,
33
- rule: match[5],
34
- fixable: false,
35
- };
36
- }
@@ -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, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
6
7
  import { parseToolRun } from "./utils/tool-failure.js";
@@ -72,7 +73,7 @@ const valeRunner = {
72
73
  priority: PRIORITY.DOC_QUALITY,
73
74
  skipTestFiles: false,
74
75
  async run(ctx) {
75
- const cwd = ctx.cwd || process.cwd();
76
+ const cwd = resolveRunnerCwd(ctx, "vale");
76
77
  // Config-gated: skip unless a .vale.ini is found
77
78
  if (!findValeConfig(cwd)) {
78
79
  return { status: "skipped", diagnostics: [], semantic: "none" };
@@ -19,14 +19,7 @@ import { BoundedLruCache } from "../../bounded-cache.js";
19
19
  import { compareOrdinal } from "../../string-utils.js";
20
20
  // --- Constants ---
21
21
  /** Overly broad patterns that match everything (cause false positive explosions) */
22
- export const OVERLY_BROAD_PATTERNS = [
23
- "$NAME",
24
- "$FIELD",
25
- "$_",
26
- "$X",
27
- "$VAR",
28
- "$EXPR",
29
- ];
22
+ const OVERLY_BROAD_PATTERNS = ["$NAME", "$FIELD", "$_", "$X", "$VAR", "$EXPR"];
30
23
  /** Maximum complexity score for rules in blockingOnly mode */
31
24
  export const MAX_BLOCKING_RULE_COMPLEXITY = 8;
32
25
  /**
@@ -126,7 +119,7 @@ export function loadYamlRulesFresh(ruleDir, severityFilter) {
126
119
  cache.set(ruleDir, { rules, signature });
127
120
  return rules;
128
121
  }
129
- export function getCachedRules(ruleDir, severityFilter) {
122
+ function getCachedRules(ruleDir, severityFilter) {
130
123
  if (!fs.existsSync(ruleDir)) {
131
124
  return [];
132
125
  }
@@ -179,17 +172,6 @@ export function isOverlyBroadPattern(pattern) {
179
172
  return true;
180
173
  return /^\$[A-Z_]+$/i.test(pattern.trim());
181
174
  }
182
- export function isValidCondition(condition) {
183
- if (!condition)
184
- return false;
185
- if (condition.all !== undefined && condition.all.length === 0)
186
- return false;
187
- if (condition.any !== undefined && condition.any.length === 0)
188
- return false;
189
- if (isOverlyBroadPattern(condition.pattern))
190
- return false;
191
- return true;
192
- }
193
175
  export function isStructuredRule(rule) {
194
176
  if (!rule.rule)
195
177
  return false;
@@ -1,7 +1,8 @@
1
1
  import { safeSpawnAsync } from "../../safe-spawn.js";
2
+ import { logRunnerAdvisoryOnce } from "../../tool-cwd.js";
2
3
  import { getLinterPolicyForCwd, hasYamllintConfig } from "../../tool-policy.js";
3
4
  import { PRIORITY } from "../priorities.js";
4
- import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
5
+ import { createAvailabilityChecker, resolveRunnerCwd, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
5
6
  import { parseToolRun } from "./utils/tool-failure.js";
6
7
  import { finishParsedRun } from "./utils/tool-failure.js";
7
8
  const yamllint = createAvailabilityChecker("yamllint", ".exe");
@@ -35,14 +36,14 @@ const yamllintRunner = {
35
36
  priority: PRIORITY.YAML_LINT,
36
37
  skipTestFiles: false,
37
38
  async run(ctx) {
38
- const cwd = ctx.cwd || process.cwd();
39
+ const cwd = resolveRunnerCwd(ctx, "yamllint");
39
40
  const policy = getLinterPolicyForCwd(ctx.filePath, cwd);
40
41
  if (policy && !policy.preferredRunners.includes("yamllint")) {
41
42
  return { status: "skipped", diagnostics: [], semantic: "none" };
42
43
  }
43
44
  const hasConfig = hasYamllintConfig(cwd);
44
45
  if (!hasConfig) {
45
- ctx.log("yamllint: no config detected, running with default rules");
46
+ logRunnerAdvisoryOnce(ctx, "yamllint", cwd, "yamllint: no config detected, running with default rules");
46
47
  }
47
48
  let cmd = null;
48
49
  if (await yamllint.isAvailableAsync(cwd)) {
@@ -54,6 +55,7 @@ const yamllintRunner = {
54
55
  if (!cmd)
55
56
  return { status: "skipped", diagnostics: [], semantic: "none" };
56
57
  const result = await safeSpawnAsync(cmd, ["-f", "parsable", ctx.filePath], {
58
+ cwd,
57
59
  timeout: 15000,
58
60
  });
59
61
  // #1816: this runner read `result.status` zero times, so a yamllint
@@ -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
  // zig rejects `--version`; the version subcommand is `zig version`. Using the
@@ -46,7 +47,7 @@ const zigCheckRunner = {
46
47
  priority: PRIORITY.GENERAL_ANALYSIS,
47
48
  skipTestFiles: false,
48
49
  async run(ctx) {
49
- const cwd = ctx.cwd || process.cwd();
50
+ const cwd = resolveRunnerCwd(ctx, "zig-check");
50
51
  if (!(await zig.isAvailableAsync(cwd))) {
51
52
  return { status: "skipped", diagnostics: [], semantic: "none" };
52
53
  }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Shared formatting utilities for the dispatch system.
3
3
  */
4
- export const EMOJI = {
4
+ const EMOJI = {
5
5
  blocking: "🔴",
6
6
  warning: "🟡",
7
7
  fixed: "✅",
@@ -12,7 +12,7 @@ export const EMOJI = {
12
12
  /**
13
13
  * Format a single diagnostic for display
14
14
  */
15
- export function formatDiagnostic(d) {
15
+ function formatDiagnostic(d) {
16
16
  const line = d.line ? `L${d.line}: ` : "";
17
17
  const indented = d.message.split("\n").join("\n ");
18
18
  const fix = d.fixSuggestion ? `\n 💡 Fix: ${d.fixSuggestion}` : "";
@@ -30,10 +30,3 @@ export function logDispositionEvent(entry) {
30
30
  }
31
31
  writer.log({ ts: new Date().toISOString(), ...entry });
32
32
  }
33
- export function getDispositionLogPath() {
34
- return DISPOSITION_LOG_FILE;
35
- }
36
- /** Resolve once all enqueued disposition writes are on disk. */
37
- export function flushDispositionLog() {
38
- return writer.flush();
39
- }
@@ -47,7 +47,9 @@ import { explainServersForFile, lspConfigOf, registerLSPConfig, } from "./lsp/co
47
47
  // apart on a Windows-shaped path (AGENTS.md defect shape 2).
48
48
  import { isSameOrWithin } from "./lsp/server.js";
49
49
  import { homeRelativePath } from "./path-utils.js";
50
+ import { resolveToolCwd } from "./tool-cwd.js";
50
51
  import { compareOrdinal } from "./string-utils.js";
52
+ import { LENS_TOOL_NAMES, resolveLensToolEnabled } from "./tool-config.js";
51
53
  /** True when a `file` half is the rejection shape, not a resolved view. */
52
54
  export function isEffectiveFileViewError(file) {
53
55
  return "error" in file;
@@ -289,6 +291,10 @@ export async function effectiveConfig(options = {}) {
289
291
  provenance: provenanceView(resolved, homeDir).entries,
290
292
  provenanceCounts: summary.countsByTier,
291
293
  recordCounts: countBy(resolution.records, (record) => record.code),
294
+ tools: LENS_TOOL_NAMES.map((name) => ({
295
+ name,
296
+ enabled: resolveLensToolEnabled(name, resolved.value, undefined, options.noTools),
297
+ })),
292
298
  ...(fileOutsideCwd
293
299
  ? {
294
300
  file: {
@@ -299,7 +305,7 @@ export async function effectiveConfig(options = {}) {
299
305
  : absolute === undefined
300
306
  ? {}
301
307
  : {
302
- file: await fileView(absolute, resolved, homeDir,
308
+ file: await fileView(absolute, resolved, homeDir, cwd,
303
309
  // The gates read the LSP slice of that SAME resolution, through
304
310
  // the same `registerLSPConfig` conversion `initLSPConfig` uses —
305
311
  // no session-root registration, no per-root config-store write
@@ -325,7 +331,7 @@ function toolReason(selected, kind) {
325
331
  return "selected";
326
332
  return kind === undefined ? "no-dispatch-plan" : "not-registered-for-kind";
327
333
  }
328
- async function fileView(absolute, resolved, homeDir, lspConfig) {
334
+ async function fileView(absolute, resolved, homeDir, workspaceCwd, lspConfig) {
329
335
  const language = resolveLanguage(absolute);
330
336
  const kind = detectFileKind(absolute);
331
337
  const section = lspSectionOf(resolved.value);
@@ -392,6 +398,10 @@ async function fileView(absolute, resolved, homeDir, lspConfig) {
392
398
  id,
393
399
  selected: available.has(id),
394
400
  reason: toolReason(available.has(id), kind),
401
+ resolvedCwd: homeRelativePath(resolveToolCwd("runner", id, absolute, {
402
+ cwd: workspaceCwd,
403
+ suppressTelemetry: true,
404
+ }), homeDir),
395
405
  }));
396
406
  return {
397
407
  path: homeRelativePath(absolute, homeDir),
@@ -88,14 +88,14 @@ export function startEventLoopMonitor(resolutionMs = 20) {
88
88
  * every block that tier cares about while keeping sub-second jitter — where
89
89
  * measurement slop rivals the signal — out of the verdict.
90
90
  */
91
- export const STALL_CLASSIFY_FLOOR_MS = 1000;
91
+ const STALL_CLASSIFY_FLOOR_MS = 1000;
92
92
  /**
93
93
  * Slack allowed to the CPU budget before a block counts as unaccounted.
94
94
  * `process.cpuUsage()` and the histogram are sampled at slightly different
95
95
  * instants and the histogram quantizes, so a block whose CPU coverage is
96
96
  * within this much of exact is called `cpu-accounted`, not a stall.
97
97
  */
98
- export const STALL_CLASSIFY_SLOP_MS = 250;
98
+ const STALL_CLASSIFY_SLOP_MS = 250;
99
99
  /**
100
100
  * Split a block into compute-vs-stall from the CPU it could possibly have
101
101
  * burned (#1980). Pure, so the discrimination is testable without the native
@@ -26,6 +26,7 @@ import { isTestMode } from "./env-utils.js";
26
26
  import { getGlobalPiLensLogDir } from "./probe-home-state.js";
27
27
  import { getMaxLogSizeMB } from "./log-cleanup.js";
28
28
  import { createNdjsonLogger } from "./ndjson-logger.js";
29
+ import { getTurnId } from "./turn-context.js";
29
30
  export const EXTENSION_LOG_FILE = path.join(getGlobalPiLensLogDir(), "extension.log");
30
31
  const writer = createNdjsonLogger({
31
32
  filePath: EXTENSION_LOG_FILE,
@@ -37,6 +38,7 @@ export function logExtension(entry) {
37
38
  writer.log({
38
39
  ts: new Date().toISOString(),
39
40
  pid: process.pid,
41
+ turnId: getTurnId(),
40
42
  level: entry.level ?? "error",
41
43
  subsystem: entry.subsystem,
42
44
  message: entry.message,
@@ -92,7 +92,7 @@ export const KIND_EXTENSIONS = {
92
92
  zig: [".zig", ".zon"],
93
93
  };
94
94
  /** Return whether a path has an extension registered for the given file kind. */
95
- export function hasKindExtension(filePath, kind) {
95
+ function hasKindExtension(filePath, kind) {
96
96
  const extension = extname(filePath).toLowerCase();
97
97
  return KIND_EXTENSIONS[kind].some((candidate) => candidate === extension);
98
98
  }
@@ -284,18 +284,6 @@ export const NON_CODE_KINDS = new Set([
284
284
  "toml",
285
285
  "yaml",
286
286
  ]);
287
- /**
288
- * Check if a file kind represents a code file (not config/markdown).
289
- */
290
- export function isCodeKind(kind) {
291
- return CODE_KINDS.has(kind);
292
- }
293
- /**
294
- * Check if a file kind represents a text/config/doc/markup file.
295
- */
296
- export function isConfigKind(kind) {
297
- return NON_CODE_KINDS.has(kind);
298
- }
299
287
  /**
300
288
  * Check if a file path resolves to a {@link CODE_KINDS} kind. Undetectable
301
289
  * files (unknown extension, e.g. `.coffee` from SOURCE_PRECEDENCE) are
@@ -351,31 +339,6 @@ export function getFileKindLabel(kind) {
351
339
  };
352
340
  return labels[kind] ?? kind;
353
341
  }
354
- /**
355
- * Get file extensions for a file kind.
356
- */
357
- export function getExtensionsForKind(kind) {
358
- return [...(KIND_EXTENSIONS[kind] ?? [])];
359
- }
360
- /**
361
- * Check if a file should be scanned for linting/formatting.
362
- * Excludes test files, generated files, etc.
363
- */
364
- export function isScannableFile(filePath) {
365
- const kind = detectFileKind(filePath);
366
- if (!kind)
367
- return false;
368
- // Exclude test files for most kinds
369
- const base = basename(filePath);
370
- if (base.includes(".test.") ||
371
- base.includes(".spec.") ||
372
- base.startsWith("test-") ||
373
- base.startsWith("spec-")) {
374
- return false;
375
- }
376
- // Only scan code and config files
377
- return isCodeKind(kind) || isConfigKind(kind);
378
- }
379
342
  /**
380
343
  * Get the language identifier for LSP/tools that use language IDs.
381
344
  */