@claude-flow/shared 3.0.0-alpha.1 → 3.0.0-alpha.8

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 (241) hide show
  1. package/.claude-flow/daemon-state.json +135 -0
  2. package/.claude-flow/data/pending-insights.jsonl +2 -0
  3. package/.claude-flow/data/ranked-context.json +5 -0
  4. package/.claude-flow/logs/daemon.log +45 -0
  5. package/.claude-flow/logs/headless/audit_1777379186972_h5un5x_prompt.log +3210 -0
  6. package/.claude-flow/logs/headless/audit_1777379186972_h5un5x_result.log +117 -0
  7. package/.claude-flow/logs/headless/audit_1777379816437_w0eaul_prompt.log +3210 -0
  8. package/.claude-flow/logs/headless/audit_1777379816437_w0eaul_result.log +53 -0
  9. package/.claude-flow/logs/headless/audit_1777380440097_621y8m_prompt.log +3210 -0
  10. package/.claude-flow/logs/headless/audit_1777380440097_621y8m_result.log +75 -0
  11. package/.claude-flow/logs/headless/optimize_1777379306973_an4lmy_prompt.log +3504 -0
  12. package/.claude-flow/logs/headless/optimize_1777379306973_an4lmy_result.log +166 -0
  13. package/.claude-flow/logs/headless/optimize_1777380274732_apxz3s_prompt.log +3504 -0
  14. package/.claude-flow/logs/headless/optimize_1777380274732_apxz3s_result.log +219 -0
  15. package/.claude-flow/logs/headless/testgaps_1777379546969_dvf2a1_prompt.log +3189 -0
  16. package/.claude-flow/logs/headless/testgaps_1777379546969_dvf2a1_result.log +155 -0
  17. package/.claude-flow/metrics/codebase-map.json +11 -0
  18. package/.claude-flow/metrics/consolidation.json +6 -0
  19. package/.claude-flow/sessions/current.json +13 -0
  20. package/.swarm/hnsw.index +0 -0
  21. package/.swarm/hnsw.metadata.json +1 -0
  22. package/.swarm/memory.db +0 -0
  23. package/.swarm/memory.db-shm +0 -0
  24. package/.swarm/memory.db-wal +0 -0
  25. package/.swarm/schema.sql +305 -0
  26. package/dist/core/config/loader.d.ts.map +1 -1
  27. package/dist/core/config/loader.js +17 -1
  28. package/dist/core/config/loader.js.map +1 -1
  29. package/dist/core/config/schema.d.ts +697 -103
  30. package/dist/core/config/schema.d.ts.map +1 -1
  31. package/dist/core/config/schema.js +3 -1
  32. package/dist/core/config/schema.js.map +1 -1
  33. package/dist/events/event-store.d.ts.map +1 -1
  34. package/dist/events/event-store.js +20 -9
  35. package/dist/events/event-store.js.map +1 -1
  36. package/dist/events/example-usage.js +1 -1
  37. package/dist/events/example-usage.js.map +1 -1
  38. package/dist/events/index.d.ts +2 -0
  39. package/dist/events/index.d.ts.map +1 -1
  40. package/dist/events/index.js +2 -0
  41. package/dist/events/index.js.map +1 -1
  42. package/dist/events/rvf-event-log.d.ts +82 -0
  43. package/dist/events/rvf-event-log.d.ts.map +1 -0
  44. package/dist/events/rvf-event-log.js +340 -0
  45. package/dist/events/rvf-event-log.js.map +1 -0
  46. package/dist/hooks/example-usage.js +3 -3
  47. package/dist/hooks/example-usage.js.map +1 -1
  48. package/dist/hooks/executor.d.ts.map +1 -1
  49. package/dist/hooks/executor.js +7 -4
  50. package/dist/hooks/executor.js.map +1 -1
  51. package/dist/hooks/verify-exports.test.js +6 -6
  52. package/dist/hooks/verify-exports.test.js.map +1 -1
  53. package/dist/index.d.ts +1 -0
  54. package/dist/index.d.ts.map +1 -1
  55. package/dist/index.js +4 -0
  56. package/dist/index.js.map +1 -1
  57. package/dist/mcp/server.d.ts.map +1 -1
  58. package/dist/mcp/server.js +3 -6
  59. package/dist/mcp/server.js.map +1 -1
  60. package/dist/mcp/types.d.ts +4 -6
  61. package/dist/mcp/types.d.ts.map +1 -1
  62. package/dist/mcp/types.js.map +1 -1
  63. package/dist/plugins/official/hive-mind-plugin.js +2 -2
  64. package/dist/plugins/official/hive-mind-plugin.js.map +1 -1
  65. package/dist/plugins/official/maestro-plugin.js +3 -3
  66. package/dist/plugins/official/maestro-plugin.js.map +1 -1
  67. package/dist/services/index.d.ts +7 -0
  68. package/dist/services/index.d.ts.map +1 -0
  69. package/dist/services/index.js +7 -0
  70. package/dist/services/index.js.map +1 -0
  71. package/dist/services/v3-progress.service.d.ts +124 -0
  72. package/dist/services/v3-progress.service.d.ts.map +1 -0
  73. package/dist/services/v3-progress.service.js +402 -0
  74. package/dist/services/v3-progress.service.js.map +1 -0
  75. package/package.json +12 -3
  76. package/ruvector.db +0 -0
  77. package/src/core/config/loader.ts +17 -1
  78. package/src/core/config/schema.ts +3 -1
  79. package/src/events/event-store.ts +18 -9
  80. package/src/events/example-usage.ts +1 -1
  81. package/src/events/index.ts +4 -0
  82. package/src/events/rvf-event-log.ts +427 -0
  83. package/src/hooks/example-usage.ts +3 -3
  84. package/src/hooks/executor.ts +7 -5
  85. package/src/hooks/verify-exports.test.ts +6 -6
  86. package/src/index.ts +5 -0
  87. package/src/mcp/server.ts +3 -6
  88. package/src/mcp/types.ts +4 -6
  89. package/src/plugins/official/hive-mind-plugin.ts +2 -2
  90. package/src/plugins/official/maestro-plugin.ts +3 -3
  91. package/src/services/index.ts +16 -0
  92. package/src/services/v3-progress.service.ts +505 -0
  93. package/tmp.json +0 -0
  94. package/tsconfig.tsbuildinfo +1 -1
  95. package/.agentic-flow/intelligence.json +0 -16
  96. package/__tests__/coverage/base.css +0 -224
  97. package/__tests__/coverage/block-navigation.js +0 -87
  98. package/__tests__/coverage/coverage-final.json +0 -50
  99. package/__tests__/coverage/favicon.png +0 -0
  100. package/__tests__/coverage/index.html +0 -326
  101. package/__tests__/coverage/lcov-report/base.css +0 -224
  102. package/__tests__/coverage/lcov-report/block-navigation.js +0 -87
  103. package/__tests__/coverage/lcov-report/favicon.png +0 -0
  104. package/__tests__/coverage/lcov-report/index.html +0 -326
  105. package/__tests__/coverage/lcov-report/prettify.css +0 -1
  106. package/__tests__/coverage/lcov-report/prettify.js +0 -2
  107. package/__tests__/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  108. package/__tests__/coverage/lcov-report/sorter.js +0 -210
  109. package/__tests__/coverage/lcov-report/src/core/config/defaults.ts.html +0 -706
  110. package/__tests__/coverage/lcov-report/src/core/config/index.html +0 -161
  111. package/__tests__/coverage/lcov-report/src/core/config/loader.ts.html +0 -898
  112. package/__tests__/coverage/lcov-report/src/core/config/schema.ts.html +0 -649
  113. package/__tests__/coverage/lcov-report/src/core/config/validator.ts.html +0 -712
  114. package/__tests__/coverage/lcov-report/src/core/event-bus.ts.html +0 -793
  115. package/__tests__/coverage/lcov-report/src/core/index.html +0 -116
  116. package/__tests__/coverage/lcov-report/src/core/interfaces/event.interface.ts.html +0 -886
  117. package/__tests__/coverage/lcov-report/src/core/interfaces/index.html +0 -116
  118. package/__tests__/coverage/lcov-report/src/core/orchestrator/event-coordinator.ts.html +0 -451
  119. package/__tests__/coverage/lcov-report/src/core/orchestrator/health-monitor.ts.html +0 -727
  120. package/__tests__/coverage/lcov-report/src/core/orchestrator/index.html +0 -176
  121. package/__tests__/coverage/lcov-report/src/core/orchestrator/lifecycle-manager.ts.html +0 -874
  122. package/__tests__/coverage/lcov-report/src/core/orchestrator/session-manager.ts.html +0 -922
  123. package/__tests__/coverage/lcov-report/src/core/orchestrator/task-manager.ts.html +0 -1036
  124. package/__tests__/coverage/lcov-report/src/events/domain-events.ts.html +0 -1837
  125. package/__tests__/coverage/lcov-report/src/events/event-store.ts.html +0 -1849
  126. package/__tests__/coverage/lcov-report/src/events/example-usage.ts.html +0 -964
  127. package/__tests__/coverage/lcov-report/src/events/index.html +0 -176
  128. package/__tests__/coverage/lcov-report/src/events/projections.ts.html +0 -1768
  129. package/__tests__/coverage/lcov-report/src/events/state-reconstructor.ts.html +0 -1132
  130. package/__tests__/coverage/lcov-report/src/events.ts.html +0 -1186
  131. package/__tests__/coverage/lcov-report/src/hooks/example-usage.ts.html +0 -1582
  132. package/__tests__/coverage/lcov-report/src/hooks/executor.ts.html +0 -1222
  133. package/__tests__/coverage/lcov-report/src/hooks/index.html +0 -191
  134. package/__tests__/coverage/lcov-report/src/hooks/registry.ts.html +0 -1084
  135. package/__tests__/coverage/lcov-report/src/hooks/safety/bash-safety.ts.html +0 -1897
  136. package/__tests__/coverage/lcov-report/src/hooks/safety/file-organization.ts.html +0 -1504
  137. package/__tests__/coverage/lcov-report/src/hooks/safety/git-commit.ts.html +0 -1954
  138. package/__tests__/coverage/lcov-report/src/hooks/safety/index.html +0 -146
  139. package/__tests__/coverage/lcov-report/src/hooks/session-hooks.ts.html +0 -1762
  140. package/__tests__/coverage/lcov-report/src/hooks/task-hooks.ts.html +0 -1624
  141. package/__tests__/coverage/lcov-report/src/hooks/types.ts.html +0 -1156
  142. package/__tests__/coverage/lcov-report/src/index.html +0 -176
  143. package/__tests__/coverage/lcov-report/src/mcp/connection-pool.ts.html +0 -1399
  144. package/__tests__/coverage/lcov-report/src/mcp/index.html +0 -176
  145. package/__tests__/coverage/lcov-report/src/mcp/server.ts.html +0 -2407
  146. package/__tests__/coverage/lcov-report/src/mcp/session-manager.ts.html +0 -1369
  147. package/__tests__/coverage/lcov-report/src/mcp/tool-registry.ts.html +0 -1783
  148. package/__tests__/coverage/lcov-report/src/mcp/transport/http.ts.html +0 -1756
  149. package/__tests__/coverage/lcov-report/src/mcp/transport/index.html +0 -146
  150. package/__tests__/coverage/lcov-report/src/mcp/transport/stdio.ts.html +0 -1057
  151. package/__tests__/coverage/lcov-report/src/mcp/transport/websocket.ts.html +0 -1537
  152. package/__tests__/coverage/lcov-report/src/mcp/types.ts.html +0 -1780
  153. package/__tests__/coverage/lcov-report/src/plugin-interface.ts.html +0 -2074
  154. package/__tests__/coverage/lcov-report/src/plugin-loader.ts.html +0 -1999
  155. package/__tests__/coverage/lcov-report/src/plugin-registry.ts.html +0 -1897
  156. package/__tests__/coverage/lcov-report/src/plugins/official/hive-mind-plugin.ts.html +0 -1075
  157. package/__tests__/coverage/lcov-report/src/plugins/official/index.html +0 -131
  158. package/__tests__/coverage/lcov-report/src/plugins/official/maestro-plugin.ts.html +0 -1609
  159. package/__tests__/coverage/lcov-report/src/resilience/bulkhead.ts.html +0 -916
  160. package/__tests__/coverage/lcov-report/src/resilience/circuit-breaker.ts.html +0 -1063
  161. package/__tests__/coverage/lcov-report/src/resilience/index.html +0 -161
  162. package/__tests__/coverage/lcov-report/src/resilience/rate-limiter.ts.html +0 -1345
  163. package/__tests__/coverage/lcov-report/src/resilience/retry.ts.html +0 -757
  164. package/__tests__/coverage/lcov-report/src/security/index.html +0 -131
  165. package/__tests__/coverage/lcov-report/src/security/input-validation.ts.html +0 -880
  166. package/__tests__/coverage/lcov-report/src/security/secure-random.ts.html +0 -562
  167. package/__tests__/coverage/lcov-report/src/types/index.html +0 -131
  168. package/__tests__/coverage/lcov-report/src/types/swarm.types.ts.html +0 -850
  169. package/__tests__/coverage/lcov-report/src/types/task.types.ts.html +0 -700
  170. package/__tests__/coverage/lcov-report/src/types.ts.html +0 -1186
  171. package/__tests__/coverage/lcov-report/src/utils/index.html +0 -116
  172. package/__tests__/coverage/lcov-report/src/utils/secure-logger.ts.html +0 -856
  173. package/__tests__/coverage/lcov.info +0 -19877
  174. package/__tests__/coverage/prettify.css +0 -1
  175. package/__tests__/coverage/prettify.js +0 -2
  176. package/__tests__/coverage/sort-arrow-sprite.png +0 -0
  177. package/__tests__/coverage/sorter.js +0 -210
  178. package/__tests__/coverage/src/core/config/defaults.ts.html +0 -706
  179. package/__tests__/coverage/src/core/config/index.html +0 -161
  180. package/__tests__/coverage/src/core/config/loader.ts.html +0 -898
  181. package/__tests__/coverage/src/core/config/schema.ts.html +0 -649
  182. package/__tests__/coverage/src/core/config/validator.ts.html +0 -712
  183. package/__tests__/coverage/src/core/event-bus.ts.html +0 -793
  184. package/__tests__/coverage/src/core/index.html +0 -116
  185. package/__tests__/coverage/src/core/interfaces/event.interface.ts.html +0 -886
  186. package/__tests__/coverage/src/core/interfaces/index.html +0 -116
  187. package/__tests__/coverage/src/core/orchestrator/event-coordinator.ts.html +0 -451
  188. package/__tests__/coverage/src/core/orchestrator/health-monitor.ts.html +0 -727
  189. package/__tests__/coverage/src/core/orchestrator/index.html +0 -176
  190. package/__tests__/coverage/src/core/orchestrator/lifecycle-manager.ts.html +0 -874
  191. package/__tests__/coverage/src/core/orchestrator/session-manager.ts.html +0 -922
  192. package/__tests__/coverage/src/core/orchestrator/task-manager.ts.html +0 -1036
  193. package/__tests__/coverage/src/events/domain-events.ts.html +0 -1837
  194. package/__tests__/coverage/src/events/event-store.ts.html +0 -1849
  195. package/__tests__/coverage/src/events/example-usage.ts.html +0 -964
  196. package/__tests__/coverage/src/events/index.html +0 -176
  197. package/__tests__/coverage/src/events/projections.ts.html +0 -1768
  198. package/__tests__/coverage/src/events/state-reconstructor.ts.html +0 -1132
  199. package/__tests__/coverage/src/events.ts.html +0 -1186
  200. package/__tests__/coverage/src/hooks/example-usage.ts.html +0 -1582
  201. package/__tests__/coverage/src/hooks/executor.ts.html +0 -1222
  202. package/__tests__/coverage/src/hooks/index.html +0 -191
  203. package/__tests__/coverage/src/hooks/registry.ts.html +0 -1084
  204. package/__tests__/coverage/src/hooks/safety/bash-safety.ts.html +0 -1897
  205. package/__tests__/coverage/src/hooks/safety/file-organization.ts.html +0 -1504
  206. package/__tests__/coverage/src/hooks/safety/git-commit.ts.html +0 -1954
  207. package/__tests__/coverage/src/hooks/safety/index.html +0 -146
  208. package/__tests__/coverage/src/hooks/session-hooks.ts.html +0 -1762
  209. package/__tests__/coverage/src/hooks/task-hooks.ts.html +0 -1624
  210. package/__tests__/coverage/src/hooks/types.ts.html +0 -1156
  211. package/__tests__/coverage/src/index.html +0 -176
  212. package/__tests__/coverage/src/mcp/connection-pool.ts.html +0 -1399
  213. package/__tests__/coverage/src/mcp/index.html +0 -176
  214. package/__tests__/coverage/src/mcp/server.ts.html +0 -2407
  215. package/__tests__/coverage/src/mcp/session-manager.ts.html +0 -1369
  216. package/__tests__/coverage/src/mcp/tool-registry.ts.html +0 -1783
  217. package/__tests__/coverage/src/mcp/transport/http.ts.html +0 -1756
  218. package/__tests__/coverage/src/mcp/transport/index.html +0 -146
  219. package/__tests__/coverage/src/mcp/transport/stdio.ts.html +0 -1057
  220. package/__tests__/coverage/src/mcp/transport/websocket.ts.html +0 -1537
  221. package/__tests__/coverage/src/mcp/types.ts.html +0 -1780
  222. package/__tests__/coverage/src/plugin-interface.ts.html +0 -2074
  223. package/__tests__/coverage/src/plugin-loader.ts.html +0 -1999
  224. package/__tests__/coverage/src/plugin-registry.ts.html +0 -1897
  225. package/__tests__/coverage/src/plugins/official/hive-mind-plugin.ts.html +0 -1075
  226. package/__tests__/coverage/src/plugins/official/index.html +0 -131
  227. package/__tests__/coverage/src/plugins/official/maestro-plugin.ts.html +0 -1609
  228. package/__tests__/coverage/src/resilience/bulkhead.ts.html +0 -916
  229. package/__tests__/coverage/src/resilience/circuit-breaker.ts.html +0 -1063
  230. package/__tests__/coverage/src/resilience/index.html +0 -161
  231. package/__tests__/coverage/src/resilience/rate-limiter.ts.html +0 -1345
  232. package/__tests__/coverage/src/resilience/retry.ts.html +0 -757
  233. package/__tests__/coverage/src/security/index.html +0 -131
  234. package/__tests__/coverage/src/security/input-validation.ts.html +0 -880
  235. package/__tests__/coverage/src/security/secure-random.ts.html +0 -562
  236. package/__tests__/coverage/src/types/index.html +0 -131
  237. package/__tests__/coverage/src/types/swarm.types.ts.html +0 -850
  238. package/__tests__/coverage/src/types/task.types.ts.html +0 -700
  239. package/__tests__/coverage/src/types.ts.html +0 -1186
  240. package/__tests__/coverage/src/utils/index.html +0 -116
  241. package/__tests__/coverage/src/utils/secure-logger.ts.html +0 -856
