@herbertgao/pi-extensions 2026.8.6 → 2026.8.8

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 (385) hide show
  1. package/README.md +8 -6
  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 +320 -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 +79 -17
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +27 -0
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +66 -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 +5 -4
  35. package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +174 -100
  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 +5 -1
  39. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/keyboard.md +10 -2
  40. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/localization.md +10 -6
  41. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/tool-schema.md +11 -5
  42. package/node_modules/@juicesharp/rpiv-ask-user-question/locales/en.json +5 -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 +140 -97
  47. package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +63 -28
  48. package/node_modules/@juicesharp/rpiv-ask-user-question/state/selectors/projections.ts +22 -15
  49. package/node_modules/@juicesharp/rpiv-ask-user-question/state/state-reducer.ts +11 -1
  50. package/node_modules/@juicesharp/rpiv-ask-user-question/state/state.ts +14 -6
  51. package/node_modules/@juicesharp/rpiv-ask-user-question/tool/response-envelope.ts +11 -0
  52. package/node_modules/@juicesharp/rpiv-ask-user-question/tool/types.ts +11 -0
  53. package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/multi-select-view.ts +31 -17
  54. package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/preview/preview-block-renderer.ts +15 -6
  55. package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/wrapping-select.ts +15 -6
  56. package/node_modules/@juicesharp/rpiv-ask-user-question/view/dialog-builder.ts +86 -38
  57. package/node_modules/@juicesharp/rpiv-ask-user-question/view/tab-content-strategy.ts +76 -9
  58. package/node_modules/@narumitw/pi-btw/README.md +120 -111
  59. package/node_modules/@narumitw/pi-btw/dist/index.ts +2898 -0
  60. package/node_modules/@narumitw/pi-btw/dist/index.ts.map +7 -0
  61. package/node_modules/@narumitw/pi-btw/package.json +10 -6
  62. package/node_modules/@narumitw/pi-btw/src/btw.ts +36 -40
  63. package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +55 -10
  64. package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +390 -0
  65. package/node_modules/@narumitw/pi-btw/src/menu.ts +45 -2
  66. package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +136 -45
  67. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs +44 -1856
  68. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs.map +1 -1
  69. package/node_modules/@pi-plugins/fast-mode/package.json +4 -6
  70. package/node_modules/pi-lens/CHANGELOG.md +999 -0
  71. package/node_modules/pi-lens/README.md +117 -3
  72. package/node_modules/pi-lens/config/ruff/core.toml +42 -0
  73. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +130 -27
  74. package/node_modules/pi-lens/dist/clients/advisory-provenance.js +126 -13
  75. package/node_modules/pi-lens/dist/clients/agent-nudge.js +67 -11
  76. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +9 -3
  77. package/node_modules/pi-lens/dist/clients/atomic-write.js +9 -3
  78. package/node_modules/pi-lens/dist/clients/bash-file-access.js +381 -13
  79. package/node_modules/pi-lens/dist/clients/biome-client.js +61 -30
  80. package/node_modules/pi-lens/dist/clients/blocker-freshness.js +428 -0
  81. package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +129 -0
  82. package/node_modules/pi-lens/dist/clients/bootstrap.js +12 -1
  83. package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +12 -3
  84. package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +206 -0
  85. package/node_modules/pi-lens/dist/clients/cache-observability.js +353 -76
  86. package/node_modules/pi-lens/dist/clients/cascade-budget.js +196 -0
  87. package/node_modules/pi-lens/dist/clients/cascade-format.js +20 -1
  88. package/node_modules/pi-lens/dist/clients/cascade-types.js +9 -1
  89. package/node_modules/pi-lens/dist/clients/child-unref.js +54 -6
  90. package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +76 -24
  91. package/node_modules/pi-lens/dist/clients/dead-code-client.js +123 -31
  92. package/node_modules/pi-lens/dist/clients/deadline-utils.js +8 -1
  93. package/node_modules/pi-lens/dist/clients/debug-handles.js +5 -0
  94. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +84 -14
  95. package/node_modules/pi-lens/dist/clients/demoted-finding-render.js +155 -0
  96. package/node_modules/pi-lens/dist/clients/dependency-checker.js +25 -3
  97. package/node_modules/pi-lens/dist/clients/deps/pi-tui.js +8 -2
  98. package/node_modules/pi-lens/dist/clients/deps/typebox.js +8 -3
  99. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +147 -33
  100. package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +298 -0
  101. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +52 -2
  102. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +256 -88
  103. package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +7 -4
  104. package/node_modules/pi-lens/dist/clients/dispatch/plan.js +5 -0
  105. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +234 -18
  106. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +187 -19
  107. package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +6 -3
  108. package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +11 -9
  109. package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +398 -0
  110. package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +9 -6
  111. package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +11 -3
  112. package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +12 -7
  113. package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +18 -0
  114. package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +9 -7
  115. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +895 -0
  116. package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +8 -6
  117. package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +4 -0
  118. package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +16 -3
  119. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +60 -53
  120. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +16 -2
  121. package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +25 -2
  122. package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +20 -5
  123. package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +44 -11
  124. package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +331 -55
  125. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +38 -5
  126. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +97 -19
  127. package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +17 -8
  128. package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +32 -4
  129. package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +47 -3
  130. package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +14 -4
  131. package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +127 -28
  132. package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +12 -7
  133. package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +73 -12
  134. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +275 -13
  135. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +21 -6
  136. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +260 -27
  137. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +734 -64
  138. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +86 -11
  139. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +188 -0
  140. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +9 -0
  141. package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +21 -10
  142. package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +18 -2
  143. package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +4 -2
  144. package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +28 -5
  145. package/node_modules/pi-lens/dist/clients/extension-log.js +22 -1
  146. package/node_modules/pi-lens/dist/clients/file-kinds.js +8 -2
  147. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +316 -0
  148. package/node_modules/pi-lens/dist/clients/finding-identity.js +88 -0
  149. package/node_modules/pi-lens/dist/clients/formatters-lazy.js +3 -2
  150. package/node_modules/pi-lens/dist/clients/formatters.js +500 -115
  151. package/node_modules/pi-lens/dist/clients/generation-guard.js +216 -0
  152. package/node_modules/pi-lens/dist/clients/git-guard.js +31 -0
  153. package/node_modules/pi-lens/dist/clients/gitleaks-client.js +181 -8
  154. package/node_modules/pi-lens/dist/clients/govulncheck-client.js +109 -9
  155. package/node_modules/pi-lens/dist/clients/grammar-source.js +333 -10
  156. package/node_modules/pi-lens/dist/clients/host-ports.js +8 -0
  157. package/node_modules/pi-lens/dist/clients/installer/index.js +1114 -100
  158. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh-session.js +58 -0
  159. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +715 -0
  160. package/node_modules/pi-lens/dist/clients/instance-reaper.js +643 -97
  161. package/node_modules/pi-lens/dist/clients/instance-registry.js +87 -17
  162. package/node_modules/pi-lens/dist/clients/jscpd-client.js +87 -8
  163. package/node_modules/pi-lens/dist/clients/knip-client.js +310 -10
  164. package/node_modules/pi-lens/dist/clients/language-policy.js +8 -2
  165. package/node_modules/pi-lens/dist/clients/language-profile.js +9 -2
  166. package/node_modules/pi-lens/dist/clients/latency-logger.js +440 -11
  167. package/node_modules/pi-lens/dist/clients/lazy-import.js +21 -0
  168. package/node_modules/pi-lens/dist/clients/ledger-bounds.js +21 -0
  169. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +8 -0
  170. package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +128 -8
  171. package/node_modules/pi-lens/dist/clients/lsp/client.js +1660 -164
  172. package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +83 -1
  173. package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +389 -0
  174. package/node_modules/pi-lens/dist/clients/lsp/index.js +2423 -151
  175. package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +215 -0
  176. package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +146 -14
  177. package/node_modules/pi-lens/dist/clients/lsp/language.js +48 -4
  178. package/node_modules/pi-lens/dist/clients/lsp/server.js +277 -16
  179. package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +22 -0
  180. package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +43 -0
  181. package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +79 -3
  182. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +43 -0
  183. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +422 -28
  184. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-session.js +30 -0
  185. package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +175 -0
  186. package/node_modules/pi-lens/dist/clients/lsp-lazy.js +3 -2
  187. package/node_modules/pi-lens/dist/clients/mcp/session.js +10 -2
  188. package/node_modules/pi-lens/dist/clients/module-report.js +22 -1
  189. package/node_modules/pi-lens/dist/clients/ndjson-logger.js +114 -23
  190. package/node_modules/pi-lens/dist/clients/opengrep-client.js +15 -1
  191. package/node_modules/pi-lens/dist/clients/package-manager.js +170 -14
  192. package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +27 -0
  193. package/node_modules/pi-lens/dist/clients/path-utils.js +160 -0
  194. package/node_modules/pi-lens/dist/clients/pipeline.js +154 -33
  195. package/node_modules/pi-lens/dist/clients/post-autofix-notice.js +37 -0
  196. package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +17 -3
  197. package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +89 -22
  198. package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +84 -14
  199. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +15 -3
  200. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +50 -2
  201. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +23 -9
  202. package/node_modules/pi-lens/dist/clients/project-lens-config.js +3 -0
  203. package/node_modules/pi-lens/dist/clients/project-report.js +62 -27
  204. package/node_modules/pi-lens/dist/clients/project-snapshot.js +299 -0
  205. package/node_modules/pi-lens/dist/clients/quiet-window-config.js +47 -0
  206. package/node_modules/pi-lens/dist/clients/quiet-window.js +11 -25
  207. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +8 -3
  208. package/node_modules/pi-lens/dist/clients/read-guard.js +253 -10
  209. package/node_modules/pi-lens/dist/clients/resource-sampler.js +49 -17
  210. package/node_modules/pi-lens/dist/clients/reverse-deps.js +50 -11
  211. package/node_modules/pi-lens/dist/clients/review-graph/builder.js +194 -31
  212. package/node_modules/pi-lens/dist/clients/review-graph/query.js +52 -4
  213. package/node_modules/pi-lens/dist/clients/review-graph/revision-drift.js +21 -0
  214. package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +6 -3
  215. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +96 -7
  216. package/node_modules/pi-lens/dist/clients/runtime-context.js +8 -1
  217. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +352 -45
  218. package/node_modules/pi-lens/dist/clients/runtime-session.js +373 -9
  219. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +217 -22
  220. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +212 -79
  221. package/node_modules/pi-lens/dist/clients/runtime-turn.js +620 -67
  222. package/node_modules/pi-lens/dist/clients/safe-spawn.js +220 -7
  223. package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +161 -0
  224. package/node_modules/pi-lens/dist/clients/search-read-registration.js +34 -6
  225. package/node_modules/pi-lens/dist/clients/security-scan-client.js +157 -24
  226. package/node_modules/pi-lens/dist/clients/session-event-guard.js +184 -0
  227. package/node_modules/pi-lens/dist/clients/sg-runner.js +116 -22
  228. package/node_modules/pi-lens/dist/clients/single-flight.js +158 -0
  229. package/node_modules/pi-lens/dist/clients/source-filter.js +6 -2
  230. package/node_modules/pi-lens/dist/clients/stale-marker.js +17 -0
  231. package/node_modules/pi-lens/dist/clients/startup-scan.js +5 -2
  232. package/node_modules/pi-lens/dist/clients/startup-timing.js +19 -1
  233. package/node_modules/pi-lens/dist/clients/test-runner-client.js +151 -16
  234. package/node_modules/pi-lens/dist/clients/tool-event.js +56 -5
  235. package/node_modules/pi-lens/dist/clients/tool-policy.js +125 -20
  236. package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +75 -1
  237. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +769 -64
  238. package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +1 -0
  239. package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +11 -0
  240. package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +90 -0
  241. package/node_modules/pi-lens/dist/clients/trivy-client.js +19 -1
  242. package/node_modules/pi-lens/dist/clients/widget-state.js +336 -36
  243. package/node_modules/pi-lens/dist/clients/zizmor-config.js +214 -14
  244. package/node_modules/pi-lens/dist/index.js +61407 -48577
  245. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +476 -57
  246. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +132 -43
  247. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -7
  248. package/node_modules/pi-lens/docs/agent-guide.md +6 -1
  249. package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +515 -506
  250. package/node_modules/pi-lens/docs/dispositions.md +21 -0
  251. package/node_modules/pi-lens/docs/features.md +19 -5
  252. package/node_modules/pi-lens/docs/globalconfig.md +3 -0
  253. package/node_modules/pi-lens/docs/language-coverage.md +71 -5
  254. package/node_modules/pi-lens/docs/mcp.md +2 -2
  255. package/node_modules/pi-lens/docs/servercapabilities.md +4 -1
  256. package/node_modules/pi-lens/docs/settings.md +19 -1
  257. package/node_modules/pi-lens/docs/usage.md +1 -0
  258. package/node_modules/pi-lens/package.json +27 -10
  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 +15 -1
  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-dupe-class-members-test.yml +33 -0
  266. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-js-test.yml +7 -1
  267. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-test.yml +7 -1
  268. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-known-value-widening-test.yml +9 -0
  269. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-non-null-assertion-test.yml +216 -0
  270. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +2 -0
  271. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +2 -0
  272. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +2 -1
  273. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +2 -1
  274. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-return-value-in-generator-test.yml +12 -0
  275. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-runtime-typeof-test.yml +33 -0
  276. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-server-bind-wildcard-test.yml +9 -0
  277. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-shape-in-symbol-names-test.yml +13 -0
  278. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-js-test.yml +5 -1
  279. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-test.yml +5 -1
  280. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-parameters-test.yml +12 -0
  281. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-returns-test.yml +16 -0
  282. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-any-test.yml +10 -0
  283. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-unknown-test.yml +8 -0
  284. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/redundant-unsafe-function-test.yml +35 -0
  285. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/require-safety-comment-for-as-unknown-as-test.yml +177 -0
  286. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/ts-void-zero-test.yml +1 -0
  287. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member-js.yml +13 -2
  288. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member.yml +13 -2
  289. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +2 -0
  290. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-object-param.yml +60 -0
  291. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +57 -12
  292. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-compile-call.yml +63 -5
  293. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-dupe-class-members.yml +52 -8
  294. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html-js.yml +27 -2
  295. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html.yml +27 -2
  296. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-known-value-widening.yml +71 -0
  297. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-non-null-assertion.yml +316 -0
  298. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +7 -0
  299. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +22 -2
  300. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +23 -2
  301. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +33 -5
  302. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +34 -8
  303. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-return-value-in-generator.yml +22 -5
  304. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-runtime-typeof.yml +121 -0
  305. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-server-bind-wildcard.yml +23 -7
  306. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-shape-in-symbol-names.yml +68 -0
  307. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code-js.yml +41 -2
  308. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code.yml +41 -2
  309. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +6 -1
  310. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-parameters.yml +67 -0
  311. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-returns.yml +106 -0
  312. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-any.yml +50 -0
  313. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-unknown.yml +56 -0
  314. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +2 -0
  315. package/node_modules/pi-lens/rules/ast-grep-rules/rules/redundant-unsafe-function.yml +32 -0
  316. package/node_modules/pi-lens/rules/ast-grep-rules/rules/require-safety-comment-for-as-unknown-as.yml +184 -0
  317. package/node_modules/pi-lens/rules/ast-grep-rules/rules/ts-void-zero.yml +5 -0
  318. package/node_modules/pi-lens/rules/ast-grep-rules/self-scan-baseline.json +5 -0
  319. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +53 -1
  320. package/node_modules/pi-lens/scripts/download-grammars.js +25 -0
  321. package/node_modules/pi-lens/scripts/grammars.lock.json +9 -0
  322. package/node_modules/pi-lens/scripts/install-selftest.mjs +99 -11
  323. package/node_modules/pi-lens/scripts/lib/host-provided-deps.mjs +75 -0
  324. package/node_modules/pi-lens/scripts/lib/warm-loader-cache.mjs +285 -0
  325. package/node_modules/pi-lens/scripts/warm-loader-cache.mjs +233 -0
  326. package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +2 -0
  327. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +80 -3
  328. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +41 -0
  329. package/node_modules/pi-lens/vendor/grammars/tree-sitter-cue.wasm +0 -0
  330. package/node_modules/pi-mcp-adapter/CHANGELOG.md +36 -0
  331. package/node_modules/pi-mcp-adapter/README.md +47 -5
  332. package/node_modules/pi-mcp-adapter/cli.js +163 -1
  333. package/node_modules/pi-mcp-adapter/commands.ts +128 -22
  334. package/node_modules/pi-mcp-adapter/config.ts +25 -7
  335. package/node_modules/pi-mcp-adapter/direct-tools.ts +5 -4
  336. package/node_modules/pi-mcp-adapter/index.ts +219 -32
  337. package/node_modules/pi-mcp-adapter/init.ts +36 -4
  338. package/node_modules/pi-mcp-adapter/lifecycle.ts +315 -24
  339. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +39 -6
  340. package/node_modules/pi-mcp-adapter/mcp-bearer-store.ts +387 -0
  341. package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +27 -3
  342. package/node_modules/pi-mcp-adapter/mcp-code.ts +4 -0
  343. package/node_modules/pi-mcp-adapter/mcp-panel.ts +42 -13
  344. package/node_modules/pi-mcp-adapter/metadata-cache.ts +32 -21
  345. package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +168 -0
  346. package/node_modules/pi-mcp-adapter/package.json +3 -1
  347. package/node_modules/pi-mcp-adapter/proxy-modes.ts +5 -4
  348. package/node_modules/pi-mcp-adapter/request-headers-command.ts +31 -37
  349. package/node_modules/pi-mcp-adapter/search-ranking.ts +92 -22
  350. package/node_modules/pi-mcp-adapter/server-manager.ts +140 -2
  351. package/node_modules/pi-mcp-adapter/session-recovery.ts +7 -0
  352. package/node_modules/pi-mcp-adapter/tool-approval.ts +15 -2
  353. package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +44 -4
  354. package/node_modules/pi-mcp-adapter/types.ts +2 -0
  355. package/node_modules/pi-mcp-adapter/ui-server.ts +18 -16
  356. package/node_modules/pi-mcp-adapter/utils.ts +70 -0
  357. package/node_modules/pi-web-access/CHANGELOG.md +37 -0
  358. package/node_modules/pi-web-access/README.md +32 -13
  359. package/node_modules/pi-web-access/anysearch.ts +4 -2
  360. package/node_modules/pi-web-access/brave.ts +16 -4
  361. package/node_modules/pi-web-access/chrome-cookies.ts +86 -15
  362. package/node_modules/pi-web-access/curator-page.ts +6 -3
  363. package/node_modules/pi-web-access/curator-server.ts +4 -1
  364. package/node_modules/pi-web-access/data-uri-sanitize.ts +406 -0
  365. package/node_modules/pi-web-access/exa.ts +18 -7
  366. package/node_modules/pi-web-access/extract.ts +40 -5
  367. package/node_modules/pi-web-access/firecrawl.ts +18 -2
  368. package/node_modules/pi-web-access/gemini-search.ts +16 -4
  369. package/node_modules/pi-web-access/github-extract.ts +65 -36
  370. package/node_modules/pi-web-access/index.ts +60 -61
  371. package/node_modules/pi-web-access/openai-search.ts +17 -6
  372. package/node_modules/pi-web-access/package.json +1 -1
  373. package/node_modules/pi-web-access/page-query.ts +4 -2
  374. package/node_modules/pi-web-access/parallel-mcp.ts +249 -0
  375. package/node_modules/pi-web-access/parallel.ts +2 -2
  376. package/node_modules/pi-web-access/pdf-extract.ts +18 -5
  377. package/node_modules/pi-web-access/query-rewrite.ts +51 -0
  378. package/node_modules/pi-web-access/serper.ts +211 -0
  379. package/node_modules/pi-web-access/ssrf-protection.ts +12 -2
  380. package/node_modules/pi-web-access/summary-model-scope.ts +12 -4
  381. package/node_modules/pi-web-access/summary-review.ts +44 -22
  382. package/node_modules/pi-web-access/tavily.ts +16 -4
  383. package/node_modules/pi-web-access/utils.ts +87 -0
  384. package/node_modules/pi-web-access/valyu.ts +199 -0
  385. package/package.json +14 -14
