awesome-slash 2.4.2

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 (95) hide show
  1. package/.claude-plugin/marketplace.json +54 -0
  2. package/.claude-plugin/plugin.json +11 -0
  3. package/.mcp.json +8 -0
  4. package/CHANGELOG.md +261 -0
  5. package/LICENSE +21 -0
  6. package/README.md +363 -0
  7. package/SECURITY.md +101 -0
  8. package/adapters/README.md +256 -0
  9. package/adapters/codex/README.md +272 -0
  10. package/adapters/codex/install.sh +179 -0
  11. package/adapters/opencode/README.md +301 -0
  12. package/adapters/opencode/install.sh +223 -0
  13. package/lib/patterns/review-patterns.js +511 -0
  14. package/lib/patterns/slop-patterns.js +647 -0
  15. package/lib/platform/detect-platform.js +535 -0
  16. package/lib/platform/verify-tools.js +235 -0
  17. package/lib/state/workflow-state.js +635 -0
  18. package/lib/state/workflow-state.schema.json +282 -0
  19. package/lib/utils/context-optimizer.js +227 -0
  20. package/mcp-server/index.js +303 -0
  21. package/mcp-server/package.json +23 -0
  22. package/package.json +63 -0
  23. package/plugins/deslop-around/.claude-plugin/plugin.json +20 -0
  24. package/plugins/deslop-around/commands/deslop-around.md +220 -0
  25. package/plugins/deslop-around/lib/patterns/review-patterns.js +511 -0
  26. package/plugins/deslop-around/lib/patterns/slop-patterns.js +641 -0
  27. package/plugins/deslop-around/lib/platform/detect-platform.js +514 -0
  28. package/plugins/deslop-around/lib/platform/verify-tools.js +235 -0
  29. package/plugins/deslop-around/lib/state/workflow-state.js +635 -0
  30. package/plugins/deslop-around/lib/state/workflow-state.schema.json +282 -0
  31. package/plugins/deslop-around/lib/utils/context-optimizer.js +222 -0
  32. package/plugins/next-task/.claude-plugin/plugin.json +24 -0
  33. package/plugins/next-task/agents/ci-fixer.md +236 -0
  34. package/plugins/next-task/agents/ci-monitor.md +291 -0
  35. package/plugins/next-task/agents/delivery-validator.md +451 -0
  36. package/plugins/next-task/agents/deslop-work.md +272 -0
  37. package/plugins/next-task/agents/docs-updater.md +506 -0
  38. package/plugins/next-task/agents/exploration-agent.md +277 -0
  39. package/plugins/next-task/agents/implementation-agent.md +427 -0
  40. package/plugins/next-task/agents/planning-agent.md +236 -0
  41. package/plugins/next-task/agents/policy-selector.md +248 -0
  42. package/plugins/next-task/agents/review-orchestrator.md +521 -0
  43. package/plugins/next-task/agents/simple-fixer.md +136 -0
  44. package/plugins/next-task/agents/task-discoverer.md +357 -0
  45. package/plugins/next-task/agents/test-coverage-checker.md +447 -0
  46. package/plugins/next-task/agents/worktree-manager.md +419 -0
  47. package/plugins/next-task/commands/delivery-approval.md +331 -0
  48. package/plugins/next-task/commands/next-task.md +627 -0
  49. package/plugins/next-task/commands/update-docs-around.md +418 -0
  50. package/plugins/next-task/hooks/hooks.json +14 -0
  51. package/plugins/next-task/lib/patterns/review-patterns.js +511 -0
  52. package/plugins/next-task/lib/patterns/slop-patterns.js +641 -0
  53. package/plugins/next-task/lib/platform/detect-platform.js +514 -0
  54. package/plugins/next-task/lib/platform/verify-tools.js +235 -0
  55. package/plugins/next-task/lib/state/tasks-registry.schema.json +85 -0
  56. package/plugins/next-task/lib/state/workflow-state.js +635 -0
  57. package/plugins/next-task/lib/state/workflow-state.schema.json +282 -0
  58. package/plugins/next-task/lib/state/worktree-status.schema.json +219 -0
  59. package/plugins/next-task/lib/utils/context-optimizer.js +222 -0
  60. package/plugins/project-review/.claude-plugin/plugin.json +20 -0
  61. package/plugins/project-review/commands/project-review-agents.md +286 -0
  62. package/plugins/project-review/commands/project-review-github.md +142 -0
  63. package/plugins/project-review/commands/project-review.md +273 -0
  64. package/plugins/project-review/lib/patterns/review-patterns.js +511 -0
  65. package/plugins/project-review/lib/patterns/slop-patterns.js +641 -0
  66. package/plugins/project-review/lib/platform/detect-platform.js +514 -0
  67. package/plugins/project-review/lib/platform/verify-tools.js +235 -0
  68. package/plugins/project-review/lib/state/workflow-state.js +635 -0
  69. package/plugins/project-review/lib/state/workflow-state.schema.json +282 -0
  70. package/plugins/project-review/lib/utils/context-optimizer.js +222 -0
  71. package/plugins/reality-check/.claude-plugin/plugin.json +23 -0
  72. package/plugins/reality-check/README.md +156 -0
  73. package/plugins/reality-check/agents/code-explorer.md +353 -0
  74. package/plugins/reality-check/agents/doc-analyzer.md +337 -0
  75. package/plugins/reality-check/agents/issue-scanner.md +231 -0
  76. package/plugins/reality-check/agents/plan-synthesizer.md +479 -0
  77. package/plugins/reality-check/commands/scan.md +242 -0
  78. package/plugins/reality-check/commands/set.md +203 -0
  79. package/plugins/reality-check/lib/state/reality-check-state.js +509 -0
  80. package/plugins/reality-check/skills/reality-analysis/SKILL.md +317 -0
  81. package/plugins/ship/.claude-plugin/plugin.json +21 -0
  82. package/plugins/ship/commands/ship-ci-review-loop.md +443 -0
  83. package/plugins/ship/commands/ship-deployment.md +330 -0
  84. package/plugins/ship/commands/ship-error-handling.md +254 -0
  85. package/plugins/ship/commands/ship.md +370 -0
  86. package/plugins/ship/lib/patterns/review-patterns.js +511 -0
  87. package/plugins/ship/lib/patterns/slop-patterns.js +641 -0
  88. package/plugins/ship/lib/platform/detect-platform.js +514 -0
  89. package/plugins/ship/lib/platform/verify-tools.js +235 -0
  90. package/plugins/ship/lib/state/workflow-state.js +635 -0
  91. package/plugins/ship/lib/state/workflow-state.schema.json +282 -0
  92. package/plugins/ship/lib/utils/context-optimizer.js +222 -0
  93. package/scripts/install/claude.sh +50 -0
  94. package/scripts/install/codex.sh +181 -0
  95. package/scripts/install/opencode.sh +211 -0
