@herbertgao/pi-extensions 2026.8.6 → 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 (343) hide show
  1. package/README.md +5 -5
  2. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +1 -1
  3. package/node_modules/@herbertgao/pi-cc-extensions/README.md +1 -1
  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/renderer/compact-mode.ts +94 -77
  8. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/message-display.ts +1 -1
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +14 -0
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +55 -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 +1 -0
  35. package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +26 -10
  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 +2 -1
  39. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/localization.md +3 -1
  40. package/node_modules/@juicesharp/rpiv-ask-user-question/locales/en.json +2 -2
  41. package/node_modules/@juicesharp/rpiv-ask-user-question/locales/zh.json +2 -2
  42. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +3 -2
  43. package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +10 -0
  44. package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +3 -1
  45. package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +30 -7
  46. package/node_modules/@juicesharp/rpiv-ask-user-question/state/state.ts +14 -6
  47. package/node_modules/@juicesharp/rpiv-ask-user-question/view/dialog-builder.ts +30 -4
  48. package/node_modules/@juicesharp/rpiv-ask-user-question/view/tab-content-strategy.ts +26 -5
  49. package/node_modules/@narumitw/pi-btw/README.md +120 -111
  50. package/node_modules/@narumitw/pi-btw/dist/index.ts +2898 -0
  51. package/node_modules/@narumitw/pi-btw/dist/index.ts.map +7 -0
  52. package/node_modules/@narumitw/pi-btw/package.json +10 -6
  53. package/node_modules/@narumitw/pi-btw/src/btw.ts +36 -40
  54. package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +55 -10
  55. package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +390 -0
  56. package/node_modules/@narumitw/pi-btw/src/menu.ts +45 -2
  57. package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +136 -45
  58. package/node_modules/pi-lens/CHANGELOG.md +909 -0
  59. package/node_modules/pi-lens/README.md +11 -3
  60. package/node_modules/pi-lens/config/ruff/core.toml +42 -0
  61. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +130 -27
  62. package/node_modules/pi-lens/dist/clients/advisory-provenance.js +126 -13
  63. package/node_modules/pi-lens/dist/clients/agent-nudge.js +67 -11
  64. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +9 -3
  65. package/node_modules/pi-lens/dist/clients/atomic-write.js +9 -3
  66. package/node_modules/pi-lens/dist/clients/bash-file-access.js +285 -8
  67. package/node_modules/pi-lens/dist/clients/biome-client.js +61 -30
  68. package/node_modules/pi-lens/dist/clients/blocker-freshness.js +428 -0
  69. package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +119 -0
  70. package/node_modules/pi-lens/dist/clients/bootstrap.js +12 -1
  71. package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +12 -3
  72. package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +192 -0
  73. package/node_modules/pi-lens/dist/clients/cascade-budget.js +196 -0
  74. package/node_modules/pi-lens/dist/clients/cascade-format.js +20 -1
  75. package/node_modules/pi-lens/dist/clients/cascade-types.js +9 -1
  76. package/node_modules/pi-lens/dist/clients/child-unref.js +54 -6
  77. package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +76 -24
  78. package/node_modules/pi-lens/dist/clients/dead-code-client.js +123 -31
  79. package/node_modules/pi-lens/dist/clients/deadline-utils.js +8 -1
  80. package/node_modules/pi-lens/dist/clients/debug-handles.js +5 -0
  81. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +62 -13
  82. package/node_modules/pi-lens/dist/clients/dependency-checker.js +25 -3
  83. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +147 -33
  84. package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +298 -0
  85. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +52 -2
  86. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +256 -88
  87. package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +7 -4
  88. package/node_modules/pi-lens/dist/clients/dispatch/plan.js +5 -0
  89. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +234 -18
  90. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +187 -19
  91. package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +6 -3
  92. package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +11 -9
  93. package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +398 -0
  94. package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +11 -3
  95. package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +12 -7
  96. package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +18 -0
  97. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +895 -0
  98. package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +4 -0
  99. package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +16 -3
  100. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +60 -53
  101. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +16 -0
  102. package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +23 -0
  103. package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +331 -55
  104. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +38 -5
  105. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +97 -19
  106. package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +14 -0
  107. package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +20 -0
  108. package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +22 -0
  109. package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +10 -0
  110. package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +18 -6
  111. package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +73 -12
  112. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +275 -13
  113. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +21 -6
  114. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +260 -27
  115. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +734 -64
  116. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +86 -11
  117. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +72 -0
  118. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +9 -0
  119. package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +9 -0
  120. package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +18 -1
  121. package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +4 -2
  122. package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +28 -5
  123. package/node_modules/pi-lens/dist/clients/extension-log.js +22 -1
  124. package/node_modules/pi-lens/dist/clients/file-kinds.js +8 -2
  125. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +294 -0
  126. package/node_modules/pi-lens/dist/clients/finding-identity.js +88 -0
  127. package/node_modules/pi-lens/dist/clients/formatters-lazy.js +3 -2
  128. package/node_modules/pi-lens/dist/clients/formatters.js +500 -115
  129. package/node_modules/pi-lens/dist/clients/generation-guard.js +216 -0
  130. package/node_modules/pi-lens/dist/clients/git-guard.js +31 -0
  131. package/node_modules/pi-lens/dist/clients/gitleaks-client.js +181 -8
  132. package/node_modules/pi-lens/dist/clients/govulncheck-client.js +109 -9
  133. package/node_modules/pi-lens/dist/clients/grammar-source.js +333 -10
  134. package/node_modules/pi-lens/dist/clients/host-ports.js +8 -0
  135. package/node_modules/pi-lens/dist/clients/installer/index.js +1114 -100
  136. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh-session.js +58 -0
  137. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +715 -0
  138. package/node_modules/pi-lens/dist/clients/instance-reaper.js +643 -97
  139. package/node_modules/pi-lens/dist/clients/instance-registry.js +87 -17
  140. package/node_modules/pi-lens/dist/clients/jscpd-client.js +82 -6
  141. package/node_modules/pi-lens/dist/clients/knip-client.js +310 -10
  142. package/node_modules/pi-lens/dist/clients/language-policy.js +8 -2
  143. package/node_modules/pi-lens/dist/clients/language-profile.js +2 -0
  144. package/node_modules/pi-lens/dist/clients/latency-logger.js +440 -11
  145. package/node_modules/pi-lens/dist/clients/lazy-import.js +21 -0
  146. package/node_modules/pi-lens/dist/clients/ledger-bounds.js +21 -0
  147. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +8 -0
  148. package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +102 -7
  149. package/node_modules/pi-lens/dist/clients/lsp/client.js +1516 -159
  150. package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +83 -1
  151. package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +389 -0
  152. package/node_modules/pi-lens/dist/clients/lsp/index.js +2274 -147
  153. package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +215 -0
  154. package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +146 -14
  155. package/node_modules/pi-lens/dist/clients/lsp/language.js +48 -4
  156. package/node_modules/pi-lens/dist/clients/lsp/server.js +277 -16
  157. package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +22 -0
  158. package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +43 -0
  159. package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +79 -3
  160. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +43 -0
  161. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +422 -28
  162. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-session.js +30 -0
  163. package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +175 -0
  164. package/node_modules/pi-lens/dist/clients/lsp-lazy.js +3 -2
  165. package/node_modules/pi-lens/dist/clients/mcp/session.js +10 -2
  166. package/node_modules/pi-lens/dist/clients/module-report.js +8 -0
  167. package/node_modules/pi-lens/dist/clients/opengrep-client.js +15 -1
  168. package/node_modules/pi-lens/dist/clients/package-manager.js +170 -14
  169. package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +27 -0
  170. package/node_modules/pi-lens/dist/clients/path-utils.js +160 -0
  171. package/node_modules/pi-lens/dist/clients/pipeline.js +154 -33
  172. package/node_modules/pi-lens/dist/clients/post-autofix-notice.js +37 -0
  173. package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +17 -3
  174. package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +89 -22
  175. package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +84 -14
  176. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +15 -3
  177. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +50 -2
  178. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +5 -0
  179. package/node_modules/pi-lens/dist/clients/project-lens-config.js +3 -0
  180. package/node_modules/pi-lens/dist/clients/project-snapshot.js +299 -0
  181. package/node_modules/pi-lens/dist/clients/quiet-window-config.js +47 -0
  182. package/node_modules/pi-lens/dist/clients/quiet-window.js +11 -25
  183. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +1 -1
  184. package/node_modules/pi-lens/dist/clients/read-guard.js +184 -10
  185. package/node_modules/pi-lens/dist/clients/resource-sampler.js +49 -17
  186. package/node_modules/pi-lens/dist/clients/reverse-deps.js +50 -11
  187. package/node_modules/pi-lens/dist/clients/review-graph/query.js +52 -4
  188. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +96 -7
  189. package/node_modules/pi-lens/dist/clients/runtime-context.js +8 -1
  190. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +308 -45
  191. package/node_modules/pi-lens/dist/clients/runtime-session.js +332 -9
  192. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +217 -22
  193. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +212 -79
  194. package/node_modules/pi-lens/dist/clients/runtime-turn.js +575 -67
  195. package/node_modules/pi-lens/dist/clients/safe-spawn.js +220 -7
  196. package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +161 -0
  197. package/node_modules/pi-lens/dist/clients/search-read-registration.js +34 -6
  198. package/node_modules/pi-lens/dist/clients/security-scan-client.js +157 -24
  199. package/node_modules/pi-lens/dist/clients/sg-runner.js +116 -22
  200. package/node_modules/pi-lens/dist/clients/single-flight.js +158 -0
  201. package/node_modules/pi-lens/dist/clients/stale-marker.js +17 -0
  202. package/node_modules/pi-lens/dist/clients/startup-timing.js +19 -1
  203. package/node_modules/pi-lens/dist/clients/test-runner-client.js +151 -16
  204. package/node_modules/pi-lens/dist/clients/tool-event.js +56 -5
  205. package/node_modules/pi-lens/dist/clients/tool-policy.js +125 -20
  206. package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +75 -1
  207. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +769 -64
  208. package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +11 -0
  209. package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +90 -0
  210. package/node_modules/pi-lens/dist/clients/trivy-client.js +19 -1
  211. package/node_modules/pi-lens/dist/clients/widget-state.js +336 -36
  212. package/node_modules/pi-lens/dist/clients/zizmor-config.js +214 -14
  213. package/node_modules/pi-lens/dist/index.js +67738 -55739
  214. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +466 -54
  215. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +132 -43
  216. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -7
  217. package/node_modules/pi-lens/docs/agent-guide.md +6 -1
  218. package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +515 -506
  219. package/node_modules/pi-lens/docs/dispositions.md +21 -0
  220. package/node_modules/pi-lens/docs/features.md +19 -5
  221. package/node_modules/pi-lens/docs/globalconfig.md +3 -0
  222. package/node_modules/pi-lens/docs/language-coverage.md +71 -5
  223. package/node_modules/pi-lens/docs/mcp.md +2 -2
  224. package/node_modules/pi-lens/docs/servercapabilities.md +4 -1
  225. package/node_modules/pi-lens/docs/settings.md +19 -1
  226. package/node_modules/pi-lens/docs/usage.md +1 -0
  227. package/node_modules/pi-lens/package.json +10 -6
  228. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-js-snapshot.yml +23 -0
  229. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-snapshot.yml +23 -0
  230. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/ts-void-zero-snapshot.yml +23 -0
  231. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-object-param-test.yml +16 -0
  232. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +15 -1
  233. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-compile-call-test.yml +29 -1
  234. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-dupe-class-members-test.yml +33 -0
  235. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-js-test.yml +7 -1
  236. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-test.yml +7 -1
  237. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-known-value-widening-test.yml +9 -0
  238. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-non-null-assertion-test.yml +216 -0
  239. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +2 -0
  240. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +2 -0
  241. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +2 -1
  242. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +2 -1
  243. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-return-value-in-generator-test.yml +12 -0
  244. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-runtime-typeof-test.yml +33 -0
  245. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-server-bind-wildcard-test.yml +9 -0
  246. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-shape-in-symbol-names-test.yml +13 -0
  247. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-js-test.yml +5 -1
  248. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-test.yml +5 -1
  249. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-parameters-test.yml +12 -0
  250. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-returns-test.yml +16 -0
  251. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-any-test.yml +10 -0
  252. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-unknown-test.yml +8 -0
  253. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/redundant-unsafe-function-test.yml +35 -0
  254. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/require-safety-comment-for-as-unknown-as-test.yml +177 -0
  255. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/ts-void-zero-test.yml +1 -0
  256. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member-js.yml +13 -2
  257. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member.yml +13 -2
  258. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +2 -0
  259. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-object-param.yml +60 -0
  260. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +57 -12
  261. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-compile-call.yml +63 -5
  262. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-dupe-class-members.yml +52 -8
  263. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html-js.yml +27 -2
  264. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html.yml +27 -2
  265. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-known-value-widening.yml +71 -0
  266. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-non-null-assertion.yml +316 -0
  267. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +7 -0
  268. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +22 -2
  269. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +23 -2
  270. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +33 -5
  271. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +34 -8
  272. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-return-value-in-generator.yml +22 -5
  273. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-runtime-typeof.yml +121 -0
  274. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-server-bind-wildcard.yml +23 -7
  275. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-shape-in-symbol-names.yml +68 -0
  276. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code-js.yml +41 -2
  277. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code.yml +41 -2
  278. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +6 -1
  279. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-parameters.yml +67 -0
  280. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-returns.yml +106 -0
  281. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-any.yml +50 -0
  282. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-unknown.yml +56 -0
  283. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +2 -0
  284. package/node_modules/pi-lens/rules/ast-grep-rules/rules/redundant-unsafe-function.yml +32 -0
  285. package/node_modules/pi-lens/rules/ast-grep-rules/rules/require-safety-comment-for-as-unknown-as.yml +184 -0
  286. package/node_modules/pi-lens/rules/ast-grep-rules/rules/ts-void-zero.yml +5 -0
  287. package/node_modules/pi-lens/rules/ast-grep-rules/self-scan-baseline.json +5 -0
  288. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +53 -1
  289. package/node_modules/pi-lens/scripts/download-grammars.js +25 -0
  290. package/node_modules/pi-lens/scripts/grammars.lock.json +9 -0
  291. package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +2 -0
  292. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +80 -3
  293. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +41 -0
  294. package/node_modules/pi-lens/vendor/grammars/tree-sitter-cue.wasm +0 -0
  295. package/node_modules/pi-mcp-adapter/CHANGELOG.md +36 -0
  296. package/node_modules/pi-mcp-adapter/README.md +47 -5
  297. package/node_modules/pi-mcp-adapter/cli.js +163 -1
  298. package/node_modules/pi-mcp-adapter/commands.ts +128 -22
  299. package/node_modules/pi-mcp-adapter/config.ts +25 -7
  300. package/node_modules/pi-mcp-adapter/direct-tools.ts +5 -4
  301. package/node_modules/pi-mcp-adapter/index.ts +219 -32
  302. package/node_modules/pi-mcp-adapter/init.ts +36 -4
  303. package/node_modules/pi-mcp-adapter/lifecycle.ts +315 -24
  304. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +39 -6
  305. package/node_modules/pi-mcp-adapter/mcp-bearer-store.ts +387 -0
  306. package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +27 -3
  307. package/node_modules/pi-mcp-adapter/mcp-code.ts +4 -0
  308. package/node_modules/pi-mcp-adapter/mcp-panel.ts +42 -13
  309. package/node_modules/pi-mcp-adapter/metadata-cache.ts +32 -21
  310. package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +168 -0
  311. package/node_modules/pi-mcp-adapter/package.json +3 -1
  312. package/node_modules/pi-mcp-adapter/proxy-modes.ts +5 -4
  313. package/node_modules/pi-mcp-adapter/request-headers-command.ts +31 -37
  314. package/node_modules/pi-mcp-adapter/search-ranking.ts +92 -22
  315. package/node_modules/pi-mcp-adapter/server-manager.ts +140 -2
  316. package/node_modules/pi-mcp-adapter/session-recovery.ts +7 -0
  317. package/node_modules/pi-mcp-adapter/tool-approval.ts +15 -2
  318. package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +44 -4
  319. package/node_modules/pi-mcp-adapter/types.ts +2 -0
  320. package/node_modules/pi-mcp-adapter/ui-server.ts +18 -16
  321. package/node_modules/pi-mcp-adapter/utils.ts +70 -0
  322. package/node_modules/pi-web-access/CHANGELOG.md +23 -0
  323. package/node_modules/pi-web-access/README.md +27 -9
  324. package/node_modules/pi-web-access/anysearch.ts +4 -2
  325. package/node_modules/pi-web-access/brave.ts +16 -4
  326. package/node_modules/pi-web-access/curator-page.ts +6 -3
  327. package/node_modules/pi-web-access/curator-server.ts +4 -1
  328. package/node_modules/pi-web-access/exa.ts +18 -7
  329. package/node_modules/pi-web-access/extract.ts +28 -3
  330. package/node_modules/pi-web-access/gemini-search.ts +16 -4
  331. package/node_modules/pi-web-access/index.ts +41 -57
  332. package/node_modules/pi-web-access/package.json +1 -1
  333. package/node_modules/pi-web-access/page-query.ts +4 -2
  334. package/node_modules/pi-web-access/parallel-mcp.ts +249 -0
  335. package/node_modules/pi-web-access/parallel.ts +2 -2
  336. package/node_modules/pi-web-access/query-rewrite.ts +51 -0
  337. package/node_modules/pi-web-access/serper.ts +211 -0
  338. package/node_modules/pi-web-access/summary-model-scope.ts +12 -4
  339. package/node_modules/pi-web-access/summary-review.ts +44 -22
  340. package/node_modules/pi-web-access/tavily.ts +16 -4
  341. package/node_modules/pi-web-access/utils.ts +87 -0
  342. package/node_modules/pi-web-access/valyu.ts +199 -0
  343. package/package.json +13 -13
