@herbertgao/pi-extensions 2026.8.5 → 2026.8.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (389) hide show
  1. package/README.md +5 -5
  2. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +2 -2
  3. package/node_modules/@herbertgao/pi-cc-extensions/README.md +2 -2
  4. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +19 -7
  5. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +30 -9
  6. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +272 -22
  7. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +74 -5
  8. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +94 -77
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +48 -6
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/message-display.ts +1 -1
  11. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +14 -0
  12. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +55 -17
  13. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/layout.ts +41 -2
  14. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +75 -6
  15. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/types.ts +7 -3
  16. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +64 -1
  17. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  18. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +16 -0
  19. package/node_modules/@herbertgao/pi-subagents/README.md +30 -22
  20. package/node_modules/@herbertgao/pi-subagents/examples/agent-tool-description.md +5 -5
  21. package/node_modules/@herbertgao/pi-subagents/package.json +7 -7
  22. package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +7 -1
  23. package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +48 -19
  24. package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +22 -15
  25. package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +26 -2
  26. package/node_modules/@herbertgao/pi-subagents/src/index.ts +219 -40
  27. package/node_modules/@herbertgao/pi-subagents/src/invocation-config.ts +101 -3
  28. package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +18 -4
  29. package/node_modules/@herbertgao/pi-subagents/src/settings.ts +99 -0
  30. package/node_modules/@herbertgao/pi-subagents/src/types.ts +22 -3
  31. package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +51 -3
  32. package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +20 -2
  33. package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +34 -10
  34. package/node_modules/@herbertgao/pi-subagents/src/usage.ts +129 -1
  35. package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +29 -5
  36. package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +3 -0
  37. package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +46 -10
  38. package/node_modules/@juicesharp/rpiv-ask-user-question/config.ts +25 -0
  39. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/configuration.md +13 -4
  40. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +8 -1
  41. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/localization.md +3 -1
  42. package/node_modules/@juicesharp/rpiv-ask-user-question/locales/en.json +2 -2
  43. package/node_modules/@juicesharp/rpiv-ask-user-question/locales/zh.json +2 -2
  44. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +3 -2
  45. package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +10 -0
  46. package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +3 -1
  47. package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +30 -7
  48. package/node_modules/@juicesharp/rpiv-ask-user-question/state/state.ts +14 -6
  49. package/node_modules/@juicesharp/rpiv-ask-user-question/view/dialog-builder.ts +30 -4
  50. package/node_modules/@juicesharp/rpiv-ask-user-question/view/tab-content-strategy.ts +26 -5
  51. package/node_modules/@narumitw/pi-btw/README.md +119 -103
  52. package/node_modules/@narumitw/pi-btw/dist/index.ts +2898 -0
  53. package/node_modules/@narumitw/pi-btw/dist/index.ts.map +7 -0
  54. package/node_modules/@narumitw/pi-btw/package.json +13 -9
  55. package/node_modules/@narumitw/pi-btw/src/btw.ts +40 -42
  56. package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +55 -10
  57. package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +390 -0
  58. package/node_modules/@narumitw/pi-btw/src/menu.ts +78 -15
  59. package/node_modules/@narumitw/pi-btw/src/settings.ts +22 -2
  60. package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +136 -45
  61. package/node_modules/pi-lens/CHANGELOG.md +1004 -0
  62. package/node_modules/pi-lens/README.md +11 -3
  63. package/node_modules/pi-lens/config/ruff/core.toml +42 -0
  64. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +130 -27
  65. package/node_modules/pi-lens/dist/clients/advisory-provenance.js +427 -0
  66. package/node_modules/pi-lens/dist/clients/agent-nudge.js +79 -16
  67. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +9 -3
  68. package/node_modules/pi-lens/dist/clients/atomic-write.js +9 -3
  69. package/node_modules/pi-lens/dist/clients/bash-file-access.js +285 -8
  70. package/node_modules/pi-lens/dist/clients/biome-client.js +176 -37
  71. package/node_modules/pi-lens/dist/clients/blocker-freshness.js +428 -0
  72. package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +119 -0
  73. package/node_modules/pi-lens/dist/clients/bootstrap.js +12 -1
  74. package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +12 -3
  75. package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +192 -0
  76. package/node_modules/pi-lens/dist/clients/bus-events-logger.js +62 -6
  77. package/node_modules/pi-lens/dist/clients/bus-publish.js +11 -3
  78. package/node_modules/pi-lens/dist/clients/cascade-budget.js +196 -0
  79. package/node_modules/pi-lens/dist/clients/cascade-format.js +76 -2
  80. package/node_modules/pi-lens/dist/clients/cascade-types.js +9 -1
  81. package/node_modules/pi-lens/dist/clients/child-unref.js +54 -6
  82. package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +76 -24
  83. package/node_modules/pi-lens/dist/clients/console-guard-install.js +16 -4
  84. package/node_modules/pi-lens/dist/clients/dead-code-client.js +249 -52
  85. package/node_modules/pi-lens/dist/clients/deadline-utils.js +8 -1
  86. package/node_modules/pi-lens/dist/clients/debug-handles.js +5 -0
  87. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +62 -13
  88. package/node_modules/pi-lens/dist/clients/dependency-checker.js +43 -9
  89. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +153 -37
  90. package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +298 -0
  91. package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +10 -3
  92. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +165 -11
  93. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +325 -72
  94. package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +7 -4
  95. package/node_modules/pi-lens/dist/clients/dispatch/plan.js +5 -0
  96. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +234 -18
  97. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +187 -19
  98. package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +6 -3
  99. package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +11 -9
  100. package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +398 -0
  101. package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +11 -3
  102. package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +12 -7
  103. package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +18 -0
  104. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +895 -0
  105. package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +4 -0
  106. package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +16 -3
  107. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +81 -41
  108. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +16 -0
  109. package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +23 -0
  110. package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +331 -55
  111. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +38 -5
  112. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +97 -19
  113. package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +14 -0
  114. package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +20 -0
  115. package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +22 -0
  116. package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +10 -0
  117. package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +18 -6
  118. package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +73 -12
  119. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +488 -0
  120. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +84 -0
  121. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +260 -27
  122. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +943 -93
  123. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +86 -11
  124. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +72 -0
  125. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +106 -0
  126. package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +9 -0
  127. package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +18 -1
  128. package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +4 -2
  129. package/node_modules/pi-lens/dist/clients/disposition-publish.js +10 -3
  130. package/node_modules/pi-lens/dist/clients/eval-timestamp.js +17 -0
  131. package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +28 -5
  132. package/node_modules/pi-lens/dist/clients/extension-log.js +317 -3
  133. package/node_modules/pi-lens/dist/clients/file-kinds.js +8 -2
  134. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +294 -0
  135. package/node_modules/pi-lens/dist/clients/finding-identity.js +88 -0
  136. package/node_modules/pi-lens/dist/clients/fix-worklog.js +5 -1
  137. package/node_modules/pi-lens/dist/clients/format-events-publish.js +39 -8
  138. package/node_modules/pi-lens/dist/clients/formatters-lazy.js +3 -2
  139. package/node_modules/pi-lens/dist/clients/formatters.js +500 -115
  140. package/node_modules/pi-lens/dist/clients/generation-guard.js +216 -0
  141. package/node_modules/pi-lens/dist/clients/git-guard.js +49 -21
  142. package/node_modules/pi-lens/dist/clients/gitleaks-client.js +181 -8
  143. package/node_modules/pi-lens/dist/clients/go-client.js +21 -39
  144. package/node_modules/pi-lens/dist/clients/govulncheck-client.js +219 -10
  145. package/node_modules/pi-lens/dist/clients/grammar-source.js +333 -10
  146. package/node_modules/pi-lens/dist/clients/host-ports.js +9 -1
  147. package/node_modules/pi-lens/dist/clients/installer/index.js +1119 -101
  148. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh-session.js +58 -0
  149. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +715 -0
  150. package/node_modules/pi-lens/dist/clients/instance-reaper.js +643 -97
  151. package/node_modules/pi-lens/dist/clients/instance-registry.js +87 -17
  152. package/node_modules/pi-lens/dist/clients/jscpd-client.js +86 -15
  153. package/node_modules/pi-lens/dist/clients/knip-client.js +361 -24
  154. package/node_modules/pi-lens/dist/clients/language-policy.js +8 -2
  155. package/node_modules/pi-lens/dist/clients/language-profile.js +2 -0
  156. package/node_modules/pi-lens/dist/clients/latency-logger.js +487 -9
  157. package/node_modules/pi-lens/dist/clients/lazy-import.js +21 -0
  158. package/node_modules/pi-lens/dist/clients/ledger-bounds.js +21 -0
  159. package/node_modules/pi-lens/dist/clients/lens-events.js +56 -25
  160. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +16 -0
  161. package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +45 -2
  162. package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +30 -4
  163. package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +160 -20
  164. package/node_modules/pi-lens/dist/clients/lsp/client.js +1666 -148
  165. package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +111 -0
  166. package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +389 -0
  167. package/node_modules/pi-lens/dist/clients/lsp/index.js +2496 -171
  168. package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +215 -0
  169. package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +146 -14
  170. package/node_modules/pi-lens/dist/clients/lsp/language.js +48 -4
  171. package/node_modules/pi-lens/dist/clients/lsp/server.js +517 -69
  172. package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +22 -0
  173. package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +43 -0
  174. package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +172 -0
  175. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +21 -5
  176. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +61 -3
  177. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +422 -28
  178. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-session.js +30 -0
  179. package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +175 -0
  180. package/node_modules/pi-lens/dist/clients/lsp-lazy.js +3 -2
  181. package/node_modules/pi-lens/dist/clients/mcp/analyze.js +4 -0
  182. package/node_modules/pi-lens/dist/clients/mcp/session.js +39 -18
  183. package/node_modules/pi-lens/dist/clients/model-provider.js +53 -0
  184. package/node_modules/pi-lens/dist/clients/module-report.js +8 -0
  185. package/node_modules/pi-lens/dist/clients/opengrep-client.js +15 -1
  186. package/node_modules/pi-lens/dist/clients/package-manager.js +170 -14
  187. package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +27 -0
  188. package/node_modules/pi-lens/dist/clients/path-utils.js +160 -0
  189. package/node_modules/pi-lens/dist/clients/pipeline.js +178 -30
  190. package/node_modules/pi-lens/dist/clients/post-autofix-notice.js +37 -0
  191. package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +17 -3
  192. package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +89 -22
  193. package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +85 -15
  194. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +15 -3
  195. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +23 -2
  196. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +50 -2
  197. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +5 -0
  198. package/node_modules/pi-lens/dist/clients/project-lens-config.js +3 -0
  199. package/node_modules/pi-lens/dist/clients/project-snapshot.js +299 -0
  200. package/node_modules/pi-lens/dist/clients/quiet-window-config.js +47 -0
  201. package/node_modules/pi-lens/dist/clients/quiet-window.js +11 -25
  202. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +1 -1
  203. package/node_modules/pi-lens/dist/clients/read-guard.js +184 -10
  204. package/node_modules/pi-lens/dist/clients/resource-sampler.js +49 -17
  205. package/node_modules/pi-lens/dist/clients/reverse-deps.js +50 -11
  206. package/node_modules/pi-lens/dist/clients/review-graph/query.js +76 -4
  207. package/node_modules/pi-lens/dist/clients/run-duration.js +55 -0
  208. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +248 -13
  209. package/node_modules/pi-lens/dist/clients/runtime-context.js +112 -12
  210. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +472 -61
  211. package/node_modules/pi-lens/dist/clients/runtime-session.js +359 -13
  212. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +217 -22
  213. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +269 -22
  214. package/node_modules/pi-lens/dist/clients/runtime-turn.js +948 -87
  215. package/node_modules/pi-lens/dist/clients/rust-client.js +21 -37
  216. package/node_modules/pi-lens/dist/clients/safe-spawn.js +220 -7
  217. package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +161 -0
  218. package/node_modules/pi-lens/dist/clients/search-read-registration.js +34 -6
  219. package/node_modules/pi-lens/dist/clients/security-scan-client.js +224 -8
  220. package/node_modules/pi-lens/dist/clients/sg-runner.js +249 -37
  221. package/node_modules/pi-lens/dist/clients/single-flight.js +158 -0
  222. package/node_modules/pi-lens/dist/clients/smells-rollup.js +18 -11
  223. package/node_modules/pi-lens/dist/clients/stale-marker.js +17 -0
  224. package/node_modules/pi-lens/dist/clients/startup-timing.js +26 -2
  225. package/node_modules/pi-lens/dist/clients/test-runner-client.js +574 -32
  226. package/node_modules/pi-lens/dist/clients/tool-event.js +56 -5
  227. package/node_modules/pi-lens/dist/clients/tool-policy.js +127 -20
  228. package/node_modules/pi-lens/dist/clients/tool-set-policy.js +76 -0
  229. package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +75 -1
  230. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +769 -64
  231. package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +11 -0
  232. package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +90 -0
  233. package/node_modules/pi-lens/dist/clients/trivy-client.js +19 -1
  234. package/node_modules/pi-lens/dist/clients/warm-attach.js +17 -0
  235. package/node_modules/pi-lens/dist/clients/widget-state.js +336 -36
  236. package/node_modules/pi-lens/dist/clients/word-index.js +305 -33
  237. package/node_modules/pi-lens/dist/clients/zizmor-config.js +214 -14
  238. package/node_modules/pi-lens/dist/index.js +64677 -49484
  239. package/node_modules/pi-lens/dist/mcp/server.js +8 -2
  240. package/node_modules/pi-lens/dist/tools/activate-tools.js +17 -5
  241. package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +9 -4
  242. package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +5 -2
  243. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +469 -56
  244. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +190 -46
  245. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -7
  246. package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -1
  247. package/node_modules/pi-lens/docs/agent-guide.md +44 -14
  248. package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +518 -501
  249. package/node_modules/pi-lens/docs/dispositions.md +21 -0
  250. package/node_modules/pi-lens/docs/features.md +33 -6
  251. package/node_modules/pi-lens/docs/globalconfig.md +14 -0
  252. package/node_modules/pi-lens/docs/language-coverage.md +71 -5
  253. package/node_modules/pi-lens/docs/mcp.md +2 -2
  254. package/node_modules/pi-lens/docs/servercapabilities.md +4 -1
  255. package/node_modules/pi-lens/docs/settings.md +25 -1
  256. package/node_modules/pi-lens/docs/usage.md +24 -5
  257. package/node_modules/pi-lens/docs/word-index.md +35 -0
  258. package/node_modules/pi-lens/package.json +10 -6
  259. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-js-snapshot.yml +23 -0
  260. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-snapshot.yml +23 -0
  261. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/ts-void-zero-snapshot.yml +23 -0
  262. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-object-param-test.yml +16 -0
  263. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +22 -0
  264. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-compile-call-test.yml +29 -1
  265. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-js-test.yml +9 -0
  266. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-test.yml +9 -0
  267. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-dupe-class-members-test.yml +33 -0
  268. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-js-test.yml +7 -1
  269. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-test.yml +7 -1
  270. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-known-value-widening-test.yml +9 -0
  271. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-non-null-assertion-test.yml +216 -0
  272. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +9 -0
  273. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +9 -0
  274. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +9 -0
  275. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +9 -0
  276. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-return-value-in-generator-test.yml +12 -0
  277. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-runtime-typeof-test.yml +33 -0
  278. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-server-bind-wildcard-test.yml +9 -0
  279. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-shape-in-symbol-names-test.yml +13 -0
  280. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-js-test.yml +5 -1
  281. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-test.yml +5 -1
  282. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-laundering-test.yml +11 -0
  283. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-parameters-test.yml +12 -0
  284. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-returns-test.yml +16 -0
  285. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-any-test.yml +10 -0
  286. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-unknown-test.yml +8 -0
  287. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/redundant-unsafe-function-test.yml +35 -0
  288. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/require-safety-comment-for-as-unknown-as-test.yml +177 -0
  289. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/ts-void-zero-test.yml +1 -0
  290. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member-js.yml +13 -2
  291. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member.yml +13 -2
  292. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +2 -0
  293. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-object-param.yml +60 -0
  294. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +66 -0
  295. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-compile-call.yml +63 -5
  296. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread-js.yml +21 -0
  297. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread.yml +29 -0
  298. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-dupe-class-members.yml +52 -8
  299. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html-js.yml +27 -2
  300. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html.yml +27 -2
  301. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-known-value-widening.yml +71 -0
  302. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-non-null-assertion.yml +316 -0
  303. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +7 -0
  304. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +29 -0
  305. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +30 -0
  306. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +41 -0
  307. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +42 -0
  308. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-return-value-in-generator.yml +22 -5
  309. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-runtime-typeof.yml +121 -0
  310. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-server-bind-wildcard.yml +23 -7
  311. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-shape-in-symbol-names.yml +68 -0
  312. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code-js.yml +41 -2
  313. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code.yml +41 -2
  314. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +32 -0
  315. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-parameters.yml +67 -0
  316. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-returns.yml +106 -0
  317. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-any.yml +50 -0
  318. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-unknown.yml +56 -0
  319. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +2 -0
  320. package/node_modules/pi-lens/rules/ast-grep-rules/rules/redundant-unsafe-function.yml +32 -0
  321. package/node_modules/pi-lens/rules/ast-grep-rules/rules/require-safety-comment-for-as-unknown-as.yml +184 -0
  322. package/node_modules/pi-lens/rules/ast-grep-rules/rules/ts-void-zero.yml +5 -0
  323. package/node_modules/pi-lens/rules/ast-grep-rules/self-scan-baseline.json +5 -0
  324. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +132 -1
  325. package/node_modules/pi-lens/scripts/download-grammars.js +25 -0
  326. package/node_modules/pi-lens/scripts/grammars.lock.json +9 -0
  327. package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +12 -11
  328. package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +22 -22
  329. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +87 -116
  330. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +170 -0
  331. package/node_modules/pi-lens/skills/pi-lens-write-tree-sitter-rule/SKILL.md +3 -1
  332. package/node_modules/pi-lens/vendor/grammars/tree-sitter-cue.wasm +0 -0
  333. package/node_modules/pi-mcp-adapter/CHANGELOG.md +49 -0
  334. package/node_modules/pi-mcp-adapter/README.md +51 -6
  335. package/node_modules/pi-mcp-adapter/agent-dir.ts +12 -4
  336. package/node_modules/pi-mcp-adapter/cli.js +188 -5
  337. package/node_modules/pi-mcp-adapter/commands.ts +128 -22
  338. package/node_modules/pi-mcp-adapter/config.ts +28 -10
  339. package/node_modules/pi-mcp-adapter/direct-tools.ts +23 -19
  340. package/node_modules/pi-mcp-adapter/index.ts +219 -32
  341. package/node_modules/pi-mcp-adapter/init.ts +36 -4
  342. package/node_modules/pi-mcp-adapter/lifecycle.ts +315 -24
  343. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +39 -6
  344. package/node_modules/pi-mcp-adapter/mcp-bearer-store.ts +387 -0
  345. package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +27 -3
  346. package/node_modules/pi-mcp-adapter/mcp-code.ts +4 -0
  347. package/node_modules/pi-mcp-adapter/mcp-panel.ts +42 -13
  348. package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +2 -1
  349. package/node_modules/pi-mcp-adapter/metadata-cache.ts +46 -25
  350. package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +168 -0
  351. package/node_modules/pi-mcp-adapter/package.json +4 -1
  352. package/node_modules/pi-mcp-adapter/proxy-modes.ts +5 -4
  353. package/node_modules/pi-mcp-adapter/request-headers-command.ts +330 -0
  354. package/node_modules/pi-mcp-adapter/search-ranking.ts +92 -22
  355. package/node_modules/pi-mcp-adapter/server-manager.ts +145 -2
  356. package/node_modules/pi-mcp-adapter/session-recovery.ts +7 -0
  357. package/node_modules/pi-mcp-adapter/tool-approval.ts +15 -2
  358. package/node_modules/pi-mcp-adapter/tool-metadata.ts +38 -18
  359. package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +44 -4
  360. package/node_modules/pi-mcp-adapter/types.ts +95 -10
  361. package/node_modules/pi-mcp-adapter/ui-server.ts +18 -16
  362. package/node_modules/pi-mcp-adapter/utils.ts +70 -0
  363. package/node_modules/pi-web-access/CHANGELOG.md +37 -0
  364. package/node_modules/pi-web-access/README.md +38 -14
  365. package/node_modules/pi-web-access/anysearch.ts +4 -2
  366. package/node_modules/pi-web-access/auth-fetch.ts +148 -0
  367. package/node_modules/pi-web-access/brave.ts +16 -4
  368. package/node_modules/pi-web-access/chrome-cookies.ts +110 -23
  369. package/node_modules/pi-web-access/curator-page.ts +8 -3
  370. package/node_modules/pi-web-access/curator-server.ts +5 -1
  371. package/node_modules/pi-web-access/exa.ts +18 -7
  372. package/node_modules/pi-web-access/extract.ts +134 -37
  373. package/node_modules/pi-web-access/fetch-params.ts +17 -3
  374. package/node_modules/pi-web-access/firecrawl.ts +172 -12
  375. package/node_modules/pi-web-access/gemini-search.ts +33 -7
  376. package/node_modules/pi-web-access/index.ts +160 -104
  377. package/node_modules/pi-web-access/package.json +2 -2
  378. package/node_modules/pi-web-access/page-query.ts +4 -2
  379. package/node_modules/pi-web-access/parallel-mcp.ts +249 -0
  380. package/node_modules/pi-web-access/parallel.ts +2 -2
  381. package/node_modules/pi-web-access/query-rewrite.ts +51 -0
  382. package/node_modules/pi-web-access/serper.ts +211 -0
  383. package/node_modules/pi-web-access/summary-model-scope.ts +12 -4
  384. package/node_modules/pi-web-access/summary-review.ts +51 -23
  385. package/node_modules/pi-web-access/tavily.ts +16 -4
  386. package/node_modules/pi-web-access/utils.ts +87 -0
  387. package/node_modules/pi-web-access/valyu.ts +199 -0
  388. package/node_modules/pi-web-access/youtube-extract.ts +2 -2
  389. package/package.json +13 -13
