@vibecheckai/cli 3.3.0 → 3.5.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 (170) hide show
  1. package/bin/registry.js +389 -269
  2. package/bin/runners/cli-utils.js +2 -33
  3. package/bin/runners/context/generators/cursor.js +49 -2
  4. package/bin/runners/lib/agent-firewall/learning/learning-engine.js +849 -0
  5. package/bin/runners/lib/analyzers.js +599 -142
  6. package/bin/runners/lib/audit-logger.js +532 -0
  7. package/bin/runners/lib/authority/authorities/architecture.js +364 -0
  8. package/bin/runners/lib/authority/authorities/compliance.js +341 -0
  9. package/bin/runners/lib/authority/authorities/human.js +343 -0
  10. package/bin/runners/lib/authority/authorities/quality.js +420 -0
  11. package/bin/runners/lib/authority/authorities/security.js +228 -0
  12. package/bin/runners/lib/authority/index.js +293 -0
  13. package/bin/runners/lib/authority-badge.js +425 -425
  14. package/bin/runners/lib/bundle/bundle-intelligence.js +846 -0
  15. package/bin/runners/lib/cli-charts.js +368 -0
  16. package/bin/runners/lib/cli-config-display.js +405 -0
  17. package/bin/runners/lib/cli-demo.js +275 -0
  18. package/bin/runners/lib/cli-errors.js +438 -0
  19. package/bin/runners/lib/cli-help-formatter.js +439 -0
  20. package/bin/runners/lib/cli-interactive-menu.js +509 -0
  21. package/bin/runners/lib/cli-prompts.js +441 -0
  22. package/bin/runners/lib/cli-scan-cards.js +362 -0
  23. package/bin/runners/lib/compliance-reporter.js +710 -0
  24. package/bin/runners/lib/conductor/index.js +671 -0
  25. package/bin/runners/lib/easy/README.md +123 -0
  26. package/bin/runners/lib/easy/index.js +140 -0
  27. package/bin/runners/lib/easy/interactive-wizard.js +788 -0
  28. package/bin/runners/lib/easy/one-click-firewall.js +564 -0
  29. package/bin/runners/lib/easy/zero-config-reality.js +714 -0
  30. package/bin/runners/lib/engines/accessibility-engine.js +218 -18
  31. package/bin/runners/lib/engines/api-consistency-engine.js +335 -30
  32. package/bin/runners/lib/engines/async-patterns-engine.js +444 -0
  33. package/bin/runners/lib/engines/bundle-size-engine.js +433 -0
  34. package/bin/runners/lib/engines/confidence-scoring.js +276 -0
  35. package/bin/runners/lib/engines/context-detection.js +264 -0
  36. package/bin/runners/lib/engines/cross-file-analysis-engine.js +292 -27
  37. package/bin/runners/lib/engines/database-patterns-engine.js +429 -0
  38. package/bin/runners/lib/engines/duplicate-code-engine.js +354 -0
  39. package/bin/runners/lib/engines/empty-catch-engine.js +127 -17
  40. package/bin/runners/lib/engines/env-variables-engine.js +458 -0
  41. package/bin/runners/lib/engines/error-handling-engine.js +437 -0
  42. package/bin/runners/lib/engines/false-positive-prevention.js +630 -0
  43. package/bin/runners/lib/engines/framework-adapters/index.js +607 -0
  44. package/bin/runners/lib/engines/framework-detection.js +508 -0
  45. package/bin/runners/lib/engines/import-order-engine.js +429 -0
  46. package/bin/runners/lib/engines/mock-data-engine.js +53 -10
  47. package/bin/runners/lib/engines/naming-conventions-engine.js +544 -0
  48. package/bin/runners/lib/engines/noise-reduction-engine.js +452 -0
  49. package/bin/runners/lib/engines/orchestrator.js +334 -0
  50. package/bin/runners/lib/engines/performance-issues-engine.js +176 -36
  51. package/bin/runners/lib/engines/react-patterns-engine.js +457 -0
  52. package/bin/runners/lib/engines/security-vulnerabilities-engine.js +382 -54
  53. package/bin/runners/lib/engines/type-aware-engine.js +263 -39
  54. package/bin/runners/lib/engines/vibecheck-engines/index.js +122 -13
  55. package/bin/runners/lib/engines/vibecheck-engines/lib/ai-hallucination-engine.js +806 -0
  56. package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +373 -73
  57. package/bin/runners/lib/engines/vibecheck-engines/lib/smart-fix-engine.js +577 -0
  58. package/bin/runners/lib/engines/vibecheck-engines/lib/vibe-score-engine.js +543 -0
  59. package/bin/runners/lib/engines/vibecheck-engines.js +514 -0
  60. package/bin/runners/lib/enhanced-features/index.js +305 -0
  61. package/bin/runners/lib/enhanced-output.js +631 -0
  62. package/bin/runners/lib/enterprise.js +300 -0
  63. package/bin/runners/lib/entitlements-v2.js +161 -478
  64. package/bin/runners/lib/firewall/command-validator.js +351 -0
  65. package/bin/runners/lib/firewall/config.js +341 -0
  66. package/bin/runners/lib/firewall/content-validator.js +519 -0
  67. package/bin/runners/lib/firewall/index.js +101 -0
  68. package/bin/runners/lib/firewall/path-validator.js +256 -0
  69. package/bin/runners/lib/html-proof-report.js +350 -700
  70. package/bin/runners/lib/intelligence/cross-repo-intelligence.js +817 -0
  71. package/bin/runners/lib/mcp-utils.js +425 -0
  72. package/bin/runners/lib/missions/plan.js +46 -6
  73. package/bin/runners/lib/missions/templates.js +232 -0
  74. package/bin/runners/lib/output/index.js +1022 -0
  75. package/bin/runners/lib/policy-engine.js +652 -0
  76. package/bin/runners/lib/polish/autofix/accessibility-fixes.js +333 -0
  77. package/bin/runners/lib/polish/autofix/async-handlers.js +273 -0
  78. package/bin/runners/lib/polish/autofix/dead-code.js +280 -0
  79. package/bin/runners/lib/polish/autofix/imports-optimizer.js +344 -0
  80. package/bin/runners/lib/polish/autofix/index.js +200 -0
  81. package/bin/runners/lib/polish/autofix/remove-consoles.js +209 -0
  82. package/bin/runners/lib/polish/autofix/strengthen-types.js +245 -0
  83. package/bin/runners/lib/polish/backend-checks.js +148 -0
  84. package/bin/runners/lib/polish/documentation-checks.js +111 -0
  85. package/bin/runners/lib/polish/frontend-checks.js +168 -0
  86. package/bin/runners/lib/polish/index.js +71 -0
  87. package/bin/runners/lib/polish/infrastructure-checks.js +131 -0
  88. package/bin/runners/lib/polish/library-detection.js +175 -0
  89. package/bin/runners/lib/polish/performance-checks.js +100 -0
  90. package/bin/runners/lib/polish/security-checks.js +148 -0
  91. package/bin/runners/lib/polish/utils.js +203 -0
  92. package/bin/runners/lib/prompt-builder.js +540 -0
  93. package/bin/runners/lib/proof-certificate.js +634 -0
  94. package/bin/runners/lib/reality/accessibility-audit.js +946 -0
  95. package/bin/runners/lib/reality/api-contract-validator.js +1012 -0
  96. package/bin/runners/lib/reality/chaos-engineering.js +1084 -0
  97. package/bin/runners/lib/reality/performance-tracker.js +1077 -0
  98. package/bin/runners/lib/reality/scenario-generator.js +1404 -0
  99. package/bin/runners/lib/reality/visual-regression.js +852 -0
  100. package/bin/runners/lib/reality-profiler.js +717 -0
  101. package/bin/runners/lib/replay/flight-recorder-viewer.js +1160 -0
  102. package/bin/runners/lib/review/ai-code-review.js +832 -0
  103. package/bin/runners/lib/rules/custom-rule-engine.js +985 -0
  104. package/bin/runners/lib/sbom-generator.js +641 -0
  105. package/bin/runners/lib/scan-output-enhanced.js +512 -0
  106. package/bin/runners/lib/scan-output.js +65 -19
  107. package/bin/runners/lib/security/owasp-scanner.js +939 -0
  108. package/bin/runners/lib/ship-output.js +18 -25
  109. package/bin/runners/lib/terminal-ui.js +113 -1
  110. package/bin/runners/lib/unified-cli-output.js +603 -430
  111. package/bin/runners/lib/upsell.js +90 -338
  112. package/bin/runners/lib/validators/contract-validator.js +283 -0
  113. package/bin/runners/lib/validators/dead-export-detector.js +279 -0
  114. package/bin/runners/lib/validators/dep-audit.js +245 -0
  115. package/bin/runners/lib/validators/env-validator.js +319 -0
  116. package/bin/runners/lib/validators/index.js +120 -0
  117. package/bin/runners/lib/validators/license-checker.js +252 -0
  118. package/bin/runners/lib/validators/route-validator.js +290 -0
  119. package/bin/runners/runAIAgent.js +5 -10
  120. package/bin/runners/runAgent.js +3 -0
  121. package/bin/runners/runApprove.js +1233 -1200
  122. package/bin/runners/runAuth.js +22 -1
  123. package/bin/runners/runAuthority.js +528 -0
  124. package/bin/runners/runCheckpoint.js +4 -24
  125. package/bin/runners/runClassify.js +862 -859
  126. package/bin/runners/runConductor.js +772 -0
  127. package/bin/runners/runContainer.js +366 -0
  128. package/bin/runners/runContext.js +3 -0
  129. package/bin/runners/runDoctor.js +28 -41
  130. package/bin/runners/runEasy.js +410 -0
  131. package/bin/runners/runFirewall.js +3 -0
  132. package/bin/runners/runFirewallHook.js +3 -0
  133. package/bin/runners/runFix.js +76 -66
  134. package/bin/runners/runGuard.js +411 -18
  135. package/bin/runners/runIaC.js +372 -0
  136. package/bin/runners/runInit.js +10 -60
  137. package/bin/runners/runMcp.js +11 -12
  138. package/bin/runners/runPolish.js +240 -64
  139. package/bin/runners/runPromptFirewall.js +5 -12
  140. package/bin/runners/runProve.js +20 -55
  141. package/bin/runners/runReality.js +68 -59
  142. package/bin/runners/runReport.js +31 -5
  143. package/bin/runners/runRuntime.js +5 -8
  144. package/bin/runners/runScan.js +194 -1273
  145. package/bin/runners/runShip.js +695 -47
  146. package/bin/runners/runTruth.js +3 -0
  147. package/bin/runners/runValidate.js +7 -11
  148. package/bin/runners/runVibe.js +791 -0
  149. package/bin/runners/runWatch.js +14 -23
  150. package/bin/vibecheck.js +179 -65
  151. package/mcp-server/index.js +202 -636
  152. package/mcp-server/lib/api-client.cjs +7 -299
  153. package/mcp-server/package.json +1 -1
  154. package/mcp-server/tier-auth.js +175 -574
  155. package/mcp-server/tools-v3.js +800 -505
  156. package/mcp-server/tools.js +495 -0
  157. package/package.json +1 -1
  158. package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +0 -164
  159. package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +0 -291
  160. package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +0 -83
  161. package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +0 -198
  162. package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +0 -275
  163. package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +0 -167
  164. package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +0 -217
  165. package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +0 -140
  166. package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +0 -164
  167. package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +0 -234
  168. package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +0 -217
  169. package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +0 -78
  170. package/mcp-server/index-v1.js +0 -698