@@ -10,7 +10,7 @@ import { Type } from "../clients/deps/typebox.js";
10
10
  import { getProjectIgnoreMatcher, isExcludedDirName, } from "../clients/file-utils.js";
11
11
  import { getLSPService, groupFilesByPrimaryServer, runPerServerGroups, } from "../clients/lsp/index.js";
12
12
  import { buildScopeKey, createWorkspaceDiagnosticsCacheContext, } from "../clients/lsp/workspace-diagnostics-cache.js";
13
- import { primaryServerId } from "../clients/lsp/config.js";
13
+ import { getServersForFileWithConfig, primaryServerId, } from "../clients/lsp/config.js";
14
14
  import { combineAbortSignals, withDeadline } from "../clients/deadline-utils.js";
15
15
  import { applyAuxiliarySuppressions, retagAuxiliaryDiagnostics, } from "../clients/dispatch/auxiliary-lsp.js";
16
16
  import { detectFileRole } from "../clients/file-role.js";
@@ -18,7 +18,8 @@ import { hashDiagnosticContent, touchCompletedConfirmationPolicy, touchCoverageG
18
18
  import { classifyCascadeWaitTier } from "../clients/lsp/wait-policy/index.js";
19
19
  import { attemptTsserverSyncDiagnostics, } from "../clients/lsp/tsserver-sync.js";
20
20
  import { convertLspDiagnostics } from "../clients/dispatch/utils/lsp-diagnostics.js";
21
- import { reconcileScanDiagnostics } from "../clients/widget-state.js";
21
+ import { demoteInferredProjectDiagnostics } from "../clients/lsp/inferred-project.js";
22
+ import { isBlocking, reconcileScanDiagnostics } from "../clients/widget-state.js";
22
23
  import { baseName, compactRenderResult } from "./render-compact.js";
23
24
  import { makeProgressReporter, scanningSummaryLine } from "./scan-progress.js";
24
25
  import { isWarmAttached, tryWarmAttachedDiagnostics, } from "../clients/warm-attach.js";
@@ -239,7 +240,14 @@ export function createLspDiagnosticsTool(
239
240
  // confirmed result reconciled into the footer reserves its token when the
240
241
  // per-file check starts, so settlement order cannot make an older result look
241
242
  // newer. Optional/undefined in tests.
242
- nextWriteIndex) {
243
+ nextWriteIndex,
244
+ // #1561: #571 wired this tool's confirmed result into the widget footer and
245
+ // stopped there. The inline-blocker map is a SECOND agent-facing store fed by
246
+ // the same dispatch verdict, and nothing retired it — so pi-lens kept
247
+ // injecting "Unresolved from this turn" for three more turns after answering
248
+ // "confirmed clean" for the same file. index.ts injects
249
+ // `runtime.retireInlineBlockerOnConfirmedClean`. Optional/undefined in tests.
250
+ onConfirmedNoBlockers) {
243
251
  return {
244
252
  name: "lsp_diagnostics",
245
253
  label: "LSP Diagnostics",
@@ -387,6 +395,7 @@ nextWriteIndex) {
387
395
  nextWriteIndex,
388
396
  serverScope,
389
397
  cwd,
398
+ onConfirmedNoBlockers,
390
399
  });
391
400
  }
