@herbertgao/pi-extensions 2026.8.6 → 2026.8.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (343) hide show
  1. package/README.md +5 -5
  2. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +1 -1
  3. package/node_modules/@herbertgao/pi-cc-extensions/README.md +1 -1
  4. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +19 -7
  5. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +30 -9
  6. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +272 -22
  7. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +94 -77
  8. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/message-display.ts +1 -1
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +14 -0
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +55 -17
  11. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/layout.ts +41 -2
  12. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +75 -6
  13. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/types.ts +7 -3
  14. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +64 -1
  15. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  16. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +6 -0
  17. package/node_modules/@herbertgao/pi-subagents/README.md +30 -22
  18. package/node_modules/@herbertgao/pi-subagents/examples/agent-tool-description.md +5 -5
  19. package/node_modules/@herbertgao/pi-subagents/package.json +7 -7
  20. package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +7 -1
  21. package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +48 -19
  22. package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +17 -13
  23. package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +26 -2
  24. package/node_modules/@herbertgao/pi-subagents/src/index.ts +219 -40
  25. package/node_modules/@herbertgao/pi-subagents/src/invocation-config.ts +101 -3
  26. package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +18 -4
  27. package/node_modules/@herbertgao/pi-subagents/src/settings.ts +99 -0
  28. package/node_modules/@herbertgao/pi-subagents/src/types.ts +22 -3
  29. package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +51 -3
  30. package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +20 -2
  31. package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +21 -6
  32. package/node_modules/@herbertgao/pi-subagents/src/usage.ts +129 -1
  33. package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +20 -0
  34. package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +1 -0
  35. package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +26 -10
  36. package/node_modules/@juicesharp/rpiv-ask-user-question/config.ts +25 -0
  37. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/configuration.md +13 -4
  38. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +2 -1
  39. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/localization.md +3 -1
  40. package/node_modules/@juicesharp/rpiv-ask-user-question/locales/en.json +2 -2
  41. package/node_modules/@juicesharp/rpiv-ask-user-question/locales/zh.json +2 -2
  42. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +3 -2
  43. package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +10 -0
  44. package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +3 -1
  45. package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +30 -7
  46. package/node_modules/@juicesharp/rpiv-ask-user-question/state/state.ts +14 -6
  47. package/node_modules/@juicesharp/rpiv-ask-user-question/view/dialog-builder.ts +30 -4
  48. package/node_modules/@juicesharp/rpiv-ask-user-question/view/tab-content-strategy.ts +26 -5
  49. package/node_modules/@narumitw/pi-btw/README.md +120 -111
  50. package/node_modules/@narumitw/pi-btw/dist/index.ts +2898 -0
  51. package/node_modules/@narumitw/pi-btw/dist/index.ts.map +7 -0
  52. package/node_modules/@narumitw/pi-btw/package.json +10 -6
  53. package/node_modules/@narumitw/pi-btw/src/btw.ts +36 -40
  54. package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +55 -10
  55. package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +390 -0
  56. package/node_modules/@narumitw/pi-btw/src/menu.ts +45 -2
  57. package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +136 -45
  58. package/node_modules/pi-lens/CHANGELOG.md +909 -0
  59. package/node_modules/pi-lens/README.md +11 -3
  60. package/node_modules/pi-lens/config/ruff/core.toml +42 -0
  61. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +130 -27
  62. package/node_modules/pi-lens/dist/clients/advisory-provenance.js +126 -13
  63. package/node_modules/pi-lens/dist/clients/agent-nudge.js +67 -11
  64. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +9 -3
  65. package/node_modules/pi-lens/dist/clients/atomic-write.js +9 -3
  66. package/node_modules/pi-lens/dist/clients/bash-file-access.js +285 -8
  67. package/node_modules/pi-lens/dist/clients/biome-client.js +61 -30
  68. package/node_modules/pi-lens/dist/clients/blocker-freshness.js +428 -0
  69. package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +119 -0
  70. package/node_modules/pi-lens/dist/clients/bootstrap.js +12 -1
  71. package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +12 -3
  72. package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +192 -0
  73. package/node_modules/pi-lens/dist/clients/cascade-budget.js +196 -0
  74. package/node_modules/pi-lens/dist/clients/cascade-format.js +20 -1
  75. package/node_modules/pi-lens/dist/clients/cascade-types.js +9 -1
  76. package/node_modules/pi-lens/dist/clients/child-unref.js +54 -6
  77. package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +76 -24
  78. package/node_modules/pi-lens/dist/clients/dead-code-client.js +123 -31
  79. package/node_modules/pi-lens/dist/clients/deadline-utils.js +8 -1
  80. package/node_modules/pi-lens/dist/clients/debug-handles.js +5 -0
  81. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +62 -13
  82. package/node_modules/pi-lens/dist/clients/dependency-checker.js +25 -3
  83. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +147 -33
  84. package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +298 -0
  85. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +52 -2
  86. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +256 -88
  87. package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +7 -4
  88. package/node_modules/pi-lens/dist/clients/dispatch/plan.js +5 -0
  89. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +234 -18
  90. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +187 -19
  91. package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +6 -3
  92. package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +11 -9
  93. package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +398 -0
  94. package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +11 -3
  95. package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +12 -7
  96. package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +18 -0
  97. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +895 -0
  98. package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +4 -0
  99. package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +16 -3
  100. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +60 -53
  101. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +16 -0
  102. package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +23 -0
  103. package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +331 -55
  104. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +38 -5
  105. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +97 -19
  106. package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +14 -0
  107. package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +20 -0
  108. package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +22 -0
  109. package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +10 -0
  110. package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +18 -6
  111. package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +73 -12
  112. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +275 -13
  113. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +21 -6
  114. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +260 -27
  115. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +734 -64
  116. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +86 -11
  117. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +72 -0
  118. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +9 -0
  119. package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +9 -0
  120. package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +18 -1
  121. package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +4 -2
  122. package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +28 -5
  123. package/node_modules/pi-lens/dist/clients/extension-log.js +22 -1
  124. package/node_modules/pi-lens/dist/clients/file-kinds.js +8 -2
  125. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +294 -0
  126. package/node_modules/pi-lens/dist/clients/finding-identity.js +88 -0
  127. package/node_modules/pi-lens/dist/clients/formatters-lazy.js +3 -2
  128. package/node_modules/pi-lens/dist/clients/formatters.js +500 -115
  129. package/node_modules/pi-lens/dist/clients/generation-guard.js +216 -0
  130. package/node_modules/pi-lens/dist/clients/git-guard.js +31 -0
  131. package/node_modules/pi-lens/dist/clients/gitleaks-client.js +181 -8
  132. package/node_modules/pi-lens/dist/clients/govulncheck-client.js +109 -9
  133. package/node_modules/pi-lens/dist/clients/grammar-source.js +333 -10
  134. package/node_modules/pi-lens/dist/clients/host-ports.js +8 -0
  135. package/node_modules/pi-lens/dist/clients/installer/index.js +1114 -100
  136. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh-session.js +58 -0
  137. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +715 -0
  138. package/node_modules/pi-lens/dist/clients/instance-reaper.js +643 -97
  139. package/node_modules/pi-lens/dist/clients/instance-registry.js +87 -17
  140. package/node_modules/pi-lens/dist/clients/jscpd-client.js +82 -6
  141. package/node_modules/pi-lens/dist/clients/knip-client.js +310 -10
  142. package/node_modules/pi-lens/dist/clients/language-policy.js +8 -2
  143. package/node_modules/pi-lens/dist/clients/language-profile.js +2 -0
  144. package/node_modules/pi-lens/dist/clients/latency-logger.js +440 -11
  145. package/node_modules/pi-lens/dist/clients/lazy-import.js +21 -0
  146. package/node_modules/pi-lens/dist/clients/ledger-bounds.js +21 -0
  147. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +8 -0
  148. package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +102 -7
  149. package/node_modules/pi-lens/dist/clients/lsp/client.js +1516 -159
  150. package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +83 -1
  151. package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +389 -0
  152. package/node_modules/pi-lens/dist/clients/lsp/index.js +2274 -147
  153. package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +215 -0
  154. package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +146 -14
  155. package/node_modules/pi-lens/dist/clients/lsp/language.js +48 -4
  156. package/node_modules/pi-lens/dist/clients/lsp/server.js +277 -16
  157. package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +22 -0
  158. package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +43 -0
  159. package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +79 -3
  160. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +43 -0
  161. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +422 -28
  162. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-session.js +30 -0
  163. package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +175 -0
  164. package/node_modules/pi-lens/dist/clients/lsp-lazy.js +3 -2
  165. package/node_modules/pi-lens/dist/clients/mcp/session.js +10 -2
  166. package/node_modules/pi-lens/dist/clients/module-report.js +8 -0
  167. package/node_modules/pi-lens/dist/clients/opengrep-client.js +15 -1
  168. package/node_modules/pi-lens/dist/clients/package-manager.js +170 -14
  169. package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +27 -0
  170. package/node_modules/pi-lens/dist/clients/path-utils.js +160 -0
  171. package/node_modules/pi-lens/dist/clients/pipeline.js +154 -33
  172. package/node_modules/pi-lens/dist/clients/post-autofix-notice.js +37 -0
  173. package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +17 -3
  174. package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +89 -22
  175. package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +84 -14
  176. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +15 -3
  177. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +50 -2
  178. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +5 -0
  179. package/node_modules/pi-lens/dist/clients/project-lens-config.js +3 -0
  180. package/node_modules/pi-lens/dist/clients/project-snapshot.js +299 -0
  181. package/node_modules/pi-lens/dist/clients/quiet-window-config.js +47 -0
  182. package/node_modules/pi-lens/dist/clients/quiet-window.js +11 -25
  183. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +1 -1
  184. package/node_modules/pi-lens/dist/clients/read-guard.js +184 -10
  185. package/node_modules/pi-lens/dist/clients/resource-sampler.js +49 -17
  186. package/node_modules/pi-lens/dist/clients/reverse-deps.js +50 -11
  187. package/node_modules/pi-lens/dist/clients/review-graph/query.js +52 -4
  188. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +96 -7
  189. package/node_modules/pi-lens/dist/clients/runtime-context.js +8 -1
  190. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +308 -45
  191. package/node_modules/pi-lens/dist/clients/runtime-session.js +332 -9
  192. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +217 -22
  193. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +212 -79
  194. package/node_modules/pi-lens/dist/clients/runtime-turn.js +575 -67
  195. package/node_modules/pi-lens/dist/clients/safe-spawn.js +220 -7
  196. package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +161 -0
  197. package/node_modules/pi-lens/dist/clients/search-read-registration.js +34 -6
  198. package/node_modules/pi-lens/dist/clients/security-scan-client.js +157 -24
  199. package/node_modules/pi-lens/dist/clients/sg-runner.js +116 -22
  200. package/node_modules/pi-lens/dist/clients/single-flight.js +158 -0
  201. package/node_modules/pi-lens/dist/clients/stale-marker.js +17 -0
  202. package/node_modules/pi-lens/dist/clients/startup-timing.js +19 -1
  203. package/node_modules/pi-lens/dist/clients/test-runner-client.js +151 -16
  204. package/node_modules/pi-lens/dist/clients/tool-event.js +56 -5
  205. package/node_modules/pi-lens/dist/clients/tool-policy.js +125 -20
  206. package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +75 -1
  207. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +769 -64
  208. package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +11 -0
  209. package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +90 -0
  210. package/node_modules/pi-lens/dist/clients/trivy-client.js +19 -1
  211. package/node_modules/pi-lens/dist/clients/widget-state.js +336 -36
  212. package/node_modules/pi-lens/dist/clients/zizmor-config.js +214 -14
  213. package/node_modules/pi-lens/dist/index.js +67738 -55739
  214. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +466 -54
  215. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +132 -43
  216. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -7
  217. package/node_modules/pi-lens/docs/agent-guide.md +6 -1
  218. package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +515 -506
  219. package/node_modules/pi-lens/docs/dispositions.md +21 -0
  220. package/node_modules/pi-lens/docs/features.md +19 -5
  221. package/node_modules/pi-lens/docs/globalconfig.md +3 -0
  222. package/node_modules/pi-lens/docs/language-coverage.md +71 -5
  223. package/node_modules/pi-lens/docs/mcp.md +2 -2
  224. package/node_modules/pi-lens/docs/servercapabilities.md +4 -1
  225. package/node_modules/pi-lens/docs/settings.md +19 -1
  226. package/node_modules/pi-lens/docs/usage.md +1 -0
  227. package/node_modules/pi-lens/package.json +10 -6
  228. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-js-snapshot.yml +23 -0
  229. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-snapshot.yml +23 -0
  230. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/ts-void-zero-snapshot.yml +23 -0
  231. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-object-param-test.yml +16 -0
  232. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +15 -1
  233. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-compile-call-test.yml +29 -1
  234. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-dupe-class-members-test.yml +33 -0
  235. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-js-test.yml +7 -1
  236. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-test.yml +7 -1
  237. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-known-value-widening-test.yml +9 -0
  238. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-non-null-assertion-test.yml +216 -0
  239. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +2 -0
  240. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +2 -0
  241. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +2 -1
  242. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +2 -1
  243. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-return-value-in-generator-test.yml +12 -0
  244. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-runtime-typeof-test.yml +33 -0
  245. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-server-bind-wildcard-test.yml +9 -0
  246. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-shape-in-symbol-names-test.yml +13 -0
  247. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-js-test.yml +5 -1
  248. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-test.yml +5 -1
  249. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-parameters-test.yml +12 -0
  250. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-returns-test.yml +16 -0
  251. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-any-test.yml +10 -0
  252. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-unknown-test.yml +8 -0
  253. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/redundant-unsafe-function-test.yml +35 -0
  254. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/require-safety-comment-for-as-unknown-as-test.yml +177 -0
  255. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/ts-void-zero-test.yml +1 -0
  256. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member-js.yml +13 -2
  257. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member.yml +13 -2
  258. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +2 -0
  259. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-object-param.yml +60 -0
  260. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +57 -12
  261. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-compile-call.yml +63 -5
  262. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-dupe-class-members.yml +52 -8
  263. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html-js.yml +27 -2
  264. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html.yml +27 -2
  265. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-known-value-widening.yml +71 -0
  266. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-non-null-assertion.yml +316 -0
  267. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +7 -0
  268. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +22 -2
  269. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +23 -2
  270. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +33 -5
  271. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +34 -8
  272. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-return-value-in-generator.yml +22 -5
  273. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-runtime-typeof.yml +121 -0
  274. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-server-bind-wildcard.yml +23 -7
  275. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-shape-in-symbol-names.yml +68 -0
  276. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code-js.yml +41 -2
  277. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code.yml +41 -2
  278. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +6 -1
  279. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-parameters.yml +67 -0
  280. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-returns.yml +106 -0
  281. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-any.yml +50 -0
  282. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-unknown.yml +56 -0
  283. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +2 -0
  284. package/node_modules/pi-lens/rules/ast-grep-rules/rules/redundant-unsafe-function.yml +32 -0
  285. package/node_modules/pi-lens/rules/ast-grep-rules/rules/require-safety-comment-for-as-unknown-as.yml +184 -0
  286. package/node_modules/pi-lens/rules/ast-grep-rules/rules/ts-void-zero.yml +5 -0
  287. package/node_modules/pi-lens/rules/ast-grep-rules/self-scan-baseline.json +5 -0
  288. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +53 -1
  289. package/node_modules/pi-lens/scripts/download-grammars.js +25 -0
  290. package/node_modules/pi-lens/scripts/grammars.lock.json +9 -0
  291. package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +2 -0
  292. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +80 -3
  293. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +41 -0
  294. package/node_modules/pi-lens/vendor/grammars/tree-sitter-cue.wasm +0 -0
  295. package/node_modules/pi-mcp-adapter/CHANGELOG.md +36 -0
  296. package/node_modules/pi-mcp-adapter/README.md +47 -5
  297. package/node_modules/pi-mcp-adapter/cli.js +163 -1
  298. package/node_modules/pi-mcp-adapter/commands.ts +128 -22
  299. package/node_modules/pi-mcp-adapter/config.ts +25 -7
  300. package/node_modules/pi-mcp-adapter/direct-tools.ts +5 -4
  301. package/node_modules/pi-mcp-adapter/index.ts +219 -32
  302. package/node_modules/pi-mcp-adapter/init.ts +36 -4
  303. package/node_modules/pi-mcp-adapter/lifecycle.ts +315 -24
  304. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +39 -6
  305. package/node_modules/pi-mcp-adapter/mcp-bearer-store.ts +387 -0
  306. package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +27 -3
  307. package/node_modules/pi-mcp-adapter/mcp-code.ts +4 -0
  308. package/node_modules/pi-mcp-adapter/mcp-panel.ts +42 -13
  309. package/node_modules/pi-mcp-adapter/metadata-cache.ts +32 -21
  310. package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +168 -0
  311. package/node_modules/pi-mcp-adapter/package.json +3 -1
  312. package/node_modules/pi-mcp-adapter/proxy-modes.ts +5 -4
  313. package/node_modules/pi-mcp-adapter/request-headers-command.ts +31 -37
  314. package/node_modules/pi-mcp-adapter/search-ranking.ts +92 -22
  315. package/node_modules/pi-mcp-adapter/server-manager.ts +140 -2
  316. package/node_modules/pi-mcp-adapter/session-recovery.ts +7 -0
  317. package/node_modules/pi-mcp-adapter/tool-approval.ts +15 -2
  318. package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +44 -4
  319. package/node_modules/pi-mcp-adapter/types.ts +2 -0
  320. package/node_modules/pi-mcp-adapter/ui-server.ts +18 -16
  321. package/node_modules/pi-mcp-adapter/utils.ts +70 -0
  322. package/node_modules/pi-web-access/CHANGELOG.md +23 -0
  323. package/node_modules/pi-web-access/README.md +27 -9
  324. package/node_modules/pi-web-access/anysearch.ts +4 -2
  325. package/node_modules/pi-web-access/brave.ts +16 -4
  326. package/node_modules/pi-web-access/curator-page.ts +6 -3
  327. package/node_modules/pi-web-access/curator-server.ts +4 -1
  328. package/node_modules/pi-web-access/exa.ts +18 -7
  329. package/node_modules/pi-web-access/extract.ts +28 -3
  330. package/node_modules/pi-web-access/gemini-search.ts +16 -4
  331. package/node_modules/pi-web-access/index.ts +41 -57
  332. package/node_modules/pi-web-access/package.json +1 -1
  333. package/node_modules/pi-web-access/page-query.ts +4 -2
  334. package/node_modules/pi-web-access/parallel-mcp.ts +249 -0
  335. package/node_modules/pi-web-access/parallel.ts +2 -2
  336. package/node_modules/pi-web-access/query-rewrite.ts +51 -0
  337. package/node_modules/pi-web-access/serper.ts +211 -0
  338. package/node_modules/pi-web-access/summary-model-scope.ts +12 -4
  339. package/node_modules/pi-web-access/summary-review.ts +44 -22
  340. package/node_modules/pi-web-access/tavily.ts +16 -4
  341. package/node_modules/pi-web-access/utils.ts +87 -0
  342. package/node_modules/pi-web-access/valyu.ts +199 -0
  343. package/package.json +13 -13
