@nebutra/next-unicorn-skill 1.0.3 → 1.0.4

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.
@@ -1,41 +1,143 @@
1
1
  /**
2
2
  * Returns the full pattern catalog covering Vibe Coding domains.
3
- * Each covered domain has 2–3 patterns for hand-rolled code detection.
3
+ *
4
+ * Domain assignment rules:
5
+ * - Each pattern goes in its MOST SPECIFIC domain (e.g., A/B test → ab-testing-experimentation, not growth-hacking)
6
+ * - Parent domains (growth-hacking, observability, ux-completeness) are used only when no specific child domain fits
7
+ * - Domains with no regex-detectable patterns are left for Gap Analysis (AI Agent)
4
8
  *
5
9
  * The catalog defines WHAT to detect, not WHAT to recommend.
6
- * Library recommendations are generated dynamically by the AI agent.
7
10
  */
8
11
  export function getPatternCatalog() {
9
12
  return [
10
13
  // -----------------------------------------------------------------------
11
- // i18n Internationalization / L10n / RTL
14
+ // A. UX / Design
12
15
  // -----------------------------------------------------------------------
16
+ // ux-completeness — General UX patterns (parent)
13
17
  {
14
- id: 'i18n-manual-pluralization',
15
- domain: 'i18n',
16
- description: 'Hand-rolled pluralization logic (if/else or ternary on count)',
17
- filePatterns: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
18
+ id: 'ux-manual-loading-states',
19
+ domain: 'empty-loading-error-states',
20
+ description: 'Hand-rolled loading state management without skeleton/spinner library',
21
+ filePatterns: ['**/*.tsx', '**/*.jsx'],
18
22
  codePatterns: [
19
- /count\s*[=!]==?\s*1\s*\?\s*['"`].*['"`]\s*:\s*['"`].*['"`]/,
20
- /\.length\s*[=!]==?\s*1\s*\?\s*['"`].*['"`]\s*:\s*['"`].*['"`]/,
23
+ /isLoading\s*\?\s*.*(?:Loading|Spinner|\.\.\.)/i,
24
+ /useState\s*<\s*boolean\s*>\s*\(\s*(?:true|false)\s*\).*loading/i,
25
+ ],
26
+ confidenceBase: 0.55,
27
+ },
28
+ // a11y-accessibility
29
+ {
30
+ id: 'a11y-manual-click-handler-div',
31
+ domain: 'a11y-accessibility',
32
+ description: 'Clickable div/span without keyboard accessibility',
33
+ filePatterns: ['**/*.tsx', '**/*.jsx'],
34
+ codePatterns: [
35
+ /<div\s[^>]*onClick\s*=\s*\{/,
36
+ /<span\s[^>]*onClick\s*=\s*\{/,
37
+ ],
38
+ confidenceBase: 0.6,
39
+ },
40
+ {
41
+ id: 'a11y-manual-focus-management',
42
+ domain: 'a11y-accessibility',
43
+ description: 'Hand-rolled focus management and keyboard trap',
44
+ filePatterns: ['**/*.tsx', '**/*.jsx', '**/*.ts', '**/*.js'],
45
+ codePatterns: [
46
+ /\.focus\s*\(\s*\)[\s\S]{0,200}(?:tabIndex|keyCode|keyDown)/i,
47
+ /addEventListener\s*\(\s*['"`]keydown['"`][\s\S]{0,200}(?:Tab|Escape|27|9)\b/,
48
+ /document\s*\.\s*activeElement/,
49
+ ],
50
+ confidenceBase: 0.55,
51
+ },
52
+ // forms-ux
53
+ {
54
+ id: 'forms-manual-state-tracking',
55
+ domain: 'forms-ux',
56
+ description: 'Multiple useState hooks for individual form fields',
57
+ filePatterns: ['**/*.tsx', '**/*.jsx'],
58
+ codePatterns: [
59
+ /const\s*\[\s*\w+,\s*set\w+\s*\]\s*=\s*useState\s*\(\s*['"`]{2}\s*\)[\s\S]{0,200}onChange/,
60
+ /e\s*\.\s*target\s*\.\s*value[\s\S]{0,50}set\w+\s*\(\s*e\s*\.\s*target\s*\.\s*value\s*\)/,
61
+ ],
62
+ confidenceBase: 0.65,
63
+ },
64
+ {
65
+ id: 'forms-manual-submit-handler',
66
+ domain: 'forms-ux',
67
+ description: 'Hand-rolled form submission with manual preventDefault and state collection',
68
+ filePatterns: ['**/*.tsx', '**/*.jsx'],
69
+ codePatterns: [
70
+ /handleSubmit[\s\S]{0,100}preventDefault\s*\(\s*\)[\s\S]{0,200}fetch\s*\(/,
71
+ /onSubmit[\s\S]{0,100}e\s*\.\s*preventDefault[\s\S]{0,200}(?:setLoading|setError)/,
72
+ ],
73
+ confidenceBase: 0.6,
74
+ },
75
+ // validation-feedback
76
+ {
77
+ id: 'validation-manual-form-errors',
78
+ domain: 'validation-feedback',
79
+ description: 'Hand-rolled form validation with manual error state tracking',
80
+ filePatterns: ['**/*.tsx', '**/*.jsx', '**/*.ts', '**/*.js'],
81
+ codePatterns: [
82
+ /setError\s*\(\s*['"`]/,
83
+ /errors\s*\[\s*['"`]\w+['"`]\s*\]/,
84
+ /validate\w*\s*=\s*\(\s*\)\s*=>/,
21
85
  ],
22
86
  confidenceBase: 0.7,
23
87
  },
88
+ // notifications-inapp
24
89
  {
25
- id: 'i18n-manual-locale-detection',
26
- domain: 'i18n',
27
- description: 'Manual navigator.language or Accept-Language header parsing',
90
+ id: 'notifications-manual-alert',
91
+ domain: 'notifications-inapp',
92
+ description: 'Using window.alert/confirm/prompt instead of a toast/notification library',
28
93
  filePatterns: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
29
94
  codePatterns: [
30
- /navigator\s*\.\s*language/,
31
- /accept-language/i,
32
- /toLocaleDateString\s*\(/,
95
+ /window\s*\.\s*alert\s*\(/,
96
+ /window\s*\.\s*confirm\s*\(/,
97
+ /window\s*\.\s*prompt\s*\(/,
33
98
  ],
34
- confidenceBase: 0.65,
99
+ confidenceBase: 0.75,
100
+ },
101
+ // design-system
102
+ {
103
+ id: 'design-hardcoded-colors',
104
+ domain: 'design-system',
105
+ description: 'Hardcoded hex/rgb colors in JSX/TSX instead of CSS variables or design tokens',
106
+ filePatterns: ['**/*.tsx', '**/*.jsx'],
107
+ codePatterns: [
108
+ /(?:color|background|border|fill|stroke)\s*[:=]\s*['"`]#[0-9a-fA-F]{3,8}['"`]/,
109
+ /(?:color|background|border)\s*[:=]\s*['"`]rgb\(/,
110
+ /className\s*=.*(?:bg|text|border)-\[#[0-9a-fA-F]{3,8}\]/,
111
+ ],
112
+ confidenceBase: 0.6,
113
+ },
114
+ {
115
+ id: 'design-inline-styles',
116
+ domain: 'design-system',
117
+ description: 'Inline style objects in JSX instead of utility classes or design tokens',
118
+ filePatterns: ['**/*.tsx', '**/*.jsx'],
119
+ codePatterns: [
120
+ /style\s*=\s*\{\s*\{/,
121
+ /style\s*=\s*\{[^}]*(?:padding|margin|fontSize|color|width|height)\s*:/,
122
+ ],
123
+ confidenceBase: 0.55,
124
+ },
125
+ {
126
+ id: 'design-no-cn-utility',
127
+ domain: 'design-system',
128
+ description: 'String concatenation for className instead of cn()/clsx/cva utility',
129
+ filePatterns: ['**/*.tsx', '**/*.jsx'],
130
+ codePatterns: [
131
+ /className\s*=\s*\{[^}]*`[^`]*\$\{/,
132
+ /className\s*=\s*\{[^}]*\+\s*['"`]/,
133
+ /className\s*=\s*\{.*\?\s*['"`][^'"]*['"`]\s*:\s*['"`]/,
134
+ ],
135
+ confidenceBase: 0.6,
35
136
  },
36
137
  // -----------------------------------------------------------------------
37
- // SEO Search Engine Optimization / GEO
138
+ // B. SEO / i18n / Content
38
139
  // -----------------------------------------------------------------------
140
+ // seo
39
141
  {
40
142
  id: 'seo-manual-meta-tags',
41
143
  domain: 'seo',
@@ -60,90 +162,31 @@ export function getPatternCatalog() {
60
162
  ],
61
163
  confidenceBase: 0.8,
62
164
  },
63
- // -----------------------------------------------------------------------
64
- // growth-hacking — A/B Testing, Analytics, Feature Flags
65
- // -----------------------------------------------------------------------
165
+ // i18n
66
166
  {
67
- id: 'growth-manual-ab-test',
68
- domain: 'growth-hacking',
69
- description: 'Hand-rolled A/B testing with Math.random() or cookie-based splits',
167
+ id: 'i18n-manual-pluralization',
168
+ domain: 'i18n',
169
+ description: 'Hand-rolled pluralization logic (if/else or ternary on count)',
70
170
  filePatterns: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
71
171
  codePatterns: [
72
- /Math\s*\.\s*random\s*\(\s*\)\s*[<>]=?\s*0?\.\s*5/,
73
- /variant\s*=\s*['"`][AB]['"`]/i,
74
- /experiment\s*[=:]\s*.*random/i,
172
+ /count\s*[=!]==?\s*1\s*\?\s*['"`].*['"`]\s*:\s*['"`].*['"`]/,
173
+ /\.length\s*[=!]==?\s*1\s*\?\s*['"`].*['"`]\s*:\s*['"`].*['"`]/,
75
174
  ],
76
175
  confidenceBase: 0.7,
77
176
  },
78
177
  {
79
- id: 'growth-manual-feature-flags',
80
- domain: 'growth-hacking',
81
- description: 'Hand-rolled feature flag checks via environment variables or config objects',
178
+ id: 'i18n-manual-locale-detection',
179
+ domain: 'i18n',
180
+ description: 'Manual navigator.language or Accept-Language header parsing',
82
181
  filePatterns: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
83
182
  codePatterns: [
84
- /process\s*\.\s*env\s*\.\s*FEATURE_/,
85
- /featureFlags?\s*\[/,
86
- /isFeatureEnabled\s*\(/,
87
- ],
88
- confidenceBase: 0.6,
89
- },
90
- // -----------------------------------------------------------------------
91
- // ai-model-serving — Inference, Model Registry, Prompt Management
92
- // -----------------------------------------------------------------------
93
- {
94
- id: 'ai-manual-prompt-template',
95
- domain: 'ai-model-serving',
96
- description: 'Hand-rolled prompt template string interpolation',
97
- filePatterns: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx', '**/*.py'],
98
- codePatterns: [
99
- /`[^`]*\$\{.*\}[^`]*`\s*.*(?:prompt|system|user|assistant)/i,
100
- /f['"].*\{.*\}.*['"].*(?:prompt|model|completion)/i,
101
- /\.replace\s*\(\s*['"`]\{.*\}['"`]/,
183
+ /navigator\s*\.\s*language/,
184
+ /accept-language/i,
185
+ /toLocaleDateString\s*\(/,
102
186
  ],
103
187
  confidenceBase: 0.65,
104
188
  },
105
- {
106
- id: 'ai-manual-inference-http',
107
- domain: 'ai-model-serving',
108
- description: 'Hand-rolled HTTP calls to model inference endpoints',
109
- filePatterns: ['**/*.ts', '**/*.js', '**/*.py'],
110
- codePatterns: [
111
- /fetch\s*\(\s*['"`].*(?:openai|anthropic|huggingface|inference)/i,
112
- /axios\s*\.\s*post\s*\(\s*['"`].*(?:completions|chat|generate)/i,
113
- /requests\s*\.\s*post\s*\(\s*['"`].*(?:v1\/|api\/)/i,
114
- ],
115
- confidenceBase: 0.7,
116
- },
117
- // -----------------------------------------------------------------------
118
- // agent-architecture — MCP Integration, Tool Orchestration, Context
119
- // -----------------------------------------------------------------------
120
- {
121
- id: 'agent-manual-tool-dispatch',
122
- domain: 'agent-architecture',
123
- description: 'Hand-rolled tool dispatch with switch/case or if/else chains',
124
- filePatterns: ['**/*.ts', '**/*.js', '**/*.py'],
125
- codePatterns: [
126
- /switch\s*\(\s*tool(?:Name|_name|Id)\s*\)/i,
127
- /if\s*\(\s*tool(?:Name|_name)\s*===?\s*['"`]/i,
128
- /tool_map\s*\[/i,
129
- ],
130
- confidenceBase: 0.7,
131
- },
132
- {
133
- id: 'agent-manual-context-window',
134
- domain: 'agent-architecture',
135
- description: 'Hand-rolled context window management (token counting, truncation)',
136
- filePatterns: ['**/*.ts', '**/*.js', '**/*.py'],
137
- codePatterns: [
138
- /token[_s]?\s*(?:count|length|limit)/i,
139
- /truncat(?:e|ion)\s*.*(?:context|message|prompt)/i,
140
- /maxTokens?\s*[=:]/i,
141
- ],
142
- confidenceBase: 0.6,
143
- },
144
- // -----------------------------------------------------------------------
145
- // content-marketing — CMS, MDX Pipelines
146
- // -----------------------------------------------------------------------
189
+ // content-marketing
147
190
  {
148
191
  id: 'content-manual-markdown-parsing',
149
192
  domain: 'content-marketing',
@@ -169,114 +212,64 @@ export function getPatternCatalog() {
169
212
  confidenceBase: 0.6,
170
213
  },
171
214
  // -----------------------------------------------------------------------
172
- // cross-border-ecommerce Payments, Shipping, Tax, Catalogs
173
- // -----------------------------------------------------------------------
174
- {
175
- id: 'ecommerce-manual-payment-integration',
176
- domain: 'cross-border-ecommerce',
177
- description: 'Hand-rolled payment gateway HTTP integration',
178
- filePatterns: ['**/*.ts', '**/*.js', '**/*.py'],
179
- codePatterns: [
180
- /fetch\s*\(\s*['"`].*(?:stripe|paypal|checkout).*['"`]/i,
181
- /payment[_-]?intent/i,
182
- /charge\s*\.\s*create/i,
183
- ],
184
- confidenceBase: 0.75,
185
- },
186
- {
187
- id: 'ecommerce-manual-tax-calculation',
188
- domain: 'cross-border-ecommerce',
189
- description: 'Hand-rolled tax/VAT calculation logic',
190
- filePatterns: ['**/*.ts', '**/*.js', '**/*.py'],
191
- codePatterns: [
192
- /tax[_-]?rate\s*[=:]\s*0?\.\d+/i,
193
- /vat\s*[=:*]/i,
194
- /calculateTax\s*\(/i,
195
- ],
196
- confidenceBase: 0.65,
197
- },
198
- // -----------------------------------------------------------------------
199
- // observability — Logging, Tracing, Metrics, Error Tracking
215
+ // C. Growth & Data
200
216
  // -----------------------------------------------------------------------
217
+ // ab-testing-experimentation (was: growth-hacking)
201
218
  {
202
- id: 'observability-manual-logging',
203
- domain: 'observability',
204
- description: 'Hand-rolled logging with console.log/console.error in production code',
205
- filePatterns: ['**/*.ts', '**/*.js', '**/*.tsx', '**/*.jsx'],
219
+ id: 'ab-test-manual-random-split',
220
+ domain: 'ab-testing-experimentation',
221
+ description: 'Hand-rolled A/B testing with Math.random() or cookie-based splits',
222
+ filePatterns: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
206
223
  codePatterns: [
207
- /console\s*\.\s*(?:log|error|warn|info)\s*\(/,
224
+ /Math\s*\.\s*random\s*\(\s*\)\s*[<>]=?\s*0?\.\s*5/,
225
+ /variant\s*=\s*['"`][AB]['"`]/i,
226
+ /experiment\s*[=:]\s*.*random/i,
208
227
  ],
209
- confidenceBase: 0.55,
228
+ confidenceBase: 0.7,
210
229
  },
230
+ // analytics-tracking
211
231
  {
212
- id: 'observability-manual-error-tracking',
213
- domain: 'observability',
214
- description: 'Hand-rolled error tracking with try/catch and HTTP reporting',
215
- filePatterns: ['**/*.ts', '**/*.js', '**/*.tsx', '**/*.jsx'],
232
+ id: 'analytics-manual-tracking',
233
+ domain: 'analytics-tracking',
234
+ description: 'Hand-rolled analytics/tracking calls instead of a product analytics SDK',
235
+ filePatterns: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
216
236
  codePatterns: [
217
- /catch\s*\(\s*\w+\s*\)\s*\{[^}]*fetch\s*\(/,
218
- /window\s*\.\s*onerror/,
219
- /process\s*\.\s*on\s*\(\s*['"`]uncaughtException['"`]/,
237
+ /window\s*\.\s*dataLayer\s*\.\s*push\s*\(/,
238
+ /gtag\s*\(\s*['"`]event['"`]/,
239
+ /fbq\s*\(\s*['"`]track['"`]/,
240
+ /navigator\s*\.\s*sendBeacon\s*\(/,
220
241
  ],
221
242
  confidenceBase: 0.7,
222
243
  },
223
244
  // -----------------------------------------------------------------------
224
- // auth-security Authentication, Authorization, Rate Limiting
245
+ // D. App / Frontend Architecture
225
246
  // -----------------------------------------------------------------------
247
+ // agent-architecture
226
248
  {
227
- id: 'auth-manual-jwt-handling',
228
- domain: 'auth-security',
229
- description: 'Hand-rolled JWT token creation/verification',
249
+ id: 'agent-manual-tool-dispatch',
250
+ domain: 'agent-architecture',
251
+ description: 'Hand-rolled tool dispatch with switch/case or if/else chains',
230
252
  filePatterns: ['**/*.ts', '**/*.js', '**/*.py'],
231
253
  codePatterns: [
232
- /atob\s*\(\s*.*split\s*\(\s*['"`]\.['"`]\s*\)/,
233
- /Buffer\s*\.\s*from\s*\(.*['"`]base64['"`]\s*\)/,
234
- /jwt\s*\.\s*sign\s*\(/i,
235
- /createHmac\s*\(/,
236
- ],
237
- confidenceBase: 0.75,
238
- },
239
- {
240
- id: 'auth-manual-rate-limiting',
241
- domain: 'auth-security',
242
- description: 'Hand-rolled rate limiting with in-memory counters or timestamps',
243
- filePatterns: ['**/*.ts', '**/*.js'],
244
- codePatterns: [
245
- /requestCount\s*[+]=\s*1/i,
246
- /rateLimi(?:t|ter)/i,
247
- /new\s+Map\s*\(\s*\).*(?:timestamp|count|window)/i,
248
- ],
249
- confidenceBase: 0.65,
250
- },
251
- // -----------------------------------------------------------------------
252
- // ux-completeness — Forms, Loading States
253
- // -----------------------------------------------------------------------
254
- {
255
- id: 'ux-manual-form-validation',
256
- domain: 'ux-completeness',
257
- description: 'Hand-rolled form validation with manual state tracking',
258
- filePatterns: ['**/*.tsx', '**/*.jsx', '**/*.ts', '**/*.js'],
259
- codePatterns: [
260
- /setError\s*\(\s*['"`]/,
261
- /errors\s*\[\s*['"`]\w+['"`]\s*\]/,
262
- /validate\w*\s*=\s*\(\s*\)\s*=>/,
254
+ /switch\s*\(\s*tool(?:Name|_name|Id)\s*\)/i,
255
+ /if\s*\(\s*tool(?:Name|_name)\s*===?\s*['"`]/i,
256
+ /tool_map\s*\[/i,
263
257
  ],
264
258
  confidenceBase: 0.7,
265
259
  },
266
260
  {
267
- id: 'ux-manual-loading-states',
268
- domain: 'ux-completeness',
269
- description: 'Hand-rolled loading state management without skeleton/spinner library',
270
- filePatterns: ['**/*.tsx', '**/*.jsx'],
261
+ id: 'agent-manual-context-window',
262
+ domain: 'agent-architecture',
263
+ description: 'Hand-rolled context window management (token counting, truncation)',
264
+ filePatterns: ['**/*.ts', '**/*.js', '**/*.py'],
271
265
  codePatterns: [
272
- /isLoading\s*\?\s*.*(?:Loading|Spinner|\.\.\.)/i,
273
- /useState\s*<\s*boolean\s*>\s*\(\s*(?:true|false)\s*\).*loading/i,
266
+ /token[_s]?\s*(?:count|length|limit)/i,
267
+ /truncat(?:e|ion)\s*.*(?:context|message|prompt)/i,
268
+ /maxTokens?\s*[=:]/i,
274
269
  ],
275
- confidenceBase: 0.55,
270
+ confidenceBase: 0.6,
276
271
  },
277
- // -----------------------------------------------------------------------
278
- // state-management — Manual state chains, Redux boilerplate
279
- // -----------------------------------------------------------------------
272
+ // state-management
280
273
  {
281
274
  id: 'state-manual-usestate-chain',
282
275
  domain: 'state-management',
@@ -312,9 +305,7 @@ export function getPatternCatalog() {
312
305
  ],
313
306
  confidenceBase: 0.75,
314
307
  },
315
- // -----------------------------------------------------------------------
316
- // data-fetching-caching — Manual fetch + useEffect patterns
317
- // -----------------------------------------------------------------------
308
+ // data-fetching-caching
318
309
  {
319
310
  id: 'data-fetch-useeffect',
320
311
  domain: 'data-fetching-caching',
@@ -351,34 +342,7 @@ export function getPatternCatalog() {
351
342
  ],
352
343
  confidenceBase: 0.7,
353
344
  },
354
- // -----------------------------------------------------------------------
355
- // forms-ux — Manual form state and validation
356
- // -----------------------------------------------------------------------
357
- {
358
- id: 'forms-manual-state-tracking',
359
- domain: 'forms-ux',
360
- description: 'Multiple useState hooks for individual form fields',
361
- filePatterns: ['**/*.tsx', '**/*.jsx'],
362
- codePatterns: [
363
- /const\s*\[\s*\w+,\s*set\w+\s*\]\s*=\s*useState\s*\(\s*['"`]{2}\s*\)[\s\S]{0,200}onChange/,
364
- /e\s*\.\s*target\s*\.\s*value[\s\S]{0,50}set\w+\s*\(\s*e\s*\.\s*target\s*\.\s*value\s*\)/,
365
- ],
366
- confidenceBase: 0.65,
367
- },
368
- {
369
- id: 'forms-manual-submit-handler',
370
- domain: 'forms-ux',
371
- description: 'Hand-rolled form submission with manual preventDefault and state collection',
372
- filePatterns: ['**/*.tsx', '**/*.jsx'],
373
- codePatterns: [
374
- /handleSubmit[\s\S]{0,100}preventDefault\s*\(\s*\)[\s\S]{0,200}fetch\s*\(/,
375
- /onSubmit[\s\S]{0,100}e\s*\.\s*preventDefault[\s\S]{0,200}(?:setLoading|setError)/,
376
- ],
377
- confidenceBase: 0.6,
378
- },
379
- // -----------------------------------------------------------------------
380
- // error-handling-resilience — Error boundaries, Result types
381
- // -----------------------------------------------------------------------
345
+ // error-handling-resilience
382
346
  {
383
347
  id: 'error-manual-error-boundary',
384
348
  domain: 'error-handling-resilience',
@@ -403,35 +367,20 @@ export function getPatternCatalog() {
403
367
  ],
404
368
  confidenceBase: 0.65,
405
369
  },
406
- // -----------------------------------------------------------------------
407
- // a11y-accessibility — Missing ARIA, keyboard navigation
408
- // -----------------------------------------------------------------------
409
- {
410
- id: 'a11y-manual-click-handler-div',
411
- domain: 'a11y-accessibility',
412
- description: 'Clickable div/span without keyboard accessibility',
413
- filePatterns: ['**/*.tsx', '**/*.jsx'],
414
- codePatterns: [
415
- /<div\s[^>]*onClick\s*=\s*\{/,
416
- /<span\s[^>]*onClick\s*=\s*\{/,
417
- ],
418
- confidenceBase: 0.6,
419
- },
370
+ // realtime-collaboration
420
371
  {
421
- id: 'a11y-manual-focus-management',
422
- domain: 'a11y-accessibility',
423
- description: 'Hand-rolled focus management and keyboard trap',
424
- filePatterns: ['**/*.tsx', '**/*.jsx', '**/*.ts', '**/*.js'],
372
+ id: 'realtime-manual-websocket',
373
+ domain: 'realtime-collaboration',
374
+ description: 'Hand-rolled WebSocket connection management',
375
+ filePatterns: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
425
376
  codePatterns: [
426
- /\.focus\s*\(\s*\)[\s\S]{0,200}(?:tabIndex|keyCode|keyDown)/i,
427
- /addEventListener\s*\(\s*['"`]keydown['"`][\s\S]{0,200}(?:Tab|Escape|27|9)\b/,
428
- /document\s*\.\s*activeElement/,
377
+ /new\s+WebSocket\s*\(/,
378
+ /\.onmessage\s*=\s*/,
379
+ /\.send\s*\(\s*JSON\s*\.\s*stringify/,
429
380
  ],
430
- confidenceBase: 0.55,
381
+ confidenceBase: 0.65,
431
382
  },
432
- // -----------------------------------------------------------------------
433
- // file-upload-media — Manual FileReader, drag-and-drop
434
- // -----------------------------------------------------------------------
383
+ // file-upload-media
435
384
  {
436
385
  id: 'upload-manual-filereader',
437
386
  domain: 'file-upload-media',
@@ -457,8 +406,9 @@ export function getPatternCatalog() {
457
406
  confidenceBase: 0.65,
458
407
  },
459
408
  // -----------------------------------------------------------------------
460
- // database-orm-migrations Raw SQL, manual migrations
409
+ // E. Backend / Platform
461
410
  // -----------------------------------------------------------------------
411
+ // database-orm-migrations
462
412
  {
463
413
  id: 'db-manual-raw-sql',
464
414
  domain: 'database-orm-migrations',
@@ -484,9 +434,90 @@ export function getPatternCatalog() {
484
434
  ],
485
435
  confidenceBase: 0.65,
486
436
  },
437
+ // caching-rate-limit
438
+ {
439
+ id: 'ratelimit-manual-counter',
440
+ domain: 'caching-rate-limit',
441
+ description: 'Hand-rolled rate limiting with in-memory counters or timestamps',
442
+ filePatterns: ['**/*.ts', '**/*.js'],
443
+ codePatterns: [
444
+ /requestCount\s*[+]=\s*1/i,
445
+ /rateLimi(?:t|ter)/i,
446
+ /new\s+Map\s*\(\s*\).*(?:timestamp|count|window)/i,
447
+ ],
448
+ confidenceBase: 0.65,
449
+ },
450
+ // feature-flags-config (was: growth-hacking)
451
+ {
452
+ id: 'feature-flags-manual-env',
453
+ domain: 'feature-flags-config',
454
+ description: 'Hand-rolled feature flag checks via environment variables or config objects',
455
+ filePatterns: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
456
+ codePatterns: [
457
+ /process\s*\.\s*env\s*\.\s*FEATURE_/,
458
+ /featureFlags?\s*\[/,
459
+ /isFeatureEnabled\s*\(/,
460
+ ],
461
+ confidenceBase: 0.6,
462
+ },
463
+ // -----------------------------------------------------------------------
464
+ // F. Security / Compliance
465
+ // -----------------------------------------------------------------------
466
+ // auth-security
467
+ {
468
+ id: 'auth-manual-jwt-handling',
469
+ domain: 'auth-security',
470
+ description: 'Hand-rolled JWT token creation/verification',
471
+ filePatterns: ['**/*.ts', '**/*.js', '**/*.py'],
472
+ codePatterns: [
473
+ /atob\s*\(\s*.*split\s*\(\s*['"`]\.['"`]\s*\)/,
474
+ /Buffer\s*\.\s*from\s*\(.*['"`]base64['"`]\s*\)/,
475
+ /jwt\s*\.\s*sign\s*\(/i,
476
+ /createHmac\s*\(/,
477
+ ],
478
+ confidenceBase: 0.75,
479
+ },
480
+ // security-hardening
481
+ {
482
+ id: 'security-manual-headers',
483
+ domain: 'security-hardening',
484
+ description: 'Hand-rolled security headers instead of helmet/middleware',
485
+ filePatterns: ['**/*.ts', '**/*.js'],
486
+ codePatterns: [
487
+ /setHeader\s*\(\s*['"`]X-Frame-Options['"`]/i,
488
+ /setHeader\s*\(\s*['"`]X-Content-Type-Options['"`]/i,
489
+ /setHeader\s*\(\s*['"`]Content-Security-Policy['"`]/i,
490
+ ],
491
+ confidenceBase: 0.7,
492
+ },
487
493
  // -----------------------------------------------------------------------
488
- // logging-tracing-metrics Structured logging, OpenTelemetry
494
+ // G. Observability / Ops
489
495
  // -----------------------------------------------------------------------
496
+ // observability (parent — generic console.log)
497
+ {
498
+ id: 'observability-manual-logging',
499
+ domain: 'observability',
500
+ description: 'Hand-rolled logging with console.log/console.error in production code',
501
+ filePatterns: ['**/*.ts', '**/*.js', '**/*.tsx', '**/*.jsx'],
502
+ codePatterns: [
503
+ /console\s*\.\s*(?:log|error|warn|info)\s*\(/,
504
+ ],
505
+ confidenceBase: 0.55,
506
+ },
507
+ // error-monitoring (was: observability)
508
+ {
509
+ id: 'error-monitoring-manual-tracking',
510
+ domain: 'error-monitoring',
511
+ description: 'Hand-rolled error tracking with try/catch and HTTP reporting',
512
+ filePatterns: ['**/*.ts', '**/*.js', '**/*.tsx', '**/*.jsx'],
513
+ codePatterns: [
514
+ /catch\s*\(\s*\w+\s*\)\s*\{[^}]*fetch\s*\(/,
515
+ /window\s*\.\s*onerror/,
516
+ /process\s*\.\s*on\s*\(\s*['"`]uncaughtException['"`]/,
517
+ ],
518
+ confidenceBase: 0.7,
519
+ },
520
+ // logging-tracing-metrics
490
521
  {
491
522
  id: 'metrics-manual-timing',
492
523
  domain: 'logging-tracing-metrics',
@@ -511,8 +542,9 @@ export function getPatternCatalog() {
511
542
  confidenceBase: 0.7,
512
543
  },
513
544
  // -----------------------------------------------------------------------
514
- // testing-strategy Manual test utilities
545
+ // H. Delivery / Quality / DevEx
515
546
  // -----------------------------------------------------------------------
547
+ // testing-strategy
516
548
  {
517
549
  id: 'test-manual-assertions',
518
550
  domain: 'testing-strategy',
@@ -537,6 +569,78 @@ export function getPatternCatalog() {
537
569
  ],
538
570
  confidenceBase: 0.5,
539
571
  },
572
+ // -----------------------------------------------------------------------
573
+ // I. Performance
574
+ // -----------------------------------------------------------------------
575
+ // performance-web-vitals
576
+ {
577
+ id: 'perf-unoptimized-images',
578
+ domain: 'performance-web-vitals',
579
+ description: 'Using raw <img> tags instead of optimized image components',
580
+ filePatterns: ['**/*.tsx', '**/*.jsx'],
581
+ codePatterns: [
582
+ /<img\s[^>]*src\s*=\s*\{/,
583
+ /<img\s[^>]*src\s*=\s*['"`](?:https?:|\/)/,
584
+ ],
585
+ confidenceBase: 0.5,
586
+ },
587
+ // -----------------------------------------------------------------------
588
+ // J. AI Engineering
589
+ // -----------------------------------------------------------------------
590
+ // ai-model-serving
591
+ {
592
+ id: 'ai-manual-prompt-template',
593
+ domain: 'ai-model-serving',
594
+ description: 'Hand-rolled prompt template string interpolation',
595
+ filePatterns: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx', '**/*.py'],
596
+ codePatterns: [
597
+ /`[^`]*\$\{.*\}[^`]*`\s*.*(?:prompt|system|user|assistant)/i,
598
+ /f['"].*\{.*\}.*['"].*(?:prompt|model|completion)/i,
599
+ /\.replace\s*\(\s*['"`]\{.*\}['"`]/,
600
+ ],
601
+ confidenceBase: 0.65,
602
+ },
603
+ {
604
+ id: 'ai-manual-inference-http',
605
+ domain: 'ai-model-serving',
606
+ description: 'Hand-rolled HTTP calls to model inference endpoints',
607
+ filePatterns: ['**/*.ts', '**/*.js', '**/*.py'],
608
+ codePatterns: [
609
+ /fetch\s*\(\s*['"`].*(?:openai|anthropic|huggingface|inference)/i,
610
+ /axios\s*\.\s*post\s*\(\s*['"`].*(?:completions|chat|generate)/i,
611
+ /requests\s*\.\s*post\s*\(\s*['"`].*(?:v1\/|api\/)/i,
612
+ ],
613
+ confidenceBase: 0.7,
614
+ },
615
+ // -----------------------------------------------------------------------
616
+ // K. Business domains
617
+ // -----------------------------------------------------------------------
618
+ // payments-billing (was: cross-border-ecommerce)
619
+ {
620
+ id: 'payments-manual-integration',
621
+ domain: 'payments-billing',
622
+ description: 'Hand-rolled payment gateway HTTP integration',
623
+ filePatterns: ['**/*.ts', '**/*.js', '**/*.py'],
624
+ codePatterns: [
625
+ /fetch\s*\(\s*['"`].*(?:stripe|paypal|checkout).*['"`]/i,
626
+ /payment[_-]?intent/i,
627
+ /charge\s*\.\s*create/i,
628
+ ],
629
+ confidenceBase: 0.75,
630
+ },
631
+ // cross-border-ecommerce
632
+ {
633
+ id: 'ecommerce-manual-tax-calculation',
634
+ domain: 'cross-border-ecommerce',
635
+ description: 'Hand-rolled tax/VAT calculation logic',
636
+ filePatterns: ['**/*.ts', '**/*.js', '**/*.py'],
637
+ codePatterns: [
638
+ /tax[_-]?rate\s*[=:]\s*0?\.\d+/i,
639
+ /vat\s*[=:*]/i,
640
+ /calculateTax\s*\(/i,
641
+ ],
642
+ confidenceBase: 0.65,
643
+ },
540
644
  ];
541
645
  }
542
646
  /**