392
401
  const rawPath = typedParams.path;
@@ -427,9 +436,10 @@ nextWriteIndex) {
427
436
  nextWriteIndex,
428
437
  serverScope,
429
438
  cwd,
439
+ onConfirmedNoBlockers,
430
440
  });
431
441
  }
432
- return runFileDiagnostics(absPath, severity, lspService, waitMs, nextWriteIndex, serverScope, cwd);
442
+ return runFileDiagnostics(absPath, severity, lspService, waitMs, nextWriteIndex, serverScope, cwd, onConfirmedNoBlockers);
433
443
  },
434
444
  };
435
445
  }
@@ -632,35 +642,66 @@ function canTrustTouchConfirmation(file, serverScope, confirmedByTouch) {
632
642
  (serverScope === "primary" || primaryServerId(file) !== "typescript"));
633
643
  }
634
644
  /**
635
- * #571: reconcile this tool's fresh LSP result into the footer cache
636
- * (`widget-state.ts`'s `allDiagnostics`) — same shared choke point
637
- * `lens_diagnostics` mode=full uses (`clients/widget-state.ts`'s
638
- * `reconcileScanDiagnostics`). A manual `lsp_diagnostics` check that proves a
639
- * stale footer error is actually gone (the real-world case that surfaced
640
- * #571) is exactly the kind of confirmed result that should correct it.
641
- * Direct `lsp_diagnostics` deliberately does not perform a second disk read at
642
- * this reconciliation seam: its collecting touch already read the content and
643
- * supplies the binding verdict. `false` is unconfirmed and is never written;
644
- * `true` is trusted, while an absent/`unknown` verdict preserves the legacy
645
- * fail-open policy for servers that cannot bind their diagnostics to content.
645
+ * #1561 F1: what this check is entitled to speak for.
646
646
  *
647
- * `rawDiags` (pre-severity-filter) is what gets writtenthe footer records
648
- * the true known state, independent of this call's display-only severity
649
- * filter. A non-empty result is definitionally confirmed (the server DID
650
- * answer with real diagnostics); an empty result is only confirmed when
651
- * `classifyEmptyResult` (#533) says "clean", not "unconfirmed" (silent
652
- * push-only server indistinguishable from still-analyzing/never-asked, so
653
- * must not overwrite a real prior footer entry).
647
+ * Inline blockers are raised by the whole dispatch eslint, biome-check,
648
+ * actionlint, ast-grep security rules while this tool only ever consults
649
+ * language servers. Retiring one therefore needs an explicit coverage claim,
650
+ * and the honest claim is exactly the servers this check consulted and got an
651
+ * answer from. `serverScope: "primary"` consults only the primary, so its claim
652
+ * is `"lsp"` alone; an all-scope check adds each auxiliary server by id, which
653
+ * is the same vocabulary `retagAuxiliaryDiagnostics` tags their findings with.
654
654
  *
655
- * #692: `retagAuxiliaryDiagnostics` re-tags aux-sourced entries (ast-grep,
656
- * opengrep, zizmor, typos) with their real tool id + semantic policy before
657
- * they're written the same treatment the per-edit dispatch runner gives
658
- * them so a scan-reconciled entry no longer keeps tool `"lsp"`. `content`
659
- * is the file content `collectDiagnosticsForFile`/the cache already read (or
660
- * undefined for a cache-hit branch, whose `rawDiags` were already suppression-
661
- * /skipTestFiles-filtered at write time — an empty string here is then a safe
662
- * no-op re-check, not a behavior gap).
655
+ * A server named in `unconfirmedServerIds` is dropped: it produced no evidence
656
+ * for this content, so claiming coverage for it would be the #1470/#1493 lie one
657
+ * layer up. (Today an aux gap also demotes the whole verdict to "unconfirmed",
658
+ * so the hook does not fire at all this stays correct if that ever narrows.)
663
659
  */
