pi-lens 3.8.52 → 3.8.61

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 (672) hide show
  1. package/CHANGELOG.md +151 -7
  2. package/LICENSE +21 -0
  3. package/README.md +137 -386
  4. package/dist/clients/bootstrap.js +3 -1
  5. package/dist/clients/dispatch/auxiliary-lsp.js +106 -0
  6. package/dist/clients/dispatch/dispatcher.js +27 -2
  7. package/dist/clients/dispatch/integration.js +96 -42
  8. package/dist/clients/dispatch/plan.js +6 -2
  9. package/dist/clients/dispatch/rules/high-complexity.js +29 -4
  10. package/dist/clients/dispatch/rules/high-fan-out.js +24 -4
  11. package/dist/clients/dispatch/runners/ast-grep-napi.js +134 -108
  12. package/dist/clients/dispatch/runners/credo.js +10 -3
  13. package/dist/clients/dispatch/runners/detekt.js +1 -1
  14. package/dist/clients/dispatch/runners/elixir-check.js +79 -15
  15. package/dist/clients/dispatch/runners/go-vet.js +41 -18
  16. package/dist/clients/dispatch/runners/index.js +4 -2
  17. package/dist/clients/dispatch/runners/lsp.js +31 -1
  18. package/dist/clients/dispatch/runners/markdownlint.js +11 -3
  19. package/dist/clients/dispatch/runners/mypy.js +15 -3
  20. package/dist/clients/dispatch/runners/phpstan.js +13 -3
  21. package/dist/clients/dispatch/runners/pyright.js +4 -1
  22. package/dist/clients/dispatch/runners/rust-clippy.js +27 -7
  23. package/dist/clients/dispatch/runners/shellcheck.js +16 -4
  24. package/dist/clients/dispatch/runners/shfmt.js +25 -1
  25. package/dist/clients/dispatch/runners/spotbugs.js +258 -0
  26. package/dist/clients/dispatch/runners/taplo.js +8 -1
  27. package/dist/clients/dispatch/runners/trivy-config.js +180 -0
  28. package/dist/clients/dispatch/runners/utils/runner-helpers.js +29 -2
  29. package/dist/clients/dispatch/runners/yaml-rule-parser.js +12 -1
  30. package/dist/clients/dispatch/runners/zig-check.js +3 -1
  31. package/dist/clients/dispatch/tool-profile.js +2 -1
  32. package/dist/clients/file-utils.js +48 -3
  33. package/dist/clients/formatters.js +52 -3
  34. package/dist/clients/gitleaks-client.js +9 -61
  35. package/dist/clients/govulncheck-client.js +8 -43
  36. package/dist/clients/host-edit-normalize.js +139 -0
  37. package/dist/clients/installer/index.js +713 -40
  38. package/dist/clients/knip-client.js +11 -10
  39. package/dist/clients/language-policy.js +14 -12
  40. package/dist/clients/language-profile.js +10 -1
  41. package/dist/clients/lens-config.js +7 -0
  42. package/dist/clients/lens-engine.js +5 -14
  43. package/dist/clients/lsp/client.js +316 -46
  44. package/dist/clients/lsp/index.js +164 -33
  45. package/dist/clients/lsp/jvm-runtime.js +158 -0
  46. package/dist/clients/lsp/launch.js +25 -14
  47. package/dist/clients/lsp/lombok.js +158 -0
  48. package/dist/clients/lsp/position-encoding.js +61 -0
  49. package/dist/clients/lsp/server-strategies.js +88 -1
  50. package/dist/clients/lsp/server.js +618 -190
  51. package/dist/clients/lsp/watch-queue.js +61 -0
  52. package/dist/clients/lsp-status.js +59 -0
  53. package/dist/clients/mcp/session.js +2 -1
  54. package/dist/clients/module-report-lsp.js +193 -0
  55. package/dist/clients/module-report.js +592 -0
  56. package/dist/clients/oldtext-autopatch.js +8 -7
  57. package/dist/clients/opengrep-config.js +80 -0
  58. package/dist/clients/partial-edit-apply.js +10 -8
  59. package/dist/clients/path-utils.js +22 -0
  60. package/dist/clients/pipeline.js +132 -63
  61. package/dist/clients/production-readiness.js +45 -69
  62. package/dist/clients/project-diagnostics/cache.js +44 -1
  63. package/dist/clients/project-diagnostics/scanner.js +64 -2
  64. package/dist/clients/project-lens-config.js +159 -0
  65. package/dist/clients/read-expansion.js +8 -0
  66. package/dist/clients/read-guard-tool-lines.js +19 -5
  67. package/dist/clients/read-guard.js +34 -0
  68. package/dist/clients/review-graph/builder.js +418 -110
  69. package/dist/clients/review-graph/import-resolvers.js +291 -0
  70. package/dist/clients/review-graph/workspace-modules.js +5 -0
  71. package/dist/clients/runtime-session.js +87 -17
  72. package/dist/clients/runtime-turn.js +95 -13
  73. package/dist/clients/safe-spawn.js +17 -1
  74. package/dist/clients/secret-findings.js +114 -0
  75. package/dist/clients/security-scan-client.js +103 -0
  76. package/dist/clients/sgconfig.js +68 -0
  77. package/dist/clients/source-filter.js +12 -1
  78. package/dist/clients/startup-scan.js +13 -4
  79. package/dist/clients/tool-policy.js +189 -9
  80. package/dist/clients/tree-sitter-client.js +328 -4
  81. package/dist/clients/tree-sitter-query-loader.js +18 -1
  82. package/dist/clients/tree-sitter-symbol-extractor.js +247 -72
  83. package/dist/clients/trivy-client.js +441 -0
  84. package/dist/clients/typos-config.js +33 -0
  85. package/dist/clients/widget-state.js +47 -1
  86. package/dist/clients/zizmor-config.js +77 -0
  87. package/dist/index.js +51 -104
  88. package/dist/mcp/server.js +87 -42
  89. package/dist/tools/ast-dump.js +1 -1
  90. package/dist/tools/ast-grep-replace.js +1 -1
  91. package/dist/tools/ast-grep-search.js +1 -1
  92. package/dist/tools/lens-diagnostics.js +77 -25
  93. package/dist/tools/lsp-diagnostics.js +31 -23
  94. package/dist/tools/lsp-navigation.js +145 -58
  95. package/dist/tools/lsp-structured-output.js +294 -0
  96. package/dist/tools/module-report.js +131 -0
  97. package/package.json +13 -7
  98. package/rules/ast-grep-rules/.sgconfig.yml +9 -0
  99. package/rules/ast-grep-rules/coderabbit/LICENSE +201 -0
  100. package/rules/ast-grep-rules/coderabbit/README.md +9 -0
  101. package/rules/ast-grep-rules/coderabbit/rules/c/security/dont-call-system-c.yml +57 -0
  102. package/rules/ast-grep-rules/coderabbit/rules/c/security/file-access-before-action-c.yml +182 -0
  103. package/rules/ast-grep-rules/coderabbit/rules/c/security/file-stat-before-action-c.yml +331 -0
  104. package/rules/ast-grep-rules/coderabbit/rules/c/security/insecure-hash-c.yml +286 -0
  105. package/rules/ast-grep-rules/coderabbit/rules/c/security/libxml2-audit-parser-c.yml +258 -0
  106. package/rules/ast-grep-rules/coderabbit/rules/c/security/null-library-function-c.yml +254 -0
  107. package/rules/ast-grep-rules/coderabbit/rules/c/security/sizeof-this-c.yml +121 -0
  108. package/rules/ast-grep-rules/coderabbit/rules/c/security/small-key-size-c.yml +40 -0
  109. package/rules/ast-grep-rules/coderabbit/rules/c/security/world-writable-file-c.yml +317 -0
  110. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/dont-call-system-cpp.yml +57 -0
  111. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/file-access-before-action-cpp.yml +271 -0
  112. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/file-stat-before-action-cpp.yml +494 -0
  113. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/fix-format-security-error-cpp.yml +18 -0
  114. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/insecure-hash-cpp.yml +122 -0
  115. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/libxml2-audit-parser-cpp.yml +258 -0
  116. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/missing-nul-cpp-string-memcpy-cpp.yml +393 -0
  117. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/null-library-function-cpp.yml +254 -0
  118. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/return-c-str-cpp.yml +124 -0
  119. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/sizeof-this-cpp.yml +41 -0
  120. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/small-key-size-cpp.yml +40 -0
  121. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/std-return-data-cpp.yml +93 -0
  122. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/std-vector-invalidation-cpp.yml +147 -0
  123. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/string-view-temporary-string-cpp.yml +924 -0
  124. package/rules/ast-grep-rules/coderabbit/rules/cpp/security/world-writable-file-cpp.yml +317 -0
  125. package/rules/ast-grep-rules/coderabbit/rules/csharp/security/httponly-false-csharp.yml +42 -0
  126. package/rules/ast-grep-rules/coderabbit/rules/csharp/security/insecure-binaryformatter-deserialization-csharp.yml +38 -0
  127. package/rules/ast-grep-rules/coderabbit/rules/csharp/security/jwt-decode-without-verify-csharp.yml +700 -0
  128. package/rules/ast-grep-rules/coderabbit/rules/csharp/security/jwt-hardcoded-secret-csharp.yml +672 -0
  129. package/rules/ast-grep-rules/coderabbit/rules/csharp/security/jwt-tokenvalidationparameters-no-expiry-validation-csharp.yml +136 -0
  130. package/rules/ast-grep-rules/coderabbit/rules/csharp/security/networkcredential-hardcoded-secret-python.yml +394 -0
  131. package/rules/ast-grep-rules/coderabbit/rules/csharp/security/npgsqlconnectionstringbuilder-hardcoded-secret-csharp.yml +339 -0
  132. package/rules/ast-grep-rules/coderabbit/rules/csharp/security/oracleconnectionstringbuilder-hardcoded-secret-csharp.yml +339 -0
  133. package/rules/ast-grep-rules/coderabbit/rules/csharp/security/sqlconnectionstringbuilder-hardcoded-secret-csharp.yml +339 -0
  134. package/rules/ast-grep-rules/coderabbit/rules/csharp/security/stacktrace-disclosure-csharp.yml +48 -0
  135. package/rules/ast-grep-rules/coderabbit/rules/csharp/security/use-ecb-mode-csharp.yml +177 -0
  136. package/rules/ast-grep-rules/coderabbit/rules/go/security/avoid-bind-to-all-interfaces-go.yml +27 -0
  137. package/rules/ast-grep-rules/coderabbit/rules/go/security/gorilla-cookie-store-hardcoded-session-key-go.yml +90 -0
  138. package/rules/ast-grep-rules/coderabbit/rules/go/security/gorilla-csrf-hardcoded-auth-key-go.yml +79 -0
  139. package/rules/ast-grep-rules/coderabbit/rules/go/security/grpc-client-insecure-connection-go.yml +60 -0
  140. package/rules/ast-grep-rules/coderabbit/rules/go/security/jwt-go-none-algorithm-go.yml +35 -0
  141. package/rules/ast-grep-rules/coderabbit/rules/go/security/missing-ssl-minversion-go.yml +42 -0
  142. package/rules/ast-grep-rules/coderabbit/rules/go/security/openai-empty-secret-go.yml +199 -0
  143. package/rules/ast-grep-rules/coderabbit/rules/go/security/openai-hardcoded-secret-go.yml +208 -0
  144. package/rules/ast-grep-rules/coderabbit/rules/go/security/ssl-v3-is-insecure-go.yml +40 -0
  145. package/rules/ast-grep-rules/coderabbit/rules/go/security/tls-with-insecure-cipher-go.yml +65 -0
  146. package/rules/ast-grep-rules/coderabbit/rules/go/security/use-of-weak-rsa-key-go.yml +253 -0
  147. package/rules/ast-grep-rules/coderabbit/rules/html/security/plaintext-http-link-html.yml +76 -0
  148. package/rules/ast-grep-rules/coderabbit/rules/java/security/cbc-padding-oracle-java.yml +17 -0
  149. package/rules/ast-grep-rules/coderabbit/rules/java/security/cookie-httponly-false-java.yml +9 -0
  150. package/rules/ast-grep-rules/coderabbit/rules/java/security/cookie-missing-httponly-java.yml +21 -0
  151. package/rules/ast-grep-rules/coderabbit/rules/java/security/cookie-missing-samesite-java.yml +64 -0
  152. package/rules/ast-grep-rules/coderabbit/rules/java/security/cookie-missing-secure-flag-java.yml +51 -0
  153. package/rules/ast-grep-rules/coderabbit/rules/java/security/cookie-secure-flag-false-java.yml +13 -0
  154. package/rules/ast-grep-rules/coderabbit/rules/java/security/datanucleus-hardcoded-connection-password-java.yml +575 -0
  155. package/rules/ast-grep-rules/coderabbit/rules/java/security/des-is-deprecated-java.yml +15 -0
  156. package/rules/ast-grep-rules/coderabbit/rules/java/security/desede-is-deprecated-java.yml +92 -0
  157. package/rules/ast-grep-rules/coderabbit/rules/java/security/documentbuilderfactory-disallow-doctype-decl-false-java.yml +45 -0
  158. package/rules/ast-grep-rules/coderabbit/rules/java/security/documentbuilderfactory-external-general-entities-true-java.yml +279 -0
  159. package/rules/ast-grep-rules/coderabbit/rules/java/security/documentbuilderfactory-external-parameter-entities-true-java.yml +279 -0
  160. package/rules/ast-grep-rules/coderabbit/rules/java/security/drivermanager-hardcoded-secret-java.yml +142 -0
  161. package/rules/ast-grep-rules/coderabbit/rules/java/security/ecb-cipher-java.yml +47 -0
  162. package/rules/ast-grep-rules/coderabbit/rules/java/security/hardcoded-connection-password-java.yml +341 -0
  163. package/rules/ast-grep-rules/coderabbit/rules/java/security/hardcoded-secret-in-credentials-java.yml +281 -0
  164. package/rules/ast-grep-rules/coderabbit/rules/java/security/java-jwt-hardcoded-secret-java.yml +124 -0
  165. package/rules/ast-grep-rules/coderabbit/rules/java/security/jedis-jedisclientconfig-hardcoded-password-java.yml +804 -0
  166. package/rules/ast-grep-rules/coderabbit/rules/java/security/jedis-jedisfactory-hardcoded-password-java.yml +930 -0
  167. package/rules/ast-grep-rules/coderabbit/rules/java/security/missing-httponly-java.yml +583 -0
  168. package/rules/ast-grep-rules/coderabbit/rules/java/security/missing-secure-java.yml +584 -0
  169. package/rules/ast-grep-rules/coderabbit/rules/java/security/no-null-cipher-java.yml +38 -0
  170. package/rules/ast-grep-rules/coderabbit/rules/java/security/passwordauthentication-hardcoded-password-java.yml +651 -0
  171. package/rules/ast-grep-rules/coderabbit/rules/java/security/rsa-no-padding-java.yml +13 -0
  172. package/rules/ast-grep-rules/coderabbit/rules/java/security/simple-command-injection-direct-input-java.yml +55 -0
  173. package/rules/ast-grep-rules/coderabbit/rules/java/security/system-setproperty-hardcoded-secret-java.yml +312 -0
  174. package/rules/ast-grep-rules/coderabbit/rules/java/security/unencrypted-socket-java.yml +20 -0
  175. package/rules/ast-grep-rules/coderabbit/rules/java/security/use-of-aes-ecb-java.yml +68 -0
  176. package/rules/ast-grep-rules/coderabbit/rules/java/security/use-of-blowfish-java.yml +45 -0
  177. package/rules/ast-grep-rules/coderabbit/rules/java/security/use-of-default-aes-java.yml +318 -0
  178. package/rules/ast-grep-rules/coderabbit/rules/java/security/use-of-md5-digest-utils-java.yml +38 -0
  179. package/rules/ast-grep-rules/coderabbit/rules/java/security/use-of-md5-java.yml +104 -0
  180. package/rules/ast-grep-rules/coderabbit/rules/java/security/use-of-rc2-java.yml +84 -0
  181. package/rules/ast-grep-rules/coderabbit/rules/java/security/use-of-rc4-java.yml +38 -0
  182. package/rules/ast-grep-rules/coderabbit/rules/java/security/use-of-sha1-java.yml +165 -0
  183. package/rules/ast-grep-rules/coderabbit/rules/java/security/weak-ssl-context-java.yml +56 -0
  184. package/rules/ast-grep-rules/coderabbit/rules/javascript/security/detect-angular-sce-disabled-javascript.yml +14 -0
  185. package/rules/ast-grep-rules/coderabbit/rules/javascript/security/express-jwt-hardcoded-secret-javascript.yml +289 -0
  186. package/rules/ast-grep-rules/coderabbit/rules/javascript/security/express-session-hardcoded-secret-javascript.yml +101 -0
  187. package/rules/ast-grep-rules/coderabbit/rules/javascript/security/jwt-simple-noverify-javascript.yml +43 -0
  188. package/rules/ast-grep-rules/coderabbit/rules/javascript/security/node-rsa-weak-key-javascript.yml +577 -0
  189. package/rules/ast-grep-rules/coderabbit/rules/javascript/security/node-sequelize-empty-password-argument-javascript.yml +191 -0
  190. package/rules/ast-grep-rules/coderabbit/rules/javascript/security/node-sequelize-hardcoded-secret-argument-javascript.yml +94 -0
  191. package/rules/ast-grep-rules/coderabbit/rules/kotlin/security/des-is-deprecated-kotlin.yml +15 -0
  192. package/rules/ast-grep-rules/coderabbit/rules/kotlin/security/desede-is-deprecated-kotlin.yml +462 -0
  193. package/rules/ast-grep-rules/coderabbit/rules/kotlin/security/jwt-hardcode-kotlin.yml +567 -0
  194. package/rules/ast-grep-rules/coderabbit/rules/kotlin/security/rsa-no-padding-kotlin.yml +13 -0
  195. package/rules/ast-grep-rules/coderabbit/rules/kotlin/security/system-setproperty-hardcoded-secret-kotlin.yml +51 -0
  196. package/rules/ast-grep-rules/coderabbit/rules/php/security/openssl-cbc-static-iv-php.yml +641 -0
  197. package/rules/ast-grep-rules/coderabbit/rules/php/security/search-active-debug-php.yml +153 -0
  198. package/rules/ast-grep-rules/coderabbit/rules/python/security/avoid-mktemp-python.yml +71 -0
  199. package/rules/ast-grep-rules/coderabbit/rules/python/security/avoid_app_run_with_bad_host-python.yml +69 -0
  200. package/rules/ast-grep-rules/coderabbit/rules/python/security/debug-enabled-python.yml +91 -0
  201. package/rules/ast-grep-rules/coderabbit/rules/python/security/hashids-with-django-secret-python.yml +273 -0
  202. package/rules/ast-grep-rules/coderabbit/rules/python/security/hashids-with-flask-secret-python.yml +190 -0
  203. package/rules/ast-grep-rules/coderabbit/rules/python/security/insecure-cipher-algorithm-rc4-python.yml +75 -0
  204. package/rules/ast-grep-rules/coderabbit/rules/python/security/jwt-python-hardcoded-secret-python.yml +116 -0
  205. package/rules/ast-grep-rules/coderabbit/rules/python/security/openai-hardcoded-secret-python.yml +21 -0
  206. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-cassandra-empty-password-python.yml +227 -0
  207. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-cassandra-hardcoded-secret-python.yml +396 -0
  208. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-couchbase-empty-password-python.yml +72 -0
  209. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-couchbase-hardcoded-secret-python.yml +183 -0
  210. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-elasticsearch-hardcoded-bearer-auth-python.yml +64 -0
  211. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-ldap3-empty-password-python.yml +92 -0
  212. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-ldap3-hardcoded-secret-python.yml +145 -0
  213. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-mariadb-empty-password-python.yml +194 -0
  214. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-mariadb-hardcoded-secret-python.yml +193 -0
  215. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-mysql-empty-password-python.yml +192 -0
  216. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-mysql-hardcoded-secret-python.yml +195 -0
  217. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-mysqlclient-empty-password-python.yml +189 -0
  218. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-mysqlclient-hardcoded-secret-python.yml +191 -0
  219. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-neo4j-empty-password-python.yml +203 -0
  220. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-neo4j-hardcoded-secret-python.yml +205 -0
  221. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-peewee-mysql-empty-password-python.yml +50 -0
  222. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-peewee-mysql-hardcoded-secret-python.yml +48 -0
  223. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-peewee-pg-empty-password-python.yml +51 -0
  224. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-peewee-pg-hardcoded-secret-python.yml +49 -0
  225. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-pg8000-empty-password-python.yml +43 -0
  226. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-pg8000-hardcoded-secret-python.yml +67 -0
  227. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-psycopg2-empty-password-python.yml +65 -0
  228. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-psycopg2-hardcoded-secret-python.yml +64 -0
  229. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-pyjwt-hardcoded-secret-python.yml +38 -0
  230. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-pymongo-empty-password-python.yml +50 -0
  231. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-pymongo-hardcoded-secret-python.yml +48 -0
  232. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-pymssql-empty-password-python.yml +50 -0
  233. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-pymssql-hardcoded-secret-python.yml +48 -0
  234. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-pymysql-empty-password-python.yml +49 -0
  235. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-pymysql-hardcoded-secret-python.yml +47 -0
  236. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-redis-empty-password-python.yml +66 -0
  237. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-redis-hardcoded-secret-python.yml +65 -0
  238. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-requests-empty-password-python.yml +42 -0
  239. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-requests-hardcoded-secret-python.yml +146 -0
  240. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-requests-oauth-hardcoded-secret-python.yml +278 -0
  241. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-tormysql-empty-password-python.yml +301 -0
  242. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-tormysql-hardcoded-secret-python.yml +292 -0
  243. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-urllib3-hardcoded-secret-python.yml +52 -0
  244. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-webrepl-empty-password-python.yml +49 -0
  245. package/rules/ast-grep-rules/coderabbit/rules/python/security/python-webrepl-hardcoded-secret-python.yml +47 -0
  246. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/force-ssl-false-ruby.yml +23 -0
  247. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/hardcoded-http-auth-in-controller-ruby.yml +55 -0
  248. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/hardcoded-secret-rsa-passphrase-ruby.yml +218 -0
  249. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/insufficient-rsa-key-size-ruby.yml +84 -0
  250. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-aws-sdk-hardcoded-secret-ruby.yml +140 -0
  251. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-cassandra-empty-password-ruby.yml +141 -0
  252. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-cassandra-hardcoded-secret-ruby.yml +138 -0
  253. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-excon-hardcoded-secret-ruby.yml +226 -0
  254. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-faraday-hardcoded-secret-ruby.yml +490 -0
  255. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-mongo-empty-password-ruby.yml +356 -0
  256. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-mongo-hardcoded-secret-ruby.yml +400 -0
  257. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-mysql2-empty-password-ruby.yml +227 -0
  258. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-mysql2-hardcoded-secret-ruby.yml +248 -0
  259. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-octokit-hardcoded-secret-ruby.yml +125 -0
  260. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-pg-empty-password-ruby.yml +150 -0
  261. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-pg-hardcoded-secret-ruby.yml +189 -0
  262. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-redis-empty-password-ruby.yml +72 -0
  263. package/rules/ast-grep-rules/coderabbit/rules/ruby/security/ruby-redis-hardcoded-secret-ruby.yml +70 -0
  264. package/rules/ast-grep-rules/coderabbit/rules/rust/security/empty-password-rust.yml +1039 -0
  265. package/rules/ast-grep-rules/coderabbit/rules/rust/security/hardcoded-password-rust.yml +1016 -0
  266. package/rules/ast-grep-rules/coderabbit/rules/rust/security/postgres-empty-password-rust.yml +283 -0
  267. package/rules/ast-grep-rules/coderabbit/rules/rust/security/reqwest-accept-invalid-rust.yml +21 -0
  268. package/rules/ast-grep-rules/coderabbit/rules/rust/security/secrets-reqwest-hardcoded-auth-rust.yml +290 -0
  269. package/rules/ast-grep-rules/coderabbit/rules/rust/security/ssl-verify-none-rust.yml +100 -0
  270. package/rules/ast-grep-rules/coderabbit/rules/rust/security/tokio-postgres-empty-password-rust.yml +235 -0
  271. package/rules/ast-grep-rules/coderabbit/rules/rust/security/tokio-postgres-hardcoded-password-rust.yml +229 -0
  272. package/rules/ast-grep-rules/coderabbit/rules/scala/security/jwt-scala-hardcode-scala.yml +109 -0
  273. package/rules/ast-grep-rules/coderabbit/rules/scala/security/scala-jwt-hardcoded-secret-scala.yml +176 -0
  274. package/rules/ast-grep-rules/coderabbit/rules/swift/security/aes-hardcoded-secret-swift.yml +345 -0
  275. package/rules/ast-grep-rules/coderabbit/rules/swift/security/blowfish-hardcoded-secret-swift.yml +345 -0
  276. package/rules/ast-grep-rules/coderabbit/rules/swift/security/chacha20-hardcoded-secret-swift.yml +345 -0
  277. package/rules/ast-grep-rules/coderabbit/rules/swift/security/insecure-biometrics-swift.yml +43 -0
  278. package/rules/ast-grep-rules/coderabbit/rules/swift/security/rabbit-hardcoded-secret-swift.yml +345 -0
  279. package/rules/ast-grep-rules/coderabbit/rules/typescript/security/detect-angular-sce-disabled-typescript.yml +36 -0
  280. package/rules/ast-grep-rules/coderabbit/rules/typescript/security/express-session-hardcoded-secret-typescript.yml +203 -0
  281. package/rules/ast-grep-rules/coderabbit/rules/typescript/security/jwt-simple-noverify-typescript.yml +112 -0
  282. package/rules/ast-grep-rules/coderabbit/rules/typescript/security/node-rsa-weak-key-typescript.yml +1483 -0
  283. package/rules/ast-grep-rules/coderabbit/rules/typescript/security/node-sequelize-empty-password-argument-typescript.yml +169 -0
  284. package/rules/ast-grep-rules/coderabbit/rules/typescript/security/node-sequelize-hardcoded-secret-argument-typescript.yml +154 -0
  285. package/rules/ast-grep-rules/rule-schema.json +7 -7
  286. package/rules/ast-grep-rules/rule-tests/array-callback-return-js-test.yml +10 -0
  287. package/rules/ast-grep-rules/rule-tests/array-callback-return-test.yml +10 -0
  288. package/rules/ast-grep-rules/rule-tests/avoid-duplicate-export-test.yml +14 -0
  289. package/rules/ast-grep-rules/rule-tests/consistent-existence-index-check-js-test.yml +10 -0
  290. package/rules/ast-grep-rules/rule-tests/consistent-existence-index-check-test.yml +10 -0
  291. package/rules/ast-grep-rules/rule-tests/defer-in-loop-test.yml +20 -0
  292. package/rules/ast-grep-rules/rule-tests/enforce-node-protocol-js-test.yml +8 -0
  293. package/rules/ast-grep-rules/rule-tests/enforce-node-protocol-test.yml +8 -0
  294. package/rules/ast-grep-rules/rule-tests/find-import-file-without-extension-test.yml +8 -0
  295. package/rules/ast-grep-rules/rule-tests/go-defer-func-call-antipattern-test.yml +8 -0
  296. package/rules/ast-grep-rules/rule-tests/go-test-functions-test.yml +9 -0
  297. package/rules/ast-grep-rules/rule-tests/gorm-find-without-where-test.yml +15 -0
  298. package/rules/ast-grep-rules/rule-tests/gorm-n-plus-one-test.yml +20 -0
  299. package/rules/ast-grep-rules/rule-tests/hardcoded-url-js-test.yml +7 -0
  300. package/rules/ast-grep-rules/rule-tests/hardcoded-url-test.yml +7 -0
  301. package/rules/ast-grep-rules/rule-tests/inline-styles-test.yml +8 -0
  302. package/rules/ast-grep-rules/rule-tests/jsx-boolean-short-circuit-test.yml +8 -0
  303. package/rules/ast-grep-rules/rule-tests/jwt-no-verify-js-test.yml +9 -0
  304. package/rules/ast-grep-rules/rule-tests/jwt-no-verify-test.yml +9 -0
  305. package/rules/ast-grep-rules/rule-tests/large-class-test.yml +15 -0
  306. package/rules/ast-grep-rules/rule-tests/long-parameter-list-test.yml +8 -0
  307. package/rules/ast-grep-rules/rule-tests/loop-var-capture-test.yml +25 -0
  308. package/rules/ast-grep-rules/rule-tests/missing-component-decorator-test.yml +7 -0
  309. package/rules/ast-grep-rules/rule-tests/mutex-unlock-mismatch-test.yml +29 -0
  310. package/rules/ast-grep-rules/rule-tests/nested-ternary-js-test.yml +8 -0
  311. package/rules/ast-grep-rules/rule-tests/nested-ternary-test.yml +8 -0
  312. package/rules/ast-grep-rules/rule-tests/nil-map-assignment-test.yml +50 -0
  313. package/rules/ast-grep-rules/rule-tests/no-absolute-path-import-js-test.yml +8 -0
  314. package/rules/ast-grep-rules/rule-tests/no-absolute-path-import-test.yml +8 -0
  315. package/rules/ast-grep-rules/rule-tests/no-accumulating-spread-js-test.yml +8 -0
  316. package/rules/ast-grep-rules/rule-tests/no-alert-js-test.yml +7 -0
  317. package/rules/ast-grep-rules/rule-tests/no-alert-test.yml +7 -0
  318. package/rules/ast-grep-rules/rule-tests/no-any-type-test.yml +9 -0
  319. package/rules/ast-grep-rules/rule-tests/no-array-constructor-js-test.yml +9 -0
  320. package/rules/ast-grep-rules/rule-tests/no-array-constructor-test.yml +9 -0
  321. package/rules/ast-grep-rules/rule-tests/no-array-reverse-mutation-js-test.yml +9 -0
  322. package/rules/ast-grep-rules/rule-tests/no-array-reverse-mutation-test.yml +9 -0
  323. package/rules/ast-grep-rules/rule-tests/no-as-any-test.yml +8 -0
  324. package/rules/ast-grep-rules/rule-tests/no-assert-tuple-test.yml +13 -0
  325. package/rules/ast-grep-rules/rule-tests/no-async-promise-executor-js-test.yml +8 -0
  326. package/rules/ast-grep-rules/rule-tests/no-async-promise-executor-test.yml +8 -0
  327. package/rules/ast-grep-rules/rule-tests/no-await-expression-member-js-test.yml +8 -0
  328. package/rules/ast-grep-rules/rule-tests/no-await-expression-member-test.yml +8 -0
  329. package/rules/ast-grep-rules/rule-tests/no-await-in-promise-all-js-test.yml +7 -0
  330. package/rules/ast-grep-rules/rule-tests/no-await-in-promise-all-test.yml +7 -0
  331. package/rules/ast-grep-rules/rule-tests/no-await-in-promise-methods-js-test.yml +10 -0
  332. package/rules/ast-grep-rules/rule-tests/no-await-in-promise-methods-test.yml +10 -0
  333. package/rules/ast-grep-rules/rule-tests/no-aws-access-key-literal-test.yml +8 -0
  334. package/rules/ast-grep-rules/rule-tests/no-aws-apigateway-no-auth-test.yml +12 -0
  335. package/rules/ast-grep-rules/rule-tests/no-aws-s3-public-access-test.yml +9 -0
  336. package/rules/ast-grep-rules/rule-tests/no-bare-except-test.yml +28 -0
  337. package/rules/ast-grep-rules/rule-tests/no-blank-target-js-test.yml +8 -0
  338. package/rules/ast-grep-rules/rule-tests/no-boolean-in-except-test.yml +28 -0
  339. package/rules/ast-grep-rules/rule-tests/no-case-declarations-js-test.yml +24 -0
  340. package/rules/ast-grep-rules/rule-tests/no-case-declarations-test.yml +24 -0
  341. package/rules/ast-grep-rules/rule-tests/no-compare-neg-zero-js-test.yml +9 -0
  342. package/rules/ast-grep-rules/rule-tests/no-compare-neg-zero-test.yml +9 -0
  343. package/rules/ast-grep-rules/rule-tests/no-comparison-to-none-test.yml +11 -0
  344. package/rules/ast-grep-rules/rule-tests/no-comparison-to-true-false-test.yml +13 -0
  345. package/rules/ast-grep-rules/rule-tests/no-compile-call-test.yml +10 -0
  346. package/rules/ast-grep-rules/rule-tests/no-cond-assign-js-test.yml +9 -0
  347. package/rules/ast-grep-rules/rule-tests/no-cond-assign-test.yml +9 -0
  348. package/rules/ast-grep-rules/rule-tests/no-console-except-error-js-test.yml +13 -0
  349. package/rules/ast-grep-rules/rule-tests/no-console-except-error-test.yml +13 -0
  350. package/rules/ast-grep-rules/rule-tests/no-constant-condition-js-test.yml +10 -0
  351. package/rules/ast-grep-rules/rule-tests/no-constant-condition-test.yml +10 -0
  352. package/rules/ast-grep-rules/rule-tests/no-db-string-literal-password-test.yml +8 -0
  353. package/rules/ast-grep-rules/rule-tests/no-demeter-message-chain-test.yml +16 -0
  354. package/rules/ast-grep-rules/rule-tests/no-discarded-error-js-test.yml +9 -0
  355. package/rules/ast-grep-rules/rule-tests/no-discarded-error-test.yml +9 -0
  356. package/rules/ast-grep-rules/rule-tests/no-dunder-exit-wrong-arity-test.yml +27 -0
  357. package/rules/ast-grep-rules/rule-tests/no-dupe-class-members-test.yml +11 -0
  358. package/rules/ast-grep-rules/rule-tests/no-dupe-keys-js-test.yml +9 -0
  359. package/rules/ast-grep-rules/rule-tests/no-dupe-keys-test.yml +9 -0
  360. package/rules/ast-grep-rules/rule-tests/no-duplicate-kwarg-test.yml +8 -0
  361. package/rules/ast-grep-rules/rule-tests/no-ellipsis-body-test.yml +20 -0
  362. package/rules/ast-grep-rules/rule-tests/no-except-non-exception-test.yml +23 -0
  363. package/rules/ast-grep-rules/rule-tests/no-extra-boolean-cast-js-test.yml +9 -0
  364. package/rules/ast-grep-rules/rule-tests/no-extra-boolean-cast-test.yml +9 -0
  365. package/rules/ast-grep-rules/rule-tests/no-fastapi-router-prefix-outside-init-test.yml +8 -0
  366. package/rules/ast-grep-rules/rule-tests/no-flag-argument-js-test.yml +37 -0
  367. package/rules/ast-grep-rules/rule-tests/no-flag-argument-test.yml +37 -0
  368. package/rules/ast-grep-rules/rule-tests/no-flask-preprocess-request-ignored-test.yml +16 -0
  369. package/rules/ast-grep-rules/rule-tests/no-flask-secret-key-literal-test.yml +11 -0
  370. package/rules/ast-grep-rules/rule-tests/no-flask-sendfile-without-mimetype-test.yml +8 -0
  371. package/rules/ast-grep-rules/rule-tests/no-global-eval-js-test.yml +17 -0
  372. package/rules/ast-grep-rules/rule-tests/no-hardcoded-password-test.yml +10 -0
  373. package/rules/ast-grep-rules/rule-tests/no-html-autoescape-off-test.yml +13 -0
  374. package/rules/ast-grep-rules/rule-tests/no-http-headers-bracket-access-test.yml +7 -0
  375. package/rules/ast-grep-rules/rule-tests/no-identity-operator-on-literals-test.yml +14 -0
  376. package/rules/ast-grep-rules/rule-tests/no-implied-eval-js-test.yml +12 -0
  377. package/rules/ast-grep-rules/rule-tests/no-implied-eval-test.yml +12 -0
  378. package/rules/ast-grep-rules/rule-tests/no-init-return-test.yml +26 -0
  379. package/rules/ast-grep-rules/rule-tests/no-inner-html-js-test.yml +8 -0
  380. package/rules/ast-grep-rules/rule-tests/no-inner-html-test.yml +8 -0
  381. package/rules/ast-grep-rules/rule-tests/no-insecure-randomness-js-test.yml +13 -0
  382. package/rules/ast-grep-rules/rule-tests/no-insecure-randomness-test.yml +13 -0
  383. package/rules/ast-grep-rules/rule-tests/no-instanceof-array-js-test.yml +8 -0
  384. package/rules/ast-grep-rules/rule-tests/no-instanceof-array-test.yml +8 -0
  385. package/rules/ast-grep-rules/rule-tests/no-instanceof-builtins-js-test.yml +11 -0
  386. package/rules/ast-grep-rules/rule-tests/no-instanceof-builtins-test.yml +11 -0
  387. package/rules/ast-grep-rules/rule-tests/no-javascript-url-js-test.yml +9 -0
  388. package/rules/ast-grep-rules/rule-tests/no-javascript-url-test.yml +9 -0
  389. package/rules/ast-grep-rules/rule-tests/no-jinja2-autoescape-off-test.yml +13 -0
  390. package/rules/ast-grep-rules/rule-tests/no-marshal-load-test.yml +10 -0
  391. package/rules/ast-grep-rules/rule-tests/no-mutable-contextvar-default-test.yml +9 -0
  392. package/rules/ast-grep-rules/rule-tests/no-mutable-default-test.yml +12 -0
  393. package/rules/ast-grep-rules/rule-tests/no-mutable-export-test.yml +10 -0
  394. package/rules/ast-grep-rules/rule-tests/no-nan-comparison-js-test.yml +11 -0
  395. package/rules/ast-grep-rules/rule-tests/no-nan-comparison-test.yml +11 -0
  396. package/rules/ast-grep-rules/rule-tests/no-negation-in-equality-check-js-test.yml +10 -0
  397. package/rules/ast-grep-rules/rule-tests/no-negation-in-equality-check-test.yml +10 -0
  398. package/rules/ast-grep-rules/rule-tests/no-nested-links-test.yml +8 -0
  399. package/rules/ast-grep-rules/rule-tests/no-new-symbol-js-test.yml +8 -0
  400. package/rules/ast-grep-rules/rule-tests/no-new-symbol-test.yml +8 -0
  401. package/rules/ast-grep-rules/rule-tests/no-new-wrappers-js-test.yml +9 -0
  402. package/rules/ast-grep-rules/rule-tests/no-new-wrappers-test.yml +9 -0
  403. package/rules/ast-grep-rules/rule-tests/no-non-null-assertion-test.yml +10 -0
  404. package/rules/ast-grep-rules/rule-tests/no-notimplemented-in-bool-test.yml +20 -0
  405. package/rules/ast-grep-rules/rule-tests/no-numpy-nan-equality-test.yml +22 -0
  406. package/rules/ast-grep-rules/rule-tests/no-octal-literal-test.yml +8 -0
  407. package/rules/ast-grep-rules/rule-tests/no-only-defined-names-in-dunder-all-test.yml +17 -0
  408. package/rules/ast-grep-rules/rule-tests/no-open-redirect-js-test.yml +12 -0
  409. package/rules/ast-grep-rules/rule-tests/no-open-redirect-test.yml +12 -0
  410. package/rules/ast-grep-rules/rule-tests/no-prototype-builtins-js-test.yml +9 -0
  411. package/rules/ast-grep-rules/rule-tests/no-prototype-builtins-native-test.yml +9 -0
  412. package/rules/ast-grep-rules/rule-tests/no-prototype-builtins-test.yml +9 -0
  413. package/rules/ast-grep-rules/rule-tests/no-python-sql-string-concat-test.yml +10 -0
  414. package/rules/ast-grep-rules/rule-tests/no-raise-not-implemented-test.yml +21 -0
  415. package/rules/ast-grep-rules/rule-tests/no-raise-stopiteration-in-generator-test.yml +22 -0
  416. package/rules/ast-grep-rules/rule-tests/no-relative-cross-package-import-test.yml +9 -0
  417. package/rules/ast-grep-rules/rule-tests/no-requests-verify-false-test.yml +11 -0
  418. package/rules/ast-grep-rules/rule-tests/no-requests-without-timeout-test.yml +10 -0
  419. package/rules/ast-grep-rules/rule-tests/no-return-await-test.yml +12 -0
  420. package/rules/ast-grep-rules/rule-tests/no-return-value-in-generator-test.yml +22 -0
  421. package/rules/ast-grep-rules/rule-tests/no-secret-in-env-var-name-test.yml +11 -0
  422. package/rules/ast-grep-rules/rule-tests/no-server-bind-wildcard-test.yml +10 -0
  423. package/rules/ast-grep-rules/rule-tests/no-single-promise-in-promise-methods-js-test.yml +10 -0
  424. package/rules/ast-grep-rules/rule-tests/no-single-promise-in-promise-methods-test.yml +10 -0
  425. package/rules/ast-grep-rules/rule-tests/no-singledispatch-on-method-test.yml +25 -0
  426. package/rules/ast-grep-rules/rule-tests/no-sort-without-comparator-test.yml +8 -0
  427. package/rules/ast-grep-rules/rule-tests/no-sql-in-code-js-test.yml +10 -0
  428. package/rules/ast-grep-rules/rule-tests/no-sql-in-code-test.yml +10 -0
  429. package/rules/ast-grep-rules/rule-tests/no-star-imports-test.yml +9 -0
  430. package/rules/ast-grep-rules/rule-tests/no-string-ref-test.yml +8 -0
  431. package/rules/ast-grep-rules/rule-tests/no-template-string-concat-test.yml +14 -0
  432. package/rules/ast-grep-rules/rule-tests/no-testclient-text-without-content-test.yml +10 -0
  433. package/rules/ast-grep-rules/rule-tests/no-throw-string-js-test.yml +10 -0
  434. package/rules/ast-grep-rules/rule-tests/no-throw-string-test.yml +10 -0
  435. package/rules/ast-grep-rules/rule-tests/no-typeof-undefined-js-test.yml +11 -0
  436. package/rules/ast-grep-rules/rule-tests/no-typeof-undefined-test.yml +11 -0
  437. package/rules/ast-grep-rules/rule-tests/no-unimplemented-stub-js-test.yml +10 -0
  438. package/rules/ast-grep-rules/rule-tests/no-unimplemented-stub-test.yml +10 -0
  439. package/rules/ast-grep-rules/rule-tests/no-unnecessary-array-flat-depth-js-test.yml +8 -0
  440. package/rules/ast-grep-rules/rule-tests/no-unnecessary-array-flat-depth-test.yml +8 -0
  441. package/rules/ast-grep-rules/rule-tests/no-unnecessary-state-initializer-test.yml +7 -0
  442. package/rules/ast-grep-rules/rule-tests/no-useless-length-check-js-test.yml +9 -0
  443. package/rules/ast-grep-rules/rule-tests/no-useless-length-check-test.yml +9 -0
  444. package/rules/ast-grep-rules/rule-tests/no-useless-promise-resolve-reject-js-test.yml +8 -0
  445. package/rules/ast-grep-rules/rule-tests/no-useless-promise-resolve-reject-test.yml +8 -0
  446. package/rules/ast-grep-rules/rule-tests/no-useless-rest-spread-js-test.yml +8 -0
  447. package/rules/ast-grep-rules/rule-tests/no-useless-rest-spread-test.yml +8 -0
  448. package/rules/ast-grep-rules/rule-tests/no-uvicorn-non-import-string-test.yml +10 -0
  449. package/rules/ast-grep-rules/rule-tests/no-xxe-vulnerable-xml-parser-test.yml +19 -0
  450. package/rules/ast-grep-rules/rule-tests/no-yield-from-non-iterable-test.yml +11 -0
  451. package/rules/ast-grep-rules/rule-tests/no-yield-return-outside-function-test.yml +19 -0
  452. package/rules/ast-grep-rules/rule-tests/only-strings-in-dunder-all-test.yml +18 -0
  453. package/rules/ast-grep-rules/rule-tests/prefer-array-find-js-test.yml +8 -0
  454. package/rules/ast-grep-rules/rule-tests/prefer-array-find-test.yml +8 -0
  455. package/rules/ast-grep-rules/rule-tests/prefer-array-flat-map-js-test.yml +8 -0
  456. package/rules/ast-grep-rules/rule-tests/prefer-array-flat-map-test.yml +8 -0
  457. package/rules/ast-grep-rules/rule-tests/prefer-array-some-js-test.yml +9 -0
  458. package/rules/ast-grep-rules/rule-tests/prefer-array-some-test.yml +9 -0
  459. package/rules/ast-grep-rules/rule-tests/prefer-at-js-test.yml +8 -0
  460. package/rules/ast-grep-rules/rule-tests/prefer-at-test.yml +8 -0
  461. package/rules/ast-grep-rules/rule-tests/prefer-date-now-js-test.yml +8 -0
  462. package/rules/ast-grep-rules/rule-tests/prefer-date-now-test.yml +8 -0
  463. package/rules/ast-grep-rules/rule-tests/prefer-dom-node-append-js-test.yml +8 -0
  464. package/rules/ast-grep-rules/rule-tests/prefer-dom-node-append-test.yml +8 -0
  465. package/rules/ast-grep-rules/rule-tests/prefer-dom-node-text-content-js-test.yml +9 -0
  466. package/rules/ast-grep-rules/rule-tests/prefer-dom-node-text-content-test.yml +9 -0
  467. package/rules/ast-grep-rules/rule-tests/prefer-keyboard-event-key-js-test.yml +11 -0
  468. package/rules/ast-grep-rules/rule-tests/prefer-keyboard-event-key-test.yml +11 -0
  469. package/rules/ast-grep-rules/rule-tests/prefer-math-min-max-js-test.yml +10 -0
  470. package/rules/ast-grep-rules/rule-tests/prefer-math-min-max-test.yml +10 -0
  471. package/rules/ast-grep-rules/rule-tests/prefer-number-properties-js-test.yml +9 -0
  472. package/rules/ast-grep-rules/rule-tests/prefer-number-properties-test.yml +9 -0
  473. package/rules/ast-grep-rules/rule-tests/prefer-optional-chain-test.yml +9 -0
  474. package/rules/ast-grep-rules/rule-tests/prefer-prototype-methods-js-test.yml +8 -0
  475. package/rules/ast-grep-rules/rule-tests/prefer-prototype-methods-test.yml +8 -0
  476. package/rules/ast-grep-rules/rule-tests/prefer-query-selector-js-test.yml +9 -0
  477. package/rules/ast-grep-rules/rule-tests/prefer-query-selector-test.yml +9 -0
  478. package/rules/ast-grep-rules/rule-tests/prefer-string-slice-js-test.yml +9 -0
  479. package/rules/ast-grep-rules/rule-tests/prefer-string-slice-test.yml +9 -0
  480. package/rules/ast-grep-rules/rule-tests/prefer-string-starts-ends-with-js-test.yml +9 -0
  481. package/rules/ast-grep-rules/rule-tests/prefer-string-starts-ends-with-test.yml +9 -0
  482. package/rules/ast-grep-rules/rule-tests/prefer-string-trim-start-end-js-test.yml +9 -0
  483. package/rules/ast-grep-rules/rule-tests/prefer-string-trim-start-end-test.yml +9 -0
  484. package/rules/ast-grep-rules/rule-tests/prefer-structured-clone-js-test.yml +8 -0
  485. package/rules/ast-grep-rules/rule-tests/prefer-structured-clone-test.yml +8 -0
  486. package/rules/ast-grep-rules/rule-tests/redos-nested-quantifier-test.yml +14 -0
  487. package/rules/ast-grep-rules/rule-tests/redundant-state-test.yml +8 -0
  488. package/rules/ast-grep-rules/rule-tests/redundant-unsafe-function-test.yml +25 -0
  489. package/rules/ast-grep-rules/rule-tests/redundant-usestate-type-test.yml +10 -0
  490. package/rules/ast-grep-rules/rule-tests/require-await-test.yml +9 -0
  491. package/rules/ast-grep-rules/rule-tests/ruby-detect-path-traversal-test.yml +9 -0
  492. package/rules/ast-grep-rules/rule-tests/rust-2024-let-chain-candidate-test.yml +27 -0
  493. package/rules/ast-grep-rules/rule-tests/strict-equality-js-test.yml +9 -0
  494. package/rules/ast-grep-rules/rule-tests/strict-equality-test.yml +9 -0
  495. package/rules/ast-grep-rules/rule-tests/strict-inequality-js-test.yml +9 -0
  496. package/rules/ast-grep-rules/rule-tests/strict-inequality-test.yml +9 -0
  497. package/rules/ast-grep-rules/rule-tests/string-concat-in-loop-test.yml +20 -0
  498. package/rules/ast-grep-rules/rule-tests/switch-without-default-test.yml +16 -0
  499. package/rules/ast-grep-rules/rule-tests/throw-new-error-js-test.yml +10 -0
  500. package/rules/ast-grep-rules/rule-tests/throw-new-error-test.yml +10 -0
  501. package/rules/ast-grep-rules/rule-tests/ts-array-concat-spread-test.yml +9 -0
  502. package/rules/ast-grep-rules/rule-tests/ts-array-every-some-test.yml +8 -0
  503. package/rules/ast-grep-rules/rule-tests/ts-boolean-return-if-else-test.yml +13 -0
  504. package/rules/ast-grep-rules/rule-tests/ts-defensive-null-guard-test.yml +14 -0
  505. package/rules/ast-grep-rules/rule-tests/ts-delete-property-test.yml +8 -0
  506. package/rules/ast-grep-rules/rule-tests/ts-double-negation-test.yml +9 -0
  507. package/rules/ast-grep-rules/rule-tests/ts-function-constructor-test.yml +8 -0
  508. package/rules/ast-grep-rules/rule-tests/ts-in-operator-loop-test.yml +13 -0
  509. package/rules/ast-grep-rules/rule-tests/ts-isnan-check-test.yml +9 -0
  510. package/rules/ast-grep-rules/rule-tests/ts-json-stringify-parse-test.yml +8 -0
  511. package/rules/ast-grep-rules/rule-tests/ts-manual-array-contains-test.yml +13 -0
  512. package/rules/ast-grep-rules/rule-tests/ts-nullish-coalescing-opportunity-test.yml +8 -0
  513. package/rules/ast-grep-rules/rule-tests/ts-object-hasown-check-test.yml +8 -0
  514. package/rules/ast-grep-rules/rule-tests/ts-optional-chaining-default-test.yml +8 -0
  515. package/rules/ast-grep-rules/rule-tests/ts-parseint-no-radix-test.yml +9 -0
  516. package/rules/ast-grep-rules/rule-tests/ts-pointless-bool-cast-test.yml +13 -0
  517. package/rules/ast-grep-rules/rule-tests/ts-redundant-filter-map-test.yml +8 -0
  518. package/rules/ast-grep-rules/rule-tests/ts-slice-copy-test.yml +8 -0
  519. package/rules/ast-grep-rules/rule-tests/ts-string-split-index-test.yml +9 -0
  520. package/rules/ast-grep-rules/rule-tests/ts-unnecessary-array-concat-test.yml +8 -0
  521. package/rules/ast-grep-rules/rule-tests/ts-unnecessary-array-from-test.yml +8 -0
  522. package/rules/ast-grep-rules/rule-tests/ts-unnecessary-bind-test.yml +9 -0
  523. package/rules/ast-grep-rules/rule-tests/ts-unnecessary-else-return-test.yml +13 -0
  524. package/rules/ast-grep-rules/rule-tests/ts-void-zero-test.yml +9 -0
  525. package/rules/ast-grep-rules/rule-tests/ts-while-index-length-test.yml +8 -0
  526. package/rules/ast-grep-rules/rule-tests/unchecked-throwing-call-js-test.yml +13 -0
  527. package/rules/ast-grep-rules/rule-tests/unchecked-throwing-call-python-test.yml +23 -0
  528. package/rules/ast-grep-rules/rule-tests/unchecked-throwing-call-test.yml +13 -0
  529. package/rules/ast-grep-rules/rule-tests/unlock-in-loop-test.yml +19 -0
  530. package/rules/ast-grep-rules/rule-tests/unmarshal-tag-is-dash-test.yml +23 -0
  531. package/rules/ast-grep-rules/rule-tests/unnecessary-react-hook-test.yml +8 -0
  532. package/rules/ast-grep-rules/rule-tests/waitgroup-done-scope-test.yml +20 -0
  533. package/rules/ast-grep-rules/rule-tests/weak-rsa-key-js-test.yml +9 -0
  534. package/rules/ast-grep-rules/rule-tests/weak-rsa-key-test.yml +9 -0
  535. package/rules/ast-grep-rules/rule-tests-disabled/no-method-field-name-collision-test.yml +23 -0
  536. package/rules/ast-grep-rules/rules/array-callback-return-js.yml +17 -10
  537. package/rules/ast-grep-rules/rules/array-callback-return.yml +16 -9
  538. package/rules/ast-grep-rules/rules/avoid-duplicate-export.yml +19 -0
  539. package/rules/ast-grep-rules/rules/defer-in-loop.yml +10 -0
  540. package/rules/ast-grep-rules/rules/find-import-file-without-extension.yml +22 -0
  541. package/rules/ast-grep-rules/rules/go-defer-func-call-antipattern.yml +34 -0
  542. package/rules/ast-grep-rules/rules/go-test-functions.yml +32 -0
  543. package/rules/ast-grep-rules/rules/gorm-find-without-where.yml +26 -0
  544. package/rules/ast-grep-rules/rules/gorm-n-plus-one.yml +16 -0
  545. package/rules/ast-grep-rules/rules/hardcoded-url-js.yml +10 -5
  546. package/rules/ast-grep-rules/rules/hardcoded-url.yml +9 -4
  547. package/rules/ast-grep-rules/rules/jsx-boolean-short-circuit.yml +33 -13
  548. package/rules/ast-grep-rules/rules/jwt-no-verify-js.yml +16 -3
  549. package/rules/ast-grep-rules/rules/jwt-no-verify.yml +15 -2
  550. package/rules/ast-grep-rules/rules/loop-var-capture.yml +42 -0
  551. package/rules/ast-grep-rules/rules/missing-component-decorator.yml +21 -0
  552. package/rules/ast-grep-rules/rules/mutex-unlock-mismatch.yml +14 -0
  553. package/rules/ast-grep-rules/rules/nil-map-assignment.yml +43 -0
  554. package/rules/ast-grep-rules/rules/no-any-type.yml +13 -4
  555. package/rules/ast-grep-rules/rules/no-assert-tuple.yml +24 -0
  556. package/rules/ast-grep-rules/rules/no-aws-access-key-literal.yml +30 -0
  557. package/rules/ast-grep-rules/rules/no-aws-apigateway-no-auth.yml +29 -0
  558. package/rules/ast-grep-rules/rules/no-aws-s3-public-access.yml +28 -0
  559. package/rules/ast-grep-rules/rules/no-bare-except.yml +21 -3
  560. package/rules/ast-grep-rules/rules/no-blank-target-js.yml +17 -6
  561. package/rules/ast-grep-rules/rules/no-boolean-in-except.yml +23 -0
  562. package/rules/ast-grep-rules/rules/no-comparison-to-none.yml +5 -0
  563. package/rules/ast-grep-rules/rules/no-comparison-to-true-false.yml +25 -0
  564. package/rules/ast-grep-rules/rules/no-compile-call.yml +29 -0
  565. package/rules/ast-grep-rules/rules/no-console-except-error-js.yml +20 -0
  566. package/rules/ast-grep-rules/rules/no-console-except-error.yml +20 -0
  567. package/rules/ast-grep-rules/rules/no-db-string-literal-password.yml +44 -0
  568. package/rules/ast-grep-rules/rules/no-demeter-message-chain.yml +25 -0
  569. package/rules/ast-grep-rules/rules/no-dunder-exit-wrong-arity.yml +25 -0
  570. package/rules/ast-grep-rules/rules/no-duplicate-kwarg.yml +26 -0
  571. package/rules/ast-grep-rules/rules/no-except-non-exception.yml +47 -0
  572. package/rules/ast-grep-rules/rules/no-extra-boolean-cast-js.yml +26 -21
  573. package/rules/ast-grep-rules/rules/no-extra-boolean-cast.yml +25 -20
  574. package/rules/ast-grep-rules/rules/no-fastapi-router-prefix-outside-init.yml +29 -0
  575. package/rules/ast-grep-rules/rules/no-flag-argument-js.yml +37 -0
  576. package/rules/ast-grep-rules/rules/no-flag-argument.yml +36 -0
  577. package/rules/ast-grep-rules/rules/no-flask-preprocess-request-ignored.yml +26 -0
  578. package/rules/ast-grep-rules/rules/no-flask-secret-key-literal.yml +36 -0
  579. package/rules/ast-grep-rules/rules/no-flask-sendfile-without-mimetype.yml +42 -0
  580. package/rules/ast-grep-rules/rules/no-global-eval-js.yml +5 -0
  581. package/rules/ast-grep-rules/rules/no-hardcoded-password.yml +42 -0
  582. package/rules/ast-grep-rules/rules/no-html-autoescape-off.yml +25 -0
  583. package/rules/ast-grep-rules/rules/no-http-headers-bracket-access.yml +22 -0
  584. package/rules/ast-grep-rules/rules/no-identity-operator-on-literals.yml +69 -0
  585. package/rules/ast-grep-rules/rules/no-implied-eval-js.yml +8 -5
  586. package/rules/ast-grep-rules/rules/no-implied-eval.yml +7 -4
  587. package/rules/ast-grep-rules/rules/no-init-return.yml +27 -0
  588. package/rules/ast-grep-rules/rules/no-inline-styles.yml +13 -6
  589. package/rules/ast-grep-rules/rules/no-javascript-url-js.yml +8 -4
  590. package/rules/ast-grep-rules/rules/no-javascript-url.yml +7 -3
  591. package/rules/ast-grep-rules/rules/no-jinja2-autoescape-off.yml +24 -0
  592. package/rules/ast-grep-rules/rules/no-marshal-load.yml +24 -0
  593. package/rules/ast-grep-rules/rules/no-mutable-contextvar-default.yml +38 -0
  594. package/rules/ast-grep-rules/rules/no-mutable-default.yml +8 -2
  595. package/rules/ast-grep-rules/rules/no-notimplemented-in-bool.yml +21 -0
  596. package/rules/ast-grep-rules/rules/no-numpy-nan-equality.yml +31 -0
  597. package/rules/ast-grep-rules/rules/no-only-defined-names-in-dunder-all.yml +36 -0
  598. package/rules/ast-grep-rules/rules/no-python-sql-string-concat.yml +37 -0
  599. package/rules/ast-grep-rules/rules/no-raise-stopiteration-in-generator.yml +28 -0
  600. package/rules/ast-grep-rules/rules/no-relative-imports.yml +13 -14
  601. package/rules/ast-grep-rules/rules/no-requests-verify-false.yml +27 -0
  602. package/rules/ast-grep-rules/rules/no-requests-without-timeout.yml +113 -0
  603. package/rules/ast-grep-rules/rules/no-return-value-in-generator.yml +31 -0
  604. package/rules/ast-grep-rules/rules/no-secret-in-env-var-name.yml +37 -0
  605. package/rules/ast-grep-rules/rules/no-server-bind-wildcard.yml +28 -0
  606. package/rules/ast-grep-rules/rules/no-singledispatch-on-method.yml +27 -0
  607. package/rules/ast-grep-rules/rules/no-sql-in-code-js.yml +15 -4
  608. package/rules/ast-grep-rules/rules/no-sql-in-code.yml +14 -3
  609. package/rules/ast-grep-rules/rules/no-string-ref.yml +13 -6
  610. package/rules/ast-grep-rules/rules/no-template-string-concat.yml +21 -0
  611. package/rules/ast-grep-rules/rules/no-testclient-text-without-content.yml +39 -0
  612. package/rules/ast-grep-rules/rules/no-uvicorn-non-import-string.yml +46 -0
  613. package/rules/ast-grep-rules/rules/no-xxe-vulnerable-xml-parser.yml +32 -0
  614. package/rules/ast-grep-rules/rules/no-yield-from-non-iterable.yml +33 -0
  615. package/rules/ast-grep-rules/rules/no-yield-return-outside-function.yml +31 -0
  616. package/rules/ast-grep-rules/rules/only-strings-in-dunder-all.yml +32 -0
  617. package/rules/ast-grep-rules/rules/redundant-unsafe-function.yml +21 -0
  618. package/rules/ast-grep-rules/rules/redundant-usestate-type.yml +15 -0
  619. package/rules/ast-grep-rules/rules/ruby-detect-path-traversal.yml +33 -0
  620. package/rules/ast-grep-rules/rules/rust-2024-let-chain-candidate.yml +56 -0
  621. package/rules/ast-grep-rules/rules/string-concat-in-loop.yml +31 -0
  622. package/rules/ast-grep-rules/rules/ts-array-concat-spread.yml +10 -0
  623. package/rules/ast-grep-rules/rules/ts-array-every-some.yml +22 -0
  624. package/rules/ast-grep-rules/rules/ts-boolean-return-if-else.yml +12 -0
  625. package/rules/ast-grep-rules/rules/ts-defensive-null-guard.yml +12 -0
  626. package/rules/ast-grep-rules/rules/ts-delete-property.yml +10 -0
  627. package/rules/ast-grep-rules/rules/ts-double-negation.yml +10 -0
  628. package/rules/ast-grep-rules/rules/ts-function-constructor.yml +12 -0
  629. package/rules/ast-grep-rules/rules/ts-in-operator-loop.yml +22 -0
  630. package/rules/ast-grep-rules/rules/ts-isnan-check.yml +10 -0
  631. package/rules/ast-grep-rules/rules/ts-json-stringify-parse.yml +17 -0
  632. package/rules/ast-grep-rules/rules/ts-manual-array-contains.yml +25 -0
  633. package/rules/ast-grep-rules/rules/ts-nullish-coalescing-opportunity.yml +20 -0
  634. package/rules/ast-grep-rules/rules/ts-object-hasown-check.yml +9 -0
  635. package/rules/ast-grep-rules/rules/ts-optional-chaining-default.yml +21 -0
  636. package/rules/ast-grep-rules/rules/ts-parseint-no-radix.yml +18 -0
  637. package/rules/ast-grep-rules/rules/ts-pointless-bool-cast.yml +10 -0
  638. package/rules/ast-grep-rules/rules/ts-redundant-filter-map.yml +10 -0
  639. package/rules/ast-grep-rules/rules/ts-slice-copy.yml +11 -0
  640. package/rules/ast-grep-rules/rules/ts-string-split-index.yml +12 -0
  641. package/rules/ast-grep-rules/rules/ts-unnecessary-array-concat.yml +9 -0
  642. package/rules/ast-grep-rules/rules/ts-unnecessary-array-from.yml +9 -0
  643. package/rules/ast-grep-rules/rules/ts-unnecessary-bind.yml +10 -0
  644. package/rules/ast-grep-rules/rules/ts-unnecessary-else-return.yml +19 -0
  645. package/rules/ast-grep-rules/rules/ts-void-zero.yml +10 -0
  646. package/rules/ast-grep-rules/rules/ts-while-index-length.yml +10 -0
  647. package/rules/ast-grep-rules/rules/unlock-in-loop.yml +22 -0
  648. package/rules/ast-grep-rules/rules/unmarshal-tag-is-dash.yml +20 -0
  649. package/rules/ast-grep-rules/rules/unnecessary-react-hook.yml +27 -0
  650. package/rules/ast-grep-rules/rules/waitgroup-done-scope.yml +11 -0
  651. package/rules/ast-grep-rules/rules/weak-rsa-key-js.yml +16 -3
  652. package/rules/ast-grep-rules/rules/weak-rsa-key.yml +15 -2
  653. package/rules/ast-grep-rules/rules-disabled/gorm-unbounded-preload.yml +41 -0
  654. package/rules/ast-grep-rules/rules-disabled/no-method-field-name-collision.yml +42 -0
  655. package/rules/ast-grep-rules/rules-disabled/shadow-err-variable.yml +38 -0
  656. package/rules/rule-catalog.json +1721 -133
  657. package/rules/tree-sitter-queries/python/aws-public-access-policy.yml +68 -0
  658. package/rules/tree-sitter-queries/python/endpoint-204-with-body.yml +62 -0
  659. package/rules/tree-sitter-queries/python/open-invalid-mode.yml +58 -0
  660. package/rules/tree-sitter-queries/python/python-special-method-arity.yml +67 -0
  661. package/rules/tree-sitter-queries/python/python-sql-injection.yml +12 -3
  662. package/rules/tree-sitter-queries/python/python-thread-global-write.yml +6 -0
  663. package/rules/tree-sitter-queries/python/python-unsafe-regex.yml +20 -19
  664. package/rules/tree-sitter-queries/python/slots-assignment-mismatch.yml +73 -0
  665. package/rules/tree-sitter-queries/python/string-format-arity-mismatch.yml +52 -0
  666. package/rules/tree-sitter-queries/{python → python-disabled}/python-print-statement.yml +14 -0
  667. package/skills/lsp-navigation/SKILL.md +4 -0
  668. package/skills/write-ast-grep-rule/SKILL.md +74 -4
  669. package/dist/clients/dispatch/runners/semgrep.js +0 -197
  670. package/dist/clients/secrets-scanner.js +0 -181
  671. package/dist/clients/semgrep-config.js +0 -157
  672. package/rules/ast-grep-rules/slop-patterns.yml +0 -469
