@herbertgao/pi-extensions 2026.9.0 → 2026.9.2

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 (360) hide show
  1. package/node_modules/@czottmann/pi-automode/CHANGELOG.md +13 -1
  2. package/node_modules/@czottmann/pi-automode/README.md +20 -0
  3. package/node_modules/@czottmann/pi-automode/docs/GLOSSARY.md +1 -1
  4. package/node_modules/@czottmann/pi-automode/docs/automode-classifier-flow.md +2 -1
  5. package/node_modules/@czottmann/pi-automode/docs/defaults.md +3 -2
  6. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/classifier.ts +38 -2
  7. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/constants.ts +5 -3
  8. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/extension.ts +11 -3
  9. package/node_modules/@czottmann/pi-automode/package.json +1 -1
  10. package/node_modules/@narumitw/pi-btw/README.md +57 -141
  11. package/node_modules/@narumitw/pi-btw/dist/index.ts +466 -41
  12. package/node_modules/@narumitw/pi-btw/dist/index.ts.map +4 -4
  13. package/node_modules/@narumitw/pi-btw/docs/workflows.md +74 -0
  14. package/node_modules/@narumitw/pi-btw/package.json +2 -1
  15. package/node_modules/@narumitw/pi-btw/src/btw.ts +15 -1
  16. package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +32 -2
  17. package/node_modules/@narumitw/pi-btw/src/keybindings.ts +330 -0
  18. package/node_modules/@narumitw/pi-btw/src/menu.ts +136 -19
  19. package/node_modules/@narumitw/pi-btw/src/settings.ts +32 -0
  20. package/node_modules/@narumitw/pi-btw/src/side-thread.ts +57 -5
  21. package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +52 -30
  22. package/node_modules/@pi-plugins/fast-mode/README.md +5 -3
  23. package/node_modules/@pi-plugins/fast-mode/dist/index.d.mts.map +1 -1
  24. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs +20 -55
  25. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs.map +1 -1
  26. package/node_modules/@pi-plugins/fast-mode/package.json +1 -1
  27. package/node_modules/pi-lens/CHANGELOG.md +1072 -0
  28. package/node_modules/pi-lens/README.md +3 -0
  29. package/node_modules/pi-lens/config/biome/core.jsonc +11 -2
  30. package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +13 -1
  31. package/node_modules/pi-lens/dist/clients/actionable-warnings-logger.js +2 -9
  32. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +927 -80
  33. package/node_modules/pi-lens/dist/clients/advisory-provenance.js +1 -1
  34. package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +13 -4
  35. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +123 -3
  36. package/node_modules/pi-lens/dist/clients/ast-grep-rule-manager.js +60 -5
  37. package/node_modules/pi-lens/dist/clients/ast-grep-tool-logger.js +2 -9
  38. package/node_modules/pi-lens/dist/clients/ast-grep-types.js +2 -0
  39. package/node_modules/pi-lens/dist/clients/bash-file-access.js +133 -3
  40. package/node_modules/pi-lens/dist/clients/biome-client.js +9 -2
  41. package/node_modules/pi-lens/dist/clients/blocker-freshness.js +14 -6
  42. package/node_modules/pi-lens/dist/clients/bootstrap.js +509 -73
  43. package/node_modules/pi-lens/dist/clients/bounded-cache.js +152 -12
  44. package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +1 -1
  45. package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +59 -9
  46. package/node_modules/pi-lens/dist/clients/bundled-resource-health.js +113 -0
  47. package/node_modules/pi-lens/dist/clients/bus-events-logger.js +3 -11
  48. package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +31 -4
  49. package/node_modules/pi-lens/dist/clients/cache-manager.js +105 -6
  50. package/node_modules/pi-lens/dist/clients/cache-observability.js +40 -19
  51. package/node_modules/pi-lens/dist/clients/cargo-manifest.js +422 -0
  52. package/node_modules/pi-lens/dist/clients/cascade-logger.js +2 -9
  53. package/node_modules/pi-lens/dist/clients/child-unref.js +1 -19
  54. package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +13 -3
  55. package/node_modules/pi-lens/dist/clients/complexity-client.js +16 -5
  56. package/node_modules/pi-lens/dist/clients/config-core/deny.js +221 -0
  57. package/node_modules/pi-lens/dist/clients/config-core/index.js +50 -0
  58. package/node_modules/pi-lens/dist/clients/config-core/merge.js +357 -0
  59. package/node_modules/pi-lens/dist/clients/config-core/normalize.js +340 -0
  60. package/node_modules/pi-lens/dist/clients/config-core/process-spec.js +248 -0
  61. package/node_modules/pi-lens/dist/clients/config-core/provenance.js +164 -0
  62. package/node_modules/pi-lens/dist/clients/config-core/records.js +218 -0
  63. package/node_modules/pi-lens/dist/clients/config-core/resolve.js +125 -0
  64. package/node_modules/pi-lens/dist/clients/config-core/safe-object.js +78 -0
  65. package/node_modules/pi-lens/dist/clients/config-core/schema.js +165 -0
  66. package/node_modules/pi-lens/dist/clients/config-diagnostic-codes.js +281 -0
  67. package/node_modules/pi-lens/dist/clients/config-locations.js +160 -0
  68. package/node_modules/pi-lens/dist/clients/config-resolve.js +789 -0
  69. package/node_modules/pi-lens/dist/clients/config-schema.js +234 -0
  70. package/node_modules/pi-lens/dist/clients/config-warn.js +407 -0
  71. package/node_modules/pi-lens/dist/clients/dead-code-client.js +19 -14
  72. package/node_modules/pi-lens/dist/clients/dead-code-logger.js +2 -6
  73. package/node_modules/pi-lens/dist/clients/deadline-utils.js +178 -0
  74. package/node_modules/pi-lens/dist/clients/debug-handles.js +2 -2
  75. package/node_modules/pi-lens/dist/clients/debug-heap.js +3 -3
  76. package/node_modules/pi-lens/dist/clients/deferred-lsp-work.js +106 -0
  77. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +113 -7
  78. package/node_modules/pi-lens/dist/clients/dependency-checker.js +8 -19
  79. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +1 -1
  80. package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +12 -9
  81. package/node_modules/pi-lens/dist/clients/diagnostic-logger.js +15 -5
  82. package/node_modules/pi-lens/dist/clients/dispatch/collect-later-tier.js +0 -4
  83. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +162 -44
  84. package/node_modules/pi-lens/dist/clients/dispatch/fact-store.js +97 -0
  85. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +27 -8
  86. package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +0 -6
  87. package/node_modules/pi-lens/dist/clients/dispatch/pending-runner-findings.js +1 -1
  88. package/node_modules/pi-lens/dist/clients/dispatch/plan.js +0 -3
  89. package/node_modules/pi-lens/dist/clients/dispatch/rules/high-complexity.js +2 -2
  90. package/node_modules/pi-lens/dist/clients/dispatch/rules/high-fan-out.js +1 -1
  91. package/node_modules/pi-lens/dist/clients/dispatch/runners/actionlint.js +0 -1
  92. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +383 -27
  93. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +0 -1
  94. package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +4 -1
  95. package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +0 -1
  96. package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +0 -1
  97. package/node_modules/pi-lens/dist/clients/dispatch/runners/dart-analyze.js +0 -1
  98. package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +0 -1
  99. package/node_modules/pi-lens/dist/clients/dispatch/runners/dotnet-build.js +0 -1
  100. package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +0 -1
  101. package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +0 -1
  102. package/node_modules/pi-lens/dist/clients/dispatch/runners/fact-rules.js +0 -1
  103. package/node_modules/pi-lens/dist/clients/dispatch/runners/fish-indent.js +0 -1
  104. package/node_modules/pi-lens/dist/clients/dispatch/runners/gleam-check.js +0 -1
  105. package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +1 -3
  106. package/node_modules/pi-lens/dist/clients/dispatch/runners/golangci-lint.js +0 -1
  107. package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +0 -1
  108. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +0 -1
  109. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +1 -2
  110. package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +0 -1
  111. package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +0 -1
  112. package/node_modules/pi-lens/dist/clients/dispatch/runners/ktlint.js +0 -1
  113. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +0 -1
  114. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +0 -1
  115. package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +0 -1
  116. package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +14 -18
  117. package/node_modules/pi-lens/dist/clients/dispatch/runners/php-lint.js +0 -1
  118. package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +0 -1
  119. package/node_modules/pi-lens/dist/clients/dispatch/runners/prisma-validate.js +0 -1
  120. package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +6 -3
  121. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +7 -4
  122. package/node_modules/pi-lens/dist/clients/dispatch/runners/rubocop.js +0 -1
  123. package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +1 -2
  124. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +1 -3
  125. package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +1 -2
  126. package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +0 -1
  127. package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +4 -3
  128. package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +0 -1
  129. package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +0 -1
  130. package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +0 -1
  131. package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +0 -1
  132. package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +0 -1
  133. package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +0 -1
  134. package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +0 -1
  135. package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +0 -1
  136. package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +0 -1
  137. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +3 -0
  138. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +3 -67
  139. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +194 -80
  140. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +84 -15
  141. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils.js +0 -21
  142. package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +0 -1
  143. package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +2 -20
  144. package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +1 -1
  145. package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +0 -1
  146. package/node_modules/pi-lens/dist/clients/dispatch/utils/format-utils.js +2 -2
  147. package/node_modules/pi-lens/dist/clients/disposition-logger.js +3 -10
  148. package/node_modules/pi-lens/dist/clients/effective-config.js +403 -0
  149. package/node_modules/pi-lens/dist/clients/error-class.js +23 -0
  150. package/node_modules/pi-lens/dist/clients/event-loop-hold.js +274 -0
  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 -2
  153. package/node_modules/pi-lens/dist/clients/feature-hints.js +2 -1
  154. package/node_modules/pi-lens/dist/clients/file-kinds.js +1 -38
  155. package/node_modules/pi-lens/dist/clients/file-time.js +7 -2
  156. package/node_modules/pi-lens/dist/clients/file-utils.js +117 -10
  157. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +50 -13
  158. package/node_modules/pi-lens/dist/clients/format-service.js +6 -2
  159. package/node_modules/pi-lens/dist/clients/formatters.js +385 -104
  160. package/node_modules/pi-lens/dist/clients/freshness-cadence.js +17 -0
  161. package/node_modules/pi-lens/dist/clients/generated-artifacts.js +116 -22
  162. package/node_modules/pi-lens/dist/clients/generation-guard.js +4 -9
  163. package/node_modules/pi-lens/dist/clients/git-guard.js +6 -1
  164. package/node_modules/pi-lens/dist/clients/go-client.js +39 -0
  165. package/node_modules/pi-lens/dist/clients/gradle-ktfmt-style.js +252 -0
  166. package/node_modules/pi-lens/dist/clients/grammar-source.js +3 -3
  167. package/node_modules/pi-lens/dist/clients/hashline-anchor.js +424 -0
  168. package/node_modules/pi-lens/dist/clients/hook-budgets.js +76 -0
  169. package/node_modules/pi-lens/dist/clients/host-edit-normalize.js +5 -2
  170. package/node_modules/pi-lens/dist/clients/host-ports.js +1 -1
  171. package/node_modules/pi-lens/dist/clients/installer/index.js +289 -59
  172. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +84 -18
  173. package/node_modules/pi-lens/dist/clients/instance-reaper.js +110 -236
  174. package/node_modules/pi-lens/dist/clients/instance-registry.js +6 -3
  175. package/node_modules/pi-lens/dist/clients/language-profile.js +0 -9
  176. package/node_modules/pi-lens/dist/clients/language-registry.js +599 -0
  177. package/node_modules/pi-lens/dist/clients/latency-logger.js +165 -9
  178. package/node_modules/pi-lens/dist/clients/ledger-bounds.js +34 -1
  179. package/node_modules/pi-lens/dist/clients/lens-config.js +160 -30
  180. package/node_modules/pi-lens/dist/clients/lens-engine.js +33 -41
  181. package/node_modules/pi-lens/dist/clients/lens-events.js +1 -1
  182. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +77 -6
  183. package/node_modules/pi-lens/dist/clients/lens-map.js +1 -1
  184. package/node_modules/pi-lens/dist/clients/log-cleanup.js +2 -38
  185. package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +3 -1
  186. package/node_modules/pi-lens/dist/clients/lsp/client.js +172 -33
  187. package/node_modules/pi-lens/dist/clients/lsp/config.js +484 -158
  188. package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +1 -1
  189. package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +1 -1
  190. package/node_modules/pi-lens/dist/clients/lsp/edits.js +18 -5
  191. package/node_modules/pi-lens/dist/clients/lsp/index.js +892 -96
  192. package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +1 -1
  193. package/node_modules/pi-lens/dist/clients/lsp/language.js +18 -177
  194. package/node_modules/pi-lens/dist/clients/lsp/launch.js +2 -1
  195. package/node_modules/pi-lens/dist/clients/lsp/path-utils.js +1 -1
  196. package/node_modules/pi-lens/dist/clients/lsp/pending-aux-coverage.js +5 -18
  197. package/node_modules/pi-lens/dist/clients/lsp/server.js +284 -147
  198. package/node_modules/pi-lens/dist/clients/lsp/session-roots.js +116 -23
  199. package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +2 -7
  200. package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +0 -1
  201. package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +14 -7
  202. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +6 -0
  203. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +2 -1
  204. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +1 -1
  205. package/node_modules/pi-lens/dist/clients/lsp-document-symbols.js +1 -1
  206. package/node_modules/pi-lens/dist/clients/lsp-mutation.js +163 -21
  207. package/node_modules/pi-lens/dist/clients/map-with-concurrency.js +36 -0
  208. package/node_modules/pi-lens/dist/clients/mcp/analyze.js +33 -4
  209. package/node_modules/pi-lens/dist/clients/mcp/session.js +5 -16
  210. package/node_modules/pi-lens/dist/clients/memory-sampler.js +8 -3
  211. package/node_modules/pi-lens/dist/clients/metrics-history.js +28 -107
  212. package/node_modules/pi-lens/dist/clients/middle-man-analysis.js +3 -5
  213. package/node_modules/pi-lens/dist/clients/module-report.js +21 -46
  214. package/node_modules/pi-lens/dist/clients/mutating-tool.js +651 -0
  215. package/node_modules/pi-lens/dist/clients/mutation-attribution.js +368 -0
  216. package/node_modules/pi-lens/dist/clients/mutation-bridge.js +240 -0
  217. package/node_modules/pi-lens/dist/clients/ndjson-logger.js +247 -24
  218. package/node_modules/pi-lens/dist/clients/observed-mutation-sources.js +101 -0
  219. package/node_modules/pi-lens/dist/clients/observed-mutation.js +1215 -0
  220. package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +70 -28
  221. package/node_modules/pi-lens/dist/clients/opengrep-config.js +5 -1
  222. package/node_modules/pi-lens/dist/clients/package-manager.js +195 -26
  223. package/node_modules/pi-lens/dist/clients/partial-edit-apply.js +359 -80
  224. package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +23 -7
  225. package/node_modules/pi-lens/dist/clients/path-keyed-map.js +21 -2
  226. package/node_modules/pi-lens/dist/clients/path-utils.js +451 -15
  227. package/node_modules/pi-lens/dist/clients/performance-report.js +2 -2
  228. package/node_modules/pi-lens/dist/clients/persist-debounce.js +8 -1
  229. package/node_modules/pi-lens/dist/clients/php-cs-fixer-config.js +114 -0
  230. package/node_modules/pi-lens/dist/clients/pipeline.js +79 -18
  231. package/node_modules/pi-lens/dist/clients/probe-home-state.js +228 -0
  232. package/node_modules/pi-lens/dist/clients/process-bridge.js +66 -0
  233. package/node_modules/pi-lens/dist/clients/process-snapshot.js +68 -0
  234. package/node_modules/pi-lens/dist/clients/project-changes.js +1 -1
  235. package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +1 -1
  236. package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +4 -3
  237. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/jscpd.js +1 -1
  238. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/knip.js +1 -1
  239. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/madge.js +1 -1
  240. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/opengrep.js +1 -1
  241. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +28 -4
  242. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +51 -20
  243. package/node_modules/pi-lens/dist/clients/project-lens-config.js +438 -122
  244. package/node_modules/pi-lens/dist/clients/project-scan-policy.js +3 -51
  245. package/node_modules/pi-lens/dist/clients/project-snapshot.js +52 -24
  246. package/node_modules/pi-lens/dist/clients/python-environment.js +217 -0
  247. package/node_modules/pi-lens/dist/clients/python-provenance.js +639 -0
  248. package/node_modules/pi-lens/dist/clients/quiet-window.js +6 -1
  249. package/node_modules/pi-lens/dist/clients/read-bridge.js +13 -21
  250. package/node_modules/pi-lens/dist/clients/read-expansion.js +9 -46
  251. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +16 -5
  252. package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +364 -212
  253. package/node_modules/pi-lens/dist/clients/read-guard.js +26 -2
  254. package/node_modules/pi-lens/dist/clients/recent-touches.js +2 -2
  255. package/node_modules/pi-lens/dist/clients/resource-sampler.js +195 -96
  256. package/node_modules/pi-lens/dist/clients/review-graph/builder.js +155 -114
  257. package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +1 -1
  258. package/node_modules/pi-lens/dist/clients/review-graph/service.js +55 -3
  259. package/node_modules/pi-lens/dist/clients/review-graph/shared-extraction-ir.js +7 -15
  260. package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +10 -74
  261. package/node_modules/pi-lens/dist/clients/review-graph-logger.js +9 -3
  262. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +19 -3
  263. package/node_modules/pi-lens/dist/clients/runtime-context.js +49 -16
  264. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +25 -6
  265. package/node_modules/pi-lens/dist/clients/runtime-session.js +184 -32
  266. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +179 -36
  267. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +797 -243
  268. package/node_modules/pi-lens/dist/clients/runtime-turn.js +1028 -53
  269. package/node_modules/pi-lens/dist/clients/rust-client.js +31 -0
  270. package/node_modules/pi-lens/dist/clients/safe-spawn.js +33 -10
  271. package/node_modules/pi-lens/dist/clients/sanitize.js +7 -12
  272. package/node_modules/pi-lens/dist/clients/scan-utils.js +1 -56
  273. package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +1 -3
  274. package/node_modules/pi-lens/dist/clients/security-scan-client.js +3 -0
  275. package/node_modules/pi-lens/dist/clients/session-lifecycle.js +1 -1
  276. package/node_modules/pi-lens/dist/clients/session-start-observability.js +79 -0
  277. package/node_modules/pi-lens/dist/clients/session-summary.js +0 -24
  278. package/node_modules/pi-lens/dist/clients/sessionstart-logger.js +12 -3
  279. package/node_modules/pi-lens/dist/clients/sgconfig.js +7 -6
  280. package/node_modules/pi-lens/dist/clients/shared-checkout-guard.js +1 -1
  281. package/node_modules/pi-lens/dist/clients/skills-resolver.js +105 -0
  282. package/node_modules/pi-lens/dist/clients/smells-rollup.js +4 -4
  283. package/node_modules/pi-lens/dist/clients/startup-scan.js +2 -10
  284. package/node_modules/pi-lens/dist/clients/string-utils.js +13 -0
  285. package/node_modules/pi-lens/dist/clients/subagent-mode.js +17 -4
  286. package/node_modules/pi-lens/dist/clients/test-runner-client.js +176 -39
  287. package/node_modules/pi-lens/dist/clients/test-runner-delivery.js +244 -0
  288. package/node_modules/pi-lens/dist/clients/tool-definition.js +41 -1
  289. package/node_modules/pi-lens/dist/clients/tool-policy.js +92 -22
  290. package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +40 -40
  291. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +87 -100
  292. package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +2 -2
  293. package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +81 -1
  294. package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +51 -46
  295. package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +28 -0
  296. package/node_modules/pi-lens/dist/clients/tui-fit.js +0 -4
  297. package/node_modules/pi-lens/dist/clients/typos-config.js +5 -0
  298. package/node_modules/pi-lens/dist/clients/user-notify.js +6 -6
  299. package/node_modules/pi-lens/dist/clients/widget-state.js +191 -26
  300. package/node_modules/pi-lens/dist/clients/word-index-logger.js +2 -9
  301. package/node_modules/pi-lens/dist/clients/word-index-store.js +23 -12
  302. package/node_modules/pi-lens/dist/clients/word-index.js +252 -47
  303. package/node_modules/pi-lens/dist/clients/workspace-topology.js +8 -1
  304. package/node_modules/pi-lens/dist/clients/zizmor-config.js +4 -1
  305. package/node_modules/pi-lens/dist/index.js +65899 -55340
  306. package/node_modules/pi-lens/dist/mcp/analyze-cli.js +3 -1
  307. package/node_modules/pi-lens/dist/mcp/build-staleness.js +1 -1
  308. package/node_modules/pi-lens/dist/mcp/server.js +127 -5
  309. package/node_modules/pi-lens/dist/scripts/lib/process-scan.mjs +583 -0
  310. package/node_modules/pi-lens/dist/scripts/lib/skills-predicate.mjs +129 -0
  311. package/node_modules/pi-lens/dist/tools/effective-config.js +89 -0
  312. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +96 -25
  313. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +104 -86
  314. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +37 -16
  315. package/node_modules/pi-lens/dist/tools/lsp-structured-output.js +3 -3
  316. package/node_modules/pi-lens/dist/tools/render-compact.js +1 -1
  317. package/node_modules/pi-lens/dist/tools/shared.js +0 -1
  318. package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -2
  319. package/node_modules/pi-lens/docs/agent-guide.md +64 -1
  320. package/node_modules/pi-lens/docs/configuration.md +222 -0
  321. package/node_modules/pi-lens/docs/dependencies.md +3 -3
  322. package/node_modules/pi-lens/docs/features.md +44 -5
  323. package/node_modules/pi-lens/docs/globalconfig.md +20 -0
  324. package/node_modules/pi-lens/docs/language-coverage.md +2 -2
  325. package/node_modules/pi-lens/docs/lsp-capability-matrix.md +9 -1
  326. package/node_modules/pi-lens/docs/pi-lens-fixer.md +25 -0
  327. package/node_modules/pi-lens/docs/pi-lens-investigator.md +25 -0
  328. package/node_modules/pi-lens/docs/pi-lens-reviewer.md +33 -0
  329. package/node_modules/pi-lens/docs/pi-lens-subagent.md +49 -0
  330. package/node_modules/pi-lens/docs/pi-lens-warden.md +55 -0
  331. package/node_modules/pi-lens/docs/public-api-stability.md +359 -0
  332. package/node_modules/pi-lens/docs/release-qa-baseline.md +190 -0
  333. package/node_modules/pi-lens/docs/servercapabilities.md +7 -3
  334. package/node_modules/pi-lens/docs/subagent-compat.md +110 -30
  335. package/node_modules/pi-lens/docs/tree-sitter_rules_catalog.md +2 -2
  336. package/node_modules/pi-lens/docs/word-index.md +1 -1
  337. package/node_modules/pi-lens/package.json +18 -35
  338. package/node_modules/pi-lens/rules/tree-sitter-queries/python/python-cross-language-method.yml +3 -3
  339. package/node_modules/pi-lens/rules/tree-sitter-queries/python/python-hallucinated-import.yml +2 -2
  340. package/node_modules/pi-lens/rules/tree-sitter-queries/python/python-sql-injection.yml +12 -2
  341. package/node_modules/pi-lens/rules/typos/_typos.toml +4 -2
  342. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +192 -1
  343. package/node_modules/pi-lens/scripts/install-selftest.mjs +58 -2
  344. package/node_modules/pi-lens/scripts/lib/skills-predicate.mjs +129 -0
  345. package/node_modules/pi-lens/scripts/lib/warm-loader-cache.mjs +1 -1
  346. package/node_modules/pi-lens/scripts/rpc-load-check.mjs +3 -1
  347. package/node_modules/pi-lens/scripts/warm-loader-cache.mjs +4 -2
  348. package/node_modules/pi-web-access/CHANGELOG.md +28 -0
  349. package/node_modules/pi-web-access/README.md +62 -15
  350. package/node_modules/pi-web-access/curator-page.ts +3 -1
  351. package/node_modules/pi-web-access/curator-server.ts +5 -1
  352. package/node_modules/pi-web-access/gemini-search.ts +8 -4
  353. package/node_modules/pi-web-access/github-extract.ts +242 -1
  354. package/node_modules/pi-web-access/index.ts +118 -64
  355. package/node_modules/pi-web-access/mistral-search.ts +281 -0
  356. package/node_modules/pi-web-access/package.json +2 -2
  357. package/node_modules/pi-web-access/perplexity.ts +14 -1
  358. package/node_modules/pi-web-access/utils.ts +23 -6
  359. package/node_modules/pi-web-access/xai-search.ts +96 -33
  360. package/package.json +6 -6
