@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
@@ -156,6 +156,22 @@ export const LENS_FLAGS = [
156
156
  default: false,
157
157
  scope: "global",
158
158
  },
159
+ {
160
+ name: "lens-compact-tool-line",
161
+ description: "Opt-in (#1327): collapse a pi-lens tool's call+result rows into ONE theme-aware line (status glyph + name + summary) instead of two. Preserves expand-to-view-full-output. Default off. Also via ui.compactToolLine=true in ~/.pi-lens/config.json.",
162
+ configKey: "ui.compactToolLine",
163
+ negated: false,
164
+ default: false,
165
+ scope: "global",
166
+ },
167
+ {
168
+ name: "no-lazy-tools",
169
+ description: "Keep all pi-lens tools active to avoid tool-list cache changes. Also via tools.lazy=false in ~/.pi-lens/config.json.",
170
+ configKey: "tools.lazy",
171
+ negated: true,
172
+ default: false,
173
+ scope: "global",
174
+ },
159
175
  ];
160
176
  const byName = new Map(LENS_FLAGS.map((spec) => [spec.name, spec]));
161
177
  export function getLensFlagSpec(name) {
@@ -21,6 +21,7 @@ import { FactStore } from "./dispatch/fact-store.js";
21
21
  import { getProjectDataDir } from "./file-utils.js";
22
22
  import { collectUntrackedIgnoredIds } from "./git-tracked-ignore.js";
23
23
  import { normalizeMapKey, toProjectRelativePath } from "./path-utils.js";
24
+ import { canonicalSourceTwin } from "./source-filter.js";
24
25
  import { buildOrUpdateGraph } from "./review-graph/service.js";
25
26
  import { detectFileRole } from "./file-role.js";
26
27
  export const DEFAULT_MAX_MAP_NODES = 500;
@@ -92,11 +93,10 @@ export function aggregateGraphToFiles(graph, options) {
92
93
  // import edges). Deterministic sibling families: .js → .ts (preferred)
93
94
  // then .tsx; .mjs → .mts; .cjs → .cts. A compiled-looking file with no
94
95
  // source twin (vendored deps, pure-JS projects) is untouched.
95
- const COMPILED_TWIN_SOURCES = [
96
- [".js", [".ts", ".tsx"]],
97
- [".mjs", [".mts"]],
98
- [".cjs", [".cts"]],
99
- ];
96
+ // Keep this pure aggregation layer on the shared source-filter policy. It
97
+ // cannot call findSourceSibling because synthetic graph fixtures and cached
98
+ // nodes are not required to exist on disk.
99
+ const compiledExtensions = new Set([".js", ".jsx", ".mjs", ".cjs"]);
100
100
  // Interplay with the untracked-gitignored exclusion (`excludeIds`):
101
101
  // twin canonicalization takes PRECEDENCE over exclusion. An excluded
102
102
  // compiled file whose source twin survives is merged onto that twin
@@ -109,19 +109,11 @@ export function aggregateGraphToFiles(graph, options) {
109
109
  const excludeIds = options?.excludeIds;
110
110
  const canonicalOf = new Map();
111
111
  for (const id of allFileIds) {
112
- for (const [compiledExt, sourceExts] of COMPILED_TWIN_SOURCES) {
113
- if (!id.endsWith(compiledExt))
114
- continue;
115
- const stem = id.slice(0, id.length - compiledExt.length);
116
- for (const sourceExt of sourceExts) {
117
- const candidate = stem + sourceExt;
118
- if (allFileIds.has(candidate) && !excludeIds?.has(candidate)) {
119
- canonicalOf.set(id, candidate);
120
- break;
121
- }
122
- }
123
- break;
124
- }
112
+ if (!compiledExtensions.has(path.extname(id).toLowerCase()))
113
+ continue;
114
+ const canonical = canonicalSourceTwin(id, allFileIds, excludeIds);
115
+ if (canonical !== id)
116
+ canonicalOf.set(id, canonical);
125
117
  }
126
118
  const compiledTwinCount = canonicalOf.size;
127
119
  // Excluded ids that actually drop: in the graph, untracked-gitignored,
@@ -137,6 +129,77 @@ export function aggregateGraphToFiles(graph, options) {
137
129
  }
138
130
  }
139
131
  const ignoredFileCount = droppedIgnoredIds.size;
132
+ // Build logical symbol identities before counting symbols or edges. A compiled
133
+ // twin can carry the same declaration and edge evidence as its source; those
134
+ // are one logical observation after canonicalization. Match source declarations
135
+ // in stable insertion order so overloads with the same name/kind stay distinct.
136
+ const logicalSymbolByNode = new Map();
137
+ const sourceSymbolsByFile = new Map();
138
+ // A symbol kind is not stable across extractor surfaces: a declaration can
139
+ // be a `function` in a JS/TS fact and a `variable` in a compiled twin's
140
+ // syntax extraction. Keep a name-only index for the safe case where there is
141
+ // exactly one source declaration with that name; this prevents equivalent
142
+ // twins from inflating the preferred source while preserving overloads and
143
+ // genuinely ambiguous same-name declarations.
144
+ const sourceSymbolsByName = new Map();
145
+ for (const node of graph.nodes.values()) {
146
+ if (node.kind !== "symbol" || !node.filePath || !node.symbolName)
147
+ continue;
148
+ const raw = normalizeMapKey(node.filePath);
149
+ const canonical = canonicalOf.get(raw) ?? raw;
150
+ if (raw !== canonical)
151
+ continue;
152
+ const key = `${node.symbolName}\u0000${node.symbolKind ?? ""}`;
153
+ const byName = sourceSymbolsByFile.get(canonical) ?? new Map();
154
+ const ids = byName.get(key) ?? [];
155
+ ids.push(node.id);
156
+ byName.set(key, ids);
157
+ sourceSymbolsByFile.set(canonical, byName);
158
+ const bySymbolName = sourceSymbolsByName.get(canonical) ?? new Map();
159
+ const nameIds = bySymbolName.get(node.symbolName) ?? [];
160
+ nameIds.push(node.id);
161
+ bySymbolName.set(node.symbolName, nameIds);
162
+ sourceSymbolsByName.set(canonical, bySymbolName);
163
+ logicalSymbolByNode.set(node.id, node.id);
164
+ }
165
+ // Assign each twin's declarations by occurrence within THAT twin file, not
166
+ // through one process-wide "used" set. A source can have several compiled
167
+ // siblings (`x.ts`, `x.js`, `x.mjs`, ...); every sibling's first `run` must
168
+ // map to the source's first `run`, while overloads with the same name/kind
169
+ // remain distinct by occurrence.
170
+ const twinOccurrencesByFile = new Map();
171
+ for (const node of graph.nodes.values()) {
172
+ if (node.kind !== "symbol" || !node.filePath || !node.symbolName)
173
+ continue;
174
+ const raw = normalizeMapKey(node.filePath);
175
+ const canonical = canonicalOf.get(raw) ?? raw;
176
+ if (raw === canonical)
177
+ continue;
178
+ const key = `${node.symbolName}\u0000${node.symbolKind ?? ""}`;
179
+ const exactSourceIds = sourceSymbolsByFile.get(canonical)?.get(key) ?? [];
180
+ const nameSourceIds = sourceSymbolsByName.get(canonical)?.get(node.symbolName) ?? [];
181
+ // Prefer the kind-qualified mapping. Fall back only when the source name
182
+ // is unique; never guess among overloads or same-name declarations.
183
+ const sourceIds = exactSourceIds.length > 0
184
+ ? exactSourceIds
185
+ : nameSourceIds.length === 1
186
+ ? nameSourceIds
187
+ : [];
188
+ const occurrenceKey = exactSourceIds.length > 0 ? key : node.symbolName;
189
+ const occurrences = twinOccurrencesByFile.get(raw) ?? new Map();
190
+ const occurrence = occurrences.get(occurrenceKey) ?? 0;
191
+ occurrences.set(occurrenceKey, occurrence + 1);
192
+ twinOccurrencesByFile.set(raw, occurrences);
193
+ const logical = sourceIds[occurrence];
194
+ if (logical) {
195
+ logicalSymbolByNode.set(node.id, logical);
196
+ }
197
+ else {
198
+ // A compiled-only declaration remains real evidence.
199
+ logicalSymbolByNode.set(node.id, node.id);
200
+ }
201
+ }
202
+ const countedLogicalSymbols = new Set();
140
203
  // ── Pass 3: aggregate nodes under their canonical file identity ─────────
141
204
  for (const node of graph.nodes.values()) {
142
205
  if (node.kind === "external")
@@ -173,9 +236,13 @@ export function aggregateGraphToFiles(graph, options) {
173
236
  continue;
174
237
  const id = canonicalOf.get(raw) ?? raw;
175
238
  nodeToFile.set(node.id, id);
239
+ const logicalId = logicalSymbolByNode.get(node.id) ?? node.id;
176
240
  const existing = files.get(id);
177
241
  if (existing) {
178
- existing.symbolCount += 1;
242
+ if (!countedLogicalSymbols.has(logicalId)) {
243
+ existing.symbolCount += 1;
244
+ countedLogicalSymbols.add(logicalId);
245
+ }
179
246
  }
180
247
  else {
181
248
  files.set(id, {
@@ -184,6 +251,7 @@ export function aggregateGraphToFiles(graph, options) {
184
251
  language: node.language || "",
185
252
  symbolCount: 1,
186
253
  });
254
+ countedLogicalSymbols.add(logicalId);
187
255
  }
188
256
  continue;
189
257
  }
@@ -197,11 +265,18 @@ export function aggregateGraphToFiles(graph, options) {
197
265
  // becomes self-referential only AFTER canonicalization (e.g. x.js → x.ts)
198
266
  // collapses through the same fromFile === toFile check.
199
267
  const edgeWeights = new Map();
268
+ const seenLogicalEdges = new Set();
200
269
  for (const edge of graph.edges) {
201
270
  const fromFile = nodeToFile.get(edge.from);
202
271
  const toFile = nodeToFile.get(edge.to);
203
272
  if (!fromFile || !toFile || fromFile === toFile)
204
273
  continue;
274
+ const logicalFrom = logicalSymbolByNode.get(edge.from) ?? fromFile;
275
+ const logicalTo = logicalSymbolByNode.get(edge.to) ?? toFile;
276
+ const logicalEdgeKey = `${logicalFrom}\u0000${logicalTo}\u0000${edge.kind}`;
277
+ if (seenLogicalEdges.has(logicalEdgeKey))
278
+ continue;
279
+ seenLogicalEdges.add(logicalEdgeKey);
205
280
  // NUL separator (same idiom as review-graph/builder.ts): the one byte
206
281
  // that can never appear in a file path, written as an escape sequence so
207
282
  // this source file stays text for grep (a literal NUL makes ripgrep
@@ -0,0 +1,73 @@
1
+ import { recordDegradation } from "./degradation-ledger.js";
2
+ import { probeCtxActive } from "./session-lifecycle.js";
3
+ import { logBusEvent, } from "./bus-events-logger.js";
4
+ const STALE_CTX_MESSAGE = "This extension ctx is stale after session replacement";
5
+ /** Ledger a dead activation once, at the publisher's occurrence-window guard. */
6
+ export function recordStaleBusFailure(subject, error) {
7
+ const reason = String(error);
8
+ if (!reason.includes(STALE_CTX_MESSAGE))
9
+ return;
10
+ recordDegradation({ kind: "bus-stale", subject, reason });
11
+ }
12
+ export function createLiveBusEmitter() {
13
+ let emit;
14
+ let getter;
15
+ return {
16
+ wire(next) {
17
+ emit = next;
18
+ getter = undefined;
19
+ },
20
+ wireGetter(next) {
21
+ getter = next;
22
+ emit = undefined;
23
+ },
24
+ resolve() {
25
+ // Invoke the getter for every delivery so session_start rewiring can
26
+ // replace a captured pre-await activation with the current primary. When
27
+ // the current target is nevertheless confirmed stale, never invoke it.
28
+ const target = getter?.() ?? emit;
29
+ if (!target)
30
+ return { outcome: "unwired", ctxSource: "unwired" };
31
+ if (typeof target === "function") {
32
+ return { outcome: "ready", emit: target, ctxSource: "global-fallback" };
33
+ }
34
+ // Object targets are always "own"-sourced (only `wire(fn)`'s bare
35
+ // function arm is "global-fallback", and it never reaches this
36
+ // branch) — compute it once so the ready/stale-session outcomes
37
+ // below both carry the same value instead of restating the
38
+ // literal independently.
39
+ const ctxSource = "own";
40
+ if (probeCtxActive(target.ctx) === false) {
41
+ return { outcome: "stale-session", ctxSource };
42
+ }
43
+ return { outcome: "ready", emit: target.emit, ctxSource };
44
+ },
45
+ reset() {
46
+ emit = undefined;
47
+ getter = undefined;
48
+ },
49
+ };
50
+ }
51
+ /**
52
+ * Resolve through the shared stale-session guard and record a declined
53
+ * target.
54
+ *
55
+ * `entry` is a THUNK, not a value (M1, #1415 review): building the log entry
56
+ * (every producer's version normalizes `cwd` via `normalizeFilePath`, a sync
57
+ * `realpathSync.native` call on Windows) is real per-publish cost that used
58
+ * to be paid on EVERY call regardless of outcome, even though it is only
59
+ * consumed on the `stale-session` branch. Invoking the thunk only there means
60
+ * the common `ready` path pays nothing for it.
61
+ */
62
+ export function resolveLiveBusEmitter(liveEmitter, entry) {
63
+ const resolution = liveEmitter.resolve();
64
+ if (resolution.outcome === "stale-session") {
65
+ logBusEvent({
66
+ ...entry(),
67
+ outcome: "skipped_stale_session",
68
+ level: "info",
69
+ ctxSource: resolution.ctxSource,
70
+ });
71
+ }
72
+ return resolution;
73
+ }
@@ -24,6 +24,7 @@ import * as fs from "node:fs";
24
24
  import * as path from "node:path";
25
25
  import { getGlobalPiLensDir } from "./file-utils.js";
26
26
  import { getRegisteredLogFiles } from "./ndjson-logger.js";
27
+ import { pathsEqual } from "./path-utils.js";
27
28
  const LOG_DIR = getGlobalPiLensDir();
28
29
  const LOGS_SUBDIR = path.join(LOG_DIR, "logs");
29
30
  /**
@@ -52,7 +53,7 @@ const LOGS_SUBDIR = path.join(LOG_DIR, "logs");
52
53
  export function getManagedLogFiles(dir = LOG_DIR) {
53
54
  const names = new Set();
54
55
  for (const absPath of getRegisteredLogFiles()) {
55
- if (path.dirname(absPath) === dir) {
56
+ if (pathsEqual(path.dirname(absPath), dir)) {
56
57
  names.add(path.basename(absPath));
57
58
  }
58
59
  }
@@ -26,9 +26,12 @@
26
26
  * receive `options.auxGraceMs` before the race finalises. Aux results within
27
27
  * that window are included; later arrivals are dropped. When no descriptors
28
28
  * carry `role:"auxiliary"` the aux-grace path is never entered.
29
- * @param options.auxGraceMs - Grace period given to auxiliary promises after all
30
- * primary promises have settled. Only relevant when at least one descriptor
31
- * carries `role:"auxiliary"`. Defaults to 500ms.
29
+ * @param options.auxGraceMs - Ceiling on the grace period given to auxiliary
30
+ * promises after all primary promises have settled. Only relevant when at
31
+ * least one descriptor carries `role:"auxiliary"`. Defaults to 500ms. When a
32
+ * still-pending auxiliary's descriptor carries `budgetMs`, the actual window
33
+ * is `min(auxGraceMs, max(budgetMs of still-pending auxiliaries))` — see
34
+ * `PromiseDescriptor.budgetMs`.
32
35
  */
33
36
  export async function raceToCompletion(promises, shouldComplete, options = { timeoutMs: 1500 }) {
34
37
  const results = new Array(promises.length).fill(undefined);
@@ -76,7 +79,30 @@ export async function raceToCompletion(promises, shouldComplete, options = { tim
76
79
  if (auxGraceStarted || completed)
77
80
  return;
78
81
  auxGraceStarted = true;
79
- const graceMs = options.auxGraceMs ?? 500;
82
+ const ceilingMs = options.auxGraceMs ?? 500;
83
+ // #1458 S2: cap the grace window by the still-pending auxiliaries' own
84
+ // declared budgets, not just the flat ceiling — mirrors touchFile's
85
+ // per-server `min(declared, ceiling)`.
86
+ //
87
+ // This is ONE shared timer, not a deadline per promise, so it grants
88
+ // every pending auxiliary the window of its slowest pending sibling.
89
+ // That is safe here only because of an invariant the caller upholds,
90
+ // not because of anything this function enforces: every promise
91
+ // `getDiagnostics` passes in is already self-bounded by the same
92
+ // `strategy.aggregateWaitMs` it declares as `budgetMs`, so a fast
93
+ // auxiliary resolves on its own deadline long before a slow sibling's
94
+ // window expires. A caller that passes a promise NOT self-bounded by
95
+ // its descriptor's `budgetMs` — or one that outlives it, the way
96
+ // `expectSemanticSecondPush` extends a primary — would get a window
97
+ // wider than it declared. `PromiseDescriptor` is public, so treat that
98
+ // as a real constraint on new callers rather than a theoretical one.
99
+ const pendingAuxBudgets = [...auxIndices]
100
+ .filter((i) => results[i] === undefined)
101
+ .map((i) => descriptors[i]?.budgetMs)
102
+ .filter((b) => typeof b === "number" && b >= 0);
103
+ const graceMs = pendingAuxBudgets.length > 0
104
+ ? Math.min(ceilingMs, Math.max(...pendingAuxBudgets))
105
+ : ceilingMs;
80
106
  if (graceMs <= 0) {
81
107
  finalize();
82
108
  return;
@@ -26,12 +26,18 @@
26
26
  * snapshot's `workspaceDiagnosticsSupport.mode` (from
27
27
  * `detectWorkspaceDiagnosticsSupport`, cached at `initialize`) and combines it
28
28
  * with the `silentOnClean` marker on that server's `DiagnosticStrategy`
29
- * (`server-strategies.ts`) — the same per-server behavioral-knowledge table
29
+ * (`wait-policy/strategies.ts`) — the same per-server behavioral-knowledge table
30
30
  * the rest of the LSP layer already uses. A server with no live snapshot yet,
31
31
  * or whose mode isn't `push-only`, or that isn't marked `silentOnClean`, is
32
32
  * NOT tier-3 — the caller keeps today's full in-lane wait. Fail-safe is
33
33
  * always "wait like before".
34
34
  *
35
+ * Native TS7 is the cascade-only exception. It is not silent on clean, but
36
+ * its publication does not settle inside the cold-snapshot budget. Cascade
37
+ * classifies it as `collect-later`, sends the same no-wait touch, and
38
+ * reconciles its later per-file push or pull publication. The shared server
39
+ * policy remains `waits`, so main-lane behavior does not change.
40
+ *
35
41
  * #524/#529/#541/#558: a server id can now be backed by more than one actual
36
42
  * binary — "typescript" is classic typescript-language-server OR TS7's
37
43
  * native `tsc --lsp --stdio` (PR #526). PR #526 originally routed the
@@ -46,9 +52,11 @@
46
52
  * confirmed still silent (`cleanPubs=0(v:0)`) in the same run. This is
47
53
  * therefore an EVIDENCE-BASED revert, not the original unverified caution:
48
54
  * native-ts7's clean-signal behavior IS known, and it is "publishes, not
49
- * silent". The snapshot's `launchVariant` marker again routes a native-ts7
50
- * snapshot through "waits" while the shared `silentOnClean` flag stays
51
- * `true` for classic. `scripts/probe-clean-signal.mjs`'s drift check no
55
+ * silent". The shared classifier still routes a native-ts7 snapshot through
56
+ * `waits`. The cascade-only wrapper routes it through `collect-later` because
57
+ * the measured publication arrives after the in-lane budget. The shared
58
+ * `silentOnClean` flag stays `true` for classic.
59
+ * `scripts/probe-clean-signal.mjs`'s drift check no
52
60
  * longer compares native-ts7 rows against the shared marker (it now expects
53
61
  * `false` for them explicitly) — see that file's header for the regression
54
62
  * watch this sets up for a future TS7 build that becomes silent again.
@@ -57,7 +65,32 @@ import { logCascade } from "../cascade-logger.js";
57
65
  import { logLatency } from "../latency-logger.js";
58
66
  import { normalizeMapKey } from "../path-utils.js";
59
67
  import { registerQuietWindowTask } from "../quiet-window.js";
60
- export { classifyCascadeWaitTier, classifyServerWaitTier, } from "./wait-policy/classification.js";
68
+ import { classifyCascadeWaitTier as classifySharedCascadeWaitTier, classifyServerWaitTier, resolvePrimaryServerForWaitPolicy, } from "./wait-policy/classification.js";
69
+ export { classifyServerWaitTier };
70
+ /**
71
+ * The cascade lane's wait tier for `filePath`. DELEGATES to the shared
72
+ * `wait-policy/classification.ts` rule — this wrapper adds exactly one
73
+ * cascade-only override on top of it (native TS7's push-only snapshot →
74
+ * `collect-later`) and never re-implements the classification itself.
75
+ *
76
+ * #1444 coverage tradeoff: the no-wait touch this tier selects is
77
+ * `clientScope: "primary"`, and the tier itself is decided from the PRIMARY
78
+ * (non-auxiliary) server alone. That tradeoff already existed for
79
+ * `tier3-silent`; the override enlarges the population it applies to — every
80
+ * native-TS7 TypeScript neighbour now takes the no-wait path too, so an
81
+ * auxiliary server configured for those files no longer gets touched in-lane
82
+ * for them (its findings arrive via the next per-edit dispatch, as they
83
+ * already did for classic tier-3 files).
84
+ */
85
+ export function classifyCascadeWaitTier(lspService, filePath, snapshots) {
86
+ const primary = resolvePrimaryServerForWaitPolicy(filePath, snapshots);
87
+ if (primary?.serverId === "typescript" &&
88
+ primary.snapshot?.launchVariant === "native-ts7" &&
89
+ primary.snapshot.workspaceDiagnosticsSupport?.mode === "push-only") {
90
+ return "collect-later";
91
+ }
92
+ return classifySharedCascadeWaitTier(lspService, filePath, snapshots);
93
+ }
61
94
  // --- Kill switch (lazy, memoized — house style per clients/runtime-config.ts /
62
95
  // clients/quiet-window.ts's isQuietWindowEnabled) ---
63
96
  let _enabledCache;
@@ -158,6 +191,7 @@ export async function reconcileOutstandingCascadeTouches(lspService) {
158
191
  outcome: found ? "resolved-found" : "resolved-clean",
159
192
  ageMs,
160
193
  diagnosticCount: entry.diags.length,
194
+ publishedAt: entry.ts,
161
195
  // #1023: carry the diagnostics so the task can re-surface them.
162
196
  ...(found && { diagnostics: entry.diags }),
163
197
  });
@@ -199,17 +233,28 @@ export function registerCascadeTierReconcileTask(getLspService, options = {}) {
199
233
  if (outcomes.length === 0)
200
234
  return;
201
235
  // #1023: re-inject each resolved-found neighbor error so it reaches the
202
- // agent (previously logs-only). Isolated per-outcome a throwing callback
203
- // must not drop the log line or the sibling re-injections.
236
+ // agent (previously logs-only). #1444: hand each resolved-CLEAN outcome to
237
+ // the footer reconcile for the mirror-image case. Isolated per-outcome a
238
+ // throwing callback must not drop the log line or the sibling deliveries.
204
239
  for (const o of outcomes) {
205
- if (o.outcome !== "resolved-found" || !o.diagnostics?.length)
206
- continue;
207
240
  try {
208
- options.onResolvedFound?.({
209
- filePath: o.filePath,
210
- serverId: o.serverId,
211
- diagnostics: o.diagnostics,
212
- });
241
+ if (o.outcome === "resolved-found" && o.diagnostics?.length) {
242
+ options.onResolvedFound?.({
243
+ filePath: o.filePath,
244
+ serverId: o.serverId,
245
+ diagnostics: o.diagnostics,
246
+ });
247
+ }
248
+ else if (o.outcome === "resolved-clean" && o.publishedAt != null) {
249
+ // #1444: the stale-footer half of the same honesty problem — the
250
+ // neighbour proved clean, but only after the in-lane wait was
251
+ // skipped, so nothing has cleared its earlier error entries.
252
+ options.onResolvedClean?.({
253
+ filePath: o.filePath,
254
+ serverId: o.serverId,
255
+ publishedAt: o.publishedAt,
256
+ });
257
+ }
213
258
  }
214
259
  catch {
215
260
  // best-effort surfacing; the log below is the durable record.