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,367 @@
1
+ # Agent Skill Kit - New Architecture
2
+
3
+ > **Status:** 🚧 In Progress - Migrating to FAANG-style layered architecture
4
+
5
+ ## Overview
6
+
7
+ This directory contains the new **layered architecture** for Agent Skill Kit, following FAANG best practices for maintainability, testability, and scalability.
8
+
9
+ ---
10
+
11
+ ## Architecture Principles
12
+
13
+ ### 1. **Layered Architecture** (Clean Architecture)
14
+ ```
15
+ ┌─────────────────────────────────────┐
16
+ │ Presentation Layer │ (CLI, UI)
17
+ ├─────────────────────────────────────┤
18
+ │ Service Layer │ (Orchestration)
19
+ ├─────────────────────────────────────┤
20
+ │ Core Domain Layer │ (Business Logic)
21
+ ├─────────────────────────────────────┤
22
+ │ Data Layer │ (Persistence)
23
+ ├─────────────────────────────────────┤
24
+ │ Infrastructure Layer │ (Config, DI, Logging)
25
+ └─────────────────────────────────────┘
26
+ ```
27
+
28
+ ### 2. **Dependency Rule**
29
+ - **Core** has ZERO external dependencies (pure business logic)
30
+ - **Data** implements interfaces defined in Core
31
+ - **Services** orchestrate Core + Data
32
+ - **Presentation** uses Services
33
+ - **Infrastructure** provides cross-cutting concerns
34
+
35
+ ### 3. **Single Responsibility Principle**
36
+ Each class/module has ONE clear purpose:
37
+ - ✅ `EvolutionSignal` - Represents a signal
38
+ - ✅ `ThresholdChecker` - Checks evolution readiness
39
+ - ✅ `SignalRepository` - Persists signals
40
+ - ✅ `SignalDetector` - Orchestrates signal workflow
41
+
42
+ ---
43
+
44
+ ## Folder Structure
45
+
46
+ ```
47
+ src/
48
+ ├── core/ # Domain Layer (Pure Business Logic)
49
+ │ ├── learning/
50
+ │ │ ├── lesson-manager.js
51
+ │ │ ├── cognitive-enhancer.js
52
+ │ │ ├── lesson-merger.js
53
+ │ │ └── index.js
54
+ │ ├── evolution/ [✅ COMPLETE]
55
+ │ │ ├── evolution-signal.js
56
+ │ │ ├── threshold-checker.js
57
+ │ │ ├── review-gate.js
58
+ │ │ ├── signal-detector.js
59
+ │ │ └── index.js
60
+ │ ├── scanning/
61
+ │ │ ├── file-scanner.js
62
+ │ │ ├── pattern-matcher.js
63
+ │ │ ├── violation-tracker.js
64
+ │ │ └── index.js
65
+ │ └── index.js
66
+
67
+ ├── services/ # Application Services (Orchestration)
68
+ │ ├── auto-learning-service.js
69
+ │ ├── stats-service.js
70
+ │ ├── backup-service.js
71
+ │ ├── export-service.js
72
+ │ └── index.js
73
+
74
+ ├── data/ # Data Access Layer
75
+ │ ├── repositories/ [✅ COMPLETE]
76
+ │ │ ├── signal-repository.js
77
+ │ │ ├── lesson-repository.js
78
+ │ │ ├── settings-repository.js
79
+ │ │ └── index.js
80
+ │ ├── storage/ [✅ COMPLETE]
81
+ │ │ ├── json-storage.js
82
+ │ │ ├── yaml-storage.js
83
+ │ │ ├── file-storage.js
84
+ │ │ └── index.js
85
+ │ └── index.js
86
+
87
+ ├── presentation/ # Presentation Layer (UI/CLI)
88
+ │ └── cli/
89
+ │ ├── commands/
90
+ │ ├── menus/
91
+ │ └── views/
92
+
93
+ ├── infrastructure/ # Cross-cutting Concerns
94
+ │ ├── config/
95
+ │ ├── di/ # Dependency Injection
96
+ │ └── logging/
97
+
98
+ └── shared/ # Shared Utilities
99
+ ├── utils/
100
+ └── types/
101
+ ```
102
+
103
+ ---
104
+
105
+ ## Migration Status
106
+
107
+ ### ✅ Completed Modules
108
+
109
+ #### Evolution Module (100%)
110
+ - [x] `EvolutionSignal` - Domain model
111
+ - [x] `ThresholdChecker` - Business rules
112
+ - [x] `ReviewGate` - Decision logic
113
+ - [x] `SignalRepository` - Data access
114
+ - [x] `JsonStorage` - Storage adapter
115
+ - [x] `SignalDetector` - Service orchestration
116
+
117
+ **Files:** 7 new files, avg 70 lines each
118
+ **Test Status:** ✅ Passing
119
+
120
+ ### 🚧 In Progress
121
+
122
+ #### Learning Module (0%)
123
+ - [ ] `LessonManager`
124
+ - [ ] `CognitiveEnhancer`
125
+ - [ ] `LessonMerger`
126
+ - [ ] `LessonRepository`
127
+
128
+ #### Scanning Module (0%)
129
+ - [ ] `FileScanner`
130
+ - [ ] `PatternMatcher`
131
+ - [ ] `ViolationTracker`
132
+
133
+ ---
134
+
135
+ ## How to Use New Architecture
136
+
137
+ ### Example: Using SignalDetector
138
+
139
+ ```javascript
140
+ // 1. Import components
141
+ import { SignalDetector } from './src/core/evolution/signal-detector.js';
142
+ import { SignalRepository } from './src/data/repositories/signal-repository.js';
143
+ import { JsonStorage } from './src/data/storage/json-storage.js';
144
+ import { KNOWLEDGE_DIR } from './lib/config.js';
145
+
146
+ // 2. Create instances (Dependency Injection)
147
+ const storage = new JsonStorage(KNOWLEDGE_DIR);
148
+ const repository = new SignalRepository(storage);
149
+ const detector = new SignalDetector(repository, { updateThreshold: 10 });
150
+
151
+ // 3. Use async API
152
+ const stats = await detector.getStats();
153
+ console.log(`Pending: ${stats.pending}`);
154
+
155
+ const pending = await detector.getPending();
156
+ pending.forEach(signal => {
157
+ console.log(`${signal.lessonId}: ${signal.reason}`);
158
+ });
159
+
160
+ // 4. Approve signals
161
+ await detector.approve(signalId);
162
+ ```
163
+
164
+ ### Testing with Mocks
165
+
166
+ ```javascript
167
+ import { SignalDetector } from './src/core/evolution/signal-detector.js';
168
+
169
+ // Create mock repository
170
+ const mockRepo = {
171
+ findAll: async () => [mockSignal1, mockSignal2],
172
+ findPending: async () => [mockSignal1],
173
+ save: async (signal) => signal
174
+ };
175
+
176
+ // Inject mock
177
+ const detector = new SignalDetector(mockRepo);
178
+
179
+ // Test easily!
180
+ const pending = await detector.getPending();
181
+ expect(pending).toHaveLength(1);
182
+ ```
183
+
184
+ ---
185
+
186
+ ## Benefits of New Architecture
187
+
188
+ ### Before (Flat Structure)
189
+ ```javascript
190
+ // lib/evolution-signal.js (343 lines)
191
+ export class EvolutionSignal { ... }
192
+ export class SignalQueue {
193
+ constructor() {
194
+ this.signals = [];
195
+ this.signalFilePath = path.join(...); // ❌ Tight coupling
196
+ }
197
+
198
+ load() {
199
+ fs.readFileSync(...); // ❌ Direct filesystem access
200
+ }
201
+ }
202
+ ```
203
+
204
+ **Problems:**
205
+ - ❌ SignalQueue mixes business logic + persistence
206
+ - ❌ Hard to test (can't mock filesystem)
207
+ - ❌ Tight coupling
208
+ - ❌ Violates Single Responsibility
209
+
210
+ ### After (Layered Architecture)
211
+ ```javascript
212
+ // Domain Model (core/evolution/evolution-signal.js)
213
+ export class EvolutionSignal {
214
+ approve() { this.status = 'approved'; } // ✅ Pure business logic
215
+ }
216
+
217
+ // Repository (data/repositories/signal-repository.js)
218
+ export class SignalRepository {
219
+ constructor(storage) {
220
+ this.storage = storage; // ✅ Dependency injection
221
+ }
222
+
223
+ async findAll() {
224
+ return this.storage.read('signals'); // ✅ Uses abstraction
225
+ }
226
+ }
227
+
228
+ // Storage Adapter (data/storage/json-storage.js)
229
+ export class JsonStorage {
230
+ async read(key) {
231
+ return JSON.parse(fs.readFileSync(...)); // ✅ Isolated I/O
232
+ }
233
+ }
234
+
235
+ // Service (core/evolution/signal-detector.js)
236
+ export class SignalDetector {
237
+ constructor(repository) {
238
+ this.repository = repository; // ✅ Dependency injection
239
+ }
240
+
241
+ async approve(id) {
242
+ const signal = await this.repository.findById(id);
243
+ signal.approve(); // ✅ Uses domain model
244
+ await this.repository.save(signal);
245
+ }
246
+ }
247
+ ```
248
+
249
+ **Benefits:**
250
+ - ✅ Single Responsibility (each class has ONE job)
251
+ - ✅ Easy to test (inject mocks)
252
+ - ✅ Loose coupling (swap storage without touching logic)
253
+ - ✅ Clear ownership (know where each responsibility lives)
254
+
255
+ ---
256
+
257
+ ## Design Patterns Used
258
+
259
+ ### 1. Repository Pattern
260
+ **Purpose:** Separate data access from business logic
261
+
262
+ **Implementation:**
263
+ - `SignalRepository` for evolution signals
264
+ - `LessonRepository` for lessons
265
+ - All repositories use storage abstraction
266
+
267
+ ### 2. Dependency Injection
268
+ **Purpose:** Enable testability and flexibility
269
+
270
+ **Implementation:**
271
+ ```javascript
272
+ class SignalDetector {
273
+ constructor(signalRepository, settings) {
274
+ this.signalRepository = signalRepository; // Injected!
275
+ this.settings = settings;
276
+ }
277
+ }
278
+ ```
279
+
280
+ ### 3. Strategy Pattern (Storage)
281
+ **Purpose:** Swap storage implementations
282
+
283
+ **Implementation:**
284
+ - `JsonStorage` for JSON files
285
+ - `YamlStorage` for YAML files
286
+ - All implement same interface (`read`, `write`, `delete`)
287
+
288
+ ---
289
+
290
+ ## Testing Strategy
291
+
292
+ ### Unit Tests (Core Layer)
293
+ ```javascript
294
+ // Test pure business logic
295
+ describe('ThresholdChecker', () => {
296
+ it('should detect hitCountThreshold', () => {
297
+ const lesson = { hitCount: 10 };
298
+ const result = ThresholdChecker.check(lesson, 10);
299
+
300
+ expect(result.ready).toBe(true);
301
+ expect(result.reason).toBe('hitCountThreshold');
302
+ });
303
+ });
304
+ ```
305
+
306
+ ### Integration Tests (Service Layer)
307
+ ```javascript
308
+ // Test with real repository + mock storage
309
+ describe('SignalDetector', () => {
310
+ it('should queue signal when threshold reached', async () => {
311
+ const mockStorage = {
312
+ read: async () => ({ signals: [] }),
313
+ write: async () => {}
314
+ };
315
+
316
+ const repository = new SignalRepository(mockStorage);
317
+ const detector = new SignalDetector(repository);
318
+
319
+ const result = await detector.queue('LESSON-1', {
320
+ ready: true,
321
+ reason: 'hitCountThreshold',
322
+ confidence: 0.9
323
+ });
324
+
325
+ expect(result.lessonId).toBe('LESSON-1');
326
+ });
327
+ });
328
+ ```
329
+
330
+ ---
331
+
332
+ ## Migration Guide
333
+
334
+ See [MIGRATION.md](./MIGRATION.md) for detailed migration instructions.
335
+
336
+ **Quick Start:**
337
+ 1. New code → Use new architecture
338
+ 2. Existing code → Gradually migrate
339
+ 3. Backward compatibility maintained in `lib/` folder
340
+
341
+ ---
342
+
343
+ ## Next Steps
344
+
345
+ 1. **Complete Learning Module** - Extract from `cognitive-lesson.js`, `learn.js`
346
+ 2. **Complete Scanning Module** - Extract from `recall.js`
347
+ 3. **Create DI Container** - Centralize dependency management
348
+ 4. **Migrate UI Layer** - Extract to `presentation/cli/`
349
+ 5. **Full Test Coverage** - Unit + integration tests
350
+
351
+ ---
352
+
353
+ ## Contributing
354
+
355
+ When adding new features:
356
+ 1. **Core logic** → `src/core/`
357
+ 2. **Data access** → `src/data/repositories/`
358
+ 3. **Orchestration** → `src/services/`
359
+ 4. **UI** → `src/presentation/`
360
+
361
+ **Remember:** Core layer has ZERO dependencies!
362
+
363
+ ---
364
+
365
+ ## Questions?
366
+
367
+ See [ARCHITECTURE.md](../../../.gemini/antigravity/brain/.../architecture_refactoring_plan.md) for full architecture details.
@@ -0,0 +1,42 @@
1
+ /**
2
+ * EvolutionSignal - Domain Model
3
+ *
4
+ * Represents a detected evolution opportunity.
5
+ * Pure domain object with NO external dependencies.
6
+ */
7
+
8
+ export class EvolutionSignal {
9
+ constructor(lessonId, reason, confidence, metadata = {}) {
10
+ this.id = `signal_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
11
+ this.lessonId = lessonId;
12
+ this.reason = reason; // 'hitCountThreshold', 'patternStable', 'highConfidence'
13
+ this.confidence = confidence; // 0.0 to 1.0
14
+ this.status = 'pending'; // 'pending', 'approved', 'rejected', 'executed'
15
+ this.metadata = metadata; // Additional context
16
+ this.createdAt = Date.now();
17
+ this.resolvedAt = null;
18
+ }
19
+
20
+ approve() {
21
+ this.status = 'approved';
22
+ this.resolvedAt = Date.now();
23
+ }
24
+
25
+ reject() {
26
+ this.status = 'rejected';
27
+ this.resolvedAt = Date.now();
28
+ }
29
+
30
+ execute() {
31
+ this.status = 'executed';
32
+ this.resolvedAt = Date.now();
33
+ }
34
+
35
+ isPending() {
36
+ return this.status === 'pending';
37
+ }
38
+
39
+ isResolved() {
40
+ return this.status !== 'pending';
41
+ }
42
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Evolution Module - Core Domain
3
+ *
4
+ * Business logic for evolution signal detection and management.
5
+ *
6
+ * Exported:
7
+ * - SignalDetector: Detect evolution opportunities
8
+ * - SignalQueue: Manage signal lifecycle
9
+ * - ThresholdChecker: Check if lesson ready for evolution
10
+ * - ReviewGate: Determine auto vs manual evolution
11
+ */
12
+
13
+ export { SignalDetector } from './signal-detector.js';
14
+ export { SignalQueue } from './signal-queue.js';
15
+ export { ThresholdChecker } from './threshold-checker.js';
16
+ export { ReviewGate } from './review-gate.js';
17
+ export { EvolutionSignal } from './evolution-signal.js';
@@ -0,0 +1,40 @@
1
+ /**
2
+ * ReviewGate - Core Business Logic
3
+ *
4
+ * Determines if a signal should auto-evolve or require manual review.
5
+ * Pure function based on signal confidence and settings.
6
+ */
7
+
8
+ export class ReviewGate {
9
+ /**
10
+ * Determine if a signal should auto-evolve or require manual review
11
+ * @param {object} signal - Evolution signal
12
+ * @param {object} settings - { autoUpdating: boolean, confidenceThreshold: number }
13
+ * @returns {{ shouldAuto: boolean, reason: string }}
14
+ */
15
+ static evaluate(signal, settings = {}) {
16
+ const { autoUpdating = false, confidenceThreshold = 0.8 } = settings;
17
+
18
+ // If auto-updating is disabled, always require review
19
+ if (!autoUpdating) {
20
+ return {
21
+ shouldAuto: false,
22
+ reason: 'autoUpdatingDisabled'
23
+ };
24
+ }
25
+
26
+ // If confidence is below threshold, require review
27
+ if (signal.confidence < confidenceThreshold) {
28
+ return {
29
+ shouldAuto: false,
30
+ reason: 'lowConfidence'
31
+ };
32
+ }
33
+
34
+ // High confidence + auto-updating enabled = auto-evolve
35
+ return {
36
+ shouldAuto: true,
37
+ reason: 'highConfidenceAutoApproved'
38
+ };
39
+ }
40
+ }
@@ -0,0 +1,137 @@
1
+ /**
2
+ * SignalDetector - Application Service
3
+ *
4
+ * Orchestrates evolution signal detection and queuing.
5
+ * Coordinates between core business logic and data layer.
6
+ */
7
+
8
+ import { EvolutionSignal } from './evolution-signal.js';
9
+ import { ThresholdChecker } from './threshold-checker.js';
10
+
11
+ export class SignalDetector {
12
+ constructor(signalRepository, settings = {}) {
13
+ this.signalRepository = signalRepository;
14
+ this.settings = settings;
15
+ }
16
+
17
+ /**
18
+ * Check if lesson is ready for evolution
19
+ * @param {object} lesson - Lesson to check
20
+ * @returns {Promise<{ready: boolean, reason?: string, confidence?: number}>}
21
+ */
22
+ async check(lesson) {
23
+ const threshold = this.settings.updateThreshold || 10;
24
+ return ThresholdChecker.check(lesson, threshold);
25
+ }
26
+
27
+ /**
28
+ * Queue an evolution signal
29
+ * @param {string} lessonId
30
+ * @param {object} checkResult - From check()
31
+ * @param {object} metadata - Additional context
32
+ * @returns {Promise<EvolutionSignal|null>}
33
+ */
34
+ async queue(lessonId, checkResult, metadata = {}) {
35
+ if (!checkResult.ready) return null;
36
+
37
+ // Create signal
38
+ const signal = new EvolutionSignal(
39
+ lessonId,
40
+ checkResult.reason,
41
+ checkResult.confidence,
42
+ metadata
43
+ );
44
+
45
+ // Check for duplicates
46
+ const existing = await this.signalRepository.findByLesson(lessonId);
47
+ const duplicate = existing.find(s =>
48
+ s.isPending() && s.reason === signal.reason
49
+ );
50
+
51
+ if (duplicate) {
52
+ // Update confidence if higher
53
+ if (signal.confidence > duplicate.confidence) {
54
+ duplicate.confidence = signal.confidence;
55
+ duplicate.metadata = signal.metadata;
56
+ await this.signalRepository.save(duplicate);
57
+ }
58
+ return duplicate;
59
+ }
60
+
61
+ // Save new signal
62
+ return await this.signalRepository.save(signal);
63
+ }
64
+
65
+ /**
66
+ * Get all pending signals
67
+ * @returns {Promise<Array<EvolutionSignal>>}
68
+ */
69
+ async getPending() {
70
+ return await this.signalRepository.findPending();
71
+ }
72
+
73
+ /**
74
+ * Get signals for a specific lesson
75
+ * @param {string} lessonId
76
+ * @returns {Promise<Array<EvolutionSignal>>}
77
+ */
78
+ async getByLesson(lessonId) {
79
+ return await this.signalRepository.findByLesson(lessonId);
80
+ }
81
+
82
+ /**
83
+ * Approve a signal
84
+ * @param {string} signalId
85
+ * @returns {Promise<EvolutionSignal>}
86
+ */
87
+ async approve(signalId) {
88
+ const signal = await this.signalRepository.findById(signalId);
89
+ if (signal) {
90
+ signal.approve();
91
+ await this.signalRepository.save(signal);
92
+ }
93
+ return signal;
94
+ }
95
+
96
+ /**
97
+ * Reject a signal
98
+ * @param {string} signalId
99
+ * @returns {Promise<EvolutionSignal>}
100
+ */
101
+ async reject(signalId) {
102
+ const signal = await this.signalRepository.findById(signalId);
103
+ if (signal) {
104
+ signal.reject();
105
+ await this.signalRepository.save(signal);
106
+ }
107
+ return signal;
108
+ }
109
+
110
+ /**
111
+ * Execute a signal
112
+ * @param {string} signalId
113
+ * @returns {Promise<EvolutionSignal>}
114
+ */
115
+ async execute(signalId) {
116
+ const signal = await this.signalRepository.findById(signalId);
117
+ if (signal) {
118
+ signal.execute();
119
+ await this.signalRepository.save(signal);
120
+ }
121
+ return signal;
122
+ }
123
+
124
+ /**
125
+ * Get evolution statistics
126
+ * @returns {Promise<{pending: number, approved: number, rejected: number, executed: number}>}
127
+ */
128
+ async getStats() {
129
+ const all = await this.signalRepository.findAll();
130
+ return {
131
+ pending: all.filter(s => s.status === 'pending').length,
132
+ approved: all.filter(s => s.status === 'approved').length,
133
+ rejected: all.filter(s => s.status === 'rejected').length,
134
+ executed: all.filter(s => s.status === 'executed').length
135
+ };
136
+ }
137
+ }
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Signal Queue - Service Facade
3
+ *
4
+ * Backward compatible wrapper around SignalDetector.
5
+ * Provides singleton-style access for legacy code.
6
+ */
7
+
8
+ import { SignalRepository } from '../data/repositories/signal-repository.js';
9
+ import { JsonStorage } from '../data/storage/json-storage.js';
10
+ import { SignalDetector } from './signal-detector.js';
11
+ import path from 'path';
12
+
13
+ // Lazy initialization
14
+ let _instance = null;
15
+
16
+ async function getInstance() {
17
+ if (!_instance) {
18
+ // Get KNOWLEDGE_DIR from old config
19
+ const { KNOWLEDGE_DIR } = await import('../../lib/config.js');
20
+
21
+ // Create storage and repository
22
+ const storage = new JsonStorage(KNOWLEDGE_DIR);
23
+ const repository = new SignalRepository(storage);
24
+
25
+ // Create detector
26
+ _instance = new SignalDetector(repository);
27
+ }
28
+ return _instance;
29
+ }
30
+
31
+ /**
32
+ * SignalQueue - Facade for backward compatibility
33
+ *
34
+ * Provides same interface as old evolution-signal.js
35
+ */
36
+ export class SignalQueue {
37
+ static async add(signal) {
38
+ const detector = await getInstance();
39
+ return detector.queue(signal.lessonId, {
40
+ ready: true,
41
+ reason: signal.reason,
42
+ confidence: signal.confidence
43
+ }, signal.metadata);
44
+ }
45
+
46
+ static async getPending() {
47
+ const detector = await getInstance();
48
+ return detector.getPending();
49
+ }
50
+
51
+ static async getByLesson(lessonId) {
52
+ const detector = await getInstance();
53
+ return detector.getByLesson(lessonId);
54
+ }
55
+
56
+ static async approve(signalId) {
57
+ const detector = await getInstance();
58
+ return detector.approve(signalId);
59
+ }
60
+
61
+ static async reject(signalId) {
62
+ const detector = await getInstance();
63
+ return detector.reject(signalId);
64
+ }
65
+
66
+ static async execute(signalId) {
67
+ const detector = await getInstance();
68
+ return detector.execute(signalId);
69
+ }
70
+
71
+ static async cleanup() {
72
+ const detector = await getInstance();
73
+ const repository = detector.signalRepository;
74
+ await repository.cleanup();
75
+ }
76
+ }
77
+
78
+ // Export singleton instance for compatibility
79
+ export const signalQueue = SignalQueue;