@herbertgao/pi-extensions 2026.8.5 → 2026.8.7

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 (389) hide show
  1. package/README.md +5 -5
  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 +272 -22
  7. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +74 -5
  8. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +94 -77
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +48 -6
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/message-display.ts +1 -1
  11. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +14 -0
  12. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +55 -17
  13. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/layout.ts +41 -2
  14. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +75 -6
  15. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/types.ts +7 -3
  16. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +64 -1
  17. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  18. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +16 -0
  19. package/node_modules/@herbertgao/pi-subagents/README.md +30 -22
  20. package/node_modules/@herbertgao/pi-subagents/examples/agent-tool-description.md +5 -5
  21. package/node_modules/@herbertgao/pi-subagents/package.json +7 -7
  22. package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +7 -1
  23. package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +48 -19
  24. package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +22 -15
  25. package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +26 -2
  26. package/node_modules/@herbertgao/pi-subagents/src/index.ts +219 -40
  27. package/node_modules/@herbertgao/pi-subagents/src/invocation-config.ts +101 -3
  28. package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +18 -4
  29. package/node_modules/@herbertgao/pi-subagents/src/settings.ts +99 -0
  30. package/node_modules/@herbertgao/pi-subagents/src/types.ts +22 -3
  31. package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +51 -3
  32. package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +20 -2
  33. package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +34 -10
  34. package/node_modules/@herbertgao/pi-subagents/src/usage.ts +129 -1
  35. package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +29 -5
  36. package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +3 -0
  37. package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +46 -10
  38. package/node_modules/@juicesharp/rpiv-ask-user-question/config.ts +25 -0
  39. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/configuration.md +13 -4
  40. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +8 -1
  41. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/localization.md +3 -1
  42. package/node_modules/@juicesharp/rpiv-ask-user-question/locales/en.json +2 -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 +3 -1
  47. package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +30 -7
  48. package/node_modules/@juicesharp/rpiv-ask-user-question/state/state.ts +14 -6
  49. package/node_modules/@juicesharp/rpiv-ask-user-question/view/dialog-builder.ts +30 -4
  50. package/node_modules/@juicesharp/rpiv-ask-user-question/view/tab-content-strategy.ts +26 -5
  51. package/node_modules/@narumitw/pi-btw/README.md +119 -103
  52. package/node_modules/@narumitw/pi-btw/dist/index.ts +2898 -0
  53. package/node_modules/@narumitw/pi-btw/dist/index.ts.map +7 -0
  54. package/node_modules/@narumitw/pi-btw/package.json +13 -9
  55. package/node_modules/@narumitw/pi-btw/src/btw.ts +40 -42
  56. package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +55 -10
  57. package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +390 -0
  58. package/node_modules/@narumitw/pi-btw/src/menu.ts +78 -15
  59. package/node_modules/@narumitw/pi-btw/src/settings.ts +22 -2
  60. package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +136 -45
  61. package/node_modules/pi-lens/CHANGELOG.md +1004 -0
  62. package/node_modules/pi-lens/README.md +11 -3
  63. package/node_modules/pi-lens/config/ruff/core.toml +42 -0
  64. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +130 -27
  65. package/node_modules/pi-lens/dist/clients/advisory-provenance.js +427 -0
  66. package/node_modules/pi-lens/dist/clients/agent-nudge.js +79 -16
  67. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +9 -3
  68. package/node_modules/pi-lens/dist/clients/atomic-write.js +9 -3
  69. package/node_modules/pi-lens/dist/clients/bash-file-access.js +285 -8
  70. package/node_modules/pi-lens/dist/clients/biome-client.js +176 -37
  71. package/node_modules/pi-lens/dist/clients/blocker-freshness.js +428 -0
  72. package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +119 -0
  73. package/node_modules/pi-lens/dist/clients/bootstrap.js +12 -1
  74. package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +12 -3
  75. package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +192 -0
  76. package/node_modules/pi-lens/dist/clients/bus-events-logger.js +62 -6
  77. package/node_modules/pi-lens/dist/clients/bus-publish.js +11 -3
  78. package/node_modules/pi-lens/dist/clients/cascade-budget.js +196 -0
  79. package/node_modules/pi-lens/dist/clients/cascade-format.js +76 -2
  80. package/node_modules/pi-lens/dist/clients/cascade-types.js +9 -1
  81. package/node_modules/pi-lens/dist/clients/child-unref.js +54 -6
  82. package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +76 -24
  83. package/node_modules/pi-lens/dist/clients/console-guard-install.js +16 -4
  84. package/node_modules/pi-lens/dist/clients/dead-code-client.js +249 -52
  85. package/node_modules/pi-lens/dist/clients/deadline-utils.js +8 -1
  86. package/node_modules/pi-lens/dist/clients/debug-handles.js +5 -0
  87. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +62 -13
  88. package/node_modules/pi-lens/dist/clients/dependency-checker.js +43 -9
  89. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +153 -37
  90. package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +298 -0
  91. package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +10 -3
  92. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +165 -11
  93. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +325 -72
  94. package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +7 -4
  95. package/node_modules/pi-lens/dist/clients/dispatch/plan.js +5 -0
  96. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +234 -18
  97. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +187 -19
  98. package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +6 -3
  99. package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +11 -9
  100. package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +398 -0
  101. package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +11 -3
  102. package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +12 -7
  103. package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +18 -0
  104. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +895 -0
  105. package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +4 -0
  106. package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +16 -3
  107. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +81 -41
  108. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +16 -0
  109. package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +23 -0
  110. package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +331 -55
  111. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +38 -5
  112. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +97 -19
  113. package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +14 -0
  114. package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +20 -0
  115. package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +22 -0
  116. package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +10 -0
  117. package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +18 -6
  118. package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +73 -12
  119. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +488 -0
  120. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +84 -0
  121. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +260 -27
  122. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +943 -93
  123. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +86 -11
  124. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +72 -0
  125. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +106 -0
  126. package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +9 -0
  127. package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +18 -1
  128. package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +4 -2
  129. package/node_modules/pi-lens/dist/clients/disposition-publish.js +10 -3
  130. package/node_modules/pi-lens/dist/clients/eval-timestamp.js +17 -0
  131. package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +28 -5
  132. package/node_modules/pi-lens/dist/clients/extension-log.js +317 -3
  133. package/node_modules/pi-lens/dist/clients/file-kinds.js +8 -2
  134. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +294 -0
  135. package/node_modules/pi-lens/dist/clients/finding-identity.js +88 -0
  136. package/node_modules/pi-lens/dist/clients/fix-worklog.js +5 -1
  137. package/node_modules/pi-lens/dist/clients/format-events-publish.js +39 -8
  138. package/node_modules/pi-lens/dist/clients/formatters-lazy.js +3 -2
  139. package/node_modules/pi-lens/dist/clients/formatters.js +500 -115
  140. package/node_modules/pi-lens/dist/clients/generation-guard.js +216 -0
  141. package/node_modules/pi-lens/dist/clients/git-guard.js +49 -21
  142. package/node_modules/pi-lens/dist/clients/gitleaks-client.js +181 -8
  143. package/node_modules/pi-lens/dist/clients/go-client.js +21 -39
  144. package/node_modules/pi-lens/dist/clients/govulncheck-client.js +219 -10
  145. package/node_modules/pi-lens/dist/clients/grammar-source.js +333 -10
  146. package/node_modules/pi-lens/dist/clients/host-ports.js +9 -1
  147. package/node_modules/pi-lens/dist/clients/installer/index.js +1119 -101
  148. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh-session.js +58 -0
  149. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +715 -0
  150. package/node_modules/pi-lens/dist/clients/instance-reaper.js +643 -97
  151. package/node_modules/pi-lens/dist/clients/instance-registry.js +87 -17
  152. package/node_modules/pi-lens/dist/clients/jscpd-client.js +86 -15
  153. package/node_modules/pi-lens/dist/clients/knip-client.js +361 -24
  154. package/node_modules/pi-lens/dist/clients/language-policy.js +8 -2
  155. package/node_modules/pi-lens/dist/clients/language-profile.js +2 -0
  156. package/node_modules/pi-lens/dist/clients/latency-logger.js +487 -9
  157. package/node_modules/pi-lens/dist/clients/lazy-import.js +21 -0
  158. package/node_modules/pi-lens/dist/clients/ledger-bounds.js +21 -0
  159. package/node_modules/pi-lens/dist/clients/lens-events.js +56 -25
  160. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +16 -0
  161. package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +45 -2
  162. package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +30 -4
  163. package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +160 -20
  164. package/node_modules/pi-lens/dist/clients/lsp/client.js +1666 -148
  165. package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +111 -0
  166. package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +389 -0
  167. package/node_modules/pi-lens/dist/clients/lsp/index.js +2496 -171
  168. package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +215 -0
  169. package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +146 -14
  170. package/node_modules/pi-lens/dist/clients/lsp/language.js +48 -4
  171. package/node_modules/pi-lens/dist/clients/lsp/server.js +517 -69
  172. package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +22 -0
  173. package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +43 -0
  174. package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +172 -0
  175. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +21 -5
  176. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +61 -3
  177. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +422 -28
  178. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-session.js +30 -0
  179. package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +175 -0
  180. package/node_modules/pi-lens/dist/clients/lsp-lazy.js +3 -2
  181. package/node_modules/pi-lens/dist/clients/mcp/analyze.js +4 -0
  182. package/node_modules/pi-lens/dist/clients/mcp/session.js +39 -18
  183. package/node_modules/pi-lens/dist/clients/model-provider.js +53 -0
  184. package/node_modules/pi-lens/dist/clients/module-report.js +8 -0
  185. package/node_modules/pi-lens/dist/clients/opengrep-client.js +15 -1
  186. package/node_modules/pi-lens/dist/clients/package-manager.js +170 -14
  187. package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +27 -0
  188. package/node_modules/pi-lens/dist/clients/path-utils.js +160 -0
  189. package/node_modules/pi-lens/dist/clients/pipeline.js +178 -30
  190. package/node_modules/pi-lens/dist/clients/post-autofix-notice.js +37 -0
  191. package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +17 -3
  192. package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +89 -22
  193. package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +85 -15
  194. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +15 -3
  195. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +23 -2
  196. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +50 -2
  197. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +5 -0
  198. package/node_modules/pi-lens/dist/clients/project-lens-config.js +3 -0
  199. package/node_modules/pi-lens/dist/clients/project-snapshot.js +299 -0
  200. package/node_modules/pi-lens/dist/clients/quiet-window-config.js +47 -0
  201. package/node_modules/pi-lens/dist/clients/quiet-window.js +11 -25
  202. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +1 -1
  203. package/node_modules/pi-lens/dist/clients/read-guard.js +184 -10
  204. package/node_modules/pi-lens/dist/clients/resource-sampler.js +49 -17
  205. package/node_modules/pi-lens/dist/clients/reverse-deps.js +50 -11
  206. package/node_modules/pi-lens/dist/clients/review-graph/query.js +76 -4
  207. package/node_modules/pi-lens/dist/clients/run-duration.js +55 -0
  208. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +248 -13
  209. package/node_modules/pi-lens/dist/clients/runtime-context.js +112 -12
  210. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +472 -61
  211. package/node_modules/pi-lens/dist/clients/runtime-session.js +359 -13
  212. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +217 -22
  213. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +269 -22
  214. package/node_modules/pi-lens/dist/clients/runtime-turn.js +948 -87
  215. package/node_modules/pi-lens/dist/clients/rust-client.js +21 -37
  216. package/node_modules/pi-lens/dist/clients/safe-spawn.js +220 -7
  217. package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +161 -0
  218. package/node_modules/pi-lens/dist/clients/search-read-registration.js +34 -6
  219. package/node_modules/pi-lens/dist/clients/security-scan-client.js +224 -8
  220. package/node_modules/pi-lens/dist/clients/sg-runner.js +249 -37
  221. package/node_modules/pi-lens/dist/clients/single-flight.js +158 -0
  222. package/node_modules/pi-lens/dist/clients/smells-rollup.js +18 -11
  223. package/node_modules/pi-lens/dist/clients/stale-marker.js +17 -0
  224. package/node_modules/pi-lens/dist/clients/startup-timing.js +26 -2
  225. package/node_modules/pi-lens/dist/clients/test-runner-client.js +574 -32
  226. package/node_modules/pi-lens/dist/clients/tool-event.js +56 -5
  227. package/node_modules/pi-lens/dist/clients/tool-policy.js +127 -20
  228. package/node_modules/pi-lens/dist/clients/tool-set-policy.js +76 -0
  229. package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +75 -1
  230. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +769 -64
  231. package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +11 -0
  232. package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +90 -0
  233. package/node_modules/pi-lens/dist/clients/trivy-client.js +19 -1
  234. package/node_modules/pi-lens/dist/clients/warm-attach.js +17 -0
  235. package/node_modules/pi-lens/dist/clients/widget-state.js +336 -36
  236. package/node_modules/pi-lens/dist/clients/word-index.js +305 -33
  237. package/node_modules/pi-lens/dist/clients/zizmor-config.js +214 -14
  238. package/node_modules/pi-lens/dist/index.js +64677 -49484
  239. package/node_modules/pi-lens/dist/mcp/server.js +8 -2
  240. package/node_modules/pi-lens/dist/tools/activate-tools.js +17 -5
  241. package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +9 -4
  242. package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +5 -2
  243. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +469 -56
  244. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +190 -46
  245. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -7
  246. package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -1
  247. package/node_modules/pi-lens/docs/agent-guide.md +44 -14
  248. package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +518 -501
  249. package/node_modules/pi-lens/docs/dispositions.md +21 -0
  250. package/node_modules/pi-lens/docs/features.md +33 -6
  251. package/node_modules/pi-lens/docs/globalconfig.md +14 -0
  252. package/node_modules/pi-lens/docs/language-coverage.md +71 -5
  253. package/node_modules/pi-lens/docs/mcp.md +2 -2
  254. package/node_modules/pi-lens/docs/servercapabilities.md +4 -1
  255. package/node_modules/pi-lens/docs/settings.md +25 -1
  256. package/node_modules/pi-lens/docs/usage.md +24 -5
  257. package/node_modules/pi-lens/docs/word-index.md +35 -0
  258. package/node_modules/pi-lens/package.json +10 -6
  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 +22 -0
  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-conditional-empty-object-spread-js-test.yml +9 -0
  266. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-test.yml +9 -0
  267. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-dupe-class-members-test.yml +33 -0
  268. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-js-test.yml +7 -1
  269. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-test.yml +7 -1
  270. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-known-value-widening-test.yml +9 -0
  271. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-non-null-assertion-test.yml +216 -0
  272. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +9 -0
  273. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +9 -0
  274. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +9 -0
  275. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +9 -0
  276. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-return-value-in-generator-test.yml +12 -0
  277. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-runtime-typeof-test.yml +33 -0
  278. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-server-bind-wildcard-test.yml +9 -0
  279. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-shape-in-symbol-names-test.yml +13 -0
  280. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-js-test.yml +5 -1
  281. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-test.yml +5 -1
  282. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-laundering-test.yml +11 -0
  283. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-parameters-test.yml +12 -0
  284. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-returns-test.yml +16 -0
  285. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-any-test.yml +10 -0
  286. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-unknown-test.yml +8 -0
  287. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/redundant-unsafe-function-test.yml +35 -0
  288. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/require-safety-comment-for-as-unknown-as-test.yml +177 -0
  289. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/ts-void-zero-test.yml +1 -0
  290. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member-js.yml +13 -2
  291. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member.yml +13 -2
  292. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +2 -0
  293. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-object-param.yml +60 -0
  294. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +66 -0
  295. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-compile-call.yml +63 -5
  296. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread-js.yml +21 -0
  297. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread.yml +29 -0
  298. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-dupe-class-members.yml +52 -8
  299. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html-js.yml +27 -2
  300. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html.yml +27 -2
  301. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-known-value-widening.yml +71 -0
  302. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-non-null-assertion.yml +316 -0
  303. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +7 -0
  304. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +29 -0
  305. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +30 -0
  306. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +41 -0
  307. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +42 -0
  308. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-return-value-in-generator.yml +22 -5
  309. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-runtime-typeof.yml +121 -0
  310. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-server-bind-wildcard.yml +23 -7
  311. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-shape-in-symbol-names.yml +68 -0
  312. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code-js.yml +41 -2
  313. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code.yml +41 -2
  314. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +32 -0
  315. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-parameters.yml +67 -0
  316. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-returns.yml +106 -0
  317. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-any.yml +50 -0
  318. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-unknown.yml +56 -0
  319. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +2 -0
  320. package/node_modules/pi-lens/rules/ast-grep-rules/rules/redundant-unsafe-function.yml +32 -0
  321. package/node_modules/pi-lens/rules/ast-grep-rules/rules/require-safety-comment-for-as-unknown-as.yml +184 -0
  322. package/node_modules/pi-lens/rules/ast-grep-rules/rules/ts-void-zero.yml +5 -0
  323. package/node_modules/pi-lens/rules/ast-grep-rules/self-scan-baseline.json +5 -0
  324. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +132 -1
  325. package/node_modules/pi-lens/scripts/download-grammars.js +25 -0
  326. package/node_modules/pi-lens/scripts/grammars.lock.json +9 -0
  327. package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +12 -11
  328. package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +22 -22
  329. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +87 -116
  330. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +170 -0
  331. package/node_modules/pi-lens/skills/pi-lens-write-tree-sitter-rule/SKILL.md +3 -1
  332. package/node_modules/pi-lens/vendor/grammars/tree-sitter-cue.wasm +0 -0
  333. package/node_modules/pi-mcp-adapter/CHANGELOG.md +49 -0
  334. package/node_modules/pi-mcp-adapter/README.md +51 -6
  335. package/node_modules/pi-mcp-adapter/agent-dir.ts +12 -4
  336. package/node_modules/pi-mcp-adapter/cli.js +188 -5
  337. package/node_modules/pi-mcp-adapter/commands.ts +128 -22
  338. package/node_modules/pi-mcp-adapter/config.ts +28 -10
  339. package/node_modules/pi-mcp-adapter/direct-tools.ts +23 -19
  340. package/node_modules/pi-mcp-adapter/index.ts +219 -32
  341. package/node_modules/pi-mcp-adapter/init.ts +36 -4
  342. package/node_modules/pi-mcp-adapter/lifecycle.ts +315 -24
  343. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +39 -6
  344. package/node_modules/pi-mcp-adapter/mcp-bearer-store.ts +387 -0
  345. package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +27 -3
  346. package/node_modules/pi-mcp-adapter/mcp-code.ts +4 -0
  347. package/node_modules/pi-mcp-adapter/mcp-panel.ts +42 -13
  348. package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +2 -1
  349. package/node_modules/pi-mcp-adapter/metadata-cache.ts +46 -25
  350. package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +168 -0
  351. package/node_modules/pi-mcp-adapter/package.json +4 -1
  352. package/node_modules/pi-mcp-adapter/proxy-modes.ts +5 -4
  353. package/node_modules/pi-mcp-adapter/request-headers-command.ts +330 -0
  354. package/node_modules/pi-mcp-adapter/search-ranking.ts +92 -22
  355. package/node_modules/pi-mcp-adapter/server-manager.ts +145 -2
  356. package/node_modules/pi-mcp-adapter/session-recovery.ts +7 -0
  357. package/node_modules/pi-mcp-adapter/tool-approval.ts +15 -2
  358. package/node_modules/pi-mcp-adapter/tool-metadata.ts +38 -18
  359. package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +44 -4
  360. package/node_modules/pi-mcp-adapter/types.ts +95 -10
  361. package/node_modules/pi-mcp-adapter/ui-server.ts +18 -16
  362. package/node_modules/pi-mcp-adapter/utils.ts +70 -0
  363. package/node_modules/pi-web-access/CHANGELOG.md +37 -0
  364. package/node_modules/pi-web-access/README.md +38 -14
  365. package/node_modules/pi-web-access/anysearch.ts +4 -2
  366. package/node_modules/pi-web-access/auth-fetch.ts +148 -0
  367. package/node_modules/pi-web-access/brave.ts +16 -4
  368. package/node_modules/pi-web-access/chrome-cookies.ts +110 -23
  369. package/node_modules/pi-web-access/curator-page.ts +8 -3
  370. package/node_modules/pi-web-access/curator-server.ts +5 -1
  371. package/node_modules/pi-web-access/exa.ts +18 -7
  372. package/node_modules/pi-web-access/extract.ts +134 -37
  373. package/node_modules/pi-web-access/fetch-params.ts +17 -3
  374. package/node_modules/pi-web-access/firecrawl.ts +172 -12
  375. package/node_modules/pi-web-access/gemini-search.ts +33 -7
  376. package/node_modules/pi-web-access/index.ts +160 -104
  377. package/node_modules/pi-web-access/package.json +2 -2
  378. package/node_modules/pi-web-access/page-query.ts +4 -2
  379. package/node_modules/pi-web-access/parallel-mcp.ts +249 -0
  380. package/node_modules/pi-web-access/parallel.ts +2 -2
  381. package/node_modules/pi-web-access/query-rewrite.ts +51 -0
  382. package/node_modules/pi-web-access/serper.ts +211 -0
  383. package/node_modules/pi-web-access/summary-model-scope.ts +12 -4
  384. package/node_modules/pi-web-access/summary-review.ts +51 -23
  385. package/node_modules/pi-web-access/tavily.ts +16 -4
  386. package/node_modules/pi-web-access/utils.ts +87 -0
  387. package/node_modules/pi-web-access/valyu.ts +199 -0
  388. package/node_modules/pi-web-access/youtube-extract.ts +2 -2
  389. package/package.json +13 -13