@@ -10,16 +10,16 @@
10
10
  */
11
11
  import * as fs from "node:fs";
12
12
  import * as path from "node:path";
13
+ import { incrementDegradationCount, recordDegradationOnce, } from "../../degradation-ledger.js";
13
14
  import { loadAstGrepNapi, } from "../../deps/ast-grep-napi.js";
14
15
  import { minimatch } from "../../deps/minimatch.js";
15
- import { getAstGrepRuleSources, } from "../../sgconfig.js";
16
16
  import { logLatency } from "../../latency-logger.js";
17
+ import { hasAuxiliaryLspPublishedForRoot } from "../../lsp/index.js";
18
+ import { clearPendingAuxiliaryCoverage, hasPendingAuxiliaryCoverage, recordNapiFallbackCoverage, } from "../../lsp/pending-aux-coverage.js";
19
+ import { getAstGrepRuleSources, } from "../../sgconfig.js";
17
20
  import { hasEslintConfig } from "../../tool-policy.js";
18
21
  import { enabledAuxiliaryLspServerIds } from "../auxiliary-lsp.js";
19
22
  import { classifyDefect } from "../diagnostic-taxonomy.js";
20
- import { incrementDegradationCount, recordDegradationOnce, } from "../../degradation-ledger.js";
21
- import { hasAuxiliaryLspPublishedForRoot } from "../../lsp/index.js";
22
- import { clearPendingAuxiliaryCoverage, hasPendingAuxiliaryCoverage, recordNapiFallbackCoverage, } from "../../lsp/pending-aux-coverage.js";
23
23
  import { PRIORITY } from "../priorities.js";