package/CHANGELOG.md CHANGED
@@ -2,6 +2,148 @@
2
2
 
3
3
  All notable changes to pi-lens will be documented in this file.
4
4
 
5
+ ## [Unreleased]
6
+
7
+ ### Added
8
+
9
+ ### Changed
10
+
11
+ ### Fixed
12
+
13
+ ## [3.8.61] - 2026-06-25
14
+
15
+ ### Added
16
+
17
+ - **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).
18
+ - **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.
19
+ - **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.
20
+ - **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).
21
+ - **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.
22
+ - **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).
23
+ - **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.)
24
+ - **`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.
25
+ - **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.
26
+ - **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.
27
+ - **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.
28
+ - **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.
29
+ - **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.
30
+
31
+ ### Changed
32
+
33
+ - **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:`.
34
+
35
+ - **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).
36
+
37
+ ### Removed
38
+
39
+ - **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).
40
+ - **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.
41
+
42
+ ### Fixed
43
+
44
+ - **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.)
45
+ - **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.
46
+ - **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.
47
+ - **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.
48
+ - **`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.
49
+ - **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.
50
+
51
+ ## [3.8.60] - 2026-06-21
52
+
53
+ ### Added
54
+
55
+ - **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.
56
+
57
+ ### Fixed
58
+
59
+ - **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`.
60
+
61
+ - **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.
62
+
63
+ - **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**.
64
+
65
+ ### Changed
66
+
67
+ - **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).
68
+
69
+ 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).
70
+
71
+ **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.)*
72
+
73
+ - **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.
74
+
75
+ ### Added
76
+
77
+ - **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.)*
78
+
79
+ - **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.)*
80
+
81
+ - **`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.)*
82
+
83
+ - **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.)*
84
+
85
+ - **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.)*
86
+
87
+ - **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`.
88
+
89
+ ### Fixed
90
+
91
+ - **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).
92
+
93
+ - **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.)*
94
+
95
+ - **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.)*
96
+
97
+ - **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).
98
+
99
+ ## [3.8.53] - 2026-06-16
100
+
101
+ ### Added
102
+
103
+ - **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.)*
104
+
105
+ - **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`.
106
+
107
+ - **Upgrade `vscode-jsonrpc` 8 → 9 (the LSP JSON-RPC transport)** — v9 introduced an `exports` map exposing the Node entry as the `./node` subpath, so the old `vscode-jsonrpc/node.js` file-path import no longer resolves (TS2307). Migrated the one import in `clients/lsp/client.ts` to `vscode-jsonrpc/node`; the API (`createMessageConnection`/`StreamMessageReader`/`StreamMessageWriter`/`MessageConnection`) and the internal `lib/node/ril.js` the error-classifier heuristic checks are unchanged. Verified with a live LSP initialize handshake. Supersedes the lockfile-only dependabot bump, which couldn't carry the required code change (closes #183).
108
+
109
+ - **Pipeline safe-autofix expanded to golangci-lint, detekt, markdownlint, oxlint (refs #209)** — four more fixable linters now apply their safe `--fix`/`--auto-correct` in the pipeline's autofix phase, each gated to **match its lint-policy strategy**: golangci-lint (Go, config-first — closes the gap where Go had no pipeline autofix), detekt (Kotlin, config-first — an alternative to the Windows-broken ktlint #218), markdownlint (smart-default), and oxlint (JS/TS, config-gated, mirroring the eslint→oxlint→biome lint precedence). Added to `AUTOFIX_CAPABILITIES` + `getAutofixPolicyForFile`. A new guard, `autofix-policy-consistency.test.ts`, locks the three hand-coded policy maps together — every autofix-selectable tool must be capability-declared and reachable, and each language's autofix gate must match its lint gate (catching config-first↔smart-default drift; it already caught an oxlint mismatch).
110
+
111
+ - **Tool-smoke harness gained an `--autofix` layer covering the pipeline's safe-autofix phase (refs #209)** — the safe-autofix phase (`runAutofix`, what `runPipeline` invokes) applies fixable linters in fix mode gated by the autofix policy. It **mutates files**, yet was exercised by neither the lint layer (lint-only) nor `--format` (formatters) — the highest-stakes path with no live coverage. `node scripts/smoke-tools.mjs --autofix` drives that exact phase per fixture (a safely-autofixable violation) and asserts the expected tool was policy-selected and applied a fix (`fixedCount > 0`, file changed). Validated end-to-end on the dev box for 11 tools: ruff (F401), biome (useConst), rubocop (spacing), sqlfluff (LT01), rust-clippy (needless_return), dart-analyze (prefer_const_declarations), stylelint (color-hex-length), eslint (semi), golangci-lint (gofmt), markdownlint (MD009), oxlint (no-var). ktlint is blocked by the Windows install bug (#218); detekt is wired + consistency-tested but live-validation needs the detekt CLI + formatting plugin (CI-deferred). `runAutofix` is now exported; the harness git-inits each autofix workspace so VCS-gated fixers (cargo fix) run as they would in a real repo.
112
+
113
+ - **Tool-smoke harness gained a `--format` layer covering the formatter pipeline (refs #209)** — formatters are a wholly separate subsystem (`getFormattersForFile` → `formatFile`, what `runFormatPhase` drives) that the lint-dispatch path the harness exercised never touched, so the formatters had zero live coverage despite mutating files in place (a silently-broken formatter is higher-stakes than a missed lint). `node scripts/smoke-tools.mjs --format` drives that exact entry per fixture: it asserts the expected formatter is **selected** for the file (config-gated formatters ship the config their `detect()` needs — `.prettierrc` / `gleam.toml` / `Gemfile` / `pyproject.toml [tool.black]` / `.cmake-format.yaml`) and that running it actually **reformats** a deliberately mis-formatted-but-valid fixture (`changed === true`). Now covers **28 of the 31 supported formatters** across 32 fixtures, all validated end-to-end on the dev box: biome, prettier, ruff, black, taplo, shfmt, gofmt, rustfmt, dart, zig, mix, gleam, rubocop, standardrb, sqlfluff, csharpier, terraform, fantomas, psscriptanalyzer-format, cmake-format, oxfmt, stylua, ormolu, cljfmt, php-cs-fixer, google-java-format, clang-format (+ ktlint, which the layer caught broken on Windows → #218). Config-gated formatters ship the config their `detect()` requires (stylua.toml / .cljfmt.edn / .php-cs-fixer.php / .editorconfig / Gemfile / pyproject.toml). The remaining 3 — nixfmt, ocamlformat, swiftformat — have no usable Windows toolchain (Nix/opam/Swift) and are left for nightly-CI. Wired into the nightly workflow alongside the tool and `--lsp` layers. (Note: the nightly run exercises whichever formatter tools it can install on the runner; standalone-binary formatters not auto-installed by pi-lens report ⚠ until a setup step is added.)
114
+
115
+ - **Tool-smoke harness now covers eight more toolchain-gated languages (refs #209)** — added live fixtures + harness entries for `zig` (zig-check), `java` (javac), `dart` (dart-analyze), `php` (php-lint), `ruby` (rubocop), `kotlin` (ktlint), `gleam` (gleam-check), and `elixir` (elixir-check), all **validated end-to-end on the Windows dev box** after installing the toolchains (JDK 21, Dart, Ruby 3.4 + MSYS2 devkit, Gleam, Zig, PHP 8.4, Erlang/OTP 29 + Elixir 1.20.1). Each produced a parseable diagnostic on its fixture's known defect. The gleam fixture is a minimal package (`gleam.toml` + `src/`) since `gleam check` compiles the whole project. This batch surfaced two genuinely-broken runners (see Fixed: #215, #216) — exactly the regression class the harness exists to catch.
116
+
117
+ - **Tool-smoke harness language expansion + LSP-install gap fix (refs #209)** — the dispatch tool-smoke fixtures now also install each kind's LSP server (not just the linter), so the lsp runner no longer spuriously `server_error`s for want of an uninstalled server. Added fixtures: `terraform` (tflint tool + terraform-ls LSP, both standalone); toolchain-gated `go` (go-vet), `powershell` (PSScriptAnalyzer), `rust` (rust-clippy tool + rust-analyzer LSP), and `csharp` (dotnet-build) — all four verified end-to-end on this box (Go/Rust/.NET/PowerShell toolchains present; rust-clippy → clippy::len_zero, dotnet-build → CS0029); plus LSP-handshake fixtures for `prisma` (@prisma/language-server — 2 diagnostics) and `php` (intelephense). Confirms the fallback→all fix end-to-end: terraform runs `lsp + tflint` together. The go fixture surfaced #214 (go-vet returns 0 diagnostics in dispatch though `go vet` reports them manually). Harness `--verbose` now prints each failed runner's `failureKind`/message so found-errors aren't misread as crashes.
118
+
119
+ - **LSP handshake layer in the tool-smoke harness (refs #209)** — `scripts/smoke-tools.mjs --lsp` drives the **same production entry the lsp runner uses** (`LSPService.touchFile`, with a generous cold-spawn budget) for each LSP fixture, so a pass means the real server installed, spawned, completed the JSON-RPC initialize handshake, and replied — not a hand-rolled handshake (the trap that false-failed typescript in the dropped smoke-lsp). Verified end-to-end for typescript-language-server, pyright, yaml-language-server, vscode-json-language-server, and bash-language-server (all handshook; yaml/json returned diagnostics). Shares the harness's startup temp-sweep and tears down spawned servers via `LSPService.shutdown()`.
120
+
121
+ ### Fixed
122
+
123
+ - **CI: `tool-discovery.test.ts` is now hermetic — no real GitHub-API fetch** — the `ensureTool force-reinstall` tests asserted on a post-download spawn, which required `installTool`'s real `node:https` GitHub-release fetch; in restricted CI (notably **dependabot PRs**) that fetch fails → 0 spawns → flaky red. `node:https` is now mocked (records the fetch, fails deterministically) and the test asserts the fetch was *attempted* (proves installTool was reached) rather than a network-dependent spawn.
124
+
125
+ - **LSP launch no longer logs scary "candidate failed / npm shim failed / Run npm install" lines when a later candidate succeeds** — `resolveAndLaunch` tries candidates in order (local `node_modules/.bin` → global PATH → managed install); each failure was logged immediately, so the common "no local install, fall back to global" path flooded the logs with failure lines that read as an LSP-availability smell even though the server launched fine. Failures are now **deferred** and surfaced only when *all* candidates fail (the all-failed case stays fully diagnosable). Guard: `resolve-and-launch-fallback.test.ts`.
126
+
127
+ - **ktlint now works on Windows — installer fetches the jar alongside ktlint.bat (closes #218)** — ktlint's Windows asset is `ktlint.bat`, a wrapper that runs `java -jar %~dp0ktlint`; the installer fetched only the `.bat`, so every invocation failed `Unable to access jarfile` (and the lint runner masked it — the error text became a fallback diagnostic that looked like a finding). The github install strategy gained an optional `extraAssets` hook; ktlint declares `["ktlint"]` (the jar) on win32, so both files now land in the managed bin. Verified end-to-end on Windows: ktlint lint emits real diagnostics and ktlint format (`-F`) reformats. Guards in `tool-registry-consistency.test.ts`: any win32 `.bat`/`.cmd` wrapper asset must declare `extraAssets`, plus a ktlint-specific check.
128
+
129
+ - **shfmt no longer nags on every unformatted shell write (closes #211)** — the shfmt runner reported a "not formatted" warning against shfmt's built-in defaults on every `.sh` write, even when the project never opted into shfmt formatting. The format-diff *warning* is now gated on a `.editorconfig` (shfmt's only config source) — out of the box shfmt reports only genuine **parse errors** (always-on, blocking); the formatting warning appears once a project opts in via `.editorconfig`. Guard: `shfmt.test.ts`.
130
+
131
+ - **shellcheck now surfaces `info`-level findings like SC2086 (closes #213)** — with no `.shellcheckrc`, the runner forced `--severity warning`, which dropped `info` findings entirely — including SC2086 (double-quote-to-prevent-globbing), a high-value, commonly-relevant check. Default is now `--severity info` (surfaces SC2086-class findings, mapped non-blocking) while still excluding pure `style` rules to limit noise; projects opt into `style` via `.shellcheckrc`. Guard updated in `shellcheck.test.ts`.
132
+
133
+ - **markdownlint produced 0 diagnostics — parser didn't match modern markdownlint-cli2 output (closes #212)** — `parseMarkdownlintOutput`'s regex expected the rule code immediately after `line[:col]`, but markdownlint-cli2 now emits a **severity token** (`error`/`warning`) in between (`file:1:1 error MD018/… msg`), and some rules carry **multiple** slash-separated names (`MD041/first-line-heading/first-line-h1`). Both made the regex miss every line → silent "succeeded, 0 diagnostics". The severity token is now optional (older/relative output still parses) and multi-segment rule codes are handled. (The issue's original "Windows abs-path glob" diagnosis was wrong — the file lints fine; the parser was the culprit, on every platform with current cli2.) Guard: a markdownlint-cli2-format case in `markdownlint-fixable.test.ts`.
134
+
135
+ - **ESLint autofix never applied fixes — keyed on `fixableErrorCount` from `--fix-dry-run` (closes #220)** — the pipeline's safe-autofix phase (`tryEslintFix`) ran `eslint --fix-dry-run --format json` and decided whether to apply fixes by summing `fixableErrorCount` + `fixableWarningCount`. But `--fix-dry-run` reports the **post-fix** state: when every problem is auto-fixable (the common case), ESLint clears `messages`, sets `fixableErrorCount: 0`, and puts the fixed source in the **`output`** field — so the count was 0 and eslint fixes were **never applied**. Now also treats a dry-run `output` field as a fix signal (apply `--fix` when `fixableCount > 0` *or* any result carries `output`). Guard: `pipeline-eslint-autofix.test.ts`. Found by the #209 `--autofix` layer (eslint v10.5.0).
136
+
137
+ - **`zig-check` never ran: availability probe used `zig --version`, which zig rejects (closes #215)** — the shared `createAvailabilityChecker` hard-coded a `--version` probe, but zig's version subcommand is `zig version` (`zig --version` → `error: unknown command: --version`, exit 1). So the probe always failed and zig-check silently skipped on **every** machine with zig installed. `createAvailabilityChecker` now takes an optional `versionArgs` (default `["--version"]`); zig-check passes `["version"]`. Guard: `runner-helpers.test.ts` asserts the override reaches the spawn. Found by the #209 harness (zig 0.16.0 reported `skipped` despite being on PATH).
138
+
139
+ - **`elixir-check` silently dropped all diagnostics on modern Elixir (closes #216)** — `parseElixirOutput` only understood the legacy diagnostic format, so on Elixir 1.16+ the runner was a no-op. Two bugs: (1) Elixir 1.16+ emits a multi-line "code snippet" format with the location on a trailing `└─ path:line:col` line, several lines after the `error:`/`warning:` header — the parser now forward-scans to that footer while keeping legacy support; (2) `elixirc` reports paths **relative to its cwd**, but the parser resolved them against `process.cwd()` instead of the runner cwd (and compared case-sensitively, breaking on Windows' lowercased drive letter) — `parseElixirOutput` now takes `cwd`, resolves against it, and matches case-insensitively on win32. Guard: `elixir-parser.test.ts` (modern error/warning, cwd-relative paths, legacy format, win32 drive-case). Found by the #209 harness (Elixir 1.20.1/OTP 29 ran clean but produced 0 diagnostics on a known compile error).
140
+
141
+ - **Windows: tools whose path contains a space now run (closes #214)** — `safeSpawnAsync`'s Windows `shell:true` path built the cmd.exe string by escaping only the **args**, not the command, so a tool resolved under a spaced path — e.g. Go at `C:\Program Files\Go\bin\go.exe` — made cmd.exe parse `C:\Program` as the command and fail with `'C:\Program' is not recognized`. This silently broke **any** such tool on Windows (npm/.pi-lens tool paths have no spaces, so it stayed hidden; the #209 harness exposed it via go-vet returning 0 diagnostics). The command is now escaped like the args (`buildWindowsShellCommand`, extracted + unit-tested); `cmdEscapeArg` is a no-op for space-free commands so the previously-working paths are unchanged. Found by the #209 tool-smoke harness; go-vet now reports diagnostics through dispatch.
142
+
143
+ - **`smart-default` linters no longer suppressed by the LSP in fallback dispatch groups (refs #209)** — the primary dispatch group for css/yaml/html/docker/toml/ruby/kotlin paired the `lsp` runner with the language's dedicated linter under `mode:"fallback"`, where the first success wins. Once the language server installed and handshook (now reliable), the LSP succeeded and the linter was **silently suppressed** — dropping rules the generic LSP never emits (yamllint style, stylelint, hadolint best-practices, htmlhint, ktlint, rubocop, taplo). Those linters are classified `smart-default` in tool-policy (designed to run with built-in defaults), and `shell`/`fish`/`powershell`/`prisma` already pair LSP+linter via `mode:"all"` — so this was an inconsistency, not intent. All seven groups are now `mode:"all"`; LSP↔linter duplicate diagnostics remain handled by `suppressLintOverlapsWithLsp` + dedup. A new guard (`tests/clients/dispatch/lsp-linter-coverage.test.ts`) fails if any `smart-default` linter ever sits behind the `lsp` in a fallback group again. Type-checker/compiler fallbacks (jsts lsp+ts-lsp, python lsp+pyright, csharp lsp+dotnet-build, …) are intentionally left as fallback. Tool-smoke harness gained css/html/toml/sql/dockerfile fixtures (+ css/html/docker/toml LSP fixtures) confirming each linter now executes alongside its LSP.
144
+
145
+ - **Wire `markdownlint` and `shfmt` into their dispatch plans — they were registered but never ran (refs #209)** — a new deterministic per-PR guard (`tests/clients/dispatch/dispatch-coverage.test.ts`) cross-checks every registered runner against the static plans (`TOOL_PLANS` ∪ `FULL_LINT_PLANS`) and fails if any runner is wired into no plan (the "markdownlint class": registered + installs + tested, but silently never dispatched) or if a plan references a phantom runner id. It immediately caught `markdownlint` (markdown's write group was only `["spellcheck","vale"]`, though its linter policy already preferred it) and `shfmt` (shell's group omitted it). Both are now in their plans, so `.md` writes get markdownlint structural lint and `.sh` writes get shfmt format-diff + parse-error checks (shfmt is check-only — never auto-applies). The live tool-smoke harness gained a `shell` fixture and confirms all three (markdownlint/shellcheck/shfmt) now execute through the real dispatch path.
146
+
5
147
  ## [3.8.52] - 2026-06-14
6
148
 
7
149
  ### Fixed
@@ -495,11 +637,11 @@ All notable changes to pi-lens will be documented in this file.
495
637
  - **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.
496
638
  - **Fixed `inline_tier: error` typo** on `ts-hallucinated-react-import` and `python-hallucinated-import` (→ `blocking`).
497
639
  - **13 new high-confidence blocking promotions across 5 languages** (all `severity: error`, `inline_tier: blocking`):
498
- - _TypeScript:_ `ts-weak-hash` (`createHash("md5"/"sha1")` — confidence: high)
499
- - _Python:_ `python-command-injection`, `python-sql-injection`, `python-insecure-deserialization`, `python-weak-hash`
500
- - _Go:_ `go-command-injection`, `go-sql-injection`, `go-shared-map-write-goroutine`, `go-weak-hash`
501
- - _Ruby:_ `ruby-weak-hash`
502
- - _Rust:_ `rust-lock-held-across-await`
640
+ - *TypeScript:* `ts-weak-hash` (`createHash("md5"/"sha1")` — confidence: high)
641
+ - *Python:* `python-command-injection`, `python-sql-injection`, `python-insecure-deserialization`, `python-weak-hash`
642
+ - *Go:* `go-command-injection`, `go-sql-injection`, `go-shared-map-write-goroutine`, `go-weak-hash`
643
+ - *Ruby:* `ruby-weak-hash`
644
+ - *Rust:* `rust-lock-held-across-await`
503
645
  - **4 new blocking tree-sitter rules (SonarCloud BLOCKER equivalents)**:
504
646
  - `ts-xss-dom-sink` (S5696) — flags dynamic values assigned to `innerHTML`/`outerHTML` or passed to `document.write()` / `document.writeln()`
505
647
  - `ts-dynamic-require` (S5335) — flags `require()` called with a non-string-literal argument (arbitrary module loading)
@@ -713,7 +855,7 @@ All notable changes to pi-lens will be documented in this file.
713
855
  - **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.
714
856
  - **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.
715
857
  - **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.
716
- - **`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`.
858
+ - **`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`.
717
859
  - **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).
718
860
  - **`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.
