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
package/commands/rate.js CHANGED
@@ -4,9 +4,10 @@
4
4
  * Provides a visual scoring breakdown of code quality across multiple dimensions.
5
5
  * Uses existing scan data to calculate scores.
6
6
  */
7
- import * as childProcess from "node:child_process";
8
7
  import * as nodeFs from "node:fs";
9
8
  import * as path from "node:path";
9
+ import { safeSpawn } from "../clients/safe-spawn.js";
10
+ import { EXCLUDED_DIRS, isTestFile } from "../clients/file-utils.js";
10
11
  import { getSourceFiles } from "../clients/scan-utils.js";
11
12
  /**
12
13
  * Run all scans and calculate scores
@@ -69,7 +70,7 @@ export async function gatherScores(targetPath, clients) {
69
70
  let securityScore = 100;
70
71
  const securityIssues = [];
71
72
  let secretsFound = 0;
72
- // Check for secrets in source files
73
+ // Check for secrets in source files (skip test files)
73
74
  const secretPatterns = [
74
75
  { name: "API Key (sk-)", pattern: /sk-[a-zA-Z0-9]{20,}/ },
75
76
  { name: "GitHub Token", pattern: /ghp_[a-zA-Z0-9]{36}/ },
@@ -82,6 +83,9 @@ export async function gatherScores(targetPath, clients) {
82
83
  },
83
84
  ];
84
85
  for (const file of files.slice(0, 100)) {
86
+ // Skip test files
87
+ if (isTestFile(file))
88
+ continue;
85
89
  try {
86
90
  const content = nodeFs.readFileSync(file, "utf-8");
87
91
  for (const line of content.split("\n")) {
@@ -97,8 +101,9 @@ export async function gatherScores(targetPath, clients) {
97
101
  }
98
102
  }
99
103
  }
100
- catch {
104
+ catch (err) {
101
105
  // Skip unreadable files
106
+ void err;
102
107
  }
103
108
  }
104
109
  securityScore = Math.max(0, 100 - secretsFound * 15);
@@ -118,14 +123,7 @@ export async function gatherScores(targetPath, clients) {
118
123
  for (const entry of nodeFs.readdirSync(dir, { withFileTypes: true })) {
119
124
  const full = path.join(dir, entry.name);
120
125
  if (entry.isDirectory()) {
121
- if ([
122
- "node_modules",
123
- ".git",
124
- "dist",
125
- "build",
126
- ".next",
127
- ".pi-lens",
128
- ].includes(entry.name))
126
+ if (EXCLUDED_DIRS.includes(entry.name))
129
127
  continue;
130
128
  scanDir(full);
131
129
  }
@@ -181,10 +179,8 @@ export async function gatherScores(targetPath, clients) {
181
179
  const testIssues = [];
182
180
  // Quick test run
183
181
  try {
184
- const testResult = childProcess.spawnSync("npx", ["vitest", "run", "--reporter=basic"], {
185
- encoding: "utf-8",
182
+ const testResult = safeSpawn("npx", ["vitest", "run", "--reporter=basic"], {
186
183
  timeout: 60000,
187
- shell: true,
188
184
  cwd: targetPath,
189
185
  });
190
186
  if (testResult.status !== 0) {
package/commands/rate.ts CHANGED
@@ -8,10 +8,12 @@
8
8
  import * as childProcess from "node:child_process";
9
9
  import * as nodeFs from "node:fs";
10
10
  import * as path from "node:path";
11
+ import { safeSpawn } from "../clients/safe-spawn.js";
11
12
  import type { ExtensionContext } from "@mariozechner/pi-coding-agent";
12
13
  import type { ArchitectClient } from "../clients/architect-client.js";
13
14
  import type { ComplexityClient } from "../clients/complexity-client.js";
14
15
  import type { KnipClient } from "../clients/knip-client.js";
16
+ import { EXCLUDED_DIRS, isTestFile } from "../clients/file-utils.js";
15
17
  import { getSourceFiles } from "../clients/scan-utils.js";
16
18
  import type { TypeCoverageClient } from "../clients/type-coverage-client.js";
17
19
 
@@ -105,7 +107,7 @@ export async function gatherScores(
105
107
  const securityIssues: string[] = [];
106
108
  let secretsFound = 0;
107
109
 
108
- // Check for secrets in source files
110
+ // Check for secrets in source files (skip test files)
109
111
  const secretPatterns = [
110
112
  { name: "API Key (sk-)", pattern: /sk-[a-zA-Z0-9]{20,}/ },
111
113
  { name: "GitHub Token", pattern: /ghp_[a-zA-Z0-9]{36}/ },
@@ -119,6 +121,8 @@ export async function gatherScores(
119
121
  ];
120
122
 
121
123
  for (const file of files.slice(0, 100)) {
124
+ // Skip test files
125
+ if (isTestFile(file)) continue;
122
126
  try {
123
127
  const content = nodeFs.readFileSync(file, "utf-8");
124
128
  for (const line of content.split("\n")) {
@@ -133,8 +137,9 @@ export async function gatherScores(
133
137
  }
134
138
  }
135
139
  }
136
- } catch {
140
+ } catch (err) {
137
141
  // Skip unreadable files
142
+ void err;
138
143
  }
139
144
  }
140
145
  securityScore = Math.max(0, 100 - secretsFound * 15);
@@ -156,17 +161,7 @@ export async function gatherScores(
156
161
  for (const entry of nodeFs.readdirSync(dir, { withFileTypes: true })) {
157
162
  const full = path.join(dir, entry.name);
158
163
  if (entry.isDirectory()) {
159
- if (
160
- [
161
- "node_modules",
162
- ".git",
163
- "dist",
164
- "build",
165
- ".next",
166
- ".pi-lens",
167
- ].includes(entry.name)
168
- )
169
- continue;
164
+ if (EXCLUDED_DIRS.includes(entry.name)) continue;
170
165
  scanDir(full);
171
166
  } else if (/\.(ts|tsx|js|jsx|py|go|rs)$/.test(entry.name)) {
172
167
  const relPath = path.relative(targetPath, full).replace(/\\/g, "/");
@@ -226,13 +221,11 @@ export async function gatherScores(
226
221
 
227
222
  // Quick test run
228
223
  try {
229
- const testResult = childProcess.spawnSync(
224
+ const testResult = safeSpawn(
230
225
  "npx",
231
226
  ["vitest", "run", "--reporter=basic"],
232
227
  {
233
- encoding: "utf-8",
234
228
  timeout: 60000,
235
- shell: true,
236
229
  cwd: targetPath,
237
230
  },
238
231
  );
@@ -7,7 +7,39 @@
7
7
  # IMPORTANT: Patterns are JavaScript regex syntax. Use single quotes for patterns
8
8
  # containing double quotes, and escape backslashes appropriately.
9
9
 
10
- version: "1.1"
10
+ version: "1.2"
11
+
12
+ # =============================================================================
13
+ # FILE SIZE LIMITS (per file type)
14
+ # =============================================================================
15
+
16
+ # Services: focused, single-purpose modules
17
+ - pattern: "**/services/**/*.ts"
18
+ max_lines: 500
19
+ must_not:
20
+ # TUNED: Was (8+ spaces, 5 lines), now (12+ spaces, 10 lines)
21
+ - pattern: '(?:\s{12,}.*\n){10,}'
22
+ message: "Extreme nesting detected (6+ levels). Refactor into smaller functions."
23
+
24
+ # Clients: can be larger but still bounded
25
+ - pattern: "**/clients/**/*.ts|**/commands/**/*.ts"
26
+ max_lines: 1000
27
+ must_not:
28
+ # TUNED: Was (8+ spaces, 5 lines), now (12+ spaces, 10 lines)
29
+ - pattern: '(?:\s{12,}.*\n){10,}'
30
+ message: "Extreme nesting detected (6+ levels). Refactor into smaller functions."
31
+
32
+ # General limit for other files (higher than before)
33
+ - pattern: "**/*.{ts,tsx,js,jsx,py,go,rs}"
34
+ max_lines: 3000
35
+ must_not:
36
+ # TUNED: Was (8+ spaces, 5 lines), now (12+ spaces, 10 lines) for extreme nesting only
37
+ - pattern: '(?:\s{12,}.*\n){10,}'
38
+ message: "Extreme nesting detected (6+ levels). Refactor into smaller functions."
39
+
40
+ # Test files: more relaxed (structure is different)
41
+ - pattern: "**/*.test.ts|**/*.test.js|**/*.spec.ts|**/*.spec.js"
42
+ max_lines: 5000
11
43
 
