@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
@@ -0,0 +1,299 @@
1
+ import * as os from "node:os";
2
+ import { existsSync, readdirSync } from "node:fs";
3
+ import * as path from "node:path";
4
+ import { logExtension } from "./extension-log.js";
5
+ import { isRealGitMarker, isAtOrAboveHomeDir, isUnderDir, isWindowsPath, nameMatchesMarkerGlob, normalizeEphemeralMapKey, } from "./path-utils.js";
6
+ import { getDegradationLedgerGeneration, recordDegradationOnce, } from "./degradation-ledger.js";
7
+ import { createGenerationMap, createGenerationSource, } from "./generation-guard.js";
8
+ export const FORMATTER_MARKERS = {
9
+ biome: ["biome.json", "biome.jsonc", "package.json", ".gitignore"],
10
+ prettier: [
11
+ ".prettierrc",
12
+ ".prettierrc.json",
13
+ ".prettierrc.yaml",
14
+ ".prettierrc.yml",
15
+ ".prettierrc.js",
16
+ ".prettierrc.cjs",
17
+ ".prettierrc.mjs",
18
+ "prettier.config.js",
19
+ "prettier.config.cjs",
20
+ "prettier.config.mjs",
21
+ ".prettierignore",
22
+ "package.json",
23
+ ".gitignore",
24
+ ],
25
+ ruff: ["pyproject.toml", "ruff.toml", ".ruff.toml", ".gitignore"],
26
+ black: ["pyproject.toml", "black.toml", ".black", ".gitignore"],
27
+ "php-cs-fixer": [".php-cs-fixer.php", ".php-cs-fixer.dist.php", ".gitignore"],
28
+ sqlfluff: [".sqlfluff", "pyproject.toml", "setup.cfg", ".gitignore"],
29
+ oxfmt: [
30
+ "oxfmt.toml",
31
+ ".oxfmtrc.json",
32
+ "vite-plus.json",
33
+ "package.json",
34
+ ".gitignore",
35
+ ],
36
+ rustfmt: ["rustfmt.toml", ".rustfmt.toml", "Cargo.toml", ".gitignore"],
37
+ rubocop: [".rubocop.yml", ".rubocop.yaml", ".gitignore"],
38
+ standardrb: [".standard.yml", ".standard.yaml", ".gitignore"],
39
+ "clang-format": [".clang-format", "_clang-format", ".gitignore"],
40
+ stylua: ["stylua.toml", ".stylua.toml", ".gitignore"],
41
+ ocamlformat: [".ocamlformat", ".gitignore"],
42
+ "google-java-format": [".google-java-format", ".editorconfig", ".gitignore"],
43
+ cljfmt: [".cljfmt.edn", "cljfmt.edn", ".cljfmt", ".gitignore"],
44
+ "cmake-format": [
45
+ ".cmake-format",
46
+ ".cmake-format.yaml",
47
+ ".cmake-format.yml",
48
+ ".cmake-format.json",
49
+ ".cmake-format.py",
50
+ "cmake-format.yaml",
51
+ "cmake-format.yml",
52
+ ".editorconfig",
53
+ ".gitignore",
54
+ ],
55
+ "psscriptanalyzer-format": [
56
+ "PSScriptAnalyzerSettings.psd1",
57
+ "ScriptAnalyzerSettings.psd1",
58
+ ".gitignore",
59
+ ],
60
+ csharpier: [
61
+ ".csharpierrc",
62
+ ".csharpierrc.json",
63
+ ".csharpierrc.yaml",
64
+ ".csharpierrc.yml",
65
+ ".gitignore",
66
+ ],
67
+ ormolu: [".ormolu", ".gitignore"],
68
+ taplo: ["taplo.toml", ".taplo.toml", ".gitignore"],
69
+ terraform: [".terraform.lock.hcl", ".gitignore"],
70
+ swiftformat: [".swiftformat", ".gitignore"],
71
+ fantomas: [".fantomasignore", ".editorconfig", ".gitignore"],
72
+ mix: [".formatter.exs", ".gitignore"],
73
+ shfmt: [".editorconfig", ".gitignore"],
74
+ ktlint: [".editorconfig", ".gitignore"],
75
+ ktfmt: [
76
+ ".editorconfig",
77
+ ".ktfmt",
78
+ ".ktfmt.kts",
79
+ "build.gradle",
80
+ "build.gradle.kts",
81
+ "settings.gradle",
82
+ "settings.gradle.kts",
83
+ ".gitignore",
84
+ ],
85
+ };
86
+ const RUNNER_MARKERS = {
87
+ yamllint: [".yamllint", "yamllint.yaml", "yamllint.yml", "pyproject.toml"],
88
+ ruff: ["pyproject.toml", "ruff.toml", ".ruff.toml"],
89
+ "spellcheck/typos": ["_typos.toml", "typos.toml"],
90
+ biome: ["biome.json", "biome.jsonc", "package.json"],
91
+ oxlint: [".oxlintrc.json", "oxlint.config.js", "package.json"],
92
+ sqlfluff: [".sqlfluff", "pyproject.toml", "setup.cfg"],
93
+ prettier: [".prettierignore", "package.json"],
94
+ // #2894: cargo must run at the package root. This is the marker walk
95
+ // `rust-clippy.ts` used to do for itself with `findNearestContaining`.
96
+ "rust-clippy": ["Cargo.toml"],
97
+ };
98
+ const toolCwdGeneration = createGenerationSource("tool-cwd");
99
+ const logged = createGenerationMap("tool-cwd-resolution-log");
100
+ const markerWalks = new Map();
101
+ const markerWalkGenerations = createGenerationMap("tool-cwd-marker-walks");
102
+ let markerWalkCount = 0;
103
+ /** Pure key seam for ephemeral tool-cwd memo and log identity. */
104
+ export function _toolCwdEphemeralKey(parts) {
105
+ return parts.map(normalizeEphemeralMapKey).join("\0");
106
+ }
107
+ /** Test probe for the per-generation walk memo; not part of runtime behavior. */
108
+ export function _getToolCwdMarkerWalkCount() {
109
+ return markerWalkCount;
110
+ }
111
+ function syncGeneration() {
112
+ if (toolCwdGeneration.current() === getDegradationLedgerGeneration())
113
+ return;
114
+ markerWalks.clear();
115
+ markerWalkGenerations.clear();
116
+ logged.clear();
117
+ while (toolCwdGeneration.current() < getDegradationLedgerGeneration()) {
118
+ toolCwdGeneration.bump();
119
+ }
120
+ }
121
+ function findMarkerRoot(startDir, markers, homeDir) {
122
+ syncGeneration();
123
+ const key = _toolCwdEphemeralKey([
124
+ path.resolve(startDir),
125
+ ...markers,
126
+ path.resolve(homeDir),
127
+ ]);
128
+ const cached = markerWalks.get(key);
129
+ if (cached && markerWalkGenerations.current(key) !== 0) {
130
+ // A negative walk is not stable: a project marker can be created after
131
+ // the first resolution, so do not cache absence across calls. Positive
132
+ // results remain memoized and are still revalidated when their marker is
133
+ // deleted (#2894).
134
+ if (!cached.marker || !cached.root) {
135
+ markerWalks.delete(key);
136
+ markerWalkGenerations.forget(key);
137
+ }
138
+ else {
139
+ // #2777: a marker can disappear during a session; do not reuse a stale root.
140
+ if (existsSync(path.join(cached.root, cached.marker)))
141
+ return cached;
142
+ markerWalks.delete(key);
143
+ markerWalkGenerations.forget(key);
144
+ }
145
+ }
146
+ markerWalkCount++;
147
+ let current = path.resolve(startDir);
148
+ let result = { root: null };
149
+ for (let depth = 0; depth < 64; depth++) {
150
+ if (isAtOrAboveHomeDir(current, homeDir))
151
+ break;
152
+ for (const marker of markers) {
153
+ const slash = marker.replace(/\\/g, "/").lastIndexOf("/");
154
+ const parent = slash >= 0 ? marker.slice(0, slash) : "";
155
+ const basename = slash >= 0 ? marker.slice(slash + 1) : marker;
156
+ const target = parent
157
+ ? path.join(current, ...parent.split("/").filter(Boolean))
158
+ : current;
159
+ let found = false;
160
+ if (basename.includes("*")) {
161
+ try {
162
+ found = readdirSync(target, { withFileTypes: true }).some((entry) => (entry.isFile() || entry.isSymbolicLink()) &&
163
+ nameMatchesMarkerGlob(entry.name, basename));
164
+ }
165
+ catch {
166
+ found = false;
167
+ }
168
+ }
169
+ else {
170
+ found = existsSync(path.join(target, basename));
171
+ }
172
+ if (found) {
173
+ result = { root: current, marker };
174
+ markerWalks.set(key, result);
175
+ markerWalkGenerations.bump(key);
176
+ return result;
177
+ }
178
+ }
179
+ const parentDir = path.dirname(current);
180
+ if (parentDir === current)
181
+ break;
182
+ current = parentDir;
183
+ }
184
+ markerWalks.set(key, result);
185
+ markerWalkGenerations.bump(key);
186
+ return result;
187
+ }
188
+ function markersFor(kind, tool, ctx) {
189
+ if (kind === "lsp")
190
+ return ctx.rootMarkers ?? [];
191
+ // #2871: caller-supplied markers count for runners too. `RUNNER_MARKERS`
192
+ // covers the linter/formatter-shaped runners this module has always known;
193
+ // a caller that owns its own marker table — the test runner, whose
194
+ // `RUNNERS[x].configFiles` IS that table — passes it here rather than
195
+ // registering a second copy of the same data in this file.
196
+ if (kind === "runner")
197
+ return ctx.rootMarkers ?? RUNNER_MARKERS[tool] ?? [];
198
+ return FORMATTER_MARKERS[tool] ?? [".gitignore"];
199
+ }
200
+ function emitResolution(kind, tool, cwd, reason) {
201
+ syncGeneration();
202
+ const key = _toolCwdEphemeralKey([kind, tool, cwd, reason]);
203
+ if (logged.current(key) !== 0)
204
+ return;
205
+ logged.bump(key);
206
+ logExtension({
207
+ subsystem: "tool-cwd",
208
+ level: "debug",
209
+ message: `cwd ${kind} ${tool} cwd=${cwd} reason=${reason}`,
210
+ });
211
+ }
212
+ /**
213
+ * Emit a constant runner advisory once per (tool, resolved root) per session
214
+ * (#2811): the yamllint/stylelint/sqlfluff "no config detected" lines and
215
+ * markdownlint's spawn-timeout cooldown notice logged once PER FILE at error
216
+ * level — 17 lines in one session for one tool. The throttle shares the
217
+ * resolution-log map and its ledger-generation reset, so `session_start`
218
+ * re-arms it like every once-latch in this module. The message rides
219
+ * `ctx.log` at debug level so the dispatch seam stays the one sink for
220
+ * runner lines, with its own filePath/kind metadata.
221
+ */
222
+ export function logRunnerAdvisoryOnce(ctx, tool, root, message) {
223
+ syncGeneration();
224
+ const key = _toolCwdEphemeralKey(["runner-advisory", tool, root]);
225
+ if (logged.current(key) !== 0)
226
+ return;
227
+ logged.bump(key);
228
+ ctx.log(message, "debug");
229
+ }
230
+ /** Resolve every child process cwd/root through one bounded, synchronous seam. */
231
+ export function resolveToolCwd(kind, tool, file, ctx) {
232
+ const dispatchRoot = path.resolve(ctx.cwd ?? process.cwd());
233
+ const absoluteFile = path.resolve(file);
234
+ const fileDir = path.dirname(absoluteFile);
235
+ const homeDir = ctx.homeDir ?? os.homedir();
236
+ const insideDispatch = isUnderDir(absoluteFile, dispatchRoot);
237
+ if (ctx.serverRoot) {
238
+ const rootPath = isWindowsPath(ctx.serverRoot) ? path.win32 : path;
239
+ const serverRoot = rootPath.resolve(ctx.serverRoot);
240
+ if (!ctx.suppressTelemetry)
241
+ emitResolution(kind, tool, serverRoot, "server-root");
242
+ return serverRoot;
243
+ }
244
+ const markers = markersFor(kind, tool, ctx);
245
+ const markerResult = markers.length
246
+ ? findMarkerRoot(fileDir, markers, ctx.allowHomeMarker ? path.parse(homeDir).root : homeDir)
247
+ : { root: null };
248
+ const markerRoot = markerResult.root;
249
+ if (markerRoot &&
250
+ (insideDispatch ? isUnderDir(markerRoot, dispatchRoot) : true)) {
251
+ const finalReason = `marker:${markerResult.marker ?? markers[0]}`;
252
+ if (!ctx.suppressTelemetry)
253
+ emitResolution(kind, tool, markerRoot, finalReason);
254
+ return markerRoot;
255
+ }
256
+ const gitResult = findMarkerRoot(fileDir, [".git"], homeDir);
257
+ const gitRoot = gitResult.root && isRealGitMarker(path.join(gitResult.root, ".git"))
258
+ ? gitResult.root
259
+ : null;
260
+ if (gitRoot && (insideDispatch ? isUnderDir(gitRoot, dispatchRoot) : true)) {
261
+ if (!ctx.suppressTelemetry)
262
+ emitResolution(kind, tool, gitRoot, "git-root");
263
+ return gitRoot;
264
+ }
265
+ if (insideDispatch) {
266
+ if (kind === "formatter") {
267
+ if (!ctx.suppressTelemetry)
268
+ emitResolution(kind, tool, fileDir, "file-dir-fallback");
269
+ if (!ctx.suppressTelemetry && !isUnderDir(fileDir, homeDir)) {
270
+ recordDegradationOnce({
271
+ kind: "tool-cwd-resolution",
272
+ subject: tool,
273
+ reason: `${kind}:home-cap:${absoluteFile}`,
274
+ });
275
+ }
276
+ return fileDir;
277
+ }
278
+ if (!ctx.suppressTelemetry)
279
+ emitResolution(kind, tool, dispatchRoot, "dispatch-root");
280
+ return dispatchRoot;
281
+ }
282
+ const reason = isUnderDir(fileDir, homeDir)
283
+ ? "file-dir-fallback"
284
+ : "home-cap";
285
+ const fallback = isUnderDir(fileDir, homeDir) ? fileDir : homeDir;
286
+ if (!ctx.suppressTelemetry)
287
+ recordDegradationOnce({
288
+ kind: "tool-cwd-resolution",
289
+ subject: tool,
290
+ reason: `${kind}:${reason}:${absoluteFile}`,
291
+ });
292
+ if (!ctx.suppressTelemetry)
293
+ emitResolution(kind, tool, fallback, reason);
294
+ return fallback;
295
+ }
296
+ /** Runner-shaped adapter kept at the same seam for every runner consumer. */
297
+ export function resolveRunnerCwd(ctx, tool) {
298
+ return resolveToolCwd("runner", tool, ctx.filePath, ctx);
299
+ }
@@ -756,7 +756,7 @@ const FORMATTER_POLICY_BY_FILENAME = new Map(TERRAGRUNT_FILENAMES.map((name) =>
756
756
  // lines don't fall at the head of the pre-existing lookup-table duplication and
757
757
  // get counted as new duplicated code. Bindings are live, so position is safe.
758
758
  export { AUTO_INSTALLABLE_DEFAULT_FORMATTERS, FORMATTER_POLICY_BY_EXTENSION, FORMATTER_POLICY_BY_FILENAME, };
759
- export function getFormatterPolicyForExtension(ext) {
759
+ function getFormatterPolicyForExtension(ext) {
760
760
  return FORMATTER_POLICY_BY_EXTENSION.get(ext.toLowerCase());
761
761
  }
762
762
  export function getFormatterPolicyForFile(filePath) {
@@ -0,0 +1,53 @@
1
+ /**
2
+ * The tool-probe spawn seam (#2894).
3
+ *
4
+ * A sibling of `tool-cwd.ts`: that module owns where a child that READS A
5
+ * PROJECT starts, this one owns the fact that a child which reads no project
6
+ * starts nowhere in particular.
7
+ *
8
+ * It is a module of its own rather than another export on `safe-spawn.ts`
9
+ * deliberately. Every availability test in this repo fakes the process
10
+ * boundary with `vi.mock("clients/safe-spawn.js", … { safeSpawnAsync })`, and
11
+ * a same-module helper would call the module's own unmocked binding — the
12
+ * probe would spawn for real while the test believed it had the boundary. One
13
+ * module hop keeps every existing double production-faithful.
14
+ */
15
+ import { safeSpawnAsync } from "./safe-spawn.js";
16
+ /**
17
+ * Run a tool's own presence/version invocation — `<tool> --version`, `cl`,
18
+ * `go version`, `which <pm>`, `Get-Module -ListAvailable …` — and hand back
19
+ * the raw spawn result for the caller's availability policy to classify.
20
+ *
21
+ * ## The contract: a probe never gets a `cwd`
22
+ *
23
+ * A probe asks whether a binary exists and what it calls itself. The answer
24
+ * does not depend on the directory the child starts in, so this seam passes
25
+ * NONE — the child inherits the host's directory and nothing it reports is
26
+ * read out of a project. That is why the sweep in
27
+ * `tests/clients/dispatch/runners/runner-spawn-cwd-sweep.test.ts` admits ONE
28
+ * cwd-less spawn here instead of the 23 it admitted before: every one of those
29
+ * sites re-decided the same thing in its own words, and 23 sentences a
30
+ * reviewer has to re-read one at a time is how an admission table stops being
31
+ * auditable (#2872 round 3 shipped 127 rows carrying two canned sentences,
32
+ * four of them false where they were read).
33
+ *
34
+ * `cwd` is STRIPPED rather than merely left out of {@link ProbeSpawnOptions}:
35
+ * the type stops an object literal from carrying one, and the destructure
36
+ * below removes one that arrived inside an already-typed options object a
37
+ * caller widened or spread. Both halves are guarded — deleting the
38
+ * destructure changes this call's text, which retires the sweep's admission
39
+ * row, and `tests/clients/probe-and-root-spawn-cwd.test.ts` reds on the
40
+ * smuggled cwd reaching the child. A probe that genuinely needs to
41
+ * run somewhere — `mix credo --version` needs a mix project, `cargo clippy
42
+ * --version` needs a package, `eslint --version` resolves a project-local
43
+ * binary — must call `safeSpawnAsync` directly and be admitted by that sweep
44
+ * on its own reason.
45
+ */
46
+ export async function probeToolAsync(command, args, options) {
47
+ // Destructured away rather than overwritten with `undefined`: the key is
48
+ // then genuinely ABSENT from what reaches the spawn, which is both what the
49
+ // contract says and what `exactOptionalPropertyTypes` wants (a present
50
+ // `cwd: undefined` is a strictness spike the `tests/config` ratchet counts).
51
+ const { cwd: _strippedCwd, ...rest } = (options ?? {});
52
+ return safeSpawnAsync(command, [...args], { ...rest });
53
+ }
@@ -1,4 +1,46 @@
1
1
  import { logLatency } from "./latency-logger.js";
2
+ import { BoundedFifoMap } from "./bounded-cache.js";
3
+ import { recordDegradationOnce } from "./degradation-ledger.js";
4
+ // pi re-runs the extension factory for session rebuilds, but imports this
5
+ // module once per process. Keep conversation activation memory here, keyed by
6
+ // pi's session file rather than by a factory closure or process-wide session.
7
+ export const REMEMBERED_LAZY_TOOLS_MAX_SESSIONS = 128;
8
+ const rememberedLazyToolsBySessionFile = new BoundedFifoMap(REMEMBERED_LAZY_TOOLS_MAX_SESSIONS);
9
+ export function rememberLazyTools(sessionFile, names) {
10
+ if (!sessionFile) {
11
+ recordDegradationOnce({
12
+ kind: "tool-set-session-file-unavailable",
13
+ subject: "activation",
14
+ reason: "session-file identity unavailable; activation memory is inert",
15
+ });
16
+ return;
17
+ }
18
+ const remembered = rememberedLazyToolsBySessionFile.get(sessionFile) ?? new Set();
19
+ for (const name of names)
20
+ remembered.add(name);
21
+ rememberedLazyToolsBySessionFile.set(sessionFile, remembered);
22
+ }
23
+ export function getRememberedLazyTools(sessionFile) {
24
+ return sessionFile
25
+ ? (rememberedLazyToolsBySessionFile.get(sessionFile) ?? new Set())
26
+ : new Set();
27
+ }
28
+ export function clearRememberedLazyTools(sessionFile) {
29
+ if (sessionFile)
30
+ rememberedLazyToolsBySessionFile.delete(sessionFile);
31
+ }
32
+ export function inheritRememberedLazyTools(parentSessionFile, childSessionFile) {
33
+ if (!parentSessionFile ||
34
+ !childSessionFile ||
35
+ parentSessionFile === childSessionFile)
36
+ return;
37
+ const remembered = rememberedLazyToolsBySessionFile.get(parentSessionFile);
38
+ if (remembered)
39
+ rememberedLazyToolsBySessionFile.set(childSessionFile, new Set(remembered));
40
+ }
41
+ export function resetRememberedLazyToolsForTests() {
42
+ rememberedLazyToolsBySessionFile.clear();
43
+ }
2
44
  /**
3
45
  * Whether the host will send this model deferred (searchable) tool
4
46
  * definitions rather than the full inline list.
@@ -80,7 +80,7 @@ function grammarFileStamp(filePath) {
80
80
  return undefined;
81
81
  }
82
82
  }
83
- export function isTreeSitterWasmAbortError(error) {
83
+ function isTreeSitterWasmAbortError(error) {
84
84
  const message = error instanceof Error ? error.message : String(error);
85
85
  return message.includes("Aborted") || message.includes("abort()");
86
86
  }
@@ -4012,54 +4012,3 @@ export class TreeSitterClient {
4012
4012
  }
4013
4013
  }
4014
4014
  // --- Simplified Pattern Search (regex fallback) ---
4015
- /**
4016
- * Fallback structural search using regex when tree-sitter unavailable
4017
- * Less accurate but works without WASM dependencies
4018
- */
4019
- export function regexStructuralSearch(pattern, files, options = {}) {
4020
- const matches = [];
4021
- const maxResults = options.maxResults ?? 50;
4022
- // Extract pattern structure for regex
4023
- // "console.log($MSG)" -> /console\.log\(([^)]+)\)/
4024
- const regexPattern = pattern
4025
- .replace(/\\/g, "\\\\")
4026
- .replace(/\./g, "\\.")
4027
- .replace(/\$\$\$[A-Z_][A-Z0-9_]*/g, "(.*?)") // variadic - non-greedy
4028
- .replace(/\$[A-Z_][A-Z0-9_]*/g, "([^,)]+)"); // single - capture group
4029
- try {
4030
- const regex = new RegExp(regexPattern, "g");
4031
- for (const file of files) {
4032
- if (matches.length >= maxResults)
4033
- break;
4034
- try {
4035
- const content = fs.readFileSync(file, "utf-8");
4036
- const lines = content.split("\n");
4037
- for (let i = 0; i < lines.length; i++) {
4038
- regex.lastIndex = 0;
4039
- const match = regex.exec(lines[i]);
4040
- if (match) {
4041
- const captures = {};
4042
- // Extract captures
4043
- for (let j = 1; j < match.length; j++) {
4044
- captures[`$${j}`] = match[j];
4045
- }
4046
- matches.push({
4047
- file,
4048
- line: i + 1,
4049
- column: match.index + 1,
4050
- matchedText: match[0],
4051
- captures,
4052
- });
4053
- if (matches.length >= maxResults)
4054
- break;
4055
- }
4056
- }
4057
- }
4058
- catch { }
4059
- }
4060
- }
4061
- catch {
4062
- // Invalid regex
4063
- }
4064
- return matches;
4065
- }
@@ -272,7 +272,15 @@ export class TrivyClient extends SecurityScanClient {
272
272
  const findings = parseTrivyReport(raw);
273
273
  const secrets = parseTrivySecrets(raw);
274
274
  const licenses = parseTrivyLicenses(raw);
275
- return { success: true, findings, secrets, licenses, scannedAt };
275
+ // #2154: the one trivy site that parsed a scan of this root.
276
+ return {
277
+ success: true,
278
+ analyzed: true,
279
+ findings,
280
+ secrets,
281
+ licenses,
282
+ scannedAt,
283
+ };
276
284
  }
277
285
  catch (err) {
278
286
  return {
@@ -18,10 +18,6 @@
18
18
  import { truncateToWidth } from "./deps/pi-tui.js";
19
19
  const ELLIPSIS_KIND = { "…": 0, "...": 1, "": 2 };
20
20
  let truncateIsNative = null;
21
- /** Test-only: reset the signature probe between test cases. */
22
- export function _resetTruncateProbeForTests() {
23
- truncateIsNative = null;
24
- }
25
21
  export function fitLine(s, maxWidth, ellipsis = "...") {
26
22
  const w = Math.max(0, maxWidth);
27
23
  const fn = truncateToWidth;
@@ -0,0 +1,52 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ import { getProcessSingleton } from "./process-singletons.js";
3
+ const FAMILY = "turn-context";
4
+ const VERSION = 2;
5
+ function state() {
6
+ return getProcessSingleton(FAMILY, VERSION, () => ({
7
+ sessions: new Map(),
8
+ activeSession: new AsyncLocalStorage(),
9
+ }));
10
+ }
11
+ function sessionState(sessionId) {
12
+ const current = state();
13
+ let session = current.sessions.get(sessionId);
14
+ if (!session) {
15
+ session = { turnId: `${sessionId}:0`, turnIndex: 0 };
16
+ current.sessions.set(sessionId, session);
17
+ }
18
+ return session;
19
+ }
20
+ /** Reset the emit identity before a new session can publish rows. */
21
+ export function resetTurnContext(sessionId) {
22
+ const current = state();
23
+ if (sessionId === undefined)
24
+ return;
25
+ current.sessions.set(sessionId, { turnId: `${sessionId}:0`, turnIndex: 0 });
26
+ }
27
+ /** Ensure a stable host session has a counter without changing detached identity. */
28
+ export function setTurnContextSession(sessionId) {
29
+ const stableSessionId = sessionId?.trim();
30
+ if (stableSessionId !== undefined && stableSessionId !== "")
31
+ sessionState(stableSessionId);
32
+ }
33
+ /** Mint the one id shared by every row emitted during this turn. */
34
+ export function beginTurnContext(sessionId) {
35
+ const session = sessionState(sessionId);
36
+ session.turnIndex += 1;
37
+ session.turnId = `${sessionId}:${session.turnIndex}`;
38
+ return session.turnId;
39
+ }
40
+ /** Run a host event with the session identity that owns its writes. */
41
+ export function runWithTurnContext(sessionId, fn) {
42
+ if (sessionId === undefined)
43
+ return fn();
44
+ return state().activeSession.run(sessionId, fn);
45
+ }
46
+ export function getTurnId() {
47
+ const current = state();
48
+ const sessionId = current.activeSession.getStore();
49
+ if (sessionId === undefined)
50
+ return "turn:0";
51
+ return sessionState(sessionId).turnId;
52
+ }
@@ -32,10 +32,6 @@ export function wireUserNotifier(portsOrGetter) {
32
32
  export function resetUserNotifier() {
33
33
  notifierGetter = undefined;
34
34
  }
35
- /** True when a host render path is available (for callers that want to branch). */
36
- export function hasUserNotifier() {
37
- return notifierGetter !== undefined;
38
- }
39
35
  /**
40
36
  * Best-effort delivery of a user-facing degradation. Never throws — a stale
41
37
  * `ctx` after a session replacement must degrade to a no-op, not break the
@@ -358,7 +358,7 @@ observedAt) {
358
358
  // #555 guard.
359
359
  const key = fileMapKey(filePath);
360
360
  if (!diagnosticsWriteGuard.shouldWrite(key, writeIndex))
361
- return;
361
+ return false;
362
362
  // Keep runner state ordered with the final diagnostic replacement. The
363
363
  // guards are deliberately advanced in both directions because either verb
364
364
  // may be the first completion from a pipeline.
@@ -369,6 +369,7 @@ observedAt) {
369
369
  const observedTs = observedAt ?? Date.now();
370
370
  const rec = getOrCreate(filePath, key);
371
371
  commitDiagnostics(rec, filePath, normalizeDiagnostics(filePath, diagnostics, observedTs), observedTs, key);
372
+ return true;
372
373
  }
373
374
  /** Map the raw diagnostic shape callers pass into stored {@link WidgetDiagnostic}s.
374
375
  * Every produced entry is stamped with `observedTs` (#1186) — the time THIS batch
@@ -605,8 +606,8 @@ export function reconcileCascadeNeighborLspErrors(filePath, lspErrorDiagnostics,
605
606
  */
606
607
  export function reconcileScanDiagnostics(filePath, diagnostics, confirmed, writeIndex, observedAt) {
607
608
  if (!confirmed)
608
- return;
609
- recordDiagnostics(filePath, diagnostics, writeIndex, observedAt);
609
+ return false;
610
+ return recordDiagnostics(filePath, diagnostics, writeIndex, observedAt);
610
611
  }
611
612
  /**
612
613
  * Commit the already-correlated result of a full diagnostics scan.
@@ -47,10 +47,3 @@ export function logWordIndex(entry) {
47
47
  cwd: normalizeFilePath(entry.cwd),
48
48
  });
49
49
  }
50
- export function getWordIndexLogPath() {
51
- return WORD_INDEX_LOG_FILE;
52
- }
53
- /** Resolve once all enqueued word-index writes are on disk (tests/shutdown). */
54
- export function flushWordIndexLog() {
55
- return writer.flush();
56
- }
@@ -30,8 +30,8 @@ import { createDeadline, yieldIfOverBudget, } from "./cooperative-budget.js";
30
30
  /**
31
31
  * Bytes of backing store per posting entry: one `fileId` lane and one `line`
32
32
  * lane, both `Int32`. This is the constant #2069's acceptance criterion is
33
- * written against, and {@link estimatePostingListBytes} is the arithmetic the
34
- * memory-sample record and the regression test both read.
33
+ * written against, and the arithmetic the memory-sample record and the
34
+ * regression test both read.
35
35
  */
36
36
  export const WORD_POSTING_ENTRY_BYTES = 8;
37
37
  /**
@@ -189,10 +189,6 @@ export class WordPostingList {
189
189
  return list;
190
190
  }
191
191
  }
192
- /** Estimated bytes one posting list holds, backing store plus fixed headers. */
193
- export function estimatePostingListBytes(list) {
194
- return list.byteLength + WORD_POSTING_LIST_OVERHEAD_BYTES;
195
- }
196
192
  /**
197
193
  * Re-home every posting list into ONE shared `ArrayBuffer`, exactly sized.
198
194
  *
@@ -405,7 +401,7 @@ export class WordForwardEntry {
405
401
  * Bytes per forward entry: one pointer-compressed slot for the shared token
406
402
  * string and one `Int32` count lane.
407
403
  */
408
- export const WORD_FORWARD_ENTRY_BYTES = 8;
404
+ const WORD_FORWARD_ENTRY_BYTES = 8;
409
405
  /**
410
406
  * The word index's dense file-id space: canonical path key → integer id →
411
407
  * display path.