@@ -3,8 +3,224 @@ valid:
3
3
  - 'const x = foo'
4
4
  - 'const x = foo?.bar'
5
5
  - 'const x: number = foo()'
6
+ # #1777: get-after-has, same map, same key — suppressed.
7
+ - |
8
+ function f(m: Map<string, number>, k: string) {
9
+ if (m.has(k)) {
10
+ return m.get(k)!;
11
+ }
12
+ }
13
+ # #1777: pop-after-length, same array, in a while loop.
14
+ - |
15
+ function f(stack: number[]) {
16
+ while (stack.length > 0) {
17
+ const x = stack.pop()!;
18
+ }
19
+ }
20
+ # #1777: shift-after-length, same array, in an if branch.
21
+ - |
22
+ function f(queue: number[]) {
23
+ if (queue.length > 0) {
24
+ return queue.shift()!;
25
+ }
26
+ }
27
+ # #1818 round 2: ternary-narrow. The consequence branch is only reached
28
+ # when the condition's own property access is truthy; the nested closure
29
+ # loses TS's narrowing across the function boundary, hence the `!`.
30
+ - |
31
+ function f(index: { forward?: Map<string, number> }, files: string[]) {
32
+ return index.forward
33
+ ? files.map((file) => index.forward!.get(file))
34
+ : undefined;
35
+ }
36
+ # #1818 round 2: property re-asserted after a `.filter()` on the same
37
+ # property, immediately followed by `.map()` in the same chain.
38
+ - |
39
+ function f(reads: Array<{ enclosingSymbol?: { name: string } }>) {
40
+ return reads
41
+ .filter((r) => r.enclosingSymbol)
42
+ .map((r) => ({ name: r.enclosingSymbol!.name }));
43
+ }
6
44
  invalid:
7
45
  - 'const x = foo!'
8
46
  - 'foo!.bar()'
9
47
  - 'const x = (foo!)!.bar'
10
48
  - 'foo!!'
49
+ # #1777 mutation guard: a get()! with NO has() check anywhere in the
50
+ # function must still flag — deleting the exclusion's pattern match
51
+ # (not just its metavariable binding) reds this.
52
+ - |
53
+ function f(m: Map<string, number>, k: string) {
54
+ return m.get(k)!;
55
+ }
56
+ # #1777 mutation guard: the has() check is for a DIFFERENT key —
57
+ # same-key binding discipline is the guard, not mere presence of
58
+ # any .has() call on the map.
59
+ - |
60
+ function f(m: Map<string, number>, k: string, other: string) {
61
+ if (m.has(other)) {
62
+ return m.get(k)!;
63
+ }
64
+ }
65
+ # #1777 mutation guard: the has() check is on a DIFFERENT map —
66
+ # same-receiver binding discipline is the guard.
67
+ - |
68
+ function f(m: Map<string, number>, other: Map<string, number>, k: string) {
69
+ if (other.has(k)) {
70
+ return m.get(k)!;
71
+ }
72
+ }
73
+ # #1777 mutation guard: pop()! with NO length check anywhere in the
74
+ # function must still flag.
75
+ - |
76
+ function f(arr: number[]) {
77
+ return arr.pop()!;
78
+ }
79
+ # #1777 mutation guard: the length check is on a DIFFERENT array —
80
+ # same-array binding discipline is the guard.
81
+ - |
82
+ function f(arr: number[], other: number[]) {
83
+ if (other.length > 0) {
84
+ return arr.pop()!;
85
+ }
86
+ }
87
+ # #1777: a length check elsewhere in the SAME function that does not
88
+ # dominate this particular pop() (documented approximation — the
89
+ # rule only requires presence in the enclosing function, not proven
90
+ # dominance) still suppresses; this fixture exists to make that
91
+ # scoping visible rather than silently assumed. Left as `invalid`
92
+ # because this specific shape (length check AFTER the pop, in an
93
+ # unrelated later branch) is outside the two named idiom shapes: the
94
+ # pop here is not itself inside the while/for/if that carries the
95
+ # length check.
96
+ - |
97
+ function f(arr: number[]) {
98
+ const x = arr.pop()!;
99
+ if (arr.length > 0) {
100
+ return x;
101
+ }
102
+ }
103
+ # #1777 F1 regression test: a `.has()` guard in an OUTER function must
104
+ # NOT suppress a `!` inside an INNER closure — the `stopBy` boundary
105
+ # has to stop the ancestor walk at the nearest enclosing function.
106
+ # Review round 1 proved the pre-fix rule got this wrong (a guard in
107
+ # the outer scope suppressed the closure's finding).
108
+ - |
109
+ function outer(m: Map<string, number>, k: string) {
110
+ if (m.has(k)) {
111
+ // guard lives here, in the OUTER function
112
+ }
113
+ return function inner() {
114
+ return m.get(k)!;
115
+ };
116
+ }
117
+ # #1777 F1 regression test, arrow-closure variant: same outer/inner
118
+ # split, `.length` guard in the outer function only.
119
+ - |
120
+ function outer(arr: number[]) {
121
+ if (arr.length > 0) {
122
+ // guard lives here, in the OUTER function
123
+ }
124
+ return () => arr.pop()!;
125
+ }
126
+ # #1777 F2 regression test: `if (!m.has(k))` guards the branch where
127
+ # the key is proven ABSENT, so `m.get(k)!` inside that branch is a
128
+ # real bug, not a narrowed-after-check idiom. ast-grep can't read
129
+ # branch polarity, so the fix is a blunt one — ANY negated `.has()`
130
+ # is refused as a guard — but it MUST catch this exact shape, the one
131
+ # review round 1 named as "the rule's most likely real bug shape."
132
+ - |
133
+ function f(m: Map<string, number>, k: string) {
134
+ if (!m.has(k)) {
135
+ return m.get(k)!;
136
+ }
137
+ }
138
+ # #1777 F2 accepted regression: this is a genuinely SAFE early-return
139
+ # guard clause — by the time `m.get(k)!` runs, `!m.has(k)` has already
140
+ # returned. It was correctly suppressed before the F2 fix. It is NOT
141
+ # anymore, and that is accepted, not a bug: ast-grep matches this
142
+ # `if (!m.has(k)) return;` identically to the real-bug shape directly
143
+ # above (same syntax, opposite control flow), and there is no cheaper
144
+ # structural signal available to tell them apart. This fixture exists
145
+ # so the known blind spot has a name and a test, and can't be
146
+ # mistaken for coverage this rule doesn't have.
147
+ - |
148
+ function f(m: Map<string, number>, k: string) {
149
+ if (!m.has(k)) return;
150
+ return m.get(k)!;
151
+ }
152
+ # #1818 mutation guard: ternary-narrow, but the assertion sits in the
153
+ # ALTERNATIVE branch (the condition's property is falsy there) — a real
154
+ # bug, must still flag.
155
+ - |
156
+ function f(index: { forward?: Map<string, number> }, files: string[]) {
157
+ return index.forward
158
+ ? undefined
159
+ : files.map((file) => index.forward!.get(file));
160
+ }
161
+ # #1818 mutation guard: ternary-narrow, but the assertion targets a
162
+ # DIFFERENT object than the condition checked — same-binding discipline
163
+ # is the guard, not mere presence of a truthy-ternary anywhere outside.
164
+ - |
165
+ function f(
166
+ index: { forward?: Map<string, number> },
167
+ other: { forward?: Map<string, number> },
168
+ files: string[],
169
+ ) {
170
+ return index.forward
171
+ ? files.map((file) => other.forward!.get(file))
172
+ : undefined;
173
+ }
174
+ # #1818 mutation guard: filter+map, but the filter checks a DIFFERENT
175
+ # property than the one asserted in map — must still flag.
176
+ - |
177
+ function f(reads: Array<{ enclosingSymbol?: { name: string }; other?: unknown }>) {
178
+ return reads
179
+ .filter((r) => r.other)
180
+ .map((r) => ({ name: r.enclosingSymbol!.name }));
181
+ }
182
+ # #1818 mutation guard: no preceding filter at all — must still flag.
183
+ - |
184
+ function f(reads: Array<{ enclosingSymbol?: { name: string } }>) {
185
+ return reads.map((r) => ({ name: r.enclosingSymbol!.name }));
186
+ }
187
+ # #1818 review round 1, N1: the SAME assertion repeated in BOTH the
188
+ # consequence AND alternative branches. The consequence instance is
189
+ # genuinely safe and suppressed; the alternative instance is a real
190
+ # bug (the condition's property is falsy on that branch) and must
191
+ # still flag. An `has: field: consequence` EXISTENCE check on the
192
+ # ternary cannot tell these two instances apart (the consequence
193
+ # branch's matching text satisfies the check for both); `field:
194
+ # consequence` as an IDENTITY check on the matched node can.
195
+ - |
196
+ function f(o: { y?: { length: number } }) {
197
+ return o.y ? o.y!.length : o.y!.length;
198
+ }
199
+ # #1818 review round 1, N2a: nested ternary. The assertion's NEAREST
200
+ # ternary is the INNER one, whose own condition (`flag`) does not
201
+ # match the asserted object/property — so it must still flag, even
202
+ # though an OUTER ternary's condition happens to match. Proves
203
+ # `stopBy: kind: ternary_expression` is a real boundary: weakening it
204
+ # to `end` lets the search escalate past the inner ternary (which
205
+ # correctly fails) to the outer one (which wrongly succeeds).
206
+ - |
207
+ function f(o: { y?: { length: number } }, flag: boolean) {
208
+ return o.y
209
+ ? flag
210
+ ? 1
211
+ : o.y!.length
212
+ : 0;
213
+ }
214
+ # #1818 review round 1, N2b: filter+map, but the asserted receiver is
215
+ # an UNRELATED variable, not the map callback's own parameter — must
216
+ # still flag. Proves the `$M` metavariable binding is load-bearing:
217
+ # decoupling it (e.g. to an unconstrained parameter name) would make
218
+ # ANY assertion inside ANY filter-then-map chain's callback body
219
+ # suppress, regardless of what is actually being asserted.
220
+ - |
221
+ function f(
222
+ rs: Array<{ sym?: { name: string } }>,
223
+ stray: { sym?: { name: string } },
224
+ ) {
225
+ return rs.filter((r) => r.sym).map((m) => stray.sym!.name);
226
+ }
@@ -2,6 +2,8 @@ id: no-reflect-apply-js
2
2
  valid:
3
3
  - 'fn.apply(obj, args)'
4
4
  - 'fn(...args)'
5
+ - 'const proxy = new Proxy(target, { apply(target, thisArg, args) { return Reflect.apply(target, thisArg, args); } });'
5
6
  invalid:
6
7
  - 'Reflect.apply(fn, obj, args)'
7
8
  - 'const r = Reflect.apply(target[method], target, argumentsList);'
9
+ - 'const ordinary = { apply(target, thisArg, args) { return Reflect.apply(target, thisArg, args); } };'
@@ -2,6 +2,8 @@ id: no-reflect-apply
2
2
  valid:
3
3
  - 'fn.apply(obj, args)'
4
4
  - 'fn(...args)'
5
+ - 'const proxy = new Proxy(target, { apply(target, thisArg, args) { return Reflect.apply(target, thisArg, args); } });'
5
6
  invalid:
6
7
  - 'Reflect.apply(fn, obj, args)'
7
8
  - 'const r = Reflect.apply(target[method], target, argumentsList);'
9
+ - 'const ordinary = { apply(target, thisArg, args) { return Reflect.apply(target, thisArg, args); } };'
@@ -2,7 +2,8 @@ id: no-reflect-get-js
2
2
  valid:
3
3
  - 'obj.prop'
4
4
  - 'obj[key]'
