@herbertgao/pi-extensions 2026.8.6 → 2026.8.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (343) hide show
  1. package/README.md +5 -5
  2. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +1 -1
  3. package/node_modules/@herbertgao/pi-cc-extensions/README.md +1 -1
  4. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +19 -7
  5. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +30 -9
  6. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +272 -22
  7. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +94 -77
  8. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/message-display.ts +1 -1
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +14 -0
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +55 -17
  11. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/layout.ts +41 -2
  12. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +75 -6
  13. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/types.ts +7 -3
  14. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +64 -1
  15. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  16. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +6 -0
  17. package/node_modules/@herbertgao/pi-subagents/README.md +30 -22
  18. package/node_modules/@herbertgao/pi-subagents/examples/agent-tool-description.md +5 -5
  19. package/node_modules/@herbertgao/pi-subagents/package.json +7 -7
  20. package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +7 -1
  21. package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +48 -19
  22. package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +17 -13
  23. package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +26 -2
  24. package/node_modules/@herbertgao/pi-subagents/src/index.ts +219 -40
  25. package/node_modules/@herbertgao/pi-subagents/src/invocation-config.ts +101 -3
  26. package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +18 -4
  27. package/node_modules/@herbertgao/pi-subagents/src/settings.ts +99 -0
  28. package/node_modules/@herbertgao/pi-subagents/src/types.ts +22 -3
  29. package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +51 -3
  30. package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +20 -2
  31. package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +21 -6
  32. package/node_modules/@herbertgao/pi-subagents/src/usage.ts +129 -1
  33. package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +20 -0
  34. package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +1 -0
  35. package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +26 -10
  36. package/node_modules/@juicesharp/rpiv-ask-user-question/config.ts +25 -0
  37. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/configuration.md +13 -4
  38. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +2 -1
  39. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/localization.md +3 -1
  40. package/node_modules/@juicesharp/rpiv-ask-user-question/locales/en.json +2 -2
  41. package/node_modules/@juicesharp/rpiv-ask-user-question/locales/zh.json +2 -2
  42. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +3 -2
  43. package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +10 -0
  44. package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +3 -1
  45. package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +30 -7
  46. package/node_modules/@juicesharp/rpiv-ask-user-question/state/state.ts +14 -6
  47. package/node_modules/@juicesharp/rpiv-ask-user-question/view/dialog-builder.ts +30 -4
  48. package/node_modules/@juicesharp/rpiv-ask-user-question/view/tab-content-strategy.ts +26 -5
  49. package/node_modules/@narumitw/pi-btw/README.md +120 -111
  50. package/node_modules/@narumitw/pi-btw/dist/index.ts +2898 -0
  51. package/node_modules/@narumitw/pi-btw/dist/index.ts.map +7 -0
  52. package/node_modules/@narumitw/pi-btw/package.json +10 -6
  53. package/node_modules/@narumitw/pi-btw/src/btw.ts +36 -40
  54. package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +55 -10
  55. package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +390 -0
  56. package/node_modules/@narumitw/pi-btw/src/menu.ts +45 -2
  57. package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +136 -45
  58. package/node_modules/pi-lens/CHANGELOG.md +909 -0
  59. package/node_modules/pi-lens/README.md +11 -3
  60. package/node_modules/pi-lens/config/ruff/core.toml +42 -0
  61. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +130 -27
  62. package/node_modules/pi-lens/dist/clients/advisory-provenance.js +126 -13
  63. package/node_modules/pi-lens/dist/clients/agent-nudge.js +67 -11
  64. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +9 -3
  65. package/node_modules/pi-lens/dist/clients/atomic-write.js +9 -3
  66. package/node_modules/pi-lens/dist/clients/bash-file-access.js +285 -8
  67. package/node_modules/pi-lens/dist/clients/biome-client.js +61 -30
  68. package/node_modules/pi-lens/dist/clients/blocker-freshness.js +428 -0
  69. package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +119 -0
  70. package/node_modules/pi-lens/dist/clients/bootstrap.js +12 -1
  71. package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +12 -3
  72. package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +192 -0
  73. package/node_modules/pi-lens/dist/clients/cascade-budget.js +196 -0
  74. package/node_modules/pi-lens/dist/clients/cascade-format.js +20 -1
  75. package/node_modules/pi-lens/dist/clients/cascade-types.js +9 -1
  76. package/node_modules/pi-lens/dist/clients/child-unref.js +54 -6
  77. package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +76 -24
  78. package/node_modules/pi-lens/dist/clients/dead-code-client.js +123 -31
  79. package/node_modules/pi-lens/dist/clients/deadline-utils.js +8 -1
  80. package/node_modules/pi-lens/dist/clients/debug-handles.js +5 -0
  81. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +62 -13
  82. package/node_modules/pi-lens/dist/clients/dependency-checker.js +25 -3
  83. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +147 -33
  84. package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +298 -0
  85. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +52 -2
  86. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +256 -88
  87. package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +7 -4
  88. package/node_modules/pi-lens/dist/clients/dispatch/plan.js +5 -0
  89. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +234 -18
  90. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +187 -19
  91. package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +6 -3
  92. package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +11 -9
  93. package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +398 -0
  94. package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +11 -3
  95. package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +12 -7
  96. package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +18 -0
  97. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +895 -0
  98. package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +4 -0
  99. package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +16 -3
  100. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +60 -53
  101. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +16 -0
  102. package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +23 -0
  103. package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +331 -55
  104. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +38 -5
  105. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +97 -19
  106. package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +14 -0
  107. package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +20 -0
  108. package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +22 -0
  109. package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +10 -0
  110. package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +18 -6
  111. package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +73 -12
  112. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +275 -13
  113. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +21 -6
  114. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +260 -27
  115. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +734 -64
  116. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +86 -11
  117. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +72 -0
  118. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +9 -0
  119. package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +9 -0
  120. package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +18 -1
  121. package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +4 -2
  122. package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +28 -5
  123. package/node_modules/pi-lens/dist/clients/extension-log.js +22 -1
  124. package/node_modules/pi-lens/dist/clients/file-kinds.js +8 -2
  125. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +294 -0
  126. package/node_modules/pi-lens/dist/clients/finding-identity.js +88 -0
  127. package/node_modules/pi-lens/dist/clients/formatters-lazy.js +3 -2
  128. package/node_modules/pi-lens/dist/clients/formatters.js +500 -115
  129. package/node_modules/pi-lens/dist/clients/generation-guard.js +216 -0
  130. package/node_modules/pi-lens/dist/clients/git-guard.js +31 -0
  131. package/node_modules/pi-lens/dist/clients/gitleaks-client.js +181 -8
  132. package/node_modules/pi-lens/dist/clients/govulncheck-client.js +109 -9
  133. package/node_modules/pi-lens/dist/clients/grammar-source.js +333 -10
  134. package/node_modules/pi-lens/dist/clients/host-ports.js +8 -0
  135. package/node_modules/pi-lens/dist/clients/installer/index.js +1114 -100
  136. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh-session.js +58 -0
  137. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +715 -0
  138. package/node_modules/pi-lens/dist/clients/instance-reaper.js +643 -97
  139. package/node_modules/pi-lens/dist/clients/instance-registry.js +87 -17
  140. package/node_modules/pi-lens/dist/clients/jscpd-client.js +82 -6
  141. package/node_modules/pi-lens/dist/clients/knip-client.js +310 -10
  142. package/node_modules/pi-lens/dist/clients/language-policy.js +8 -2
  143. package/node_modules/pi-lens/dist/clients/language-profile.js +2 -0
  144. package/node_modules/pi-lens/dist/clients/latency-logger.js +440 -11
  145. package/node_modules/pi-lens/dist/clients/lazy-import.js +21 -0
  146. package/node_modules/pi-lens/dist/clients/ledger-bounds.js +21 -0
  147. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +8 -0
  148. package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +102 -7
  149. package/node_modules/pi-lens/dist/clients/lsp/client.js +1516 -159
  150. package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +83 -1
  151. package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +389 -0
  152. package/node_modules/pi-lens/dist/clients/lsp/index.js +2274 -147
  153. package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +215 -0
  154. package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +146 -14
  155. package/node_modules/pi-lens/dist/clients/lsp/language.js +48 -4
  156. package/node_modules/pi-lens/dist/clients/lsp/server.js +277 -16
  157. package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +22 -0
  158. package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +43 -0
  159. package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +79 -3
  160. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +43 -0
  161. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +422 -28
  162. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-session.js +30 -0
  163. package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +175 -0
  164. package/node_modules/pi-lens/dist/clients/lsp-lazy.js +3 -2
  165. package/node_modules/pi-lens/dist/clients/mcp/session.js +10 -2
  166. package/node_modules/pi-lens/dist/clients/module-report.js +8 -0
  167. package/node_modules/pi-lens/dist/clients/opengrep-client.js +15 -1
  168. package/node_modules/pi-lens/dist/clients/package-manager.js +170 -14
  169. package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +27 -0
  170. package/node_modules/pi-lens/dist/clients/path-utils.js +160 -0
  171. package/node_modules/pi-lens/dist/clients/pipeline.js +154 -33
  172. package/node_modules/pi-lens/dist/clients/post-autofix-notice.js +37 -0
  173. package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +17 -3
  174. package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +89 -22
  175. package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +84 -14
  176. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +15 -3
  177. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +50 -2
  178. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +5 -0
  179. package/node_modules/pi-lens/dist/clients/project-lens-config.js +3 -0
  180. package/node_modules/pi-lens/dist/clients/project-snapshot.js +299 -0
  181. package/node_modules/pi-lens/dist/clients/quiet-window-config.js +47 -0
  182. package/node_modules/pi-lens/dist/clients/quiet-window.js +11 -25
  183. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +1 -1
  184. package/node_modules/pi-lens/dist/clients/read-guard.js +184 -10
  185. package/node_modules/pi-lens/dist/clients/resource-sampler.js +49 -17
  186. package/node_modules/pi-lens/dist/clients/reverse-deps.js +50 -11
  187. package/node_modules/pi-lens/dist/clients/review-graph/query.js +52 -4
  188. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +96 -7
  189. package/node_modules/pi-lens/dist/clients/runtime-context.js +8 -1
  190. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +308 -45
  191. package/node_modules/pi-lens/dist/clients/runtime-session.js +332 -9
  192. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +217 -22
  193. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +212 -79
  194. package/node_modules/pi-lens/dist/clients/runtime-turn.js +575 -67
  195. package/node_modules/pi-lens/dist/clients/safe-spawn.js +220 -7
  196. package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +161 -0
  197. package/node_modules/pi-lens/dist/clients/search-read-registration.js +34 -6
  198. package/node_modules/pi-lens/dist/clients/security-scan-client.js +157 -24
  199. package/node_modules/pi-lens/dist/clients/sg-runner.js +116 -22
  200. package/node_modules/pi-lens/dist/clients/single-flight.js +158 -0
  201. package/node_modules/pi-lens/dist/clients/stale-marker.js +17 -0
  202. package/node_modules/pi-lens/dist/clients/startup-timing.js +19 -1
  203. package/node_modules/pi-lens/dist/clients/test-runner-client.js +151 -16
  204. package/node_modules/pi-lens/dist/clients/tool-event.js +56 -5
  205. package/node_modules/pi-lens/dist/clients/tool-policy.js +125 -20
  206. package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +75 -1
  207. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +769 -64
  208. package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +11 -0
  209. package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +90 -0
  210. package/node_modules/pi-lens/dist/clients/trivy-client.js +19 -1
  211. package/node_modules/pi-lens/dist/clients/widget-state.js +336 -36
  212. package/node_modules/pi-lens/dist/clients/zizmor-config.js +214 -14
  213. package/node_modules/pi-lens/dist/index.js +67738 -55739
  214. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +466 -54
  215. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +132 -43
  216. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -7
  217. package/node_modules/pi-lens/docs/agent-guide.md +6 -1
  218. package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +515 -506
  219. package/node_modules/pi-lens/docs/dispositions.md +21 -0
  220. package/node_modules/pi-lens/docs/features.md +19 -5
  221. package/node_modules/pi-lens/docs/globalconfig.md +3 -0
  222. package/node_modules/pi-lens/docs/language-coverage.md +71 -5
  223. package/node_modules/pi-lens/docs/mcp.md +2 -2
  224. package/node_modules/pi-lens/docs/servercapabilities.md +4 -1
  225. package/node_modules/pi-lens/docs/settings.md +19 -1
  226. package/node_modules/pi-lens/docs/usage.md +1 -0
  227. package/node_modules/pi-lens/package.json +10 -6
  228. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-js-snapshot.yml +23 -0
  229. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-snapshot.yml +23 -0
  230. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/ts-void-zero-snapshot.yml +23 -0
  231. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-object-param-test.yml +16 -0
  232. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +15 -1
  233. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-compile-call-test.yml +29 -1
  234. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-dupe-class-members-test.yml +33 -0
  235. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-js-test.yml +7 -1
  236. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-test.yml +7 -1
  237. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-known-value-widening-test.yml +9 -0
  238. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-non-null-assertion-test.yml +216 -0
  239. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +2 -0
  240. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +2 -0
  241. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +2 -1
  242. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +2 -1
  243. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-return-value-in-generator-test.yml +12 -0
  244. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-runtime-typeof-test.yml +33 -0
  245. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-server-bind-wildcard-test.yml +9 -0
  246. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-shape-in-symbol-names-test.yml +13 -0
  247. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-js-test.yml +5 -1
  248. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-test.yml +5 -1
  249. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-parameters-test.yml +12 -0
  250. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-returns-test.yml +16 -0
  251. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-any-test.yml +10 -0
  252. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-unknown-test.yml +8 -0
  253. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/redundant-unsafe-function-test.yml +35 -0
  254. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/require-safety-comment-for-as-unknown-as-test.yml +177 -0
  255. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/ts-void-zero-test.yml +1 -0
  256. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member-js.yml +13 -2
  257. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member.yml +13 -2
  258. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +2 -0
  259. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-object-param.yml +60 -0
  260. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +57 -12
  261. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-compile-call.yml +63 -5
  262. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-dupe-class-members.yml +52 -8
  263. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html-js.yml +27 -2
  264. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html.yml +27 -2
  265. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-known-value-widening.yml +71 -0
  266. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-non-null-assertion.yml +316 -0
  267. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +7 -0
  268. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +22 -2
  269. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +23 -2
  270. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +33 -5
  271. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +34 -8
  272. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-return-value-in-generator.yml +22 -5
  273. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-runtime-typeof.yml +121 -0
  274. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-server-bind-wildcard.yml +23 -7
  275. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-shape-in-symbol-names.yml +68 -0
  276. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code-js.yml +41 -2
  277. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code.yml +41 -2
  278. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +6 -1
  279. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-parameters.yml +67 -0
  280. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-returns.yml +106 -0
  281. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-any.yml +50 -0
  282. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-unknown.yml +56 -0
  283. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +2 -0
  284. package/node_modules/pi-lens/rules/ast-grep-rules/rules/redundant-unsafe-function.yml +32 -0
  285. package/node_modules/pi-lens/rules/ast-grep-rules/rules/require-safety-comment-for-as-unknown-as.yml +184 -0
  286. package/node_modules/pi-lens/rules/ast-grep-rules/rules/ts-void-zero.yml +5 -0
  287. package/node_modules/pi-lens/rules/ast-grep-rules/self-scan-baseline.json +5 -0
  288. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +53 -1
  289. package/node_modules/pi-lens/scripts/download-grammars.js +25 -0
  290. package/node_modules/pi-lens/scripts/grammars.lock.json +9 -0
  291. package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +2 -0
  292. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +80 -3
  293. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +41 -0
  294. package/node_modules/pi-lens/vendor/grammars/tree-sitter-cue.wasm +0 -0
  295. package/node_modules/pi-mcp-adapter/CHANGELOG.md +36 -0
  296. package/node_modules/pi-mcp-adapter/README.md +47 -5
  297. package/node_modules/pi-mcp-adapter/cli.js +163 -1
  298. package/node_modules/pi-mcp-adapter/commands.ts +128 -22
  299. package/node_modules/pi-mcp-adapter/config.ts +25 -7
  300. package/node_modules/pi-mcp-adapter/direct-tools.ts +5 -4
  301. package/node_modules/pi-mcp-adapter/index.ts +219 -32
  302. package/node_modules/pi-mcp-adapter/init.ts +36 -4
  303. package/node_modules/pi-mcp-adapter/lifecycle.ts +315 -24
  304. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +39 -6
  305. package/node_modules/pi-mcp-adapter/mcp-bearer-store.ts +387 -0
  306. package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +27 -3
  307. package/node_modules/pi-mcp-adapter/mcp-code.ts +4 -0
  308. package/node_modules/pi-mcp-adapter/mcp-panel.ts +42 -13
  309. package/node_modules/pi-mcp-adapter/metadata-cache.ts +32 -21
  310. package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +168 -0
  311. package/node_modules/pi-mcp-adapter/package.json +3 -1
  312. package/node_modules/pi-mcp-adapter/proxy-modes.ts +5 -4
  313. package/node_modules/pi-mcp-adapter/request-headers-command.ts +31 -37
  314. package/node_modules/pi-mcp-adapter/search-ranking.ts +92 -22
  315. package/node_modules/pi-mcp-adapter/server-manager.ts +140 -2
  316. package/node_modules/pi-mcp-adapter/session-recovery.ts +7 -0
  317. package/node_modules/pi-mcp-adapter/tool-approval.ts +15 -2
  318. package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +44 -4
  319. package/node_modules/pi-mcp-adapter/types.ts +2 -0
  320. package/node_modules/pi-mcp-adapter/ui-server.ts +18 -16
  321. package/node_modules/pi-mcp-adapter/utils.ts +70 -0
  322. package/node_modules/pi-web-access/CHANGELOG.md +23 -0
  323. package/node_modules/pi-web-access/README.md +27 -9
  324. package/node_modules/pi-web-access/anysearch.ts +4 -2
  325. package/node_modules/pi-web-access/brave.ts +16 -4
  326. package/node_modules/pi-web-access/curator-page.ts +6 -3
  327. package/node_modules/pi-web-access/curator-server.ts +4 -1
  328. package/node_modules/pi-web-access/exa.ts +18 -7
  329. package/node_modules/pi-web-access/extract.ts +28 -3
  330. package/node_modules/pi-web-access/gemini-search.ts +16 -4
  331. package/node_modules/pi-web-access/index.ts +41 -57
  332. package/node_modules/pi-web-access/package.json +1 -1
  333. package/node_modules/pi-web-access/page-query.ts +4 -2
  334. package/node_modules/pi-web-access/parallel-mcp.ts +249 -0
  335. package/node_modules/pi-web-access/parallel.ts +2 -2
  336. package/node_modules/pi-web-access/query-rewrite.ts +51 -0
  337. package/node_modules/pi-web-access/serper.ts +211 -0
  338. package/node_modules/pi-web-access/summary-model-scope.ts +12 -4
  339. package/node_modules/pi-web-access/summary-review.ts +44 -22
  340. package/node_modules/pi-web-access/tavily.ts +16 -4
  341. package/node_modules/pi-web-access/utils.ts +87 -0
  342. package/node_modules/pi-web-access/valyu.ts +199 -0
  343. package/package.json +13 -13