24
24
  import { calculateRuleComplexity, isOverlyBroadPattern, isStructuredRule, loadYamlRules, loadYamlRulesFresh, MAX_BLOCKING_RULE_COMPLEXITY, } from "./yaml-rule-parser.js";
25
25
  const defaultUnsupportedLanguageLog = new Set();
@@ -184,7 +184,9 @@ export async function loadSg() {
184
184
  }
185
185
  })();
186
186
  sgLoadPromise = task;
187
- task.finally(() => {
187
+ // `task` never rejects (the IIFE catches), so the derived promise is inert;
188
+ // `void` records that no consumer awaits it (oxlint no-floating-promises).
189
+ void task.finally(() => {
188
190
  if (sgLoadPromise === task)
189
191
  sgLoadPromise = undefined;
190
192
  });
@@ -436,6 +438,218 @@ export function getLang(filePath, sgModule) {
436
438
  }
437
439
  return lang;
438
440
  }
441
+ /**
442
+ * Budget for embedded-`<script>` evaluation (#2347 review F2/F4). Every nonempty
443
+ * script body is reparsed as JS and EVERY `language: JavaScript` rule runs
444
+ * against it, so the work is `rules * bodies * body-size`, all multiplied by
445
+ * the native addon's per-call overhead. Measured on this seam (full catalog,
446
+ * real addon, 2026-08-30): ~8.5 ms per small body, ~9 s for 500 blocks, and
447
+ * ~19.5 s for one ~1 MiB dense body (the shape that made the byte axis the
448
+ * real bound). The caps apply to EVERY body — first one included — so an
449
+ * oversized single inline script is omitted and recorded like any other
450
+ * over-budget body. Hand-authored HTML carries a handful of small inline
451
+ * scripts, so the caps only ever trip on generated/pathological pages, where a
452
+ * bounded, recorded partial evaluation beats a seconds-long synchronous stall
453
+ * on the per-edit hook. Budget truncation is a coverage loss and is recorded
454
+ * (see `emitHtmlScriptDegradations`).
455
+ */
456
+ export const MAX_SCRIPT_BODIES_EVALUATED = 64;
457
+ /**
458
+ * Cumulative parsed script-body size cap; bounds the `rules * bytes` work.
459
+ * Every body — including the first — must fit within the running total.
460
+ */
461
+ export const MAX_SCRIPT_BODY_BYTES_EVALUATED = 128 * 1024;
462
+ /**
463
+ * UTF-16 code-unit indexes, in the original file, of every line start, newest
464
+ * line last. `@ast-grep/napi` reports line/column/index in UTF-16 code units
465
+ * (verified against 0.45.1 with `é` and emoji), so the line table must be
466
+ * built in the SAME unit; a UTF-8 byte walk would shift every coordinate that
467
+ * follows a multibyte character.
468
+ */
469
+ function computeLineStartsUtf16(content) {
470
+ const starts = [0];
471
+ for (let i = 0; i < content.length; i++) {
472
+ if (content.charCodeAt(i) === 0x0a)
473
+ starts.push(i + 1);
474
+ }
475
+ return starts;
476
+ }
477
+ /** 0-based line and code-unit column for a UTF-16 index, via binary search. */
478
+ function filePositionForIndex(lineStarts, index) {
479
+ let lo = 0;
480
+ let hi = lineStarts.length - 1;
481
+ while (lo < hi) {
482
+ const mid = (lo + hi + 1) >> 1;
483
+ if (lineStarts[mid] <= index)
484
+ lo = mid;
485
+ else
486
+ hi = mid - 1;
487
+ }
488
+ return { line: lo, column: index - lineStarts[lo] };
489
+ }
490
+ /**
491
+ * Extract every `<script>` body from an HTML root and parse it as JavaScript
492
+ * (#2347). Mirrors the ast-grep CLI/LSP: the injection is unconditional —
493
+ * `type` and `src` attributes do not suppress it (verified against the 0.45.1
494
+ * CLI with `text/template`, `application/ld+json`, and `src`-bearing script
495
+ * tags, all injected). Whitespace-only bodies are skipped (nothing to match).
496
+ * A body the JS grammar cannot parse is dropped the way an unparseable `.js`
497
+ * file would be; the failure is counted, never silent. The evaluation budget
498
+ * (count + cumulative bytes) is applied BEFORE any grammar parse. The caller
499
+ * emits the bounded degradation records from the result — collection stays
500
+ * pure so the count evidence is directly testable.
501
+ */
502
+ export function collectHtmlScriptInjections(htmlRoot, sgModule) {
503
+ // SAFETY: `AstGrepNapi` is the loaded addon module's own (typed) shape, so
504
+ // its `js` accessor is guaranteed present while the addon lives; this
505
+ // narrowing only names the subshape this helper consumes (a `js` grammar
506
+ // whose parses expose `findAll`), and the absence check right below
507
+ // degrades to "no embedded coverage" rather than throwing when the addon
508
+ // ever drops the grammar.
509
+ const addon = sgModule;
510
+ if (!addon.js) {
511
+ return {
512
+ injections: [],
513
+ scriptElementCount: 0,
514
+ bodiesEvaluated: 0,
515
+ truncatedBodies: 0,
516
+ parseFailures: 0,
517
+ missingJsGrammar: true,
518
+ htmlScanFailure: false,
519
+ };
520
+ }
521
+ let scripts;
522
+ try {
523
+ scripts = htmlRoot.findAll({ rule: { kind: "script_element" } });
524
+ }
525
+ catch {
526
+ return {
527
+ injections: [],
528
+ scriptElementCount: 0,
529
+ bodiesEvaluated: 0,
530
+ truncatedBodies: 0,
531
+ parseFailures: 0,
532
+ missingJsGrammar: false,
533
+ htmlScanFailure: true,
534
+ };
535
+ }
536
+ // Extract every nonempty body first (text extraction is cheap) so the raw
537
+ // script-element count is exact, then apply the budget BEFORE parsing any
538
+ // of them.
539
+ let scriptElementCount = 0;
540
+ const candidates = [];
541
+ for (const element of scripts) {
542
+ scriptElementCount += 1;
543
+ let raw;
544
+ for (const child of element.children()) {
545
+ if (child.kind() === "raw_text") {
546
+ raw = child;
547
+ break;
548
+ }
549
+ }
550
+ if (!raw)
551
+ continue;
552
+ const body = raw.text();
553
+ if (!body.trim())
554
+ continue;
555
+ candidates.push({
556
+ body,
557
+ startIndex: raw.range().start.index,
558
+ });
559
+ }
560
+ let budgetedBytes = 0;
561
+ const selected = [];
562
+ let truncatedBodies = 0;
563
+ for (const candidate of candidates) {
564
+ const bytes = Buffer.byteLength(candidate.body, "utf8");
565
+ // EVERY body must fit inside both caps — including the first. There is
566
+ // no "one big script" allowance: a single over-cap body (a ~1 MiB dense
567
+ // inline script measured 19.5 s of synchronous rule traversal on this
568
+ // seam) is omitted like any other over-budget body, and the omission is
569
+ // recorded via `truncatedBodies`, so the bounded
570
+ // `ast-grep-napi-html-script-budget` degradation record always explains
571
+ // why that file lost embedded coverage.
572
+ if (selected.length >= MAX_SCRIPT_BODIES_EVALUATED ||
573
+ budgetedBytes + bytes > MAX_SCRIPT_BODY_BYTES_EVALUATED) {
574
+ truncatedBodies += 1;
575
+ continue;
576
+ }
577
+ selected.push(candidate);
578
+ budgetedBytes += bytes;
579
+ }
580
+ const injections = [];
581
+ let parseFailures = 0;
582
+ for (const candidate of selected) {
583
+ try {
584
+ const root = addon.js.parse(candidate.body).root();
585
+ injections.push({
586
+ body: candidate.body,
587
+ startIndex: candidate.startIndex,
588
+ root,
589
+ });
590
+ }
591
+ catch {
592
+ parseFailures += 1;
593
+ }
594
+ }
595
+ return {
596
+ injections,
597
+ scriptElementCount,
598
+ bodiesEvaluated: selected.length,
599
+ truncatedBodies,
600
+ parseFailures,
601
+ missingJsGrammar: false,
602
+ htmlScanFailure: false,
603
+ };
604
+ }
605
+ /**
606
+ * Emit bounded, discriminating degradation records for every embedded-script
607
+ * coverage loss (#2347 review F3). Each failure mode keeps its own kind so the
608
+ * ledger answers WHICH failure and WHICH file; subjects are the normalized file
609
+ * path, bounded by the ledger's own per-kind window. Collection failures
610
+ * (`missingJsGrammar`, `htmlScanFailure`) are once-per-file-per-session
611
+ * categorical events; parse failures and budget truncation are counted per file
612
+ * so the EXACT totals survive past the retained-entry window.
613
+ */
614
+ function emitHtmlScriptDegradations(filePath, result) {
615
+ if (result.missingJsGrammar) {
616
+ recordDegradationOnce({
617
+ kind: "ast-grep-napi-html-js-grammar-missing",
618
+ subject: filePath,
619
+ reason: "addon exposes no js grammar; embedded <script> coverage dropped",
620
+ });
621
+ }
622
+ if (result.htmlScanFailure) {
623
+ recordDegradationOnce({
624
+ kind: "ast-grep-napi-html-script-scan-failed",
625
+ subject: filePath,
626
+ reason: "script_element enumeration failed; embedded <script> coverage dropped",
627
+ });
628
+ }
629
+ if (result.parseFailures > 0) {
630
+ incrementDegradationCount({
631
+ kind: "ast-grep-napi-html-script-parse-failed",
632
+ subject: filePath,
633
+ reason: `${result.parseFailures} of ${result.bodiesEvaluated} script bodies refused to parse as JS`,
634
+ metadata: {
635
+ scriptElementCount: result.scriptElementCount,
636
+ parseFailures: result.parseFailures,
637
+ },
638
+ });
639
+ }
640
+ if (result.truncatedBodies > 0) {
641
+ incrementDegradationCount({
642
+ kind: "ast-grep-napi-html-script-budget",
643
+ subject: filePath,
644
+ reason: `script budget truncated coverage: ${result.bodiesEvaluated}/${result.scriptElementCount} bodies evaluated, ${result.truncatedBodies} dropped`,
645
+ metadata: {
646
+ scriptElementCount: result.scriptElementCount,
647
+ bodiesEvaluated: result.bodiesEvaluated,
648
+ truncatedBodies: result.truncatedBodies,
649
+ },
650
+ });
651
+ }
652
+ }
439
653
  function duplicateRuleIds(rules) {
440
654
  const counts = new Map();
441
655
  for (const rule of rules) {
@@ -512,6 +726,38 @@ export function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}
512
726
  const seenRuleIds = new Set();
513
727
  const suppressLinterOverlap = kind === "jsts" && hasEslintConfig(cwd);
514
728
  const fileLang = ruleLanguageForFile(filePath);
729
+ // Embedded `<script>` coverage (#2347): on an HTML file, every script body
730
+ // is parsed as JavaScript and `language: JavaScript` rules run inside it —
731
+ // the exact behavior the ast-grep CLI/LSP has (verified against 0.45.1).
732
+ // `content` + `sgModule` are only needed for HTML; other callers of this
733
+ // shared seam (the per-edit runner and the project scanner both now pass
734
+ // them) cost a no-op on non-HTML files. The collection is budget-bounded
735
+ // and every silent-failure mode plus the budget cut is recorded, so "no
736
+ // embedded findings" stays distinguishable from "coverage was dropped"
737
+ // (#2347 review F2/F3).
738
+ const htmlCollection = fileLang === "html" &&
739
+ options.content !== undefined &&
740
+ options.sgModule !== undefined
741
+ ? collectHtmlScriptInjections(rootNode, options.sgModule)
742
+ : {
743
+ injections: [],
744
+ scriptElementCount: 0,
745
+ bodiesEvaluated: 0,
746
+ truncatedBodies: 0,
747
+ parseFailures: 0,
748
+ missingJsGrammar: false,
749
+ htmlScanFailure: false,
750
+ };
751
+ const htmlInjections = htmlCollection.injections;
752
+ emitHtmlScriptDegradations(filePath, htmlCollection);
753
+ // UTF-16 code-unit index of each line start in the ORIGINAL file, used to
754
+ // translate an injected match's body-relative UTF-16 index back to file
755
+ // line/column. The unit matters: napi positions are UTF-16, so a UTF-8 byte
756
+ // table would shift every coordinate after a multibyte character (#2347
757
+ // review F1).
758
+ const fileLineStarts = htmlInjections.length > 0 && options.content !== undefined
759
+ ? computeLineStartsUtf16(options.content)
760
+ : [];
515
761
  // Unsupported-language skips are expected in bulk (every non-jsts rule in the
516
762
  // catalog, e.g. ~30 Python rules) — aggregate them into ONE latency-log entry
517
763
  // per evaluation instead of per-rule terminal lines (#282 follow-up).
@@ -547,6 +793,18 @@ export function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}
547
793
  // ship for a language nobody decided a route for, which is the
548
794
  // class this issue closed regrowing.
549
795
  route: skipRouteFor(language),
796
+ // #2347 observability: on an HTML file the per-language skip
797
+ // count is only part of the picture — `mismatch:*->html`
798
+ // entries name a rule family that never enters scripts, and
799
+ // `htmlInlineScriptCount` says whether the file offered any
800
+ // script bodies to enter. A `javascript->html` mismatch here
801
+ // is necessarily `0` (JS rules RUN when scripts exist), so the
802
+ // field makes "no injection target" distinguishable from the
803
+ // same key on a plain non-HTML file, keeping the residual
804
+ // coverage gap countable in production.
805
+ ...(fileLang === "html"
806
+ ? { htmlInlineScriptCount: htmlInjections.length }
807
+ : {}),
550
808
  },