@@ -0,0 +1,3210 @@
1
+ [2026-04-28T12:36:56.443Z] PROMPT
2
+ ============================================================
3
+ Analyze this codebase for security vulnerabilities:
4
+ - Check for hardcoded secrets (API keys, passwords)
5
+ - Identify SQL injection risks
6
+ - Find XSS vulnerabilities
7
+ - Check for insecure dependencies
8
+ - Identify authentication/authorization issues
9
+
10
+ Provide a JSON report with:
11
+ {
12
+ "vulnerabilities": [{ "severity": "high|medium|low", "file": "...", "line": N, "description": "..." }],
13
+ "riskScore": 0-100,
14
+ "recommendations": ["..."]
15
+ }
16
+
17
+ ## Codebase Context
18
+
19
+ --- src/utils/secure-logger.js (truncated) ---
20
+ /**
21
+ * Secure Logger Utility
22
+ *
23
+ * Provides sanitized error logging that strips sensitive information
24
+ * before logging to prevent information disclosure.
25
+ *
26
+ * Security features:
27
+ * - Removes stack traces in production
28
+ * - Sanitizes file paths to prevent internal structure disclosure
29
+ * - Filters sensitive keys from error objects
30
+ * - Truncates long messages to prevent log injection
31
+ *
32
+ * @module @claude-flow/shared/utils/secure-logger
33
+ */
34
+ const DEFAULT_CONFIG = {
35
+ environment: process.env.NODE_ENV || 'development',
36
+ maxMessageLength: 1000,
37
+ includeStackTrace: process.env.NODE_ENV === 'development',
38
+ sensitiveKeys: [
39
+ 'password', 'passwd', 'secret', 'token', 'apikey', 'api_key',
40
+ 'authorization', 'auth', 'credential', 'private', 'key',
41
+ 'session', 'cookie', 'jwt', 'bearer', 'access_token', 'refresh_token',
42
+ ],
43
+ pathPatterns: [
44
+ /\/home\/[^/]+/g, // Unix home directories
45
+ /\/Users\/[^/]+/g, // macOS home directories
46
+ /C:\\Users\\[^\\]+/gi, // Windows user directories
47
+ /\/var\/[^/]+/g, // Var directories
48
+ /\/tmp\/[^/]+/g, // Temp directories
49
+ ],
50
+ };
51
+ // ============================================================================
52
+ // Sanitization Functions
53
+ // ============================================================================
54
+ /**
55
+ * Sanitize a string message
56
+ */
57
+ function sanitizeMessage(message, config) {
58
+ let sanitized = message;
59
+ // Truncate long messages
60
+ if (sanitized.length > config.maxMessageLength) {
61
+ sanitized = sanitized.substring(0, config.maxMessageLength) + '... [truncated]';
62
+ }
63
+ // Sanitize paths
64
+ for (const pattern of config.pathPatterns) {
65
+ sanitized = sanitized.replace(pattern, '[PATH]');
66
+ }
67
+ // Remove potential sensitive data patterns
68
+ sanitized = sanitized.replace(/[a-zA-Z0-9+/]{40,}={0,2}/g, '[REDACTED_KEY]');
69
+ sanitized = sanitized.replace(/Bearer\s+[^\s]+/gi, 'Bearer [REDACTED]');
70
+ sanitized = sanitized.replace(/token[=:]\s*[^\s&]+/gi, 'token=[REDACTED]');
71
+ return sanitized;
72
+ }
73
+ /**
74
+ * Sanitize an error object
75
+ */
76
+ function sanitizeError(error, config) {
77
+ if (error === null || error === undefined) {
78
+ return { message: 'Unknown error' };
79
+ }
80
+ if (typeof error === 'string') {
81
+ return { message: sanitizeMessage(error, config) };
82
+ }
83
+ if (error instanceof Error) {
84
+ const sanitized = {
85
+ name: error.name,
86
+ message: sanitizeMessage(error.message, config),
87
+ };
88
+ // Only include stack in development
89
+ if (config.includeStackTrace && error.stack) {
90
+ sanitized.stack = sanitizeMessage(error.stack, config);
91
+ }
92
+ // Include code if present (common in Node.js errors)
93
+ if ('code' in error) {
94
+ sanitized.code = error.code;
95
+ }
96
+ return sanitized;
97
+ }
98
+ if (typeof error === 'object') {
99
+ return sanitizeObject(error, config);
100
+ }
101
+ return { message: String(error) };
102
+ }
103
+ /**
104
+ * Sanitize a plain object
105
+ */
106
+ function sanitizeObject(obj, config) {
107
+ const sanitized = {};
108
+ for (const [key, value] of Object.entries(obj)) {
109
+ const lowerKey = key.toLowerCase();
110
+ // Skip sensitive keys
111
+ if (config.sensitiveKeys.some(sk => lowerKey.includes(sk))) {
112
+ sanitized[key] = '[REDACTED]';
113
+ continue;
114
+ }
115
+ // Recursively sanitize nested objects
116
+ if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
117
+ sanitized[key] = sanitizeObject(value, config);
118
+ }
119
+ else if (typeof value === 'string') {
120
+ sanitized[key] = sanitizeMessage(value, config);
121
+ }
122
+ else {
123
+ sanitized[key] = value;
124
+ }
125
+ }
126
+ return sanitized;
127
+ }
128
+ // ============================================================================
129
+ // Logger Class
130
+ // ============================================================================
131
+ export class SecureLogger {
132
+ config;
133
+ prefix;
134
+ constructor(prefix = '', config = {}) {
135
+ this.prefix = prefix;
136
+ this.config = { ...DEFAULT_CONFIG, ...config };
137
+ }
138
+ /**
139
+ * Log an info message
140
+ */
141
+ info(message, data) {
142
+ const sanitizedMessage = sanitizeMessage(message, this.config);
143
+ const sanitizedData = data ? sanitizeObject(data, this.config) : undefined;
144
+ if (sanitizedData) {
145
+ console.info(`[INFO]${this.prefix ? ` [${this.prefix}]` : ''} ${sanitizedMessage}`, sanitizedData);
146
+ }
147
+ else {
148
+ console.info(`[INFO]${this.prefix ? ` [${this.prefix}]` : ''} ${sanitizedMessage}`);
149
+ }
150
+ }
151
+ /**
152
+ * Log a warning message
153
+ */
154
+ warn(message, data) {
155
+ const sanitizedMessage = sanitizeMessage(message, this.config);
156
+ const sanitizedData = data ? sanitizeObject(data, this.config) : undefined;
157
+ if (sanitizedData) {
158
+ console.warn(`[WARN]${this.prefix ? ` [${this.prefix}]` : ''} ${sanitizedMessage}`, sanitiz
159
+
160
+ --- __tests__/hooks/bash-safety.test.ts (truncated) ---
161
+ /**
162
+ * V3 Bash Safety Hook Tests
163
+ *
164
+ * Tests for command safety analysis and dangerous command detection.
165
+ *
166
+ * @module v3/shared/hooks/__tests__/bash-safety.test
167
+ */
168
+
169
+ import { describe, it, expect, beforeEach } from 'vitest';
170
+ import {
171
+ createHookRegistry,
172
+ createBashSafetyHook,
173
+ BashSafetyHook,
174
+ HookRegistry,
175
+ } from '../../src/hooks/index.js';
176
+
177
+ describe('BashSafetyHook', () => {
178
+ let registry: HookRegistry;
179
+ let bashSafety: BashSafetyHook;
180
+
181
+ beforeEach(() => {
182
+ registry = createHookRegistry();
183
+ bashSafety = createBashSafetyHook(registry);
184
+ });
185
+
186
+ describe('dangerous command detection', () => {
187
+ it('should block rm -rf / command', async () => {
188
+ const result = await bashSafety.analyze('rm -rf /');
189
+
190
+ expect(result.blocked).toBe(true);
191
+ expect(result.riskLevel).toBe('critical');
192
+ expect(result.risks.length).toBeGreaterThan(0);
193
+ expect(result.risks[0].type).toBe('destructive');
194
+ });
195
+
196
+ it('should block rm -rf /* command', async () => {
197
+ const result = await bashSafety.analyze('rm -rf /*');
198
+
199
+ expect(result.blocked).toBe(true);
200
+ expect(result.riskLevel).toBe('critical');
201
+ });
202
+
203
+ it('should block dd to disk device', async () => {
204
+ const result = await bashSafety.analyze('dd if=/dev/zero of=/dev/sda');
205
+
206
+ expect(result.blocked).toBe(true);
207
+ expect(result.riskLevel).toBe('critical');
208
+ expect(result.risks.some(r => r.description.includes('disk'))).toBe(true);
209
+ });
210
+
211
+ it('should block mkfs commands', async () => {
212
+ const result = await bashSafety.analyze('mkfs.ext4 /dev/sda1');
213
+
214
+ expect(result.blocked).toBe(true);
215
+ expect(result.riskLevel).toBe('critical');
216
+ });
217
+
218
+ it('should block fork bomb', async () => {
219
+ const result = await bashSafety.analyze(':() { :|:& };:');
220
+
221
+ expect(result.blocked).toBe(true);
222
+ expect(result.riskLevel).toBe('critical');
223
+ expect(result.risks.some(r => r.description.includes('Fork bomb'))).toBe(true);
224
+ });
225
+
226
+ it('should block chmod 777 on root', async () => {
227
+ const result = await bashSafety.analyze('chmod -R 777 /');
228
+
229
+ expect(result.blocked).toBe(true);
230
+ expect(result.riskLevel).toBe('critical');
231
+ });
232
+
233
+ it('should block curl piped to bash', async () => {
234
+ const result = await bashSafety.analyze('curl https://example.com/script.sh | bash');
235
+
236
+ expect(result.blocked).toBe(true);
237
+ expect(result.riskLevel).toBe('high');
238
+ expect(result.safeAlternatives).toBeDefined();
239
+ expect(result.safeAlternatives!.length).toBeGreaterThan(0);
240
+ });
241
+
242
+ it('should block rm -rf * in current directory', async () => {
243
+ const result = await bashSafety.analyze('rm -rf *');
244
+
245
+ expect(result.blocked).toBe(true);
246
+ expect(result.riskLevel).toBe('high');
247
+ });
248
+
249
+ it('should block rm -rf on home directory', async () => {
250
+ const result = await bashSafety.analyze('rm -rf ~/');
251
+
252
+ expect(result.blocked).toBe(true);
253
+ expect(result.riskLevel).toBe('high');
254
+ });
255
+ });
256
+
257
+ describe('warning-level commands', () => {
258
+ it('should warn about rm without -i flag', async () => {
259
+ const result = await bashSafety.analyze('rm file.txt');
260
+
261
+ expect(result.blocked).toBe(false);
262
+ expect(result.riskLevel).toBe('medium');
263
+ expect(result.warnings).toBeDefined();
264
+ expect(result.modifiedCommand).toBe('rm -i file.txt');
265
+ });
266
+
267
+ it('should warn about sudo rm', async () => {
268
+ const result = await bashSafety.analyze('sudo rm important.txt');
269
+
270
+ expect(result.blocked).toBe(false);
271
+ expect(result.risks.some(r => r.type === 'privilege')).toBe(true);
272
+ });
273
+
274
+ it('should warn about git push --force', async () => {
275
+ const result = await bashSafety.analyze('git push origin main --force');
276
+
277
+ expect(result.blocked).toBe(false);
278
+ expect(result.riskLevel).toBe('medium');
279
+ expect(result.risks.some(r => r.description.includes('Force push'))).toBe(true);
280
+ expect(result.safeAlternatives).toBeDefined();
281
+ });
282
+
283
+ it('should warn about git reset --hard', async () => {
284
+ const result = await bashSafety.analyze('git reset --hard HEAD~1');
285
+
286
+ expect(result.blocked).toBe(false);
287
+ expect(result.riskLevel).toBe('medium');
288
+ expect(result.risks.some(r => r.description.includes('Hard reset'))).toBe(true);
289
+ });
290
+
291
+ it('should warn about DROP DATABASE', async () => {
292
+ const result = await bashSafety.analyze('mysql -e "DROP DATABASE production"');
293
+
294
+ expect(result.blocked).toBe(false);
295
+ expect(result.riskLevel).toBe('high');
296
+ });
297
+
298
+ it('should warn about kill -9', async () => {
299
+ const result = await bashSafety.analyze('kill -9 12345');
300
+
301
+ expect(result.blocked).toBe(false);
302
+ expect(result.riskLevel).toBe('low');
303
+ });
304
+ });
305
+
306
+ describe('secret detection', () => {
307
+ it('should detect password in command', async () => {
308
+ const result = await bashSafety.analyze('mysql -p password=secret123');
309
+
310
+ expect(result.risks.some(r => r
311
+
312
+ --- __tests__/hooks/file-organization.test.ts (truncated) ---
313
+ /**
314
+ * V3 File Organization Hook Tests
315
+ *
316
+ * Tests for file organization enforcement and formatter recommendations.
317
+ *
318
+ * @module v3/shared/hooks/__tests__/file-organization.test
319
+ */
320
+
321
+ import { describe, it, expect, beforeEach } from 'vitest';
322
+ import {
323
+ createHookRegistry,
324
+ createFileOrganizationHook,
325
+ FileOrganizationHook,
326
+ HookRegistry,
327
+ } from '../../src/hooks/index.js';
328
+
329
+ describe('FileOrganizationHook', () => {
330
+ let registry: HookRegistry;
331
+ let fileOrg: FileOrganizationHook;
332
+
333
+ beforeEach(() => {
334
+ registry = createHookRegistry();
335
+ fileOrg = createFileOrganizationHook(registry);
336
+ });
337
+
338
+ describe('root folder blocking', () => {
339
+ it('should block TypeScript source files in root', async () => {
340
+ const result = await fileOrg.analyze('utils.ts');
341
+
342
+ expect(result.blocked).toBe(true);
343
+ expect(result.blockReason).toBeDefined();
344
+ expect(result.suggestedDirectory).toBe('src/');
345
+ expect(result.suggestedPath).toBe('src/utils.ts');
346
+ });
347
+
348
+ it('should block JavaScript source files in root', async () => {
349
+ const result = await fileOrg.analyze('index.js');
350
+
351
+ expect(result.blocked).toBe(true);
352
+ expect(result.suggestedDirectory).toBe('src/');
353
+ });
354
+
355
+ it('should block TypeScript test files in root', async () => {
356
+ const result = await fileOrg.analyze('utils.test.ts');
357
+
358
+ expect(result.blocked).toBe(true);
359
+ expect(result.suggestedDirectory).toBe('tests/');
360
+ expect(result.suggestedPath).toBe('tests/utils.test.ts');
361
+ });
362
+
363
+ it('should block spec files in root', async () => {
364
+ const result = await fileOrg.analyze('api.spec.ts');
365
+
366
+ expect(result.blocked).toBe(true);
367
+ expect(result.suggestedDirectory).toBe('tests/');
368
+ });
369
+
370
+ it('should block Python files in root', async () => {
371
+ const result = await fileOrg.analyze('main.py');
372
+
373
+ expect(result.blocked).toBe(true);
374
+ expect(result.suggestedDirectory).toBe('src/');
375
+ });
376
+
377
+ it('should block Go files in root', async () => {
378
+ const result = await fileOrg.analyze('main.go');
379
+
380
+ expect(result.blocked).toBe(true);
381
+ expect(result.suggestedDirectory).toBe('cmd/');
382
+ });
383
+
384
+ it('should block shell scripts in root', async () => {
385
+ const result = await fileOrg.analyze('deploy.sh');
386
+
387
+ expect(result.blocked).toBe(true);
388
+ expect(result.suggestedDirectory).toBe('scripts/');
389
+ });
390
+
391
+ it('should block CSS files in root', async () => {
392
+ const result = await fileOrg.analyze('styles.css');
393
+
394
+ expect(result.blocked).toBe(true);
395
+ expect(result.suggestedDirectory).toBe('styles/');
396
+ });
397
+ });
398
+
399
+ describe('allowed root files', () => {
400
+ it('should allow JSON config files in root', async () => {
401
+ const result = await fileOrg.analyze('package.json');
402
+
403
+ expect(result.blocked).toBe(false);
404
+ });
405
+
406
+ it('should allow YAML config files in root', async () => {
407
+ const result = await fileOrg.analyze('config.yaml');
408
+
409
+ expect(result.blocked).toBe(false);
410
+ });
411
+
412
+ it('should allow Markdown files in root', async () => {
413
+ const result = await fileOrg.analyze('README.md');
414
+
415
+ expect(result.blocked).toBe(false);
416
+ });
417
+
418
+ it('should allow environment files in root', async () => {
419
+ const result = await fileOrg.analyze('.env');
420
+
421
+ expect(result.blocked).toBe(false);
422
+ });
423
+
424
+ it('should allow .env.local files in root', async () => {
425
+ const result = await fileOrg.analyze('.env.local');
426
+
427
+ expect(result.blocked).toBe(false);
428
+ });
429
+ });
430
+
431
+ describe('files in correct directories', () => {
432
+ it('should allow TypeScript files in src/', async () => {
433
+ const result = await fileOrg.analyze('src/utils.ts');
434
+
435
+ expect(result.blocked).toBe(false);
436
+ expect(result.issues?.some(i => i.type === 'wrong-directory')).toBeFalsy();
437
+ });
438
+
439
+ it('should allow test files in tests/', async () => {
440
+ const result = await fileOrg.analyze('tests/utils.test.ts');
441
+
442
+ expect(result.blocked).toBe(false);
443
+ });
444
+
445
+ it('should allow test files in __tests__/', async () => {
446
+ const result = await fileOrg.analyze('__tests__/utils.test.ts');
447
+
448
+ expect(result.blocked).toBe(false);
449
+ });
450
+
451
+ it('should allow scripts in scripts/', async () => {
452
+ const result = await fileOrg.analyze('scripts/deploy.sh');
453
+
454
+ expect(result.blocked).toBe(false);
455
+ });
456
+
457
+ it('should allow Go files in cmd/', async () => {
458
+ const result = await fileOrg.analyze('cmd/main.go');
459
+
460
+ expect(result.blocked).toBe(false);
461
+ });
462
+ });
463
+
464
+ describe('files in wrong directories', () => {
465
+ it('should warn about test files in src/', async () => {
466
+ const result = await fileOrg.analyze('src/utils.test.ts');
467
+
468
+ expect(result.blocked).toBe(false);
469
+ expect(result.issues?.some(i => i.type === 'wrong-directory')).toBe(true);
470
+ expect(result.warnings?.length).toBeGreaterThan(0);
471
+ });
472
+
473
+ it('should warn about source files in tests/', async () => {
474
+ const result = await fileO
475
+
476
+ --- __tests__/hooks/git-commit.test.ts (truncated) ---
477
+ /**
478
+ * V3 Git Commit Hook Tests
479
+ *
480
+ * Tests for git commit message formatting and validation.
481
+ *
482
+ * @module v3/shared/hooks/__tests__/git-commit.test
483
+ */
484
+
485
+ import { describe, it, expect, beforeEach } from 'vitest';
486
+ import {
487
+ createHookRegistry,
488
+ createGitCommitHook,
489
+ GitCommitHook,
490
+ HookRegistry,
491
+ } from '../../src/hooks/index.js';
492
+
493
+ describe('GitCommitHook', () => {
494
+ let registry: HookRegistry;
495
+ let gitCommit: GitCommitHook;
496
+
497
+ beforeEach(() => {
498
+ registry = createHookRegistry();
499
+ gitCommit = createGitCommitHook(registry);
500
+ });
501
+
502
+ describe('commit type detection', () => {
503
+ it('should detect feat type from message', async () => {
504
+ const result = await gitCommit.process('Add user authentication');
505
+
506
+ expect(result.commitType).toBe('feat');
507
+ expect(result.modifiedMessage).toMatch(/^feat:/);
508
+ });
509
+
510
+ it('should detect fix type from message', async () => {
511
+ const result = await gitCommit.process('Fix login validation bug');
512
+
513
+ expect(result.commitType).toBe('fix');
514
+ expect(result.modifiedMessage).toMatch(/^fix:/);
515
+ });
516
+
517
+ it('should detect docs type from message', async () => {
518
+ const result = await gitCommit.process('Update README documentation');
519
+
520
+ expect(result.commitType).toBe('docs');
521
+ expect(result.modifiedMessage).toMatch(/^docs:/);
522
+ });
523
+
524
+ it('should detect refactor type from message', async () => {
525
+ const result = await gitCommit.process('Refactor authentication module');
526
+
527
+ expect(result.commitType).toBe('refactor');
528
+ expect(result.modifiedMessage).toMatch(/^refactor:/);
529
+ });
530
+
531
+ it('should detect test type from message', async () => {
532
+ const result = await gitCommit.process('Add unit tests for user service');
533
+
534
+ expect(result.commitType).toBe('test');
535
+ expect(result.modifiedMessage).toMatch(/^test:/);
536
+ });
537
+
538
+ it('should detect perf type from message', async () => {
539
+ const result = await gitCommit.process('Optimize database queries');
540
+
541
+ expect(result.commitType).toBe('perf');
542
+ expect(result.modifiedMessage).toMatch(/^perf:/);
543
+ });
544
+
545
+ it('should detect build type from message', async () => {
546
+ const result = await gitCommit.process('Update webpack configuration');
547
+
548
+ expect(result.commitType).toBe('build');
549
+ expect(result.modifiedMessage).toMatch(/^build:/);
550
+ });
551
+
552
+ it('should detect ci type from message', async () => {
553
+ const result = await gitCommit.process('Update GitHub Actions workflow');
554
+
555
+ expect(result.commitType).toBe('ci');
556
+ expect(result.modifiedMessage).toMatch(/^ci:/);
557
+ });
558
+
559
+ it('should detect chore type from message', async () => {
560
+ const result = await gitCommit.process('Update dependencies');
561
+
562
+ expect(result.commitType).toBe('chore');
563
+ expect(result.modifiedMessage).toMatch(/^chore:/);
564
+ });
565
+
566
+ it('should detect revert type from message', async () => {
567
+ const result = await gitCommit.process('Revert previous commit');
568
+
569
+ expect(result.commitType).toBe('revert');
570
+ expect(result.modifiedMessage).toMatch(/^revert:/);
571
+ });
572
+ });
573
+
574
+ describe('preserving existing prefixes', () => {
575
+ it('should not add duplicate prefix if already present', async () => {
576
+ const result = await gitCommit.process('feat: add user authentication');
577
+
578
+ expect(result.commitType).toBe('feat');
579
+ // Should not have double prefix
580
+ expect(result.modifiedMessage).not.toMatch(/^feat:.*feat:/);
581
+ });
582
+
583
+ it('should detect type from existing prefix', async () => {
584
+ const result = await gitCommit.process('fix(auth): resolve login issue');
585
+
586
+ expect(result.commitType).toBe('fix');
587
+ });
588
+
589
+ it('should handle scoped commits', async () => {
590
+ const result = await gitCommit.process('feat(api): add new endpoint');
591
+
592
+ expect(result.commitType).toBe('feat');
593
+ });
594
+ });
595
+
596
+ describe('ticket extraction', () => {
597
+ it('should extract JIRA ticket from branch name', async () => {
598
+ const result = await gitCommit.process('Add feature', 'feature/ABC-123-new-feature');
599
+
600
+ expect(result.ticketReference).toBe('ABC-123');
601
+ expect(result.modifiedMessage).toContain('Refs: ABC-123');
602
+ });
603
+
604
+ it('should extract GitHub issue from branch name', async () => {
605
+ const result = await gitCommit.process('Fix bug', 'fix/#456-login-bug');
606
+
607
+ expect(result.ticketReference).toBe('#456');
608
+ expect(result.modifiedMessage).toContain('Refs: #456');
609
+ });
610
+
611
+ it('should not duplicate ticket if already in message', async () => {
612
+ const result = await gitCommit.process('Fix ABC-123 bug', 'feature/ABC-123-test');
613
+
614
+ // Should only appear once
615
+ const matches = result.modifiedMessage.match(/ABC-123/g);
616
+ expect(matches).toBeDefined();
617
+ expect(matches!.length).toBeLessThanOrEqual(2);
618
+ });
619
+ });
620
+
621
+ describe('co-author addition', () => {
622
+ it('should add co-author by default', async () => {
623
+ const result = await gitCommit.process('Add feature');
624
+
625
+ expect(res
626
+
627
+ --- __tests__/hooks/index.ts ---
628
+ /**
629
+ * V3 Hooks Tests Index
630
+ *
631
+ * Exports all hook tests for the V3 hooks system.
632
+ *
633
+ * @module v3/shared/hooks/__tests__
634
+ */
635
+
636
+ // Test files are automatically discovered by vitest
637
+ // This file serves as documentation of available tests
638
+
639
+ export const testFiles = [
640
+ './task-hooks.test.ts',
641
+ './session-hooks.test.ts',
642
+ './bash-safety.test.ts',
643
+ './file-organization.test.ts',
644
+ './git-commit.test.ts',
645
+ ];
646
+
647
+ export const testCategories = {
648
+ 'Core Hooks': ['task-hooks.test.ts', 'session-hooks.test.ts'],
649
+ 'Safety Hooks': ['bash-safety.test.ts', 'file-organization.test.ts', 'git-commit.test.ts'],
650
+ };
651
+
652
+
653
+ --- __tests__/hooks/session-hooks.test.ts (truncated) ---
654
+ /**
655
+ * V3 Session Hooks Tests
656
+ *
657
+ * Tests for session-end and session-restore hook functionality.
658
+ *
659
+ * @module v3/shared/hooks/__tests__/session-hooks.test
660
+ */
661
+
662
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
663
+ import {
664
+ createHookRegistry,
665
+ createSessionHooksManager,
666
+ SessionHooksManager,
667
+ HookRegistry,
668
+ HookEvent,
669
+ InMemorySessionStorage,
670
+ } from '../../src/hooks/index.js';
671
+
672
+ describe('SessionHooksManager', () => {
673
+ let registry: HookRegistry;
674
+ let sessionManager: SessionHooksManager;
675
+ let storage: InMemorySessionStorage;
676
+
677
+ beforeEach(() => {
678
+ registry = createHookRegistry();
679
+ storage = new InMemorySessionStorage();
680
+ sessionManager = createSessionHooksManager(registry, storage);
681
+ });
682
+
683
+ describe('session lifecycle hooks', () => {
684
+ it('should register session hooks on creation', () => {
685
+ const startHooks = registry.getHandlers(HookEvent.SessionStart);
686
+ const endHooks = registry.getHandlers(HookEvent.SessionEnd);
687
+ const resumeHooks = registry.getHandlers(HookEvent.SessionResume);
688
+
689
+ expect(startHooks.some(h => h.name === 'session-hooks:start')).toBe(true);
690
+ expect(endHooks.some(h => h.name === 'session-hooks:end')).toBe(true);
691
+ expect(resumeHooks.some(h => h.name === 'session-hooks:resume')).toBe(true);
692
+ });
693
+ });
694
+
695
+ describe('session-end hook', () => {
696
+ it('should end session and return summary', async () => {
697
+ // Simulate session start by triggering tracking
698
+ const context = {
699
+ event: HookEvent.SessionStart,
700
+ timestamp: new Date(),
701
+ session: { id: 'test-session', startTime: new Date() },
702
+ };
703
+ await sessionManager['handleSessionStart'](context);
704
+
705
+ // Wait a moment to ensure duration > 0
706
+ await new Promise(resolve => setTimeout(resolve, 10));
707
+
708
+ const result = await sessionManager.executeSessionEnd();
709
+
710
+ expect(result.success).toBe(true);
711
+ expect(result.duration).toBeGreaterThanOrEqual(0);
712
+ expect(result.summary).toBeDefined();
713
+ expect(result.summary!.tasksExecuted).toBe(0);
714
+ expect(result.summary!.commandsExecuted).toBe(0);
715
+ });
716
+
717
+ it('should persist session state', async () => {
718
+ // Start session
719
+ const startContext = {
720
+ event: HookEvent.SessionStart,
721
+ timestamp: new Date(),
722
+ session: { id: 'persist-session', startTime: new Date() },
723
+ };
724
+ await sessionManager['handleSessionStart'](startContext);
725
+
726
+ const result = await sessionManager.executeSessionEnd();
727
+
728
+ expect(result.persistedState).toBeDefined();
729
+ expect(result.statePath).toBeDefined();
730
+
731
+ // Verify state was saved
732
+ const sessions = await storage.list();
733
+ expect(sessions.length).toBeGreaterThan(0);
734
+ });
735
+
736
+ it('should handle ending session without active session', async () => {
737
+ const result = await sessionManager.executeSessionEnd();
738
+ expect(result.success).toBe(true);
739
+ });
740
+
741
+ it('should reset activity tracking after session end', async () => {
742
+ // Start session
743
+ const context = {
744
+ event: HookEvent.SessionStart,
745
+ timestamp: new Date(),
746
+ session: { id: 'reset-session', startTime: new Date() },
747
+ };
748
+ await sessionManager['handleSessionStart'](context);
749
+
750
+ await sessionManager.executeSessionEnd();
751
+
752
+ expect(sessionManager.getCurrentSessionId()).toBeNull();
753
+ });
754
+ });
755
+
756
+ describe('session-restore hook', () => {
757
+ it('should restore a previous session', async () => {
758
+ // Create and end a session first
759
+ const startContext = {
760
+ event: HookEvent.SessionStart,
761
+ timestamp: new Date(),
762
+ session: { id: 'restore-test', startTime: new Date() },
763
+ };
764
+ await sessionManager['handleSessionStart'](startContext);
765
+ await sessionManager.executeSessionEnd();
766
+
767
+ // Restore the session
768
+ const result = await sessionManager.executeSessionRestore('restore-test');
769
+
770
+ expect(result.success).toBe(true);
771
+ expect(result.restoredState).toBeDefined();
772
+ expect(result.restoredState!.sessionId).toBe('restore-test');
773
+ });
774
+
775
+ it('should restore latest session when no ID specified', async () => {
776
+ // Create and end multiple sessions
777
+ for (const id of ['session-1', 'session-2', 'session-3']) {
778
+ const context = {
779
+ event: HookEvent.SessionStart,
780
+ timestamp: new Date(),
781
+ session: { id, startTime: new Date() },
782
+ };
783
+ await sessionManager['handleSessionStart'](context);
784
+ await sessionManager.executeSessionEnd();
785
+ await new Promise(resolve => setTimeout(resolve, 5));
786
+ }
787
+
788
+ const result = await sessionManager.executeSessionRestore();
789
+
790
+ expect(result.success).toBe(true);
791
+ expect(result.restoredState).toBeDefined();
792
+ });
793
+
794
+ it('should fail gracefully when session not found', async () => {
795
+ const result = await sessionManager.executeSessionRestore('non-existent');
796
+
797
+ expect(result.success).toBe(false);
798
+ expect(result.error).toBeDefin
799
+
800
+ --- __tests__/hooks/task-hooks.test.ts (truncated) ---
801
+ /**
802
+ * V3 Task Hooks Tests
803
+ *
804
+ * Tests for pre-task and post-task hook functionality.
805
+ *
806
+ * @module v3/shared/hooks/__tests__/task-hooks.test
807
+ */
808
+
809
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
810
+ import {
811
+ createHookRegistry,
812
+ createTaskHooksManager,
813
+ TaskHooksManager,
814
+ HookRegistry,
815
+ HookEvent,
816
+ } from '../../src/hooks/index.js';
817
+
818
+ describe('TaskHooksManager', () => {
819
+ let registry: HookRegistry;
820
+ let taskManager: TaskHooksManager;
821
+
822
+ beforeEach(() => {
823
+ registry = createHookRegistry();
824
+ taskManager = createTaskHooksManager(registry);
825
+ });
826
+
827
+ describe('pre-task hook', () => {
828
+ it('should register pre-task hook on creation', () => {
829
+ const hooks = registry.getHandlers(HookEvent.PreTaskExecute);
830
+ expect(hooks.length).toBeGreaterThan(0);
831
+ expect(hooks.some(h => h.name === 'task-hooks:pre-task')).toBe(true);
832
+ });
833
+
834
+ it('should analyze task and suggest agents for coding task', async () => {
835
+ const result = await taskManager.executePreTask(
836
+ 'task-123',
837
+ 'Implement user authentication feature'
838
+ );
839
+
840
+ expect(result.success).toBe(true);
841
+ expect(result.suggestedAgents).toBeDefined();
842
+ expect(result.suggestedAgents!.length).toBeGreaterThan(0);
843
+ expect(result.suggestedAgents![0].type).toBe('coder');
844
+ expect(result.suggestedAgents![0].confidence).toBeGreaterThan(0);
845
+ });
846
+
847
+ it('should suggest security-architect for security tasks', async () => {
848
+ const result = await taskManager.executePreTask(
849
+ 'task-456',
850
+ 'Fix security vulnerability in authentication'
851
+ );
852
+
853
+ expect(result.success).toBe(true);
854
+ expect(result.suggestedAgents).toBeDefined();
855
+ const securityAgent = result.suggestedAgents!.find(a => a.type === 'security-architect');
856
+ expect(securityAgent).toBeDefined();
857
+ });
858
+
859
+ it('should suggest tester for test-related tasks', async () => {
860
+ const result = await taskManager.executePreTask(
861
+ 'task-789',
862
+ 'Write unit tests for user service'
863
+ );
864
+
865
+ expect(result.success).toBe(true);
866
+ expect(result.suggestedAgents).toBeDefined();
867
+ const testerAgent = result.suggestedAgents!.find(a => a.type === 'tester');
868
+ expect(testerAgent).toBeDefined();
869
+ });
870
+
871
+ it('should estimate complexity based on task description', async () => {
872
+ // Simple task
873
+ const simpleResult = await taskManager.executePreTask(
874
+ 'task-simple',
875
+ 'Fix typo in readme'
876
+ );
877
+ expect(simpleResult.complexity).toBe('low');
878
+
879
+ // Complex task
880
+ const complexResult = await taskManager.executePreTask(
881
+ 'task-complex',
882
+ 'Refactor and redesign the entire authentication system with multiple OAuth providers'
883
+ );
884
+ expect(complexResult.complexity).toBe('high');
885
+ });
886
+
887
+ it('should detect risks in task description', async () => {
888
+ const result = await taskManager.executePreTask(
889
+ 'task-risky',
890
+ 'Delete old data from production database'
891
+ );
892
+
893
+ expect(result.risks).toBeDefined();
894
+ expect(result.risks!.length).toBeGreaterThan(0);
895
+ expect(result.risks!.some(r => r.includes('production'))).toBe(true);
896
+ });
897
+
898
+ it('should track active tasks', async () => {
899
+ await taskManager.executePreTask('task-1', 'Task 1');
900
+ await taskManager.executePreTask('task-2', 'Task 2');
901
+
902
+ const activeTasks = taskManager.getActiveTasks();
903
+ expect(activeTasks.size).toBe(2);
904
+ expect(activeTasks.has('task-1')).toBe(true);
905
+ expect(activeTasks.has('task-2')).toBe(true);
906
+ });
907
+
908
+ it('should provide recommendations for high complexity tasks', async () => {
909
+ const result = await taskManager.executePreTask(
910
+ 'task-high-complexity',
911
+ 'Implement complex distributed system with multiple services'
912
+ );
913
+
914
+ expect(result.recommendations).toBeDefined();
915
+ expect(result.recommendations!.length).toBeGreaterThan(0);
916
+ });
917
+ });
918
+
919
+ describe('post-task hook', () => {
920
+ it('should register post-task hook on creation', () => {
921
+ const hooks = registry.getHandlers(HookEvent.PostTaskExecute);
922
+ expect(hooks.length).toBeGreaterThan(0);
923
+ expect(hooks.some(h => h.name === 'task-hooks:post-task')).toBe(true);
924
+ });
925
+
926
+ it('should record successful task outcome', async () => {
927
+ // First start the task
928
+ await taskManager.executePreTask('task-success', 'Test task');
929
+
930
+ // Then complete it
931
+ const result = await taskManager.executePostTask('task-success', true);
932
+
933
+ expect(result.success).toBe(true);
934
+ expect(result.outcome).toBeDefined();
935
+ expect(result.outcome!.success).toBe(true);
936
+ expect(result.outcome!.duration).toBeGreaterThanOrEqual(0);
937
+ });
938
+
939
+ it('should record failed task outcome', async () => {
940
+ await taskManager.executePreTask('task-failed', 'Test task');
941
+
942
+ const result = await taskManager.executePostTask('task-failed', false, {
943
+ error: 'Test failed due to timeout',
944
+ });
945
+
946
+ ex
947
+
948
+ --- src/core/config/defaults.ts ---
949
+ /**
950
+ * V3 Default Configuration Values
951
+ */
952
+
953
+ import type {
954
+ AgentConfig,
955
+ TaskConfig,
956
+ SwarmConfig,
957
+ MemoryConfig,
958
+ MCPServerConfig,
959
+ OrchestratorConfig,
960
+ SystemConfig,
961
+ } from './schema.js';
962
+
963
+ /**
964
+ * Default agent configuration
965
+ */
966
+ export const defaultAgentConfig: Partial<AgentConfig> = {
967
+ capabilities: [],
968
+ maxConcurrentTasks: 5,
969
+ priority: 50,
970
+ retryPolicy: {
971
+ maxRetries: 3,
972
+ backoffMs: 1000,
973
+ backoffMultiplier: 2,
974
+ },
975
+ };
976
+
977
+ /**
978
+ * Default task configuration
979
+ */
980
+ export const defaultTaskConfig: Partial<TaskConfig> = {
981
+ priority: 50,
982
+ metadata: {
983
+ maxRetries: 3,
984
+ },
985
+ };
986
+
987
+ /**
988
+ * Default swarm configuration (core version)
989
+ */
990
+ export const defaultSwarmConfigCore: SwarmConfig = {
991
+ topology: 'hierarchical-mesh',
992
+ maxAgents: 20,
993
+ autoScale: {
994
+ enabled: false,
995
+ minAgents: 1,
996
+ maxAgents: 20,
997
+ scaleUpThreshold: 0.8,
998
+ scaleDownThreshold: 0.3,
999
+ },
1000
+ coordination: {
1001
+ consensusRequired: false,
1002
+ timeoutMs: 10000,
1003
+ retryPolicy: {
1004
+ maxRetries: 3,
1005
+ backoffMs: 500,
1006
+ },
1007
+ },
1008
+ communication: {
1009
+ protocol: 'events',
1010
+ batchSize: 10,
1011
+ flushIntervalMs: 100,
1012
+ },
1013
+ };
1014
+
1015
+ /**
1016
+ * Default memory configuration (hybrid backend - ADR-009)
1017
+ */
1018
+ export const defaultMemoryConfig: MemoryConfig = {
1019
+ type: 'hybrid',
1020
+ path: './data/memory',
1021
+ sqlite: {
1022
+ inMemory: false,
1023
+ wal: true,
1024
+ },
1025
+ agentdb: {
1026
+ dimensions: 1536,
1027
+ indexType: 'hnsw',
1028
+ efConstruction: 200,
1029
+ m: 16,
1030
+ quantization: 'none',
1031
+ },
1032
+ hybrid: {
1033
+ vectorThreshold: 100,
1034
+ },
1035
+ };
1036
+
1037
+ /**
1038
+ * Default MCP server configuration
1039
+ */
1040
+ export const defaultMCPServerConfig: MCPServerConfig = {
1041
+ name: 'claude-flow',
1042
+ version: '3.0.0',
1043
+ transport: {
1044
+ type: 'stdio',
1045
+ },
1046
+ capabilities: {
1047
+ tools: true,
1048
+ resources: true,
1049
+ prompts: true,
1050
+ logging: true,
1051
+ },
1052
+ };
1053
+
1054
+ /**
1055
+ * Default orchestrator configuration
1056
+ */
1057
+ export const defaultOrchestratorConfig: OrchestratorConfig = {
1058
+ session: {
1059
+ persistSessions: true,
1060
+ dataDir: './data',
1061
+ sessionRetentionMs: 3600000, // 1 hour
1062
+ },
1063
+ health: {
1064
+ checkInterval: 30000, // 30 seconds
1065
+ historyLimit: 100,
1066
+ degradedThreshold: 1,
1067
+ unhealthyThreshold: 2,
1068
+ },
1069
+ lifecycle: {
1070
+ maxConcurrentAgents: 20,
1071
+ spawnTimeout: 30000, // 30 seconds
1072
+ terminateTimeout: 10000, // 10 seconds
1073
+ maxSpawnRetries: 3,
1074
+ },
1075
+ };
1076
+
1077
+ /**
1078
+ * Default full system configuration
1079
+ */
1080
+ export const defaultSystemConfig: SystemConfig = {
1081
+ orchestrator: defaultOrchestratorConfig,
1082
+ memory: defaultMemoryConfig,
1083
+ mcp: defaultMCPServerConfig,
1084
+ swarm: defaultSwarmConfigCore,
1085
+ };
1086
+
1087
+ /**
1088
+ * Agent type presets
1089
+ */
1090
+ export const agentTypePresets: Record<string, Partial<AgentConfig>> = {
1091
+ coder: {
1092
+ type: 'coder',
1093
+ capabilities: ['code', 'debug', 'refactor', 'test'],
1094
+ maxConcurrentTasks: 3,
1095
+ priority: 70,
1096
+ },
1097
+ reviewer: {
1098
+ type: 'reviewer',
1099
+ capabilities: ['review', 'analyze', 'suggest'],
1100
+ maxConcurrentTasks: 5,
1101
+ priority: 60,
1102
+ },
1103
+ tester: {
1104
+ type: 'tester',
1105
+ capabilities: ['test', 'validate', 'benchmark'],
1106
+ maxConcurrentTasks: 4,
1107
+ priority: 65,
1108
+ },
1109
+ researcher: {
1110
+ type: 'researcher',
1111
+ capabilities: ['research', 'analyze', 'summarize'],
1112
+ maxConcurrentTasks: 3,
1113
+ priority: 50,
1114
+ },
1115
+ planner: {
1116
+ type: 'planner',
1117
+ capabilities: ['plan', 'organize', 'decompose'],
1118
+ maxConcurrentTasks: 2,
1119
+ priority: 80,
1120
+ },
1121
+ architect: {
1122
+ type: 'architect',
1123
+ capabilities: ['design', 'architecture', 'patterns'],
1124
+ maxConcurrentTasks: 2,
1125
+ priority: 85,
1126
+ },
1127
+ coordinator: {
1128
+ type: 'coordinator',
1129
+ capabilities: ['coordinate', 'delegate', 'monitor'],
1130
+ maxConcurrentTasks: 10,
1131
+ priority: 90,
1132
+ },
1133
+ security: {
1134
+ type: 'security',
1135
+ capabilities: ['audit', 'scan', 'validate', 'secure'],
1136
+ maxConcurrentTasks: 3,
1137
+ priority: 95,
1138
+ },
1139
+ performance: {
1140
+ type: 'performance',
1141
+ capabilities: ['benchmark', 'optimize', 'profile'],
1142
+ maxConcurrentTasks: 2,
1143
+ priority: 70,
1144
+ },
1145
+ };
1146
+
1147
+ /**
1148
+ * Get merged configuration with defaults
1149
+ */
1150
+ export function mergeWithDefaults<T extends Record<string, unknown>>(
1151
+ config: Partial<T>,
1152
+ defaults: T,
1153
+ ): T {
1154
+ return { ...defaults, ...config } as T;
1155
+ }
1156
+
1157
+
1158
+ --- src/core/config/index.ts ---
1159
+ /**
1160
+ * V3 Configuration - Public API
1161
+ */
1162
+
1163
+ // Schemas
1164
+ export * from './schema.js';
1165
+
1166
+ // Validation
1167
+ export * from './validator.js';
1168
+
1169
+ // Defaults
1170
+ export * from './defaults.js';
1171
+
1172
+ // Loader
1173
+ export * from './loader.js';
1174
+
1175
+
1176
+ --- src/core/config/loader.ts (truncated) ---
1177
+ /**
1178
+ * V3 Configuration Loader
1179
+ * Load configuration from various sources
1180
+ */
1181
+
1182
+ import { readFile } from 'fs/promises';
1183
+ import { join, resolve } from 'path';
1184
+ import { existsSync } from 'fs';
1185
+ import type { SystemConfig } from './schema.js';
1186
+ import { validateSystemConfig, type ValidationResult } from './validator.js';
1187
+ import { defaultSystemConfig, mergeWithDefaults } from './defaults.js';
1188
+
1189
+ /**
1190
+ * Configuration source type
1191
+ */
1192
+ export type ConfigSource = 'file' | 'env' | 'default' | 'merged';
1193
+
1194
+ /**
1195
+ * Loaded configuration with metadata
1196
+ */
1197
+ export interface LoadedConfig {
1198
+ config: SystemConfig;
1199
+ source: ConfigSource;
1200
+ path?: string;
1201
+ warnings?: string[];
1202
+ }
1203
+
1204
+ /**
1205
+ * Configuration file names to search for
1206
+ */
1207
+ const CONFIG_FILE_NAMES = [
1208
+ 'claude-flow.config.json',
1209
+ 'claude-flow.config.js',
1210
+ 'claude-flow.json',
1211
+ '.claude-flow.json',
1212
+ ];
1213
+
1214
+ /**
1215
+ * Find configuration file in directory
1216
+ */
1217
+ async function findConfigFile(directory: string): Promise<string | null> {
1218
+ for (const name of CONFIG_FILE_NAMES) {
1219
+ const path = join(directory, name);
1220
+ if (existsSync(path)) {
1221
+ return path;
1222
+ }
1223
+ }
1224
+ return null;
1225
+ }
1226
+
1227
+ /**
1228
+ * Load configuration from JSON file
1229
+ */
1230
+ async function loadJsonConfig(path: string): Promise<unknown> {
1231
+ const content = await readFile(path, 'utf8');
1232
+ return JSON.parse(content);
1233
+ }
1234
+
1235
+ /**
1236
+ * Load configuration from environment variables
1237
+ */
1238
+ function loadEnvConfig(): Partial<SystemConfig> {
1239
+ const config: Partial<SystemConfig> = {};
1240
+
1241
+ // Orchestrator settings
1242
+ if (process.env.CLAUDE_FLOW_MAX_AGENTS) {
1243
+ config.orchestrator = {
1244
+ ...defaultSystemConfig.orchestrator,
1245
+ lifecycle: {
1246
+ ...defaultSystemConfig.orchestrator.lifecycle,
1247
+ maxConcurrentAgents: parseInt(process.env.CLAUDE_FLOW_MAX_AGENTS, 10),
1248
+ },
1249
+ };
1250
+ }
1251
+
1252
+ // Data directory
1253
+ if (process.env.CLAUDE_FLOW_DATA_DIR) {
1254
+ config.orchestrator = {
1255
+ ...config.orchestrator,
1256
+ ...defaultSystemConfig.orchestrator,
1257
+ session: {
1258
+ ...defaultSystemConfig.orchestrator.session,
1259
+ dataDir: process.env.CLAUDE_FLOW_DATA_DIR,
1260
+ },
1261
+ };
1262
+ }
1263
+
1264
+ // Memory type
1265
+ if (process.env.CLAUDE_FLOW_MEMORY_TYPE) {
1266
+ const memoryType = process.env.CLAUDE_FLOW_MEMORY_TYPE as NonNullable<SystemConfig['memory']>['type'];
1267
+ if (['sqlite', 'agentdb', 'hybrid', 'redis', 'memory'].includes(memoryType)) {
1268
+ config.memory = {
1269
+ ...(defaultSystemConfig.memory ?? { type: 'hybrid' }),
1270
+ type: memoryType,
1271
+ };
1272
+ }
1273
+ }
1274
+
1275
+ // MCP transport
1276
+ const defaultMcp = defaultSystemConfig.mcp ?? { name: 'claude-flow', version: '3.0.0', transport: { type: 'stdio' as const } };
1277
+ if (process.env.CLAUDE_FLOW_MCP_TRANSPORT) {
1278
+ const transport = process.env.CLAUDE_FLOW_MCP_TRANSPORT as 'stdio' | 'http' | 'websocket';
1279
+ if (['stdio', 'http', 'websocket'].includes(transport)) {
1280
+ config.mcp = {
1281
+ ...defaultMcp,
1282
+ transport: {
1283
+ ...defaultMcp.transport,
1284
+ type: transport,
1285
+ },
1286
+ };
1287
+ }
1288
+ }
1289
+
1290
+ if (process.env.CLAUDE_FLOW_MCP_PORT) {
1291
+ config.mcp = {
1292
+ ...config.mcp,
1293
+ ...defaultMcp,
1294
+ transport: {
1295
+ ...config.mcp?.transport,
1296
+ ...defaultMcp.transport,
1297
+ port: parseInt(process.env.CLAUDE_FLOW_MCP_PORT, 10),
1298
+ },
1299
+ };
1300
+ }
1301
+
1302
+ // Swarm topology
1303
+ const defaultSwarm = defaultSystemConfig.swarm ?? { topology: 'hierarchical-mesh' as const, maxAgents: 20 };
1304
+ if (process.env.CLAUDE_FLOW_SWARM_TOPOLOGY) {
1305
+ const topology = process.env.CLAUDE_FLOW_SWARM_TOPOLOGY as NonNullable<SystemConfig['swarm']>['topology'];
1306
+ if (['hierarchical', 'mesh', 'ring', 'star', 'adaptive', 'hierarchical-mesh'].includes(topology)) {
1307
+ config.swarm = {
1308
+ ...defaultSwarm,
1309
+ topology,
1310
+ };
1311
+ }
1312
+ }
1313
+
1314
+ return config;
1315
+ }
1316
+
1317
+ /**
1318
+ * Configuration loader class
1319
+ */
1320
+ export class ConfigLoader {
1321
+ private searchPaths: string[] = [];
1322
+
1323
+ constructor(additionalPaths?: string[]) {
1324
+ // Default search paths
1325
+ this.searchPaths = [
1326
+ process.cwd(),
1327
+ resolve(process.cwd(), '..'),
1328
+ resolve(process.env.HOME ?? '', '.claude-flow'),
1329
+ ];
1330
+
1331
+ if (additionalPaths) {
1332
+ this.searchPaths.push(...additionalPaths);
1333
+ }
1334
+ }
1335
+
1336
+ /**
1337
+ * Load configuration from all sources
1338
+ */
1339
+ async load(): Promise<LoadedConfig> {
1340
+ const warnings: string[] = [];
1341
+
1342
+ // Start with defaults
1343
+ let config: SystemConfig = { ...defaultSystemConfig };
1344
+ let source: ConfigSource = 'default';
1345
+ let path: string | undefined;
1346
+
1347
+ // Try to load from file
1348
+ for (const searchPath of this.searchPaths) {
1349
+ const configPath = await findConfigFile(searchPath);
1350
+ if (configPath) {
1351
+ try {
1352
+ const fileConfig = await loadJsonConfig(configPath);
1353
+ const validation = validateSystemConfig(fileConfig);
1354
+
1355
+ if (validation.success) {
1356
+ config = mergeWithDefaults(validation.data!, defaultSystemConfig) as SystemConfig;
1357
+ source = 'file';
1358
+ path = configPath;
1359
+ break;
1360
+ } else {
1361
+
1362
+
1363
+ --- src/core/config/schema.ts (truncated) ---
1364
+ /**
1365
+ * V3 Configuration Schemas
1366
+ * Zod schemas for all configuration types
1367
+ */
1368
+
1369
+ import { z } from 'zod';
1370
+
1371
+ /**
1372
+ * Agent configuration schema
1373
+ */
1374
+ export const AgentConfigSchema = z.object({
1375
+ id: z.string().min(1),
1376
+ name: z.string().min(1),
1377
+ type: z.string().min(1),
1378
+ capabilities: z.array(z.string()).default([]),
1379
+ maxConcurrentTasks: z.number().int().min(1).default(5),
1380
+ priority: z.number().int().min(0).max(100).default(50),
1381
+ timeout: z.number().int().positive().optional(),
1382
+ retryPolicy: z.object({
1383
+ maxRetries: z.number().int().min(0).default(3),
1384
+ backoffMs: z.number().int().positive().default(1000),
1385
+ backoffMultiplier: z.number().positive().default(2),
1386
+ }).optional(),
1387
+ resources: z.object({
1388
+ maxMemoryMb: z.number().int().positive().optional(),
1389
+ maxCpuPercent: z.number().min(0).max(100).optional(),
1390
+ }).optional(),
1391
+ metadata: z.record(z.unknown()).optional(),
1392
+ });
1393
+
1394
+ /**
1395
+ * Task configuration schema
1396
+ */
1397
+ export const TaskConfigSchema = z.object({
1398
+ type: z.string().min(1),
1399
+ description: z.string().min(1),
1400
+ priority: z.number().int().min(0).max(100).default(50),
1401
+ timeout: z.number().int().positive().optional(),
1402
+ assignedAgent: z.string().optional(),
1403
+ input: z.record(z.unknown()).optional(),
1404
+ metadata: z.object({
1405
+ requiredCapabilities: z.array(z.string()).optional(),
1406
+ retryCount: z.number().int().min(0).optional(),
1407
+ maxRetries: z.number().int().min(0).optional(),
1408
+ critical: z.boolean().optional(),
1409
+ parentTaskId: z.string().optional(),
1410
+ childTaskIds: z.array(z.string()).optional(),
1411
+ tags: z.array(z.string()).optional(),
1412
+ }).optional(),
1413
+ });
1414
+
1415
+ /**
1416
+ * Swarm configuration schema
1417
+ */
1418
+ export const SwarmConfigSchema = z.object({
1419
+ topology: z.enum(['hierarchical', 'mesh', 'ring', 'star', 'adaptive', 'hierarchical-mesh']),
1420
+ maxAgents: z.number().int().positive().default(20),
1421
+ autoScale: z.object({
1422
+ enabled: z.boolean().default(false),
1423
+ minAgents: z.number().int().min(0).default(1),
1424
+ maxAgents: z.number().int().positive().default(20),
1425
+ scaleUpThreshold: z.number().min(0).max(1).default(0.8),
1426
+ scaleDownThreshold: z.number().min(0).max(1).default(0.3),
1427
+ }).optional(),
1428
+ coordination: z.object({
1429
+ consensusRequired: z.boolean().default(false),
1430
+ timeoutMs: z.number().int().positive().default(10000),
1431
+ retryPolicy: z.object({
1432
+ maxRetries: z.number().int().min(0).default(3),
1433
+ backoffMs: z.number().int().positive().default(500),
1434
+ }),
1435
+ }).optional(),
1436
+ communication: z.object({
1437
+ protocol: z.enum(['events', 'messages', 'shared-memory']).default('events'),
1438
+ batchSize: z.number().int().positive().default(10),
1439
+ flushIntervalMs: z.number().int().positive().default(100),
1440
+ }).optional(),
1441
+ metadata: z.record(z.unknown()).optional(),
1442
+ });
1443
+
1444
+ /**
1445
+ * Memory configuration schema
1446
+ */
1447
+ export const MemoryConfigSchema = z.object({
1448
+ type: z.enum(['sqlite', 'agentdb', 'hybrid', 'redis', 'memory']).default('hybrid'),
1449
+ path: z.string().optional(),
1450
+ maxSize: z.number().int().positive().optional(),
1451
+ ttlMs: z.number().int().positive().optional(),
1452
+ sqlite: z.object({
1453
+ filename: z.string().optional(),
1454
+ inMemory: z.boolean().default(false),
1455
+ wal: z.boolean().default(true),
1456
+ }).optional(),
1457
+ agentdb: z.object({
1458
+ dimensions: z.number().int().positive().default(1536),
1459
+ indexType: z.enum(['hnsw', 'flat', 'ivf']).default('hnsw'),
1460
+ efConstruction: z.number().int().positive().default(200),
1461
+ m: z.number().int().positive().default(16),
1462
+ quantization: z.enum(['none', 'scalar', 'product']).default('none'),
1463
+ }).optional(),
1464
+ redis: z.object({
1465
+ host: z.string().default('localhost'),
1466
+ port: z.number().int().positive().default(6379),
1467
+ password: z.string().optional(),
1468
+ db: z.number().int().min(0).default(0),
1469
+ keyPrefix: z.string().default('claude-flow:'),
1470
+ }).optional(),
1471
+ hybrid: z.object({
1472
+ vectorThreshold: z.number().int().positive().default(100),
1473
+ }).optional(),
1474
+ });
1475
+
1476
+ /**
1477
+ * MCP server configuration schema
1478
+ */
1479
+ export const MCPServerConfigSchema = z.object({
1480
+ name: z.string().min(1).default('claude-flow'),
1481
+ version: z.string().min(1).default('3.0.0'),
1482
+ transport: z.object({
1483
+ type: z.enum(['stdio', 'http', 'websocket']).default('stdio'),
1484
+ port: z.number().int().positive().optional(),
1485
+ host: z.string().optional(),
1486
+ path: z.string().optional(),
1487
+ }),
1488
+ capabilities: z.object({
1489
+ tools: z.boolean().default(true),
1490
+ resources: z.boolean().default(true),
1491
+ prompts: z.boolean().default(true),
1492
+ logging: z.boolean().default(true),
1493
+ experimental: z.record(z.boolean()).optional(),
1494
+ }).optional(),
1495
+ });
1496
+
1497
+ /**
1498
+ * Orchestrator configuration schema
1499
+ */
1500
+ export const OrchestratorConfigSchema = z.object({
1501
+ session: z.object({
1502
+ persistSessions: z.boolean().default(true),
1503
+ dataDir: z.string().default('./data'),
1504
+ sessionRetentionMs: z.number().int().positive().default(3600000),
1505
+ }),
1506
+ health: z.object({
1507
+ checkInterval: z.number().int().positive().default(30000),
1508
+ historyLimit: z.number().int().positive()
1509
+
1510
+ --- src/core/config/validator.ts ---
1511
+ /**
1512
+ * V3 Configuration Validator
1513
+ * Validation logic using Zod schemas
1514
+ */
1515
+
1516
+ import { z, type ZodError } from 'zod';
1517
+ import {
1518
+ AgentConfigSchema,
1519
+ TaskConfigSchema,
1520
+ SwarmConfigSchema,
1521
+ MemoryConfigSchema,
1522
+ MCPServerConfigSchema,
1523
+ OrchestratorConfigSchema,
1524
+ SystemConfigSchema,
1525
+ type AgentConfig,
1526
+ type TaskConfig,
1527
+ type SwarmConfig,
1528
+ type MemoryConfig,
1529
+ type MCPServerConfig,
1530
+ type OrchestratorConfig,
1531
+ type SystemConfig,
1532
+ } from './schema.js';
1533
+
1534
+ /**
1535
+ * Validation result
1536
+ */
1537
+ export interface ValidationResult<T> {
1538
+ success: boolean;
1539
+ data?: T;
1540
+ errors?: ValidationError[];
1541
+ }
1542
+
1543
+ /**
1544
+ * Validation error
1545
+ */
1546
+ export interface ValidationError {
1547
+ path: string;
1548
+ message: string;
1549
+ code: string;
1550
+ }
1551
+
1552
+ /**
1553
+ * Convert Zod error to validation errors
1554
+ */
1555
+ function zodErrorToValidationErrors(error: ZodError): ValidationError[] {
1556
+ return error.errors.map((e) => ({
1557
+ path: e.path.join('.'),
1558
+ message: e.message,
1559
+ code: e.code,
1560
+ }));
1561
+ }
1562
+
1563
+ /**
1564
+ * Generic validation function
1565
+ * Uses parse + try/catch to get output types with defaults applied
1566
+ */
1567
+ function validate<TInput, TOutput>(
1568
+ schema: z.ZodType<TOutput, z.ZodTypeDef, TInput>,
1569
+ data: unknown
1570
+ ): ValidationResult<TOutput> {
1571
+ try {
1572
+ const parsed = schema.parse(data);
1573
+ return {
1574
+ success: true,
1575
+ data: parsed,
1576
+ };
1577
+ } catch (error) {
1578
+ if (error instanceof z.ZodError) {
1579
+ return {
1580
+ success: false,
1581
+ errors: zodErrorToValidationErrors(error),
1582
+ };
1583
+ }
1584
+ throw error;
1585
+ }
1586
+ }
1587
+
1588
+ /**
1589
+ * Validate agent configuration
1590
+ */
1591
+ export function validateAgentConfig(data: unknown): ValidationResult<AgentConfig> {
1592
+ return validate(AgentConfigSchema, data);
1593
+ }
1594
+
1595
+ /**
1596
+ * Validate task configuration
1597
+ */
1598
+ export function validateTaskConfig(data: unknown): ValidationResult<TaskConfig> {
1599
+ return validate(TaskConfigSchema, data);
1600
+ }
1601
+
1602
+ /**
1603
+ * Validate swarm configuration
1604
+ */
1605
+ export function validateSwarmConfig(data: unknown): ValidationResult<SwarmConfig> {
1606
+ return validate(SwarmConfigSchema, data);
1607
+ }
1608
+
1609
+ /**
1610
+ * Validate memory configuration
1611
+ */
1612
+ export function validateMemoryConfig(data: unknown): ValidationResult<MemoryConfig> {
1613
+ return validate(MemoryConfigSchema, data);
1614
+ }
1615
+
1616
+ /**
1617
+ * Validate MCP server configuration
1618
+ */
1619
+ export function validateMCPServerConfig(data: unknown): ValidationResult<MCPServerConfig> {
1620
+ return validate(MCPServerConfigSchema, data);
1621
+ }
1622
+
1623
+ /**
1624
+ * Validate orchestrator configuration
1625
+ */
1626
+ export function validateOrchestratorConfig(data: unknown): ValidationResult<OrchestratorConfig> {
1627
+ return validate(OrchestratorConfigSchema, data);
1628
+ }
1629
+
1630
+ /**
1631
+ * Validate full system configuration
1632
+ */
1633
+ export function validateSystemConfig(data: unknown): ValidationResult<SystemConfig> {
1634
+ return validate(SystemConfigSchema, data);
1635
+ }
1636
+
1637
+ /**
1638
+ * Configuration validator class
1639
+ */
1640
+ export class ConfigValidator {
1641
+ /**
1642
+ * Validate and throw on error
1643
+ */
1644
+ static validateOrThrow<TInput, TOutput>(
1645
+ schema: z.ZodType<TOutput, z.ZodTypeDef, TInput>,
1646
+ data: unknown,
1647
+ configName: string
1648
+ ): TOutput {
1649
+ const result = validate(schema, data);
1650
+
1651
+ if (!result.success) {
1652
+ const errorMessages = result.errors
1653
+ ?.map((e) => ` - ${e.path}: ${e.message}`)
1654
+ .join('\n');
1655
+ throw new Error(`Invalid ${configName} configuration:\n${errorMessages}`);
1656
+ }
1657
+
1658
+ return result.data!;
1659
+ }
1660
+
1661
+ /**
1662
+ * Validate agent config or throw
1663
+ */
1664
+ static validateAgentOrThrow(data: unknown): AgentConfig {
1665
+ return this.validateOrThrow(AgentConfigSchema, data, 'agent');
1666
+ }
1667
+
1668
+ /**
1669
+ * Validate task config or throw
1670
+ */
1671
+ static validateTaskOrThrow(data: unknown): TaskConfig {
1672
+ return this.validateOrThrow(TaskConfigSchema, data, 'task');
1673
+ }
1674
+
1675
+ /**
1676
+ * Validate swarm config or throw
1677
+ */
1678
+ static validateSwarmOrThrow(data: unknown): SwarmConfig {
1679
+ return this.validateOrThrow(SwarmConfigSchema, data, 'swarm');
1680
+ }
1681
+
1682
+ /**
1683
+ * Validate memory config or throw
1684
+ */
1685
+ static validateMemoryOrThrow(data: unknown): MemoryConfig {
1686
+ return this.validateOrThrow(MemoryConfigSchema, data, 'memory');
1687
+ }
1688
+
1689
+ /**
1690
+ * Validate MCP server config or throw
1691
+ */
1692
+ static validateMCPServerOrThrow(data: unknown): MCPServerConfig {
1693
+ return this.validateOrThrow(MCPServerConfigSchema, data, 'MCP server');
1694
+ }
1695
+
1696
+ /**
1697
+ * Validate orchestrator config or throw
1698
+ */
1699
+ static validateOrchestratorOrThrow(data: unknown): OrchestratorConfig {
1700
+ return this.validateOrThrow(OrchestratorConfigSchema, data, 'orchestrator');
1701
+ }
1702
+
1703
+ /**
1704
+ * Validate system config or throw
1705
+ */
1706
+ static validateSystemOrThrow(data: unknown): SystemConfig {
1707
+ return this.validateOrThrow(SystemConfigSchema, data, 'system');
1708
+ }
1709
+
1710
+ /**
1711
+ * Check if data matches schema
1712
+ */
1713
+ static isValid<TInput, TOutput>(
1714
+ schema: z.ZodType<TOutput, z.ZodTypeDef, TInput>,
1715
+ data: unknown
1716
+ ): boolean {
1717
+ return validate(schema, data).success;
1718
+ }
1719
+ }
1720
+
1721
+
1722
+ --- src/core/event-bus.ts (truncated) ---
1723
+ /**
1724
+ * V3 Event Bus
1725
+ * Core event pub/sub implementation
1726
+ */
1727
+
1728
+ import type {
1729
+ IEvent,
1730
+ IEventBus,
1731
+ IEventCreate,
1732
+ IEventHandler,
1733
+ IEventSubscription,
1734
+ IEventFilter,
1735
+ } from './interfaces/event.interface.js';
1736
+ import { randomBytes } from 'crypto';
1737
+
1738
+ // Secure event ID generation
1739
+ function generateSecureEventId(): string {
1740
+ const timestamp = Date.now().toString(36);
1741
+ const random = randomBytes(12).toString('hex');
1742
+ return `evt_${timestamp}_${random}`;
1743
+ }
1744
+
1745
+ /**
1746
+ * Event subscription implementation
1747
+ */
1748
+ class EventSubscription implements IEventSubscription {
1749
+ private active = true;
1750
+ private paused = false;
1751
+
1752
+ constructor(
1753
+ readonly id: string,
1754
+ readonly filter: IEventFilter,
1755
+ private removeCallback: () => void,
1756
+ ) {}
1757
+
1758
+ unsubscribe(): void {
1759
+ this.active = false;
1760
+ this.removeCallback();
1761
+ }
1762
+
1763
+ pause(): void {
1764
+ this.paused = true;
1765
+ }
1766
+
1767
+ resume(): void {
1768
+ this.paused = false;
1769
+ }
1770
+
1771
+ isActive(): boolean {
1772
+ return this.active && !this.paused;
1773
+ }
1774
+ }
1775
+
1776
+ /**
1777
+ * Event bus implementation
1778
+ */
1779
+ export class EventBus implements IEventBus {
1780
+ private handlers = new Map<string, Set<IEventHandler>>();
1781
+ private subscriptions = new Map<string, { filter: IEventFilter; handler: IEventHandler; subscription: EventSubscription }>();
1782
+ private subscriptionId = 0;
1783
+
1784
+ emit<T = unknown>(type: string, payload: T, options?: Partial<IEventCreate<T>>): void {
1785
+ const event = this.createEvent(type, payload, options);
1786
+ this.dispatchEvent(event);
1787
+ }
1788
+
1789
+ async emitAsync<T = unknown>(type: string, payload: T, options?: Partial<IEventCreate<T>>): Promise<void> {
1790
+ const event = this.createEvent(type, payload, options);
1791
+ await this.dispatchEventAsync(event);
1792
+ }
1793
+
1794
+ on<T = unknown>(type: string, handler: IEventHandler<T>): IEventSubscription {
1795
+ return this.subscribe({ types: [type] }, handler);
1796
+ }
1797
+
1798
+ subscribe<T = unknown>(filter: IEventFilter, handler: IEventHandler<T>): IEventSubscription {
1799
+ const id = `sub_${++this.subscriptionId}`;
1800
+
1801
+ // Register for all matching types
1802
+ const types = filter.types ?? ['*'];
1803
+ for (const type of types) {
1804
+ let handlers = this.handlers.get(type);
1805
+ if (!handlers) {
1806
+ handlers = new Set();
1807
+ this.handlers.set(type, handlers);
1808
+ }
1809
+ handlers.add(handler as IEventHandler);
1810
+ }
1811
+
1812
+ const subscription = new EventSubscription(id, filter, () => {
1813
+ this.removeSubscription(id);
1814
+ });
1815
+
1816
+ this.subscriptions.set(id, { filter, handler: handler as IEventHandler, subscription });
1817
+
1818
+ return subscription;
1819
+ }
1820
+
1821
+ once<T = unknown>(type: string, handler: IEventHandler<T>): IEventSubscription {
1822
+ const wrappedHandler: IEventHandler<T> = async (event) => {
1823
+ subscription.unsubscribe();
1824
+ await handler(event);
1825
+ };
1826
+
1827
+ const subscription = this.on(type, wrappedHandler);
1828
+ return subscription;
1829
+ }
1830
+
1831
+ off(type: string, handler: IEventHandler): void {
1832
+ const handlers = this.handlers.get(type);
1833
+ if (handlers) {
1834
+ handlers.delete(handler);
1835
+ if (handlers.size === 0) {
1836
+ this.handlers.delete(type);
1837
+ }
1838
+ }
1839
+ }
1840
+
1841
+ removeAllListeners(type?: string): void {
1842
+ if (type) {
1843
+ this.handlers.delete(type);
1844
+ } else {
1845
+ this.handlers.clear();
1846
+ }
1847
+ }
1848
+
1849
+ listenerCount(type: string): number {
1850
+ return this.handlers.get(type)?.size ?? 0;
1851
+ }
1852
+
1853
+ eventNames(): string[] {
1854
+ return Array.from(this.handlers.keys());
1855
+ }
1856
+
1857
+ private createEvent<T>(type: string, payload: T, options?: Partial<IEventCreate<T>>): IEvent<T> {
1858
+ return {
1859
+ id: generateSecureEventId(),
1860
+ type,
1861
+ timestamp: new Date(),
1862
+ source: options?.source ?? 'event-bus',
1863
+ payload,
1864
+ priority: options?.priority,
1865
+ correlationId: options?.correlationId,
1866
+ causationId: options?.causationId,
1867
+ metadata: options?.metadata,
1868
+ };
1869
+ }
1870
+
1871
+ private dispatchEvent<T>(event: IEvent<T>): void {
1872
+ // Get handlers for specific type
1873
+ const typeHandlers = this.handlers.get(event.type);
1874
+
1875
+ // Get wildcard handlers
1876
+ const wildcardHandlers = this.handlers.get('*');
1877
+
1878
+ const allHandlers = new Set<IEventHandler>();
1879
+
1880
+ if (typeHandlers) {
1881
+ for (const handler of typeHandlers) {
1882
+ allHandlers.add(handler);
1883
+ }
1884
+ }
1885
+
1886
+ if (wildcardHandlers) {
1887
+ for (const handler of wildcardHandlers) {
1888
+ allHandlers.add(handler);
1889
+ }
1890
+ }
1891
+
1892
+ for (const handler of allHandlers) {
1893
+ try {
1894
+ const result = handler(event);
1895
+ if (result instanceof Promise) {
1896
+ result.catch((error) => {
1897
+ console.error(`Error in async event handler for ${event.type}:`, error);
1898
+ });
1899
+ }
1900
+ } catch (error) {
1901
+ console.error(`Error in event handler for ${event.type}:`, error);
1902
+ }
1903
+ }
1904
+ }
1905
+
1906
+ private async dispatchEventAsync<T>(event: IEvent<T>): Promise<void> {
1907
+ const typeHandlers = this.handlers.get(event.type);
1908
+ const wildcardHandlers = this.handlers.get('*');
1909
+
1910
+ const allHandlers = new Set<IEventHandler>();
1911
+
1912
+ if (typeHandlers) {
1913
+ for (const handler
1914
+
1915
+ --- src/core/index.ts ---
1916
+ /**
1917
+ * V3 Core Module - Public API
1918
+ * Domain-Driven Design with Clean Architecture
1919
+ *
1920
+ * This module provides the core architecture for claude-flow v3:
1921
+ * - Decomposed orchestrator (task, session, health, lifecycle management)
1922
+ * - Event-driven architecture with event bus and coordinator
1923
+ * - Type-safe configuration with Zod validation
1924
+ * - Clean interfaces following DDD principles
1925
+ */
1926
+
1927
+ // Interfaces (Domain contracts)
1928
+ export * from './interfaces/index.js';
1929
+
1930
+ // Event system
1931
+ export { EventBus, createEventBus } from './event-bus.js';
1932
+
1933
+ // Orchestrator components (decomposed)
1934
+ export * from './orchestrator/index.js';
1935
+
1936
+ // Configuration
1937
+ export * from './config/index.js';
1938
+
1939
+
1940
+ --- src/core/interfaces/agent.interface.ts ---
1941
+ /**
1942
+ * V3 Agent Interfaces
1943
+ * Domain-Driven Design - Agent Lifecycle Bounded Context
1944
+ */
1945
+
1946
+ /**
1947
+ * Agent status in the system
1948
+ */
1949
+ export type AgentStatus = 'spawning' | 'active' | 'idle' | 'busy' | 'error' | 'terminated';
1950
+
1951
+ /**
1952
+ * Agent type classification
1953
+ */
1954
+ export type AgentType =
1955
+ | 'coder'
1956
+ | 'reviewer'
1957
+ | 'tester'
1958
+ | 'researcher'
1959
+ | 'planner'
1960
+ | 'architect'
1961
+ | 'coordinator'
1962
+ | 'security'
1963
+ | 'performance'
1964
+ | 'custom';
1965
+
1966
+ /**
1967
+ * Agent capability declaration
1968
+ */
1969
+ export interface IAgentCapability {
1970
+ name: string;
1971
+ level: 'basic' | 'intermediate' | 'advanced' | 'expert';
1972
+ description?: string;
1973
+ }
1974
+
1975
+ /**
1976
+ * Agent configuration for spawning
1977
+ */
1978
+ export interface IAgentConfig {
1979
+ readonly id: string;
1980
+ readonly name: string;
1981
+ readonly type: AgentType | string;
1982
+
1983
+ capabilities: string[];
1984
+ maxConcurrentTasks: number;
1985
+ priority: number;
1986
+
1987
+ timeout?: number;
1988
+ retryPolicy?: {
1989
+ maxRetries: number;
1990
+ backoffMs: number;
1991
+ backoffMultiplier: number;
1992
+ };
1993
+
1994
+ resources?: {
1995
+ maxMemoryMb?: number;
1996
+ maxCpuPercent?: number;
1997
+ };
1998
+
1999
+ metadata?: Record<string, unknown>;
2000
+ }
2001
+
2002
+ /**
2003
+ * Core agent entity
2004
+ */
2005
+ export interface IAgent {
2006
+ readonly id: string;
2007
+ readonly name: string;
2008
+ readonly type: AgentType | string;
2009
+ readonly config: IAgentConfig;
2010
+ readonly createdAt: Date;
2011
+
2012
+ status: AgentStatus;
2013
+ currentTaskCount: number;
2014
+ lastActivity: Date;
2015
+
2016
+ sessionId?: string;
2017
+ terminalId?: string;
2018
+ memoryBankId?: string;
2019
+
2020
+ metrics?: {
2021
+ tasksCompleted: number;
2022
+ tasksFailed: number;
2023
+ avgTaskDuration: number;
2024
+ errorCount: number;
2025
+ uptime: number;
2026
+ };
2027
+
2028
+ health?: {
2029
+ status: 'healthy' | 'degraded' | 'unhealthy';
2030
+ lastCheck: Date;
2031
+ issues?: string[];
2032
+ };
2033
+ }
2034
+
2035
+ /**
2036
+ * Agent session for tracking active work
2037
+ */
2038
+ export interface IAgentSession {
2039
+ readonly id: string;
2040
+ readonly agentId: string;
2041
+ readonly startTime: Date;
2042
+
2043
+ status: 'active' | 'idle' | 'terminated';
2044
+ terminalId: string;
2045
+ memoryBankId: string;
2046
+
2047
+ lastActivity: Date;
2048
+ endTime?: Date;
2049
+
2050
+ metadata?: Record<string, unknown>;
2051
+ }
2052
+
2053
+ /**
2054
+ * Agent pool for managing multiple agents
2055
+ */
2056
+ export interface IAgentPool {
2057
+ /**
2058
+ * Add an agent to the pool
2059
+ */
2060
+ add(agent: IAgent): void;
2061
+
2062
+ /**
2063
+ * Remove an agent from the pool
2064
+ */
2065
+ remove(agentId: string): boolean;
2066
+
2067
+ /**
2068
+ * Get an agent by ID
2069
+ */
2070
+ get(agentId: string): IAgent | undefined;
2071
+
2072
+ /**
2073
+ * Get all agents in the pool
2074
+ */
2075
+ getAll(): IAgent[];
2076
+
2077
+ /**
2078
+ * Get agents by status
2079
+ */
2080
+ getByStatus(status: AgentStatus): IAgent[];
2081
+
2082
+ /**
2083
+ * Get agents by type
2084
+ */
2085
+ getByType(type: AgentType | string): IAgent[];
2086
+
2087
+ /**
2088
+ * Get available agents (can accept more tasks)
2089
+ */
2090
+ getAvailable(): IAgent[];
2091
+
2092
+ /**
2093
+ * Get pool size
2094
+ */
2095
+ size(): number;
2096
+
2097
+ /**
2098
+ * Check if pool has capacity
2099
+ */
2100
+ hasCapacity(maxSize: number): boolean;
2101
+
2102
+ /**
2103
+ * Clear all agents
2104
+ */
2105
+ clear(): void;
2106
+ }
2107
+
2108
+ /**
2109
+ * Agent lifecycle manager interface
2110
+ */
2111
+ export interface IAgentLifecycleManager {
2112
+ /**
2113
+ * Spawn a new agent
2114
+ */
2115
+ spawn(config: IAgentConfig): Promise<IAgent>;
2116
+
2117
+ /**
2118
+ * Spawn multiple agents in parallel
2119
+ */
2120
+ spawnBatch(configs: IAgentConfig[]): Promise<Map<string, IAgent>>;
2121
+
2122
+ /**
2123
+ * Terminate an agent
2124
+ */
2125
+ terminate(agentId: string, reason?: string): Promise<void>;
2126
+
2127
+ /**
2128
+ * Terminate all agents
2129
+ */
2130
+ terminateAll(reason?: string): Promise<void>;
2131
+
2132
+ /**
2133
+ * Restart an agent
2134
+ */
2135
+ restart(agentId: string): Promise<IAgent>;
2136
+
2137
+ /**
2138
+ * Update agent configuration
2139
+ */
2140
+ updateConfig(agentId: string, config: Partial<IAgentConfig>): Promise<void>;
2141
+
2142
+ /**
2143
+ * Get agent by ID
2144
+ */
2145
+ getAgent(agentId: string): IAgent | undefined;
2146
+
2147
+ /**
2148
+ * Get all agents
2149
+ */
2150
+ getAllAgents(): IAgent[];
2151
+
2152
+ /**
2153
+ * Get active agents count
2154
+ */
2155
+ getActiveCount(): number;
2156
+
2157
+ /**
2158
+ * Check agent health
2159
+ */
2160
+ checkHealth(agentId: string): Promise<IAgent['health']>;
2161
+ }
2162
+
2163
+ /**
2164
+ * Agent registry for type definitions
2165
+ */
2166
+ export interface IAgentRegistry {
2167
+ /**
2168
+ * Register an agent type with default config
2169
+ */
2170
+ register(type: string, defaultConfig: Partial<IAgentConfig>): void;
2171
+
2172
+ /**
2173
+ * Unregister an agent type
2174
+ */
2175
+ unregister(type: string): boolean;
2176
+
2177
+ /**
2178
+ * Get default config for a type
2179
+ */
2180
+ getDefaultConfig(type: string): Partial<IAgentConfig> | undefined;
2181
+
2182
+ /**
2183
+ * Get all registered types
2184
+ */
2185
+ getRegisteredTypes(): string[];
2186
+
2187
+ /**
2188
+ * Check if a type is registered
2189
+ */
2190
+ isRegistered(type: string): boolean;
2191
+ }
2192
+
2193
+
2194
+ --- src/core/interfaces/coordinator.interface.ts (truncated) ---
2195
+ /**
2196
+ * V3 Coordinator Interfaces
2197
+ * Domain-Driven Design - Coordination Bounded Context
2198
+ * Aligned with ADR-003 (Single Coordination Engine)
2199
+ */
2200
+
2201
+ import type { ITask, ITaskResult } from './task.interface.js';
2202
+ import type { IAgent, IAgentConfig } from './agent.interface.js';
2203
+
2204
+ /**
2205
+ * Swarm topology types
2206
+ */
2207
+ export type SwarmTopology =
2208
+ | 'hierarchical'
2209
+ | 'mesh'
2210
+ | 'ring'
2211
+ | 'star'
2212
+ | 'adaptive'
2213
+ | 'hierarchical-mesh';
2214
+
2215
+ /**
2216
+ * Coordination status
2217
+ */
2218
+ export type CoordinationStatus =
2219
+ | 'initializing'
2220
+ | 'ready'
2221
+ | 'coordinating'
2222
+ | 'degraded'
2223
+ | 'error'
2224
+ | 'shutdown';
2225
+
2226
+ /**
2227
+ * Swarm configuration
2228
+ */
2229
+ export interface ISwarmConfig {
2230
+ topology: SwarmTopology;
2231
+ maxAgents: number;
2232
+
2233
+ autoScale?: {
2234
+ enabled: boolean;
2235
+ minAgents: number;
2236
+ maxAgents: number;
2237
+ scaleUpThreshold: number;
2238
+ scaleDownThreshold: number;
2239
+ };
2240
+
2241
+ coordination?: {
2242
+ consensusRequired: boolean;
2243
+ timeoutMs: number;
2244
+ retryPolicy: {
2245
+ maxRetries: number;
2246
+ backoffMs: number;
2247
+ };
2248
+ };
2249
+
2250
+ communication?: {
2251
+ protocol: 'events' | 'messages' | 'shared-memory';
2252
+ batchSize: number;
2253
+ flushIntervalMs: number;
2254
+ };
2255
+
2256
+ metadata?: Record<string, unknown>;
2257
+ }
2258
+
2259
+ /**
2260
+ * Swarm state
2261
+ */
2262
+ export interface ISwarmState {
2263
+ readonly id: string;
2264
+ readonly topology: SwarmTopology;
2265
+ readonly createdAt: Date;
2266
+
2267
+ status: CoordinationStatus;
2268
+ agentCount: number;
2269
+ taskCount: number;
2270
+
2271
+ metrics?: {
2272
+ throughput: number;
2273
+ latencyMs: number;
2274
+ successRate: number;
2275
+ resourceUtilization: number;
2276
+ };
2277
+ }
2278
+
2279
+ /**
2280
+ * Coordinator interface - unified coordination engine
2281
+ */
2282
+ export interface ICoordinator {
2283
+ /**
2284
+ * Initialize the coordinator
2285
+ */
2286
+ initialize(): Promise<void>;
2287
+
2288
+ /**
2289
+ * Shutdown the coordinator
2290
+ */
2291
+ shutdown(): Promise<void>;
2292
+
2293
+ /**
2294
+ * Initialize a swarm with configuration
2295
+ */
2296
+ initializeSwarm(config: ISwarmConfig): Promise<ISwarmState>;
2297
+
2298
+ /**
2299
+ * Get swarm state
2300
+ */
2301
+ getSwarmState(): ISwarmState | undefined;
2302
+
2303
+ /**
2304
+ * Assign a task to an agent
2305
+ */
2306
+ assignTask(task: ITask, agentId: string): Promise<void>;
2307
+
2308
+ /**
2309
+ * Get tasks assigned to an agent
2310
+ */
2311
+ getAgentTasks(agentId: string): Promise<ITask[]>;
2312
+
2313
+ /**
2314
+ * Get task count for an agent
2315
+ */
2316
+ getAgentTaskCount(agentId: string): Promise<number>;
2317
+
2318
+ /**
2319
+ * Cancel a task
2320
+ */
2321
+ cancelTask(taskId: string): Promise<void>;
2322
+
2323
+ /**
2324
+ * Report task completion
2325
+ */
2326
+ reportTaskComplete(taskId: string, result: ITaskResult): Promise<void>;
2327
+
2328
+ /**
2329
+ * Get coordination health status
2330
+ */
2331
+ getHealthStatus(): Promise<{ healthy: boolean; error?: string; metrics?: Record<string, number> }>;
2332
+
2333
+ /**
2334
+ * Perform maintenance tasks
2335
+ */
2336
+ performMaintenance(): Promise<void>;
2337
+ }
2338
+
2339
+ /**
2340
+ * Coordination manager interface - higher-level orchestration
2341
+ */
2342
+ export interface ICoordinationManager extends ICoordinator {
2343
+ /**
2344
+ * Register an agent with the coordinator
2345
+ */
2346
+ registerAgent(agent: IAgent): Promise<void>;
2347
+
2348
+ /**
2349
+ * Unregister an agent
2350
+ */
2351
+ unregisterAgent(agentId: string): Promise<void>;
2352
+
2353
+ /**
2354
+ * Get all registered agents
2355
+ */
2356
+ getRegisteredAgents(): IAgent[];
2357
+
2358
+ /**
2359
+ * Request agent consensus on a decision
2360
+ */
2361
+ requestConsensus(topic: string, options: unknown[], timeout?: number): Promise<unknown>;
2362
+
2363
+ /**
2364
+ * Broadcast message to all agents
2365
+ */
2366
+ broadcast(message: unknown): Promise<void>;
2367
+
2368
+ /**
2369
+ * Send message to specific agent
2370
+ */
2371
+ sendToAgent(agentId: string, message: unknown): Promise<void>;
2372
+
2373
+ /**
2374
+ * Acquire a distributed lock
2375
+ */
2376
+ acquireLock(resourceId: string, agentId: string, timeout?: number): Promise<boolean>;
2377
+
2378
+ /**
2379
+ * Release a distributed lock
2380
+ */
2381
+ releaseLock(resourceId: string, agentId: string): Promise<void>;
2382
+
2383
+ /**
2384
+ * Check for deadlocks
2385
+ */
2386
+ detectDeadlocks(): Promise<{ detected: boolean; agents?: string[]; resources?: string[] }>;
2387
+ }
2388
+
2389
+ /**
2390
+ * Health status for components
2391
+ */
2392
+ export interface IHealthStatus {
2393
+ status: 'healthy' | 'degraded' | 'unhealthy';
2394
+ components: Record<string, IComponentHealth>;
2395
+ timestamp: Date;
2396
+ }
2397
+
2398
+ /**
2399
+ * Component health details
2400
+ */
2401
+ export interface IComponentHealth {
2402
+ name: string;
2403
+ status: 'healthy' | 'degraded' | 'unhealthy';
2404
+ lastCheck: Date;
2405
+ error?: string;
2406
+ metrics?: Record<string, number>;
2407
+ }
2408
+
2409
+ /**
2410
+ * Health monitor interface
2411
+ */
2412
+ export interface IHealthMonitor {
2413
+ /**
2414
+ * Start health monitoring
2415
+ */
2416
+ start(): void;
2417
+
2418
+ /**
2419
+ * Stop health monitoring
2420
+ */
2421
+ stop(): void;
2422
+
2423
+ /**
2424
+ * Get current health status
2425
+ */
2426
+ getStatus(): Promise<IHealthStatus>;
2427
+
2428
+ /**
2429
+ * Register a health check
2430
+ */
2431
+ registerCheck(
2432
+ name: string,
2433
+ check: () => Promise<{ healthy: boolean; error?: string; metrics?: Record<string, number> }>
2434
+ ): void;
2435
+
2436
+ /**
2437
+ * Unregister a health check
2438
+ */
2439
+ unregisterCheck(name: string): void;
2440
+
2441
+ /**
2442
+ * Get health history
2443
+ */
2444
+ getHistory(limit?: number): IHealthStatus[];
2445
+
2446
+ /**
2447
+ * Subscribe to health changes
2448
+ */
2449
+ onHealthChange(callback: (status: IHealthStatus) => void): () => void;
2450
+ }
2451
+
2452
+ /**
2453
+ * Metrics co
2454
+
2455
+ --- src/core/interfaces/event.interface.ts (truncated) ---
2456
+ /**
2457
+ * V3 Event Interfaces
2458
+ * Domain-Driven Design - Event Sourcing Pattern (ADR-007)
2459
+ */
2460
+
2461
+ /**
2462
+ * Event priority levels
2463
+ */
2464
+ export type EventPriority = 'critical' | 'high' | 'normal' | 'low';
2465
+
2466
+ /**
2467
+ * Core event structure
2468
+ */
2469
+ export interface IEvent<T = unknown> {
2470
+ readonly id: string;
2471
+ readonly type: string;
2472
+ readonly timestamp: Date;
2473
+ readonly source: string;
2474
+
2475
+ payload: T;
2476
+ priority?: EventPriority;
2477
+ correlationId?: string;
2478
+ causationId?: string;
2479
+
2480
+ metadata?: {
2481
+ version?: number;
2482
+ userId?: string;
2483
+ sessionId?: string;
2484
+ [key: string]: unknown;
2485
+ };
2486
+ }
2487
+
2488
+ /**
2489
+ * Event creation parameters
2490
+ */
2491
+ export interface IEventCreate<T = unknown> {
2492
+ type: string;
2493
+ payload: T;
2494
+ source?: string;
2495
+ priority?: EventPriority;
2496
+ correlationId?: string;
2497
+ causationId?: string;
2498
+ metadata?: IEvent['metadata'];
2499
+ }
2500
+
2501
+ /**
2502
+ * Event handler function type
2503
+ */
2504
+ export type IEventHandler<T = unknown> = (event: IEvent<T>) => void | Promise<void>;
2505
+
2506
+ /**
2507
+ * Event filter for subscriptions
2508
+ */
2509
+ export interface IEventFilter {
2510
+ types?: string[];
2511
+ sources?: string[];
2512
+ priority?: EventPriority[];
2513
+ correlationId?: string;
2514
+ }
2515
+
2516
+ /**
2517
+ * Event subscription handle
2518
+ */
2519
+ export interface IEventSubscription {
2520
+ readonly id: string;
2521
+ readonly filter: IEventFilter;
2522
+
2523
+ /**
2524
+ * Unsubscribe from events
2525
+ */
2526
+ unsubscribe(): void;
2527
+
2528
+ /**
2529
+ * Pause subscription
2530
+ */
2531
+ pause(): void;
2532
+
2533
+ /**
2534
+ * Resume subscription
2535
+ */
2536
+ resume(): void;
2537
+
2538
+ /**
2539
+ * Check if subscription is active
2540
+ */
2541
+ isActive(): boolean;
2542
+ }
2543
+
2544
+ /**
2545
+ * Event bus interface for pub/sub communication
2546
+ */
2547
+ export interface IEventBus {
2548
+ /**
2549
+ * Emit an event to all subscribers
2550
+ */
2551
+ emit<T = unknown>(type: string, payload: T, options?: Partial<IEventCreate<T>>): void;
2552
+
2553
+ /**
2554
+ * Emit an event and wait for all handlers
2555
+ */
2556
+ emitAsync<T = unknown>(type: string, payload: T, options?: Partial<IEventCreate<T>>): Promise<void>;
2557
+
2558
+ /**
2559
+ * Subscribe to events matching a type pattern
2560
+ */
2561
+ on<T = unknown>(type: string, handler: IEventHandler<T>): IEventSubscription;
2562
+
2563
+ /**
2564
+ * Subscribe to events with filter
2565
+ */
2566
+ subscribe<T = unknown>(filter: IEventFilter, handler: IEventHandler<T>): IEventSubscription;
2567
+
2568
+ /**
2569
+ * Subscribe to a single event occurrence
2570
+ */
2571
+ once<T = unknown>(type: string, handler: IEventHandler<T>): IEventSubscription;
2572
+
2573
+ /**
2574
+ * Remove a specific handler
2575
+ */
2576
+ off(type: string, handler: IEventHandler): void;
2577
+
2578
+ /**
2579
+ * Remove all handlers for a type
2580
+ */
2581
+ removeAllListeners(type?: string): void;
2582
+
2583
+ /**
2584
+ * Get count of listeners for a type
2585
+ */
2586
+ listenerCount(type: string): number;
2587
+
2588
+ /**
2589
+ * Get all event types with active listeners
2590
+ */
2591
+ eventNames(): string[];
2592
+ }
2593
+
2594
+ /**
2595
+ * System event types enumeration
2596
+ */
2597
+ export const SystemEventTypes = {
2598
+ // System lifecycle
2599
+ SYSTEM_READY: 'system:ready',
2600
+ SYSTEM_SHUTDOWN: 'system:shutdown',
2601
+ SYSTEM_ERROR: 'system:error',
2602
+ SYSTEM_HEALTHCHECK: 'system:healthcheck',
2603
+
2604
+ // Agent lifecycle
2605
+ AGENT_SPAWNED: 'agent:spawned',
2606
+ AGENT_TERMINATED: 'agent:terminated',
2607
+ AGENT_ERROR: 'agent:error',
2608
+ AGENT_IDLE: 'agent:idle',
2609
+ AGENT_BUSY: 'agent:busy',
2610
+ AGENT_HEALTH_CHANGED: 'agent:health:changed',
2611
+
2612
+ // Task lifecycle
2613
+ TASK_CREATED: 'task:created',
2614
+ TASK_ASSIGNED: 'task:assigned',
2615
+ TASK_STARTED: 'task:started',
2616
+ TASK_COMPLETED: 'task:completed',
2617
+ TASK_FAILED: 'task:failed',
2618
+ TASK_CANCELLED: 'task:cancelled',
2619
+ TASK_TIMEOUT: 'task:timeout',
2620
+ TASK_RETRY: 'task:retry',
2621
+
2622
+ // Session lifecycle
2623
+ SESSION_CREATED: 'session:created',
2624
+ SESSION_RESTORED: 'session:restored',
2625
+ SESSION_TERMINATED: 'session:terminated',
2626
+ SESSION_PERSISTED: 'session:persisted',
2627
+
2628
+ // Memory events
2629
+ MEMORY_STORED: 'memory:stored',
2630
+ MEMORY_RETRIEVED: 'memory:retrieved',
2631
+ MEMORY_CLEARED: 'memory:cleared',
2632
+
2633
+ // Coordination events
2634
+ COORDINATION_STARTED: 'coordination:started',
2635
+ COORDINATION_COMPLETED: 'coordination:completed',
2636
+ DEADLOCK_DETECTED: 'coordination:deadlock',
2637
+
2638
+ // Metrics events
2639
+ METRICS_COLLECTED: 'metrics:collected',
2640
+ } as const;
2641
+
2642
+ export type SystemEventType = typeof SystemEventTypes[keyof typeof SystemEventTypes];
2643
+
2644
+ /**
2645
+ * Event store interface for event sourcing
2646
+ */
2647
+ export interface IEventStore {
2648
+ /**
2649
+ * Append an event to the store
2650
+ */
2651
+ append(event: IEvent): Promise<void>;
2652
+
2653
+ /**
2654
+ * Get events by aggregate ID
2655
+ */
2656
+ getByAggregateId(aggregateId: string, fromVersion?: number): Promise<IEvent[]>;
2657
+
2658
+ /**
2659
+ * Get events by type
2660
+ */
2661
+ getByType(type: string, options?: { limit?: number; offset?: number }): Promise<IEvent[]>;
2662
+
2663
+ /**
2664
+ * Get events in time range
2665
+ */
2666
+ getByTimeRange(start: Date, end: Date): Promise<IEvent[]>;
2667
+
2668
+ /**
2669
+ * Get events by correlation ID
2670
+ */
2671
+ getByCorrelationId(correlationId: string): Promise<IEvent[]>;
2672
+
2673
+ /**
2674
+ * Get all events (paginated)
2675
+ */
2676
+ getAll(options?: { limit?: number; offset?: number }): Promise<IEvent[]>;
2677
+
2678
+ /**
2679
+ * Get event count
2680
+ */
2681
+ count(filter?: IEventFilter): Promise<number>;
2682
+
2683
+ /**
2684
+ * Clear old events
2685
+ */
2686
+ prune(olderThan: Date): P
2687
+
2688
+ --- src/core/interfaces/index.ts ---
2689
+ /**
2690
+ * V3 Core Interfaces - Public API
2691
+ * Domain-Driven Design with Clean Architecture
2692
+ */
2693
+
2694
+ // Task interfaces
2695
+ export * from './task.interface.js';
2696
+
2697
+ // Agent interfaces
2698
+ export * from './agent.interface.js';
2699
+
2700
+ // Event interfaces
2701
+ export * from './event.interface.js';
2702
+
2703
+ // Memory interfaces
2704
+ export * from './memory.interface.js';
2705
+
2706
+ // Coordinator interfaces
2707
+ export * from './coordinator.interface.js';
2708
+
2709
+
2710
+ --- src/core/interfaces/memory.interface.ts (truncated) ---
2711
+ /**
2712
+ * V3 Memory Interfaces
2713
+ * Domain-Driven Design - Memory Management Bounded Context
2714
+ * Aligned with ADR-006 (Unified Memory Service) and ADR-009 (Hybrid Memory Backend)
2715
+ */
2716
+
2717
+ /**
2718
+ * Memory entry types
2719
+ */
2720
+ export type MemoryType = 'session' | 'persistent' | 'vector' | 'cache' | 'pattern';
2721
+
2722
+ /**
2723
+ * Memory entry structure
2724
+ */
2725
+ export interface IMemoryEntry {
2726
+ readonly id: string;
2727
+ readonly key: string;
2728
+ readonly type: MemoryType;
2729
+ readonly createdAt: Date;
2730
+
2731
+ value: unknown;
2732
+ updatedAt: Date;
2733
+ expiresAt?: Date;
2734
+
2735
+ metadata?: {
2736
+ source?: string;
2737
+ agentId?: string;
2738
+ sessionId?: string;
2739
+ version?: number;
2740
+ tags?: string[];
2741
+ embedding?: number[];
2742
+ [key: string]: unknown;
2743
+ };
2744
+ }
2745
+
2746
+ /**
2747
+ * Memory entry creation parameters
2748
+ */
2749
+ export interface IMemoryEntryCreate {
2750
+ key: string;
2751
+ value: unknown;
2752
+ type?: MemoryType;
2753
+ expiresAt?: Date;
2754
+ ttlMs?: number;
2755
+ metadata?: IMemoryEntry['metadata'];
2756
+ }
2757
+
2758
+ /**
2759
+ * Vector search parameters
2760
+ */
2761
+ export interface IVectorSearchParams {
2762
+ embedding: number[];
2763
+ k?: number;
2764
+ threshold?: number;
2765
+ filter?: {
2766
+ type?: MemoryType;
2767
+ tags?: string[];
2768
+ agentId?: string;
2769
+ };
2770
+ }
2771
+
2772
+ /**
2773
+ * Vector search result
2774
+ */
2775
+ export interface IVectorSearchResult {
2776
+ entry: IMemoryEntry;
2777
+ score: number;
2778
+ distance: number;
2779
+ }
2780
+
2781
+ /**
2782
+ * Memory backend interface for storage operations
2783
+ */
2784
+ export interface IMemoryBackend {
2785
+ /**
2786
+ * Initialize the backend
2787
+ */
2788
+ initialize(): Promise<void>;
2789
+
2790
+ /**
2791
+ * Shutdown the backend
2792
+ */
2793
+ shutdown(): Promise<void>;
2794
+
2795
+ /**
2796
+ * Store a memory entry
2797
+ */
2798
+ store(entry: IMemoryEntryCreate): Promise<IMemoryEntry>;
2799
+
2800
+ /**
2801
+ * Retrieve a memory entry by key
2802
+ */
2803
+ retrieve(key: string): Promise<IMemoryEntry | undefined>;
2804
+
2805
+ /**
2806
+ * Retrieve by ID
2807
+ */
2808
+ retrieveById(id: string): Promise<IMemoryEntry | undefined>;
2809
+
2810
+ /**
2811
+ * Update a memory entry
2812
+ */
2813
+ update(key: string, value: unknown, metadata?: Partial<IMemoryEntry['metadata']>): Promise<IMemoryEntry | undefined>;
2814
+
2815
+ /**
2816
+ * Delete a memory entry
2817
+ */
2818
+ delete(key: string): Promise<boolean>;
2819
+
2820
+ /**
2821
+ * Check if a key exists
2822
+ */
2823
+ exists(key: string): Promise<boolean>;
2824
+
2825
+ /**
2826
+ * List all keys matching a pattern
2827
+ */
2828
+ keys(pattern?: string): Promise<string[]>;
2829
+
2830
+ /**
2831
+ * Get all entries matching filter
2832
+ */
2833
+ list(filter?: { type?: MemoryType; tags?: string[] }): Promise<IMemoryEntry[]>;
2834
+
2835
+ /**
2836
+ * Clear all entries
2837
+ */
2838
+ clear(): Promise<void>;
2839
+
2840
+ /**
2841
+ * Get entry count
2842
+ */
2843
+ count(): Promise<number>;
2844
+
2845
+ /**
2846
+ * Prune expired entries
2847
+ */
2848
+ prune(): Promise<number>;
2849
+
2850
+ /**
2851
+ * Get health status
2852
+ */
2853
+ getHealthStatus(): Promise<{ healthy: boolean; error?: string; metrics?: Record<string, number> }>;
2854
+ }
2855
+
2856
+ /**
2857
+ * Vector memory backend for similarity search
2858
+ */
2859
+ export interface IVectorMemoryBackend extends IMemoryBackend {
2860
+ /**
2861
+ * Store with embedding
2862
+ */
2863
+ storeVector(entry: IMemoryEntryCreate & { embedding: number[] }): Promise<IMemoryEntry>;
2864
+
2865
+ /**
2866
+ * Search by vector similarity
2867
+ */
2868
+ search(params: IVectorSearchParams): Promise<IVectorSearchResult[]>;
2869
+
2870
+ /**
2871
+ * Update embedding for an entry
2872
+ */
2873
+ updateEmbedding(key: string, embedding: number[]): Promise<boolean>;
2874
+
2875
+ /**
2876
+ * Build or rebuild index
2877
+ */
2878
+ buildIndex(): Promise<void>;
2879
+
2880
+ /**
2881
+ * Get index statistics
2882
+ */
2883
+ getIndexStats(): Promise<{
2884
+ vectorCount: number;
2885
+ dimensions: number;
2886
+ indexType: string;
2887
+ memoryUsageMb: number;
2888
+ }>;
2889
+ }
2890
+
2891
+ /**
2892
+ * Memory bank for agent-specific storage
2893
+ */
2894
+ export interface IMemoryBank {
2895
+ readonly id: string;
2896
+ readonly agentId: string;
2897
+ readonly createdAt: Date;
2898
+
2899
+ /**
2900
+ * Store in bank
2901
+ */
2902
+ store(key: string, value: unknown, options?: Partial<IMemoryEntryCreate>): Promise<IMemoryEntry>;
2903
+
2904
+ /**
2905
+ * Retrieve from bank
2906
+ */
2907
+ retrieve(key: string): Promise<IMemoryEntry | undefined>;
2908
+
2909
+ /**
2910
+ * Delete from bank
2911
+ */
2912
+ delete(key: string): Promise<boolean>;
2913
+
2914
+ /**
2915
+ * List all entries in bank
2916
+ */
2917
+ list(): Promise<IMemoryEntry[]>;
2918
+
2919
+ /**
2920
+ * Clear all entries in bank
2921
+ */
2922
+ clear(): Promise<void>;
2923
+
2924
+ /**
2925
+ * Get bank size
2926
+ */
2927
+ size(): Promise<number>;
2928
+
2929
+ /**
2930
+ * Close the bank
2931
+ */
2932
+ close(): Promise<void>;
2933
+ }
2934
+
2935
+ /**
2936
+ * Memory manager interface
2937
+ */
2938
+ export interface IMemoryManager {
2939
+ /**
2940
+ * Initialize the manager
2941
+ */
2942
+ initialize(): Promise<void>;
2943
+
2944
+ /**
2945
+ * Shutdown the manager
2946
+ */
2947
+ shutdown(): Promise<void>;
2948
+
2949
+ /**
2950
+ * Create a memory bank for an agent
2951
+ */
2952
+ createBank(agentId: string): Promise<string>;
2953
+
2954
+ /**
2955
+ * Get a memory bank
2956
+ */
2957
+ getBank(bankId: string): IMemoryBank | undefined;
2958
+
2959
+ /**
2960
+ * Close a memory bank
2961
+ */
2962
+ closeBank(bankId: string): Promise<void>;
2963
+
2964
+ /**
2965
+ * Store in global memory
2966
+ */
2967
+ store(entry: IMemoryEntryCreate): Promise<IMemoryEntry>;
2968
+
2969
+ /**
2970
+ * Retrieve from global memory
2971
+ */
2972
+ retrieve(key: string): Promise<IMemoryEntry | undefined>;
2973
+
2974
+ /**
2975
+ * Search vectors (if vector backend available)
2976
+ */
2977
+ searchVectors?(params: IVectorSearchParams): Promise<IVectorSearchResult[]>;
2978
+
2979
+ /**
2980
+
2981
+
2982
+ --- src/core/interfaces/task.interface.ts ---
2983
+ /**
2984
+ * V3 Task Interfaces
2985
+ * Domain-Driven Design - Task Bounded Context
2986
+ */
2987
+
2988
+ /**
2989
+ * Task priority levels
2990
+ */
2991
+ export type TaskPriority = 'critical' | 'high' | 'medium' | 'low';
2992
+
2993
+ /**
2994
+ * Task status throughout its lifecycle
2995
+ */
2996
+ export type TaskStatus =
2997
+ | 'pending'
2998
+ | 'queued'
2999
+ | 'assigned'
3000
+ | 'running'
3001
+ | 'completed'
3002
+ | 'failed'
3003
+ | 'cancelled'
3004
+ | 'timeout';
3005
+
3006
+ /**
3007
+ * Core task entity
3008
+ */
3009
+ export interface ITask {
3010
+ readonly id: string;
3011
+ readonly type: string;
3012
+ readonly description: string;
3013
+ readonly priority: number;
3014
+ readonly createdAt: Date;
3015
+
3016
+ status: TaskStatus;
3017
+ assignedAgent?: string;
3018
+ startedAt?: Date;
3019
+ completedAt?: Date;
3020
+ timeout?: number;
3021
+
3022
+ input?: Record<string, unknown>;
3023
+ output?: Record<string, unknown>;
3024
+ error?: Error;
3025
+
3026
+ metadata?: {
3027
+ requiredCapabilities?: string[];
3028
+ retryCount?: number;
3029
+ maxRetries?: number;
3030
+ critical?: boolean;
3031
+ parentTaskId?: string;
3032
+ childTaskIds?: string[];
3033
+ tags?: string[];
3034
+ [key: string]: unknown;
3035
+ };
3036
+ }
3037
+
3038
+ /**
3039
+ * Task creation parameters
3040
+ */
3041
+ export interface ITaskCreate {
3042
+ type: string;
3043
+ description: string;
3044
+ priority?: number;
3045
+ timeout?: number;
3046
+ assignedAgent?: string;
3047
+ input?: Record<string, unknown>;
3048
+ metadata?: ITask['metadata'];
3049
+ }
3050
+
3051
+ /**
3052
+ * Task result after completion
3053
+ */
3054
+ export interface ITaskResult {
3055
+ taskId: string;
3056
+ success: boolean;
3057
+ output?: Record<string, unknown>;
3058
+ error?: Error;
3059
+ duration: number;
3060
+ agentId?: string;
3061
+ metrics?: {
3062
+ tokensUsed?: number;
3063
+ memoryPeakMb?: number;
3064
+ retryCount?: number;
3065
+ };
3066
+ }
3067
+
3068
+ /**
3069
+ * Task queue interface for managing task ordering and processing
3070
+ */
3071
+ export interface ITaskQueue {
3072
+ /**
3073
+ * Add a task to the queue
3074
+ */
3075
+ enqueue(task: ITask): Promise<void>;
3076
+
3077
+ /**
3078
+ * Remove and return the highest priority task
3079
+ */
3080
+ dequeue(): Promise<ITask | undefined>;
3081
+
3082
+ /**
3083
+ * Peek at the next task without removing it
3084
+ */
3085
+ peek(): Promise<ITask | undefined>;
3086
+
3087
+ /**
3088
+ * Get the current queue size
3089
+ */
3090
+ size(): number;
3091
+
3092
+ /**
3093
+ * Check if the queue is empty
3094
+ */
3095
+ isEmpty(): boolean;
3096
+
3097
+ /**
3098
+ * Clear all tasks from the queue
3099
+ */
3100
+ clear(): Promise<void>;
3101
+
3102
+ /**
3103
+ * Get all queued tasks (for inspection)
3104
+ */
3105
+ getAll(): Promise<ITask[]>;
3106
+
3107
+ /**
3108
+ * Remove a specific task by ID
3109
+ */
3110
+ remove(taskId: string): Promise<boolean>;
3111
+
3112
+ /**
3113
+ * Update task priority
3114
+ */
3115
+ updatePriority(taskId: string, priority: number): Promise<boolean>;
3116
+ }
3117
+
3118
+ /**
3119
+ * Task manager interface for lifecycle management
3120
+ */
3121
+ export interface ITaskManager {
3122
+ /**
3123
+ * Create a new task
3124
+ */
3125
+ createTask(params: ITaskCreate): Promise<ITask>;
3126
+
3127
+ /**
3128
+ * Get a task by ID
3129
+ */
3130
+ getTask(taskId: string): ITask | undefined;
3131
+
3132
+ /**
3133
+ * Get all tasks matching optional filter
3134
+ */
3135
+ getTasks(filter?: Partial<Pick<ITask, 'status' | 'type' | 'assignedAgent'>>): ITask[];
3136
+
3137
+ /**
3138
+ * Assign a task to an agent
3139
+ */
3140
+ assignTask(taskId: string, agentId: string): Promise<void>;
3141
+
3142
+ /**
3143
+ * Start task execution
3144
+ */
3145
+ startTask(taskId: string): Promise<void>;
3146
+
3147
+ /**
3148
+ * Complete a task with result
3149
+ */
3150
+ completeTask(taskId: string, result: ITaskResult): Promise<void>;
3151
+
3152
+ /**
3153
+ * Fail a task with error
3154
+ */
3155
+ failTask(taskId: string, error: Error): Promise<void>;
3156
+
3157
+ /**
3158
+ * Cancel a task
3159
+ */
3160
+ cancelTask(taskId: string, reason?: string): Promise<void>;
3161
+
3162
+ /**
3163
+ * Retry a failed task
3164
+ */
3165
+ retryTask(taskId: string): Promise<void>;
3166
+
3167
+ /**
3168
+ * Get task metrics
3169
+ */
3170
+ getMetrics(): TaskManagerMetrics;
3171
+
3172
+ /**
3173
+ * Clean up old completed/failed tasks
3174
+ */
3175
+ cleanup(olderThan: Date): Promise<number>;
3176
+ }
3177
+
3178
+ /**
3179
+ * Task manager metrics
3180
+ */
3181
+ export interface TaskManagerMetrics {
3182
+ totalTasks: number;
3183
+ pendingTasks: number;
3184
+ runningTasks: number;
3185
+ completedTasks: number;
3186
+ failedTasks: number;
3187
+ cancelledTasks: number;
3188
+ avgDuration: number;
3189
+ avgWaitTime: number;
3190
+ }
3191
+
3192
+ /**
3193
+ * Task assignment strategy interface
3194
+ */
3195
+ export interface ITaskAssignmentStrategy {
3196
+ /**
3197
+ * Select the best agent for a task
3198
+ */
3199
+ selectAgent(task: ITask, availableAgents: string[]): Promise<string | undefined>;
3200
+
3201
+ /**
3202
+ * Score an agent for a task (higher is better)
3203
+ */
3204
+ scoreAgent(task: ITask, agentId: string): Promise<number>;
3205
+ }
3206
+
3207
+
3208
+ ## Instructions
3209
+
3210
+ Analyze the above codebase context and provide your response following the format specified in the task.