pi-lens 3.8.53 → 3.8.62

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 (700) hide show
  1. package/CHANGELOG.md +124 -8
  2. package/LICENSE +21 -0
  3. package/README.md +138 -386
  4. package/banner.png +0 -0
  5. package/banner.svg +54 -46
  6. package/dist/clients/ast-grep-client.js +160 -3
  7. package/dist/clients/ast-grep-tool-logger.js +1 -1
  8. package/dist/clients/ast-grep-yaml-synth.js +30 -6
  9. package/dist/clients/bootstrap.js +99 -31
  10. package/dist/clients/complexity-client.js +1 -1
  11. package/dist/clients/dead-code-client.js +304 -0
  12. package/dist/clients/dead-code-logger.js +46 -0
  13. package/dist/clients/dependency-checker.js +55 -16
  14. package/dist/clients/deps/ast-grep-napi.js +3 -0
  15. package/dist/clients/deps/js-yaml.js +9 -0
  16. package/dist/clients/deps/minimatch.js +4 -0
  17. package/dist/clients/deps/pi-tui.js +5 -0
  18. package/dist/clients/deps/typebox.js +6 -0
  19. package/dist/clients/deps/typescript.js +15 -0
  20. package/dist/clients/deps/vscode-jsonrpc.js +1 -0
  21. package/dist/clients/deps/web-tree-sitter.js +3 -0
  22. package/dist/clients/dispatch/auxiliary-lsp.js +106 -0
  23. package/dist/clients/dispatch/dispatcher.js +27 -2
  24. package/dist/clients/dispatch/fact-runner.js +59 -0
  25. package/dist/clients/dispatch/facts/comment-facts.js +1 -1
  26. package/dist/clients/dispatch/facts/function-facts.js +1 -1
  27. package/dist/clients/dispatch/facts/import-facts.js +1 -1
  28. package/dist/clients/dispatch/facts/try-catch-facts.js +1 -1
  29. package/dist/clients/dispatch/integration.js +103 -62
  30. package/dist/clients/dispatch/rules/high-complexity.js +29 -4
  31. package/dist/clients/dispatch/rules/high-fan-out.js +24 -4
  32. package/dist/clients/dispatch/rules/quality-rules.js +1 -1
  33. package/dist/clients/dispatch/rules/sonar-rules.js +1 -1
  34. package/dist/clients/dispatch/runners/ast-grep-napi.js +136 -109
  35. package/dist/clients/dispatch/runners/credo.js +10 -3
  36. package/dist/clients/dispatch/runners/go-vet.js +41 -18
  37. package/dist/clients/dispatch/runners/index.js +4 -2
  38. package/dist/clients/dispatch/runners/lsp.js +31 -1
  39. package/dist/clients/dispatch/runners/mypy.js +15 -3
  40. package/dist/clients/dispatch/runners/phpstan.js +13 -3
  41. package/dist/clients/dispatch/runners/pyright.js +4 -1
  42. package/dist/clients/dispatch/runners/rust-clippy.js +27 -7
  43. package/dist/clients/dispatch/runners/shellcheck.js +11 -1
  44. package/dist/clients/dispatch/runners/spotbugs.js +258 -0
  45. package/dist/clients/dispatch/runners/taplo.js +8 -1
  46. package/dist/clients/dispatch/runners/trivy-config.js +180 -0
  47. package/dist/clients/dispatch/runners/utils/runner-helpers.js +21 -0
  48. package/dist/clients/dispatch/runners/yaml-rule-parser.js +13 -2
  49. package/dist/clients/dispatch/tool-profile.js +2 -1
  50. package/dist/clients/event-loop-monitor.js +18 -3
  51. package/dist/clients/file-utils.js +49 -4
  52. package/dist/clients/gitleaks-client.js +9 -61
  53. package/dist/clients/govulncheck-client.js +8 -43
  54. package/dist/clients/grammar-source.js +71 -0
  55. package/dist/clients/host-edit-normalize.js +139 -0
  56. package/dist/clients/install-diagnostics.js +141 -0
  57. package/dist/clients/installer/index.js +685 -37
  58. package/dist/clients/knip-client.js +73 -53
  59. package/dist/clients/language-policy.js +7 -5
  60. package/dist/clients/language-profile.js +10 -1
  61. package/dist/clients/lens-config.js +7 -0
  62. package/dist/clients/lens-engine.js +5 -14
  63. package/dist/clients/lsp/client.js +314 -46
  64. package/dist/clients/lsp/index.js +183 -35
  65. package/dist/clients/lsp/interactive-install.js +26 -24
  66. package/dist/clients/lsp/jvm-runtime.js +158 -0
  67. package/dist/clients/lsp/launch.js +25 -14
  68. package/dist/clients/lsp/lombok.js +158 -0
  69. package/dist/clients/lsp/position-encoding.js +61 -0
  70. package/dist/clients/lsp/server-strategies.js +88 -1
  71. package/dist/clients/lsp/server.js +591 -175
  72. package/dist/clients/lsp/watch-queue.js +61 -0
  73. package/dist/clients/lsp-status.js +59 -0
  74. package/dist/clients/mcp/session.js +4 -1
  75. package/dist/clients/module-report-lsp.js +193 -0
  76. package/dist/clients/module-report.js +1654 -0
  77. package/dist/clients/oldtext-autopatch.js +8 -7
  78. package/dist/clients/opengrep-config.js +80 -0
  79. package/dist/clients/partial-edit-apply.js +10 -8
  80. package/dist/clients/path-utils.js +22 -0
  81. package/dist/clients/pipeline.js +5 -58
  82. package/dist/clients/production-readiness.js +45 -69
  83. package/dist/clients/project-diagnostics/cache.js +44 -1
  84. package/dist/clients/project-diagnostics/runner-adapters/knip.js +3 -0
  85. package/dist/clients/project-diagnostics/scanner.js +85 -6
  86. package/dist/clients/project-lens-config.js +159 -0
  87. package/dist/clients/read-expansion.js +8 -0
  88. package/dist/clients/read-guard-tool-lines.js +24 -6
  89. package/dist/clients/read-guard.js +34 -0
  90. package/dist/clients/review-graph/builder.js +433 -114
  91. package/dist/clients/review-graph/import-resolvers.js +291 -0
  92. package/dist/clients/review-graph/workspace-modules.js +5 -0
  93. package/dist/clients/runtime-session.js +128 -18
  94. package/dist/clients/runtime-turn.js +170 -26
  95. package/dist/clients/secret-findings.js +114 -0
  96. package/dist/clients/security-scan-client.js +103 -0
  97. package/dist/clients/sgconfig.js +68 -0
  98. package/dist/clients/source-filter.js +12 -1
  99. package/dist/clients/startup-scan.js +13 -4
  100. package/dist/clients/tool-policy.js +43 -0
  101. package/dist/clients/tree-sitter-client.js +408 -41
  102. package/dist/clients/tree-sitter-query-loader.js +18 -1
  103. package/dist/clients/tree-sitter-symbol-extractor.js +333 -73
  104. package/dist/clients/trivy-client.js +441 -0
  105. package/dist/clients/ts-service.js +1 -1
  106. package/dist/clients/typescript-client.js +1 -1
  107. package/dist/clients/typos-config.js +33 -0
  108. package/dist/clients/widget-state.js +48 -2
  109. package/dist/clients/zizmor-config.js +77 -0
  110. package/dist/index.js +85 -108
  111. package/dist/mcp/server.js +87 -42
  112. package/dist/tools/ast-dump.js +77 -30
  113. package/dist/tools/ast-grep-outline.js +148 -0
  114. package/dist/tools/ast-grep-replace.js +14 -2
  115. package/dist/tools/ast-grep-search.js +406 -113
  116. package/dist/tools/lens-diagnostics.js +134 -34
  117. package/dist/tools/lsp-diagnostics.js +48 -24
  118. package/dist/tools/lsp-navigation.js +159 -59
  119. package/dist/tools/lsp-structured-output.js +294 -0
  120. package/dist/tools/module-report.js +361 -0
  121. package/dist/tools/render-compact.js +95 -0
  122. package/package.json +16 -6
  123. package/rules/ast-grep-rules/.sgconfig.yml +9 -0
  124. package/rules/ast-grep-rules/coderabbit/LICENSE +201 -0
  125. package/rules/ast-grep-rules/coderabbit/README.md +9 -0
  126. package/rules/ast-grep-rules/coderabbit/rules/c/security/dont-call-system-c.yml +57 -0
  127. package/rules/ast-grep-rules/coderabbit/rules/c/security/file-access-before-action-c.yml +182 -0
  128. package/rules/ast-grep-rules/coderabbit/rules/c/security/file-stat-before-action-c.yml +331 -0
  129. package/rules/ast-grep-rules/coderabbit/rules/c/security/insecure-hash-c.yml +286 -0
  130. package/rules/ast-grep-rules/coderabbit/rules/c/security/libxml2-audit-parser-c.yml +258 -0
  131. package/rules/ast-grep-rules/coderabbit/rules/c/security/null-library-function-c.yml +254 -0
  132. package/rules/ast-grep-rules/coderabbit/rules/c/security/sizeof-this-c.yml +121 -0
  133. package/rules/ast-grep-rules/coderabbit/rules/c/security/small-key-size-c.yml +40 -0
  134. package/rules/ast-grep-rules/coderabbit/rules/c/security/world-writable-file-c.yml +317 -0
  135. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/dont-call-system-cpp.yml +57 -0
  136. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/file-access-before-action-cpp.yml +271 -0
  137. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/file-stat-before-action-cpp.yml +494 -0
  138. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/fix-format-security-error-cpp.yml +18 -0
  139. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/insecure-hash-cpp.yml +122 -0
  140. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/libxml2-audit-parser-cpp.yml +258 -0
  141. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/missing-nul-cpp-string-memcpy-cpp.yml +393 -0
  142. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/null-library-function-cpp.yml +254 -0
  143. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/return-c-str-cpp.yml +124 -0
  144. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/sizeof-this-cpp.yml +41 -0
  145. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/small-key-size-cpp.yml +40 -0
  146. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/std-return-data-cpp.yml +93 -0
  147. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/std-vector-invalidation-cpp.yml +147 -0
  148. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/string-view-temporary-string-cpp.yml +924 -0
  149. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/world-writable-file-cpp.yml +317 -0
  150. package/rules/ast-grep-rules/coderabbit/rules/csharp/security/httponly-false-csharp.yml +42 -0
  151. package/rules/ast-grep-rules/coderabbit/rules/csharp/security/insecure-binaryformatter-deserialization-csharp.yml +38 -0
  152. package/rules/ast-grep-rules/coderabbit/rules/csharp/security/jwt-decode-without-verify-csharp.yml +700 -0
  153. package/rules/ast-grep-rules/coderabbit/rules/csharp/security/jwt-hardcoded-secret-csharp.yml +672 -0
  154. package/rules/ast-grep-rules/coderabbit/rules/csharp/security/jwt-tokenvalidationparameters-no-expiry-validation-csharp.yml +136 -0
  155. package/rules/ast-grep-rules/coderabbit/rules/csharp/security/networkcredential-hardcoded-secret-python.yml +394 -0
  156. package/rules/ast-grep-rules/coderabbit/rules/csharp/security/npgsqlconnectionstringbuilder-hardcoded-secret-csharp.yml +339 -0
  157. package/rules/ast-grep-rules/coderabbit/rules/csharp/security/oracleconnectionstringbuilder-hardcoded-secret-csharp.yml +339 -0
  158. package/rules/ast-grep-rules/coderabbit/rules/csharp/security/sqlconnectionstringbuilder-hardcoded-secret-csharp.yml +339 -0
  159. package/rules/ast-grep-rules/coderabbit/rules/csharp/security/stacktrace-disclosure-csharp.yml +48 -0
  160. package/rules/ast-grep-rules/coderabbit/rules/csharp/security/use-ecb-mode-csharp.yml +177 -0
  161. package/rules/ast-grep-rules/coderabbit/rules/go/security/avoid-bind-to-all-interfaces-go.yml +27 -0
  162. package/rules/ast-grep-rules/coderabbit/rules/go/security/gorilla-cookie-store-hardcoded-session-key-go.yml +90 -0
  163. package/rules/ast-grep-rules/coderabbit/rules/go/security/gorilla-csrf-hardcoded-auth-key-go.yml +79 -0
  164. package/rules/ast-grep-rules/coderabbit/rules/go/security/grpc-client-insecure-connection-go.yml +60 -0
  165. package/rules/ast-grep-rules/coderabbit/rules/go/security/jwt-go-none-algorithm-go.yml +35 -0
  166. package/rules/ast-grep-rules/coderabbit/rules/go/security/missing-ssl-minversion-go.yml +42 -0
  167. package/rules/ast-grep-rules/coderabbit/rules/go/security/openai-empty-secret-go.yml +199 -0
  168. package/rules/ast-grep-rules/coderabbit/rules/go/security/openai-hardcoded-secret-go.yml +208 -0
  169. package/rules/ast-grep-rules/coderabbit/rules/go/security/ssl-v3-is-insecure-go.yml +40 -0
  170. package/rules/ast-grep-rules/coderabbit/rules/go/security/tls-with-insecure-cipher-go.yml +65 -0
  171. package/rules/ast-grep-rules/coderabbit/rules/go/security/use-of-weak-rsa-key-go.yml +253 -0
  172. package/rules/ast-grep-rules/coderabbit/rules/html/security/plaintext-http-link-html.yml +76 -0
  173. package/rules/ast-grep-rules/coderabbit/rules/java/security/cbc-padding-oracle-java.yml +17 -0
  174. package/rules/ast-grep-rules/coderabbit/rules/java/security/cookie-httponly-false-java.yml +9 -0
  175. package/rules/ast-grep-rules/coderabbit/rules/java/security/cookie-missing-httponly-java.yml +21 -0
  176. package/rules/ast-grep-rules/coderabbit/rules/java/security/cookie-missing-samesite-java.yml +64 -0
  177. package/rules/ast-grep-rules/coderabbit/rules/java/security/cookie-missing-secure-flag-java.yml +51 -0
  178. package/rules/ast-grep-rules/coderabbit/rules/java/security/cookie-secure-flag-false-java.yml +13 -0
  179. package/rules/ast-grep-rules/coderabbit/rules/java/security/datanucleus-hardcoded-connection-password-java.yml +575 -0
  180. package/rules/ast-grep-rules/coderabbit/rules/java/security/des-is-deprecated-java.yml +15 -0
  181. package/rules/ast-grep-rules/coderabbit/rules/java/security/desede-is-deprecated-java.yml +92 -0
  182. package/rules/ast-grep-rules/coderabbit/rules/java/security/documentbuilderfactory-disallow-doctype-decl-false-java.yml +45 -0
  183. package/rules/ast-grep-rules/coderabbit/rules/java/security/documentbuilderfactory-external-general-entities-true-java.yml +279 -0
  184. package/rules/ast-grep-rules/coderabbit/rules/java/security/documentbuilderfactory-external-parameter-entities-true-java.yml +279 -0
  185. package/rules/ast-grep-rules/coderabbit/rules/java/security/drivermanager-hardcoded-secret-java.yml +142 -0
  186. package/rules/ast-grep-rules/coderabbit/rules/java/security/ecb-cipher-java.yml +47 -0
  187. package/rules/ast-grep-rules/coderabbit/rules/java/security/hardcoded-connection-password-java.yml +341 -0
  188. package/rules/ast-grep-rules/coderabbit/rules/java/security/hardcoded-secret-in-credentials-java.yml +281 -0
  189. package/rules/ast-grep-rules/coderabbit/rules/java/security/java-jwt-hardcoded-secret-java.yml +124 -0
  190. package/rules/ast-grep-rules/coderabbit/rules/java/security/jedis-jedisclientconfig-hardcoded-password-java.yml +804 -0
  191. package/rules/ast-grep-rules/coderabbit/rules/java/security/jedis-jedisfactory-hardcoded-password-java.yml +930 -0
  192. package/rules/ast-grep-rules/coderabbit/rules/java/security/missing-httponly-java.yml +583 -0
  193. package/rules/ast-grep-rules/coderabbit/rules/java/security/missing-secure-java.yml +584 -0
  194. package/rules/ast-grep-rules/coderabbit/rules/java/security/no-null-cipher-java.yml +38 -0
  195. package/rules/ast-grep-rules/coderabbit/rules/java/security/passwordauthentication-hardcoded-password-java.yml +651 -0
  196. package/rules/ast-grep-rules/coderabbit/rules/java/security/rsa-no-padding-java.yml +13 -0
  197. package/rules/ast-grep-rules/coderabbit/rules/java/security/simple-command-injection-direct-input-java.yml +55 -0
  198. package/rules/ast-grep-rules/coderabbit/rules/java/security/system-setproperty-hardcoded-secret-java.yml +312 -0
  199. package/rules/ast-grep-rules/coderabbit/rules/java/security/unencrypted-socket-java.yml +20 -0
  200. package/rules/ast-grep-rules/coderabbit/rules/java/security/use-of-aes-ecb-java.yml +68 -0
  201. package/rules/ast-grep-rules/coderabbit/rules/java/security/use-of-blowfish-java.yml +45 -0
  202. package/rules/ast-grep-rules/coderabbit/rules/java/security/use-of-default-aes-java.yml +318 -0
  203. package/rules/ast-grep-rules/coderabbit/rules/java/security/use-of-md5-digest-utils-java.yml +38 -0
  204. package/rules/ast-grep-rules/coderabbit/rules/java/security/use-of-md5-java.yml +104 -0
  205. package/rules/ast-grep-rules/coderabbit/rules/java/security/use-of-rc2-java.yml +84 -0
  206. package/rules/ast-grep-rules/coderabbit/rules/java/security/use-of-rc4-java.yml +38 -0
  207. package/rules/ast-grep-rules/coderabbit/rules/java/security/use-of-sha1-java.yml +165 -0
  208. package/rules/ast-grep-rules/coderabbit/rules/java/security/weak-ssl-context-java.yml +56 -0
  209. package/rules/ast-grep-rules/coderabbit/rules/javascript/security/detect-angular-sce-disabled-javascript.yml +14 -0
  210. package/rules/ast-grep-rules/coderabbit/rules/javascript/security/express-jwt-hardcoded-secret-javascript.yml +289 -0
  211. package/rules/ast-grep-rules/coderabbit/rules/javascript/security/express-session-hardcoded-secret-javascript.yml +101 -0
  212. package/rules/ast-grep-rules/coderabbit/rules/javascript/security/jwt-simple-noverify-javascript.yml +43 -0
  213. package/rules/ast-grep-rules/coderabbit/rules/javascript/security/node-rsa-weak-key-javascript.yml +577 -0
  214. package/rules/ast-grep-rules/coderabbit/rules/javascript/security/node-sequelize-empty-password-argument-javascript.yml +191 -0
  215. package/rules/ast-grep-rules/coderabbit/rules/javascript/security/node-sequelize-hardcoded-secret-argument-javascript.yml +94 -0
  216. package/rules/ast-grep-rules/coderabbit/rules/kotlin/security/des-is-deprecated-kotlin.yml +15 -0
  217. package/rules/ast-grep-rules/coderabbit/rules/kotlin/security/desede-is-deprecated-kotlin.yml +462 -0
  218. package/rules/ast-grep-rules/coderabbit/rules/kotlin/security/jwt-hardcode-kotlin.yml +567 -0
  219. package/rules/ast-grep-rules/coderabbit/rules/kotlin/security/rsa-no-padding-kotlin.yml +13 -0
  220. package/rules/ast-grep-rules/coderabbit/rules/kotlin/security/system-setproperty-hardcoded-secret-kotlin.yml +51 -0
  221. package/rules/ast-grep-rules/coderabbit/rules/php/security/openssl-cbc-static-iv-php.yml +641 -0
  222. package/rules/ast-grep-rules/coderabbit/rules/php/security/search-active-debug-php.yml +153 -0
  223. package/rules/ast-grep-rules/coderabbit/rules/python/security/avoid-mktemp-python.yml +71 -0
  224. package/rules/ast-grep-rules/coderabbit/rules/python/security/avoid_app_run_with_bad_host-python.yml +69 -0
  225. package/rules/ast-grep-rules/coderabbit/rules/python/security/debug-enabled-python.yml +91 -0
  226. package/rules/ast-grep-rules/coderabbit/rules/python/security/hashids-with-django-secret-python.yml +273 -0
  227. package/rules/ast-grep-rules/coderabbit/rules/python/security/hashids-with-flask-secret-python.yml +190 -0
  228. package/rules/ast-grep-rules/coderabbit/rules/python/security/insecure-cipher-algorithm-rc4-python.yml +75 -0
  229. package/rules/ast-grep-rules/coderabbit/rules/python/security/jwt-python-hardcoded-secret-python.yml +116 -0
  230. package/rules/ast-grep-rules/coderabbit/rules/python/security/openai-hardcoded-secret-python.yml +21 -0
  231. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-cassandra-empty-password-python.yml +227 -0
  232. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-cassandra-hardcoded-secret-python.yml +396 -0
  233. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-couchbase-empty-password-python.yml +72 -0
  234. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-couchbase-hardcoded-secret-python.yml +183 -0
  235. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-elasticsearch-hardcoded-bearer-auth-python.yml +64 -0
  236. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-ldap3-empty-password-python.yml +92 -0
  237. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-ldap3-hardcoded-secret-python.yml +145 -0
  238. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-mariadb-empty-password-python.yml +194 -0
  239. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-mariadb-hardcoded-secret-python.yml +193 -0
  240. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-mysql-empty-password-python.yml +192 -0
  241. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-mysql-hardcoded-secret-python.yml +195 -0
  242. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-mysqlclient-empty-password-python.yml +189 -0
  243. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-mysqlclient-hardcoded-secret-python.yml +191 -0
  244. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-neo4j-empty-password-python.yml +203 -0
  245. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-neo4j-hardcoded-secret-python.yml +205 -0
  246. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-peewee-mysql-empty-password-python.yml +50 -0
  247. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-peewee-mysql-hardcoded-secret-python.yml +48 -0
  248. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-peewee-pg-empty-password-python.yml +51 -0
  249. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-peewee-pg-hardcoded-secret-python.yml +49 -0
  250. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-pg8000-empty-password-python.yml +43 -0
  251. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-pg8000-hardcoded-secret-python.yml +67 -0
  252. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-psycopg2-empty-password-python.yml +65 -0
  253. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-psycopg2-hardcoded-secret-python.yml +64 -0
  254. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-pyjwt-hardcoded-secret-python.yml +38 -0
  255. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-pymongo-empty-password-python.yml +50 -0
  256. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-pymongo-hardcoded-secret-python.yml +48 -0
  257. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-pymssql-empty-password-python.yml +50 -0
  258. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-pymssql-hardcoded-secret-python.yml +48 -0
  259. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-pymysql-empty-password-python.yml +49 -0
  260. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-pymysql-hardcoded-secret-python.yml +47 -0
  261. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-redis-empty-password-python.yml +66 -0
  262. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-redis-hardcoded-secret-python.yml +65 -0
  263. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-requests-empty-password-python.yml +42 -0
  264. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-requests-hardcoded-secret-python.yml +146 -0
  265. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-requests-oauth-hardcoded-secret-python.yml +278 -0
  266. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-tormysql-empty-password-python.yml +301 -0
  267. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-tormysql-hardcoded-secret-python.yml +292 -0
  268. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-urllib3-hardcoded-secret-python.yml +52 -0
  269. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-webrepl-empty-password-python.yml +49 -0
  270. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-webrepl-hardcoded-secret-python.yml +47 -0
  271. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/force-ssl-false-ruby.yml +23 -0
  272. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/hardcoded-http-auth-in-controller-ruby.yml +55 -0
  273. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/hardcoded-secret-rsa-passphrase-ruby.yml +218 -0
  274. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/insufficient-rsa-key-size-ruby.yml +84 -0
  275. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-aws-sdk-hardcoded-secret-ruby.yml +140 -0
  276. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-cassandra-empty-password-ruby.yml +141 -0
  277. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-cassandra-hardcoded-secret-ruby.yml +138 -0
  278. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-excon-hardcoded-secret-ruby.yml +226 -0
  279. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-faraday-hardcoded-secret-ruby.yml +490 -0
  280. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-mongo-empty-password-ruby.yml +356 -0
  281. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-mongo-hardcoded-secret-ruby.yml +400 -0
  282. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-mysql2-empty-password-ruby.yml +227 -0
  283. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-mysql2-hardcoded-secret-ruby.yml +248 -0
  284. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-octokit-hardcoded-secret-ruby.yml +125 -0
  285. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-pg-empty-password-ruby.yml +150 -0
  286. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-pg-hardcoded-secret-ruby.yml +189 -0
  287. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-redis-empty-password-ruby.yml +72 -0
  288. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-redis-hardcoded-secret-ruby.yml +70 -0
  289. package/rules/ast-grep-rules/coderabbit/rules/rust/security/empty-password-rust.yml +1039 -0
  290. package/rules/ast-grep-rules/coderabbit/rules/rust/security/hardcoded-password-rust.yml +1016 -0
  291. package/rules/ast-grep-rules/coderabbit/rules/rust/security/postgres-empty-password-rust.yml +283 -0
  292. package/rules/ast-grep-rules/coderabbit/rules/rust/security/reqwest-accept-invalid-rust.yml +21 -0
  293. package/rules/ast-grep-rules/coderabbit/rules/rust/security/secrets-reqwest-hardcoded-auth-rust.yml +290 -0
  294. package/rules/ast-grep-rules/coderabbit/rules/rust/security/ssl-verify-none-rust.yml +100 -0
  295. package/rules/ast-grep-rules/coderabbit/rules/rust/security/tokio-postgres-empty-password-rust.yml +235 -0
  296. package/rules/ast-grep-rules/coderabbit/rules/rust/security/tokio-postgres-hardcoded-password-rust.yml +229 -0
  297. package/rules/ast-grep-rules/coderabbit/rules/scala/security/jwt-scala-hardcode-scala.yml +109 -0
  298. package/rules/ast-grep-rules/coderabbit/rules/scala/security/scala-jwt-hardcoded-secret-scala.yml +176 -0
  299. package/rules/ast-grep-rules/coderabbit/rules/swift/security/aes-hardcoded-secret-swift.yml +345 -0
  300. package/rules/ast-grep-rules/coderabbit/rules/swift/security/blowfish-hardcoded-secret-swift.yml +345 -0
  301. package/rules/ast-grep-rules/coderabbit/rules/swift/security/chacha20-hardcoded-secret-swift.yml +345 -0
  302. package/rules/ast-grep-rules/coderabbit/rules/swift/security/insecure-biometrics-swift.yml +43 -0
  303. package/rules/ast-grep-rules/coderabbit/rules/swift/security/rabbit-hardcoded-secret-swift.yml +345 -0
  304. package/rules/ast-grep-rules/coderabbit/rules/typescript/security/detect-angular-sce-disabled-typescript.yml +36 -0
  305. package/rules/ast-grep-rules/coderabbit/rules/typescript/security/express-session-hardcoded-secret-typescript.yml +203 -0
  306. package/rules/ast-grep-rules/coderabbit/rules/typescript/security/jwt-simple-noverify-typescript.yml +112 -0
  307. package/rules/ast-grep-rules/coderabbit/rules/typescript/security/node-rsa-weak-key-typescript.yml +1483 -0
  308. package/rules/ast-grep-rules/coderabbit/rules/typescript/security/node-sequelize-empty-password-argument-typescript.yml +169 -0
  309. package/rules/ast-grep-rules/coderabbit/rules/typescript/security/node-sequelize-hardcoded-secret-argument-typescript.yml +154 -0
  310. package/rules/ast-grep-rules/rule-schema.json +7 -7
  311. package/rules/ast-grep-rules/rule-tests/array-callback-return-js-test.yml +10 -0
  312. package/rules/ast-grep-rules/rule-tests/array-callback-return-test.yml +10 -0
  313. package/rules/ast-grep-rules/rule-tests/avoid-duplicate-export-test.yml +14 -0
  314. package/rules/ast-grep-rules/rule-tests/consistent-existence-index-check-js-test.yml +10 -0
  315. package/rules/ast-grep-rules/rule-tests/consistent-existence-index-check-test.yml +10 -0
  316. package/rules/ast-grep-rules/rule-tests/defer-in-loop-test.yml +20 -0
  317. package/rules/ast-grep-rules/rule-tests/enforce-node-protocol-js-test.yml +8 -0
  318. package/rules/ast-grep-rules/rule-tests/enforce-node-protocol-test.yml +8 -0
  319. package/rules/ast-grep-rules/rule-tests/find-import-file-without-extension-test.yml +8 -0
  320. package/rules/ast-grep-rules/rule-tests/go-defer-func-call-antipattern-test.yml +8 -0
  321. package/rules/ast-grep-rules/rule-tests/go-test-functions-test.yml +9 -0
  322. package/rules/ast-grep-rules/rule-tests/gorm-find-without-where-test.yml +15 -0
  323. package/rules/ast-grep-rules/rule-tests/gorm-n-plus-one-test.yml +20 -0
  324. package/rules/ast-grep-rules/rule-tests/hardcoded-url-js-test.yml +7 -0
  325. package/rules/ast-grep-rules/rule-tests/hardcoded-url-test.yml +7 -0
  326. package/rules/ast-grep-rules/rule-tests/inline-styles-test.yml +8 -0
  327. package/rules/ast-grep-rules/rule-tests/jsx-boolean-short-circuit-test.yml +8 -0
  328. package/rules/ast-grep-rules/rule-tests/jwt-no-verify-js-test.yml +9 -0
  329. package/rules/ast-grep-rules/rule-tests/jwt-no-verify-test.yml +9 -0
  330. package/rules/ast-grep-rules/rule-tests/large-class-test.yml +15 -0
  331. package/rules/ast-grep-rules/rule-tests/long-parameter-list-test.yml +8 -0
  332. package/rules/ast-grep-rules/rule-tests/loop-var-capture-test.yml +25 -0
  333. package/rules/ast-grep-rules/rule-tests/missing-component-decorator-test.yml +7 -0
  334. package/rules/ast-grep-rules/rule-tests/mutex-unlock-mismatch-test.yml +29 -0
  335. package/rules/ast-grep-rules/rule-tests/nested-ternary-js-test.yml +8 -0
  336. package/rules/ast-grep-rules/rule-tests/nested-ternary-test.yml +8 -0
  337. package/rules/ast-grep-rules/rule-tests/nil-map-assignment-test.yml +50 -0
  338. package/rules/ast-grep-rules/rule-tests/no-absolute-path-import-js-test.yml +8 -0
  339. package/rules/ast-grep-rules/rule-tests/no-absolute-path-import-test.yml +8 -0
  340. package/rules/ast-grep-rules/rule-tests/no-accumulating-spread-js-test.yml +8 -0
  341. package/rules/ast-grep-rules/rule-tests/no-alert-js-test.yml +7 -0
  342. package/rules/ast-grep-rules/rule-tests/no-alert-test.yml +7 -0
  343. package/rules/ast-grep-rules/rule-tests/no-any-type-test.yml +9 -0
  344. package/rules/ast-grep-rules/rule-tests/no-array-constructor-js-test.yml +9 -0
  345. package/rules/ast-grep-rules/rule-tests/no-array-constructor-test.yml +9 -0
  346. package/rules/ast-grep-rules/rule-tests/no-array-reverse-mutation-js-test.yml +9 -0
  347. package/rules/ast-grep-rules/rule-tests/no-array-reverse-mutation-test.yml +9 -0
  348. package/rules/ast-grep-rules/rule-tests/no-as-any-test.yml +8 -0
  349. package/rules/ast-grep-rules/rule-tests/no-assert-tuple-test.yml +13 -0
  350. package/rules/ast-grep-rules/rule-tests/no-async-promise-executor-js-test.yml +8 -0
  351. package/rules/ast-grep-rules/rule-tests/no-async-promise-executor-test.yml +8 -0
  352. package/rules/ast-grep-rules/rule-tests/no-await-expression-member-js-test.yml +8 -0
  353. package/rules/ast-grep-rules/rule-tests/no-await-expression-member-test.yml +8 -0
  354. package/rules/ast-grep-rules/rule-tests/no-await-in-promise-all-js-test.yml +7 -0
  355. package/rules/ast-grep-rules/rule-tests/no-await-in-promise-all-test.yml +7 -0
  356. package/rules/ast-grep-rules/rule-tests/no-await-in-promise-methods-js-test.yml +10 -0
  357. package/rules/ast-grep-rules/rule-tests/no-await-in-promise-methods-test.yml +10 -0
  358. package/rules/ast-grep-rules/rule-tests/no-aws-access-key-literal-test.yml +8 -0
  359. package/rules/ast-grep-rules/rule-tests/no-aws-apigateway-no-auth-test.yml +12 -0
  360. package/rules/ast-grep-rules/rule-tests/no-aws-s3-public-access-test.yml +9 -0
  361. package/rules/ast-grep-rules/rule-tests/no-bare-except-test.yml +28 -0
  362. package/rules/ast-grep-rules/rule-tests/no-blank-target-js-test.yml +8 -0
  363. package/rules/ast-grep-rules/rule-tests/no-boolean-in-except-test.yml +28 -0
  364. package/rules/ast-grep-rules/rule-tests/no-case-declarations-js-test.yml +24 -0
  365. package/rules/ast-grep-rules/rule-tests/no-case-declarations-test.yml +24 -0
  366. package/rules/ast-grep-rules/rule-tests/no-compare-neg-zero-js-test.yml +9 -0
  367. package/rules/ast-grep-rules/rule-tests/no-compare-neg-zero-test.yml +9 -0
  368. package/rules/ast-grep-rules/rule-tests/no-comparison-to-none-test.yml +11 -0
  369. package/rules/ast-grep-rules/rule-tests/no-comparison-to-true-false-test.yml +13 -0
  370. package/rules/ast-grep-rules/rule-tests/no-compile-call-test.yml +10 -0
  371. package/rules/ast-grep-rules/rule-tests/no-cond-assign-js-test.yml +9 -0
  372. package/rules/ast-grep-rules/rule-tests/no-cond-assign-test.yml +9 -0
  373. package/rules/ast-grep-rules/rule-tests/no-console-except-error-js-test.yml +13 -0
  374. package/rules/ast-grep-rules/rule-tests/no-console-except-error-test.yml +13 -0
  375. package/rules/ast-grep-rules/rule-tests/no-constant-condition-js-test.yml +10 -0
  376. package/rules/ast-grep-rules/rule-tests/no-constant-condition-test.yml +10 -0
  377. package/rules/ast-grep-rules/rule-tests/no-db-string-literal-password-test.yml +8 -0
  378. package/rules/ast-grep-rules/rule-tests/no-demeter-message-chain-test.yml +16 -0
  379. package/rules/ast-grep-rules/rule-tests/no-discarded-error-js-test.yml +9 -0
  380. package/rules/ast-grep-rules/rule-tests/no-discarded-error-test.yml +9 -0
  381. package/rules/ast-grep-rules/rule-tests/no-dunder-exit-wrong-arity-test.yml +27 -0
  382. package/rules/ast-grep-rules/rule-tests/no-dupe-class-members-test.yml +11 -0
  383. package/rules/ast-grep-rules/rule-tests/no-dupe-keys-js-test.yml +9 -0
  384. package/rules/ast-grep-rules/rule-tests/no-dupe-keys-test.yml +9 -0
  385. package/rules/ast-grep-rules/rule-tests/no-duplicate-kwarg-test.yml +8 -0
  386. package/rules/ast-grep-rules/rule-tests/no-ellipsis-body-test.yml +20 -0
  387. package/rules/ast-grep-rules/rule-tests/no-except-non-exception-test.yml +23 -0
  388. package/rules/ast-grep-rules/rule-tests/no-extra-boolean-cast-js-test.yml +9 -0
  389. package/rules/ast-grep-rules/rule-tests/no-extra-boolean-cast-test.yml +9 -0
  390. package/rules/ast-grep-rules/rule-tests/no-fastapi-router-prefix-outside-init-test.yml +8 -0
  391. package/rules/ast-grep-rules/rule-tests/no-flag-argument-js-test.yml +37 -0
  392. package/rules/ast-grep-rules/rule-tests/no-flag-argument-test.yml +37 -0
  393. package/rules/ast-grep-rules/rule-tests/no-flask-preprocess-request-ignored-test.yml +16 -0
  394. package/rules/ast-grep-rules/rule-tests/no-flask-secret-key-literal-test.yml +11 -0
  395. package/rules/ast-grep-rules/rule-tests/no-flask-sendfile-without-mimetype-test.yml +8 -0
  396. package/rules/ast-grep-rules/rule-tests/no-global-eval-js-test.yml +17 -0
  397. package/rules/ast-grep-rules/rule-tests/no-hardcoded-password-test.yml +10 -0
  398. package/rules/ast-grep-rules/rule-tests/no-html-autoescape-off-test.yml +13 -0
  399. package/rules/ast-grep-rules/rule-tests/no-http-headers-bracket-access-test.yml +7 -0
  400. package/rules/ast-grep-rules/rule-tests/no-identity-operator-on-literals-test.yml +14 -0
  401. package/rules/ast-grep-rules/rule-tests/no-implied-eval-js-test.yml +12 -0
  402. package/rules/ast-grep-rules/rule-tests/no-implied-eval-test.yml +12 -0
  403. package/rules/ast-grep-rules/rule-tests/no-init-return-test.yml +26 -0
  404. package/rules/ast-grep-rules/rule-tests/no-inner-html-js-test.yml +8 -0
  405. package/rules/ast-grep-rules/rule-tests/no-inner-html-test.yml +8 -0
  406. package/rules/ast-grep-rules/rule-tests/no-insecure-randomness-js-test.yml +13 -0
  407. package/rules/ast-grep-rules/rule-tests/no-insecure-randomness-test.yml +13 -0
  408. package/rules/ast-grep-rules/rule-tests/no-instanceof-array-js-test.yml +8 -0
  409. package/rules/ast-grep-rules/rule-tests/no-instanceof-array-test.yml +8 -0
  410. package/rules/ast-grep-rules/rule-tests/no-instanceof-builtins-js-test.yml +11 -0
  411. package/rules/ast-grep-rules/rule-tests/no-instanceof-builtins-test.yml +11 -0
  412. package/rules/ast-grep-rules/rule-tests/no-javascript-url-js-test.yml +9 -0
  413. package/rules/ast-grep-rules/rule-tests/no-javascript-url-test.yml +9 -0
  414. package/rules/ast-grep-rules/rule-tests/no-jinja2-autoescape-off-test.yml +13 -0
  415. package/rules/ast-grep-rules/rule-tests/no-marshal-load-test.yml +10 -0
  416. package/rules/ast-grep-rules/rule-tests/no-mutable-contextvar-default-test.yml +9 -0
  417. package/rules/ast-grep-rules/rule-tests/no-mutable-default-test.yml +12 -0
  418. package/rules/ast-grep-rules/rule-tests/no-mutable-export-test.yml +10 -0
  419. package/rules/ast-grep-rules/rule-tests/no-nan-comparison-js-test.yml +11 -0
  420. package/rules/ast-grep-rules/rule-tests/no-nan-comparison-test.yml +11 -0
  421. package/rules/ast-grep-rules/rule-tests/no-negation-in-equality-check-js-test.yml +10 -0
  422. package/rules/ast-grep-rules/rule-tests/no-negation-in-equality-check-test.yml +10 -0
  423. package/rules/ast-grep-rules/rule-tests/no-nested-links-test.yml +8 -0
  424. package/rules/ast-grep-rules/rule-tests/no-new-symbol-js-test.yml +8 -0
  425. package/rules/ast-grep-rules/rule-tests/no-new-symbol-test.yml +8 -0
  426. package/rules/ast-grep-rules/rule-tests/no-new-wrappers-js-test.yml +9 -0
  427. package/rules/ast-grep-rules/rule-tests/no-new-wrappers-test.yml +9 -0
  428. package/rules/ast-grep-rules/rule-tests/no-non-null-assertion-test.yml +10 -0
  429. package/rules/ast-grep-rules/rule-tests/no-notimplemented-in-bool-test.yml +20 -0
  430. package/rules/ast-grep-rules/rule-tests/no-numpy-nan-equality-test.yml +22 -0
  431. package/rules/ast-grep-rules/rule-tests/no-octal-literal-test.yml +8 -0
  432. package/rules/ast-grep-rules/rule-tests/no-only-defined-names-in-dunder-all-test.yml +17 -0
  433. package/rules/ast-grep-rules/rule-tests/no-open-redirect-js-test.yml +12 -0
  434. package/rules/ast-grep-rules/rule-tests/no-open-redirect-test.yml +12 -0
  435. package/rules/ast-grep-rules/rule-tests/no-prototype-builtins-js-test.yml +9 -0
  436. package/rules/ast-grep-rules/rule-tests/no-prototype-builtins-native-test.yml +9 -0
  437. package/rules/ast-grep-rules/rule-tests/no-prototype-builtins-test.yml +9 -0
  438. package/rules/ast-grep-rules/rule-tests/no-python-sql-string-concat-test.yml +10 -0
  439. package/rules/ast-grep-rules/rule-tests/no-raise-not-implemented-test.yml +21 -0
  440. package/rules/ast-grep-rules/rule-tests/no-raise-stopiteration-in-generator-test.yml +22 -0
  441. package/rules/ast-grep-rules/rule-tests/no-relative-cross-package-import-test.yml +9 -0
  442. package/rules/ast-grep-rules/rule-tests/no-requests-verify-false-test.yml +11 -0
  443. package/rules/ast-grep-rules/rule-tests/no-requests-without-timeout-test.yml +10 -0
  444. package/rules/ast-grep-rules/rule-tests/no-return-await-test.yml +12 -0
  445. package/rules/ast-grep-rules/rule-tests/no-return-value-in-generator-test.yml +22 -0
  446. package/rules/ast-grep-rules/rule-tests/no-secret-in-env-var-name-test.yml +11 -0
  447. package/rules/ast-grep-rules/rule-tests/no-server-bind-wildcard-test.yml +10 -0
  448. package/rules/ast-grep-rules/rule-tests/no-single-promise-in-promise-methods-js-test.yml +10 -0
  449. package/rules/ast-grep-rules/rule-tests/no-single-promise-in-promise-methods-test.yml +10 -0
  450. package/rules/ast-grep-rules/rule-tests/no-singledispatch-on-method-test.yml +25 -0
  451. package/rules/ast-grep-rules/rule-tests/no-sort-without-comparator-test.yml +8 -0
  452. package/rules/ast-grep-rules/rule-tests/no-sql-in-code-js-test.yml +10 -0
  453. package/rules/ast-grep-rules/rule-tests/no-sql-in-code-test.yml +10 -0
  454. package/rules/ast-grep-rules/rule-tests/no-star-imports-test.yml +9 -0
  455. package/rules/ast-grep-rules/rule-tests/no-string-ref-test.yml +8 -0
  456. package/rules/ast-grep-rules/rule-tests/no-template-string-concat-test.yml +14 -0
  457. package/rules/ast-grep-rules/rule-tests/no-testclient-text-without-content-test.yml +10 -0
  458. package/rules/ast-grep-rules/rule-tests/no-throw-string-js-test.yml +10 -0
  459. package/rules/ast-grep-rules/rule-tests/no-throw-string-test.yml +10 -0
  460. package/rules/ast-grep-rules/rule-tests/no-typeof-undefined-js-test.yml +11 -0
  461. package/rules/ast-grep-rules/rule-tests/no-typeof-undefined-test.yml +11 -0
  462. package/rules/ast-grep-rules/rule-tests/no-unimplemented-stub-js-test.yml +10 -0
  463. package/rules/ast-grep-rules/rule-tests/no-unimplemented-stub-test.yml +10 -0
  464. package/rules/ast-grep-rules/rule-tests/no-unnecessary-array-flat-depth-js-test.yml +8 -0
  465. package/rules/ast-grep-rules/rule-tests/no-unnecessary-array-flat-depth-test.yml +8 -0
  466. package/rules/ast-grep-rules/rule-tests/no-unnecessary-state-initializer-test.yml +7 -0
  467. package/rules/ast-grep-rules/rule-tests/no-useless-length-check-js-test.yml +9 -0
  468. package/rules/ast-grep-rules/rule-tests/no-useless-length-check-test.yml +9 -0
  469. package/rules/ast-grep-rules/rule-tests/no-useless-promise-resolve-reject-js-test.yml +8 -0
  470. package/rules/ast-grep-rules/rule-tests/no-useless-promise-resolve-reject-test.yml +8 -0
  471. package/rules/ast-grep-rules/rule-tests/no-useless-rest-spread-js-test.yml +8 -0
  472. package/rules/ast-grep-rules/rule-tests/no-useless-rest-spread-test.yml +8 -0
  473. package/rules/ast-grep-rules/rule-tests/no-uvicorn-non-import-string-test.yml +10 -0
  474. package/rules/ast-grep-rules/rule-tests/no-xxe-vulnerable-xml-parser-test.yml +19 -0
  475. package/rules/ast-grep-rules/rule-tests/no-yield-from-non-iterable-test.yml +11 -0
  476. package/rules/ast-grep-rules/rule-tests/no-yield-return-outside-function-test.yml +19 -0
  477. package/rules/ast-grep-rules/rule-tests/only-strings-in-dunder-all-test.yml +18 -0
  478. package/rules/ast-grep-rules/rule-tests/prefer-array-find-js-test.yml +8 -0
  479. package/rules/ast-grep-rules/rule-tests/prefer-array-find-test.yml +8 -0
  480. package/rules/ast-grep-rules/rule-tests/prefer-array-flat-map-js-test.yml +8 -0
  481. package/rules/ast-grep-rules/rule-tests/prefer-array-flat-map-test.yml +8 -0
  482. package/rules/ast-grep-rules/rule-tests/prefer-array-some-js-test.yml +9 -0
  483. package/rules/ast-grep-rules/rule-tests/prefer-array-some-test.yml +9 -0
  484. package/rules/ast-grep-rules/rule-tests/prefer-at-js-test.yml +8 -0
  485. package/rules/ast-grep-rules/rule-tests/prefer-at-test.yml +8 -0
  486. package/rules/ast-grep-rules/rule-tests/prefer-date-now-js-test.yml +8 -0
  487. package/rules/ast-grep-rules/rule-tests/prefer-date-now-test.yml +8 -0
  488. package/rules/ast-grep-rules/rule-tests/prefer-dom-node-append-js-test.yml +8 -0
  489. package/rules/ast-grep-rules/rule-tests/prefer-dom-node-append-test.yml +8 -0
  490. package/rules/ast-grep-rules/rule-tests/prefer-dom-node-text-content-js-test.yml +9 -0
  491. package/rules/ast-grep-rules/rule-tests/prefer-dom-node-text-content-test.yml +9 -0
  492. package/rules/ast-grep-rules/rule-tests/prefer-keyboard-event-key-js-test.yml +11 -0
  493. package/rules/ast-grep-rules/rule-tests/prefer-keyboard-event-key-test.yml +11 -0
  494. package/rules/ast-grep-rules/rule-tests/prefer-math-min-max-js-test.yml +10 -0
  495. package/rules/ast-grep-rules/rule-tests/prefer-math-min-max-test.yml +10 -0
  496. package/rules/ast-grep-rules/rule-tests/prefer-number-properties-js-test.yml +9 -0
  497. package/rules/ast-grep-rules/rule-tests/prefer-number-properties-test.yml +9 -0
  498. package/rules/ast-grep-rules/rule-tests/prefer-optional-chain-test.yml +9 -0
  499. package/rules/ast-grep-rules/rule-tests/prefer-prototype-methods-js-test.yml +8 -0
  500. package/rules/ast-grep-rules/rule-tests/prefer-prototype-methods-test.yml +8 -0
  501. package/rules/ast-grep-rules/rule-tests/prefer-query-selector-js-test.yml +9 -0
  502. package/rules/ast-grep-rules/rule-tests/prefer-query-selector-test.yml +9 -0
  503. package/rules/ast-grep-rules/rule-tests/prefer-string-slice-js-test.yml +9 -0
  504. package/rules/ast-grep-rules/rule-tests/prefer-string-slice-test.yml +9 -0
  505. package/rules/ast-grep-rules/rule-tests/prefer-string-starts-ends-with-js-test.yml +9 -0
  506. package/rules/ast-grep-rules/rule-tests/prefer-string-starts-ends-with-test.yml +9 -0
  507. package/rules/ast-grep-rules/rule-tests/prefer-string-trim-start-end-js-test.yml +9 -0
  508. package/rules/ast-grep-rules/rule-tests/prefer-string-trim-start-end-test.yml +9 -0
  509. package/rules/ast-grep-rules/rule-tests/prefer-structured-clone-js-test.yml +8 -0
  510. package/rules/ast-grep-rules/rule-tests/prefer-structured-clone-test.yml +8 -0
  511. package/rules/ast-grep-rules/rule-tests/redos-nested-quantifier-test.yml +14 -0
  512. package/rules/ast-grep-rules/rule-tests/redundant-state-test.yml +8 -0
  513. package/rules/ast-grep-rules/rule-tests/redundant-unsafe-function-test.yml +25 -0
  514. package/rules/ast-grep-rules/rule-tests/redundant-usestate-type-test.yml +10 -0
  515. package/rules/ast-grep-rules/rule-tests/require-await-test.yml +9 -0
  516. package/rules/ast-grep-rules/rule-tests/ruby-detect-path-traversal-test.yml +9 -0
  517. package/rules/ast-grep-rules/rule-tests/rust-2024-let-chain-candidate-test.yml +27 -0
  518. package/rules/ast-grep-rules/rule-tests/strict-equality-js-test.yml +9 -0
  519. package/rules/ast-grep-rules/rule-tests/strict-equality-test.yml +9 -0
  520. package/rules/ast-grep-rules/rule-tests/strict-inequality-js-test.yml +9 -0
  521. package/rules/ast-grep-rules/rule-tests/strict-inequality-test.yml +9 -0
  522. package/rules/ast-grep-rules/rule-tests/string-concat-in-loop-test.yml +20 -0
  523. package/rules/ast-grep-rules/rule-tests/switch-without-default-test.yml +16 -0
  524. package/rules/ast-grep-rules/rule-tests/throw-new-error-js-test.yml +10 -0
  525. package/rules/ast-grep-rules/rule-tests/throw-new-error-test.yml +10 -0
  526. package/rules/ast-grep-rules/rule-tests/ts-array-concat-spread-test.yml +9 -0
  527. package/rules/ast-grep-rules/rule-tests/ts-array-every-some-test.yml +8 -0
  528. package/rules/ast-grep-rules/rule-tests/ts-boolean-return-if-else-test.yml +13 -0
  529. package/rules/ast-grep-rules/rule-tests/ts-defensive-null-guard-test.yml +14 -0
  530. package/rules/ast-grep-rules/rule-tests/ts-delete-property-test.yml +8 -0
  531. package/rules/ast-grep-rules/rule-tests/ts-double-negation-test.yml +9 -0
  532. package/rules/ast-grep-rules/rule-tests/ts-function-constructor-test.yml +8 -0
  533. package/rules/ast-grep-rules/rule-tests/ts-in-operator-loop-test.yml +13 -0
  534. package/rules/ast-grep-rules/rule-tests/ts-isnan-check-test.yml +9 -0
  535. package/rules/ast-grep-rules/rule-tests/ts-json-stringify-parse-test.yml +8 -0
  536. package/rules/ast-grep-rules/rule-tests/ts-manual-array-contains-test.yml +13 -0
  537. package/rules/ast-grep-rules/rule-tests/ts-nullish-coalescing-opportunity-test.yml +8 -0
  538. package/rules/ast-grep-rules/rule-tests/ts-object-hasown-check-test.yml +8 -0
  539. package/rules/ast-grep-rules/rule-tests/ts-optional-chaining-default-test.yml +8 -0
  540. package/rules/ast-grep-rules/rule-tests/ts-parseint-no-radix-test.yml +9 -0
  541. package/rules/ast-grep-rules/rule-tests/ts-pointless-bool-cast-test.yml +13 -0
  542. package/rules/ast-grep-rules/rule-tests/ts-redundant-filter-map-test.yml +8 -0
  543. package/rules/ast-grep-rules/rule-tests/ts-slice-copy-test.yml +8 -0
  544. package/rules/ast-grep-rules/rule-tests/ts-string-split-index-test.yml +9 -0
  545. package/rules/ast-grep-rules/rule-tests/ts-unnecessary-array-concat-test.yml +8 -0
  546. package/rules/ast-grep-rules/rule-tests/ts-unnecessary-array-from-test.yml +8 -0
  547. package/rules/ast-grep-rules/rule-tests/ts-unnecessary-bind-test.yml +9 -0
  548. package/rules/ast-grep-rules/rule-tests/ts-unnecessary-else-return-test.yml +13 -0
  549. package/rules/ast-grep-rules/rule-tests/ts-void-zero-test.yml +9 -0
  550. package/rules/ast-grep-rules/rule-tests/ts-while-index-length-test.yml +8 -0
  551. package/rules/ast-grep-rules/rule-tests/unchecked-throwing-call-js-test.yml +13 -0
  552. package/rules/ast-grep-rules/rule-tests/unchecked-throwing-call-python-test.yml +23 -0
  553. package/rules/ast-grep-rules/rule-tests/unchecked-throwing-call-test.yml +13 -0
  554. package/rules/ast-grep-rules/rule-tests/unlock-in-loop-test.yml +19 -0
  555. package/rules/ast-grep-rules/rule-tests/unmarshal-tag-is-dash-test.yml +23 -0
  556. package/rules/ast-grep-rules/rule-tests/unnecessary-react-hook-test.yml +8 -0
  557. package/rules/ast-grep-rules/rule-tests/waitgroup-done-scope-test.yml +20 -0
  558. package/rules/ast-grep-rules/rule-tests/weak-rsa-key-js-test.yml +9 -0
  559. package/rules/ast-grep-rules/rule-tests/weak-rsa-key-test.yml +9 -0
  560. package/rules/ast-grep-rules/rule-tests-disabled/no-method-field-name-collision-test.yml +23 -0
  561. package/rules/ast-grep-rules/rules/array-callback-return-js.yml +17 -10
  562. package/rules/ast-grep-rules/rules/array-callback-return.yml +16 -9
  563. package/rules/ast-grep-rules/rules/avoid-duplicate-export.yml +19 -0
  564. package/rules/ast-grep-rules/rules/defer-in-loop.yml +10 -0
  565. package/rules/ast-grep-rules/rules/find-import-file-without-extension.yml +22 -0
  566. package/rules/ast-grep-rules/rules/go-defer-func-call-antipattern.yml +34 -0
  567. package/rules/ast-grep-rules/rules/go-test-functions.yml +32 -0
  568. package/rules/ast-grep-rules/rules/gorm-find-without-where.yml +26 -0
  569. package/rules/ast-grep-rules/rules/gorm-n-plus-one.yml +16 -0
  570. package/rules/ast-grep-rules/rules/hardcoded-url-js.yml +10 -5
  571. package/rules/ast-grep-rules/rules/hardcoded-url.yml +9 -4
  572. package/rules/ast-grep-rules/rules/jsx-boolean-short-circuit.yml +33 -13
  573. package/rules/ast-grep-rules/rules/jwt-no-verify-js.yml +16 -3
  574. package/rules/ast-grep-rules/rules/jwt-no-verify.yml +15 -2
  575. package/rules/ast-grep-rules/rules/loop-var-capture.yml +42 -0
  576. package/rules/ast-grep-rules/rules/missing-component-decorator.yml +21 -0
  577. package/rules/ast-grep-rules/rules/mutex-unlock-mismatch.yml +14 -0
  578. package/rules/ast-grep-rules/rules/nil-map-assignment.yml +43 -0
  579. package/rules/ast-grep-rules/rules/no-any-type.yml +13 -4
  580. package/rules/ast-grep-rules/rules/no-assert-tuple.yml +24 -0
  581. package/rules/ast-grep-rules/rules/no-aws-access-key-literal.yml +30 -0
  582. package/rules/ast-grep-rules/rules/no-aws-apigateway-no-auth.yml +29 -0
  583. package/rules/ast-grep-rules/rules/no-aws-s3-public-access.yml +28 -0
  584. package/rules/ast-grep-rules/rules/no-bare-except.yml +21 -3
  585. package/rules/ast-grep-rules/rules/no-blank-target-js.yml +17 -6
  586. package/rules/ast-grep-rules/rules/no-boolean-in-except.yml +23 -0
  587. package/rules/ast-grep-rules/rules/no-comparison-to-none.yml +5 -0
  588. package/rules/ast-grep-rules/rules/no-comparison-to-true-false.yml +25 -0
  589. package/rules/ast-grep-rules/rules/no-compile-call.yml +29 -0
  590. package/rules/ast-grep-rules/rules/no-console-except-error-js.yml +20 -0
  591. package/rules/ast-grep-rules/rules/no-console-except-error.yml +20 -0
  592. package/rules/ast-grep-rules/rules/no-db-string-literal-password.yml +44 -0
  593. package/rules/ast-grep-rules/rules/no-demeter-message-chain.yml +25 -0
  594. package/rules/ast-grep-rules/rules/no-dunder-exit-wrong-arity.yml +25 -0
  595. package/rules/ast-grep-rules/rules/no-duplicate-kwarg.yml +26 -0
  596. package/rules/ast-grep-rules/rules/no-except-non-exception.yml +47 -0
  597. package/rules/ast-grep-rules/rules/no-extra-boolean-cast-js.yml +26 -21
  598. package/rules/ast-grep-rules/rules/no-extra-boolean-cast.yml +25 -20
  599. package/rules/ast-grep-rules/rules/no-fastapi-router-prefix-outside-init.yml +29 -0
  600. package/rules/ast-grep-rules/rules/no-flag-argument-js.yml +37 -0
  601. package/rules/ast-grep-rules/rules/no-flag-argument.yml +36 -0
  602. package/rules/ast-grep-rules/rules/no-flask-preprocess-request-ignored.yml +26 -0
  603. package/rules/ast-grep-rules/rules/no-flask-secret-key-literal.yml +36 -0
  604. package/rules/ast-grep-rules/rules/no-flask-sendfile-without-mimetype.yml +42 -0
  605. package/rules/ast-grep-rules/rules/no-global-eval-js.yml +5 -0
  606. package/rules/ast-grep-rules/rules/no-hardcoded-password.yml +42 -0
  607. package/rules/ast-grep-rules/rules/no-html-autoescape-off.yml +25 -0
  608. package/rules/ast-grep-rules/rules/no-http-headers-bracket-access.yml +22 -0
  609. package/rules/ast-grep-rules/rules/no-identity-operator-on-literals.yml +69 -0
  610. package/rules/ast-grep-rules/rules/no-implied-eval-js.yml +8 -5
  611. package/rules/ast-grep-rules/rules/no-implied-eval.yml +7 -4
  612. package/rules/ast-grep-rules/rules/no-init-return.yml +27 -0
  613. package/rules/ast-grep-rules/rules/no-inline-styles.yml +13 -6
  614. package/rules/ast-grep-rules/rules/no-javascript-url-js.yml +8 -4
  615. package/rules/ast-grep-rules/rules/no-javascript-url.yml +7 -3
  616. package/rules/ast-grep-rules/rules/no-jinja2-autoescape-off.yml +24 -0
  617. package/rules/ast-grep-rules/rules/no-marshal-load.yml +24 -0
  618. package/rules/ast-grep-rules/rules/no-mutable-contextvar-default.yml +38 -0
  619. package/rules/ast-grep-rules/rules/no-mutable-default.yml +8 -2
  620. package/rules/ast-grep-rules/rules/no-notimplemented-in-bool.yml +21 -0
  621. package/rules/ast-grep-rules/rules/no-numpy-nan-equality.yml +31 -0
  622. package/rules/ast-grep-rules/rules/no-only-defined-names-in-dunder-all.yml +36 -0
  623. package/rules/ast-grep-rules/rules/no-python-sql-string-concat.yml +37 -0
  624. package/rules/ast-grep-rules/rules/no-raise-stopiteration-in-generator.yml +28 -0
  625. package/rules/ast-grep-rules/rules/no-relative-imports.yml +13 -14
  626. package/rules/ast-grep-rules/rules/no-requests-verify-false.yml +27 -0
  627. package/rules/ast-grep-rules/rules/no-requests-without-timeout.yml +113 -0
  628. package/rules/ast-grep-rules/rules/no-return-value-in-generator.yml +31 -0
  629. package/rules/ast-grep-rules/rules/no-secret-in-env-var-name.yml +37 -0
  630. package/rules/ast-grep-rules/rules/no-server-bind-wildcard.yml +28 -0
  631. package/rules/ast-grep-rules/rules/no-singledispatch-on-method.yml +27 -0
  632. package/rules/ast-grep-rules/rules/no-sql-in-code-js.yml +15 -4
  633. package/rules/ast-grep-rules/rules/no-sql-in-code.yml +14 -3
  634. package/rules/ast-grep-rules/rules/no-string-ref.yml +13 -6
  635. package/rules/ast-grep-rules/rules/no-template-string-concat.yml +21 -0
  636. package/rules/ast-grep-rules/rules/no-testclient-text-without-content.yml +39 -0
  637. package/rules/ast-grep-rules/rules/no-uvicorn-non-import-string.yml +46 -0
  638. package/rules/ast-grep-rules/rules/no-xxe-vulnerable-xml-parser.yml +32 -0
  639. package/rules/ast-grep-rules/rules/no-yield-from-non-iterable.yml +33 -0
  640. package/rules/ast-grep-rules/rules/no-yield-return-outside-function.yml +31 -0
  641. package/rules/ast-grep-rules/rules/only-strings-in-dunder-all.yml +32 -0
  642. package/rules/ast-grep-rules/rules/redundant-unsafe-function.yml +21 -0
  643. package/rules/ast-grep-rules/rules/redundant-usestate-type.yml +15 -0
  644. package/rules/ast-grep-rules/rules/ruby-detect-path-traversal.yml +33 -0
  645. package/rules/ast-grep-rules/rules/rust-2024-let-chain-candidate.yml +56 -0
  646. package/rules/ast-grep-rules/rules/string-concat-in-loop.yml +31 -0
  647. package/rules/ast-grep-rules/rules/ts-array-concat-spread.yml +10 -0
  648. package/rules/ast-grep-rules/rules/ts-array-every-some.yml +22 -0
  649. package/rules/ast-grep-rules/rules/ts-boolean-return-if-else.yml +12 -0
  650. package/rules/ast-grep-rules/rules/ts-defensive-null-guard.yml +12 -0
  651. package/rules/ast-grep-rules/rules/ts-delete-property.yml +10 -0
  652. package/rules/ast-grep-rules/rules/ts-double-negation.yml +10 -0
  653. package/rules/ast-grep-rules/rules/ts-function-constructor.yml +12 -0
  654. package/rules/ast-grep-rules/rules/ts-in-operator-loop.yml +22 -0
  655. package/rules/ast-grep-rules/rules/ts-isnan-check.yml +10 -0
  656. package/rules/ast-grep-rules/rules/ts-json-stringify-parse.yml +17 -0
  657. package/rules/ast-grep-rules/rules/ts-manual-array-contains.yml +25 -0
  658. package/rules/ast-grep-rules/rules/ts-nullish-coalescing-opportunity.yml +20 -0
  659. package/rules/ast-grep-rules/rules/ts-object-hasown-check.yml +9 -0
  660. package/rules/ast-grep-rules/rules/ts-optional-chaining-default.yml +21 -0
  661. package/rules/ast-grep-rules/rules/ts-parseint-no-radix.yml +18 -0
  662. package/rules/ast-grep-rules/rules/ts-pointless-bool-cast.yml +10 -0
  663. package/rules/ast-grep-rules/rules/ts-redundant-filter-map.yml +10 -0
  664. package/rules/ast-grep-rules/rules/ts-slice-copy.yml +11 -0
  665. package/rules/ast-grep-rules/rules/ts-string-split-index.yml +12 -0
  666. package/rules/ast-grep-rules/rules/ts-unnecessary-array-concat.yml +9 -0
  667. package/rules/ast-grep-rules/rules/ts-unnecessary-array-from.yml +9 -0
  668. package/rules/ast-grep-rules/rules/ts-unnecessary-bind.yml +10 -0
  669. package/rules/ast-grep-rules/rules/ts-unnecessary-else-return.yml +19 -0
  670. package/rules/ast-grep-rules/rules/ts-void-zero.yml +10 -0
  671. package/rules/ast-grep-rules/rules/ts-while-index-length.yml +10 -0
  672. package/rules/ast-grep-rules/rules/unlock-in-loop.yml +22 -0
  673. package/rules/ast-grep-rules/rules/unmarshal-tag-is-dash.yml +20 -0
  674. package/rules/ast-grep-rules/rules/unnecessary-react-hook.yml +27 -0
  675. package/rules/ast-grep-rules/rules/waitgroup-done-scope.yml +11 -0
  676. package/rules/ast-grep-rules/rules/weak-rsa-key-js.yml +16 -3
  677. package/rules/ast-grep-rules/rules/weak-rsa-key.yml +15 -2
  678. package/rules/ast-grep-rules/rules-disabled/gorm-unbounded-preload.yml +41 -0
  679. package/rules/ast-grep-rules/rules-disabled/no-method-field-name-collision.yml +42 -0
  680. package/rules/ast-grep-rules/rules-disabled/shadow-err-variable.yml +38 -0
  681. package/rules/rule-catalog.json +1721 -133
  682. package/rules/tree-sitter-queries/python/aws-public-access-policy.yml +68 -0
  683. package/rules/tree-sitter-queries/python/endpoint-204-with-body.yml +62 -0
  684. package/rules/tree-sitter-queries/python/open-invalid-mode.yml +58 -0
  685. package/rules/tree-sitter-queries/python/python-special-method-arity.yml +67 -0
  686. package/rules/tree-sitter-queries/python/python-sql-injection.yml +12 -3
  687. package/rules/tree-sitter-queries/python/python-thread-global-write.yml +6 -0
  688. package/rules/tree-sitter-queries/python/python-unsafe-regex.yml +20 -19
  689. package/rules/tree-sitter-queries/python/slots-assignment-mismatch.yml +73 -0
  690. package/rules/tree-sitter-queries/python/string-format-arity-mismatch.yml +52 -0
  691. package/rules/tree-sitter-queries/{python → python-disabled}/python-print-statement.yml +14 -0
  692. package/scripts/install-selftest.mjs +173 -0
  693. package/scripts/rpc-load-check.mjs +80 -0
  694. package/skills/ast-grep/SKILL.md +26 -6
  695. package/skills/lsp-navigation/SKILL.md +4 -0
  696. package/skills/write-ast-grep-rule/SKILL.md +74 -4
  697. package/dist/clients/dispatch/runners/semgrep.js +0 -197
  698. package/dist/clients/secrets-scanner.js +0 -181
  699. package/dist/clients/semgrep-config.js +0 -157
  700. package/rules/ast-grep-rules/slop-patterns.yml +0 -469