@@ -18,10 +18,14 @@
18
18
  * Install: cargo install typos-cli
19
19
  * Or: npm install -g typos-cli (if wrapped)
20
20
  */
21
+ import { skipUnlessToolRan } from "./utils/tool-failure.js";
21
22
  import { safeSpawnAsync } from "../../safe-spawn.js";
22
23
  import { PRIORITY } from "../priorities.js";
23
24
  import { createAvailabilityChecker } from "./utils/runner-helpers.js";
24
25
  const typos = createAvailabilityChecker("typos", ".exe");
26
+ // typos-cli exit codes: 0 = no typos, 2 = typos found, 1 = an error that
27
+ // stopped the scan. Anything nonzero outside {2} is a rejected invocation.
28
+ const TYPOS_EXIT_CODES = { ran: [2] };
25
29
  /**
26
30
  * Parse typos-cli JSON output (JSON Lines format)
27
31
  *
@@ -90,6 +94,16 @@ const spellcheckRunner = {
90
94
  const result = await safeSpawnAsync(typos.getCommand(ctx.cwd || process.cwd()), args, {
91
95
  timeout: 15000,
92
96
  });
97
+ // #1816: typos-cli exits 0 clean, 2 with typos found, and 1 on an ERROR
98
+ // (unreadable config, bad argument). The `status === 2 || stdout` test
99
+ // below is false for exit 1 with an empty stdout, so a failed run was
100
+ // reported as a clean file. Only 0 and 2 are runs.
101
+ const skipped = skipUnlessToolRan("spellcheck", {
102
+ result,
103
+ exitCodes: TYPOS_EXIT_CODES,
104
+ });
105
+ if (skipped)
106
+ return skipped;
93
107
  // typos-cli exits with code 2 if typos found, 0 if clean
94
108
  const hasTypos = result.status === 2 || result.stdout?.trim();
95
109
  if (!hasTypos) {
@@ -2,7 +2,17 @@ import { safeSpawnAsync } from "../../safe-spawn.js";
2
2
  import { getLinterPolicyForCwd, hasSqlfluffConfig } from "../../tool-policy.js";
3
3
  import { PRIORITY } from "../priorities.js";
4
4
  import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
5
+ import { skipUnlessToolRan } from "./utils/tool-failure.js";
5
6
  const sqlfluff = createAvailabilityChecker("sqlfluff", ".exe");
7
+ // sqlfluff exit codes (its CLI docs): 0 = clean, 1 = violations found, 2 = a
8
+ // user error that stopped the lint (unknown dialect, unreadable config).
9
+ // Only 2 is a rejected invocation.
10
+ //
11
+ // The exit TABLE is what protects this runner, not the nothing-to-parse rule:
12
+ // sqlfluff writes its user errors to STDOUT, not stderr (live: an unknown
13
+ // dialect prints the error there), so stdout is non-empty and the fallback
14
+ // rule would read the failed run as a run that found nothing.
15
+ const SQLFLUFF_EXIT_CODES = { ran: [1] };
6
16
  export { hasSqlfluffConfig };
7
17
  // sqlfluff's JSON lint output does not carry a per-violation fixable flag —
8
18
  // `sqlfluff fix` is a separate command and the lint surface doesn't tell us
@@ -131,7 +141,17 @@ const sqlfluffRunner = {
131
141
  }
132
142
  const result = await safeSpawnAsync(cmd, args, {
133
143
  timeout: 20000,
144
+ cwd,
145
+ });
146
+ // #1816: this runner read `result.status` zero times, so a user error
147
+ // fell through `parseSqlfluffOutput`'s JSON catch to zero violations and
148
+ // reported the SQL file as clean.
149
+ const skipped = skipUnlessToolRan("sqlfluff", {
150
+ result,
151
+ exitCodes: SQLFLUFF_EXIT_CODES,
134
152
  });
153
+ if (skipped)
154
+ return skipped;
135
155
  const diagnostics = parseSqlfluffOutput(result.stdout ?? "", ctx.filePath);
136
156
  if (diagnostics.length === 0) {
137
157
  return { status: "succeeded", diagnostics: [], semantic: "none" };
@@ -3,7 +3,20 @@ import { safeSpawnAsync } from "../../safe-spawn.js";
3
3
  import { getLinterPolicyForCwd, hasStylelintConfig, } from "../../tool-policy.js";
4
4
  import { PRIORITY } from "../priorities.js";
5
5
  import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
6
+ import { skipUnlessToolRan } from "./utils/tool-failure.js";
6
7
  const stylelint = createAvailabilityChecker("stylelint", ".cmd");
8
+ // stylelint exit codes (its "Exit codes" docs page): 0 = no problems, 1 = a
9
+ // fatal error, 2 = lint problems found, 78 = a configuration error.
10
+ //
11
+ // 1 is listed as a run here rather than a rejection. The evidence for that is
12
+ // NOT a live stylelint: it is this repo's own hand-written fixture
13
+ // (tests/clients/dispatch/runners/stylelint-fixable.test.ts), which reports
14
+ // findings under exit 1. Rather than rewrite a fixture whose provenance is
15
+ // unknown, the table keeps 1 permissive. That is safe because a genuinely
16
+ // fatal stylelint under `--formatter json` writes nothing to stdout, so the
17
+ // nothing-to-parse rule still catches it. 78 is the rejection this table
18
+ // exists to name.
19
+ const STYLELINT_EXIT_CODES = { ran: [1, 2] };
7
20
  // Stylelint's standard JSON output reports only aggregate fixableErrorCount /
8
21
  // fixableWarningCount per file — there is no per-warning fix flag in the CLI
9
22
  // surface. To route the actionable warnings here without a tool rewrite, we
@@ -100,6 +113,15 @@ const stylelintRunner = {
100
113
  if (!cmd)
101
114
  return { status: "skipped", diagnostics: [], semantic: "none" };
102
115
  const result = await safeSpawnAsync(cmd, ["--formatter", "json", ctx.filePath], { timeout: 20000, cwd });
116
+ // #1816: this runner read `result.status` zero times, so an exit-78
117
+ // config error (or an exit-1 crash) fell through parseStylelintJson's
118
+ // catch to zero diagnostics and reported a clean stylesheet.
119
+ const skipped = skipUnlessToolRan("stylelint", {
120
+ result,
121
+ exitCodes: STYLELINT_EXIT_CODES,
122
+ });
123
+ if (skipped)
124
+ return skipped;
103
125
  const raw = result.stdout ?? "";
104
126
  const diagnostics = parseStylelintJson(raw, ctx.filePath);
105
127
  if (diagnostics.length === 0) {
@@ -2,6 +2,7 @@ import * as path from "node:path";
2
2
  import { safeSpawnAsync } from "../../safe-spawn.js";
3
3
  import { PRIORITY } from "../priorities.js";
4
4
  import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
5
+ import { skipUnlessToolRan } from "./utils/tool-failure.js";
5
6
  const swiftlint = createAvailabilityChecker("swiftlint", ".exe");
6
7
  // SwiftLint rules whose rule class declares a `corrector` — i.e. rules that
7
8
  // `swiftlint --fix` rewrites deterministically. The JSON reporter does not
@@ -126,6 +127,15 @@ const swiftlintRunner = {
126
127
  if (!cmd)
127
128
  return { status: "skipped", diagnostics: [], semantic: "none" };
128
129
  const result = await safeSpawnAsync(cmd, ["--reporter", "json", path.resolve(cwd, ctx.filePath)], { cwd, timeout: 15000 });
130
+ // #1816: this runner read `result.status` zero times, so a SwiftLint
131
+ // that refused the invocation reported a clean Swift file. No exit-code
132
+ // table is declared: SwiftLint's nonzero codes are not documented
133
+ // stably enough to call any of them a rejection, so classification
134
+ // rests on the conservative rule — a nonzero exit with nothing to parse
135
+ // never ran.
136
+ const skipped = skipUnlessToolRan("swiftlint", { result });
137
+ if (skipped)
138
+ return skipped;
129
139
  // SwiftLint exits non-zero on violations — stdout still has the JSON
130
140
  const raw = result.stdout || "";
131
141
  const diagnostics = parseSwiftLintOutput(raw, ctx.filePath);
@@ -1,4 +1,5 @@
1
1
  import * as path from "node:path";
2
+ import { findLocalBinUpwards } from "../../package-manager.js";
2
3
  import { safeSpawnAsync } from "../../safe-spawn.js";
3
4
  import { getLinterPolicyForCwd } from "../../tool-policy.js";
4
5
  import { PRIORITY } from "../priorities.js";
@@ -45,12 +46,23 @@ const taploRunner = {
45
46
  if (lspPrimaryCoversFile(ctx, "toml") && (await ctx.hasTool("taplo"))) {
46
47
  return { status: "skipped", diagnostics: [], semantic: "none" };
47
48
  }
48
- let cmd = null;
49
- if (await (taplo.isAvailableAsync(cwd))) {
50
- cmd = taplo.getCommand(cwd);
51
- }
52
- else {
53
- cmd = await resolveToolCommandWithInstallFallback(cwd, "taplo");
49
+ // Project binary first (#1731, discipline B): `taplo.isAvailableAsync`
50
+ // resolves through `findManagedNodeToolBinary`, pi-lens's own managed
51
+ // shim — checked BEFORE any project-local candidate, so a project's own
52
+ // `node_modules/.bin/taplo` (npm `@taplo/cli`) never won once the managed
53
+ // copy answered. `findLocalBinUpwards` defaults to `.cmd` on Windows,
54
+ // matching that npm shim; the availability checker's `.exe` extension is
55
+ // correct for pi-lens's OWN managed install (a GitHub-release binary,
56
+ // `clients/installer/index.ts` taplo entry), a different artifact with a
57
+ // different extension, so it stays as the checker's fallback only.
58
+ let cmd = findLocalBinUpwards("taplo", cwd) ?? null;
59
+ if (!cmd) {
60
+ if (await (taplo.isAvailableAsync(cwd))) {
61
+ cmd = taplo.getCommand(cwd);
62
+ }
63
+ else {
64
+ cmd = await resolveToolCommandWithInstallFallback(cwd, "taplo");
65
+ }
54
66
  }
55
67
  if (!cmd)
56
68
  return { status: "skipped", diagnostics: [], semantic: "none" };
@@ -10,6 +10,11 @@
10
10
  * v1 scope — the highest-value, lowest-overlap surface:
11
11
  * - **Kubernetes manifests** (yaml with an `apiVersion:` + `kind:` signature):
12
12
  * zero existing coverage in pi-lens, so no dedup needed.
13
+ * - **CloudFormation templates** (yaml OR json with an
14
+ * `AWSTemplateFormatVersion` key, or a `Resources` map whose entries carry
15
+ * an `AWS::`/`Custom::`-namespaced `Type`; refs #1757): same zero-overlap
16
+ * rationale as Kubernetes — trivy's `cloudformation` misconfig scanner is
17
+ * the only IaC-misconfig coverage pi-lens has for CFN.
13
18
  * - **Dockerfiles**: overlaps hadolint on a few rules (`:latest`, root, …);
14
19
  * the dispatcher suppresses trivy-config findings that hadolint already
15
20
  * reports at the same line (`suppressTrivyConfigDockerOverlap`), so trivy
@@ -17,12 +22,11 @@
17
22
  *
18
23
  * - **Terraform**: the `.tf` language files themselves — trivy evaluates
19
24
  * the Terraform language directly, so no content gate is needed (unlike
20
- * the yaml/k8s heuristic above). Terragrunt (`.hcl`) is deliberately
21
- * excluded: trivy has no terragrunt support, and terragrunt config is
22
- * covered by the terragrunt runner instead.
25
+ * the yaml/k8s/CloudFormation heuristics above). Terragrunt (`.hcl`) is
26
+ * deliberately excluded: trivy has no terragrunt support, and terragrunt
27
+ * config is covered by the terragrunt runner instead.
23
28
  *
24
- * Deferred (tracked on #131): Helm chart rendering, Docker Compose,
25
- * CloudFormation.
29
+ * Deferred (tracked on #131): Helm chart rendering, Docker Compose.
26
30
  *
27
31
  * Gating: the same explicit `trivy.enabled` opt-in as the session-scan modes —
28
32
  * trivy is opt-in, period. (Misconfig needs only the small policy bundle, not
@@ -31,13 +35,14 @@
31
35
  *
32
36
  * Refs: #131 (Mode 2)
33
37
  */
