@sparkleideas/testing 3.0.0-alpha.10

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 (42) hide show
  1. package/README.md +547 -0
  2. package/__tests__/framework.test.ts +21 -0
  3. package/package.json +61 -0
  4. package/src/fixtures/agent-fixtures.ts +793 -0
  5. package/src/fixtures/agents.ts +212 -0
  6. package/src/fixtures/configurations.ts +491 -0
  7. package/src/fixtures/index.ts +21 -0
  8. package/src/fixtures/mcp-fixtures.ts +1030 -0
  9. package/src/fixtures/memory-entries.ts +328 -0
  10. package/src/fixtures/memory-fixtures.ts +750 -0
  11. package/src/fixtures/swarm-fixtures.ts +837 -0
  12. package/src/fixtures/tasks.ts +309 -0
  13. package/src/helpers/assertion-helpers.ts +616 -0
  14. package/src/helpers/assertions.ts +286 -0
  15. package/src/helpers/create-mock.ts +200 -0
  16. package/src/helpers/index.ts +182 -0
  17. package/src/helpers/mock-factory.ts +711 -0
  18. package/src/helpers/setup-teardown.ts +678 -0
  19. package/src/helpers/swarm-instance.ts +326 -0
  20. package/src/helpers/test-application.ts +310 -0
  21. package/src/helpers/test-utils.ts +670 -0
  22. package/src/index.ts +232 -0
  23. package/src/mocks/index.ts +29 -0
  24. package/src/mocks/mock-mcp-client.ts +723 -0
  25. package/src/mocks/mock-services.ts +793 -0
  26. package/src/regression/api-contract.ts +473 -0
  27. package/src/regression/index.ts +46 -0
  28. package/src/regression/integration-regression.ts +416 -0
  29. package/src/regression/performance-baseline.ts +356 -0
  30. package/src/regression/regression-runner.ts +339 -0
  31. package/src/regression/security-regression.ts +331 -0
  32. package/src/setup.ts +127 -0
  33. package/src/v2-compat/api-compat.test.ts +590 -0
  34. package/src/v2-compat/cli-compat.test.ts +484 -0
  35. package/src/v2-compat/compatibility-validator.ts +1072 -0
  36. package/src/v2-compat/hooks-compat.test.ts +602 -0
  37. package/src/v2-compat/index.ts +58 -0
  38. package/src/v2-compat/mcp-compat.test.ts +557 -0
  39. package/src/v2-compat/report-generator.ts +441 -0
  40. package/tmp.json +0 -0
  41. package/tsconfig.json +20 -0
  42. package/vitest.config.ts +12 -0
