@sparkleideas/swarm 3.0.0-alpha.7

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 (65) hide show
  1. package/MIGRATION.md +472 -0
  2. package/README.md +634 -0
  3. package/__tests__/consensus.test.ts +577 -0
  4. package/__tests__/coordinator.test.ts +501 -0
  5. package/__tests__/queen-coordinator.test.ts +1335 -0
  6. package/__tests__/topology.test.ts +621 -0
  7. package/package.json +32 -0
  8. package/src/agent-pool.ts +476 -0
  9. package/src/application/commands/create-task.command.ts +124 -0
  10. package/src/application/commands/spawn-agent.command.ts +122 -0
  11. package/src/application/index.ts +30 -0
  12. package/src/application/services/swarm-application-service.ts +200 -0
  13. package/src/attention-coordinator.ts +1000 -0
  14. package/src/consensus/byzantine.ts +431 -0
  15. package/src/consensus/gossip.ts +513 -0
  16. package/src/consensus/index.ts +267 -0
  17. package/src/consensus/raft.ts +443 -0
  18. package/src/coordination/agent-registry.ts +544 -0
  19. package/src/coordination/index.ts +23 -0
  20. package/src/coordination/swarm-hub.ts +776 -0
  21. package/src/coordination/task-orchestrator.ts +605 -0
  22. package/src/domain/entities/agent.d.ts +151 -0
  23. package/src/domain/entities/agent.d.ts.map +1 -0
  24. package/src/domain/entities/agent.js +280 -0
  25. package/src/domain/entities/agent.js.map +1 -0
  26. package/src/domain/entities/agent.ts +370 -0
  27. package/src/domain/entities/task.d.ts +133 -0
  28. package/src/domain/entities/task.d.ts.map +1 -0
  29. package/src/domain/entities/task.js +261 -0
  30. package/src/domain/entities/task.js.map +1 -0
  31. package/src/domain/entities/task.ts +319 -0
  32. package/src/domain/index.ts +41 -0
  33. package/src/domain/repositories/agent-repository.interface.d.ts +57 -0
  34. package/src/domain/repositories/agent-repository.interface.d.ts.map +1 -0
  35. package/src/domain/repositories/agent-repository.interface.js +9 -0
  36. package/src/domain/repositories/agent-repository.interface.js.map +1 -0
  37. package/src/domain/repositories/agent-repository.interface.ts +69 -0
  38. package/src/domain/repositories/task-repository.interface.d.ts +61 -0
  39. package/src/domain/repositories/task-repository.interface.d.ts.map +1 -0
  40. package/src/domain/repositories/task-repository.interface.js +9 -0
  41. package/src/domain/repositories/task-repository.interface.js.map +1 -0
  42. package/src/domain/repositories/task-repository.interface.ts +75 -0
  43. package/src/domain/services/coordination-service.ts +320 -0
  44. package/src/federation-hub.d.ts +284 -0
  45. package/src/federation-hub.d.ts.map +1 -0
  46. package/src/federation-hub.js +692 -0
  47. package/src/federation-hub.js.map +1 -0
  48. package/src/federation-hub.ts +979 -0
  49. package/src/index.ts +348 -0
  50. package/src/message-bus.ts +607 -0
  51. package/src/queen-coordinator.ts +2025 -0
  52. package/src/shared/events.ts +285 -0
  53. package/src/shared/types.ts +389 -0
  54. package/src/topology-manager.ts +656 -0
  55. package/src/types.ts +545 -0
  56. package/src/unified-coordinator.ts +1844 -0
  57. package/src/workers/index.ts +65 -0
  58. package/src/workers/worker-dispatch.d.ts +234 -0
  59. package/src/workers/worker-dispatch.d.ts.map +1 -0
  60. package/src/workers/worker-dispatch.js +842 -0
  61. package/src/workers/worker-dispatch.js.map +1 -0
  62. package/src/workers/worker-dispatch.ts +1076 -0
  63. package/tmp.json +0 -0
  64. package/tsconfig.json +9 -0
  65. package/vitest.config.ts +20 -0
