add-skill-kit 3.2.4 → 3.2.6

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 (78) hide show
  1. package/README.md +179 -119
  2. package/bin/lib/commands/help.js +0 -4
  3. package/bin/lib/commands/install.js +129 -9
  4. package/bin/lib/ui.js +1 -1
  5. package/lib/agent-cli/__tests__/adaptive_engine.test.js +190 -0
  6. package/lib/agent-cli/__tests__/integration/cross_script.test.js +222 -0
  7. package/lib/agent-cli/__tests__/integration/full_cycle.test.js +230 -0
  8. package/lib/agent-cli/__tests__/pattern_analyzer.test.js +173 -0
  9. package/lib/agent-cli/__tests__/pre_execution_check.test.js +167 -0
  10. package/lib/agent-cli/__tests__/skill_injector.test.js +191 -0
  11. package/lib/agent-cli/bin/{ag-smart.js → agent.js} +48 -15
  12. package/lib/agent-cli/dashboard/dashboard_server.js +340 -0
  13. package/lib/agent-cli/dashboard/index.html +538 -0
  14. package/lib/agent-cli/lib/audit.js +2 -2
  15. package/lib/agent-cli/lib/auto-learn.js +8 -8
  16. package/lib/agent-cli/lib/eslint-fix.js +1 -1
  17. package/lib/agent-cli/lib/fix.js +5 -5
  18. package/lib/agent-cli/lib/hooks/install-hooks.js +4 -4
  19. package/lib/agent-cli/lib/hooks/lint-learn.js +4 -4
  20. package/lib/agent-cli/lib/learn.js +10 -10
  21. package/lib/agent-cli/lib/recall.js +1 -1
  22. package/lib/agent-cli/lib/settings.js +24 -0
  23. package/lib/agent-cli/lib/skill-learn.js +2 -2
  24. package/lib/agent-cli/lib/stats.js +3 -3
  25. package/lib/agent-cli/lib/ui/dashboard-ui.js +103 -4
  26. package/lib/agent-cli/lib/ui/index.js +36 -6
  27. package/lib/agent-cli/lib/watcher.js +2 -2
  28. package/lib/agent-cli/package.json +4 -4
  29. package/lib/agent-cli/scripts/adaptive_engine.js +381 -0
  30. package/lib/agent-cli/scripts/dashboard_server.js +224 -0
  31. package/lib/agent-cli/scripts/error_sensor.js +565 -0
  32. package/lib/agent-cli/scripts/learn_from_failure.js +225 -0
  33. package/lib/agent-cli/scripts/pattern_analyzer.js +781 -0
  34. package/lib/agent-cli/scripts/pre_execution_check.js +623 -0
  35. package/lib/agent-cli/scripts/rule_sharing.js +374 -0
  36. package/lib/agent-cli/scripts/skill_injector.js +387 -0
  37. package/lib/agent-cli/scripts/success_sensor.js +500 -0
  38. package/lib/agent-cli/scripts/user_correction_sensor.js +426 -0
  39. package/lib/agent-cli/services/auto-learn-service.js +247 -0
  40. package/lib/agent-cli/src/MIGRATION.md +418 -0
  41. package/lib/agent-cli/src/README.md +367 -0
  42. package/lib/agent-cli/src/core/evolution/evolution-signal.js +42 -0
  43. package/lib/agent-cli/src/core/evolution/index.js +17 -0
  44. package/lib/agent-cli/src/core/evolution/review-gate.js +40 -0
  45. package/lib/agent-cli/src/core/evolution/signal-detector.js +137 -0
  46. package/lib/agent-cli/src/core/evolution/signal-queue.js +79 -0
  47. package/lib/agent-cli/src/core/evolution/threshold-checker.js +79 -0
  48. package/lib/agent-cli/src/core/index.js +15 -0
  49. package/lib/agent-cli/src/core/learning/cognitive-enhancer.js +282 -0
  50. package/lib/agent-cli/src/core/learning/index.js +12 -0
  51. package/lib/agent-cli/src/core/learning/lesson-synthesizer.js +83 -0
  52. package/lib/agent-cli/src/core/scanning/index.js +14 -0
  53. package/lib/agent-cli/src/data/index.js +13 -0
  54. package/lib/agent-cli/src/data/repositories/index.js +8 -0
  55. package/lib/agent-cli/src/data/repositories/lesson-repository.js +130 -0
  56. package/lib/agent-cli/src/data/repositories/signal-repository.js +119 -0
  57. package/lib/agent-cli/src/data/storage/index.js +8 -0
  58. package/lib/agent-cli/src/data/storage/json-storage.js +64 -0
  59. package/lib/agent-cli/src/data/storage/yaml-storage.js +66 -0
  60. package/lib/agent-cli/src/infrastructure/index.js +13 -0
  61. package/lib/agent-cli/src/presentation/formatters/skill-formatter.js +232 -0
  62. package/lib/agent-cli/src/services/export-service.js +162 -0
  63. package/lib/agent-cli/src/services/index.js +13 -0
  64. package/lib/agent-cli/src/services/learning-service.js +99 -0
  65. package/lib/agent-cli/types/index.d.ts +343 -0
  66. package/lib/agent-cli/utils/benchmark.js +269 -0
  67. package/lib/agent-cli/utils/logger.js +303 -0
  68. package/lib/agent-cli/utils/ml_patterns.js +300 -0
  69. package/lib/agent-cli/utils/recovery.js +312 -0
  70. package/lib/agent-cli/utils/telemetry.js +290 -0
  71. package/lib/agentskillskit-cli/ag-smart.js +15 -15
  72. package/lib/agentskillskit-cli/package.json +3 -3
  73. package/package.json +12 -6
  74. package/lib/agent-cli/lib/auto_preview.py +0 -148
  75. package/lib/agent-cli/lib/checklist.py +0 -222
  76. package/lib/agent-cli/lib/session_manager.py +0 -120
  77. package/lib/agent-cli/lib/verify_all.py +0 -327
  78. /package/bin/{cli.js → kit.js} +0 -0
