pi-lens 2.2.9 → 3.0.0

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 (304) hide show
  1. package/CHANGELOG.md +198 -0
  2. package/README.md +709 -519
  3. package/clients/__tests__/file-time.test.js +216 -0
  4. package/clients/__tests__/file-time.test.ts +276 -0
  5. package/clients/__tests__/format-service.test.js +245 -0
  6. package/clients/__tests__/format-service.test.ts +339 -0
  7. package/clients/__tests__/formatters.test.js +271 -0
  8. package/clients/__tests__/formatters.test.ts +401 -0
  9. package/clients/amain-types.js +164 -0
  10. package/clients/amain-types.ts +165 -0
  11. package/clients/architect-client.js +56 -12
  12. package/clients/architect-client.ts +81 -16
  13. package/clients/ast-grep-client.js +2 -2
  14. package/clients/ast-grep-client.ts +14 -39
  15. package/clients/ast-grep-parser.ts +1 -1
  16. package/clients/ast-grep-rule-manager.js +8 -0
  17. package/clients/ast-grep-rule-manager.ts +10 -1
  18. package/clients/ast-grep-types.js +9 -0
  19. package/clients/ast-grep-types.ts +106 -0
  20. package/clients/auto-loop.js +10 -0
  21. package/clients/auto-loop.ts +14 -1
  22. package/clients/biome-client.js +81 -19
  23. package/clients/biome-client.ts +103 -22
  24. package/clients/bus/bus.js +191 -0
  25. package/clients/bus/bus.ts +251 -0
  26. package/clients/bus/events.js +214 -0
  27. package/clients/bus/events.ts +279 -0
  28. package/clients/bus/index.js +8 -0
  29. package/clients/bus/index.ts +9 -0
  30. package/clients/bus/integration.js +158 -0
  31. package/clients/bus/integration.ts +214 -0
  32. package/clients/complexity-client.js +13 -7
  33. package/clients/complexity-client.ts +13 -7
  34. package/clients/config-validator.js +465 -0
  35. package/clients/config-validator.ts +558 -0
  36. package/clients/dependency-checker.js +4 -10
  37. package/clients/dependency-checker.ts +4 -10
  38. package/clients/dispatch/__tests__/autofix-integration.test.js +245 -0
  39. package/clients/dispatch/__tests__/autofix-integration.test.ts +300 -0
  40. package/clients/dispatch/__tests__/runner-registration.test.js +236 -0
  41. package/clients/dispatch/__tests__/runner-registration.test.ts +282 -0
  42. package/clients/dispatch/bus-dispatcher.js +177 -0
  43. package/clients/dispatch/bus-dispatcher.ts +251 -0
  44. package/clients/dispatch/dispatcher.edge.test.js +82 -0
  45. package/clients/dispatch/dispatcher.edge.test.ts +100 -0
  46. package/clients/dispatch/dispatcher.format.test.js +46 -0
  47. package/clients/dispatch/dispatcher.format.test.ts +58 -0
  48. package/clients/dispatch/dispatcher.inline.test.js +74 -0
  49. package/clients/dispatch/dispatcher.inline.test.ts +93 -0
  50. package/clients/dispatch/dispatcher.js +19 -53
  51. package/clients/dispatch/dispatcher.ts +20 -67
  52. package/clients/dispatch/plan.js +9 -4
  53. package/clients/dispatch/plan.ts +9 -4
  54. package/clients/dispatch/runners/architect.js +21 -7
  55. package/clients/dispatch/runners/architect.test.js +138 -0
  56. package/clients/dispatch/runners/architect.test.ts +162 -0
  57. package/clients/dispatch/runners/architect.ts +22 -7
  58. package/clients/dispatch/runners/ast-grep-napi.js +462 -0
  59. package/clients/dispatch/runners/ast-grep-napi.test.js +111 -0
  60. package/clients/dispatch/runners/ast-grep-napi.test.ts +133 -0
  61. package/clients/dispatch/runners/ast-grep-napi.ts +506 -0
  62. package/clients/dispatch/runners/ast-grep.js +62 -19
  63. package/clients/dispatch/runners/ast-grep.ts +70 -18
  64. package/clients/dispatch/runners/biome.js +29 -53
  65. package/clients/dispatch/runners/biome.ts +29 -63
  66. package/clients/dispatch/runners/config-validation.js +67 -0
  67. package/clients/dispatch/runners/config-validation.ts +82 -0
  68. package/clients/dispatch/runners/go-vet.js +4 -28
  69. package/clients/dispatch/runners/go-vet.ts +4 -32
  70. package/clients/dispatch/runners/index.js +30 -10
  71. package/clients/dispatch/runners/index.ts +30 -10
  72. package/clients/dispatch/runners/oxlint.js +141 -0
  73. package/clients/dispatch/runners/oxlint.test.js +230 -0
  74. package/clients/dispatch/runners/oxlint.test.ts +303 -0
  75. package/clients/dispatch/runners/oxlint.ts +175 -0
  76. package/clients/dispatch/runners/pyright.js +40 -70
  77. package/clients/dispatch/runners/pyright.test.js +16 -2
  78. package/clients/dispatch/runners/pyright.test.ts +14 -2
  79. package/clients/dispatch/runners/pyright.ts +48 -91
  80. package/clients/dispatch/runners/python-slop.js +97 -0
  81. package/clients/dispatch/runners/python-slop.test.js +203 -0
  82. package/clients/dispatch/runners/python-slop.test.ts +298 -0
  83. package/clients/dispatch/runners/python-slop.ts +124 -0
  84. package/clients/dispatch/runners/ruff.js +18 -71
  85. package/clients/dispatch/runners/ruff.ts +19 -79
  86. package/clients/dispatch/runners/rust-clippy.js +28 -32
  87. package/clients/dispatch/runners/rust-clippy.ts +29 -31
  88. package/clients/dispatch/runners/scan_codebase.test.js +89 -0
  89. package/clients/dispatch/runners/scan_codebase.test.ts +105 -0
  90. package/clients/dispatch/runners/shellcheck.js +147 -0
  91. package/clients/dispatch/runners/shellcheck.test.js +98 -0
  92. package/clients/dispatch/runners/shellcheck.test.ts +129 -0
  93. package/clients/dispatch/runners/shellcheck.ts +188 -0
  94. package/clients/dispatch/runners/similarity.js +230 -0
  95. package/clients/dispatch/runners/similarity.ts +339 -0
  96. package/clients/dispatch/runners/spellcheck.js +106 -0
  97. package/clients/dispatch/runners/spellcheck.test.js +158 -0
  98. package/clients/dispatch/runners/spellcheck.test.ts +214 -0
  99. package/clients/dispatch/runners/spellcheck.ts +136 -0
  100. package/clients/dispatch/runners/tree-sitter.js +107 -0
  101. package/clients/dispatch/runners/tree-sitter.ts +135 -0
  102. package/clients/dispatch/runners/ts-lsp.js +104 -33
  103. package/clients/dispatch/runners/ts-lsp.ts +120 -38
  104. package/clients/dispatch/runners/ts-slop.js +113 -0
  105. package/clients/dispatch/runners/ts-slop.test.js +180 -0
  106. package/clients/dispatch/runners/ts-slop.test.ts +230 -0
  107. package/clients/dispatch/runners/ts-slop.ts +142 -0
  108. package/clients/dispatch/runners/utils/diagnostic-parsers.js +134 -0
  109. package/clients/dispatch/runners/utils/diagnostic-parsers.ts +186 -0
  110. package/clients/dispatch/runners/utils/runner-helpers.js +115 -0
  111. package/clients/dispatch/runners/utils/runner-helpers.ts +167 -0
  112. package/clients/dispatch/runners/utils.js +2 -4
  113. package/clients/dispatch/runners/utils.ts +2 -4
  114. package/clients/dispatch/types.ts +1 -1
  115. package/clients/dispatch/utils/format-utils.js +49 -0
  116. package/clients/dispatch/utils/format-utils.ts +60 -0
  117. package/clients/dogfood.test.js +201 -0
  118. package/clients/dogfood.test.ts +269 -0
  119. package/clients/file-time.js +152 -0
  120. package/clients/file-time.ts +208 -0
  121. package/clients/file-utils.js +40 -0
  122. package/clients/file-utils.ts +44 -0
  123. package/clients/fix-scanners.js +10 -20
  124. package/clients/fix-scanners.ts +10 -22
  125. package/clients/format-service.js +172 -0
  126. package/clients/format-service.ts +254 -0
  127. package/clients/formatters.js +435 -0
  128. package/clients/formatters.ts +508 -0
  129. package/clients/go-client.js +5 -14
  130. package/clients/go-client.ts +5 -13
  131. package/clients/installer/index.js +356 -0
  132. package/clients/installer/index.ts +426 -0
  133. package/clients/jscpd-client.js +11 -9
  134. package/clients/jscpd-client.ts +12 -8
  135. package/clients/knip-client.js +3 -7
  136. package/clients/knip-client.ts +3 -6
  137. package/clients/lsp/__tests__/client.test.js +325 -0
  138. package/clients/lsp/__tests__/client.test.ts +434 -0
  139. package/clients/lsp/__tests__/config.test.js +166 -0
  140. package/clients/lsp/__tests__/config.test.ts +209 -0
  141. package/clients/lsp/__tests__/error-recovery.test.js +213 -0
  142. package/clients/lsp/__tests__/error-recovery.test.ts +279 -0
  143. package/clients/lsp/__tests__/integration.test.js +127 -0
  144. package/clients/lsp/__tests__/integration.test.ts +160 -0
  145. package/clients/lsp/__tests__/launch.test.js +260 -0
  146. package/clients/lsp/__tests__/launch.test.ts +329 -0
  147. package/clients/lsp/__tests__/server.test.js +259 -0
  148. package/clients/lsp/__tests__/server.test.ts +332 -0
  149. package/clients/lsp/__tests__/service.test.js +417 -0
  150. package/clients/lsp/__tests__/service.test.ts +499 -0
  151. package/clients/lsp/client.js +235 -0
  152. package/clients/lsp/client.ts +328 -0
  153. package/clients/lsp/config.js +115 -0
  154. package/clients/lsp/config.ts +149 -0
  155. package/clients/lsp/index.js +222 -0
  156. package/clients/lsp/index.ts +280 -0
  157. package/clients/lsp/installer/index.js +391 -0
  158. package/clients/lsp/interactive-install.js +210 -0
  159. package/clients/lsp/interactive-install.ts +251 -0
  160. package/clients/lsp/language.js +170 -0
  161. package/clients/lsp/language.ts +216 -0
  162. package/clients/lsp/launch.js +174 -0
  163. package/clients/lsp/launch.ts +240 -0
  164. package/clients/lsp/lsp/launch.js +116 -0
  165. package/clients/lsp/lsp/server.js +532 -0
  166. package/clients/lsp/lsp-index.js +10 -0
  167. package/clients/lsp/lsp-index.ts +11 -0
  168. package/clients/lsp/path-utils.js +48 -0
  169. package/clients/lsp/path-utils.ts +52 -0
  170. package/clients/lsp/server.js +615 -0
  171. package/clients/lsp/server.ts +800 -0
  172. package/clients/lsp/test-py-spawn/requirements.txt +1 -0
  173. package/clients/lsp/test-py-spawn/test.py +3 -0
  174. package/clients/lsp/test-py-svc/requirements.txt +1 -0
  175. package/clients/lsp/test-py-svc/test.py +3 -0
  176. package/clients/lsp/test-python-project/requirements.txt +1 -0
  177. package/clients/lsp/test-python-project/test.py +5 -0
  178. package/clients/metrics-history.js +2 -2
  179. package/clients/metrics-history.ts +2 -2
  180. package/clients/production-readiness.js +522 -0
  181. package/clients/production-readiness.ts +556 -0
  182. package/clients/project-index.js +255 -0
  183. package/clients/project-index.ts +383 -0
  184. package/clients/project-metadata.js +531 -0
  185. package/clients/project-metadata.ts +624 -0
  186. package/clients/ruff-client.js +56 -16
  187. package/clients/ruff-client.ts +72 -15
  188. package/clients/runner-tracker.js +152 -0
  189. package/clients/runner-tracker.ts +213 -0
  190. package/clients/rust-client.js +4 -11
  191. package/clients/rust-client.ts +5 -11
  192. package/clients/safe-spawn.js +96 -0
  193. package/clients/safe-spawn.ts +128 -0
  194. package/clients/scan-architectural-debt.js +3 -6
  195. package/clients/scan-architectural-debt.ts +3 -6
  196. package/clients/scan-utils.js +5 -20
  197. package/clients/scan-utils.ts +5 -29
  198. package/clients/secrets-scanner.js +3 -17
  199. package/clients/secrets-scanner.ts +4 -20
  200. package/clients/services/__tests__/effect-integration.test.js +86 -0
  201. package/clients/services/__tests__/effect-integration.test.ts +111 -0
  202. package/clients/services/effect-integration.js +194 -0
  203. package/clients/services/effect-integration.ts +268 -0
  204. package/clients/services/index.js +7 -0
  205. package/clients/services/index.ts +8 -0
  206. package/clients/services/runner-service.js +105 -0
  207. package/clients/services/runner-service.ts +179 -0
  208. package/clients/sg-runner.js +87 -13
  209. package/clients/sg-runner.ts +97 -13
  210. package/clients/state-matrix.js +160 -0
  211. package/clients/state-matrix.ts +202 -0
  212. package/clients/subprocess-client.js +10 -9
  213. package/clients/subprocess-client.ts +10 -8
  214. package/clients/test-runner-client.js +3 -7
  215. package/clients/test-runner-client.ts +3 -6
  216. package/clients/tool-availability.js +4 -10
  217. package/clients/tool-availability.ts +4 -9
  218. package/clients/tree-sitter-client.js +564 -0
  219. package/clients/tree-sitter-client.ts +797 -0
  220. package/clients/tree-sitter-query-loader.js +355 -0
  221. package/clients/tree-sitter-query-loader.ts +425 -0
  222. package/clients/type-coverage-client.js +3 -7
  223. package/clients/type-coverage-client.ts +3 -6
  224. package/clients/typescript-client.codefix.test.js +157 -0
  225. package/clients/typescript-client.codefix.test.ts +186 -0
  226. package/clients/typescript-client.js +43 -0
  227. package/clients/typescript-client.ts +98 -0
  228. package/commands/booboo.js +799 -219
  229. package/commands/booboo.ts +1004 -225
  230. package/commands/clients/ast-grep-client.js +250 -0
  231. package/commands/clients/ast-grep-parser.js +86 -0
  232. package/commands/clients/ast-grep-rule-manager.js +91 -0
  233. package/commands/clients/ast-grep-types.js +9 -0
  234. package/commands/clients/biome-client.js +380 -0
  235. package/commands/clients/complexity-client.js +667 -0
  236. package/commands/clients/file-kinds.js +177 -0
  237. package/commands/clients/file-utils.js +40 -0
  238. package/commands/clients/jscpd-client.js +169 -0
  239. package/commands/clients/knip-client.js +211 -0
  240. package/commands/clients/ruff-client.js +297 -0
  241. package/commands/clients/safe-spawn.js +88 -0
  242. package/commands/clients/scan-utils.js +83 -0
  243. package/commands/clients/sg-runner.js +190 -0
  244. package/commands/clients/types.js +11 -0
  245. package/commands/clients/typescript-client.js +505 -0
  246. package/commands/fix-from-booboo.js +398 -0
  247. package/commands/fix-from-booboo.ts +485 -0
  248. package/commands/fix-simplified.js +618 -0
  249. package/commands/fix-simplified.ts +768 -0
  250. package/commands/rate.js +10 -14
  251. package/commands/rate.ts +9 -16
  252. package/default-architect.yaml +59 -15
  253. package/index.ts +342 -429
  254. package/package.json +16 -3
  255. package/rules/ast-grep-rules/rules/empty-catch.yml +38 -13
  256. package/rules/ast-grep-rules/rules/no-array-constructor.yml +1 -0
  257. package/rules/ast-grep-rules/rules/no-debugger.yml +2 -0
  258. package/rules/python-slop-rules/.sgconfig.yml +4 -0
  259. package/rules/python-slop-rules/rules/slop-rules.yml +647 -0
  260. package/rules/tree-sitter-queries/python/bare-except.yml +54 -0
  261. package/rules/tree-sitter-queries/python/eval-exec.yml +50 -0
  262. package/rules/tree-sitter-queries/python/is-vs-equals.yml +60 -0
  263. package/rules/tree-sitter-queries/python/mutable-default-arg.yml +57 -0
  264. package/rules/tree-sitter-queries/python/unreachable-except.yml +60 -0
  265. package/rules/tree-sitter-queries/python/wildcard-import.yml +46 -0
  266. package/rules/tree-sitter-queries/tsx/dangerously-set-inner-html.yml +63 -0
  267. package/rules/tree-sitter-queries/typescript/await-in-loop.yml +56 -0
  268. package/rules/tree-sitter-queries/typescript/console-statement.yml +47 -0
  269. package/rules/tree-sitter-queries/typescript/debugger.yml +47 -0
  270. package/rules/tree-sitter-queries/typescript/deep-nesting.yml +117 -0
  271. package/rules/tree-sitter-queries/typescript/deep-promise-chain.yml +73 -0
  272. package/rules/tree-sitter-queries/typescript/empty-catch.yml +64 -0
  273. package/rules/tree-sitter-queries/typescript/eval.yml +48 -0
  274. package/rules/tree-sitter-queries/typescript/hardcoded-secrets.yml +78 -0
  275. package/rules/tree-sitter-queries/typescript/long-parameter-list.yml +62 -0
  276. package/rules/tree-sitter-queries/typescript/mixed-async-styles.yml +49 -0
  277. package/rules/tree-sitter-queries/typescript/nested-ternary.yml +45 -0
  278. package/rules/ts-slop-rules/.sgconfig.yml +4 -0
  279. package/rules/ts-slop-rules/rules/in-correct-optional-input-type.yml +10 -0
  280. package/rules/ts-slop-rules/rules/jwt-no-verify.yml +13 -0
  281. package/rules/ts-slop-rules/rules/no-architecture-violation.yml +10 -0
  282. package/rules/ts-slop-rules/rules/no-case-declarations.yml +10 -0
  283. package/rules/ts-slop-rules/rules/no-dangerously-set-inner-html.yml +10 -0
  284. package/rules/ts-slop-rules/rules/no-debugger.yml +10 -0
  285. package/rules/ts-slop-rules/rules/no-dupe-args.yml +10 -0
  286. package/rules/ts-slop-rules/rules/no-dupe-class-members.yml +10 -0
  287. package/rules/ts-slop-rules/rules/no-dupe-keys.yml +10 -0
  288. package/rules/ts-slop-rules/rules/no-eval.yml +13 -0
  289. package/rules/ts-slop-rules/rules/no-hardcoded-secrets.yml +12 -0
  290. package/rules/ts-slop-rules/rules/no-implied-eval.yml +12 -0
  291. package/rules/ts-slop-rules/rules/no-inner-html.yml +13 -0
  292. package/rules/ts-slop-rules/rules/no-javascript-url.yml +10 -0
  293. package/rules/ts-slop-rules/rules/no-mutable-default.yml +10 -0
  294. package/rules/ts-slop-rules/rules/no-nested-links.yml +12 -0
  295. package/rules/ts-slop-rules/rules/no-new-symbol.yml +10 -0
  296. package/rules/ts-slop-rules/rules/no-new-wrappers.yml +13 -0
  297. package/rules/ts-slop-rules/rules/no-open-redirect.yml +16 -0
  298. package/rules/ts-slop-rules/rules/slop-rules.yml +455 -0
  299. package/rules/ts-slop-rules/rules/weak-rsa-key.yml +12 -0
  300. package/skills/ast-grep/SKILL.md +182 -0
  301. package/clients/dispatch/runners/secrets.js +0 -109
  302. package/commands/fix.js +0 -244
  303. package/commands/fix.ts +0 -373
  304. package/rules/ast-grep-rules/rules/no-lonely-if.yml +0 -13