660
+ function coveredSourcesForCheck(file, serverScope, unconfirmedServerIds) {
661
+ const unconfirmed = new Set(unconfirmedServerIds);
662
+ const covered = new Set();
663
+ let servers = [];
664
+ try {
665
+ servers = (getServersForFileWithConfig(file) ?? []);
666
+ }
667
+ catch {
668
+ // A registry we cannot read is not a coverage claim. Returning an empty
669
+ // set makes every retire fail closed, which is the safe direction for a
670
+ // commit gate.
671
+ return [];
672
+ }
673
+ for (const server of servers) {
674
+ const auxiliary = server.role === "auxiliary";
675
+ if (auxiliary && serverScope === "primary")
676
+ continue;
677
+ if (unconfirmed.has(server.id))
678
+ continue;
679
+ // The dispatch runner tags the primary language server's findings `lsp`;
680
+ // auxiliaries keep their own tool id.
681
+ covered.add(auxiliary ? server.id : "lsp");
682
+ }
683
+ return [...covered];
684
+ }
685
+ /**
686
+ * #1645 review F3: `lsp_diagnostics` writes into the SAME widget store as
687
+ * `lens_diagnostics mode=full`. Two tools writing one store must apply ONE rule
688
+ * for "is this file's diagnostics demoted" — otherwise an orphan file blocks or
689
+ * does not depending purely on which tool ran last, which is the #1633-V1
690
+ * lesson. Every path in this file that reaches `reconcileWidgetFromLspResult`
691
+ * or the rendered output routes its raw diagnostics through here first, so the
692
+ * store, the counts, and the text all agree.
693
+ *
694
+ * Applied AFTER the confirmation verdict is computed, never before: confirmation
695
+ * asks "did the server answer for this content", which the demotion must not
696
+ * influence.
697
+ */
698
+ function demoteInferredForFile(file, diagnostics, cwd, lspService) {
699
+ return demoteInferredProjectDiagnostics(diagnostics, {
700
+ filePath: file,
701
+ cwd,
702
+ service: lspService,
703
+ });
704
+ }
664
705
  function reconcileWidgetFromLspResult(file, rawDiags, confirmation, writeIndex, cwd, content,
665
706
  // #1095: true when the result's content binding demonstrably mismatches disk
666
707
  // (boundToCurrentDisk === false). Such a result — even a NON-EMPTY one, which
@@ -678,7 +719,7 @@ boundMismatch = false,
678
719
  observedAt) {
679
720
  const confirmed = (rawDiags.length > 0 || confirmation !== "unconfirmed") && !boundMismatch;
680
721
  if (!confirmed)
681
- return;
722
+ return { confirmed: false, blocking: true };
682
723
  try {
683
724
  // #692: provenance label ONLY — must never affect `rule`/identity (see
684
725
  // `ConvertLspDiagnosticsOptions.scanOrigin`'s doc comment).
@@ -687,9 +728,16 @@ observedAt) {
687
728
  });
