@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
@@ -14,8 +14,10 @@ import { isFileKind } from "./file-kinds.js";
14
14
  import { getGlobalPiLensDir } from "./file-utils.js";
15
15
  import { findGlobalBinary } from "./package-manager.js";
16
16
  import { safeSpawnAsync } from "./safe-spawn.js";
17
+ import { probeToolAsync } from "./tool-probe.js";
17
18
  import { createSingleFlight } from "./single-flight.js";
18
19
  import { biomeConfigArgs } from "./tool-policy.js";
20
+ import { resolveToolCwd } from "./tool-cwd.js";
19
21
  import { resolveManagedToolClient, } from "./dispatch/runners/utils/runner-helpers.js";
20
22
  import { classifyProbeFailure, describeInstallAttempt, createAvailabilityLatch, logAvailabilityDecision, startHostStallSampler, } from "./dispatch/runners/utils/availability-policy.js";
21
23
  // --- Client ---
@@ -169,7 +171,14 @@ export class BiomeClient {
169
171
  let result;
170
172
  let hostStallMs;
171
173
  try {
172
- result = await this.spawnBiomeAsync(["--version"], PROBE_TIMEOUT_MS);
174
+ // The presence probe asks whether biome answers at all, so it goes
175
+ // through the probe seam (no cwd) rather than through
176
+ // `spawnBiomeAsync`, whose optional `cwd` exists for the analysis
177
+ // spawns that DO resolve a project config (#2894).
178
+ const { cmd, args: prefix } = await this.getBiomeBinary();
179
+ result = await probeToolAsync(cmd, [...prefix, "--version"], {
180
+ timeout: PROBE_TIMEOUT_MS,
181
+ });
173
182
  }
174
183
  finally {
175
184
  hostStallMs = sampler.stop();
@@ -314,7 +323,9 @@ export class BiomeClient {
314
323
  }
315
324
  try {
316
325
  const before = await fs.promises.readFile(absolutePath, "utf-8");
317
- const configCwd = cwd ?? path.dirname(absolutePath);
326
+ const configCwd = resolveToolCwd("runner", "biome", absolutePath, {
327
+ ...(cwd !== undefined && { cwd }),
328
+ });
318
329
  // Shared config-args seam (#1247): the lint runner consumes the same
319
330
  // builder, so `lint --write` can never drift to biome's default
320
331
  // config when a user config or the package fallback exists.
@@ -167,12 +167,6 @@ async function resolveForwardImportsMemoized(cwd, filePath, resolveForwardImport
167
167
  });
168
168
  return imports;
169
169
  }
170
- /** Test-only: clear the extractor and import-resolution memos. */
171
- export function _resetBlockerFreshnessForTests() {
172
- extractorCache.clear();
173
- importResolutionMemo.clear();
174
- importResolutionMemoTurnIndex = undefined;
175
- }
176
170
  /**
177
171
  * Production forward-import resolver. Parses `filePath` with its tree-sitter grammar
178
172
  * and resolves every extracted import source to in-project files. Degrades to an
@@ -114,7 +114,7 @@ const bootstrapFlight = createSingleFlight();
114
114
  * budget — it is the liveness bound AGENTS.md's both-bounds rule requires, so
115
115
  * a wedged module evaluation cannot park a `tool_call` handler forever.
116
116
  */
117
- export const BOOTSTRAP_LOAD_TIMEOUT_MS = 10_000;
117
+ const BOOTSTRAP_LOAD_TIMEOUT_MS = 10_000;
118
118
  /**
119
119
  * How many consecutive failed builds before the seam stops rebuilding.
120
120
  *
@@ -129,7 +129,7 @@ export const BOOTSTRAP_LOAD_TIMEOUT_MS = 10_000;
129
129
  * the demand fails OPEN immediately, and `session_start` re-arms the latch so
130
130
  * a repaired environment is never locked out for the life of the process.
131
131
  */
132
- export const BOOTSTRAP_FAILURE_STRIKE_LIMIT = 3;
132
+ const BOOTSTRAP_FAILURE_STRIKE_LIMIT = 3;
133
133
  /**
134
134
  * A stand-in for an analysis client whose module failed to load (an unresolved
135
135
  * runtime dependency under a package-manager layout the resolver can't traverse
@@ -268,7 +268,7 @@ async function buildBootstrapClients() {
268
268
  * {@link requestBootstrapClients} never says which on its own, so the reason
269
269
  * travels in the bounded record and the ledger entry instead.
270
270
  */
271
- export const BOOTSTRAP_UNAVAILABLE_REASONS = [
271
+ const BOOTSTRAP_UNAVAILABLE_REASONS = [
272
272
  "shutdown",
273
273
  "timeout",
274
274
  "aborted",
@@ -276,7 +276,7 @@ export const BOOTSTRAP_UNAVAILABLE_REASONS = [
276
276
  "latched",
277
277
  ];
278
278
  /** A demand that could not be served. Carries the discriminating reason. */
279
- export class BootstrapUnavailableError extends Error {
279
+ class BootstrapUnavailableError extends Error {
280
280
  unavailableReason;
281
281
  constructor(unavailableReason, message) {
282
282
  super(message);
@@ -194,7 +194,7 @@ export function acquireBoundedPidFileLock(lockPath, options) {
194
194
  options.logContention();
195
195
  return null;
196
196
  }
197
- throw new Error(options.timeoutMessage);
197
+ throw new Error(options.timeoutMessage, { cause: error });
198
198
  }
199
199
  Atomics.wait(waitArray, 0, 0, options.retryMs);
200
200
  }
@@ -50,6 +50,8 @@ import { logLatency } from "./latency-logger.js";
50
50
  * must not also be written by a raw `logLatency` call somewhere else.
51
51
  */
52
52
  export const BOUNDED_TELEMETRY_PHASES = [
53
+ /** #2890: a duplicate pi RPC session_start was admitted but suppressed. */
54
+ "session_start_duplicate_suppressed",
53
55
  /**
54
56
  * #2467: a demand for the analyzer bootstrap clients was not served and
55
57
  * the caller proceeded without them. Rising-edge per demand reason, with
@@ -171,11 +173,6 @@ export const BOUNDED_TELEMETRY_PHASES = [
171
173
  */
172
174
  "observed_handled_evicted",
173
175
  ];
174
- const REGISTERED_PHASES = new Set(BOUNDED_TELEMETRY_PHASES);
175
- /** Report whether a phase name is in the registry (used by the sweep). */
176
- export function isBoundedTelemetryPhase(phase) {
177
- return REGISTERED_PHASES.has(phase);
178
- }
179
176
  /**
180
177
  * Per-turn admission counters, keyed by turn and phase. Multiple turns remain
181
178
  * live because async work can finish T1 after T2 has already emitted. The map
@@ -22,8 +22,7 @@
22
22
  * This module gives bus events the same durable trace every other pi-lens
23
23
  * subsystem already has (latency.log, cascade.log, read-guard.log, ...) —
24
24
  * see clients/latency-logger.ts for the house pattern this mirrors exactly:
25
- * one shared `createNdjsonLogger` writer, `isTestMode()` no-op guard,
26
- * `getBusEventsLogPath()` for testability.
25
+ * one shared `createNdjsonLogger` writer, `isTestMode()` no-op guard.
27
26
  *
28
27
  * Logging volume: `emitted` and `emit_failed` are logged on every call —
29
28
  * they're the two outcomes an operator actually needs a per-event trace for.
@@ -104,10 +103,3 @@ export function emitBusEventRollupAtSessionEnd(cwd) {
104
103
  }
105
104
  resetBusEventRollupCounts();
106
105
  }
107
- export function getBusEventsLogPath() {
108
- return BUS_EVENTS_LOG_FILE;
109
- }
110
- /** Resolve once all enqueued bus-event writes are on disk (tests/shutdown). */
111
- export function flushBusEventsLog() {
112
- return writer.flush();
113
- }
@@ -91,7 +91,7 @@ const CHARS_PER_ESTIMATED_TOKEN = 4;
91
91
  */
92
92
  export const DEFAULT_PROVIDER_CACHE_TTL_MS = 60_000;
93
93
  const _providerCacheTtl = lazyEnvNumber("PI_LENS_PROVIDER_CACHE_TTL_MS", DEFAULT_PROVIDER_CACHE_TTL_MS);
94
- export const getProviderCacheTtlMs = _providerCacheTtl.get;
94
+ const getProviderCacheTtlMs = _providerCacheTtl.get;
95
95
  export const _resetProviderCacheTtlForTests = _providerCacheTtl._resetForTests;
96
96
  /**
97
97
  * A turn counts as "anomalously low" when it reads back less than half of what
@@ -176,9 +176,50 @@ function newAttributionState() {
176
176
  injectedCharsSinceLastUsage: 0,
177
177
  newTranscriptCharsSinceLastUsage: 0,
178
178
  attributionCharsCapped: false,
179
+ injectedBytes: emptyInjectedBytes(),
180
+ injectedFindingsRepeated: 0,
181
+ findingIdentities: new Set(),
182
+ findingIdentityCapRecorded: false,
183
+ turnEndAdvisoryBytes: 0,
184
+ toolResultBytes: 0,
185
+ toolResultsTruncated: 0,
179
186
  summary: newCacheUsageSummary(),
180
187
  };
181
188
  }
189
+ const MAX_FINDING_IDENTITIES = 2_000;
190
+ function emptyInjectedBytes() {
191
+ return {
192
+ sessionGuidance: 0,
193
+ turnFindings: 0,
194
+ testFindings: 0,
195
+ agentNudge: 0,
196
+ turnEndAdvisory: 0,
197
+ other: 0,
198
+ };
199
+ }
200
+ function sourceKey(source) {
201
+ return {
202
+ "session-guidance": "sessionGuidance",
203
+ "turn-findings": "turnFindings",
204
+ "test-findings": "testFindings",
205
+ "agent-nudge": "agentNudge",
206
+ }[source];
207
+ }
208
+ /** Best-effort, language-neutral identity extraction from rendered findings. */
209
+ function findingIdentities(text) {
210
+ const out = [];
211
+ for (const line of text.split(/\r?\n/)) {
212
+ const location = line.match(/(?:^|\s)([^\s:]+):(\d+)(?::\d+)?/);
213
+ if (!location)
214
+ continue;
215
+ const rule = line.match(/(?:rule|code)\s*[:=]\s*([\w./-]+)/i)?.[1] ??
216
+ line.match(/\(([\w./-]+)\)\s*$/)?.[1] ??
217
+ line.match(/:\d+(?::\d+)?\s+([\w./-]+)/)?.[1];
218
+ if (rule)
219
+ out.push(`${location[1]}:${location[2]}:${rule}`);
220
+ }
221
+ return out;
222
+ }
182
223
  /**
183
224
  * Fetch (creating if absent) one session's attribution state, refreshing LRU
184
225
  * recency and evicting the oldest entries past the cap — same bounding as
@@ -688,10 +729,37 @@ export function observeCacheContext(args) {
688
729
  countsCapped: sliceSize.capped,
689
730
  };
690
731
  });
732
+ const state = attributionFor(attributionKey(args.sessionId, args.sessionRole));
733
+ for (const slice of injectionSlices) {
734
+ const key = sourceKey(slice.source);
735
+ const bytes = measureInjectedMessages(slice.messages).bytes;
736
+ state.injectedBytes[key] += bytes;
737
+ for (const message of slice.messages) {
738
+ for (const identity of findingIdentities(typeof message.content === "string" ? message.content : "")) {
739
+ if (state.findingIdentities.has(identity)) {
740
+ state.injectedFindingsRepeated += 1;
741
+ continue;
742
+ }
743
+ if (state.findingIdentities.size >= MAX_FINDING_IDENTITIES) {
744
+ if (!state.findingIdentityCapRecorded) {
745
+ state.findingIdentityCapRecorded = true;
746
+ logLatency({
747
+ type: "phase",
748
+ filePath: "<pi-lens>",
749
+ phase: "injected_finding_identity_cap",
750
+ durationMs: 0,
751
+ metadata: { cap: MAX_FINDING_IDENTITIES },
752
+ });
753
+ }
754
+ continue;
755
+ }
756
+ state.findingIdentities.add(identity);
757
+ }
758
+ }
759
+ }
691
760
  const messageCountCapped = existingMessages.length > MAX_REPORTED_MESSAGES ||
692
761
  resultMessages.length > MAX_REPORTED_MESSAGES;
693
762
  recordContextAttribution(attributionKey(args.sessionId, args.sessionRole), existingMessages, sizes);
694
- const state = attributionFor(attributionKey(args.sessionId, args.sessionRole));
695
763
  state.sequenceHashTruncatedSinceLastUsage ||=
696
764
  beforeSequence.truncated ||
697
765
  beforeSequence.contentTruncated ||
@@ -721,6 +789,10 @@ export function observeCacheContext(args) {
721
789
  injectedMessageCountCapped: injectedMessages.length > MAX_REPORTED_MESSAGES,
722
790
  injectedChars: sizes.chars,
723
791
  injectedBytes: sizes.bytes,
792
+ injectedBytesBySource: Object.fromEntries(sourceBreakdown.map((entry) => [
793
+ sourceKey(entry.source),
794
+ entry.bytes,
795
+ ])),
724
796
  injectedEstimatedTokens: estimateTokens(sizes.chars),
725
797
  injectedTokenBasis: "chars-per-token-4-estimate-not-provider-measured",
726
798
  injectedCountsCapped: sizes.capped,
@@ -881,6 +953,13 @@ export function logCacheUsage(message, dbg, context) {
881
953
  const injectedCharsSinceLastTurn = state.injectedCharsSinceLastUsage;
882
954
  const newTranscriptCharsSinceLastTurn = state.newTranscriptCharsSinceLastUsage;
883
955
  const attributionCharsCapped = state.attributionCharsCapped;
956
+ const injectedBytes = {
957
+ ...state.injectedBytes,
958
+ turnEndAdvisory: state.turnEndAdvisoryBytes + state.injectedBytes.turnEndAdvisory,
959
+ };
960
+ const injectedFindingsRepeated = state.injectedFindingsRepeated;
961
+ const toolResultBytes = state.toolResultBytes;
962
+ const toolResultsTruncated = state.toolResultsTruncated;
884
963
  // This record is the turn boundary: reset the per-turn accumulators and
885
964
  // re-arm the prefix-break flag so the next verdict describes the NEXT gap.
886
965
  state.lastUsageAtMs = nowMs;
@@ -898,6 +977,11 @@ export function logCacheUsage(message, dbg, context) {
898
977
  state.injectedCharsSinceLastUsage = 0;
899
978
  state.newTranscriptCharsSinceLastUsage = 0;
900
979
  state.attributionCharsCapped = false;
980
+ state.injectedBytes = emptyInjectedBytes();
981
+ state.injectedFindingsRepeated = 0;
982
+ state.turnEndAdvisoryBytes = 0;
983
+ state.toolResultBytes = 0;
984
+ state.toolResultsTruncated = 0;
901
985
  // Clear the request stamp too: the next turn measures from ITS request, and
902
986
  // a turn whose `context` call pi-lens never saw must fall back rather than
903
987
  // reuse this one.
@@ -939,6 +1023,13 @@ export function logCacheUsage(message, dbg, context) {
939
1023
  injectedCharsSinceLastTurn,
940
1024
  newTranscriptCharsSinceLastTurn,
941
1025
  attributionCharsCapped,
1026
+ injectedBytes,
1027
+ injectedFindingsRepeated,
1028
+ // Delivered tool-result aggregation over the turn (#2800 item 7):
1029
+ // the sum of each delivered footer's bytes= figure and the count
1030
+ // of results whose bound fired.
1031
+ toolResultBytes,
1032
+ toolResultsTruncated,
942
1033
  ...(context
943
1034
  ? {
944
1035
  // MessageEndEvent has no request/context id in the host API. These
@@ -1126,6 +1217,29 @@ export function clearCachePrefixSession(sessionId, sessionRole) {
1126
1217
  // a stale gap baseline and a stale prefix-break flag.
1127
1218
  attributionBySession.delete(key);
1128
1219
  }
1220
+ /** Record the exact quiet-window summary content handed to pi.sendMessage. */
1221
+ export function recordTurnEndAdvisoryBytes(sessionId, bytes, sessionRole = "primary") {
1222
+ const state = attributionFor(attributionKey(sessionId, sessionRole));
1223
+ state.turnEndAdvisoryBytes = Math.min(MAX_INJECTED_BYTES, state.turnEndAdvisoryBytes + Math.max(0, bytes));
1224
+ }
1225
+ /**
1226
+ * Fold one delivered tool result into the per-turn aggregation the
1227
+ * `cache_usage` row reports as `toolResultBytes` / `toolResultsTruncated`
1228
+ * (#2800 item 7). `bytes` is the delivered payload's UTF-8 byte count as
1229
+ * stamped in the result's own footer, and `truncated` is the footer's
1230
+ * truncated flag. Called from each host adapter's delivery seam; the row is
1231
+ * emitted by `logCacheUsage`, which resets both figures at the turn boundary.
1232
+ * The byte sum saturates at the attribution bound so the row stays bounded.
1233
+ */
1234
+ export function recordToolResultDelivery(args) {
1235
+ const state = attributionFor(attributionKey(args.sessionId, args.sessionRole));
1236
+ const bytes = Number.isFinite(args.bytes)
1237
+ ? Math.max(0, Math.floor(args.bytes))
1238
+ : 0;
1239
+ state.toolResultBytes = Math.min(MAX_ATTRIBUTION_BYTES, state.toolResultBytes + bytes);
1240
+ if (args.truncated === true)
1241
+ state.toolResultsTruncated += 1;
1242
+ }
1129
1243
  /**
1130
1244
  * Emit one bounded session summary and retire its attribution state. The
1131
1245
  * summary contains fixed-key counters only; it never serializes transcript or
@@ -1165,10 +1279,12 @@ export function resetCachePrefixObservation() {
1165
1279
  prefixHashBySession.clear();
1166
1280
  attributionBySession.clear();
1167
1281
  }
1168
- /** #2442 test-only membership reads, bypassing emitCacheUsageSummaryAtSessionEnd's
1169
- * usageRecords>0 gate and log side effects. */
1170
- export function _attributionKeyForTests(sessionId, sessionRole) {
1171
- return attributionKey(sessionId, sessionRole);
1282
+ export function resetCacheFindingIdentitiesSession(sessionId, sessionRole) {
1283
+ const state = attributionBySession.get(attributionKey(sessionId, sessionRole));
1284
+ if (!state)
1285
+ return;
1286
+ state.findingIdentities.clear();
1287
+ state.findingIdentityCapRecorded = false;
1172
1288
  }
1173
1289
  export function _attributionBySessionHasForTests(key) {
1174
1290
  return attributionBySession.has(key);
@@ -177,7 +177,7 @@ export function parseTomlStringArray(content, key) {
177
177
  * true`) never matches either — the literal key is immediately followed by
178
178
  * `=`, not `.`.
179
179
  */
180
- export function parseTomlScalarString(content, key) {
180
+ function parseTomlScalarString(content, key) {
181
181
  if (content === undefined)
182
182
  return undefined;
183
183
  const match = content.match(new RegExp(`^[ \\t]*${key}[ \\t]*=[ \\t]*(?:"([^"]*)"|'([^']*)')`, "m"));
@@ -292,7 +292,7 @@ export function readCargoDependencyNames(content) {
292
292
  * (`edition.workspace = true`) or the inline-table form
293
293
  * (`edition = { workspace = true }`).
294
294
  */
295
- export function isTomlKeyWorkspaceInherited(content, key) {
295
+ function isTomlKeyWorkspaceInherited(content, key) {
296
296
  if (content === undefined)
297
297
  return false;
298
298
  const dotted = new RegExp(`^[ \\t]*${key}\\.workspace[ \\t]*=[ \\t]*true`, "m");
@@ -29,10 +29,3 @@ export function logCascade(entry) {
29
29
  filePath: normalizeLoggedPath(entry.filePath),
30
30
  });
31
31
  }
32
- export function getCascadeLogPath() {
33
- return CASCADE_LOG_FILE;
34
- }
35
- /** Resolve once all enqueued cascade writes are on disk (tests/shutdown). */
36
- export function flushCascadeLog() {
37
- return writer.flush();
38
- }
@@ -2,7 +2,7 @@
2
2
  * Shared plumbing for best-effort, fire-and-forget child-process spawns
3
3
  * (shape 4 of the recurring-defect catalog in AGENTS.md: "a timer / promise /
4
4
  * worker / child that outlives its one-shot settle"). Extracted from the
5
- * orphan reaper's `unrefReaperChild`/`spawnCollectStdout` (#1153/#1160) into a
5
+ * orphan reaper's `unrefReaperChild` (#1153/#1160) into a
6
6
  * shared, dependency-free module so every one-shot
7
7
  * `spawn(..., { stdio: ["ignore","pipe",...] })` call site in the codebase —
8
8
  * the reaper's enumeration/kill spawns AND the resource sampler's Windows
@@ -46,24 +46,6 @@ export function unrefChildAndPipes(child) {
46
46
  }
47
47
  }
48
48
  /**
49
- * Spawn a best-effort, fire-and-forget child, accumulate its full stdout, and
50
- * resolve with the collected text (empty string on a synchronous spawn
51
- * failure or an `error` event). Consolidates the spawn → unref →
52
- * pipe-stdout → `close` plumbing shared by every one-shot OS-process-table
53
- * query in the codebase — each caller supplies only its command/args/options
54
- * and does its own output parse. The child + its stdio pipes are `unref`'d
55
- * here (via `unrefChildAndPipes`) so a settled one-shot `pi --print` process
56
- * can exit without waiting, and both the unref and the collect plumbing live
57
- * in exactly ONE place rather than being re-derived at each spawn site.
58
- * Never rejects — any failure resolves to `""`, which every caller's parse
59
- * turns into an empty/absent result (the best-effort contract every caller
60
- * here already has).
61
- */
62
- export function spawnCollectStdout(command, args, options) {
63
- return spawnCollectStdoutResult(command, args, options).then((result) => result.stdout);
64
- }
65
- /**
66
- * `spawnCollectStdout` plus the reason the output is what it is. Same spawn,
67
49
  * unref, collect, settle plumbing; the only additions are an optional hard
68
50
  * timeout and a status discriminator. Never rejects.
69
51
  */
@@ -13,6 +13,7 @@
13
13
  import { createSubsystemLogger } from "./extension-log.js";
14
14
  import * as fs from "node:fs";
15
15
  import * as path from "node:path";
16
+ import { calcCyclomaticComplexity } from "./dispatch/facts/function-facts.js";
16
17
  import { firstChildOfType, withTreeSitterRoot, isComplexityLanguageId, isComplexitySupportedFile, resolveTreeSitterLanguage, walk, } from "./tree-sitter-shared.js";
17
18
  // JS/TS/JSX share one grammar shape.
18
19
  const JSTS = {
@@ -190,6 +191,9 @@ function isLogicalOp(node, nodes) {
190
191
  }
191
192
  /** Cyclomatic contribution of a subtree: decision points + logical operators. */
192
193
  function subtreeCyclomatic(root, nodes) {
194
+ // Dispatch uses 1-based McCabe; this client exposes 0-based contributions (#2697).
195
+ if (nodes === JSTS)
196
+ return calcCyclomaticComplexity(root) - 1;
193
197
  let cc = 0;
194
198
  walk(root, (n) => {
195
199
  if (nodes.decision.has(n.type))
@@ -438,6 +442,7 @@ export class ComplexityClient {
438
442
  aiCommentPatterns: countAICommentPatterns(content),
439
443
  singleUseFunctions: countSingleUseFunctions(functions),
440
444
  tryCatchCount: countTryCatch(root, nodes),
445
+ functions,
441
446
  };
442
447
  }
443
448
  aggregateFunctionStats(functions) {
@@ -31,17 +31,20 @@
31
31
  * (`loadPiLensProjectConfig`) are now projections of one resolution. #2416
32
32
  * brings the `lsp.servers.<id>` shape the schema currently only reserves.
33
33
  */
34
- export { additionalPropertyPolicy, DEFAULT_MERGE_STRATEGY, DENY_KEY, DENY_POLICIES, denyPolicyOf, isDenyPolicy, isConfigObject, isKnownSchemaType, isMergeStrategy, isPlainObject, isSchemaNode, itemsSchema, keyedField, MERGE_STRATEGY_KEY, mergeStrategyOf, propertySchema, SCHEMA_TYPES, schemaType, STABILITY_TIER_KEY, } from "./schema.js";
35
- export { compareKeys, isOperatorTier, isRepoTier, provenanceFor, provenanceView, SOURCE_TIERS, TIER_CLASS, TIER_PRECEDENCE, tierPrecedence, } from "./provenance.js";
36
- export { isUnsafeConfigKey, MAX_CONFIG_DEPTH, safeAssign, UNSAFE_CONFIG_KEYS, UNSAFE_KEY_REASON, } from "./safe-object.js";
37
- export { denyProvenance, resolveArrayDeny, resolveBooleanDeny, } from "./deny.js";
38
- export { validate, } from "./normalize.js";
39
- export { boundedKeyLabel, jsonTypeName, MAX_MIGRATION_RECORDS, MAX_RECORD_KEY_LENGTH, MigrationRecordCollector, migrationSubject, } from "./records.js";
40
- export { buildProcessSpec, MAX_ARGV_BYTES, MAX_ARGV_ENTRIES, MAX_ENV_BYTES, MAX_ENV_ENTRIES, MAX_TIMEOUT_MS, redactProcessSpec, toSpawnArgs, } from "./process-spec.js";
34
+ export { SOURCE_TIERS } from "./provenance.js";
35
+ // `merge()` itself is NOT re-exported. Its input type only PROMISES a
36
+ // post-`validate()` value; nothing in the language enforces that a caller
37
+ // who imports it directly honors the promise, and `merge()`'s own bounds are
38
+ // a narrow backstop, not a second validator (see `merge.ts`'s module doc).
39
+ // `resolveConfig` (re-exported at the bottom of this file, from `resolve.js`)
40
+ // is the one supported way in: it always validates
41
+ // every source before merging. `merge()` stays exported from `merge.ts`
42
+ // itself — marked `@internal` there — for this module's own use and for
43
+ // tests that probe it directly.
41
44
  // `resolveConfig` and its types live in `./resolve.js` (#2426) so a caller can
42
45
  // import the front door without also importing this barrel's width — in
43
46
  // particular `process-spec.js` -> `project-trust.js`, which closed three
44
47
  // import cycles once the config loaders (all downstream of `file-utils.ts`)
45
48
  // started resolving through the core. The public surface is unchanged: this is
46
49
  // still where the supported entry point is exported from.
47
- export { resolveConfig, } from "./resolve.js";
50
+ export { resolveConfig } from "./resolve.js";
@@ -36,7 +36,7 @@ import { compareKeys, isRepoTier, } from "./provenance.js";
36
36
  /** Longest argv a spec may carry. A command line, not a file list. */
37
37
  export const MAX_ARGV_ENTRIES = 128;
38
38
  /** Total argv bytes a spec may carry. */
39
- export const MAX_ARGV_BYTES = 32 * 1024;
39
+ const MAX_ARGV_BYTES = 32 * 1024;
40
40
  /** Most env entries a spec may carry. */
41
41
  export const MAX_ENV_ENTRIES = 64;
42
42
  /** Total env bytes (names plus values) a spec may carry. */
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * Two orderings live here, and they are NOT the same ordering:
13
13
  *
14
- * - `TIER_PRECEDENCE` decides who wins a plain value. Later beats earlier, so a
14
+ * - `SOURCE_TIERS` decides who wins a plain value. Later beats earlier, so a
15
15
  * CLI flag beats a project file beats a global file beats a built-in default.
16
16
  * - `TIER_CLASS` decides who may LIFT a deny. `deny.ts` builds monotonic deny
17
17
  * precedence on this split, and nothing else re-derives it.
@@ -34,13 +34,6 @@ export const SOURCE_TIERS = [
34
34
  "cli",
35
35
  "host",
36
36
  ];
37
- /**
38
- * Value precedence, lowest first. A later tier's value replaces an earlier
39
- * tier's value for the same leaf. `merge()` sorts its sources by this order
40
- * rather than trusting caller order, so a caller that assembles sources in a
41
- * different order cannot silently invert precedence.
42
- */
43
- export const TIER_PRECEDENCE = SOURCE_TIERS;
44
37
  /**
45
38
  * Who each tier speaks for. THREE classes, not two (#2440 review finding F3).
46
39
  *
@@ -79,7 +72,7 @@ export const TIER_CLASS = {
79
72
  };
80
73
  /** Numeric precedence of a tier. Higher wins. */
81
74
  export function tierPrecedence(tier) {
82
- return TIER_PRECEDENCE.indexOf(tier);
75
+ return SOURCE_TIERS.indexOf(tier);
83
76
  }
84
77
  /** True for tiers whose content arrives with the checkout. */
85
78
  export function isRepoTier(tier) {
@@ -101,7 +101,7 @@ export function jsonTypeName(value) {
101
101
  * A list with no records cannot overflow, so this is the floor under an
102
102
  * anchorless producer rather than a case production reaches.
103
103
  */
104
- export const UNANCHORED_RECORD_LABEL = "(config resolution)";
104
+ const UNANCHORED_RECORD_LABEL = "(config resolution)";
105
105
  /**
106
106
  * A bounded collector for one resolution.
107
107
  *
@@ -21,8 +21,6 @@
21
21
  *
22
22
  * Pure accessors only. Nothing here reads a file, and nothing holds state.
23
23
  */
24
- import { STABILITY_TIER_KEY } from "../config-diagnostic-codes.js";
25
- export { STABILITY_TIER_KEY };
26
24
  /** Narrows to the recursive domain type, not to `unknown`. */
27
25
  export function isConfigObject(value) {
28
26
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -30,7 +28,7 @@ export function isConfigObject(value) {
30
28
  // --- x-merge-strategy ---
31
29
  /** The annotation key selecting how an array node combines across tiers. */
32
30
  export const MERGE_STRATEGY_KEY = "x-merge-strategy";
33
- export const DEFAULT_MERGE_STRATEGY = "replace";
31
+ const DEFAULT_MERGE_STRATEGY = "replace";
34
32
  const KEYED_PREFIX = "keyed:";
35
33
  export function isMergeStrategy(value) {
36
34
  if (typeof value !== "string")
@@ -71,7 +69,7 @@ export const DENY_KEY = "x-deny";
71
69
  * the field someone spelled differently, and silently claims one that merely
72
70
  * looks the part. A schema says what it means.
73
71
  */
74
- export const DENY_POLICIES = ["boolean-false", "array-union"];
72
+ const DENY_POLICIES = ["boolean-false", "array-union"];
75
73
  export function isDenyPolicy(value) {
76
74
  return (typeof value === "string" &&
77
75
  DENY_POLICIES.includes(value));
@@ -104,7 +102,7 @@ export function schemaType(node) {
104
102
  * field while the merger replaced it whole, so the same schema typo produced
105
103
  * two different merge semantics.
106
104
  */
107
- export const SCHEMA_TYPES = [
105
+ const SCHEMA_TYPES = [
108
106
  "object",
109
107
  "array",
110
108
  "string",
@@ -34,7 +34,7 @@ export const STABILITY_TIER_KEY = "x-stability";
34
34
  * The closed tier vocabulary. `experimental` fields may change or be removed
35
35
  * in a minor; `stable` fields are covered by the compatibility guarantee.
36
36
  */
37
- export const STABILITY_TIERS = ["experimental", "stable"];
37
+ const STABILITY_TIERS = ["experimental", "stable"];
38
38
  export function isStabilityTier(value) {
39
39
  return (typeof value === "string" &&
40
40
  STABILITY_TIERS.includes(value));
@@ -171,6 +171,8 @@ export const CONFIG_DIAGNOSTIC_CODES = {
171
171
  * suppressed" about a configuration that applied nothing at all.
172
172
  */
173
173
  PILENS_CFG_0008: "config resolution failed; whole configuration ignored",
174
+ /** A tool key is unknown or names a required, non-disableable tool. */
175
+ PILENS_CFG_0009: "unknown or non-disableable tool config key ignored",
174
176
  };
175
177
  /** The shape every code in the namespace must match. */
176
178
  export const CONFIG_DIAGNOSTIC_CODE_PATTERN = /^PILENS_CFG_\d{4}$/;
@@ -12,7 +12,7 @@
12
12
  *
13
13
  * builtin -> global -> project root -> nested-project -> env -> cli -> host
14
14
  *
15
- * It is `config-core`'s own `TIER_PRECEDENCE`, not a second ordering: this
15
+ * It is `config-core`'s own `SOURCE_TIERS`, not a second ordering: this
16
16
  * module places files into tiers and the core sorts them. `docs/configuration.md`
17
17
  * documents the same order once, and `tests/clients/config-resolve.test.ts`
18
18
  * walks it.
@@ -151,7 +151,7 @@ function collectDocuments(dir, locations, tier, onReadError) {
151
151
  * is `nested-project`, which is what makes "nearest wins, per field" fall out
152
152
  * of the core's tier precedence instead of being re-implemented here.
153
153
  */
154
- export function collectPiLensConfigDocuments(options) {
154
+ function collectPiLensConfigDocuments(options) {
155
155
  const documents = [];
156
156
  const { globalDir, onReadError } = options;
157
157
  const globalConfigPath = canonicalGlobalFile(options);
@@ -408,7 +408,7 @@ function assignRaw(target, key, value) {
408
408
  * half-migrated the file it was written in is the defect this whole change
409
409
  * exists to remove.
410
410
  */
411
- export function configSources(documents) {
411
+ function configSources(documents) {
412
412
  const sources = [];
413
413
  for (const document of documents) {
414
414
  const value = document.value;
@@ -576,7 +576,7 @@ function record(input) {
576
576
  * duplicate notice about a config that failed to load is noise, while silence
577
577
  * about it is the failure mode this module exists to prevent.
578
578
  */
579
- export function configRecordOwner(record) {
579
+ function configRecordOwner(record) {
580
580
  const key = record.canonicalKey ?? record.key;
581
581
  if (key.length === 0)
582
582
  return undefined;
@@ -740,8 +740,8 @@ export function reportPiLensConfigRecords(records) {
740
740
  */
741
741
  export function ignoredRecordCollector(configPath, tier) {
742
742
  const noted = [];
743
- const note = (reason) => {
744
- noted.push({
743
+ const note = (reason, code = "PILENS_CFG_0001") => {
744
+ let notedRecord = {
745
745
  code: "PILENS_CFG_0001",
746
746
  file: configPath,
747
747
  key: "",
@@ -752,7 +752,10 @@ export function ignoredRecordCollector(configPath, tier) {
752
752
  sourceText: reason.sourceText,
753
753
  }),
754
754
  tier,
755
- });
755
+ };
756
+ if (code !== "PILENS_CFG_0001")
757
+ notedRecord.code = code;
758
+ noted.push(notedRecord);
756
759
  };
757
760
  return {
758
761
  note,