package/CHANGELOG.md CHANGED
@@ -4,11 +4,125 @@ All notable changes to pi-lens will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ### Added
8
+
9
+ ### Changed
10
+
11
+ ### Fixed
12
+
13
+ ## [3.8.62] - 2026-06-28
14
+
15
+ ### Added
16
+
17
+ - **Compact, blue-branded tool-result rendering (refs #345)** — the navigable/structural/diagnostic tools (`module_report`, `read_symbol`, `read_enclosing`, `ast_grep_search`, `ast_grep_replace`, `ast_grep_dump`/`ast_dump`, `ast_grep_outline`, `lsp_navigation`, `lsp_diagnostics`, `lens_diagnostics`) no longer flood the terminal with their full body. Each now defines a `renderResult` that shows a one-line summary by default — in pi-lens **blue characters** (bold blue text on the default tool-shell background) built from the tool's structured `details` (semantic counts/ranges, not blind truncation) — while the **model still receives the untouched full `content`**; the full output is one keystroke away via expand. Errors stay theme-red. The pi host only dumps a tool's `content` verbatim when it defines no `renderResult`, so supplying one decouples the model payload from the terminal view. Coexists with global renderer extensions (pi-tool-display / pi-claude-style-tools), which default to respecting a tool's own renderer. Shared helper `tools/render-compact.ts`, with unit tests; `pi-tui` `Text` routed through the `clients/deps/*` accessor (dep-centralization seam #285/#335).
18
+ - **Cross-file dead-code detection for non-JS/TS languages — Phase 1: Python via vulture (#127)** — Knip gives JS/TS projects project-wide unused exports/files/deps at session-start, but per-file dispatch linters can't catch "this exported symbol is unused anywhere in the project" for other languages. New `DeadCodeClient` interface (`clients/dead-code-client.ts`) parallels Knip's lifecycle (detect → ensureAvailable → analyze, cached at session-start, surfaced as a turn-end advisory), with a Python implementation backed by [`vulture`](https://github.com/jendrikseipp/vulture). Detection gates on a Python marker (`pyproject.toml`/`setup.py`/`requirements.txt`/…) with the same home-dir + VCS-boundary containment as Knip, so a scan launched from a bare cwd can't recurse `$HOME`. **Presence-gated, never auto-installed** — vulture is a pure-Python package with no standalone binary, so auto-installing would mean mutating the user's active Python environment (wrong for uv/poetry/conda/pipx); pi-lens uses it only when already present, probing both the `vulture` script and `python -m vulture` (mirrors `govulncheck`'s no-install gating). Its text output (`path:line: unused <kind> '<name>' (NN% confidence)`) is parsed into the uniform `DeadCodeResult` buckets. The turn-end advisory reads the cached session-start scan (project-wide scans are slow — no per-turn re-scan) and merges across languages for polyglot repos; advisory-only, never a blocker. Telemetry: one NDJSON event per scan to `~/.pi-lens/dead-code.log`. Future phases add Go/Rust/etc. by implementing the interface. Guards: parser unit tests against captured real vulture output + a guarded real-binary integration test.
19
+
20
+ ### Changed
21
+
22
+ - **Round-2 agent-tool ergonomics (#345): validation, summary tiers, and high-volume caps** — `ast_grep_search` gains `validateOnly` (compile a pattern/rule against a throwaway snippet to distinguish a bad pattern from a real no-match), `maxMatches` (per-call cap, default 50 / max 200; also the pagination step for `skip`), and `groupByFile` (compact one-line-per-file `L<line>:<col>` distribution instead of full match bodies — for high-volume searches; per-match read slices stay in `details.matchLocations`). The pattern/rule validator uses a per-language temp snippet so the throwaway file parses under the requested lang, rejects NUL/oversized inputs before spawning, and treats only line-anchored `error:` stderr as failure (not warnings like "contains ERROR node"). `module_report` gains a `summary` view tier (top-level read handles + `recommendedReads`; heavy callback/usedBy/blast-radius payloads omitted) and section-level `provenance` (`syntax` / `cached-review-graph` / `heuristic` / `none`); the unimplemented `deep` view tier was dropped. Unit tests cover each. (Block-unit selection from the same plan was deliberately deferred — per-language tree-sitter block queries across ~15 grammars are high-risk/low-marginal-value over the existing `read_enclosing onOversize=slice`.)
23
+ - **Agent-tool ergonomics for ast-grep search/debug flows** — `ast_grep_search` results now include `details.matchLocations[]` with ready `readSlice` handles so agents can jump from a structural hit to bounded context without manually computing offsets. Zero-match results now point at `ast_grep_dump` and include a bounded `suggestedDump` hint instead of leaving agents to guess node kinds. Added `ast_grep_dump` as the preferred AST dump tool name while keeping `ast_dump` as a compatibility alias; the ast-grep skill now includes lifecycle/callback search recipes. New `ast_grep_outline` exposes `ast-grep outline` as a syntax-only structure tool (symbols/imports/exports/members for files or directories, with `items`/`view`/`type`/`match`/`pubMembers`/`globs` and ready `read` handles) — fast, local, no index/LSP; `module_report` stays the pi-lens-aware default.
24
+
25
+ - **`module_report` now surfaces callback/closure handles, with per-language semantics** — reports include a `callbacks[]` section for high-signal inline executable nodes that normal symbol outlines miss: event handlers (`pi.on`/`*.on`), timers, promise callbacks, object/dict function properties, and assigned closures/lambdas/function literals. Each entry has stable synthetic `name`, flags such as `captures ctx.ui` / `detached timer`, and ready `read` args. `read_symbol` now accepts those handles, returns the exact body, and records read-guard coverage just like a named symbol. New `read_enclosing` bridges search/diagnostic line hits to the smallest enclosing symbol/callback body, also with read-guard coverage. `module_report.focus` can optionally rank existing symbols/callbacks in `recommendedReads` without expanding scope, building the graph, or calling LSP. The inline-executable *node kinds* are language-uniform over the tree-sitter WASMs, but the callback *semantics* are per-language via a `CALLBACK_RULES` table keyed like `SYMBOL_QUERIES`: JS/TS-tuned rules are the default, plus language slices for Go (goroutine/`defer` closures), Python (scheduler/future lambdas — `call_later`/`call_soon`/`Timer`/`add_done_callback`), Rust (`spawn` and `move` closures), Swift (strong-vs-`[weak self]` capture — the retain-cycle signal), C++ (`[&]` by-reference capture + `std::thread`/`std::async` launches), Kotlin (coroutine builders — `launch`/`async`/`withContext`/…), Java (`new Thread`, executor `submit`/`execute`/`schedule`, UI/event listeners), and C# (`Task.Run`/`StartNew` + `event += handler` subscriptions) that surface lifecycle callbacks the generic rules previously dropped. The report's `callbackSupport: "tuned" | "generic"` flag tells callers whether language-specific rules applied, so the list isn't over-trusted for untuned languages. (Named-symbol navigation — `module_report` outline, `read_symbol`, `read_enclosing` — already spans all ~19 tree-sitter `SYMBOL_QUERIES` languages.) Each symbol/member entry now also carries `decorators[]` — the declaration's decorators/attributes/annotations in source order (`@app.get("/x")`, `#[tokio::main]`, `@Override`), surfacing a symbol's role (route/test/fixture/entrypoint) without reading its body. Extracted structurally from the declaration node (preceding-sibling / own-child / `modifiers`-nested shapes), spanning Python/Rust/TS/Java/Kotlin/C# including nested method members. Async/suspend functions and methods now carry an `async` flag (structurally detected — `async` keyword node or `async`/`suspend` in a modifiers container), marking concurrency boundaries.
26
+
27
+ - **Fuller, more correct utilization of knip + madge (tool-utilization audit)** — an audit of our whole-project analyzers (validated by running them on this repo) found gaps and silent-failure modes. (1) **knip** now requests `enumMembers` in `--include` — finer-grained dead code (unused enum members) than file-level exports, advisory-only. *(The audit also caught a bug: knip 6.x has **no `classMembers` issue type** — requesting it makes knip exit 2 with zero output, silently disabling the scan. Verified against knip 6.20.)* (2) **madge** now passes `--ts-config <tsconfig.json>` when one exists, so TypeScript `paths` aliases (`@/foo`) resolve — previously alias-routed imports were silently unresolved and **cycles through an alias were missed**. (3) **madge** `--extensions` gained `mjs,cjs`. (4) **madge** now runs with `--warning` and we parse its stderr for **skipped (unresolvable) files** — previously `--json` mode hid these, so a skipped *local* file could silently drop an internal edge and hide a cycle; local skips are now logged (external package skips are expected and ignored). jscpd was already broad (≈20 languages, unrestricted scan since #126) — no gap there. Guards: knip member-type parse test, `buildMadgeArgs` + `parseMadgeSkips` unit tests.
28
+ - **Turn-end injects only this-turn, high-confidence findings — not the full project-wide warning set** — measured on this repo, the whole-project analyzers emit hundreds of findings (knip 390, jscpd 136 clones in `clients/` alone), most pre-existing and noisy. Injecting that wall every turn would drown the genuine blockers and burn context. So the turn-end knip advisory now surfaces only the **delta attributable to the agent's edits** (symbols in files it just touched that became unused) — low-volume and actionable — instead of the whole project. The full picture remains available on demand via `lens_diagnostics`, and the delta still feeds the session-slop record. (madge already operated in this blockers-only mode.)
29
+ - **Read-guard: every blocking verdict ends with a concrete next-action line (#328)** — an LLM recovers best when each blocking/retryable verdict tells it exactly what to do next. An audit found the read-guard verdicts were *almost* uniform — `read-guard.ts` (zero-read / file-modified / out-of-range / range-stale) and the oldText-not-found path all already end with a recovery instruction — except the `unsupported_hashline_edit_target` block (malformed/unsupported hashline anchors), which listed the errors with no next step. It now ends with a single concrete next-action ("Re-read `<file>` to get current #line anchors, then retry with `set_line` / `replace_lines` — or use a native ranged edit"). Message-only; a guard test asserts the next-action line is present.
30
+
31
+ ### Fixed
32
+
33
+ - **LSP idle reset no longer touches stale pi contexts after session replacement (#338)** — the detached 240s idle timer now captures any footer repaint callback while the `turn_end` event context is still active, skips resets from superseded session generations, and swallows timer-only cleanup errors so `ctx.newSession()` / `ctx.fork()` / `ctx.switchSession()` / `ctx.reload()` cannot crash later when the old `ctx.ui` getter becomes stale.
34
+
35
+ ## [3.8.61] - 2026-06-25
36
+
37
+ ### Added
38
+
39
+ - **Release notes now come from CHANGELOG.md (single source of truth) + per-language rule catalogs** — the GitHub release body is now the curated `## [VERSION]` CHANGELOG section instead of an auto-generated PR-title list, condensed to a scannable summary (bold titles grouped by Added/Changed/Fixed) by `scripts/changelog-extract.mjs --summary`; `release.yml` posts it via `gh release create --notes-file`. New helpers: `scripts/lib/changelog.mjs` (pure section parser), `changelog-release.mjs` (`npm run changelog:release` promotes `[Unreleased]` → a dated version section at bump time), and `backfill-github-releases.mjs` (retroactively set existing release bodies; all 35 v3.8.x releases were backfilled). Also added two generated docs — `docs/ast-grep_rules_catalog.md` and `docs/tree-sitter_rules_catalog.md` (rules listed per language via `npm run docs:rule-catalogs`, kept in sync by a `--check` test).
40
+ - **Trivy security suite — four scan modes (#131)** — integrated [Trivy](https://github.com/aquasecurity/trivy) as the consolidated dependency/secret/IaC scanner that the removed built-in regex scanner and the scattered overlapping paths pointed toward. **Mode 1 — dependency CVEs** (#313): a session-scan client that resolves the project's lockfiles and surfaces known-vulnerable dependencies once per session (not per-edit). **Mode 3 — secret scan** (#314): edit/write-path secret detection with cross-source dedup so a secret already flagged by gitleaks or an ast-grep `*-hardcoded-secret-*` rule isn't reported twice. **Mode 2 — IaC misconfiguration** (#316): a per-edit runner for Terraform/Kubernetes/Dockerfile/etc. misconfigurations. **Mode 4 — dependency license risk** (#318): flags dependencies whose licenses fall outside an allow/deny policy. Trivy auto-installs on demand; each mode is independently gated.
41
+ - **typos spell-checker as a cross-cutting auxiliary LSP (#283)** — [`typos-lsp`](https://github.com/tekumara/typos-lsp) (wrapping `crate-ci/typos`) attaches as a `role:"auxiliary"` diagnostic server alongside the file's primary language server, surfacing source-code and Markdown misspellings warm (the Opengrep/ast-grep auxiliary-LSP template). Allow-list based — it only flags *known* misspellings against a compiled-in dictionary, so the false-positive rate on code is low. Default-on when the binary is available (`--no-typos` to disable); a repo-local `typos.toml`/`_typos.toml`/`.typos.toml` opts in to blocking. Validated end-to-end via a tool-smoke fixture.
42
+ - **ast-grep project scan via the bundled napi engine (#308)** — the project-wide ast-grep pass now runs in-process through `@ast-grep/napi` (#309) instead of shelling out, and de-dups its findings against the warm `ast-grep` LSP so a rule that fires in both surfaces is reported once (#311).
43
+ - **37 SonarCloud Python BLOCKER rules as ast-grep rules (#317)** — ported SonarCloud's Python BLOCKER-severity checks to bundled ast-grep rules, with style-consistency passes and false-positive fixes. The same batch also added a set of Python **security** detectors — Flask/Jinja2 autoescape-off, XXE-vulnerable XML parsers, hardcoded secrets/passwords, AWS S3 public-access / API-Gateway no-auth misconfig, `requests` without timeout / `verify=False`, SQL string concatenation, wildcard server binds — for ~55 new rule files total. **6 more SonarCloud Python BLOCKER rules as tree-sitter queries (#319)** for checks that need structural matching ast-grep patterns can't express.
44
+ - **ast-grep flag-argument + Law-of-Demeter rules (#305)** — new detector rules for boolean flag arguments and long message chains (Law of Demeter), with behavioural fixtures (#326). Plus a behavioural-fixture harness covering the rule catalog with 15 accompanying rule fixes (#310).
45
+ - **Go concurrency / correctness / GORM ast-grep rules** — a batch of Go idiom detectors: **concurrency** — `loop-var-capture` (loop var captured by a goroutine closure), `mutex-unlock-mismatch` / `unlock-in-loop` (unpaired `Lock`/`Unlock`), `waitgroup-done-scope` (`WaitGroup.Done()` outside the goroutine that called `Add`); **correctness** — `nil-map-assignment` (assignment to a nil map panics), `defer-in-loop` + `go-defer-func-call-antipattern` (defer semantics inside loops / eager arg evaluation); **performance** — `string-concat-in-loop` (prefer `strings.Builder`); **GORM** — `gorm-find-without-where` (unbounded full-table `.Find()`), `gorm-n-plus-one` (DB call inside a loop), plus a `go-test-functions` naming-convention detector. `gorm-unbounded-preload` ships disabled (`rules-disabled/`). Each rule has a positive/negative fixture pair. (Landed alongside a `ruby-detect-path-traversal` security rule in the same batch.)
46
+ - **`module_report` cross-file blast-radius (#304)** — `module_report` gained an opt-in `blastRadius` section: transitive dependents of the file, aggregated per-file and ranked, surfaced as read-only `read` args over the cached review graph (cold-omitted). This replaces the standalone `pilens_impact` tool (removed — see below). Plus cold-cache import resolution made language-uniform with member nesting (#301) and C/C++ `#include` support (#302) so the outline is populated even on a cold start.
47
+ - **Contributor guide + issue/PR templates** — added `CONTRIBUTING.md` with step-by-step wiring checklists for new dispatch runners, language servers (primary and auxiliary), formatters, ast-grep rules, and tree-sitter rules; added GitHub issue templates for bug reports, feature proposals, and enhancements; added a pull request template. Also added `docs/audit1.md` documenting the centralization gaps and stale docs found during the write-up.
48
+ - **License, Code of Conduct, security policy, and all-contributors** — added an MIT `LICENSE` file, `CODE_OF_CONDUCT.md` adapted from the Contributor Covenant 2.1, `SECURITY.md` for private vulnerability reporting, and an `.all-contributorsrc` plus generated contributor table in `README.md` covering code contributors and resolved-issue reporters.
49
+ - **Issue/PR automation** — added `stale.yml` workflow to mark and close stale issues/PRs, `greetings.yml` to welcome first-time contributors, `.github/labels.yml` plus a label-sync workflow, and `.github/release.yml` to categorize generated GitHub release notes.
50
+ - **GitHub Actions hardening** — pinned workflow actions to full commit SHAs, disabled persisted checkout credentials where push credentials are unnecessary, replaced the release action with `gh release create`, and removed `pull_request_target` from the greetings workflow.
51
+ - **README split into a landing page + docs** — trimmed README to install, docs links, contributing/security/license, and contributors; moved detailed sections into `docs/features.md`, `docs/tools.md`, `docs/globalconfig.md`, `docs/env_variables.md`, `docs/language-coverage.md`, `docs/dependencies.md`, and `docs/usage.md`. Fixed the generated contributor table markup so GitHub renders rows instead of showing raw `<tr>` fragments.
52
+
53
+ ### Changed
54
+
55
+ - **Tool schemas aligned with the pi SDK house style** — compared pi-lens's registered tools against pi's built-ins (`read`/`write`/`edit`/`grep`/`find`/`ls`) and closed two consistency gaps. (1) **`promptSnippet` phrasing**: ours restated the tool name ("Use module_report to…"), which the SDK renders as `- module_report: Use module_report to…` (the name doubled); rewrote the six non-`lens_diagnostics` snippets to bare imperatives matching the built-ins (e.g. "Navigable file outline — a cheap substitute for reading a whole file"). (2) **Input param `filePath` → `path`** (and `filePaths` → `paths`): every pi built-in file tool uses `path`, so `module_report`, `read_symbol`, `lsp_navigation`, and `lsp_diagnostics` now take `path`/`paths` — schema keys, impl, and the user-facing error/hint strings, leaving result-object `filePath` output fields and internal LSP-service args untouched. **Note for hardcoded callers**: agents read the tool schema each session and adapt automatically, but any script/hook that invokes these tools with `filePath:` must switch to `path:`.
56
+
57
+ - **Session-start guidance now surfaces `module_report` + `read_symbol`, and is leaner** — the session-start orientation advertised `lens_diagnostics`/`lsp_*`/`ast_grep` but never the #245 read-substitute tools, so agents rarely reached for them. Replaced the ~300-token block (which re-documented each tool's args — already in their registered descriptions) with a ~130-token nudge that names the high-value tools, adds `module_report` + `read_symbol`, and keeps only the one non-obvious behaviour (`lens_diagnostics mode=all` resurfaces stale blocking errors dropped from turn context).
58
+
59
+ ### Removed
60
+
61
+ - **Standalone `pilens_impact` tool — folded into `module_report` (#304)** — the separate transitive-impact MCP tool was removed; the same blast-radius analysis is now an opt-in `blastRadius` section on `module_report` (see Added), so there's one navigable read-substitute surface instead of two. The now-unused `symbolImpact` lens-engine seam was removed as a follow-up (#324).
62
+ - **Built-in regex secrets scanner (`clients/secrets-scanner.ts`)** — the hand-rolled, always-on content scanner that regex-matched a handful of secret shapes (Stripe/OpenAI `sk-*`, GitHub tokens, AWS `AKIA*`, Slack `xox*`, private keys, generic api-key/password) on the edit/write path and blocked the pipeline. It's now redundant: the bundled CodeRabbit ast-grep ruleset ships dozens of language-specific `*-hardcoded-secret-*` rules and gitleaks covers repo-level entropy/history scanning, so three overlapping paths produced duplicate, noisy blocks. Removed the scanner, its dedicated pipeline stage + import, and its tests; the `"secrets"` defect class and taxonomy hints remain (now served by the ast-grep rules and gitleaks). Trivy is slated as the consolidated secret/vuln/IaC scanner in a later slice.
63
+
64
+ ### Fixed
65
+
66
+ - **Full-suite "Worker exited unexpectedly" flake (#283)** — the LSP teardown's Windows tree-kill (`taskkill /F /T /PID`) force-killed a PID's whole process tree, but once a child LSP process had exited its PID can be OS-recycled, so the tree-kill could land on an unrelated process — under `vitest` that was a sibling worker fork (bare worker-exit, no Node crash dump), and in production it was a latent hazard against any recycled PID. Both kill paths (`killWindowsTree` in `launch.ts`, `killProcessTree` in `client.ts`) now early-return when the tracked process has already exited (`exitCode`/`signalCode` set) unless the session itself is tearing down. Also gave the spawn-heavy `lifecycle.test.ts` cases an explicit 20s timeout. (Vitest 4 config note: `execArgv` moved to a direct `test` field — the v3 `poolOptions.forks.execArgv` nesting is silently ignored.)
67
+ - **Read-guard no longer false-blocks edits the host would apply** (#257) — the guard gates the host's edit tool but resolved `oldText` → line range with a *weaker* normalizer than the host applies it with, so an edit whose `oldText` carried a smart quote, em-dash, NBSP, BOM, lone `\r`, or any NFKC-equivalent form matched on the host side but not in the guard, surfacing as a spurious `RETRYABLE — edit target not found` for a valid edit. Vendored the host's fuzzy-match normalization ladder (`normalizeForFuzzyMatch` + `normalizeToLF`/`stripBom`, from `@earendil-works/pi-coding-agent` `core/tools/edit-diff`) into a new `clients/host-edit-normalize.ts` and routed all three guard match-space normalizers through it, so the gate and the host now agree by construction. The partial-apply self-write path additionally adopts the host's first-occurrence-wins `detectLineEnding`/`restoreLineEndings` (was "any CRLF present"). A host-pin sync test re-reads the SDK source from devDeps and fails if the host's normalization set drifts. The SDK stays a type-only dependency — the ~50 lines are deliberately vendored, not imported.
68
+ - **Edit shapes pinned to the host's `EditToolInput` type** (#257 follow-on) — the read-guard's edit-input parser (`getTouchedLinesForGuard`) and the partial-apply edit element (`PartiallyApplicableEdit`, previously declared twice) now derive their `oldText`/`newText` fields from the SDK's exported `EditToolInput` instead of re-declaring them as bare `string`. A host edit-schema rename is now a compile error at the lint gate rather than a silent fall-through to `unknown_edit_schema`. Type-only (`import type`, fully erased) — no runtime SDK coupling.
69
+ - **Cached project diagnostics no longer replay stale findings** (#298) — `lens_diagnostics mode=full refreshRunners=cached` reads a persisted, cross-session snapshot (`project-diagnostics.json`), but `loadProjectDiagnosticsSnapshot` validated only the cache *version* — it never checked whether the underlying files had changed. So a diagnostic recorded for a file the agent later fixed (or deleted) was replayed verbatim on the next `mode=full` call, which is the "the cache needs to be cleaned before running diagnostics because it became stale" symptom in the report (reproduced: a snapshot entry survives an edit that bumps the file's mtime past `scannedAt`, and survives outright deletion). Added `reconcileProjectDiagnosticsSnapshot` — the snapshot analogue of `reconcileStaleWidgetFiles` for the in-memory widget — which drops any diagnostic whose file's `mtimeMs > scannedAt` (+1ms tolerance) or no longer exists, applied at the cached-full-mode consumer so `loadProjectDiagnosticsSnapshot` stays a pure reader. Fail-safe on an unparseable `scannedAt` (keeps everything rather than risk dropping live findings). Guards: 4 reconcile unit tests (edited-after-scan, deleted, unchanged no-op, unparseable-timestamp). Note: the `ignore`/`rules` parts of #298 were already addressed by #279 (mode=full/all cache-ignore filter) and #297 (cascade); this closes the remaining staleness leg.
70
+ - **`lsp_diagnostics` directory scans reuse the canonical exclusions and honor project `ignore`** (PR #299, originally by @StartupBros) — the tool's directory walk (`collectFiles` in `tools/lsp-diagnostics.ts`) filtered subdirectories through its own small local `SKIP_DIRS` set (10 build/dep names), so it both diverged from the shared `isExcludedDirName` list (missing agent/runtime + vendored dirs like `.claude`, `.codex`, `.pi`, `.agents`, `.worktrees`, `.pi-lens`, `vendor`, `third_party`) and ignored the project's `.pi-lens.json`/`.gitignore` patterns entirely — the same private-skip-list divergence #243 fixed for the workspace-diagnostics walk. Swapped `SKIP_DIRS` for `isExcludedDirName` (a strict superset, case-insensitive, glob-aware) and additionally threaded a fail-open `getProjectIgnoreMatcher` predicate through the walk so a directory scan now also suppresses user-ignored paths — bringing this surface in line with the workspace walk and `lens_diagnostics` (#243/#297/#298). Explicitly targeting an excluded/ignored path still scans it (exclusion is checked on recursion children, not the root). Guards: the contributor's canonical-exclusion tests on both surfaces, plus a `.pi-lens.json` ignore-honored directory-scan test and `.git`-anchored, global-config-isolated fixtures for determinism.
71
+ - **Cascade no longer surfaces diagnostics from ignored files** (#297) — when an edit's blast radius reached a file the project ignores (e.g. a `*.test.ts` glob in `.pi-lens.json`), the cascade neighbour analysis still surfaced that file's LSP errors at turn-end. This produced false positives in exactly the case the reporter hit: editing `reader.ts` to add an export made its `reader.test.ts` importer a cascade neighbour, and the TypeScript server's *partial* view (which hadn't re-indexed the new export the way a full `tsc` does) flagged the import as unresolved — a phantom blocker on a file the user had deliberately excluded. Cascade was the last diagnostic surface that filtered neighbours only by vendor/`node_modules` (`isExternalOrVendorFile`) and not by the project ignore config; both neighbour-collection sites in `computeCascadeForFile` (the primary `sortedNeighbors` walk and the passive `appendFallbackNeighbors` fallback) now also route through the shared `getProjectIgnoreMatcher`, the same matcher the project walk, LSP workspace scan, and `lens_diagnostics` (#279) already use. Fail-open: an ignore-config probe error never drops a neighbour. Guards: 2 cascade-compute regression tests (snapshot + fallback paths). Note: this also closes the remaining ignore-leak called out in #298 — its `mode=full`/`all` cache-leak was already fixed in #279 (which landed after #298 was filed); the cascade path was the one surface #279 didn't cover.
72
+
73
+ ## [3.8.60] - 2026-06-21
74
+
75
+ ### Added
76
+
77
+ - **ast-grep catalog port + upstream playground cross-validator** — 11 detector-only rules from the [official ast-grep catalog](https://ast-grep.github.io/catalog) were ported into `rules/ast-grep-rules/rules/` (filling real gaps: Go `unmarshal-tag-is-dash` CWE-639, Rust `redundant-unsafe-function` / `avoid-duplicate-export` / `rust-2024-let-chain-candidate`, TS `no-console-except-error` / `missing-component-decorator` / `unnecessary-react-hook` / `find-import-file-without-extension` / `redundant-usestate-type`, plus a Cpp format-string detector that's vendored from CodeRabbit to avoid a duplicate). The 4 rules with a mechanical `fix:` re-export the upstream rewrite (the LSP surfaces it as a codeAction; the napi runner surfaces it as a text `fixSuggestion`); the other 7 are detection-only (manual refactor hints in the `note:`). Validated end-to-end by `tests/clients/dispatch/runners/ast-grep-catalog-rules.test.ts` — each rule gets a positive/negative fixture pair run through the real `ast-grep scan -r` CLI, and the 4 fix-carrying rules additionally get the `ast-grep scan --json=compact` `replacement` field checked end-to-end so a typo in the `fix:` string can't slip through. New `scripts/playground-verify-rule.mjs` cross-validates any rule against the **upstream web playground** (a headless-CDP tool that loads the rule into <https://ast-grep.github.io/playground.html>, scrapes the `Found N match(es)` / `No match found` text, and reports the match count the upstream engine produces — useful as a second opinion against the local CLI test to catch pattern-level drift between the version of `ast-grep` pinned in `package.json` and the version the upstream binary ships; the playground uses a fixed source, so this is a pattern-level smoke test, not a source-level one; see `docs/astplayground.md`). The verifier bundles its own minimal CDP driver + Chrome lifecycle (port 9224, isolated profile at `<tmpdir>/pilens-playground-profile/`, hard-exit after each command to avoid the Windows close-handshake hang) — adapted from [GreedySearch-pi's `bin/cdp.mjs`](https://github.com/apmantza/GreedySearch-pi) and `bin/launch.mjs` with the port/profile changed. Auto-installs Chrome (PATH auto-detect; `PILENS_PLAYGROUND_CHROME` for non-standard installs). First-run ~11s (cold start + page paint), reuse mode ~1.5s. Run `npm run audit:playground -- <rule.yml>` or `node scripts/playground-verify-rule.mjs <rule.yml> --keep-chrome --expected N` for assertions. Test suite auto-skips when Chrome is unavailable.
78
+
79
+ ### Fixed
80
+
81
+ - **Stale schema/docs said the napi runner didn't support `inside` / `stopBy` / `field` / `constraints`** — the runner has used napi's native engine (#206) since it landed, which supports the full ast-grep rule grammar; the schema and `docs/custom-rules.md` claimed otherwise, which would have scared catalog-port authors off the very features their rules need. Updated the schema descriptions and the docs table to reflect what the engine actually accepts. Same latent bug surfaced in the runner itself: `isOverlyBroadPattern(pattern)` called `.trim()` on the rich-pattern form `{context, selector, ...}` — now guards on `typeof !== "string"` (rich patterns are never single-metavar traps). `isStructuredRule` also recognises the rich form as structure so a rule whose only top-level structure is `{context, selector}` isn't dropped by the runner's safety net. `YamlRuleCondition.pattern` is now typed as `string | YamlRichPattern` (new exported `YamlRichPattern` type). Guards: 2 new unit tests in `tests/clients/dispatch/runners/yaml-rule-parser.test.ts`.
82
+
83
+ - **Java LSP Lombok support (refs #244)** — JDT LS launches with `JDTLS_JVM_ARGS=-javaagent:<lombok.jar>` when a Java project declares Lombok (`lombok.config`, Maven, or Gradle) and pi-lens can resolve a jar. Resolution order: explicit `PI_LENS_LOMBOK_JAR` / `LOMBOK_JAR`, project-local `lombok.jar` / `.lombok/lombok.jar` / `lib(s)/lombok.jar`, then Maven/Gradle caches. Existing `JDTLS_JVM_ARGS` are preserved, an existing Lombok javaagent is not duplicated, and `PI_LENS_JAVA_LOMBOK=0` disables the integration. Added unit coverage plus a live LSP smoke fixture (`node scripts/smoke-tools.mjs --lsp java-lombok`) that downloads Lombok into the temp workspace and verifies JDT LS no longer reports Lombok-generated getters as unresolved when `jdtls` is available.
84
+
85
+ - **Project-level `.pi-lens.json` config now honored (`ignore` + `rules`)** — pi-lens already walked up to find a `.pi-lens.json` for LSP server config (`lsp.json` schema), but the `ignore` and `rules` fields on that same file were parsed and discarded. Originally contributed by @greg-hass in #246; this change wires them in: a new `clients/project-lens-config.ts` loader (discovery+parse cached, JSON-parse-fault-tolerant with one-shot warnings, reusing the shared `walkUpDirs` walk-up helper like other project-root probes) is plumbed into two places. (1) **Scanner exclusion** — `getProjectIgnoreMatcher` now takes the loaded `ignore` patterns as `extraPatterns` to the existing `createProjectIgnoreMatcher` extension point, so any matching path is skipped by every diagnostic scan (LSP walk, fact-rules, tree-sitter, jscpd, knip, review graph, source-filter). The cache is invalidated by the actual inherited `.pi-lens.json`/`pi-lens.json` path + mtime as well as `.gitignore` mtime, so editing the file takes effect on the next scan without a session restart. (2) **Rule threshold overrides** — `high-complexity` (cyclomatic complexity) and `high-fan-out` (distinct function calls) had hardcoded `const` thresholds (`15` / `20`); converted to `let` with positive-finite guarded `setHighComplexityThresholds(cc, depth)` / `setHighFanOutThreshold(n)` setters, plus `reset…` helpers for tests. Dispatch contexts now carry the loaded project config, and the two fact rules read thresholds from that per-dispatch context instead of mutating process-global rule state; `applyProjectLensConfig(cwd)` remains as a thin loader integration seam, and `resetDispatchBaselines` can invoke it to warm the cache. The runtime wiring: `runtime-session.ts`'s `handleSessionStart` and the MCP adapter `mcp/session.ts`'s `runSessionStart` both pass `cwd` through, so the config is applied on every session start. The depth sub-threshold of `high-complexity` is intentionally not exposed (keeps the schema tight). Unknown top-level keys and unknown rule ids are ignored for forward-compat; a malformed JSON file is logged once and treated as "no config" so a syntax error in your own file never blocks diagnostics. End-to-end: write `.pi-lens.json` with `ignore: ["fixtures/**"]` and a `fixtures/noise.ts`, then `collectSourceFiles` (and every consumer) skips it; set `rules["high-complexity"].threshold: 5` and a function with `cc=7` that the default `15` would have ignored now triggers a warning. Guards: 5 new test files (loader unit, ignore integration via sync+async `collectSourceFiles`, threshold-setter units, and context-scoped config integration through `createDispatchContext`) plus regression coverage for inherited-config mtime invalidation, gitignore negation, invalid thresholds, config removal, and cross-project bleed; the existing source-filter / file-utils / dispatch-rules suites remain green; full suite 1999/2001 (the 2 pre-existing timing-sensitive failures in `runner-timeout.test.ts` are unrelated to this change). Documented in README under **Project Config** alongside **Global Config**.
86
+
87
+ ### Changed
88
+
89
+ - **Replaced Semgrep with Opengrep, integrated as an auxiliary diagnostic LSP + introduced the auxiliary-LSP capability (closes #111)** — [Opengrep](https://github.com/opengrep/opengrep) is an open, login-free fork of Semgrep (same rule format, semgrep-compatible CLI) that ships as a **single standalone binary** with **no account, token, or telemetry**, so pi-lens **auto-installs it on demand** via the `github` strategy (Semgrep was never auto-installable). Rather than a per-file CLI runner (~8s/file: the rule set recompiles on every invocation), Opengrep now runs as a **warm LSP server** (`opengrep lsp`) that compiles its rules **once per session** → **~1–2s per file warm** (measured: 1.4–1.7s on edits to a large file).
90
+
91
+ This is delivered via a new, reusable **auxiliary-diagnostic-LSP capability**: a `role:"auxiliary"` tag on `LSPServerInfo` marks cross-cutting, diagnostic-only servers that attach *alongside* the file's primary language server (never selected as primary) and are collected on a new `with-auxiliary` `touchFile` scope; the aggregation layer merges/dedups their diagnostics. A profile registry (`clients/dispatch/auxiliary-lsp.ts`) maps each one's LSP `source` → pi-lens `tool` + semantic policy + enablement gate (Opengrep's `source:"Semgrep"` → `tool:"opengrep"`). **Blocking policy:** the LSP diagnostic carries severity + rule id but **not confidence** (the CLI's `metadata.confidence` is stripped), and Opengrep's `auto` Community set is uniformly ERROR/LOW-confidence audit-tier — so a naive "ERROR → blocking" would block ~15 findings on a single normal file. Instead a profile declares `allowBlocking(cwd)`: Opengrep blocks ERROR findings **only when the repo supplies its own curated rules** (`.opengrep.yml`/`.semgrep.yml` — the author's deliberate severity); the `auto` set is **advisory** (warning) regardless. Either way all findings surface in `lens_diagnostics` (via widget-state `recordDiagnostics`). Future cross-cutting scanners (spelling, secrets, …) plug in by registration. Per-server `reopenOnResync` was added because **Opengrep re-scans only on a fresh `didOpen`** (it ignores `didChange`) — auxiliaries with this flag are re-synced via `didClose`+`didOpen` so edits actually trigger a re-scan (without it, warm edits silently returned zero).
92
+
93
+ **Default-on** (a registered LSP server) when the binary is available; disable with `--no-opengrep`. Rules: a repo `.opengrep.yml`/`.semgrep.yml` if present, else the login-free `auto` Community ruleset. **Removed** the interim CLI `opengrep` dispatch runner, `withOpengrepGroup`, the `lens-opengrep`/`lens-opengrep-config` flags, and the persisted `.pi-lens/opengrep.json` — superseded by the LSP integration. **Validated end-to-end on the dev box** (cold scan delivers findings; warm edits return correct, content-scaled findings at ~1.4–1.7s) with **no regression across 227 LSP + dispatch tests** on the shared notify/collection hot path. Guards: `auxiliary-lsp.test.ts` (enablement kill-switch + source routing + semantic policy), the auto-deriving `lsp-registry-consistency` guard, and a **generic auxiliary layer in the tool-smoke harness** (`scripts/smoke-tools.mjs --lsp`): a fixture declaring `auxiliaryServerIds` drives the real `with-auxiliary` `touchFile` and asserts the cross-cutting server produced a finding (matched by LSP `source`) — verified end-to-end (opengrep auto-installs, spawns, scans `eval(userInput)`, and its `Semgrep`-sourced diagnostic returns alongside the TypeScript primary). New cross-cutting adopters get harness coverage by adding one fixture entry. *(typos-lsp is the validating second adopter; ast-grep's full-engine LSP a noted strategic migration. FindSecBugs/PMD remain unrelated JVM follow-ups.)*
94
+
95
+ - **Removed the dormant ESLint language-server definition (37 LSP servers now)** — `ESLintServer` was registered for `.js/.jsx/.svelte/.vue`, but `getClientForFile` is first-match and the TypeScript server claims all of `jsts` ahead of it, so the ESLint LSP only ever activated for `.svelte/.vue` and **never `.js/.jsx`** — the case its own config targeted. ESLint coverage is and remains the config-gated **`eslint` CLI runner**, which works across ESLint v8/v9/**v10**. A latency probe confirmed the warm-LSP path isn't worth reviving today: cold `eslint` v10 is **~400 ms** (not the 1–3 s of the old eslintrc era), and while a warm `vscode-eslint-language-server` validates in **~3–4 ms/edit** on ESLint v9, the current 4.10 server is **incompatible with ESLint v10** — it still calls the removed `FlatESLint` API and silently returns **zero diagnostics**. Removing the dead server (plus its `EslintRoot` helper, the now-orphaned `vscode-langservers-extracted` installer entry, and the `ESLintServer.root` tests) eliminates a misleading, version-fragile half-wiring; the json/css/html members of the same npm package are unaffected (separate tool ids). ESLint-as-auxiliary can be revisited once the language server supports ESLint v10.
96
+
97
+ ### Added
98
+
99
+ - **ast-grep LSP as a cross-cutting auxiliary diagnostic server (sgconfig-gated) — Phase 1 of #239** — pi-lens now honors a project's OWN `ast-grep` rules: when a repo has an `sgconfig.y[a]ml`, the `ast-grep lsp` server attaches as a `role:"auxiliary"` scanner alongside the file's primary language server (the Opengrep auxiliary-LSP template), surfacing the team's curated structural rules warm, full-engine, with codeAction fixes. Doubly gated so it never over-reaches: (1) the root detector keys on `sgconfig.y[a]ml`, so **no sgconfig ⇒ it never attaches and the existing napi ast-grep runner stays the path** (this is purely additive — the runner is untouched); (2) it only attaches to files whose extension is in ast-grep's supported-language set (`AST_GREP_EXTENSIONS`, ~15 languages). Blocking-eligible by construction (an sgconfig is the team's deliberately-authored ruleset — mirrors Opengrep's curated-config gate); the auxiliary-lsp profile routes `source:"ast-grep"` → `tool:"ast-grep"` with severity→semantic policy. Validated end-to-end via a new `scripts/smoke-tools.mjs --lsp` fixture (sgconfig + a rule + a violating file → install → spawn → compile rules → scan → `ast-grep`-sourced diagnostic alongside the primary). Latency (Gate A, #239): cold ~3.5s (spawn + rule compile), warm **~0.9s/edit and file-size-independent** (a 1 KiB and a 105 KiB file both ~0.9s — the cost is fixed re-sync overhead, not scan), in the same range as the shipped Opengrep auxiliary. *(Phase 2 — consolidating the no-sgconfig baseline onto the LSP via `--config` + shipped rules and retiring the napi runner — remains gated on that warm-latency floor vs napi's in-process ~40ms; tracked in #239.)*
100
+
101
+ - **LSP server command support — capability/command caching + hardened `workspace/executeCommand`** — pi-lens now captures each server's advertised commands and can run them, closing the "we don't know or use server commands" gap. **Discovery:** at `initialize` we already cached the operation-provider flags but discarded the rest of `ServerCapabilities`; now `detectExecuteCommands` also retains `executeCommandProvider.commands` into a per-client allowlist (`state.advertisedCommands`), and `client/registerCapability` merges any dynamically-registered `registerOptions.commands` (the dynamic path previously kept only `id→method`). Surfaced via `getAdvertisedCommands()` on the client, the `LSPCapabilitySnapshot`, and the `capabilities` nav op (which now lists the advertised commands). **Execution** (`executeCommand` op on `pilens_lsp_navigation` / `lsp_navigation`) is deliberately hardened: (1) **allowlist-by-advertisement** — a command is refused without being sent unless the server itself advertised it (enforced in the client, the authoritative chokepoint, *and* pre-checked in the tool — defense in depth); (2) **dry-run by default** — the op only reports whether a command is advertised; mutation requires explicit `apply:true`; (3) **gated server-initiated edits** — a new `workspace/applyEdit` handler honors server-pushed edits *only* while an opted-in `executeCommand` is in flight (`serverEditsAllowed` counter), so a server cannot push edits to disk unsolicited, and those edits route through the same `applyWorkspaceEdit` path as every other edit. Guards: real-wire integration tests (extended fake LSP server advertises commands, runs one, refuses an unadvertised one, and applies a solicited `workspace/applyEdit` to a temp file end-to-end) + tool-level tests (dry-run default, apply executes, unadvertised refused) + capability-snapshot coverage. *(Origin: the "are we OK on capabilities/commands?" audit — capability negotiation was already solid; command discovery/execution was the real gap.)*
102
+
103
+ - **`typeDefinition` + `declaration` LSP navigation operations** — `pilens_lsp_navigation` / the `lsp_navigation` tool gained two position operations that round out the LSP "go-to" family: `typeDefinition` (jump to the definition of a symbol's **type** — e.g. the class/interface behind a variable, which `definition` alone never gives you) and `declaration` (jump to a symbol's declaration, distinct from its definition for languages with a decl/def split, e.g. C/C++ externs or ambient TS declarations). Both reuse the existing `navRequest` location pattern (mirroring `implementation`): wired through `client.ts` (method + `LSPOperationSupport.{typeDefinition,declaration}` + static `typeDefinitionProvider`/`declarationProvider` capability detection + dynamic-registration map), `index.ts` service delegation, and the tool's operation list, position handling, empty-result retry, capability table, and per-location `searchReads` registration (so their results feed the read-guard like `definition`/`references` do). Guards: two new `lsp-navigation` tests (typeDefinition resolves + attaches location searchReads; empty declaration reports the no-results reason) plus the existing capability-snapshot tests updated for the two new keys. *(Adopted from the LSP 3.18 feature-gap audit; the heavier `workspace/diagnostic` bulk-pull gap is tracked separately.)*
104
+
105
+ - **Alternate-primary LSP reachability — static guard + live harness coverage (refs #111)** — the ESLint removal exposed a blind spot: nothing verified that a registered non-auxiliary server is actually *selectable* as primary. `getClientForFile` is first-match by availability, so a server can be permanently shadowed (ESLint), and the live `--lsp` harness only ever exercised the *selected* server — so a shadowed/alternate server was never tested either. Two layers now close this: (1) **`lsp-primary-reachability.test.ts`** (per-PR, deterministic) asserts every non-auxiliary server is either the default first-match winner for ≥1 extension it claims **or** a declared alternate (`deno`↔typescript, `python-jedi`↔pyright, `omnisharp`↔csharp — the registry's actual zero-default-win set), and that each alternate is wired behind its default and becomes the next pick when predecessors drop out; a server that is neither fails with guidance to mark it `role:"auxiliary"` or declare it (the exact ESLint-class catch). (2) A **live alternate layer in the tool-smoke harness** (`scripts/smoke-tools.mjs --lsp`) drives the real selection fallthrough: it writes a `.pi-lens/lsp.json` disabling the default into the temp workspace (the genuine user-facing mechanism) so `getClientForFile` falls through to the alternate, then asserts the alternate spawns + handshakes + diagnoses by fingerprinting the diagnostic `source`. **Validated end-to-end on the dev box** for **deno** (`deno-ts` type error) and **python-jedi** (`compile` syntax error). Alternates are PATH-only (no installer entry — see Fixed), so the layer prechecks the binary and skips cleanly when absent. *(omnisharp left for nightly — heavier toolchain.)*
106
+
107
+ - **SpotBugs bytecode bug-pattern analyzer for Java + Kotlin (closes #133)** — Java's pipeline was `javac`-only (compile errors, no static analysis); SpotBugs (Apache-2.0) adds 400+ bytecode-level bug patterns (null derefs, resource leaks, thread-safety, performance, bad-practice), and since it analyzes JVM **bytecode**, Kotlin projects get it for free. **Opt-in** behind the `lens-spotbugs` flag (it's heavyweight — JVM cold start + whole-tree analysis), wired via a `withSpotbugsGroup` dispatch group that only activates when the flag is set **and** a Java build descriptor (`pom.xml`/`build.gradle{.kts}`/`settings.gradle{.kts}`) **and** a compiled-classes dir (`target/classes`, `build/classes`, `out/production`, `bin/main`) are present. The runner operates on the compiled tree (not the edited source) and **mtime-caches** — it only re-invokes SpotBugs after a rebuild changes the `.class` files, returning cached findings otherwise. `<BugInstance>` XML (`-xml:withMessages`) is parsed by a bounded, zero-dep, ReDoS-safe reader: priority→severity (1=error/2=warning/3=info), category→defect-class (`CORRECTNESS`/`MT_CORRECTNESS`→correctness, `SECURITY`→safety, `PERFORMANCE`/`BAD_PRACTICE`/`STYLE`/`I18N`/`EXPERIMENTAL`→style), `type`→rule, the primary `<SourceLine>`→location, and the `<LongMessage>` first sentence→`fixSuggestion`; bugs stay advisory (`semantic: warning`). Auto-installs via the archive strategy. **Validated end-to-end on the dev box**: a `NP_ALWAYS_NULL` null-deref in a compiled Maven fixture surfaced as `error`/`correctness` at the right line, through the real dispatch path (coexisting with javac). Guards: `spotbugs-parser.test.ts` (severity×category mapping + primary-line selection + drop-no-source), `spotbugs-runner.test.ts` (scan/cache/rebuild-reinvoke/skip-when-unbuilt), and detection-helper + dispatch-coverage/smoke-coverage exemptions. *(FindSecBugs security plugin + PMD are noted follow-ups.)*
108
+
109
+ - **Archive-extraction install strategy (refs #133)** — the installer gained an `archive` strategy alongside npm/pip/gem/github/maven, for JVM tools that ship as a **distribution archive** (a `lib/` of many JARs + `bin/` launchers) rather than a single runnable binary or fat JAR. It downloads the `.tgz`/`.zip`, extracts it (top-level dir stripped via `--strip-components=1`) into `~/.pi-lens/tools/<id>/`, and writes a thin launcher shim into the managed bin so the tool resolves like any other via `findGitHubToolPath`. Extraction shells out to `tar` (present on Windows 10+ as bsdtar, which also reads `.zip`); the spawn uses `cwd` + **relative** paths so no argument carries a drive-letter colon — GNU tar (MSYS) otherwise misreads `C:\…` as an rsync `host:path` (avoids the GNU-only `--force-local`, which bsdtar rejects). First consumer registered: **SpotBugs** (`spotbugs-4.10.2.tgz`) — verified end-to-end on the dev box (`ensureTool("spotbugs")` → shim → `spotbugs -version` → `4.10.2`). This is the prerequisite the SpotBugs runner (#133) needs; #133's premise that SpotBugs uses #129's maven fat-JAR path was incorrect — SpotBugs has no runnable standalone JAR on Maven Central, only the distribution archive. Guard: an `archive`-strategy install-contract case in `tool-registry-consistency.test.ts`.
110
+
111
+ ### Fixed
112
+
113
+ - **Installer security hardening — tighter tool perms + PATH-safe extraction (SonarCloud S2612 + S4036, new code on `master`)** — the installer's executable-perm sites set `0o755` (read/execute for *others*), but managed tools live in user-scoped `~/.pi-lens/` and are only ever run by the installing user. Aligned all six `0o755` binary/launcher/shim modes to **`0o750`** (no "other" access — matching the installer's existing `0o750` chmod sites), clearing the S2612 vulnerability. Also resolved the archive-extraction `tar` spawn to an absolute path on Windows (`%SystemRoot%\System32\tar.exe`, the bundled bsdtar) so it can't be hijacked via a writable `PATH` entry — the same hardening already applied to the `taskkill` spawn; POSIX keeps bare `tar` (a trusted coreutil whose path varies by distro).
114
+
115
+ - **Windows libuv abort on `pi update` (`Assertion !(handle->flags & UV_HANDLE_CLOSING)`, `src\win\async.c`) (closes #234)** — `pi update` tears the session down (→ `session_shutdown`) to reload the updated extension, and pi-lens's shutdown killed every LSP server by **spawning `taskkill /F /T`** child processes. Spawning a child while the event loop is already closing makes libuv call `uv_async_send` on the closing loop-wakeup handle → hard abort (a native crash, uncatchable in JS). Fixed by adding a `processExiting` shutdown flag (set only on `session_shutdown`): in that state `killProcessTree` kills via the process handle it already holds (`TerminateProcess`, synchronous, no new async handle) instead of spawning. Mid-session teardowns (subagent/turn boundaries, idle shutdown) where the host keeps running still use the `taskkill /T` tree-kill to avoid zombie accumulation. Guard: `kill-process-tree.test.ts` (mocks `child_process`, forces win32 — asserts no spawn when `processExiting`, tree-kill spawn otherwise). *(Also noticed `stopLSP` in `launch.ts` — which carried a second teardown `taskkill` spawn — is dead code with no callers; left untouched.)*
116
+
117
+ - **Alternate LSP servers `deno` + `python-jedi` now auto-install (refs #111)** — previously both resolved straight off PATH (no installer entry, no `managedToolId`), so unlike `typescript`/`pyright` they never auto-installed and pi-lens couldn't offer them when absent. Added installer entries — **deno** via the `github` strategy (per-platform `.zip` containing the `deno` binary, extracted like rust-analyzer's; added to `GITHUB_TOOLS`) and **jedi-language-server** via `pip` — and rewired `DenoServer`/`PythonJediServer` `spawn` to `resolveAndLaunch({ candidates, managedToolId }, allowInstall)` (the opengrep pattern: try PATH, else install on demand). **Validated end-to-end on the dev box**: with `deno` absent from PATH, `ensureTool("deno")` downloaded it to the managed bin, then the server spawned, handshook, and returned a `deno-ts` diagnostic; jedi resolved + diagnosed (`compile`) via the pip strategy. Guards: github full-matrix + pip install-contract in `tool-registry-consistency.test.ts`; both ids in `managed-tool-ids.test.ts`. *(omnisharp — the C# alternate — still doesn't auto-install: it ships as per-platform archive **trees**, which the single-URL `archive` strategy can't express; needs a per-platform-URL archive extension, tracked separately.)*
118
+
119
+ - **Jedi LSP returned zero diagnostics on cold start (refs #111)** — surfaced immediately by the new alternate-primary harness layer. `jedi-language-server` is push-only and its first (complete) `publishDiagnostics` lands ~1011 ms after `didOpen` on cold start (Python/parso import), but the `python-jedi` diagnostic strategy capped the aggregate wait at **1000 ms** — so pi-lens stopped listening ~11 ms too early and surfaced nothing, despite the server working (verified via a raw JSON-RPC handshake). Bumped `python-jedi` `aggregateWaitMs` 1000 → **3000** for cold-start headroom (still seeds on the first push; warm path unaffected).
120
+
7
121
  ## [3.8.53] - 2026-06-16
8
122
 
9
123
  ### Added
10
124
 
11
- - **ktfmt wired as a config-gated Kotlin formatter + safe autofix (closes #129)** — projects that use [ktfmt](https://github.com/facebook/ktfmt) (Facebook's opinionated, gofmt-style Kotlin formatter) now get real formatting support. ktfmt is a *pure formatter* (no lint rules), so it's wired only where that fits: as a **formatter** (`getFormattersForFile` → `ktfmtFormatter`, in-place) and a **safe pipeline autofix** (`runAutofix` → `tryKtfmtFix`), **not** as a lint runner — a "not formatted" nag would be redundant with the autofix pass (unlike shfmt, which has no autofix). Both are **config-first**: ktfmt activates only when the project opts in (a `.ktfmt`/`.ktfmt.kts` marker or the ktfmt gradle plugin in `build.gradle{.kts}`, via `hasKtfmtConfig`). When opted in, ktfmt **replaces ktlint** for formatting (the lint policy drops ktlint from `preferredRunners` so its style suggestions don't conflict with ktfmt's output); detekt's *semantic* lint is unaffected. Installs via the new maven-JAR strategy. Validated end-to-end on the dev box through the harness `--format` and `--autofix` layers (ktfmt reformats + applies a fix). Guards: `formatters.test.ts` (ktfmt wins over the ktlint default when opted in), `tool-policy.test.ts` (lint suppresses ktlint / autofix selects ktfmt + `hasKtfmtConfig` detection), and the `autofix-policy-consistency` gate-match. _(Follow-up filed: re-evaluate ktlint's default lint runner now that ktlint is itself a safe autofix — the same redundancy question applies to pure-formatter-linters generally.)_
125
+ - **ktfmt wired as a config-gated Kotlin formatter + safe autofix (closes #129)** — projects that use [ktfmt](https://github.com/facebook/ktfmt) (Facebook's opinionated, gofmt-style Kotlin formatter) now get real formatting support. ktfmt is a *pure formatter* (no lint rules), so it's wired only where that fits: as a **formatter** (`getFormattersForFile` → `ktfmtFormatter`, in-place) and a **safe pipeline autofix** (`runAutofix` → `tryKtfmtFix`), **not** as a lint runner — a "not formatted" nag would be redundant with the autofix pass (unlike shfmt, which has no autofix). Both are **config-first**: ktfmt activates only when the project opts in (a `.ktfmt`/`.ktfmt.kts` marker or the ktfmt gradle plugin in `build.gradle{.kts}`, via `hasKtfmtConfig`). When opted in, ktfmt **replaces ktlint** for formatting (the lint policy drops ktlint from `preferredRunners` so its style suggestions don't conflict with ktfmt's output); detekt's *semantic* lint is unaffected. Installs via the new maven-JAR strategy. Validated end-to-end on the dev box through the harness `--format` and `--autofix` layers (ktfmt reformats + applies a fix). Guards: `formatters.test.ts` (ktfmt wins over the ktlint default when opted in), `tool-policy.test.ts` (lint suppresses ktlint / autofix selects ktfmt + `hasKtfmtConfig` detection), and the `autofix-policy-consistency` gate-match. *(Follow-up filed: re-evaluate ktlint's default lint runner now that ktlint is itself a safe autofix — the same redundancy question applies to pure-formatter-linters generally.)*
12
126
 
13
127
  - **Maven-JAR auto-install strategy (refs #129)** — the installer gained a `maven` strategy alongside npm/pip/gem/github: it downloads a runnable fat JAR from Maven Central into the managed bin and writes a `java -jar` launcher next to it, so the tool resolves like any managed binary (gated on a JRE). First consumer registered: **ktfmt** (`com.facebook:ktfmt:0.63:with-dependencies`) — verified end-to-end on the dev box (`ensureTool("ktfmt")` → launcher → `ktfmt --version`). Unblocks JVM-ecosystem tools that ship only as Maven JARs (ktfmt, google-java-format, SpotBugs). Guard: a `maven`-strategy install-contract case in `tool-registry-consistency.test.ts`.
14
128
 
@@ -545,11 +659,11 @@ All notable changes to pi-lens will be documented in this file.
545
659
  - **Severity alignment for 3 existing TS tree-sitter blocking rules** — `ts-command-injection`, `ts-ssrf`, `unsafe-regex` had `inline_tier: blocking` but `severity: warning`, producing `semantic: "warning"` which is never shown inline. Fixed to `severity: error` → `semantic: "blocking"` → actually surfaces to the agent.
546
660
  - **Fixed `inline_tier: error` typo** on `ts-hallucinated-react-import` and `python-hallucinated-import` (→ `blocking`).
547
661
  - **13 new high-confidence blocking promotions across 5 languages** (all `severity: error`, `inline_tier: blocking`):
548
- - _TypeScript:_ `ts-weak-hash` (`createHash("md5"/"sha1")` — confidence: high)
549
- - _Python:_ `python-command-injection`, `python-sql-injection`, `python-insecure-deserialization`, `python-weak-hash`
550
- - _Go:_ `go-command-injection`, `go-sql-injection`, `go-shared-map-write-goroutine`, `go-weak-hash`
551
- - _Ruby:_ `ruby-weak-hash`
552
- - _Rust:_ `rust-lock-held-across-await`
662
+ - *TypeScript:* `ts-weak-hash` (`createHash("md5"/"sha1")` — confidence: high)
663
+ - *Python:* `python-command-injection`, `python-sql-injection`, `python-insecure-deserialization`, `python-weak-hash`
664
+ - *Go:* `go-command-injection`, `go-sql-injection`, `go-shared-map-write-goroutine`, `go-weak-hash`
665
+ - *Ruby:* `ruby-weak-hash`
666
+ - *Rust:* `rust-lock-held-across-await`
553
667
  - **4 new blocking tree-sitter rules (SonarCloud BLOCKER equivalents)**:
554
668
  - `ts-xss-dom-sink` (S5696) — flags dynamic values assigned to `innerHTML`/`outerHTML` or passed to `document.write()` / `document.writeln()`
555
669
  - `ts-dynamic-require` (S5335) — flags `require()` called with a non-string-literal argument (arbitrary module loading)
@@ -763,7 +877,7 @@ All notable changes to pi-lens will be documented in this file.
763
877
  - **Test log pollution fix for read-guard** — `read-guard.test.ts` now mocks `read-guard-logger` unconditionally, so test events never reach `~/.pi-lens/read-guard.log` regardless of how the test suite is invoked.
764
878
  - **Tab/space indentation mismatch correction in the edit hook** — some models output spaces in `oldText` when the file uses tabs (or vice versa), causing edits to fail with a cryptic "not found" error. The `tool_call` hook now detects this before execution by trying tabs↔2-spaces and tabs↔4-spaces conversions against the actual file. On mismatch it blocks with a `🔄 RETRYABLE` message containing the corrected `oldText` verbatim, so the model retries successfully on the next attempt at zero cost when `oldText` already matches.
765
879
  - **Global project-data storage is now the default for new projects** — project-scoped pi-lens artifacts (turn state, worklog, metrics history, index, install choices, runner scratch data) now default to `~/.pi-lens/projects/<project-slug>/` instead of creating `<project>/.pi-lens/`. Existing projects that already have `<project>/.pi-lens/` continue to reuse it unless `PILENS_DATA_DIR` is explicitly set. This closes issue #40 while preserving backward compatibility.
766
- - **`PILENS_DATA_DIR` and `PI_LENS_STARTUP_MODE` documented in README** — both env vars are now listed under a dedicated _Environment Variables_ section between `## Run` and `## Key Commands`.
880
+ - **`PILENS_DATA_DIR` and `PI_LENS_STARTUP_MODE` documented in README** — both env vars are now listed under a dedicated *Environment Variables* section between `## Run` and `## Key Commands`.
767
881
  - **Tree-sitter read expansion for the read-before-edit guard** — partial reads (requested `limit ≤ 60` lines) are now automatically expanded to cover the full enclosing function, method, or class using the tree-sitter AST. The agent receives the full symbol as context, and the read guard records symbol-level coverage so edits anywhere within the symbol pass without requiring the agent to have read every line. Supports TypeScript, TSX, JavaScript, JSX, Python, Go, Rust, and Ruby. Runs within a 200 ms budget; falls back silently on parse failure or unsupported extension. Replaces the dead LSP-based expansion (which required `limit = 1` and a warm server — zero production hits).
768
882
  - **`read_pattern` structured log on every read** — `~/.pi-lens/read-guard.log` now records a `read_pattern` JSONL event for each read tool call: `offset`, `limit`, `totalLines`, `fractionRead`, `isPartial`, `fileKind`, and `expandedByTs`. Enables analysis of actual agent read behaviour across sessions.
769
883
  - **`prettier.config.ts` and `eslint.config.ts` added to config detection arrays** — both config filenames are now recognised by `hasPrettierConfig` and `hasEslintConfig` respectively. Previously only `.js`/`.cjs`/`.mjs` variants were listed, so TypeScript-based configs were silently ignored.
@@ -1952,6 +2066,7 @@ All runtime-applicable TypeScript ast-grep rules now have JavaScript equivalents
1952
2066
  ### Changed
1953
2067
 
1954
2068
  - **Updated `/lens-tdi` display** — Shows 5 category breakdown with descriptions:
2069
+
1955
2070
  ```
1956
2071
  Debt breakdown:
1957
2072
  Maintainability: 45% (MI-based)
@@ -1960,6 +2075,7 @@ All runtime-applicable TypeScript ast-grep rules now have JavaScript equivalents
1960
2075
  Max Cyclomatic: 10% (worst function)
1961
2076
  Entropy: 5% (code unpredictability)
1962
2077
  ```
2078
+
1963
2079
  - **Extended MetricSnapshot** — Added `maxCyclomatic` and `entropy` fields for historical tracking
1964
2080
 
1965
2081
  ---
@@ -2681,7 +2797,7 @@ Three new lint runners with full test coverage:
2681
2797
 
2682
2798
  ### Changed
2683
2799
 
2684
- - **Delta mode for real-time feedback**: ast-grep and Biome now only show _new_ violations introduced by the current edit — not all pre-existing ones. Fixed violations shown as `✓ Fixed: rule-name (-N)`. No change = silent.
2800
+ - **Delta mode for real-time feedback**: ast-grep and Biome now only show *new* violations introduced by the current edit — not all pre-existing ones. Fixed violations shown as `✓ Fixed: rule-name (-N)`. No change = silent.
2685
2801
  - **Removed redundant pre-write hints**: ast-grep and Biome pre-write counts removed (delta mode makes them obsolete). TypeScript pre-write warning kept (blocking errors).
2686
2802
  - **Test files excluded from AI slop warnings**: MI/complexity thresholds are inherently low in test files — warnings suppressed for `*.test.ts` / `*.spec.ts`.
2687
2803
  - **Test files excluded from TODO scanner**: Test fixture annotations (`FIXME`, `BUG`, etc.) no longer appear in TODO reports.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Apostolos Mantzaris and pi-lens contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.