@sparkleideas/ruv-swarm 1.0.18-patch.1

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 (87) hide show
  1. package/README.md +1565 -0
  2. package/bin/ruv-swarm-clean.js +1872 -0
  3. package/bin/ruv-swarm-memory.js +119 -0
  4. package/bin/ruv-swarm-secure-heartbeat.js +1549 -0
  5. package/bin/ruv-swarm-secure.js +1689 -0
  6. package/package.json +221 -0
  7. package/src/agent.ts +342 -0
  8. package/src/benchmark.js +267 -0
  9. package/src/claude-flow-enhanced.js +839 -0
  10. package/src/claude-integration/advanced-commands.js +561 -0
  11. package/src/claude-integration/core.js +112 -0
  12. package/src/claude-integration/docs.js +1548 -0
  13. package/src/claude-integration/env-template.js +39 -0
  14. package/src/claude-integration/index.js +209 -0
  15. package/src/claude-integration/remote.js +408 -0
  16. package/src/cli-diagnostics.js +364 -0
  17. package/src/cognitive-pattern-evolution.js +1317 -0
  18. package/src/daa-cognition.js +977 -0
  19. package/src/daa-service.d.ts +298 -0
  20. package/src/daa-service.js +1116 -0
  21. package/src/diagnostics.js +533 -0
  22. package/src/errors.js +528 -0
  23. package/src/github-coordinator/README.md +193 -0
  24. package/src/github-coordinator/claude-hooks.js +162 -0
  25. package/src/github-coordinator/gh-cli-coordinator.js +260 -0
  26. package/src/hooks/cli.js +82 -0
  27. package/src/hooks/index.js +1900 -0
  28. package/src/index-enhanced.d.ts +371 -0
  29. package/src/index-enhanced.js +734 -0
  30. package/src/index.d.ts +287 -0
  31. package/src/index.js +405 -0
  32. package/src/index.ts +457 -0
  33. package/src/logger.js +182 -0
  34. package/src/logging-config.js +179 -0
  35. package/src/mcp-daa-tools.js +735 -0
  36. package/src/mcp-tools-benchmarks.js +328 -0
  37. package/src/mcp-tools-enhanced.js +2863 -0
  38. package/src/memory-config.js +42 -0
  39. package/src/meta-learning-framework.js +1359 -0
  40. package/src/neural-agent.js +830 -0
  41. package/src/neural-coordination-protocol.js +1363 -0
  42. package/src/neural-models/README.md +118 -0
  43. package/src/neural-models/autoencoder.js +543 -0
  44. package/src/neural-models/base.js +269 -0
  45. package/src/neural-models/cnn.js +497 -0
  46. package/src/neural-models/gnn.js +447 -0
  47. package/src/neural-models/gru.js +536 -0
  48. package/src/neural-models/index.js +273 -0
  49. package/src/neural-models/lstm.js +551 -0
  50. package/src/neural-models/neural-presets-complete.js +1306 -0
  51. package/src/neural-models/presets/graph.js +392 -0
  52. package/src/neural-models/presets/index.js +279 -0
  53. package/src/neural-models/presets/nlp.js +328 -0
  54. package/src/neural-models/presets/timeseries.js +368 -0
  55. package/src/neural-models/presets/vision.js +387 -0
  56. package/src/neural-models/resnet.js +534 -0
  57. package/src/neural-models/transformer.js +515 -0
  58. package/src/neural-models/vae.js +489 -0
  59. package/src/neural-network-manager.js +1938 -0
  60. package/src/neural-network.ts +296 -0
  61. package/src/neural.js +574 -0
  62. package/src/performance-benchmarks.js +898 -0
  63. package/src/performance.js +458 -0
  64. package/src/persistence-pooled.js +695 -0
  65. package/src/persistence.js +480 -0
  66. package/src/schemas.js +864 -0
  67. package/src/security.js +218 -0
  68. package/src/singleton-container.js +183 -0
  69. package/src/sqlite-pool.js +587 -0
  70. package/src/sqlite-worker.js +141 -0
  71. package/src/types.ts +164 -0
  72. package/src/utils.ts +286 -0
  73. package/src/wasm-loader.js +601 -0
  74. package/src/wasm-loader2.js +404 -0
  75. package/src/wasm-memory-optimizer.js +783 -0
  76. package/src/wasm-types.d.ts +63 -0
  77. package/wasm/README.md +347 -0
  78. package/wasm/neuro-divergent.wasm +0 -0
  79. package/wasm/package.json +18 -0
  80. package/wasm/ruv-fann.wasm +0 -0
  81. package/wasm/ruv_swarm_simd.wasm +0 -0
  82. package/wasm/ruv_swarm_wasm.d.ts +391 -0
  83. package/wasm/ruv_swarm_wasm.js +2164 -0
  84. package/wasm/ruv_swarm_wasm_bg.wasm +0 -0
  85. package/wasm/ruv_swarm_wasm_bg.wasm.d.ts +123 -0
  86. package/wasm/wasm-bindings-loader.mjs +435 -0
  87. package/wasm/wasm-updates.md +684 -0