@@ -0,0 +1,121 @@
1
+ id: no-runtime-typeof
2
+ language: TypeScript
3
+ severity: hint
4
+ message: "Runtime 'typeof' check — decode/parse the value at its I/O boundary, then branch on the domain value"
5
+ note: |
6
+ Adapted from dmmulroy/anti-slop's `no-runtime-typeof`
7
+ (src/rules/no-runtime-typeof.ts, MIT). Upstream's own
8
+ `allowInTypeGuards` option only exempts a `typeof` sitting inside a
9
+ function whose return type is a type predicate (`x is T`) — the 2026-
10
+ 08-19 audit found that option alone doesn't rescue the rule for this
11
+ codebase (73 predicate functions out of 404 client hits), so this
12
+ port adds two more exemptions, informed by where the audit found the
13
+ remaining hits actually concentrated: third-party JSON/LSP wire
14
+ payloads decoded inside functions already named for that job
15
+ (`trivy-client.ts`, `lsp/client.ts`, `git-guard.ts`).
16
+
17
+ Exemptions (all three must miss for a hit to fire):
18
+ 1. `typeof` inside a function whose OWN return type is a type
19
+ predicate (`x is T`) — upstream's `allowInTypeGuards`.
20
+ 2. `typeof` inside a function/method whose name starts with
21
+ `parse`, `decode`, `validate`, `is`, or `assert` — these are this
22
+ codebase's own naming convention for a boundary-parsing or
23
+ predicate function (`asRecord`, `errorMessage`), even when
24
+ TypeScript's `is`-predicate return-type syntax isn't used.
25
+ 3. `.d.ts` files — declaration files have no runtime, so a `typeof`
26
+ there is a type query, not a check (the language keeps these
27
+ syntactically distinct in tree-sitter, but this glob is cheap
28
+ insurance).
29
+
30
+ These exemptions are structural, not semantic: they check the
31
+ ENCLOSING function's name/return-type, not what the `typeof` result
32
+ is actually used for, so a mis-named function (a real boundary
33
+ parser not named `parse*`, or a `checkFoo` predicate) still fires,
34
+ and a `parse*`-named function with an unrelated internal `typeof`
35
+ check is still exempted. `stopBy: end` searches to the nearest
36
+ enclosing function of that shape at ANY depth, which also exempts a
37
+ `typeof` inside a nested non-guard closure defined inside a guard —
38
+ a conservative (under-fires, not over-fires) choice.
39
+
40
+ Shipped at `hint`: the 2026-08-19 audit rejected outright adopting
41
+ this rule against pi-lens's own tree — it has no schema-decoding
42
+ library, and the concentration of hits is exactly where the rule
43
+ wants a schema layer (third-party JSON/LSP wire payloads), so
44
+ self-conformance would be an architecture decision, not a lint fix.
45
+ That verdict stands for pi-lens's own code; it doesn't mean the
46
+ pattern has no value for a repository that DOES have a decoder at its
47
+ boundaries. Self-scan note: do NOT try to make pi-lens's own tree
48
+ clean against this rule (#1718's baseline problem, likely never, per
49
+ the architecture-decision finding above); the adopting PR records the
50
+ 2026-08-19 hit count so a rule that fires thousands of times against
51
+ its own product's source gets its pattern tightened before anyone
52
+ trusts the count on a real target repo.
53
+
54
+ 2026-08-20 (refs #1727, #1777): CONSIDERED for promotion to `error`,
55
+ KEPT at `hint`. Four-corpus census, ast-grep CLI 0.45, with the three
56
+ exemptions above already applied:
57
+
58
+ | corpus | hits |
59
+ |---|---:|
60
+ | pi-lens `clients/` | 257 |
61
+ | pi-lens `tests/` | 232 |
62
+ | pi core `packages/` | 543 (431 outside test paths) |
63
+ | opencode `packages/` | 1122 (991) |
64
+ | oh-my-pi `packages/` | 4114 (3239) |
65
+
66
+ Verdict: the highest-volume rule in the whole catalog, and the volume is
67
+ not noise — it is the finding the note already records, that a codebase
68
+ without a decoding layer answers this rule with an architecture change.
69
+ The suppression the maintainer's own framing asks for ("suppress a
70
+ `typeof` whose checked binding comes from a source typed `unknown`")
71
+ needs the binding's declared type, which is type information ast-grep
72
+ does not have; the three exemptions here are the closest structural
73
+ approximation and they still leave 3,239 hits on one corpus. Promoting
74
+ at this volume would block agent turns across every one of these trees.
75
+ ignores:
76
+ - "**/*.d.ts"
77
+ rule:
78
+ kind: unary_expression
79
+ pattern: typeof $X
80
+ not:
81
+ any:
82
+ - inside:
83
+ stopBy: end
84
+ any:
85
+ - kind: function_declaration
86
+ - kind: function_expression
87
+ - kind: arrow_function
88
+ - kind: method_definition
89
+ has:
90
+ stopBy: neighbor
91
+ kind: type_annotation
92
+ has:
93
+ stopBy: neighbor
94
+ kind: type_predicate
95
+ - inside:
96
+ stopBy: end
97
+ kind: function_declaration
98
+ has:
99
+ stopBy: neighbor
100
+ kind: identifier
101
+ regex: '^(parse|decode|validate|is|assert)'
102
+ - inside:
103
+ stopBy: end
104
+ kind: function_expression
105
+ has:
106
+ stopBy: neighbor
107
+ kind: identifier
108
+ regex: '^(parse|decode|validate|is|assert)'
109
+ - inside:
110
+ stopBy: end
111
+ kind: method_definition
112
+ has:
113
+ stopBy: neighbor
114
+ kind: property_identifier
115
+ regex: '^(parse|decode|validate|is|assert)'
116
+ - inside:
117
+ stopBy: end
118
+ kind: variable_declarator
119
+ all:
120
+ - has: { stopBy: neighbor, kind: identifier, regex: '^(parse|decode|validate|is|assert)' }
121
+ - has: { stopBy: neighbor, kind: arrow_function }
@@ -9,14 +9,26 @@ note: |
9
9
  network interface, including public ones. Production servers
10
10
  should bind to a specific interface or use a reverse proxy.
11
11
 
12
- Matches any `call` node whose text contains `host=` followed
13
- by `0.0.0.0` (within a few characters). Note: `0.0.0.0` in
14
- `app.run()` (Flask dev server) is also flagged — for
15
- development, prefer `127.0.0.1`.
12
+ Matches any `call` node whose text contains `host=` followed by
13
+ `0.0.0.0` (within a few characters). Note: `0.0.0.0` in `app.run()`
14
+ (Flask dev server) is also flagged — for development, prefer
15
+ `127.0.0.1`.
16
16
 
17
- Style: regex on the call node's text. The pattern doesn't
18
- anchor at start (the call has the function name first, e.g.
19
- `app.run(`); the regex matches anywhere in the call text.
17
+ 2026-08-20 (review round, refs #1806): a prior fix anchored this to
18
+ `.run(...)` / `.listen(...)` / `.serve(...)` call targets specifically,
19
+ to exclude a pydantic `Settings.model_construct(...)` test fixture
20
+ that happened to have a `host`-named field set to `"0.0.0.0"`. That
21
+ traded one false positive for a false-negative CLASS: a bare
22
+ `run(host='0.0.0.0')` (no receiver), `uvicorn.Config(app,
23
+ host='0.0.0.0')` (a different call name — the config object, not the
24
+ `.run()` invocation), and `app.run_server(...)` (a different method
25
+ name) all went invisible. For a BLOCKER-severity security rule, a
26
+ rare false positive is the acceptable trade, not a missed detection
27
+ class — reverted to the broad `kind: call` + regex match, and
28
+ excluded the SPECIFIC false-positive shape instead: a call to
29
+ `.model_construct(...)` / `.construct(...)` (pydantic's
30
+ validation-skipping constructors — the "this builds a config object,
31
+ it doesn't bind a socket" case the FP actually was).
20
32
 
21
33
  The regex uses `.{0,5}` between `host` and `0.0.0.0` to
22
34
  accept either `host='0.0.0.0'` (single quote) or
@@ -26,3 +38,7 @@ metadata:
26
38
  rule:
27
39
  kind: call
28
40
  regex: 'host.{0,5}0\.0\.0\.0'
41
+ not:
42
+ any:
43
+ - pattern: $X.model_construct($$$ARGS)
44
+ - pattern: $X.construct($$$ARGS)
@@ -0,0 +1,68 @@
1
+ id: no-shape-in-symbol-names
2
+ language: TypeScript
3
+ severity: hint
4
+ message: "Symbol name contains 'shape' — name it for its domain role, not its structure"
5
+ note: |
6
+ Adapted from dmmulroy/anti-slop's `no-shape-in-symbol-names`
7
+ (src/rules/no-shape-in-symbol-names.ts, MIT). Upstream bans the
8
+ case-insensitive substring "shape" in every identifier, private
9
+ identifier, and JSX identifier: "shape" describes the STRUCTURE of a
10
+ value, not what it MEANS, and a name that only says "this has some
11
+ shape" (`PackageJsonShape`, `windowsShaped`) is filler a domain term
12
+ would replace (`PackageJsonManifest`, `usesWindowsSeparators`).
13
+
14
+ Explicitly NOT self-applied: AGENTS.md's own "Recurring defect shapes"
15
+ catalog uses "shape" as load-bearing review vocabulary, and pi-lens's
16
+ own code mirrors it — `ProbeFailureShape`, `windowsShaped`,
17
+ `basenameForShape`, 27 distinct identifiers / 291 occurrences in the
18
+ 2026-08-19 audit. Banning the word in THIS repo would fight the
19
+ convention its own review process runs on. That is a reason not to
20
+ wire this rule into pi-lens's self-scan (#1718's decision to make),
21
+ not a reason to withhold it from the catalog — a repo without that
22
+ convention gets real signal from it. Self-scan note: do NOT try to
23
+ make pi-lens's own tree clean against this rule; the adopting PR
24
+ records the 2026-08-19 hit count instead.
25
+
26
+ Scope: `identifier`, `property_identifier`, `private_property_identifier`,
27
+ and `type_identifier` nodes whose text contains "shape"
28
+ case-insensitively, anywhere in the name (matches upstream's
29
+ substring semantics, so `reshape`/`Shapeless` are in scope too, not
30
+ just whole-word `shape`). `jsx_identifier` is dropped — this repo
31
+ ships no `.tsx`, so it has nothing to match (same call as
32
+ `no-unknown-laundering.yml`'s "no JS variant" note).
33
+
34
+ 2026-08-20 (refs #1727, #1777): CONSIDERED for promotion to `error`,
35
+ KEPT at `hint`. Four-corpus census, ast-grep CLI 0.45:
36
+
37
+ | corpus | hits |
38
+ |---|---:|
39
+ | pi-lens `clients/` | 48 (13 distinct identifiers) |
40
+ | pi-lens `tests/` | 140 |
41
+ | pi core `packages/` | 5 (5 outside test paths, 1 file) |
42
+ | opencode `packages/` | 88 (76) |
43
+ | oh-my-pi `packages/` | 837 (608, 65 files) |
44
+
45
+ Verdict: structural scoping was applied and was not enough. Excluding
46
+ test paths — the mechanism this catalog now uses for
47
+ `require-safety-comment-for-as-unknown-as.yml` — removes pi-lens's 140
48
+ `tests/` hits and leaves all 48 `clients/` hits, because they are not a
49
+ test idiom. They are 13 production identifiers, several of them the
50
+ review vocabulary this repo runs on (`ProbeFailureShape`,
51
+ `basenameForShape`, `windowsShaped`, `checkManifestShape`,
52
+ `validateInputShape`) and one that is upstream's own headline example
53
+ (`PackageJsonShape`). The only ways to zero are an allowlist of pi-lens
54
+ identifiers baked into a rule that ships to other repositories — a
55
+ hand-maintained parallel list, which AGENTS.md forbids — or renaming 13
56
+ exported production symbols, which is a refactor with its own blast
57
+ radius and its own issue, not a severity change. Left at `hint` and
58
+ still NOT tagged for the self-scan.
59
+ rule:
60
+ any:
61
+ - kind: identifier
62
+ regex: "(?i)shape"
63
+ - kind: property_identifier
64
+ regex: "(?i)shape"
65
+ - kind: private_property_identifier
66
+ regex: "(?i)shape"
67
+ - kind: type_identifier
68
+ regex: "(?i)shape"
@@ -3,8 +3,9 @@ language: JavaScript
3
3
  message: "Raw SQL string in code — use query builder or ORM"
4
4
  severity: error
5
5
  note: |
6
- Raw SQL strings are error-prone and hard to maintain.
7
- Use a query builder (knex, drizzle) or ORM (prisma, typeorm).
6
+ Raw SQL strings built via concatenation or template substitution are
7
+ error-prone and open to injection. Use a query builder (knex, drizzle)
8
+ or ORM (prisma, typeorm), or pass the value as a bind parameter.
8
9
  The `, $$$REST` suffix matches the optional parameters/options
9
10
  argument common to ORM `query()`/`execute()` signatures. Without
10
11
  it, only the 1-arg form (no params) matches.
@@ -12,6 +13,27 @@ note: |
12
13
  because the SQL literal lives 2 levels below the call_expression
13
14
  (inside `arguments`); the default `has` neighbor doesn't drill
14
15
  that deep.
16
+
17
+ `$SQL` is constrained to a `binary_expression` (string concatenation,
18
+ e.g. `"SELECT ... " + id`) or a template string with at least one
19
+ `${...}` substitution — the two shapes that actually interpolate a
20
+ runtime value into the query text. A plain string literal (even one
21
+ containing a `?` placeholder passed alongside a params array — the
22
+ parameterized-query idiom) is NOT flagged: the query text itself is
23
+ static, so there's nothing to inject. Before this constraint, EVERY
24
+ `db.query("<literal SQL>")` call matched regardless of how the value
25
+ was passed, which is why the shipped rule produced 261 hits on a
26
+ correctly-parameterized DB layer (#1806 audit). Mirrors the Python
27
+ sibling `no-python-sql-string-concat`, which already restricted to
28
+ `binary_operator` concatenation.
29
+
30
+ 2026-08-20 (review round, refs #1806, low-severity finding): a
31
+ `binary_expression` where BOTH sides are string literals
32
+ (`"SELECT * FROM " + "users"`) is compile-time-constant text, not
33
+ runtime interpolation — nothing to inject. Excluded via a `has:
34
+ field: left/right, kind: string` check on both operands. A
35
+ literal-plus-variable concatenation (the actual injection shape)
36
+ still flags.
15
37
  rule:
16
38
  all:
17
39
  - any:
@@ -22,3 +44,20 @@ rule:
22
44
  regex: >-
23
45
  (?i)(SELECT|INSERT|UPDATE|DELETE|CREATE TABLE|DROP TABLE|ALTER
24
46
  TABLE)
47
+ constraints:
48
+ SQL:
49
+ any:
50
+ - all:
51
+ - kind: binary_expression
52
+ - not:
53
+ all:
54
+ - has:
55
+ field: left
56
+ kind: string
57
+ - has:
58
+ field: right
59
+ kind: string
60
+ - all:
61
+ - kind: template_string
62
+ - has:
63
+ kind: template_substitution
@@ -3,8 +3,9 @@ language: TypeScript
3
3
  message: "Raw SQL string in code — use query builder or ORM"
4
4
  severity: error
5
5
  note: |
6
- Raw SQL strings are error-prone and hard to maintain.
7
- Use a query builder (knex, drizzle) or ORM (prisma, typeorm).
6
+ Raw SQL strings built via concatenation or template substitution are
7
+ error-prone and open to injection. Use a query builder (knex, drizzle)
8
+ or ORM (prisma, typeorm), or pass the value as a bind parameter.
8
9
  The `, $$$REST` suffix matches the optional parameters/options
9
10
  argument common to ORM `query()`/`execute()` signatures. Without
10
11
  it, only the 1-arg form (no params) matches.
@@ -12,6 +13,27 @@ note: |
12
13
  because the SQL literal lives 2 levels below the call_expression
13
14
  (inside `arguments`); the default `has` neighbor doesn't drill
14
15
  that deep.
16
+
17
+ `$SQL` is constrained to a `binary_expression` (string concatenation,
18
+ e.g. `"SELECT ... " + id`) or a template string with at least one
19
+ `${...}` substitution — the two shapes that actually interpolate a
20
+ runtime value into the query text. A plain string literal (even one
21
+ containing a `?` placeholder passed alongside a params array — the
22
+ parameterized-query idiom) is NOT flagged: the query text itself is
23
+ static, so there's nothing to inject. Before this constraint, EVERY
24
+ `db.query("<literal SQL>")` call matched regardless of how the value
25
+ was passed, which is why the shipped rule produced 261 hits on a
26
+ correctly-parameterized DB layer (#1806 audit). Mirrors the Python
27
+ sibling `no-python-sql-string-concat`, which already restricted to
28
+ `binary_operator` concatenation.
29
+
30
+ 2026-08-20 (review round, refs #1806, low-severity finding): a
31
+ `binary_expression` where BOTH sides are string literals
32
+ (`"SELECT * FROM " + "users"`) is compile-time-constant text, not
33
+ runtime interpolation — nothing to inject. Excluded via a `has:
34
+ field: left/right, kind: string` check on both operands. A
35
+ literal-plus-variable concatenation (the actual injection shape)
36
+ still flags.
15
37
  rule:
16
38
  all:
17
39
  - any:
@@ -22,3 +44,20 @@ rule:
22
44
  regex: >-
23
45
  (?i)(SELECT|INSERT|UPDATE|DELETE|CREATE TABLE|DROP TABLE|ALTER
24
46
  TABLE)
47
+ constraints:
48
+ SQL:
49
+ any:
50
+ - all:
51
+ - kind: binary_expression
52
+ - not:
53
+ all:
54
+ - has:
55
+ field: left
56
+ kind: string
57
+ - has:
58
+ field: right
59
+ kind: string
60
+ - all:
61
+ - kind: template_string
62
+ - has:
63
+ kind: template_substitution
@@ -1,7 +1,9 @@
1
1
  id: no-unknown-laundering
2
2
  language: TypeScript
3
- severity: warning
3
+ severity: error
4
4
  message: "type alias to bare 'unknown' — give the alias real shape or inline 'unknown' at the one call site that needs it"
5
+ metadata:
6
+ category: pi-lens-self-scan
5
7
  note: |
6
8
  `type X = unknown` adds a name but zero type information — every
7
9
  consumer of X still has to narrow from scratch, so the alias only
@@ -23,5 +25,8 @@ note: |
23
25
  forces the caller to narrow — so it is not syntactically distinguishable
24
26
  from a laundered one; only `type X = unknown` stayed a reliable
25
27
  precision signal (zero hits in the same scan).
28
+
29
+ 2026-08-20 (refs #1856): PROMOTED from `warning` to `error` after a
30
+ fresh scan confirmed zero hits in pi-lens's own tree.
26
31
  rule:
27
32
  pattern: "type $T = unknown"
@@ -0,0 +1,67 @@
1
+ id: no-unknown-parameters
2
+ language: TypeScript
3
+ severity: hint
4
+ message: "Parameter typed 'unknown' — decode it at the I/O boundary instead of leaving it unparsed"
5
+ note: |
6
+ Adapted from dmmulroy/anti-slop's `no-unknown-parameters`
7
+ (src/rules/no-unknown-parameters.ts, MIT). Upstream exempts a
8
+ parameter literally named `cause` (the standard `Error` cause-chain
9
+ field, which is `unknown` by the language's own `ErrorOptions` type)
10
+ — kept here for the same reason.
11
+
12
+ Shipped at `hint`, not `error`: AGENTS.md smell 3 records that this
13
+ exact arm was dropped from `no-unknown-laundering.yml` after an
14
+ FP-scan found 166 legitimate `unknown` parameters in pi-lens's own
15
+ tree (type-guard/validator functions like
16
+ `errorMessage(err: unknown)`). That finding is about THIS repo's own
17
+ code, not a reason to withhold the pattern from the shipped catalog —
18
+ other repositories may have real slop here — so it ships as a
19
+ discoverable hint instead. Self-scan note: do NOT try to make
20
+ pi-lens's own tree clean against this rule (#1718's baseline
21
+ problem); the adopting PR records the 2026-08-19 hit count instead.
22
+
23
+ Scope: a direct `unknown` annotation on a required or optional
24
+ parameter, matched structurally at the `predefined_type` leaf (same
25
+ shape as `no-bare-object-param.yml`). Rest/default-value parameters
26
+ (`...rest: unknown[]`, `x = y: unknown`) are out of scope — ast-grep
27
+ doesn't unwrap those parameter-pattern wrappers the way upstream's
28
+ AST-walk does. A union member (`unknown | null`) is not flagged for
29
+ the same "direct annotation only" reason `no-bare-object-param.yml`
30
+ gives.
31
+
32
+ 2026-08-20 (refs #1727, #1777): CONSIDERED for promotion to `error`,
33
+ KEPT at `hint`. Four-corpus census, ast-grep CLI 0.45:
34
+
35
+ | corpus | hits |
36
+ |---|---:|
37
+ | pi-lens `clients/` | 149 |
38
+ | pi-lens `tests/` | 146 |
39
+ | pi core `packages/` | 381 (194 outside test paths) |
40
+ | opencode `packages/` | 678 (522) |
41
+ | oh-my-pi `packages/` | 2140 (1697) |
42
+
43
+ Verdict: structural narrowing was probed and does not reach zero. The
44
+ type-guard suppression (a parameter inside a function whose return type
45
+ is a `value is T` predicate) and a parser-name suppression together
46
+ clear the large predicate/validator block, but the residual is a second
47
+ legitimate class they cannot touch: opaque-payload SINKS that never
48
+ parse their argument at all — `setFileFact(path, id, value: unknown)`,
49
+ `bus(channel, payload: unknown)`, `emitLensEvent(name, payload:
50
+ unknown)`, `(err: unknown) => …` rejection handlers. `unknown` is the
51
+ CORRECT parameter type there, and it is syntactically identical to the
52
+ unparsed-boundary case the rule targets.
53
+ rule:
54
+ kind: predefined_type
55
+ regex: "^unknown$"
56
+ inside:
57
+ kind: type_annotation
58
+ inside:
59
+ all:
60
+ - any:
61
+ - kind: required_parameter
62
+ - kind: optional_parameter
63
+ - not:
64
+ has:
65
+ stopBy: neighbor
66
+ kind: identifier
67
+ regex: "^cause$"
@@ -0,0 +1,106 @@
1
+ id: no-unknown-returns
2
+ language: TypeScript
3
+ severity: error
4
+ message: "Function returns 'unknown' — parse the value at its boundary and return a named domain type"
5
+ metadata:
6
+ category: pi-lens-self-scan
7
+ note: |
8
+ Adapted from dmmulroy/anti-slop's `no-unknown-returns`
9
+ (src/rules/no-unknown-returns.ts, MIT). Upstream also resolves
10
+ `Promise<unknown>` and same-file type aliases that resolve to
11
+ `unknown`; both are dropped here — same-file alias/generic resolution
12
+ is out of ast-grep's reach (the `no-bare-object-param.yml` precedent).
13
+
14
+ Shipped at `hint`, not `error`: AGENTS.md smell 3 records that this
15
+ arm was dropped from `no-unknown-laundering.yml` after an FP-scan
16
+ found 192 legitimate `unknown` return types in pi-lens's own tree
17
+ (parsers, and a `ProxyHandler.get` trap whose signature TypeScript
18
+ itself requires). That's a finding about this repo's own code, not a
19
+ reason to withhold the pattern from the catalog, so it ships as a
20
+ discoverable hint. Self-scan note: do NOT try to make pi-lens's own
21
+ tree clean against this rule (#1718's baseline problem); the adopting
22
+ PR records the 2026-08-19 hit count instead.
23
+
24
+ Scope: a direct `unknown` return-type annotation, matched
25
+ structurally. Most function-like nodes wrap their return type in a
26
+ `type_annotation` node that is a DIRECT child of the function node
27
+ (function declaration/expression, arrow function, method signature/
28
+ definition, call/construct signature) — that is exactly the
29
+ return-type position; a parameter's `type_annotation` is nested one
30
+ level deeper, inside `required_parameter`/`optional_parameter`, so
31
+ the two never collide. `function_type` (`(x: T) => R`, used in
32
+ function-type aliases) was the one exception in
33
+ tree-sitter-typescript's grammar: its return type sits directly after
34
+ `=>` with no `type_annotation` wrapper at all, so it needed its own
35
+ branch. The #1824 scope correction removed that branch because callback
36
+ result types describe what callers consume, not an unparsed value crossing
37
+ a boundary. See the 2026-08-20 #1824 entry below for why that branch is
38
+ now gone.
39
+
40
+ 2026-08-20 (refs #1727, #1777): CONSIDERED for promotion to `error`,
41
+ KEPT at `hint`. Four-corpus census, ast-grep CLI 0.45:
42
+
43
+ | corpus | hits |
44
+ |---|---:|
45
+ | pi-lens `clients/` | 19 |
46
+ | pi-lens `tests/` | 58 |
47
+ | pi core `packages/` | 17 (14 outside test paths) |
48
+ | opencode `packages/` | 111 (105) |
49
+ | oh-my-pi `packages/` | 288 (226) |
50
+
51
+ Verdict: the closest of the six to promotable, and still not there. A
52
+ probed narrowing — drop the `function_type` arm (a callback TYPE
53
+ declaring `=> unknown` says "the caller ignores my result", not "a
54
+ boundary went unparsed") plus a parser-name suppression — takes pi-lens
55
+ from 77 hits to 16, and `clients/` from 19 to 3. The residual 3 are
56
+ generic pass-through wrappers (`clients/extension-log.ts`'s console
57
+ capture and proxy wrapper) whose return value genuinely IS the wrapped
58
+ function's, so `unknown` is correct. Reaching zero needed a third
59
+ suppression shaped around those three sites specifically, which is
60
+ overfitting to one tree, so nothing was changed here. The
61
+ `function_type` scope question is worth its own issue on its own merits;
62
+ it is a scope correction, not a tier change, and this PR does not make
63
+ it.
64
+
65
+ 2026-08-20 (#1824, refs #1727, #1815, review round 1 N4): dropped
66
+ the `function_type` arm named above. A TYPE-POSITION `unknown`
67
+ return is a legitimate contract ("the caller ignores my result"),
68
+ not a value-position return that skipped parsing at a boundary. This
69
+ is a scope correction, not a severity change. Same scan setup,
70
+ before → after: pi-lens full tree 79 → 23; pi-lens `clients/` +
71
+ `index.ts` 21 → 9 (see the adopting PR for the four-corpus
72
+ before/after on the same narrow scope). The value-position arm below
73
+ is unchanged and is what the rule now exclusively targets.
74
+ 2026-08-20 (refs #1856): PROMOTED from `hint` to `error` after the
75
+ remaining value-position returns were given named domain types or made
76
+ generic so their pass-through contract stays exact. The pi-lens
77
+ self-scan is clean at promotion time.
78
+ Test paths stay excluded: mocks and interleaving controls intentionally
79
+ return opaque sentinel values, while this rule governs production
80
+ boundaries whose domain shape is knowable.
81
+ ignores:
82
+ - "**/*.test.ts"
83
+ - "**/*.test.tsx"
84
+ - "**/*.test.mts"
85
+ - "**/*.test.cts"
86
+ - "**/*.spec.ts"
87
+ - "**/*.spec.tsx"
88
+ - "**/tests/**"
89
+ - "**/test/**"
90
+ - "**/__tests__/**"
91
+ rule:
92
+ kind: predefined_type
93
+ regex: "^unknown$"
94
+ inside:
95
+ kind: type_annotation
96
+ inside:
97
+ any:
98
+ - kind: function_declaration
99
+ - kind: function_expression
100
+ - kind: generator_function_declaration
101
+ - kind: arrow_function
102
+ - kind: method_signature
103
+ - kind: method_definition
104
+ - kind: construct_signature
105
+ - kind: constructor_type
106
+ - kind: call_signature
@@ -0,0 +1,50 @@
1
+ id: no-unsafe-dictionary-any
2
+ language: TypeScript
3
+ severity: error
4
+ metadata:
5
+ category: pi-lens-self-scan
6
+ message: "Record<K, any> — the value type gives callers no contract; use Record<K, unknown> or a real value type"
7
+ note: |
8
+ Adapted from dmmulroy/anti-slop's `no-unsafe-dictionary-type`
9
+ (src/rules/no-unsafe-dictionary-type.ts, MIT), narrowed to the `any`
10
+ arm only. Upstream also flags `unknown`, bare `object`, `{}`, and
11
+ unions/aliases that resolve to one of those — this port drops all of
12
+ that (see the `no-unsafe-dictionary-unknown.yml` sibling for the
13
+ `unknown` arm, shipped separately at `hint`). `Record<K, any>` is the
14
+ one arm this repo's own FP scan (AGENTS.md smell 3) found ZERO
15
+ legitimate uses for: `any` as a dictionary's value type doesn't just
16
+ widen, it turns off checking for every property read off that
17
+ dictionary, which `unknown` does not do.
18
+
19
+ Scope: a direct `Record<$K, any>` type reference, matched
20
+ structurally — the same "direct annotation only" cut as
21
+ `no-bare-object-param.yml`. Upstream's alias-resolution and
22
+ type-literal-index-signature arms (`{ [key: string]: any }`,
23
+ an alias that resolves to `Record<string, any>`) are dropped for the
24
+ same reason: same-file symbol/generic resolution ast-grep doesn't do.
25
+
26
+ FP-scan (napi engine, clients/ + tests/, 2026-08-19): 4 hits, not the
27
+ 2 the original audit measured — the audit's grep missed two test
28
+ files. `clients/cache/rule-cache.ts:81` and
29
+ `clients/tree-sitter-query-loader.ts:129` are genuine dictionary
30
+ value-type contracts (`post_filter_params?: Record<string, any>` on
31
+ loaded query metadata) and are fixed in the same PR to
32
+ `Record<string, unknown>` — every consumer already narrows manually
33
+ (`clients/tree-sitter-client.ts` takes `postFilterParams?: unknown`
34
+ or `any` as a local parameter type at the point it's actually
35
+ destructured, never relies on the interface field being `any`).
36
+ `tests/clients/call-graph.test.ts:736` and
37
+ `tests/tools/lens-diagnostics.test.ts:198` are a different shape:
38
+ ad-hoc mutation/access of a raw JSON fixture object
39
+ (`raw.edges[0].evidenceKind = "..."`, `props.mode.enum`) across
40
+ several unrelated nested paths, where `unknown` would require a cast
41
+ at every access and buys nothing — the same "test fixture shaping"
42
+ class already exempted for `require-safety-comment` and the empty-
43
+ object-spread hint. Excluded by path rather than fixed.
44
+ ignores:
45
+ - "**/tests/clients/call-graph.test.ts"
46
+ - "**/tests/tools/lens-diagnostics.test.ts"
47
+ rule:
48
+ pattern:
49
+ context: "type T = Record<$K, any>;"
50
+ selector: generic_type
@@ -0,0 +1,56 @@
1
+ id: no-unsafe-dictionary-unknown
2
+ language: TypeScript
3
+ severity: hint
4
+ message: "Record<K, unknown> — every read still needs a runtime narrow; prefer a real value type where the shape is known"
5
+ note: |
6
+ Adapted from dmmulroy/anti-slop's `no-unsafe-dictionary-type`
7
+ (src/rules/no-unsafe-dictionary-type.ts, MIT), narrowed to the
8
+ `unknown` arm — the sibling of `no-unsafe-dictionary-any.yml`, which
9
+ covers the `any` arm at `error`.
10
+
11
+ Shipped at `hint`, not `error` or `warning`: AGENTS.md smell 3
12
+ already records that `Record<string, unknown>` dictionaries are the
13
+ CORRECT, idiomatic contract at this repo's own validator/parser/
14
+ telemetry/metadata boundaries (9+ legitimate hits in the original
15
+ FP scan that got the wider `no-unknown-laundering` fan-out dropped
16
+ down to the alias-only arm). That finding doesn't generalize to every
17
+ repository this catalog ships to, so the pattern stays in the catalog
18
+ as a discoverable hint — "here's every open dictionary whose value
19
+ type forces the caller to narrow before use, go look and decide" —
20
+ rather than a rule that tells this repo's own idiom it's wrong.
21
+
22
+ Self-scan note: do NOT try to make pi-lens's own tree clean against
23
+ this rule (that is #1718's baseline problem, not this PR's). Recorded
24
+ in the adopting PR body per rule instead: 2026-08-19 hit count on
25
+ clients/ + tests/, napi engine.
26
+
27
+ Scope: same direct-annotation cut as the `any` arm — a `Record<$K,
28
+ unknown>` type reference, matched structurally. Alias resolution and
29
+ type-literal index signatures are out of scope for the same reason.
30
+
31
+ 2026-08-20 (refs #1727, #1777): CONSIDERED for promotion to `error`,
32
+ KEPT at `hint`. Four-corpus census, ast-grep CLI 0.45:
33
+
34
+ | corpus | hits |
35
+ |---|---:|
36
+ | pi-lens `clients/` | 142 |
37
+ | pi-lens `tests/` | 247 |
38
+ | pi core `packages/` | 299 (162 outside test paths) |
39
+ | opencode `packages/` | 533 (392) |
40
+ | oh-my-pi `packages/` | 2994 (1727) |
41
+
42
+ Verdict: promoting this rule would contradict AGENTS.md's own written
43
+ guidance in the same repository. Smell 3 records `Record<string,
44
+ unknown>` as the CORRECT contract at this codebase's validator, parser,
45
+ telemetry, and metadata boundaries. The suppression that would rescue it
46
+ — "suppress when the enclosing scope narrows the value before use" —
47
+ needs data flow from the dictionary's declaration to each read, which
48
+ ast-grep's structural matcher does not do; a syntactic stand-in would be
49
+ the vacuous guard this repo's review process screens for. The `any` arm
50
+ (`no-unsafe-dictionary-any.yml`) stays the error-tier member of the
51
+ pair, and it is clean on pi-lens: `any` turns checking OFF for every
52
+ property read, which is the discriminator `unknown` does not share.
53
+ rule:
54
+ pattern:
55
+ context: "type T = Record<$K, unknown>;"
56
+ selector: generic_type
@@ -1,6 +1,8 @@
1
1
  id: no-win32-isabsolute-for-qualification
2
2
  language: TypeScript
3
3
  severity: warning
4
+ metadata:
5
+ category: pi-lens-self-scan
4
6
  message: "Use isFullyQualified for path qualification instead of win32.isAbsolute"
5
7
  note: |
6
8
  Qualification must follow the input path's shape. Use clients/path-utils.ts