@herbertgao/pi-extensions 2026.8.4 → 2026.8.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (360) hide show
  1. package/README.md +5 -5
  2. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +11 -3
  3. package/node_modules/@herbertgao/pi-cc-extensions/README.md +11 -3
  4. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +24 -0
  5. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +91 -1
  6. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +7 -3
  7. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +74 -5
  8. package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +7 -6
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +21 -12
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +4 -5
  11. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +53 -14
  12. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +22 -12
  13. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +2 -4
  14. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  15. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +18 -0
  16. package/node_modules/@herbertgao/pi-subagents/package.json +8 -4
  17. package/node_modules/@herbertgao/pi-subagents/src/agent-color.ts +72 -67
  18. package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +255 -0
  19. package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +191 -3
  20. package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +20 -4
  21. package/node_modules/@herbertgao/pi-subagents/src/index.ts +289 -113
  22. package/node_modules/@herbertgao/pi-subagents/src/output-file.ts +24 -1
  23. package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +24 -2
  24. package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +15 -6
  25. package/node_modules/@herbertgao/pi-subagents/src/ui/schedule-menu.ts +9 -8
  26. package/node_modules/@herbertgao/pi-subagents/src/ui/select-item.ts +48 -0
  27. package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +9 -5
  28. package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +2 -0
  29. package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +20 -0
  30. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +6 -0
  31. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/keyboard.md +7 -0
  32. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
  33. package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +7 -0
  34. package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +16 -5
  35. package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +4 -2
  36. package/node_modules/@narumitw/pi-btw/README.md +32 -24
  37. package/node_modules/@narumitw/pi-btw/package.json +6 -6
  38. package/node_modules/@narumitw/pi-btw/src/btw.ts +4 -2
  39. package/node_modules/@narumitw/pi-btw/src/menu.ts +34 -13
  40. package/node_modules/@narumitw/pi-btw/src/settings.ts +22 -2
  41. package/node_modules/pi-lens/CHANGELOG.md +2535 -954
  42. package/node_modules/pi-lens/README.md +13 -0
  43. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +73 -18
  44. package/node_modules/pi-lens/dist/clients/advisory-provenance.js +314 -0
  45. package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +21 -4
  46. package/node_modules/pi-lens/dist/clients/agent-nudge.js +14 -7
  47. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +68 -16
  48. package/node_modules/pi-lens/dist/clients/ast-grep-types.js +0 -1
  49. package/node_modules/pi-lens/dist/clients/ast-grep-yaml-synth.js +37 -10
  50. package/node_modules/pi-lens/dist/clients/atomic-write-staging.js +63 -0
  51. package/node_modules/pi-lens/dist/clients/atomic-write.js +114 -14
  52. package/node_modules/pi-lens/dist/clients/bash-file-access.js +193 -23
  53. package/node_modules/pi-lens/dist/clients/biome-client.js +136 -24
  54. package/node_modules/pi-lens/dist/clients/bootstrap.js +11 -2
  55. package/node_modules/pi-lens/dist/clients/bounded-cache.js +34 -0
  56. package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +192 -0
  57. package/node_modules/pi-lens/dist/clients/bus-events-logger.js +62 -6
  58. package/node_modules/pi-lens/dist/clients/bus-publish.js +19 -4
  59. package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +47 -5
  60. package/node_modules/pi-lens/dist/clients/cache-manager.js +97 -9
  61. package/node_modules/pi-lens/dist/clients/cache-observability.js +301 -14
  62. package/node_modules/pi-lens/dist/clients/call-graph.js +449 -117
  63. package/node_modules/pi-lens/dist/clients/cascade-format.js +57 -2
  64. package/node_modules/pi-lens/dist/clients/child-unref.js +85 -0
  65. package/node_modules/pi-lens/dist/clients/codebase-model.js +52 -23
  66. package/node_modules/pi-lens/dist/clients/collateral-test-role.js +40 -0
  67. package/node_modules/pi-lens/dist/clients/complexity-client.js +2 -1
  68. package/node_modules/pi-lens/dist/clients/console-guard-install.js +26 -0
  69. package/node_modules/pi-lens/dist/clients/cooperative-budget.js +42 -0
  70. package/node_modules/pi-lens/dist/clients/dead-code-client.js +137 -31
  71. package/node_modules/pi-lens/dist/clients/debug-handles.js +206 -0
  72. package/node_modules/pi-lens/dist/clients/debug-heap.js +167 -0
  73. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +153 -0
  74. package/node_modules/pi-lens/dist/clients/dependency-checker.js +361 -77
  75. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +65 -13
  76. package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +18 -4
  77. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +176 -29
  78. package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +23 -7
  79. package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +8 -18
  80. package/node_modules/pi-lens/dist/clients/dispatch/facts/tree-sitter-facts.js +8 -5
  81. package/node_modules/pi-lens/dist/clients/dispatch/indent-detect.js +35 -0
  82. package/node_modules/pi-lens/dist/clients/dispatch/inline-suppressions.js +17 -8
  83. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +1172 -683
  84. package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +14 -0
  85. package/node_modules/pi-lens/dist/clients/dispatch/plan.js +11 -1
  86. package/node_modules/pi-lens/dist/clients/dispatch/rule-id-normalize.js +50 -0
  87. package/node_modules/pi-lens/dist/clients/dispatch/rule-policy.js +135 -0
  88. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +23 -5
  89. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +5 -9
  90. package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +3 -2
  91. package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +2 -1
  92. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +154 -0
  93. package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +3 -2
  94. package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +5 -1
  95. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +47 -6
  96. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +4 -9
  97. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +9 -5
  98. package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +4 -8
  99. package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +2 -3
  100. package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +2 -3
  101. package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +2 -1
  102. package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +2 -1
  103. package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +163 -0
  104. package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +37 -5
  105. package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +3 -1
  106. package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +13 -7
  107. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +226 -0
  108. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +69 -0
  109. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +3 -0
  110. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +473 -42
  111. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +22 -0
  112. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +97 -0
  113. package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +5 -4
  114. package/node_modules/pi-lens/dist/clients/disposition-publish.js +18 -4
  115. package/node_modules/pi-lens/dist/clients/durable-store.js +97 -0
  116. package/node_modules/pi-lens/dist/clients/eval-timestamp.js +17 -0
  117. package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +94 -3
  118. package/node_modules/pi-lens/dist/clients/extension-log.js +432 -0
  119. package/node_modules/pi-lens/dist/clients/extension-mode.js +73 -0
  120. package/node_modules/pi-lens/dist/clients/file-kinds.js +57 -0
  121. package/node_modules/pi-lens/dist/clients/file-role.js +18 -3
  122. package/node_modules/pi-lens/dist/clients/file-utils.js +56 -34
  123. package/node_modules/pi-lens/dist/clients/fix-worklog.js +5 -1
  124. package/node_modules/pi-lens/dist/clients/format-events-publish.js +51 -7
  125. package/node_modules/pi-lens/dist/clients/format-service.js +24 -8
  126. package/node_modules/pi-lens/dist/clients/formatters-lazy.js +8 -0
  127. package/node_modules/pi-lens/dist/clients/formatters.js +358 -61
  128. package/node_modules/pi-lens/dist/clients/generated-artifacts.js +148 -15
  129. package/node_modules/pi-lens/dist/clients/git-guard.js +678 -11
  130. package/node_modules/pi-lens/dist/clients/git-tracked-ignore.js +4 -0
  131. package/node_modules/pi-lens/dist/clients/go-client.js +23 -40
  132. package/node_modules/pi-lens/dist/clients/govulncheck-client.js +124 -7
  133. package/node_modules/pi-lens/dist/clients/grammar-source.js +12 -4
  134. package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +21 -3
  135. package/node_modules/pi-lens/dist/clients/host-ports.js +31 -0
  136. package/node_modules/pi-lens/dist/clients/installer/index.js +395 -100
  137. package/node_modules/pi-lens/dist/clients/instance-reaper.js +142 -172
  138. package/node_modules/pi-lens/dist/clients/jscpd-client.js +27 -55
  139. package/node_modules/pi-lens/dist/clients/knip-client.js +58 -42
  140. package/node_modules/pi-lens/dist/clients/language-policy.js +14 -2
  141. package/node_modules/pi-lens/dist/clients/language-profile.js +13 -7
  142. package/node_modules/pi-lens/dist/clients/latency-logger.js +72 -1
  143. package/node_modules/pi-lens/dist/clients/lens-config.js +12 -1
  144. package/node_modules/pi-lens/dist/clients/lens-engine.js +86 -17
  145. package/node_modules/pi-lens/dist/clients/lens-events.js +63 -9
  146. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +16 -0
  147. package/node_modules/pi-lens/dist/clients/lens-map.js +94 -19
  148. package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +73 -0
  149. package/node_modules/pi-lens/dist/clients/log-cleanup.js +2 -1
  150. package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +30 -4
  151. package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +59 -14
  152. package/node_modules/pi-lens/dist/clients/lsp/client.js +662 -56
  153. package/node_modules/pi-lens/dist/clients/lsp/config.js +13 -2
  154. package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +115 -0
  155. package/node_modules/pi-lens/dist/clients/lsp/edits.js +1012 -121
  156. package/node_modules/pi-lens/dist/clients/lsp/index.js +2025 -800
  157. package/node_modules/pi-lens/dist/clients/lsp/launch.js +32 -26
  158. package/node_modules/pi-lens/dist/clients/lsp/path-utils.js +1 -1
  159. package/node_modules/pi-lens/dist/clients/lsp/ruby-drive-dirs.js +83 -0
  160. package/node_modules/pi-lens/dist/clients/lsp/server.js +437 -86
  161. package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +96 -0
  162. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +21 -5
  163. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +18 -3
  164. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +28 -4
  165. package/node_modules/pi-lens/dist/clients/lsp-lazy.js +8 -0
  166. package/node_modules/pi-lens/dist/clients/lsp-mutation.js +248 -0
  167. package/node_modules/pi-lens/dist/clients/mcp/analyze.js +127 -32
  168. package/node_modules/pi-lens/dist/clients/mcp/ipc.js +157 -24
  169. package/node_modules/pi-lens/dist/clients/mcp/session.js +235 -14
  170. package/node_modules/pi-lens/dist/clients/memory-sampler.js +115 -0
  171. package/node_modules/pi-lens/dist/clients/metrics-client.js +2 -1
  172. package/node_modules/pi-lens/dist/clients/metrics-history.js +2 -1
  173. package/node_modules/pi-lens/dist/clients/model-provider.js +53 -0
  174. package/node_modules/pi-lens/dist/clients/module-report-lsp.js +5 -0
  175. package/node_modules/pi-lens/dist/clients/module-report.js +168 -3
  176. package/node_modules/pi-lens/dist/clients/ndjson-logger.js +319 -118
  177. package/node_modules/pi-lens/dist/clients/opengrep-client.js +1 -1
  178. package/node_modules/pi-lens/dist/clients/partial-edit-apply.js +120 -5
  179. package/node_modules/pi-lens/dist/clients/path-utils.js +110 -9
  180. package/node_modules/pi-lens/dist/clients/pipeline.js +76 -15
  181. package/node_modules/pi-lens/dist/clients/print-mode.js +21 -0
  182. package/node_modules/pi-lens/dist/clients/project-changes.js +40 -0
  183. package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +3 -2
  184. package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +1 -1
  185. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +8 -0
  186. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +23 -2
  187. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +21 -1
  188. package/node_modules/pi-lens/dist/clients/project-lens-config.js +86 -9
  189. package/node_modules/pi-lens/dist/clients/project-report.js +27 -13
  190. package/node_modules/pi-lens/dist/clients/project-snapshot.js +175 -20
  191. package/node_modules/pi-lens/dist/clients/project-trust.js +181 -0
  192. package/node_modules/pi-lens/dist/clients/quiet-window.js +18 -4
  193. package/node_modules/pi-lens/dist/clients/read-bridge.js +147 -0
  194. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +159 -1
  195. package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +150 -29
  196. package/node_modules/pi-lens/dist/clients/read-guard.js +185 -4
  197. package/node_modules/pi-lens/dist/clients/resource-sampler.js +70 -84
  198. package/node_modules/pi-lens/dist/clients/review-graph/builder.js +1122 -221
  199. package/node_modules/pi-lens/dist/clients/review-graph/git-identity.js +2 -1
  200. package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +21 -10
  201. package/node_modules/pi-lens/dist/clients/review-graph/query.js +24 -0
  202. package/node_modules/pi-lens/dist/clients/review-graph/symbol-id.js +46 -0
  203. package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +57 -6
  204. package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +51 -3
  205. package/node_modules/pi-lens/dist/clients/review-graph-logger.js +30 -1
  206. package/node_modules/pi-lens/dist/clients/ruff-client.js +27 -44
  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 +257 -77
  209. package/node_modules/pi-lens/dist/clients/runtime-context.js +129 -12
  210. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +242 -26
  211. package/node_modules/pi-lens/dist/clients/runtime-session.js +428 -117
  212. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +71 -48
  213. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +342 -33
  214. package/node_modules/pi-lens/dist/clients/runtime-turn.js +619 -93
  215. package/node_modules/pi-lens/dist/clients/rust-client.js +23 -38
  216. package/node_modules/pi-lens/dist/clients/safe-spawn.js +777 -62
  217. package/node_modules/pi-lens/dist/clients/security-scan-client.js +90 -6
  218. package/node_modules/pi-lens/dist/clients/session-state-store.js +3 -2
  219. package/node_modules/pi-lens/dist/clients/sg-runner.js +424 -196
  220. package/node_modules/pi-lens/dist/clients/slow-fs.js +2 -1
  221. package/node_modules/pi-lens/dist/clients/smells-rollup.js +231 -0
  222. package/node_modules/pi-lens/dist/clients/source-filter.js +184 -20
  223. package/node_modules/pi-lens/dist/clients/source-walker.js +66 -10
  224. package/node_modules/pi-lens/dist/clients/startup-scan.js +15 -16
  225. package/node_modules/pi-lens/dist/clients/startup-timing.js +7 -1
  226. package/node_modules/pi-lens/dist/clients/test-runner-client.js +469 -32
  227. package/node_modules/pi-lens/dist/clients/tool-event.js +35 -0
  228. package/node_modules/pi-lens/dist/clients/tool-policy.js +390 -39
  229. package/node_modules/pi-lens/dist/clients/tool-render.js +155 -0
  230. package/node_modules/pi-lens/dist/clients/tool-set-policy.js +76 -0
  231. package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +6 -1
  232. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +419 -50
  233. package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +21 -0
  234. package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +7 -1
  235. package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +7 -2
  236. package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +44 -7
  237. package/node_modules/pi-lens/dist/clients/user-notify.js +51 -0
  238. package/node_modules/pi-lens/dist/clients/vanished-instance-marker.js +57 -0
  239. package/node_modules/pi-lens/dist/clients/warm-attach.js +50 -13
  240. package/node_modules/pi-lens/dist/clients/widget-state.js +300 -43
  241. package/node_modules/pi-lens/dist/clients/word-index.js +680 -81
  242. package/node_modules/pi-lens/dist/clients/workspace-topology.js +89 -6
  243. package/node_modules/pi-lens/dist/index.js +51785 -36118
  244. package/node_modules/pi-lens/dist/mcp/analyze-cli.js +182 -29
  245. package/node_modules/pi-lens/dist/mcp/server.js +219 -46
  246. package/node_modules/pi-lens/dist/tools/activate-tools.js +17 -5
  247. package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +9 -4
  248. package/node_modules/pi-lens/dist/tools/ast-grep-search.js +93 -27
  249. package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +5 -2
  250. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +203 -38
  251. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +210 -42
  252. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -3
  253. package/node_modules/pi-lens/dist/tools/module-report.js +9 -0
  254. package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -1
  255. package/node_modules/pi-lens/docs/agent-guide.md +40 -15
  256. package/node_modules/pi-lens/docs/agent-tools.md +21 -10
  257. package/node_modules/pi-lens/docs/analysisall.md +192 -0
  258. package/node_modules/pi-lens/docs/api-ports-inventory.md +165 -0
  259. package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +14 -3
  260. package/node_modules/pi-lens/docs/durable-store-audit-1202.md +32 -0
  261. package/node_modules/pi-lens/docs/environment-variables.md +44 -0
  262. package/node_modules/pi-lens/docs/fable.md +27 -0
  263. package/node_modules/pi-lens/docs/features.md +45 -3
  264. package/node_modules/pi-lens/docs/globalconfig.md +56 -1
  265. package/node_modules/pi-lens/docs/language-coverage.md +4 -3
  266. package/node_modules/pi-lens/docs/lsp-capability-matrix.md +2 -2
  267. package/node_modules/pi-lens/docs/mcp.md +37 -4
  268. package/node_modules/pi-lens/docs/servercapabilities.md +3 -3
  269. package/node_modules/pi-lens/docs/settings.md +18 -1
  270. package/node_modules/pi-lens/docs/tools.md +4 -1
  271. package/node_modules/pi-lens/docs/usage.md +41 -5
  272. package/node_modules/pi-lens/docs/word-index.md +35 -0
  273. package/node_modules/pi-lens/package.json +10 -10
  274. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-except-test.yml +49 -0
  275. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-host-path-in-win32-branch-test.yml +87 -0
  276. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +8 -0
  277. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-js-test.yml +9 -0
  278. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-test.yml +9 -0
  279. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-nested-links-test.yml +11 -1
  280. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-raw-json-store-write-test.yml +17 -0
  281. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +7 -0
  282. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +7 -0
  283. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +8 -0
  284. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +8 -0
  285. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-laundering-test.yml +11 -0
  286. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-win32-isabsolute-for-qualification-test.yml +16 -0
  287. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-except.yml +3 -15
  288. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +25 -0
  289. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +21 -0
  290. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread-js.yml +21 -0
  291. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread.yml +29 -0
  292. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-nested-links.yml +7 -0
  293. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +30 -0
  294. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +9 -0
  295. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +9 -0
  296. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +13 -0
  297. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +16 -0
  298. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +27 -0
  299. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +23 -0
  300. package/node_modules/pi-lens/rules/tree-sitter-queries/tsx/no-nested-links.yml +4 -6
  301. package/node_modules/pi-lens/rules/tree-sitter-queries/typescript/duplicate-function-arg.yml +2 -2
  302. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +134 -2
  303. package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +10 -11
  304. package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +22 -22
  305. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +8 -114
  306. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +129 -0
  307. package/node_modules/pi-lens/skills/pi-lens-write-tree-sitter-rule/SKILL.md +3 -1
  308. package/node_modules/pi-mcp-adapter/CHANGELOG.md +38 -0
  309. package/node_modules/pi-mcp-adapter/README.md +38 -4
  310. package/node_modules/pi-mcp-adapter/agent-dir.ts +12 -4
  311. package/node_modules/pi-mcp-adapter/agent-plugin-loader.ts +1 -1
  312. package/node_modules/pi-mcp-adapter/cli.js +25 -4
  313. package/node_modules/pi-mcp-adapter/commands.ts +15 -7
  314. package/node_modules/pi-mcp-adapter/config.ts +4 -4
  315. package/node_modules/pi-mcp-adapter/direct-tools.ts +58 -8
  316. package/node_modules/pi-mcp-adapter/host-html-template.ts +0 -8
  317. package/node_modules/pi-mcp-adapter/index.ts +8 -3
  318. package/node_modules/pi-mcp-adapter/init.ts +29 -5
  319. package/node_modules/pi-mcp-adapter/lifecycle.ts +0 -4
  320. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +1 -2
  321. package/node_modules/pi-mcp-adapter/mcp-auth.ts +60 -2
  322. package/node_modules/pi-mcp-adapter/mcp-panel.ts +45 -9
  323. package/node_modules/pi-mcp-adapter/mcp-script-worker.mjs +22 -20
  324. package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +2 -1
  325. package/node_modules/pi-mcp-adapter/metadata-cache.ts +37 -4
  326. package/node_modules/pi-mcp-adapter/npx-resolver.ts +81 -26
  327. package/node_modules/pi-mcp-adapter/package.json +4 -3
  328. package/node_modules/pi-mcp-adapter/proxy-modes.ts +108 -26
  329. package/node_modules/pi-mcp-adapter/request-headers-command.ts +336 -0
  330. package/node_modules/pi-mcp-adapter/search-ranking.ts +86 -7
  331. package/node_modules/pi-mcp-adapter/server-manager.ts +41 -7
  332. package/node_modules/pi-mcp-adapter/session-recovery.ts +8 -2
  333. package/node_modules/pi-mcp-adapter/tool-approval.ts +48 -7
  334. package/node_modules/pi-mcp-adapter/tool-metadata.ts +62 -4
  335. package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +138 -12
  336. package/node_modules/pi-mcp-adapter/types.ts +176 -27
  337. package/node_modules/pi-mcp-adapter/ui-server.ts +20 -1
  338. package/node_modules/pi-web-access/CHANGELOG.md +14 -0
  339. package/node_modules/pi-web-access/README.md +18 -12
  340. package/node_modules/pi-web-access/auth-fetch.ts +148 -0
  341. package/node_modules/pi-web-access/chrome-cookies.ts +110 -23
  342. package/node_modules/pi-web-access/curator-page.ts +5 -3
  343. package/node_modules/pi-web-access/curator-server.ts +2 -1
  344. package/node_modules/pi-web-access/extract.ts +106 -34
  345. package/node_modules/pi-web-access/fetch-params.ts +17 -3
  346. package/node_modules/pi-web-access/firecrawl.ts +172 -12
  347. package/node_modules/pi-web-access/gemini-search.ts +18 -4
  348. package/node_modules/pi-web-access/index.ts +120 -48
  349. package/node_modules/pi-web-access/package.json +2 -2
  350. package/node_modules/pi-web-access/summary-review.ts +11 -5
  351. package/node_modules/pi-web-access/youtube-extract.ts +2 -2
  352. package/package.json +12 -13
  353. package/node_modules/pi-lens/dist/clients/ast-grep-parser.js +0 -86
  354. package/node_modules/pi-lens/dist/clients/lsp/interactive-install.js +0 -367
  355. package/node_modules/pi-lens/dist/clients/lsp/lsp-index.js +0 -10
  356. package/node_modules/pi-lens/dist/clients/lsp/server-strategies.js +0 -5
  357. package/node_modules/pi-lens/dist/clients/project-metadata.js +0 -690
  358. package/node_modules/pi-lens/dist/clients/source-groups.js +0 -96
  359. package/node_modules/pi-lens/dist/clients/startup-marker.js +0 -6
  360. package/node_modules/pi-lens/dist/clients/types.js +0 -11