@@ -12,6 +12,62 @@ const t = require("@babel/types");
12
12
 
13
13
  const { routeMatches } = require("./claims");
14
14
  const { matcherCoversPath } = require("./auth-truth");
15
+ const {
16
+ getFrameworks,
17
+ hasFramework,
18
+ getFileContext,
19
+ isServerComponent,
20
+ isClientComponent,
21
+ isRouteHandler,
22
+ FRAMEWORKS,
23
+ } = require("./engines/framework-detection");
24
+
25
+ // V6: Bulletproof noise reduction and false positive prevention
26
+ let noiseReduction, falsePositivePrevention;
27
+ try {
28
+ noiseReduction = require("./engines/noise-reduction-engine");
29
+ falsePositivePrevention = require("./engines/false-positive-prevention");
30
+ } catch {
31
+ // Engines not available - continue without them
32
+ }
33
+
34
+ /* ============================================================================
35
+ * STANDARD IGNORE PATTERNS
36
+ * Used by all analyzers to exclude non-production code
37
+ * ========================================================================== */
38
+ const STANDARD_IGNORE_PATTERNS = [
39
+ // Core excludes
40
+ "**/node_modules/**",
41
+ "**/.next/**",
42
+ "**/dist/**",
43
+ "**/build/**",
44
+ "**/*.d.ts",
45
+ "**/*.d.ts.map",
46
+ // Test files
47
+ "**/__tests__/**",
48
+ "**/tests/**",
49
+ "**/*.test.ts",
50
+ "**/*.test.tsx",
51
+ "**/*.test.js",
52
+ "**/*.spec.ts",
53
+ "**/*.spec.tsx",
54
+ "**/*.spec.js",
55
+ "**/fixtures/**",
56
+ // Internal tooling
57
+ "**/mcp-server/**",
58
+ "**/bin/**",
59
+ "**/packages/cli/**",
60
+ // Examples and templates
61
+ "**/examples/**",
62
+ "**/templates/**",
63
+ "**/docs/**",
64
+ // Cache and generated
65
+ "**/.guardrail/**",
66
+ "**/.cursor/**",
67
+ "**/.vibecheck/**",
68
+ "**/coverage/**",
69
+ "**/_archive/**",
70
+ ];
15
71
 