12
44
  # =============================================================================
13
45
  # LANGUAGE-AGNOSTIC RULES (The "Universal Truths")
@@ -19,27 +51,33 @@ rules:
19
51
  must_not:
20
52
  - pattern: '[a-zA-Z]:\\(?:Users|Program Files|Windows|Temp)\\[^\\]*'
21
53
  message: "No absolute Windows paths — breaks CI and cross-platform builds."
54
+ fix: "Use path.join(__dirname, 'relative/path') or process.cwd()"
22
55
  - pattern: '/(?:home|Users|usr|etc|var)/[a-zA-Z0-9_-]+/'
23
56
  message: "Potential absolute Unix path detected — use relative paths or path.join()."
57
+ fix: "Use path.join(process.cwd(), 'relative/path') or path.resolve()"
24
58
  - pattern: 'https?://localhost:[0-9]+'
25
59
  message: "No hardcoded localhost URLs — use environment variables or a config service."
60
+ fix: "Use process.env.API_URL || 'http://localhost:3000'"
26
61
 
27
62
  # --- Complexity & Technical Debt ---
28
63
  - pattern: "**/*.{ts,tsx,js,jsx,py,go,rs}"
29
- max_lines: 3000
30
64
  must_not:
31
- - pattern: '(?:\s{8,}.*\n){5,}'
32
- message: "Deep nesting detected (4+ levels). Refactor into smaller functions to reduce cognitive load."
33
65
  - pattern: '(?:(?://|#).*\n){10,}'