@@ -13,7 +13,7 @@ Same `id` as a built-in overrides it. Multiple rules per file: separate with `--
13
13
  ```yaml
14
14
  id: no-foo-bar
15
15
  language: TypeScript # PascalCase — see languages below
16
- severity: warning # error | warning | info
16
+ severity: warning # error | warning | hint | info — pick by evidence, see below
17
17
  message: "Avoid foo.bar() — use baz() instead"
18
18
  note: |
19
19
  Longer explanation / fix guidance here.
@@ -21,6 +21,39 @@ rule:
21
21
  pattern: foo.bar($ARG)
22
22
  ```
23
23
 
24
+ **Pick the severity by the evidence behind the rule, not by feel:**
25
+
26
+ - **`error`** — only with a documented zero-false-positive audit in the `note`.
27
+ Only `error` maps to semantic `blocking` and stops a turn.
28
+ - **`warning`** — a real finding with a known, bounded false-positive rate.
29
+ - **`hint` / `info`** — style opinions. They render as advisory text, never
30
+ block, and lose the report budget to warnings when a report is capped.
31
+
32
+ Full policy and the `error`-promotion procedure: AGENTS.md's "Severity policy
33
+ (#1777)" section. Read it before shipping anything above `warning`.
34
+
35
+ ## Before promoting to error
36
+
37
+ Three things must all be true, and the rule's `note` must record them:
38
+
39
+ 1. **A multi-corpus false-positive census**, not a single-tree count. Run the
40
+ rule over pi-lens's `clients/`/`tests/` plus at least one real external
41
+ codebase of the kind the rule targets, classify every hit, and put the
42
+ table in the note.
43
+ 2. **Structural narrowing before exemption.** Suppress a legitimate idiom
44
+ with a relational constraint (`inside`/`has`/`follows`, scoped path
45
+ globs), not with prose telling readers to ignore the hit. Narrow first —
46
+ don't reach for a lower tier as the easy way out. `no-non-null-assertion`
47
+ was demoted to `hint` (`0124608a`), then reverted back to `warning` once
48
+ the same false positives were closed with a structural exclusion instead
49
+ (`b3e1fd79`).
50
+ 3. **Self-scan wiring.** Tag the rule `metadata.category: pi-lens-self-scan`
51
+ so `npm run astgrep:self-scan` holds this tree at zero in CI. An `error`
52
+ rule that never runs against pi-lens's own source is an unaudited claim.
53
+
54
+ If the post-narrowing residual is still tens of legitimate hits, stop and
55
+ report the numbers instead of shipping at `error`.
56
+
24
57
  ## Language values
25
58
 
26
59
  `TypeScript` `JavaScript` `Python` `Go` `Rust` `Java` `C` `Cpp` `CSharp` `Kotlin` `Ruby` `Php`
@@ -67,7 +100,14 @@ constraints: # metavariable regex constraints work
67
100
 
68
101
  ⚠ **`has`/`inside` default to the immediate child/parent (`stopBy: neighbor`).** For a
69
102
  recursive descendant/ancestor search add `stopBy: end`. This is the #1 migration
70
- gotcha — see the `has` note below.
103
+ gotcha — see the `has` note in `reference.md`.
104
+
105
+ ⚠ **`stopBy: end` alone is not a boundary.** It's a search-depth control — how far
106
+ the walk searches — not a stop condition; the `any:` kind list only decides what
107
+ CAN satisfy the match, not where the walk halts. To scope a relation to the
108
+ nearest enclosing function (or any other boundary), give `stopBy` its own rule.
109
+ See "Scoping to the nearest enclosing X" in `reference.md` (#1794 F1 — this bug
110
+ shipped twice in one window).
71
111
 
72
112
  ## YAML quoting — REQUIRED (js-yaml will reject the rule otherwise)
73
113
 
@@ -100,123 +140,54 @@ The parser is a real YAML parser, so unquoted special chars throw and the rule i
100
140
  ✅ Docs: docs/custom-rules.md
101
141
  ```