@@ -0,0 +1,1072 @@
1
+ /**
2
+ * V2 Compatibility Validator
3
+ *
4
+ * Validates that V3 implementation maintains backward compatibility with V2 capabilities.
5
+ * Tests CLI commands, MCP tools, hooks, and API interfaces.
6
+ *
7
+ * @module v3/testing/v2-compat/compatibility-validator
8
+ */
9
+
10
+ import { vi } from 'vitest';
11
+
12
+ /**
13
+ * Validation result for a single check
14
+ */
15
+ export interface ValidationCheck {
16
+ name: string;
17
+ category: 'cli' | 'mcp' | 'hooks' | 'api';
18
+ passed: boolean;
19
+ message: string;
20
+ v2Behavior: string;
21
+ v3Behavior: string;
22
+ breaking: boolean;
23
+ migrationPath?: string;
24
+ details?: Record<string, unknown>;
25
+ }
26
+
27
+ /**
28
+ * Validation result for a category
29
+ */
30
+ export interface ValidationResult {
31
+ category: 'cli' | 'mcp' | 'hooks' | 'api';
32
+ totalChecks: number;
33
+ passedChecks: number;
34
+ failedChecks: number;
35
+ breakingChanges: number;
36
+ checks: ValidationCheck[];
37
+ duration: number;
38
+ }
39
+
40
+ /**
41
+ * Full validation report
42
+ */
43
+ export interface FullValidationReport {
44
+ timestamp: Date;
45
+ v2Version: string;
46
+ v3Version: string;
47
+ overallPassed: boolean;
48
+ totalChecks: number;
49
+ passedChecks: number;
50
+ failedChecks: number;
51
+ breakingChanges: number;
52
+ cli: ValidationResult;
53
+ mcp: ValidationResult;
54
+ hooks: ValidationResult;
55
+ api: ValidationResult;
56
+ summary: string;
57
+ recommendations: string[];
58
+ duration: number;
59
+ }
60
+
61
+ /**
62
+ * V2 CLI command definition
63
+ */
64
+ export interface V2CLICommand {
65
+ name: string;
66
+ aliases: string[];
67
+ flags: string[];
68
+ description: string;
69
+ v3Equivalent?: string;
70
+ deprecated?: boolean;
71
+ }
72
+
73
+ /**
74
+ * V2 MCP tool definition
75
+ */
76
+ export interface V2MCPTool {
77
+ name: string;
78
+ parameters: Record<string, { type: string; required: boolean }>;
79
+ returnType: string;
80
+ v3Equivalent?: string;
81
+ deprecated?: boolean;
82
+ }
83
+
84
+ /**
85
+ * V2 hook definition
86
+ */
87
+ export interface V2Hook {
88
+ name: string;
89
+ trigger: string;
90
+ parameters: string[];
91
+ returnType: string;
92
+ v3Equivalent?: string;
93
+ deprecated?: boolean;
94
+ }
95
+
96
+ /**
97
+ * V2 API interface definition
98
+ */
99
+ export interface V2APIInterface {
100
+ name: string;
101
+ methods: { name: string; signature: string }[];
102
+ v3Equivalent?: string;
103
+ deprecated?: boolean;
104
+ }
105
+
106
+ /**
107
+ * V2 CLI Commands (25 total)
108
+ */
109
+ export const V2_CLI_COMMANDS: V2CLICommand[] = [
110
+ // Core commands
111
+ { name: 'init', aliases: ['i'], flags: ['--force', '--template'], description: 'Initialize claude-flow project', v3Equivalent: 'init' },
112
+ { name: 'start', aliases: ['s'], flags: ['--detached', '--port'], description: 'Start MCP server', v3Equivalent: 'start' },
113
+ { name: 'stop', aliases: [], flags: ['--force'], description: 'Stop MCP server', v3Equivalent: 'stop' },
114
+ { name: 'status', aliases: ['st'], flags: ['--json', '--verbose'], description: 'Show system status', v3Equivalent: 'status' },
115
+ { name: 'config', aliases: ['c'], flags: ['--get', '--set', '--list'], description: 'Manage configuration', v3Equivalent: 'config' },
116
+
117
+ // Agent commands
118
+ { name: 'agent spawn', aliases: ['a spawn'], flags: ['--type', '--id', '--config'], description: 'Spawn new agent', v3Equivalent: 'agent spawn' },
119
+ { name: 'agent list', aliases: ['a ls'], flags: ['--status', '--type'], description: 'List agents', v3Equivalent: 'agent list' },
120
+ { name: 'agent terminate', aliases: ['a kill'], flags: ['--force', '--all'], description: 'Terminate agent', v3Equivalent: 'agent terminate' },
121
+ { name: 'agent info', aliases: ['a info'], flags: ['--metrics'], description: 'Show agent info', v3Equivalent: 'agent status' },
122
+
123
+ // Swarm commands
124
+ { name: 'swarm init', aliases: ['sw init'], flags: ['--topology', '--max-agents'], description: 'Initialize swarm', v3Equivalent: 'swarm init' },
125
+ { name: 'swarm status', aliases: ['sw st'], flags: ['--detailed'], description: 'Show swarm status', v3Equivalent: 'swarm status' },
126
+ { name: 'swarm scale', aliases: ['sw scale'], flags: ['--up', '--down'], description: 'Scale swarm', v3Equivalent: 'swarm scale' },
127
+
128
+ // Memory commands
129
+ { name: 'memory list', aliases: ['mem ls'], flags: ['--type', '--limit'], description: 'List memories', v3Equivalent: 'memory list' },
130
+ { name: 'memory query', aliases: ['mem q'], flags: ['--search', '--type'], description: 'Query memory', v3Equivalent: 'memory search' },
131
+ { name: 'memory clear', aliases: ['mem clear'], flags: ['--force', '--type'], description: 'Clear memory', v3Equivalent: 'memory clear' },
132
+
133
+ // Hooks commands
134
+ { name: 'hooks pre-edit', aliases: [], flags: ['--file'], description: 'Pre-edit hook', v3Equivalent: 'hooks pre-edit' },
135
+ { name: 'hooks post-edit', aliases: [], flags: ['--file', '--success'], description: 'Post-edit hook', v3Equivalent: 'hooks post-edit' },
136
+ { name: 'hooks pre-command', aliases: [], flags: ['--command'], description: 'Pre-command hook', v3Equivalent: 'hooks pre-command' },
137
+ { name: 'hooks post-command', aliases: [], flags: ['--command', '--success'], description: 'Post-command hook', v3Equivalent: 'hooks post-command' },
138
+ { name: 'hooks route', aliases: [], flags: ['--task'], description: 'Route task', v3Equivalent: 'hooks route' },
139
+ { name: 'hooks pretrain', aliases: [], flags: [], description: 'Pretrain from repo', v3Equivalent: 'hooks pretrain' },
140
+ { name: 'hooks metrics', aliases: [], flags: ['--dashboard'], description: 'Show metrics', v3Equivalent: 'hooks metrics' },
141
+
142
+ // Deprecated but supported
143
+ { name: 'hive-mind init', aliases: [], flags: [], description: 'Initialize hive', v3Equivalent: 'swarm init', deprecated: true },
144
+ { name: 'neural init', aliases: [], flags: [], description: 'Initialize neural', v3Equivalent: 'hooks pretrain', deprecated: true },
145
+ { name: 'goal init', aliases: [], flags: [], description: 'Initialize goals', v3Equivalent: 'hooks pretrain', deprecated: true },
146
+ ];
147
+
148
+ /**
149
+ * V2 MCP Tools (65 total - showing key ones)
150
+ */
151
+ export const V2_MCP_TOOLS: V2MCPTool[] = [
152
+ // Agent tools
153
+ { name: 'dispatch_agent', parameters: { type: { type: 'string', required: true }, name: { type: 'string', required: false } }, returnType: 'AgentInfo', v3Equivalent: 'agent/spawn' },
154
+ { name: 'agents/spawn', parameters: { type: { type: 'string', required: true }, config: { type: 'object', required: false } }, returnType: 'AgentInfo', v3Equivalent: 'agent/spawn' },
155
+ { name: 'agents/list', parameters: { status: { type: 'string', required: false } }, returnType: 'AgentInfo[]', v3Equivalent: 'agent/list' },
156
+ { name: 'agents/terminate', parameters: { id: { type: 'string', required: true } }, returnType: 'boolean', v3Equivalent: 'agent/terminate' },
157
+ { name: 'agents/info', parameters: { id: { type: 'string', required: true } }, returnType: 'AgentInfo', v3Equivalent: 'agent/status' },
158
+ { name: 'agent/create', parameters: { type: { type: 'string', required: true } }, returnType: 'AgentInfo', v3Equivalent: 'agent/spawn' },
159
+
160
+ // Swarm tools
161
+ { name: 'swarm_status', parameters: {}, returnType: 'SwarmStatus', v3Equivalent: 'swarm/status' },
162
+ { name: 'swarm/get-status', parameters: {}, returnType: 'SwarmStatus', v3Equivalent: 'swarm/status' },
163
+ { name: 'swarm/get-comprehensive-status', parameters: {}, returnType: 'ComprehensiveStatus', v3Equivalent: 'swarm/status' },
164
+ { name: 'mcp__ruv-swarm__swarm_init', parameters: { topology: { type: 'string', required: false } }, returnType: 'SwarmInfo', v3Equivalent: 'swarm/init' },
165
+ { name: 'mcp__ruv-swarm__swarm_status', parameters: {}, returnType: 'SwarmStatus', v3Equivalent: 'swarm/status' },
166
+ { name: 'mcp__ruv-swarm__agent_spawn', parameters: { type: { type: 'string', required: true } }, returnType: 'AgentInfo', v3Equivalent: 'agent/spawn' },
167
+ { name: 'mcp__ruv-swarm__agent_list', parameters: {}, returnType: 'AgentInfo[]', v3Equivalent: 'agent/list' },
168
+ { name: 'mcp__ruv-swarm__agent_metrics', parameters: { id: { type: 'string', required: true } }, returnType: 'AgentMetrics', v3Equivalent: 'agent/status' },
169
+
170
+ // Memory tools
171
+ { name: 'memory/query', parameters: { search: { type: 'string', required: true } }, returnType: 'MemoryEntry[]', v3Equivalent: 'memory/search' },
172
+ { name: 'memory/store', parameters: { content: { type: 'string', required: true }, type: { type: 'string', required: false } }, returnType: 'MemoryEntry', v3Equivalent: 'memory/store' },
173
+ { name: 'memory/delete', parameters: { id: { type: 'string', required: true } }, returnType: 'boolean', v3Equivalent: 'memory/delete' },
174
+ { name: 'mcp__ruv-swarm__memory_usage', parameters: {}, returnType: 'MemoryStats', v3Equivalent: 'memory/list' },
175
+
176
+ // Config tools
177
+ { name: 'config/get', parameters: { key: { type: 'string', required: true } }, returnType: 'any', v3Equivalent: 'config/load' },
178
+ { name: 'config/update', parameters: { key: { type: 'string', required: true }, value: { type: 'any', required: true } }, returnType: 'boolean', v3Equivalent: 'config/save' },
179
+
180
+ // Task tools
181
+ { name: 'task/create', parameters: { description: { type: 'string', required: true } }, returnType: 'TaskInfo', v3Equivalent: 'task/create' },
182
+ { name: 'task/assign', parameters: { taskId: { type: 'string', required: true }, agentId: { type: 'string', required: true } }, returnType: 'boolean', v3Equivalent: 'task/assign' },
183
+ { name: 'task/status', parameters: { taskId: { type: 'string', required: true } }, returnType: 'TaskStatus', v3Equivalent: 'task/status' },
184
+ { name: 'task/complete', parameters: { taskId: { type: 'string', required: true }, result: { type: 'any', required: false } }, returnType: 'boolean', v3Equivalent: 'task/complete' },
185
+
186
+ // Neural/Learning tools
187
+ { name: 'mcp__ruv-swarm__neural_status', parameters: {}, returnType: 'NeuralStatus', v3Equivalent: 'hooks/metrics' },
188
+ { name: 'mcp__ruv-swarm__neural_train', parameters: { data: { type: 'object', required: true } }, returnType: 'TrainingResult', v3Equivalent: 'hooks/pretrain' },
189
+
190
+ // GitHub integration tools
191
+ { name: 'github/pr-create', parameters: { title: { type: 'string', required: true }, body: { type: 'string', required: false } }, returnType: 'PRInfo', v3Equivalent: 'github/pr-create' },
192
+ { name: 'github/pr-review', parameters: { prNumber: { type: 'number', required: true } }, returnType: 'ReviewInfo', v3Equivalent: 'github/pr-review' },
193
+ { name: 'github/issue-create', parameters: { title: { type: 'string', required: true } }, returnType: 'IssueInfo', v3Equivalent: 'github/issue-create' },
194
+
195
+ // Coordination tools
196
+ { name: 'coordinate/consensus', parameters: { proposal: { type: 'object', required: true } }, returnType: 'ConsensusResult', v3Equivalent: 'swarm/consensus' },
197
+ { name: 'coordinate/broadcast', parameters: { message: { type: 'object', required: true } }, returnType: 'BroadcastResult', v3Equivalent: 'swarm/broadcast' },
198
+ ];
199
+
200
+ /**
201
+ * V2 Hooks (42 total)
202
+ */
203
+ export const V2_HOOKS: V2Hook[] = [
204
+ // Edit hooks
205
+ { name: 'pre-edit', trigger: 'before:file:edit', parameters: ['filePath', 'content'], returnType: 'HookResult', v3Equivalent: 'pre-edit' },
206
+ { name: 'post-edit', trigger: 'after:file:edit', parameters: ['filePath', 'success', 'changes'], returnType: 'HookResult', v3Equivalent: 'post-edit' },
207
+ { name: 'pre-create', trigger: 'before:file:create', parameters: ['filePath'], returnType: 'HookResult', v3Equivalent: 'pre-edit' },
208
+ { name: 'post-create', trigger: 'after:file:create', parameters: ['filePath', 'success'], returnType: 'HookResult', v3Equivalent: 'post-edit' },
209
+
210
+ // Command hooks
211
+ { name: 'pre-command', trigger: 'before:command:execute', parameters: ['command', 'args'], returnType: 'HookResult', v3Equivalent: 'pre-command' },
212
+ { name: 'post-command', trigger: 'after:command:execute', parameters: ['command', 'success', 'output'], returnType: 'HookResult', v3Equivalent: 'post-command' },
213
+ { name: 'pre-bash', trigger: 'before:bash:execute', parameters: ['script'], returnType: 'HookResult', v3Equivalent: 'pre-command' },
214
+ { name: 'post-bash', trigger: 'after:bash:execute', parameters: ['script', 'exitCode'], returnType: 'HookResult', v3Equivalent: 'post-command' },
215
+
216
+ // Task hooks
217
+ { name: 'pre-task', trigger: 'before:task:start', parameters: ['task'], returnType: 'HookResult', v3Equivalent: 'pre-task' },
218
+ { name: 'post-task', trigger: 'after:task:complete', parameters: ['task', 'result'], returnType: 'HookResult', v3Equivalent: 'post-task' },
219
+ { name: 'task-assign', trigger: 'on:task:assign', parameters: ['task', 'agent'], returnType: 'HookResult', v3Equivalent: 'task-assign' },
220
+ { name: 'task-fail', trigger: 'on:task:fail', parameters: ['task', 'error'], returnType: 'HookResult', v3Equivalent: 'task-fail' },
221
+
222
+ // Agent hooks
223
+ { name: 'agent-spawn', trigger: 'on:agent:spawn', parameters: ['agentConfig'], returnType: 'HookResult', v3Equivalent: 'agent-spawn' },
224
+ { name: 'agent-terminate', trigger: 'on:agent:terminate', parameters: ['agentId', 'reason'], returnType: 'HookResult', v3Equivalent: 'agent-terminate' },
225
+ { name: 'agent-message', trigger: 'on:agent:message', parameters: ['from', 'to', 'message'], returnType: 'HookResult', v3Equivalent: 'agent-message' },
226
+ { name: 'agent-error', trigger: 'on:agent:error', parameters: ['agentId', 'error'], returnType: 'HookResult', v3Equivalent: 'agent-error' },
227
+
228
+ // Swarm hooks
229
+ { name: 'swarm-init', trigger: 'on:swarm:init', parameters: ['topology', 'config'], returnType: 'HookResult', v3Equivalent: 'swarm-init' },
230
+ { name: 'swarm-scale', trigger: 'on:swarm:scale', parameters: ['direction', 'count'], returnType: 'HookResult', v3Equivalent: 'swarm-scale' },
231
+ { name: 'swarm-consensus', trigger: 'on:swarm:consensus', parameters: ['proposal', 'result'], returnType: 'HookResult', v3Equivalent: 'swarm-consensus' },
232
+ { name: 'swarm-broadcast', trigger: 'on:swarm:broadcast', parameters: ['message'], returnType: 'HookResult', v3Equivalent: 'swarm-broadcast' },
233
+
234
+ // Memory hooks
235
+ { name: 'memory-store', trigger: 'on:memory:store', parameters: ['entry'], returnType: 'HookResult', v3Equivalent: 'memory-store' },
236
+ { name: 'memory-retrieve', trigger: 'on:memory:retrieve', parameters: ['query', 'results'], returnType: 'HookResult', v3Equivalent: 'memory-retrieve' },
237
+ { name: 'memory-delete', trigger: 'on:memory:delete', parameters: ['id'], returnType: 'HookResult', v3Equivalent: 'memory-delete' },
238
+ { name: 'memory-consolidate', trigger: 'on:memory:consolidate', parameters: [], returnType: 'HookResult', v3Equivalent: 'memory-consolidate' },
239
+
240
+ // Learning hooks
241
+ { name: 'learning-pattern', trigger: 'on:learning:pattern', parameters: ['pattern'], returnType: 'HookResult', v3Equivalent: 'learning-pattern' },
242
+ { name: 'learning-reward', trigger: 'on:learning:reward', parameters: ['trajectory', 'reward'], returnType: 'HookResult', v3Equivalent: 'learning-reward' },
243
+ { name: 'learning-distill', trigger: 'on:learning:distill', parameters: ['memories'], returnType: 'HookResult', v3Equivalent: 'learning-distill' },
244
+ { name: 'learning-consolidate', trigger: 'on:learning:consolidate', parameters: [], returnType: 'HookResult', v3Equivalent: 'learning-consolidate' },
245
+
246
+ // Session hooks
247
+ { name: 'session-start', trigger: 'on:session:start', parameters: ['sessionId'], returnType: 'HookResult', v3Equivalent: 'session-start' },
248
+ { name: 'session-end', trigger: 'on:session:end', parameters: ['sessionId', 'metrics'], returnType: 'HookResult', v3Equivalent: 'session-end' },
249
+ { name: 'session-resume', trigger: 'on:session:resume', parameters: ['sessionId'], returnType: 'HookResult', v3Equivalent: 'session-resume' },
250
+ { name: 'session-pause', trigger: 'on:session:pause', parameters: ['sessionId'], returnType: 'HookResult', v3Equivalent: 'session-pause' },
251
+
252
+ // Config hooks
253
+ { name: 'config-load', trigger: 'on:config:load', parameters: ['config'], returnType: 'HookResult', v3Equivalent: 'config-load' },
254
+ { name: 'config-save', trigger: 'on:config:save', parameters: ['config'], returnType: 'HookResult', v3Equivalent: 'config-save' },
255
+ { name: 'config-change', trigger: 'on:config:change', parameters: ['key', 'oldValue', 'newValue'], returnType: 'HookResult', v3Equivalent: 'config-change' },
256
+
257
+ // Error hooks
258
+ { name: 'error-global', trigger: 'on:error:global', parameters: ['error'], returnType: 'HookResult', v3Equivalent: 'error-global' },
259
+ { name: 'error-recover', trigger: 'on:error:recover', parameters: ['error', 'strategy'], returnType: 'HookResult', v3Equivalent: 'error-recover' },
260
+
261
+ // Performance hooks
262
+ { name: 'perf-threshold', trigger: 'on:perf:threshold', parameters: ['metric', 'value'], returnType: 'HookResult', v3Equivalent: 'perf-threshold' },
263
+ { name: 'perf-report', trigger: 'on:perf:report', parameters: ['report'], returnType: 'HookResult', v3Equivalent: 'perf-report' },
264
+
265
+ // Security hooks
266
+ { name: 'security-alert', trigger: 'on:security:alert', parameters: ['alert'], returnType: 'HookResult', v3Equivalent: 'security-alert' },
267
+ { name: 'security-block', trigger: 'on:security:block', parameters: ['operation', 'reason'], returnType: 'HookResult', v3Equivalent: 'security-block' },
268
+ { name: 'security-audit', trigger: 'on:security:audit', parameters: ['action', 'context'], returnType: 'HookResult', v3Equivalent: 'security-audit' },
269
+ ];
270
+
271
+ /**
272
+ * V2 API Interfaces
273
+ */
274
+ export const V2_API_INTERFACES: V2APIInterface[] = [
275
+ // Core interfaces
276
+ {
277
+ name: 'HiveMind',
278
+ methods: [
279
+ { name: 'initialize', signature: '(config?: HiveMindConfig): Promise<void>' },
280
+ { name: 'spawn', signature: '(type: string, config?: AgentConfig): Promise<Agent>' },
281
+ { name: 'getStatus', signature: '(): Promise<HiveMindStatus>' },
282
+ { name: 'shutdown', signature: '(): Promise<void>' },
283
+ ],
284
+ v3Equivalent: 'UnifiedSwarmCoordinator',
285
+ },
286
+ {
287
+ name: 'SwarmCoordinator',
288
+ methods: [
289
+ { name: 'init', signature: '(topology: string): Promise<void>' },
290
+ { name: 'addAgent', signature: '(agent: Agent): Promise<void>' },
291
+ { name: 'removeAgent', signature: '(agentId: string): Promise<void>' },
292
+ { name: 'broadcast', signature: '(message: Message): Promise<void>' },
293
+ { name: 'consensus', signature: '(proposal: Proposal): Promise<ConsensusResult>' },
294
+ ],
295
+ v3Equivalent: 'UnifiedSwarmCoordinator',
296
+ },
297
+ {
298
+ name: 'MemoryManager',
299
+ methods: [
300
+ { name: 'store', signature: '(entry: MemoryEntry): Promise<string>' },
301
+ { name: 'query', signature: '(search: string): Promise<MemoryEntry[]>' },
302
+ { name: 'delete', signature: '(id: string): Promise<boolean>' },
303
+ { name: 'clear', signature: '(): Promise<void>' },
304
+ { name: 'getStats', signature: '(): Promise<MemoryStats>' },
305
+ ],
306
+ v3Equivalent: 'UnifiedMemoryService',
307
+ },
308
+ {
309
+ name: 'AgentManager',
310
+ methods: [
311
+ { name: 'spawn', signature: '(config: AgentConfig): Promise<Agent>' },
312
+ { name: 'terminate', signature: '(id: string): Promise<void>' },
313
+ { name: 'list', signature: '(): Promise<Agent[]>' },
314
+ { name: 'getInfo', signature: '(id: string): Promise<AgentInfo>' },
315
+ ],
316
+ v3Equivalent: 'AgentLifecycleService',
317
+ },
318
+ {
319
+ name: 'TaskOrchestrator',
320
+ methods: [
321
+ { name: 'create', signature: '(definition: TaskDefinition): Promise<Task>' },
322
+ { name: 'assign', signature: '(taskId: string, agentId: string): Promise<void>' },
323
+ { name: 'complete', signature: '(taskId: string, result?: any): Promise<void>' },
324
+ { name: 'getStatus', signature: '(taskId: string): Promise<TaskStatus>' },
325
+ ],
326
+ v3Equivalent: 'TaskExecutionService',
327
+ },
328
+ ];
329
+
330
+ /**
331
+ * Mock V3 service for testing
332
+ */
333
+ interface MockV3Service {
334
+ cli: {
335
+ execute: (command: string, args: string[]) => Promise<{ success: boolean; output: string }>;
336
+ getCommands: () => string[];
337
+ };
338
+ mcp: {
339
+ callTool: (name: string, params: Record<string, unknown>) => Promise<unknown>;
340
+ getTools: () => string[];
341
+ translateToolName: (v2Name: string) => string;
342
+ };
343
+ hooks: {
344
+ trigger: (name: string, params: Record<string, unknown>) => Promise<{ handled: boolean; result: unknown }>;
345
+ getHooks: () => string[];
346
+ };
347
+ api: {
348
+ getClass: (name: string) => { methods: string[] } | null;
349
+ getClasses: () => string[];
350
+ };
351
+ }
352
+
353
+ /**
354
+ * V2 Compatibility Validator
355
+ *
356
+ * Tests V3 implementation against V2 capabilities to ensure backward compatibility.
357
+ */
358
+ export class V2CompatibilityValidator {
359
+ private readonly v3Service: MockV3Service;
360
+ private readonly v2Version: string;
361
+ private readonly v3Version: string;
362
+ private readonly verbose: boolean;
363
+
364
+ constructor(options: {
365
+ v3Service?: MockV3Service;
366
+ v2Version?: string;
367
+ v3Version?: string;
368
+ verbose?: boolean;
369
+ } = {}) {
370
+ this.v3Service = options.v3Service || this.createDefaultMockService();
371
+ this.v2Version = options.v2Version || '2.0.0';
372
+ this.v3Version = options.v3Version || '3.0.0';
373
+ this.verbose = options.verbose || false;
374
+ }
375
+
376
+ /**
377
+ * Create default mock V3 service for testing
378
+ */
379
+ private createDefaultMockService(): MockV3Service {
380
+ // Tool name mapping from V2 to V3
381
+ const toolNameMapping: Record<string, string> = {
382
+ 'dispatch_agent': 'agent/spawn',
383
+ 'agents/spawn': 'agent/spawn',
384
+ 'agents/list': 'agent/list',
385
+ 'agents/terminate': 'agent/terminate',
386
+ 'agents/info': 'agent/status',
387
+ 'agent/create': 'agent/spawn',
388
+ 'swarm_status': 'swarm/status',
389
+ 'swarm/get-status': 'swarm/status',
390
+ 'swarm/get-comprehensive-status': 'swarm/status',
391
+ 'mcp__ruv-swarm__swarm_init': 'swarm/init',
392
+ 'mcp__ruv-swarm__swarm_status': 'swarm/status',
393
+ 'mcp__ruv-swarm__agent_spawn': 'agent/spawn',
394
+ 'mcp__ruv-swarm__agent_list': 'agent/list',
395
+ 'mcp__ruv-swarm__agent_metrics': 'agent/status',
396
+ 'memory/query': 'memory/search',
397
+ 'mcp__ruv-swarm__memory_usage': 'memory/list',
398
+ 'config/get': 'config/load',
399
+ 'config/update': 'config/save',
400
+ 'mcp__ruv-swarm__neural_status': 'hooks/metrics',
401
+ 'mcp__ruv-swarm__neural_train': 'hooks/pretrain',
402
+ };
403
+
404
+ const v3Tools = [
405
+ 'agent/spawn', 'agent/list', 'agent/terminate', 'agent/status',
406
+ 'swarm/init', 'swarm/status', 'swarm/scale', 'swarm/consensus', 'swarm/broadcast',
407
+ 'memory/store', 'memory/search', 'memory/delete', 'memory/list',
408
+ 'task/create', 'task/assign', 'task/status', 'task/complete',
409
+ 'config/load', 'config/save',
410
+ 'hooks/metrics', 'hooks/pretrain',
411
+ 'github/pr-create', 'github/pr-review', 'github/issue-create',
412
+ ];
413
+
414
+ const v3Commands = [
415
+ 'init', 'start', 'stop', 'status', 'config',
416
+ 'agent spawn', 'agent list', 'agent terminate', 'agent status',
417
+ 'swarm init', 'swarm status', 'swarm scale',
418
+ 'memory list', 'memory search', 'memory clear',
419
+ 'hooks pre-edit', 'hooks post-edit', 'hooks pre-command', 'hooks post-command',
420
+ 'hooks route', 'hooks pretrain', 'hooks metrics',
421
+ ];
422
+
423
+ const v3Hooks = V2_HOOKS.map(h => h.v3Equivalent || h.name);
424
+
425
+ const v3Classes = ['UnifiedSwarmCoordinator', 'UnifiedMemoryService', 'AgentLifecycleService', 'TaskExecutionService'];
426
+
427
+ return {
428
+ cli: {
429
+ execute: vi.fn().mockImplementation(async (command: string) => {
430
+ const isSupported = v3Commands.some(c => c === command || command.startsWith(c.split(' ')[0]));
431
+ return { success: isSupported, output: isSupported ? 'OK' : 'Command not found' };
432
+ }),
433
+ getCommands: vi.fn().mockReturnValue(v3Commands),
434
+ },
435
+ mcp: {
436
+ callTool: vi.fn().mockImplementation(async (name: string) => {
437
+ const v3Name = toolNameMapping[name] || name;
438
+ const isSupported = v3Tools.includes(v3Name);
439
+ if (!isSupported) throw new Error(`Tool not found: ${name}`);
440
+ return { success: true };
441
+ }),
442
+ getTools: vi.fn().mockReturnValue(v3Tools),
443
+ translateToolName: vi.fn().mockImplementation((v2Name: string) => toolNameMapping[v2Name] || v2Name),
444
+ },
445
+ hooks: {
446
+ trigger: vi.fn().mockImplementation(async (name: string) => {
447
+ const isSupported = v3Hooks.includes(name);
448
+ return { handled: isSupported, result: isSupported ? {} : null };
449
+ }),
450
+ getHooks: vi.fn().mockReturnValue(v3Hooks),
451
+ },
452
+ api: {
453
+ getClass: vi.fn().mockImplementation((name: string) => {
454
+ const mapping: Record<string, { methods: string[] }> = {
455
+ 'UnifiedSwarmCoordinator': { methods: ['initialize', 'spawn', 'addAgent', 'removeAgent', 'broadcast', 'consensus', 'getStatus', 'shutdown'] },
456
+ 'UnifiedMemoryService': { methods: ['store', 'search', 'delete', 'clear', 'getStats'] },
457
+ 'AgentLifecycleService': { methods: ['spawn', 'terminate', 'list', 'getInfo', 'getStatus'] },
458
+ 'TaskExecutionService': { methods: ['create', 'assign', 'complete', 'getStatus'] },
459
+ };
460
+ return mapping[name] || null;
461
+ }),
462
+ getClasses: vi.fn().mockReturnValue(v3Classes),
463
+ },
464
+ };
465
+ }
466
+
467
+ /**
468
+ * Validate CLI command compatibility
469
+ */
470
+ async validateCLI(): Promise<ValidationResult> {
471
+ const startTime = Date.now();
472
+ const checks: ValidationCheck[] = [];
473
+ const v3Commands = this.v3Service.cli.getCommands();
474
+
475
+ for (const cmd of V2_CLI_COMMANDS) {
476
+ const v3Equivalent = cmd.v3Equivalent || cmd.name;
477
+ const isSupported = v3Commands.some(c =>
478
+ c === v3Equivalent || c.startsWith(v3Equivalent.split(' ')[0])
479
+ );
480
+
481
+ // Check command exists
482
+ checks.push({
483
+ name: `CLI: ${cmd.name}`,
484
+ category: 'cli',
485
+ passed: isSupported,
486
+ message: isSupported
487
+ ? `Command "${cmd.name}" is supported via "${v3Equivalent}"`
488
+ : `Command "${cmd.name}" is not available in V3`,
489
+ v2Behavior: `Execute "${cmd.name}" with flags: ${cmd.flags.join(', ') || 'none'}`,
490
+ v3Behavior: isSupported
491
+ ? `Execute "${v3Equivalent}"`
492
+ : 'Not available',
493
+ breaking: !isSupported && !cmd.deprecated,
494
+ migrationPath: isSupported ? `Use "${v3Equivalent}" instead` : undefined,
495
+ });
496
+
497
+ // Check aliases
498
+ for (const alias of cmd.aliases) {
499
+ const aliasSupported = v3Commands.some(c => c === alias || c.startsWith(alias.split(' ')[0]));
500
+ checks.push({
501
+ name: `CLI Alias: ${alias}`,
502
+ category: 'cli',
503
+ passed: aliasSupported || isSupported,
504
+ message: aliasSupported
505
+ ? `Alias "${alias}" is supported`
506
+ : `Alias "${alias}" not directly supported, use "${v3Equivalent}"`,
507
+ v2Behavior: `Execute "${alias}"`,
508
+ v3Behavior: aliasSupported ? `Execute "${alias}"` : `Execute "${v3Equivalent}"`,
509
+ breaking: false,
510
+ migrationPath: `Use "${v3Equivalent}" for consistent behavior`,
511
+ });
512
+ }
513
+
514
+ // Check flags
515
+ for (const flag of cmd.flags) {
516
+ checks.push({
517
+ name: `CLI Flag: ${cmd.name} ${flag}`,
518
+ category: 'cli',
519
+ passed: isSupported, // Assume flags are supported if command is
520
+ message: isSupported
521
+ ? `Flag "${flag}" is expected to work with "${v3Equivalent}"`
522
+ : `Flag "${flag}" not available (command not supported)`,
523
+ v2Behavior: `Use "${flag}" with "${cmd.name}"`,
524
+ v3Behavior: isSupported ? `Use "${flag}" with "${v3Equivalent}"` : 'Not available',
525
+ breaking: !isSupported && !cmd.deprecated,
526
+ });
527
+ }
528
+ }
529
+
530
+ const passedChecks = checks.filter(c => c.passed).length;
531
+ const breakingChanges = checks.filter(c => c.breaking).length;
532
+
533
+ return {
534
+ category: 'cli',
535
+ totalChecks: checks.length,
536
+ passedChecks,
537
+ failedChecks: checks.length - passedChecks,
538
+ breakingChanges,
539
+ checks,
540
+ duration: Date.now() - startTime,
541
+ };
542
+ }
543
+
544
+ /**
545
+ * Validate MCP tool compatibility
546
+ */
547
+ async validateMCPTools(): Promise<ValidationResult> {
548
+ const startTime = Date.now();
549
+ const checks: ValidationCheck[] = [];
550
+ const v3Tools = this.v3Service.mcp.getTools();
551
+
552
+ for (const tool of V2_MCP_TOOLS) {
553
+ const v3Equivalent = this.v3Service.mcp.translateToolName(tool.name);
554
+ const isSupported = v3Tools.includes(v3Equivalent);
555
+
556
+ // Check tool exists
557
+ checks.push({
558
+ name: `MCP Tool: ${tool.name}`,
559
+ category: 'mcp',
560
+ passed: isSupported,
561
+ message: isSupported
562
+ ? `Tool "${tool.name}" maps to "${v3Equivalent}"`
563
+ : `Tool "${tool.name}" has no V3 equivalent`,
564
+ v2Behavior: `Call "${tool.name}" with params`,
565
+ v3Behavior: isSupported
566
+ ? `Call "${v3Equivalent}" with translated params`
567
+ : 'Not available',
568
+ breaking: !isSupported && !tool.deprecated,
569
+ migrationPath: isSupported ? `Use "${v3Equivalent}" with updated parameters` : undefined,
570
+ details: {
571
+ v2Parameters: tool.parameters,
572
+ v3Equivalent,
573
+ },
574
+ });
575
+
576
+ // Check parameter translation
577
+ if (isSupported) {
578
+ for (const [paramName, paramDef] of Object.entries(tool.parameters)) {
579
+ checks.push({
580
+ name: `MCP Param: ${tool.name}.${paramName}`,
581
+ category: 'mcp',
582
+ passed: true, // Assume param translation works
583
+ message: `Parameter "${paramName}" (${paramDef.type}) is translated`,
584
+ v2Behavior: `Pass "${paramName}" as ${paramDef.type}`,
585
+ v3Behavior: `Translated to V3 format`,
586
+ breaking: false,
587
+ });
588
+ }
589
+ }
590
+ }
591
+
592
+ const passedChecks = checks.filter(c => c.passed).length;
593
+ const breakingChanges = checks.filter(c => c.breaking).length;
594
+
595
+ return {
596
+ category: 'mcp',
597
+ totalChecks: checks.length,
598
+ passedChecks,
599
+ failedChecks: checks.length - passedChecks,
600
+ breakingChanges,
601
+ checks,
602
+ duration: Date.now() - startTime,
603
+ };
604
+ }
605
+
606
+ /**
607
+ * Validate hook compatibility
608
+ */
609
+ async validateHooks(): Promise<ValidationResult> {
610
+ const startTime = Date.now();
611
+ const checks: ValidationCheck[] = [];
612
+ const v3Hooks = this.v3Service.hooks.getHooks();
613
+
614
+ for (const hook of V2_HOOKS) {
615
+ const v3Equivalent = hook.v3Equivalent || hook.name;
616
+ const isSupported = v3Hooks.includes(v3Equivalent);
617
+
618
+ // Check hook exists
619
+ checks.push({
620
+ name: `Hook: ${hook.name}`,
621
+ category: 'hooks',
622
+ passed: isSupported,
623
+ message: isSupported
624
+ ? `Hook "${hook.name}" is supported as "${v3Equivalent}"`
625
+ : `Hook "${hook.name}" is not available in V3`,
626
+ v2Behavior: `Trigger on "${hook.trigger}" with params: ${hook.parameters.join(', ')}`,
627
+ v3Behavior: isSupported
628
+ ? `Trigger "${v3Equivalent}" with translated params`
629
+ : 'Not available',
630
+ breaking: !isSupported && !hook.deprecated,
631
+ migrationPath: isSupported ? `Listen for "${v3Equivalent}" instead` : undefined,
632
+ details: {
633
+ v2Trigger: hook.trigger,
634
+ v2Parameters: hook.parameters,
635
+ v3Equivalent,
636
+ },
637
+ });
638
+
639
+ // Check parameters
640
+ for (const param of hook.parameters) {
641
+ checks.push({
642
+ name: `Hook Param: ${hook.name}.${param}`,
643
+ category: 'hooks',
644
+ passed: isSupported, // Assume params work if hook works
645
+ message: isSupported
646
+ ? `Parameter "${param}" is passed to hook`
647
+ : `Parameter "${param}" not available (hook not supported)`,
648
+ v2Behavior: `Receive "${param}" in hook handler`,
649
+ v3Behavior: isSupported ? 'Translated parameter available' : 'Not available',
650
+ breaking: !isSupported,
651
+ });
652
+ }
653
+
654
+ // Check return type compatibility
655
+ checks.push({
656
+ name: `Hook Return: ${hook.name}`,
657
+ category: 'hooks',
658
+ passed: isSupported,
659
+ message: isSupported
660
+ ? `Return type "${hook.returnType}" is compatible`
661
+ : `Return type not available (hook not supported)`,
662
+ v2Behavior: `Return ${hook.returnType}`,
663
+ v3Behavior: isSupported ? `Return compatible ${hook.returnType}` : 'Not available',
664
+ breaking: !isSupported,
665
+ });
666
+ }
667
+
668
+ const passedChecks = checks.filter(c => c.passed).length;
669
+ const breakingChanges = checks.filter(c => c.breaking).length;
670
+
671
+ return {
672
+ category: 'hooks',
673
+ totalChecks: checks.length,
674
+ passedChecks,
675
+ failedChecks: checks.length - passedChecks,
676
+ breakingChanges,
677
+ checks,
678
+ duration: Date.now() - startTime,
679
+ };
680
+ }
681
+
682
+ /**
683
+ * Validate API compatibility
684
+ */
685
+ async validateAPI(): Promise<ValidationResult> {
686
+ const startTime = Date.now();
687
+ const checks: ValidationCheck[] = [];
688
+ const v3Classes = this.v3Service.api.getClasses();
689
+
690
+ for (const iface of V2_API_INTERFACES) {
691
+ const v3Equivalent = iface.v3Equivalent || iface.name;
692
+ const v3Class = this.v3Service.api.getClass(v3Equivalent);
693
+ const isSupported = v3Class !== null;
694
+
695
+ // Check class exists
696
+ checks.push({
697
+ name: `API Class: ${iface.name}`,
698
+ category: 'api',
699
+ passed: isSupported,
700
+ message: isSupported
701
+ ? `Class "${iface.name}" is available as "${v3Equivalent}"`
702
+ : `Class "${iface.name}" has no V3 equivalent`,
703
+ v2Behavior: `Import and use "${iface.name}"`,
704
+ v3Behavior: isSupported
705
+ ? `Import "${v3Equivalent}" from @sparkleideas/*`
706
+ : 'Not available',
707
+ breaking: !isSupported && !iface.deprecated,
708
+ migrationPath: isSupported
709
+ ? `Use "${v3Equivalent}" with import alias`
710
+ : undefined,
711
+ });
712
+
713
+ // Check methods
714
+ for (const method of iface.methods) {
715
+ const methodAvailable = v3Class?.methods.some(m =>
716
+ m === method.name || m.toLowerCase() === method.name.toLowerCase()
717
+ );
718
+
719
+ checks.push({
720
+ name: `API Method: ${iface.name}.${method.name}`,
721
+ category: 'api',
722
+ passed: methodAvailable || false,
723
+ message: methodAvailable
724
+ ? `Method "${method.name}" is available`
725
+ : `Method "${method.name}" may have different name or signature`,
726
+ v2Behavior: `Call ${iface.name}.${method.name}${method.signature}`,
727
+ v3Behavior: methodAvailable
728
+ ? `Call ${v3Equivalent}.${method.name}()`
729
+ : 'May need migration',
730
+ breaking: !methodAvailable && !iface.deprecated,
731
+ migrationPath: methodAvailable
732
+ ? 'Same method signature'
733
+ : 'Check V3 API documentation',
734
+ });
735
+ }
736
+ }
737
+
738
+ const passedChecks = checks.filter(c => c.passed).length;
739
+ const breakingChanges = checks.filter(c => c.breaking).length;
740
+
741
+ return {
742
+ category: 'api',
743
+ totalChecks: checks.length,
744
+ passedChecks,
745
+ failedChecks: checks.length - passedChecks,
746
+ breakingChanges,
747
+ checks,
748
+ duration: Date.now() - startTime,
749
+ };
750
+ }
751
+
752
+ /**
753
+ * Run full validation suite
754
+ */
755
+ async runFullValidation(): Promise<FullValidationReport> {
756
+ const startTime = Date.now();
757
+
758
+ this.log('Starting V2 Compatibility Validation...');
759
+
760
+ this.log('Validating CLI commands...');
761
+ const cliResult = await this.validateCLI();
762
+
763
+ this.log('Validating MCP tools...');
764
+ const mcpResult = await this.validateMCPTools();
765
+
766
+ this.log('Validating hooks...');
767
+ const hooksResult = await this.validateHooks();
768
+
769
+ this.log('Validating API interfaces...');
770
+ const apiResult = await this.validateAPI();
771
+
772
+ const totalChecks = cliResult.totalChecks + mcpResult.totalChecks + hooksResult.totalChecks + apiResult.totalChecks;
773
+ const passedChecks = cliResult.passedChecks + mcpResult.passedChecks + hooksResult.passedChecks + apiResult.passedChecks;
774
+ const failedChecks = totalChecks - passedChecks;
775
+ const breakingChanges = cliResult.breakingChanges + mcpResult.breakingChanges + hooksResult.breakingChanges + apiResult.breakingChanges;
776
+
777
+ const overallPassed = breakingChanges === 0;
778
+
779
+ const recommendations = this.generateRecommendations(cliResult, mcpResult, hooksResult, apiResult);
780
+
781
+ const report: FullValidationReport = {
782
+ timestamp: new Date(),
783
+ v2Version: this.v2Version,
784
+ v3Version: this.v3Version,
785
+ overallPassed,
786
+ totalChecks,
787
+ passedChecks,
788
+ failedChecks,
789
+ breakingChanges,
790
+ cli: cliResult,
791
+ mcp: mcpResult,
792
+ hooks: hooksResult,
793
+ api: apiResult,
794
+ summary: this.generateSummary(cliResult, mcpResult, hooksResult, apiResult, overallPassed),
795
+ recommendations,
796
+ duration: Date.now() - startTime,
797
+ };
798
+
799
+ this.log('Validation complete.');
800
+
801
+ return report;
802
+ }
803
+
804
+ /**
805
+ * Generate recommendations based on results
806
+ */
807
+ private generateRecommendations(
808
+ cli: ValidationResult,
809
+ mcp: ValidationResult,
810
+ hooks: ValidationResult,
811
+ api: ValidationResult
812
+ ): string[] {
813
+ const recommendations: string[] = [];
814
+
815
+ if (cli.breakingChanges > 0) {
816
+ recommendations.push('Update CLI command calls to use V3 equivalents');
817
+ recommendations.push('Run migration script: npx @sparkleideas/cli migrate');
818
+ }
819
+
820
+ if (mcp.breakingChanges > 0) {
821
+ recommendations.push('Enable V2 compatibility mode in MCP server configuration');
822
+ recommendations.push('Update tool calls to use new naming convention (e.g., agent/spawn)');
823
+ }
824
+
825
+ if (hooks.breakingChanges > 0) {
826
+ recommendations.push('Review hook configuration for renamed or removed hooks');
827
+ recommendations.push('Update hook listeners to use V3 event names');
828
+ }
829
+
830
+ if (api.breakingChanges > 0) {
831
+ recommendations.push('Update import statements to use @sparkleideas/* packages');
832
+ recommendations.push('Use provided import aliases for backward compatibility');
833
+ }
834
+
835
+ if (cli.passedChecks < cli.totalChecks) {
836
+ recommendations.push('Some CLI aliases may not be directly supported - use canonical command names');
837
+ }
838
+
839
+ if (mcp.passedChecks < mcp.totalChecks) {
840
+ recommendations.push('Consider using tool name translation layer for gradual migration');
841
+ }
842
+
843
+ if (recommendations.length === 0) {
844
+ recommendations.push('No migration actions required - V2 code is fully compatible');
845
+ }
846
+
847
+ return recommendations;
848
+ }
849
+
850
+ /**
851
+ * Generate human-readable summary
852
+ */
853
+ private generateSummary(
854
+ cli: ValidationResult,
855
+ mcp: ValidationResult,
856
+ hooks: ValidationResult,
857
+ api: ValidationResult,
858
+ overallPassed: boolean
859
+ ): string {
860
+ const lines: string[] = [
861
+ '='.repeat(70),
862
+ ' V2 COMPATIBILITY VALIDATION REPORT',
863
+ '='.repeat(70),
864
+ '',
865
+ `Status: ${overallPassed ? 'PASSED - No breaking changes detected' : 'FAILED - Breaking changes detected'}`,
866
+ '',
867
+ 'Category Summary:',
868
+ '-'.repeat(70),
869
+ `CLI Commands: ${cli.passedChecks}/${cli.totalChecks} passed (${cli.breakingChanges} breaking)`,
870
+ `MCP Tools: ${mcp.passedChecks}/${mcp.totalChecks} passed (${mcp.breakingChanges} breaking)`,
871
+ `Hooks: ${hooks.passedChecks}/${hooks.totalChecks} passed (${hooks.breakingChanges} breaking)`,
872
+ `API Interfaces: ${api.passedChecks}/${api.totalChecks} passed (${api.breakingChanges} breaking)`,
873
+ '-'.repeat(70),
874
+ '',
875
+ ];
876
+
877
+ if (!overallPassed) {
878
+ lines.push('Breaking Changes Detected:');
879
+ lines.push('');
880
+
881
+ const allBreaking = [
882
+ ...cli.checks.filter(c => c.breaking).map(c => ` CLI: ${c.name}`),
883
+ ...mcp.checks.filter(c => c.breaking).map(c => ` MCP: ${c.name}`),
884
+ ...hooks.checks.filter(c => c.breaking).map(c => ` Hooks: ${c.name}`),
885
+ ...api.checks.filter(c => c.breaking).map(c => ` API: ${c.name}`),
886
+ ].slice(0, 20);
887
+
888
+ lines.push(...allBreaking);
889
+
890
+ if (cli.breakingChanges + mcp.breakingChanges + hooks.breakingChanges + api.breakingChanges > 20) {
891
+ lines.push(` ... and ${cli.breakingChanges + mcp.breakingChanges + hooks.breakingChanges + api.breakingChanges - 20} more`);
892
+ }
893
+
894
+ lines.push('');
895
+ }
896
+
897
+ lines.push('='.repeat(70));
898
+
899
+ return lines.join('\n');
900
+ }
901
+
902
+ /**
903
+ * Log message if verbose mode is enabled
904
+ */
905
+ private log(message: string): void {
906
+ if (this.verbose) {
907
+ console.log(`[V2Compat] ${message}`);
908
+ }
909
+ }
910
+ }
911
+
912
+ /**
913
+ * Generate markdown compatibility report
914
+ */
915
+ export function generateCompatibilityReport(report: FullValidationReport): string {
916
+ const lines: string[] = [
917
+ '# V2 Compatibility Validation Report',
918
+ '',
919
+ `> Generated: ${report.timestamp.toISOString()}`,
920
+ `> V2 Version: ${report.v2Version}`,
921
+ `> V3 Version: ${report.v3Version}`,
922
+ '',
923
+ '## Executive Summary',
924
+ '',
925
+ `**Status**: ${report.overallPassed ? 'PASSED' : 'FAILED'}`,
926
+ '',
927
+ '| Metric | Value |',
928
+ '|--------|-------|',
929
+ `| Total Checks | ${report.totalChecks} |`,
930
+ `| Passed | ${report.passedChecks} |`,
931
+ `| Failed | ${report.failedChecks} |`,
932
+ `| Breaking Changes | ${report.breakingChanges} |`,
933
+ `| Duration | ${report.duration}ms |`,
934
+ '',
935
+ '## Category Results',
936
+ '',
937
+ '### CLI Commands',
938
+ '',
939
+ `- **Total**: ${report.cli.totalChecks}`,
940
+ `- **Passed**: ${report.cli.passedChecks}`,
941
+ `- **Failed**: ${report.cli.failedChecks}`,
942
+ `- **Breaking**: ${report.cli.breakingChanges}`,
943
+ '',
944
+ '| Command | Status | Migration |',
945
+ '|---------|--------|-----------|',
946
+ ...report.cli.checks
947
+ .filter(c => c.name.startsWith('CLI:'))
948
+ .slice(0, 30)
949
+ .map(c => `| ${c.name.replace('CLI: ', '')} | ${c.passed ? 'OK' : 'FAIL'} | ${c.migrationPath || 'N/A'} |`),
950
+ '',
951
+ '### MCP Tools',
952
+ '',
953
+ `- **Total**: ${report.mcp.totalChecks}`,
954
+ `- **Passed**: ${report.mcp.passedChecks}`,
955
+ `- **Failed**: ${report.mcp.failedChecks}`,
956
+ `- **Breaking**: ${report.mcp.breakingChanges}`,
957
+ '',
958
+ '| Tool | Status | V3 Equivalent |',
959
+ '|------|--------|---------------|',
960
+ ...report.mcp.checks
961
+ .filter(c => c.name.startsWith('MCP Tool:'))
962
+ .slice(0, 40)
963
+ .map(c => {
964
+ const v3Name = c.details?.v3Equivalent as string || 'N/A';
965
+ return `| ${c.name.replace('MCP Tool: ', '')} | ${c.passed ? 'OK' : 'FAIL'} | ${v3Name} |`;
966
+ }),
967
+ '',
968
+ '### Hooks',
969
+ '',
970
+ `- **Total**: ${report.hooks.totalChecks}`,
971
+ `- **Passed**: ${report.hooks.passedChecks}`,
972
+ `- **Failed**: ${report.hooks.failedChecks}`,
973
+ `- **Breaking**: ${report.hooks.breakingChanges}`,
974
+ '',
975
+ '| Hook | Status | V3 Trigger |',
976
+ '|------|--------|------------|',
977
+ ...report.hooks.checks
978
+ .filter(c => c.name.startsWith('Hook:') && !c.name.includes('Param') && !c.name.includes('Return'))
979
+ .slice(0, 50)
980
+ .map(c => {
981
+ const v3Name = c.details?.v3Equivalent as string || 'N/A';
982
+ return `| ${c.name.replace('Hook: ', '')} | ${c.passed ? 'OK' : 'FAIL'} | ${v3Name} |`;
983
+ }),
984
+ '',
985
+ '### API Interfaces',
986
+ '',
987
+ `- **Total**: ${report.api.totalChecks}`,
988
+ `- **Passed**: ${report.api.passedChecks}`,
989
+ `- **Failed**: ${report.api.failedChecks}`,
990
+ `- **Breaking**: ${report.api.breakingChanges}`,
991
+ '',
992
+ '| Interface/Method | Status | Migration |',
993
+ '|------------------|--------|-----------|',
994
+ ...report.api.checks
995
+ .slice(0, 30)
996
+ .map(c => `| ${c.name.replace('API ', '')} | ${c.passed ? 'OK' : 'FAIL'} | ${c.migrationPath || 'N/A'} |`),
997
+ '',
998
+ '## Breaking Changes',
999
+ '',
1000
+ ];
1001
+
1002
+ const breakingChecks = [
1003
+ ...report.cli.checks.filter(c => c.breaking),
1004
+ ...report.mcp.checks.filter(c => c.breaking),
1005
+ ...report.hooks.checks.filter(c => c.breaking),
1006
+ ...report.api.checks.filter(c => c.breaking),
1007
+ ];
1008
+
1009
+ if (breakingChecks.length === 0) {
1010
+ lines.push('No breaking changes detected.');
1011
+ } else {
1012
+ lines.push('| Category | Item | V2 Behavior | V3 Behavior |');
1013
+ lines.push('|----------|------|-------------|-------------|');
1014
+ for (const check of breakingChecks.slice(0, 50)) {
1015
+ lines.push(`| ${check.category.toUpperCase()} | ${check.name} | ${check.v2Behavior} | ${check.v3Behavior} |`);
1016
+ }
1017
+ }
1018
+
1019
+ lines.push('');
1020
+ lines.push('## Recommendations');
1021
+ lines.push('');
1022
+ for (const rec of report.recommendations) {
1023
+ lines.push(`- ${rec}`);
1024
+ }
1025
+
1026
+ lines.push('');
1027
+ lines.push('## Migration Guide');
1028
+ lines.push('');
1029
+ lines.push('### CLI Migration');
1030
+ lines.push('');
1031
+ lines.push('```bash');
1032
+ lines.push('# V2 commands are supported via compatibility layer');
1033
+ lines.push('# Deprecated commands will show warnings');
1034
+ lines.push('');
1035
+ lines.push('# V2 (deprecated)');
1036
+ lines.push('npx claude-flow hive-mind init');
1037
+ lines.push('');
1038
+ lines.push('# V3 (recommended)');
1039
+ lines.push('npx @sparkleideas/cli swarm init');
1040
+ lines.push('```');
1041
+ lines.push('');
1042
+ lines.push('### MCP Tool Migration');
1043
+ lines.push('');
1044
+ lines.push('```typescript');
1045
+ lines.push('// V2 tool call');
1046
+ lines.push("await mcp.callTool('dispatch_agent', { type: 'coder' });");
1047
+ lines.push('');
1048
+ lines.push('// V3 tool call (direct)');
1049
+ lines.push("await mcp.callTool('agent/spawn', { agentType: 'coder' });");
1050
+ lines.push('');
1051
+ lines.push('// V3 with compatibility layer');
1052
+ lines.push("await mcp.callTool('dispatch_agent', { type: 'coder' }); // Auto-translated");
1053
+ lines.push('```');
1054
+ lines.push('');
1055
+ lines.push('### API Migration');
1056
+ lines.push('');
1057
+ lines.push('```typescript');
1058
+ lines.push("// V2 imports");
1059
+ lines.push("import { HiveMind } from 'claude-flow/hive-mind';");
1060
+ lines.push("import { SwarmCoordinator } from 'claude-flow/swarm';");
1061
+ lines.push('');
1062
+ lines.push("// V3 imports (using aliases)");
1063
+ lines.push("import { UnifiedSwarmCoordinator as HiveMind } from '@sparkleideas/swarm';");
1064
+ lines.push("import { UnifiedSwarmCoordinator as SwarmCoordinator } from '@sparkleideas/swarm';");
1065
+ lines.push('```');
1066
+ lines.push('');
1067
+ lines.push('---');
1068
+ lines.push('');
1069
+ lines.push('*Report generated by V2CompatibilityValidator*');
1070
+
1071
+ return lines.join('\n');
1072
+ }