551
809
  ])),
552
810
  },
@@ -627,9 +885,20 @@ export function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}
627
885
  // rules) goes dark on every .tsx file. `language: TSX` rules
628
886
  // stay tsx-exclusive — they're already scoped to fileLang
629
887
  // "tsx" by the exact-match check.
888
+ // #2347: `language: JavaScript` rules run INSIDE an HTML file's
889
+ // embedded `<script>` bodies instead of being filtered out as a
890
+ // language mismatch — that filter is what closed napi's embedded
891
+ // coverage entirely while the ast-grep CLI/LSP resolves the
892
+ // injections itself. Only when the file has at least one inline
893
+ // script body; with none, a `javascript->html` rule stays a
894
+ // genuine mismatch with nothing to run against (countable via
895
+ // `htmlInlineScriptCount` in the skip record).
896
+ const runsInsideHtmlScript = fileLang === "html" &&
897
+ lang === "javascript" &&
898
+ htmlInjections.length > 0;
630
899
  if (lang && fileLang && lang !== fileLang) {
631
900
  const runsAsTsOnTsx = fileLang === "tsx" && lang === "typescript";
632
- if (!runsAsTsOnTsx) {
901
+ if (!runsAsTsOnTsx && !runsInsideHtmlScript) {
633
902
  const key = `mismatch:${lang}->${fileLang}`;
634
903
  if (!unsupportedLanguageLog.has(key)) {
635
904
  const ids = newlyUnsupported.get(key) ?? [];
@@ -648,7 +917,31 @@ export function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}
648
917
  if (!rule.rule)
649
918
  continue;
650
919
  try {
651
- let matches = [];
920
+ // A `language: JavaScript` rule on an HTML file with inline
921
+ // scripts runs against EACH parsed script body; every other rule
922
+ // runs against the file root. `scope.position` maps a match onto
923
+ // 0-based FILE line/column — injection matches are body-relative
924
+ // and must be translated via the injection's `startIndex` and the
925
+ // file's line-start table, all in UTF-16 code units (#2347); the
926
+ // file-root scope is the node's own range, so its derived
927
+ // id/diagnostic stay byte-identical to the pre-#2347 path.
928
+ const scopes = runsInsideHtmlScript
929
+ ? htmlInjections.map((injection) => ({
930
+ root: injection.root,
931
+ position(match) {
932
+ const start = match.range().start;
933
+ return filePositionForIndex(fileLineStarts, injection.startIndex + start.index);
934
+ },
935
+ }))
936
+ : [
937
+ {
938
+ root: rootNode,
939
+ position(match) {
940
+ const start = match.range().start;
941
+ return { line: start.line, column: start.column };
942
+ },
943
+ },
944
+ ];
652
945
  // Delegate matching to napi's native engine, which handles the
653
946
  // full ast-grep rule grammar (pattern, kind, has/inside/follows/
654
947
  // precedes/stopBy/field/nthChild, any/all/not) plus metavariable
@@ -657,28 +950,41 @@ export function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}
657
950
  // (#663; `NapiConfig.utils: Record<string, Rule>` per
658
951
  // @ast-grep/napi's types, same shape napi already expects for
659
952
  // `rule`/`constraints`). A faithful js-yaml parse feeds the rule
660
- // object straight through. If napi rejects the rule (a malformed
661
- // or invalid-kind rule, or an unresolved `matches:` reference),
662
- // skip it — never silently match nothing through a partial
663
- // interpreter.
953
+ // object straight through. If napi rejects the rule for a scope
954
+ // (a malformed or invalid-kind rule, or an unresolved `matches:`
955
+ // reference), skip that scope — never silently match nothing
956
+ // through a partial interpreter. The reject log fires once per
957
+ // rule; a grammar-level rejection is uniform across scopes.
664
958
  const nativeConfig = { rule: rule.rule };
665
959
  if (rule.constraints)
666
960
  nativeConfig.constraints = rule.constraints;
667
961
  if (rule.utils)
668
962
  nativeConfig.utils = rule.utils;
669
- try {
670
- matches = rootNode.findAll(nativeConfig);
671
- }
672
- catch (err) {
673
- matches = [];
674
- log?.(`ast-grep-napi: rule "${rule.id}" rejected by native engine (${err instanceof Error ? err.message : String(err)})`);
963
+ const collected = [];
964
+ let rejectLogged = false;
965
+ for (const scope of scopes) {
966
+ let found;
967
+ try {
968
+ found = scope.root.findAll(nativeConfig);
969
+ }
970
+ catch (err) {
971
+ if (!rejectLogged) {
972
+ rejectLogged = true;
973
+ log?.(`ast-grep-napi: rule "${rule.id}" rejected by native engine (${err instanceof Error ? err.message : String(err)})`);
974
+ }
975
+ continue;
976
+ }
977
+ for (const match of found) {
978
+ if (collected.length >= maxMatchesPerRule)
979
+ break;
980
+ collected.push({ match, position: scope.position(match) });
981
+ }
982
+ if (collected.length >= maxMatchesPerRule)
983
+ break;
675
984
  }
676
- const limitedMatches = matches.slice(0, maxMatchesPerRule);
677
- for (const match of limitedMatches) {
985
+ for (const { position } of collected) {
678
986
  if (diagnostics.length >= maxTotalDiagnostics)
679
987
  break;
680
- const node = match;
681
- const range = node.range();
682
988
  // #1777: carry the rule's own tier through. The old collapse
683
989
  // (`=== "error" ? "error" : "warning"`) erased hint and info,
684
990
  // so the quiet tier the #1727 anti-slop rules ship at did not
@@ -691,11 +997,11 @@ export function evaluateAstGrepRules(filePath, rootNode, cwd, kind, options = {}
691
997
  const defectClass = classifyDefect(rule.id, "ast-grep-napi", rule.message || rule.id);
692
998
  const ruleFix = explicitRuleFixSuggestion(rule);
693
999
  diagnostics.push({
694
- id: `ast-grep-napi-${range.start.line}-${rule.id}`,
1000
+ id: `ast-grep-napi-${position.line}-${rule.id}`,
695
1001
  message: `[${rule.metadata?.category || "slop"}] ${rule.message || rule.id}`,
696
1002
  filePath,
697
- line: range.start.line + 1,
698
- column: range.start.column + 1,
1003
+ line: position.line + 1,
1004
+ column: position.column + 1,
699
1005
  severity,
700
1006
  semantic,
701
1007
  tool: "ast-grep-napi",
@@ -725,7 +1031,6 @@ const astGrepNapiRunner = {
725
1031
  id: "ast-grep-napi",
726
1032
  appliesTo: ["jsts", "css", "html"],
727
1033
  priority: PRIORITY.SPECIALIZED_ANALYSIS,
728
- enabledByDefault: true,
729
1034
  skipTestFiles: true,
730
1035
  async run(ctx) {
731
1036
  if (!canHandle(ctx.filePath)) {
@@ -812,7 +1117,12 @@ const astGrepNapiRunner = {
812
1117
  catch {
813
1118
  return { status: "skipped", diagnostics: [], semantic: "none" };
814
1119
  }
815
- if (astGrepLspEnabled && !astGrepLspPublished) {
1120
+ // #2336: napi is standing in for the ast-grep auxiliary LSP exactly when
1121
+ // that server is expected but has not published for this root. Gate B
1122
+ // above already returned for the published case, so reaching here with
1123
+ // the auxiliary enabled IS the substitute role.
1124
+ const runningAsLspSubstitute = astGrepLspEnabled && !astGrepLspPublished;
1125
+ if (runningAsLspSubstitute) {
816
1126
  // #2324 F3/R2-A/R2-B: napi is about to ACTUALLY EVALUATE RULES —
817
1127
  // every early-return skip above (load failure, missing file,
818
1128
  // unresolved language, stat/size/read/parse failure) is now behind
@@ -837,11 +1147,57 @@ const astGrepNapiRunner = {
837
1147
  recordNapiFallbackCoverage(ctx.filePath);
838
1148
  clearPendingAuxiliaryCoverage(ctx.filePath, "ast-grep");
839
1149
  }
1150
+ // #2336: the substitute runs at the severity floor the server it replaces
1151
+ // would have used. The ast-grep auxiliary profile states that floor in
1152
+ // words — "the rule severity is deliberate, so preserve ast-grep's
1153
+ // severity semantics: ERROR can block, WARNING/INFO stay advisory"
1154
+ // (clients/dispatch/auxiliary-lsp.ts:179-183). `blockingOnly` drops every
1155
+ // rule whose declared severity is not `error`, which is 380 of the 481
1156
+ // bundled rules, so the substitute delivered a fifth of the coverage the
1157
+ // LSP delivers and the runner reported zero diagnostics in all 255
1158
+ // retained dispatch records. Nothing downstream needs the filter for
1159
+ // noise control: `dispatcher.ts` already shows only `semantic:
1160
+ // "blocking"` diagnostics inline and routes warning-tier ones to
1161
+ // lens_diagnostics, and `tree-sitter.ts:525` already runs its full query
1162
+ // set under `blockingOnly` for the same reason.
1163
+ //
1164
+ // Scoped to the substitute role deliberately. Evaluating the full catalog
1165
+ // costs ~6x more per file (measured on this repo: 2.4 ms -> 23 ms at 68
1166
+ // lines, 19 ms -> 188 ms at 1275 lines), and outside the substitute role
1167
+ // either the LSP is publishing (Gate B skipped napi already) or the user
1168
+ // retired ast-grep with `no-ast-grep`. Paying the cost only when napi is
1169
+ // the sole ast-grep surface buys coverage that nothing else provides.
840
1170
  const diagnostics = evaluateAstGrepRules(ctx.filePath, rootNode, ctx.cwd, ctx.kind, {
841
- blockingOnly: ctx.blockingOnly,
1171
+ blockingOnly: runningAsLspSubstitute ? false : ctx.blockingOnly,
842
1172
  projectRoot: ctx.projectRoot,
843
1173
  log: (message) => ctx.log(message),
1174
+ content,
1175
+ sgModule,
844
1176
  });
1177
+ if (runningAsLspSubstitute) {
1178
+ // #2336 observability: the dispatcher's own runner record carries
1179
+ // `diagnosticCount`, which is what showed 0 of 255. It cannot say WHICH
1180
+ // severity floor produced that count. One line per substitute run —
1181
+ // the same cadence as the runner record it annotates — names the floor
1182
+ // and the tier mix, so a future "napi found nothing" reading can tell
1183
+ // an empty catalog pass from a filtered one.
1184
+ const bySeverity = {};
1185
+ for (const d of diagnostics) {
1186
+ bySeverity[d.severity] = (bySeverity[d.severity] ?? 0) + 1;
1187
+ }
1188
+ logLatency({
1189
+ type: "phase",
1190
+ phase: "astgrep_napi_substitute_floor",
1191
+ filePath: ctx.filePath,
1192
+ durationMs: 0,
1193
+ metadata: {
1194
+ floor: "lsp-equivalent",
1195
+ ctxBlockingOnly: ctx.blockingOnly === true,
1196
+ diagnosticCount: diagnostics.length,
1197
+ bySeverity,
1198
+ },
1199
+ });
1200
+ }
845
1201
  const hasBlocking = diagnostics.some((d) => d.semantic === "blocking");
846
1202
  let semantic = "none";
847
1203
  if (hasBlocking) {
@@ -197,7 +197,6 @@ const biomeCheckJsonRunner = {
197
197
  id: "biome-check-json",
198
198
  appliesTo: ["jsts"],
199
199
  priority: PRIORITY.FORMAT_AND_LINT_PRIMARY,
200
- enabledByDefault: true,
201
200
  async run(ctx) {
202
201
  const cwd = ctx.cwd || path.dirname(ctx.filePath);
203
202
  const policy = getJstsLintPolicyForCwd(cwd);
@@ -97,6 +97,10 @@ async function resolveCompiler(absPath, cwd) {
97
97
  flavor: "msvc",
98
98
  };
99
99
  }
100
+ // Mirrors the deliberate global-PATH probes in utils/runner-helpers.ts:
101
+ // this never resolves a config file or a target path, so there is no cwd
102
+ // for it to get wrong.
103
+ // cwd-exempt: presence probe only -- `cl` with no args and no target file, used solely to detect whether MSVC is on PATH
100
104
  const clProbe = await safeSpawnAsync("cl", [], { timeout: 5000 });
101
105
  if (!clProbe.error && clProbe.status !== null) {
102
106
  return {
@@ -175,7 +179,6 @@ const cppCheckRunner = {
175
179
  id: "cpp-check",
176
180
  appliesTo: ["cxx"],
177
181
  priority: PRIORITY.GENERAL_ANALYSIS,
178
- enabledByDefault: true,
179
182
  skipTestFiles: false,
180
183
  async run(ctx) {
181
184
  const cwd = ctx.cwd || process.cwd();
@@ -48,7 +48,6 @@ const credoRunner = {
48
48
  id: "credo",
49
49
  appliesTo: ["elixir"],
50
50
  priority: PRIORITY.GENERAL_ANALYSIS,
51
- enabledByDefault: true,
52
51
  skipTestFiles: false,
53
52
  async run(ctx) {
54
53
  const cwd = ctx.cwd || process.cwd();
@@ -278,7 +278,6 @@ const cueVetRunner = {
278
278
  id: "cue-vet",
279
279
  appliesTo: ["cue"],
280
280
  priority: PRIORITY.GENERAL_ANALYSIS,
281
- enabledByDefault: true,
282
281
  skipTestFiles: false,
283
282
  timeoutMs: 30_000,
284
283
  async run(ctx) {
@@ -145,7 +145,6 @@ const dartAnalyzeRunner = {
145
145
  id: "dart-analyze",
146
146
  appliesTo: ["dart"],
147
147
  priority: PRIORITY.GENERAL_ANALYSIS,
148
- enabledByDefault: true,
149
148
  skipTestFiles: false,
150
149
  async run(ctx) {
151
150
  const cwd = ctx.cwd || process.cwd();
@@ -126,7 +126,6 @@ const detektRunner = {
126
126
  id: "detekt",
127
127
  appliesTo: ["kotlin"],
128
128
  priority: PRIORITY.GENERAL_ANALYSIS,
129
- enabledByDefault: true,
130
129
  timeoutMs: 90_000,
131
130
  skipTestFiles: false,
132
131
  async run(ctx) {
@@ -115,7 +115,6 @@ const dotnetBuildRunner = {
115
115
  id: "dotnet-build",
116
116
  appliesTo: ["csharp"],
117
117
  priority: PRIORITY.GENERAL_ANALYSIS,
118
- enabledByDefault: true,
119
118
  timeoutMs: 90_000,
120
119
  skipTestFiles: false,
121
120
  async run(ctx) {
@@ -139,7 +139,6 @@ const elixirCheckRunner = {
139
139
  id: "elixir-check",
140
140
  appliesTo: ["elixir"],
141
141
  priority: PRIORITY.GENERAL_ANALYSIS,
142
- enabledByDefault: true,
143
142
  skipTestFiles: false,
144
143
  async run(ctx) {
145
144
  const cwd = ctx.cwd || process.cwd();
@@ -78,7 +78,6 @@ const eslintRunner = {
78
78
  id: "eslint",
79
79
  appliesTo: ["jsts"],
80
80
  priority: PRIORITY.LINT_SECONDARY,
81
- enabledByDefault: true,
82
81
  async run(ctx) {
83
82
  const cwd = ctx.cwd || process.cwd();
84
83
  const userHasConfig = hasEslintConfig(cwd);
@@ -13,7 +13,6 @@ const factRulesRunner = {
13
13
  id: "fact-rules",
14
14
  appliesTo: ["jsts", "python", "go", "rust", "ruby", "shell", "cmake"],
15
15
  priority: PRIORITY.GENERAL_ANALYSIS + 1,
16
- enabledByDefault: true,
17
16
  async run(ctx) {
18
17
  const diagnostics = evaluateRules(ctx);
19
18
  if (diagnostics.length === 0) {
@@ -7,7 +7,6 @@ const fishIndentRunner = {
7
7
  id: "fish-indent",
8
8
  appliesTo: ["fish"],
9
9
  priority: PRIORITY.FORMAT_AND_LINT_PRIMARY,
10
- enabledByDefault: true,
11
10
  skipTestFiles: false,
12
11
  async run(ctx) {
13
12
  const cwd = ctx.cwd || process.cwd();
@@ -39,7 +39,6 @@ const gleamCheckRunner = {
39
39
  id: "gleam-check",
40
40
  appliesTo: ["gleam"],
41
41
  priority: PRIORITY.GENERAL_ANALYSIS,
42
- enabledByDefault: true,
43
42
  skipTestFiles: false,
44
43
  async run(ctx) {
45
44
  const cwd = ctx.cwd || process.cwd();
@@ -4,18 +4,16 @@
4
4
  * Runs `go vet` for Go files to catch common mistakes.
5
5
  */
6
6
  import { relative, resolve, sep, posix } from "node:path";
7
- import { GoClient } from "../../go-client.js";
7
+ import { goClient } from "../../go-client.js";
8
8
  import { safeSpawnAsync } from "../../safe-spawn.js";
9
9
  import { stripAnsi } from "../../sanitize.js";
10
10
  import { skipUnlessToolRan } from "./utils/tool-failure.js";
11
11
  import { parseGoVetOutput } from "./utils/diagnostic-parsers.js";
12
12
  import { PRIORITY } from "../priorities.js";
13
- const goClient = new GoClient();
14
13
  const goVetRunner = {
15
14
  id: "go-vet",
16
15
  appliesTo: ["go"],
17
16
  priority: PRIORITY.SPECIALIZED_ANALYSIS,
18
- enabledByDefault: true,
19
17
  timeoutMs: 40_000,
20
18
  async run(ctx) {
21
19
  // Resolve go path using platform-aware lookup (handles system install paths on Windows)
@@ -78,7 +78,6 @@ const golangciRunner = {
78
78
  id: "golangci-lint",
79
79
  appliesTo: ["go"],
80
80
  priority: PRIORITY.GENERAL_ANALYSIS,
81
- enabledByDefault: true,
82
81
  timeoutMs: 90_000,
83
82
  async run(ctx) {
84
83
  const cwd = ctx.cwd || process.cwd();