@herbertgao/pi-extensions 2026.8.13 → 2026.8.15

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 (263) hide show
  1. package/README.md +19 -14
  2. package/THIRD_PARTY_NOTICES.md +0 -1
  3. package/node_modules/@czottmann/pi-automode/CHANGELOG.md +19 -0
  4. package/node_modules/@czottmann/pi-automode/README.md +5 -1
  5. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/classifier.ts +126 -13
  6. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/config.ts +7 -3
  7. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/constants.ts +2 -0
  8. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/hard-deny.ts +134 -23
  9. package/node_modules/@czottmann/pi-automode/package.json +1 -1
  10. package/node_modules/@herbertgao/{pi-stash → pi-bark}/LICENSE +4 -5
  11. package/node_modules/@herbertgao/pi-bark/README.md +44 -0
  12. package/node_modules/@herbertgao/pi-bark/assets/pi-icon.png +0 -0
  13. package/node_modules/@herbertgao/pi-bark/package.json +53 -0
  14. package/node_modules/@herbertgao/pi-bark/src/index.ts +178 -0
  15. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +1 -1
  16. package/node_modules/@herbertgao/pi-cc-extensions/README.md +1 -1
  17. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  18. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +6 -0
  19. package/node_modules/@herbertgao/pi-subagents/package.json +2 -1
  20. package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +8 -1
  21. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
  22. package/node_modules/@narumitw/pi-btw/README.md +125 -88
  23. package/node_modules/@narumitw/pi-btw/dist/index.ts +140 -45
  24. package/node_modules/@narumitw/pi-btw/dist/index.ts.map +2 -2
  25. package/node_modules/@narumitw/pi-btw/package.json +5 -8
  26. package/node_modules/@narumitw/pi-btw/src/btw.ts +31 -26
  27. package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +106 -17
  28. package/node_modules/@narumitw/pi-btw/src/menu.ts +34 -2
  29. package/node_modules/@narumitw/pi-btw/src/settings.ts +16 -0
  30. package/node_modules/@tifan/pi-handoff/README.md +36 -13
  31. package/node_modules/@tifan/pi-handoff/package.json +2 -2
  32. package/node_modules/@tifan/pi-handoff/src/index.ts +160 -4
  33. package/node_modules/@tifan/pi-preferred-thinking/README.md +1 -1
  34. package/node_modules/@tifan/pi-preferred-thinking/package.json +1 -1
  35. package/node_modules/@tifan/pi-preferred-thinking/src/index.ts +15 -2
  36. package/node_modules/@tifan/pi-recap/README.md +1 -1
  37. package/node_modules/@tifan/pi-recap/package.json +2 -2
  38. package/node_modules/@tifan/pi-recap/src/index.ts +15 -0
  39. package/node_modules/@tifan/pi-rename/README.md +42 -21
  40. package/node_modules/@tifan/pi-rename/package.json +1 -1
  41. package/node_modules/@tifan/pi-rename/src/index.ts +62 -11
  42. package/node_modules/@tifan/pi-rename/src/language.ts +18 -0
  43. package/node_modules/@tifan/pi-rename/src/models.ts +69 -13
  44. package/node_modules/@tifan/pi-rename/src/naming.ts +36 -7
  45. package/node_modules/@tifan/pi-rename/src/sanitize.ts +22 -14
  46. package/node_modules/pi-lens/CHANGELOG.md +320 -0
  47. package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +79 -0
  48. package/node_modules/pi-lens/dist/clients/actionable-warnings-logger.js +16 -1
  49. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +13 -6
  50. package/node_modules/pi-lens/dist/clients/availability-probe-flight.js +12 -0
  51. package/node_modules/pi-lens/dist/clients/biome-client.js +7 -0
  52. package/node_modules/pi-lens/dist/clients/blocker-freshness.js +20 -0
  53. package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +56 -19
  54. package/node_modules/pi-lens/dist/clients/build-identity.js +95 -0
  55. package/node_modules/pi-lens/dist/clients/bus-publish.js +3 -0
  56. package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +2 -1
  57. package/node_modules/pi-lens/dist/clients/cache-observability.js +2 -1
  58. package/node_modules/pi-lens/dist/clients/cascade-logger.js +15 -1
  59. package/node_modules/pi-lens/dist/clients/dead-code-client.js +14 -11
  60. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +56 -4
  61. package/node_modules/pi-lens/dist/clients/demoted-finding-render.js +14 -0
  62. package/node_modules/pi-lens/dist/clients/dependency-checker.js +20 -3
  63. package/node_modules/pi-lens/dist/clients/deps/minimatch.js +1 -1
  64. package/node_modules/pi-lens/dist/clients/dispatch/collect-later-tier.js +39 -0
  65. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +150 -9
  66. package/node_modules/pi-lens/dist/clients/dispatch/fact-store.js +231 -9
  67. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +205 -100
  68. package/node_modules/pi-lens/dist/clients/dispatch/pending-runner-findings.js +87 -0
  69. package/node_modules/pi-lens/dist/clients/dispatch/plan.js +21 -5
  70. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +174 -55
  71. package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +5 -1
  72. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +16 -3
  73. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +54 -9
  74. package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +1 -3
  75. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +37 -1
  76. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +4 -1
  77. package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +11 -4
  78. package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +4 -0
  79. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +8 -3
  80. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +76 -25
  81. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +4 -0
  82. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +19 -7
  83. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +7 -13
  84. package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +51 -17
  85. package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +66 -1
  86. package/node_modules/pi-lens/dist/clients/file-utils.js +157 -7
  87. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +5 -0
  88. package/node_modules/pi-lens/dist/clients/formatters.js +28 -3
  89. package/node_modules/pi-lens/dist/clients/git-guard.js +197 -47
  90. package/node_modules/pi-lens/dist/clients/git-tracked-ignore.js +32 -1
  91. package/node_modules/pi-lens/dist/clients/govulncheck-client.js +5 -1
  92. package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +7 -0
  93. package/node_modules/pi-lens/dist/clients/installer/index.js +131 -34
  94. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +3 -1
  95. package/node_modules/pi-lens/dist/clients/instance-reaper.js +4 -13
  96. package/node_modules/pi-lens/dist/clients/instance-registry-lock.js +145 -0
  97. package/node_modules/pi-lens/dist/clients/instance-registry.js +432 -122
  98. package/node_modules/pi-lens/dist/clients/jscpd-client.js +6 -1
  99. package/node_modules/pi-lens/dist/clients/language-profile.js +4 -2
  100. package/node_modules/pi-lens/dist/clients/latency-logger.js +19 -1
  101. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +8 -0
  102. package/node_modules/pi-lens/dist/clients/lens-map.js +3 -1
  103. package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +4 -0
  104. package/node_modules/pi-lens/dist/clients/lsp/client.js +516 -31
  105. package/node_modules/pi-lens/dist/clients/lsp/config.js +25 -2
  106. package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +9 -4
  107. package/node_modules/pi-lens/dist/clients/lsp/index.js +509 -182
  108. package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +5 -0
  109. package/node_modules/pi-lens/dist/clients/lsp/launch.js +36 -8
  110. package/node_modules/pi-lens/dist/clients/lsp/pending-aux-coverage.js +116 -4
  111. package/node_modules/pi-lens/dist/clients/lsp/server.js +142 -13
  112. package/node_modules/pi-lens/dist/clients/lsp/session-roots.js +99 -0
  113. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +16 -6
  114. package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +32 -23
  115. package/node_modules/pi-lens/dist/clients/lsp-mutation.js +16 -2
  116. package/node_modules/pi-lens/dist/clients/mcp/analyze.js +12 -6
  117. package/node_modules/pi-lens/dist/clients/mcp/session.js +14 -1
  118. package/node_modules/pi-lens/dist/clients/memory-sampler.js +23 -1
  119. package/node_modules/pi-lens/dist/clients/message-end-attribution.js +30 -0
  120. package/node_modules/pi-lens/dist/clients/metrics-history.js +21 -4
  121. package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +232 -18
  122. package/node_modules/pi-lens/dist/clients/package-manager.js +6 -18
  123. package/node_modules/pi-lens/dist/clients/path-keyed-map.js +14 -1
  124. package/node_modules/pi-lens/dist/clients/path-utils.js +32 -0
  125. package/node_modules/pi-lens/dist/clients/pipeline.js +0 -8
  126. package/node_modules/pi-lens/dist/clients/process-singletons.js +210 -0
  127. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/madge.js +2 -1
  128. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +10 -4
  129. package/node_modules/pi-lens/dist/clients/project-snapshot.js +33 -11
  130. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +24 -2
  131. package/node_modules/pi-lens/dist/clients/read-guard.js +74 -7
  132. package/node_modules/pi-lens/dist/clients/recent-touches.js +17 -5
  133. package/node_modules/pi-lens/dist/clients/review-graph/builder.js +639 -62
  134. package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +5 -1
  135. package/node_modules/pi-lens/dist/clients/review-graph-logger.js +21 -1
  136. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +68 -0
  137. package/node_modules/pi-lens/dist/clients/runtime-session.js +30 -12
  138. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +15 -0
  139. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +106 -7
  140. package/node_modules/pi-lens/dist/clients/runtime-turn.js +242 -27
  141. package/node_modules/pi-lens/dist/clients/safe-spawn.js +158 -18
  142. package/node_modules/pi-lens/dist/clients/security-scan-client.js +48 -17
  143. package/node_modules/pi-lens/dist/clients/session-lifecycle.js +238 -42
  144. package/node_modules/pi-lens/dist/clients/sg-runner.js +27 -15
  145. package/node_modules/pi-lens/dist/clients/shared-checkout-guard.js +338 -0
  146. package/node_modules/pi-lens/dist/clients/spawn-output-cap.js +37 -0
  147. package/node_modules/pi-lens/dist/clients/spawn-timeout-cooldown.js +15 -1
  148. package/node_modules/pi-lens/dist/clients/startup-scan.js +6 -7
  149. package/node_modules/pi-lens/dist/clients/startup-timing.js +69 -4
  150. package/node_modules/pi-lens/dist/clients/string-utils.js +20 -0
  151. package/node_modules/pi-lens/dist/clients/test-runner-client.js +419 -88
  152. package/node_modules/pi-lens/dist/clients/tool-policy.js +1 -1
  153. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +11 -5
  154. package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +17 -1
  155. package/node_modules/pi-lens/dist/clients/warm-attach.js +8 -10
  156. package/node_modules/pi-lens/dist/clients/word-index-logger.js +13 -1
  157. package/node_modules/pi-lens/dist/clients/word-index-store.js +448 -0
  158. package/node_modules/pi-lens/dist/clients/word-index.js +582 -104
  159. package/node_modules/pi-lens/dist/clients/workspace-topology.js +17 -0
  160. package/node_modules/pi-lens/dist/clients/zizmor-config.js +26 -6
  161. package/node_modules/pi-lens/dist/index.js +11243 -6651
  162. package/node_modules/pi-lens/dist/mcp/build-staleness.js +8 -7
  163. package/node_modules/pi-lens/dist/mcp/cli.js +3 -1
  164. package/node_modules/pi-lens/dist/mcp/server.js +6 -1
  165. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +4 -0
  166. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +14 -5
  167. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +3 -1
  168. package/node_modules/pi-lens/docs/agent-guide.md +4 -2
  169. package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +41 -10
  170. package/node_modules/pi-lens/docs/astplayground.md +26 -17
  171. package/node_modules/pi-lens/package.json +5 -1
  172. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/c-no-malloc-free-test.yml +20 -0
  173. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/cpp-no-malloc-free-test.yml +25 -0
  174. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/cpp-no-printf-test.yml +19 -0
  175. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/go-no-fmt-println-test.yml +19 -0
  176. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/go-no-panic-in-lib-test.yml +17 -0
  177. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/go-no-underscore-func-name-test.yml +18 -0
  178. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/go-prefer-errors-is-test.yml +15 -0
  179. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/go-prefer-string-builder-test.yml +21 -0
  180. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/hyphenated-svg-attribute-test.yml +11 -0
  181. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-lateinit-test.yml +17 -0
  182. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-nullable-boolean-test.yml +15 -0
  183. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-println-test.yml +19 -0
  184. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-unnecessary-let-test.yml +7 -0
  185. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-unsafe-cast-test.yml +7 -0
  186. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-var-test.yml +7 -0
  187. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-prefer-data-class-test.yml +25 -0
  188. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-prefer-is-empty-test.yml +11 -0
  189. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-important-test.yml +21 -0
  190. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-raw-types-test.yml +30 -0
  191. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-string-concat-in-loop-test.yml +100 -0
  192. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-system-out-println-test.yml +7 -0
  193. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/prefer-string-is-empty-test.yml +7 -0
  194. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/python-optional-type-test.yml +9 -0
  195. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/reducible-list-comprehension-test.yml +11 -0
  196. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/ruby-symbol-to-proc-candidate-test.yml +10 -0
  197. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/rust-no-chars-enumerate-test.yml +7 -0
  198. package/node_modules/pi-lens/rules/ast-grep-rules/rules/c-no-malloc-free.yml +39 -0
  199. package/node_modules/pi-lens/rules/ast-grep-rules/rules/cpp-no-malloc-free.yml +45 -0
  200. package/node_modules/pi-lens/rules/ast-grep-rules/rules/cpp-no-printf.yml +41 -0
  201. package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-no-fmt-println.yml +43 -0
  202. package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-no-panic-in-lib.yml +41 -0
  203. package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-no-underscore-func-name.yml +35 -0
  204. package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-prefer-errors-is.yml +40 -0
  205. package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-prefer-string-builder.yml +43 -0
  206. package/node_modules/pi-lens/rules/ast-grep-rules/rules/hyphenated-svg-attribute.yml +32 -0
  207. package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-lateinit.yml +37 -0
  208. package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-nullable-boolean.yml +33 -0
  209. package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-println.yml +42 -0
  210. package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-unnecessary-let.yml +28 -0
  211. package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-unsafe-cast.yml +28 -0
  212. package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-var.yml +35 -0
  213. package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-prefer-data-class.yml +66 -0
  214. package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-prefer-is-empty.yml +35 -0
  215. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-important.yml +21 -0
  216. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-types.yml +33 -0
  217. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-string-concat-in-loop.yml +90 -0
  218. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-system-out-println.yml +16 -0
  219. package/node_modules/pi-lens/rules/ast-grep-rules/rules/prefer-string-is-empty.yml +11 -0
  220. package/node_modules/pi-lens/rules/ast-grep-rules/rules/python-optional-type.yml +22 -0
  221. package/node_modules/pi-lens/rules/ast-grep-rules/rules/reducible-list-comprehension.yml +29 -0
  222. package/node_modules/pi-lens/rules/ast-grep-rules/rules/ruby-symbol-to-proc-candidate.yml +25 -0
  223. package/node_modules/pi-lens/rules/ast-grep-rules/rules/rust-no-chars-enumerate.yml +19 -0
  224. package/node_modules/pi-mcp-adapter/CHANGELOG.md +35 -0
  225. package/node_modules/pi-mcp-adapter/README.md +5 -2
  226. package/node_modules/pi-mcp-adapter/cli.js +4 -4
  227. package/node_modules/pi-mcp-adapter/commands.ts +1 -1
  228. package/node_modules/pi-mcp-adapter/config.ts +1 -0
  229. package/node_modules/pi-mcp-adapter/dist/config.js +1 -0
  230. package/node_modules/pi-mcp-adapter/dist/config.js.map +1 -1
  231. package/node_modules/pi-mcp-adapter/dist/mcp-bearer-store.d.ts +24 -0
  232. package/node_modules/pi-mcp-adapter/dist/mcp-bearer-store.js +336 -0
  233. package/node_modules/pi-mcp-adapter/dist/mcp-bearer-store.js.map +1 -0
  234. package/node_modules/pi-mcp-adapter/dist/types.d.ts +3 -1
  235. package/node_modules/pi-mcp-adapter/dist/types.js.map +1 -1
  236. package/node_modules/pi-mcp-adapter/index.ts +90 -6
  237. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +124 -32
  238. package/node_modules/pi-mcp-adapter/mcp-bearer-store.ts +0 -2
  239. package/node_modules/pi-mcp-adapter/mcp-oauth-provider.ts +89 -0
  240. package/node_modules/pi-mcp-adapter/mcp-references.ts +9 -1
  241. package/node_modules/pi-mcp-adapter/package.json +1 -1
  242. package/node_modules/pi-mcp-adapter/proxy-modes.ts +62 -22
  243. package/node_modules/pi-mcp-adapter/request-headers-command.ts +1 -1
  244. package/node_modules/pi-mcp-adapter/server-manager.ts +6 -0
  245. package/node_modules/pi-mcp-adapter/types.ts +3 -1
  246. package/node_modules/pi-web-access/CHANGELOG.md +42 -0
  247. package/node_modules/pi-web-access/README.md +26 -10
  248. package/node_modules/pi-web-access/curator-page.ts +12 -3
  249. package/node_modules/pi-web-access/curator-server.ts +3 -1
  250. package/node_modules/pi-web-access/extract.ts +88 -13
  251. package/node_modules/pi-web-access/gemini-search.ts +10 -5
  252. package/node_modules/pi-web-access/github-extract.ts +47 -3
  253. package/node_modules/pi-web-access/index.ts +40 -40
  254. package/node_modules/pi-web-access/package.json +1 -1
  255. package/node_modules/pi-web-access/page-query.ts +61 -8
  256. package/node_modules/pi-web-access/xcrawl.ts +264 -0
  257. package/package.json +19 -22
  258. package/node_modules/@herbertgao/pi-stash/README.md +0 -34
  259. package/node_modules/@herbertgao/pi-stash/package.json +0 -51
  260. package/node_modules/@herbertgao/pi-stash/src/index.ts +0 -118
  261. package/node_modules/@tifan/pi-titlebar-spinner/README.md +0 -24
  262. package/node_modules/@tifan/pi-titlebar-spinner/package.json +0 -39
  263. package/node_modules/@tifan/pi-titlebar-spinner/src/index.ts +0 -49