@@ -1,22 +1,97 @@
1
+ import { LEDGER_FIELD_MAX } from "../../../ledger-bounds.js";
2
+ /**
3
+ * The first non-empty line of a tool's output, bounded.
4
+ *
5
+ * Replaces six hand-rolled copies that spelled the same idea two ways —
6
+ * `text.trim().split("\n")[0]` and `(text ?? "").trim().split("\n")[0] ||
7
+ * fallback` — with differing (or absent) length caps. Two behaviours the
8
+ * copies got wrong and this does not: a leading blank line no longer yields an
9
+ * empty "first line", and `\r\n` output no longer keeps its carriage return.
10
+ *
11
+ * Returns `""` when the text is empty or all-whitespace, so callers keep using
12
+ * `firstOutputLine(x) || fallback`.
13
+ */
14
+ export function firstOutputLine(text, max = LEDGER_FIELD_MAX) {
15
+ for (const line of String(text ?? "").split(/\r?\n/)) {
16
+ const trimmed = line.trim();
17
+ if (!trimmed)
18
+ continue;
19
+ return trimmed.length > max ? `${trimmed.slice(0, max)}…` : trimmed;
20
+ }
21
+ return "";
22
+ }
23
+ /**
24
+ * Decide whether a tool ran, and if not, why (#1816).
25
+ *
26
+ * The defect this closes (the #1736 class): a runner that reads only its
27
+ * parsed diagnostics reports a CLEAN file whenever the parse yields nothing —
28
+ * including when the tool exited non-zero on an unknown flag, was killed by a
29
+ * signal, or never spawned at all. An empty result must distinguish clean from
30
+ * errored.
31
+ *
32
+ * Classification order, most specific first:
33
+ * 1. `result.error` or a signal — the process never completed. `did-not-run`.
34
+ * 2. `status === null` with no error — no exit status ever arrived, so no
35
+ * analysis can be claimed. `did-not-run`.
36
+ * 3. `reportMissing` — an artifact tool wrote no report. Nonzero exit means
37
+ * `report-missing`; exit 0 means a genuinely clean run that had nothing
38
+ * to write.
39
+ * 4. A nonzero status outside the caller's declared `ran` table.
40
+ * `rejected-invocation`.
41
+ * 5. A nonzero status with nothing to parse. `did-not-run` — a tool that
42
+ * analysed the file says SOMETHING, so silence plus failure is evidence
43
+ * it never got that far.
44
+ * Everything else ran.
45
+ *
46
+ * Note what is deliberately NOT a non-ran path: a nonzero status WITH output
47
+ * and no contradicting table. Most linters exit non-zero precisely because
48
+ * they found something, and their findings are on stdout.
49
+ */
50
+ export function classifyRunOutcome(input) {
51
+ const { result, exitCodes, reportMissing } = input;
52
+ const status = result.status ?? null;
53
+ const signal = result.signal ?? null;
54
+ const output = input.output ?? result.stdout;
55
+ const base = {
56
+ status,
57
+ signal,
58
+ firstOutputLine: firstOutputLine(result.stderr) ||
59
+ firstOutputLine(result.stdout) ||
60
+ firstOutputLine(result.error?.message),
61
+ };
62
+ if (result.error || signal)
63
+ return { kind: "did-not-run", ...base };
64
+ if (status === null)
65
+ return { kind: "did-not-run", ...base };
66
+ if (reportMissing) {
67
+ return status === 0
68
+ ? { kind: "ran", ...base }
69
+ : { kind: "report-missing", ...base };
70
+ }
71
+ if (status !== 0 && exitCodes && !exitCodes.ran.includes(status)) {
72
+ return { kind: "rejected-invocation", ...base };
73
+ }
74
+ if (status !== 0 && !output?.trim()) {
75
+ return { kind: "did-not-run", ...base };
76
+ }
77
+ return { kind: "ran", ...base };
78
+ }
1
79
  /**
2
80
  * True when a tool both failed and produced nothing to parse — it never got as
3
81
  * far as linting the file. Callers map this to `skipped`, never `succeeded`.
4
82
  *
5
- * Guarding on `result.error` alone covers only half of it: safe-spawn sets
6
- * `error` for spawn/timeout/signal failures and resolves a NORMAL exit with no
7
- * `error` at any status (see `SpawnResult.failure` "nonzero exit statuses are
8
- * not spawn failures"). An unknown subcommand, a rejected flag, or a config
9
- * that fails to load exits non-zero with the message on stderr and an empty
10
- * stdout, so an `error`-only guard falls through, parses "" into zero
11
- * diagnostics, and reports a clean file that nothing ever checked.
12
- *
13
- * Tools that exit non-zero *because* they found something are unaffected: their
14
- * findings are on stdout, so the output half of the test is false.
83
+ * Kept as its own export because callers outside the dispatch runners use it
84
+ * (`dead-code-client.ts`, `knip-client.ts`). It now DELEGATES to
85
+ * `classifyRunOutcome` rather than restating the rule, but keeps its exact
86
+ * historical semantics: the `!output.trim()` conjunct stays here so a spawn
87
+ * error that still produced partial output keeps reaching the parser, which is
88
+ * what today's callers depend on. `classifyRunOutcome` is the stricter,
89
+ * outcome-typed reading; migrate callers to it deliberately, not by accident.
15
90
  *
16
91
  * `output` defaults to stdout. Runners that parse stderr too pass the exact
17
92
  * string they are about to hand the parser, so "nothing to parse" means both
18
93
  * streams rather than just one.
19
94
  */