38
+ import { formatToolFailure } from "./utils/tool-failure.js";
34
39
  import * as fs from "node:fs";
35
40
  import * as path from "node:path";
41
+ import { incrementDegradationCount } from "../../degradation-ledger.js";
36
42
  import { safeSpawnAsync } from "../../safe-spawn.js";
37
43
  import { isTrivyEnabled, resolveSeverityFloor, } from "../../trivy-client.js";
38
44
  import { PRIORITY } from "../priorities.js";
39
45
  import { createAvailabilityChecker, resolveAvailableOrInstall, } from "./utils/runner-helpers.js";
40
- import { spawnFailedWithNoOutput } from "./utils/spawn-outcome.js";
41
46
  const trivy = createAvailabilityChecker("trivy", ".exe");
42
47
  /**
43
48
  * Heuristic: does this YAML look like a Kubernetes manifest (vs a CI workflow,
@@ -53,6 +58,23 @@ export function looksLikeKubernetesManifest(content) {
53
58
  }
54
59
  return false;
55
60
  }
61
+ /**
62
+ * Heuristic: does this file (yaml OR json) look like a CloudFormation
63
+ * template? The unambiguous signal is the `AWSTemplateFormatVersion` key,
64
+ * present on the vast majority of real templates; SAM templates instead
65
+ * declare `Transform: AWS::Serverless-2016-10-31` (or an array containing
66
+ * it). Templates that skip both still always declare a `Resources` map whose
67
+ * entries carry a `Type` in the `AWS::`/`Custom::`/`Alexa::` namespaces — the
68
+ * one field CFN mandates on every resource. Any one signal qualifies (refs
69
+ * #1757).
70
+ */
71
+ export function looksLikeCloudFormationTemplate(content) {
72
+ if (/AWSTemplateFormatVersion/.test(content))
73
+ return true;
74
+ if (/Transform:\s*(\[.*)?["']?AWS::Serverless/.test(content))
75
+ return true;
76
+ return /Type["']?\s*:\s*["']?(AWS|Custom|Alexa)::/.test(content);
77
+ }
56
78
  function normalizeSeverity(raw) {
57
79
  const s = typeof raw === "string" ? raw.toUpperCase() : "";
58
80
  if (s === "CRITICAL" || s === "HIGH" || s === "MEDIUM" || s === "LOW") {
@@ -122,7 +144,7 @@ export function parseTrivyConfigOutput(raw, filePath) {
122
144
  }
123
145
  const trivyConfigRunner = {
124
146
  id: "trivy-config",
125
- appliesTo: ["docker", "yaml", "terraform"],
147
+ appliesTo: ["docker", "yaml", "terraform", "json"],
126
148
  priority: PRIORITY.GENERAL_ANALYSIS,
127
149
  enabledByDefault: true,
128
150
  skipTestFiles: false,
@@ -133,8 +155,10 @@ const trivyConfigRunner = {
133
155
  return { status: "skipped", diagnostics: [], semantic: "none" };
134
156
  }
135
157
  const absPath = path.resolve(cwd, ctx.filePath);
136
- // YAML is far broader than k8s; only scan files that look like manifests.
137
- if (ctx.kind === "yaml") {
158
+ // YAML is far broader than k8s/CloudFormation; JSON is far broader than
159
+ // CloudFormation — only scan files that look like one of the IaC
160
+ // manifest shapes trivy's misconfig scanners understand (refs #1757).
161
+ if (ctx.kind === "yaml" || ctx.kind === "json") {
138
162
  let content = "";
139
163
  try {
140
164
  content = fs.readFileSync(absPath, "utf-8");
@@ -142,7 +166,11 @@ const trivyConfigRunner = {
142
166
  catch {
143
167
  return { status: "skipped", diagnostics: [], semantic: "none" };
144
168
  }
145
- if (!looksLikeKubernetesManifest(content)) {
169
+ const isManifest = ctx.kind === "yaml"
170
+ ? looksLikeKubernetesManifest(content) ||
171
+ looksLikeCloudFormationTemplate(content)
172
+ : looksLikeCloudFormationTemplate(content);
173
+ if (!isManifest) {
146
174
  return { status: "skipped", diagnostics: [], semantic: "none" };
147
175
  }
148
176
  }
@@ -160,15 +188,48 @@ const trivyConfigRunner = {
160
188
  const severities = resolveSeverityFloor(cwd).join(",");
161
189
  const result = await safeSpawnAsync(cmd, [
162
190
  "config",
191
+ // `--quiet` alone suppresses both the progress bar and log output.
192
+ // `--no-progress` is NOT a `config` subcommand flag (unlike `fs`,
193
+ // which does accept it) — trivy 0.73.0 exits 1 on the rejected
194
+ // flag, but prints its full usage/help text (thousands of bytes)
195
+ // to STDOUT before the FATAL line on stderr. That stdout is
196
+ // non-empty, so an empty-output-only guard did not catch it: the
197
+ // help text failed to JSON-parse, `parseTrivyConfigOutput`
198
+ // returned `[]`, and this reported `{ status: "succeeded",
199
+ // diagnostics: [] }` — a clean scan — on every single real
200
+ // invocation (refs #1757; verified against the real installed
201
+ // binary, not assumed).
163
202
  "--quiet",
164
- "--no-progress",
165
203
  "--format",
166
204
  "json",
167
205
  "--severity",
168
206
  severities,
169
207
  absPath,
170
208
  ], { cwd, timeout: 60_000 });
171
- if (spawnFailedWithNoOutput(result)) {
209
+ // `trivy config` is not given `--exit-code`, so it exits 0 whenever it
210
+ // completed (findings included — see parseTrivyConfigOutput's severity
211
+ // mapping for how CRITICAL becomes blocking). ANY nonzero status is
212
+ // therefore a real error, WITH or WITHOUT something on stdout — mirrors
213
+ // the model already in clients/dispatch/runners/helm-render.ts's
214
+ // runIacPass, which has the same "trivy prints usage text on a bad
215
+ // flag" exposure and already got this right. A bounded ledger record
216
+ // means a broken trivy invocation can no longer go unnoticed for an
217
+ // entire lane's lifetime the way this one did (refs #1757).
218
+ if (result.error || result.status !== 0) {
219
+ // #1816: one shared wording, one truncation, signal named. `subject`
220
+ // stays the file path — the discriminating identity a reader needs
221
+ // is WHICH file trivy stopped covering.
222
+ incrementDegradationCount({
223
+ kind: "runner-empty-result",
224
+ subject: absPath,
225
+ reason: formatToolFailure({
226
+ tool: "trivy config",
227
+ status: result.status,
228
+ signal: result.signal,
229
+ stderr: result.stderr || result.error?.message,
230
+ stdout: result.stdout,
231
+ }),
232
+ });
172
233
  return { status: "skipped", diagnostics: [], semantic: "none" };
173
234
  }
174
235
  const diagnostics = parseTrivyConfigOutput(result.stdout || "", ctx.filePath);