@herbertgao/pi-extensions 2026.8.6 → 2026.8.8

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 (385) hide show
  1. package/README.md +8 -6
  2. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +2 -2
  3. package/node_modules/@herbertgao/pi-cc-extensions/README.md +2 -2
  4. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +19 -7
  5. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +30 -9
  6. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +320 -22
  7. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +94 -77
  8. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/message-display.ts +79 -17
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +27 -0
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +66 -17
  11. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/layout.ts +41 -2
  12. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +75 -6
  13. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/types.ts +7 -3
  14. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +64 -1
  15. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  16. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +6 -0
  17. package/node_modules/@herbertgao/pi-subagents/README.md +30 -22
  18. package/node_modules/@herbertgao/pi-subagents/examples/agent-tool-description.md +5 -5
  19. package/node_modules/@herbertgao/pi-subagents/package.json +7 -7
  20. package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +7 -1
  21. package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +48 -19
  22. package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +17 -13
  23. package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +26 -2
  24. package/node_modules/@herbertgao/pi-subagents/src/index.ts +219 -40
  25. package/node_modules/@herbertgao/pi-subagents/src/invocation-config.ts +101 -3
  26. package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +18 -4
  27. package/node_modules/@herbertgao/pi-subagents/src/settings.ts +99 -0
  28. package/node_modules/@herbertgao/pi-subagents/src/types.ts +22 -3
  29. package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +51 -3
  30. package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +20 -2
  31. package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +21 -6
  32. package/node_modules/@herbertgao/pi-subagents/src/usage.ts +129 -1
  33. package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +20 -0
  34. package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +5 -4
  35. package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +174 -100
  36. package/node_modules/@juicesharp/rpiv-ask-user-question/config.ts +25 -0
  37. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/configuration.md +13 -4
  38. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +5 -1
  39. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/keyboard.md +10 -2
  40. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/localization.md +10 -6
  41. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/tool-schema.md +11 -5
  42. package/node_modules/@juicesharp/rpiv-ask-user-question/locales/en.json +5 -2
  43. package/node_modules/@juicesharp/rpiv-ask-user-question/locales/zh.json +2 -2
  44. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +3 -2
  45. package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +10 -0
  46. package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +140 -97
  47. package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +63 -28
  48. package/node_modules/@juicesharp/rpiv-ask-user-question/state/selectors/projections.ts +22 -15
  49. package/node_modules/@juicesharp/rpiv-ask-user-question/state/state-reducer.ts +11 -1
  50. package/node_modules/@juicesharp/rpiv-ask-user-question/state/state.ts +14 -6
  51. package/node_modules/@juicesharp/rpiv-ask-user-question/tool/response-envelope.ts +11 -0
  52. package/node_modules/@juicesharp/rpiv-ask-user-question/tool/types.ts +11 -0
  53. package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/multi-select-view.ts +31 -17
  54. package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/preview/preview-block-renderer.ts +15 -6
  55. package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/wrapping-select.ts +15 -6
  56. package/node_modules/@juicesharp/rpiv-ask-user-question/view/dialog-builder.ts +86 -38
  57. package/node_modules/@juicesharp/rpiv-ask-user-question/view/tab-content-strategy.ts +76 -9
  58. package/node_modules/@narumitw/pi-btw/README.md +120 -111
  59. package/node_modules/@narumitw/pi-btw/dist/index.ts +2898 -0
  60. package/node_modules/@narumitw/pi-btw/dist/index.ts.map +7 -0
  61. package/node_modules/@narumitw/pi-btw/package.json +10 -6
  62. package/node_modules/@narumitw/pi-btw/src/btw.ts +36 -40
  63. package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +55 -10
  64. package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +390 -0
  65. package/node_modules/@narumitw/pi-btw/src/menu.ts +45 -2
  66. package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +136 -45
  67. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs +44 -1856
  68. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs.map +1 -1
  69. package/node_modules/@pi-plugins/fast-mode/package.json +4 -6
  70. package/node_modules/pi-lens/CHANGELOG.md +999 -0
  71. package/node_modules/pi-lens/README.md +117 -3
  72. package/node_modules/pi-lens/config/ruff/core.toml +42 -0
  73. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +130 -27
  74. package/node_modules/pi-lens/dist/clients/advisory-provenance.js +126 -13
  75. package/node_modules/pi-lens/dist/clients/agent-nudge.js +67 -11
  76. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +9 -3
  77. package/node_modules/pi-lens/dist/clients/atomic-write.js +9 -3
  78. package/node_modules/pi-lens/dist/clients/bash-file-access.js +381 -13
  79. package/node_modules/pi-lens/dist/clients/biome-client.js +61 -30
  80. package/node_modules/pi-lens/dist/clients/blocker-freshness.js +428 -0
  81. package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +129 -0
  82. package/node_modules/pi-lens/dist/clients/bootstrap.js +12 -1
  83. package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +12 -3
  84. package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +206 -0
  85. package/node_modules/pi-lens/dist/clients/cache-observability.js +353 -76
  86. package/node_modules/pi-lens/dist/clients/cascade-budget.js +196 -0
  87. package/node_modules/pi-lens/dist/clients/cascade-format.js +20 -1
  88. package/node_modules/pi-lens/dist/clients/cascade-types.js +9 -1
  89. package/node_modules/pi-lens/dist/clients/child-unref.js +54 -6
  90. package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +76 -24
  91. package/node_modules/pi-lens/dist/clients/dead-code-client.js +123 -31
  92. package/node_modules/pi-lens/dist/clients/deadline-utils.js +8 -1
  93. package/node_modules/pi-lens/dist/clients/debug-handles.js +5 -0
  94. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +84 -14
  95. package/node_modules/pi-lens/dist/clients/demoted-finding-render.js +155 -0
  96. package/node_modules/pi-lens/dist/clients/dependency-checker.js +25 -3
  97. package/node_modules/pi-lens/dist/clients/deps/pi-tui.js +8 -2
  98. package/node_modules/pi-lens/dist/clients/deps/typebox.js +8 -3
  99. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +147 -33
  100. package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +298 -0
  101. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +52 -2
  102. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +256 -88
  103. package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +7 -4
  104. package/node_modules/pi-lens/dist/clients/dispatch/plan.js +5 -0
  105. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +234 -18
  106. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +187 -19
  107. package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +6 -3
  108. package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +11 -9
  109. package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +398 -0
  110. package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +9 -6
  111. package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +11 -3
  112. package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +12 -7
  113. package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +18 -0
  114. package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +9 -7
  115. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +895 -0
  116. package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +8 -6
  117. package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +4 -0
  118. package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +16 -3
  119. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +60 -53
  120. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +16 -2
  121. package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +25 -2
  122. package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +20 -5
  123. package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +44 -11
  124. package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +331 -55
  125. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +38 -5
  126. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +97 -19
  127. package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +17 -8
  128. package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +32 -4
  129. package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +47 -3
  130. package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +14 -4
  131. package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +127 -28
  132. package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +12 -7
  133. package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +73 -12
  134. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +275 -13
  135. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +21 -6
  136. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +260 -27
  137. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +734 -64
  138. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +86 -11
  139. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +188 -0
  140. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +9 -0
  141. package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +21 -10
  142. package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +18 -2
  143. package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +4 -2
  144. package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +28 -5
  145. package/node_modules/pi-lens/dist/clients/extension-log.js +22 -1
  146. package/node_modules/pi-lens/dist/clients/file-kinds.js +8 -2
  147. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +316 -0
  148. package/node_modules/pi-lens/dist/clients/finding-identity.js +88 -0
  149. package/node_modules/pi-lens/dist/clients/formatters-lazy.js +3 -2
  150. package/node_modules/pi-lens/dist/clients/formatters.js +500 -115
  151. package/node_modules/pi-lens/dist/clients/generation-guard.js +216 -0
  152. package/node_modules/pi-lens/dist/clients/git-guard.js +31 -0
  153. package/node_modules/pi-lens/dist/clients/gitleaks-client.js +181 -8
  154. package/node_modules/pi-lens/dist/clients/govulncheck-client.js +109 -9
  155. package/node_modules/pi-lens/dist/clients/grammar-source.js +333 -10
  156. package/node_modules/pi-lens/dist/clients/host-ports.js +8 -0
  157. package/node_modules/pi-lens/dist/clients/installer/index.js +1114 -100
  158. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh-session.js +58 -0
  159. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +715 -0
  160. package/node_modules/pi-lens/dist/clients/instance-reaper.js +643 -97
  161. package/node_modules/pi-lens/dist/clients/instance-registry.js +87 -17
  162. package/node_modules/pi-lens/dist/clients/jscpd-client.js +87 -8
  163. package/node_modules/pi-lens/dist/clients/knip-client.js +310 -10
  164. package/node_modules/pi-lens/dist/clients/language-policy.js +8 -2
  165. package/node_modules/pi-lens/dist/clients/language-profile.js +9 -2
  166. package/node_modules/pi-lens/dist/clients/latency-logger.js +440 -11
  167. package/node_modules/pi-lens/dist/clients/lazy-import.js +21 -0
  168. package/node_modules/pi-lens/dist/clients/ledger-bounds.js +21 -0
  169. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +8 -0
  170. package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +128 -8
  171. package/node_modules/pi-lens/dist/clients/lsp/client.js +1660 -164
  172. package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +83 -1
  173. package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +389 -0
  174. package/node_modules/pi-lens/dist/clients/lsp/index.js +2423 -151
  175. package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +215 -0
  176. package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +146 -14
  177. package/node_modules/pi-lens/dist/clients/lsp/language.js +48 -4
  178. package/node_modules/pi-lens/dist/clients/lsp/server.js +277 -16
  179. package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +22 -0
  180. package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +43 -0
  181. package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +79 -3
  182. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +43 -0
  183. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +422 -28
  184. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-session.js +30 -0
  185. package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +175 -0
  186. package/node_modules/pi-lens/dist/clients/lsp-lazy.js +3 -2
  187. package/node_modules/pi-lens/dist/clients/mcp/session.js +10 -2
  188. package/node_modules/pi-lens/dist/clients/module-report.js +22 -1
  189. package/node_modules/pi-lens/dist/clients/ndjson-logger.js +114 -23
  190. package/node_modules/pi-lens/dist/clients/opengrep-client.js +15 -1
  191. package/node_modules/pi-lens/dist/clients/package-manager.js +170 -14
  192. package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +27 -0
  193. package/node_modules/pi-lens/dist/clients/path-utils.js +160 -0
  194. package/node_modules/pi-lens/dist/clients/pipeline.js +154 -33
  195. package/node_modules/pi-lens/dist/clients/post-autofix-notice.js +37 -0
  196. package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +17 -3
  197. package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +89 -22
  198. package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +84 -14
  199. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +15 -3
  200. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +50 -2
  201. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +23 -9
  202. package/node_modules/pi-lens/dist/clients/project-lens-config.js +3 -0
  203. package/node_modules/pi-lens/dist/clients/project-report.js +62 -27
  204. package/node_modules/pi-lens/dist/clients/project-snapshot.js +299 -0
  205. package/node_modules/pi-lens/dist/clients/quiet-window-config.js +47 -0
  206. package/node_modules/pi-lens/dist/clients/quiet-window.js +11 -25
  207. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +8 -3
  208. package/node_modules/pi-lens/dist/clients/read-guard.js +253 -10
  209. package/node_modules/pi-lens/dist/clients/resource-sampler.js +49 -17
  210. package/node_modules/pi-lens/dist/clients/reverse-deps.js +50 -11
  211. package/node_modules/pi-lens/dist/clients/review-graph/builder.js +194 -31
  212. package/node_modules/pi-lens/dist/clients/review-graph/query.js +52 -4
  213. package/node_modules/pi-lens/dist/clients/review-graph/revision-drift.js +21 -0
  214. package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +6 -3
  215. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +96 -7
  216. package/node_modules/pi-lens/dist/clients/runtime-context.js +8 -1
  217. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +352 -45
  218. package/node_modules/pi-lens/dist/clients/runtime-session.js +373 -9
  219. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +217 -22
  220. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +212 -79
  221. package/node_modules/pi-lens/dist/clients/runtime-turn.js +620 -67
  222. package/node_modules/pi-lens/dist/clients/safe-spawn.js +220 -7
  223. package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +161 -0
  224. package/node_modules/pi-lens/dist/clients/search-read-registration.js +34 -6
  225. package/node_modules/pi-lens/dist/clients/security-scan-client.js +157 -24
  226. package/node_modules/pi-lens/dist/clients/session-event-guard.js +184 -0
  227. package/node_modules/pi-lens/dist/clients/sg-runner.js +116 -22
  228. package/node_modules/pi-lens/dist/clients/single-flight.js +158 -0
  229. package/node_modules/pi-lens/dist/clients/source-filter.js +6 -2
  230. package/node_modules/pi-lens/dist/clients/stale-marker.js +17 -0
  231. package/node_modules/pi-lens/dist/clients/startup-scan.js +5 -2
  232. package/node_modules/pi-lens/dist/clients/startup-timing.js +19 -1
  233. package/node_modules/pi-lens/dist/clients/test-runner-client.js +151 -16
  234. package/node_modules/pi-lens/dist/clients/tool-event.js +56 -5
  235. package/node_modules/pi-lens/dist/clients/tool-policy.js +125 -20
  236. package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +75 -1
  237. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +769 -64
  238. package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +1 -0
  239. package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +11 -0
  240. package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +90 -0
  241. package/node_modules/pi-lens/dist/clients/trivy-client.js +19 -1
  242. package/node_modules/pi-lens/dist/clients/widget-state.js +336 -36
  243. package/node_modules/pi-lens/dist/clients/zizmor-config.js +214 -14
  244. package/node_modules/pi-lens/dist/index.js +61407 -48577
  245. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +476 -57
  246. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +132 -43
  247. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -7
  248. package/node_modules/pi-lens/docs/agent-guide.md +6 -1
  249. package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +515 -506
  250. package/node_modules/pi-lens/docs/dispositions.md +21 -0
  251. package/node_modules/pi-lens/docs/features.md +19 -5
  252. package/node_modules/pi-lens/docs/globalconfig.md +3 -0
  253. package/node_modules/pi-lens/docs/language-coverage.md +71 -5
  254. package/node_modules/pi-lens/docs/mcp.md +2 -2
  255. package/node_modules/pi-lens/docs/servercapabilities.md +4 -1
  256. package/node_modules/pi-lens/docs/settings.md +19 -1
  257. package/node_modules/pi-lens/docs/usage.md +1 -0
  258. package/node_modules/pi-lens/package.json +27 -10
  259. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-js-snapshot.yml +23 -0
  260. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-snapshot.yml +23 -0
  261. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/ts-void-zero-snapshot.yml +23 -0
  262. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-object-param-test.yml +16 -0
  263. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +15 -1
  264. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-compile-call-test.yml +29 -1
  265. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-dupe-class-members-test.yml +33 -0
  266. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-js-test.yml +7 -1
  267. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-test.yml +7 -1
  268. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-known-value-widening-test.yml +9 -0
  269. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-non-null-assertion-test.yml +216 -0
  270. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +2 -0
  271. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +2 -0
  272. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +2 -1
  273. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +2 -1
  274. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-return-value-in-generator-test.yml +12 -0
  275. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-runtime-typeof-test.yml +33 -0
  276. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-server-bind-wildcard-test.yml +9 -0
  277. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-shape-in-symbol-names-test.yml +13 -0
  278. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-js-test.yml +5 -1
  279. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-test.yml +5 -1
  280. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-parameters-test.yml +12 -0
  281. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-returns-test.yml +16 -0
  282. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-any-test.yml +10 -0
  283. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-unknown-test.yml +8 -0
  284. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/redundant-unsafe-function-test.yml +35 -0
  285. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/require-safety-comment-for-as-unknown-as-test.yml +177 -0
  286. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/ts-void-zero-test.yml +1 -0
  287. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member-js.yml +13 -2
  288. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member.yml +13 -2
  289. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +2 -0
  290. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-object-param.yml +60 -0
  291. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +57 -12
  292. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-compile-call.yml +63 -5
  293. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-dupe-class-members.yml +52 -8
  294. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html-js.yml +27 -2
  295. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html.yml +27 -2
  296. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-known-value-widening.yml +71 -0
  297. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-non-null-assertion.yml +316 -0
  298. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +7 -0
  299. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +22 -2
  300. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +23 -2
  301. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +33 -5
  302. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +34 -8
  303. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-return-value-in-generator.yml +22 -5
  304. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-runtime-typeof.yml +121 -0
  305. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-server-bind-wildcard.yml +23 -7
  306. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-shape-in-symbol-names.yml +68 -0
  307. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code-js.yml +41 -2
  308. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code.yml +41 -2
  309. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +6 -1
  310. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-parameters.yml +67 -0
  311. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-returns.yml +106 -0
  312. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-any.yml +50 -0
  313. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-unknown.yml +56 -0
  314. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +2 -0
  315. package/node_modules/pi-lens/rules/ast-grep-rules/rules/redundant-unsafe-function.yml +32 -0
  316. package/node_modules/pi-lens/rules/ast-grep-rules/rules/require-safety-comment-for-as-unknown-as.yml +184 -0
  317. package/node_modules/pi-lens/rules/ast-grep-rules/rules/ts-void-zero.yml +5 -0
  318. package/node_modules/pi-lens/rules/ast-grep-rules/self-scan-baseline.json +5 -0
  319. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +53 -1
  320. package/node_modules/pi-lens/scripts/download-grammars.js +25 -0
  321. package/node_modules/pi-lens/scripts/grammars.lock.json +9 -0
  322. package/node_modules/pi-lens/scripts/install-selftest.mjs +99 -11
  323. package/node_modules/pi-lens/scripts/lib/host-provided-deps.mjs +75 -0
  324. package/node_modules/pi-lens/scripts/lib/warm-loader-cache.mjs +285 -0
  325. package/node_modules/pi-lens/scripts/warm-loader-cache.mjs +233 -0
  326. package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +2 -0
  327. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +80 -3
  328. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +41 -0
  329. package/node_modules/pi-lens/vendor/grammars/tree-sitter-cue.wasm +0 -0
  330. package/node_modules/pi-mcp-adapter/CHANGELOG.md +36 -0
  331. package/node_modules/pi-mcp-adapter/README.md +47 -5
  332. package/node_modules/pi-mcp-adapter/cli.js +163 -1
  333. package/node_modules/pi-mcp-adapter/commands.ts +128 -22
  334. package/node_modules/pi-mcp-adapter/config.ts +25 -7
  335. package/node_modules/pi-mcp-adapter/direct-tools.ts +5 -4
  336. package/node_modules/pi-mcp-adapter/index.ts +219 -32
  337. package/node_modules/pi-mcp-adapter/init.ts +36 -4
  338. package/node_modules/pi-mcp-adapter/lifecycle.ts +315 -24
  339. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +39 -6
  340. package/node_modules/pi-mcp-adapter/mcp-bearer-store.ts +387 -0
  341. package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +27 -3
  342. package/node_modules/pi-mcp-adapter/mcp-code.ts +4 -0
  343. package/node_modules/pi-mcp-adapter/mcp-panel.ts +42 -13
  344. package/node_modules/pi-mcp-adapter/metadata-cache.ts +32 -21
  345. package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +168 -0
  346. package/node_modules/pi-mcp-adapter/package.json +3 -1
  347. package/node_modules/pi-mcp-adapter/proxy-modes.ts +5 -4
  348. package/node_modules/pi-mcp-adapter/request-headers-command.ts +31 -37
  349. package/node_modules/pi-mcp-adapter/search-ranking.ts +92 -22
  350. package/node_modules/pi-mcp-adapter/server-manager.ts +140 -2
  351. package/node_modules/pi-mcp-adapter/session-recovery.ts +7 -0
  352. package/node_modules/pi-mcp-adapter/tool-approval.ts +15 -2
  353. package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +44 -4
  354. package/node_modules/pi-mcp-adapter/types.ts +2 -0
  355. package/node_modules/pi-mcp-adapter/ui-server.ts +18 -16
  356. package/node_modules/pi-mcp-adapter/utils.ts +70 -0
  357. package/node_modules/pi-web-access/CHANGELOG.md +37 -0
  358. package/node_modules/pi-web-access/README.md +32 -13
  359. package/node_modules/pi-web-access/anysearch.ts +4 -2
  360. package/node_modules/pi-web-access/brave.ts +16 -4
  361. package/node_modules/pi-web-access/chrome-cookies.ts +86 -15
  362. package/node_modules/pi-web-access/curator-page.ts +6 -3
  363. package/node_modules/pi-web-access/curator-server.ts +4 -1
  364. package/node_modules/pi-web-access/data-uri-sanitize.ts +406 -0
  365. package/node_modules/pi-web-access/exa.ts +18 -7
  366. package/node_modules/pi-web-access/extract.ts +40 -5
  367. package/node_modules/pi-web-access/firecrawl.ts +18 -2
  368. package/node_modules/pi-web-access/gemini-search.ts +16 -4
  369. package/node_modules/pi-web-access/github-extract.ts +65 -36
  370. package/node_modules/pi-web-access/index.ts +60 -61
  371. package/node_modules/pi-web-access/openai-search.ts +17 -6
  372. package/node_modules/pi-web-access/package.json +1 -1
  373. package/node_modules/pi-web-access/page-query.ts +4 -2
  374. package/node_modules/pi-web-access/parallel-mcp.ts +249 -0
  375. package/node_modules/pi-web-access/parallel.ts +2 -2
  376. package/node_modules/pi-web-access/pdf-extract.ts +18 -5
  377. package/node_modules/pi-web-access/query-rewrite.ts +51 -0
  378. package/node_modules/pi-web-access/serper.ts +211 -0
  379. package/node_modules/pi-web-access/ssrf-protection.ts +12 -2
  380. package/node_modules/pi-web-access/summary-model-scope.ts +12 -4
  381. package/node_modules/pi-web-access/summary-review.ts +44 -22
  382. package/node_modules/pi-web-access/tavily.ts +16 -4
  383. package/node_modules/pi-web-access/utils.ts +87 -0
  384. package/node_modules/pi-web-access/valyu.ts +199 -0
  385. package/package.json +14 -14
