add-skill-kit 3.2.4 → 3.2.5

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 (74) hide show
  1. package/README.md +1 -1
  2. package/bin/lib/commands/help.js +0 -4
  3. package/bin/lib/commands/install.js +90 -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 +11 -5
  74. /package/bin/{cli.js → kit.js} +0 -0
@@ -0,0 +1,426 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * User Correction Sensor - Detect when user corrects AI-generated code
4
+ *
5
+ * Part of FAANG-Grade Auto-Learn System Phase 1
6
+ *
7
+ * Monitors git diff to detect:
8
+ * - Files modified shortly after AI generation
9
+ * - Common correction patterns
10
+ * - Import/path fixes
11
+ *
12
+ * Usage:
13
+ * node user_correction_sensor.js --scan
14
+ * node user_correction_sensor.js --recent 1h
15
+ * node user_correction_sensor.js --stats
16
+ */
17
+
18
+ import fs from 'fs';
19
+ import path from 'path';
20
+ import { execSync } from 'child_process';
21
+ import { fileURLToPath } from 'url';
22
+
23
+ const __filename = fileURLToPath(import.meta.url);
24
+ const __dirname = path.dirname(__filename);
25
+
26
+ // Colors
27
+ const c = {
28
+ reset: '\x1b[0m',
29
+ red: '\x1b[31m',
30
+ green: '\x1b[32m',
31
+ yellow: '\x1b[33m',
32
+ blue: '\x1b[34m',
33
+ cyan: '\x1b[36m',
34
+ gray: '\x1b[90m',
35
+ bold: '\x1b[1m'
36
+ };
37
+
38
+ // Find project root
39
+ function findProjectRoot() {
40
+ let current = process.cwd();
41
+ while (current !== path.dirname(current)) {
42
+ if (fs.existsSync(path.join(current, '.agent'))) {
43
+ return current;
44
+ }
45
+ current = path.dirname(current);
46
+ }
47
+ return process.cwd();
48
+ }
49
+
50
+ const projectRoot = findProjectRoot();
51
+ const knowledgePath = path.join(projectRoot, '.agent', 'knowledge');
52
+ const correctionsPath = path.join(knowledgePath, 'user-corrections.json');
53
+
54
+ // Ensure files exist
55
+ function ensureFiles() {
56
+ if (!fs.existsSync(knowledgePath)) {
57
+ fs.mkdirSync(knowledgePath, { recursive: true });
58
+ }
59
+ if (!fs.existsSync(correctionsPath)) {
60
+ fs.writeFileSync(correctionsPath, JSON.stringify({
61
+ _comment: "User corrections detected by correction_sensor",
62
+ corrections: [],
63
+ lastScan: null
64
+ }, null, 2));
65
+ }
66
+ }
67
+
68
+ // Load corrections
69
+ function loadCorrections() {
70
+ ensureFiles();
71
+ try {
72
+ const data = JSON.parse(fs.readFileSync(correctionsPath, 'utf8'));
73
+ return data.corrections || [];
74
+ } catch {
75
+ return [];
76
+ }
77
+ }
78
+
79
+ // Save corrections
80
+ function saveCorrections(corrections) {
81
+ ensureFiles();
82
+ const data = {
83
+ _comment: "User corrections detected by correction_sensor",
84
+ lastScan: new Date().toISOString(),
85
+ totalCorrections: corrections.length,
86
+ corrections
87
+ };
88
+ fs.writeFileSync(correctionsPath, JSON.stringify(data, null, 2));
89
+ }
90
+
91
+ // Add correction
92
+ function addCorrection(correction) {
93
+ const corrections = loadCorrections();
94
+
95
+ // Check for duplicates
96
+ const isDuplicate = corrections.some(c =>
97
+ c.file === correction.file &&
98
+ c.pattern === correction.pattern
99
+ );
100
+
101
+ if (!isDuplicate) {
102
+ corrections.push({
103
+ id: `COR-${Date.now()}`,
104
+ ...correction,
105
+ timestamp: new Date().toISOString()
106
+ });
107
+ saveCorrections(corrections);
108
+ return true;
109
+ }
110
+ return false;
111
+ }
112
+
113
+ // Common correction patterns to detect
114
+ const CORRECTION_PATTERNS = [
115
+ {
116
+ name: 'import_path_fix',
117
+ regex: /^[-+].*import.*from\s+['"](\.+\/|@)/,
118
+ description: 'Import path correction',
119
+ severity: 'HIGH'
120
+ },
121
+ {
122
+ name: 'type_annotation_fix',
123
+ regex: /^[-+].*:\s*(string|number|boolean|any|unknown|void)\b/,
124
+ description: 'Type annotation correction',
125
+ severity: 'MEDIUM'
126
+ },
127
+ {
128
+ name: 'null_check_added',
129
+ regex: /^\+.*(\?\.|!= null|!== null|\?\?)/,
130
+ description: 'Null check added',
131
+ severity: 'HIGH'
132
+ },
133
+ {
134
+ name: 'async_await_fix',
135
+ regex: /^[-+].*(async|await)\b/,
136
+ description: 'Async/await correction',
137
+ severity: 'HIGH'
138
+ },
139
+ {
140
+ name: 'variable_rename',
141
+ regex: /^-.*const\s+(\w+).*\n^\+.*const\s+(\w+)/m,
142
+ description: 'Variable renamed',
143
+ severity: 'MEDIUM'
144
+ },
145
+ {
146
+ name: 'error_handling_added',
147
+ regex: /^\+.*(try\s*{|catch\s*\(|\.catch\()/,
148
+ description: 'Error handling added',
149
+ severity: 'HIGH'
150
+ },
151
+ {
152
+ name: 'dependency_added',
153
+ regex: /^\+.*"[^"]+"\s*:\s*"[~^]?\d/,
154
+ description: 'Dependency added',
155
+ severity: 'MEDIUM'
156
+ },
157
+ {
158
+ name: 'condition_fix',
159
+ regex: /^[-+].*if\s*\(/,
160
+ description: 'Condition logic correction',
161
+ severity: 'HIGH'
162
+ },
163
+ {
164
+ name: 'return_value_fix',
165
+ regex: /^[-+].*return\s+/,
166
+ description: 'Return value correction',
167
+ severity: 'HIGH'
168
+ },
169
+ {
170
+ name: 'spelling_fix',
171
+ regex: /^-.*(\w+).*\n^\+.*\1[a-z]/i,
172
+ description: 'Spelling/typo fix',
173
+ severity: 'LOW'
174
+ }
175
+ ];
176
+
177
+ /**
178
+ * Get git diff from recent changes
179
+ */
180
+ function getRecentDiff(since = '1 hour ago') {
181
+ try {
182
+ // Get diff of uncommitted changes
183
+ const staged = execSync('git diff --cached', {
184
+ cwd: projectRoot,
185
+ encoding: 'utf8',
186
+ maxBuffer: 10 * 1024 * 1024
187
+ });
188
+
189
+ const unstaged = execSync('git diff', {
190
+ cwd: projectRoot,
191
+ encoding: 'utf8',
192
+ maxBuffer: 10 * 1024 * 1024
193
+ });
194
+
195
+ return staged + '\n' + unstaged;
196
+ } catch {
197
+ return '';
198
+ }
199
+ }
200
+
201
+ /**
202
+ * Parse diff and detect correction patterns
203
+ */
204
+ function detectCorrections(diffOutput) {
205
+ const corrections = [];
206
+ const files = diffOutput.split(/^diff --git/m).slice(1);
207
+
208
+ for (const fileDiff of files) {
209
+ // Extract file name
210
+ const fileMatch = fileDiff.match(/a\/(.+)\s+b\//);
211
+ if (!fileMatch) continue;
212
+
213
+ const fileName = fileMatch[1];
214
+
215
+ // Skip non-code files
216
+ if (!/\.(js|ts|jsx|tsx|json|py|rb|go)$/.test(fileName)) continue;
217
+
218
+ // Get the actual diff content
219
+ const diffContent = fileDiff.split('\n').filter(l => l.startsWith('+') || l.startsWith('-'));
220
+
221
+ // Check each pattern
222
+ for (const pattern of CORRECTION_PATTERNS) {
223
+ for (const line of diffContent) {
224
+ if (pattern.regex.test(line)) {
225
+ corrections.push({
226
+ file: fileName,
227
+ pattern: pattern.name,
228
+ description: pattern.description,
229
+ severity: pattern.severity,
230
+ line: line.substring(0, 100), // Truncate for storage
231
+ category: categorizeCorrection(pattern.name)
232
+ });
233
+ break; // One match per pattern per file
234
+ }
235
+ }
236
+ }
237
+ }
238
+
239
+ return corrections;
240
+ }
241
+
242
+ /**
243
+ * Categorize correction for pattern analysis
244
+ */
245
+ function categorizeCorrection(patternName) {
246
+ const categories = {
247
+ import_path_fix: 'imports',
248
+ type_annotation_fix: 'types',
249
+ null_check_added: 'null-safety',
250
+ async_await_fix: 'async',
251
+ variable_rename: 'naming',
252
+ error_handling_added: 'error-handling',
253
+ dependency_added: 'dependencies',
254
+ condition_fix: 'logic',
255
+ return_value_fix: 'logic',
256
+ spelling_fix: 'typo'
257
+ };
258
+ return categories[patternName] || 'other';
259
+ }
260
+
261
+ /**
262
+ * Analyze corrections to find patterns
263
+ */
264
+ function analyzePatterns(corrections) {
265
+ const byCategory = {};
266
+ const byFile = {};
267
+
268
+ for (const corr of corrections) {
269
+ // By category
270
+ byCategory[corr.category] = (byCategory[corr.category] || 0) + 1;
271
+
272
+ // By file
273
+ const dir = path.dirname(corr.file);
274
+ byFile[dir] = (byFile[dir] || 0) + 1;
275
+ }
276
+
277
+ return {
278
+ byCategory,
279
+ byFile,
280
+ total: corrections.length,
281
+ topCategory: Object.entries(byCategory).sort((a, b) => b[1] - a[1])[0],
282
+ topDirectory: Object.entries(byFile).sort((a, b) => b[1] - a[1])[0]
283
+ };
284
+ }
285
+
286
+ // ==================== MAIN ====================
287
+
288
+ function runScan() {
289
+ console.log(`${c.cyan}🔍 User Correction Sensor${c.reset}\n`);
290
+ console.log(`${c.gray}Scanning git diff for correction patterns...${c.reset}\n`);
291
+
292
+ const diff = getRecentDiff();
293
+
294
+ if (!diff.trim()) {
295
+ console.log(`${c.yellow}No uncommitted changes found.${c.reset}`);
296
+ console.log(`${c.gray}Tip: Make changes and run again before committing.${c.reset}`);
297
+ return [];
298
+ }
299
+
300
+ const detected = detectCorrections(diff);
301
+
302
+ // Save new corrections
303
+ let newCount = 0;
304
+ for (const corr of detected) {
305
+ if (addCorrection(corr)) {
306
+ newCount++;
307
+ }
308
+ }
309
+
310
+ // Display results
311
+ console.log(`${c.cyan}════════════════════════════════════════${c.reset}`);
312
+ console.log(`${c.bold}Scan Complete${c.reset}`);
313
+ console.log(` Patterns detected: ${detected.length}`);
314
+ console.log(` New corrections: ${c.yellow}${newCount}${c.reset}`);
315
+ console.log(`${c.cyan}════════════════════════════════════════${c.reset}\n`);
316
+
317
+ if (detected.length > 0) {
318
+ console.log(`${c.bold}Detected Corrections:${c.reset}`);
319
+ for (const corr of detected) {
320
+ const sevColor = { HIGH: c.yellow, MEDIUM: c.blue, LOW: c.gray }[corr.severity] || c.gray;
321
+ console.log(` ${sevColor}●${c.reset} ${corr.file}`);
322
+ console.log(` ${c.gray}${corr.description} (${corr.category})${c.reset}`);
323
+ }
324
+ }
325
+
326
+ return detected;
327
+ }
328
+
329
+ function showStats() {
330
+ const corrections = loadCorrections();
331
+ const analysis = analyzePatterns(corrections);
332
+
333
+ console.log(`${c.cyan}╔════════════════════════════════════════╗${c.reset}`);
334
+ console.log(`${c.cyan}║${c.reset} 📊 Correction Statistics ${c.cyan}║${c.reset}`);
335
+ console.log(`${c.cyan}╚════════════════════════════════════════╝${c.reset}\n`);
336
+
337
+ console.log(`${c.bold}By Category:${c.reset}`);
338
+ for (const [cat, count] of Object.entries(analysis.byCategory).sort((a, b) => b[1] - a[1])) {
339
+ const bar = '█'.repeat(Math.min(count, 20));
340
+ console.log(` ${cat.padEnd(15)} ${c.cyan}${bar}${c.reset} ${count}`);
341
+ }
342
+
343
+ console.log(`\n${c.bold}Hot Directories (most corrections):${c.reset}`);
344
+ for (const [dir, count] of Object.entries(analysis.byFile).sort((a, b) => b[1] - a[1]).slice(0, 5)) {
345
+ console.log(` ${dir}: ${count}`);
346
+ }
347
+
348
+ if (analysis.topCategory) {
349
+ console.log(`\n${c.yellow}⚠️ Most common issue: ${analysis.topCategory[0]} (${analysis.topCategory[1]} times)${c.reset}`);
350
+ console.log(`${c.gray} Consider creating a rule to prevent this pattern.${c.reset}`);
351
+ }
352
+
353
+ console.log(`\n${c.gray}Total corrections tracked: ${corrections.length}${c.reset}`);
354
+ }
355
+
356
+ function suggestLessons() {
357
+ const corrections = loadCorrections();
358
+ const analysis = analyzePatterns(corrections);
359
+
360
+ console.log(`${c.cyan}💡 Suggested Lessons${c.reset}\n`);
361
+
362
+ // Find patterns that occur 3+ times
363
+ const frequent = Object.entries(analysis.byCategory)
364
+ .filter(([_, count]) => count >= 3)
365
+ .sort((a, b) => b[1] - a[1]);
366
+
367
+ if (frequent.length === 0) {
368
+ console.log(`${c.gray}Not enough data yet. Keep coding and run again.${c.reset}`);
369
+ return;
370
+ }
371
+
372
+ for (const [category, count] of frequent) {
373
+ console.log(`${c.bold}Pattern: ${category}${c.reset} (${count} occurrences)`);
374
+
375
+ const suggestions = {
376
+ 'imports': 'Always use relative imports from project root. Check tsconfig paths.',
377
+ 'types': 'Add explicit type annotations to function parameters and return types.',
378
+ 'null-safety': 'Use optional chaining (?.) and nullish coalescing (??) operators.',
379
+ 'async': 'Always use async/await pattern. Never mix callbacks and promises.',
380
+ 'error-handling': 'Wrap async operations in try/catch. Never use empty catch blocks.',
381
+ 'logic': 'Review conditional logic carefully. Add edge case tests.',
382
+ 'naming': 'Follow naming conventions: camelCase for variables, PascalCase for types.'
383
+ };
384
+
385
+ console.log(` ${c.gray}Suggested rule: ${suggestions[category] || 'Review and document this pattern.'}${c.reset}\n`);
386
+ }
387
+ }
388
+
389
+ // Parse CLI args
390
+ const args = process.argv.slice(2);
391
+
392
+ if (args.includes('--scan') || args.includes('-s')) {
393
+ runScan();
394
+ } else if (args.includes('--stats')) {
395
+ showStats();
396
+ } else if (args.includes('--suggest')) {
397
+ suggestLessons();
398
+ } else if (args.includes('--clear')) {
399
+ saveCorrections([]);
400
+ console.log(`${c.green}✓ Cleared all corrections${c.reset}`);
401
+ } else {
402
+ console.log(`${c.cyan}user_correction_sensor - Detect AI code corrections${c.reset}
403
+
404
+ ${c.bold}Usage:${c.reset}
405
+ node user_correction_sensor.js --scan Scan uncommitted changes
406
+ node user_correction_sensor.js --stats Show correction statistics
407
+ node user_correction_sensor.js --suggest Suggest lessons from patterns
408
+ node user_correction_sensor.js --clear Clear recorded corrections
409
+
410
+ ${c.bold}What it detects:${c.reset}
411
+ • Import path corrections
412
+ • Type annotation fixes
413
+ • Added null checks
414
+ • Async/await corrections
415
+ • Error handling additions
416
+ • Logic/condition fixes
417
+
418
+ ${c.bold}Example workflow:${c.reset}
419
+ 1. AI generates code
420
+ 2. User fixes issues
421
+ 3. Run: node user_correction_sensor.js --scan
422
+ 4. Patterns are recorded for analysis
423
+ `);
424
+ }
425
+
426
+ export { runScan, detectCorrections, loadCorrections, analyzePatterns };
@@ -0,0 +1,247 @@
1
+ /**
2
+ * Auto-Learn Service
3
+ *
4
+ * Orchestrates all Auto-Learn scripts:
5
+ * - error_sensor.js
6
+ * - success_sensor.js
7
+ * - pattern_analyzer.js
8
+ * - pre_execution_check.js
9
+ * - adaptive_engine.js
10
+ * - skill_injector.js
11
+ *
12
+ * Usage:
13
+ * import autoLearnService from './auto-learn-service.js';
14
+ * await autoLearnService.runFullCycle();
15
+ */
16
+
17
+ import { spawn } from 'child_process';
18
+ import path from 'path';
19
+ import { fileURLToPath } from 'url';
20
+ import fs from 'fs';
21
+
22
+ const __filename = fileURLToPath(import.meta.url);
23
+ const __dirname = path.dirname(__filename);
24
+
25
+ // ==================== CONFIG ====================
26
+
27
+ const SCRIPTS_DIR = path.join(__dirname, '..', 'scripts');
28
+
29
+ const SCRIPTS = {
30
+ errorSensor: 'error_sensor.js',
31
+ successSensor: 'success_sensor.js',
32
+ patternAnalyzer: 'pattern_analyzer.js',
33
+ preExecutionCheck: 'pre_execution_check.js',
34
+ adaptiveEngine: 'adaptive_engine.js',
35
+ skillInjector: 'skill_injector.js',
36
+ ruleSharing: 'rule_sharing.js'
37
+ };
38
+
39
+ // ==================== COLORS ====================
40
+
41
+ const c = {
42
+ reset: '\x1b[0m',
43
+ green: '\x1b[32m',
44
+ yellow: '\x1b[33m',
45
+ red: '\x1b[31m',
46
+ cyan: '\x1b[36m',
47
+ gray: '\x1b[90m'
48
+ };
49
+
50
+ // ==================== RUNNER ====================
51
+
52
+ /**
53
+ * Run a script and return result
54
+ * @param {string} scriptName - Script filename
55
+ * @param {string[]} args - Arguments
56
+ * @returns {Promise<{success: boolean, output: string}>}
57
+ */
58
+ function runScript(scriptName, args = []) {
59
+ return new Promise((resolve) => {
60
+ const scriptPath = path.join(SCRIPTS_DIR, scriptName);
61
+
62
+ if (!fs.existsSync(scriptPath)) {
63
+ console.log(`${c.yellow}⚠️ Script not found: ${scriptName}${c.reset}`);
64
+ resolve({ success: false, output: 'Script not found' });
65
+ return;
66
+ }
67
+
68
+ console.log(`${c.gray}▶ Running ${scriptName}...${c.reset}`);
69
+
70
+ const child = spawn('node', [scriptPath, ...args], {
71
+ cwd: process.cwd(),
72
+ stdio: ['pipe', 'pipe', 'pipe']
73
+ });
74
+
75
+ let output = '';
76
+
77
+ child.stdout.on('data', (data) => {
78
+ output += data.toString();
79
+ });
80
+
81
+ child.stderr.on('data', (data) => {
82
+ output += data.toString();
83
+ });
84
+
85
+ child.on('close', (code) => {
86
+ if (code === 0) {
87
+ console.log(`${c.green}✓ ${scriptName} completed${c.reset}`);
88
+ resolve({ success: true, output });
89
+ } else {
90
+ console.log(`${c.red}✗ ${scriptName} failed (code ${code})${c.reset}`);
91
+ resolve({ success: false, output });
92
+ }
93
+ });
94
+
95
+ child.on('error', (err) => {
96
+ console.log(`${c.red}✗ ${scriptName} error: ${err.message}${c.reset}`);
97
+ resolve({ success: false, output: err.message });
98
+ });
99
+ });
100
+ }
101
+
102
+ // ==================== SERVICE FUNCTIONS ====================
103
+
104
+ /**
105
+ * Run error sensor
106
+ */
107
+ async function runErrorSensor() {
108
+ return runScript(SCRIPTS.errorSensor);
109
+ }
110
+
111
+ /**
112
+ * Run success sensor
113
+ */
114
+ async function runSuccessSensor() {
115
+ return runScript(SCRIPTS.successSensor);
116
+ }
117
+
118
+ /**
119
+ * Run pattern analyzer
120
+ */
121
+ async function runPatternAnalyzer() {
122
+ return runScript(SCRIPTS.patternAnalyzer);
123
+ }
124
+
125
+ /**
126
+ * Run pre-execution check
127
+ * @param {string} intent - User intent to check
128
+ */
129
+ async function checkIntent(intent) {
130
+ return runScript(SCRIPTS.preExecutionCheck, [intent]);
131
+ }
132
+
133
+ /**
134
+ * Run adaptive engine
135
+ */
136
+ async function runAdaptiveEngine() {
137
+ return runScript(SCRIPTS.adaptiveEngine);
138
+ }
139
+
140
+ /**
141
+ * Run skill injector
142
+ * @param {boolean} dryRun - Only simulate
143
+ */
144
+ async function runSkillInjector(dryRun = true) {
145
+ const args = dryRun ? ['--dry-run'] : [];
146
+ return runScript(SCRIPTS.skillInjector, args);
147
+ }
148
+
149
+ /**
150
+ * Run rule sharing sync
151
+ */
152
+ async function syncRules() {
153
+ return runScript(SCRIPTS.ruleSharing, ['--sync']);
154
+ }
155
+
156
+ // ==================== FULL CYCLE ====================
157
+
158
+ /**
159
+ * Run full Auto-Learn cycle
160
+ * @returns {Promise<{success: boolean, results: object}>}
161
+ */
162
+ async function runFullCycle() {
163
+ console.log(`\n${c.cyan}╔════════════════════════════════════════╗${c.reset}`);
164
+ console.log(`${c.cyan}║${c.reset} 🧠 Auto-Learn Full Cycle ${c.cyan}║${c.reset}`);
165
+ console.log(`${c.cyan}╚════════════════════════════════════════╝${c.reset}\n`);
166
+
167
+ const results = {};
168
+ let allSuccess = true;
169
+
170
+ // Step 1: Scan for errors
171
+ console.log(`${c.cyan}[1/5]${c.reset} Scanning for errors...`);
172
+ results.errorSensor = await runErrorSensor();
173
+ if (!results.errorSensor.success) allSuccess = false;
174
+
175
+ // Step 2: Scan for successes
176
+ console.log(`\n${c.cyan}[2/5]${c.reset} Scanning for successes...`);
177
+ results.successSensor = await runSuccessSensor();
178
+ if (!results.successSensor.success) allSuccess = false;
179
+
180
+ // Step 3: Analyze patterns
181
+ console.log(`\n${c.cyan}[3/5]${c.reset} Analyzing patterns...`);
182
+ results.patternAnalyzer = await runPatternAnalyzer();
183
+ if (!results.patternAnalyzer.success) allSuccess = false;
184
+
185
+ // Step 4: Run adaptive engine
186
+ console.log(`\n${c.cyan}[4/5]${c.reset} Running adaptive engine...`);
187
+ results.adaptiveEngine = await runAdaptiveEngine();
188
+ if (!results.adaptiveEngine.success) allSuccess = false;
189
+
190
+ // Step 5: Check skill injection (dry run)
191
+ console.log(`\n${c.cyan}[5/5]${c.reset} Checking skill candidates...`);
192
+ results.skillInjector = await runSkillInjector(true);
193
+
194
+ // Summary
195
+ console.log(`\n${c.cyan}════════════════════════════════════════${c.reset}`);
196
+ if (allSuccess) {
197
+ console.log(`${c.green}✓ Auto-Learn cycle completed successfully!${c.reset}`);
198
+ } else {
199
+ console.log(`${c.yellow}⚠️ Auto-Learn cycle completed with some issues${c.reset}`);
200
+ }
201
+
202
+ return { success: allSuccess, results };
203
+ }
204
+
205
+ /**
206
+ * Quick scan (errors + success only)
207
+ */
208
+ async function quickScan() {
209
+ console.log(`${c.cyan}🔍 Quick Auto-Learn scan...${c.reset}\n`);
210
+
211
+ const errorResult = await runErrorSensor();
212
+ const successResult = await runSuccessSensor();
213
+
214
+ return {
215
+ success: errorResult.success && successResult.success,
216
+ errors: errorResult,
217
+ successes: successResult
218
+ };
219
+ }
220
+
221
+ // ==================== EXPORTS ====================
222
+
223
+ const autoLearnService = {
224
+ runErrorSensor,
225
+ runSuccessSensor,
226
+ runPatternAnalyzer,
227
+ checkIntent,
228
+ runAdaptiveEngine,
229
+ runSkillInjector,
230
+ syncRules,
231
+ runFullCycle,
232
+ quickScan
233
+ };
234
+
235
+ export {
236
+ runErrorSensor,
237
+ runSuccessSensor,
238
+ runPatternAnalyzer,
239
+ checkIntent,
240
+ runAdaptiveEngine,
241
+ runSkillInjector,
242
+ syncRules,
243
+ runFullCycle,
244
+ quickScan
245
+ };
246
+
247
+ export default autoLearnService;