@@ -0,0 +1,2025 @@
1
+ /**
2
+ * Queen Coordinator - Central Orchestrator for 15-Agent Swarm
3
+ *
4
+ * The Queen Coordinator is the strategic decision-maker for the V3 hive-mind system.
5
+ * It analyzes tasks, delegates to appropriate agents, monitors swarm health,
6
+ * coordinates consensus, and learns from outcomes using ReasoningBank patterns.
7
+ *
8
+ * Features:
9
+ * - Strategic task analysis with ReasoningBank pattern matching
10
+ * - Agent delegation with capability scoring and load balancing
11
+ * - Swarm health monitoring with bottleneck detection
12
+ * - Consensus coordination (majority, weighted, unanimous)
13
+ * - Learning from outcomes for continuous improvement
14
+ *
15
+ * Performance Targets:
16
+ * - Task analysis: <50ms
17
+ * - Agent scoring: <20ms
18
+ * - Consensus coordination: <100ms
19
+ * - Health check: <30ms
20
+ *
21
+ * @module @sparkleideas/swarm/queen-coordinator
22
+ */
23
+
24
+ import { EventEmitter } from 'events';
25
+ import type {
26
+ AgentState,
27
+ AgentType,
28
+ AgentId,
29
+ TaskDefinition,
30
+ TaskType,
31
+ TaskPriority,
32
+ TaskStatus,
33
+ CoordinatorMetrics,
34
+ ConsensusResult,
35
+ SwarmEvent,
36
+ SwarmEventType,
37
+ } from './types.js';
38
+ import type { AgentDomain, DomainConfig, DomainStatus } from './unified-coordinator.js';
39
+
40
+ // =============================================================================
41
+ // Types
42
+ // =============================================================================
43
+
44
+ /**
45
+ * Task analysis result from the Queen
46
+ */
47
+ export interface TaskAnalysis {
48
+ /** Unique analysis ID */
49
+ analysisId: string;
50
+ /** Original task ID */
51
+ taskId: string;
52
+ /** Task complexity score (0-1) */
53
+ complexity: number;
54
+ /** Estimated duration in milliseconds */
55
+ estimatedDurationMs: number;
56
+ /** Required capabilities for this task */
57
+ requiredCapabilities: string[];
58
+ /** Recommended domain for execution */
59
+ recommendedDomain: AgentDomain;
60
+ /** Sub-tasks if decomposition is needed */
61
+ subtasks: SubTask[];
62
+ /** Patterns found from ReasoningBank */
63
+ matchedPatterns: MatchedPattern[];
64
+ /** Resource requirements */
65
+ resourceRequirements: ResourceRequirements;
66
+ /** Confidence in this analysis (0-1) */
67
+ confidence: number;
68
+ /** Analysis timestamp */
69
+ timestamp: Date;
70
+ }
71
+
72
+ /**
73
+ * Sub-task from task decomposition
74
+ */
75
+ export interface SubTask {
76
+ id: string;
77
+ name: string;
78
+ description: string;
79
+ type: TaskType;
80
+ priority: TaskPriority;
81
+ dependencies: string[];
82
+ estimatedDurationMs: number;
83
+ requiredCapabilities: string[];
84
+ recommendedDomain: AgentDomain;
85
+ }
86
+
87
+ /**
88
+ * Pattern matched from ReasoningBank
89
+ */
90
+ export interface MatchedPattern {
91
+ patternId: string;
92
+ strategy: string;
93
+ successRate: number;
94
+ relevanceScore: number;
95
+ keyLearnings: string[];
96
+ }
97
+
98
+ /**
99
+ * Resource requirements for a task
100
+ */
101
+ export interface ResourceRequirements {
102
+ minAgents: number;
103
+ maxAgents: number;
104
+ memoryMb: number;
105
+ cpuIntensive: boolean;
106
+ ioIntensive: boolean;
107
+ networkRequired: boolean;
108
+ }
109
+
110
+ /**
111
+ * Delegation plan for task execution
112
+ */
113
+ export interface DelegationPlan {
114
+ /** Plan ID */
115
+ planId: string;
116
+ /** Task ID being delegated */
117
+ taskId: string;
118
+ /** Analysis that informed this plan */
119
+ analysisId: string;
120
+ /** Primary agent assignment */
121
+ primaryAgent: AgentAssignment;
122
+ /** Backup agents for failover */
123
+ backupAgents: AgentAssignment[];
124
+ /** Parallel sub-task assignments */
125
+ parallelAssignments: ParallelAssignment[];
126
+ /** Execution strategy */
127
+ strategy: ExecutionStrategy;
128
+ /** Estimated completion time */
129
+ estimatedCompletionMs: number;
130
+ /** Plan creation timestamp */
131
+ timestamp: Date;
132
+ }
133
+
134
+ /**
135
+ * Agent assignment in a delegation plan
136
+ */
137
+ export interface AgentAssignment {
138
+ agentId: string;
139
+ domain: AgentDomain;
140
+ taskId: string;
141
+ score: number;
142
+ assignedAt: Date;
143
+ }
144
+
145
+ /**
146
+ * Parallel task assignment
147
+ */
148
+ export interface ParallelAssignment {
149
+ subtaskId: string;
150
+ agentId: string;
151
+ domain: AgentDomain;
152
+ dependencies: string[];
153
+ }
154
+
155
+ /**
156
+ * Execution strategy for delegation
157
+ */
158
+ export type ExecutionStrategy =
159
+ | 'sequential'
160
+ | 'parallel'
161
+ | 'pipeline'
162
+ | 'fan-out-fan-in'
163
+ | 'hybrid';
164
+
165
+ /**
166
+ * Agent score for task assignment
167
+ */
168
+ export interface AgentScore {
169
+ agentId: string;
170
+ domain: AgentDomain;
171
+ totalScore: number;
172
+ capabilityScore: number;
173
+ loadScore: number;
174
+ performanceScore: number;
175
+ healthScore: number;
176
+ availabilityScore: number;
177
+ }
178
+
179
+ /**
180
+ * Health report for the swarm
181
+ */
182
+ export interface HealthReport {
183
+ /** Report ID */
184
+ reportId: string;
185
+ /** Report timestamp */
186
+ timestamp: Date;
187
+ /** Overall swarm health (0-1) */
188
+ overallHealth: number;
189
+ /** Status of each domain */
190
+ domainHealth: Map<AgentDomain, DomainHealthStatus>;
191
+ /** Individual agent health */
192
+ agentHealth: AgentHealthEntry[];
193
+ /** Detected bottlenecks */
194
+ bottlenecks: Bottleneck[];
195
+ /** Active alerts */
196
+ alerts: HealthAlert[];
197
+ /** Performance metrics */
198
+ metrics: HealthMetrics;
199
+ /** Recommendations for improvement */
200
+ recommendations: string[];
201
+ }
202
+
203
+ /**
204
+ * Domain health status
205
+ */
206
+ export interface DomainHealthStatus {
207
+ domain: AgentDomain;
208
+ health: number;
209
+ activeAgents: number;
210
+ totalAgents: number;
211
+ queuedTasks: number;
212
+ avgResponseTimeMs: number;
213
+ errorRate: number;
214
+ }
215
+
216
+ /**
217
+ * Agent health entry
218
+ */
219
+ export interface AgentHealthEntry {
220
+ agentId: string;
221
+ domain: AgentDomain;
222
+ health: number;
223
+ status: string;
224
+ lastHeartbeat: Date;
225
+ currentLoad: number;
226
+ recentErrors: number;
227
+ }
228
+
229
+ /**
230
+ * Bottleneck detection result
231
+ */
232
+ export interface Bottleneck {
233
+ type: 'agent' | 'domain' | 'task' | 'resource';
234
+ location: string;
235
+ severity: 'low' | 'medium' | 'high' | 'critical';
236
+ description: string;
237
+ impact: string;
238
+ suggestedAction: string;
239
+ }
240
+
241
+ /**
242
+ * Health alert
243
+ */
244
+ export interface HealthAlert {
245
+ alertId: string;
246
+ type: 'warning' | 'error' | 'critical';
247
+ source: string;
248
+ message: string;
249
+ timestamp: Date;
250
+ acknowledged: boolean;
251
+ }
252
+
253
+ /**
254
+ * Health metrics
255
+ */
256
+ export interface HealthMetrics {
257
+ totalAgents: number;
258
+ activeAgents: number;
259
+ idleAgents: number;
260
+ errorAgents: number;
261
+ totalTasks: number;
262
+ completedTasks: number;
263
+ failedTasks: number;
264
+ avgTaskDurationMs: number;
265
+ taskThroughputPerMin: number;
266
+ consensusSuccessRate: number;
267
+ }
268
+
269
+ /**
270
+ * Decision requiring consensus
271
+ */
272
+ export interface Decision {
273
+ decisionId: string;
274
+ type: DecisionType;
275
+ proposal: unknown;
276
+ requiredConsensus: ConsensusType;
277
+ timeout: number;
278
+ initiator: string;
279
+ metadata: Record<string, unknown>;
280
+ }
281
+
282
+ /**
283
+ * Decision types
284
+ */
285
+ export type DecisionType =
286
+ | 'task-assignment'
287
+ | 'resource-allocation'
288
+ | 'topology-change'
289
+ | 'agent-termination'
290
+ | 'priority-override'
291
+ | 'emergency-action';
292
+
293
+ /**
294
+ * Consensus types
295
+ */
296
+ export type ConsensusType =
297
+ | 'majority'
298
+ | 'supermajority'
299
+ | 'unanimous'
300
+ | 'weighted'
301
+ | 'queen-override';
302
+
303
+ /**
304
+ * Task result for learning
305
+ */
306
+ export interface TaskResult {
307
+ taskId: string;
308
+ success: boolean;
309
+ output?: unknown;
310
+ error?: string;
311
+ durationMs: number;
312
+ agentId: string;
313
+ domain: AgentDomain;
314
+ metrics: TaskMetrics;
315
+ }
316
+
317
+ /**
318
+ * Task execution metrics
319
+ */
320
+ export interface TaskMetrics {
321
+ startTime: Date;
322
+ endTime: Date;
323
+ retries: number;
324
+ resourceUsage: {
325
+ memoryMb: number;
326
+ cpuPercent: number;
327
+ };
328
+ stepsCompleted: number;
329
+ qualityScore: number;
330
+ }
331
+
332
+ /**
333
+ * Queen Coordinator configuration
334
+ */
335
+ export interface QueenCoordinatorConfig {
336
+ /** Enable ReasoningBank integration */
337
+ enableLearning: boolean;
338
+ /** Number of patterns to retrieve for analysis */
339
+ patternRetrievalK: number;
340
+ /** Minimum pattern relevance threshold */
341
+ patternThreshold: number;
342
+ /** Task complexity thresholds */
343
+ complexityThresholds: {
344
+ simple: number;
345
+ moderate: number;
346
+ complex: number;
347
+ };
348
+ /** Health check interval in ms */
349
+ healthCheckIntervalMs: number;
350
+ /** Bottleneck detection thresholds */
351
+ bottleneckThresholds: {
352
+ queueDepth: number;
353
+ errorRate: number;
354
+ responseTimeMs: number;
355
+ };
356
+ /** Consensus timeouts */
357
+ consensusTimeouts: {
358
+ majority: number;
359
+ supermajority: number;
360
+ unanimous: number;
361
+ };
362
+ /** Enable automatic failover */
363
+ enableFailover: boolean;
364
+ /** Maximum delegation attempts */
365
+ maxDelegationAttempts: number;
366
+ }
367
+
368
+ /**
369
+ * Default Queen Coordinator configuration
370
+ */
371
+ const DEFAULT_CONFIG: QueenCoordinatorConfig = {
372
+ enableLearning: true,
373
+ patternRetrievalK: 5,
374
+ patternThreshold: 0.6,
375
+ complexityThresholds: {
376
+ simple: 0.3,
377
+ moderate: 0.6,
378
+ complex: 0.85,
379
+ },
380
+ healthCheckIntervalMs: 10000,
381
+ bottleneckThresholds: {
382
+ queueDepth: 10,
383
+ errorRate: 0.1,
384
+ responseTimeMs: 5000,
385
+ },
386
+ consensusTimeouts: {
387
+ majority: 5000,
388
+ supermajority: 10000,
389
+ unanimous: 30000,
390
+ },
391
+ enableFailover: true,
392
+ maxDelegationAttempts: 3,
393
+ };
394
+
395
+ // =============================================================================
396
+ // Interfaces for Dependencies
397
+ // =============================================================================
398
+
399
+ /**
400
+ * Interface for swarm coordinator interactions
401
+ */
402
+ export interface ISwarmCoordinator {
403
+ getAgentsByDomain(domain: AgentDomain): AgentState[];
404
+ getAllAgents(): AgentState[];
405
+ getAvailableAgents(): AgentState[];
406
+ getMetrics(): CoordinatorMetrics;
407
+ getDomainConfigs(): Map<AgentDomain, DomainConfig>;
408
+ getStatus(): {
409
+ domains: DomainStatus[];
410
+ metrics: CoordinatorMetrics;
411
+ };
412
+ assignTaskToDomain(taskId: string, domain: AgentDomain): Promise<string | undefined>;
413
+ proposeConsensus(value: unknown): Promise<ConsensusResult>;
414
+ broadcastMessage(payload: unknown, priority?: 'urgent' | 'high' | 'normal' | 'low'): Promise<void>;
415
+ }
416
+
417
+ /**
418
+ * Interface for neural learning system interactions
419
+ */
420
+ export interface INeuralLearningSystem {
421
+ initialize(): Promise<void>;
422
+ beginTask(context: string, domain?: string): string;
423
+ recordStep(trajectoryId: string, action: string, reward: number, stateEmbedding: Float32Array): void;
424
+ completeTask(trajectoryId: string, quality?: number): Promise<void>;
425
+ findPatterns(queryEmbedding: Float32Array, k?: number): Promise<PatternMatchResult[]>;
426
+ retrieveMemories(queryEmbedding: Float32Array, k?: number): Promise<MemoryRetrievalResult[]>;
427
+ triggerLearning(): Promise<void>;
428
+ }
429
+
430
+ /**
431
+ * Pattern match result from neural system
432
+ */
433
+ export interface PatternMatchResult {
434
+ patternId: string;
435
+ strategy: string;
436
+ successRate: number;
437
+ relevanceScore: number;
438
+ keyLearnings?: string[];
439
+ }
440
+
441
+ /**
442
+ * Memory retrieval result from neural system
443
+ */
444
+ export interface MemoryRetrievalResult {
445
+ memory: {
446
+ memoryId: string;
447
+ strategy: string;
448
+ quality: number;
449
+ keyLearnings: string[];
450
+ };
451
+ relevanceScore: number;
452
+ combinedScore: number;
453
+ }
454
+
455
+ /**
456
+ * Interface for memory service interactions
457
+ */
458
+ export interface IMemoryService {
459
+ semanticSearch(query: string, k?: number): Promise<SearchResultEntry[]>;
460
+ store(entry: MemoryStoreEntry): Promise<void>;
461
+ }
462
+
463
+ /**
464
+ * Search result entry from memory service
465
+ */
466
+ export interface SearchResultEntry {
467
+ entry: {
468
+ id: string;
469
+ content: string;
470
+ metadata: Record<string, unknown>;
471
+ };
472
+ score: number;
473
+ }
474
+
475
+ /**
476
+ * Memory store entry
477
+ */
478
+ export interface MemoryStoreEntry {
479
+ key: string;
480
+ content: string;
481
+ namespace: string;
482
+ tags: string[];
483
+ metadata: Record<string, unknown>;
484
+ }
485
+
486
+ // =============================================================================
487
+ // Queen Coordinator Class
488
+ // =============================================================================
489
+
490
+ /**
491
+ * Queen Coordinator - Central orchestrator for the 15-agent hive-mind swarm
492
+ *
493
+ * The Queen is responsible for:
494
+ * 1. Strategic task analysis and decomposition
495
+ * 2. Agent delegation with load balancing
496
+ * 3. Swarm health monitoring
497
+ * 4. Consensus coordination
498
+ * 5. Learning from outcomes
499
+ */
500
+ export class QueenCoordinator extends EventEmitter {
501
+ private config: QueenCoordinatorConfig;
502
+ private swarm: ISwarmCoordinator;
503
+ private neural?: INeuralLearningSystem;
504
+ private memory?: IMemoryService;
505
+
506
+ // Internal state
507
+ private analysisCache: Map<string, TaskAnalysis> = new Map();
508
+ private delegationPlans: Map<string, DelegationPlan> = new Map();
509
+ private activeDecisions: Map<string, Decision> = new Map();
510
+ private outcomeHistory: TaskResult[] = [];
511
+ private healthHistory: HealthReport[] = [];
512
+
513
+ // Counters for IDs
514
+ private analysisCounter = 0;
515
+ private planCounter = 0;
516
+ private reportCounter = 0;
517
+ private decisionCounter = 0;
518
+
519
+ // Health monitoring
520
+ private healthCheckInterval?: NodeJS.Timeout;
521
+ private lastHealthReport?: HealthReport;
522
+
523
+ // Performance tracking
524
+ private analysisLatencies: number[] = [];
525
+ private delegationLatencies: number[] = [];
526
+ private consensusLatencies: number[] = [];
527
+
528
+ constructor(
529
+ swarm: ISwarmCoordinator,
530
+ config: Partial<QueenCoordinatorConfig> = {},
531
+ neural?: INeuralLearningSystem,
532
+ memory?: IMemoryService
533
+ ) {
534
+ super();
535
+ this.swarm = swarm;
536
+ this.config = { ...DEFAULT_CONFIG, ...config };
537
+ this.neural = neural;
538
+ this.memory = memory;
539
+ }
540
+
541
+ // ===========================================================================
542
+ // Lifecycle
543
+ // ===========================================================================
544
+
545
+ /**
546
+ * Initialize the Queen Coordinator
547
+ */
548
+ async initialize(): Promise<void> {
549
+ // Initialize neural system if available
550
+ if (this.neural && this.config.enableLearning) {
551
+ await this.neural.initialize();
552
+ }
553
+
554
+ // Start health monitoring
555
+ this.startHealthMonitoring();
556
+
557
+ this.emitEvent('queen.initialized', {
558
+ config: this.config,
559
+ learningEnabled: this.config.enableLearning && !!this.neural,
560
+ });
561
+ }
562
+
563
+ /**
564
+ * Shutdown the Queen Coordinator
565
+ */
566
+ async shutdown(): Promise<void> {
567
+ this.stopHealthMonitoring();
568
+
569
+ // Trigger final learning if enabled
570
+ if (this.neural && this.config.enableLearning) {
571
+ await this.neural.triggerLearning();
572
+ }
573
+
574
+ this.emitEvent('queen.shutdown', {
575
+ totalAnalyses: this.analysisCounter,
576
+ totalPlans: this.planCounter,
577
+ totalDecisions: this.decisionCounter,
578
+ });
579
+ }
580
+
581
+ // ===========================================================================
582
+ // Strategic Task Analysis
583
+ // ===========================================================================
584
+
585
+ /**
586
+ * Analyze a task for optimal execution
587
+ *
588
+ * @param task - Task to analyze
589
+ * @returns Task analysis with recommendations
590
+ */
591
+ async analyzeTask(task: TaskDefinition): Promise<TaskAnalysis> {
592
+ const startTime = performance.now();
593
+
594
+ this.analysisCounter++;
595
+ const analysisId = `analysis_${Date.now()}_${this.analysisCounter}`;
596
+
597
+ // Decompose complex tasks
598
+ const subtasks = this.decomposeTask(task);
599
+
600
+ // Identify required capabilities
601
+ const requiredCapabilities = this.identifyRequiredCapabilities(task);
602
+
603
+ // Calculate complexity
604
+ const complexity = this.calculateComplexity(task, subtasks);
605
+
606
+ // Estimate duration
607
+ const estimatedDurationMs = this.estimateDuration(task, complexity, subtasks);
608
+
609
+ // Determine recommended domain
610
+ const recommendedDomain = this.determineOptimalDomain(task, requiredCapabilities);
611
+
612
+ // Find matching patterns from ReasoningBank
613
+ const matchedPatterns = await this.findMatchingPatterns(task);
614
+
615
+ // Estimate resource requirements
616
+ const resourceRequirements = this.estimateResources(task, complexity);
617
+
618
+ // Calculate confidence
619
+ const confidence = this.calculateAnalysisConfidence(
620
+ matchedPatterns,
621
+ complexity,
622
+ requiredCapabilities
623
+ );
624
+
625
+ const analysis: TaskAnalysis = {
626
+ analysisId,
627
+ taskId: task.id.id,
628
+ complexity,
629
+ estimatedDurationMs,
630
+ requiredCapabilities,
631
+ recommendedDomain,
632
+ subtasks,
633
+ matchedPatterns,
634
+ resourceRequirements,
635
+ confidence,
636
+ timestamp: new Date(),
637
+ };
638
+
639
+ // Cache the analysis
640
+ this.analysisCache.set(analysisId, analysis);
641
+
642
+ // Record latency
643
+ const latency = performance.now() - startTime;
644
+ this.analysisLatencies.push(latency);
645
+ if (this.analysisLatencies.length > 100) {
646
+ this.analysisLatencies.shift();
647
+ }
648
+
649
+ this.emitEvent('queen.task.analyzed', {
650
+ analysisId,
651
+ taskId: task.id.id,
652
+ complexity,
653
+ recommendedDomain,
654
+ patternsFound: matchedPatterns.length,
655
+ latencyMs: latency,
656
+ });
657
+
658
+ return analysis;
659
+ }
660
+
661
+ /**
662
+ * Decompose a complex task into subtasks
663
+ */
664
+ private decomposeTask(task: TaskDefinition): SubTask[] {
665
+ const subtasks: SubTask[] = [];
666
+
667
+ // Simple tasks don't need decomposition
668
+ if (this.isSimpleTask(task)) {
669
+ return subtasks;
670
+ }
671
+
672
+ // Decompose based on task type
673
+ switch (task.type) {
674
+ case 'coding':
675
+ subtasks.push(...this.decomposeCodingTask(task));
676
+ break;
677
+ case 'testing':
678
+ subtasks.push(...this.decomposeTestingTask(task));
679
+ break;
680
+ case 'research':
681
+ subtasks.push(...this.decomposeResearchTask(task));
682
+ break;
683
+ case 'coordination':
684
+ subtasks.push(...this.decomposeCoordinationTask(task));
685
+ break;
686
+ default:
687
+ // Generic decomposition
688
+ subtasks.push(...this.decomposeGenericTask(task));
689
+ }
690
+
691
+ return subtasks;
692
+ }
693
+
694
+ private isSimpleTask(task: TaskDefinition): boolean {
695
+ // Estimate if task is simple based on description length and type
696
+ const descLength = task.description?.length || 0;
697
+ const isSimpleType = ['documentation', 'review'].includes(task.type);
698
+ return descLength < 200 || isSimpleType;
699
+ }
700
+
701
+ private decomposeCodingTask(task: TaskDefinition): SubTask[] {
702
+ return [
703
+ {
704
+ id: `${task.id.id}_design`,
705
+ name: 'Design & Planning',
706
+ description: 'Design the solution architecture',
707
+ type: 'analysis',
708
+ priority: task.priority,
709
+ dependencies: [],
710
+ estimatedDurationMs: 10000,
711
+ requiredCapabilities: ['design', 'architecture'],
712
+ recommendedDomain: 'core',
713
+ },
714
+ {
715
+ id: `${task.id.id}_implement`,
716
+ name: 'Implementation',
717
+ description: 'Implement the designed solution',
718
+ type: 'coding',
719
+ priority: task.priority,
720
+ dependencies: [`${task.id.id}_design`],
721
+ estimatedDurationMs: 30000,
722
+ requiredCapabilities: ['coding', 'implementation'],
723
+ recommendedDomain: 'integration',
724
+ },
725
+ {
726
+ id: `${task.id.id}_test`,
727
+ name: 'Testing',
728
+ description: 'Test the implementation',
729
+ type: 'testing',
730
+ priority: task.priority,
731
+ dependencies: [`${task.id.id}_implement`],
732
+ estimatedDurationMs: 15000,
733
+ requiredCapabilities: ['testing', 'validation'],
734
+ recommendedDomain: 'support',
735
+ },
736
+ ];
737
+ }
738
+
739
+ private decomposeTestingTask(task: TaskDefinition): SubTask[] {
740
+ return [
741
+ {
742
+ id: `${task.id.id}_analyze`,
743
+ name: 'Test Analysis',
744
+ description: 'Analyze what needs to be tested',
745
+ type: 'analysis',
746
+ priority: task.priority,
747
+ dependencies: [],
748
+ estimatedDurationMs: 5000,
749
+ requiredCapabilities: ['analysis', 'testing'],
750
+ recommendedDomain: 'support',
751
+ },
752
+ {
753
+ id: `${task.id.id}_execute`,
754
+ name: 'Test Execution',
755
+ description: 'Execute the tests',
756
+ type: 'testing',
757
+ priority: task.priority,
758
+ dependencies: [`${task.id.id}_analyze`],
759
+ estimatedDurationMs: 20000,
760
+ requiredCapabilities: ['testing', 'execution'],
761
+ recommendedDomain: 'support',
762
+ },
763
+ ];
764
+ }
765
+
766
+ private decomposeResearchTask(task: TaskDefinition): SubTask[] {
767
+ return [
768
+ {
769
+ id: `${task.id.id}_gather`,
770
+ name: 'Information Gathering',
771
+ description: 'Gather relevant information',
772
+ type: 'research',
773
+ priority: task.priority,
774
+ dependencies: [],
775
+ estimatedDurationMs: 15000,
776
+ requiredCapabilities: ['research', 'analysis'],
777
+ recommendedDomain: 'core',
778
+ },
779
+ {
780
+ id: `${task.id.id}_analyze`,
781
+ name: 'Analysis',
782
+ description: 'Analyze gathered information',
783
+ type: 'analysis',
784
+ priority: task.priority,
785
+ dependencies: [`${task.id.id}_gather`],
786
+ estimatedDurationMs: 10000,
787
+ requiredCapabilities: ['analysis', 'synthesis'],
788
+ recommendedDomain: 'core',
789
+ },
790
+ ];
791
+ }
792
+
793
+ private decomposeCoordinationTask(task: TaskDefinition): SubTask[] {
794
+ return [
795
+ {
796
+ id: `${task.id.id}_plan`,
797
+ name: 'Planning',
798
+ description: 'Create coordination plan',
799
+ type: 'coordination',
800
+ priority: task.priority,
801
+ dependencies: [],
802
+ estimatedDurationMs: 5000,
803
+ requiredCapabilities: ['planning', 'coordination'],
804
+ recommendedDomain: 'queen',
805
+ },
806
+ {
807
+ id: `${task.id.id}_execute`,
808
+ name: 'Execution',
809
+ description: 'Execute coordination plan',
810
+ type: 'coordination',
811
+ priority: task.priority,
812
+ dependencies: [`${task.id.id}_plan`],
813
+ estimatedDurationMs: 10000,
814
+ requiredCapabilities: ['coordination', 'oversight'],
815
+ recommendedDomain: 'queen',
816
+ },
817
+ ];
818
+ }
819
+
820
+ private decomposeGenericTask(task: TaskDefinition): SubTask[] {
821
+ return [
822
+ {
823
+ id: `${task.id.id}_execute`,
824
+ name: 'Task Execution',
825
+ description: task.description,
826
+ type: task.type,
827
+ priority: task.priority,
828
+ dependencies: [],
829
+ estimatedDurationMs: 20000,
830
+ requiredCapabilities: this.identifyRequiredCapabilities(task),
831
+ recommendedDomain: this.inferDomainFromType(task.type),
832
+ },
833
+ ];
834
+ }
835
+
836
+ /**
837
+ * Identify required capabilities for a task
838
+ */
839
+ private identifyRequiredCapabilities(task: TaskDefinition): string[] {
840
+ const capabilities: Set<string> = new Set();
841
+
842
+ // Add type-based capabilities
843
+ const typeCapabilities: Record<TaskType, string[]> = {
844
+ research: ['research', 'analysis', 'synthesis'],
845
+ analysis: ['analysis', 'reasoning', 'synthesis'],
846
+ coding: ['coding', 'implementation', 'debugging'],
847
+ testing: ['testing', 'validation', 'quality'],
848
+ review: ['review', 'analysis', 'feedback'],
849
+ documentation: ['documentation', 'writing', 'clarity'],
850
+ coordination: ['coordination', 'planning', 'oversight'],
851
+ consensus: ['consensus', 'voting', 'agreement'],
852
+ custom: ['general', 'execution'],
853
+ };
854
+
855
+ for (const cap of typeCapabilities[task.type] || ['general']) {
856
+ capabilities.add(cap);
857
+ }
858
+
859
+ // Extract additional capabilities from description
860
+ const descLower = (task.description || '').toLowerCase();
861
+ if (descLower.includes('security')) capabilities.add('security');
862
+ if (descLower.includes('performance')) capabilities.add('performance');
863
+ if (descLower.includes('architecture')) capabilities.add('architecture');
864
+ if (descLower.includes('integration')) capabilities.add('integration');
865
+ if (descLower.includes('deploy')) capabilities.add('deployment');
866
+
867
+ return Array.from(capabilities);
868
+ }
869
+
870
+ /**
871
+ * Calculate task complexity score
872
+ */
873
+ private calculateComplexity(task: TaskDefinition, subtasks: SubTask[]): number {
874
+ let complexity = 0.3; // Base complexity
875
+
876
+ // Add complexity for subtasks
877
+ complexity += subtasks.length * 0.1;
878
+
879
+ // Add complexity for dependencies
880
+ const totalDeps = subtasks.reduce((sum, st) => sum + st.dependencies.length, 0);
881
+ complexity += totalDeps * 0.05;
882
+
883
+ // Add complexity for priority
884
+ const priorityMultipliers: Record<TaskPriority, number> = {
885
+ critical: 1.3,
886
+ high: 1.15,
887
+ normal: 1.0,
888
+ low: 0.9,
889
+ background: 0.8,
890
+ };
891
+ complexity *= priorityMultipliers[task.priority];
892
+
893
+ // Add complexity for task type
894
+ const typeComplexity: Record<TaskType, number> = {
895
+ coordination: 0.2,
896
+ consensus: 0.25,
897
+ coding: 0.15,
898
+ testing: 0.1,
899
+ analysis: 0.1,
900
+ research: 0.1,
901
+ review: 0.05,
902
+ documentation: 0.05,
903
+ custom: 0.1,
904
+ };
905
+ complexity += typeComplexity[task.type] || 0.1;
906
+
907
+ // Add complexity for description length
908
+ const descLength = task.description?.length || 0;
909
+ complexity += Math.min(descLength / 2000, 0.2);
910
+
911
+ return Math.min(complexity, 1.0);
912
+ }
913
+
914
+ /**
915
+ * Estimate task duration
916
+ */
917
+ private estimateDuration(
918
+ task: TaskDefinition,
919
+ complexity: number,
920
+ subtasks: SubTask[]
921
+ ): number {
922
+ // Base duration by type (in ms)
923
+ const baseDurations: Record<TaskType, number> = {
924
+ research: 30000,
925
+ analysis: 20000,
926
+ coding: 60000,
927
+ testing: 30000,
928
+ review: 15000,
929
+ documentation: 20000,
930
+ coordination: 10000,
931
+ consensus: 15000,
932
+ custom: 30000,
933
+ };
934
+
935
+ const baseDuration = baseDurations[task.type] || 30000;
936
+
937
+ // Adjust for complexity
938
+ const complexityMultiplier = 0.5 + complexity * 1.5;
939
+
940
+ // Add subtask durations
941
+ const subtaskDuration = subtasks.reduce((sum, st) => sum + st.estimatedDurationMs, 0);
942
+
943
+ // Total estimate
944
+ return Math.round(baseDuration * complexityMultiplier + subtaskDuration * 0.5);
945
+ }
946
+
947
+ /**
948
+ * Determine optimal domain for task execution
949
+ */
950
+ private determineOptimalDomain(
951
+ task: TaskDefinition,
952
+ capabilities: string[]
953
+ ): AgentDomain {
954
+ // Check capabilities for domain hints
955
+ if (capabilities.includes('security')) return 'security';
956
+ if (capabilities.includes('coordination') || capabilities.includes('planning')) return 'queen';
957
+ if (capabilities.includes('testing') || capabilities.includes('performance')) return 'support';
958
+ if (capabilities.includes('integration')) return 'integration';
959
+
960
+ // Fall back to type-based inference
961
+ return this.inferDomainFromType(task.type);
962
+ }
963
+
964
+ private inferDomainFromType(type: TaskType): AgentDomain {
965
+ const typeDomains: Record<TaskType, AgentDomain> = {
966
+ coordination: 'queen',
967
+ consensus: 'queen',
968
+ coding: 'integration',
969
+ testing: 'support',
970
+ review: 'security',
971
+ analysis: 'core',
972
+ research: 'core',
973
+ documentation: 'support',
974
+ custom: 'core',
975
+ };
976
+ return typeDomains[type] || 'core';
977
+ }
978
+
979
+ /**
980
+ * Find matching patterns from ReasoningBank
981
+ */
982
+ private async findMatchingPatterns(task: TaskDefinition): Promise<MatchedPattern[]> {
983
+ const patterns: MatchedPattern[] = [];
984
+
985
+ if (!this.neural || !this.config.enableLearning) {
986
+ return patterns;
987
+ }
988
+
989
+ try {
990
+ // Create a simple embedding from task description
991
+ const embedding = this.createSimpleEmbedding(task.description || task.name);
992
+
993
+ // Query ReasoningBank for similar patterns
994
+ const results = await this.neural.findPatterns(embedding, this.config.patternRetrievalK);
995
+
996
+ for (const result of results) {
997
+ if (result.relevanceScore >= this.config.patternThreshold) {
998
+ patterns.push({
999
+ patternId: result.patternId,
1000
+ strategy: result.strategy,
1001
+ successRate: result.successRate,
1002
+ relevanceScore: result.relevanceScore,
1003
+ keyLearnings: result.keyLearnings || [],
1004
+ });
1005
+ }
1006
+ }
1007
+ } catch (error) {
1008
+ // Log but don't fail - patterns are optional
1009
+ this.emitEvent('queen.pattern.error', { error: String(error) });
1010
+ }
1011
+
1012
+ return patterns;
1013
+ }
1014
+
1015
+ /**
1016
+ * Create a simple embedding from text using hash-based approach.
1017
+ * For higher quality embeddings, integrate @sparkleideas/agentic-flow's computeEmbedding.
1018
+ */
1019
+ private createSimpleEmbedding(text: string): Float32Array {
1020
+ // Hash-based embedding - lightweight and fast for local similarity matching
1021
+ // For production ML embeddings, use: import('@sparkleideas/agentic-flow').computeEmbedding
1022
+ const embedding = new Float32Array(768);
1023
+ const words = text.toLowerCase().split(/\s+/);
1024
+
1025
+ for (let i = 0; i < words.length; i++) {
1026
+ const word = words[i];
1027
+ for (let j = 0; j < word.length; j++) {
1028
+ const idx = (word.charCodeAt(j) * (i + 1) * (j + 1)) % 768;
1029
+ embedding[idx] += 1 / words.length;
1030
+ }
1031
+ }
1032
+
1033
+ // Normalize
1034
+ let norm = 0;
1035
+ for (let i = 0; i < embedding.length; i++) {
1036
+ norm += embedding[i] * embedding[i];
1037
+ }
1038
+ norm = Math.sqrt(norm);
1039
+ if (norm > 0) {
1040
+ for (let i = 0; i < embedding.length; i++) {
1041
+ embedding[i] /= norm;
1042
+ }
1043
+ }
1044
+
1045
+ return embedding;
1046
+ }
1047
+
1048
+ /**
1049
+ * Estimate resource requirements
1050
+ */
1051
+ private estimateResources(task: TaskDefinition, complexity: number): ResourceRequirements {
1052
+ const minAgents = complexity > 0.7 ? 2 : 1;
1053
+ const maxAgents = complexity > 0.8 ? 4 : complexity > 0.5 ? 3 : 2;
1054
+
1055
+ return {
1056
+ minAgents,
1057
+ maxAgents,
1058
+ memoryMb: Math.round(256 + complexity * 512),
1059
+ cpuIntensive: ['coding', 'analysis'].includes(task.type),
1060
+ ioIntensive: ['research', 'testing'].includes(task.type),
1061
+ networkRequired: task.type === 'research',
1062
+ };
1063
+ }
1064
+
1065
+ /**
1066
+ * Calculate confidence in analysis
1067
+ */
1068
+ private calculateAnalysisConfidence(
1069
+ patterns: MatchedPattern[],
1070
+ complexity: number,
1071
+ capabilities: string[]
1072
+ ): number {
1073
+ let confidence = 0.5; // Base confidence
1074
+
1075
+ // Higher confidence with more matching patterns
1076
+ confidence += patterns.length * 0.1;
1077
+
1078
+ // Higher confidence for simpler tasks
1079
+ confidence += (1 - complexity) * 0.2;
1080
+
1081
+ // Higher confidence with clear capabilities
1082
+ confidence += Math.min(capabilities.length * 0.05, 0.15);
1083
+
1084
+ // Boost from high-success patterns
1085
+ const avgPatternSuccess = patterns.length > 0
1086
+ ? patterns.reduce((sum, p) => sum + p.successRate, 0) / patterns.length
1087
+ : 0;
1088
+ confidence += avgPatternSuccess * 0.1;
1089
+
1090
+ return Math.min(confidence, 0.95);
1091
+ }
1092
+
1093
+ // ===========================================================================
1094
+ // Agent Delegation
1095
+ // ===========================================================================
1096
+
1097
+ /**
1098
+ * Delegate a task to agents based on analysis
1099
+ *
1100
+ * @param task - Task to delegate
1101
+ * @param analysis - Previous task analysis
1102
+ * @returns Delegation plan
1103
+ */
1104
+ async delegateToAgents(task: TaskDefinition, analysis: TaskAnalysis): Promise<DelegationPlan> {
1105
+ const startTime = performance.now();
1106
+
1107
+ this.planCounter++;
1108
+ const planId = `plan_${Date.now()}_${this.planCounter}`;
1109
+
1110
+ // Score all available agents for this task
1111
+ const agentScores = this.scoreAgents(task, analysis.matchedPatterns);
1112
+
1113
+ // Select primary agent
1114
+ const primaryAgent = this.selectPrimaryAgent(task, agentScores, analysis);
1115
+
1116
+ // Select backup agents
1117
+ const backupAgents = this.selectBackupAgents(task, agentScores, primaryAgent);
1118
+
1119
+ // Create parallel assignments for subtasks
1120
+ const parallelAssignments = this.createParallelAssignments(
1121
+ analysis.subtasks,
1122
+ agentScores
1123
+ );
1124
+
1125
+ // Determine execution strategy
1126
+ const strategy = this.determineExecutionStrategy(analysis);
1127
+
1128
+ const plan: DelegationPlan = {
1129
+ planId,
1130
+ taskId: task.id.id,
1131
+ analysisId: analysis.analysisId,
1132
+ primaryAgent,
1133
+ backupAgents,
1134
+ parallelAssignments,
1135
+ strategy,
1136
+ estimatedCompletionMs: analysis.estimatedDurationMs,
1137
+ timestamp: new Date(),
1138
+ };
1139
+
1140
+ // Store the plan
1141
+ this.delegationPlans.set(planId, plan);
1142
+
1143
+ // Execute the delegation
1144
+ await this.executeDelegation(plan);
1145
+
1146
+ // Record latency
1147
+ const latency = performance.now() - startTime;
1148
+ this.delegationLatencies.push(latency);
1149
+ if (this.delegationLatencies.length > 100) {
1150
+ this.delegationLatencies.shift();
1151
+ }
1152
+
1153
+ this.emitEvent('queen.task.delegated', {
1154
+ planId,
1155
+ taskId: task.id.id,
1156
+ primaryAgent: primaryAgent.agentId,
1157
+ strategy,
1158
+ latencyMs: latency,
1159
+ });
1160
+
1161
+ return plan;
1162
+ }
1163
+
1164
+ /**
1165
+ * Score agents for task assignment
1166
+ */
1167
+ scoreAgents(task: TaskDefinition, patterns: MatchedPattern[]): AgentScore[] {
1168
+ const agents = this.swarm.getAllAgents();
1169
+ const scores: AgentScore[] = [];
1170
+
1171
+ for (const agent of agents) {
1172
+ const score = this.scoreAgent(agent, task, patterns);
1173
+ scores.push(score);
1174
+ }
1175
+
1176
+ // Sort by total score descending
1177
+ scores.sort((a, b) => b.totalScore - a.totalScore);
1178
+
1179
+ return scores;
1180
+ }
1181
+
1182
+ private scoreAgent(
1183
+ agent: AgentState,
1184
+ task: TaskDefinition,
1185
+ patterns: MatchedPattern[]
1186
+ ): AgentScore {
1187
+ const domain = this.getAgentDomain(agent);
1188
+
1189
+ // Capability score - how well agent capabilities match task
1190
+ const capabilityScore = this.calculateCapabilityScore(agent, task);
1191
+
1192
+ // Load score - prefer less loaded agents
1193
+ const loadScore = 1 - agent.workload;
1194
+
1195
+ // Performance score - based on past performance
1196
+ const performanceScore = this.calculatePerformanceScore(agent, patterns);
1197
+
1198
+ // Health score - agent health
1199
+ const healthScore = agent.health;
1200
+
1201
+ // Availability score - is agent actually available
1202
+ const availabilityScore = agent.status === 'idle' ? 1.0 :
1203
+ agent.status === 'busy' ? 0.3 : 0.0;
1204
+
1205
+ // Weighted total
1206
+ const totalScore =
1207
+ capabilityScore * 0.30 +
1208
+ loadScore * 0.20 +
1209
+ performanceScore * 0.25 +
1210
+ healthScore * 0.15 +
1211
+ availabilityScore * 0.10;
1212
+
1213
+ return {
1214
+ agentId: agent.id.id,
1215
+ domain,
1216
+ totalScore,
1217
+ capabilityScore,
1218
+ loadScore,
1219
+ performanceScore,
1220
+ healthScore,
1221
+ availabilityScore,
1222
+ };
1223
+ }
1224
+
1225
+ private calculateCapabilityScore(agent: AgentState, task: TaskDefinition): number {
1226
+ let score = 0.5; // Base score
1227
+
1228
+ // Check type match
1229
+ const typeMatches: Record<TaskType, AgentType[]> = {
1230
+ research: ['researcher'],
1231
+ analysis: ['analyst', 'researcher'],
1232
+ coding: ['coder'],
1233
+ testing: ['tester'],
1234
+ review: ['reviewer'],
1235
+ documentation: ['documenter'],
1236
+ coordination: ['coordinator', 'queen'],
1237
+ consensus: ['coordinator', 'queen'],
1238
+ custom: ['worker'],
1239
+ };
1240
+
1241
+ const preferredTypes = typeMatches[task.type] || ['worker'];
1242
+ if (preferredTypes.includes(agent.type)) {
1243
+ score += 0.3;
1244
+ }
1245
+
1246
+ // Check specific capabilities
1247
+ const caps = agent.capabilities;
1248
+ if (task.type === 'coding' && caps.codeGeneration) score += 0.1;
1249
+ if (task.type === 'review' && caps.codeReview) score += 0.1;
1250
+ if (task.type === 'testing' && caps.testing) score += 0.1;
1251
+ if (task.type === 'coordination' && caps.coordination) score += 0.1;
1252
+
1253
+ return Math.min(score, 1.0);
1254
+ }
1255
+
1256
+ private calculatePerformanceScore(
1257
+ agent: AgentState,
1258
+ patterns: MatchedPattern[]
1259
+ ): number {
1260
+ // Base on agent's success rate
1261
+ let score = agent.metrics.successRate;
1262
+
1263
+ // Boost if patterns suggest this agent type is successful
1264
+ const agentDomain = this.getAgentDomain(agent);
1265
+ for (const pattern of patterns) {
1266
+ if (pattern.strategy.toLowerCase().includes(agentDomain)) {
1267
+ score += pattern.successRate * 0.1;
1268
+ }
1269
+ }
1270
+
1271
+ return Math.min(score, 1.0);
1272
+ }
1273
+
1274
+ private getAgentDomain(agent: AgentState): AgentDomain {
1275
+ // Determine domain from agent type
1276
+ switch (agent.type) {
1277
+ case 'queen':
1278
+ return 'queen';
1279
+ case 'specialist':
1280
+ return 'security';
1281
+ case 'architect':
1282
+ return 'core';
1283
+ case 'coder':
1284
+ return 'integration';
1285
+ case 'tester':
1286
+ return 'support';
1287
+ default:
1288
+ return 'core';
1289
+ }
1290
+ }
1291
+
1292
+ private selectPrimaryAgent(
1293
+ task: TaskDefinition,
1294
+ scores: AgentScore[],
1295
+ analysis: TaskAnalysis
1296
+ ): AgentAssignment {
1297
+ // Prefer agent from recommended domain
1298
+ const domainAgents = scores.filter(s => s.domain === analysis.recommendedDomain);
1299
+
1300
+ // Fall back to best overall if no domain match
1301
+ const bestScore = domainAgents.length > 0 ? domainAgents[0] : scores[0];
1302
+
1303
+ return {
1304
+ agentId: bestScore.agentId,
1305
+ domain: bestScore.domain,
1306
+ taskId: task.id.id,
1307
+ score: bestScore.totalScore,
1308
+ assignedAt: new Date(),
1309
+ };
1310
+ }
1311
+
1312
+ private selectBackupAgents(
1313
+ task: TaskDefinition,
1314
+ scores: AgentScore[],
1315
+ primary: AgentAssignment
1316
+ ): AgentAssignment[] {
1317
+ const backups: AgentAssignment[] = [];
1318
+
1319
+ // Select up to 2 backup agents
1320
+ for (const score of scores) {
1321
+ if (score.agentId === primary.agentId) continue;
1322
+ if (score.totalScore < 0.3) continue;
1323
+ if (backups.length >= 2) break;
1324
+
1325
+ backups.push({
1326
+ agentId: score.agentId,
1327
+ domain: score.domain,
1328
+ taskId: task.id.id,
1329
+ score: score.totalScore,
1330
+ assignedAt: new Date(),
1331
+ });
1332
+ }
1333
+
1334
+ return backups;
1335
+ }
1336
+
1337
+ private createParallelAssignments(
1338
+ subtasks: SubTask[],
1339
+ scores: AgentScore[]
1340
+ ): ParallelAssignment[] {
1341
+ const assignments: ParallelAssignment[] = [];
1342
+
1343
+ for (const subtask of subtasks) {
1344
+ // Find best agent for this subtask's domain
1345
+ const domainScores = scores.filter(s => s.domain === subtask.recommendedDomain);
1346
+ const bestScore = domainScores.length > 0 ? domainScores[0] : scores[0];
1347
+
1348
+ assignments.push({
1349
+ subtaskId: subtask.id,
1350
+ agentId: bestScore.agentId,
1351
+ domain: subtask.recommendedDomain,
1352
+ dependencies: subtask.dependencies,
1353
+ });
1354
+ }
1355
+
1356
+ return assignments;
1357
+ }
1358
+
1359
+ private determineExecutionStrategy(analysis: TaskAnalysis): ExecutionStrategy {
1360
+ const subtaskCount = analysis.subtasks.length;
1361
+
1362
+ if (subtaskCount === 0) {
1363
+ return 'sequential';
1364
+ }
1365
+
1366
+ // Check for dependencies
1367
+ const hasDependencies = analysis.subtasks.some(st => st.dependencies.length > 0);
1368
+
1369
+ if (!hasDependencies && subtaskCount > 2) {
1370
+ return 'parallel';
1371
+ }
1372
+
1373
+ if (hasDependencies && subtaskCount > 3) {
1374
+ return 'pipeline';
1375
+ }
1376
+
1377
+ if (analysis.complexity > 0.7) {
1378
+ return 'fan-out-fan-in';
1379
+ }
1380
+
1381
+ return 'hybrid';
1382
+ }
1383
+
1384
+ private async executeDelegation(plan: DelegationPlan): Promise<void> {
1385
+ // Delegate to the primary agent
1386
+ await this.swarm.assignTaskToDomain(plan.taskId, plan.primaryAgent.domain);
1387
+
1388
+ // Notify about the delegation
1389
+ await this.swarm.broadcastMessage(
1390
+ {
1391
+ type: 'delegation',
1392
+ planId: plan.planId,
1393
+ taskId: plan.taskId,
1394
+ primaryAgent: plan.primaryAgent.agentId,
1395
+ strategy: plan.strategy,
1396
+ },
1397
+ 'normal'
1398
+ );
1399
+ }
1400
+
1401
+ // ===========================================================================
1402
+ // Swarm Health Monitoring
1403
+ // ===========================================================================
1404
+
1405
+ /**
1406
+ * Monitor swarm health and detect issues
1407
+ *
1408
+ * @returns Health report
1409
+ */
1410
+ async monitorSwarmHealth(): Promise<HealthReport> {
1411
+ this.reportCounter++;
1412
+ const reportId = `health_${Date.now()}_${this.reportCounter}`;
1413
+
1414
+ const agents = this.swarm.getAllAgents();
1415
+ const status = this.swarm.getStatus();
1416
+ const metrics = this.swarm.getMetrics();
1417
+
1418
+ // Compute domain health
1419
+ const domainHealth = this.computeDomainHealth(status.domains);
1420
+
1421
+ // Compute agent health
1422
+ const agentHealth = this.computeAgentHealth(agents);
1423
+
1424
+ // Detect bottlenecks
1425
+ const bottlenecks = this.detectBottlenecks(status, agents, metrics);
1426
+
1427
+ // Generate alerts
1428
+ const alerts = this.generateAlerts(bottlenecks, agentHealth, metrics);
1429
+
1430
+ // Overall health score
1431
+ const overallHealth = this.calculateOverallHealth(domainHealth, agentHealth, bottlenecks);
1432
+
1433
+ // Generate recommendations
1434
+ const recommendations = this.generateRecommendations(bottlenecks, overallHealth);
1435
+
1436
+ // Compile health metrics
1437
+ const healthMetrics: HealthMetrics = {
1438
+ totalAgents: agents.length,
1439
+ activeAgents: agents.filter(a => a.status === 'idle' || a.status === 'busy').length,
1440
+ idleAgents: agents.filter(a => a.status === 'idle').length,
1441
+ errorAgents: agents.filter(a => a.status === 'error').length,
1442
+ totalTasks: metrics.totalTasks,
1443
+ completedTasks: metrics.completedTasks,
1444
+ failedTasks: metrics.failedTasks,
1445
+ avgTaskDurationMs: metrics.avgTaskDurationMs,
1446
+ taskThroughputPerMin: metrics.completedTasks / Math.max(metrics.uptime / 60, 1),
1447
+ consensusSuccessRate: metrics.consensusSuccessRate,
1448
+ };
1449
+
1450
+ const report: HealthReport = {
1451
+ reportId,
1452
+ timestamp: new Date(),
1453
+ overallHealth,
1454
+ domainHealth,
1455
+ agentHealth,
1456
+ bottlenecks,
1457
+ alerts,
1458
+ metrics: healthMetrics,
1459
+ recommendations,
1460
+ };
1461
+
1462
+ // Store in history
1463
+ this.healthHistory.push(report);
1464
+ if (this.healthHistory.length > 100) {
1465
+ this.healthHistory.shift();
1466
+ }
1467
+ this.lastHealthReport = report;
1468
+
1469
+ this.emitEvent('queen.health.report', {
1470
+ reportId,
1471
+ overallHealth,
1472
+ bottleneckCount: bottlenecks.length,
1473
+ alertCount: alerts.length,
1474
+ });
1475
+
1476
+ return report;
1477
+ }
1478
+
1479
+ private computeDomainHealth(domains: DomainStatus[]): Map<AgentDomain, DomainHealthStatus> {
1480
+ const health = new Map<AgentDomain, DomainHealthStatus>();
1481
+
1482
+ for (const domain of domains) {
1483
+ const utilization = domain.agentCount > 0
1484
+ ? domain.busyAgents / domain.agentCount
1485
+ : 0;
1486
+
1487
+ const queuePressure = domain.tasksQueued > 5 ? 0.3 : domain.tasksQueued * 0.05;
1488
+ const domainHealth = Math.max(0, 1 - queuePressure - (1 - utilization) * 0.2);
1489
+
1490
+ health.set(domain.name, {
1491
+ domain: domain.name,
1492
+ health: domainHealth,
1493
+ activeAgents: domain.availableAgents + domain.busyAgents,
1494
+ totalAgents: domain.agentCount,
1495
+ queuedTasks: domain.tasksQueued,
1496
+ avgResponseTimeMs: 0, // Would need tracking
1497
+ errorRate: 0, // Would need tracking
1498
+ });
1499
+ }
1500
+
1501
+ return health;
1502
+ }
1503
+
1504
+ private computeAgentHealth(agents: AgentState[]): AgentHealthEntry[] {
1505
+ return agents.map(agent => ({
1506
+ agentId: agent.id.id,
1507
+ domain: this.getAgentDomain(agent),
1508
+ health: agent.health,
1509
+ status: agent.status,
1510
+ lastHeartbeat: agent.lastHeartbeat,
1511
+ currentLoad: agent.workload,
1512
+ recentErrors: agent.metrics.tasksFailed,
1513
+ }));
1514
+ }
1515
+
1516
+ private detectBottlenecks(
1517
+ status: { domains: DomainStatus[]; metrics: CoordinatorMetrics },
1518
+ agents: AgentState[],
1519
+ metrics: CoordinatorMetrics
1520
+ ): Bottleneck[] {
1521
+ const bottlenecks: Bottleneck[] = [];
1522
+
1523
+ // Check domain queues
1524
+ for (const domain of status.domains) {
1525
+ if (domain.tasksQueued > this.config.bottleneckThresholds.queueDepth) {
1526
+ bottlenecks.push({
1527
+ type: 'domain',
1528
+ location: domain.name,
1529
+ severity: domain.tasksQueued > 20 ? 'critical' : 'high',
1530
+ description: `High task queue depth in ${domain.name} domain`,
1531
+ impact: `${domain.tasksQueued} tasks waiting for processing`,
1532
+ suggestedAction: `Consider scaling ${domain.name} domain agents`,
1533
+ });
1534
+ }
1535
+ }
1536
+
1537
+ // Check error agents
1538
+ const errorAgents = agents.filter(a => a.status === 'error');
1539
+ if (errorAgents.length > 0) {
1540
+ bottlenecks.push({
1541
+ type: 'agent',
1542
+ location: errorAgents.map(a => a.id.id).join(', '),
1543
+ severity: errorAgents.length > 3 ? 'critical' : 'medium',
1544
+ description: `${errorAgents.length} agents in error state`,
1545
+ impact: 'Reduced processing capacity',
1546
+ suggestedAction: 'Investigate and recover error agents',
1547
+ });
1548
+ }
1549
+
1550
+ // Check coordination latency
1551
+ if (metrics.coordinationLatencyMs > this.config.bottleneckThresholds.responseTimeMs) {
1552
+ bottlenecks.push({
1553
+ type: 'resource',
1554
+ location: 'coordination',
1555
+ severity: 'high',
1556
+ description: 'High coordination latency detected',
1557
+ impact: `Current latency: ${metrics.coordinationLatencyMs}ms`,
1558
+ suggestedAction: 'Optimize coordination or reduce concurrent tasks',
1559
+ });
1560
+ }
1561
+
1562
+ return bottlenecks;
1563
+ }
1564
+
1565
+ private generateAlerts(
1566
+ bottlenecks: Bottleneck[],
1567
+ agentHealth: AgentHealthEntry[],
1568
+ metrics: CoordinatorMetrics
1569
+ ): HealthAlert[] {
1570
+ const alerts: HealthAlert[] = [];
1571
+
1572
+ // Generate alerts for critical bottlenecks
1573
+ for (const bottleneck of bottlenecks) {
1574
+ if (bottleneck.severity === 'critical' || bottleneck.severity === 'high') {
1575
+ alerts.push({
1576
+ alertId: `alert_${Date.now()}_${alerts.length}`,
1577
+ type: bottleneck.severity === 'critical' ? 'critical' : 'error',
1578
+ source: bottleneck.location,
1579
+ message: bottleneck.description,
1580
+ timestamp: new Date(),
1581
+ acknowledged: false,
1582
+ });
1583
+ }
1584
+ }
1585
+
1586
+ // Alert on low overall agent health
1587
+ const avgHealth = agentHealth.length > 0
1588
+ ? agentHealth.reduce((sum, a) => sum + a.health, 0) / agentHealth.length
1589
+ : 1.0;
1590
+
1591
+ if (avgHealth < 0.5) {
1592
+ alerts.push({
1593
+ alertId: `alert_${Date.now()}_health`,
1594
+ type: avgHealth < 0.3 ? 'critical' : 'warning',
1595
+ source: 'swarm',
1596
+ message: `Low average agent health: ${(avgHealth * 100).toFixed(1)}%`,
1597
+ timestamp: new Date(),
1598
+ acknowledged: false,
1599
+ });
1600
+ }
1601
+
1602
+ // Alert on high failure rate
1603
+ const failureRate = metrics.totalTasks > 0
1604
+ ? metrics.failedTasks / metrics.totalTasks
1605
+ : 0;
1606
+
1607
+ if (failureRate > this.config.bottleneckThresholds.errorRate) {
1608
+ alerts.push({
1609
+ alertId: `alert_${Date.now()}_failures`,
1610
+ type: failureRate > 0.2 ? 'critical' : 'warning',
1611
+ source: 'tasks',
1612
+ message: `High task failure rate: ${(failureRate * 100).toFixed(1)}%`,
1613
+ timestamp: new Date(),
1614
+ acknowledged: false,
1615
+ });
1616
+ }
1617
+
1618
+ return alerts;
1619
+ }
1620
+
1621
+ private calculateOverallHealth(
1622
+ domainHealth: Map<AgentDomain, DomainHealthStatus>,
1623
+ agentHealth: AgentHealthEntry[],
1624
+ bottlenecks: Bottleneck[]
1625
+ ): number {
1626
+ // Average domain health
1627
+ const domainHealthAvg = domainHealth.size > 0
1628
+ ? Array.from(domainHealth.values()).reduce((sum, d) => sum + d.health, 0) / domainHealth.size
1629
+ : 1.0;
1630
+
1631
+ // Average agent health
1632
+ const agentHealthAvg = agentHealth.length > 0
1633
+ ? agentHealth.reduce((sum, a) => sum + a.health, 0) / agentHealth.length
1634
+ : 1.0;
1635
+
1636
+ // Bottleneck penalty
1637
+ const bottleneckPenalty = bottlenecks.reduce((penalty, b) => {
1638
+ switch (b.severity) {
1639
+ case 'critical': return penalty + 0.2;
1640
+ case 'high': return penalty + 0.1;
1641
+ case 'medium': return penalty + 0.05;
1642
+ case 'low': return penalty + 0.02;
1643
+ default: return penalty;
1644
+ }
1645
+ }, 0);
1646
+
1647
+ const overallHealth = (domainHealthAvg * 0.4 + agentHealthAvg * 0.4) - bottleneckPenalty;
1648
+ return Math.max(0, Math.min(1, overallHealth));
1649
+ }
1650
+
1651
+ private generateRecommendations(bottlenecks: Bottleneck[], overallHealth: number): string[] {
1652
+ const recommendations: string[] = [];
1653
+
1654
+ // Add bottleneck-specific recommendations
1655
+ for (const bottleneck of bottlenecks) {
1656
+ recommendations.push(bottleneck.suggestedAction);
1657
+ }
1658
+
1659
+ // General recommendations based on health
1660
+ if (overallHealth < 0.5) {
1661
+ recommendations.push('Consider reducing task load or adding more agents');
1662
+ }
1663
+
1664
+ if (overallHealth < 0.3) {
1665
+ recommendations.push('URGENT: Investigate system-wide issues immediately');
1666
+ }
1667
+
1668
+ return [...new Set(recommendations)]; // Deduplicate
1669
+ }
1670
+
1671
+ private startHealthMonitoring(): void {
1672
+ this.healthCheckInterval = setInterval(async () => {
1673
+ try {
1674
+ await this.monitorSwarmHealth();
1675
+ } catch (error) {
1676
+ this.emitEvent('queen.health.error', { error: String(error) });
1677
+ }
1678
+ }, this.config.healthCheckIntervalMs);
1679
+ }
1680
+
1681
+ private stopHealthMonitoring(): void {
1682
+ if (this.healthCheckInterval) {
1683
+ clearInterval(this.healthCheckInterval);
1684
+ this.healthCheckInterval = undefined;
1685
+ }
1686
+ }
1687
+
1688
+ // ===========================================================================
1689
+ // Consensus Coordination
1690
+ // ===========================================================================
1691
+
1692
+ /**
1693
+ * Coordinate consensus for a decision
1694
+ *
1695
+ * @param decision - Decision requiring consensus
1696
+ * @returns Consensus result
1697
+ */
1698
+ async coordinateConsensus(decision: Decision): Promise<ConsensusResult> {
1699
+ const startTime = performance.now();
1700
+
1701
+ this.decisionCounter++;
1702
+ decision.decisionId = `decision_${Date.now()}_${this.decisionCounter}`;
1703
+
1704
+ // Store active decision
1705
+ this.activeDecisions.set(decision.decisionId, decision);
1706
+
1707
+ try {
1708
+ let result: ConsensusResult;
1709
+
1710
+ switch (decision.requiredConsensus) {
1711
+ case 'queen-override':
1712
+ // Queen can make unilateral decisions for certain types
1713
+ result = this.queenOverride(decision);
1714
+ break;
1715
+
1716
+ case 'unanimous':
1717
+ result = await this.unanimousConsensus(decision);
1718
+ break;
1719
+
1720
+ case 'supermajority':
1721
+ result = await this.supermajorityConsensus(decision);
1722
+ break;
1723
+
1724
+ case 'weighted':
1725
+ result = await this.weightedConsensus(decision);
1726
+ break;
1727
+
1728
+ case 'majority':
1729
+ default:
1730
+ result = await this.majorityConsensus(decision);
1731
+ }
1732
+
1733
+ // Record latency
1734
+ const latency = performance.now() - startTime;
1735
+ this.consensusLatencies.push(latency);
1736
+ if (this.consensusLatencies.length > 100) {
1737
+ this.consensusLatencies.shift();
1738
+ }
1739
+
1740
+ this.emitEvent('queen.consensus.completed', {
1741
+ decisionId: decision.decisionId,
1742
+ type: decision.requiredConsensus,
1743
+ approved: result.approved,
1744
+ approvalRate: result.approvalRate,
1745
+ latencyMs: latency,
1746
+ });
1747
+
1748
+ return result;
1749
+ } finally {
1750
+ this.activeDecisions.delete(decision.decisionId);
1751
+ }
1752
+ }
1753
+
1754
+ private queenOverride(decision: Decision): ConsensusResult {
1755
+ // Queen can make immediate decisions for:
1756
+ // - Emergency actions
1757
+ // - Agent termination
1758
+ // - Priority overrides
1759
+ const allowedTypes: DecisionType[] = ['emergency-action', 'agent-termination', 'priority-override'];
1760
+
1761
+ if (!allowedTypes.includes(decision.type)) {
1762
+ throw new Error(`Queen override not allowed for decision type: ${decision.type}`);
1763
+ }
1764
+
1765
+ return {
1766
+ proposalId: decision.decisionId,
1767
+ approved: true,
1768
+ approvalRate: 1.0,
1769
+ participationRate: 1.0,
1770
+ finalValue: decision.proposal,
1771
+ rounds: 1,
1772
+ durationMs: 0,
1773
+ };
1774
+ }
1775
+
1776
+ private async majorityConsensus(decision: Decision): Promise<ConsensusResult> {
1777
+ // Use swarm's consensus engine with majority threshold
1778
+ const result = await this.swarm.proposeConsensus({
1779
+ decision,
1780
+ threshold: 0.51,
1781
+ timeout: this.config.consensusTimeouts.majority,
1782
+ });
1783
+
1784
+ return result;
1785
+ }
1786
+
1787
+ private async supermajorityConsensus(decision: Decision): Promise<ConsensusResult> {
1788
+ // Use swarm's consensus engine with 2/3 threshold
1789
+ const result = await this.swarm.proposeConsensus({
1790
+ decision,
1791
+ threshold: 0.67,
1792
+ timeout: this.config.consensusTimeouts.supermajority,
1793
+ });
1794
+
1795
+ return result;
1796
+ }
1797
+
1798
+ private async unanimousConsensus(decision: Decision): Promise<ConsensusResult> {
1799
+ // Use swarm's consensus engine with unanimous requirement
1800
+ const result = await this.swarm.proposeConsensus({
1801
+ decision,
1802
+ threshold: 1.0,
1803
+ timeout: this.config.consensusTimeouts.unanimous,
1804
+ });
1805
+
1806
+ return result;
1807
+ }
1808
+
1809
+ private async weightedConsensus(decision: Decision): Promise<ConsensusResult> {
1810
+ // Weighted consensus based on agent performance
1811
+ // For now, delegate to the standard consensus with metadata
1812
+ const agents = this.swarm.getAllAgents();
1813
+ const weights = new Map<string, number>();
1814
+
1815
+ for (const agent of agents) {
1816
+ const weight = agent.metrics.successRate * agent.health;
1817
+ weights.set(agent.id.id, weight);
1818
+ }
1819
+
1820
+ const result = await this.swarm.proposeConsensus({
1821
+ decision,
1822
+ weights: Object.fromEntries(weights),
1823
+ threshold: 0.51,
1824
+ timeout: this.config.consensusTimeouts.majority,
1825
+ });
1826
+
1827
+ return result;
1828
+ }
1829
+
1830
+ // ===========================================================================
1831
+ // Learning from Outcomes
1832
+ // ===========================================================================
1833
+
1834
+ /**
1835
+ * Record task outcome for learning
1836
+ *
1837
+ * @param task - Completed task
1838
+ * @param result - Task result
1839
+ */
1840
+ async recordOutcome(task: TaskDefinition, result: TaskResult): Promise<void> {
1841
+ // Store in outcome history
1842
+ this.outcomeHistory.push(result);
1843
+ if (this.outcomeHistory.length > 1000) {
1844
+ this.outcomeHistory.shift();
1845
+ }
1846
+
1847
+ // Learn from outcome if neural system available
1848
+ if (this.neural && this.config.enableLearning) {
1849
+ await this.learnFromOutcome(task, result);
1850
+ }
1851
+
1852
+ // Store in memory service if available
1853
+ if (this.memory) {
1854
+ await this.storeOutcomeMemory(task, result);
1855
+ }
1856
+
1857
+ this.emitEvent('queen.outcome.recorded', {
1858
+ taskId: task.id.id,
1859
+ success: result.success,
1860
+ durationMs: result.durationMs,
1861
+ qualityScore: result.metrics.qualityScore,
1862
+ });
1863
+ }
1864
+
1865
+ private async learnFromOutcome(task: TaskDefinition, result: TaskResult): Promise<void> {
1866
+ if (!this.neural) return;
1867
+
1868
+ // Create trajectory for this task
1869
+ const trajectoryId = this.neural.beginTask(
1870
+ task.description || task.name,
1871
+ result.domain
1872
+ );
1873
+
1874
+ // Record the execution step
1875
+ const embedding = this.createSimpleEmbedding(task.description || task.name);
1876
+ const reward = result.success
1877
+ ? result.metrics.qualityScore * 0.8 + 0.2
1878
+ : result.metrics.qualityScore * 0.3;
1879
+
1880
+ this.neural.recordStep(
1881
+ trajectoryId,
1882
+ `executed_${task.type}_in_${result.domain}`,
1883
+ reward,
1884
+ embedding
1885
+ );
1886
+
1887
+ // Complete the task trajectory
1888
+ await this.neural.completeTask(trajectoryId, result.metrics.qualityScore);
1889
+ }
1890
+
1891
+ private async storeOutcomeMemory(task: TaskDefinition, result: TaskResult): Promise<void> {
1892
+ if (!this.memory) return;
1893
+
1894
+ try {
1895
+ await this.memory.store({
1896
+ key: `outcome_${task.id.id}`,
1897
+ content: this.formatOutcomeContent(task, result),
1898
+ namespace: 'queen-outcomes',
1899
+ tags: [
1900
+ task.type,
1901
+ result.domain,
1902
+ result.success ? 'success' : 'failure',
1903
+ ],
1904
+ metadata: {
1905
+ taskId: task.id.id,
1906
+ success: result.success,
1907
+ durationMs: result.durationMs,
1908
+ qualityScore: result.metrics.qualityScore,
1909
+ agentId: result.agentId,
1910
+ },
1911
+ });
1912
+ } catch (error) {
1913
+ // Log but don't fail - memory storage is optional
1914
+ this.emitEvent('queen.memory.error', { error: String(error) });
1915
+ }
1916
+ }
1917
+
1918
+ private formatOutcomeContent(task: TaskDefinition, result: TaskResult): string {
1919
+ return [
1920
+ `Task: ${task.name}`,
1921
+ `Type: ${task.type}`,
1922
+ `Domain: ${result.domain}`,
1923
+ `Agent: ${result.agentId}`,
1924
+ `Success: ${result.success}`,
1925
+ `Duration: ${result.durationMs}ms`,
1926
+ `Quality: ${result.metrics.qualityScore}`,
1927
+ `Description: ${task.description || 'N/A'}`,
1928
+ ].join('\n');
1929
+ }
1930
+
1931
+ // ===========================================================================
1932
+ // Utility Methods
1933
+ // ===========================================================================
1934
+
1935
+ /**
1936
+ * Get the last health report
1937
+ */
1938
+ getLastHealthReport(): HealthReport | undefined {
1939
+ return this.lastHealthReport;
1940
+ }
1941
+
1942
+ /**
1943
+ * Get outcome history
1944
+ */
1945
+ getOutcomeHistory(): TaskResult[] {
1946
+ return [...this.outcomeHistory];
1947
+ }
1948
+
1949
+ /**
1950
+ * Get analysis cache
1951
+ */
1952
+ getAnalysisCache(): Map<string, TaskAnalysis> {
1953
+ return new Map(this.analysisCache);
1954
+ }
1955
+
1956
+ /**
1957
+ * Get delegation plans
1958
+ */
1959
+ getDelegationPlans(): Map<string, DelegationPlan> {
1960
+ return new Map(this.delegationPlans);
1961
+ }
1962
+
1963
+ /**
1964
+ * Get performance statistics
1965
+ */
1966
+ getPerformanceStats(): {
1967
+ avgAnalysisLatencyMs: number;
1968
+ avgDelegationLatencyMs: number;
1969
+ avgConsensusLatencyMs: number;
1970
+ totalAnalyses: number;
1971
+ totalDelegations: number;
1972
+ totalDecisions: number;
1973
+ } {
1974
+ const avg = (arr: number[]) => arr.length > 0
1975
+ ? arr.reduce((a, b) => a + b, 0) / arr.length
1976
+ : 0;
1977
+
1978
+ return {
1979
+ avgAnalysisLatencyMs: avg(this.analysisLatencies),
1980
+ avgDelegationLatencyMs: avg(this.delegationLatencies),
1981
+ avgConsensusLatencyMs: avg(this.consensusLatencies),
1982
+ totalAnalyses: this.analysisCounter,
1983
+ totalDelegations: this.planCounter,
1984
+ totalDecisions: this.decisionCounter,
1985
+ };
1986
+ }
1987
+
1988
+ /**
1989
+ * Check if learning is enabled
1990
+ */
1991
+ isLearningEnabled(): boolean {
1992
+ return this.config.enableLearning && !!this.neural;
1993
+ }
1994
+
1995
+ private emitEvent(type: string, data: Record<string, unknown>): void {
1996
+ const event = {
1997
+ id: `event_${Date.now()}_${Math.random().toString(36).substr(2, 6)}`,
1998
+ type,
1999
+ source: 'queen-coordinator',
2000
+ timestamp: new Date(),
2001
+ data,
2002
+ };
2003
+
2004
+ this.emit(type, event);
2005
+ this.emit('event', event);
2006
+ }
2007
+ }
2008
+
2009
+ // =============================================================================
2010
+ // Factory Function
2011
+ // =============================================================================
2012
+
2013
+ /**
2014
+ * Create a Queen Coordinator instance
2015
+ */
2016
+ export function createQueenCoordinator(
2017
+ swarm: ISwarmCoordinator,
2018
+ config?: Partial<QueenCoordinatorConfig>,
2019
+ neural?: INeuralLearningSystem,
2020
+ memory?: IMemoryService
2021
+ ): QueenCoordinator {
2022
+ return new QueenCoordinator(swarm, config, neural, memory);
2023
+ }
2024
+
2025
+ export default QueenCoordinator;