@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
@@ -10,15 +10,16 @@ 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";
17
- import { hashDiagnosticContent, } from "../clients/lsp/diagnostic-binding.js";
17
+ import { hashDiagnosticContent, touchCompletedConfirmationPolicy, touchCoverageGap, } from "../clients/lsp/diagnostic-binding.js";
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
  }
@@ -471,8 +481,15 @@ async function collectDiagnosticsForFile(absPath, lspService, waitMs, serverScop
471
481
  // confirmation: it carries the same caveat all-scope local
472
482
  // touches do, and classic TypeScript still needs the primary-only
473
483
  // tsserver sync check below rather than this verdict.
474
- confirmedByTouch: attached.response.confirmation === "confirmed" &&
484
+ // #1470: `"partial"` counts, for the same reason the local touch
485
+ // branch below accepts it — the incumbent's primary confirmed; only
486
+ // a named auxiliary did not.
487
+ confirmedByTouch: attached.response.confirmation !== undefined &&
475
488
  primaryServerId(absPath) !== "typescript",
489
+ // #1470: the incumbent's narrowed verdict, carried as an explicit DTO
490
+ // field across the socket. An older incumbent omits it → empty → the
491
+ // pre-#1470 handling, unchanged.
492
+ unconfirmedServerIds: attached.response.unconfirmedServerIds ?? [],
476
493
  content,
477
494
  };
478
495
  }
@@ -526,11 +543,20 @@ async function collectDiagnosticsForFile(absPath, lspService, waitMs, serverScop
526
543
  // one; the openFile-only / getDiagnostics fallback leaves it undefined →
527
544
  // "unknown", no demotion).
528
545
  const binding = usedTouch ? touched?.binding : undefined;
529
- const confirmedByTouch = usedTouch && touched?.confirmation === "confirmed";
546
+ // #1470: `"partial"` counts here. `confirmedByTouch` feeds
547
+ // `canTrustTouchConfirmation`, which asks about the PRIMARY's own verdict —
548
+ // and a partial touch is one whose primary confirmed while an auxiliary was
549
+ // cut off. Excluding it would render "Primary LSP: unconfirmed" for a primary
550
+ // that did confirm. The coverage gap is carried separately, below.
551
+ const confirmedByTouch = usedTouch && touchCompletedConfirmationPolicy(touched);
530
552
  return {
531
553
  diagnostics: filtered,
532
554
  timedOut,
533
555
  confirmedByTouch,
556
+ // #1470: only a touch actually contributes a coverage gap; the
557
+ // openFile+getDiagnostics fallback never reports one, which is honest —
558
+ // that path claims no confirmation at all.
559
+ unconfirmedServerIds: usedTouch ? touchCoverageGap(touched) : [],
534
560
  content,
535
561
  binding,
536
562
  };
@@ -616,35 +642,66 @@ function canTrustTouchConfirmation(file, serverScope, confirmedByTouch) {
616
642
  (serverScope === "primary" || primaryServerId(file) !== "typescript"));
617
643
  }