@@ -0,0 +1,565 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Error Sensor - Auto-detect errors from multiple sources
4
+ *
5
+ * Part of FAANG-Grade Auto-Learn System Phase 1
6
+ *
7
+ * Sensors:
8
+ * - test: Parse vitest/jest output
9
+ * - build: Parse tsc/webpack errors
10
+ * - lint: Parse eslint warnings
11
+ * - runtime: Capture console.error/exceptions
12
+ *
13
+ * Usage:
14
+ * node error_sensor.js --scan test
15
+ * node error_sensor.js --scan build
16
+ * node error_sensor.js --scan lint
17
+ * node error_sensor.js --scan all
18
+ * node error_sensor.js --watch
19
+ */
20
+
21
+ import fs from 'fs';
22
+ import path from 'path';
23
+ import { execSync } from 'child_process';
24
+ import { fileURLToPath } from 'url';
25
+
26
+ const __filename = fileURLToPath(import.meta.url);
27
+ const __dirname = path.dirname(__filename);
28
+
29
+ // Colors
30
+ const c = {
31
+ reset: '\x1b[0m',
32
+ red: '\x1b[31m',
33
+ green: '\x1b[32m',
34
+ yellow: '\x1b[33m',
35
+ blue: '\x1b[34m',
36
+ cyan: '\x1b[36m',
37
+ gray: '\x1b[90m',
38
+ bold: '\x1b[1m'
39
+ };
40
+
41
+ // Find project root
42
+ function findProjectRoot() {
43
+ let current = process.cwd();
44
+ while (current !== path.dirname(current)) {
45
+ if (fs.existsSync(path.join(current, '.agent'))) {
46
+ return current;
47
+ }
48
+ current = path.dirname(current);
49
+ }
50
+ return process.cwd();
51
+ }
52
+
53
+ const projectRoot = findProjectRoot();
54
+ const knowledgePath = path.join(projectRoot, '.agent', 'knowledge');
55
+ const errorsPath = path.join(knowledgePath, 'detected-errors.json');
56
+ const lessonsPath = path.join(knowledgePath, 'lessons-learned.json');
57
+
58
+ // Ensure files exist
59
+ function ensureFiles() {
60
+ if (!fs.existsSync(knowledgePath)) {
61
+ fs.mkdirSync(knowledgePath, { recursive: true });
62
+ }
63
+ if (!fs.existsSync(errorsPath)) {
64
+ fs.writeFileSync(errorsPath, JSON.stringify({
65
+ _comment: "Auto-detected errors by error_sensor",
66
+ errors: [],
67
+ lastScan: null
68
+ }, null, 2));
69
+ }
70
+ }
71
+
72
+ // Load detected errors
73
+ function loadErrors() {
74
+ ensureFiles();
75
+ try {
76
+ const data = JSON.parse(fs.readFileSync(errorsPath, 'utf8'));
77
+ return data.errors || [];
78
+ } catch {
79
+ return [];
80
+ }
81
+ }
82
+
83
+ // Save detected errors
84
+ function saveErrors(errors) {
85
+ ensureFiles();
86
+ const data = {
87
+ _comment: "Auto-detected errors by error_sensor",
88
+ lastScan: new Date().toISOString(),
89
+ totalErrors: errors.length,
90
+ errors
91
+ };
92
+ fs.writeFileSync(errorsPath, JSON.stringify(data, null, 2));
93
+ }
94
+
95
+ // Add error to collection
96
+ function addError(error) {
97
+ const errors = loadErrors();
98
+
99
+ // Check for duplicates (same type + message within last hour)
100
+ const oneHourAgo = Date.now() - 3600000;
101
+ const isDuplicate = errors.some(e =>
102
+ e.type === error.type &&
103
+ e.message === error.message &&
104
+ new Date(e.timestamp).getTime() > oneHourAgo
105
+ );
106
+
107
+ if (!isDuplicate) {
108
+ errors.push({
109
+ id: `ERR-${Date.now()}`,
110
+ ...error,
111
+ timestamp: new Date().toISOString()
112
+ });
113
+ saveErrors(errors);
114
+ return true;
115
+ }
116
+ return false;
117
+ }
118
+
119
+ // ==================== CONTEXT DETECTION ====================
120
+
121
+ /**
122
+ * Detect project context from package.json and folder structure
123
+ */
124
+ function detectProjectContext() {
125
+ const context = {
126
+ projectType: 'unknown',
127
+ framework: null,
128
+ language: 'javascript',
129
+ hasTypeScript: false,
130
+ hasTesting: false
131
+ };
132
+
133
+ try {
134
+ const pkgPath = path.join(projectRoot, 'package.json');
135
+ if (fs.existsSync(pkgPath)) {
136
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
137
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
138
+
139
+ // Detect project type
140
+ if (deps['next']) {
141
+ context.projectType = 'nextjs';
142
+ context.framework = 'next';
143
+ } else if (deps['react-native'] || deps['expo']) {
144
+ context.projectType = 'react-native';
145
+ context.framework = 'react-native';
146
+ } else if (deps['react']) {
147
+ context.projectType = 'react';
148
+ context.framework = 'react';
149
+ } else if (deps['vue']) {
150
+ context.projectType = 'vue';
151
+ context.framework = 'vue';
152
+ } else if (deps['express'] || deps['fastify'] || deps['koa']) {
153
+ context.projectType = 'backend';
154
+ context.framework = deps['express'] ? 'express' : deps['fastify'] ? 'fastify' : 'koa';
155
+ }
156
+
157
+ // Detect TypeScript
158
+ if (deps['typescript'] || fs.existsSync(path.join(projectRoot, 'tsconfig.json'))) {
159
+ context.hasTypeScript = true;
160
+ context.language = 'typescript';
161
+ }
162
+
163
+ // Detect testing framework
164
+ if (deps['vitest'] || deps['jest'] || deps['mocha']) {
165
+ context.hasTesting = true;
166
+ }
167
+ }
168
+ } catch { }
169
+
170
+ return context;
171
+ }
172
+
173
+ /**
174
+ * Detect file context from file path
175
+ */
176
+ function detectFileContext(filePath) {
177
+ const ext = path.extname(filePath).toLowerCase();
178
+ const dir = path.dirname(filePath);
179
+ const relativePath = path.relative(projectRoot, filePath);
180
+
181
+ const context = {
182
+ fileType: ext,
183
+ isTypeScript: ext === '.ts' || ext === '.tsx',
184
+ isTest: /\.(test|spec)\./i.test(filePath) || relativePath.includes('__tests__'),
185
+ isComponent: ext === '.tsx' || ext === '.jsx',
186
+ directory: relativePath.split(path.sep)[0] || 'root',
187
+ fullPath: relativePath
188
+ };
189
+
190
+ // Detect specific directories
191
+ if (relativePath.startsWith('src')) {
192
+ context.area = 'source';
193
+ } else if (relativePath.startsWith('lib')) {
194
+ context.area = 'library';
195
+ } else if (relativePath.startsWith('test') || relativePath.startsWith('__tests__')) {
196
+ context.area = 'test';
197
+ } else if (relativePath.startsWith('scripts')) {
198
+ context.area = 'scripts';
199
+ } else {
200
+ context.area = 'other';
201
+ }
202
+
203
+ return context;
204
+ }
205
+
206
+ /**
207
+ * Add context to error object
208
+ */
209
+ function addErrorWithContext(error) {
210
+ const projectContext = detectProjectContext();
211
+ const fileContext = error.file ? detectFileContext(error.file) : null;
212
+
213
+ const enrichedError = {
214
+ ...error,
215
+ context: {
216
+ project: projectContext,
217
+ file: fileContext
218
+ }
219
+ };
220
+
221
+ return addError(enrichedError);
222
+ }
223
+
224
+ // ==================== SENSORS ====================
225
+
226
+ /**
227
+ * Parse test output (vitest/jest)
228
+ */
229
+ function scanTestErrors() {
230
+ const errors = [];
231
+
232
+ try {
233
+ // Try to run tests and capture output
234
+ const testOutput = execSync('npm test 2>&1', {
235
+ cwd: projectRoot,
236
+ encoding: 'utf8',
237
+ timeout: 60000
238
+ });
239
+
240
+ // Parse vitest output
241
+ const failedTests = testOutput.match(/FAIL\s+(.+)/g) || [];
242
+ const errorMessages = testOutput.match(/Error:\s*(.+)/g) || [];
243
+ const assertionFails = testOutput.match(/expect\(.+\)\.(.+)/g) || [];
244
+
245
+ for (const fail of failedTests) {
246
+ errors.push({
247
+ type: 'test',
248
+ source: 'vitest',
249
+ message: fail.trim(),
250
+ severity: 'HIGH',
251
+ raw: fail
252
+ });
253
+ }
254
+
255
+ for (const err of errorMessages) {
256
+ errors.push({
257
+ type: 'test',
258
+ source: 'vitest',
259
+ message: err.replace('Error:', '').trim(),
260
+ severity: 'HIGH',
261
+ raw: err
262
+ });
263
+ }
264
+
265
+ } catch (e) {
266
+ // Test command failed - parse error output
267
+ const output = e.stdout || e.stderr || '';
268
+ const lines = output.split('\n');
269
+
270
+ for (const line of lines) {
271
+ if (line.includes('FAIL') || line.includes('Error') || line.includes('✗')) {
272
+ errors.push({
273
+ type: 'test',
274
+ source: 'vitest',
275
+ message: line.trim(),
276
+ severity: 'HIGH',
277
+ raw: line
278
+ });
279
+ }
280
+ }
281
+ }
282
+
283
+ return errors;
284
+ }
285
+
286
+ /**
287
+ * Parse build errors (TypeScript)
288
+ */
289
+ function scanBuildErrors() {
290
+ const errors = [];
291
+
292
+ try {
293
+ execSync('npx tsc --noEmit 2>&1', {
294
+ cwd: projectRoot,
295
+ encoding: 'utf8',
296
+ timeout: 60000
297
+ });
298
+ } catch (e) {
299
+ const output = e.stdout || e.stderr || '';
300
+ // Parse TypeScript errors: file.ts(line,col): error TS1234: message
301
+ const tsErrors = output.match(/(.+\.tsx?)\((\d+),(\d+)\):\s*error\s+(TS\d+):\s*(.+)/g) || [];
302
+
303
+ for (const err of tsErrors) {
304
+ const match = err.match(/(.+\.tsx?)\((\d+),(\d+)\):\s*error\s+(TS\d+):\s*(.+)/);
305
+ if (match) {
306
+ errors.push({
307
+ type: 'build',
308
+ source: 'typescript',
309
+ file: match[1],
310
+ line: parseInt(match[2]),
311
+ code: match[4],
312
+ message: match[5],
313
+ severity: 'HIGH',
314
+ raw: err
315
+ });
316
+ }
317
+ }
318
+ }
319
+
320
+ return errors;
321
+ }
322
+
323
+ /**
324
+ * Parse lint errors (ESLint)
325
+ */
326
+ function scanLintErrors() {
327
+ const errors = [];
328
+
329
+ try {
330
+ execSync('npm run lint 2>&1', {
331
+ cwd: projectRoot,
332
+ encoding: 'utf8',
333
+ timeout: 60000
334
+ });
335
+ } catch (e) {
336
+ const output = e.stdout || e.stderr || '';
337
+ // Parse ESLint output: file.js:line:col error/warning message rule
338
+ const lintErrors = output.match(/(.+):(\d+):(\d+)\s+(error|warning)\s+(.+?)\s{2,}(.+)/g) || [];
339
+
340
+ for (const err of lintErrors) {
341
+ const match = err.match(/(.+):(\d+):(\d+)\s+(error|warning)\s+(.+?)\s{2,}(.+)/);
342
+ if (match) {
343
+ errors.push({
344
+ type: 'lint',
345
+ source: 'eslint',
346
+ file: match[1],
347
+ line: parseInt(match[2]),
348
+ level: match[4],
349
+ message: match[5],
350
+ rule: match[6],
351
+ severity: match[4] === 'error' ? 'HIGH' : 'MEDIUM',
352
+ raw: err
353
+ });
354
+ }
355
+ }
356
+ }
357
+
358
+ return errors;
359
+ }
360
+
361
+ /**
362
+ * Scan for common code patterns that indicate errors
363
+ */
364
+ function scanCodePatterns() {
365
+ const errors = [];
366
+ const srcDirs = ['src', 'lib', 'app', 'components', 'pages'];
367
+
368
+ for (const dir of srcDirs) {
369
+ const fullPath = path.join(projectRoot, dir);
370
+ if (!fs.existsSync(fullPath)) continue;
371
+
372
+ // Recursively scan files
373
+ const files = getAllFiles(fullPath, ['.js', '.ts', '.jsx', '.tsx']);
374
+
375
+ for (const file of files) {
376
+ const content = fs.readFileSync(file, 'utf8');
377
+ const lines = content.split('\n');
378
+
379
+ lines.forEach((line, idx) => {
380
+ // Detect console.error
381
+ if (line.includes('console.error')) {
382
+ errors.push({
383
+ type: 'pattern',
384
+ source: 'code-scan',
385
+ file: file,
386
+ line: idx + 1,
387
+ message: 'console.error detected',
388
+ severity: 'LOW',
389
+ raw: line.trim()
390
+ });
391
+ }
392
+
393
+ // Detect TODO/FIXME with error keywords
394
+ if (/\/\/\s*(TODO|FIXME|BUG|HACK).*error/i.test(line)) {
395
+ errors.push({
396
+ type: 'pattern',
397
+ source: 'code-scan',
398
+ file: file,
399
+ line: idx + 1,
400
+ message: 'TODO/FIXME with error keyword',
401
+ severity: 'MEDIUM',
402
+ raw: line.trim()
403
+ });
404
+ }
405
+
406
+ // Detect empty catch blocks
407
+ if (/catch\s*\([^)]*\)\s*{\s*}/.test(line)) {
408
+ errors.push({
409
+ type: 'pattern',
410
+ source: 'code-scan',
411
+ file: file,
412
+ line: idx + 1,
413
+ message: 'Empty catch block - errors silently swallowed',
414
+ severity: 'HIGH',
415
+ raw: line.trim()
416
+ });
417
+ }
418
+ });
419
+ }
420
+ }
421
+
422
+ return errors;
423
+ }
424
+
425
+ // Helper: Get all files recursively
426
+ function getAllFiles(dir, extensions) {
427
+ const files = [];
428
+
429
+ try {
430
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
431
+
432
+ for (const entry of entries) {
433
+ const fullPath = path.join(dir, entry.name);
434
+
435
+ if (entry.isDirectory() && !entry.name.startsWith('.') && entry.name !== 'node_modules') {
436
+ files.push(...getAllFiles(fullPath, extensions));
437
+ } else if (entry.isFile() && extensions.some(ext => entry.name.endsWith(ext))) {
438
+ files.push(fullPath);
439
+ }
440
+ }
441
+ } catch {
442
+ // Ignore permission errors
443
+ }
444
+
445
+ return files;
446
+ }
447
+
448
+ // ==================== MAIN ====================
449
+
450
+ function runScan(type) {
451
+ console.log(`${c.cyan}🔍 Error Sensor - Scanning ${type}...${c.reset}\n`);
452
+
453
+ let allErrors = [];
454
+
455
+ if (type === 'all' || type === 'test') {
456
+ console.log(`${c.gray} Scanning test output...${c.reset}`);
457
+ const testErrors = scanTestErrors();
458
+ allErrors.push(...testErrors);
459
+ console.log(`${c.gray} Found ${testErrors.length} test errors${c.reset}`);
460
+ }
461
+
462
+ if (type === 'all' || type === 'build') {
463
+ console.log(`${c.gray} Scanning build output...${c.reset}`);
464
+ const buildErrors = scanBuildErrors();
465
+ allErrors.push(...buildErrors);
466
+ console.log(`${c.gray} Found ${buildErrors.length} build errors${c.reset}`);
467
+ }
468
+
469
+ if (type === 'all' || type === 'lint') {
470
+ console.log(`${c.gray} Scanning lint output...${c.reset}`);
471
+ const lintErrors = scanLintErrors();
472
+ allErrors.push(...lintErrors);
473
+ console.log(`${c.gray} Found ${lintErrors.length} lint errors${c.reset}`);
474
+ }
475
+
476
+ if (type === 'all' || type === 'pattern') {
477
+ console.log(`${c.gray} Scanning code patterns...${c.reset}`);
478
+ const patternErrors = scanCodePatterns();
479
+ allErrors.push(...patternErrors);
480
+ console.log(`${c.gray} Found ${patternErrors.length} pattern issues${c.reset}`);
481
+ }
482
+
483
+ // Save detected errors
484
+ let newCount = 0;
485
+ for (const error of allErrors) {
486
+ if (addError(error)) {
487
+ newCount++;
488
+ }
489
+ }
490
+
491
+ console.log(`\n${c.cyan}════════════════════════════════════════${c.reset}`);
492
+ console.log(`${c.bold}Scan Complete${c.reset}`);
493
+ console.log(` Total detected: ${allErrors.length}`);
494
+ console.log(` New errors: ${c.yellow}${newCount}${c.reset}`);
495
+ console.log(` Saved to: ${c.gray}${errorsPath}${c.reset}`);
496
+ console.log(`${c.cyan}════════════════════════════════════════${c.reset}`);
497
+
498
+ return allErrors;
499
+ }
500
+
501
+ function showStats() {
502
+ const errors = loadErrors();
503
+
504
+ console.log(`${c.cyan}╔════════════════════════════════════════╗${c.reset}`);
505
+ console.log(`${c.cyan}║${c.reset} 📊 Error Sensor Statistics ${c.cyan}║${c.reset}`);
506
+ console.log(`${c.cyan}╚════════════════════════════════════════╝${c.reset}\n`);
507
+
508
+ // Group by type
509
+ const byType = {};
510
+ const bySeverity = {};
511
+
512
+ for (const err of errors) {
513
+ byType[err.type] = (byType[err.type] || 0) + 1;
514
+ bySeverity[err.severity] = (bySeverity[err.severity] || 0) + 1;
515
+ }
516
+
517
+ console.log(`${c.bold}By Type:${c.reset}`);
518
+ for (const [type, count] of Object.entries(byType)) {
519
+ console.log(` ${type}: ${count}`);
520
+ }
521
+
522
+ console.log(`\n${c.bold}By Severity:${c.reset}`);
523
+ for (const [sev, count] of Object.entries(bySeverity)) {
524
+ const color = { CRITICAL: c.red, HIGH: c.yellow, MEDIUM: c.blue, LOW: c.gray }[sev] || c.gray;
525
+ console.log(` ${color}${sev}${c.reset}: ${count}`);
526
+ }
527
+
528
+ console.log(`\n${c.gray}Total errors tracked: ${errors.length}${c.reset}`);
529
+ }
530
+
531
+ // Parse CLI args
532
+ const args = process.argv.slice(2);
533
+
534
+ if (args.includes('--scan') || args.includes('-s')) {
535
+ const idx = args.findIndex(a => a === '--scan' || a === '-s');
536
+ const type = args[idx + 1] || 'all';
537
+ runScan(type);
538
+ } else if (args.includes('--stats')) {
539
+ showStats();
540
+ } else if (args.includes('--clear')) {
541
+ saveErrors([]);
542
+ console.log(`${c.green}✓ Cleared all detected errors${c.reset}`);
543
+ } else {
544
+ console.log(`${c.cyan}error_sensor - Auto-detect errors from test/build/lint${c.reset}
545
+
546
+ ${c.bold}Usage:${c.reset}
547
+ node error_sensor.js --scan <type> Scan for errors
548
+ node error_sensor.js --stats Show error statistics
549
+ node error_sensor.js --clear Clear recorded errors
550
+
551
+ ${c.bold}Scan types:${c.reset}
552
+ test Scan test output (vitest/jest)
553
+ build Scan TypeScript errors
554
+ lint Scan ESLint errors
555
+ pattern Scan code for error patterns
556
+ all Scan all sources (default)
557
+
558
+ ${c.bold}Examples:${c.reset}
559
+ node error_sensor.js --scan all
560
+ node error_sensor.js --scan test
561
+ node error_sensor.js --stats
562
+ `);
563
+ }
564
+
565
+ export { runScan, scanTestErrors, scanBuildErrors, scanLintErrors, scanCodePatterns, loadErrors };