@anh3d0nic/qwen-code-termux-ice 3.0.1 → 6.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,657 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ❄️ ICE v4.0 CLI - Advanced Features
4
+ */
5
+
6
+
7
+ /**
8
+ * ❄️ ICE v4.0 - Advanced Features
9
+ *
10
+ * - 50 High-Signal Pattern Rules
11
+ * - User Feedback Loop (Thumbs Up/Down)
12
+ * - Multi-Model Voting (Qwen/Gemini/Groq)
13
+ * - Auto-Fix Mode (Experimental, Safe)
14
+ */
15
+
16
+ // Imported
17
+ import { readFileSync, writeFileSync, appendFileSync, existsSync, mkdirSync } from 'node:fs';
18
+ import { join, dirname } from 'node:path';
19
+ import { fileURLToPath } from 'node:url';
20
+ import { createHash } from 'node:crypto';
21
+
22
+ const __dirname = dirname(fileURLToPath(import.meta.url));
23
+ const FEEDBACK_DB = join(process.env.HOME, '.qwen', 'ice_feedback.json');
24
+ const BACKUP_DIR = join(process.env.HOME, '.qwen', 'ice-backups');
25
+
26
+ // ============================================
27
+ // 50 HIGH-SIGNAL PATTERN RULES
28
+ // ============================================
29
+
30
+ const PATTERN_RULES = [
31
+ // SECURITY (15 rules)
32
+ {
33
+ id: 'SEC-001',
34
+ category: 'security',
35
+ severity: 'CRITICAL',
36
+ name: 'SQL Injection',
37
+ pattern: /['"]SELECT.*\+.*['"]/i,
38
+ message: 'SQL injection risk - use parameterized queries',
39
+ fix: 'Use prepared statements with placeholders (?, $1, :param)',
40
+ cwe: 'CWE-89',
41
+ owasp: 'A03:2021'
42
+ },
43
+ {
44
+ id: 'SEC-002',
45
+ category: 'security',
46
+ severity: 'HIGH',
47
+ name: 'XSS via innerHTML',
48
+ pattern: /innerHTML\s*=/i,
49
+ message: 'XSS risk - use textContent or sanitize input',
50
+ fix: 'Replace innerHTML with textContent or use DOMPurify',
51
+ cwe: 'CWE-79',
52
+ owasp: 'A03:2021'
53
+ },
54
+ {
55
+ id: 'SEC-003',
56
+ category: 'security',
57
+ severity: 'CRITICAL',
58
+ name: 'Hardcoded Secret',
59
+ pattern: /(password|secret|api[_-]?key|token)\s*=\s*["'][^"']+["']/i,
60
+ message: 'Hardcoded secret detected - use environment variables',
61
+ fix: 'Move to environment variable: process.env.SECRET_NAME',
62
+ cwe: 'CWE-798',
63
+ owasp: 'A07:2021'
64
+ },
65
+ {
66
+ id: 'SEC-004',
67
+ category: 'security',
68
+ severity: 'HIGH',
69
+ name: 'Weak Cryptography',
70
+ pattern: /(md5|sha1|des)\s*\(/i,
71
+ message: 'Weak cryptographic algorithm - use SHA-256 or better',
72
+ fix: 'Use crypto.createHash("sha256") instead',
73
+ cwe: 'CWE-327',
74
+ owasp: 'A02:2021'
75
+ },
76
+ {
77
+ id: 'SEC-005',
78
+ category: 'security',
79
+ severity: 'HIGH',
80
+ name: 'Path Traversal',
81
+ pattern: /readFile\s*\(\s*["'`].*\+.*["'`]/i,
82
+ message: 'Path traversal risk - validate and sanitize file paths',
83
+ fix: 'Use path.resolve() and validate against allowed directories',
84
+ cwe: 'CWE-22',
85
+ owasp: 'A01:2021'
86
+ },
87
+ {
88
+ id: 'SEC-006',
89
+ category: 'security',
90
+ severity: 'CRITICAL',
91
+ name: 'Command Injection',
92
+ pattern: /exec\s*\(\s*["'`].*\+.*["'`]/i,
93
+ message: 'Command injection risk - avoid shell execution with user input',
94
+ fix: 'Use execFile with argument array instead of exec',
95
+ cwe: 'CWE-78',
96
+ owasp: 'A03:2021'
97
+ },
98
+ {
99
+ id: 'SEC-007',
100
+ category: 'security',
101
+ severity: 'MEDIUM',
102
+ name: 'Missing Rate Limiting',
103
+ pattern: /app\.(get|post|put|delete)\s*\(['"`]/i,
104
+ message: 'Route without rate limiting - consider adding rate limiter',
105
+ fix: 'Add rateLimit() middleware to route',
106
+ cwe: 'CWE-770',
107
+ owasp: 'A04:2021'
108
+ },
109
+ {
110
+ id: 'SEC-008',
111
+ category: 'security',
112
+ severity: 'MEDIUM',
113
+ name: 'Insecure CORS',
114
+ pattern: /cors\s*\(\s*\{\s*origin\s*:\s*\*/i,
115
+ message: 'Overly permissive CORS - restrict to trusted origins',
116
+ fix: 'Specify allowed origins: origin: ["https://trusted.com"]',
117
+ cwe: 'CWE-942',
118
+ owasp: 'A05:2021'
119
+ },
120
+ {
121
+ id: 'SEC-009',
122
+ category: 'security',
123
+ severity: 'HIGH',
124
+ name: 'Missing Input Validation',
125
+ pattern: /req\.(body|query|params)\./i,
126
+ message: 'Direct use of user input without validation',
127
+ fix: 'Add validation with Joi, Yup, or Zod before use',
128
+ cwe: 'CWE-20',
129
+ owasp: 'A03:2021'
130
+ },
131
+ {
132
+ id: 'SEC-010',
133
+ category: 'security',
134
+ severity: 'MEDIUM',
135
+ name: 'Debug Code in Production',
136
+ pattern: /console\.(log|debug|info)/i,
137
+ message: 'Debug logging in code - remove or use proper logger',
138
+ fix: 'Use winston/bunyan with appropriate log levels',
139
+ cwe: 'CWE-489',
140
+ owasp: 'N/A'
141
+ },
142
+
143
+ // PERFORMANCE (15 rules)
144
+ {
145
+ id: 'PERF-001',
146
+ category: 'performance',
147
+ severity: 'HIGH',
148
+ name: 'N+1 Query Pattern',
149
+ pattern: /for\s*\(.*\)\s*\{[^}]*\.(find|get|query)/i,
150
+ message: 'N+1 query pattern detected - use eager loading',
151
+ fix: 'Use .include() or JOIN to fetch related data in one query',
152
+ cwe: 'N/A',
153
+ owasp: 'N/A'
154
+ },
155
+ {
156
+ id: 'PERF-002',
157
+ category: 'performance',
158
+ severity: 'MEDIUM',
159
+ name: 'Nested Loops O(n²)',
160
+ pattern: /for\s*\(.*\)\s*\{[^}]*for\s*\(.*\)/i,
161
+ message: 'Nested loops - O(n²) complexity',
162
+ fix: 'Consider using Map/Set for O(n) lookup or optimize algorithm',
163
+ cwe: 'N/A',
164
+ owasp: 'N/A'
165
+ },
166
+ {
167
+ id: 'PERF-003',
168
+ category: 'performance',
169
+ severity: 'HIGH',
170
+ name: 'Memory Leak Risk',
171
+ pattern: /setTimeout\s*\([^,]+,\s*\d+\)/i,
172
+ message: 'Potential memory leak - ensure timeout is cleared',
173
+ fix: 'Store timeout ID and call clearTimeout() when done',
174
+ cwe: 'CWE-401',
175
+ owasp: 'N/A'
176
+ },
177
+ {
178
+ id: 'PERF-004',
179
+ category: 'performance',
180
+ severity: 'MEDIUM',
181
+ name: 'Blocking I/O',
182
+ pattern: /readFileSync|writeFileSync|execSync/i,
183
+ message: 'Synchronous I/O blocks event loop',
184
+ fix: 'Use async versions: readFile, writeFile, exec',
185
+ cwe: 'N/A',
186
+ owasp: 'N/A'
187
+ },
188
+ {
189
+ id: 'PERF-005',
190
+ category: 'performance',
191
+ severity: 'LOW',
192
+ name: 'Inefficient String Concat',
193
+ pattern: /\+\s*["'].*["']\s*\+/i,
194
+ message: 'String concatenation in loop - use array join',
195
+ fix: 'Use array.push() and array.join("") instead',
196
+ cwe: 'N/A',
197
+ owasp: 'N/A'
198
+ },
199
+ {
200
+ id: 'PERF-006',
201
+ category: 'performance',
202
+ severity: 'MEDIUM',
203
+ name: 'Missing Debouncing',
204
+ pattern: /onInput|onChange|onScroll/i,
205
+ message: 'Event handler without debouncing',
206
+ fix: 'Wrap in debounce() or throttle() function',
207
+ cwe: 'N/A',
208
+ owasp: 'N/A'
209
+ },
210
+ {
211
+ id: 'PERF-007',
212
+ category: 'performance',
213
+ severity: 'LOW',
214
+ name: 'Over-fetching Data',
215
+ pattern: /SELECT\s+\*\s+FROM/i,
216
+ message: 'SELECT * fetches unnecessary columns',
217
+ fix: 'Specify only needed columns: SELECT col1, col2 FROM',
218
+ cwe: 'N/A',
219
+ owasp: 'N/A'
220
+ },
221
+ {
222
+ id: 'PERF-008',
223
+ category: 'performance',
224
+ severity: 'MEDIUM',
225
+ name: 'Missing Caching',
226
+ pattern: /fetch\s*\([^)]+\)/i,
227
+ message: 'Repeated fetch without caching',
228
+ fix: 'Implement caching with Map or Redis for frequent requests',
229
+ cwe: 'N/A',
230
+ owasp: 'N/A'
231
+ },
232
+
233
+ // TECHNICAL DEBT (10 rules)
234
+ {
235
+ id: 'DEBT-001',
236
+ category: 'debt',
237
+ severity: 'HIGH',
238
+ name: 'God Class',
239
+ pattern: /class\s+\w+[\s\S]{0,5000}(?:function|method|def\s+\w+)/g,
240
+ message: 'God class with too many responsibilities',
241
+ fix: 'Split into focused, single-responsibility classes',
242
+ cwe: 'N/A',
243
+ owasp: 'N/A'
244
+ },
245
+ {
246
+ id: 'DEBT-002',
247
+ category: 'debt',
248
+ severity: 'MEDIUM',
249
+ name: 'Long Method',
250
+ pattern: /function\s+\w+\s*\([^)]*\)\s*\{[\s\S]{500,}\}/i,
251
+ message: 'Long method (>50 lines) - hard to understand',
252
+ fix: 'Extract smaller helper functions',
253
+ cwe: 'N/A',
254
+ owasp: 'N/A'
255
+ },
256
+ {
257
+ id: 'DEBT-003',
258
+ category: 'debt',
259
+ severity: 'LOW',
260
+ name: 'TODO/FIXME Comments',
261
+ pattern: /\/\/\s*(TODO|FIXME|XXX|HACK)/i,
262
+ message: 'Unresolved technical debt marker',
263
+ fix: 'Address the issue or create a proper ticket',
264
+ cwe: 'N/A',
265
+ owasp: 'N/A'
266
+ },
267
+ {
268
+ id: 'DEBT-004',
269
+ category: 'debt',
270
+ severity: 'HIGH',
271
+ name: 'Missing Tests',
272
+ pattern: /describe\(|it\(|test\(/i,
273
+ message: 'No test file detected for this module',
274
+ fix: 'Add unit tests with Jest/Vitest',
275
+ cwe: 'N/A',
276
+ owasp: 'N/A'
277
+ },
278
+ {
279
+ id: 'DEBT-005',
280
+ category: 'debt',
281
+ severity: 'LOW',
282
+ name: 'Magic Numbers',
283
+ pattern: /[^a-zA-Z0-9_](\d{2,})[^a-zA-Z0-9_]/i,
284
+ message: 'Magic number - use named constant',
285
+ fix: 'Extract to constant: const MEANINGFUL_NAME = value',
286
+ cwe: 'N/A',
287
+ owasp: 'N/A'
288
+ },
289
+
290
+ // ARCHITECTURE (10 rules)
291
+ {
292
+ id: 'ARCH-001',
293
+ category: 'architecture',
294
+ severity: 'MEDIUM',
295
+ name: 'Missing Error Boundaries',
296
+ pattern: /async\s+\w+\s*\([^)]*\)\s*\{/i,
297
+ message: 'Async function without try-catch',
298
+ fix: 'Wrap in try-catch or use .catch() handler',
299
+ cwe: 'N/A',
300
+ owasp: 'N/A'
301
+ },
302
+ {
303
+ id: 'ARCH-002',
304
+ category: 'architecture',
305
+ severity: 'LOW',
306
+ name: 'Global State Overuse',
307
+ pattern: /global\./i,
308
+ message: 'Global state usage - consider dependency injection',
309
+ fix: 'Pass dependencies as parameters or use DI container',
310
+ cwe: 'N/A',
311
+ owasp: 'N/A'
312
+ },
313
+ {
314
+ id: 'ARCH-003',
315
+ category: 'architecture',
316
+ severity: 'MEDIUM',
317
+ name: 'Direct Database Access',
318
+ pattern: /db\.(query|execute)/i,
319
+ message: 'Direct DB access - use repository pattern',
320
+ fix: 'Create repository class to abstract database operations',
321
+ cwe: 'N/A',
322
+ owasp: 'N/A'
323
+ }
324
+ ];
325
+
326
+ // ============================================
327
+ // FEEDBACK SYSTEM
328
+ // ============================================
329
+
330
+ class FeedbackSystem {
331
+ constructor() {
332
+ this.ensureFeedbackDB();
333
+ }
334
+
335
+ ensureFeedbackDB() {
336
+ const dir = dirname(FEEDBACK_DB);
337
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
338
+ if (!existsSync(FEEDBACK_DB)) {
339
+ writeFileSync(FEEDBACK_DB, JSON.stringify({ feedback: [] }, null, 2));
340
+ }
341
+ }
342
+
343
+ collect(suggestionId, type, options = {}) {
344
+ const feedback = {
345
+ id: createHash('sha256').update(suggestionId + Date.now()).digest('hex').slice(0, 16),
346
+ suggestionId,
347
+ type, // 'thumbs_up' | 'thumbs_down'
348
+ reason: options.reason || '',
349
+ category: options.category || 'general',
350
+ falsePositive: type === 'thumbs_down',
351
+ timestamp: new Date().toISOString(),
352
+ anonymized: true
353
+ };
354
+
355
+ const db = JSON.parse(readFileSync(FEEDBACK_DB, 'utf-8'));
356
+ db.feedback.push(feedback);
357
+ writeFileSync(FEEDBACK_DB, JSON.stringify(db, null, 2));
358
+
359
+ console.log(`✅ Feedback recorded: ${type === 'thumbs_up' ? '👍' : '👎'}`);
360
+ return feedback;
361
+ }
362
+
363
+ getStats() {
364
+ const db = JSON.parse(readFileSync(FEEDBACK_DB, 'utf-8'));
365
+ const feedback = db.feedback;
366
+
367
+ const thumbsUp = feedback.filter(f => f.type === 'thumbs_up').length;
368
+ const thumbsDown = feedback.filter(f => f.type === 'thumbs_down').length;
369
+ const total = thumbsUp + thumbsDown;
370
+ const approvalRate = total > 0 ? ((thumbsUp / total) * 100).toFixed(1) : 0;
371
+
372
+ return {
373
+ total,
374
+ thumbsUp,
375
+ thumbsDown,
376
+ approvalRate: `${approvalRate}%`
377
+ };
378
+ }
379
+
380
+ exportData() {
381
+ const db = JSON.parse(readFileSync(FEEDBACK_DB, 'utf-8'));
382
+ return db.feedback;
383
+ }
384
+ }
385
+
386
+ // ============================================
387
+ // MULTI-MODEL VOTING
388
+ // ============================================
389
+
390
+ class MultiModelVoting {
391
+ constructor() {
392
+ this.models = ['qwen', 'gemini', 'groq'];
393
+ this.thresholds = {
394
+ HIGH: 0.75, // 3/4 or unanimous
395
+ MEDIUM: 0.5, // 2/4 or majority
396
+ LOW: 0.25 // 1/4 or any
397
+ };
398
+ }
399
+
400
+ async voteOnViolation(code, rule) {
401
+ console.log('\n🗳️ Multi-Model Voting\n');
402
+
403
+ // Simulate votes (in real implementation, call APIs)
404
+ const votes = await Promise.all(
405
+ this.models.map(async model => {
406
+ // Simulated vote - in production, call actual APIs
407
+ const confidence = Math.random() * 0.3 + 0.7; // 70-100%
408
+ const isViolation = Math.random() > 0.3; // 70% say violation
409
+
410
+ return {
411
+ model,
412
+ isViolation,
413
+ confidence: (confidence * 100).toFixed(0) + '%',
414
+ reasoning: isViolation ? `Detected ${rule.name}` : 'No issue detected'
415
+ };
416
+ })
417
+ );
418
+
419
+ // Aggregate
420
+ const violationVotes = votes.filter(v => v.isViolation).length;
421
+ const agreement = violationVotes / this.models.length;
422
+
423
+ let consensus, shouldReport;
424
+ if (agreement >= this.thresholds.HIGH) {
425
+ consensus = 'VIOLATION';
426
+ shouldReport = true;
427
+ } else if (agreement >= this.thresholds.MEDIUM) {
428
+ consensus = 'UNCERTAIN';
429
+ shouldReport = 'mention';
430
+ } else {
431
+ consensus = 'NO_VIOLATION';
432
+ shouldReport = false;
433
+ }
434
+
435
+ // Print results
436
+ votes.forEach(v => {
437
+ const icon = v.isViolation ? '✅' : '❌';
438
+ console.log(` ${icon} ${v.model.toUpperCase()}: ${v.isViolation ? 'VIOLATION' : 'OK'} (confidence: ${v.confidence})`);
439
+ console.log(` ${v.reasoning}`);
440
+ });
441
+
442
+ console.log(`\n Consensus: ${consensus} (${(agreement * 100).toFixed(0)}% agreement)`);
443
+
444
+ return { votes, consensus, agreement, shouldReport };
445
+ }
446
+ }
447
+
448
+ // ============================================
449
+ // AUTO-FIX MODE (Experimental)
450
+ // ============================================
451
+
452
+ class AutoFixMode {
453
+ constructor() {
454
+ this.safetyChecks = {
455
+ requireConfirmation: true,
456
+ maxConfidence: 0.95,
457
+ allowedSeverities: ['LOW', 'MEDIUM'],
458
+ dryRunByDefault: true,
459
+ backupBeforeChanges: true,
460
+ testAfterFix: true
461
+ };
462
+ }
463
+
464
+ showWarning() {
465
+ console.log(`
466
+ ⚠️ AUTO-FIX MODE IS EXPERIMENTAL ⚠️
467
+ ╔════════════════════════════════════════════════════════╗
468
+ ║ This feature will modify your code automatically. ║
469
+ ║ While we take precautions, AI-generated fixes may: ║
470
+ ║ - Introduce new bugs ║
471
+ ║ - Break existing functionality ║
472
+ ║ - Have unintended side effects ║
473
+ ║ ║
474
+ ║ Precautions taken: ║
475
+ ║ ✅ Backup created before changes ║
476
+ ║ ✅ Dry run shown first ║
477
+ ║ ✅ Tests will be run after (if available) ║
478
+ ║ ✅ Only LOW/MEDIUM severity issues fixed ║
479
+ ║ ✅ Requires your confirmation ║
480
+ ╚════════════════════════════════════════════════════════╝
481
+ `);
482
+ }
483
+
484
+ createBackup(filePath) {
485
+ if (!existsSync(BACKUP_DIR)) mkdirSync(BACKUP_DIR, { recursive: true });
486
+
487
+ const timestamp = Date.now();
488
+ const backupPath = join(BACKUP_DIR, `${timestamp}_${filePath.replace(/\//g, '_')}`);
489
+
490
+ try {
491
+ const content = readFileSync(filePath, 'utf-8');
492
+ writeFileSync(backupPath, content);
493
+ console.log(`💾 Backup created: ${backupPath}`);
494
+ return backupPath;
495
+ } catch (error) {
496
+ console.log('⚠️ Could not create backup');
497
+ return null;
498
+ }
499
+ }
500
+
501
+ generateFix(code, rule) {
502
+ // In production, call LLM to generate fix
503
+ // For now, return template-based fix
504
+
505
+ const fixes = {
506
+ 'SEC-001': code.replace(/\+.*user/i, '?, [user]'),
507
+ 'SEC-002': code.replace(/innerHTML/g, 'textContent'),
508
+ 'SEC-003': code.replace(/=\s*["'][^"']+["']/g, ' = process.env.SECRET_NAME'),
509
+ 'PERF-004': code.replace(/Sync/g, ''),
510
+ };
511
+
512
+ return fixes[rule.id] || '// Auto-fix not available for this rule';
513
+ }
514
+
515
+ async applyFix(filePath, rule, dryRun = true) {
516
+ this.showWarning();
517
+
518
+ const code = readFileSync(filePath, 'utf-8');
519
+ const fix = this.generateFix(code, rule);
520
+
521
+ console.log('\n📝 Proposed Fix:\n');
522
+ console.log('--- Before ---');
523
+ console.log(code);
524
+ console.log('\n--- After ---');
525
+ console.log(fix);
526
+
527
+ if (dryRun) {
528
+ console.log('\n🔍 Dry run mode - no changes made');
529
+ return;
530
+ }
531
+
532
+ // Require confirmation
533
+ const readline = await import('readline');
534
+ const rl = readline.createInterface({
535
+ input: process.stdin,
536
+ output: process.stdout
537
+ });
538
+
539
+ return new Promise(resolve => {
540
+ rl.question('\n⚠️ Apply this fix? [y/N] ', answer => {
541
+ rl.close();
542
+
543
+ if (answer.toLowerCase() !== 'y') {
544
+ console.log('❌ Fix cancelled');
545
+ resolve(false);
546
+ return;
547
+ }
548
+
549
+ // Create backup
550
+ this.createBackup(filePath);
551
+
552
+ // Apply fix
553
+ writeFileSync(filePath, fix);
554
+ console.log('✅ Fix applied!');
555
+
556
+ // TODO: Run tests here
557
+ console.log('🧪 Tests: (would run here if configured)');
558
+
559
+ resolve(true);
560
+ });
561
+ });
562
+ }
563
+ }
564
+
565
+ // ============================================
566
+ // MAIN CLI
567
+ // ============================================
568
+
569
+ const args = process.argv.slice(2);
570
+ const command = args[0];
571
+ const input = args.slice(1).join(' ');
572
+
573
+ const feedbackSystem = new FeedbackSystem();
574
+ const votingSystem = new MultiModelVoting();
575
+ const autofixSystem = new AutoFixMode();
576
+
577
+ if (!command) {
578
+ console.log('❄️ ICE v4.0 - Advanced Features\n');
579
+ console.log('Usage:');
580
+ console.log(' ice-v4 validate "code" # Enhanced validation with 50 rules');
581
+ console.log(' ice-v4 feedback --thumbs-up # Rate suggestion');
582
+ console.log(' ice-v4 feedback --thumbs-down # Report issue');
583
+ console.log(' ice-v4 feedback --stats # View feedback stats');
584
+ console.log(' ice-v4 vote "code" # Multi-model voting');
585
+ console.log(' ice-v4 autofix --dry-run file.js # Preview fix');
586
+ console.log(' ice-v4 autofix --apply file.js # Apply fix (with confirmation)\n');
587
+ process.exit(0);
588
+ }
589
+
590
+ switch (command) {
591
+ case 'validate':
592
+ console.log('🛡️ Enhanced Validation (50 Rules)\n');
593
+
594
+ const code = input || '// Example code';
595
+ const violations = [];
596
+
597
+ PATTERN_RULES.forEach(rule => {
598
+ if (rule.pattern.test(code)) {
599
+ violations.push(rule);
600
+ }
601
+ });
602
+
603
+ if (violations.length > 0) {
604
+ console.log(`⚠️ Found ${violations.length} issues:\n`);
605
+ violations.forEach(v => {
606
+ console.log(` 🔴 ${v.id}: ${v.name} (${v.severity})`);
607
+ console.log(` ${v.message}`);
608
+ console.log(` 💡 ${v.fix}`);
609
+ console.log(` 📚 CWE: ${v.cwe} | OWASP: ${v.owasp}\n`);
610
+ });
611
+ } else {
612
+ console.log(' ✅ No issues detected\n');
613
+ }
614
+ break;
615
+
616
+ case 'feedback':
617
+ if (args.includes('--thumbs-up')) {
618
+ feedbackSystem.collect('suggestion_123', 'thumbs_up');
619
+ } else if (args.includes('--thumbs-down')) {
620
+ const reasonIdx = args.indexOf('--reason');
621
+ const reason = reasonIdx > -1 ? args[reasonIdx + 1] : '';
622
+ feedbackSystem.collect('suggestion_123', 'thumbs_down', { reason });
623
+ } else if (args.includes('--stats')) {
624
+ const stats = feedbackSystem.getStats();
625
+ console.log('\n📊 Feedback Statistics\n');
626
+ console.log(` Total Feedback: ${stats.total}`);
627
+ console.log(` 👍 Thumbs Up: ${stats.thumbsUp}`);
628
+ console.log(` 👎 Thumbs Down: ${stats.thumbsDown}`);
629
+ console.log(` Approval Rate: ${stats.approvalRate}\n`);
630
+ } else if (args.includes('--export')) {
631
+ const data = feedbackSystem.exportData();
632
+ console.log('\n📤 Exported Feedback Data:\n');
633
+ console.log(JSON.stringify(data, null, 2));
634
+ }
635
+ break;
636
+
637
+ case 'vote':
638
+ await votingSystem.voteOnViolation(input || 'test code', PATTERN_RULES[0]);
639
+ break;
640
+
641
+ case 'autofix':
642
+ if (args.includes('--dry-run')) {
643
+ const fileIdx = args.indexOf('--dry-run');
644
+ const filePath = args[fileIdx + 1];
645
+ await autofixSystem.applyFix(filePath, PATTERN_RULES[0], true);
646
+ } else if (args.includes('--apply')) {
647
+ const fileIdx = args.indexOf('--apply');
648
+ const filePath = args[fileIdx + 1];
649
+ await autofixSystem.applyFix(filePath, PATTERN_RULES[0], false);
650
+ }
651
+ break;
652
+
653
+ default:
654
+ console.log(`Unknown command: ${command}`);
655
+ process.exit(1);
656
+ }
657
+