719
861
  - **`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.
@@ -1902,6 +2044,7 @@ All runtime-applicable TypeScript ast-grep rules now have JavaScript equivalents
1902
2044
  ### Changed
1903
2045
 
1904
2046
  - **Updated `/lens-tdi` display** — Shows 5 category breakdown with descriptions:
2047
+
1905
2048
  ```
1906
2049
  Debt breakdown:
1907
2050
  Maintainability: 45% (MI-based)
@@ -1910,6 +2053,7 @@ All runtime-applicable TypeScript ast-grep rules now have JavaScript equivalents
1910
2053
  Max Cyclomatic: 10% (worst function)
1911
2054
  Entropy: 5% (code unpredictability)
1912
2055
  ```
2056
+
1913
2057
  - **Extended MetricSnapshot** — Added `maxCyclomatic` and `entropy` fields for historical tracking
1914
2058
 
1915
2059
  ---
@@ -2631,7 +2775,7 @@ Three new lint runners with full test coverage:
2631
2775
 
2632
2776
  ### Changed
2633
2777
 
2634
- - **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.
2778
+ - **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.
2635
2779
  - **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).
2636
2780
  - **Test files excluded from AI slop warnings**: MI/complexity thresholds are inherently low in test files — warnings suppressed for `*.test.ts` / `*.spec.ts`.
2637
2781
  - **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.