20
95
  export function spawnFailedWithNoOutput(result, output = result.stdout) {
21
- return (Boolean(result.error) || result.status !== 0) && !output?.trim();
96
+ return (classifyRunOutcome({ result, output }).kind !== "ran" && !output?.trim());
22
97
  }
@@ -0,0 +1,72 @@
1
+ /**
2
+ * One wording for a tool that produced no usable result, and the runner gate
3
+ * that emits it to the degradation ledger (#1816).
4
+ */
5
+ import { incrementDegradationCount } from "../../../degradation-ledger.js";
6
+ import { truncateForLedger } from "../../../ledger-bounds.js";
7
+ import { classifyRunOutcome, firstOutputLine, } from "./spawn-outcome.js";
8
+ /**
9
+ * One wording for "this tool did not produce a usable result" (#1816).
10
+ *
11
+ * Before this, five reason builders spelled the same sentence five ways and
12
+ * twelve sites truncated with their own literal, and NONE of them named the
13
+ * signal — so a SIGKILLed tool read exactly like a clean exit 0. The wording
14
+ * here is fixed, the truncation is the ledger's own `LEDGER_FIELD_MAX` policy
15
+ * applied once at the end, and the signal is always named when present.
16
+ *
17
+ * Shape: `tool (k=v, k=v) <what happened> with <what was missing>: <detail>`
18
+ */
19
+ export function formatToolFailure(input) {
20
+ const entries = Object.entries(input.fields ?? {}).filter(([, value]) => value !== undefined && value !== "");
21
+ const identity = entries.length
22
+ ? `${input.tool} (${entries.map(([key, value]) => `${key}=${value}`).join(", ")})`
23
+ : input.tool;
24
+ // A signal is the strongest available explanation, so it displaces the exit
25
+ // status rather than sitting beside a `null` one.
26
+ const what = input.signal
27
+ ? `was killed by ${input.signal}`
28
+ : input.status === null
29
+ ? "did not run (spawn failure)"
30
+ : `exited ${input.status}`;
31
+ const missing = input.reportMissing ? "no report file" : "no output";
32
+ const detail = firstOutputLine(input.stderr) || firstOutputLine(input.stdout) || "no stderr";
33
+ return truncateForLedger(`${identity} ${what} with ${missing}: ${detail}`);
34
+ }
35
+ /**
36
+ * `formatToolFailure` fed straight from a `classifyRunOutcome` verdict — the
37
+ * path every migrated runner takes, so the outcome and the wording can never
38
+ * disagree about the status or the signal.
39
+ */
40
+ export function formatRunOutcomeFailure(tool, outcome, fields) {
41
+ return formatToolFailure({
42
+ tool,
43
+ status: outcome.status,
44
+ signal: outcome.signal,
45
+ stderr: outcome.firstOutputLine,
46
+ reportMissing: outcome.kind === "report-missing",
47
+ fields: { outcome: outcome.kind, ...fields },
48
+ });
49
+ }
50
+ /**
51
+ * The migrated runners' one call: classify the spawn, and when the tool did
52
+ * NOT run, record a bounded `runner-empty-result` row and hand back the
53
+ * `skipped` verdict. Returns `null` when the tool ran, meaning "carry on and
54
+ * parse".
55
+ *
56
+ * `incrementDegradationCount` keeps the record bounded — one latest-reason
57
+ * entry per (kind, subject) with an exact event tally — so a permanently
58
+ * broken tool costs one ledger row, not one per dispatched file. `subject` is
59
+ * the tool id, which is the discriminating identity a reader needs: WHICH tool
60
+ * is silently contributing nothing.
61
+ */
62
+ export function skipUnlessToolRan(tool, input, fields) {
63
+ const outcome = classifyRunOutcome(input);
64
+ if (outcome.kind === "ran")
65
+ return null;
66
+ incrementDegradationCount({
67
+ kind: "runner-empty-result",
68
+ subject: tool,
69
+ reason: formatRunOutcomeFailure(tool, outcome, fields),
70
+ });
71
+ return { status: "skipped", diagnostics: [], semantic: "none" };
72
+ }
@@ -26,6 +26,8 @@ export function createToolchainAvailability(config) {
26
26
  let sweepSawTransient = false;
27
27
  let sweepTransientCause = "probe-timeout";
28
28
  let sweepHostStallMs = 0;
29
+ /** What the last classified candidate returned, for the decision record. */
30
+ let sweepEvidence;
29
31
  let ensureInFlight = null;
30
32
  async function findPath() {
31
33
  if (toolPath)
@@ -35,6 +37,7 @@ export function createToolchainAvailability(config) {
35
37
  sweepSawTransient = sweep.sawTransient;
36
38
  sweepTransientCause = sweep.transientCause;
37
39
  sweepHostStallMs = sweep.hostStallMs;
40
+ sweepEvidence = sweep.evidence;
38
41
  if (sweep.foundPath)
39
42
  toolPath = sweep.foundPath;
40
43
  return sweep.foundPath;
@@ -54,6 +57,8 @@ export function createToolchainAvailability(config) {
54
57
  latched: true,
55
58
  hostStallMs: sweepHostStallMs,
56
59
  budgetMs: config.budgetMs,
60
+ classifiedBy: "probe",
61
+ ...(sweepEvidence !== undefined && { evidence: sweepEvidence }),
57
62
  });
58
63
  return true;
59
64
  }
@@ -72,6 +77,10 @@ export function createToolchainAvailability(config) {
72
77
  hostStallMs: sweepHostStallMs,
73
78
  ...(retryAfterMs > 0 && { retryAfterMs }),
74
79
  budgetMs: config.budgetMs,
80
+ // Derived from the sweep's own candidate probes, and carrying what the
81
+ // last of them returned (#1500).
82
+ classifiedBy: "probe",
83
+ ...(sweepEvidence !== undefined && { evidence: sweepEvidence }),
75
84
  });
