@sparkleideas/shared 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 (96) hide show
  1. package/README.md +323 -0
  2. package/__tests__/hooks/bash-safety.test.ts +289 -0
  3. package/__tests__/hooks/file-organization.test.ts +335 -0
  4. package/__tests__/hooks/git-commit.test.ts +336 -0
  5. package/__tests__/hooks/index.ts +23 -0
  6. package/__tests__/hooks/session-hooks.test.ts +357 -0
  7. package/__tests__/hooks/task-hooks.test.ts +193 -0
  8. package/docs/EVENTS_IMPLEMENTATION_SUMMARY.md +388 -0
  9. package/docs/EVENTS_QUICK_REFERENCE.md +470 -0
  10. package/docs/EVENTS_README.md +352 -0
  11. package/package.json +39 -0
  12. package/src/core/config/defaults.ts +207 -0
  13. package/src/core/config/index.ts +15 -0
  14. package/src/core/config/loader.ts +271 -0
  15. package/src/core/config/schema.ts +188 -0
  16. package/src/core/config/validator.ts +209 -0
  17. package/src/core/event-bus.ts +236 -0
  18. package/src/core/index.ts +22 -0
  19. package/src/core/interfaces/agent.interface.ts +251 -0
  20. package/src/core/interfaces/coordinator.interface.ts +363 -0
  21. package/src/core/interfaces/event.interface.ts +267 -0
  22. package/src/core/interfaces/index.ts +19 -0
  23. package/src/core/interfaces/memory.interface.ts +332 -0
  24. package/src/core/interfaces/task.interface.ts +223 -0
  25. package/src/core/orchestrator/event-coordinator.ts +122 -0
  26. package/src/core/orchestrator/health-monitor.ts +214 -0
  27. package/src/core/orchestrator/index.ts +89 -0
  28. package/src/core/orchestrator/lifecycle-manager.ts +263 -0
  29. package/src/core/orchestrator/session-manager.ts +279 -0
  30. package/src/core/orchestrator/task-manager.ts +317 -0
  31. package/src/events/domain-events.ts +584 -0
  32. package/src/events/event-store.test.ts +387 -0
  33. package/src/events/event-store.ts +588 -0
  34. package/src/events/example-usage.ts +293 -0
  35. package/src/events/index.ts +90 -0
  36. package/src/events/projections.ts +561 -0
  37. package/src/events/state-reconstructor.ts +349 -0
  38. package/src/events.ts +367 -0
  39. package/src/hooks/INTEGRATION.md +658 -0
  40. package/src/hooks/README.md +532 -0
  41. package/src/hooks/example-usage.ts +499 -0
  42. package/src/hooks/executor.ts +379 -0
  43. package/src/hooks/hooks.test.ts +421 -0
  44. package/src/hooks/index.ts +131 -0
  45. package/src/hooks/registry.ts +333 -0
  46. package/src/hooks/safety/bash-safety.ts +604 -0
  47. package/src/hooks/safety/file-organization.ts +473 -0
  48. package/src/hooks/safety/git-commit.ts +623 -0
  49. package/src/hooks/safety/index.ts +46 -0
  50. package/src/hooks/session-hooks.ts +559 -0
  51. package/src/hooks/task-hooks.ts +513 -0
  52. package/src/hooks/types.ts +357 -0
  53. package/src/hooks/verify-exports.test.ts +125 -0
  54. package/src/index.ts +195 -0
  55. package/src/mcp/connection-pool.ts +438 -0
  56. package/src/mcp/index.ts +183 -0
  57. package/src/mcp/server.ts +774 -0
  58. package/src/mcp/session-manager.ts +428 -0
  59. package/src/mcp/tool-registry.ts +566 -0
  60. package/src/mcp/transport/http.ts +557 -0
  61. package/src/mcp/transport/index.ts +294 -0
  62. package/src/mcp/transport/stdio.ts +324 -0
  63. package/src/mcp/transport/websocket.ts +484 -0
  64. package/src/mcp/types.ts +565 -0
  65. package/src/plugin-interface.ts +663 -0
  66. package/src/plugin-loader.ts +638 -0
  67. package/src/plugin-registry.ts +604 -0
  68. package/src/plugins/index.ts +34 -0
  69. package/src/plugins/official/hive-mind-plugin.ts +330 -0
  70. package/src/plugins/official/index.ts +24 -0
  71. package/src/plugins/official/maestro-plugin.ts +508 -0
  72. package/src/plugins/types.ts +108 -0
  73. package/src/resilience/bulkhead.ts +277 -0
  74. package/src/resilience/circuit-breaker.ts +326 -0
  75. package/src/resilience/index.ts +26 -0
  76. package/src/resilience/rate-limiter.ts +420 -0
  77. package/src/resilience/retry.ts +224 -0
  78. package/src/security/index.ts +39 -0
  79. package/src/security/input-validation.ts +265 -0
  80. package/src/security/secure-random.ts +159 -0
  81. package/src/services/index.ts +16 -0
  82. package/src/services/v3-progress.service.ts +505 -0
  83. package/src/types/agent.types.ts +144 -0
  84. package/src/types/index.ts +22 -0
  85. package/src/types/mcp.types.ts +300 -0
  86. package/src/types/memory.types.ts +263 -0
  87. package/src/types/swarm.types.ts +255 -0
  88. package/src/types/task.types.ts +205 -0
  89. package/src/types.ts +367 -0
  90. package/src/utils/secure-logger.d.ts +69 -0
  91. package/src/utils/secure-logger.d.ts.map +1 -0
  92. package/src/utils/secure-logger.js +208 -0
  93. package/src/utils/secure-logger.js.map +1 -0
  94. package/src/utils/secure-logger.ts +257 -0
  95. package/tmp.json +0 -0
  96. package/tsconfig.json +9 -0