618
644
  /**
619
- * #571: reconcile this tool's fresh LSP result into the footer cache
620
- * (`widget-state.ts`'s `allDiagnostics`) — same shared choke point
621
- * `lens_diagnostics` mode=full uses (`clients/widget-state.ts`'s
622
- * `reconcileScanDiagnostics`). A manual `lsp_diagnostics` check that proves a
623
- * stale footer error is actually gone (the real-world case that surfaced
624
- * #571) is exactly the kind of confirmed result that should correct it.
625
- * Direct `lsp_diagnostics` deliberately does not perform a second disk read at
626
- * this reconciliation seam: its collecting touch already read the content and
627
- * supplies the binding verdict. `false` is unconfirmed and is never written;
628
- * `true` is trusted, while an absent/`unknown` verdict preserves the legacy
629
- * fail-open policy for servers that cannot bind their diagnostics to content.
645
+ * #1561 F1: what this check is entitled to speak for.
630
646
  *
631
- * `rawDiags` (pre-severity-filter) is what gets written — the footer records
632
- * the true known state, independent of this call's display-only severity
633
- * filter. A non-empty result is definitionally confirmed (the server DID
634
- * answer with real diagnostics); an empty result is only confirmed when
635
- * `classifyEmptyResult` (#533) says "clean", not "unconfirmed" (silent
636
- * push-only server — indistinguishable from still-analyzing/never-asked, so
637
- * 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.
638
654
  *
639
- * #692: `retagAuxiliaryDiagnostics` re-tags aux-sourced entries (ast-grep,
640
- * opengrep, zizmor, typos) with their real tool id + semantic policy before
641
- * they're written — the same treatment the per-edit dispatch runner gives
642
- * them — so a scan-reconciled entry no longer keeps tool `"lsp"`. `content`
643
- * is the file content `collectDiagnosticsForFile`/the cache already read (or
644
- * undefined for a cache-hit branch, whose `rawDiags` were already suppression-
645
- * /skipTestFiles-filtered at write time — an empty string here is then a safe
646
- * 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.)
647
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
+ }
648
705
  function reconcileWidgetFromLspResult(file, rawDiags, confirmation, writeIndex, cwd, content,
649
706
  // #1095: true when the result's content binding demonstrably mismatches disk
650
707
  // (boundToCurrentDisk === false). Such a result — even a NON-EMPTY one, which
@@ -662,7 +719,7 @@ boundMismatch = false,
662
719
  observedAt) {
663
720
  const confirmed = (rawDiags.length > 0 || confirmation !== "unconfirmed") && !boundMismatch;
664
721
  if (!confirmed)
665
- return;
722
+ return { confirmed: false, blocking: true };
666
723
  try {
667
724
  // #692: provenance label ONLY — must never affect `rule`/identity (see
668
725
  // `ConvertLspDiagnosticsOptions.scanOrigin`'s doc comment).
@@ -671,9 +728,16 @@ observedAt) {
671
728
  });
672
729
  const retagged = retagAuxiliaryDiagnostics(diagnostics, rawDiags, content ?? "", { cwd, fileRole: detectFileRole(file, content) });
673
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) };
674
735
  }
675
736
  catch {
676
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 };
677
741
  }
678
742
  }
679
743
  async function collectFileDiagnosticResult(file, severity, lspService, waitMs, nextWriteIndex, serverScope = "all",
@@ -687,7 +751,11 @@ cacheCtx, scopeKey,
687
751
  // `allowBlocking(cwd)` for a scan-reconciled aux finding — defaults to
688
752
  // `process.cwd()` for any call site that predates this (there are none
689
753
  // today besides the two below, both of which now pass it explicitly).
690
- 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) {
691
759
  // Reserve the ordering token when this diagnostic operation starts, not when
692
760
  // its LSP promise settles. A slower old result must not receive a newer token
693
761
  // merely because it completed later (#1198).
@@ -709,8 +777,13 @@ cwd = process.cwd()) {
709
777
  // NOT served — fall through to a fresh touch instead of replaying a stale
710
778
  // cached result. "unknown"/true bindings serve as before.
711
779
  if (cached && cached.binding.boundToCurrentDisk !== false) {
712
- const filteredDiags = applySeverityFilter(cached.diagnostics, severity);
713
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);
714
787
  // #692: cached.diagnostics were already suppression-/skipTestFiles-
715
788
  // filtered at write time (this same code path); no file content was
716
789
  // cached alongside them, so `undefined` here is a safe re-check, not
@@ -720,7 +793,7 @@ cwd = process.cwd()) {
720
793
  // now(), or a repeat check that only re-serves the cache would keep
721
794
  // re-arming the mtime-staleness gate and a resolved finding would render
722
795
  // forever (the #1092 defect).
723
- reconcileWidgetFromLspResult(file, cached.diagnostics, confirmation, writeIndex, cwd, undefined,
796
+ reconcileWidgetFromLspResult(file, cachedDiags, confirmation, writeIndex, cwd, undefined,
724
797
  // This branch only runs when the cache binding is not a mismatch
725
798
  // (guarded above), so boundMismatch is false; #1093's observedAt is
726
799
  // the cache entry's original scan time.
@@ -733,7 +806,7 @@ cwd = process.cwd()) {
733
806
  };
734
807
  }
735
808
  }
736
- const { diagnostics: rawDiags, timedOut, confirmedByTouch, content: collectedContent, binding, } = await collectDiagnosticsForFile(file, lspService, waitMs, serverScope);
809
+ const { diagnostics: rawDiags, timedOut, confirmedByTouch, unconfirmedServerIds, content: collectedContent, binding, } = await collectDiagnosticsForFile(file, lspService, waitMs, serverScope);
737
810
  const health = lspService.getDiagnosticsHealth?.(file);
738
811
  // #570: a timed-out priming check is never a confirmed "clean" — treat it
739
812
  // as unconfirmed without consulting the (unrelated) silent-tier
@@ -773,8 +846,27 @@ cwd = process.cwd()) {
773
846
  const boundMismatch = binding?.boundToCurrentDisk === false;
774
847
  if (boundMismatch)
775
848
  confirmation = "unconfirmed";
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
851
+ // about this file, so a "clean" verdict computed from the merged result would
852
+ // be claiming coverage this batch does not have. Demote it — that also keeps
853
+ // the entry out of the workspace cache below, which would otherwise replay the
854
+ // partial answer as a confirmed clean on every later sweep.
855
+ if (unconfirmedServerIds.length > 0 && confirmation === "clean") {
856
+ confirmation = "unconfirmed";
857
+ }
858
+ // #1645 review F3: one demotion rule for every writer of the widget store.
859
+ effectiveRawDiags = await demoteInferredForFile(file, effectiveRawDiags, cwd, lspService);
776
860
  const filteredDiags = applySeverityFilter(effectiveRawDiags, severity);
777
- 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
+ }
778
870
  // #671: only a CONFIRMED outcome ("clean", or a non-empty result — either
779
871
  // is definitionally confirmed per this function's own doctrine above) is
780
872
  // safe to cache; "unconfirmed" (timeout OR a silent-tier server's
@@ -782,7 +874,10 @@ cwd = process.cwd()) {
782
874
  // result — same false-clean bug class `runWorkspaceDiagnostics`'s cache
783
875
  // wiring guards against. #1095: the entry carries the content fingerprint so a
784
876
  // later lookup can verify it against disk beyond the mtime proxy.
785
- if (cacheCtx && scopeKey !== undefined && confirmation !== "unconfirmed") {
877
+ if (cacheCtx &&
878
+ scopeKey !== undefined &&
879
+ confirmation !== "unconfirmed" &&
880
+ unconfirmedServerIds.length === 0) {
786
881
  cacheCtx.record(file, scopeKey, effectiveRawDiags, stat.mtimeMs, collectedContent !== undefined
787
882
  ? hashDiagnosticContent(collectedContent)
788
883
  : undefined);
@@ -796,11 +891,14 @@ cwd = process.cwd()) {
796
891
  primaryServerId: primaryServerId(file),
797
892
  };
798
893
  }
799
- 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) {
800
898
  // Reserve the token before awaiting this file's LSP result. The direct-file
801
899
  // path performs its own confirmation/reconciliation below (#1198).
802
900
  const writeIndex = nextWriteIndex?.();
803
- const { diagnostics: rawDiags, timedOut, confirmedByTouch, content: collectedContent, binding, } = await collectDiagnosticsForFile(absPath, lspService, waitMs, serverScope);
901
+ const { diagnostics: rawDiags, timedOut, confirmedByTouch, unconfirmedServerIds, content: collectedContent, binding, } = await collectDiagnosticsForFile(absPath, lspService, waitMs, serverScope);
804
902
  const lspHealth = lspService.getDiagnosticsHealth?.(absPath);
805
903
  const unavailable = lspUnavailableMessage(absPath, lspHealth);
806
904
  // #533: an empty result needs a confirmed/unconfirmed verdict — a push-only,
@@ -842,12 +940,36 @@ async function runFileDiagnostics(absPath, severity, lspService, waitMs, nextWri
842
940
  const boundMismatch = binding?.boundToCurrentDisk === false;
843
941
  if (boundMismatch)
844
942
  confirmation = "unconfirmed";
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
947
+ // PRIMARY's own verdict is untouched (`primaryCoverageGapOnly` below), so a
948
+ // TypeScript answer stays "confirmed clean" on its own line while an explicit
949
+ // line names the scanner whose coverage is absent.
950
+ const primaryCoverageGapOnly = unconfirmedServerIds.length > 0 && confirmation === "clean";
951
+ if (primaryCoverageGapOnly)
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);
845
955
  const filtered = applySeverityFilter(effectiveRawDiags, severity);
846
956
  const total = filtered.length;
847
957
  const truncated = total > MAX_DIAGNOSTICS;
848
958
  const limited = truncated ? filtered.slice(0, MAX_DIAGNOSTICS) : filtered;
849
959
  const unconfirmed = confirmation === "unconfirmed";
850
- 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
+ }
851
973
  const primaryId = primaryServerId(absPath);
852
974
  const primaryDiags = limited.filter((d) => d.source === primaryId);
853
975
  const auxiliaryDiags = limited.filter((d) => d.source !== primaryId);
@@ -860,7 +982,11 @@ async function runFileDiagnostics(absPath, severity, lspService, waitMs, nextWri
860
982
  "file may still have errors that just hadn't been reported yet. " +
861
983
  "Re-check after the server settles, or increase waitMs.");
862
984
  }
863
- if (unconfirmed) {
985
+ // #1470: a file demoted ONLY because an auxiliary was cut off must not render
986
+ // the silent-on-clean text — the primary did confirm, and saying otherwise is
987
+ // the same overclaim in the opposite direction. The coverage line below names
988
+ // what is actually missing.
989
+ if (unconfirmed && !primaryCoverageGapOnly) {
864
990
  return (`Primary LSP${primaryId ? ` (${primaryId})` : ""}: unconfirmed — ` +
865
991
  "cannot confirm clean (push-only, silent-on-clean, e.g. classic " +
866
992
  "typescript-language-server never publishes on a clean re-check). " +
@@ -872,9 +998,20 @@ async function runFileDiagnostics(absPath, severity, lspService, waitMs, nextWri
872
998
  }
873
999
  return `Primary LSP${primaryId ? ` (${primaryId})` : ""}: ${primaryDiags.length} diagnostic${primaryDiags.length === 1 ? "" : "s"}.`;
874
1000
  })();
1001
+ // #1470: this is the narrowing made readable. It states exactly which servers
1002
+ // this result does NOT speak for, so "no auxiliary findings" can never be read
1003
+ // as "the security scanners found nothing".
1004
+ const coverageLine = unconfirmedServerIds.length > 0
1005
+ ? `Auxiliary coverage INCOMPLETE — ${[...unconfirmedServerIds].join(", ")} did not answer within the wait budget, so ${unconfirmedServerIds.length === 1 ? "its findings are" : "their findings are"} NOT included here. This is not a clean bill of health for ${unconfirmedServerIds.length === 1 ? "that scanner" : "those scanners"}; re-check after the next edit, or use waitMs to wait longer.`
1006
+ : undefined;
875
1007
  let text;
876
1008
  if (total === 0) {
877
- text = [primaryLine, "", unavailable ?? "No auxiliary findings."].join("\n");
1009
+ text = [
1010
+ primaryLine,
1011
+ "",
1012
+ unavailable ?? "No auxiliary findings.",
1013
+ ...(coverageLine ? [coverageLine] : []),
1014
+ ].join("\n");
878
1015
  }
879
1016
  else {
880
1017
  const lines = [primaryLine, ""];
@@ -885,6 +1022,8 @@ async function runFileDiagnostics(absPath, severity, lspService, waitMs, nextWri
885
1022
  lines.push(`Auxiliary findings (${auxiliaryDiags.length}):`);
886
1023
  lines.push(...auxiliaryDiags.map(formatDiag));
887
1024
  }
1025
+ if (coverageLine)
1026
+ lines.push("", coverageLine);
888
1027
  if (unavailable)
889
1028
  lines.unshift(unavailable, "");
890
1029
  if (truncated) {
@@ -914,6 +1053,11 @@ async function runFileDiagnostics(absPath, severity, lspService, waitMs, nextWri
914
1053
  truncated,
915
1054
  unconfirmed,
916
1055
  timedOut: unconfirmed ? timedOut : undefined,
1056
+ // #1470: which servers this result does NOT speak for. Absent when it
1057
+ // speaks for all of them.
1058
+ ...(unconfirmedServerIds.length > 0 && {
1059
+ unconfirmedServerIds: [...unconfirmedServerIds],
1060
+ }),
917
1061
  lspHealth,
918
1062
  waitMs,
919
1063
  },
@@ -1023,7 +1167,7 @@ async function collectBatchDiagnostics(files, severity, lspService, options) {
1023
1167
  const cacheCtx = createWorkspaceDiagnosticsCacheContext(resolvedCwd);
1024
1168
  const scopeKey = buildScopeKey(options.serverScope ?? "all");
1025
1169
  const results = await mapWithConcurrency(files, options.concurrency, async (file) => {
1026
- 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);
1027
1171
  const bounded = withDeadline(work, {
1028
1172
  ms: batchFileDeadlineMs(),
1029
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:
@@ -33,7 +33,7 @@ export function createSymbolSearchTool(getProjectRoot) {
33
33
  }),
34
34
  parameters: Type.Object({
35
35
  query: Type.String({
36
- description: "Identifier-ish query, e.g. 'authenticate user'.",
36
+ description: "Identifier-ish query, e.g. 'authenticate user'. Mix in composable prefix filters: lang:<kind> (e.g. lang:jsts, lang:python — kinds from file-kinds.ts), file:<substr> (path substring), ext:<ext> (e.g. ext:ts or ext:.ts), each optionally negated with a leading '-' (-file:test). Filters apply before ranking; e.g. 'lang:jsts file:clients/ -file:test rank'. Unknown prefixes/kinds error with the supported list.",
37
37
  }),
38
38
  limit: Type.Optional(Type.Number({
39
39
  description: "Max files to return (default 20).",