@triedotdev/mcp 1.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.
@@ -0,0 +1,927 @@
1
+ import {
2
+ AhoCorasick
3
+ } from "./chunk-6NLHFIYA.js";
4
+
5
+ // src/trie/vibe-code-signatures.ts
6
+ var VIBE_CODE_PATTERNS = [
7
+ // ============================================
8
+ // CRITICAL: Security issues AI often creates
9
+ // ============================================
10
+ {
11
+ pattern: "NEXT_PUBLIC_",
12
+ metadata: {
13
+ type: "pattern",
14
+ severity: "serious",
15
+ category: "exposed-secrets",
16
+ description: "Environment variable exposed to browser",
17
+ commonMistake: "AI puts API keys in NEXT_PUBLIC_ variables, exposing them to users",
18
+ fix: "Only NEXT_PUBLIC_ for non-sensitive data. Move secrets to server-side API routes",
19
+ learnMore: "https://nextjs.org/docs/basic-features/environment-variables"
20
+ }
21
+ },
22
+ {
23
+ pattern: "VITE_",
24
+ metadata: {
25
+ type: "pattern",
26
+ severity: "serious",
27
+ category: "exposed-secrets",
28
+ description: "Environment variable exposed to browser",
29
+ commonMistake: "AI puts API keys in VITE_ variables, exposing them to users",
30
+ fix: "Only VITE_ for non-sensitive data. Create a backend API to hide secrets",
31
+ learnMore: "https://vitejs.dev/guide/env-and-mode.html"
32
+ }
33
+ },
34
+ {
35
+ pattern: "REACT_APP_",
36
+ metadata: {
37
+ type: "pattern",
38
+ severity: "serious",
39
+ category: "exposed-secrets",
40
+ description: "Environment variable exposed to browser",
41
+ commonMistake: "AI puts sensitive keys in REACT_APP_ making them visible in bundle",
42
+ fix: "Never put secrets in REACT_APP_. Use a backend proxy for API calls"
43
+ }
44
+ },
45
+ {
46
+ pattern: '"sk-',
47
+ metadata: {
48
+ type: "pattern",
49
+ severity: "critical",
50
+ category: "exposed-secrets",
51
+ description: "OpenAI API key pattern detected in string",
52
+ commonMistake: "AI generates code with OpenAI key in frontend - anyone can steal it!",
53
+ fix: "NEVER put sk- keys in frontend. Create /api/chat endpoint on server"
54
+ }
55
+ },
56
+ {
57
+ pattern: "'sk-",
58
+ metadata: {
59
+ type: "pattern",
60
+ severity: "critical",
61
+ category: "exposed-secrets",
62
+ description: "OpenAI API key pattern detected in string",
63
+ commonMistake: "AI generates code with OpenAI key in frontend - anyone can steal it!",
64
+ fix: "NEVER put sk- keys in frontend. Create /api/chat endpoint on server"
65
+ }
66
+ },
67
+ {
68
+ pattern: "`sk-",
69
+ metadata: {
70
+ type: "pattern",
71
+ severity: "critical",
72
+ category: "exposed-secrets",
73
+ description: "OpenAI API key pattern detected in template",
74
+ commonMistake: "AI generates code with OpenAI key in frontend - anyone can steal it!",
75
+ fix: "NEVER put sk- keys in frontend. Create /api/chat endpoint on server"
76
+ }
77
+ },
78
+ {
79
+ pattern: "sk_live_",
80
+ metadata: {
81
+ type: "pattern",
82
+ severity: "critical",
83
+ category: "exposed-secrets",
84
+ description: "Stripe live secret key detected",
85
+ commonMistake: "Stripe secret key in frontend = attackers can charge your account",
86
+ fix: "Use Stripe.js with publishable key only. Secret key stays on server"
87
+ }
88
+ },
89
+ {
90
+ pattern: "sk_test_",
91
+ metadata: {
92
+ type: "pattern",
93
+ severity: "serious",
94
+ category: "exposed-secrets",
95
+ description: "Stripe test secret key in code",
96
+ commonMistake: "Even test keys shouldnt be in frontend - bad habit",
97
+ fix: "Move to environment variables on server side"
98
+ }
99
+ },
100
+ // ============================================
101
+ // SERIOUS: Giant file anti-patterns
102
+ // ============================================
103
+ {
104
+ pattern: "function App()",
105
+ metadata: {
106
+ type: "pattern",
107
+ severity: "moderate",
108
+ category: "giant-file",
109
+ description: "Main App component - check file size",
110
+ commonMistake: "AI puts EVERYTHING in App.jsx - 1000+ lines, impossible to maintain",
111
+ fix: "Split into components: Header, Sidebar, MainContent, Footer, etc."
112
+ }
113
+ },
114
+ {
115
+ pattern: "export default function Home",
116
+ metadata: {
117
+ type: "pattern",
118
+ severity: "moderate",
119
+ category: "giant-file",
120
+ description: "Next.js page component - check file size",
121
+ commonMistake: "AI dumps entire page logic in one file including API calls",
122
+ fix: "Extract components to /components, hooks to /hooks, API to /lib"
123
+ }
124
+ },
125
+ {
126
+ pattern: "useState(",
127
+ metadata: {
128
+ type: "pattern",
129
+ severity: "low",
130
+ category: "state-management",
131
+ description: "useState hook - check if overused",
132
+ commonMistake: "AI creates 20+ useState calls in one component instead of useReducer",
133
+ fix: "Group related state with useReducer or create custom hooks"
134
+ }
135
+ },
136
+ // ============================================
137
+ // No error handling
138
+ // ============================================
139
+ {
140
+ pattern: "fetch(",
141
+ metadata: {
142
+ type: "pattern",
143
+ severity: "moderate",
144
+ category: "no-error-handling",
145
+ description: "fetch call - verify error handling exists",
146
+ commonMistake: "AI generates fetch() without try/catch or .catch() - app crashes on network error",
147
+ fix: "Wrap in try/catch, add loading state, show error message to user"
148
+ }
149
+ },
150
+ {
151
+ pattern: "axios.",
152
+ metadata: {
153
+ type: "pattern",
154
+ severity: "moderate",
155
+ category: "no-error-handling",
156
+ description: "axios call - verify error handling exists",
157
+ commonMistake: "AI uses axios without error handling or loading states",
158
+ fix: "Add try/catch, loading state, and user-friendly error messages"
159
+ }
160
+ },
161
+ {
162
+ pattern: ".then(",
163
+ metadata: {
164
+ type: "pattern",
165
+ severity: "low",
166
+ category: "no-error-handling",
167
+ description: "Promise chain - check for .catch()",
168
+ commonMistake: "AI chains .then() without .catch() - silent failures",
169
+ fix: "Always add .catch() or use async/await with try/catch"
170
+ }
171
+ },
172
+ {
173
+ pattern: "await ",
174
+ metadata: {
175
+ type: "pattern",
176
+ severity: "low",
177
+ category: "no-error-handling",
178
+ description: "await - verify try/catch exists",
179
+ commonMistake: "AI uses await without try/catch wrapper",
180
+ fix: "Wrap async operations in try/catch blocks"
181
+ }
182
+ },
183
+ // ============================================
184
+ // Missing loading/empty states
185
+ // ============================================
186
+ {
187
+ pattern: "isLoading",
188
+ metadata: {
189
+ type: "pattern",
190
+ severity: "low",
191
+ category: "loading-state",
192
+ description: "Loading state exists - good!",
193
+ commonMistake: "This is actually good! Just verify its being used",
194
+ fix: "Make sure to show spinner/skeleton while isLoading is true"
195
+ }
196
+ },
197
+ {
198
+ pattern: "loading ?",
199
+ metadata: {
200
+ type: "pattern",
201
+ severity: "low",
202
+ category: "loading-state",
203
+ description: "Conditional loading render",
204
+ commonMistake: "AI sometimes forgets the else case for loading",
205
+ fix: "Show meaningful loading UI, not just null"
206
+ }
207
+ },
208
+ {
209
+ pattern: "{data &&",
210
+ metadata: {
211
+ type: "pattern",
212
+ severity: "low",
213
+ category: "empty-state",
214
+ description: "Conditional data render",
215
+ commonMistake: "AI checks if data exists but no UI for when its missing",
216
+ fix: 'Add empty state: "No items found" or call-to-action'
217
+ }
218
+ },
219
+ {
220
+ pattern: "{data?.map(",
221
+ metadata: {
222
+ type: "pattern",
223
+ severity: "low",
224
+ category: "empty-state",
225
+ description: "Optional chaining on map",
226
+ commonMistake: "Shows nothing when data is empty - confusing for users",
227
+ fix: 'Check data.length and show "No items yet" message'
228
+ }
229
+ },
230
+ // ============================================
231
+ // Hardcoded values
232
+ // ============================================
233
+ {
234
+ pattern: "localhost:",
235
+ metadata: {
236
+ type: "pattern",
237
+ severity: "serious",
238
+ category: "hardcoded",
239
+ description: "Hardcoded localhost URL",
240
+ commonMistake: "AI hardcodes localhost:3000 URLs - breaks in production",
241
+ fix: "Use environment variable: process.env.NEXT_PUBLIC_API_URL"
242
+ }
243
+ },
244
+ {
245
+ pattern: "http://localhost",
246
+ metadata: {
247
+ type: "pattern",
248
+ severity: "serious",
249
+ category: "hardcoded",
250
+ description: "Hardcoded localhost URL",
251
+ commonMistake: "Works locally, fails when deployed",
252
+ fix: "Use relative URLs (/api/...) or environment variables"
253
+ }
254
+ },
255
+ {
256
+ pattern: "127.0.0.1",
257
+ metadata: {
258
+ type: "pattern",
259
+ severity: "serious",
260
+ category: "hardcoded",
261
+ description: "Hardcoded localhost IP",
262
+ commonMistake: "Hardcoded local IP wont work in production",
263
+ fix: "Use environment variables for all URLs"
264
+ }
265
+ },
266
+ // ============================================
267
+ // Copy-paste code smells
268
+ // ============================================
269
+ {
270
+ pattern: "TODO",
271
+ metadata: {
272
+ type: "pattern",
273
+ severity: "low",
274
+ category: "incomplete",
275
+ description: "TODO comment left behind",
276
+ commonMistake: "AI leaves TODO comments that never get done",
277
+ fix: "Either implement the TODO or remove it"
278
+ }
279
+ },
280
+ {
281
+ pattern: "FIXME",
282
+ metadata: {
283
+ type: "pattern",
284
+ severity: "moderate",
285
+ category: "incomplete",
286
+ description: "FIXME comment - known issue",
287
+ commonMistake: "AI acknowledges a problem but doesnt fix it",
288
+ fix: "Actually fix the issue or create a GitHub issue to track it"
289
+ }
290
+ },
291
+ {
292
+ pattern: "// eslint-disable",
293
+ metadata: {
294
+ type: "pattern",
295
+ severity: "moderate",
296
+ category: "code-smell",
297
+ description: "ESLint rule disabled",
298
+ commonMistake: "AI disables linter instead of fixing the actual problem",
299
+ fix: "Fix the underlying issue, dont silence the linter"
300
+ }
301
+ },
302
+ {
303
+ pattern: "@ts-ignore",
304
+ metadata: {
305
+ type: "pattern",
306
+ severity: "moderate",
307
+ category: "code-smell",
308
+ description: "TypeScript error ignored",
309
+ commonMistake: "AI uses @ts-ignore to hide type errors instead of fixing them",
310
+ fix: "Fix the type error properly or use @ts-expect-error with explanation"
311
+ }
312
+ },
313
+ {
314
+ pattern: "@ts-nocheck",
315
+ metadata: {
316
+ type: "pattern",
317
+ severity: "serious",
318
+ category: "code-smell",
319
+ description: "TypeScript checking disabled for entire file",
320
+ commonMistake: "AI disables all type checking - defeats the purpose of TypeScript",
321
+ fix: "Remove @ts-nocheck and fix type errors one by one"
322
+ }
323
+ },
324
+ {
325
+ pattern: ": any",
326
+ metadata: {
327
+ type: "pattern",
328
+ severity: "moderate",
329
+ category: "code-smell",
330
+ description: "any type used",
331
+ commonMistake: 'AI uses "any" to avoid writing proper types',
332
+ fix: "Define proper interfaces/types for your data"
333
+ }
334
+ },
335
+ {
336
+ pattern: "as any",
337
+ metadata: {
338
+ type: "pattern",
339
+ severity: "moderate",
340
+ category: "code-smell",
341
+ description: "Type assertion to any",
342
+ commonMistake: 'AI casts to "any" to silence type errors',
343
+ fix: "Use proper type narrowing or define correct types"
344
+ }
345
+ },
346
+ // ============================================
347
+ // Debug code left in
348
+ // ============================================
349
+ {
350
+ pattern: "console.log(",
351
+ metadata: {
352
+ type: "pattern",
353
+ severity: "low",
354
+ category: "debug-code",
355
+ description: "console.log left in code",
356
+ commonMistake: "AI adds console.log for debugging, forgets to remove",
357
+ fix: "Remove before production or use proper logging library"
358
+ }
359
+ },
360
+ {
361
+ pattern: "console.error(",
362
+ metadata: {
363
+ type: "pattern",
364
+ severity: "low",
365
+ category: "debug-code",
366
+ description: "console.error in code",
367
+ commonMistake: "Error logging is fine but should use proper error tracking",
368
+ fix: "Consider using Sentry, LogRocket, or similar for production"
369
+ }
370
+ },
371
+ {
372
+ pattern: "debugger",
373
+ metadata: {
374
+ type: "pattern",
375
+ severity: "serious",
376
+ category: "debug-code",
377
+ description: "debugger statement left in code",
378
+ commonMistake: "AI leaves debugger statements - freezes browser in production!",
379
+ fix: "Remove all debugger statements before deploying"
380
+ }
381
+ },
382
+ // ============================================
383
+ // Bad practices specific to frameworks
384
+ // ============================================
385
+ {
386
+ pattern: "useEffect(() => {",
387
+ metadata: {
388
+ type: "pattern",
389
+ severity: "low",
390
+ category: "react-antipattern",
391
+ description: "useEffect usage - verify necessity",
392
+ commonMistake: "AI overuses useEffect for things that dont need it",
393
+ fix: "Consider: Is this really a side effect? Could use useMemo, derived state, or event handler instead?",
394
+ learnMore: "https://react.dev/learn/you-might-not-need-an-effect"
395
+ }
396
+ },
397
+ {
398
+ pattern: "useEffect(async",
399
+ metadata: {
400
+ type: "pattern",
401
+ severity: "serious",
402
+ category: "react-antipattern",
403
+ description: "async useEffect - incorrect pattern",
404
+ commonMistake: "AI makes useEffect async directly - causes warnings and bugs",
405
+ fix: "Define async function inside useEffect, then call it"
406
+ }
407
+ },
408
+ {
409
+ pattern: ", [])",
410
+ metadata: {
411
+ type: "pattern",
412
+ severity: "low",
413
+ category: "react-antipattern",
414
+ description: "Empty dependency array",
415
+ commonMistake: 'AI uses [] to "fix" useEffect warnings without understanding why',
416
+ fix: "Verify all dependencies are listed, or intentionally run once"
417
+ }
418
+ },
419
+ {
420
+ pattern: "key={index}",
421
+ metadata: {
422
+ type: "pattern",
423
+ severity: "moderate",
424
+ category: "react-antipattern",
425
+ description: "Array index used as key",
426
+ commonMistake: "AI uses array index as key - causes bugs with reordering/filtering",
427
+ fix: "Use unique identifier from data: key={item.id}"
428
+ }
429
+ },
430
+ {
431
+ pattern: "key={i}",
432
+ metadata: {
433
+ type: "pattern",
434
+ severity: "moderate",
435
+ category: "react-antipattern",
436
+ description: "Loop index used as key",
437
+ commonMistake: "Using loop index as key breaks React reconciliation",
438
+ fix: "Use unique identifier: key={item.id} or key={item.slug}"
439
+ }
440
+ },
441
+ // ============================================
442
+ // No input validation
443
+ // ============================================
444
+ {
445
+ pattern: "req.body.",
446
+ metadata: {
447
+ type: "pattern",
448
+ severity: "serious",
449
+ category: "no-validation",
450
+ description: "Request body accessed directly",
451
+ commonMistake: "AI trusts user input without validation - security risk!",
452
+ fix: "Validate with Zod, Yup, or joi before using req.body"
453
+ }
454
+ },
455
+ {
456
+ pattern: "req.query.",
457
+ metadata: {
458
+ type: "pattern",
459
+ severity: "moderate",
460
+ category: "no-validation",
461
+ description: "Query param accessed directly",
462
+ commonMistake: "AI doesnt validate query parameters",
463
+ fix: "Validate and sanitize query parameters before use"
464
+ }
465
+ },
466
+ {
467
+ pattern: "req.params.",
468
+ metadata: {
469
+ type: "pattern",
470
+ severity: "moderate",
471
+ category: "no-validation",
472
+ description: "URL param accessed directly",
473
+ commonMistake: "AI trusts URL parameters without validation",
474
+ fix: "Validate params (especially IDs) before database queries"
475
+ }
476
+ },
477
+ // ============================================
478
+ // Mixing concerns (DB in components)
479
+ // ============================================
480
+ {
481
+ pattern: "prisma.",
482
+ metadata: {
483
+ type: "pattern",
484
+ severity: "moderate",
485
+ category: "mixing-concerns",
486
+ description: "Prisma in component/page",
487
+ commonMistake: "AI puts database calls directly in React components",
488
+ fix: "Move to API routes, server actions, or /lib/db.ts"
489
+ }
490
+ },
491
+ {
492
+ pattern: "mongoose.",
493
+ metadata: {
494
+ type: "pattern",
495
+ severity: "moderate",
496
+ category: "mixing-concerns",
497
+ description: "Mongoose in component",
498
+ commonMistake: "Database logic mixed with UI code",
499
+ fix: "Create separate /lib/db.ts or /services/ for data access"
500
+ }
501
+ },
502
+ {
503
+ pattern: "supabase.",
504
+ metadata: {
505
+ type: "pattern",
506
+ severity: "low",
507
+ category: "mixing-concerns",
508
+ description: "Supabase client usage",
509
+ commonMistake: "AI puts Supabase calls everywhere instead of centralizing",
510
+ fix: "Create /lib/supabase.ts with helper functions"
511
+ }
512
+ },
513
+ // ============================================
514
+ // Common AI oversights
515
+ // ============================================
516
+ {
517
+ pattern: "onClick={() =>",
518
+ metadata: {
519
+ type: "pattern",
520
+ severity: "low",
521
+ category: "performance",
522
+ description: "Inline arrow function in onClick",
523
+ commonMistake: "AI creates new function on every render",
524
+ fix: "For simple cases its fine, but consider useCallback for expensive components"
525
+ }
526
+ },
527
+ {
528
+ pattern: "style={{",
529
+ metadata: {
530
+ type: "pattern",
531
+ severity: "low",
532
+ category: "performance",
533
+ description: "Inline style object",
534
+ commonMistake: "AI uses inline styles creating new objects every render",
535
+ fix: "Use CSS classes, Tailwind, or define styles outside component"
536
+ }
537
+ },
538
+ {
539
+ pattern: "new Date()",
540
+ metadata: {
541
+ type: "pattern",
542
+ severity: "low",
543
+ category: "dates",
544
+ description: "Date creation",
545
+ commonMistake: "AI uses new Date() without considering timezones",
546
+ fix: "Consider timezone handling, use date-fns or dayjs for complex date logic"
547
+ }
548
+ },
549
+ // ============================================
550
+ // Vibe coding specific patterns (r/vibecoding)
551
+ // ============================================
552
+ {
553
+ pattern: "just works",
554
+ metadata: {
555
+ type: "pattern",
556
+ severity: "low",
557
+ category: "vibe-smell",
558
+ description: 'Comment suggesting "it just works"',
559
+ commonMistake: "Classic vibe coding - accepting code without understanding it",
560
+ fix: "Take time to understand WHY it works, or it will break later"
561
+ }
562
+ },
563
+ {
564
+ pattern: "idk why",
565
+ metadata: {
566
+ type: "pattern",
567
+ severity: "moderate",
568
+ category: "vibe-smell",
569
+ description: "Comment admitting confusion",
570
+ commonMistake: "AI generated something you dont understand - tech debt waiting to happen",
571
+ fix: "Ask the AI to explain what this code does and why"
572
+ }
573
+ },
574
+ {
575
+ pattern: "dont touch",
576
+ metadata: {
577
+ type: "pattern",
578
+ severity: "moderate",
579
+ category: "vibe-smell",
580
+ description: "Warning comment about fragile code",
581
+ commonMistake: 'Code that "works but nobody knows how" - very fragile',
582
+ fix: "Refactor this section or at least document what it does"
583
+ }
584
+ },
585
+ {
586
+ pattern: "// ai generated",
587
+ metadata: {
588
+ type: "pattern",
589
+ severity: "low",
590
+ category: "vibe-smell",
591
+ description: "AI generated code marker",
592
+ commonMistake: "At least you labeled it! But did you review it?",
593
+ fix: "Review AI-generated code for security issues and edge cases"
594
+ }
595
+ },
596
+ {
597
+ pattern: "// cursor",
598
+ metadata: {
599
+ type: "pattern",
600
+ severity: "low",
601
+ category: "vibe-smell",
602
+ description: "Cursor-generated code marker",
603
+ commonMistake: "Marked as Cursor-generated - make sure to review",
604
+ fix: "Verify the logic is correct and handles errors properly"
605
+ }
606
+ },
607
+ {
608
+ pattern: "// copilot",
609
+ metadata: {
610
+ type: "pattern",
611
+ severity: "low",
612
+ category: "vibe-smell",
613
+ description: "Copilot-generated code marker",
614
+ commonMistake: "Copilot suggestion accepted without review",
615
+ fix: "Always review Copilot suggestions for correctness"
616
+ }
617
+ },
618
+ // ============================================
619
+ // Deployment/Production issues
620
+ // ============================================
621
+ {
622
+ pattern: "npm run dev",
623
+ metadata: {
624
+ type: "pattern",
625
+ severity: "low",
626
+ category: "deployment",
627
+ description: "Dev script reference",
628
+ commonMistake: "Make sure you also have build and start scripts for production",
629
+ fix: "Verify you can run: npm run build && npm start"
630
+ }
631
+ },
632
+ {
633
+ pattern: "development",
634
+ metadata: {
635
+ type: "pattern",
636
+ severity: "low",
637
+ category: "deployment",
638
+ description: "Development mode reference",
639
+ commonMistake: "Ensure dev-only code doesnt run in production",
640
+ fix: "Check NODE_ENV and use proper environment detection"
641
+ }
642
+ },
643
+ {
644
+ pattern: ".env.local",
645
+ metadata: {
646
+ type: "pattern",
647
+ severity: "low",
648
+ category: "deployment",
649
+ description: "Local env file reference",
650
+ commonMistake: "Local env works, but did you set up production env vars?",
651
+ fix: "Set up environment variables in your deployment platform"
652
+ }
653
+ },
654
+ // ============================================
655
+ // Common LLM hallucination patterns
656
+ // ============================================
657
+ {
658
+ pattern: "import { something }",
659
+ metadata: {
660
+ type: "pattern",
661
+ severity: "low",
662
+ category: "hallucination",
663
+ description: "Named import - verify it exists",
664
+ commonMistake: "AI sometimes imports functions that dont exist in the library",
665
+ fix: 'If you get "X is not exported" error, check library docs'
666
+ }
667
+ },
668
+ {
669
+ pattern: "v3",
670
+ metadata: {
671
+ type: "pattern",
672
+ severity: "low",
673
+ category: "hallucination",
674
+ description: "Version number in code",
675
+ commonMistake: "AI may use outdated API patterns from old library versions",
676
+ fix: "Check you are using the correct API for your installed version"
677
+ }
678
+ },
679
+ // ============================================
680
+ // Quick prototyping shortcuts that become problems
681
+ // ============================================
682
+ {
683
+ pattern: "setTimeout(",
684
+ metadata: {
685
+ type: "pattern",
686
+ severity: "moderate",
687
+ category: "timing-hack",
688
+ description: "setTimeout usage",
689
+ commonMistake: 'AI uses setTimeout to "fix" race conditions instead of proper async',
690
+ fix: "Use proper async/await, promises, or state management instead"
691
+ }
692
+ },
693
+ {
694
+ pattern: "sleep(",
695
+ metadata: {
696
+ type: "pattern",
697
+ severity: "moderate",
698
+ category: "timing-hack",
699
+ description: "Sleep function usage",
700
+ commonMistake: "Artificial delays hide real timing issues",
701
+ fix: "Fix the underlying race condition instead of adding delays"
702
+ }
703
+ },
704
+ {
705
+ pattern: "window.location.reload",
706
+ metadata: {
707
+ type: "pattern",
708
+ severity: "moderate",
709
+ category: "hack",
710
+ description: 'Page reload to "fix" state issues',
711
+ commonMistake: "AI reloads page instead of properly managing state",
712
+ fix: "Fix state management - reloading is bad UX"
713
+ }
714
+ },
715
+ {
716
+ pattern: "force: true",
717
+ metadata: {
718
+ type: "pattern",
719
+ severity: "moderate",
720
+ category: "hack",
721
+ description: "Force flag usage",
722
+ commonMistake: "AI uses force flags to bypass checks instead of fixing root cause",
723
+ fix: "Understand why the check exists before bypassing it"
724
+ }
725
+ }
726
+ ];
727
+ function checkFileLevelIssues(filePath, content) {
728
+ const issues = [];
729
+ const lines = content.split("\n");
730
+ const lineCount = lines.length;
731
+ const fileName = filePath.split("/").pop() || "";
732
+ if (lineCount > 500) {
733
+ issues.push({
734
+ file: filePath,
735
+ issue: `File has ${lineCount} lines - way too big!`,
736
+ severity: lineCount > 1e3 ? "serious" : "moderate",
737
+ category: "giant-file",
738
+ commonMistake: "AI dumps everything in one file. Reddit is FULL of posts about 2000 line App.jsx files",
739
+ fix: `Split into smaller files. Rule of thumb: components < 200 lines, pages < 300 lines`
740
+ });
741
+ }
742
+ const useStateCount = (content.match(/useState\(/g) || []).length;
743
+ if (useStateCount > 10) {
744
+ issues.push({
745
+ file: filePath,
746
+ issue: `${useStateCount} useState hooks in one component`,
747
+ severity: useStateCount > 15 ? "serious" : "moderate",
748
+ category: "state-explosion",
749
+ commonMistake: "AI creates separate useState for every field instead of grouping",
750
+ fix: "Group related state into objects, or use useReducer for complex state"
751
+ });
752
+ }
753
+ const useEffectCount = (content.match(/useEffect\(/g) || []).length;
754
+ if (useEffectCount > 5) {
755
+ issues.push({
756
+ file: filePath,
757
+ issue: `${useEffectCount} useEffect hooks - probably too many`,
758
+ severity: "moderate",
759
+ category: "effect-hell",
760
+ commonMistake: "AI creates useEffect for everything. Most effects are unnecessary",
761
+ fix: "Review each useEffect - many can be replaced with event handlers or derived state"
762
+ });
763
+ }
764
+ if (/^(App|app|main|Main|index|page)\.(jsx?|tsx?)$/.test(fileName) && lineCount > 300) {
765
+ issues.push({
766
+ file: filePath,
767
+ issue: `Main entry file is ${lineCount} lines`,
768
+ severity: "serious",
769
+ category: "giant-main",
770
+ commonMistake: "Classic AI pattern: everything in App.jsx or page.tsx",
771
+ fix: "Extract: Header, Footer, Sidebar, MainContent as separate components"
772
+ });
773
+ }
774
+ if (filePath.endsWith(".tsx") || filePath.endsWith(".ts")) {
775
+ const anyCount = (content.match(/:\s*any\b/g) || []).length;
776
+ if (anyCount > 5) {
777
+ issues.push({
778
+ file: filePath,
779
+ issue: `${anyCount} uses of "any" type`,
780
+ severity: "moderate",
781
+ category: "weak-typing",
782
+ commonMistake: 'AI uses "any" to avoid writing proper types',
783
+ fix: 'Define interfaces for your data shapes. AI can help: "Generate types for this data"'
784
+ });
785
+ }
786
+ }
787
+ const consoleLogCount = (content.match(/console\.(log|warn|error|debug)/g) || []).length;
788
+ if (consoleLogCount > 10) {
789
+ issues.push({
790
+ file: filePath,
791
+ issue: `${consoleLogCount} console statements - cleanup needed`,
792
+ severity: "low",
793
+ category: "debug-code",
794
+ commonMistake: "AI adds console.log for debugging, user never removes them",
795
+ fix: "Remove debug logs before deploying. Use proper error tracking for production."
796
+ });
797
+ }
798
+ return issues;
799
+ }
800
+ var vibeCodeTrie = null;
801
+ function getVibeCodeTrie() {
802
+ if (!vibeCodeTrie) {
803
+ vibeCodeTrie = new AhoCorasick();
804
+ for (const { pattern, metadata } of VIBE_CODE_PATTERNS) {
805
+ vibeCodeTrie.addPattern(pattern, metadata, metadata);
806
+ }
807
+ vibeCodeTrie.build();
808
+ console.error(` \u{1F3AF} Loaded ${VIBE_CODE_PATTERNS.length} vibe-code patterns into trie`);
809
+ }
810
+ return vibeCodeTrie;
811
+ }
812
+ var VIBE_EXCLUDED_PATTERNS = [
813
+ /package-lock\.json$/,
814
+ /yarn\.lock$/,
815
+ /pnpm-lock\.yaml$/,
816
+ /node_modules\//,
817
+ /\.min\.[jt]s$/,
818
+ /dist\//,
819
+ /build\//,
820
+ /\.d\.ts$/
821
+ ];
822
+ function shouldExcludeVibeFile(filePath) {
823
+ return VIBE_EXCLUDED_PATTERNS.some((pattern) => pattern.test(filePath));
824
+ }
825
+ function isVibeFalsePositive(line, pattern, filePath, category) {
826
+ const trimmedLine = line.trim();
827
+ if (trimmedLine.startsWith("//") || trimmedLine.startsWith("*") || trimmedLine.startsWith("/*") || trimmedLine.startsWith("#")) {
828
+ return true;
829
+ }
830
+ if (/^\s*(interface|type|export\s+interface|export\s+type)\s/.test(line)) {
831
+ return true;
832
+ }
833
+ if (/process\.env|import\.meta\.env/.test(line)) {
834
+ if (["exposed-secrets"].includes(category) && !/=\s*['"`]/.test(line)) {
835
+ return true;
836
+ }
837
+ }
838
+ switch (pattern) {
839
+ case "console.log(":
840
+ case "console.error(":
841
+ if (/debug|dev|development/i.test(filePath)) return true;
842
+ if (pattern === "console.error(") return true;
843
+ break;
844
+ case "useState(":
845
+ return true;
846
+ // Don't flag individual useState
847
+ case "await ":
848
+ return true;
849
+ case ".then(":
850
+ return true;
851
+ // Too noisy, disable
852
+ case "TODO":
853
+ case "FIXME":
854
+ break;
855
+ case "useEffect(() => {":
856
+ return true;
857
+ case ", [])":
858
+ return true;
859
+ case "development":
860
+ return true;
861
+ case "import { something }":
862
+ return true;
863
+ case "v3":
864
+ return true;
865
+ case "new Date()":
866
+ return true;
867
+ case "style={{":
868
+ case "onClick={() =>":
869
+ return true;
870
+ }
871
+ if (/\.(test|spec)\.[jt]sx?$/.test(filePath) || /__tests__\//.test(filePath)) {
872
+ if (!["exposed-secrets"].includes(category)) {
873
+ return true;
874
+ }
875
+ }
876
+ return false;
877
+ }
878
+ function scanForVibeCodeIssues(code, filePath) {
879
+ if (shouldExcludeVibeFile(filePath)) {
880
+ return [];
881
+ }
882
+ const trie = getVibeCodeTrie();
883
+ const rawMatches = trie.search(code);
884
+ const lines = code.split("\n");
885
+ const matches = [];
886
+ const seen = /* @__PURE__ */ new Set();
887
+ for (const match of rawMatches) {
888
+ const key = `${match.line}:${match.pattern}`;
889
+ if (seen.has(key)) continue;
890
+ seen.add(key);
891
+ const line = lines[match.line - 1] || "";
892
+ const meta = match.metadata;
893
+ const category = meta.category || "unknown";
894
+ if (isVibeFalsePositive(line, match.pattern, filePath, category)) continue;
895
+ matches.push({
896
+ pattern: match.pattern,
897
+ line: match.line,
898
+ column: match.column,
899
+ severity: meta.severity,
900
+ category,
901
+ description: meta.description || "",
902
+ commonMistake: meta.commonMistake || "",
903
+ fix: meta.fix || "",
904
+ learnMore: meta.learnMore
905
+ });
906
+ }
907
+ return matches;
908
+ }
909
+ function getVibeCodeStats() {
910
+ const byCategory = {};
911
+ for (const { metadata } of VIBE_CODE_PATTERNS) {
912
+ const cat = metadata.category || "unknown";
913
+ byCategory[cat] = (byCategory[cat] || 0) + 1;
914
+ }
915
+ return {
916
+ total: VIBE_CODE_PATTERNS.length,
917
+ byCategory
918
+ };
919
+ }
920
+
921
+ export {
922
+ checkFileLevelIssues,
923
+ getVibeCodeTrie,
924
+ scanForVibeCodeIssues,
925
+ getVibeCodeStats
926
+ };
927
+ //# sourceMappingURL=chunk-3CS6Z2SL.js.map