@@ -0,0 +1,1900 @@
1
+ /**
2
+ * Claude Code Hooks Implementation for @sparkleideas/ruv-swarm
3
+ * Provides automated coordination, formatting, and learning capabilities
4
+ */
5
+
6
+ import { promises as fs } from 'fs';
7
+ import path from 'path';
8
+ import { execSync } from 'child_process';
9
+ import { fileURLToPath } from 'url';
10
+ import { SwarmPersistence } from '../persistence.js';
11
+
12
+ const __filename = fileURLToPath(import.meta.url);
13
+ const __dirname = path.dirname(__filename);
14
+
15
+ class RuvSwarmHooks {
16
+ constructor() {
17
+ this.sessionData = {
18
+ startTime: Date.now(),
19
+ operations: [],
20
+ agents: new Map(),
21
+ learnings: [],
22
+ metrics: {
23
+ tokensSaved: 0,
24
+ tasksCompleted: 0,
25
+ patternsImproved: 0,
26
+ },
27
+ };
28
+
29
+ // Initialize persistence layer for cross-agent memory
30
+ this.persistence = null;
31
+ this.initializePersistence();
32
+ }
33
+
34
+ /**
35
+ * Initialize persistence layer with error handling
36
+ */
37
+ async initializePersistence() {
38
+ try {
39
+ this.persistence = new SwarmPersistence();
40
+ console.log('🗄️ Hook persistence layer initialized');
41
+ } catch (error) {
42
+ console.warn('⚠️ Failed to initialize persistence layer:', error.message);
43
+ console.warn('⚠️ Operating in memory-only mode');
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Main hook handler - routes to specific hook implementations
49
+ */
50
+ async handleHook(hookType, args) {
51
+ try {
52
+ switch (hookType) {
53
+ // Pre-operation hooks
54
+ case 'pre-edit':
55
+ return await this.preEditHook(args);
56
+ case 'pre-bash':
57
+ return await this.preBashHook(args);
58
+ case 'pre-task':
59
+ return await this.preTaskHook(args);
60
+ case 'pre-search':
61
+ return await this.preSearchHook(args);
62
+ case 'pre-mcp':
63
+ return await this.preMcpHook(args);
64
+
65
+ // Post-operation hooks
66
+ case 'post-edit':
67
+ return await this.postEditHook(args);
68
+ case 'post-bash':
69
+ return await this.postBashHook(args);
70
+ case 'post-task':
71
+ return await this.postTaskHook(args);
72
+ case 'post-search':
73
+ return await this.postSearchHook(args);
74
+ case 'post-web-search':
75
+ return await this.postWebSearchHook(args);
76
+ case 'post-web-fetch':
77
+ return await this.postWebFetchHook(args);
78
+
79
+ // MCP-specific hooks
80
+ case 'mcp-swarm-initialized':
81
+ return await this.mcpSwarmInitializedHook(args);
82
+ case 'mcp-agent-spawned':
83
+ return await this.mcpAgentSpawnedHook(args);
84
+ case 'mcp-task-orchestrated':
85
+ return await this.mcpTaskOrchestratedHook(args);
86
+ case 'mcp-neural-trained':
87
+ return await this.mcpNeuralTrainedHook(args);
88
+
89
+ // System hooks
90
+ case 'notification':
91
+ return await this.notificationHook(args);
92
+ case 'session-end':
93
+ return await this.sessionEndHook(args);
94
+ case 'session-restore':
95
+ return await this.sessionRestoreHook(args);
96
+ case 'agent-complete':
97
+ return await this.agentCompleteHook(args);
98
+
99
+ default:
100
+ return { continue: true, reason: `Unknown hook type: ${hookType}` };
101
+ }
102
+ } catch (error) {
103
+ console.error(`Hook error (${hookType}):`, error.message);
104
+ return {
105
+ continue: true,
106
+ error: error.message,
107
+ fallback: 'Hook error - continuing with default behavior',
108
+ };
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Pre-search hook - Prepare cache and optimize search
114
+ */
115
+ async preSearchHook(args) {
116
+ const { pattern } = args;
117
+
118
+ // Initialize search cache
119
+ if (!this.sessionData.searchCache) {
120
+ this.sessionData.searchCache = new Map();
121
+ }
122
+
123
+ // Check cache for similar patterns
124
+ const cachedResult = this.sessionData.searchCache.get(pattern);
125
+ if (cachedResult && Date.now() - cachedResult.timestamp < 300000) { // 5 min cache
126
+ return {
127
+ continue: true,
128
+ cached: true,
129
+ cacheHit: cachedResult.files.length,
130
+ metadata: { pattern, cached: true },
131
+ };
132
+ }
133
+
134
+ return {
135
+ continue: true,
136
+ reason: 'Search prepared',
137
+ metadata: { pattern, cacheReady: true },
138
+ };
139
+ }
140
+
141
+ /**
142
+ * Pre-MCP hook - Validate MCP tool state
143
+ */
144
+ async preMcpHook(args) {
145
+ const { tool, params } = args;
146
+
147
+ // Parse params if string
148
+ const toolParams = typeof params === 'string' ? JSON.parse(params) : params;
149
+
150
+ // Validate swarm state for MCP operations
151
+ if (tool.includes('agent_spawn') || tool.includes('task_orchestrate')) {
152
+ const swarmStatus = await this.checkSwarmStatus();
153
+ if (!swarmStatus.initialized) {
154
+ return {
155
+ continue: true,
156
+ warning: 'Swarm not initialized - will be created automatically',
157
+ autoInit: true,
158
+ };
159
+ }
160
+ }
161
+
162
+ // Track MCP operations
163
+ this.sessionData.operations.push({
164
+ type: 'mcp',
165
+ tool,
166
+ params: toolParams,
167
+ timestamp: Date.now(),
168
+ });
169
+
170
+ return {
171
+ continue: true,
172
+ reason: 'MCP tool validated',
173
+ metadata: { tool, state: 'ready' },
174
+ };
175
+ }
176
+
177
+ /**
178
+ * Pre-edit hook - Ensure coordination before file modifications
179
+ */
180
+ async preEditHook(args) {
181
+ const { file } = args;
182
+
183
+ // Determine file type and assign appropriate agent
184
+ const fileExt = path.extname(file);
185
+ const agentType = this.getAgentTypeForFile(fileExt);
186
+
187
+ // Check if swarm is initialized
188
+ const swarmStatus = await this.checkSwarmStatus();
189
+ if (!swarmStatus.initialized) {
190
+ return {
191
+ continue: false,
192
+ reason: 'Swarm not initialized - run mcp__ruv-swarm__swarm_init first',
193
+ suggestion: 'Initialize swarm with appropriate topology',
194
+ };
195
+ }
196
+
197
+ // Ensure appropriate agent exists
198
+ const agent = await this.ensureAgent(agentType);
199
+
200
+ // Record operation
201
+ this.sessionData.operations.push({
202
+ type: 'edit',
203
+ file,
204
+ agent: agent.id,
205
+ timestamp: Date.now(),
206
+ });
207
+
208
+ return {
209
+ continue: true,
210
+ reason: `${agentType} agent assigned for ${fileExt} file`,
211
+ metadata: {
212
+ agent_id: agent.id,
213
+ agent_type: agentType,
214
+ cognitive_pattern: agent.pattern,
215
+ readiness: agent.readiness,
216
+ },
217
+ };
218
+ }
219
+
220
+ /**
221
+ * Pre-task hook - Auto-spawn agents and optimize topology
222
+ */
223
+ async preTaskHook(args) {
224
+ const { description, autoSpawnAgents, optimizeTopology } = args;
225
+
226
+ // Analyze task complexity
227
+ const complexity = this.analyzeTaskComplexity(description);
228
+
229
+ // Determine optimal topology
230
+ const topology = optimizeTopology ? this.selectOptimalTopology(complexity) : 'mesh';
231
+
232
+ // Auto-spawn required agents
233
+ if (autoSpawnAgents) {
234
+ const requiredAgents = this.determineRequiredAgents(description, complexity);
235
+ for (const agentType of requiredAgents) {
236
+ await this.ensureAgent(agentType);
237
+ }
238
+ }
239
+
240
+ return {
241
+ continue: true,
242
+ reason: 'Task prepared with optimal configuration',
243
+ metadata: {
244
+ complexity,
245
+ topology,
246
+ agentsReady: true,
247
+ estimatedDuration: complexity.estimatedMinutes * 60000,
248
+ },
249
+ };
250
+ }
251
+
252
+ /**
253
+ * Post-edit hook - Format and learn from edits
254
+ */
255
+ async postEditHook(args) {
256
+ const { file, autoFormat, trainPatterns, updateGraph } = args;
257
+ const result = {
258
+ continue: true,
259
+ formatted: false,
260
+ training: null,
261
+ };
262
+
263
+ // Auto-format if requested
264
+ if (autoFormat) {
265
+ const formatted = await this.autoFormatFile(file);
266
+ result.formatted = formatted.success;
267
+ result.formatDetails = formatted.details;
268
+ }
269
+
270
+ // Train neural patterns
271
+ if (trainPatterns) {
272
+ const training = await this.trainPatternsFromEdit(file);
273
+ result.training = training;
274
+ this.sessionData.metrics.patternsImproved += training.improvement || 0;
275
+ }
276
+
277
+ // Update knowledge graph if requested
278
+ if (updateGraph) {
279
+ await this.updateKnowledgeGraph(file, 'edit');
280
+ }
281
+
282
+ // Update session data
283
+ this.sessionData.metrics.tokensSaved += 10; // Estimated savings
284
+
285
+ return result;
286
+ }
287
+
288
+ /**
289
+ * Post-task hook - Analyze performance and update coordination
290
+ */
291
+ async postTaskHook(args) {
292
+ const { taskId, analyzePerformance, updateCoordination } = args;
293
+
294
+ const performance = {
295
+ taskId,
296
+ completionTime: Date.now() - (this.sessionData.taskStartTimes?.get(taskId) || Date.now()),
297
+ agentsUsed: this.sessionData.taskAgents?.get(taskId) || [],
298
+ success: true,
299
+ };
300
+
301
+ // Analyze performance
302
+ if (analyzePerformance) {
303
+ performance.analysis = {
304
+ efficiency: this.calculateEfficiency(performance),
305
+ bottlenecks: this.identifyBottlenecks(performance),
306
+ improvements: this.suggestImprovements(performance),
307
+ };
308
+ }
309
+
310
+ // Update coordination strategies
311
+ if (updateCoordination) {
312
+ this.updateCoordinationStrategy(performance);
313
+ }
314
+
315
+ this.sessionData.metrics.tasksCompleted++;
316
+
317
+ return {
318
+ continue: true,
319
+ performance,
320
+ metadata: { taskId, optimized: true },
321
+ };
322
+ }
323
+
324
+ /**
325
+ * Post-web-search hook - Analyze results and update knowledge
326
+ */
327
+ async postWebSearchHook(args) {
328
+ const { query, updateKnowledge } = args;
329
+
330
+ // Track search patterns
331
+ if (!this.sessionData.searchPatterns) {
332
+ this.sessionData.searchPatterns = new Map();
333
+ }
334
+
335
+ const patterns = this.extractSearchPatterns(query);
336
+ patterns.forEach(pattern => {
337
+ const count = this.sessionData.searchPatterns.get(pattern) || 0;
338
+ this.sessionData.searchPatterns.set(pattern, count + 1);
339
+ });
340
+
341
+ // Update knowledge base
342
+ if (updateKnowledge) {
343
+ await this.updateKnowledgeBase('search', { query, patterns });
344
+ }
345
+
346
+ return {
347
+ continue: true,
348
+ reason: 'Search analyzed and knowledge updated',
349
+ metadata: {
350
+ query,
351
+ patternsExtracted: patterns.length,
352
+ knowledgeUpdated: updateKnowledge,
353
+ },
354
+ };
355
+ }
356
+
357
+ /**
358
+ * Post-web-fetch hook - Extract patterns and cache content
359
+ */
360
+ async postWebFetchHook(args) {
361
+ const { url, extractPatterns, cacheContent } = args;
362
+
363
+ const result = {
364
+ continue: true,
365
+ patterns: [],
366
+ cached: false,
367
+ };
368
+
369
+ // Extract patterns from URL
370
+ if (extractPatterns) {
371
+ result.patterns = this.extractUrlPatterns(url);
372
+ }
373
+
374
+ // Cache content for future use
375
+ if (cacheContent) {
376
+ if (!this.sessionData.contentCache) {
377
+ this.sessionData.contentCache = new Map();
378
+ }
379
+ this.sessionData.contentCache.set(url, {
380
+ timestamp: Date.now(),
381
+ patterns: result.patterns,
382
+ });
383
+ result.cached = true;
384
+ }
385
+
386
+ return result;
387
+ }
388
+
389
+ /**
390
+ * Notification hook - Handle notifications with swarm status
391
+ */
392
+ async notificationHook(args) {
393
+ const { message, level, withSwarmStatus, sendTelemetry, type, context, agentId } = args;
394
+
395
+ const notification = {
396
+ message,
397
+ level: level || 'info',
398
+ type: type || 'general',
399
+ context: context || {},
400
+ agentId: agentId || null,
401
+ timestamp: Date.now(),
402
+ };
403
+
404
+ // Add swarm status if requested
405
+ if (withSwarmStatus) {
406
+ const status = await this.getSwarmStatus();
407
+ notification.swarmStatus = {
408
+ agents: status.agents?.size || 0,
409
+ activeTasks: status.activeTasks || 0,
410
+ health: status.health || 'unknown',
411
+ };
412
+ }
413
+
414
+ // Send telemetry if enabled
415
+ if (sendTelemetry && process.env.RUV_SWARM_TELEMETRY_ENABLED === 'true') {
416
+ this.sendTelemetry('notification', notification);
417
+ }
418
+
419
+ // Store notification in both runtime memory AND persistent database
420
+ if (!this.sessionData.notifications) {
421
+ this.sessionData.notifications = [];
422
+ }
423
+ this.sessionData.notifications.push(notification);
424
+
425
+ // CRITICAL FIX: Also store in persistent database for cross-agent access
426
+ await this.storeNotificationInDatabase(notification);
427
+
428
+ return {
429
+ continue: true,
430
+ notification,
431
+ handled: true,
432
+ };
433
+ }
434
+
435
+ /**
436
+ * Pre-bash hook - Validate commands before execution
437
+ */
438
+ async preBashHook(args) {
439
+ const { command } = args;
440
+
441
+ // Safety checks
442
+ const safetyCheck = this.validateCommandSafety(command);
443
+ if (!safetyCheck.safe) {
444
+ return {
445
+ continue: false,
446
+ reason: safetyCheck.reason,
447
+ riskLevel: safetyCheck.riskLevel,
448
+ };
449
+ }
450
+
451
+ // Check resource requirements
452
+ const resources = this.estimateCommandResources(command);
453
+ if (resources.requiresAgent) {
454
+ await this.ensureAgent(resources.agentType);
455
+ }
456
+
457
+ return {
458
+ continue: true,
459
+ reason: 'Command validated and resources available',
460
+ metadata: {
461
+ estimatedDuration: resources.duration,
462
+ requiresAgent: resources.requiresAgent,
463
+ },
464
+ };
465
+ }
466
+
467
+ /**
468
+ * MCP swarm initialized hook - Persist configuration
469
+ */
470
+ async mcpSwarmInitializedHook(args) {
471
+ const { swarmId, topology, persistConfig, enableMonitoring } = args;
472
+
473
+ // Store swarm configuration
474
+ const swarmConfig = {
475
+ id: swarmId,
476
+ topology,
477
+ initialized: Date.now(),
478
+ monitoring: enableMonitoring,
479
+ };
480
+
481
+ // Persist configuration
482
+ if (persistConfig) {
483
+ const configDir = path.join(process.cwd(), '.@sparkleideas/ruv-swarm');
484
+ await fs.mkdir(configDir, { recursive: true });
485
+ await fs.writeFile(
486
+ path.join(configDir, 'swarm-config.json'),
487
+ JSON.stringify(swarmConfig, null, 2),
488
+ );
489
+ }
490
+
491
+ // Initialize monitoring
492
+ if (enableMonitoring) {
493
+ this.sessionData.monitoring = {
494
+ swarmId,
495
+ startTime: Date.now(),
496
+ events: [],
497
+ };
498
+ }
499
+
500
+ return {
501
+ continue: true,
502
+ reason: 'Swarm initialized and configured',
503
+ metadata: swarmConfig,
504
+ };
505
+ }
506
+
507
+ /**
508
+ * MCP agent spawned hook - Update roster and train
509
+ */
510
+ async mcpAgentSpawnedHook(args) {
511
+ const { agentId, type, updateRoster, trainSpecialization } = args;
512
+
513
+ // Update agent roster
514
+ if (updateRoster) {
515
+ const agent = {
516
+ id: agentId,
517
+ type,
518
+ specialization: this.getSpecializationForType(type),
519
+ spawned: Date.now(),
520
+ performance: { tasks: 0, successRate: 1.0 },
521
+ };
522
+
523
+ this.sessionData.agents.set(agentId, agent);
524
+
525
+ // Persist roster
526
+ const rosterPath = path.join(process.cwd(), '.@sparkleideas/ruv-swarm', 'agent-roster.json');
527
+ const roster = Array.from(this.sessionData.agents.values());
528
+ await fs.writeFile(rosterPath, JSON.stringify(roster, null, 2));
529
+ }
530
+
531
+ // Train specialization patterns
532
+ if (trainSpecialization) {
533
+ const training = {
534
+ agentId,
535
+ type,
536
+ patterns: this.generateSpecializationPatterns(type),
537
+ confidence: 0.9 + Math.random() * 0.1,
538
+ };
539
+
540
+ this.sessionData.learnings.push(training);
541
+ }
542
+
543
+ return {
544
+ continue: true,
545
+ agentId,
546
+ type,
547
+ specialized: true,
548
+ };
549
+ }
550
+
551
+ /**
552
+ * MCP task orchestrated hook - Monitor and optimize
553
+ */
554
+ async mcpTaskOrchestratedHook(args) {
555
+ const { taskId, monitorProgress, optimizeDistribution } = args;
556
+
557
+ // Initialize task tracking
558
+ if (!this.sessionData.taskStartTimes) {
559
+ this.sessionData.taskStartTimes = new Map();
560
+ }
561
+ if (!this.sessionData.taskAgents) {
562
+ this.sessionData.taskAgents = new Map();
563
+ }
564
+
565
+ this.sessionData.taskStartTimes.set(taskId, Date.now());
566
+
567
+ // Monitor progress setup
568
+ if (monitorProgress) {
569
+ this.sessionData.taskMonitoring = this.sessionData.taskMonitoring || new Map();
570
+ this.sessionData.taskMonitoring.set(taskId, {
571
+ checkpoints: [],
572
+ resources: [],
573
+ bottlenecks: [],
574
+ });
575
+ }
576
+
577
+ // Optimize distribution
578
+ if (optimizeDistribution) {
579
+ const optimization = {
580
+ taskId,
581
+ strategy: 'load-balanced',
582
+ agentAllocation: this.optimizeAgentAllocation(taskId),
583
+ parallelization: this.calculateParallelization(taskId),
584
+ };
585
+
586
+ return {
587
+ continue: true,
588
+ taskId,
589
+ optimization,
590
+ };
591
+ }
592
+
593
+ return {
594
+ continue: true,
595
+ taskId,
596
+ monitoring: monitorProgress,
597
+ };
598
+ }
599
+
600
+ /**
601
+ * MCP neural trained hook - Save improvements
602
+ */
603
+ async mcpNeuralTrainedHook(args) {
604
+ const { improvement, saveWeights, updatePatterns } = args;
605
+
606
+ const result = {
607
+ continue: true,
608
+ improvement: parseFloat(improvement),
609
+ saved: false,
610
+ patternsUpdated: false,
611
+ };
612
+
613
+ // Save neural weights
614
+ if (saveWeights) {
615
+ const weightsDir = path.join(process.cwd(), '.@sparkleideas/ruv-swarm', 'neural-weights');
616
+ await fs.mkdir(weightsDir, { recursive: true });
617
+
618
+ const weightData = {
619
+ timestamp: Date.now(),
620
+ improvement,
621
+ weights: this.generateMockWeights(),
622
+ version: this.sessionData.learnings.length,
623
+ };
624
+
625
+ await fs.writeFile(
626
+ path.join(weightsDir, `weights-${Date.now()}.json`),
627
+ JSON.stringify(weightData, null, 2),
628
+ );
629
+
630
+ result.saved = true;
631
+ }
632
+
633
+ // Update cognitive patterns
634
+ if (updatePatterns) {
635
+ this.sessionData.metrics.patternsImproved++;
636
+
637
+ const patternUpdate = {
638
+ timestamp: Date.now(),
639
+ improvement,
640
+ patterns: ['convergent', 'divergent', 'lateral'],
641
+ confidence: 0.85 + parseFloat(improvement),
642
+ };
643
+
644
+ this.sessionData.learnings.push(patternUpdate);
645
+ result.patternsUpdated = true;
646
+ }
647
+
648
+ return result;
649
+ }
650
+
651
+ /**
652
+ * Agent complete hook - Commit to git with detailed report
653
+ */
654
+ async agentCompleteHook(args) {
655
+ const { agent, prompt, output, commitToGit, generateReport, pushToGithub } = args;
656
+
657
+ try {
658
+ const timestamp = new Date().toISOString();
659
+ const agentName = agent || 'Unknown Agent';
660
+ // const shortOutput = output ? `${output.substring(0, 500) }...` : 'No output';
661
+
662
+ // Generate detailed report
663
+ let reportPath = null;
664
+ if (generateReport) {
665
+ const reportDir = path.join(process.cwd(), '.@sparkleideas/ruv-swarm', 'agent-reports');
666
+ await fs.mkdir(reportDir, { recursive: true });
667
+
668
+ const sanitizedAgent = agentName.replace(/[^a-zA-Z0-9-]/g, '-').toLowerCase();
669
+ reportPath = path.join(reportDir, `${sanitizedAgent}-${Date.now()}.md`);
670
+
671
+ const report = `# Agent Completion Report: ${agentName}
672
+
673
+ ## Metadata
674
+ - **Agent**: ${agentName}
675
+ - **Timestamp**: ${timestamp}
676
+ - **Session**: ${this.sessionData.sessionId || 'N/A'}
677
+ - **Duration**: ${this.formatDuration(Date.now() - this.sessionData.startTime)}
678
+
679
+ ## Task Description
680
+ \`\`\`
681
+ ${prompt || 'No prompt available'}
682
+ \`\`\`
683
+
684
+ ## Output Summary
685
+ ${output ? `### Key Accomplishments\n${ this.extractKeyPoints(output)}` : 'No output captured'}
686
+
687
+ ## Performance Metrics
688
+ - **Total Operations**: ${this.sessionData.operations.length}
689
+ - **Files Modified**: ${this.getModifiedFilesCount()}
690
+ - **Efficiency Score**: ${this.calculateEfficiency({ completionTime: Date.now() - this.sessionData.startTime }).rating}
691
+ - **Tokens Saved**: ${this.sessionData.metrics.tokensSaved}
692
+
693
+ ## Files Modified
694
+ ${this.getModifiedFilesList()}
695
+
696
+ ## Coordination Activity
697
+ - **Memory Operations**: ${this.sessionData.operations.filter(op => op.type === 'memory').length}
698
+ - **Hook Executions**: ${this.sessionData.operations.filter(op => op.type === 'hook').length}
699
+ - **Neural Training**: ${this.sessionData.metrics.patternsImproved} patterns improved
700
+
701
+ ## Learnings & Patterns
702
+ ${this.sessionData.learnings.length > 0 ? this.sessionData.learnings.map(l => `- ${l.type || 'General'}: ${l.description || JSON.stringify(l)}`).join('\n') : 'No specific learnings captured'}
703
+
704
+ ---
705
+ *Generated by @sparkleideas/ruv-swarm agent coordination system*
706
+ `;
707
+
708
+ await fs.writeFile(reportPath, report);
709
+ }
710
+
711
+ // Commit to git if requested
712
+ if (commitToGit) {
713
+ try {
714
+ // Check if we're in a git repo
715
+ execSync('git rev-parse --git-dir', { stdio: 'ignore' });
716
+
717
+ // Get git status
718
+ const status = execSync('git status --porcelain', { encoding: 'utf-8' });
719
+
720
+ if (status.trim()) {
721
+ // Stage changes
722
+ execSync('git add -A');
723
+
724
+ // Create detailed commit message
725
+ const commitMessage = `feat(${agentName.toLowerCase().replace(/[^a-z0-9]/g, '-')}): Complete agent task
726
+
727
+ Agent: ${agentName}
728
+ Timestamp: ${timestamp}
729
+
730
+ ## Task Summary
731
+ ${prompt ? `${prompt.split('\n')[0].substring(0, 100) }...` : 'No task description'}
732
+
733
+ ## Achievements
734
+ ${this.extractBulletPoints(output)}
735
+
736
+ ## Metrics
737
+ - Operations: ${this.sessionData.operations.length}
738
+ - Files: ${this.getModifiedFilesCount()}
739
+ - Efficiency: ${this.calculateEfficiency({ completionTime: Date.now() - this.sessionData.startTime }).rating}
740
+ ${reportPath ? `\n## Report\nDetailed report: ${path.relative(process.cwd(), reportPath)}` : ''}
741
+
742
+ 🤖 Generated by @sparkleideas/ruv-swarm agent coordination
743
+ Co-Authored-By: ${agentName} <agent@ruv-swarm.ai>`;
744
+
745
+ // Commit using heredoc to handle complex messages
746
+ const commitCmd = `git commit -m "$(cat <<'EOF'
747
+ ${commitMessage}
748
+ EOF
749
+ )"`;
750
+ execSync(commitCmd, { shell: '/bin/bash' });
751
+
752
+ // Log commit info
753
+ const commitHash = execSync('git rev-parse HEAD', { encoding: 'utf-8' }).trim();
754
+ console.log(`✅ Committed agent work: ${commitHash.substring(0, 7)}`);
755
+
756
+ // Push if requested and configured
757
+ if (pushToGithub && process.env.RUV_SWARM_AUTO_PUSH === 'true') {
758
+ console.log('📤 Pushing to GitHub...');
759
+ execSync('git push', { stdio: 'inherit' });
760
+ console.log('✅ Pushed to GitHub');
761
+ }
762
+ } else {
763
+ console.log('ℹ️ No changes to commit');
764
+ }
765
+
766
+ } catch (gitError) {
767
+ console.error('Git operation failed:', gitError.message);
768
+ }
769
+ }
770
+
771
+ // Update telemetry
772
+ this.sendTelemetry('agent_complete', {
773
+ agent: agentName,
774
+ hasReport: generateReport,
775
+ hasCommit: commitToGit,
776
+ operationCount: this.sessionData.operations.length,
777
+ duration: Date.now() - this.sessionData.startTime,
778
+ });
779
+
780
+ return {
781
+ continue: true,
782
+ agent: agentName,
783
+ reportGenerated: generateReport,
784
+ reportPath: reportPath ? path.relative(process.cwd(), reportPath) : null,
785
+ committed: commitToGit,
786
+ duration: this.formatDuration(Date.now() - this.sessionData.startTime),
787
+ };
788
+
789
+ } catch (error) {
790
+ console.error('Agent complete hook error:', error);
791
+ return {
792
+ continue: true,
793
+ error: error.message,
794
+ };
795
+ }
796
+ }
797
+
798
+ /**
799
+ * Extract key points from output
800
+ */
801
+ extractKeyPoints(output) {
802
+ const lines = output.split('\n').filter(l => l.trim());
803
+ const keyPoints = [];
804
+
805
+ // Look for bullet points or numbered items
806
+ lines.forEach(line => {
807
+ if (line.match(/^[\-\*•]\s/) || line.match(/^\d+\.\s/)) {
808
+ keyPoints.push(line);
809
+ }
810
+ });
811
+
812
+ // If no bullet points, take first few lines
813
+ if (keyPoints.length === 0) {
814
+ keyPoints.push(...lines.slice(0, 5));
815
+ }
816
+
817
+ return keyPoints.slice(0, 10).join('\n');
818
+ }
819
+
820
+ /**
821
+ * Extract bullet points for commit message
822
+ */
823
+ extractBulletPoints(output) {
824
+ if (!output) {
825
+ return '- No specific achievements captured';
826
+ }
827
+
828
+ const points = this.extractKeyPoints(output)
829
+ .split('\n')
830
+ .slice(0, 5)
831
+ .map(p => `- ${p.replace(/^[\-\*•\d+\.\s]+/, '').trim()}`);
832
+
833
+ return points.length > 0 ? points.join('\n') : '- Task completed successfully';
834
+ }
835
+
836
+ /**
837
+ * Get count of modified files
838
+ */
839
+ getModifiedFilesCount() {
840
+ const fileOps = this.sessionData.operations.filter(op =>
841
+ ['edit', 'write', 'create'].includes(op.type),
842
+ );
843
+
844
+ const uniqueFiles = new Set(fileOps.map(op => op.file).filter(Boolean));
845
+ return uniqueFiles.size;
846
+ }
847
+
848
+ /**
849
+ * Get list of modified files
850
+ */
851
+ getModifiedFilesList() {
852
+ const fileOps = this.sessionData.operations.filter(op =>
853
+ ['edit', 'write', 'create'].includes(op.type),
854
+ );
855
+
856
+ const fileMap = new Map();
857
+ fileOps.forEach(op => {
858
+ if (op.file) {
859
+ if (!fileMap.has(op.file)) {
860
+ fileMap.set(op.file, []);
861
+ }
862
+ fileMap.get(op.file).push(op.type);
863
+ }
864
+ });
865
+
866
+ if (fileMap.size === 0) {
867
+ return 'No files modified';
868
+ }
869
+
870
+ return Array.from(fileMap.entries())
871
+ .map(([file, ops]) => `- ${file} (${[...new Set(ops)].join(', ')})`)
872
+ .join('\n');
873
+ }
874
+
875
+ /**
876
+ * Session restore hook - Load previous state
877
+ */
878
+ async sessionRestoreHook(args) {
879
+ const { loadMemory, loadAgents } = args;
880
+
881
+ const result = {
882
+ continue: true,
883
+ restored: {
884
+ memory: false,
885
+ agents: false,
886
+ metrics: false,
887
+ },
888
+ };
889
+
890
+ try {
891
+ const sessionDir = path.join(process.cwd(), '.@sparkleideas/ruv-swarm');
892
+
893
+ // Load memory state
894
+ if (loadMemory) {
895
+ const memoryPath = path.join(sessionDir, 'memory-state.json');
896
+ if (await fs.access(memoryPath).then(() => true).catch(() => false)) {
897
+ const memory = JSON.parse(await fs.readFile(memoryPath, 'utf-8'));
898
+ this.sessionData = { ...this.sessionData, ...memory };
899
+ result.restored.memory = true;
900
+ }
901
+ }
902
+
903
+ // Load agent roster
904
+ if (loadAgents) {
905
+ const rosterPath = path.join(sessionDir, 'agent-roster.json');
906
+ if (await fs.access(rosterPath).then(() => true).catch(() => false)) {
907
+ const roster = JSON.parse(await fs.readFile(rosterPath, 'utf-8'));
908
+ roster.forEach(agent => {
909
+ this.sessionData.agents.set(agent.id, agent);
910
+ });
911
+ result.restored.agents = true;
912
+ }
913
+ }
914
+
915
+ // Load metrics
916
+ const metricsPath = path.join(sessionDir, 'session-metrics.json');
917
+ if (await fs.access(metricsPath).then(() => true).catch(() => false)) {
918
+ const metrics = JSON.parse(await fs.readFile(metricsPath, 'utf-8'));
919
+ this.sessionData.metrics = { ...this.sessionData.metrics, ...metrics };
920
+ result.restored.metrics = true;
921
+ }
922
+
923
+ } catch (error) {
924
+ console.error('Session restore error:', error.message);
925
+ }
926
+
927
+ return result;
928
+ }
929
+
930
+ /**
931
+ * Session end hook - Generate summary and persist state
932
+ */
933
+ async sessionEndHook(args) {
934
+ const { generateSummary, saveMemory, exportMetrics } = args;
935
+ const sessionDir = path.join(process.cwd(), '.claude', 'sessions');
936
+ await fs.mkdir(sessionDir, { recursive: true });
937
+
938
+ const timestamp = new Date().toISOString().replace(/:/g, '-');
939
+ const results = {};
940
+
941
+ // Generate summary
942
+ if (generateSummary) {
943
+ const summary = this.generateSessionSummary();
944
+ const summaryPath = path.join(sessionDir, `${timestamp}-summary.md`);
945
+ await fs.writeFile(summaryPath, summary);
946
+ results.summary = summaryPath;
947
+ }
948
+
949
+ // Save memory state
950
+ if (saveMemory) {
951
+ const state = this.captureSwarmState();
952
+ const statePath = path.join(sessionDir, `${timestamp}-state.json`);
953
+ await fs.writeFile(statePath, JSON.stringify(state, null, 2));
954
+ results.state = statePath;
955
+ }
956
+
957
+ // Export metrics
958
+ if (exportMetrics) {
959
+ const metrics = this.calculateSessionMetrics();
960
+ const metricsPath = path.join(sessionDir, `${timestamp}-metrics.json`);
961
+ await fs.writeFile(metricsPath, JSON.stringify(metrics, null, 2));
962
+ results.metrics = metricsPath;
963
+ }
964
+
965
+ console.log('\n🎯 Session Summary:');
966
+ console.log(`Duration: ${this.formatDuration(Date.now() - this.sessionData.startTime)}`);
967
+ console.log(`Operations: ${this.sessionData.operations.length}`);
968
+ console.log(`Tokens Saved: ${this.sessionData.metrics.tokensSaved}`);
969
+ console.log(`Patterns Improved: ${this.sessionData.metrics.patternsImproved}`);
970
+
971
+ return {
972
+ continue: true,
973
+ files: results,
974
+ summary: {
975
+ duration: Date.now() - this.sessionData.startTime,
976
+ operations: this.sessionData.operations.length,
977
+ improvements: this.sessionData.metrics.patternsImproved,
978
+ },
979
+ };
980
+ }
981
+
982
+ // Helper methods
983
+
984
+ getAgentTypeForFile(extension) {
985
+ const mapping = {
986
+ '.js': 'coder',
987
+ '.ts': 'coder',
988
+ '.jsx': 'coder',
989
+ '.tsx': 'coder',
990
+ '.py': 'coder',
991
+ '.go': 'coder',
992
+ '.rs': 'coder',
993
+ '.md': 'researcher',
994
+ '.txt': 'researcher',
995
+ '.json': 'analyst',
996
+ '.yaml': 'analyst',
997
+ '.yml': 'analyst',
998
+ '.toml': 'analyst',
999
+ '.xml': 'analyst',
1000
+ '.sql': 'analyst',
1001
+ };
1002
+ return mapping[extension] || 'coordinator';
1003
+ }
1004
+
1005
+ async checkSwarmStatus() {
1006
+ try {
1007
+ // Check if swarm is initialized via file or global state
1008
+ const statusFile = path.join(process.cwd(), '.@sparkleideas/ruv-swarm', 'status.json');
1009
+ const exists = await fs.access(statusFile).then(() => true).catch(() => false);
1010
+
1011
+ if (exists) {
1012
+ const status = JSON.parse(await fs.readFile(statusFile, 'utf-8'));
1013
+ return { initialized: true, ...status };
1014
+ }
1015
+
1016
+ return { initialized: false };
1017
+ } catch (_error) {
1018
+ return { initialized: false };
1019
+ }
1020
+ }
1021
+
1022
+ async ensureAgent(type) {
1023
+ let agent = this.sessionData.agents.get(type);
1024
+
1025
+ if (!agent) {
1026
+ // Simulate agent creation
1027
+ agent = {
1028
+ id: `${type}-${Date.now()}`,
1029
+ type,
1030
+ pattern: this.getCognitivePattern(type),
1031
+ readiness: 0.95,
1032
+ created: Date.now(),
1033
+ };
1034
+ this.sessionData.agents.set(type, agent);
1035
+ }
1036
+
1037
+ return agent;
1038
+ }
1039
+
1040
+ getCognitivePattern(agentType) {
1041
+ const patterns = {
1042
+ coder: 'convergent',
1043
+ researcher: 'divergent',
1044
+ analyst: 'critical',
1045
+ coordinator: 'systems',
1046
+ architect: 'abstract',
1047
+ optimizer: 'lateral',
1048
+ };
1049
+ return patterns[agentType] || 'balanced';
1050
+ }
1051
+
1052
+ async autoFormatFile(filePath) {
1053
+ const ext = path.extname(filePath);
1054
+ const formatters = {
1055
+ '.js': 'prettier --write',
1056
+ '.ts': 'prettier --write',
1057
+ '.jsx': 'prettier --write',
1058
+ '.tsx': 'prettier --write',
1059
+ '.json': 'prettier --write',
1060
+ '.md': 'prettier --write --prose-wrap always',
1061
+ '.py': 'black',
1062
+ '.go': 'gofmt -w',
1063
+ '.rs': 'rustfmt',
1064
+ };
1065
+
1066
+ const formatter = formatters[ext];
1067
+ if (!formatter) {
1068
+ return { success: false, reason: 'No formatter configured for file type' };
1069
+ }
1070
+
1071
+ try {
1072
+ execSync(`${formatter} "${filePath}"`, { stdio: 'pipe' });
1073
+ return { success: true, details: { formatter, fileType: ext } };
1074
+ } catch (error) {
1075
+ return { success: false, reason: error.message };
1076
+ }
1077
+ }
1078
+
1079
+ async trainPatternsFromEdit(filePath) {
1080
+ // Simulate neural pattern training
1081
+ const improvement = Math.random() * 0.05; // 0-5% improvement
1082
+ const confidence = 0.85 + Math.random() * 0.1; // 85-95% confidence
1083
+
1084
+ this.sessionData.learnings.push({
1085
+ file: filePath,
1086
+ timestamp: Date.now(),
1087
+ improvement,
1088
+ confidence,
1089
+ pattern: `edit_pattern_${ path.extname(filePath)}`,
1090
+ });
1091
+
1092
+ return {
1093
+ pattern_updated: true,
1094
+ improvement: improvement.toFixed(3),
1095
+ confidence: confidence.toFixed(2),
1096
+ total_examples: this.sessionData.learnings.length,
1097
+ };
1098
+ }
1099
+
1100
+ validateCommandSafety(command) {
1101
+ const dangerousPatterns = [
1102
+ /rm\s+-rf\s+\//,
1103
+ /curl.*\|\s*bash/,
1104
+ /wget.*\|\s*sh/,
1105
+ /eval\s*\(/,
1106
+ />\/dev\/null\s+2>&1/,
1107
+ ];
1108
+
1109
+ for (const pattern of dangerousPatterns) {
1110
+ if (pattern.test(command)) {
1111
+ return {
1112
+ safe: false,
1113
+ reason: 'Command contains potentially dangerous pattern',
1114
+ riskLevel: 'high',
1115
+ };
1116
+ }
1117
+ }
1118
+
1119
+ return { safe: true };
1120
+ }
1121
+
1122
+ estimateCommandResources(command) {
1123
+ const resourceMap = {
1124
+ 'npm test': { duration: 30000, requiresAgent: true, agentType: 'coordinator' },
1125
+ 'npm run build': { duration: 60000, requiresAgent: true, agentType: 'optimizer' },
1126
+ 'git': { duration: 1000, requiresAgent: false },
1127
+ 'ls': { duration: 100, requiresAgent: false },
1128
+ };
1129
+
1130
+ for (const [pattern, resources] of Object.entries(resourceMap)) {
1131
+ if (command.includes(pattern)) {
1132
+ return resources;
1133
+ }
1134
+ }
1135
+
1136
+ return { duration: 5000, requiresAgent: false };
1137
+ }
1138
+
1139
+ generateSessionSummary() {
1140
+ const duration = Date.now() - this.sessionData.startTime;
1141
+ const agentList = Array.from(this.sessionData.agents.values());
1142
+
1143
+ return `# @sparkleideas/ruv-swarm Session Summary
1144
+ Date: ${new Date().toISOString()}
1145
+ Duration: ${this.formatDuration(duration)}
1146
+ Token Reduction: ${this.sessionData.metrics.tokensSaved} tokens
1147
+
1148
+ ## Swarm Activity
1149
+ - Active Agents: ${agentList.length} (${agentList.map(a => a.type).join(', ')})
1150
+ - Operations Performed: ${this.sessionData.operations.length}
1151
+ - Files Modified: ${new Set(this.sessionData.operations.map(o => o.file)).size}
1152
+ - Neural Improvements: ${this.sessionData.metrics.patternsImproved}
1153
+
1154
+ ## Operations Breakdown
1155
+ ${this.sessionData.operations.slice(-10).map(op =>
1156
+ `- ${new Date(op.timestamp).toLocaleTimeString()}: ${op.type} on ${op.file} (${op.agent})`,
1157
+ ).join('\n')}
1158
+
1159
+ ## Learning Highlights
1160
+ ${this.sessionData.learnings.slice(-5).map(l =>
1161
+ `- Pattern "${l.pattern}" improved by ${(l.improvement * 100).toFixed(1)}% (confidence: ${l.confidence})`,
1162
+ ).join('\n')}
1163
+
1164
+ ## Performance Metrics
1165
+ - Average Operation Time: ${(duration / this.sessionData.operations.length / 1000).toFixed(1)}s
1166
+ - Token Efficiency: ${(this.sessionData.metrics.tokensSaved / this.sessionData.operations.length).toFixed(0)} tokens/operation
1167
+ - Learning Rate: ${(this.sessionData.metrics.patternsImproved / this.sessionData.operations.length).toFixed(2)} improvements/operation
1168
+ `;
1169
+ }
1170
+
1171
+ captureSwarmState() {
1172
+ return {
1173
+ session_id: `sess-${Date.now()}`,
1174
+ agents: Object.fromEntries(this.sessionData.agents),
1175
+ operations: this.sessionData.operations,
1176
+ learnings: this.sessionData.learnings,
1177
+ metrics: this.sessionData.metrics,
1178
+ timestamp: new Date().toISOString(),
1179
+ };
1180
+ }
1181
+
1182
+ calculateSessionMetrics() {
1183
+ const duration = Date.now() - this.sessionData.startTime;
1184
+ return {
1185
+ performance: {
1186
+ duration_ms: duration,
1187
+ operations_per_minute: (this.sessionData.operations.length / (duration / 60000)).toFixed(1),
1188
+ tokens_saved: this.sessionData.metrics.tokensSaved,
1189
+ efficiency_score: (this.sessionData.metrics.tokensSaved / this.sessionData.operations.length).toFixed(1),
1190
+ },
1191
+ learning: {
1192
+ patterns_improved: this.sessionData.metrics.patternsImproved,
1193
+ average_improvement: (this.sessionData.learnings.reduce((acc, l) => acc + l.improvement, 0) / this.sessionData.learnings.length).toFixed(3),
1194
+ confidence_average: (this.sessionData.learnings.reduce((acc, l) => acc + l.confidence, 0) / this.sessionData.learnings.length).toFixed(2),
1195
+ },
1196
+ agents: {
1197
+ total_spawned: this.sessionData.agents.size,
1198
+ by_type: Object.fromEntries(
1199
+ Array.from(this.sessionData.agents.values())
1200
+ .reduce((acc, agent) => {
1201
+ acc.set(agent.type, (acc.get(agent.type) || 0) + 1);
1202
+ return acc;
1203
+ }, new Map()),
1204
+ ),
1205
+ },
1206
+ };
1207
+ }
1208
+
1209
+ formatDuration(ms) {
1210
+ const seconds = Math.floor(ms / 1000);
1211
+ const minutes = Math.floor(seconds / 60);
1212
+ const hours = Math.floor(minutes / 60);
1213
+
1214
+ if (hours > 0) {
1215
+ return `${hours}h ${minutes % 60}m`;
1216
+ } else if (minutes > 0) {
1217
+ return `${minutes}m ${seconds % 60}s`;
1218
+ }
1219
+ return `${seconds}s`;
1220
+
1221
+ }
1222
+
1223
+ // Additional helper methods for optimization
1224
+
1225
+ analyzeTaskComplexity(description) {
1226
+ const keywords = {
1227
+ simple: ['fix', 'update', 'change', 'modify', 'rename'],
1228
+ medium: ['implement', 'create', 'add', 'integrate', 'refactor'],
1229
+ complex: ['architect', 'design', 'optimize', 'migrate', 'scale'],
1230
+ };
1231
+
1232
+ const desc = description.toLowerCase();
1233
+ let complexity = 'simple';
1234
+ let score = 1;
1235
+ let estimatedMinutes = 5;
1236
+
1237
+ // Check for complex keywords
1238
+ if (keywords.complex.some(k => desc.includes(k))) {
1239
+ complexity = 'complex';
1240
+ score = 3;
1241
+ estimatedMinutes = 60;
1242
+ } else if (keywords.medium.some(k => desc.includes(k))) {
1243
+ complexity = 'medium';
1244
+ score = 2;
1245
+ estimatedMinutes = 30;
1246
+ }
1247
+
1248
+ // Adjust for multiple files or components
1249
+ const fileCount = (desc.match(/\b(files?|components?|modules?)\b/g) || []).length;
1250
+ if (fileCount > 1) {
1251
+ score += 0.5;
1252
+ estimatedMinutes *= 1.5;
1253
+ }
1254
+
1255
+ return {
1256
+ level: complexity,
1257
+ score,
1258
+ estimatedMinutes,
1259
+ requiresResearch: desc.includes('research') || desc.includes('analyze'),
1260
+ requiresTesting: desc.includes('test') || desc.includes('verify'),
1261
+ };
1262
+ }
1263
+
1264
+ selectOptimalTopology(complexity) {
1265
+ const topologyMap = {
1266
+ simple: 'star', // Centralized for simple tasks
1267
+ medium: 'mesh', // Flexible for medium complexity
1268
+ complex: 'hierarchical', // Structured for complex tasks
1269
+ };
1270
+
1271
+ return topologyMap[complexity.level] || 'mesh';
1272
+ }
1273
+
1274
+ determineRequiredAgents(description, complexity) {
1275
+ const agents = new Set(['coordinator']); // Always need a coordinator
1276
+
1277
+ const desc = description.toLowerCase();
1278
+
1279
+ // Add agents based on task keywords
1280
+ if (desc.includes('code') || desc.includes('implement') || desc.includes('fix')) {
1281
+ agents.add('coder');
1282
+ }
1283
+ if (desc.includes('research') || desc.includes('analyze') || desc.includes('investigate')) {
1284
+ agents.add('researcher');
1285
+ }
1286
+ if (desc.includes('data') || desc.includes('metrics') || desc.includes('performance')) {
1287
+ agents.add('analyst');
1288
+ }
1289
+ if (desc.includes('design') || desc.includes('architect') || desc.includes('structure')) {
1290
+ agents.add('architect');
1291
+ }
1292
+ if (desc.includes('optimize') || desc.includes('improve') || desc.includes('enhance')) {
1293
+ agents.add('optimizer');
1294
+ }
1295
+
1296
+ // Add more agents for complex tasks
1297
+ if (complexity.score >= 3) {
1298
+ agents.add('reviewer');
1299
+ }
1300
+
1301
+ return Array.from(agents);
1302
+ }
1303
+
1304
+ async updateKnowledgeGraph(file, operation) {
1305
+ if (!this.sessionData.knowledgeGraph) {
1306
+ this.sessionData.knowledgeGraph = {
1307
+ nodes: new Map(),
1308
+ edges: [],
1309
+ };
1310
+ }
1311
+
1312
+ const graph = this.sessionData.knowledgeGraph;
1313
+
1314
+ // Add or update node
1315
+ const nodeId = file;
1316
+ if (!graph.nodes.has(nodeId)) {
1317
+ graph.nodes.set(nodeId, {
1318
+ id: nodeId,
1319
+ type: this.getFileType(file),
1320
+ operations: [],
1321
+ lastModified: Date.now(),
1322
+ });
1323
+ }
1324
+
1325
+ const node = graph.nodes.get(nodeId);
1326
+ node.operations.push({
1327
+ type: operation,
1328
+ timestamp: Date.now(),
1329
+ agent: this.getCurrentAgent(),
1330
+ });
1331
+ node.lastModified = Date.now();
1332
+
1333
+ // Add edges for related files
1334
+ const relatedFiles = await this.findRelatedFiles(file);
1335
+ relatedFiles.forEach(related => {
1336
+ if (!graph.edges.find(e =>
1337
+ (e.from === nodeId && e.to === related) ||
1338
+ (e.from === related && e.to === nodeId),
1339
+ )) {
1340
+ graph.edges.push({
1341
+ from: nodeId,
1342
+ to: related,
1343
+ type: 'related',
1344
+ weight: 1,
1345
+ });
1346
+ }
1347
+ });
1348
+ }
1349
+
1350
+ calculateEfficiency(performance) {
1351
+ const baselineTime = 60000; // 1 minute baseline
1352
+ const efficiencyScore = Math.max(0, Math.min(1, baselineTime / performance.completionTime));
1353
+
1354
+ // Adjust for agent utilization
1355
+ const agentUtilization = performance.agentsUsed.length > 0 ?
1356
+ 0.8 + (0.2 * Math.min(1, 3 / performance.agentsUsed.length)) : 0.5;
1357
+
1358
+ return {
1359
+ score: (efficiencyScore * agentUtilization).toFixed(2),
1360
+ timeEfficiency: efficiencyScore.toFixed(2),
1361
+ agentEfficiency: agentUtilization.toFixed(2),
1362
+ rating: efficiencyScore > 0.8 ? 'excellent' :
1363
+ efficiencyScore > 0.6 ? 'good' :
1364
+ efficiencyScore > 0.4 ? 'fair' : 'needs improvement',
1365
+ };
1366
+ }
1367
+
1368
+ identifyBottlenecks(performance) {
1369
+ const bottlenecks = [];
1370
+
1371
+ // Time-based bottlenecks
1372
+ if (performance.completionTime > 300000) { // > 5 minutes
1373
+ bottlenecks.push({
1374
+ type: 'time',
1375
+ severity: 'high',
1376
+ description: 'Task took longer than expected',
1377
+ recommendation: 'Consider breaking into smaller subtasks',
1378
+ });
1379
+ }
1380
+
1381
+ // Agent-based bottlenecks
1382
+ if (performance.agentsUsed.length === 1) {
1383
+ bottlenecks.push({
1384
+ type: 'coordination',
1385
+ severity: 'medium',
1386
+ description: 'Single agent used for complex task',
1387
+ recommendation: 'Spawn specialized agents for parallel work',
1388
+ });
1389
+ }
1390
+
1391
+ // Resource bottlenecks
1392
+ if (this.sessionData.operations.length > 100) {
1393
+ bottlenecks.push({
1394
+ type: 'operations',
1395
+ severity: 'medium',
1396
+ description: 'High number of operations',
1397
+ recommendation: 'Optimize operation batching',
1398
+ });
1399
+ }
1400
+
1401
+ return bottlenecks;
1402
+ }
1403
+
1404
+ suggestImprovements(performance) {
1405
+ const improvements = [];
1406
+ const efficiency = this.calculateEfficiency(performance);
1407
+
1408
+ // Time improvements
1409
+ if (efficiency.timeEfficiency < 0.7) {
1410
+ improvements.push({
1411
+ area: 'execution_time',
1412
+ suggestion: 'Use parallel task execution',
1413
+ expectedImprovement: '30-50% time reduction',
1414
+ });
1415
+ }
1416
+
1417
+ // Coordination improvements
1418
+ if (efficiency.agentEfficiency < 0.8) {
1419
+ improvements.push({
1420
+ area: 'agent_coordination',
1421
+ suggestion: 'Implement specialized agent patterns',
1422
+ expectedImprovement: '20-30% efficiency gain',
1423
+ });
1424
+ }
1425
+
1426
+ // Pattern improvements
1427
+ if (this.sessionData.learnings.length < 5) {
1428
+ improvements.push({
1429
+ area: 'learning',
1430
+ suggestion: 'Enable neural pattern training',
1431
+ expectedImprovement: 'Cumulative performance gains',
1432
+ });
1433
+ }
1434
+
1435
+ return improvements;
1436
+ }
1437
+
1438
+ updateCoordinationStrategy(performance) {
1439
+ const efficiency = this.calculateEfficiency(performance);
1440
+
1441
+ // Update strategy based on performance
1442
+ if (!this.sessionData.coordinationStrategy) {
1443
+ this.sessionData.coordinationStrategy = {
1444
+ current: 'balanced',
1445
+ history: [],
1446
+ adjustments: 0,
1447
+ };
1448
+ }
1449
+
1450
+ const strategy = this.sessionData.coordinationStrategy;
1451
+ strategy.history.push({
1452
+ timestamp: Date.now(),
1453
+ efficiency: efficiency.score,
1454
+ strategy: strategy.current,
1455
+ });
1456
+
1457
+ // Adjust strategy if needed
1458
+ if (parseFloat(efficiency.score) < 0.6) {
1459
+ strategy.current = 'adaptive';
1460
+ strategy.adjustments++;
1461
+ } else if (parseFloat(efficiency.score) > 0.9) {
1462
+ strategy.current = 'specialized';
1463
+ strategy.adjustments++;
1464
+ }
1465
+ }
1466
+
1467
+ extractSearchPatterns(query) {
1468
+ const patterns = [];
1469
+
1470
+ // Extract file type patterns
1471
+ const fileTypes = query.match(/\.(js|ts|py|go|rs|md|json|yaml)\b/gi);
1472
+ if (fileTypes) {
1473
+ patterns.push(...fileTypes.map(ft => `filetype:${ft}`));
1474
+ }
1475
+
1476
+ // Extract function/class patterns
1477
+ const codePatterns = query.match(/\b(function|class|interface|struct|impl)\s+\w+/gi);
1478
+ if (codePatterns) {
1479
+ patterns.push(...codePatterns.map(cp => `code:${cp}`));
1480
+ }
1481
+
1482
+ // Extract scope patterns
1483
+ const scopePatterns = query.match(/\b(src|test|lib|bin|docs?)\//gi);
1484
+ if (scopePatterns) {
1485
+ patterns.push(...scopePatterns.map(sp => `scope:${sp}`));
1486
+ }
1487
+
1488
+ return patterns;
1489
+ }
1490
+
1491
+ async updateKnowledgeBase(type, data) {
1492
+ const kbPath = path.join(process.cwd(), '.@sparkleideas/ruv-swarm', 'knowledge-base.json');
1493
+
1494
+ // Load existing knowledge base
1495
+ let kb = {};
1496
+ try {
1497
+ if (await fs.access(kbPath).then(() => true).catch(() => false)) {
1498
+ kb = JSON.parse(await fs.readFile(kbPath, 'utf-8'));
1499
+ }
1500
+ } catch (_error) {
1501
+ kb = { searches: [], patterns: {}, insights: [] };
1502
+ }
1503
+
1504
+ // Update based on type
1505
+ if (type === 'search') {
1506
+ if (!kb.searches) {
1507
+ kb.searches = [];
1508
+ }
1509
+ kb.searches.push({
1510
+ query: data.query,
1511
+ patterns: data.patterns,
1512
+ timestamp: Date.now(),
1513
+ });
1514
+
1515
+ // Update pattern frequency
1516
+ if (!kb.patterns) {
1517
+ kb.patterns = {};
1518
+ }
1519
+ data.patterns.forEach(pattern => {
1520
+ kb.patterns[pattern] = (kb.patterns[pattern] || 0) + 1;
1521
+ });
1522
+ }
1523
+
1524
+ // Keep only recent data
1525
+ if (kb.searches && kb.searches.length > 100) {
1526
+ kb.searches = kb.searches.slice(-100);
1527
+ }
1528
+
1529
+ // Save updated knowledge base
1530
+ await fs.mkdir(path.dirname(kbPath), { recursive: true });
1531
+ await fs.writeFile(kbPath, JSON.stringify(kb, null, 2));
1532
+ }
1533
+
1534
+ extractUrlPatterns(url) {
1535
+ const patterns = [];
1536
+
1537
+ try {
1538
+ const urlObj = new URL(url);
1539
+
1540
+ // Domain pattern
1541
+ patterns.push(`domain:${urlObj.hostname}`);
1542
+
1543
+ // Path patterns
1544
+ const pathParts = urlObj.pathname.split('/').filter(p => p);
1545
+ if (pathParts.length > 0) {
1546
+ patterns.push(`path:/${pathParts[0]}`); // Top level path
1547
+ }
1548
+
1549
+ // Content type patterns
1550
+ if (urlObj.pathname.endsWith('.md')) {
1551
+ patterns.push('content:markdown');
1552
+ }
1553
+ if (urlObj.pathname.includes('docs')) {
1554
+ patterns.push('content:documentation');
1555
+ }
1556
+ if (urlObj.pathname.includes('api')) {
1557
+ patterns.push('content:api');
1558
+ }
1559
+ if (urlObj.pathname.includes('guide')) {
1560
+ patterns.push('content:guide');
1561
+ }
1562
+
1563
+ // Query patterns
1564
+ if (urlObj.search) {
1565
+ patterns.push('has:queryparams');
1566
+ }
1567
+ } catch (_error) {
1568
+ patterns.push('pattern:invalid-url');
1569
+ }
1570
+
1571
+ return patterns;
1572
+ }
1573
+
1574
+ async getSwarmStatus() {
1575
+ try {
1576
+ const statusPath = path.join(process.cwd(), '.@sparkleideas/ruv-swarm', 'status.json');
1577
+ if (await fs.access(statusPath).then(() => true).catch(() => false)) {
1578
+ return JSON.parse(await fs.readFile(statusPath, 'utf-8'));
1579
+ }
1580
+ } catch (_error) {
1581
+ // Fallback to session data
1582
+ }
1583
+
1584
+ return {
1585
+ agents: this.sessionData.agents,
1586
+ activeTasks: this.sessionData.operations.filter(op =>
1587
+ Date.now() - op.timestamp < 300000, // Last 5 minutes
1588
+ ).length,
1589
+ health: 'operational',
1590
+ };
1591
+ }
1592
+
1593
+ sendTelemetry(event, data) {
1594
+ // In production, this would send to telemetry service
1595
+ // For now, just log to telemetry file
1596
+ const telemetryPath = path.join(process.cwd(), '.@sparkleideas/ruv-swarm', 'telemetry.jsonl');
1597
+
1598
+ const telemetryEvent = {
1599
+ event,
1600
+ data,
1601
+ timestamp: Date.now(),
1602
+ sessionId: this.sessionData.sessionId || 'unknown',
1603
+ version: '1.0.0',
1604
+ };
1605
+
1606
+ // Async write without blocking
1607
+ fs.appendFile(telemetryPath, `${JSON.stringify(telemetryEvent) }\n`).catch(() => { /* intentionally empty */ });
1608
+ }
1609
+
1610
+ // Helper methods for other functionality
1611
+
1612
+ getSpecializationForType(type) {
1613
+ const specializations = {
1614
+ researcher: ['literature-review', 'data-analysis', 'trend-identification'],
1615
+ coder: ['implementation', 'refactoring', 'optimization'],
1616
+ analyst: ['metrics', 'performance', 'data-visualization'],
1617
+ architect: ['system-design', 'api-design', 'database-schema'],
1618
+ coordinator: ['task-planning', 'resource-allocation', 'progress-tracking'],
1619
+ optimizer: ['performance-tuning', 'algorithm-optimization', 'resource-usage'],
1620
+ };
1621
+ return specializations[type] || ['general'];
1622
+ }
1623
+
1624
+ generateSpecializationPatterns(type) {
1625
+ const patterns = {
1626
+ researcher: ['depth-first-search', 'breadth-first-search', 'citation-tracking'],
1627
+ coder: ['modular-design', 'error-handling', 'code-reuse'],
1628
+ analyst: ['statistical-analysis', 'trend-detection', 'anomaly-detection'],
1629
+ architect: ['layered-architecture', 'microservices', 'event-driven'],
1630
+ coordinator: ['dependency-tracking', 'parallel-execution', 'milestone-planning'],
1631
+ optimizer: ['bottleneck-identification', 'caching-strategies', 'lazy-loading'],
1632
+ };
1633
+ return patterns[type] || ['adaptive-learning'];
1634
+ }
1635
+
1636
+ generateMockWeights() {
1637
+ // Generate mock neural network weights for demonstration
1638
+ return {
1639
+ layers: [
1640
+ { neurons: 128, weights: Array(128).fill(0).map(() => Math.random() - 0.5) },
1641
+ { neurons: 64, weights: Array(64).fill(0).map(() => Math.random() - 0.5) },
1642
+ { neurons: 32, weights: Array(32).fill(0).map(() => Math.random() - 0.5) },
1643
+ ],
1644
+ biases: Array(224).fill(0).map(() => Math.random() - 0.5),
1645
+ };
1646
+ }
1647
+
1648
+ optimizeAgentAllocation(_taskId) {
1649
+ // Simple load balancing algorithm
1650
+ const agents = Array.from(this.sessionData.agents.values());
1651
+ const allocation = {};
1652
+
1653
+ agents.forEach(agent => {
1654
+ // Allocate based on agent type and current load
1655
+ const load = this.sessionData.operations.filter(op =>
1656
+ op.agent === agent.id &&
1657
+ Date.now() - op.timestamp < 60000,
1658
+ ).length;
1659
+
1660
+ allocation[agent.id] = {
1661
+ agent: agent.id,
1662
+ type: agent.type,
1663
+ currentLoad: load,
1664
+ capacity: Math.max(0, 10 - load), // Max 10 concurrent ops
1665
+ priority: load < 5 ? 'high' : 'normal',
1666
+ };
1667
+ });
1668
+
1669
+ return allocation;
1670
+ }
1671
+
1672
+ calculateParallelization(_taskId) {
1673
+ // Determine parallelization factor based on task and resources
1674
+ const agentCount = this.sessionData.agents.size;
1675
+ const complexity = this.sessionData.taskComplexity || { score: 2 };
1676
+
1677
+ return {
1678
+ factor: Math.min(agentCount, Math.ceil(complexity.score * 1.5)),
1679
+ strategy: agentCount > 3 ? 'distributed' : 'local',
1680
+ maxConcurrency: Math.min(agentCount * 2, 10),
1681
+ };
1682
+ }
1683
+
1684
+ getFileType(filePath) {
1685
+ const ext = path.extname(filePath);
1686
+ const typeMap = {
1687
+ '.js': 'javascript',
1688
+ '.ts': 'typescript',
1689
+ '.py': 'python',
1690
+ '.go': 'golang',
1691
+ '.rs': 'rust',
1692
+ '.json': 'config',
1693
+ '.yaml': 'config',
1694
+ '.yml': 'config',
1695
+ '.md': 'documentation',
1696
+ '.txt': 'text',
1697
+ };
1698
+ return typeMap[ext] || 'unknown';
1699
+ }
1700
+
1701
+ getCurrentAgent() {
1702
+ // Get the most recently active agent
1703
+ const recentOps = this.sessionData.operations.slice(-10);
1704
+ const agentCounts = {};
1705
+
1706
+ recentOps.forEach(op => {
1707
+ if (op.agent) {
1708
+ agentCounts[op.agent] = (agentCounts[op.agent] || 0) + 1;
1709
+ }
1710
+ });
1711
+
1712
+ const sorted = Object.entries(agentCounts).sort((a, b) => b[1] - a[1]);
1713
+ return sorted.length > 0 ? sorted[0][0] : 'coordinator';
1714
+ }
1715
+
1716
+ async findRelatedFiles(filePath) {
1717
+ const related = [];
1718
+ const _baseName = path.basename(filePath, path.extname(filePath));
1719
+ // const dirName = path.dirname(filePath);
1720
+
1721
+ // Common related file patterns
1722
+ // const patterns = [
1723
+ // `${baseName}.test.*`, // Test files
1724
+ // `${baseName}.spec.*`, // Spec files
1725
+ // `test-${baseName}.*`, // Alternative test pattern
1726
+ // `${baseName}.d.ts`, // TypeScript definitions
1727
+ // `${baseName}.types.*`, // Type definitions
1728
+ // ];
1729
+
1730
+ // For now, return mock related files
1731
+ // In production, would use file system search
1732
+ if (filePath.endsWith('.js')) {
1733
+ related.push(filePath.replace('.js', '.test.js'));
1734
+ }
1735
+ if (filePath.endsWith('.ts')) {
1736
+ related.push(filePath.replace('.ts', '.test.ts'));
1737
+ related.push(filePath.replace('.ts', '.d.ts'));
1738
+ }
1739
+
1740
+ return related.filter(f => f !== filePath);
1741
+ }
1742
+
1743
+ /**
1744
+ * 🔧 CRITICAL FIX: Store notification in database for cross-agent access
1745
+ */
1746
+ async storeNotificationInDatabase(notification) {
1747
+ if (!this.persistence) {
1748
+ console.warn('⚠️ No persistence layer - notification stored in memory only');
1749
+ return;
1750
+ }
1751
+
1752
+ try {
1753
+ // Store as agent memory with special hook prefix
1754
+ const agentId = notification.agentId || 'hook-system';
1755
+ const memoryKey = `notifications/${notification.type}/${Date.now()}`;
1756
+
1757
+ await this.persistence.storeAgentMemory(agentId, memoryKey, {
1758
+ type: notification.type,
1759
+ message: notification.message,
1760
+ context: notification.context,
1761
+ timestamp: notification.timestamp,
1762
+ source: 'hook-system',
1763
+ sessionId: this.getSessionId(),
1764
+ });
1765
+
1766
+ console.log(`📝 Notification stored in database: ${memoryKey}`);
1767
+ } catch (error) {
1768
+ console.error('❌ Failed to store notification in database:', error.message);
1769
+ }
1770
+ }
1771
+
1772
+ /**
1773
+ * 🔧 CRITICAL FIX: Retrieve notifications from database for cross-agent access
1774
+ */
1775
+ async getNotificationsFromDatabase(agentId = null, type = null) {
1776
+ if (!this.persistence) {
1777
+ return [];
1778
+ }
1779
+
1780
+ try {
1781
+ const targetAgentId = agentId || 'hook-system';
1782
+ const memories = await this.persistence.getAllMemory(targetAgentId);
1783
+
1784
+ return memories
1785
+ .filter(memory => memory.key.startsWith('notifications/'))
1786
+ .filter(memory => !type || memory.value.type === type)
1787
+ .map(memory => memory.value)
1788
+ .sort((a, b) => b.timestamp - a.timestamp);
1789
+ } catch (error) {
1790
+ console.error('❌ Failed to retrieve notifications from database:', error.message);
1791
+ return [];
1792
+ }
1793
+ }
1794
+
1795
+ /**
1796
+ * 🔧 CRITICAL FIX: Enhanced agent completion with database coordination
1797
+ */
1798
+ async agentCompleteHook(args) {
1799
+ const { agentId, taskId, results, learnings } = args;
1800
+
1801
+ // Store completion in database for other agents to see
1802
+ if (this.persistence && agentId) {
1803
+ try {
1804
+ await this.persistence.storeAgentMemory(agentId, `completion/${taskId}`, {
1805
+ taskId,
1806
+ results,
1807
+ learnings,
1808
+ completedAt: Date.now(),
1809
+ source: 'agent-completion',
1810
+ });
1811
+
1812
+ // Update agent status in database
1813
+ await this.persistence.updateAgentStatus(agentId, 'completed');
1814
+
1815
+ console.log(`✅ Agent ${agentId} completion stored in database`);
1816
+ } catch (error) {
1817
+ console.error('❌ Failed to store agent completion:', error.message);
1818
+ }
1819
+ }
1820
+
1821
+ // Store in runtime memory as before
1822
+ const agent = this.sessionData.agents.get(agentId);
1823
+ if (agent) {
1824
+ agent.lastCompletion = {
1825
+ taskId,
1826
+ results,
1827
+ learnings,
1828
+ timestamp: Date.now(),
1829
+ };
1830
+ agent.status = 'completed';
1831
+ }
1832
+
1833
+ return {
1834
+ continue: true,
1835
+ stored: true,
1836
+ agent: agentId,
1837
+ };
1838
+ }
1839
+
1840
+ /**
1841
+ * Get current session ID for coordination
1842
+ */
1843
+ getSessionId() {
1844
+ if (!this._sessionId) {
1845
+ this._sessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
1846
+ }
1847
+ return this._sessionId;
1848
+ }
1849
+
1850
+ /**
1851
+ * 🔧 CRITICAL FIX: Cross-agent memory retrieval for coordinated decisions
1852
+ */
1853
+ async getSharedMemory(key, agentId = null) {
1854
+ // Check runtime memory first
1855
+ const runtimeValue = this.sessionData[key];
1856
+
1857
+ // Check database for persistent cross-agent memory
1858
+ if (this.persistence) {
1859
+ try {
1860
+ const targetAgentId = agentId || 'shared-memory';
1861
+ const memory = await this.persistence.getAgentMemory(targetAgentId, key);
1862
+
1863
+ if (memory) {
1864
+ console.log(`📖 Retrieved shared memory from database: ${key}`);
1865
+ return memory.value;
1866
+ }
1867
+ } catch (error) {
1868
+ console.error('❌ Failed to retrieve shared memory:', error.message);
1869
+ }
1870
+ }
1871
+
1872
+ return runtimeValue;
1873
+ }
1874
+
1875
+ /**
1876
+ * 🔧 CRITICAL FIX: Cross-agent memory storage for coordinated decisions
1877
+ */
1878
+ async setSharedMemory(key, value, agentId = null) {
1879
+ // Store in runtime memory
1880
+ this.sessionData[key] = value;
1881
+
1882
+ // Store in database for cross-agent access
1883
+ if (this.persistence) {
1884
+ try {
1885
+ const targetAgentId = agentId || 'shared-memory';
1886
+ await this.persistence.storeAgentMemory(targetAgentId, key, value);
1887
+ console.log(`📝 Stored shared memory in database: ${key}`);
1888
+ } catch (error) {
1889
+ console.error('❌ Failed to store shared memory:', error.message);
1890
+ }
1891
+ }
1892
+ }
1893
+ }
1894
+
1895
+ // Export singleton instance and its methods
1896
+ const hooksInstance = new RuvSwarmHooks();
1897
+
1898
+ export const handleHook = (hookType, options) => hooksInstance.handleHook(hookType, options);
1899
+
1900
+ export default hooksInstance;