5
- - 'Reflect.get(target, prop, receiver)'
5
+ - 'const proxy = new Proxy(api, { get(target, prop, receiver) { return Reflect.get(target, prop, receiver); } });'
6
6
  invalid:
7
7
  - 'Reflect.get(obj, "key")'
8
8
  - 'const v = Reflect.get(target, prop);'
9
+ - 'const ordinary = { get(target, prop, receiver) { return Reflect.get(target, prop, receiver); } };'
@@ -2,7 +2,8 @@ id: no-reflect-get
2
2
  valid:
3
3
  - 'obj.prop'
4
4
  - 'obj[key]'
5
- - 'Reflect.get(target, prop, receiver)'
5
+ - 'const proxy = new Proxy(api, { get(target, prop, receiver) { return Reflect.get(target, prop, receiver); } });'
6
6
  invalid:
7
7
  - 'Reflect.get(obj, "key")'
8
8
  - 'const v = Reflect.get(target, prop);'
9
+ - 'const ordinary = { get(target, prop, receiver) { return Reflect.get(target, prop, receiver); } };'
@@ -11,6 +11,12 @@ valid:
11
11
  - |
12
12
  def regular():
13
13
  return 42
14
+ - |
15
+ @asynccontextmanager
16
+ async def lifespan(app):
17
+ def handler():
18
+ return 42
19
+ yield
14
20
  invalid:
15
21
  - |
16
22
  def gen():
@@ -20,3 +26,9 @@ invalid:
20
26
  def gen():
21
27
  yield from iter([1, 2])
22
28
  return result
29
+ - |
30
+ def outer():
31
+ def inner_gen():
32
+ yield 1
33
+ return 99
34
+ return inner_gen
@@ -0,0 +1,33 @@
1
+ id: no-runtime-typeof
2
+ valid:
3
+ - |
4
+ function isFoo(x: unknown): x is Foo {
5
+ return typeof x === "object";
6
+ }
7
+ - |
8
+ const isBar = (x: unknown): x is Bar => typeof x === "object";
9
+ - |
10
+ function parseThing(x: unknown) {
11
+ return typeof x === "string";
12
+ }
13
+ - |
14
+ const validateThing = (x: unknown) => typeof x === "string";
15
+ - |
16
+ class C {
17
+ isFoo(x: unknown): x is Foo {
18
+ return typeof x === "object";
19
+ }
20
+ }
21
+ invalid:
22
+ - |
23
+ function plain(x: unknown) {
24
+ return typeof x === "string";
25
+ }
26
+ - |
27
+ const check = (x: unknown) => typeof x === "string";
28
+ - |
29
+ class C {
30
+ plain(x: unknown) {
31
+ return typeof x === "string";
32
+ }
33
+ }
@@ -4,7 +4,16 @@ valid:
4
4
  - "app.run(host='localhost', port=8000)"
5
5
  - "uvicorn.run(app, host='127.0.0.1', port=8000)"
6
6
  - "uvicorn.run(app, host=HOST, port=PORT)" # env var is OK
7
+ - |
8
+ return Settings.model_construct(
9
+ gh_proxy_bind_host='0.0.0.0',
10
+ )
7
11
  invalid:
8
12
  - "app.run(host='0.0.0.0', port=8000)"
9
13
  - "uvicorn.run(app, host='0.0.0.0', port=8000)"
10
14
  - 'app.run(host="0.0.0.0", port=8000)'
15
+ - "server.listen(host='0.0.0.0', port=8000)"
16
+ - "app.serve(host='0.0.0.0', port=8000)"
17
+ - "run(host='0.0.0.0', port=8000)"
18
+ - "config = uvicorn.Config(app, host='0.0.0.0', port=8000)"
19
+ - "app.run_server(host='0.0.0.0', port=8000)"
@@ -0,0 +1,13 @@
1
+ id: no-shape-in-symbol-names
2
+ valid:
3
+ - "const manifest = 1;"
4
+ - "interface I { name: string; }"
5
+ - "type Manifest = 1;"
6
+ invalid:
7
+ - "const shape = 1;"
8
+ - "const packageJsonShape = 1;"
9
+ - "class C { shapeField = 1; }"
10
+ - "class C { #shapeField = 1; }"
11
+ - "interface I { shapeProp: string; }"
12
+ - "type PackageJsonShape = 1;"
13
+ - "function reshape() {}"
@@ -3,8 +3,12 @@ valid:
3
3
  - "db.find({ id })"
4
4
  - "db.findOne({ where: { id } })"
5
5
  - 'sql.unsafe("non-sql")'
6
- invalid:
7
6
  - 'db.query("SELECT * FROM users")'
8
7
  - 'db.query("INSERT INTO x VALUES (1)")'
9
8
  - 'db.query("UPDATE users SET x = 1")'
10
9
  - 'db.query("SELECT * FROM users WHERE id = ?", [id])'
10
+ - 'db.query("SELECT * FROM " + "users")'
11
+ invalid:
12
+ - 'db.query("SELECT * FROM users WHERE id = " + id)'
13
+ - 'db.query("DELETE FROM sessions WHERE token = " + token, [])'
14
+ - 'db.query(`SELECT * FROM users WHERE id = ${id}`)'
@@ -3,8 +3,12 @@ valid:
3
3
  - "db.find({ id })"
4
4
  - "db.findOne({ where: { id } })"
5
5
  - 'sql.unsafe("non-sql")'
6
- invalid:
7
6
  - 'db.query("SELECT * FROM users")'
8
7
  - 'db.query("INSERT INTO x VALUES (1)")'
9
8
  - 'db.query("UPDATE users SET x = 1")'
10
9
  - 'db.query("SELECT * FROM users WHERE id = ?", [id])'