688
729
  const retagged = retagAuxiliaryDiagnostics(diagnostics, rawDiags, content ?? "", { cwd, fileRole: detectFileRole(file, content) });
689
730
  reconcileScanDiagnostics(file, retagged, true, writeIndex, observedAt);
731
+ // #1561: the blocking tally comes from the SAME `isBlocking` predicate the
732
+ // footer counts with — no second severity rule for the blocker-retire
733
+ // decision to drift away from.
734
+ return { confirmed: true, blocking: retagged.some(isBlocking) };
690
735
  }
691
736
  catch {
692
737
  // Never let a footer-reconciliation hiccup fail the diagnostics check.
738
+ // A verdict we could not compute is NOT evidence of clean: report it as
739
+ // still-blocking so no caller retires a blocker off a failed reconcile.
740
+ return { confirmed: false, blocking: true };
693
741
  }
694
742
  }
695
743
  async function collectFileDiagnosticResult(file, severity, lspService, waitMs, nextWriteIndex, serverScope = "all",
@@ -703,7 +751,11 @@ cacheCtx, scopeKey,
703
751
  // `allowBlocking(cwd)` for a scan-reconciled aux finding — defaults to
704
752
  // `process.cwd()` for any call site that predates this (there are none
705
753
  // today besides the two below, both of which now pass it explicitly).
706
- cwd = process.cwd()) {
754
+ cwd = process.cwd(),
755
+ // #1561: see `createLspDiagnosticsTool`'s parameter doc. Called only for a
756
+ // FRESH observation — never on the cache-hit replay below, whose `rawDiags`
757
+ // are an OLD observation (#1093) and therefore no evidence about now.
758
+ onConfirmedNoBlockers) {
707
759
  // Reserve the ordering token when this diagnostic operation starts, not when
708
760
  // its LSP promise settles. A slower old result must not receive a newer token
709
761
  // merely because it completed later (#1198).
@@ -725,8 +777,13 @@ cwd = process.cwd()) {
725
777
  // NOT served — fall through to a fresh touch instead of replaying a stale
726
778
  // cached result. "unknown"/true bindings serve as before.
727
779
  if (cached && cached.binding.boundToCurrentDisk !== false) {
728
- const filteredDiags = applySeverityFilter(cached.diagnostics, severity);
729
780
  const confirmation = cached.diagnostics.length === 0 ? "clean" : undefined;
781
+ // #1645 review F3: a cache REPLAY writes the widget store exactly like a
782
+ // fresh touch does, so it gets the same demotion. Without this, replaying
783
+ // yesterday's cached blocker would re-cement an orphan file as blocking
784
+ // after mode=full had demoted it.
785
+ const cachedDiags = await demoteInferredForFile(file, cached.diagnostics, cwd, lspService);
786
+ const filteredDiags = applySeverityFilter(cachedDiags, severity);
730
787
  // #692: cached.diagnostics were already suppression-/skipTestFiles-
731
788
  // filtered at write time (this same code path); no file content was
732
789
  // cached alongside them, so `undefined` here is a safe re-check, not
@@ -736,7 +793,7 @@ cwd = process.cwd()) {
736
793
  // now(), or a repeat check that only re-serves the cache would keep
737
794
  // re-arming the mtime-staleness gate and a resolved finding would render
738
795
  // forever (the #1092 defect).
739
- reconcileWidgetFromLspResult(file, cached.diagnostics, confirmation, writeIndex, cwd, undefined,
796
+ reconcileWidgetFromLspResult(file, cachedDiags, confirmation, writeIndex, cwd, undefined,
740
797
  // This branch only runs when the cache binding is not a mismatch
741
798
  // (guarded above), so boundMismatch is false; #1093's observedAt is
742
799
  // the cache entry's original scan time.
@@ -789,7 +846,8 @@ cwd = process.cwd()) {
789
846
  const boundMismatch = binding?.boundToCurrentDisk === false;
790
847
  if (boundMismatch)
791
848
  confirmation = "unconfirmed";
792
- // #1470: an auxiliary cut off by the aux grace timer contributed no evidence
849
+ // #1470/#1493: an auxiliary that never reported — cut off by the aux grace timer,
850
+ // or silent with nothing published for this content — contributed no evidence
793
851
  // about this file, so a "clean" verdict computed from the merged result would
794
852
  // be claiming coverage this batch does not have. Demote it — that also keeps
795
853
  // the entry out of the workspace cache below, which would otherwise replay the
@@ -797,8 +855,18 @@ cwd = process.cwd()) {
797
855
  if (unconfirmedServerIds.length > 0 && confirmation === "clean") {
798
856
  confirmation = "unconfirmed";
799
857
  }
858
+ // #1645 review F3: one demotion rule for every writer of the widget store.
859
+ effectiveRawDiags = await demoteInferredForFile(file, effectiveRawDiags, cwd, lspService);
800
860
  const filteredDiags = applySeverityFilter(effectiveRawDiags, severity);
801
- reconcileWidgetFromLspResult(file, effectiveRawDiags, confirmation, writeIndex, cwd, collectedContent, boundMismatch);
861
+ const verdict = reconcileWidgetFromLspResult(file, effectiveRawDiags, confirmation, writeIndex, cwd, collectedContent, boundMismatch);
862
+ if (verdict.confirmed && !verdict.blocking) {
863
+ onConfirmedNoBlockers?.({
864
+ filePath: file,
865
+ writeIndex,
866
+ coveredSources: coveredSourcesForCheck(file, serverScope, unconfirmedServerIds),
867
+ cwd,
868
+ });
869
+ }
802
870
  // #671: only a CONFIRMED outcome ("clean", or a non-empty result — either
803
871
  // is definitionally confirmed per this function's own doctrine above) is
804
872
  // safe to cache; "unconfirmed" (timeout OR a silent-tier server's
@@ -806,7 +874,10 @@ cwd = process.cwd()) {
806
874
  // result — same false-clean bug class `runWorkspaceDiagnostics`'s cache
807
875
  // wiring guards against. #1095: the entry carries the content fingerprint so a
808
876
  // later lookup can verify it against disk beyond the mtime proxy.
809
- if (cacheCtx && scopeKey !== undefined && confirmation !== "unconfirmed") {
877
+ if (cacheCtx &&
878
+ scopeKey !== undefined &&
879
+ confirmation !== "unconfirmed" &&
880
+ unconfirmedServerIds.length === 0) {
810
881
  cacheCtx.record(file, scopeKey, effectiveRawDiags, stat.mtimeMs, collectedContent !== undefined
811
882
  ? hashDiagnosticContent(collectedContent)
812
883
  : undefined);
@@ -820,7 +891,10 @@ cwd = process.cwd()) {
820
891
  primaryServerId: primaryServerId(file),
821
892
  };
822
893
  }
823
- async function runFileDiagnostics(absPath, severity, lspService, waitMs, nextWriteIndex, serverScope = "all", cwd = process.cwd()) {
894
+ async function runFileDiagnostics(absPath, severity, lspService, waitMs, nextWriteIndex, serverScope = "all", cwd = process.cwd(),
895
+ // #1561: see `createLspDiagnosticsTool`'s parameter doc. This is the path the
896
+ // live incident took (`mode: "file"`).
897
+ onConfirmedNoBlockers) {
824
898
  // Reserve the token before awaiting this file's LSP result. The direct-file
825
899
  // path performs its own confirmation/reconciliation below (#1198).
826
900
  const writeIndex = nextWriteIndex?.();
@@ -866,21 +940,36 @@ async function runFileDiagnostics(absPath, severity, lspService, waitMs, nextWri
866
940
  const boundMismatch = binding?.boundToCurrentDisk === false;
867
941
  if (boundMismatch)
868
942
  confirmation = "unconfirmed";
869
- // #1470: NARROWED, not collapsed. An auxiliary the aux grace timer cut off makes
870
- // the FILE-level verdict unconfirmed the merged result is missing whatever that
871
- // scanner would have said, and this tool is the security lane's read surface. The
943
+ // #1470/#1493: NARROWED, not collapsed. An auxiliary that never reported the aux
944
+ // grace timer cut it off, or it stayed silent with nothing published for this
945
+ // content makes the FILE-level verdict unconfirmed. The merged result is missing
946
+ // whatever that scanner would have said, and this tool is the security lane's read surface. The
872
947
  // PRIMARY's own verdict is untouched (`primaryCoverageGapOnly` below), so a
873
948
  // TypeScript answer stays "confirmed clean" on its own line while an explicit
874
949
  // line names the scanner whose coverage is absent.
875
950
  const primaryCoverageGapOnly = unconfirmedServerIds.length > 0 && confirmation === "clean";
876
951
  if (primaryCoverageGapOnly)
877
952
  confirmation = "unconfirmed";
953
+ // #1645 review F3: one demotion rule for every writer of the widget store.
954
+ effectiveRawDiags = await demoteInferredForFile(absPath, effectiveRawDiags, cwd, lspService);
878
955
  const filtered = applySeverityFilter(effectiveRawDiags, severity);
879
956
  const total = filtered.length;
880
957
  const truncated = total > MAX_DIAGNOSTICS;
881
958
  const limited = truncated ? filtered.slice(0, MAX_DIAGNOSTICS) : filtered;
882
959
  const unconfirmed = confirmation === "unconfirmed";
883
- reconcileWidgetFromLspResult(absPath, effectiveRawDiags, confirmation, writeIndex, cwd, collectedContent, boundMismatch);
960
+ const verdict = reconcileWidgetFromLspResult(absPath, effectiveRawDiags, confirmation, writeIndex, cwd, collectedContent, boundMismatch);
961
+ // #1561: a confirmed current view with nothing at the blocking tier retires
962
+ // this file's stale inline blocker — the store #571 corrected the footer for
963
+ // but never reached, which is how a resolved cross-file finding kept being
964
+ // injected as "Unresolved from this turn" for the rest of the session.
965
+ if (verdict.confirmed && !verdict.blocking) {
966
+ onConfirmedNoBlockers?.({
967
+ filePath: absPath,
968
+ writeIndex,
969
+ coveredSources: coveredSourcesForCheck(absPath, serverScope, unconfirmedServerIds),
970
+ cwd,
971
+ });
972
+ }
884
973
  const primaryId = primaryServerId(absPath);
885
974
  const primaryDiags = limited.filter((d) => d.source === primaryId);
886
975
  const auxiliaryDiags = limited.filter((d) => d.source !== primaryId);
@@ -1078,7 +1167,7 @@ async function collectBatchDiagnostics(files, severity, lspService, options) {
1078
1167
  const cacheCtx = createWorkspaceDiagnosticsCacheContext(resolvedCwd);
1079
1168
  const scopeKey = buildScopeKey(options.serverScope ?? "all");
1080
1169
  const results = await mapWithConcurrency(files, options.concurrency, async (file) => {
1081
- const work = collectFileDiagnosticResult(file, severity, lspService, options.waitMs, options.nextWriteIndex, options.serverScope, cacheCtx, scopeKey, resolvedCwd);
1170
+ const work = collectFileDiagnosticResult(file, severity, lspService, options.waitMs, options.nextWriteIndex, options.serverScope, cacheCtx, scopeKey, resolvedCwd, options.onConfirmedNoBlockers);
1082
1171
  const bounded = withDeadline(work, {
1083
1172
  ms: batchFileDeadlineMs(),
1084
1173
  onTimeout: "undefined",
@@ -9,9 +9,10 @@ import { fileURLToPath, pathToFileURL } from "node:url";
9
9
  import { Type } from "../clients/deps/typebox.js";
10
10
  import { logLatency } from "../clients/latency-logger.js";
11
11
  import { newLspMutationCorrelationId, recordLspMutationOutcome, } from "../clients/lsp-mutation.js";
12
+ import { uriToPath } from "../clients/path-utils.js";
12
13
  import { compactRenderResult } from "./render-compact.js";
13
14
  import { applyWorkspaceEdit, summarizeWorkspaceEdit, } from "../clients/lsp/edits.js";
14
- import { getLSPService } from "../clients/lsp/index.js";
15
+ import { getLSPService, } from "../clients/lsp/index.js";
15
16
  import { buildLspNavigationEnvelope } from "./lsp-structured-output.js";
16
17
  import { SYMBOL_KIND_NAMES } from "../clients/lsp-document-symbols.js";
17
18
  const VALID_OPERATIONS = [
@@ -678,6 +679,7 @@ getFlag, mutationDeps) {
678
679
  let columnResolution;
679
680
  let mutationContext;
680
681
  let requestedApply = false;
682
+ const workspaceScopeAttribution = {};
681
683
  const finalize = (payload, meta) => {
682
684
  if (payload.isError &&
683
685
  requestedApply &&
@@ -698,6 +700,9 @@ getFlag, mutationDeps) {
698
700
  supported,
699
701
  diagnosticsMode,
700
702
  columnResolution,
703
+ ...(Object.keys(workspaceScopeAttribution).length > 0
704
+ ? { workspaceScopeAttribution }
705
+ : {}),
701
706
  },
702
707
  });
703
708
  const text = payload.content[0]?.text ?? "";
@@ -821,7 +826,9 @@ getFlag, mutationDeps) {
821
826
  }
822
827
  const lspService = getLSPService();
823
828
  if (operation === "capabilities") {
824
- const snapshots = await lspService.getCapabilitySnapshots(rawPath ? filePath : undefined);
829
+ const snapshots = rawPath
830
+ ? await lspService.getCapabilitySnapshots(filePath)
831
+ : await lspService.getCapabilitySnapshots(undefined, workspaceScopeAttribution);
825
832
  const output = formatCapabilities(snapshots, rawPath ? filePath : undefined);
826
833
  return finalize({
827
834
  content: [{ type: "text", text: output }],
@@ -838,7 +845,9 @@ getFlag, mutationDeps) {
838
845
  });
839
846
  }
840
847
  if (operation === "workspaceDiagnostics") {
841
- const wsDiagSupport = await lspService.getWorkspaceDiagnosticsSupport(rawPath ? filePath : undefined);
848
+ const wsDiagSupport = rawPath
849
+ ? await lspService.getWorkspaceDiagnosticsSupport(filePath)
850
+ : await lspService.getWorkspaceDiagnosticsSupport(undefined, workspaceScopeAttribution);
842
851
  diagnosticsMode = wsDiagSupport?.mode ?? "unknown";
843
852
  if (rawPath && !filePathIsDirectory) {
844
853
  const hasLSP = lspService.supportsLSP(filePath);
@@ -1007,7 +1016,10 @@ getFlag, mutationDeps) {
1007
1016
  const lspEndLine = (endLine ?? line ?? 1) - 1;
1008
1017
  const lspEndChar = (endCharacter ?? resolvedCharacter.character) - 1;
1009
1018
  const runWorkspaceSymbolOperation = async () => {
1010
- supported = operationSupportStatus(operation, await lspService.getOperationSupport(rawPath ? filePath : undefined));
1019
+ const support = rawPath
1020
+ ? await lspService.getOperationSupport(filePath)
1021
+ : await lspService.getOperationSupport(undefined, workspaceScopeAttribution);
1022
+ supported = operationSupportStatus(operation, support);
1011
1023
  if (supported === false) {
1012
1024
  throw new Error("__UNSUPPORTED__ Active LSP server does not advertise support for workspaceSymbol");
1013
1025
  }
@@ -1018,7 +1030,9 @@ getFlag, mutationDeps) {
1018
1030
  await openFileBestEffort(lspService, filePath);
1019
1031
  }
1020
1032
  try {
1021
- const raw = await lspService.workspaceSymbol(query ?? "", rawPath ? filePath : undefined);
1033
+ const raw = rawPath
1034
+ ? await lspService.workspaceSymbol(query ?? "", filePath)
1035
+ : await lspService.workspaceSymbol(query ?? "", undefined, workspaceScopeAttribution);
1022
1036
  const filtered = (Array.isArray(raw) ? raw : [raw]).filter((s) => typeof s === "object" &&
1023
1037
  s !== null &&
1024
1038
  (!s.kind || NAVIGABLE_SYMBOL_KINDS.has(s.kind)));
@@ -1127,7 +1141,9 @@ getFlag, mutationDeps) {
1127
1141
  if (!command || command.trim().length === 0) {
1128
1142
  throw new Error("__BADINPUT__ command parameter required for executeCommand");
1129
1143
  }
1130
- const advertised = await lspService.getAdvertisedCommands(rawPath ? filePath : undefined);
1144
+ const advertised = rawPath
1145
+ ? await lspService.getAdvertisedCommands(filePath)
1146
+ : await lspService.getAdvertisedCommands(undefined, workspaceScopeAttribution);
1131
1147
  const isAdvertised = advertised.includes(command);
1132
1148
  // Dry-run by default: report advertisement status without running.
1133
1149
  // Mutation only on explicit apply:true (and the client re-checks
@@ -1147,18 +1163,41 @@ getFlag, mutationDeps) {
1147
1163
  if (!isAdvertised) {
1148
1164
  throw new Error(`__UNSUPPORTED__ command "${command}" is not advertised by the active LSP server (advertised: ${advertised.join(", ") || "none"})`);
1149
1165
  }
1150
- return lspService.executeCommand(rawPath ? filePath : undefined, command, commandArguments, mutationContext);
1166
+ return rawPath
1167
+ ? lspService.executeCommand(filePath, command, commandArguments, mutationContext)
1168
+ : lspService.executeCommand(undefined, command, commandArguments, mutationContext, workspaceScopeAttribution);
1151
1169
  }
1152
1170
  case "incomingCalls": {
1153
1171
  if (!callHierarchyItem) {
1154
1172
  throw new Error("__BADINPUT__ callHierarchyItem parameter required for incomingCalls");
1155
1173
  }
1174
+ // #1803 fix-round F1: needsFilePath is false for call-hierarchy
1175
+ // traversal (the operand is callHierarchyItem, not path), so the
1176
+ // shared needsFilePath pre-check at line ~1319 never runs for
1177
+ // this operation — LSPService.incomingCalls' own capability gate
1178
+ // (clients/lsp/index.ts) returns a bare [], which this tool layer
1179
+ // cannot distinguish from "supported server, zero callers found".
1180
+ // Pre-check here, keyed off the item's own uri (the file the
1181
+ // resolved server is scoped to), mirrors
1182
+ // runWorkspaceSymbolOperation's supported-check above: throwing
1183
+ // __UNSUPPORTED__ routes through the catch block below into the
1184
+ // same discriminated isError:true/emptyReason:"unsupported" shape
1185
+ // every other capability-gated operation already reports.
1186
+ supported = operationSupportStatus(operation, await lspService.getOperationSupport(uriToPath(callHierarchyItem.uri)));
1187
+ if (supported === false) {
1188
+ throw new Error("__UNSUPPORTED__ Active LSP server does not advertise support for incomingCalls");
1189
+ }
1156
1190
  return lspService.incomingCalls(callHierarchyItem);
1157
1191
  }
1158
1192
  case "outgoingCalls": {
1159
1193
  if (!callHierarchyItem) {
1160
1194
  throw new Error("__BADINPUT__ callHierarchyItem parameter required for outgoingCalls");
1161
1195
  }
1196
+ // #1803 fix-round F1: same pre-check as incomingCalls above.
1197
+ supported = operationSupportStatus(operation, await lspService.getOperationSupport(uriToPath(callHierarchyItem.uri)));
1198
+ if (supported === false) {
1199
+ throw new Error("__UNSUPPORTED__ Active LSP server does not advertise support for outgoingCalls");
1200
+ }
1162
1201
  return lspService.outgoingCalls(callHierarchyItem);
1163
1202
  }
1164
1203
  default:
@@ -95,7 +95,7 @@ not clean**:
95
95
  | **`unconfirmed`** | A push-only/silent-on-clean LSP server returned empty; emptiness could not be *proven* clean. | Don't report the file as clean. |
96
96
  | **`cold` (not applicable / unavailable this run)** | A heavyweight analyzer (knip/jscpd/madge/gitleaks/govulncheck/trivy/dead-code) didn't contribute. | Don't fold its silence into "no issues." |
97
97
  | **`partial` / `truncated` / file-cap** | A walk/scan hit a file cap or coverage limit; results are a partial view. | Don't treat as whole-project coverage. |
98
- | **`stale`** | A cached diagnostic's file changed on disk since the scan. | Don't trust the stale value. |
98
+ | **`stale`** | A cached diagnostic's file changed on disk since the scan. Secrets findings demote to `🔑 ACTION NEEDED` advisory with the line number withheld, never silently dropped; govulncheck keeps the CVE and drops only the cached line. | Don't trust the stale value or its line number. Re-scan to confirm. |
99
99
  | **cold-LSP `0` (e.g. MCP `fresh` mode)** | LSP cold-spawned and under-reported; a `0` carries an explicit `lsp` signal. | Don't read the `0` as "clean." |
100
100
  | **unsafe root** | cwd resolved at/above `$HOME`, so scanners were skipped. | Re-run from inside the project. |
101
101
 
@@ -113,6 +113,11 @@ is blocking when `semantic === "blocking"`, else it falls back to severity):
113
113
 
114
114
  - **🔴 Blocking** — a hard stop. Secrets, CRITICAL CVEs, unresolved errors, etc.
115
115
  **Resolve every blocker before you consider the work complete.**
116
+ - **🔑 ACTION NEEDED** — a third tier, distinct from both: a secrets finding
117
+ whose cached file changed since the scan. It does not gate commit-guard like
118
+ a blocker does, but it is not "no action required" like an advisory either —
119
+ the finding is unverified, not dismissed. Re-run a secrets scan to confirm
120
+ or clear it.
116
121
  - **Advisory** — informational (🟡 warnings, 📜 license notes, style/hygiene).
117
122
  Address when relevant; they do not gate completion.
118
123