34
66
  message: "Large block of commented-out code detected. This is dead code — delete it and rely on Git history."
67
+ fix: "Delete the commented code. Git history preserves it if needed later."
35
68
 
36
69
  # --- Reliability & Fragility ---
37
70
  - pattern: "**/*.{ts,tsx,js,jsx,py,go,rs}"
38
71
  must_not:
39
72
  - pattern: '(?:catch|except)\s*\(?.*?\)?\s*\{\s*\}'
40
73
  message: "No empty catch/except blocks. Swallowing errors makes debugging impossible — at least log the error."
74
+ fix: |
75
+ console.error(`[context] Operation failed:`, err);
76
+ // or: throw err;
77
+ // or: return null;
41
78
  - pattern: '\b(?:password|secret|api_?key|token|private_?key)\b\s*[:=]\s*(?:"|'')[^''"]{8,}(?:"|'')'
42
79
  message: "No hardcoded secrets — use environment variables or a secrets manager."
80
+ fix: "Use process.env.SECRET_NAME and add to .env.example (not .env!)"
43
81
 
44
82
  # =============================================================================
45
83
  # JS/TS-SPECIFIC RULES (Node.js & Frontend)
@@ -50,28 +88,34 @@ rules:
50
88
  must_not:
51
89
  - pattern: ':\s*any\b|as\s+any\b'
52
90
  message: "No 'any' types — use 'unknown' or define a proper interface to maintain type safety."
91
+ fix: |
92
+ // Instead of: x as any
93
+ x as unknown as SpecificType
94
+ // Or define proper interface and use it
53
95
  must:
54
96
  - "Use strict TypeScript mode"
55
97
 
56
98
  # --- Configuration & IO ---
57
- - pattern: "**/services/**/*.ts|**/domain/**/*.ts"
58
- must_not:
59
- - pattern: 'process\.env'
60
- message: "Domain/Service logic must not read env vars directly — inject config via constructor or a config service."
61
- - pattern: 'console\.(log|warn|error)'
62
- message: "Core logic should use a structured logger, not console.log."
99
+ # REMOVED: no process.env rule - extensions and CLI tools need env access
100
+ # If you want this rule for your project, add it to your .pi-lens/architect.yaml:
101
+ # - pattern: "**/services/**/*.ts|**/domain/**/*.ts"
102
+ # must_not:
103
+ # - pattern: 'process\.env'
104
+ # message: "Domain/Service logic must not read env vars directly — inject config."
63
105
 
64
106
  # --- Async Patterns ---
65
- - pattern: "**/*.{ts,tsx,js,jsx}"
66
- must_not:
67
- - pattern: '\.then\('
68
- message: "Prefer async/await over .then() chains for better readability and error handling."
107
+ # DISABLED: .then() rule was too aggressive - flagged all promise usage
108
+ # Only flag in specific contexts (3+ level chains) via tree-sitter instead
109
+ # - pattern: "**/*.{ts,tsx,js,jsx}"
110
+ # must_not:
111
+ # - pattern: '\.then\('
112
+ # message: "Prefer async/await over .then() chains for better readability."
69
113
 
70
114
  # --- Grep-ability & Agent Search ---
71
115
  # Note: 'export default' is acceptable for entry points (index.ts)
72
116
  - pattern: "**/*.{ts,tsx}"
73
117
  must_not:
74
- - pattern: "from\s+['\"]\.\./\.\./\.\./"
118
+ - pattern: "from\\s+['\"]\.\./\.\./\.\./"
75
119
  message: "Avoid deep relative imports (3+ levels) — use absolute imports (@app/...) for agent reasoning."
76
120
 
77
121
  # =============================================================================