10
+ - 'db.query("SELECT * FROM " + "users")'
11
+ invalid:
12
+ - 'db.query("SELECT * FROM users WHERE id = " + id)'
13
+ - 'db.query("DELETE FROM sessions WHERE token = " + token, [])'
14
+ - 'db.query(`SELECT * FROM users WHERE id = ${id}`)'
@@ -0,0 +1,12 @@
1
+ id: no-unknown-parameters
2
+ valid:
3
+ - "function f(x: string) {}"
4
+ - "function f(cause: unknown) {}"
5
+ - "const g = (cause?: unknown) => {};"
6
+ - "class C { m(cause: unknown) {} }"
7
+ invalid:
8
+ - "function f(x: unknown) {}"
9
+ - "const g = (x: unknown) => {};"
10
+ - "class C { m(x: unknown) {} }"
11
+ - "interface I { m(x: unknown): void; }"
12
+ - "function f(x?: unknown) {}"
@@ -0,0 +1,16 @@
1
+ id: no-unknown-returns
2
+ valid:
3
+ - "function f(x: unknown): string { return String(x); }"
4
+ - "const g = (x: unknown): number => 1;"
5
+ - "class C { m(): void {} }"
6
+ # #1824: a function_type is a TYPE-POSITION annotation (a callback
7
+ # signature or type alias), not a value returning unknown — "the
8
+ # caller ignores my result" is a legitimate contract, so it must not
9
+ # flag. Covers both a standalone alias and a parameter position use.
10
+ - "type H = () => unknown;"
11
+ - "interface I { on(cb: () => unknown): void; }"
12
+ invalid:
13
+ - "function f(): unknown { return 1; }"
14
+ - "const g = (): unknown => 1;"
15
+ - "class C { m(): unknown { return 1; } }"
16
+ - "interface I { m(): unknown; }"
@@ -0,0 +1,10 @@
1
+ id: no-unsafe-dictionary-any
2
+ valid:
3
+ - "type T = Record<string, unknown>;"
4
+ - "function f(x: Record<string, string>) {}"
5
+ - "interface I { m: Record<string, number>; }"
6
+ invalid:
7
+ - "type T = Record<string, any>;"
8
+ - "function f(x: Record<string, any>) {}"
9
+ - "interface I { m: Record<string, any>; }"
10
+ - "const m: Record<number, any> = {};"
@@ -0,0 +1,8 @@
1
+ id: no-unsafe-dictionary-unknown
2
+ valid:
3
+ - "type T = Record<string, string>;"
4
+ - "function f(x: Record<string, any>) {}"
5
+ invalid:
6
+ - "type T = Record<string, unknown>;"
7
+ - "function f(x: Record<string, unknown>) {}"
8
+ - "interface I { m: Record<string, unknown>; }"
@@ -9,6 +9,16 @@ valid:
9
9
  }
10
10
  - |
11
11
  fn f() -> i32 { 42 }
12
+ - |
13
+ /// Dereferences a raw pointer.
14
+ ///
15
+ /// # Safety
16
+ ///
17
+ /// Caller must ensure the pointer is valid and aligned.
18
+ unsafe fn ptr_deref(p: *const i32) -> i32 {
19
+ let x = 1;
20
+ x
21
+ }
12
22
  invalid:
13
23
  - |
14
24
  unsafe fn f() {
@@ -23,3 +33,28 @@ invalid:
23
33
  let ptr = 0x1234 as *const i32;
24
34
  ptr
25
35
  }