@@ -3,7 +3,7 @@ import { safeSpawnAsync } from "../../safe-spawn.js";
3
3
  import { getLinterPolicyForCwd } from "../../tool-policy.js";
4
4
  import { PRIORITY } from "../priorities.js";
5
5
  import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
6
- import { spawnFailedWithNoOutput } from "./utils/spawn-outcome.js";
6
+ import { parseToolRun } from "./utils/tool-failure.js";
7
7
  const htmlhint = createAvailabilityChecker("htmlhint");
8
8
  const HTMLHINT_RULES = {
9
9
  "tag-pair": true,
@@ -55,7 +55,7 @@ const htmlhintRunner = {
55
55
  return { status: "skipped", diagnostics: [], semantic: "none" };
56
56
  }
57
57
  let cmd = null;
58
- if (await (htmlhint.isAvailableAsync(cwd))) {
58
+ if (await htmlhint.isAvailableAsync(cwd)) {
59
59
  cmd = htmlhint.getCommand(cwd);
60
60
  }
61
61
  else {
@@ -72,11 +72,13 @@ const htmlhintRunner = {
72
72
  "unix",
73
73
  path.resolve(cwd, ctx.filePath),
74
74
  ], { cwd });
75
+ // #1948: htmlhint exits 1 when it finds errors and prints them in `unix`
76
+ // format on stdout. Zero parsed out of a nonzero exit is a parser break.
75
77
  const output = result.stdout || result.stderr || "";
76
- if (spawnFailedWithNoOutput(result, output)) {
77
- return { status: "skipped", diagnostics: [], semantic: "none" };
78
- }
79
- const diagnostics = parseHtmlhintOutput(output, ctx.filePath);
78
+ const run = parseToolRun("htmlhint", { result, output }, (out) => parseHtmlhintOutput(out, ctx.filePath));
79
+ if (run.skipped)
80
+ return run.skipped;
81
+ const diagnostics = run.diagnostics;
80
82
  if (diagnostics.length === 0) {
81
83
  return { status: "succeeded", diagnostics: [], semantic: "none" };
82
84
  }
@@ -6,6 +6,7 @@ import astGrepNapiRunner from "./ast-grep-napi.js";
6
6
  import biomeCheckJsonRunner from "./biome-check.js";
7
7
  import cppCheckRunner from "./cpp-check.js";
8
8
  import credoRunner from "./credo.js";
9
+ import cueVetRunner from "./cue-vet.js";
9
10
  import dartAnalyzeRunner from "./dart-analyze.js";
10
11
  import detektRunner from "./detekt.js";
11
12
  import dotnetBuildRunner from "./dotnet-build.js";
@@ -17,6 +18,7 @@ import goVetRunner from "./go-vet.js";
17
18
  import golangciRunner from "./golangci-lint.js";
18
19
  import hadolintRunner from "./hadolint.js";
19
20
  import helmLintRunner from "./helm-lint.js";
21
+ import helmRenderRunner from "./helm-render.js";
20
22
  import htmlhintRunner from "./htmlhint.js";
21
23
  import javacRunner from "./javac.js";
22
24
  import ktlintRunner from "./ktlint.js";
@@ -84,6 +86,7 @@ export function registerDefaultRunners(registry) {
84
86
  registry.register(htmlhintRunner); // HTML linting — tag pairs, attribute rules (priority 20)
85
87
  registry.register(hadolintRunner); // Dockerfile linting — syntax, best practices (priority 20)
86
88
  registry.register(helmLintRunner); // Helm chart linting (priority 20)
89
+ registry.register(helmRenderRunner); // Rendered-manifest validation (priority 20, helm.renderValidation.enabled-gated, off by default)
87
90
  registry.register(valeRunner); // Prose/style linting for Markdown — config-gated (.vale.ini) (priority 30)
88
91
  registry.register(phpLintRunner); // PHP syntax validation via php -l (priority 20)
89
92
  registry.register(psScriptAnalyzerRunner); // PowerShell linting via PSScriptAnalyzer module (priority 20)
@@ -103,4 +106,5 @@ export function registerDefaultRunners(registry) {
103
106
  registry.register(credoRunner); // Elixir static analysis via credo (priority 20, mix.exs-gated)
104
107
  registry.register(elixirCheckRunner); // Elixir compile/syntax diagnostics via mix/elixirc (priority 20)
105
108
  registry.register(phpstanRunner); // PHP static analysis via phpstan (priority 20, config-gated)
109
+ registry.register(cueVetRunner); // CUE evaluation-error validation via cue vet (priority 20) — covers the class cuelsp doesn't publish
106
110
  }
@@ -1,5 +1,6 @@
1
1
  import * as path from "node:path";
2
2
  import { safeSpawnAsync } from "../../safe-spawn.js";
3
+ import { hasJavaBuildDescriptor } from "../../tool-policy.js";
3
4
  import { PRIORITY } from "../priorities.js";
4
5
  import { createAvailabilityChecker } from "./utils/runner-helpers.js";
5
6
  const javac = createAvailabilityChecker("javac", ".exe");
@@ -24,7 +25,9 @@ function parseJavacOutput(raw, filePath) {
24
25
  line: lineNum,
25
26
  column: 1,
26
27
  severity,
27
- semantic: severity === "error" ? "blocking" : "warning",
28
+ // A standalone single-file javac run has no project classpath. It can
29
+ // report useful syntax/type evidence, but it cannot prove a blocker.
30
+ semantic: "warning",
28
31
  tool: "javac",
29
32
  rule: "compile",
30
33
  fixable: false,
@@ -40,6 +43,17 @@ const javacRunner = {
40
43
  skipTestFiles: false,
41
44
  async run(ctx) {
42
45
  const cwd = ctx.cwd || process.cwd();
46
+ const absPath = path.resolve(cwd, ctx.filePath);
47
+ // Inside a Maven/Gradle project a classpath-less single-file compile
48
+ // cannot produce a valid verdict: every non-JDK import becomes a
49
+ // "package does not exist" error, and the fallback turns those into
50
+ // false blocking diagnostics (#1877). jdtls owns those projects; this
51
+ // runner keeps its value for standalone files with no build descriptor.
52
+ // Same shared descriptor walk the SpotBugs gate uses.
53
+ if (hasJavaBuildDescriptor(path.dirname(absPath), ctx.projectRoot ?? ctx.cwd)) {
54
+ ctx.log?.("javac: skipped — file is inside a Maven/Gradle project; a classpath-less compile would emit false positives");
55
+ return { status: "skipped", diagnostics: [], semantic: "none" };
56
+ }
43
57
  if (!(await (javac.isAvailableAsync(cwd)))) {
44
58
  return { status: "skipped", diagnostics: [], semantic: "none" };
45
59
  }
@@ -47,7 +61,6 @@ const javacRunner = {
47
61
  if (!cmd) {
48
62
  return { status: "skipped", diagnostics: [], semantic: "none" };
49
63
  }
50
- const absPath = path.resolve(cwd, ctx.filePath);
51
64
  const result = await safeSpawnAsync(cmd, ["-Xlint:none", "-proc:none", absPath], {
52
65
  cwd,
53
66
  timeout: 30000,
@@ -69,7 +82,7 @@ const javacRunner = {
69
82
  return {
70
83
  status: hasErrors ? "failed" : "succeeded",
71
84
  diagnostics,
72
- semantic: hasErrors ? "blocking" : "warning",
85
+ semantic: "warning",
73
86
  };
74
87
  },
75
88
  };
@@ -12,12 +12,14 @@
12
12
  * unified runner that delegates to the LSP service.
13
13
  */
14
14
  import { logExtension } from "../../extension-log.js";
15
+ import { getLspCapableKinds } from "../../language-policy.js";
15
16
  import { touchCoverageGap } from "../../lsp/diagnostic-binding.js";
16
17
  import { getLSPService } from "../../lsp/index.js";
17
18
  import { RUNTIME_CONFIG } from "../../runtime-config.js";
18
19
  import { PRIORITY } from "../priorities.js";
19
20
  import { resolveRunnerPath } from "../runner-context.js";
20
21
  import { convertLspDiagnostics } from "../utils/lsp-diagnostics.js";
22
+ import { demoteInferredProjectDiagnostics } from "../../lsp/inferred-project.js";
21
23
  import { enabledAuxiliaryLspServerIds, retagAuxiliaryDiagnostics, } from "../auxiliary-lsp.js";
22
24
  import { readFileContent } from "./utils.js";
23
25
  import { tryWarmAttachedCodeActions, tryWarmAttachedDiagnostics, } from "../../warm-attach.js";
@@ -50,41 +52,11 @@ function buildCodeActionSuggestion(actions) {
50
52
  }
51
53
  const lspRunner = {
52
54
  id: "lsp",
53
- appliesTo: [
54
- "jsts",
55
- "python",
56
- "go",
57
- "rust",
58
- "ruby",
59
- "cxx",
60
- "cmake",
61
- "shell",
62
- "json",
63
- "markdown",
64
- "css",
65
- "yaml",
66
- "html",
67
- "docker",
68
- "php",
69
- "powershell",
70
- "prisma",
71
- "csharp",
72
- "fsharp",
73
- "java",
74
- "kotlin",
75
- "swift",
76
- "dart",
77
- "lua",
78
- "zig",
79
- "haskell",
80
- "elixir",
81
- "gleam",
82
- "ocaml",
83
- "clojure",
84
- "terraform",
85
- "nix",
86
- "toml",
87
- ],
55
+ // Derived from LANGUAGE_POLICY, never hand-maintained: the copy this
56
+ // replaced had drifted (fish was lspCapable but absent, so getForKind
57
+ // answered that no LSP runs on fish). Registering a language as lspCapable
58
+ // is now the only step this seam needs (#1545).
59
+ appliesTo: getLspCapableKinds(),
88
60
  priority: PRIORITY.LSP_PRIMARY,
89
61
  enabledByDefault: true,
90
62
  async run(ctx) {
@@ -112,10 +84,12 @@ const lspRunner = {
112
84
  // one spawned server) — an empty `lspDiags` in that case is NOT a
113
85
  // confirmed clean result and must not be reported as one (#570).
114
86
  let diagnosticsInconclusive = false;
115
- // #1470: server ids the touch carries no evidence for — an auxiliary whose
116
- // push wait our aux grace timer cut off. The touch is NOT inconclusive (the
117
- // primary answered, and its findings below are real), so this is tracked
118
- // separately: the only claim it invalidates is "0 diagnostics means clean".
87
+ // #1470/#1493: server ids the touch carries no evidence for — an auxiliary
88
+ // whose push wait our aux grace timer cut off (#1470), or one that stayed
89
+ // silent with no stored publication for this content (#1493). The touch is
90
+ // NOT inconclusive (the primary answered, and its findings below are real),
91
+ // so this is tracked separately: the only claim it invalidates is "0
92
+ // diagnostics means clean".
119
93
  let unconfirmedServerIds = [];
120
94
  let usedWarmAttach = false;
121
95
  let failureReason = "";
@@ -138,8 +112,9 @@ const lspRunner = {
138
112
  // #1179 (shape-5 structural fix): both branches normalize to the
139
113
  // `touchFile` wrapper shape. The warm-attach IPC branch resolves a plain
140
114
  // diagnostics array — `available` no longer implies a fully confirmed
141
- // answer: a `partial` confirmation (an auxiliary cut off by the grace
142
- // timer) is served as `available: true` too (the IPC gate at
115
+ // answer: a `partial` confirmation (an auxiliary that never
116
+ // reported — cut off by the grace timer, or silent) is served as
117
+ // `available: true` too (the IPC gate at
143
118
  // `clients/mcp/ipc.ts:248` rejects only `inconclusive`). Carry the
144
119
  // incumbent's `unconfirmedServerIds` onto the wrapper so
145
120
  // `touchCoverageGap` below sees it — dropping it here is the same
@@ -228,18 +203,22 @@ const lspRunner = {
228
203
  }
229
204
  if (lspDiags.length === 0) {
230
205
  if (unconfirmedServerIds.length > 0) {
231
- // #1470: an auxiliary was cut off by the aux grace timer, so this empty
232
- // merged result is missing whatever that scanner would have said — a
233
- // hung opengrep must not read as a clean bill of health on the security
234
- // lane. `RunnerResult` has no channel for "clean for these servers,
235
- // unknown for those", so the only honest verdict this seam can express
236
- // for an EMPTY result is "not checked" — which is what "skipped" means
237
- // here, and it lets the coverage notice say so once. Nothing is thrown
238
- // away: the primary answered with zero findings, so there is nothing to
206
+ // #1470/#1493: an auxiliary never reported — cut off by the aux grace
207
+ // timer, or silent with nothing published for this content — so this
208
+ // empty merged result is missing whatever that scanner would have said.
209
+ // A hung OR silent opengrep must not read as a clean bill of health on
210
+ // the security lane. The empty result remains skipped, while the correlated
211
+ // server ids let the coverage notice name the missing scanners once. Nothing
212
+ // is thrown away: the primary answered with zero findings, so there is nothing to
239
213
  // report; when it DOES have findings the branches below still report
240
214
  // them (see the non-empty path), which is how a trustworthy primary
241
- // stays trustworthy under a cut-off auxiliary.
242
- return { status: "skipped", diagnostics: [], semantic: "none" };
215
+ // stays trustworthy under an auxiliary that never reported.
216
+ return {
217
+ status: "skipped",
218
+ diagnostics: [],
219
+ semantic: "none",
220
+ unconfirmedServerIds: [...unconfirmedServerIds],
221
+ };
243
222
  }
244
223
  return {
245
224
  status: "succeeded",
@@ -250,9 +229,34 @@ const lspRunner = {
250
229
  }
251
230
  // Convert LSP diagnostics to our format
252
231
  // Defensive: filter out malformed diagnostics that may lack range
253
- const validLspDiags = lspDiags.filter((d) => d.range?.start?.line !== undefined);
232
+ const rawValidLspDiags = lspDiags.filter((d) => d.range?.start?.line !== undefined);
233
+ // #1640: the per-edit path renders the same authority as the mode=full
234
+ // sweep, so it applies the same demotion. Costs one bounded `projectInfo`
235
+ // request, and only when the file already has a TypeScript ERROR — an edit
236
+ // that type-checks clean pays nothing.
237
+ //
238
+ // #1645 review F2: NOT under warm attach. There, diagnostics came from an
239
+ // already-running remote session over IPC and no local client exists — so
240
+ // the probe would have to spawn a whole tsserver fleet to answer, breaking
241
+ // this branch's spawn-free contract (see the comment below), and the
242
+ // answer it spawned for would be the NEW server's project resolution, not
243
+ // the warm session's. A meaningless answer bought with a process is worse
244
+ // than no answer, so the warm-attach path keeps pre-#1640 rendering. This
245
+ // is a known gap, recorded on the issue rather than papered over with an
246
+ // "unverified" label that would fire on every warm-attach file including
247
+ // the properly configured majority.
248
+ const validLspDiags = usedWarmAttach
249
+ ? rawValidLspDiags
250
+ : await demoteInferredProjectDiagnostics(rawValidLspDiags, {
251
+ filePath: diagnosticPath,
252
+ cwd: ctx.cwd,
253
+ service: lspService,
254
+ });
254
255
  const fixSuggestionByIndex = new Map();
255
- const blockingDiagIndexes = validLspDiags
256
+ // #1640: read severity off the RAW list. A demoted diagnostic is still
257
+ // worth a quick-fix suggestion — the demotion changes its authority, not
258
+ // whether tsserver can offer a fix. Indexes align 1:1 with `validLspDiags`.
259
+ const blockingDiagIndexes = rawValidLspDiags
256
260
  .map((d, idx) => ({ d, idx }))
257
261
  .filter(({ d }) => d.severity === 1)
258
262
  .slice(0, WARM_CODE_ACTION_LOOKUP_LIMIT);
@@ -312,6 +316,9 @@ const lspRunner = {
312
316
  failureKind: hasErrors ? "blocking_diagnostics" : undefined,
313
317
  diagnostics: keptDiagnostics,
314
318
  semantic: resultSemantic,
319
+ ...(unconfirmedServerIds.length > 0 && {
320
+ unconfirmedServerIds: [...unconfirmedServerIds],
321
+ }),
315
322
  };
316
323
  },
317
324
  };
@@ -2,7 +2,12 @@ import { safeSpawnAsync } from "../../safe-spawn.js";
2
2
  import { getLinterPolicyForCwd, markdownlintConfigArgs, } from "../../tool-policy.js";
3
3
  import { PRIORITY } from "../priorities.js";
4
4
  import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
5
+ import { parseToolRun } from "./utils/tool-failure.js";
5
6
  const markdownlint = createAvailabilityChecker("markdownlint-cli2", ".cmd");
7
+ // markdownlint-cli2 exit codes (its README's "Exit Codes" section): 0 = no
8
+ // findings, 1 = lint findings, 2 = unexpected error (unreadable config, bad
9
+ // glob, crash). Only 2 is a rejected invocation.
10
+ const MARKDOWNLINT_EXIT_CODES = { ran: [1] };
6
11
  // markdownlint-cli2 text output does not include per-violation fixability,
7
12
  // so we keep a static allowlist of MD### rules whose --fix is deterministic.
8
13
  // Sourced from the rule pages in
@@ -93,7 +98,7 @@ const markdownlintRunner = {
93
98
  return { status: "skipped", diagnostics: [], semantic: "none" };
94
99
  }
95
100
  let cmd = null;
96
- if (await (markdownlint.isAvailableAsync(cwd))) {
101
+ if (await markdownlint.isAvailableAsync(cwd)) {
97
102
  cmd = markdownlint.getCommand(cwd);
98
103
  }
99
104
  else {
@@ -108,8 +113,17 @@ const markdownlintRunner = {
108
113
  timeout: 15000,
109
114
  cwd,
110
115
  });
116
+ // #1816: this runner read `result.status` zero times, so an exit-2
117
+ // config error with an empty stdout parsed to zero diagnostics and was
118
+ // reported as a clean Markdown file. An empty result must distinguish
119
+ // clean from errored.
111
120
  const raw = `${result.stdout ?? ""}${result.stderr ?? ""}`;
112
- const diagnostics = parseMarkdownlintOutput(raw, ctx.filePath);
121
+ // #1948: one seam for both gates — the tool produced nothing, and the
122
+ // tool produced something the parser could not read.
123
+ const run = parseToolRun("markdownlint", { result, output: raw, exitCodes: MARKDOWNLINT_EXIT_CODES }, (out) => parseMarkdownlintOutput(out, ctx.filePath));
124
+ if (run.skipped)
125
+ return run.skipped;
126
+ const diagnostics = run.diagnostics;
113
127
  if (diagnostics.length === 0) {
114
128
  return { status: "succeeded", diagnostics: [], semantic: "none" };
115
129
  }
@@ -3,7 +3,19 @@ import { safeSpawnAsync } from "../../safe-spawn.js";
3
3
  import { hasMypyConfig } from "../../tool-policy.js";
4
4
  import { PRIORITY } from "../priorities.js";
5
5
  import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
6
+ import { parseToolRun } from "./utils/tool-failure.js";
6
7
  const mypy = createAvailabilityChecker("mypy", "");
8
+ // mypy exit codes: 0 = no type errors, 1 = type errors found, 2 = a blocking
9
+ // error. 2 is NOT a rejected invocation on its own — mypy reports a source
10
+ // SYNTAX error under 2 and still writes a normal parsable diagnostic to stdout
11
+ // (verified live against mypy 2.3.1: `syn.py:1: error: Invalid syntax
12
+ // [syntax]`). A bad flag or unreadable config also exits 2, but writes its
13
+ // message to STDERR and leaves stdout empty.
14
+ //
15
+ // So the exit code cannot separate the two, and the STREAM does: the gate below
16
+ // judges "nothing to parse" on stdout alone, while the parser still reads both.
17
+ // The table's remaining job is to reject any OTHER nonzero status.
18
+ const MYPY_EXIT_CODES = { ran: [1, 2] };
7
19
  // mypy output: file.py:10: error: Incompatible types [assignment]
8
20
  //
9
21
  // mypy follows imports and reports errors in OTHER modules, not just the file
@@ -55,7 +67,7 @@ const mypyRunner = {
55
67
  return { status: "skipped", diagnostics: [], semantic: "none" };
56
68
  }
57
69
  let cmd = null;
58
- if (await (mypy.isAvailableAsync(cwd))) {
70
+ if (await mypy.isAvailableAsync(cwd)) {
59
71
  cmd = mypy.getCommand(cwd);
60
72
  }
61
73
  else {
@@ -64,8 +76,19 @@ const mypyRunner = {
64
76
  if (!cmd)
65
77
  return { status: "skipped", diagnostics: [], semantic: "none" };
66
78
  const result = await safeSpawnAsync(cmd, ["--no-error-summary", "--show-column-numbers", ctx.filePath], { timeout: 30000, cwd });
79
+ // #1816: this runner read `result.status` zero times, so an exit-2
80
+ // config error reported the file as cleanly type-checked. The gate reads
81
+ // stdout only (see MYPY_EXIT_CODES) so an exit-2 SYNTAX error, which
82
+ // does write a diagnostic there, still reaches the parser.
67
83
  const raw = `${result.stdout ?? ""}${result.stderr ?? ""}`;
68
- const diagnostics = parseMypyOutput(raw, ctx.filePath, cwd);
84
+ // #1948: `parseOutput` keeps the split this runner already had — the gate
85
+ // judges "did it run" on stdout alone, the parser still reads both
86
+ // streams — so adding the parsed-nothing record does not widen the
87
+ // did-it-run verdict.
88
+ const run = parseToolRun("mypy", { result, output: result.stdout, exitCodes: MYPY_EXIT_CODES }, (out) => parseMypyOutput(out, ctx.filePath, cwd), { parseOutput: raw });
89
+ if (run.skipped)
90
+ return run.skipped;
91
+ const diagnostics = run.diagnostics;
69
92
  if (diagnostics.length === 0) {
70
93
  return { status: "succeeded", diagnostics: [], semantic: "none" };
71
94
  }
@@ -76,10 +76,13 @@ const oxlintRunner = {
76
76
  const result = await safeSpawnAsync(cmd, args, {
77
77
  timeout: 30000,
78
78
  });
79
- // Oxlint returns non-zero when issues found
80
- if (result.status === 0) {
81
- return { status: "succeeded", diagnostics: [], semantic: "none" };
82
- }
79
+ // Oxlint exits 0 whenever nothing at ERROR severity was found — that
80
+ // includes a run that found only warnings, its own default severity
81
+ // (#1947). A run that found nothing at all also exits 0, but still
82
+ // prints a report with an empty `diagnostics` array, so parsing
83
+ // unconditionally and branching on the parsed count (below) tells the
84
+ // two apart instead of the exit code discarding the warning case.
85
+ //
83
86
  // Parse JSON output. Fall back to the unix-format parser if JSON parsing
84
87
  // fails (older oxlint versions, malformed stderr noise, etc.) — keeps the
85
88
  // runner producing diagnostics even when the structured-fix metadata is
@@ -94,8 +97,20 @@ const oxlintRunner = {
94
97
  return { status: "succeeded", diagnostics: [], semantic: "none" };
95
98
  }
96
99
  const hasBlocking = diagnostics.some((d) => d.semantic === "blocking");
100
+ // A warning-only result on exit 0 is oxlint's normal outcome, not a
101
+ // failure: exit 0 means nothing hit ERROR severity. `status: "failed"`
102
+ // here would stop this arm from reporting "succeeded", which breaks two
103
+ // things downstream — plan.ts's ["eslint", "oxlint", "biome-check-json"]
104
+ // fallback group only stops at the first `status: "succeeded"` runner
105
+ // (dispatcher.ts's `runGroup`), so biome-check-json would run again on
106
+ // every warning-only save (extra spawns, a possible install, duplicate
107
+ // findings); and it would mismatch the sibling convention (biome-check,
108
+ // golangci-lint, rubocop) of keying `status` off blocking severity, not
109
+ // off the tool's raw exit code. The findings themselves still reach the
110
+ // delivery pipeline regardless of `status` — dispatcher.ts buckets by
111
+ // each diagnostic's own `semantic`, so a warning stays a warning.
97
112
  return {
98
- status: "failed",
113
+ status: !hasBlocking && result.status === 0 ? "succeeded" : "failed",
99
114
  diagnostics,
100
115
  semantic: hasBlocking ? "blocking" : "warning",
101
116
  };
@@ -3,6 +3,11 @@ import { safeSpawnAsync } from "../../safe-spawn.js";
3
3
  import { getLinterPolicyForCwd, hasPhpstanConfig } from "../../tool-policy.js";
4
4
  import { PRIORITY } from "../priorities.js";
5
5
  import { createAvailabilityChecker, resolveVendorToolCommand, } from "./utils/runner-helpers.js";
6
+ import { parseToolRun } from "./utils/tool-failure.js";
7
+ // phpstan's documented exit codes: 0 = no errors, 1 = errors found, 2 = a
8
+ // fatal/internal error that stopped the analysis. Only 1 is a run that carries
9
+ // findings.
10
+ const PHPSTAN_EXIT_CODES = { ran: [1] };
6
11
  const phpstan = createAvailabilityChecker("phpstan", ".phar");
7
12
  // phpstan analyses the target file PLUS its dependency closure and keys errors
8
13
  // by the real file in `output.files`. Attribute each diagnostic to that key
@@ -19,7 +24,7 @@ export function parsePhpstanJson(raw, fallbackPath, cwd) {
19
24
  ? file
20
25
  : path.resolve(cwd, file)
21
26
  : fallbackPath;
22
- for (const err of fileErrors.errors ?? []) {
27
+ for (const err of fileErrors?.messages ?? []) {
23
28
  diagnostics.push({
24
29
  id: `phpstan:${err.line ?? 1}:${err.message.slice(0, 40)}`,
25
30
  message: err.message,
@@ -29,11 +34,38 @@ export function parsePhpstanJson(raw, fallbackPath, cwd) {
29
34
  severity: "error",
30
35
  semantic: "blocking",
31
36
  tool: "phpstan",
32
- rule: "phpstan",
37
+ rule: err.identifier || "phpstan",
33
38
  fixable: false,
34
39
  });
35
40
  }
36
41
  }
42
+ // #1937 round 2: the top-level `errors[]` array carries phpstan's
43
+ // FILE-INDEPENDENT findings — internal errors, and ignore patterns that
44
+ // matched nothing. A run can report `totals.errors: 1` with `files: {}`
45
+ // and exit 1, and reading only `files` turned that into zero
46
+ // diagnostics: the same defect class as the `errors`-vs-`messages` bug
47
+ // above, one level up. Pinned by
48
+ // tests/fixtures/runner-output/phpstan/top-level-errors.captured.json.
49
+ //
50
+ // These have no file or line, so they attach to the edited file at line
51
+ // 1. That is the honest placement: the reader needs to see them, and
52
+ // there is nowhere truer to put them.
53
+ for (const message of output.errors ?? []) {
54
+ if (typeof message !== "string" || !message.trim())
55
+ continue;
56
+ diagnostics.push({
57
+ id: `phpstan:global:${message.slice(0, 40)}`,
58
+ message,
59
+ filePath: fallbackPath,
60
+ line: 1,
61
+ column: 1,
62
+ severity: "error",
63
+ semantic: "blocking",
64
+ tool: "phpstan",
65
+ rule: "phpstan/analysis",
66
+ fixable: false,
67
+ });
68
+ }
37
69
  return diagnostics;
38
70
  }
39
71
  catch {
@@ -41,7 +73,7 @@ export function parsePhpstanJson(raw, fallbackPath, cwd) {
41
73
  }
42
74
  }
43
75
  async function resolvePhpstan(cwd) {
44
- if (await (phpstan.isAvailableAsync(cwd)))
76
+ if (await phpstan.isAvailableAsync(cwd))
45
77
  return phpstan.getCommand(cwd);
46
78
  return resolveVendorToolCommand(cwd, "phpstan", ".bat");
47
79
  }
@@ -66,14 +98,15 @@ const phpstanRunner = {
66
98
  return { status: "skipped", diagnostics: [], semantic: "none" };
67
99
  const absPath = path.resolve(cwd, ctx.filePath);
68
100
  const result = await safeSpawnAsync(cmd, ["analyse", "--error-format=json", "--no-progress", absPath], { timeout: 30000, cwd });
69
- // phpstan exits 0 = no errors, 1 = errors found, 2 = fatal
70
- if (result.status === 2 || result.error) {
71
- return { status: "skipped", diagnostics: [], semantic: "none" };
72
- }
73
- if (result.status === 0) {
74
- return { status: "succeeded", diagnostics: [], semantic: "none" };
75
- }
76
- const diagnostics = parsePhpstanJson(result.stdout ?? "", ctx.filePath, cwd);
101
+ // phpstan exits 0 = no errors, 1 = errors found, 2 = fatal. The fatal
102
+ // case used to return `skipped` silently; routing it through the shared
103
+ // seam keeps that verdict and adds the bounded `runner-empty-result` row
104
+ // (#1816), and the exit-1 case now also records when the JSON report
105
+ // parses to nothing (#1948) — the shape the error-count-as-array bug had.
106
+ const run = parseToolRun("phpstan", { result, exitCodes: PHPSTAN_EXIT_CODES }, (out) => parsePhpstanJson(out, ctx.filePath, cwd), { parseOutput: result.stdout ?? "" });
107
+ if (run.skipped)
108
+ return run.skipped;
109
+ const diagnostics = run.diagnostics;
77
110
  if (diagnostics.length === 0) {
78
111
  return { status: "succeeded", diagnostics: [], semantic: "none" };
79
112
  }