@@ -14,17 +14,21 @@ import * as path from "node:path";
14
14
  import { Type } from "../clients/deps/typebox.js";
15
15
  import { anchorsForDiagnostic, applyDispositions, applyWeakDispositions, getDisposition, } from "../clients/diagnostic-dispositions.js";
16
16
  import { applyInlineSuppressions } from "../clients/dispatch/inline-suppressions.js";
17
+ import { normalizeRuleId } from "../clients/dispatch/rule-id-normalize.js";
18
+ import { applyRulePolicy, rulePolicyMapFromConfig } from "../clients/dispatch/rule-policy.js";
19
+ import { loadPiLensProjectConfig } from "../clients/project-lens-config.js";
17
20
  import { compactRenderResult } from "./render-compact.js";
18
21
  import { combineAbortSignals } from "../clients/deadline-utils.js";
19
22
  import { getProjectIgnoreMatcher } from "../clients/file-utils.js";
20
23
  import { isAtOrAboveHomeDir, normalizeFilePath, } from "../clients/path-utils.js";
21
24
  import { getLSPService } from "../clients/lsp/index.js";
22
25
  import { primaryServerId } from "../clients/lsp/config.js";
26
+ import { hashDiagnosticContent, } from "../clients/lsp/diagnostic-binding.js";
23
27
  import { loadProjectDiagnosticsDeltaReport, loadProjectDiagnosticsSnapshot, PROJECT_DIAGNOSTICS_CACHE_VERSION, reconcileProjectDiagnosticsSnapshot, } from "../clients/project-diagnostics/cache.js";