76
85
  return false;
77
86
  }
@@ -3,6 +3,7 @@ import * as path from "node:path";
3
3
  import { safeSpawnAsync } from "../../safe-spawn.js";
4
4
  import { PRIORITY } from "../priorities.js";
5
5
  import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
6
+ import { skipUnlessToolRan } from "./utils/tool-failure.js";
6
7
  const vale = createAvailabilityChecker("vale", ".exe");
7
8
  /**
8
9
  * Check for a .vale.ini config file in cwd or parent dirs.
@@ -89,6 +90,14 @@ const valeRunner = {
89
90
  return { status: "skipped", diagnostics: [], semantic: "none" };
90
91
  // Vale exits 0 even on findings, non-zero only on errors
91
92
  const result = await safeSpawnAsync(cmd, ["--output", "JSON", ctx.filePath], { cwd, timeout: 15000 });
93
+ // #1816: this runner read `result.status` zero times, so a Vale that
94
+ // rejected its config exited nonzero with an empty stdout, parsed to
95
+ // zero alerts, and reported clean prose. No exit-code table: Vale's
96
+ // nonzero codes vary with --minAlertLevel, so the conservative
97
+ // nothing-to-parse rule is the only safe discriminator here.
98
+ const skipped = skipUnlessToolRan("vale", { result });
99
+ if (skipped)
100
+ return skipped;
92
101
  const raw = result.stdout || "";
93
102
  const diagnostics = parseValeOutput(raw, ctx.filePath);
94
103
  if (diagnostics.length === 0) {
@@ -2,6 +2,7 @@ import { safeSpawnAsync } from "../../safe-spawn.js";
2
2
  import { getLinterPolicyForCwd, hasYamllintConfig } from "../../tool-policy.js";
3
3
  import { PRIORITY } from "../priorities.js";
4
4
  import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
5
+ import { skipUnlessToolRan } from "./utils/tool-failure.js";
5
6
  const yamllint = createAvailabilityChecker("yamllint", ".exe");
6
7
  export { hasYamllintConfig };
7
8
  function parseYamllintParsable(raw, filePath) {
@@ -55,7 +56,23 @@ const yamllintRunner = {
55
56
  const result = await safeSpawnAsync(cmd, ["-f", "parsable", ctx.filePath], {
56
57
  timeout: 15000,
57
58
  });
58
- const diagnostics = parseYamllintParsable(`${result.stdout ?? ""}${result.stderr ?? ""}`, ctx.filePath);
59
+ // #1816: this runner read `result.status` zero times, so a yamllint
60
+ // that rejected its config reported a clean YAML file.
61
+ //
62
+ // No exit-code table: yamllint returns 2 both for "warnings only" and
63
+ // for an argparse usage error, so declaring 2 a rejection would discard
64
+ // real warnings. The discriminator is the STREAM instead. `-f parsable`
65
+ // writes findings to stdout and nothing else; stderr carries usage text
66
+ // and tracebacks. So the gate judges "nothing to parse" on stdout alone,
67
+ // while the parser still reads both streams.
68
+ const raw = `${result.stdout ?? ""}${result.stderr ?? ""}`;
69
+ const skipped = skipUnlessToolRan("yamllint", {
70
+ result,
71
+ output: result.stdout,
72
+ });
73
+ if (skipped)
74
+ return skipped;
75
+ const diagnostics = parseYamllintParsable(raw, ctx.filePath);
59
76
  if (diagnostics.length === 0) {
60
77
  return { status: "succeeded", diagnostics: [], semantic: "none" };
61
78
  }
@@ -24,7 +24,9 @@ function parseZigOutput(raw, filePath) {
24
24
  line: Number.parseInt(lineStr, 10) || 1,
25
25
  column: Number.parseInt(colStr, 10) || 1,
26
26
  severity,
27
- semantic: severity === "error" ? "blocking" : "warning",
27
+ // `zig build-exe <file>` does not load build.zig module/import context.
28
+ // Its findings are useful evidence, but cannot prove a project blocker.
29
+ semantic: "warning",
28
30
  tool: "zig",
29
31
  rule: `zig-${level}`,
30
32
  fixable: false,
@@ -82,7 +84,7 @@ const zigCheckRunner = {
82
84
  return {
83
85
  status: hasErrors ? "failed" : "succeeded",
84
86
  diagnostics,
85
- semantic: hasErrors ? "blocking" : "warning",
87
+ semantic: "warning",
86
88
  };
87
89
  },
88
90
  };
@@ -143,15 +143,38 @@ export function resetEventLoopMonitor() {
143
143
  windowStartCpuMs = cpuTotalMs();
144
144
  }
145
145
  /**
146
- * Decide whether a freeze is worth persisting to `latency.log`. Pure so the
147
- * threshold logic is testable without the (vitest-flaky) native histogram.
148
- * Logs only a *new* worst block (`maxMs > lastLoggedMs + deltaMs`) above a
149
- * floor (`minMs`), so a turn that froze worse than ever before is recorded
150
- * once — not the same growing max every turn.
146
+ * Decide whether THIS block beats the session's running high-water. Pure so
147
+ * the threshold logic is testable without the (vitest-flaky) native
148
+ * histogram. Requires `maxMs > lastLoggedMs + deltaMs` above a floor
149
+ * (`minMs`) so noise near the current max doesn't keep re-triggering the
150
+ * high-water bookkeeping.
151
+ *
152
+ * NOTE (#1723): this is no longer the logging gate — see
153
+ * `shouldLogLoopBlock` for that. This function now answers a narrower
154
+ * question ("is this a new session worst?", used for the `worstSoFar`
155
+ * metadata flag and for deciding whether to advance the high-water), because
156
+ * gating the LOG on it hid every sub-maximum block after a session's first
157
+ * large one, which made loop_block-vs-pull-timeout correlation undecidable.
151
158
  */