@@ -0,0 +1,604 @@
1
+ /**
2
+ * V3 Plugin Registry
3
+ * Domain-Driven Design - Plugin-Based Architecture (ADR-004)
4
+ *
5
+ * Central registry for tracking plugin state, metadata, and registrations
6
+ */
7
+
8
+ import type {
9
+ ClaudeFlowPlugin,
10
+ PluginInfo,
11
+ PluginLifecycleState,
12
+ PluginContext,
13
+ AgentTypeDefinition,
14
+ TaskTypeDefinition,
15
+ MCPToolDefinition,
16
+ CLICommandDefinition,
17
+ MemoryBackendFactory,
18
+ } from './plugin-interface.js';
19
+ import { PluginError } from './plugin-interface.js';
20
+
21
+ /**
22
+ * Plugin registry for managing plugin lifecycle and registrations
23
+ */
24
+ export class PluginRegistry {
25
+ private plugins = new Map<string, PluginInfo>();
26
+ private agentTypes = new Map<string, { plugin: string; definition: AgentTypeDefinition }>();
27
+ private taskTypes = new Map<string, { plugin: string; definition: TaskTypeDefinition }>();
28
+ private mcpTools = new Map<string, { plugin: string; definition: MCPToolDefinition }>();
29
+ private cliCommands = new Map<string, { plugin: string; definition: CLICommandDefinition }>();
30
+ private memoryBackends = new Map<string, { plugin: string; factory: MemoryBackendFactory }>();
31
+
32
+ /**
33
+ * Register a plugin in the registry
34
+ */
35
+ registerPlugin(
36
+ plugin: ClaudeFlowPlugin,
37
+ initialState: PluginLifecycleState,
38
+ context: PluginContext
39
+ ): void {
40
+ if (this.plugins.has(plugin.name)) {
41
+ throw new PluginError(
42
+ `Plugin '${plugin.name}' is already registered`,
43
+ plugin.name,
44
+ 'DUPLICATE_PLUGIN'
45
+ );
46
+ }
47
+
48
+ const info: PluginInfo = {
49
+ plugin,
50
+ state: initialState,
51
+ context,
52
+ metrics: {
53
+ agentTypesRegistered: 0,
54
+ taskTypesRegistered: 0,
55
+ mcpToolsRegistered: 0,
56
+ cliCommandsRegistered: 0,
57
+ memoryBackendsRegistered: 0,
58
+ },
59
+ };
60
+
61
+ this.plugins.set(plugin.name, info);
62
+ }
63
+
64
+ /**
65
+ * Unregister a plugin from the registry
66
+ */
67
+ unregisterPlugin(pluginName: string): boolean {
68
+ const info = this.plugins.get(pluginName);
69
+ if (!info) {
70
+ return false;
71
+ }
72
+
73
+ // Unregister all plugin's registrations
74
+ this.unregisterPluginAgentTypes(pluginName);
75
+ this.unregisterPluginTaskTypes(pluginName);
76
+ this.unregisterPluginMCPTools(pluginName);
77
+ this.unregisterPluginCLICommands(pluginName);
78
+ this.unregisterPluginMemoryBackends(pluginName);
79
+
80
+ // Remove plugin
81
+ return this.plugins.delete(pluginName);
82
+ }
83
+
84
+ /**
85
+ * Get a plugin by name
86
+ */
87
+ getPlugin(pluginName: string): PluginInfo | undefined {
88
+ return this.plugins.get(pluginName);
89
+ }
90
+
91
+ /**
92
+ * Get all registered plugins
93
+ */
94
+ getAllPlugins(): Map<string, PluginInfo> {
95
+ return new Map(this.plugins);
96
+ }
97
+
98
+ /**
99
+ * Get all plugin names
100
+ */
101
+ getPluginNames(): string[] {
102
+ return Array.from(this.plugins.keys());
103
+ }
104
+
105
+ /**
106
+ * Check if a plugin is registered
107
+ */
108
+ hasPlugin(pluginName: string): boolean {
109
+ return this.plugins.has(pluginName);
110
+ }
111
+
112
+ /**
113
+ * Get plugins by state
114
+ */
115
+ getPluginsByState(state: PluginLifecycleState): PluginInfo[] {
116
+ return Array.from(this.plugins.values()).filter((info) => info.state === state);
117
+ }
118
+
119
+ /**
120
+ * Get plugin count
121
+ */
122
+ getPluginCount(): number {
123
+ return this.plugins.size;
124
+ }
125
+
126
+ /**
127
+ * Update plugin state
128
+ */
129
+ updatePluginState(pluginName: string, state: PluginLifecycleState, error?: Error): void {
130
+ const info = this.plugins.get(pluginName);
131
+ if (!info) {
132
+ throw new PluginError(
133
+ `Plugin '${pluginName}' not found`,
134
+ pluginName,
135
+ 'INVALID_PLUGIN'
136
+ );
137
+ }
138
+
139
+ info.state = state;
140
+
141
+ if (state === 'initialized') {
142
+ info.initializedAt = new Date();
143
+ } else if (state === 'shutdown') {
144
+ info.shutdownAt = new Date();
145
+ } else if (state === 'error') {
146
+ info.error = error;
147
+ }
148
+ }
149
+
150
+ /**
151
+ * Collect and update plugin metrics
152
+ */
153
+ collectPluginMetrics(pluginName: string): void {
154
+ const info = this.plugins.get(pluginName);
155
+ if (!info || !info.metrics) {
156
+ return;
157
+ }
158
+
159
+ const plugin = info.plugin;
160
+
161
+ // Count registered items
162
+ info.metrics.agentTypesRegistered = plugin.registerAgentTypes?.()?.length || 0;
163
+ info.metrics.taskTypesRegistered = plugin.registerTaskTypes?.()?.length || 0;
164
+ info.metrics.mcpToolsRegistered = plugin.registerMCPTools?.()?.length || 0;
165
+ info.metrics.cliCommandsRegistered = plugin.registerCLICommands?.()?.length || 0;
166
+ info.metrics.memoryBackendsRegistered = plugin.registerMemoryBackends?.()?.length || 0;
167
+ }
168
+
169
+ /**
170
+ * Get plugin status summary
171
+ */
172
+ getStatusSummary(): PluginRegistryStatus {
173
+ const states = Array.from(this.plugins.values()).reduce((acc, info) => {
174
+ acc[info.state] = (acc[info.state] || 0) + 1;
175
+ return acc;
176
+ }, {} as Record<PluginLifecycleState, number>);
177
+
178
+ return {
179
+ totalPlugins: this.plugins.size,
180
+ states,
181
+ agentTypesRegistered: this.agentTypes.size,
182
+ taskTypesRegistered: this.taskTypes.size,
183
+ mcpToolsRegistered: this.mcpTools.size,
184
+ cliCommandsRegistered: this.cliCommands.size,
185
+ memoryBackendsRegistered: this.memoryBackends.size,
186
+ };
187
+ }
188
+
189
+ // =============================================================================
190
+ // Agent Type Registry
191
+ // =============================================================================
192
+
193
+ /**
194
+ * Register agent types from a plugin
195
+ */
196
+ registerAgentTypes(pluginName: string): void {
197
+ const info = this.plugins.get(pluginName);
198
+ if (!info) {
199
+ throw new PluginError(
200
+ `Plugin '${pluginName}' not found`,
201
+ pluginName,
202
+ 'INVALID_PLUGIN'
203
+ );
204
+ }
205
+
206
+ const agentTypes = info.plugin.registerAgentTypes?.();
207
+ if (!agentTypes || agentTypes.length === 0) {
208
+ return;
209
+ }
210
+
211
+ for (const definition of agentTypes) {
212
+ if (this.agentTypes.has(definition.type)) {
213
+ throw new PluginError(
214
+ `Agent type '${definition.type}' is already registered by plugin '${this.agentTypes.get(definition.type)?.plugin}'`,
215
+ pluginName,
216
+ 'DUPLICATE_PLUGIN'
217
+ );
218
+ }
219
+
220
+ this.agentTypes.set(definition.type, { plugin: pluginName, definition });
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Unregister agent types from a plugin
226
+ */
227
+ unregisterPluginAgentTypes(pluginName: string): void {
228
+ for (const [type, entry] of Array.from(this.agentTypes.entries())) {
229
+ if (entry.plugin === pluginName) {
230
+ this.agentTypes.delete(type);
231
+ }
232
+ }
233
+ }
234
+
235
+ /**
236
+ * Get agent type definition
237
+ */
238
+ getAgentType(type: string): AgentTypeDefinition | undefined {
239
+ return this.agentTypes.get(type)?.definition;
240
+ }
241
+
242
+ /**
243
+ * Get all agent types
244
+ */
245
+ getAllAgentTypes(): AgentTypeDefinition[] {
246
+ return Array.from(this.agentTypes.values()).map((entry) => entry.definition);
247
+ }
248
+
249
+ /**
250
+ * Get agent types by plugin
251
+ */
252
+ getAgentTypesByPlugin(pluginName: string): AgentTypeDefinition[] {
253
+ return Array.from(this.agentTypes.values())
254
+ .filter((entry) => entry.plugin === pluginName)
255
+ .map((entry) => entry.definition);
256
+ }
257
+
258
+ // =============================================================================
259
+ // Task Type Registry
260
+ // =============================================================================
261
+
262
+ /**
263
+ * Register task types from a plugin
264
+ */
265
+ registerTaskTypes(pluginName: string): void {
266
+ const info = this.plugins.get(pluginName);
267
+ if (!info) {
268
+ throw new PluginError(
269
+ `Plugin '${pluginName}' not found`,
270
+ pluginName,
271
+ 'INVALID_PLUGIN'
272
+ );
273
+ }
274
+
275
+ const taskTypes = info.plugin.registerTaskTypes?.();
276
+ if (!taskTypes || taskTypes.length === 0) {
277
+ return;
278
+ }
279
+
280
+ for (const definition of taskTypes) {
281
+ if (this.taskTypes.has(definition.type)) {
282
+ throw new PluginError(
283
+ `Task type '${definition.type}' is already registered by plugin '${this.taskTypes.get(definition.type)?.plugin}'`,
284
+ pluginName,
285
+ 'DUPLICATE_PLUGIN'
286
+ );
287
+ }
288
+
289
+ this.taskTypes.set(definition.type, { plugin: pluginName, definition });
290
+ }
291
+ }
292
+
293
+ /**
294
+ * Unregister task types from a plugin
295
+ */
296
+ unregisterPluginTaskTypes(pluginName: string): void {
297
+ for (const [type, entry] of Array.from(this.taskTypes.entries())) {
298
+ if (entry.plugin === pluginName) {
299
+ this.taskTypes.delete(type);
300
+ }
301
+ }
302
+ }
303
+
304
+ /**
305
+ * Get task type definition
306
+ */
307
+ getTaskType(type: string): TaskTypeDefinition | undefined {
308
+ return this.taskTypes.get(type)?.definition;
309
+ }
310
+
311
+ /**
312
+ * Get all task types
313
+ */
314
+ getAllTaskTypes(): TaskTypeDefinition[] {
315
+ return Array.from(this.taskTypes.values()).map((entry) => entry.definition);
316
+ }
317
+
318
+ /**
319
+ * Get task types by plugin
320
+ */
321
+ getTaskTypesByPlugin(pluginName: string): TaskTypeDefinition[] {
322
+ return Array.from(this.taskTypes.values())
323
+ .filter((entry) => entry.plugin === pluginName)
324
+ .map((entry) => entry.definition);
325
+ }
326
+
327
+ // =============================================================================
328
+ // MCP Tool Registry
329
+ // =============================================================================
330
+
331
+ /**
332
+ * Register MCP tools from a plugin
333
+ */
334
+ registerMCPTools(pluginName: string): void {
335
+ const info = this.plugins.get(pluginName);
336
+ if (!info) {
337
+ throw new PluginError(
338
+ `Plugin '${pluginName}' not found`,
339
+ pluginName,
340
+ 'INVALID_PLUGIN'
341
+ );
342
+ }
343
+
344
+ const mcpTools = info.plugin.registerMCPTools?.();
345
+ if (!mcpTools || mcpTools.length === 0) {
346
+ return;
347
+ }
348
+
349
+ for (const definition of mcpTools) {
350
+ if (this.mcpTools.has(definition.name)) {
351
+ throw new PluginError(
352
+ `MCP tool '${definition.name}' is already registered by plugin '${this.mcpTools.get(definition.name)?.plugin}'`,
353
+ pluginName,
354
+ 'DUPLICATE_PLUGIN'
355
+ );
356
+ }
357
+
358
+ // Add plugin metadata
359
+ definition.pluginName = pluginName;
360
+
361
+ this.mcpTools.set(definition.name, { plugin: pluginName, definition });
362
+ }
363
+ }
364
+
365
+ /**
366
+ * Unregister MCP tools from a plugin
367
+ */
368
+ unregisterPluginMCPTools(pluginName: string): void {
369
+ for (const [name, entry] of Array.from(this.mcpTools.entries())) {
370
+ if (entry.plugin === pluginName) {
371
+ this.mcpTools.delete(name);
372
+ }
373
+ }
374
+ }
375
+
376
+ /**
377
+ * Get MCP tool definition
378
+ */
379
+ getMCPTool(name: string): MCPToolDefinition | undefined {
380
+ return this.mcpTools.get(name)?.definition;
381
+ }
382
+
383
+ /**
384
+ * Get all MCP tools
385
+ */
386
+ getAllMCPTools(): MCPToolDefinition[] {
387
+ return Array.from(this.mcpTools.values()).map((entry) => entry.definition);
388
+ }
389
+
390
+ /**
391
+ * Get MCP tools by plugin
392
+ */
393
+ getMCPToolsByPlugin(pluginName: string): MCPToolDefinition[] {
394
+ return Array.from(this.mcpTools.values())
395
+ .filter((entry) => entry.plugin === pluginName)
396
+ .map((entry) => entry.definition);
397
+ }
398
+
399
+ // =============================================================================
400
+ // CLI Command Registry
401
+ // =============================================================================
402
+
403
+ /**
404
+ * Register CLI commands from a plugin
405
+ */
406
+ registerCLICommands(pluginName: string): void {
407
+ const info = this.plugins.get(pluginName);
408
+ if (!info) {
409
+ throw new PluginError(
410
+ `Plugin '${pluginName}' not found`,
411
+ pluginName,
412
+ 'INVALID_PLUGIN'
413
+ );
414
+ }
415
+
416
+ const cliCommands = info.plugin.registerCLICommands?.();
417
+ if (!cliCommands || cliCommands.length === 0) {
418
+ return;
419
+ }
420
+
421
+ for (const definition of cliCommands) {
422
+ if (this.cliCommands.has(definition.name)) {
423
+ throw new PluginError(
424
+ `CLI command '${definition.name}' is already registered by plugin '${this.cliCommands.get(definition.name)?.plugin}'`,
425
+ pluginName,
426
+ 'DUPLICATE_PLUGIN'
427
+ );
428
+ }
429
+
430
+ this.cliCommands.set(definition.name, { plugin: pluginName, definition });
431
+
432
+ // Register aliases
433
+ if (definition.aliases) {
434
+ for (const alias of definition.aliases) {
435
+ if (this.cliCommands.has(alias)) {
436
+ throw new PluginError(
437
+ `CLI command alias '${alias}' is already registered`,
438
+ pluginName,
439
+ 'DUPLICATE_PLUGIN'
440
+ );
441
+ }
442
+ this.cliCommands.set(alias, { plugin: pluginName, definition });
443
+ }
444
+ }
445
+ }
446
+ }
447
+
448
+ /**
449
+ * Unregister CLI commands from a plugin
450
+ */
451
+ unregisterPluginCLICommands(pluginName: string): void {
452
+ for (const [name, entry] of Array.from(this.cliCommands.entries())) {
453
+ if (entry.plugin === pluginName) {
454
+ this.cliCommands.delete(name);
455
+ }
456
+ }
457
+ }
458
+
459
+ /**
460
+ * Get CLI command definition
461
+ */
462
+ getCLICommand(name: string): CLICommandDefinition | undefined {
463
+ return this.cliCommands.get(name)?.definition;
464
+ }
465
+
466
+ /**
467
+ * Get all CLI commands
468
+ */
469
+ getAllCLICommands(): CLICommandDefinition[] {
470
+ const seen = new Set<CLICommandDefinition>();
471
+ return Array.from(this.cliCommands.values())
472
+ .map((entry) => entry.definition)
473
+ .filter((def) => {
474
+ if (seen.has(def)) return false;
475
+ seen.add(def);
476
+ return true;
477
+ });
478
+ }
479
+
480
+ /**
481
+ * Get CLI commands by plugin
482
+ */
483
+ getCLICommandsByPlugin(pluginName: string): CLICommandDefinition[] {
484
+ const seen = new Set<CLICommandDefinition>();
485
+ return Array.from(this.cliCommands.values())
486
+ .filter((entry) => entry.plugin === pluginName)
487
+ .map((entry) => entry.definition)
488
+ .filter((def) => {
489
+ if (seen.has(def)) return false;
490
+ seen.add(def);
491
+ return true;
492
+ });
493
+ }
494
+
495
+ // =============================================================================
496
+ // Memory Backend Registry
497
+ // =============================================================================
498
+
499
+ /**
500
+ * Register memory backends from a plugin
501
+ */
502
+ registerMemoryBackends(pluginName: string): void {
503
+ const info = this.plugins.get(pluginName);
504
+ if (!info) {
505
+ throw new PluginError(
506
+ `Plugin '${pluginName}' not found`,
507
+ pluginName,
508
+ 'INVALID_PLUGIN'
509
+ );
510
+ }
511
+
512
+ const memoryBackends = info.plugin.registerMemoryBackends?.();
513
+ if (!memoryBackends || memoryBackends.length === 0) {
514
+ return;
515
+ }
516
+
517
+ for (const factory of memoryBackends) {
518
+ if (this.memoryBackends.has(factory.name)) {
519
+ throw new PluginError(
520
+ `Memory backend '${factory.name}' is already registered by plugin '${this.memoryBackends.get(factory.name)?.plugin}'`,
521
+ pluginName,
522
+ 'DUPLICATE_PLUGIN'
523
+ );
524
+ }
525
+
526
+ this.memoryBackends.set(factory.name, { plugin: pluginName, factory });
527
+ }
528
+ }
529
+
530
+ /**
531
+ * Unregister memory backends from a plugin
532
+ */
533
+ unregisterPluginMemoryBackends(pluginName: string): void {
534
+ for (const [name, entry] of Array.from(this.memoryBackends.entries())) {
535
+ if (entry.plugin === pluginName) {
536
+ this.memoryBackends.delete(name);
537
+ }
538
+ }
539
+ }
540
+
541
+ /**
542
+ * Get memory backend factory
543
+ */
544
+ getMemoryBackend(name: string): MemoryBackendFactory | undefined {
545
+ return this.memoryBackends.get(name)?.factory;
546
+ }
547
+
548
+ /**
549
+ * Get all memory backends
550
+ */
551
+ getAllMemoryBackends(): MemoryBackendFactory[] {
552
+ return Array.from(this.memoryBackends.values()).map((entry) => entry.factory);
553
+ }
554
+
555
+ /**
556
+ * Get memory backends by plugin
557
+ */
558
+ getMemoryBackendsByPlugin(pluginName: string): MemoryBackendFactory[] {
559
+ return Array.from(this.memoryBackends.values())
560
+ .filter((entry) => entry.plugin === pluginName)
561
+ .map((entry) => entry.factory);
562
+ }
563
+
564
+ // =============================================================================
565
+ // Bulk Registration
566
+ // =============================================================================
567
+
568
+ /**
569
+ * Register all extension points from a plugin
570
+ */
571
+ registerAllFromPlugin(pluginName: string): void {
572
+ this.registerAgentTypes(pluginName);
573
+ this.registerTaskTypes(pluginName);
574
+ this.registerMCPTools(pluginName);
575
+ this.registerCLICommands(pluginName);
576
+ this.registerMemoryBackends(pluginName);
577
+ this.collectPluginMetrics(pluginName);
578
+ }
579
+
580
+ /**
581
+ * Clear all registrations (for testing)
582
+ */
583
+ clear(): void {
584
+ this.plugins.clear();
585
+ this.agentTypes.clear();
586
+ this.taskTypes.clear();
587
+ this.mcpTools.clear();
588
+ this.cliCommands.clear();
589
+ this.memoryBackends.clear();
590
+ }
591
+ }
592
+
593
+ /**
594
+ * Plugin registry status summary
595
+ */
596
+ export interface PluginRegistryStatus {
597
+ totalPlugins: number;
598
+ states: Record<PluginLifecycleState, number>;
599
+ agentTypesRegistered: number;
600
+ taskTypesRegistered: number;
601
+ mcpToolsRegistered: number;
602
+ cliCommandsRegistered: number;
603
+ memoryBackendsRegistered: number;
604
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Plugins System - ADR-004 Implementation
3
+ *
4
+ * Plugin architecture for extending Claude Flow functionality.
5
+ *
6
+ * @module v3/shared/plugins
7
+ */
8
+
9
+ // Types
10
+ export type {
11
+ PluginConfig,
12
+ PluginContext,
13
+ PluginEvent,
14
+ PluginEventHandler,
15
+ ClaudeFlowPlugin,
16
+ PluginMetadata,
17
+ IPluginRegistry,
18
+ IPluginLoader,
19
+ } from './types.js';
20
+
21
+ // Official Plugins
22
+ export {
23
+ HiveMindPlugin,
24
+ createHiveMindPlugin,
25
+ type HiveMindConfig,
26
+ type CollectiveDecision,
27
+ type EmergentPattern,
28
+ MaestroPlugin,
29
+ createMaestroPlugin,
30
+ type MaestroConfig,
31
+ type WorkflowStep,
32
+ type Workflow,
33
+ type OrchestrationResult,
34
+ } from './official/index.js';