36
+ - |
37
+ /// Does something.
38
+ unsafe fn no_real_safety_doc() {
39
+ println!("nope");
40
+ }
41
+ - |
42
+ // # Safety
43
+ // This is a stray file-top comment, not attached to any function.
44
+
45
+ fn helper() {}
46
+
47
+ unsafe fn no_doc_at_all() {
48
+ println!("bad 1");
49
+ }
50
+ - |
51
+ /// # Safety
52
+ /// Caller must ensure the pointer is valid.
53
+ unsafe fn documented_fn(p: *const i32) -> i32 {
54
+ let x = 1;
55
+ x
56
+ }
57
+
58
+ unsafe fn undocumented_fn_b() {
59
+ println!("no doc for me");
60
+ }
@@ -0,0 +1,177 @@
1
+ id: require-safety-comment-for-as-unknown-as
2
+ valid:
3
+ - |
4
+ // SAFETY: checked above
5
+ const a = x as unknown as Foo;
6
+ - |
7
+ const b = /* SAFETY: inline */ x as unknown as Foo;
8
+ - |
9
+ // SAFETY: arg is validated upstream
10
+ foo(x as unknown as Foo);
11
+ # 2026-08-20 (#1727/#1777): this rule now owns the `as unknown as` shape
12
+ # alone, so a single concrete `as` and a concrete CHAIN are both out of scope
13
+ # here (the chain belongs to no-chained-type-assertions.yml). Widening the
14
+ # pattern back to any assertion reds both.
15
+ - 'const c = x as Foo;'
16
+ - 'const d = x as A as B;'
17
+ # #1847: the `inside:` kind list omitted `export_statement`, so a
18
+ # SAFETY: comment above an EXPORTED cast could not satisfy the valve.
19
+ # Dropping `export_statement` from the rule's kind list reds this case.
20
+ - |
21
+ // SAFETY: node exposes this at runtime, absent from @types/node
22
+ export const b = (globalThis as unknown as { z: number }).z;
23
+ # #1847: same gap for a class-field cast — the kind list omitted
24
+ # `public_field_definition`. Dropping it from the rule's kind list
25
+ # reds this case.
26
+ - |
27
+ class Foo {
28
+ // SAFETY: server always sends this field at runtime
29
+ bar: unknown = (globalThis as unknown as { z: number }).z;
30
+ }
31
+ # #1852 review (F1): same gap for an enum member's initializer cast —
32
+ # the kind list omitted `enum_assignment`. Dropping it from the
33
+ # rule's kind list reds this case. Covers plain, `const`, and
34
+ # `export` enum alike — `enum_assignment` is the member node itself,
35
+ # unaffected by keywords on the enclosing `enum_declaration`.
36
+ # (`declare enum` members have no initializer expression to cast, so
37
+ # there is nothing to probe for that flavor.)
38
+ - |
39
+ enum Direction {
40
+ // SAFETY: node exposes this at runtime, absent from @types/node
41
+ Up = (globalThis as unknown as { z: number }).z,
42
+ }
43
+ - |
44
+ const enum Direction {
45
+ // SAFETY: node exposes this at runtime, absent from @types/node
46
+ Up = (globalThis as unknown as { z: number }).z,
47
+ }
48
+ - |
49
+ export enum Direction {
50
+ // SAFETY: node exposes this at runtime, absent from @types/number
51
+ Up = (globalThis as unknown as { z: number }).z,
52
+ }
53
+ # #1852 review over-suppression probe: two casts inside ONE exported
54
+ # declaration under a single SAFETY: comment. This is pre-existing
55
+ # behavior, not new — the same one-comment-covers-the-whole-statement
56
+ # trade already applied to `lexical_declaration`/`variable_declaration`
57
+ # before #1847 (verified: an unexported `const pair = {a: x as unknown
58
+ # as Foo, b: y as unknown as Foo}` under one SAFETY: comment was
59
+ # already 0 findings on master). The "Scope and known gap" note above
60
+ # states the valve is statement-scoped, not cast-scoped, by design:
61
+ # "a comment is accepted if it directly precedes... the assertion's
62
+ # containing... statement." `export_statement` inherits that same
63
+ # trade; it does not introduce a new one. Locked in here so a future
64
+ # narrowing of the scope is a deliberate choice, not an accident.
65
+ - |
66
+ // SAFETY: both fields document the same upstream payload shape
67
+ export const pair = { a: x as unknown as Foo, b: y as unknown as Foo };
68
+ # #1870: tree-sitter-typescript calls an object-literal member a `pair`.
69
+ # A comment directly above that pair is the natural local anchor.
70
+ - |
71
+ const config = {
72
+ // SAFETY: input is validated by the config loader
73
+ value: input as unknown as string,
74
+ };
75
+ - |
76
+ configure({
77
+ // SAFETY: input is validated by the config loader
78
+ value: input as unknown as string,
79
+ });
80
+ # Direct comments immediately above casts in array elements and call
81
+ # arguments are supported by the direct-cast arm.
82
+ - |
83
+ const values = [
84
+ // SAFETY: input is validated by the config loader
85
+ input as unknown as string,
86
+ ];
87
+ - |
88
+ configure(
89
+ // SAFETY: input is validated by the config loader
90
+ input as unknown as string,
91
+ );
92
+ invalid:
93
+ - "const a = x as unknown as Foo;"
94
+ - |
95
+ const b = x as unknown as Foo; // no safety note
96
+ - |
97
+ // some other comment
98
+ const c = x as unknown as Foo;
99
+ # The comment must actually claim safety. A comment mentioning the word in
100
+ # prose without the `SAFETY:` marker does not clear it — deleting the
101
+ # `SAFETY\s*:` regex from the rule reds this case.
102
+ - |
103
+ // this cast is safe, trust me
104
+ const d = x as unknown as Foo;
105
+ # #1834: the `follows: {stopBy: end}` scan is unbounded — it must not walk
106
+ # past the contiguous comment block into an EARLIER statement's SAFETY:
107
+ # comment. A stray SAFETY: comment anywhere earlier in the same block must
108
+ # not exempt a later, undocumented cast.
109
+ - |
110
+ function f(x: unknown, y: unknown) {
111
+ // SAFETY: this comment documents a DIFFERENT assertion below.
112
+ const a = (y as unknown as string).length;
113
+
114
+ const b = (x as unknown as string).length;
115
+ return a + b;
116
+ }
117
+ # SAFETY: on cast A must not bleed to cast B directly below it, even with
118
+ # no other statement in between.
119
+ - |
120
+ // SAFETY: documents castA only
121
+ const castA = a as unknown as Foo;
122
+ const castB = b as unknown as Foo;
123
+ # #1847: an exported cast with no SAFETY: comment must still flag —
124
+ # adding `export_statement` to the valve must not turn it into a
125
+ # blanket exemption for every exported cast.
126
+ - "export const b = (globalThis as unknown as { z: number }).z;"
127
+ # #1847: an undocumented class-field cast must still flag — adding
128
+ # `public_field_definition` to the valve must not exempt every field
129
+ # cast regardless of a SAFETY: comment.
130
+ - |
131
+ class Foo {
132
+ bar: unknown = (globalThis as unknown as { z: number }).z;
133
+ }
134
+ # #1852 review (F1): an undocumented enum-member cast must still flag
135
+ # — adding `enum_assignment` to the valve must not exempt every enum
136
+ # member cast regardless of a SAFETY: comment.
137
+ - |
138
+ enum Direction {
139
+ Up = (globalThis as unknown as { z: number }).z,
140
+ }
141
+ # #1852 review over-suppression probe: a SAFETY: comment separated
142
+ # from the cast by an unrelated statement must NOT suppress. This is
143
+ # already enforced by #1834's `stopBy: {not: {kind: comment}}` bound
144
+ # (the comment is no longer the statement's immediate preceding
145
+ # sibling once another statement sits between them), but it had no
146
+ # dedicated minimal fixture — the existing #1834 cases both pair the
147
+ # comment with a DIFFERENT documented cast, not a bare intervening
148
+ # statement.
149
+ - |
150
+ // SAFETY: documents nothing below — an unrelated call sits between
151
+ doSomethingUnrelated();
152
+ const b = x as unknown as Foo;
153
+ # A comment on an unrelated sibling pair must not reach a later pair.
154
+ - |
155
+ const config = {
156
+ unrelated: 1,
157
+ // SAFETY: this documents a different property
158
+ other: 2,
159
+ target: input as unknown as string,
160
+ };
161
+ # An outer pair comment must not cross into a nested pair.
162
+ - |
163
+ const config = {
164
+ // SAFETY: only the parent property is validated
165
+ parent: {
166
+ nestedTarget: value as unknown as string,
167
+ },
168
+ };
169
+ # A nested pair comment must not travel outward to a parent cast.
170
+ - |
171
+ const config = {
172
+ parent: value as unknown as string,
173
+ // SAFETY: only the nested property is validated
174
+ nested: {
175
+ child: value as unknown as string,
176
+ },
177
+ };
@@ -3,6 +3,7 @@ valid:
3
3
  - 'undefined'
4
4
  - 'void x'
5
5
  - 'void 1'
6
+ - 'function probe(undefined) { return undefined; }'
6
7
  invalid:
7
8
  - 'void 0'
8
9
  - 'const x = void 0'