@@ -0,0 +1,455 @@
1
+ ---
2
+ # DISABLED: This rule produces false positives for legitimate index-based operations
3
+ # (e.g., matrix calculations, line number tracking)
4
+ # id: ts-for-index-length
5
+ # language: typescript
6
+ # severity: warning
7
+ # message: for (let i = 0; i < arr.length; i++) suggests index juggling; prefer for-of or forEach
8
+ # metadata:
9
+ # weight: 3
10
+ # category: slop
11
+ # rule:
12
+ # kind: for_statement
13
+ # pattern: "for (let $I = 0; $I < $ARR.length; $I++) { $$$ }"
14
+ ---
15
+ id: ts-while-index-length
16
+ language: typescript
17
+ severity: warning
18
+ message: while loop with index < length - consider for-of or array methods
19
+ metadata:
20
+ weight: 3
21
+ category: slop
22
+ rule:
23
+ kind: while_statement
24
+ pattern: "while ($I < $ARR.length) { $$$ }"
25
+ ---
26
+ id: ts-manual-min-max
27
+ language: typescript
28
+ severity: warning
29
+ message: Manual min/max logic - use Math.min() or Math.max()
30
+ metadata:
31
+ weight: 3
32
+ category: slop
33
+ rule:
34
+ kind: if_statement
35
+ any:
36
+ - pattern: "if ($A > $B) { $M = $A; } else { $M = $B; }"
37
+ - pattern: "if ($A < $B) { $M = $A; } else { $M = $B; }"
38
+ ---
39
+ id: ts-array-map-ceremony
40
+ language: typescript
41
+ severity: warning
42
+ message: Array.from(arr) or arr.map(x => x) is unnecessary ceremony - use arr directly
43
+ metadata:
44
+ weight: 2
45
+ category: slop
46
+ rule:
47
+ any:
48
+ - kind: call_expression
49
+ pattern: "Array.from($ARR)"
50
+ not:
51
+ has:
52
+ kind: arguments
53
+ - kind: arrow_function
54
+ pattern: "$ARR.map(x => x)"
55
+ ---
56
+ id: ts-boolean-return-if-else
57
+ language: typescript
58
+ severity: warning
59
+ message: if/else returning true/false - simplify to return the condition directly
60
+ metadata:
61
+ weight: 3
62
+ category: slop
63
+ rule:
64
+ kind: if_statement
65
+ any:
66
+ - pattern: "if ($COND) { return true; } else { return false; }"
67
+ - pattern: "if ($COND) { return false; } else { return true; }"
68
+ ---
69
+ id: ts-json-stringify-parse
70
+ language: typescript
71
+ severity: warning
72
+ message: JSON.parse(JSON.stringify(x)) is noisy; use structuredClone or copy properly
73
+ metadata:
74
+ weight: 3
75
+ category: slop
76
+ rule:
77
+ kind: call_expression
78
+ pattern: "JSON.parse(JSON.stringify($X))"
79
+ ---
80
+ id: ts-pointless-bool-cast
81
+ language: typescript
82
+ severity: warning
83
+ message: Wrapping a condition in Boolean() is redundant ceremony
84
+ metadata:
85
+ weight: 3
86
+ category: slop
87
+ rule:
88
+ kind: if_statement
89
+ pattern: "if (Boolean($COND)) { $$$ }"
90
+ ---
91
+ id: ts-double-negation
92
+ language: typescript
93
+ severity: warning
94
+ message: !!value to coerce boolean - use Boolean(value) or truthiness directly
95
+ metadata:
96
+ weight: 2
97
+ category: slop
98
+ rule:
99
+ kind: unary_expression
100
+ pattern: "!!$X"
101
+ ---
102
+ id: ts-unnecessary-array-concat
103
+ language: typescript
104
+ severity: warning
105
+ message: arr.concat([item]) in loop - use arr.push(item) or spread [...arr, item]
106
+ metadata:
107
+ weight: 3
108
+ category: slop
109
+ rule:
110
+ kind: for_statement
111
+ has:
112
+ kind: block
113
+ has:
114
+ kind: expression_statement
115
+ has:
116
+ kind: call_expression
117
+ pattern: "$ARR.concat([$ITEM])"
118
+ ---
119
+ id: ts-defensive-null-guard
120
+ language: typescript
121
+ severity: warning
122
+ message: if (x === null || x === undefined) return null - overly defensive early guard
123
+ metadata:
124
+ weight: 2
125
+ category: slop
126
+ rule:
127
+ kind: if_statement
128
+ any:
129
+ - pattern: "if ($X === null || $X === undefined) { return null; }"
130
+ - pattern: "if ($X == null) { return null; }"
131
+ ---
132
+ id: ts-optional-chain-opportunity
133
+ language: typescript
134
+ severity: warning
135
+ message: obj && obj.prop && obj.prop.nested - use optional chaining obj?.prop?.nested
136
+ metadata:
137
+ weight: 3
138
+ category: slop
139
+ rule:
140
+ kind: binary_expression
141
+ pattern: "$A && $A.$B && $A.$B.$C"
142
+ ---
143
+ id: ts-explicit-undefined-check
144
+ language: typescript
145
+ severity: warning
146
+ message: typeof x === 'undefined' - use x === undefined or check truthiness
147
+ metadata:
148
+ weight: 2
149
+ category: slop
150
+ rule:
151
+ kind: binary_expression
152
+ pattern: "typeof $X === 'undefined'"
153
+ ---
154
+ id: ts-array-length-check
155
+ language: typescript
156
+ severity: warning
157
+ message: arr.length > 0 - use truthiness if (arr) or arr.length
158
+ metadata:
159
+ weight: 2
160
+ category: slop
161
+ rule:
162
+ kind: binary_expression
163
+ any:
164
+ - pattern: "$ARR.length > 0"
165
+ - pattern: "$ARR.length !== 0"
166
+ - pattern: "$ARR.length >= 1"
167
+ ---
168
+ id: ts-unnecessary-array-from
169
+ language: typescript
170
+ severity: warning
171
+ message: Array.from(iterable) in for-of - iterate directly
172
+ metadata:
173
+ weight: 2
174
+ category: slop
175
+ rule:
176
+ kind: for_of_statement
177
+ has:
178
+ kind: call_expression
179
+ pattern: "Array.from($ITER)"
180
+ ---
181
+ id: ts-redundant-filter-map
182
+ language: typescript
183
+ severity: warning
184
+ message: arr.filter(x => x).map(...) - use flatMap or a single pass
185
+ metadata:
186
+ weight: 3
187
+ category: slop
188
+ rule:
189
+ kind: call_expression
190
+ pattern: "$ARR.filter($F).map($G)"
191
+ ---
192
+ id: ts-unnecessary-ternary-boolean
193
+ language: typescript
194
+ severity: warning
195
+ message: cond ? true : false - use Boolean(cond) or cond directly
196
+ metadata:
197
+ weight: 2
198
+ category: slop
199
+ rule:
200
+ kind: conditional_expression
201
+ any:
202
+ - pattern: "$COND ? true : false"
203
+ - pattern: "$COND ? false : true"
204
+ ---
205
+ id: ts-typeof-equality
206
+ language: typescript
207
+ severity: warning
208
+ message: typeof x === 'string' checks - consider instanceof or proper type guards
209
+ metadata:
210
+ weight: 2
211
+ category: slop
212
+ rule:
213
+ kind: binary_expression
214
+ pattern: "typeof $X === '$TYPE'"
215
+ ---
216
+ id: ts-manual-array-contains
217
+ language: typescript
218
+ severity: warning
219
+ message: arr.indexOf(x) !== -1 - use arr.includes(x)
220
+ metadata:
221
+ weight: 2
222
+ category: slop
223
+ rule:
224
+ kind: binary_expression
225
+ pattern: "$ARR.indexOf($X) !== -1"
226
+ ---
227
+ id: ts-slice-copy
228
+ language: typescript
229
+ severity: warning
230
+ message: arr.slice() to copy - use [...arr] spread
231
+ metadata:
232
+ weight: 2
233
+ category: slop
234
+ rule:
235
+ kind: call_expression
236
+ pattern: "$ARR.slice()"
237
+ not:
238
+ has:
239
+ kind: arguments
240
+ ---
241
+ id: ts-parseint-no-radix
242
+ language: typescript
243
+ severity: warning
244
+ message: parseInt(x) without radix - use parseInt(x, 10)
245
+ metadata:
246
+ weight: 2
247
+ category: slop
248
+ rule:
249
+ kind: call_expression
250
+ all:
251
+ - has:
252
+ kind: identifier
253
+ regex: ^parseInt$
254
+ - has:
255
+ kind: arguments
256
+ not:
257
+ has:
258
+ nthChild:
259
+ position: 2
260
+ ---
261
+ id: ts-isnan-check
262
+ language: typescript
263
+ severity: warning
264
+ message: x !== x to check NaN - use Number.isNaN(x)
265
+ metadata:
266
+ weight: 3
267
+ category: slop
268
+ rule:
269
+ kind: binary_expression
270
+ pattern: "$X !== $X"
271
+ ---
272
+ id: ts-void-zero
273
+ language: typescript
274
+ severity: warning
275
+ message: void 0 for undefined - use undefined directly
276
+ metadata:
277
+ weight: 2
278
+ category: slop
279
+ rule:
280
+ kind: unary_expression
281
+ pattern: "void 0"
282
+ ---
283
+ id: ts-function-constructor
284
+ language: typescript
285
+ severity: warning
286
+ message: new Function() - avoid dynamic code evaluation
287
+ metadata:
288
+ weight: 4
289
+ category: slop
290
+ rule:
291
+ kind: new_expression
292
+ has:
293
+ kind: identifier
294
+ regex: ^Function$
295
+ ---
296
+ id: ts-unnecessary-bind
297
+ language: typescript
298
+ severity: warning
299
+ message: fn.bind(this) in arrow function context - arrow functions capture this lexically
300
+ metadata:
301
+ weight: 2
302
+ category: slop
303
+ rule:
304
+ kind: call_expression
305
+ pattern: "$FN.bind(this)"
306
+ ---
307
+ id: ts-empty-array-check
308
+ language: typescript
309
+ severity: warning
310
+ message: arr.length === 0 - use !arr.length or arr.length (truthiness)
311
+ metadata:
312
+ weight: 2
313
+ category: slop
314
+ rule:
315
+ kind: binary_expression
316
+ pattern: "$ARR.length === 0"
317
+ ---
318
+ id: ts-array-every-some
319
+ language: typescript
320
+ severity: warning
321
+ message: arr.map(x => x.prop).every(Boolean) - use arr.every(x => !!x.prop)
322
+ metadata:
323
+ weight: 3
324
+ category: slop
325
+ rule:
326
+ kind: call_expression
327
+ pattern: "$ARR.map($FN).every(Boolean)"
328
+ ---
329
+ id: ts-string-split-index
330
+ language: typescript
331
+ severity: warning
332
+ message: str.split('.')[1] with magic index - use destructuring or named variables
333
+ metadata:
334
+ weight: 3
335
+ category: slop
336
+ rule:
337
+ kind: element_access_expression
338
+ all:
339
+ - has:
340
+ kind: call_expression
341
+ has:
342
+ kind: property_access_expression
343
+ regex: \.split$
344
+ - has:
345
+ kind: number
346
+ regex: ^[1-9][0-9]*$
347
+ ---
348
+ id: ts-unnecessary-else-return
349
+ language: typescript
350
+ severity: warning
351
+ message: else after return - the else block is redundant
352
+ metadata:
353
+ weight: 2
354
+ category: slop
355
+ rule:
356
+ kind: if_statement
357
+ all:
358
+ - has:
359
+ kind: block
360
+ has:
361
+ kind: return_statement
362
+ - has:
363
+ kind: else_clause
364
+ ---
365
+ id: ts-object-hasown-check
366
+ language: typescript
367
+ severity: warning
368
+ message: obj.hasOwnProperty(key) - use Object.hasOwn(obj, key) or Object.prototype.hasOwnProperty.call
369
+ metadata:
370
+ weight: 2
371
+ category: slop
372
+ rule:
373
+ kind: call_expression
374
+ has:
375
+ kind: property_access_expression
376
+ regex: \.hasOwnProperty$
377
+ ---
378
+ id: ts-delete-property
379
+ language: typescript
380
+ severity: warning
381
+ message: delete obj.prop - consider setting to undefined or restructuring instead
382
+ metadata:
383
+ weight: 3
384
+ category: slop
385
+ rule:
386
+ kind: unary_expression
387
+ pattern: "delete $OBJ.$PROP"
388
+ ---
389
+ id: ts-in-operator-loop
390
+ language: typescript
391
+ severity: warning
392
+ message: for (const key in obj) - use Object.keys/entries/values for safer iteration
393
+ metadata:
394
+ weight: 3
395
+ category: slop
396
+ rule:
397
+ kind: for_in_statement
398
+ not:
399
+ has:
400
+ kind: if_statement
401
+ has:
402
+ kind: call_expression
403
+ pattern: "obj.hasOwnProperty(key)"
404
+ ---
405
+ id: ts-array-concat-spread
406
+ language: typescript
407
+ severity: warning
408
+ message: arr.concat([...items]) - use arr.push(...items) or [...arr, ...items]
409
+ metadata:
410
+ weight: 2
411
+ category: slop
412
+ rule:
413
+ kind: call_expression
414
+ pattern: "$ARR.concat([...$ITEMS])"
415
+ ---
416
+ # DISABLED: This rule has false positives - matches files without Array.isArray()
417
+ # id: ts-unnecessary-array-isarray
418
+ # language: typescript
419
+ # severity: warning
420
+ # message: Array.isArray(arr) check when already known to be array - redundant type check
421
+ # metadata:
422
+ # weight: 2
423
+ # category: slop
424
+ # rule:
425
+ # kind: call_expression
426
+ # pattern: "Array.isArray($X)"
427
+ # inside:
428
+ # kind: if_statement
429
+ # follows:
430
+ # kind: expression_statement
431
+ # has:
432
+ # kind: call_expression
433
+ # pattern: "$X.push"
434
+ ---
435
+ id: ts-nullish-coalescing-opportunity
436
+ language: typescript
437
+ severity: warning
438
+ message: x !== null && x !== undefined ? x : default - use x ?? default
439
+ metadata:
440
+ weight: 3
441
+ category: slop
442
+ rule:
443
+ kind: conditional_expression
444
+ pattern: "$X !== null && $X !== undefined ? $X : $DEFAULT"
445
+ ---
446
+ id: ts-optional-chaining-default
447
+ language: typescript
448
+ severity: warning
449
+ message: obj && obj.prop ? obj.prop : default - use obj?.prop ?? default
450
+ metadata:
451
+ weight: 3
452
+ category: slop
453
+ rule:
454
+ kind: conditional_expression
455
+ pattern: "$OBJ && $OBJ.$PROP ? $OBJ.$PROP : $DEFAULT"
@@ -0,0 +1,12 @@
1
+ ---
2
+ id: ts-weak-rsa-key
3
+ language: TypeScript
4
+ severity: warning
5
+ message: "Weak RSA key size — use at least 2048 bits"
6
+ metadata:
7
+ weight: 4
8
+ category: security
9
+ rule:
10
+ any:
11
+ - pattern: "crypto.generateKeyPairSync('rsa', { modulusLength: $LEN, $$$ })"
12
+ - pattern: "crypto.generateKeyPair('rsa', { modulusLength: $LEN, $$$ }, $$$)"
@@ -0,0 +1,182 @@
1
+ ---
2
+ name: ast-grep
3
+ description: Use when searching or replacing code patterns - use ast-grep instead of text search for semantic accuracy
4
+ ---
5
+
6
+ # AST-Grep Code Search
7
+
8
+ Use `ast_grep_search` and `ast_grep_replace` for semantic code search/replace. ast-grep understands code structure, not just text.
9
+
10
+ ## When to Use
11
+
12
+ - Finding function calls, imports, class methods (structured code)
13
+ - Replacing patterns safely across files
14
+ - Finding "X inside Y" (e.g., console.log inside classes)
15
+ - **Use grep instead for:** comments/strings, URLs, or when ast-grep fails twice
16
+
17
+ ## Golden Rules
18
+
19
+ 1. **Be specific** - Use `fetchMetrics($ARGS)` not `fetchMetrics`
20
+ 2. **Scope it** - Always specify `paths` to relevant files
21
+ 3. **Dry-run first** - Always use `apply: false` (or `ast_grep_search`) before `apply: true`
22
+ 4. **Pattern must be valid code** - `function $NAME(` ❌, `function $NAME($$$PARAMS) { $$$BODY }` ✅
23
+ 5. **Use metavariables** - `$VAR` for single node, `$$$` for multiple; handles whitespace automatically
24
+
25
+ ## Quick Reference
26
+
27
+ ### TypeScript/JavaScript
28
+
29
+ ```typescript
30
+ // Function call
31
+ fetchMetrics($ARGS)
32
+
33
+ // Function definition
34
+ function $NAME($$$PARAMS) { $$$BODY }
35
+
36
+ // Import
37
+ import { $NAMES } from "$PATH"
38
+
39
+ // Nested pattern (async function with await)
40
+ all:
41
+ - kind: function_declaration
42
+ - has:
43
+ pattern: await $EXPR
44
+ stopBy: end
45
+
46
+ // Inside relationship
47
+ pattern: console.log($$$)
48
+ inside:
49
+ kind: method_definition
50
+ stopBy: end
51
+ ```
52
+
53
+ ### Python
54
+
55
+ ```python
56
+ # Function
57
+ def $FUNC($$$ARGS):
58
+ $$$BODY
59
+
60
+ # Class
61
+ class $CLASS($$$BASE):
62
+ $$$BODY
63
+ ```
64
+
65
+ ## Examples
66
+
67
+ ```typescript
68
+ // Step 1: Dry-run (preview changes)
69
+ ast_grep_replace
70
+ pattern: "fetchMetrics($ARGS)"
71
+ rewrite: "collectMetrics($ARGS)"
72
+ lang: typescript
73
+ paths: ["src/"]
74
+ apply: false
75
+
76
+ // Step 2: Apply if preview looks correct
77
+ // apply: true
78
+
79
+ // Find all usages
80
+ ast_grep_search
81
+ pattern: "fetchMetrics($ARGS)"
82
+ lang: typescript
83
+ paths: ["src/"]
84
+ ```
85
+
86
+ ## Common Failures
87
+
88
+ ```typescript
89
+ // ❌ INVALID: Incomplete
90
+ pattern: "function $NAME("
91
+ // ✅ VALID: Complete code
92
+ pattern: "function $NAME($$$PARAMS) { $$$BODY }"
93
+
94
+ // ❌ Won't match spaced variants
95
+ pattern: "const x=1"
96
+ // ✅ Matches any whitespace
97
+ pattern: "const $NAME = $VALUE"
98
+
99
+ // ❌ Regex syntax
100
+ pattern: "console.log(.*)"
101
+ // ✅ Metavariables
102
+ pattern: "console.log($$$ARGS)"
103
+ ```
104
+
105
+ **Fallback:** If pattern fails twice → `grep -rn "pattern" src/`
106
+
107
+ **Debug:** https://ast-grep.github.io/playground.html
108
+
109
+ ## CLI Tips
110
+
111
+ ```bash
112
+ # Test inline rule
113
+ ast-grep scan --inline-rules "rule: {pattern: 'await \$EXPR'}" --stdin
114
+
115
+ # Debug AST (find correct 'kind' values)
116
+ ast-grep run --pattern 'async function ex() {}' --lang javascript --debug-query=cst
117
+
118
+ # Composite: async without try-catch
119
+ ast-grep scan --inline-rules 'rule: {all: [{kind: function_declaration, has: {pattern: await $EXPR, stopBy: end}}, {not: {has: {pattern: try { $$$ } catch, stopBy: end}}}]}' .
120
+ ```
121
+
122
+ **Escape `$` in bash:** `\$` or single quotes `'pattern: "$ARG"'`
123
+
124
+ **Key principle:** For `inside`/`has` rules, always add `stopBy: end`
125
+
126
+ ## Creating YAML Rules
127
+
128
+ For reusable rules, create `.yml` files:
129
+
130
+ ```yaml
131
+ # rules/no-console-in-src.yml
132
+ id: no-console-in-src
133
+ language: javascript
134
+ rule:
135
+ pattern: console.$METHOD($$$ARGS)
136
+ inside:
137
+ kind: class_declaration
138
+ stopBy: end
139
+ message: "Avoid console in classes"
140
+ severity: warning
141
+ ```
142
+
143
+ Run: `ast-grep scan --rule rules/no-console-in-src.yml src/`
144
+
145
+ ### Rule Structure
146
+
147
+ | Field | Purpose |
148
+ |-------|---------|
149
+ | `id` | Unique rule name |
150
+ | `language` | typescript, javascript, python, etc. |
151
+ | `rule` | Pattern or composite logic |
152
+ | `message` | Diagnostic message |
153
+ | `severity` | error, warning, info, hint |
154
+
155
+ ### Rule Types
156
+
157
+ ```yaml
158
+ # Simple pattern
159
+ rule:
160
+ pattern: eval($$$ARGS)
161
+
162
+ # Match by AST node kind
163
+ rule:
164
+ kind: function_declaration
165
+ has:
166
+ pattern: await $EXPR
167
+ stopBy: end
168
+
169
+ # Composite (all/any/not)
170
+ rule:
171
+ all:
172
+ - kind: function_declaration
173
+ - has:
174
+ pattern: await $EXPR
175
+ stopBy: end
176
+ - not:
177
+ has:
178
+ pattern: try { $$$ } catch
179
+ stopBy: end
180
+ ```
181
+
182
+ **Tip:** Test rules in playground before saving to file.