152
159
  export function shouldLogWorstBlock(maxMs, lastLoggedMs, minMs = 60, deltaMs = 25) {
153
160
  return maxMs >= minMs && maxMs > lastLoggedMs + deltaMs;
154
161
  }
162
+ /**
163
+ * Decide whether a block is worth persisting to `latency.log` AT ALL (#1723).
164
+ * Every block at or above the floor (`minMs`) qualifies — not only a new
165
+ * session worst — because a session's later blocks can be smaller than an
166
+ * early spike yet still be exactly the ones that starved an LSP pull
167
+ * (#1549/#1713) and are otherwise invisible to the correlation.
168
+ *
169
+ * Volume is bounded by CALL CADENCE, not by this gate: the `turn_end` caller
170
+ * invokes this at most once per turn (the histogram window is reset every
171
+ * turn), so the natural cap is one `loop_block` record per turn — a jittery
172
+ * session cannot flood the log because there is nowhere for a second sample
173
+ * to come from within the same turn.
174
+ */
175
+ export function shouldLogLoopBlock(maxMs, minMs = 60) {
176
+ return maxMs >= minMs;
177
+ }
155
178
  /** Test-only: stop and clear the monitor so cases don't leak into each other. */
156
179
  export function _stopEventLoopMonitorForTest() {
157
180
  histogram?.disable();
@@ -55,6 +55,11 @@ export function createSubsystemLogger(subsystem, defaultLevel = "debug") {
55
55
  }
56
56
  /** No-op with the `SubsystemLogger` shape, for the verbose-off branch. */
57
57
  export function noopSubsystemLogger() {
58
+ // SAFETY: `SubsystemLogger` is a callable with `error`/`warn`/`debug`
59
+ // properties. TypeScript cannot type a function literal that gains its
60
+ // properties on the following lines, so the cast runs ahead of the three
61
+ // assignments that complete the shape. Every member of the interface is
62
+ // assigned before `noop` escapes this function.
58
63
  const noop = (() => { });
59
64
  noop.error = () => { };
60
65
  noop.warn = () => { };
@@ -175,6 +180,13 @@ export function runInConsoleCaptureWindow(fn) {
175
180
  return storage.run(true, fn);
176
181
  }
177
182
  function inCaptureWindow(fn) {
183
+ // SAFETY: the wrapper forwards `this` and every argument to `fn` unchanged
184
+ // and returns its result unchanged, so it is call-compatible with `T` at
185
+ // runtime. TypeScript cannot prove that for a generic `T` it did not
186
+ // construct, because a variadic `(...args: unknown[]) => unknown` is not
187
+ // assignable to an arbitrary function type. The invariant is the
188
+ // pass-through itself: change the body to alter arguments or the return
189
+ // value and this cast stops being true.
178
190
  return function (...args) {
179
191
  return runInConsoleCaptureWindow(() => fn.apply(this, args));
180
192
  };
@@ -313,7 +325,7 @@ export function withConsoleCaptureWindows(api) {
313
325
  // A host that returns `this` for chaining would hand back the raw API,
314
326
  // so a chained `on(...).on(...)` would register an unwrapped handler.
315
327
  // Keep the proxy on the chain.
316
- const keepProxy = (result) => result === target ? proxy : result;
328
+ const keepProxy = (result) => Object.is(result, target) ? proxy : result;
317
329
  // Pass-through members are cached too (S3a/S3b: `proxy.getFlag ===
318
330
  // proxy.getFlag`), but the cached wrapper re-reads `target[prop]` on
319
331
  // EVERY call rather than closing over `method` -- a plain
@@ -379,6 +391,11 @@ export function installConsoleGuard() {
379
391
  if (process.env.PI_LENS_CONSOLE_GUARD === "0")
380
392
  return false;
381
393
  consoleGuardInstalled = true;
394
+ // SAFETY: re-views `console` as a string-keyed record so the loop below can
395
+ // read and replace methods by name. `ConsoleMethod` is the union of keys
396
+ // that exist on `Console`, and each read is guarded by `typeof original ===
397
+ // "function"` before use, so a host whose console lacks a method is skipped
398
+ // rather than patched with undefined.
382
399
  const target = console;
383
400
  for (const method of CONSOLE_METHODS) {
384
401
  const original = target[method];
@@ -413,6 +430,10 @@ export function uninstallConsoleGuard() {
413
430
  if (!consoleGuardInstalled)
414
431
  return false;
415
432
  consoleGuardInstalled = false;
433
+ // SAFETY: same re-view as `installConsoleGuard`. Only keys this module
434
+ // recorded in `originalConsoleMethods` at install time are written back,
435
+ // and only when the current value is still the replacement this module
436
+ // installed, so a method someone else patched afterwards is left alone.
416
437
  const target = console;
417
438
  for (const [method, original] of originalConsoleMethods) {
418
439
  if (target[method] === installedConsoleMethods.get(method)) {
@@ -25,6 +25,7 @@ export const KIND_EXTENSIONS = {
25
25
  ".sass",
26
26
  ".scss",
27
27
  ],
28
+ cue: [".cue"],
28
29
  // From llvm-project/clang/lib/Driver/Types.cpp clang::driver::types::lookupTypeForExtension:
29
30
  cxx: [
30
31
  // C
@@ -260,8 +261,10 @@ for (const [kind, exts] of Object.entries(KIND_EXTENSIONS)) {
260
261
  }
261
262
  }
262
263
  }
263
- // Special filenames that indicate a file kind
264
- const SPECIAL_FILENAMES = [
264
+ // Special filenames that indicate a file kind. Exported so other seams that
265
+ // classify by basename (e.g. lsp/language.ts's language-id resolution) derive
266
+ // from this list instead of hand-keeping their own basename literals (#1594).
267
+ export const SPECIAL_FILENAMES = [
265
268
  { pattern: /^CMakeLists\.txt$/i, kind: "cmake" },
266
269
  { pattern: /^Makefile$/i, kind: "shell" },
267
270
  { pattern: /^Dockerfile(\.\w+)?$/i, kind: "docker" },
@@ -336,6 +339,7 @@ export const CODE_KINDS = new Set([
336
339
  "clojure",
337
340
  "cmake",
338
341
  "csharp",
342
+ "cue",
339
343
  "cxx",
340
344
  "dart",
341
345
  "docker",
@@ -434,6 +438,7 @@ export function getFileKindLabel(kind) {
434
438
  gleam: "Gleam",
435
439
  ocaml: "OCaml",
436
440
  clojure: "Clojure",
441
+ cue: "CUE",
437
442
  terraform: "Terraform",
438
443
  terragrunt: "Terragrunt",
439
444
  nix: "Nix",
@@ -504,6 +509,7 @@ export function getLanguageId(kind) {
504
509
  gleam: "gleam",
505
510
  ocaml: "ocaml",
506
511
  clojure: "clojure",
512
+ cue: "cue",
507
513
  terraform: "terraform",
508
514
  terragrunt: "terragrunt",
509
515
  nix: "nix",