@@ -0,0 +1,647 @@
1
+ /**
2
+ * Slop Detection Patterns
3
+ * Pattern library for detecting and removing AI-generated code slop
4
+ *
5
+ * @author Avi Fenesh
6
+ * @license MIT
7
+ */
8
+
9
+ /**
10
+ * Deep freeze an object for V8 optimization and immutability
11
+ * @param {Object} obj - Object to freeze
12
+ * @returns {Object} Frozen object
13
+ */
14
+ function deepFreeze(obj) {
15
+ Object.keys(obj).forEach(key => {
16
+ if (typeof obj[key] === 'object' && obj[key] !== null && !(obj[key] instanceof RegExp)) {
17
+ deepFreeze(obj[key]);
18
+ }
19
+ });
20
+ return Object.freeze(obj);
21
+ }
22
+
23
+ // Pre-compiled regex cache for performance (limited to prevent memory growth)
24
+ const MAX_PATTERN_CACHE_SIZE = 50;
25
+ const _compiledExcludePatterns = new Map();
26
+
27
+ /**
28
+ * Get a compiled regex for an exclude pattern (cached)
29
+ * @param {string} pattern - Glob pattern to compile
30
+ * @returns {RegExp} Compiled regex
31
+ */
32
+ function getCompiledPattern(pattern) {
33
+ if (!_compiledExcludePatterns.has(pattern)) {
34
+ // Enforce cache size limit using FIFO eviction
35
+ if (_compiledExcludePatterns.size >= MAX_PATTERN_CACHE_SIZE) {
36
+ const firstKey = _compiledExcludePatterns.keys().next().value;
37
+ _compiledExcludePatterns.delete(firstKey);
38
+ }
39
+ // Escape all regex metacharacters except *, then replace * with .*
40
+ const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
41
+ const regexStr = '^' + escaped.replace(/\*/g, '.*') + '$';
42
+ _compiledExcludePatterns.set(pattern, new RegExp(regexStr));
43
+ }
44
+ return _compiledExcludePatterns.get(pattern);
45
+ }
46
+
47
+ /**
48
+ * Auto-fix strategies:
49
+ * - remove: Delete the matching line(s)
50
+ * - replace: Replace with suggested fix
51
+ * - add_logging: Add proper error logging
52
+ * - flag: Mark for manual review
53
+ * - none: Report only, no auto-fix
54
+ */
55
+
56
+ const slopPatterns = {
57
+ /**
58
+ * Console debugging in JavaScript/TypeScript
59
+ */
60
+ console_debugging: {
61
+ pattern: /console\.(log|debug|info|warn)\(/,
62
+ exclude: ['*.test.*', '*.spec.*', '*.config.*'],
63
+ severity: 'medium',
64
+ autoFix: 'remove',
65
+ language: 'javascript',
66
+ description: 'Console.log statements left in production code'
67
+ },
68
+
69
+ /**
70
+ * Python debugging statements
71
+ */
72
+ python_debugging: {
73
+ pattern: /(print\(|import pdb|breakpoint\(\)|import ipdb)/,
74
+ exclude: ['test_*.py', '*_test.py', 'conftest.py'],
75
+ severity: 'medium',
76
+ autoFix: 'remove',
77
+ language: 'python',
78
+ description: 'Debug print/breakpoint statements in production'
79
+ },
80
+
81
+ /**
82
+ * Rust debugging macros
83
+ */
84
+ rust_debugging: {
85
+ pattern: /(println!|dbg!|eprintln!)\(/,
86
+ exclude: ['*_test.rs', '*_tests.rs'],
87
+ severity: 'medium',
88
+ autoFix: 'remove',
89
+ language: 'rust',
90
+ description: 'Debug print macros in production code'
91
+ },
92
+
93
+ /**
94
+ * Old TODO comments (>90 days)
95
+ */
96
+ old_todos: {
97
+ pattern: /(TODO|FIXME|HACK|XXX):/,
98
+ exclude: [],
99
+ severity: 'low',
100
+ autoFix: 'flag',
101
+ language: null, // All languages
102
+ description: 'TODO/FIXME comments older than 90 days',
103
+ requiresAgeCheck: true,
104
+ ageThreshold: 90 // days
105
+ },
106
+
107
+ /**
108
+ * Commented out code blocks
109
+ */
110
+ commented_code: {
111
+ pattern: /^\s*(\/\/|#)\s*\w{5,}/,
112
+ exclude: [],
113
+ severity: 'medium',
114
+ autoFix: 'remove',
115
+ language: null,
116
+ description: 'Large blocks of commented-out code',
117
+ minConsecutiveLines: 5
118
+ },
119
+
120
+ /**
121
+ * Placeholder text
122
+ */
123
+ placeholder_text: {
124
+ pattern: /(lorem ipsum|test test test|asdf|foo bar baz|placeholder|replace this|todo: implement)/i,
125
+ exclude: ['*.test.*', '*.spec.*', 'README.*', '*.md'],
126
+ severity: 'high',
127
+ autoFix: 'flag',
128
+ language: null,
129
+ description: 'Placeholder text that should be replaced'
130
+ },
131
+
132
+ /**
133
+ * Empty catch blocks (JavaScript/TypeScript)
134
+ */
135
+ empty_catch_js: {
136
+ pattern: /catch\s*\([^)]*\)\s*\{\s*\}/,
137
+ exclude: [],
138
+ severity: 'high',
139
+ autoFix: 'add_logging',
140
+ language: 'javascript',
141
+ description: 'Empty catch blocks without error handling'
142
+ },
143
+
144
+ /**
145
+ * Empty except blocks (Python)
146
+ */
147
+ empty_except_py: {
148
+ pattern: /except\s*[^:]*:\s*pass\s*$/,
149
+ exclude: [],
150
+ severity: 'high',
151
+ autoFix: 'add_logging',
152
+ language: 'python',
153
+ description: 'Empty except blocks with just pass'
154
+ },
155
+
156
+ /**
157
+ * Magic numbers (large hardcoded numbers)
158
+ */
159
+ magic_numbers: {
160
+ pattern: /(?<![a-zA-Z_\d])[0-9]{4,}(?![a-zA-Z_\d])/,
161
+ exclude: ['*.test.*', '*.spec.*', '*.config.*', 'package.json', 'package-lock.json'],
162
+ severity: 'low',
163
+ autoFix: 'flag',
164
+ language: null,
165
+ description: 'Magic numbers that should be constants'
166
+ },
167
+
168
+ /**
169
+ * Disabled linter rules
170
+ */
171
+ disabled_linter: {
172
+ pattern: /(eslint-disable|pylint: disable|#\s*noqa|@SuppressWarnings|#\[allow\()/,
173
+ exclude: [],
174
+ severity: 'medium',
175
+ autoFix: 'flag',
176
+ language: null,
177
+ description: 'Disabled linter rules that may hide issues'
178
+ },
179
+
180
+ /**
181
+ * Unused imports (basic pattern, language-specific tools better)
182
+ */
183
+ unused_imports_hint: {
184
+ pattern: /^import .* from .* \/\/ unused$/,
185
+ exclude: [],
186
+ severity: 'low',
187
+ autoFix: 'remove',
188
+ language: null,
189
+ description: 'Imports marked as unused'
190
+ },
191
+
192
+ /**
193
+ * Duplicate string literals (same string >5 times)
194
+ */
195
+ duplicate_strings: {
196
+ pattern: null, // Requires multi-pass analysis
197
+ exclude: ['*.test.*', '*.spec.*'],
198
+ severity: 'low',
199
+ autoFix: 'flag',
200
+ language: null,
201
+ description: 'Duplicate string literals that should be constants',
202
+ requiresMultiPass: true
203
+ },
204
+
205
+ /**
206
+ * Inconsistent indentation markers
207
+ */
208
+ mixed_indentation: {
209
+ pattern: /^\t+ +|^ +\t+/,
210
+ exclude: ['Makefile', '*.mk'],
211
+ severity: 'low',
212
+ autoFix: 'replace',
213
+ language: null,
214
+ description: 'Mixed tabs and spaces'
215
+ },
216
+
217
+ /**
218
+ * Trailing whitespace
219
+ */
220
+ trailing_whitespace: {
221
+ pattern: /\s+$/,
222
+ exclude: ['*.md'], // Markdown uses trailing spaces for line breaks
223
+ severity: 'low',
224
+ autoFix: 'remove',
225
+ language: null,
226
+ description: 'Trailing whitespace at end of lines'
227
+ },
228
+
229
+ /**
230
+ * Multiple consecutive blank lines
231
+ */
232
+ multiple_blank_lines: {
233
+ pattern: /^\s*\n\s*\n\s*\n/,
234
+ exclude: [],
235
+ severity: 'low',
236
+ autoFix: 'replace',
237
+ language: null,
238
+ description: 'More than 2 consecutive blank lines'
239
+ },
240
+
241
+ /**
242
+ * Hardcoded credentials patterns (expanded for comprehensive detection)
243
+ */
244
+ hardcoded_secrets: {
245
+ pattern: /(password|secret|api[_-]?key|token|credential|auth)[_-]?(key|token|secret|pass)?\s*[:=]\s*["'`][^"'`\s]{8,}["'`]/i,
246
+ exclude: ['*.test.*', '*.spec.*', '*.example.*', '*.sample.*', 'README.*', '*.md'],
247
+ severity: 'critical',
248
+ autoFix: 'flag',
249
+ language: null,
250
+ description: 'Potential hardcoded credentials'
251
+ },
252
+
253
+ /**
254
+ * JWT tokens (eyJ prefix indicates base64 JSON header)
255
+ */
256
+ jwt_tokens: {
257
+ pattern: /eyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/,
258
+ exclude: ['*.test.*', '*.spec.*', '*.example.*'],
259
+ severity: 'critical',
260
+ autoFix: 'flag',
261
+ language: null,
262
+ description: 'Hardcoded JWT token'
263
+ },
264
+
265
+ /**
266
+ * OpenAI API keys (sk-... format)
267
+ */
268
+ openai_api_key: {
269
+ pattern: /sk-[a-zA-Z0-9]{32,}/,
270
+ exclude: ['*.test.*', '*.spec.*', '*.example.*'],
271
+ severity: 'critical',
272
+ autoFix: 'flag',
273
+ language: null,
274
+ description: 'Hardcoded OpenAI API key'
275
+ },
276
+
277
+ /**
278
+ * GitHub tokens (personal access tokens, fine-grained tokens, OAuth)
279
+ */
280
+ github_token: {
281
+ pattern: /(ghp_[a-zA-Z0-9]{36}|gho_[a-zA-Z0-9]{36}|ghu_[a-zA-Z0-9]{36}|ghs_[a-zA-Z0-9]{36}|ghr_[a-zA-Z0-9]{36}|github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59})/,
282
+ exclude: ['*.test.*', '*.spec.*', '*.example.*'],
283
+ severity: 'critical',
284
+ autoFix: 'flag',
285
+ language: null,
286
+ description: 'Hardcoded GitHub token'
287
+ },
288
+
289
+ /**
290
+ * AWS credentials (access key IDs and secret keys)
291
+ */
292
+ aws_credentials: {
293
+ pattern: /(AKIA[0-9A-Z]{16}|aws_secret_access_key\s*[:=]\s*["'`][A-Za-z0-9/+=]{40}["'`])/i,
294
+ exclude: ['*.test.*', '*.spec.*', '*.example.*'],
295
+ severity: 'critical',
296
+ autoFix: 'flag',
297
+ language: null,
298
+ description: 'Hardcoded AWS credentials'
299
+ },
300
+
301
+ /**
302
+ * Google Cloud / Firebase API keys and service accounts
303
+ */
304
+ google_api_key: {
305
+ pattern: /(AIza[0-9A-Za-z_-]{35}|[0-9]+-[a-z0-9_]{32}\.apps\.googleusercontent\.com)/,
306
+ exclude: ['*.test.*', '*.spec.*', '*.example.*'],
307
+ severity: 'critical',
308
+ autoFix: 'flag',
309
+ language: null,
310
+ description: 'Hardcoded Google/Firebase API key'
311
+ },
312
+
313
+ /**
314
+ * Stripe API keys (live and test)
315
+ */
316
+ stripe_api_key: {
317
+ pattern: /(sk_live_[a-zA-Z0-9]{24,}|sk_test_[a-zA-Z0-9]{24,}|rk_live_[a-zA-Z0-9]{24,}|rk_test_[a-zA-Z0-9]{24,})/,
318
+ exclude: ['*.test.*', '*.spec.*', '*.example.*'],
319
+ severity: 'critical',
320
+ autoFix: 'flag',
321
+ language: null,
322
+ description: 'Hardcoded Stripe API key'
323
+ },
324
+
325
+ /**
326
+ * Slack tokens (bot, user, webhook)
327
+ */
328
+ slack_token: {
329
+ pattern: /(xoxb-[0-9]{10,}-[0-9]{10,}-[a-zA-Z0-9]{24}|xoxp-[0-9]{10,}-[0-9]{10,}-[a-zA-Z0-9]{24}|xoxa-[0-9]{10,}-[a-zA-Z0-9]{24}|https:\/\/hooks\.slack\.com\/services\/T[A-Z0-9]{8}\/B[A-Z0-9]{8,}\/[a-zA-Z0-9]{24})/,
330
+ exclude: ['*.test.*', '*.spec.*', '*.example.*'],
331
+ severity: 'critical',
332
+ autoFix: 'flag',
333
+ language: null,
334
+ description: 'Hardcoded Slack token or webhook URL'
335
+ },
336
+
337
+ /**
338
+ * Discord tokens and webhook URLs
339
+ */
340
+ discord_token: {
341
+ pattern: /(discord.*["'`][A-Za-z0-9_-]{24}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27}["'`]|https:\/\/discord(?:app)?\.com\/api\/webhooks\/[0-9]+\/[A-Za-z0-9_-]+)/i,
342
+ exclude: ['*.test.*', '*.spec.*', '*.example.*'],
343
+ severity: 'critical',
344
+ autoFix: 'flag',
345
+ language: null,
346
+ description: 'Hardcoded Discord token or webhook'
347
+ },
348
+
349
+ /**
350
+ * SendGrid API key
351
+ */
352
+ sendgrid_api_key: {
353
+ pattern: /SG\.[a-zA-Z0-9_-]{22}\.[a-zA-Z0-9_-]{43}/,
354
+ exclude: ['*.test.*', '*.spec.*', '*.example.*'],
355
+ severity: 'critical',
356
+ autoFix: 'flag',
357
+ language: null,
358
+ description: 'Hardcoded SendGrid API key'
359
+ },
360
+
361
+ /**
362
+ * Twilio credentials
363
+ */
364
+ twilio_credentials: {
365
+ pattern: /(AC[a-f0-9]{32}|SK[a-f0-9]{32})/,
366
+ exclude: ['*.test.*', '*.spec.*', '*.example.*'],
367
+ severity: 'critical',
368
+ autoFix: 'flag',
369
+ language: null,
370
+ description: 'Hardcoded Twilio credentials'
371
+ },
372
+
373
+ /**
374
+ * NPM tokens
375
+ */
376
+ npm_token: {
377
+ pattern: /npm_[a-zA-Z0-9]{36}/,
378
+ exclude: ['*.test.*', '*.spec.*', '*.example.*'],
379
+ severity: 'critical',
380
+ autoFix: 'flag',
381
+ language: null,
382
+ description: 'Hardcoded NPM token'
383
+ },
384
+
385
+ /**
386
+ * Private keys (RSA, DSA, EC, PGP)
387
+ */
388
+ private_key: {
389
+ pattern: /-----BEGIN\s+(RSA\s+)?PRIVATE\s+KEY-----/,
390
+ exclude: ['*.test.*', '*.spec.*', '*.example.*', '*.pem.example'],
391
+ severity: 'critical',
392
+ autoFix: 'flag',
393
+ language: null,
394
+ description: 'Private key in source code'
395
+ },
396
+
397
+ /**
398
+ * Generic high-entropy strings (potential secrets)
399
+ */
400
+ high_entropy_string: {
401
+ pattern: /["'`][A-Za-z0-9+/=_-]{40,}["'`]/,
402
+ exclude: ['*.test.*', '*.spec.*', '*.example.*', '*.lock', 'package-lock.json', 'yarn.lock', 'pnpm-lock.yaml'],
403
+ severity: 'medium',
404
+ autoFix: 'flag',
405
+ language: null,
406
+ description: 'High-entropy string that may be a secret',
407
+ requiresEntropyCheck: true,
408
+ entropyThreshold: 4.5
409
+ },
410
+
411
+ /**
412
+ * Process.exit in libraries
413
+ */
414
+ process_exit: {
415
+ pattern: /process\.exit\(/,
416
+ exclude: ['*.test.*', 'cli.js', 'index.js', 'bin/*'],
417
+ severity: 'high',
418
+ autoFix: 'flag',
419
+ language: 'javascript',
420
+ description: 'process.exit() should not be in library code'
421
+ },
422
+
423
+ /**
424
+ * Bare URLs in code (should use constants)
425
+ */
426
+ bare_urls: {
427
+ pattern: /https?:\/\/[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/,
428
+ exclude: ['*.test.*', '*.md', 'package.json', 'README.*'],
429
+ severity: 'low',
430
+ autoFix: 'flag',
431
+ language: null,
432
+ description: 'Hardcoded URLs that should be configuration'
433
+ }
434
+ };
435
+
436
+ // Freeze the patterns object for V8 optimization
437
+ deepFreeze(slopPatterns);
438
+
439
+ // ============================================================================
440
+ // Pre-indexed Maps for O(1) lookup performance (#18)
441
+ // Built once at module load time, avoiding iteration on every lookup
442
+ // ============================================================================
443
+
444
+ /**
445
+ * Pre-indexed patterns by language
446
+ * Key: language name (or 'universal' for language-agnostic patterns)
447
+ * Value: Object of pattern name -> pattern definition
448
+ */
449
+ const _patternsByLanguage = new Map();
450
+
451
+ /**
452
+ * Pre-indexed patterns by severity
453
+ * Key: severity level ('critical', 'high', 'medium', 'low')
454
+ * Value: Object of pattern name -> pattern definition
455
+ */
456
+ const _patternsBySeverity = new Map();
457
+
458
+ /**
459
+ * Pre-indexed patterns by autoFix strategy
460
+ * Key: autoFix type ('remove', 'replace', 'add_logging', 'flag', 'none')
461
+ * Value: Object of pattern name -> pattern definition
462
+ */
463
+ const _patternsByAutoFix = new Map();
464
+
465
+ /**
466
+ * Set of all available languages for O(1) existence check
467
+ */
468
+ const _availableLanguages = new Set();
469
+
470
+ /**
471
+ * Set of all available severity levels for O(1) existence check
472
+ */
473
+ const _availableSeverities = new Set();
474
+
475
+ // Build indexes at module load time
476
+ (function buildIndexes() {
477
+ for (const [name, pattern] of Object.entries(slopPatterns)) {
478
+ // Index by language
479
+ const lang = pattern.language || 'universal';
480
+ if (!_patternsByLanguage.has(lang)) {
481
+ _patternsByLanguage.set(lang, {});
482
+ }
483
+ _patternsByLanguage.get(lang)[name] = pattern;
484
+ _availableLanguages.add(lang);
485
+
486
+ // Index by severity
487
+ const severity = pattern.severity;
488
+ if (!_patternsBySeverity.has(severity)) {
489
+ _patternsBySeverity.set(severity, {});
490
+ }
491
+ _patternsBySeverity.get(severity)[name] = pattern;
492
+ _availableSeverities.add(severity);
493
+
494
+ // Index by autoFix strategy
495
+ const autoFix = pattern.autoFix || 'none';
496
+ if (!_patternsByAutoFix.has(autoFix)) {
497
+ _patternsByAutoFix.set(autoFix, {});
498
+ }
499
+ _patternsByAutoFix.get(autoFix)[name] = pattern;
500
+ }
501
+ })();
502
+
503
+ // Freeze the index Sets
504
+ Object.freeze(_availableLanguages);
505
+ Object.freeze(_availableSeverities);
506
+
507
+ /**
508
+ * Get patterns for a specific language (O(1) lookup via pre-indexed Map)
509
+ * Includes universal patterns that apply to all languages
510
+ * @param {string} language - Language identifier ('javascript', 'python', 'rust', etc.)
511
+ * @returns {Object} Filtered patterns (language-specific + universal)
512
+ */
513
+ function getPatternsForLanguage(language) {
514
+ const langPatterns = _patternsByLanguage.get(language) || {};
515
+ const universalPatterns = _patternsByLanguage.get('universal') || {};
516
+
517
+ // Merge language-specific with universal patterns
518
+ return { ...universalPatterns, ...langPatterns };
519
+ }
520
+
521
+ /**
522
+ * Get patterns for a specific language only (excludes universal patterns)
523
+ * @param {string} language - Language identifier
524
+ * @returns {Object} Language-specific patterns only
525
+ */
526
+ function getPatternsForLanguageOnly(language) {
527
+ return _patternsByLanguage.get(language) || {};
528
+ }
529
+
530
+ /**
531
+ * Get universal patterns (apply to all languages)
532
+ * @returns {Object} Universal patterns
533
+ */
534
+ function getUniversalPatterns() {
535
+ return _patternsByLanguage.get('universal') || {};
536
+ }
537
+
538
+ /**
539
+ * Get patterns by severity (O(1) lookup via pre-indexed Map)
540
+ * @param {string} severity - Severity level ('critical', 'high', 'medium', 'low')
541
+ * @returns {Object} Filtered patterns
542
+ */
543
+ function getPatternsBySeverity(severity) {
544
+ return _patternsBySeverity.get(severity) || {};
545
+ }
546
+
547
+ /**
548
+ * Get patterns by autoFix strategy (O(1) lookup via pre-indexed Map)
549
+ * @param {string} autoFix - AutoFix strategy ('remove', 'replace', 'add_logging', 'flag', 'none')
550
+ * @returns {Object} Filtered patterns
551
+ */
552
+ function getPatternsByAutoFix(autoFix) {
553
+ return _patternsByAutoFix.get(autoFix) || {};
554
+ }
555
+
556
+ /**
557
+ * Get patterns matching multiple criteria (language AND severity)
558
+ * @param {Object} criteria - Filter criteria
559
+ * @param {string} [criteria.language] - Language filter
560
+ * @param {string} [criteria.severity] - Severity filter
561
+ * @param {string} [criteria.autoFix] - AutoFix strategy filter
562
+ * @returns {Object} Patterns matching all criteria
563
+ */
564
+ function getPatternsByCriteria(criteria = {}) {
565
+ let result = { ...slopPatterns };
566
+
567
+ if (criteria.language) {
568
+ const langPatterns = getPatternsForLanguage(criteria.language);
569
+ result = Object.fromEntries(
570
+ Object.entries(result).filter(([name]) => name in langPatterns)
571
+ );
572
+ }
573
+
574
+ if (criteria.severity) {
575
+ const severityPatterns = getPatternsBySeverity(criteria.severity);
576
+ result = Object.fromEntries(
577
+ Object.entries(result).filter(([name]) => name in severityPatterns)
578
+ );
579
+ }
580
+
581
+ if (criteria.autoFix) {
582
+ const autoFixPatterns = getPatternsByAutoFix(criteria.autoFix);
583
+ result = Object.fromEntries(
584
+ Object.entries(result).filter(([name]) => name in autoFixPatterns)
585
+ );
586
+ }
587
+
588
+ return result;
589
+ }
590
+
591
+ /**
592
+ * Get all available languages
593
+ * @returns {Array<string>} List of language identifiers
594
+ */
595
+ function getAvailableLanguages() {
596
+ return Array.from(_availableLanguages);
597
+ }
598
+
599
+ /**
600
+ * Get all available severity levels
601
+ * @returns {Array<string>} List of severity levels
602
+ */
603
+ function getAvailableSeverities() {
604
+ return Array.from(_availableSeverities);
605
+ }
606
+
607
+ /**
608
+ * Check if patterns exist for a language
609
+ * @param {string} language - Language identifier
610
+ * @returns {boolean} True if patterns exist
611
+ */
612
+ function hasLanguage(language) {
613
+ return _patternsByLanguage.has(language);
614
+ }
615
+
616
+ /**
617
+ * Check if a file should be excluded based on pattern rules
618
+ * Uses pre-compiled regex cache for performance
619
+ * @param {string} filePath - File path to check
620
+ * @param {Array<string>} excludePatterns - Exclude patterns
621
+ * @returns {boolean} True if file should be excluded
622
+ */
623
+ function isFileExcluded(filePath, excludePatterns) {
624
+ if (!excludePatterns || excludePatterns.length === 0) return false;
625
+
626
+ return excludePatterns.some(pattern => {
627
+ const regex = getCompiledPattern(pattern);
628
+ return regex.test(filePath);
629
+ });
630
+ }
631
+
632
+ module.exports = {
633
+ slopPatterns,
634
+ // Pre-indexed lookup functions (O(1) performance)
635
+ getPatternsForLanguage,
636
+ getPatternsForLanguageOnly,
637
+ getUniversalPatterns,
638
+ getPatternsBySeverity,
639
+ getPatternsByAutoFix,
640
+ getPatternsByCriteria,
641
+ // Metadata functions
642
+ getAvailableLanguages,
643
+ getAvailableSeverities,
644
+ hasLanguage,
645
+ // File exclusion
646
+ isFileExcluded
647
+ };