102
142
 
103
- ## Hard-won gotchas (NAPI runner specifics — verified)
104
-
105
- ```
106
- ⚠ `has`/`inside` default to DIRECT child/parent — add `stopBy: end` for a recursive search.
107
- This cuts BOTH ways, so think about where the target node actually lives:
108
- - Target is a grandchild+ → you MUST add `stopBy: end` or the `has` never matches.
109
- `switch-without-default` = `switch_statement` not has `switch_default`: the default
110
- lives under `switch_body`, so without `stopBy: end` it matches nothing and every
111
- switch (even ones WITH a default) is flagged. Same for `nested-ternary` catching a
112
- parenthesized `a ? (b ? c : d) : e`.
113
- - Target is the direct child → leave it at `neighbor` (default). Adding `stopBy: end`
114
- OVER-reports: `throw_statement` has `string` + `stopBy: end` flags `throw new
115
- Error("x")` (the string is nested), and `expression_statement` has `new_expression`
116
- + `stopBy: end` flags `fn(new Error())` as a discarded error. Keep these direct.
117
- napi's `has` never matches the node itself, so a self-referential `kind: X` has
118
- `kind: X` (with `stopBy: end`) correctly flags only genuinely-nested X.
119
-
120
- ✅ Prefer `regex` on the matched node's OWN text over `has` when you only need to
121
- inspect the node — avoids recursive-descendant false positives:
122
- kind: export_statement
123
- regex: '^export\s+(let|var)\b' # precise; no has-recursion FP
124
- (NAPI evaluates `regex` with JS RegExp on node.text() — keep it LINEAR so the
125
- detector can't itself ReDoS.)
126
-
127
- ⚠ String-literal regexes match SOURCE text, not the runtime string value.
128
- Inspect the exact node text before writing constraints:
129
- ast-grep run --kind string --lang ts sample.ts --json=compact
130
- Example: source `"\\|"` is node text `"\\\\|"` in JSON; to match a
131
- source-level escaped backslash (`\\`) followed by a non-backslash, the rule
132
- regex needs FOUR regex backslashes, preferably in a YAML block scalar:
133
- regex: >-
134
- ^["'`]\\\\[^\\A-Za-z0-9$]
135
- This is how `incomplete-string-escaping` catches both `"\\|"` and
136
- `'\\"'`. Avoid shell here-doc probes for this class — shell/JSON escaping
137
- can silently eat a backslash and make the rule look broken.
138
-
139
- ⚠ `-js` twins: remember there are TWO execution surfaces.
140
- - ast-grep CLI/LSP language-gates by `language:`. A `language: TypeScript`
141
- rule is not enough for standalone `.js` coverage, so shipped user-facing
142
- TS/JS rules that should fire under the ast-grep LSP usually need a `-js`
143
- twin with `language: JavaScript` plus its own fixture.
144
- - the in-process NAPI fallback (`ast-grep-napi.ts`) parses the target file's
145
- own grammar and currently runs both TS and JS rules on every jsts file. A
146
- grammar-agnostic twin can therefore duplicate in fallback mode.
147
- - **Decide explicitly:** if the rule must cover `.js` through the ast-grep
148
- CLI/LSP baseline, ship the twin and test both. If a rule is NAPI-only or
149
- fallback duplication is unacceptable, fix runner dedup/normalization before
150
- relying on a single TypeScript rule for JS coverage.
151
- - **Grammar-divergent bodies** still need separate variants regardless:
152
- e.g. `no-flag-argument` uses `required_parameter` in TS and
153
- `assignment_pattern` in JS.
154
-
155
- ✅ Node-kind facts (tree-sitter-typescript grammar — NOT the TS compiler / Roslyn):
156
- - let / const → `lexical_declaration` (var is NOT here)
157
- - var → `variable_declaration`
158
- - a regex literal's pattern text → `regex_pattern`
159
- - x[i] index access → `subscript_expression` (NOT element_access_expression)
160
- - obj.prop access → `member_expression` (NOT property_access_expression)
161
- - !x / -x / typeof x → `unary_expression`
162
- - a ? b : c → `ternary_expression`
163
-
164
- ❌ Wrong-grammar kind names = silent dead rule. `element_access_expression`,
165
- `property_access_expression`, `binary_operator`, etc. are TS-compiler/Roslyn names, not
166
- tree-sitter's. napi REJECTS the whole rule ("invalid kind matcher") so it never runs.
167
- Verify a kind exists before shipping:
168
- node -e 'import("@ast-grep/napi").then(s=>{const r=s.ts.parse("x[i]").root();
169
- const f=(n,k)=>{let c=n.kind()===k?1:0;for(const x of n.children())c+=f(x,k);return c};
170
- console.log(f(r,"subscript_expression"))})' # >0 means the kind is real
171
-
172
- ✅ Test through the REAL runner from the repo root — it loads the actual shipped
173
- rules from rules/ast-grep-rules/rules. Assert on diagnostic `rule` ids:
174
- const res = await runner.run(ctx); // ctx.filePath = temp .ts, cwd = repo
175
- For pattern/kind/regex-only rules (CLI-identical semantics) `ast-grep scan` is fine.
176
-
177
- ✅ Before shipping any text/regex detector, FP-scan the codebase:
178
- ast-grep scan -r <rule>.yml clients tools
179
- Real safe variants bite (e.g. ReDoS: (ba+)+ is safe — a mandatory prefix makes
180
- the partition unique; flag only a single quantified atom inside the group).
181
- ```
182
-
183
- ## Matching things a pattern can't express (#305)
184
-
185
- ```
186
- ❌ A parameter default is NOT a `$X = false` pattern. `pattern: $FLAG = false` parses as
187
- an `assignment_expression` (statement context) and never matches a function parameter.
188
- Match the PARAM NODE + its child literal instead, capturing the name for reuse:
189
- # TS grammar
190
- - kind: required_parameter
191
- all:
192
- - has: { field: pattern, pattern: $FLAG }
193
- - has: { any: [ { kind: "true" }, { kind: "false" } ] }
194
- # JS grammar (assignment_pattern, with fields left/right)
195
- - kind: assignment_pattern
196
- all:
197
- - has: { field: left, pattern: $FLAG }
198
- - has: { field: right, any: [ { kind: "true" }, { kind: "false" } ] }
199
-
200
- ✅ Metavar consistency works ACROSS sibling clauses of an `all` — a metavar bound in one
201
- `has` must match the SAME text everywhere it reappears. Use it to CORRELATE nodes, which
202
- is what makes a structural rule precise:
203
- all:
204
- - has: { stopBy: end, kind: required_parameter, has: { field: pattern, pattern: $FLAG } }
205
- - has: { stopBy: end, any: [ { pattern: "if ($FLAG) $$$" }, { pattern: "if (!$FLAG) $$$" } ] }
206
- This fires ONLY when the function branches on the SAME param it declared boolean — a
207
- boolean default that's never branched on, or a branch on a different var, won't match.
208
-
209
- ❌ Two `has:` keys in one mapping silently OVERWRITE (YAML: last key wins). For multiple
210
- descendant constraints use `all:` with a LIST of `has` entries, never repeated `has:`.
211
-
212
- ✅ Prefer a high-precision structural guard over an unbounded denylist. Message-chain
213
- (Demeter) floods on fluent/promise/builder chains; rather than denylist every fluent
214
- method name, REQUIRE the chain's first calls to be accessors (`get*`/`is*`/`has*`) via
215
- `constraints` regex — promise/fluent/builder methods aren't accessor-named, so they're
216
- excluded by construction. Precision over recall.
143
+ ## Reference doc — read before writing a NAPI-runner-specific or hard-to-express rule
144
+
145
+ `reference.md` (same directory) covers: ReDoS-safe regex authoring, node-text
146
+ string-escape quirks, `has`/`inside` `stopBy` defaults (and when to override
147
+ them), scoping a relation to the nearest enclosing node with a `stopBy`
148
+ boundary rule, the `-js` twin dedup behavior (#657), boolean-parameter
149
+ matching across the TS/JS grammars, and precision-over-recall heuristics for
150
+ denylist-shaped rules. Read it when a rule isn't matching (or over-matching)
151
+ the way you expect, or before shipping a `regex`/`has`-heavy rule.
152
+
153
+ ## Testing a suppression
154
+
155
+ Every relational suppression (a `has`/`inside`/`not` exclusion for a
156
+ legitimate idiom) needs two fixtures per bound metavariable, not one:
157
+
158
+ 1. **A same-binding valid case** — the idiom the exclusion is meant to
159
+ suppress, with the metavariable bound consistently (same receiver, same
160
+ key).
161
+ 2. **A mutation-guard invalid case** — the same shape with the binding
162
+ broken: a different key, a different receiver, or a boundary-crossing
163
+ lookalike (the guard lives in the wrong scope). This proves the
164
+ exclusion checks the BINDING, not just the pattern's presence somewhere
165
+ in the file.
166
+
167
+ `rules/ast-grep-rules/rule-tests/no-non-null-assertion-test.yml` is the model: alongside the
168
+ get-after-has/pop-after-length valid cases, it fixtures a different-key
169
+ guard, a different-map guard, and an outer-function guard that must NOT
170
+ suppress an inner closure — each one red if the corresponding binding check
171
+ is deleted.
172
+
173
+ Corpus silence is not evidence. A valve with zero corpus hits needs
174
+ adversarial fixtures MORE, not less — `redundant-unsafe-function` targets
175
+ Rust, so it has no pi-lens corpus to census against, and its `# Safety`
176
+ valve still shipped an unbounded backward scan that over-suppressed real
177
+ detections, caught only by adversarial fixtures in review (`00284bcc`). A
178
+ documented blind spot (an idiom the rule knowingly can't distinguish from a
179
+ bug) becomes an `invalid`-direction fixture with a comment naming the gap,
180
+ never silence.
181
+
182
+ Regenerate the catalog doc with `npm run docs:rule-catalogs` after adding or
183
+ changing a rule — never hand-edit the generated catalog.
217
184
 
218
185
  ## Validating a candidate rule against the REAL engine (not the warm MCP cache)
219
186
 
187
+ Live-binary discipline (AGENTS.md shape 16) applies here too: verify parsing
188
+ and match behavior against a real `ast-grep` run before you write it into a
189
+ rule note or a test fixture — a hand-written fixture pins a guess, not a fact.
190
+
220
191
  ```
221
192
 
222
193
  # inspect how a PATTERN parses → find the node kind you actually need
@@ -0,0 +1,170 @@
1
+ # pi-lens ast-grep Rule Reference
2
+
3
+ Deep-dive companion to `SKILL.md`. Read this when you're debugging a rule
4
+ that isn't matching (or over-matching) the way you expect: ReDoS-safe regex
5
+ authoring, string-escape quirks in node text, `has`/`inside` `stopBy`
6
+ defaults and when to override them, boolean-parameter matching across two
7
+ grammars, and precision-over-recall heuristics for denylist-shaped rules.
8
+
9
+ ## Hard-won gotchas (NAPI runner specifics — verified)
10
+
11
+ ```
12
+ ⚠ `has`/`inside` default to DIRECT child/parent — add `stopBy: end` for a recursive search.
13
+ This cuts BOTH ways, so think about where the target node actually lives:
14
+ - Target is a grandchild+ → you MUST add `stopBy: end` or the `has` never matches.
15
+ `switch-without-default` = `switch_statement` not has `switch_default`: the default
16
+ lives under `switch_body`, so without `stopBy: end` it matches nothing and every
17
+ switch (even ones WITH a default) is flagged. Same for `nested-ternary` catching a
18
+ parenthesized `a ? (b ? c : d) : e`.
19
+ - Target is the direct child → leave it at `neighbor` (default). Adding `stopBy: end`
20
+ OVER-reports: `throw_statement` has `string` + `stopBy: end` flags `throw new
21
+ Error("x")` (the string is nested), and `expression_statement` has `new_expression`
22
+ + `stopBy: end` flags `fn(new Error())` as a discarded error. Keep these direct.
23
+ napi's `has` never matches the node itself, so a self-referential `kind: X` has
24
+ `kind: X` (with `stopBy: end`) correctly flags only genuinely-nested X.
25
+
26
+ ✅ Prefer `regex` on the matched node's OWN text over `has` when you only need to
27
+ inspect the node — avoids recursive-descendant false positives:
28
+ kind: export_statement
29
+ regex: '^export\s+(let|var)\b' # precise; no has-recursion FP
30
+ (NAPI evaluates `regex` with JS RegExp on node.text() — keep it LINEAR so the
31
+ detector can't itself ReDoS.)
32
+
33
+ ⚠ String-literal regexes match SOURCE text, not the runtime string value.
34
+ Inspect the exact node text before writing constraints:
35
+ ast-grep run --kind string --lang ts sample.ts --json=compact
36
+ Example: source `"\\|"` is node text `"\\\\|"` in JSON; to match a
37
+ source-level escaped backslash (`\\`) followed by a non-backslash, the rule
38
+ regex needs FOUR regex backslashes, preferably in a YAML block scalar:
39
+ regex: >-
40
+ ^["'`]\\\\[^\\A-Za-z0-9$]
41
+ This is how `incomplete-string-escaping` catches both `"\\|"` and
42
+ `'\\"'`. Avoid shell here-doc probes for this class — shell/JSON escaping
43
+ can silently eat a backslash and make the rule look broken.
44
+
45
+ ⚠ `-js` twins: remember there are TWO execution surfaces.
46
+ <!-- verified: clients/dispatch/runners/ast-grep-napi.ts:205-216,450-455, c170d94b -->
47
+ - ast-grep CLI/LSP language-gates by `language:`. A `language: TypeScript`
48
+ rule is not enough for standalone `.js` coverage, so shipped user-facing
49
+ TS/JS rules that should fire under the ast-grep LSP usually need a `-js`
50
+ twin with `language: JavaScript` plus its own fixture.
51
+ - the in-process NAPI fallback (`ast-grep-napi.ts` — pi-lens source checkout
52
+ only, not present in the installed package) already DEDUPES by grammar
53
+ (#657): `ruleLanguageForFile` (`ast-grep-napi.ts:205-216`) maps each file
54
+ extension to its actual grammar, and the matcher (`:450-455`) skips any
55
+ `language:`-tagged rule whose tag doesn't match that grammar. A TS rule
56
+ and its JS twin no longer double-fire on the same file in fallback mode.
57
+ - **`-js` twins are needed only when the rule body itself is
58
+ grammar-divergent** (different node kinds/fields between the TS and JS
59
+ grammars). A grammar-agnostic body doesn't need a twin for fallback
60
+ coverage — the dedup above already scopes it correctly; ship a twin only
61
+ when standalone `.js` coverage through the ast-grep CLI/LSP baseline is
62
+ required (see the first bullet).
63
+ - **Grammar-divergent bodies** still need separate variants regardless:
64
+ e.g. `no-flag-argument` uses `required_parameter` in TS and
65
+ `assignment_pattern` in JS.
66
+
67
+ ✅ Node-kind facts (tree-sitter-typescript grammar — NOT the TS compiler / Roslyn):
68
+ - let / const → `lexical_declaration` (var is NOT here)
69
+ - var → `variable_declaration`
70
+ - a regex literal's pattern text → `regex_pattern`
71
+ - x[i] index access → `subscript_expression` (NOT element_access_expression)
72
+ - obj.prop access → `member_expression` (NOT property_access_expression)
73
+ - !x / -x / typeof x → `unary_expression`
74
+ - a ? b : c → `ternary_expression`
75
+
76
+ ❌ Wrong-grammar kind names = silent dead rule. `element_access_expression`,
77
+ `property_access_expression`, `binary_operator`, etc. are TS-compiler/Roslyn names, not
78
+ tree-sitter's. napi REJECTS the whole rule ("invalid kind matcher") so it never runs.
79
+ Verify a kind exists before shipping:
80
+ node -e 'import("@ast-grep/napi").then(s=>{const r=s.ts.parse("x[i]").root();
81
+ const f=(n,k)=>{let c=n.kind()===k?1:0;for(const x of n.children())c+=f(x,k);return c};
82
+ console.log(f(r,"subscript_expression"))})' # >0 means the kind is real
83
+
84
+ ✅ Test through the REAL runner from the pi-lens source checkout's repo root — it loads the actual shipped
85
+ rules from rules/ast-grep-rules/rules. Assert on diagnostic `rule` ids:
86
+ const res = await runner.run(ctx); // ctx.filePath = temp .ts, cwd = repo (pi-lens source checkout only — not present in the installed package)
87
+ For pattern/kind/regex-only rules (CLI-identical semantics) `ast-grep scan` is fine.
88
+
89
+ ✅ Before shipping any text/regex detector, FP-scan the codebase:
90
+ ast-grep scan -r <rule>.yml clients tools
91
+ Real safe variants bite (e.g. ReDoS: (ba+)+ is safe — a mandatory prefix makes
92
+ the partition unique; flag only a single quantified atom inside the group).
93
+ ```
94
+
95
+ ## Scoping to the nearest enclosing X (#1794 F1)
96
+
97
+ `stopBy` controls how far the ancestor/descendant walk searches. It is not a
98
+ stop CONDITION. An `any:` kind list inside `inside`/`has` decides which
99
+ nodes the walk is ALLOWED to match — it does not tell the walk where to
100
+ halt. `stopBy: end` alone searches every ancestor up to the file root, so a
101
+ guard several scopes out can suppress a finding inside an unrelated closure.
102
+
103
+ To scope a relation to the nearest enclosing function (or any other
104
+ boundary), give `stopBy` its OWN rule — the same kind list used as the
105
+ match target — so the walk stops at the first satisfying ancestor and can
106
+ never escalate past it:
107
+
108
+ ```yaml
109
+ inside:
110
+ stopBy: # the BOUNDARY: halts the walk here
111
+ any:
112
+ - kind: function_declaration
113
+ - kind: method_definition
114
+ - kind: arrow_function
115
+ - kind: function_expression
116
+ any: # the MATCH TARGET: same list, different job
117
+ - kind: function_declaration
118
+ - kind: method_definition
119
+ - kind: arrow_function
120
+ - kind: function_expression
121
+ has:
122
+ stopBy: end
123
+ pattern: $M.has($K)
124
+ ```
125
+
126
+ This is the fix for #1794 F1: an earlier `no-non-null-assertion` exclusion
127
+ used `stopBy: end` with only the `any:` kind list as the match target, so a
128
+ `.has()`/`.length` guard in an OUTER function suppressed a closure's `!`
129
+ several scopes in. The same defect shape — `stopBy: end` mistaken for a
130
+ boundary — shipped twice in the same 2026-08-20 window: once here, and once
131
+ in `redundant-unsafe-function`'s `# Safety` valve (an unbounded backward
132
+ comment scan, fixed in `00284bcc`). See
133
+ `rules/ast-grep-rules/rules/no-non-null-assertion.yml` for the full working
134
+ rule.
135
+
136
+ ## Matching things a pattern can't express (#305)
137
+
138
+ ```
139
+ ❌ A parameter default is NOT a `$X = false` pattern. `pattern: $FLAG = false` parses as
140
+ an `assignment_expression` (statement context) and never matches a function parameter.
141
+ Match the PARAM NODE + its child literal instead, capturing the name for reuse:
142
+ # TS grammar
143
+ - kind: required_parameter
144
+ all:
145
+ - has: { field: pattern, pattern: $FLAG }
146
+ - has: { any: [ { kind: "true" }, { kind: "false" } ] }
147
+ # JS grammar (assignment_pattern, with fields left/right)
148
+ - kind: assignment_pattern
149
+ all:
150
+ - has: { field: left, pattern: $FLAG }
151
+ - has: { field: right, any: [ { kind: "true" }, { kind: "false" } ] }
152
+
153
+ ✅ Metavar consistency works ACROSS sibling clauses of an `all` — a metavar bound in one
154
+ `has` must match the SAME text everywhere it reappears. Use it to CORRELATE nodes, which
155
+ is what makes a structural rule precise:
156
+ all:
157
+ - has: { stopBy: end, kind: required_parameter, has: { field: pattern, pattern: $FLAG } }
158
+ - has: { stopBy: end, any: [ { pattern: "if ($FLAG) $$$" }, { pattern: "if (!$FLAG) $$$" } ] }
159
+ This fires ONLY when the function branches on the SAME param it declared boolean — a
160
+ boolean default that's never branched on, or a branch on a different var, won't match.
161
+
162
+ ❌ Two `has:` keys in one mapping silently OVERWRITE (YAML: last key wins). For multiple
163
+ descendant constraints use `all:` with a LIST of `has` entries, never repeated `has:`.
164
+
165
+ ✅ Prefer a high-precision structural guard over an unbounded denylist. Message-chain
166
+ (Demeter) floods on fluent/promise/builder chains; rather than denylist every fluent
167
+ method name, REQUIRE the chain's first calls to be accessors (`get*`/`is*`/`has*`) via
168
+ `constraints` regex — promise/fluent/builder methods aren't accessor-named, so they're
169
+ excluded by construction. Precision over recall.
170
+ ```
@@ -6,7 +6,7 @@ description: Use when writing a new pi-lens tree-sitter query rule YAML file —
6
6
  # Writing a pi-lens tree-sitter Rule
7
7
 
8
8
  Drop path: `rules/tree-sitter-queries/<language>/<id>.yml`
9
- Language dir is **lowercase**: `typescript` `javascript` `tsx` `python` `go` `rust` `java` `csharp` `kotlin` `ruby` `cpp` `c` `css`
9
+ Language dir is **lowercase**: `typescript` `javascript` `tsx` `python` `go` `rust` `java` `csharp` `kotlin` `php` `ruby` `cpp` `c` `css`
10
10
 
11
11
  Project rules merge with built-ins (both run). To disable a language's built-ins: rename dir to `<lang>-disabled/`.
12
12
 
@@ -115,6 +115,8 @@ predicates:
115
115
  treeSitterRunner.run() via makeRealRunnerCtx (tests/support/real-runner-ctx.ts) —
116
116
  runQueryOnFile bypasses dispatch (skip_test_files, tiers, delta, rule cache).
117
117
  Template: tests/clients/dispatch/runners/tree-sitter-skip-test-files.test.ts.
118
+ (These test paths exist only in a pi-lens source checkout — the installed
119
+ npm package ships no tests/ directory.)
118
120
 
119
121
  ✅ JS files also run typescript/ rules (shared grammar) — one rule in
120
122
  rules/tree-sitter-queries/typescript/ covers BOTH .ts and .js. No -js copy needed.
@@ -7,6 +7,55 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.27.0] - 2026-08-20
11
+
12
+ ### Highlights
13
+ - MCP servers can now come from packages, runtime extension APIs, or the usual config files.
14
+ - Static bearer tokens can use the OS credential store, with a stdin-only CLI for safer token management.
15
+ - Long-lived sessions recover better when remote MCP servers are slow, refreshed, or reconnected.
16
+ - OAuth flows clean up their callback listener when idle and work better inside nested terminal UI prompts.
17
+ - Search, metadata cache writes, direct-tool counts, and UI stream pruning now do less repeated work.
18
+
19
+ ### Added
20
+ - `/pi-mcp` now works as an alias for `/mcp` when a host reserves `/mcp`. Thanks to [@inxeoz](https://github.com/inxeoz) for #391.
21
+ - `registerMcpServer({ pi, name, definition })` lets other extensions register and dispose session-scoped MCP servers at runtime. Registrations are proxy-tool-only, never persisted, and duplicate names fail closed. Thanks to [@bendavis78](https://github.com/bendavis78) and [@fmoda3](https://github.com/fmoda3) for the runtime API request in #376/#382.
22
+ - Pi packages can ship prefixed MCP server definitions with `pi.mcp` manifest entries, without asking users to edit MCP config files. Thanks to [@bendavis78](https://github.com/bendavis78) for #376 and [@fmoda3](https://github.com/fmoda3) for the manifest design.
23
+ - Static bearer tokens can opt into OS credential-store lookup with URL-bound records by setting `bearerTokenStore: true`. The new `pi-mcp-adapter token set|status|remove <server>` CLI reads tokens from stdin and never accepts a token as an argument. Thanks to [@AlexanderBartash](https://github.com/AlexanderBartash) for issue #366.
24
+
25
+ ### Changed
26
+ - Search ranking now reuses normalized MCP tool fields and keyword tokens per catalog.
27
+ - Per-request header commands collect process cleanup data in one snapshot per pass, reducing cold HTTP connect overhead.
28
+ - Metadata cache saves write compact JSON while preserving atomic replacement and cross-process merges.
29
+ - High-frequency UI stream event-log pruning tracks the latest checkpoint event ID instead of rescanning retained patches.
30
+ - The MCP panel reuses direct-tool counts and token totals across renders while keeping toggle and reconnect updates immediate.
31
+
32
+ ### Fixed
33
+ - Short-lived `mcpScript` workers no longer emit false unmanaged file-descriptor warnings on Node 24. Thanks to [@blalor](https://github.com/blalor) for PR #407.
34
+ - OAuth callback listeners are released after idle auth flows, and MCP pickers stay hidden while nested OAuth input is active. Thanks to [@trevorleibert-mixpanel](https://github.com/trevorleibert-mixpanel) for PRs #403 and #404.
35
+ - Request-header command cleanup can scan large process lists without overflowing `spawnSync`'s 1 MiB default buffer, which previously caused spurious `HTTP request headers command cleanup failed: ps exited with code unknown` refresh failures on busy hosts. Thanks to [@rtfpessoa](https://github.com/rtfpessoa) for PR #399.
36
+ - Slow but healthy remote keep-alive servers are no longer marked failed when a bounded tools/list refresh times out. Thanks to [@brightmeowso](https://github.com/brightmeowso) for #400.
37
+ - Cached metadata reconstruction now reuses one selector candidate index, avoiding repeated scans of large cached catalogs at startup.
38
+ - MCP status consumers no longer see a connected catalog before Pi's model-facing tool surface is current. The first connected status snapshot now waits for direct-tool synchronization. Thanks to [@dmorn](https://github.com/dmorn) for PR #380.
39
+ - JSON-string MCP tool-call arguments are normalized before approval and transport, preserving all fields and embedded quotes. Thanks to [@sebbean](https://github.com/sebbean) for PR #377.
40
+ - Session tool approvals are scoped to the approved argument payload instead of every later call to the same tool. Thanks to [@spaceshipmike](https://github.com/spaceshipmike) for #367.
41
+ - MCP panel commands no longer hang in RPC, JSON, and print modes when terminal-only custom UI is unavailable. Thanks to [@shixin-guo](https://github.com/shixin-guo) for PR #365.
42
+ - Compact MCP rows now show a bounded tool-input preview and skip leading blank output lines in collapsed result previews.
43
+ - MCP gateway requests nested inside proxy `args` are recovered instead of silently showing status, and invalid nested gateway requests now fail with guidance. Thanks to [@ibrmora](https://github.com/ibrmora) for #363.
44
+ - Remote keep-alive tool catalogs refresh before user input, adapter-triggered turns, and health checks. Expired Streamable HTTP sessions reconnect so long-lived Pi sessions can discover replacement catalogs without restarting. Thanks to [@dmorn](https://github.com/dmorn) for #369 and PR #370.
45
+
46
+ ## [2.26.0] - 2026-08-14
47
+
48
+ ### Added
49
+ - Added per-server `requestHeadersCommand` support for deriving fail-closed HTTP headers from the exact outbound request on every Streamable HTTP or SSE call. Thanks @kgreen18 for PR #353.
50
+ - Added `settings.warnOnLargeDirectTools` to suppress the advisory for 75 or more resolved direct tools. Thanks @Roshvan for issue #358.
51
+
52
+ ### Changed
53
+ - Refined request-header command result handling types without changing runtime behavior.
54
+
55
+ ### Fixed
56
+ - Matched adapter-owned config and state paths to the host agent directory when Pi is rebranded, including its environment override and config directory. Thanks @mindplay-dk for issue #356.
57
+ - Avoided O(tools²) cross-server tool-name collision scans at startup by skipping collision candidates when selectors are absent and sharing one indexed candidate set when `includeTools` or `excludeTools` is configured. Thanks @mjlbach for PR #357 and @cataldoc for issue #354.
58
+
10
59
  ## [2.25.0] - 2026-08-13
11
60
 
12
61
  ### Added