@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
@@ -16,6 +16,266 @@ All notable changes to pi-lens will be documented in this file.
16
16
 
17
17
  ### Security
18
18
 
19
+ ## [4.1.6] - 2026-09-10
20
+
21
+ ### Added
22
+
23
+ - **Add an advisory incremental Stryker lane for changed scripts (refs #1844)** — `npm run mutation:diff` and the pull-request mutation lane use Stryker's command runner over changed `scripts/**/*.mjs` files and their related tests, report uncovered files, retain incremental results under ignored paths, and publish the mutation report for review.
24
+
25
+ - **CI failures now distinguish infrastructure outages from real test failures and arm one rerun** (refs #2103, #2784) — the classifier recognizes exit-137 kills, CodeQL/SARIF outages, codeload throttling, and npm CI timeouts, while preserving assertion and TypeScript failures as real. It updates one PR comment, applies the manifest-managed CI label, and lets the verdict report an armed infrastructure rerun as pending; **Terminal CI rerun finalization now covers master push and repository-dispatch runs** (refs #2103, #2784) — the workflow finalizes second-attempt classifications for every supported event and records a bounded step summary when no associated PR exists.
26
+
27
+ - Add an AST governance sweep for `vi.mock` factories that omit production exports. Refs #2281.
28
+
29
+ - **Add an advisory Windows Vitest lane (refs #2536)** — Run the path-shape and configuration test subset on `windows-latest`.
30
+
31
+ - **Add the tool-smoke install lane to the release-QA baseline (refs #2663, #2784)** — a `tool-smoke-install` row installs every npm/pip installer-registry entry through the real smoke harness, so a dead registry entry is a red do-not-ship row, a registry-unreachable lane is INCONCLUSIVE, and neither reads as green.
32
+
33
+ - **Add a TypeScript strictness spike with scratch configs, per-directory counts, a two-sided ratchet, and an advisory report lane (refs #2697)** — the migration remains staged by directory instead of enabling either flag globally.
34
+
35
+ - **Add a cwd-sensitive yamllint tool-smoke row (refs #2697, refs #2691)** — the real runner proves yamllint uses the dispatch cwd instead of the host process cwd for config discovery.
36
+
37
+ - **Add tool-smoke cwd rows for nested discovery (refs #2777)** — the runner, formatter, and LSP smoke shapes assert their resolved cwd and reason log, while missing binaries remain visible skips.
38
+
39
+ - **Add one command for every mechanical PR gate (refs #2790, #2784)** — `npm run preflight` runs the ordered local build, lint, formatting, changelog, lockfile, governance, and PR-document checks.
40
+
41
+ - Stamp one session-scoped turn identifier on observability sink rows (refs #2815).
42
+
43
+ - **Add a real pi RPC harness for load, tool-set restore, and read-guard scenarios (refs #2825)** — the serialized `real-harness` lane drives the built extension with a deterministic scripted provider and hermetic sinks.
44
+
45
+ - **Make Knip a hard local preflight gate and cover every admitted test lane** (refs #2837) — `npm run preflight` runs Knip, while the Knip entry census covers real-harness, Windows, wall-clock, and workflow-invoked script populations with documented same-file export admissions.
46
+
47
+ - **Gate nightly LSP smoke rows on primary diagnostics** (refs #2780) — the tool-smoke workflow now drives opted-in seeded fixtures through the real `lsp_diagnostics` handler, reports unavailable toolchains correctly, and tracks gate failures.
48
+
49
+ - **`complexity (advisory)` CI job dogfoods pi-lens's own complexity client over `clients/`, `tools/` and `mcp/` (refs #2697)** — `npm run complexity` writes a Markdown report (top functions by cyclomatic/cognitive complexity, files over 1,000 lines, split candidates at the dispatch threshold of 15) to the step summary and an artifact; `ComplexityClient` exposes the per-function metrics it already computes, uses the dispatch cyclomatic metric for JS/TS, and fails when analysis produces no files or throws.
50
+
51
+ - **One session-end line names the tools never activated or called (refs #2800)** — a bounded debug record per session on both surfaces, keyed by the tool registry, so roster decisions can read which tools carried no weight in a session; the monitor readout gains the line. MCP owns the row for the connection and emits it at `pilens_session_end` or transport close, whichever comes first; repeated `pilens_session_start` calls refresh without clearing observations. Pi records the row for fresh sessions only: a reload, resume, or fork start suppresses the session's row entirely (conversation-owned accounting tracked in #2858).
52
+
53
+ - **Per-call tool-result observability**: the `usage tokens=<n> elapsed-ms=<n>` contract footer gains `bytes=<delivered payload bytes> truncated=<true|false>` on both host surfaces, the payload byte bound runs before the footer is stamped with the footer's own maximum size reserved so the delivered text (footer included) never exceeds 40 KiB for the single-text-block results production emits (the bound is per text block, inherited from #2852), and the per-turn `cache_usage` latency row aggregates `toolResultBytes` and `toolResultsTruncated` over the turn's tool calls (refs #2800)
54
+
55
+ - **Guard workflow shell portability (refs #2625, #2784)** — Reject bash 4-only constructs in steps that can run on macOS runners, including matrix and reusable-workflow input expansion and executable command substitutions nested inside double quotes.
56
+
57
+ - **Record injected bytes and repeated findings per turn (refs #2838)** — the existing cache attribution row records UTF-8 bytes by model-facing injection source and counts repeated finding identities with bounded per-session state.
58
+
59
+ - **Check lockfile completeness under CI's npm (refs #2803, #2784)** — preflight and `check:lockfile --complete` reject optional dependency drift before merge; **Pin the clean production install to npm@11.18.0 (refs #2803, #2784)** — use
60
+ the repository's exact npm pin so a different npm version cannot rewrite the
61
+ committed lockfile.
62
+
63
+ - **`tools.<name>.enabled` proven through a real pi RPC session (refs #2800)** — real-harness scenarios show a disabled tool absent from the tool list pi reports, the loader and MCP lifecycle tools refusing to be disabled with the config diagnostic, and `--no-tool` winning over config; the roster bytes pi receives per tool are measured on the wire.
64
+
65
+ ### Changed
66
+
67
+ - Keep admission registries sorted and enforce declaration order with one shared sweep helper (refs #2671, #2784).
68
+
69
+ - **Skip the PR title, body and close-keyword checks for dependabot PRs (refs #2714)** — the `pr-title-lint` and `pr-body-lint` jobs in lint.yml and the lint job in close-keywords.yml now carry a `dependabot[bot]` skip condition. A bump can never carry an issue ref or the PR-body template, so these checks no longer go red on every bump and no merge-train pass has to ignore them by hand. Lint, Unit tests, the install tests and the advisory lanes still run on bumps.
70
+
71
+ - **Trim the three largest tool parameter schemas and pin both host rosters (refs #2800).**
72
+
73
+ - **Adaptively demote budget-hitting auxiliaries, re-promote fast late answers, and deliver findings through the deferred runner path (refs #2810).**
74
+
75
+ - **Tool probes and hand-derived package roots resolve through shared seams (refs #2894)** — a `probeToolAsync` seam owns the "a presence/version probe never gets a `cwd`" contract for 23 spawn sites that each decided it locally, `rust-clippy` takes its package root from `resolveRunnerCwd` (with `Cargo.toml` registered as its runner marker) instead of an uncapped `findNearestContaining` walk, and `ruff-client`'s autofix resolves its config root through `resolveToolCwd` so a file in a nested package gets that package's `pyproject.toml` rather than the workspace one.
76
+
77
+ - **Preserve per-row auxiliary publication evidence semantics (refs #2892)** — demoted waits accept an advanced per-path stamp alongside a content binding, while sibling and aggregate rows remain binding-only.
78
+
79
+ - **`ast_grep_dump` folded into `ast_grep_search` (refs #2800)** — AST inspection is `ast_grep_search` with `dump=true`, with the same result contract; the retired name answers for one session through a bounded compatibility response on both surfaces (one `ast-grep-dump-compatibility` record per session) and is absent from the tool registry and every tool listing.
80
+
81
+ - **Audit and update user-facing and contributor docs against master for the v4.1.6 cut.** `docs/agent-tools.md` now describes `lens_diagnostics`' `source`/`scope`/`severity`-threshold contract, the one-release MCP compatibility redirect, the `lsp_navigation` 19-operation roster with a link to its SKILL.md parameter reference, and the result-delivery contract (`finalizeToolResult`, 40 KiB bound, `bytes=`/`truncated=` usage footer). `docs/settings.md`, `docs/globalconfig.md`, and `docs/usage.md` now agree on all registry flags, including the seven analyzer toggles. `docs/features.md`'s formatter list is corrected to the current 34-entry autoformat registry (drops `fish_indent`, which is a check-only dispatch runner rather than an entry in that registry, and adds `ktfmt` and `terragrunt-hcl`). `docs/environment-variables.md` drops `PI_LENS_AUTO_INSTALL`, which no longer exists in code. (refs #2800)
82
+
83
+ - **Fold `lsp_diagnostics` into `lens_diagnostics` with source and scope modifiers; retain the MCP compatibility shim for one release.** (refs #2800)
84
+ Deprecated: `pilens_lsp_diagnostics` remains accepted by MCP for one release and maps to `source=lsp`.
85
+
86
+ - **Make the oxfmt format check a CI gate (refs #2790, #2784)** — the workflow job now uses the gating name `oxfmt format check`, matching the hard `fmt:check` preflight gate and keeping formatting drift out of master.
87
+
88
+ - **Fold `allowStamp` out of auxiliary coverage (closes #2914)** — The stamp-union predicate keeps one behaviour; the sibling and aggregate rows call the binding predicate directly.
89
+
90
+ - **One result renderer for pi tool results and the MCP mirror (refs #2800)** — result status, diagnostic severity and usage lines come from one shared renderer on both surfaces, pinned by a both-surfaces governance test that drives real inputs for every paired registry tool and explicitly covers pi-only rows.
91
+ The renderer runs after each tool has set `isError`, then applies stale warnings, and bounds the final MCP payload to 40 KiB.
92
+
93
+ - **Dropped a no-op string replacement in the tsgolint preflight test (refs #2709)** — CodeQL alert 49 (`js/identity-replacement`): the helper replaced `/package.json` with itself; the key lookup now only strips the `/tmp/` prefix.
94
+
95
+ - **Pin the tool-roster description budget and trim paid metadata (refs #2800)** — pi and MCP tool registration now use concise contract-plus-example descriptions, with a two-sided baseline covering descriptions and schemas on both surfaces; the model-facing contract sentences (read coverage, diagnostic suppression ordering, configuration redaction, cold-cache guidance) stay in the paid description and are pinned per surface so a later trim cannot drop them.
96
+
97
+ - **Add per-tool enablement (refs #2800)** — `tools.<name>.enabled` and repeatable `--no-tool=<name>` prevent disabled lens tools from registering on the pi and MCP surfaces. One registry now covers every model-facing tool, keeps the activation and MCP lifecycle tools non-disableable, and emits stable diagnostic code `PILENS_CFG_0009` for unknown or non-disableable keys. The resolved state appears in `effective_config`.
98
+
99
+ - **`sql-injection` (TypeScript tree-sitter rule) is a warning, not a blocking error.** The query keys on the callee name only (`query|execute|exec|run`), so any template literal passed to a same-named non-SQL function fired a blocking finding; it stays as a warning until the rule gains a receiver/type signal.
100
+
101
+ ### Fixed
102
+
103
+ - **Windows lane enumerated zero files because six scripts detected "am I the entry module" by string-comparing `import.meta.url` with `file://${process.argv[1]}`** (refs #2536) — on Windows the two spellings never match, so the main block never ran; every gate now compares against `pathToFileURL(process.argv[1]).href`, the win32 gate scanner excludes fixtures by the platform separator, and a governance test rejects the hand-built comparison.
104
+
105
+ - **Bound turn-end Gitleaks classification (refs #2575)** — timed-out classification keeps raw findings fail-open. Thanks @stekman08.
106
+
107
+ - **Prune merged clean worktrees with a per-run cap; never a tree with untracked files (refs #2631, #2538, #2784)** — the agent-worktree hygiene sweep now also removes any registered worktree whose branch tip is an ancestor of `origin/master` and whose checkout is clean, clears `.claude/worktrees/agent-*` leftovers that hold nothing but git's own `.git` gitlink, and caps removals per run with `--max` (default 10). An untracked file counts as a deliverable: only an empty `git status --porcelain` is clean, and the keep record names the first entry it protected.
108
+
109
+ - **The format smoke lane installs the managed formatters it selects (refs #2767)** —
110
+ The `--install` path prefetches configured formatters through `ensureTool`
111
+ and the formatter pipeline resolves those managed binaries, with venv/local
112
+ → PATH → managed precedence; every managed resolver returns the typed
113
+ unavailable outcome instead of falling through to a bare command; GitHub and
114
+ archive installs record a typed unavailable outcome when no asset exists for
115
+ the host platform and architecture; the formatter-absence tests pin the
116
+ installer's independent PATH lookup so npm's `node_modules/.bin` prefix on
117
+ CI cannot resolve a dev-dependency binary.
118
+
119
+ - **Unify tool cwd and root resolution (refs #2777)** — Runners, formatters, and LSP configuration walks now use one bounded, logged resolution seam.
120
+
121
+ - **Fix runner no-config advisories logging once per tool and root at debug level (refs #2811)** — Dispatch now bounds constant runner advisories to one record per tool and resolved root per session.
122
+
123
+ - **Key vi.mock export admissions by factory content and ratchet missing counts across line moves.** (refs #2816)
124
+
125
+ - Make vi.mock export sweep warnings visible in default Vitest output and keep baseline regeneration successful when admissions change.
126
+
127
+ - **Harden real pi harness waits and isolation (refs #2825)** — consume cursor-based events, honor scenario scripts, pin lane membership, and sweep shared scratch directories.
128
+
129
+ - **Verify explicit existing records in PR-body observability lint (refs #2855)** — require the named kind in the named source file and verify its cited line is within 20 lines of the literal.
130
+
131
+ - **Report peak RSS for exit-137 classifications (refs #2856)** — retain master’s real-failure precedence and include the three heaviest `[mem-file]` peaks in kill details.
132
+
133
+ - **Attribute pi situational-tool observations by session file and emit on replacement.** A shutdown with `targetSessionFile` emits the conversation that is ending; reload re-runs the extension factory but keeps the same file and row. (refs #2858)
134
+
135
+ - **Fail session-start tests when the awaited handler crashes or exceeds its test budget, instead of passing vacuously.** (refs #2859)
136
+
137
+ - **Bound joined tool-result text with one conservative footer reserve, write one complete-result log, and convert rejecting pi tool executions into contract errors.** (refs #2862)
138
+
139
+ - **Derive lens diagnostics limits and scope metadata from the LSP probe, preserve single-file names, and honor session severity tiers.** (refs #2864)
140
+
141
+ - **Test-runner selection is per file kind and per module root, and a go `[setup failed]` result is advisory (refs #2870)** — a repo carrying both a `go.mod` and a Gradle build no longer hands every `.java` file to `go test` (the `RUNNERS` declaration order used to decide), a `README.md` or `.yaml` under a test directory no longer becomes its own test target, a nested Gradle or Go module anchors at its own build while a single-language repo keeps the runner it selected before, and go's `FAIL <pkg> [setup failed]` verdict reports as "could not run tests" instead of a fabricated blocking failure whose classification depended on whether go printed the word "error".
142
+
143
+ - **The test runner spawns its child through `resolveToolCwd`, so a nested module's tests run from that module (refs #2871)** — a `.go` file in a nested `go.mod` module now runs `go test ./internal/…` from the module that owns the package instead of a root-relative path the root module cannot resolve, with the shared seam supplying marker discovery, the `.git`/dispatch-root fallbacks, the `$HOME` ceiling and one `tool-cwd` log line per resolution key; a whole-project build launches from the directory that owns its wrapper (`gradle`, `maven`), a child is never anchored on a config file the detector itself rejected as evidence (`pytest`'s `pyproject.toml`, `phpunit`'s `composer.json`), and the failed-target ledger stays keyed on the dispatch root.
144
+
145
+ - **Make the runner spawn-cwd sweep verify resolver origin across the child-spawn population (refs #2872).** Bindings resolve by the grammar's own scope rather than a list of node kinds, any later rebinding leaves the value unproven, promoted resolvers must be a single seam return, and each admitted site is keyed by its cwd expression and the locals that expression reads, so a laundered or edited cwd cannot inherit an admission.
146
+
147
+ - **Keep diagnostics visible for tolerant MCP severity inputs and apply one threshold across session and LSP sources, including error-only files at the warning threshold.** (refs #2864)
148
+
149
+ - **Surface a crashed pi hook handler instead of swallowing it silently (refs #2884)** — the nine `index.ts` catch sites that absorb a handler crash (`session_start`, `session_before_fork`, `observed_settled_sweep`, `observed_ledger_refresh`, `agent_end`, `turn_end`, the `agent_settled` deferred-mutation drain, `quiet_window`, and `message_end`) now route through one shared `surfaceHandlerCrash` guard: production keeps the swallow but leaves one bounded `hook-handler-crash` degradation row per handler per session, and under the test runner the crash is rethrown so the awaiting test fails instead of resolving as if the handler had completed. The fire-and-forget `quiet_window` catch records the row without rethrowing, so a crash cannot terminate the pi host with an unhandled rejection.
150
+
151
+ - **Resolve aliased child-process bindings (closes #2888)** — Extend the spawn-cwd test sweep to resolve aliased and namespaced child-process bindings.
152
+
153
+ - **Make pi RPC `session_start` idempotent per reason and session ID, with a session-file fallback (refs #2890)** — repeated replacement events no longer repeat tool restoration or session-state resets, while a different session identity starts a new mutation pass.
154
+
155
+ - **Deduplicate repeated RPC session starts (refs #2890)** — use the stable session ID, fall back to the session file, and re-run the restore when the host's active tool posture drifted.
156
+
157
+ - **`lens_diagnostics mode=full` retires a stale finding only when the result that replaces it is genuinely authoritative: an LSP write the ordering guard accepted, or a project runner that actually analysed the root this call. A runner that reported success without running — no project root, no source files, a scan that crashed before writing its report — is reported cold instead of silently deleting the finding, and a retained result that could not be reconciled is labelled stale rather than served as a current blocker (refs #2154).**
158
+
159
+ - **Require Windows-only test gates to name and enter the Windows Vitest lane (refs #2536, #2784)** — one shared population script drives the Windows job and governance sweep, with a job summary recording the executed gate count.
160
+
161
+ - **Require runtime Observability sections to name a diff record (refs #2543, #2784)** — the PR-body checker matches observability record literals against added runtime lines and rejects unsupported no-failure claims.
162
+
163
+ - **Make the merge-train warden label `red-ci` for any failing non-advisory check on the exact pull-request head (refs #2616, #2784)**.
164
+
165
+ - **CI failure classifier: a test timeout beside registry network failures is infra, not real (refs #2839)** — A Unit-tests job whose only test-level failure is a vitest `Test timed out in Nms` line (no `AssertionError`, no compiler diagnostic) now classifies `infra-net` when the log also carries registry-unreachable evidence (`npm error code ECONNRESET` through every `npm-retry` attempt, codeload/SARIF 429/503, `npm ci` ETIMEDOUT, `npm-retry: attempt N network error`), so the once-per-SHA automatic rerun arms instead of the job sitting `ci:real`; PRs #2834 and #2835 both hit this and were re-run by hand. An `AssertionError` or a TypeScript `error TS` line beside the same network noise still classifies `real`, and a lone timeout with no network evidence is unchanged.
166
+
167
+ - **`detectFileRole` recognises Go `_test.go` and the other table conventions (closes #2880)** — Editing `pkg/foo_test.go` produced no test target because the shared role classifier only knew `.test.`/`.spec.`/prefix/dir patterns. It now also matches the `_test.`/`_spec.` suffix infixes and the case-sensitive `*Test(s).<ext>` CamelCase suffix for Java/Kotlin/C#/F#/PHP, informed by the test-runner client's `SOURCE_TO_TEST_PATTERNS` + `RUNNERS` table; hand-written, see #2928 for the single-classifier fold, so an edited Go test file runs its own package tests.
168
+
169
+ - **Route helm-lint through the runner cwd resolver (closes #2882)** — Helm lint now runs with the cwd selected by the shared dispatch runner seam.
170
+
171
+ - **Preserve situational tool activations across pi rebuilds (refs #2889)** — Remember activations by session file so reload, resume, and fork restore the conversation's tool posture.
172
+
173
+ - Run the installed-registry release-QA smoke with a scratch-home pip policy and keep the measured registry deterministic.
174
+
175
+ - **Diagnostic verification guidance (closes #2792).** Agent and MCP descriptions distinguish cache-only reporting from active scans. Use `mode=full` with `paths` when changed files have absent or stale cached findings.
176
+
177
+ - **Partition LSP diagnostics by server provenance (refs #2776)** — custom language servers now render their diagnostics as primary findings even when their server-authored `source` value differs from the registered server id.
178
+
179
+ - **Re-sync LSP diagnostics after Git tree changes (refs #2817)** — open documents and bounded cached import dependencies are touched before scoped full diagnostics serve cached results; files without import-fact coverage receive a fresh requested-file touch; **Prove language-neutral LSP dependency resync through the real server path** (refs #2817); the language matrix derives its facts and fallback rows from the production import-facts predicate; the shared drift pass gives a Git-queued file one resync opportunity even when ordinary stat drift identifies the same file in that pass.
180
+
181
+ - **Bound MCP tool results through the shared pi result seam (refs #2799, #2800)** — oversized results retain head and tail context, report omitted characters, and preserve the complete payload in the session log; the roster budget rejects duplicate tool names; results above the documented 8 MiB input budget keep a bounded head, an explicit incomplete marker and the tail in the session log, with one `mcp-complete-result-budget-exceeded` degradation per session.
182
+
183
+ - **Flake-shape ratchet governs support-helper waits (refs #2563, #2784)** — the contention ratchet scans `.ts` and `.mts` support helpers, resolves aliased timers, and requires every support baseline row to carry a detector-specific reason, header, and serialized-lane proof through its importing tests; **Reduce flake-shape ratchet AST scanning cost (refs #2563, #2784)** — the whole-tree scan uses a comment/string-blanked textual pre-pass and parses each timer-bearing source file at most once per run.
184
+
185
+ - **Label-sync post-merge validation fails when the syncer deletes or loses any label (refs #2614)** — the `labels.yml` sync job now snapshots the live label set before `action-label-syncer` runs and re-validates after: any before-vs-after deletion, or any manifest label missing from the live set, fails the job through `::error::label sync deleted or missing labels:` with the names printed, instead of a silent success while prune deletes labels (the #2553 recurrence, twice for the priority labels).
186
+
187
+ - **Route built-in LSP roots through the tool-cwd seam and expose resolved cwd in `lens_diagnostics` (refs #2777)** — Built-in server marker tables now use the shared bounded resolver, and diagnostic rows identify the cwd used for their language server. Workspace-priority roots keep their complete marker tables through the seam (Go, JSON), and a server-computed root is the seam's input, never replaced (review rounds 2 and 4).
188
+
189
+ - **Run the release-QA tool smoke from the export root (closes #2893)** — the install lane now executes the smoke harness from the archived source tree while loading the installer registry from the installed package, and measures pip entries under its scratch-pinned package policy.
190
+
191
+ - **Docs membership guard asserts list members, not counts (closes #2919).** `tests/docs/features-counts.test.ts` now compares the `docs/features.md` formatter list member-by-member against `ALL_FORMATTERS`, the LSP language list against non-auxiliary `LSP_SERVERS` ids, and the `docs/mcp.md` tool table against `TOOL_REGISTRY`, and reports missing and extra names, so reinstating a removed member or swapping in a stale name fails the suite.
192
+
193
+ - **Route tool configuration diagnostics through the shared note seam (refs #2800)** — unknown and non-disableable tool names use the bounded config notice path, and `tools.<name>.enabled` is documented across the config references.
194
+
195
+ ## [4.1.5] - 2026-09-08
196
+
197
+ ### Added
198
+
199
+ - **Dogfood knip on pi-lens's own source (closes #2698)** — `knip.jsonc` now resolves the compiled-sibling layout (`clients/*.js` sitting gitignored beside `clients/*.ts` after `npm run build`) that previously made knip report 491 source files "unused"; `npm run knip` (advisory in `lint.yml`, `continue-on-error`) purges those build artifacts before every run, declares the real `mcp/`/`scripts/` entry points, and documents each dependency/binary/file exemption it needed (husky, `@biomejs/biome`, `typescript-language-server`, `markdownlint-cli2`, two parked/dynamically-loaded files) with the reason knip can't see the usage on its own.
200
+
201
+ - **`PreToolUse` Bash guard hook for the fixer/reviewer non-negotiables (closes #2699)** — `scripts/hooks/guard-bash.mjs`, registered in `.claude/settings.json` on the Bash tool via `${CLAUDE_PROJECT_DIR}`, mechanically denies `git stash` in any form, `git reset --soft origin/<branch>` / `--hard`, a hand-typed `git worktree remove` with two force flags, and an unpinned `node` probe that loads runtime code from `clients/`/`dist/` with no `PI_LENS_HOME` — the same rules a fixer ran afoul of by hand on 2026-09-07 and 2026-09-02. Command text is read by a single region pass that subtracts what bash cannot execute (comments, and heredoc bodies — a PR description, an issue comment, a written file) before anything is tokenized, so a forbidden command *mentioned* in a document is never mistaken for one being run; a heredoc body with an unquoted delimiter still has its `$( )`/backtick substitutions scanned, because bash does expand those. Never blocks the tool on its own failure: malformed or missing stdin degrades to allow.
202
+
203
+ - **Add per-analyzer `knip.enabled`, `jscpd.enabled`, `madge.enabled`, `gitleaks.enabled`, `govulncheck.enabled`, `deadCode.enabled`, and `complexity.enabled` keys plus `startup.mode` and `startup.scans.enabled` controls (refs #2721)** — project and global configuration can disable startup analyzers or heavyweight startup scans while preserving diagnostics and LSP.
204
+
205
+ ### Changed
206
+
207
+ - **Nightly tracking-issue updates share one reusable CLI (closes #2683)** — compat-smoke, install-smoke, and clean-signal drift use one exact-title issue seam that fails loudly on a GitHub error and searches beyond the first page; both smoke workflows now auto-close their tracker on a clean run.
208
+
209
+ - **oxlint advisory tier (categories, plugins, type-aware) and publint on the packed tarball (refs #2700, refs #2697)** — `npm run lint:js` (gating) additionally denies 32 individually-named rules from the `suspicious`/`perf` categories and the `import`/`promise`/`typescript`/`unicorn`/`oxc` plugins that produce zero findings on master today. A new `npm run lint:js:advisory` runs the full intended set — categories `correctness`+`suspicious`+`perf`, plugins `typescript`+`unicorn`+`promise`+`import`+`oxc`, and `--type-aware` (paired `oxlint-tsgolint@7.0.2001` devDependency, per oxlint 1.80.0's own `peerDependencies` pin) — over the whole repo including tests, with eight rules policy-allowed for named reasons (four are overwhelming test-tree noise, four are documented false positives on deliberate patterns: a `void`-ignored promise in a callback, an explicit `.call(bus, …)` this-binding, a side-effect import, and an AbortSignal property poll). It runs as a new `oxlint (advisory)` job in `lint.yml`, classified advisory by the repo's `(advisory)` name-suffix convention (no `continue-on-error`) — the job's own conclusion is green whenever the type-aware sweep actually ran (a rule-count floor guards against a silently-degraded `oxlint-tsgolint` peer) regardless of how many un-triaged findings it reports, and red only on that degradation. A governance test resolves both scripts' real enabled-rule sets via oxlint's own `--print-config` and asserts the gating set stays a subset of the advisory set.
210
+
211
+ `ci.yml`'s `prod-install-build` job now packs the built package (`npm pack`) and runs `publint` on the tarball (gating) — the check #2587's manifest regression was missing. `attw` (arethetypeswrong) is not added: the package ships no `.d.ts` at all, so there is nothing for it to grade; `docs/release-qa-baseline.md` records both facts under the `npm-pack` modality.
212
+
213
+ - **Internal: 295 unused exports, 235 unused exported types and 4 duplicate exports removed, with the 85 declarations that became dead (refs #2708)** — no user-facing behaviour changes; the public entry points, the MCP server and every script keep their exports. Found by knip with tests counted as entry points, so nothing a test imports was touched.
214
+
215
+ - **knip advisory job green: the last three unused test-support exports are private, the dead `scripts/hooks/**/*.ts` entry pattern is gone, and the path-spawned `jscpd` devDependency is credited (closes #2708)** — `testSourceFiles`, `testsRelative` and `SCAN_INFRASTRUCTURE` in `tests/support/flake-shape-scan.ts` had no importer after #2749; the hooks are `.mjs`, so the `.ts` entry pattern matched nothing.
216
+
217
+ - **Cleared 51 of the 54 knip rows (23 of the 26 unused test exports; the 3 flake-shape rows stay for #2742) and 28 unused exported test types (refs #2708)** — test-support APIs are now private where their consumers are local, while the packaging workflow's pinned `publint` dependency remains declared and documented to Knip.
218
+
219
+ - **Advisory CI adds jscpd, yamllint, typos, and taplo (refs #2706)** — pinned tooling jobs make duplication, YAML style, spelling, and TOML checks visible without blocking the merge train.
220
+
221
+ - **Delegated-worker contract: handoff files for workers without Git authority (refs #2733, #2721)** — `docs/pi-lens-subagent.md` and the AGENTS.md role-contract section now name the `PR_BODY.md` / `COMMIT_MSG.txt` worktree-root handoff the orchestrator commits from, and the sandbox test incantation (`--configLoader runner`, offline grammar prefetch) that plegma codex workers need.
222
+
223
+ - **Reviewer contract diffs from the merge base** — two reviews this week reported another lane's merge in reverse as a HIGH regression because they diffed two-dot against a newer `origin/master`; the contract now names the three-dot form.
224
+
225
+ ### Fixed
226
+
227
+ - Keep admission registry ordering checks mutation-sensitive.
228
+
229
+ - **Turn-end session test doubles use the shared runner-error predicate (closes #2673)** — partial runner errors with `failed === 0` now exercise the same classification as production instead of requiring `passed === 0` in four local `formatResult` doubles.
230
+
231
+ - **yamllint, ruff, spellcheck, psscriptanalyzer, oxlint, and shellcheck now lint from the project's cwd, not the extension host's (closes #2691)** — six dispatch runners already computed `ctx.cwd` for their availability probe and config-detection helper, then spawned the actual lint/analysis process without passing that same `cwd`. yamllint's config discovery walks upward from the process's cwd, so it could silently pick up the wrong `.yamllint` (or none) when the extension host's own working directory differed from the project being linted; the other five get the same `cwd` for consistency with their probes, and typos additionally resolves any `extend-exclude` patterns against it. A new sweep over every `safeSpawnAsync`/`safeSpawnSync` call site under `clients/dispatch/runners/*.ts` — including spawns routed through a same-file helper, which is checked at the helper's own call sites — fails by file:line on any that omit `cwd`, so the next tool with this shape can't slip through a symbol-only check the way this one did for five runners after #1731 fixed sqlfluff.
232
+
233
+ - **Call-site sweeps now share the AST-backed `sweep-kit.callSites` seam (refs #2694)** — runner cwd and real-process detectors no longer hand-roll balanced-parenthesis scans, so nested syntax, comments, and strings cannot change a call's boundaries.
234
+
235
+ - **The sweep-floor meta-sweep now matches floor calls over comment- and string-blanked source (closes #2710)** — the meta-sweep registered a test file as floor-covered whenever `/assertNonEmptyScan\s*\(/` or the `auditRegistry({…minScanned…})` pattern matched its raw source, so a docblock merely quoting the helper name excused a sweep that made no real floor call (AGENTS.md shape 38; the same raw-vs-blanked mismatch #2693 round 2 F1 fixed in the runner-spawn-cwd sweep). Registration now runs through `stripSource`, and fixture tests pin that a prose-only mention is reported uncovered while a real call still registers.
236
+
237
+ - **PHP LSP (intelephense) now installs (closes #2722)** — the managed installer verified every npm tool by spawning `--version`, and intelephense has no CLI: it prints ~4 MB of bundled source before the "connection input stream is not set" line that proves it is a healthy stdio server, and Node drops everything past 1 MiB of a piped stderr, so that proof never reached pi-lens and the installer deleted the package it had just installed — every time, since 2026-04-17. A managed npm server can now declare that it is verified from the installed tree instead (package manifest + entry module on disk, no spawn at all), which intelephense does; and for every tool still verified by spawning, a probe that ran out of readable output before it could decide now keeps the installation when the installed tree is intact (an incomplete tree is still cleaned up so the next install can repair it) instead of treating "cannot tell" as "broken".
238
+
239
+ - **Custom LSP servers that never publish diagnostics are navigation-only, not timed out (closes #2765)** — a custom server with no pull-diagnostics provider gets one bounded first-contact push wait per session; silence for the full push budget latches it navigation-only (no wait on later files, a distinct summary bucket, never counted clean), a publish latches it push-capable, concurrent first touches share the one probe, and a hook-deadline cutoff stays unconfirmed instead of latching; a rejected or shutdown-aborted shared probe fails closed for every waiting touch, clears its single-flight entry and is retried without latching.
240
+
241
+ - **Read-guard exemption globs and the file-utils directory glob no longer backtrack on adjacent wildcards (closes #2622)** — runs of adjacent `*` are collapsed to one before compiling, which is semantically identical for the `*`-only dialect and removes the measured backtracking (a 12-star pattern against a 40-component path took >15 s before the fix and ~2 ms after it); a differential corpus pins both matchers' answers unchanged.
242
+
243
+ - **The install-time warm-loader log now honors `PI_LENS_HOME` (closes #2628)** — agent-worktree installs no longer write `warm_loader_cache` records to the maintainer's real `~/.pi-lens/install.log` when the worktree home is pinned.
244
+
245
+ - Require title close keywords to be repeated in the PR body, preventing the four 2026-09-06 incidents including #2610's merge commit from appearing to close issues that GitHub left open.
246
+
247
+ - **The flake-shape ratchet now sees child processes routed through test support helpers (refs #2653)** — code-channel calls to `gitFixtureSpawnAsync`, `safeSpawnAsync`, and the other support helpers that reach `node:child_process` now join the real-process census.
248
+
249
+ - **Managed npm refreshes deduplicate shared packages (closes #2666)** — one package update now covers every registered tool id that shares its package, preserving refresh budget slots for other packages.
250
+
251
+ - **Hold the merge train for unconcluded gating checks (closes #2679)** — Keep approved PRs pending until every non-advisory check reaches a terminal conclusion.
252
+
253
+ - **`scripts/npm-retry.mjs` annotates `infra: registry unreachable` only for network-shaped failures (closes #2684)** — a deterministic npm failure (`ERESOLVE`, `E404`, `EINTEGRITY`, `ETARGET`) now stops after one attempt with a plain "failed after N attempt(s)" line and the exit code preserved, while timeouts, spawn errors, and the restored shared `NET_PATTERN` plus npm-local transient patterns keep the retry backoff and origin/master's `failed 3 times` infra annotation; network evidence wins over a mixed deterministic code, and unknown non-network failures retain retry behavior.
254
+
255
+ - **LSP and smoke harness scratch directories use liveness-gated cleanup (closes #2688, closes #2687)** — shared per-run scratch directories record their owner process, preserve live workspaces, remove dead or aged orphaned entries, and announce each scratch home for reliable telemetry discovery.
256
+
257
+ - **Guard-bash preserves here-string boundaries and classifies heredoc substitutions the way bash expands them (closes #2705, refs #2726)** — `<<<` is consumed as a here-string operator instead of being re-read as a phantom heredoc delimiter; an unclosed `$(` or backtick in an unquoted heredoc body is treated as non-executable while later live commands remain classified; and a valid `$()` or backtick substitution discovered before a later unclosed one stays classified, with substitutions nested inside the malformed span kept inert like bash.
258
+
259
+ - **Fail the oxlint advisory tier when type-aware support is unavailable (refs #2709)** — `lint:js:advisory` now checks that `oxlint-tsgolint` resolves, exposes its binary, and satisfies oxlint's declared peer range before running.
260
+
261
+ - **A red `Tool smoke (nightly)` run now notifies through a persistent tracking issue, on the failure path too (closes #2723)** — the workflow's only tracking-issue writer (`Notify on silentOnClean drift`, #529/#594) sat behind the LSP handshake layer step with `continue-on-error: true` but no `if: always()`, so GitHub skipped it — and everything after it — exactly when an earlier step failed: 13 consecutive red nights (2026-08-26 → 2026-09-07) with no automated notice, and that notifier is scoped to unrelated `silentOnClean` telemetry regardless. The three gating steps (Tool layer, LSP handshake layer, Format layer — the only three without `continue-on-error`) now each carry an `id:` and a captured `tee` log, feeding a new, final `if: always()` step that reads all three outcomes into `scripts/notify-tool-smoke-red.mjs`: it upserts a single persistent tracking issue naming the failing layer, the `✗` rows with reason text, and a consecutive-red count, closing it automatically on the first fully green run. Mirrors `install-smoke.yml`'s existing `Notify install drift` step and reuses its four-outcome (`success`/`failure`/`cancelled`/`skipped`) classification and drift-issue title lookup rather than re-deriving them; cross-references #2683's not-yet-landed consolidation of these notifiers.
262
+
263
+ - **Heredoc bodies no longer leak into Bash command analysis (refs #2726)** — `tokenizeShellCommand` now consumes `<<` and `<<-` bodies, stops delimiter parsing at shell metacharacters, drops quoted body text, and retains substitutions from unquoted bodies so git-guard does not classify prose as an executable command.
264
+
265
+ - **Turn-end test failures now reach the next model context without a terminal entry (closes #2733)** — settled failures keep their provenance and advisory framing, survive session reset until delivery, then deliver once through the next context build. Rehydration matches the stable session id only, so `--session` quit-and-resume works across activation owners while in-process activation isolation stays in the pending map. Pull diagnostics and MCP turn-end handling remain unchanged.
266
+
267
+ - **Test ratchets now ignore comment and string laundering when matching source requirements (closes #2736)** — the Git-fixture, NDJSON writer, runner outcome, flake-shape, and LSP double-admission header detectors now use `stripSource`-based evidence, preserving string literals only where they carry the command or import path being checked.
268
+
269
+ - **Formatters now run from the project root (closes #2756)** — `formatFile` uses the nearest formatter config or `.gitignore`, with a real `.git` fallback capped at `$HOME`, so `.prettierignore`, `.gitignore`, and cwd-discovered configs resolve as at the CLI. Prettier, Biome, and oxfmt are covered.
270
+
271
+ - **Remove the unused scratch export and declaration, and fix oxfmt violations in two tests (refs #2759).**
272
+
273
+ - **Nightly tool smoke: the six `--install` steps share one tool tree again (refs #2762, refs #2687)** — #2755 dropped the job-level `PI_LENS_HOME`/`PILENS_DATA_DIR` pin from `tool-smoke.yml` and `parser-smoke.yml`, so the Format layer started from an empty scratch home and seven managed formatters ran against nothing; the pin and its workflow test are restored, per-run scratch isolation stays the local default.
274
+
275
+ - **Format smoke rows classify typed unavailable outcomes as skips (refs #2767)** — The format smoke harness no longer reports missing formatter executables as formatting failures.
276
+
277
+ - **Ledger fields no longer read `[object Object]`, and a rejected LSP push-wait no longer surfaces as an unhandled rejection (refs #2700)** — `normalizeForLedger` serialises plain objects and arrays instead of `String()`-ing them (a value with its own throwing `toString` still raises into the ledger's corrupted-input failsafe); the LSP push-wait settle marker attaches on both the resolve and the reject path. Found by the oxlint type-aware pass (`no-base-to-string`, `no-floating-promises`); the same pass's `preserve-caught-error` sites now carry `{ cause }`.
278
+
19
279
  ## [4.1.4] - 2026-09-07
20
280
 
21
281
  Patch release carrying everything merged since 4.1.3 (152 entries, including 12 under Added and 2 under Deprecated — the additions are extension-internal and CI/test-harness surfaces, no new user-facing commands). Release-QA (`scripts/release-qa.mjs`, #2606) reports SHIP on pi 0.80.10 and pi 0.85.1: 11 of 11 rows witnessed, 0 failed, 0 skipped, git-install row included.
@@ -155,6 +155,14 @@ pi install git:github.com/apmantza/pi-lens
155
155
  Requires Node.js >=22.19.0 (matches the pi host's own floor — see `engines`
156
156
  in `package.json`).
157
157
 
158
+ Letting a coding agent do it: paste this into its prompt.
159
+
160
+ ```text
161
+ Install pi-lens (npm:pi-lens) into pi, then read AGENTS.md in
162
+ https://github.com/apmantza/pi-lens for how the extension works and how it
163
+ expects to be operated.
164
+ ```
165
+
158
166
  > **npm v12 users:** dependency lifecycle scripts (e.g. `@ast-grep/cli`'s
159
167
  > `postinstall`) now require explicit approval — if `npm install` warns about
160
168
  > unreviewed install scripts, review and allow them with
@@ -336,6 +344,11 @@ Thanks goes to these wonderful people:
336
344
  <td align="center" valign="top" width="14.28%"><a href="https://github.com/mjfaga"><img src="https://avatars.githubusercontent.com/u/7584015?v=4" width="100px;" alt=""/><br /><sub><b>Mark</b></sub></a><br /><a href="#code-mjfaga" title="Code">💻</a></td>
337
345
  <td align="center" valign="top" width="14.28%"><a href="https://aeturnal.io/"><img src="https://avatars.githubusercontent.com/u/219271200?v=4" width="100px;" alt=""/><br /><sub><b>aeturnal</b></sub></a><br /><a href="#code-aeturnal" title="Code">💻</a></td>
338
346
  <td align="center" valign="top" width="14.28%"><a href="https://github.com/floatGray"><img src="https://avatars.githubusercontent.com/u/44295302?v=4" width="100px;" alt=""/><br /><sub><b>floatGray</b></sub></a><br /><a href="#code-floatGray" title="Code">💻</a></td>
347
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/thomasfsteeples"><img src="https://avatars.githubusercontent.com/u/32720359?v=4" width="100px;" alt=""/><br /><sub><b>Thomas F Steeples</b></sub></a><br /><a href="#code-thomasfsteeples" title="Code">💻</a></td>
348
+ </tr>
349
+ <tr>
350
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/amasen02"><img src="https://avatars.githubusercontent.com/u/97525823?v=4" width="100px;" alt=""/><br /><sub><b>Ama Senevirathne</b></sub></a><br /><a href="#code-amasen02" title="Code">💻</a></td>
351
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/AcademyKUB8"><img src="https://avatars.githubusercontent.com/u/217174854?v=4" width="100px;" alt=""/><br /><sub><b>AcademyKUB8</b></sub></a><br /><a href="#code-AcademyKUB8" title="Code">💻</a></td>
339
352
  </tr>
340
353
  </tbody>
341
354
  </table>
@@ -344,11 +357,3 @@ Thanks goes to these wonderful people:
344
357
  <!-- prettier-ignore-end -->
345
358
 
346
359
  <!-- ALL-CONTRIBUTORS-LIST:END -->
347
-
348
- The following commit identities also appear in `git shortlog -sne HEAD` but are
349
- not represented in the generated table above: Anas Alsbei, Claude,
350
- Christopher Patti,
351
- dependabot[bot], Fabio-D, github-actions[bot], JSup, Kenny McCormick,
352
- Max Lupus, Moritz Hofmann, ricardo, and root.
353
-
354
- If you land a pull request or report an issue that gets fixed, we'll add you here.
@@ -26,7 +26,6 @@
26
26
  "./clients/format-events-publish.js",
27
27
  "./clients/format-service.js",
28
28
  "./clients/formatters-lazy.js",
29
- "./clients/git-guard.js",
30
29
  "./clients/host-ports.js",
31
30
  "./clients/installer/index.js",
32
31
  "./clients/instance-reaper.js",
@@ -75,13 +74,16 @@
75
74
  "./clients/session-start-observability.js",
76
75
  "./clients/session-state-store.js",
77
76
  "./clients/sessionstart-logger.js",
77
+ "./clients/situational-tool-telemetry.js",
78
78
  "./clients/skills-resolver.js",
79
79
  "./clients/smells-rollup.js",
80
80
  "./clients/startup-timing.js",
81
81
  "./clients/test-runner-delivery.js",
82
+ "./clients/tool-config.js",
82
83
  "./clients/tool-definition.js",
83
84
  "./clients/tool-render.js",
84
85
  "./clients/tool-set-policy.js",
86
+ "./clients/turn-context.js",
85
87
  "./clients/turn-summary-render.js",
86
88
  "./clients/turn-summary.js",
87
89
  "./clients/user-notify.js",
@@ -33,10 +33,3 @@ export function logActionableWarningsEvent(entry) {
33
33
  : {}),
34
34
  });
35
35
  }
36
- export function getActionableWarningsLogPath() {
37
- return AW_LOG_FILE;
38
- }
39
- /** Resolve once all enqueued actionable-warnings writes are on disk. */
40
- export function flushActionableWarningsLog() {
41
- return writer.flush();
42
- }
@@ -223,7 +223,7 @@ export function validateAdvisoryProvenance(record, cwd, runtime) {
223
223
  // of which any #1461 slice writes yet, so nothing here currently touches
224
224
  // it.
225
225
  /** Stat budget: one per unique cited path, sharing the envelope's own cap. */
226
- export const MAX_FINDING_PATH_STATS = MAX_ADVISORY_AFFECTED_FILES;
226
+ const MAX_FINDING_PATH_STATS = MAX_ADVISORY_AFFECTED_FILES;
227
227
  /** How many dead paths a single drop record names before it stops. */
228
228
  const MAX_LOGGED_DEAD_PATHS = 3;
229
229
  /**
@@ -0,0 +1 @@
1
+ export {};
@@ -61,7 +61,7 @@ function reportAstGrepRulesHealth(bundledRuleDir) {
61
61
  * Exported for tests: they drive it against a registered bridge instead of
62
62
  * spawning ast-grep.
63
63
  */
64
- export function recordAstGrepApply(matches) {
64
+ function recordAstGrepApply(matches) {
65
65
  const bridge = getMutationBridge();
66
66
  if (!bridge || matches.length === 0)
67
67
  return;
@@ -99,7 +99,7 @@ export function astGrepRemediationHint(kind) {
99
99
  case "json_parse_failed":
100
100
  return "Hint: ast-grep produced output that could not be parsed — retry with a simpler pattern; the installed CLI version may be incompatible.";
101
101
  default:
102
- return "Hint: verify the pattern is a single valid AST node for this `lang` (use ast_grep_dump to discover node kinds), or fall back to grep for plain-text search.";
102
+ return "Hint: verify the pattern is a single valid AST node for this `lang` (use ast_grep_search with dump=true to discover node kinds), or fall back to grep for plain-text search.";
103
103
  }
104
104
  }
105
105
  export function logAstGrepToolEvent(event) {
@@ -115,11 +115,4 @@ export function logAstGrepToolEvent(event) {
115
115
  };
116
116
  writer.log({ ts: new Date().toISOString(), ...payload });
117
117
  }
118
- export function getAstGrepToolLogPath() {
119
- return AG_LOG_FILE;
120
- }
121
- /** Resolve once all enqueued ast-grep-tool writes are on disk. */
122
- export function flushAstGrepToolLog() {
123
- return writer.flush();
124
- }
125
118
  export { countLines as _countLinesForTest };
@@ -6,3 +6,5 @@
6
6
  * - ast-grep-rule-manager.ts
7
7
  */
8
8
  export {};
9
+ // =============================================================================
10
+ // JSON FORMAT (ast-grep CLI output)
@@ -29,8 +29,121 @@ function stripQuotes(token) {
29
29
  }
30
30
  return token;
31
31
  }
32
+ function parseHeredocDelimiter(command, start) {
33
+ let i = start;
34
+ const stripTabs = command[i] === "-";
35
+ if (stripTabs)
36
+ i += 1;
37
+ while (/\s/.test(command[i] ?? ""))
38
+ i += 1;
39
+ let delimiter = "";
40
+ let quoted = false;
41
+ while (i < command.length && !/[\s;&|<>]/.test(command[i] ?? "")) {
42
+ const ch = command[i];
43
+ if (ch === "'" || ch === '"') {
44
+ quoted = true;
45
+ const quote = ch;
46
+ i += 1;
47
+ while (i < command.length && command[i] !== quote) {
48
+ delimiter += command[i++];
49
+ }
50
+ if (command[i] !== quote)
51
+ return undefined;
52
+ i += 1;
53
+ continue;
54
+ }
55
+ if (ch === "\\") {
56
+ quoted = true;
57
+ i += 1;
58
+ if (i >= command.length)
59
+ return undefined;
60
+ delimiter += command[i++];
61
+ continue;
62
+ }
63
+ delimiter += ch;
64
+ i += 1;
65
+ }
66
+ if (!delimiter)
67
+ return undefined;
68
+ return { heredoc: { delimiter, stripTabs, quoted }, end: i - 1 };
69
+ }
70
+ function heredocSubstitutionBodies(body) {
71
+ const substitutions = [];
72
+ for (let i = 0; i < body.length; i += 1) {
73
+ if (body.startsWith("$(", i)) {
74
+ let depth = 1;
75
+ let quote;
76
+ for (let end = i + 2; end < body.length; end += 1) {
77
+ const ch = body[end];
78
+ if (quote === "single") {
79
+ if (ch === "'")
80
+ quote = undefined;
81
+ continue;
82
+ }
83
+ if (quote === "double") {
84
+ if (ch === '"' && body[end - 1] !== "\\")
85
+ quote = undefined;
86
+ continue;
87
+ }
88
+ if (ch === "'" || ch === '"') {
89
+ quote = ch === "'" ? "single" : "double";
90
+ }
91
+ else if (body.startsWith("$(", end)) {
92
+ depth += 1;
93
+ end += 1;
94
+ }
95
+ else if (ch === ")") {
96
+ depth -= 1;
97
+ if (depth === 0) {
98
+ substitutions.push(body.slice(i + 2, end));
99
+ i = end;
100
+ break;
101
+ }
102
+ }
103
+ }
104
+ }
105
+ else if (body[i] === "`" && body[i - 1] !== "\\") {
106
+ const end = body.indexOf("`", i + 1);
107
+ if (end >= 0) {
108
+ substitutions.push(body.slice(i + 1, end));
109
+ i = end;
110
+ }
111
+ }
112
+ }
113
+ return substitutions;
114
+ }
115
+ function consumeHeredocBodies(command, start, heredocs) {
116
+ let cursor = start;
117
+ const substitutions = [];
118
+ for (const heredoc of heredocs) {
119
+ const bodyStart = cursor;
120
+ let found = false;
121
+ while (cursor < command.length) {
122
+ const lineEnd = command.indexOf("\n", cursor);
123
+ const end = lineEnd < 0 ? command.length : lineEnd;
124
+ let line = command.slice(cursor, end);
125
+ if (heredoc.stripTabs)
126
+ line = line.replace(/^\t+/, "");
127
+ if (line.replace(/\r$/, "") === heredoc.delimiter) {
128
+ if (!heredoc.quoted)
129
+ substitutions.push(...heredocSubstitutionBodies(command.slice(bodyStart, cursor)));
130
+ cursor = lineEnd < 0 ? end : end + 1;
131
+ found = true;
132
+ break;
133
+ }
134
+ cursor = lineEnd < 0 ? end : end + 1;
135
+ }
136
+ if (!found) {
137
+ if (!heredoc.quoted)
138
+ substitutions.push(...heredocSubstitutionBodies(command.slice(bodyStart)));
139
+ return { end: command.length - 1, substitutions };
140
+ }
141
+ }
142
+ return { end: cursor - 1, substitutions };
143
+ }
32
144
  export function tokenizeShellCommand(command) {
33
145
  const segments = [];
146
+ const pendingHeredocs = [];
34
147
  let tokens = [];
35
148
  let word = "";
36
149
  let quote;
@@ -114,12 +227,21 @@ export function tokenizeShellCommand(command) {
114
227
  i++;
115
228
  continue;
116
229
  }
117
- if (/\s/.test(ch)) {
230
+ if (/\s/.test(ch) && ch !== "\n") {
118
231
  flushWord();
119
232
  continue;
120
233
  }
121
234
  if (ch === ";" || ch === "\n" || ch === "|" || ch === "&") {
122
235
  flushWord();
236
+ if (ch === "\n" && pendingHeredocs.length > 0) {
237
+ const heredocs = pendingHeredocs.splice(0);
238
+ flushSegment();
239
+ const consumed = consumeHeredocBodies(command, i + 1, heredocs);
240
+ for (const substitution of consumed.substitutions)
241
+ segments.push(...tokenizeShellCommand(substitution));
242
+ i = consumed.end;
243
+ continue;
244
+ }
123
245
  let terminator;
124
246
  if (ch === "|" && next === "|")
125
247
  i++;
@@ -136,6 +258,16 @@ export function tokenizeShellCommand(command) {
136
258
  }
137
259
  if (ch === "<" || ch === ">") {
138
260
  flushWord();
261
+ if (ch === "<" &&
262
+ next === "<" &&
263
+ command[i - 1] !== "<" &&
264
+ command[i + 2] !== "<") {
265
+ const parsed = parseHeredocDelimiter(command, i + 2);
266
+ if (parsed) {
267
+ pendingHeredocs.push(parsed.heredoc);
268
+ i = parsed.end;
269
+ }
270
+ }
139
271
  unsupported = true;
140
272
  continue;
141
273
  }