@@ -0,0 +1,43 @@
1
+ # Go Prefer strings.Builder Over Repeated Concatenation
2
+ # Detects repeated string concatenation (x = x + y / x += "y") that should use
3
+ # strings.Builder instead. The += arm requires a string literal because
4
+ # ast-grep has no type information to distinguish string and numeric operands.
5
+ # Ported from vinhnx/VTCode rules/go/prefer-string-builder.yml
6
+ # (#2200, refs #2195).
7
+ id: go-prefer-string-builder
8
+ language: go
9
+ severity: hint
10
+ message: "Use strings.Builder instead of repeated string concatenation"
11
+ note: |
12
+ Repeated string concatenation with + creates a new string allocation on
13
+ each operation (O(n^2) total). strings.Builder accumulates bytes in a
14
+ buffer and produces the final string with one allocation.
15
+ Detection-only, with no autofix: a single concatenation site cannot show
16
+ this is a genuine accumulation loop rather than a one-off assignment where
17
+ concatenation is clearer, and no fix can safely introduce the surrounding
18
+ strings.Builder declaration and .String() call. Scoped to non-test Go
19
+ files.
20
+ rule:
21
+ any:
22
+ - pattern: $VAR = $VAR + $OTHER
23
+ - pattern: $VAR += "$OTHER"
24
+ ignores:
25
+ - "**/*_test.go"
26
+ tags:
27
+ - go
28
+ - idiom
29
+ - performance
30
+ examples:
31
+ bad: |
32
+ func concat(a string, b string) string {
33
+ a = a + b
34
+ return a
35
+ }
36
+ good: |
37
+ func build(parts []string) string {
38
+ var b strings.Builder
39
+ for _, p := range parts {
40
+ b.WriteString(p)
41
+ }
42
+ return b.String()
43
+ }
@@ -0,0 +1,32 @@
1
+ id: hyphenated-svg-attribute
2
+ language: Tsx
3
+ severity: warning
4
+ message: "Use camelCase for this known SVG attribute in JSX"
5
+ note: |
6
+ React JSX uses camelCase for SVG attributes. The rule is limited to the
7
+ known SVG attribute names below, so custom elements and web components with
8
+ legitimate hyphenated properties are not reported.
9
+ rule:
10
+ kind: jsx_attribute
11
+ has:
12
+ kind: property_identifier
13
+ regex: "^(stroke-width|stroke-linecap|stroke-linejoin|stroke-miterlimit|stroke-dasharray|stroke-dashoffset|fill-rule|clip-rule|clip-path|font-family|font-size|font-weight|text-anchor|dominant-baseline|stop-color|stop-opacity|fill-opacity|stroke-opacity|color-interpolation-filters|shape-rendering|vector-effect|flood-color|flood-opacity|lighting-color|marker-height|marker-width|xlink-href|mask-type)$"
14
+ inside:
15
+ any:
16
+ - kind: jsx_self_closing_element
17
+ has:
18
+ field: name
19
+ regex: '^(svg|path|circle|rect|line|polyline|polygon|ellipse|g|defs|use|symbol|clipPath|mask|pattern|marker|linearGradient|radialGradient|stop|text|tspan|foreignObject)$'
20
+ - kind: jsx_opening_element
21
+ has:
22
+ field: name
23
+ regex: '^(svg|path|circle|rect|line|polyline|polygon|ellipse|g|defs|use|symbol|clipPath|mask|pattern|marker|linearGradient|radialGradient|stop|text|tspan|foreignObject)$'
24
+ has_fix: false
25
+ tags:
26
+ - tsx
27
+ - jsx
28
+ - svg
29
+ - modernization
30
+ examples:
31
+ bad: "const icon = <svg stroke-width=\"2\" />;"
32
+ good: "const icon = <svg strokeWidth=\"2\" />;"
@@ -0,0 +1,37 @@
1
+ # Kotlin No lateinit
2
+ # Detects `lateinit var` property declarations.
3
+ # Ported from vinhnx/VTCode rules/kotlin/no-lateinit.yml (#2198, refs #2195).
4
+ id: kotlin-no-lateinit
5
+ language: kotlin
6
+ severity: warning
7
+ message: "Avoid lateinit var; prefer a nullable type or constructor injection"
8
+ note: |
9
+ lateinit defers initialization past the constructor and throws
10
+ UninitializedPropertyAccessException on an unguarded read before the
11
+ property is set. A nullable type, a lazy delegate, or constructor/DI-based
12
+ initialization all make the missing-value case visible to the type system
13
+ instead of a runtime crash.
14
+ Detection-only: the correct replacement depends on the property's
15
+ lifecycle (Android view binding, DI-managed fields, test fixtures) and on
16
+ whether callers can tolerate a nullable read, both of which this rule
17
+ cannot verify.
18
+ rule:
19
+ kind: property_declaration
20
+ has:
21
+ kind: modifiers
22
+ has:
23
+ kind: member_modifier
24
+ regex: "^lateinit$"
25
+ files:
26
+ - "**/*.kt"
27
+ tags:
28
+ - kotlin
29
+ - idiom
30
+ - null-safety
31
+ examples:
32
+ bad: |
33
+ class UserRepository {
34
+ lateinit var apiClient: ApiClient
35
+ }
36
+ good: |
37
+ class UserRepository(private val apiClient: ApiClient)
@@ -0,0 +1,33 @@
1
+ # Kotlin No nullable Boolean
2
+ # Detects a `Boolean?` type on a property, parameter, or return type.
3
+ # Ported from vinhnx/VTCode rules/kotlin/no-nullable-boolean.yml (#2198, refs #2195).
4
+ id: kotlin-no-nullable-boolean
5
+ language: kotlin
6
+ severity: warning
7
+ message: "Avoid a nullable Boolean; a two-value enum or a non-null default is usually clearer"
8
+ note: |
9
+ A nullable Boolean gives a value three states (true/false/unknown) but the
10
+ type only documents two, so callers routinely forget to handle null and
11
+ either crash on an unboxing NPE or silently treat it as false.
12
+ Detection-only: null is a legitimate third state for some APIs (an
13
+ unanswered tri-state form field, a "not yet loaded" flag), and this rule
14
+ cannot tell that case from an accidental nullable Boolean.
15
+ rule:
16
+ kind: nullable_type
17
+ has:
18
+ kind: user_type
19
+ has:
20
+ kind: type_identifier
21
+ regex: "^Boolean$"
22
+ files:
23
+ - "**/*.kt"
24
+ tags:
25
+ - kotlin
26
+ - idiom
27
+ - null-safety
28
+ examples:
29
+ bad: |
30
+ fun isEligible(): Boolean? = null
31
+ good: |
32
+ enum class Eligibility { ELIGIBLE, INELIGIBLE, UNKNOWN }
33
+ fun eligibility(): Eligibility = Eligibility.UNKNOWN
@@ -0,0 +1,42 @@
1
+ # Kotlin No println
2
+ # Detects bare `println`/`print` calls.
3
+ # Ported from vinhnx/VTCode rules/kotlin/no-println.yml (#2198, refs #2195).
4
+ id: kotlin-no-println
5
+ language: kotlin
6
+ severity: warning
7
+ message: "Avoid println/print; use a structured logger"
8
+ note: |
9
+ Direct console output via println/print is not configurable and cannot be
10
+ routed to log aggregators or filtered by level. Use a structured logging
11
+ library (kotlin-logging, SLF4J, android.util.Log) for production code.
12
+ Detection-only: which logger to use, and whether a given call site is a
13
+ CLI entry point or a test where println is acceptable, is a project
14
+ policy call this rule cannot make.
15
+ Scoped to the unqualified call. A fully-qualified spelling
16
+ (`kotlin.io.println(...)`) is missed on purpose: syntactically it is the
17
+ same navigation-call shape as `anyReceiver.println(...)`, a member call on
18
+ an arbitrary type (a Writer, a PrintStream) that this rule must not flag,
19
+ and there is no type information here to tell the two apart.
20
+ rule:
21
+ any:
22
+ - pattern: println($$$ARGS)
23
+ - pattern: print($$$ARGS)
24
+ files:
25
+ - "**/*.kt"
26
+ ignores:
27
+ - "**/*Test.kt"
28
+ - "**/test/**"
29
+ tags:
30
+ - kotlin
31
+ - idiom
32
+ - logging
33
+ examples:
34
+ bad: |
35
+ fun main() {
36
+ println("starting up")
37
+ }
38
+ good: |
39
+ private val logger = KotlinLogging.logger {}
40
+ fun main() {
41
+ logger.info { "starting up" }
42
+ }
@@ -0,0 +1,28 @@
1
+ # Kotlin No unnecessary let
2
+ # Detects `.let { }` called on a receiver without a preceding safe-call `?.`.
3
+ # Ported from vinhnx/VTCode rules/kotlin/no-unnecessary-let.yml (#2198, refs #2195).
4
+ id: kotlin-no-unnecessary-let
5
+ language: kotlin
6
+ severity: warning
7
+ message: "let on a non-null-checked receiver adds indirection; use the value directly"
8
+ note: |
9
+ `.let { }` exists to scope a null-safe transform after `?.`. Calling it on
10
+ a receiver that is already known non-null (no `?.`) just renames the
11
+ receiver to `it` inside a lambda, adding a level of nesting with no
12
+ null-safety benefit.
13
+ Detection-only: the receiver's own nullability is not tracked here, and
14
+ `.let` also has legitimate uses for scoping a mutable local or chaining a
15
+ builder, which this pattern cannot distinguish from the redundant case.
16
+ rule:
17
+ pattern: $RECEIVER.let { $$$BODY }
18
+ files:
19
+ - "**/*.kt"
20
+ tags:
21
+ - kotlin
22
+ - idiom
23
+ - readability
24
+ examples:
25
+ bad: |
26
+ val length = name.let { it.length }
27
+ good: |
28
+ val length = name.length
@@ -0,0 +1,28 @@
1
+ # Kotlin No unsafe cast
2
+ # Detects the unsafe `as` cast (as opposed to the safe `as?` cast).
3
+ # Ported from vinhnx/VTCode rules/kotlin/no-unsafe-cast.yml (#2198, refs #2195).
4
+ id: kotlin-no-unsafe-cast
5
+ language: kotlin
6
+ severity: warning
7
+ message: "Unsafe cast (as) throws ClassCastException on a mismatch; consider as?"
8
+ note: |
9
+ `as` throws ClassCastException immediately when the value isn't the target
10
+ type. `as?` returns null instead, which is usually safer when the caller
11
+ can handle a missing value.
12
+ Detection-only: `as?` changes a thrown failure into a silent null, which
13
+ is a real behavior change a caller must handle explicitly. Whether the
14
+ unsafe throw is actually the intended contract (a precondition the caller
15
+ already established) is a call this rule cannot make.
16
+ rule:
17
+ pattern: $VALUE as $TYPE
18
+ files:
19
+ - "**/*.kt"
20
+ tags:
21
+ - kotlin
22
+ - idiom
23
+ - null-safety
24
+ examples:
25
+ bad: |
26
+ val name = value as String
27
+ good: |
28
+ val name = value as? String ?: return
@@ -0,0 +1,35 @@
1
+ # Kotlin No var
2
+ # Detects a `var` property or local declaration (as opposed to `val`).
3
+ # Ported from vinhnx/VTCode rules/kotlin/no-var.yml (#2198, refs #2195).
4
+ id: kotlin-no-var
5
+ language: kotlin
6
+ severity: warning
7
+ message: "Prefer val over var; mutability should be explicit and scoped"
8
+ note: |
9
+ Kotlin favors immutability by default. A `var` where a `val` would do
10
+ widens the set of places a value can change, which makes reasoning about
11
+ the surrounding code harder as it grows.
12
+ Detection-only: some `var`s are load-bearing (loop counters, accumulators,
13
+ lifecycle-managed fields), and rewriting to `val` requires knowing every
14
+ call site's mutation intent, which this rule cannot verify.
15
+ A `lateinit var` also matches `kotlin-no-lateinit`, so it reports twice.
16
+ That's intentional, not a bug to dedupe: the two findings name different
17
+ problems (mutability here, deferred-initialization risk there) and either
18
+ one could be fixed independently of the other.
19
+ rule:
20
+ kind: property_declaration
21
+ has:
22
+ kind: binding_pattern_kind
23
+ regex: "^var$"
24
+ files:
25
+ - "**/*.kt"
26
+ tags:
27
+ - kotlin
28
+ - idiom
29
+ - immutability
30
+ examples:
31
+ bad: |
32
+ var total = 0
33
+ total = total + price
34
+ good: |
35
+ val total = prices.sum()
@@ -0,0 +1,66 @@
1
+ # Kotlin Prefer data class
2
+ # Detects a plain class whose primary constructor is made entirely of
3
+ # val/var properties and that carries no additional behavior (a function, an
4
+ # init block, or a computed property), a strong signal it's a value holder
5
+ # that should be a data class.
6
+ # Ported from vinhnx/VTCode rules/kotlin/prefer-data-class.yml (#2198, refs #2195).
7
+ id: kotlin-prefer-data-class
8
+ language: kotlin
9
+ severity: warning
10
+ message: "This class looks like a plain value holder; consider a data class"
11
+ note: |
12
+ A data class generates equals/hashCode/toString/copy/componentN for free,
13
+ which a hand-written value holder either lacks or must maintain by hand.
14
+ Detection-only: adding `data` changes equality semantics (structural
15
+ instead of referential) and generates a public API surface (copy,
16
+ componentN) the class may not want to expose, neither of which this rule
17
+ can verify — it excludes classes carrying any modifier
18
+ (open/abstract/sealed/inner/data/enum/…) and classes with a function, an
19
+ init block, or a computed property in their body, but a caller may still
20
+ have other reasons the plain class is intentional.
21
+ A class that extends another type through its primary constructor (a
22
+ delegation specifier, e.g. `class Ok(val v: String) : Result()`) still
23
+ matches: since Kotlin 1.1, a data class may extend another class, so
24
+ inheritance alone is not a reason to exclude it.
25
+ rule:
26
+ all:
27
+ - kind: class_declaration
28
+ - not:
29
+ has:
30
+ kind: modifiers
31
+ - has:
32
+ kind: primary_constructor
33
+ has:
34
+ kind: class_parameter
35
+ not:
36
+ has:
37
+ kind: class_parameter
38
+ not:
39
+ has:
40
+ kind: binding_pattern_kind
41
+ - not:
42
+ has:
43
+ kind: class_body
44
+ any:
45
+ - has:
46
+ kind: function_declaration
47
+ - has:
48
+ kind: anonymous_initializer
49
+ - has:
50
+ kind: property_declaration
51
+ any:
52
+ - has:
53
+ kind: getter
54
+ - has:
55
+ kind: setter
56
+ files:
57
+ - "**/*.kt"
58
+ tags:
59
+ - kotlin
60
+ - idiom
61
+ - readability
62
+ examples:
63
+ bad: |
64
+ class Point(val x: Int, val y: Int)
65
+ good: |
66
+ data class Point(val x: Int, val y: Int)
@@ -0,0 +1,35 @@
1
+ # Kotlin Prefer isEmpty
2
+ # Detects `.size == 0` / `.length == 0`, which usually reads better as
3
+ # `.isEmpty()`.
4
+ # Ported from vinhnx/VTCode rules/kotlin/prefer-is-empty.yml (#2198, refs #2195).
5
+ id: kotlin-prefer-is-empty
6
+ language: kotlin
7
+ severity: warning
8
+ message: "Use isEmpty() instead of comparing size/length to zero"
9
+ note: |
10
+ `.isEmpty()` states intent directly. It is exactly equivalent to a
11
+ zero-size/zero-length comparison for every Kotlin collection, Array, and
12
+ String, but this rule cannot see the receiver's actual type — a class with
13
+ its own unrelated `size`/`length` property (e.g. `class Segment(val
14
+ length: Int)`) has no `isEmpty()` member at all, so a blind rewrite would
15
+ emit code that doesn't compile.
16
+ Detection-only for that reason, matching the Java sibling
17
+ `prefer-string-is-empty.yml`: the receiver's type is not checked here
18
+ either. Only the exact `== 0` comparison is flagged; `> 0`, `!= 0`, and
19
+ other comparisons are left alone because their natural rewrite
20
+ (isNotEmpty, or none) differs per shape.
21
+ rule:
22
+ any:
23
+ - pattern: $RECEIVER.size == 0
24
+ - pattern: $RECEIVER.length == 0
25
+ files:
26
+ - "**/*.kt"
27
+ tags:
28
+ - kotlin
29
+ - idiom
30
+ - readability
31
+ examples:
32
+ bad: |
33
+ if (items.size == 0) return
34
+ good: |
35
+ if (items.isEmpty()) return
@@ -0,0 +1,21 @@
1
+ id: no-important
2
+ language: Css
3
+ severity: warning
4
+ message: "Avoid `!important` — increase selector specificity instead"
5
+ note: |
6
+ Ported from VTCode (https://github.com/vinhnx/VTCode/tree/main/rules/css,
7
+ Apache-2.0 license) per #2199 / #2195.
8
+
9
+ `!important` overrides normal cascade order and makes CSS harder to
10
+ maintain: once one declaration reaches for it, overriding it later
11
+ requires either another `!important` or a `style` attribute, and the
12
+ arms race compounds. Prefer raising selector specificity or restructuring
13
+ the cascade so the intended rule already wins.
14
+
15
+ Detection-only: a safe fix would need to know which selector should win
16
+ and why, which this rule cannot infer from the declaration alone. Ported
17
+ as-is from upstream (no fix upstream either).
18
+ rule:
19
+ pattern: "!important"
20
+ files:
21
+ - "**/*.css"
@@ -0,0 +1,33 @@
1
+ id: no-raw-types
2
+ language: java
3
+ severity: warning
4
+ message: Use parameterized types instead of raw types.
5
+ note: Ported from VTCode (https://github.com/vinhnx/VTCode), refs #2195. Raw collection types need a project/API-aware generic choice, so this rule is detection-only. Contexts with no valid parameterized form are excluded.
6
+ rule:
7
+ kind: type_identifier
8
+ regex: "^(List|Map|Set|Collection|Iterator|Iterable|Queue|Deque|Optional)$"
9
+ not:
10
+ any:
11
+ # Already parameterized. These carry no `stopBy`, so they test only the
12
+ # immediate parent. `stopBy: end` walked every ancestor instead, which
13
+ # silenced a raw type nested in a type argument: in `Map<String, List>`
14
+ # the inner `List` has a generic_type ancestor and went unreported.
15
+ - inside:
16
+ kind: generic_type
17
+ # The qualifier chain of a parameterized qualified type, so
18
+ # `java.util.List<String>` and `Map.Entry<K, V>` stay silent.
19
+ - inside:
20
+ kind: scoped_type_identifier
21
+ inside:
22
+ kind: generic_type
23
+ # `o instanceof List` and `List.class` have no valid parameterized form.
24
+ # `o instanceof List<String>` and `List<String>.class` are both compile
25
+ # errors, so a finding here is unactionable.
26
+ - inside:
27
+ kind: instanceof_expression
28
+ - inside:
29
+ kind: class_literal
30
+ files:
31
+ - "**/*.java"
32
+ ignores:
33
+ - "**/test/**"
@@ -0,0 +1,90 @@
1
+ id: no-string-concat-in-loop
2
+ language: java
3
+ severity: warning
4
+ message: Use StringBuilder instead of string concatenation in loops.
5
+ note: Ported from VTCode (https://github.com/vinhnx/VTCode), refs #2195. Loop allocation and readability context make this detection-only. The accumulator must be a String, established either by a direct string-literal operand or by the declaration that binds the same name in scope.
6
+ rule:
7
+ all:
8
+ # An accumulating assignment: `s += x` or `s = s + x`.
9
+ - any:
10
+ - pattern: $VAR += $EXPR
11
+ - pattern: $VAR = $VAR + $EXPR
12
+ # ... inside a loop body.
13
+ - any:
14
+ - inside:
15
+ kind: for_statement
16
+ stopBy: end
17
+ - inside:
18
+ kind: enhanced_for_statement
19
+ stopBy: end
20
+ - inside:
21
+ kind: while_statement
22
+ stopBy: end
23
+ - inside:
24
+ kind: do_statement
25
+ stopBy: end
26
+ # ... where the accumulator is a String. Without this arm the rule fires on
27
+ # `total += counts.get("label")`, because a `stopBy: end` search for a
28
+ # string_literal accepts one anywhere in the subtree, including inside a
29
+ # call argument. Each branch below binds String-ness to $VAR itself.
30
+ - any:
31
+ # The right-hand side is, or directly contains, a string literal. The
32
+ # inner `has` carries no `stopBy`, so it only inspects direct operands
33
+ # of the `+` and never descends into a call's arguments.
34
+ - has:
35
+ field: right
36
+ any:
37
+ - kind: string_literal
38
+ - all:
39
+ - kind: binary_expression
40
+ - has:
41
+ kind: string_literal
42
+ # $VAR is declared String in the enclosing method or constructor,
43
+ # either as a local or as a parameter. $VAR is the same metavariable
44
+ # the pattern above bound, so the names must match.
45
+ - inside:
46
+ stopBy: end
47
+ any:
48
+ - kind: method_declaration
49
+ - kind: constructor_declaration
50
+ has:
51
+ stopBy: end
52
+ any:
53
+ - all:
54
+ - kind: local_variable_declaration
55
+ - has:
56
+ field: type
57
+ regex: ^String$
58
+ - has:
59
+ kind: variable_declarator
60
+ has:
61
+ field: name
62
+ pattern: $VAR
63
+ - all:
64
+ - kind: formal_parameter
65
+ - has:
66
+ field: type
67
+ regex: ^String$
68
+ - has:
69
+ field: name
70
+ pattern: $VAR
71
+ # $VAR is a String field of the enclosing class.
72
+ - inside:
73
+ stopBy: end
74
+ kind: class_body
75
+ has:
76
+ stopBy: end
77
+ all:
78
+ - kind: field_declaration
79
+ - has:
80
+ field: type
81
+ regex: ^String$
82
+ - has:
83
+ kind: variable_declarator
84
+ has:
85
+ field: name
86
+ pattern: $VAR
87
+ files:
88
+ - "**/*.java"
89
+ ignores:
90
+ - "**/test/**"
@@ -0,0 +1,16 @@
1
+ id: no-system-out-println
2
+ language: java
3
+ severity: warning
4
+ message: Avoid System.out.println; use a logging framework instead.
5
+ note: Ported from VTCode (https://github.com/vinhnx/VTCode), refs #2195. Logger policy and intentional console output vary by project, so this rule is detection-only.
6
+ rule:
7
+ any:
8
+ - pattern: System.out.println($$$)
9
+ - pattern: System.out.print($$$)
10
+ - pattern: System.err.println($$$)
11
+ - pattern: System.err.print($$$)
12
+ files:
13
+ - "**/*.java"
14
+ ignores:
15
+ - "**/test/**"
16
+ - "**/*Test.java"
@@ -0,0 +1,11 @@
1
+ id: prefer-string-is-empty
2
+ language: java
3
+ severity: warning
4
+ message: Use .isEmpty() instead of .length() == 0 or .equals("").
5
+ note: Ported from VTCode (https://github.com/vinhnx/VTCode), refs #2195. The receiver's type is not checked, so this rule is detection-only. Detection is limited to the exact empty-string and zero-length forms.
6
+ rule:
7
+ any:
8
+ - pattern: $S.length() == 0
9
+ - pattern: $S.equals("")
10
+ files:
11
+ - "**/*.java"
@@ -0,0 +1,22 @@
1
+ id: python-optional-type
2
+ language: Python
3
+ severity: hint
4
+ message: "Optional[T] requires Python 3.10+ to rewrite as T | None"
5
+ note: |
6
+ `Optional[T]` can be written as `T | None` on Python 3.10 and later.
7
+ A CPython 3.11 stdlib census found 1,675 matches and zero defects, so this
8
+ remains a modernization hint rather than a warning about incorrect code.
9
+ This rule is detection-only because the target project's Python version is
10
+ not available to a syntax-only matcher. Do not apply the rewrite to Python
11
+ 3.8 or 3.9 code.
12
+ rule:
13
+ kind: type
14
+ regex: '^(Optional|typing\.Optional|t\.Optional)\['
15
+ has_fix: false
16
+ tags:
17
+ - python
18
+ - typing
19
+ - modernization
20
+ examples:
21
+ bad: "value: Optional[str]"
22
+ good: "value: str | None"
@@ -0,0 +1,29 @@
1
+ id: reducible-list-comprehension
2
+ language: Python
3
+ severity: warning
4
+ message: "A list comprehension is unnecessary here; use a generator expression"
5
+ note: |
6
+ `any`, `all`, and `sum` consume iterables directly, so the list allocation
7
+ can be removed without changing the operation's result. The generator
8
+ expression can short-circuit, so evaluation counts differ; apply this fix
9
+ only when the element expression is side-effect-free.
10
+ rule:
11
+ pattern: $FN([$X for $Y in $Z])
12
+ not:
13
+ any:
14
+ - pattern: $FN([$X async for $Y in $Z])
15
+ - pattern: $FN([await $X for $Y in $Z])
16
+ - has:
17
+ pattern: await $$$
18
+ stopBy: end
19
+ constraints:
20
+ FN:
21
+ regex: "^(any|all|sum)$"
22
+ fix: "$FN($X for $Y in $Z)"
23
+ tags:
24
+ - python
25
+ - performance
26
+ - modernization
27
+ examples:
28
+ bad: "total = sum([price for price in prices])"
29
+ good: "total = sum(price for price in prices)"
@@ -0,0 +1,25 @@
1
+ id: ruby-symbol-to-proc-candidate
2
+ language: Ruby
3
+ severity: warning
4
+ message: "Use a symbol-to-proc shorthand for this simple iterator block"
5
+ note: |
6
+ A block that forwards its one parameter to one receiver method can use the
7
+ equivalent symbol-to-proc form. Side-effect-oriented iterators such as
8
+ `each` are excluded because replacing them is less useful as a default hint.
9
+ rule:
10
+ pattern: $LIST.$ITER { |$X| $X.$METHOD }
11
+ not:
12
+ pattern: $LIST.$ITER { |$X| $X.$METHOD($$$ARGS) }
13
+ constraints:
14
+ ITER:
15
+ regex: '^(map|collect|filter|select|reject|find|detect|any\?|all\?|none\?|one\?|flat_map|sort_by|group_by)$'
16
+ METHOD:
17
+ regex: '^[A-Za-z_][A-Za-z0-9_]*[?!=]?$'
18
+ fix: "$LIST.$ITER(&:$METHOD)"
19
+ tags:
20
+ - ruby
21
+ - style
22
+ - modernization
23
+ examples:
24
+ bad: "names.map { |name| name.upcase }"
25
+ good: "names.map(&:upcase)"
@@ -0,0 +1,19 @@
1
+ id: rust-no-chars-enumerate
2
+ language: Rust
3
+ severity: warning
4
+ message: "chars().enumerate() may confuse character indices with byte offsets"
5
+ note: |
6
+ `chars().enumerate()` produces character positions, while many Rust APIs
7
+ require byte offsets. This rule is detection-only because the intended index
8
+ semantics cannot be proved from syntax. Use `char_indices()` only when the
9
+ consumer requires byte offsets.
10
+ rule:
11
+ pattern: $TEXT.chars().enumerate()
12
+ has_fix: false
13
+ tags:
14
+ - rust
15
+ - correctness
16
+ - unicode
17
+ examples:
18
+ bad: "for (index, character) in text.chars().enumerate() {}"
19
+ good: "for (index, character) in text.char_indices() {}"