24
28
  import { warmTriggerFor } from "../clients/project-diagnostics/extractors.js";
25
29
  import { fetchFreshProjectDiagnostics } from "../clients/project-diagnostics/fresh-fetch.js";
26
30
  import { loadBootstrapClients } from "../clients/bootstrap.js";
27
- import { scanTruncationNotice } from "../clients/lens-engine.js";
31
+ import { generatedSkipNotice, scanTruncationNotice, } from "../clients/lens-engine.js";
28
32
  import { scanProjectDiagnostics } from "../clients/project-diagnostics/scanner.js";
29
33
  import { getFileDiagnosticSummaries, reconcileScanDiagnostics, reconcileStaleWidgetFiles, } from "../clients/widget-state.js";
30
34
  import { convertLspDiagnostics } from "../clients/dispatch/utils/lsp-diagnostics.js";
@@ -50,6 +54,48 @@ const FULL_SCAN_WALL_CLOCK_MS = (() => {
50
54
  const raw = Number(process.env.PI_LENS_LENS_DIAGNOSTICS_FULL_TIMEOUT_MS);
51
55
  return Number.isFinite(raw) && raw > 0 ? raw : 300_000; // 5 min default
52
56
  })();
57
+ // Binding verification is a fallback for result producers that supplied a
58
+ // content hash without an already-computed disk verdict. Keep it one-file-at-a-
59
+ // time and yield periodically: a full scan can contain thousands of results,
60
+ // and a synchronous read loop here would freeze the host even though the LSP
61
+ // work itself was asynchronous (#1198 follow-up).
62
+ const FULL_SCAN_BINDING_YIELD_EVERY = 16;
63
+ async function findFullScanBindingMismatches(results) {
64
+ const mismatched = new WeakSet();
65
+ let sinceYield = 0;
66
+ for (const result of results) {
67
+ if (result.boundToCurrentDisk === false) {
68
+ mismatched.add(result);
69
+ }
70
+ else if (
71
+ // A `true` verdict came from the LSP/cache binding seam and has already
72
+ // compared its fingerprint with disk. Only legacy/partial producers need
73
+ // this fallback read; `unknown` remains unknown when no hash exists.
74
+ result.boundToCurrentDisk !== true &&
75
+ result.contentHash !== undefined) {
76
+ try {
77
+ // Promise-based, sequential reads bound both event-loop occupancy and
78
+ // outstanding file handles. A read failure deliberately leaves the
79
+ // verdict unknown (the historical fail-open behavior).
80
+ const content = await fs.readFile(result.filePath, "utf-8");
81
+ if (hashDiagnosticContent(content) !== result.contentHash) {
82
+ mismatched.add(result);
83
+ }
84
+ }
85
+ catch {
86
+ // Unreadable/deleted files cannot disprove the binding. Leave them
87
+ // unknown for the existing caller policy, rather than manufacturing a
88
+ // mismatch or a clean verdict here.
89
+ }
90
+ }
91
+ sinceYield += 1;
92
+ if (sinceYield >= FULL_SCAN_BINDING_YIELD_EVERY) {
93
+ sinceYield = 0;
94
+ await new Promise((resolve) => setImmediate(resolve));
95
+ }
96
+ }
97
+ return mismatched;
98
+ }
53
99
  export function createLensDiagnosticsTool(cacheManager, getCwd, getLspService = getLSPService,
54
100
  // Flush any debounced per-edit dispatches before reading, so files the agent
55
101
  // fixed earlier in the turn are re-dispatched and the widget reflects the
@@ -72,7 +118,7 @@ nextWriteIndex,
72
118
  // #798/#338: capture host UI methods synchronously from the active tool event.
73
119
  // The returned closure is safe for the later async sweep to invoke because it
74
120
  // never dereferences the session-guarded ctx.ui getter.
75
- captureLspStatusRepaint) {
121
+ captureLspStatusRepaint, getRuntime) {
76
122
  return {
77
123
  name: "lens_diagnostics",
78
124
  label: "Project Diagnostics",
@@ -156,6 +202,9 @@ captureLspStatusRepaint) {
156
202
  maxLspFiles: Type.Optional(Type.Number({
157
203
  description: "mode=full only: cap the number of files routed through the language server for the project-wide LSP sweep. On large projects (e.g. a Next.js app with thousands of source files) the uncapped sweep can take many minutes; set this to bound it. Default is generous (env PI_LENS_LSP_WORKSPACE_MAX_FILES, else 5000).",
158
204
  })),
205
+ includeGenerated: Type.Optional(Type.Boolean({
206
+ description: "mode=full refreshRunners=cheap/all only (no effect with refreshRunners=cached/none, since no project scan runs to apply it to): scan WITHOUT the generated/artifact NAME-heuristic filter (lockfiles, gen.ts-style names, generated/ dirs, …). Default false. Use when a scan's 'excluded by generated-name heuristics' notice suggests a real file was skipped.",
207
+ })),
159
208
  severity: Type.Optional(Type.String({
160
209
  enum: ["error", "warning", "all"],
161
210
  description: "Filter by severity (default: all).",
@@ -192,6 +241,7 @@ captureLspStatusRepaint) {
192
241
  : undefined;
193
242
  const maxProjectFiles = parsePositiveInt(params.maxProjectFiles);
194
243
  const maxLspFiles = parsePositiveInt(params.maxLspFiles);
244
+ const includeGenerated = params.includeGenerated === true;
195
245
  const cwd = ctx.cwd ?? getCwd();
196
246
  let pathsScope;
197
247
  try {
@@ -236,12 +286,14 @@ captureLspStatusRepaint) {
236
286
  refreshRunners,
237
287
  maxProjectFiles,
238
288
  maxLspFiles,
289
+ includeGenerated,
239
290
  signal: fullSignal,
240
291
  wallClockMs: FULL_SCAN_WALL_CLOCK_MS,
241
292
  onProgress,
242
293
  onServerReady: repaintLspStatus,
243
294
  pathsScope,
244
295
  nextWriteIndex,
296
+ runtime: getRuntime?.(),
245
297
  });
246
298
  }
247
299
  return formatDeltaMode(cacheManager, cwd, severity, pathsScope);
@@ -281,23 +333,46 @@ function appendProjectDiagnosticsDeltaLines(lines, cwd, report, severity, includ
281
333
  * delta mode re-serves them. Anchored via `projectDiagnosticToWidget` so the
282
334
  * (tool, rule) an agent's mark binds to matches mode=full's own project-runner
283
335
  * filter (`applyInlineSuppressionsToSummaries`), keeping the two paths in
284
- * agreement. Weak-anchored → no file read.
336
+ * agreement. Weak-anchored → no file read. Also applies the project's
337
+ * `.pi-lens.json` `rules.<id>.disable`/`select` policy so a project's policy
338
+ * overlays the same delta report cache; the cache is otherwise insensitive to
339
+ * a project-config edit (the per-edit path picks it up immediately, but a
340
+ * non-dispatch tool query would replay the pre-edit state).
285
341
  */
286
- function filterDeltaReportDispositions(report, cwd) {
342
+ function filterDeltaReportDispositions(report, cwd, policyMap) {
287
343
  if (!report?.diagnostics.length)
288
344
  return report;
289
345
  const kept = report.diagnostics.filter((d) => applyWeakDispositions([projectDiagnosticToWidget(d)], cwd, d.filePath)
290
346
  .length === 1);
291
- return kept.length === report.diagnostics.length
292
- ? report
293
- : { ...report, diagnostics: kept };
347
+ const policyKept = applyRulePolicy(kept, policyMap);
348
+ if (policyKept.length === report.diagnostics.length)
349
+ return report;
350
+ return { ...report, diagnostics: policyKept };
351
+ }
352
+ /**
353
+ * Load the rule-policy map from a project's `.pi-lens.json` — same source the
354
+ * per-edit dispatch path uses, so a project's policy applies consistently
355
+ * across every output surface. `loadPiLensProjectConfig` is mtime-cached, and
356
+ * the map is filtered to entries that actually have a `disable`/`select` list
357
+ * (thresholds are handled elsewhere), so the common case returns undefined and
358
+ * the filter step is skipped outright.
359
+ */
360
+ function loadProjectRulePolicyMap(cwd) {
361
+ return rulePolicyMapFromConfig(loadPiLensProjectConfig(cwd).rules);
294
362
  }
295
363
  function formatDeltaMode(cacheManager, cwd, severity, pathsScope) {
296
364
  const actionableEntry = cacheManager.readCache("actionable-warnings", cwd);
297
365
  const qualityEntry = cacheManager.readCache("code-quality-warnings", cwd);
298
366
  const actionable = actionableEntry?.data;
299
367
  const quality = qualityEntry?.data;
300
- const projectDelta = filterDeltaReportDispositions(loadProjectDiagnosticsDeltaReport(cwd), cwd);
368
+ // Project rule policy (`.pi-lens.json` `rules.<id>.disable` /
369
+ // `rules.<id>.select`) — output-only filtering applied consistently across
370
+ // every mode. The cache-only delta/all paths would otherwise leak project-
371
+ // policy oversight (the per-edit dispatch already filters, but the cache
372
+ // snapshots predate the user's project config edit and would replay
373
+ // filtered findings). Weak-anchored like weak disposition — zero I/O.
374
+ const policyMap = loadProjectRulePolicyMap(cwd);
375
+ const projectDelta = filterDeltaReportDispositions(loadProjectDiagnosticsDeltaReport(cwd), cwd, policyMap);
301
376
  const ignoreFile = createCurrentIgnoreFilter(cwd);
302
377
  const includeFile = (filePath) => ignoreFile(filePath) && (!pathsScope || pathsScope.includeFile(filePath));
303
378
  // #755: delta re-serves the actionable/quality caches verbatim, but those
@@ -305,20 +380,15 @@ function formatDeltaMode(cacheManager, cwd, severity, pathsScope) {
305
380
  // the weak disposition filter (suppress/defer) here so a mark converges
306
381
  // immediately, not only on the next edit. Weak-anchored → zero file I/O, so
307
382
  // this stays "instant" (see applyWeakDispositions).
308
- const actionableFiles = (actionable?.files ?? [])
383
+ const visibleWarningFiles = (files) => (files ?? [])
309
384
  .filter((file) => includeFile(file.filePath))
310
385
  .map((file) => ({
311
386
  filePath: file.filePath,
312
- warnings: applyWeakDispositions(file.warnings ?? [], cwd, file.filePath),
313
- }))
314
- .filter((file) => file.warnings.length > 0);
315
- const qualityFiles = (quality?.files ?? [])
316
- .filter((file) => includeFile(file.filePath))
317
- .map((file) => ({
318
- filePath: file.filePath,
319
- warnings: applyWeakDispositions(file.warnings ?? [], cwd, file.filePath),
387
+ warnings: applyRulePolicy(applyWeakDispositions(file.warnings ?? [], cwd, file.filePath), policyMap),
320
388
  }))
321
389
  .filter((file) => file.warnings.length > 0);
390
+ const actionableFiles = visibleWarningFiles(actionable?.files);
391
+ const qualityFiles = visibleWarningFiles(quality?.files);
322
392
  const lines = [];
323
393
  // Fixable warnings from actionable-warnings
324
394
  if (severity !== "error") {
@@ -353,7 +423,7 @@ function formatDeltaMode(cacheManager, cwd, severity, pathsScope) {
353
423
  .filter((f) => includeFile(f.filePath))
354
424
  .map((f) => ({
355
425
  ...f,
356
- diagnostics: applyWeakDispositions(f.diagnostics, cwd, f.filePath),
426
+ diagnostics: applyRulePolicy(applyWeakDispositions(f.diagnostics, cwd, f.filePath), policyMap),
357
427
  }))
358
428
  .filter((f) => f.diagnostics.length > 0);
359
429
  const carriedIssues = carried.reduce((n, f) => n + f.diagnostics.length, 0);
@@ -484,6 +554,20 @@ function filterProjectDiagnosticsDeltaReport(report, includeFile) {
484
554
  diagnostics: report.diagnostics.filter((d) => includeFile(d.filePath)),
485
555
  };
486
556
  }
557
+ /**
558
+ * Apply the project rule policy to a project-diagnostics snapshot/delta
559
+ * report's `diagnostics` list, in place of the collection's shape. Used by
560
+ * `formatFullMode` so `projectSnapshot.diagnostics.length` /
561
+ * `projectDelta.diagnostics.length` — which feed both the merged summaries
562
+ * and the `details.projectDiagnostics`/`details.projectDiagnosticsDelta`
563
+ * counts — already reflect the policy instead of reporting a pre-policy
564
+ * count that disagrees with the rendered text.
565
+ */
566
+ function applyProjectRulePolicy(value, policyMap) {
567
+ if (!value)
568
+ return undefined;
569
+ return { ...value, diagnostics: applyRulePolicy(value.diagnostics, policyMap) };
570
+ }
487
571
  /** A diagnostic counts as error-like when it blocks or has error severity. */
488
572
  function isErrorLike(d) {
489
573
  return d.semantic === "blocking" || d.severity === "error";
@@ -553,12 +637,12 @@ function projectDiagnosticToWidget(diagnostic) {
553
637
  // violation must collapse to one finding in mode=full's merge regardless of which
554
638
  // engine produced it. Strip the `ast-grep:` source prefix and the `-js` language
555
639
  // suffix (the napi runner already treats `<id>` / `<id>-js` as one rule) so the
556
- // LSP sweep and the napi scan don't double-report the same line.
557
- function normalizeRuleForDedup(ruleId) {
558
- return ruleId.replace(/^ast-grep:/, "").replace(/-js$/, "");
559
- }
640
+ // LSP sweep and the napi scan don't double-report the same line. The
641
+ // normalization itself now lives in `clients/dispatch/rule-id-normalize.ts` so the
642
+ // inline suppression parser, the project rule-policy matcher, and dedup all apply
643
+ // the same canonical form.
560
644
  function diagnosticDedupKey(filePath, diagnostic) {
561
- const ruleId = normalizeRuleForDedup(diagnostic.rule ?? diagnostic.tool ?? "");
645
+ const ruleId = normalizeRuleId(diagnostic.rule ?? diagnostic.tool ?? "");
562
646
  return [path.resolve(filePath), diagnostic.line ?? "?", ruleId].join(":");
563
647
  }
564
648
  function summarizeDiagnostics(filePath, diagnostics, hasFinalSnapshot) {
@@ -701,8 +785,14 @@ function mergeDiagnosticsWithWidgetSummaries(widgetSummaries, lspResults, projec
701
785
  * a read failure is fail-safe (keep the diagnostics rather than hide a finding on
702
786
  * an I/O error). Re-summarizes so the blocking/error/warning counts reflect the
703
787
  * suppression.
788
+ *
789
+ * Also applies the project's `.pi-lens.json` `rules.<id>.disable`/`select`
790
+ * policy AFTER inline suppression / disposition so the same set of findings
791
+ * the per-edit `dispatcher.ts` filters is what's rendered here. The policy
792
+ * map is passed in (computed once per `formatFullMode` call) rather than
793
+ * re-deriving per file — see `loadProjectRulePolicyMap(cwd)`.
704
794
  */
705
- async function applyInlineSuppressionsToSummaries(summaries, cwd) {
795
+ async function applyInlineSuppressionsToSummaries(summaries, cwd, policyMap) {
706
796
  return Promise.all(summaries.map(async (summary) => {
707
797
  if (!summary.diagnostics.length)
708
798
  return summary;
@@ -711,7 +801,13 @@ async function applyInlineSuppressionsToSummaries(summaries, cwd) {
711
801
  content = await fs.readFile(summary.filePath, "utf8");
712
802
  }
713
803
  catch {
714
- return summary; // never hide a finding on a read error
804
+ // Inline suppression/disposition remains fail-open when the file cannot
805
+ // be read, but project policy does not depend on content and must still
806
+ // be applied so a fresh full-mode result cannot bypass `disable`/`select`.
807
+ const policyKept = applyRulePolicy(summary.diagnostics, policyMap);
808
+ return policyKept.length === summary.diagnostics.length
809
+ ? summary
810
+ : summarizeDiagnostics(summary.filePath, policyKept, summary.hasFinalSnapshot);
715
811
  }
716
812
  const inlineKept = applyInlineSuppressions(summary.diagnostics, content);
717
813
  // #690: same false-positive/suppress/defer disposition filter the
@@ -719,11 +815,16 @@ async function applyInlineSuppressionsToSummaries(summaries, cwd) {
719
815
  // diagnostics from a fresh LSP sweep/project scan that never went
720
816
  // through that path, so without this a disposed finding reappears here.
721
817
  const kept = applyDispositions(inlineKept, cwd, summary.filePath, content);
818
+ // Project rule policy (`.pi-lens.json` `rules.<id>.disable`/`select`).
819
+ // Applied after inline suppression / disposition so the policy's
820
+ // output-only filtering affects the same surface the per-edit path
821
+ // produces (no double-counting, no leftover policy-rejected findings).
822
+ const policyKept = applyRulePolicy(kept, policyMap);
722
823
  // Tag `flagged` diagnostics for the render loop (formatAllMode). Content
723
824
  // is already in hand here (unlike mode=all/delta's cache-only path), so
724
825
  // this is the one place the tag can be computed without adding I/O to
725
826
  // the "instant" modes.
726
- for (const d of kept) {
827
+ for (const d of policyKept) {
727
828
  // flagged is weak-anchored (module doc, diagnostic-dispositions.ts) so
728
829
  // the tag survives incidental edits to the flagged line itself.
729
830
  const { weak } = anchorsForDiagnostic(cwd, summary.filePath, d, content);
@@ -731,9 +832,9 @@ async function applyInlineSuppressionsToSummaries(summaries, cwd) {
731
832
  d.flagged = true;
732
833
  }
733
834
  }
734
- if (kept.length === summary.diagnostics.length)
835
+ if (policyKept.length === summary.diagnostics.length)
735
836
  return summary;
736
- return summarizeDiagnostics(summary.filePath, kept, summary.hasFinalSnapshot);
837
+ return summarizeDiagnostics(summary.filePath, policyKept, summary.hasFinalSnapshot);
737
838
  }));
738
839
  }
739
840
  function shouldUseCachedProjectDiagnostics(value) {
@@ -781,6 +882,7 @@ async function getProjectDiagnosticsSnapshotForFullMode(cwd, options) {
781
882
  maxFiles: options.maxProjectFiles,
782
883
  signal: options.signal,
783
884
  files: options.files,
885
+ includeGenerated: options.includeGenerated,
784
886
  });
785
887
  }
786
888
  if (shouldUseCachedProjectDiagnostics(options.refreshRunners)) {
@@ -834,7 +936,7 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
834
936
  // scan, makes it genuinely concurrent — all three phases now race the SAME
835
937
  // signal from the same starting point instead of stacking.
836
938
  const analyzersPromise = shouldIncludeProjectRunners(options.refreshRunners)
837
- ? loadBootstrapClients().then((clients) => fetchFreshProjectDiagnostics(cacheManager, cwd, clients, signal))
939
+ ? loadBootstrapClients().then((clients) => fetchFreshProjectDiagnostics(cacheManager, cwd, clients, signal, { runtime: options.runtime }))
838
940
  : Promise.resolve({
839
941
  diagnostics: [],
840
942
  runners: [],
@@ -848,6 +950,7 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
848
950
  signal,
849
951
  onProgress: options.onProgress,
850
952
  onServerReady: options.onServerReady,
953
+ nextWriteIndex: options.nextWriteIndex,
851
954
  files: explicitFiles,
852
955
  }),
853
956
  getProjectDiagnosticsSnapshotForFullMode(cwd, {
@@ -858,6 +961,12 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
858
961
  ]);
859
962
  const aborted = signal?.aborted ?? false;
860
963
  const lspResults = rawLspResults.filter((result) => includeFile(result.filePath));
964
+ // A result bound to a different document must not replace the current
965
+ // widget state, even when it contains real diagnostics. Pull results may carry
966
+ // a content hash without the push binding verdict, so verify that hash against
967
+ // disk through the bounded async fallback above; unreadable files remain
968
+ // unknown and retain the existing fail-open policy.
969
+ const mismatchedLspResults = await findFullScanBindingMismatches(lspResults);
861
970
  // #630: `timedOut`/`error` means the per-file check never actually
862
971
  // completed or was inconclusive (#570's `touchFile().inconclusive`, or
863
972
  // this sweep's own outer per-file deadline/throw — see
@@ -869,8 +978,12 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
869
978
  // the unfiltered `lspResults` in, so a timed-out file's placeholder `[]`
870
979
  // read as "0 diagnostics" — false-clean — in the rendered/`details`
871
980
  // output (#630).
872
- const confirmedLspResults = lspResults.filter((result) => !result.timedOut && !result.error);
873
- const unconfirmedLspResults = lspResults.filter((result) => result.timedOut || result.error);
981
+ const confirmedLspResults = lspResults.filter((result) => !result.timedOut &&
982
+ !result.error &&
983
+ !mismatchedLspResults.has(result));
984
+ const unconfirmedLspResults = lspResults.filter((result) => result.timedOut ||
985
+ result.error ||
986
+ mismatchedLspResults.has(result));
874
987
  // #571: reconcile this scan's fresh, CONFIRMED per-file results into the
875
988
  // footer cache. A footer write is never allowed to fail the tool call, so
876
989
  // any unexpected throw is swallowed.
@@ -891,12 +1004,33 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
891
1004
  // (`applyAuxiliarySuppressions`), so an empty content string here is a
892
1005
  // safe no-op re-check rather than a behavior gap.
893
1006
  const retagged = retagAuxiliaryDiagnostics(diagnostics, result.diagnostics, "", { cwd, fileRole: detectFileRole(result.filePath) });
894
- reconcileScanDiagnostics(result.filePath, retagged, true, nextWriteIndex?.());
1007
+ reconcileScanDiagnostics(result.filePath, retagged, true,
1008
+ // The service reserves this token when the file enters the scan. The
1009
+ // fallback preserves compatibility with older test doubles/services.
1010
+ result.writeIndex ?? nextWriteIndex?.(),
1011
+ // #1093: `observedAt` is set only when this result was served from
1012
+ // the workspace-diagnostics cache (a replay of an older scan) —
1013
+ // stamp `touchedAt` with when it was scanned, not now(), so a
1014
+ // mode=full that only re-serves the cache can't keep a resolved
1015
+ // finding on screen by re-arming the mtime gate. Undefined for
1016
+ // freshly-touched results (observed now).
1017
+ result.observedAt);
895
1018
  }
896
1019
  catch {
897
1020
  // Never let a footer-reconciliation hiccup fail the scan itself.
898
1021
  }
899
1022
  }
1023
+ // Project rule policy (`.pi-lens.json` `rules.<id>.disable`/`select`) —
1024
+ // loaded once per mode=full call, BEFORE `projectSnapshot`/`projectDelta`
1025
+ // are built below, so `.diagnostics.length` on both (which feeds
1026
+ // `details.projectDiagnostics`/`details.projectDiagnosticsDelta` as well
1027
+ // as the merge into `summaries`) is the POST-policy count. Threaded into
1028
+ // `applyInlineSuppressionsToSummaries` too (idempotent re-apply there) so
1029
+ // the merged summaries honor the same policy the per-edit dispatch path
1030
+ // applies. A project config read failure is treated as "no policy"
1031
+ // (defensive, matches the `applyInlineSuppressionsToSummaries` read-error
1032
+ // discipline).
1033
+ const policyMap = loadProjectRulePolicyMap(cwd);
900
1034
  const scannedSnapshot = filterProjectDiagnosticsSnapshot(rawProjectSnapshot, includeFile);
901
1035
  // Heavyweight-analyzer findings (jscpd, madge, gitleaks, knip, govulncheck,
902
1036
  // trivy, dead-code) — a FRESH run of each (#585), not a cache-only read:
@@ -911,14 +1045,14 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
911
1045
  // computed above, in the SAME `Promise.all` as the LSP sweep (#613) — only
912
1046
  // when the caller opted into project-runner state (otherwise it's the
913
1047
  // `Promise.resolve({...})` stub from `analyzersPromise` above).
914
- const projectSnapshot = foldExtraDiagnosticsIntoSnapshot(scannedSnapshot, extracted.diagnostics.filter((d) => includeFile(d.filePath)), extracted.runners, cwd);
915
- const projectDelta = filterProjectDiagnosticsDeltaReport(loadProjectDiagnosticsDeltaReport(cwd), includeFile);
1048
+ const projectSnapshot = applyProjectRulePolicy(foldExtraDiagnosticsIntoSnapshot(scannedSnapshot, extracted.diagnostics.filter((d) => includeFile(d.filePath)), extracted.runners, cwd), policyMap);
1049
+ const projectDelta = applyProjectRulePolicy(filterProjectDiagnosticsDeltaReport(loadProjectDiagnosticsDeltaReport(cwd), includeFile), policyMap);
916
1050
  // #630: only the CONFIRMED LSP results contribute diagnostics to the merge
917
1051
  // — an unconfirmed (timed-out/errored) file's placeholder `[]` must not be
918
1052
  // read as "0 issues, clean" via its LSP contribution. It can still
919
1053
  // legitimately show diagnostics from widgetSummaries/project-runner state
920
1054
  // below if those independently have entries for it.
921
- const summaries = await applyInlineSuppressionsToSummaries(mergeDiagnosticsWithWidgetSummaries(getFileDiagnosticSummaries().filter((summary) => includeFile(summary.filePath)), confirmedLspResults, projectSnapshot, projectDelta), cwd);
1055
+ const summaries = await applyInlineSuppressionsToSummaries(mergeDiagnosticsWithWidgetSummaries(getFileDiagnosticSummaries().filter((summary) => includeFile(summary.filePath)), confirmedLspResults, projectSnapshot, projectDelta), cwd, policyMap);
922
1056
  const result = formatAllMode(cwd, severity, summaries, {
923
1057
  mode: "full",
924
1058
  lspFilesChecked: rawLspResults.length,
@@ -1057,6 +1191,14 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
1057
1191
  const scanTruncatedNote = scanTruncatedNoticeText
1058
1192
  ? `\n\n${scanTruncatedNoticeText}`
1059
1193
  : "";
1194
+ // #1107 phase 2: same "reached the seam, nothing rendered it" gap as #784
1195
+ // above, for the generated-name/dir skip counters.
1196
+ const generatedSkipNoticeText = projectSnapshot
1197
+ ? generatedSkipNotice(projectSnapshot)
1198
+ : undefined;
1199
+ const generatedSkipNote = generatedSkipNoticeText
1200
+ ? `\n\n${generatedSkipNoticeText}`
1201
+ : "";
1060
1202
  const abortedNote = abortedIds.size > 0
1061
1203
  ? `\n\nstopped mid-scan (still running in the background, not reflected in this result): ${[
1062
1204
  ...abortedIds,
@@ -1110,6 +1252,19 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
1110
1252
  // #784: lets a caller check "was the cheap project scan truncated"
1111
1253
  // without parsing the text note.
1112
1254
  projectScanTruncated: projectSnapshot?.scanTruncated ?? false,
1255
+ // #1107 phase 2: same machine-readable convention, for the
1256
+ // generated-name/dir skip counters.
1257
+ ...(projectSnapshot?.generatedFileSkips
1258
+ ? { projectGeneratedFileSkips: projectSnapshot.generatedFileSkips }
1259
+ : {}),
1260
+ ...(projectSnapshot?.generatedNameOnlySkips
1261
+ ? {
1262
+ projectGeneratedNameOnlySkips: projectSnapshot.generatedNameOnlySkips,
1263
+ }
1264
+ : {}),
1265
+ ...(projectSnapshot?.generatedDirSkips
1266
+ ? { projectGeneratedDirSkips: projectSnapshot.generatedDirSkips }
1267
+ : {}),
1113
1268
  },
1114
1269
  };
1115
1270
  // Stopped mid-scan: the results above are whatever completed before the abort.
@@ -1138,6 +1293,7 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
1138
1293
  failedNote +
1139
1294
  walkUnsafeRootNote +
1140
1295
  scanTruncatedNote +
1296
+ generatedSkipNote +
1141
1297
  abortedNote +
1142
1298
  freshNote +
1143
1299
  missingNote,
@@ -1152,6 +1308,7 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
1152
1308
  failedNote ||
1153
1309
  walkUnsafeRootNote ||
1154
1310
  scanTruncatedNote ||
1311
+ generatedSkipNote ||
1155
1312
  abortedNote ||
1156
1313
  freshNote ||
1157
1314
  unconfirmedLspNote ||
@@ -1168,6 +1325,7 @@ async function formatFullMode(cwd, severity, lspService, cacheManager, options =
1168
1325
  failedNote +
1169
1326
  walkUnsafeRootNote +
1170
1327
  scanTruncatedNote +
1328
+ generatedSkipNote +
1171
1329
  abortedNote +
1172
1330
  freshNote +
1173
1331
  missingNote,
@@ -1197,13 +1355,20 @@ function formatAllMode(cwd, severity, summaries = getFileDiagnosticSummaries(),
1197
1355
  // post-dispatch lens_diagnostic_mark (suppress/defer) would otherwise still
1198
1356
  // show here. Re-apply the weak filter (zero I/O) for the cache-only path and
1199
1357
  // re-summarize so blocking/error/warning counts reflect the drop.
1358
+ // Same project rule policy (`.pi-lens.json` `rules.<id>.disable`/`select`)
1359
+ // overlays both modes: mode=full re-applies it after inline suppression /
1360
+ // disposition (zero I/O), mode=all applies it here on the cache-only path.
1361
+ // The full path's policyMover is loaded below in `applyInlineSuppressionsToSummaries`.
1362
+ const policyMap = loadProjectRulePolicyMap(cwd);
1200
1363
  const dispositioned = isFullMode
1201
1364
  ? summaries
1202
1365
  : summaries.map((s) => {
1203
1366
  const kept = applyWeakDispositions(s.diagnostics ?? [], cwd, s.filePath);
1204
- return kept.length === (s.diagnostics?.length ?? 0)
1205
- ? s
1206
- : summarizeDiagnostics(s.filePath, kept, s.hasFinalSnapshot);
1367
+ const policyKept = applyRulePolicy(kept, policyMap);
1368
+ if (policyKept.length === kept.length &&
1369
+ kept.length === (s.diagnostics?.length ?? 0))
1370
+ return s;
1371
+ return summarizeDiagnostics(s.filePath, policyKept, s.hasFinalSnapshot);
1207
1372
  });
1208
1373
  const visibleSummaries = dispositioned.filter((s) => includeFile(s.filePath));
1209
1374
  // Filter to files with actual issues