16
72
  /* ============================================================================
17
73
  * WORLD-CLASS INFRA HELPERS
@@ -914,7 +970,7 @@ function findFakeSuccess(repoRoot) {
914
970
  const files = fg.sync(["**/*.{ts,tsx,js,jsx}"], {
915
971
  cwd: repoRoot,
916
972
  absolute: true,
917
- ignore: ["**/node_modules/**", "**/.next/**", "**/dist/**", "**/build/**"],
973
+ ignore: STANDARD_IGNORE_PATTERNS,
918
974
  });
919
975
 
920
976
  for (const fileAbs of files) {
@@ -925,6 +981,21 @@ function findFakeSuccess(repoRoot) {
925
981
  // relevant keywords (toast/push/navigate AND fetch/axios).
926
982
  const hasSuccessUI = /\b(toast|\.push|navigate)\b/.test(code);
927
983
  const hasNetworkCall = /\b(fetch|axios)\b/.test(code);
984
+
985
+ // Enhanced: Also check for TanStack Query / React Query mutations
986
+ // These have built-in error handling via onError callback
987
+ const hasTanstackMutation = /\buseMutation\b/.test(code);
988
+ const hasTRPCMutation = /\.useMutation\b/.test(code);
989
+
990
+ // Skip files that use TanStack Query mutations with onSuccess/onError
991
+ // These are properly handling async state
992
+ if (hasTanstackMutation || hasTRPCMutation) {
993
+ const hasProperCallbacks = /onSuccess\s*:|onError\s*:|onSettled\s*:/.test(code);
994
+ if (hasProperCallbacks) {
995
+ continue; // Properly handled
996
+ }
997
+ }
998
+
928
999
  if (!hasSuccessUI || !hasNetworkCall) {
929
1000
  continue;
930
1001
  }
@@ -1013,18 +1084,58 @@ function findFakeSuccess(repoRoot) {
1013
1084
  * ========================================================================== */
1014
1085
 
1015
1086
  function looksSensitive(pathStr) {
1016
- const p = String(pathStr || "");
1017
- return (
1018
- p.startsWith("/api/admin") ||
1019
- p.startsWith("/api/billing") ||
1020
- p.startsWith("/api/stripe") ||
1021
- p.startsWith("/api/org") ||
1022
- p.startsWith("/api/team") ||
1023
- p.startsWith("/api/account") ||
1024
- p.startsWith("/api/settings") ||
1025
- p.startsWith("/api/users") ||
1026
- p.startsWith("/api/user")
1027
- );
1087
+ const p = String(pathStr || "").toLowerCase();
1088
+
1089
+ // Sensitive path prefixes
1090
+ const sensitivePathPrefixes = [
1091
+ "/api/admin",
1092
+ "/api/billing",
1093
+ "/api/stripe",
1094
+ "/api/org",
1095
+ "/api/team",
1096
+ "/api/account",
1097
+ "/api/settings",
1098
+ "/api/users",
1099
+ "/api/user",
1100
+ "/api/profile",
1101
+ "/api/dashboard",
1102
+ "/api/private",
1103
+ "/api/internal",
1104
+ "/api/manage",
1105
+ "/api/payment",
1106
+ "/api/subscription",
1107
+ "/api/checkout",
1108
+ "/api/webhook", // Webhooks need verification
1109
+ "/api/upload",
1110
+ "/api/delete",
1111
+ "/api/export",
1112
+ "/api/import",
1113
+ ];
1114
+
1115
+ // Sensitive path patterns (regex)
1116
+ const sensitivePathPatterns = [
1117
+ /\/api\/.*\/admin/,
1118
+ /\/api\/.*\/delete/,
1119
+ /\/api\/.*\/edit/,
1120
+ /\/api\/.*\/update/,
1121
+ /\/api\/.*\/create/,
1122
+ /\/api\/.*\/remove/,
1123
+ /\/api\/.*\/modify/,
1124
+ /\/api\/me\b/,
1125
+ /\/api\/\[.*id\]/, // Dynamic user/resource routes
1126
+ ];
1127
+
1128
+ // Check prefixes
1129
+ if (sensitivePathPrefixes.some(prefix => p.startsWith(prefix))) {
1130
+ return true;
1131
+ }
1132
+
1133
+ // Check patterns
1134
+ if (sensitivePathPatterns.some(pattern => pattern.test(p))) {
1135
+ return true;
1136
+ }
1137
+
1138
+ return false;
1028
1139
  }
1029
1140
 
1030
1141
  function hasRouteLevelProtection(routeDef) {
@@ -1037,11 +1148,69 @@ function handlerHasAuthSignal(repoRoot, handlerRel) {
1037
1148
  if (!fs.existsSync(abs)) return false;
1038
1149
  const code = readFileCached(abs);
1039
1150
 
1040
- return (
1041
- /\bgetServerSession\b|\bauth\(\)\b|\bclerk\b|@clerk\/nextjs|\bcreateRouteHandlerClient\b|@supabase/i.test(code) ||
1042
- /\b(jwtVerify|authorization|bearer|verifyToken|verifyJWT)\b/i.test(code) ||
1043
- /\b(isAdmin|adminOnly|permissions|rbac)\b/i.test(code)
1044
- );
1151
+ // Next.js / NextAuth patterns
1152
+ const nextAuthPatterns = [
1153
+ /\bgetServerSession\b/,
1154
+ /\bauth\(\)\b/,
1155
+ /\bgetSession\b/,
1156
+ /\buseSession\b/,
1157
+ /\bgetToken\b/,
1158
+ ];
1159
+
1160
+ // Clerk patterns
1161
+ const clerkPatterns = [
1162
+ /\bclerk\b/i,
1163
+ /@clerk\/nextjs/,
1164
+ /\bauth\(\)\s*\.\s*userId/,
1165
+ /\bcurrentUser\b/,
1166
+ /\bgetAuth\b/,
1167
+ ];
1168
+
1169
+ // Supabase patterns
1170
+ const supabasePatterns = [
1171
+ /\bcreateRouteHandlerClient\b/,
1172
+ /\bcreateServerComponentClient\b/,
1173
+ /\bsupabase\b.*\bauth\b/i,
1174
+ /@supabase/,
1175
+ /\bgetUser\(\)/,
1176
+ ];
1177
+
1178
+ // General auth patterns
1179
+ const generalAuthPatterns = [
1180
+ /\b(jwtVerify|verifyToken|verifyJWT)\b/i,
1181
+ /\bauthorization\b/i,
1182
+ /\bbearer\s+token/i,
1183
+ /\b(isAdmin|adminOnly|permissions|rbac)\b/i,
1184
+ /\bauthenticated\b/i,
1185
+ /\brequireAuth\b/i,
1186
+ /\bprotectedProcedure\b/, // tRPC
1187
+ ];
1188
+
1189
+ // Next.js App Router specific patterns
1190
+ const appRouterPatterns = [
1191
+ /\bcookies\(\)\s*\.\s*get\s*\(\s*['"](?:session|token|auth)/i,
1192
+ /\bheaders\(\)\s*\.\s*get\s*\(\s*['"]authorization/i,
1193
+ /\bNextResponse\.redirect\s*\(.*(?:login|signin|unauthorized)/i,
1194
+ ];
1195
+
1196
+ // tRPC context patterns (context often has auth)
1197
+ const trpcPatterns = [
1198
+ /ctx\.session/,
1199
+ /ctx\.user/,
1200
+ /ctx\.auth/,
1201
+ /\.protectedProcedure/,
1202
+ ];
1203
+
1204
+ const allPatterns = [
1205
+ ...nextAuthPatterns,
1206
+ ...clerkPatterns,
1207
+ ...supabasePatterns,
1208
+ ...generalAuthPatterns,
1209
+ ...appRouterPatterns,
1210
+ ...trpcPatterns,
1211
+ ];
1212
+
1213
+ return allPatterns.some(pattern => pattern.test(code));
1045
1214
  }
1046
1215
 
1047
1216
  function isProtectedByNextMiddleware(truthpack, routePath) {
@@ -1205,7 +1374,7 @@ function findOwnerModeBypass(repoRoot) {
1205
1374
  const files = fg.sync(["**/*.{ts,tsx,js,jsx}"], {
1206
1375
  cwd: repoRoot,
1207
1376
  absolute: true,
1208
- ignore: ["**/node_modules/**", "**/.next/**", "**/dist/**", "**/build/**"],
1377
+ ignore: STANDARD_IGNORE_PATTERNS,
1209
1378
  });
1210
1379
 
1211
1380
  const patterns = [
@@ -1250,17 +1419,7 @@ function findMockData(repoRoot) {
1250
1419
  const files = fg.sync(["**/*.{ts,tsx,js,jsx}"], {
1251
1420
  cwd: repoRoot,
1252
1421
  absolute: true,
1253
- ignore: [
1254
- "**/node_modules/**",
1255
- "**/.next/**",
1256
- "**/dist/**",
1257
- "**/build/**",
1258
- "**/*.test.*",
1259
- "**/*.spec.*",
1260
- "**/tests/**",
1261
- "**/test/**",
1262
- "**/__tests__/**",
1263
- ],
1422
+ ignore: STANDARD_IGNORE_PATTERNS,
1264
1423
  });
1265
1424
 
1266
1425
  for (const fileAbs of files) {
@@ -1311,13 +1470,7 @@ function findTodoFixme(repoRoot) {
1311
1470
  const files = fg.sync(["**/*.{ts,tsx,js,jsx}"], {
1312
1471
  cwd: repoRoot,
1313
1472
  absolute: true,
1314
- ignore: [
1315
- "**/node_modules/**",
1316
- "**/.next/**",
1317
- "**/dist/**",
1318
- "**/build/**",
1319
- "**/*.d.ts",
1320
- ],
1473
+ ignore: STANDARD_IGNORE_PATTERNS,
1321
1474
  });
1322
1475
 
1323
1476
  for (const fileAbs of files) {
@@ -1384,13 +1537,7 @@ function findConsoleLogs(repoRoot) {
1384
1537
  const files = fg.sync(["**/*.{ts,tsx,js,jsx}"], {
1385
1538
  cwd: repoRoot,
1386
1539
  absolute: true,
1387
- ignore: [
1388
- "**/node_modules/**",
1389
- "**/.next/**",
1390
- "**/dist/**",
1391
- "**/build/**",
1392
- "**/*.d.ts",
1393
- ],
1540
+ ignore: STANDARD_IGNORE_PATTERNS,
1394
1541
  });
1395
1542
 
1396
1543
  for (const fileAbs of files) {
@@ -1436,16 +1583,7 @@ function findHardcodedSecrets(repoRoot) {
1436
1583
  const files = fg.sync(["**/*.{ts,tsx,js,jsx,json}"], {
1437
1584
  cwd: repoRoot,
1438
1585
  absolute: true,
1439
- ignore: [
1440
- "**/node_modules/**",
1441
- "**/.next/**",
1442
- "**/dist/**",
1443
- "**/build/**",
1444
- "**/package*.json",
1445
- "**/*.test.*",
1446
- "**/tests/**",
1447
- "**/*.d.ts",
1448
- ],
1586
+ ignore: [...STANDARD_IGNORE_PATTERNS, "**/package*.json"],
1449
1587
  });
1450
1588
 
1451
1589
  for (const fileAbs of files) {
@@ -1502,13 +1640,7 @@ function findDeadCode(repoRoot) {
1502
1640
  const files = fg.sync(["**/*.{ts,tsx,js,jsx}"], {
1503
1641
  cwd: repoRoot,
1504
1642
  absolute: true,
1505
- ignore: [
1506
- "**/node_modules/**",
1507
- "**/.next/**",
1508
- "**/dist/**",
1509
- "**/build/**",
1510
- "**/*.d.ts",
1511
- ],
1643
+ ignore: STANDARD_IGNORE_PATTERNS,
1512
1644
  });
1513
1645
 
1514
1646
  for (const fileAbs of files) {
@@ -1554,13 +1686,7 @@ function findDeprecatedApis(repoRoot) {
1554
1686
  const files = fg.sync(["**/*.{ts,tsx,js,jsx}"], {
1555
1687
  cwd: repoRoot,
1556
1688
  absolute: true,
1557
- ignore: [
1558
- "**/node_modules/**",
1559
- "**/.next/**",
1560
- "**/dist/**",
1561
- "**/build/**",
1562
- "**/*.d.ts",
1563
- ],
1689
+ ignore: STANDARD_IGNORE_PATTERNS,
1564
1690
  });
1565
1691
 
1566
1692
  for (const fileAbs of files) {
@@ -1606,13 +1732,7 @@ function findEmptyCatch(repoRoot) {
1606
1732
  const files = fg.sync(["**/*.{ts,tsx,js,jsx}"], {
1607
1733
  cwd: repoRoot,
1608
1734
  absolute: true,
1609
- ignore: [
1610
- "**/node_modules/**",
1611
- "**/.next/**",
1612
- "**/dist/**",
1613
- "**/build/**",
1614
- "**/*.d.ts",
1615
- ],
1735
+ ignore: STANDARD_IGNORE_PATTERNS,
1616
1736
  });
1617
1737
 
1618
1738
  for (const fileAbs of files) {
@@ -1658,13 +1778,7 @@ function findUnsafeRegex(repoRoot) {
1658
1778
  const files = fg.sync(["**/*.{ts,tsx,js,jsx}"], {
1659
1779
  cwd: repoRoot,
1660
1780
  absolute: true,
1661
- ignore: [
1662
- "**/node_modules/**",
1663
- "**/.next/**",
1664
- "**/dist/**",
1665
- "**/build/**",
1666
- "**/*.d.ts",
1667
- ],
1781
+ ignore: STANDARD_IGNORE_PATTERNS,
1668
1782
  });
1669
1783
 
1670
1784
  for (const fileAbs of files) {
@@ -1712,13 +1826,7 @@ function findSecurityVulnerabilities(repoRoot) {
1712
1826
  const files = fg.sync(["**/*.{ts,tsx,js,jsx}"], {
1713
1827
  cwd: repoRoot,
1714
1828
  absolute: true,
1715
- ignore: [
1716
- "**/node_modules/**",
1717
- "**/.next/**",
1718
- "**/dist/**",
1719
- "**/build/**",
1720
- "**/*.d.ts",
1721
- ],
1829
+ ignore: STANDARD_IGNORE_PATTERNS,
1722
1830
  });
1723
1831
 
1724
1832
  for (const fileAbs of files) {
@@ -1762,13 +1870,7 @@ function findPerformanceIssues(repoRoot) {
1762
1870
  const files = fg.sync(["**/*.{ts,tsx,js,jsx}"], {
1763
1871
  cwd: repoRoot,
1764
1872
  absolute: true,
1765
- ignore: [
1766
- "**/node_modules/**",
1767
- "**/.next/**",
1768
- "**/dist/**",
1769
- "**/build/**",
1770
- "**/*.d.ts",
1771
- ],
1873
+ ignore: STANDARD_IGNORE_PATTERNS,
1772
1874
  });
1773
1875
 
1774
1876
  for (const fileAbs of files) {
@@ -1813,13 +1915,7 @@ function findCodeQualityIssues(repoRoot) {
1813
1915
  const files = fg.sync(["**/*.{ts,tsx,js,jsx}"], {
1814
1916
  cwd: repoRoot,
1815
1917
  absolute: true,
1816
- ignore: [
1817
- "**/node_modules/**",
1818
- "**/.next/**",
1819
- "**/dist/**",
1820
- "**/build/**",
1821
- "**/*.d.ts",
1822
- ],
1918
+ ignore: STANDARD_IGNORE_PATTERNS,
1823
1919
  });
1824
1920
 
1825
1921
  for (const fileAbs of files) {
@@ -1865,16 +1961,7 @@ function findCrossFileIssues(repoRoot) {
1865
1961
  const files = fg.sync(["**/*.{ts,tsx,js,jsx}"], {
1866
1962
  cwd: repoRoot,
1867
1963
  absolute: true,
1868
- ignore: [
1869
- "**/node_modules/**",
1870
- "**/.next/**",
1871
- "**/dist/**",
1872
- "**/build/**",
1873
- "**/*.d.ts",
1874
- "**/*.test.*",
1875
- "**/*.spec.*",
1876
- "**/tests/**",
1877
- ],
1964
+ ignore: STANDARD_IGNORE_PATTERNS,
1878
1965
  });
1879
1966
 
1880
1967
  const engineFindings = analyzeCrossFile(files, repoRoot);
@@ -1909,13 +1996,7 @@ function findTypeSafetyIssues(repoRoot) {
1909
1996
  const files = fg.sync(["**/*.{ts,tsx,js,jsx}"], {
1910
1997
  cwd: repoRoot,
1911
1998
  absolute: true,
1912
- ignore: [
1913
- "**/node_modules/**",
1914
- "**/.next/**",
1915
- "**/dist/**",
1916
- "**/build/**",
1917
- "**/*.d.ts",
1918
- ],
1999
+ ignore: STANDARD_IGNORE_PATTERNS,
1919
2000
  });
1920
2001
 
1921
2002
  for (const fileAbs of files) {
@@ -1959,16 +2040,7 @@ function findAccessibilityIssues(repoRoot) {
1959
2040
  const files = fg.sync(["**/*.{tsx,jsx}"], {
1960
2041
  cwd: repoRoot,
1961
2042
  absolute: true,
1962
- ignore: [
1963
- "**/node_modules/**",
1964
- "**/.next/**",
1965
- "**/dist/**",
1966
- "**/build/**",
1967
- "**/*.d.ts",
1968
- "**/*.test.*",
1969
- "**/*.spec.*",
1970
- "**/tests/**",
1971
- ],
2043
+ ignore: STANDARD_IGNORE_PATTERNS,
1972
2044
  });
1973
2045
 
1974
2046
  for (const fileAbs of files) {
@@ -2012,16 +2084,7 @@ function findAPIConsistencyIssues(repoRoot) {
2012
2084
  const files = fg.sync(["**/*.{ts,tsx,js,jsx}"], {
2013
2085
  cwd: repoRoot,
2014
2086
  absolute: true,
2015
- ignore: [
2016
- "**/node_modules/**",
2017
- "**/.next/**",
2018
- "**/dist/**",
2019
- "**/build/**",
2020
- "**/*.d.ts",
2021
- "**/*.test.*",
2022
- "**/*.spec.*",
2023
- "**/tests/**",
2024
- ],
2087
+ ignore: STANDARD_IGNORE_PATTERNS,
2025
2088
  });
2026
2089
 
2027
2090
  for (const fileAbs of files) {
@@ -2058,14 +2121,397 @@ function findAPIConsistencyIssues(repoRoot) {
2058
2121
  return findings;
2059
2122
  }
2060
2123
 
2124
+ /* ============================================================================
2125
+ * REACT PATTERNS ANALYZER
2126
+ * Only runs on .tsx/.jsx files for performance
2127
+ * ========================================================================== */
2128
+
2129
+ function findReactPatternIssues(repoRoot) {
2130
+ const { analyzeReactPatterns } = require("./engines/react-patterns-engine");
2131
+ const findings = [];
2132
+
2133
+ // Only scan React files for performance
2134
+ const files = fg.sync(["**/*.{tsx,jsx}"], {
2135
+ cwd: repoRoot,
2136
+ absolute: true,
2137
+ ignore: STANDARD_IGNORE_PATTERNS,
2138
+ });
2139
+
2140
+ for (const fileAbs of files) {
2141
+ try {
2142
+ const code = readFileCached(fileAbs);
2143
+ const fileRel = path.relative(repoRoot, fileAbs).replace(/\\/g, "/");
2144
+
2145
+ const engineFindings = analyzeReactPatterns(code, fileRel);
2146
+
2147
+ // Only include BLOCK and WARN severity for performance
2148
+ for (const finding of engineFindings) {
2149
+ if (finding.severity === "INFO") continue;
2150
+
2151
+ findings.push({
2152
+ id: stableId("F_REACT", `${fileRel}:${finding.type}:${finding.line}`),
2153
+ severity: finding.severity,
2154
+ category: finding.category || "ReactPatterns",
2155
+ title: finding.title,
2156
+ message: finding.message,
2157
+ file: finding.file,
2158
+ line: finding.line,
2159
+ why: "React anti-patterns can cause bugs, performance issues, and maintenance problems.",
2160
+ confidence: finding.confidence,
2161
+ evidence: [{ file: fileRel, reason: finding.title, line: finding.line }],
2162
+ fixHints: [finding.fixHint].filter(Boolean),
2163
+ });
2164
+ }
2165
+ } catch (err) {
2166
+ continue;
2167
+ }
2168
+ }
2169
+
2170
+ return findings;
2171
+ }
2172
+
2173
+ /* ============================================================================
2174
+ * ERROR HANDLING ANALYZER
2175
+ * Checks error handling patterns across all JS/TS files
2176
+ * ========================================================================== */
2177
+
2178
+ function findErrorHandlingIssues(repoRoot) {
2179
+ const { analyzeErrorHandling } = require("./engines/error-handling-engine");
2180
+ const findings = [];
2181
+ const files = fg.sync(["**/*.{ts,tsx,js,jsx}"], {
2182
+ cwd: repoRoot,
2183
+ absolute: true,
2184
+ ignore: STANDARD_IGNORE_PATTERNS,
2185
+ });
2186
+
2187
+ for (const fileAbs of files) {
2188
+ try {
2189
+ const code = readFileCached(fileAbs);
2190
+ const fileRel = path.relative(repoRoot, fileAbs).replace(/\\/g, "/");
2191
+
2192
+ const engineFindings = analyzeErrorHandling(code, fileRel);
2193
+
2194
+ // Only include BLOCK and WARN severity
2195
+ for (const finding of engineFindings) {
2196
+ if (finding.severity === "INFO") continue;
2197
+
2198
+ findings.push({
2199
+ id: stableId("F_ERROR", `${fileRel}:${finding.type}:${finding.line}`),
2200
+ severity: finding.severity,
2201
+ category: finding.category || "ErrorHandling",
2202
+ title: finding.title,
2203
+ message: finding.message,
2204
+ file: finding.file,
2205
+ line: finding.line,
2206
+ why: "Poor error handling leads to silent failures, security issues, and hard-to-debug problems.",
2207
+ confidence: finding.confidence,
2208
+ evidence: [{ file: fileRel, reason: finding.title, line: finding.line }],
2209
+ fixHints: [finding.fixHint].filter(Boolean),
2210
+ });
2211
+ }
2212
+ } catch (err) {
2213
+ continue;
2214
+ }
2215
+ }
2216
+
2217
+ return findings;
2218
+ }
2219
+
2220
+ /* ============================================================================
2221
+ * DATABASE PATTERNS ANALYZER
2222
+ * Only runs when ORM usage is detected (Prisma, Drizzle, etc.)
2223
+ * ========================================================================== */
2224
+
2225
+ function findDatabasePatternIssues(repoRoot) {
2226
+ const { analyzeDatabasePatterns, detectORM } = require("./engines/database-patterns-engine");
2227
+ const findings = [];
2228
+
2229
+ // Quick check: only run if an ORM is likely in use
2230
+ const packageJsonPath = path.join(repoRoot, "package.json");
2231
+ let hasORM = false;
2232
+
2233
+ try {
2234
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
2235
+ const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
2236
+ const ormPackages = ["@prisma/client", "drizzle-orm", "typeorm", "sequelize", "mongoose", "knex"];
2237
+ hasORM = ormPackages.some(pkg => deps[pkg]);
2238
+ } catch (err) {
2239
+ // No package.json or can't read - check files for ORM patterns
2240
+ hasORM = true; // Fall back to checking files
2241
+ }
2242
+
2243
+ if (!hasORM) return findings;
2244
+
2245
+ const files = fg.sync(["**/*.{ts,tsx,js,jsx}"], {
2246
+ cwd: repoRoot,
2247
+ absolute: true,
2248
+ ignore: STANDARD_IGNORE_PATTERNS,
2249
+ });
2250
+
2251
+ for (const fileAbs of files) {
2252
+ try {
2253
+ const code = readFileCached(fileAbs);
2254
+ const fileRel = path.relative(repoRoot, fileAbs).replace(/\\/g, "/");
2255
+
2256
+ // Skip files without ORM imports for performance
2257
+ const orm = detectORM(code);
2258
+ if (!orm) continue;
2259
+
2260
+ const engineFindings = analyzeDatabasePatterns(code, fileRel);
2261
+
2262
+ // Only include BLOCK and WARN severity
2263
+ for (const finding of engineFindings) {
2264
+ if (finding.severity === "INFO") continue;
2265
+
2266
+ findings.push({
2267
+ id: stableId("F_DB", `${fileRel}:${finding.type}:${finding.line}`),
2268
+ severity: finding.severity,
2269
+ category: finding.category || "DatabasePatterns",
2270
+ title: finding.title,
2271
+ message: finding.message,
2272
+ file: finding.file,
2273
+ line: finding.line,
2274
+ why: "Database anti-patterns cause performance issues, data integrity problems, and security vulnerabilities.",
2275
+ confidence: finding.confidence,
2276
+ evidence: [{ file: fileRel, reason: finding.title, line: finding.line }],
2277
+ fixHints: [finding.fixHint].filter(Boolean),
2278
+ });
2279
+ }
2280
+ } catch (err) {
2281
+ continue;
2282
+ }
2283
+ }
2284
+
2285
+ return findings;
2286
+ }
2287
+
2288
+ /* ============================================================================
2289
+ * ASYNC PATTERNS ANALYZER
2290
+ * Detects Promise and async/await anti-patterns
2291
+ * ========================================================================== */
2292
+
2293
+ function findAsyncPatternIssues(repoRoot) {
2294
+ const engines = require("./engines/vibecheck-engines");
2295
+ if (!engines.analyzeAsyncPatterns) return [];
2296
+
2297
+ const findings = [];
2298
+ const files = fg.sync(["**/*.{ts,tsx,js,jsx}"], {
2299
+ cwd: repoRoot,
2300
+ absolute: true,
2301
+ ignore: STANDARD_IGNORE_PATTERNS,
2302
+ });
2303
+
2304
+ for (const fileAbs of files) {
2305
+ try {
2306
+ const code = readFileCached(fileAbs);
2307
+ const fileRel = path.relative(repoRoot, fileAbs).replace(/\\/g, "/");
2308
+
2309
+ const engineFindings = engines.analyzeAsyncPatterns(code, fileRel);
2310
+
2311
+ // Only include BLOCK and WARN severity
2312
+ for (const finding of engineFindings) {
2313
+ if (finding.severity === "INFO") continue;
2314
+
2315
+ findings.push({
2316
+ id: stableId("F_ASYNC", `${fileRel}:${finding.type}:${finding.line}`),
2317
+ severity: finding.severity,
2318
+ category: finding.category || "AsyncPatterns",
2319
+ title: finding.title,
2320
+ message: finding.message,
2321
+ file: finding.file,
2322
+ line: finding.line,
2323
+ why: "Async anti-patterns cause race conditions, memory leaks, and hard-to-debug failures.",
2324
+ confidence: finding.confidence,
2325
+ evidence: [{ file: fileRel, reason: finding.title, line: finding.line }],
2326
+ fixHints: [finding.fixHint].filter(Boolean),
2327
+ });
2328
+ }
2329
+ } catch (err) {
2330
+ continue;
2331
+ }
2332
+ }
2333
+
2334
+ return findings;
2335
+ }
2336
+
2337
+ /* ============================================================================
2338
+ * BUNDLE SIZE ANALYZER
2339
+ * Only runs on client-side code to detect heavy imports
2340
+ * ========================================================================== */
2341
+
2342
+ function findBundleSizeIssues(repoRoot) {
2343
+ const engines = require("./engines/vibecheck-engines");
2344
+ if (!engines.bundleSizeEngine?.analyzeBundleSize) return [];
2345
+
2346
+ const findings = [];
2347
+
2348
+ // Focus on likely client-side code paths
2349
+ const files = fg.sync([
2350
+ "**/app/**/*.{ts,tsx,js,jsx}",
2351
+ "**/pages/**/*.{ts,tsx,js,jsx}",
2352
+ "**/src/**/*.{ts,tsx,js,jsx}",
2353
+ "**/components/**/*.{ts,tsx,js,jsx}",
2354
+ ], {
2355
+ cwd: repoRoot,
2356
+ absolute: true,
2357
+ ignore: [
2358
+ ...STANDARD_IGNORE_PATTERNS,
2359
+ "**/api/**", // Skip API routes (server-side)
2360
+ "**/server/**",
2361
+ "**/lib/server/**",
2362
+ ],
2363
+ });
2364
+
2365
+ for (const fileAbs of files) {
2366
+ try {
2367
+ const code = readFileCached(fileAbs);
2368
+ const fileRel = path.relative(repoRoot, fileAbs).replace(/\\/g, "/");
2369
+
2370
+ const engineFindings = engines.bundleSizeEngine.analyzeBundleSize(code, fileRel);
2371
+
2372
+ // Only include BLOCK and WARN severity
2373
+ for (const finding of engineFindings) {
2374
+ if (finding.severity === "INFO") continue;
2375
+
2376
+ findings.push({
2377
+ id: stableId("F_BUNDLE", `${fileRel}:${finding.type}:${finding.line}`),
2378
+ severity: finding.severity,
2379
+ category: finding.category || "BundleSize",
2380
+ title: finding.title,
2381
+ message: finding.message,
2382
+ file: finding.file,
2383
+ line: finding.line,
2384
+ why: "Large bundles slow down page load and hurt user experience.",
2385
+ confidence: finding.confidence,
2386
+ evidence: [{ file: fileRel, reason: finding.title, line: finding.line }],
2387
+ fixHints: [finding.fixHint].filter(Boolean),
2388
+ });
2389
+ }
2390
+ } catch (err) {
2391
+ continue;
2392
+ }
2393
+ }
2394
+
2395
+ return findings;
2396
+ }
2397
+
2398
+ /* ============================================================================
2399
+ * V6: BULLETPROOF FINDINGS FILTER
2400
+ * Applies noise reduction and false positive prevention to any findings array
2401
+ * ========================================================================== */
2402
+
2403
+ /**
2404
+ * Apply bulletproof filtering to findings
2405
+ * @param {Array} findings - Raw findings from analyzers
2406
+ * @param {Object} options - Configuration options
2407
+ * @returns {Object} { findings, stats }
2408
+ */
2409
+ function bulletproofFindings(findings, options = {}) {
2410
+ const {
2411
+ projectPath = ".",
2412
+ projectStats = {},
2413
+ config = {},
2414
+ minConfidence = 0.4,
2415
+ minQualityScore = 0.35,
2416
+ verbose = false,
2417
+ } = options;
2418
+
2419
+ let processed = [...findings];
2420
+ const stats = {
2421
+ input: findings.length,
2422
+ afterFalsePositiveFilter: 0,
2423
+ afterNoiseReduction: 0,
2424
+ output: 0,
2425
+ };
2426
+
2427
+ // Step 1: Filter false positives
2428
+ if (falsePositivePrevention?.filterFalsePositives) {
2429
+ const fpResult = falsePositivePrevention.filterFalsePositives(processed, {
2430
+ projectPath,
2431
+ minConfidence,
2432
+ });
2433
+ processed = fpResult.findings;
2434
+ stats.afterFalsePositiveFilter = processed.length;
2435
+
2436
+ if (verbose && fpResult.removed.length > 0) {
2437
+ console.log(` [FP Filter] Removed ${fpResult.removed.length} false positives`);
2438
+ }
2439
+ } else {
2440
+ stats.afterFalsePositiveFilter = processed.length;
2441
+ }
2442
+
2443
+ // Step 2: Apply noise reduction
2444
+ if (noiseReduction?.reduceNoise) {
2445
+ const nrResult = noiseReduction.reduceNoise(processed, {
2446
+ projectStats,
2447
+ config,
2448
+ minQualityScore,
2449
+ verbose,
2450
+ });
2451
+ processed = nrResult.findings;
2452
+ stats.afterNoiseReduction = processed.length;
2453
+ stats.noiseStats = nrResult.stats;
2454
+ } else {
2455
+ stats.afterNoiseReduction = processed.length;
2456
+ }
2457
+
2458
+ stats.output = processed.length;
2459
+ stats.reduction = Math.round((1 - stats.output / Math.max(stats.input, 1)) * 100);
2460
+
2461
+ return { findings: processed, stats };
2462
+ }
2463
+
2464
+ /**
2465
+ * Get project statistics for adaptive caps
2466
+ */
2467
+ function getProjectStats(projectPath) {
2468
+ let fileCount = 0;
2469
+ let lineCount = 0;
2470
+
2471
+ try {
2472
+ const files = fg.sync(["**/*.{ts,tsx,js,jsx,mjs,cjs}"], {
2473
+ cwd: projectPath,
2474
+ absolute: true,
2475
+ ignore: STANDARD_IGNORE_PATTERNS,
2476
+ });
2477
+
2478
+ fileCount = files.length;
2479
+
2480
+ // Sample line count from up to 100 files for performance
2481
+ const sampleFiles = files.slice(0, 100);
2482
+ let sampleLines = 0;
2483
+ for (const file of sampleFiles) {
2484
+ try {
2485
+ const content = fs.readFileSync(file, "utf8");
2486
+ sampleLines += content.split("\n").length;
2487
+ } catch {
2488
+ // Ignore errors
2489
+ }
2490
+ }
2491
+
2492
+ // Extrapolate line count
2493
+ if (sampleFiles.length > 0) {
2494
+ lineCount = Math.round((sampleLines / sampleFiles.length) * fileCount);
2495
+ }
2496
+ } catch {
2497
+ // Ignore errors
2498
+ }
2499
+
2500
+ return { fileCount, lineCount };
2501
+ }
2502
+
2061
2503
  module.exports = {
2504
+ // V6: Bulletproof filtering (apply to any findings array)
2505
+ bulletproofFindings,
2506
+ getProjectStats,
2507
+
2062
2508
  // V3: Cache management - call after scan completes to prevent memory leaks
2063
2509
  clearFileCache,
2064
2510
 
2065
2511
  // V3: Entropy helper - exported for testing/reuse
2066
2512
  getShannonEntropy,
2067
2513
 
2068
- // Analyzers
2514
+ // Core analyzers (route integrity, env, auth)
2069
2515
  findMissingRoutes,
2070
2516
  findEnvGaps,
2071
2517
  findFakeSuccess,
@@ -2073,6 +2519,8 @@ module.exports = {
2073
2519
  findStripeWebhookViolations,
2074
2520
  findPaidSurfaceNotEnforced,
2075
2521
  findOwnerModeBypass,
2522
+
2523
+ // Code quality analyzers (mock, TODO, console, etc.)
2076
2524
  findMockData,
2077
2525
  findTodoFixme,
2078
2526
  findConsoleLogs,
@@ -2081,13 +2529,22 @@ module.exports = {
2081
2529
  findDeprecatedApis,
2082
2530
  findEmptyCatch,
2083
2531
  findUnsafeRegex,
2084
- // Enhanced analyzers
2532
+
2533
+ // Enhanced analyzers (security, performance, quality)
2085
2534
  findSecurityVulnerabilities,
2086
2535
  findPerformanceIssues,
2087
2536
  findCodeQualityIssues,
2537
+
2088
2538
  // Advanced analyzers
2089
2539
  findCrossFileIssues,
2090
2540
  findTypeSafetyIssues,
2091
2541
  findAccessibilityIssues,
2092
2542
  findAPIConsistencyIssues,
2543
+
2544
+ // V5: New pattern analyzers (integrated, not separate commands)
2545
+ findReactPatternIssues, // React best practices (BLOCK/WARN only)
2546
+ findErrorHandlingIssues, // Error handling patterns
2547
+ findDatabasePatternIssues, // N+1, transactions, raw queries
2548
+ findAsyncPatternIssues, // Promise/async anti-patterns
2549
+ findBundleSizeIssues, // Heavy imports, bundle bloat
2093
2550
  };