enhance_swarm 1.0.0

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 (64) hide show
  1. checksums.yaml +7 -0
  2. data/.enhance_swarm/agent_scripts/frontend_agent.md +39 -0
  3. data/.enhance_swarm/user_patterns.json +37 -0
  4. data/CHANGELOG.md +184 -0
  5. data/LICENSE +21 -0
  6. data/PRODUCTION_TEST_LOG.md +502 -0
  7. data/README.md +905 -0
  8. data/Rakefile +28 -0
  9. data/USAGE_EXAMPLES.md +477 -0
  10. data/examples/enhance_workflow.md +346 -0
  11. data/examples/rails_project.md +253 -0
  12. data/exe/enhance-swarm +30 -0
  13. data/lib/enhance_swarm/additional_commands.rb +299 -0
  14. data/lib/enhance_swarm/agent_communicator.rb +460 -0
  15. data/lib/enhance_swarm/agent_reviewer.rb +283 -0
  16. data/lib/enhance_swarm/agent_spawner.rb +462 -0
  17. data/lib/enhance_swarm/cleanup_manager.rb +245 -0
  18. data/lib/enhance_swarm/cli.rb +1592 -0
  19. data/lib/enhance_swarm/command_executor.rb +78 -0
  20. data/lib/enhance_swarm/configuration.rb +324 -0
  21. data/lib/enhance_swarm/control_agent.rb +307 -0
  22. data/lib/enhance_swarm/dependency_validator.rb +195 -0
  23. data/lib/enhance_swarm/error_recovery.rb +785 -0
  24. data/lib/enhance_swarm/generator.rb +194 -0
  25. data/lib/enhance_swarm/interrupt_handler.rb +512 -0
  26. data/lib/enhance_swarm/logger.rb +106 -0
  27. data/lib/enhance_swarm/mcp_integration.rb +85 -0
  28. data/lib/enhance_swarm/monitor.rb +28 -0
  29. data/lib/enhance_swarm/notification_manager.rb +444 -0
  30. data/lib/enhance_swarm/orchestrator.rb +313 -0
  31. data/lib/enhance_swarm/output_streamer.rb +281 -0
  32. data/lib/enhance_swarm/process_monitor.rb +266 -0
  33. data/lib/enhance_swarm/progress_tracker.rb +215 -0
  34. data/lib/enhance_swarm/project_analyzer.rb +612 -0
  35. data/lib/enhance_swarm/resource_manager.rb +177 -0
  36. data/lib/enhance_swarm/retry_handler.rb +40 -0
  37. data/lib/enhance_swarm/session_manager.rb +247 -0
  38. data/lib/enhance_swarm/signal_handler.rb +95 -0
  39. data/lib/enhance_swarm/smart_defaults.rb +708 -0
  40. data/lib/enhance_swarm/task_integration.rb +150 -0
  41. data/lib/enhance_swarm/task_manager.rb +174 -0
  42. data/lib/enhance_swarm/version.rb +5 -0
  43. data/lib/enhance_swarm/visual_dashboard.rb +555 -0
  44. data/lib/enhance_swarm/web_ui.rb +211 -0
  45. data/lib/enhance_swarm.rb +69 -0
  46. data/setup.sh +86 -0
  47. data/sig/enhance_swarm.rbs +4 -0
  48. data/templates/claude/CLAUDE.md +160 -0
  49. data/templates/claude/MCP.md +117 -0
  50. data/templates/claude/PERSONAS.md +114 -0
  51. data/templates/claude/RULES.md +221 -0
  52. data/test_builtin_functionality.rb +121 -0
  53. data/test_core_components.rb +156 -0
  54. data/test_real_claude_integration.rb +285 -0
  55. data/test_security.rb +150 -0
  56. data/test_smart_defaults.rb +155 -0
  57. data/test_task_integration.rb +173 -0
  58. data/test_web_ui.rb +245 -0
  59. data/web/assets/css/main.css +645 -0
  60. data/web/assets/js/kanban.js +499 -0
  61. data/web/assets/js/main.js +525 -0
  62. data/web/templates/dashboard.html.erb +226 -0
  63. data/web/templates/kanban.html.erb +193 -0
  64. metadata +293 -0
@@ -0,0 +1,194 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'erb'
4
+ require 'fileutils'
5
+ require_relative 'command_executor'
6
+
7
+ module EnhanceSwarm
8
+ class Generator
9
+ def initialize
10
+ @config = EnhanceSwarm.configuration
11
+ @template_dir = File.expand_path('../../templates', __dir__)
12
+ end
13
+
14
+ def init_project
15
+ create_directories
16
+ create_config_file
17
+ generate_claude_files
18
+ generate_git_hooks
19
+ setup_task_management
20
+
21
+ puts '✅ Project initialized with EnhanceSwarm'
22
+ end
23
+
24
+ def generate_claude_files
25
+ claude_dir = File.join(EnhanceSwarm.root, '.claude')
26
+ FileUtils.mkdir_p(claude_dir)
27
+
28
+ # Generate main Claude files
29
+ %w[CLAUDE.md RULES.md MCP.md PERSONAS.md].each do |file|
30
+ generate_from_template(
31
+ "claude/#{file}",
32
+ File.join(claude_dir, file)
33
+ )
34
+ end
35
+
36
+ puts '✅ Generated Claude configuration files in .claude/'
37
+ end
38
+
39
+ def generate_mcp_config
40
+ mcp_dir = File.join(EnhanceSwarm.root, '.mcp')
41
+ FileUtils.mkdir_p(mcp_dir)
42
+
43
+ # Generate MCP configuration
44
+ config = {
45
+ 'tools' => {
46
+ 'gemini' => {
47
+ 'enabled' => @config.gemini_enabled,
48
+ 'command' => 'gemini',
49
+ 'description' => 'Large context analysis with Gemini CLI'
50
+ },
51
+ 'desktop_commander' => {
52
+ 'enabled' => @config.desktop_commander_enabled,
53
+ 'description' => 'File operations outside project directory'
54
+ }
55
+ }
56
+ }
57
+
58
+ File.write(
59
+ File.join(mcp_dir, 'config.json'),
60
+ JSON.pretty_generate(config)
61
+ )
62
+
63
+ puts '✅ Generated MCP configuration'
64
+ end
65
+
66
+ def generate_git_hooks
67
+ hooks_dir = File.join(EnhanceSwarm.root, '.git', 'hooks')
68
+ FileUtils.mkdir_p(hooks_dir)
69
+
70
+ # Pre-commit hook with sanitized command
71
+ safe_test_command = sanitize_shell_command(@config.test_command)
72
+ pre_commit = <<~HOOK
73
+ #!/bin/bash
74
+ # EnhanceSwarm pre-commit hook
75
+
76
+ # Run tests before committing
77
+ echo "Running tests..."
78
+ #{safe_test_command}
79
+
80
+ if [ $? -ne 0 ]; then
81
+ echo "❌ Tests failed! Please fix before committing."
82
+ exit 1
83
+ fi
84
+
85
+ echo "✅ All tests passed!"
86
+ HOOK
87
+
88
+ hook_path = File.join(hooks_dir, 'pre-commit')
89
+ File.write(hook_path, pre_commit)
90
+ File.chmod(0o755, hook_path)
91
+
92
+ puts '✅ Generated Git hooks'
93
+ end
94
+
95
+ def setup_task_management
96
+ # Check if swarm-tasks is available
97
+
98
+ CommandExecutor.execute('gem', 'list', 'swarm_tasks', '-i')
99
+ puts '✅ swarm_tasks gem detected'
100
+ rescue CommandExecutor::CommandError
101
+ # Create basic task directories
102
+ %w[backlog active completed].each do |state|
103
+ FileUtils.mkdir_p(File.join(EnhanceSwarm.root, 'tasks', state))
104
+ end
105
+
106
+ puts '⚠️ swarm_tasks gem not found. Created basic task directories.'
107
+ puts ' Install with: gem install swarm_tasks'
108
+ end
109
+
110
+ private
111
+
112
+ def create_directories
113
+ dirs = [
114
+ '.claude',
115
+ '.claude/agents',
116
+ '.claude/automation',
117
+ '.mcp',
118
+ 'tasks/backlog',
119
+ 'tasks/active',
120
+ 'tasks/completed'
121
+ ]
122
+
123
+ dirs.each do |dir|
124
+ FileUtils.mkdir_p(File.join(EnhanceSwarm.root, dir))
125
+ end
126
+ end
127
+
128
+ def create_config_file
129
+ config_path = File.join(EnhanceSwarm.root, '.enhance_swarm.yml')
130
+
131
+ return if File.exist?(config_path)
132
+
133
+ @config.save!
134
+ puts '✅ Created .enhance_swarm.yml configuration file'
135
+ end
136
+
137
+ def generate_from_template(template_name, output_path)
138
+ template_path = File.join(@template_dir, template_name)
139
+
140
+ unless File.exist?(template_path)
141
+ puts "⚠️ Template not found: #{template_name}"
142
+ return
143
+ end
144
+
145
+ # Read template
146
+ template_content = File.read(template_path)
147
+ erb = ERB.new(template_content)
148
+
149
+ # Render with configuration
150
+ rendered = erb.result(binding)
151
+
152
+ # Write output
153
+ File.write(output_path, rendered)
154
+ end
155
+
156
+ # Helper methods for ERB templates
157
+ def project_name
158
+ @config.project_name
159
+ end
160
+
161
+ def project_description
162
+ @config.project_description
163
+ end
164
+
165
+ def technology_stack
166
+ @config.technology_stack
167
+ end
168
+
169
+ def test_command
170
+ @config.test_command
171
+ end
172
+
173
+ def task_command
174
+ @config.task_command
175
+ end
176
+
177
+ def task_move_command
178
+ @config.task_move_command
179
+ end
180
+
181
+ def code_standards
182
+ @config.code_standards.join("\n")
183
+ end
184
+
185
+ def important_notes
186
+ @config.important_notes.join("\n")
187
+ end
188
+
189
+ def sanitize_shell_command(command)
190
+ # Remove dangerous shell metacharacters while preserving basic functionality
191
+ command.to_s.gsub(/[;&|`$\\]/, '').strip
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,512 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'io/console'
4
+
5
+ module EnhanceSwarm
6
+ class InterruptHandler
7
+ STUCK_THRESHOLD = 600 # 10 minutes
8
+ MEMORY_THRESHOLD = 1000 # 1GB in MB
9
+ RESPONSE_TIMEOUT = 30 # 30 seconds for user response
10
+
11
+ def initialize(notification_manager = nil)
12
+ @notification_manager = notification_manager || NotificationManager.instance
13
+ @interrupts_enabled = true
14
+ @monitoring_active = false
15
+ @user_responses = {}
16
+ end
17
+
18
+ def start_monitoring(agents)
19
+ return if @monitoring_active
20
+
21
+ @monitoring_active = true
22
+ @monitoring_thread = Thread.new do
23
+ monitor_for_interrupts(agents)
24
+ end
25
+ end
26
+
27
+ def stop_monitoring
28
+ @monitoring_active = false
29
+ @monitoring_thread&.kill
30
+ @monitoring_thread = nil
31
+ end
32
+
33
+ def handle_agent_stuck(agent)
34
+ return unless @interrupts_enabled
35
+
36
+ agent_id = agent[:id]
37
+ role = agent[:role]
38
+ last_activity = agent[:last_activity]
39
+ current_task = agent[:current_task]
40
+
41
+ # Calculate how long stuck
42
+ time_stuck = Time.now - last_activity
43
+
44
+ # Only interrupt if stuck for significant time
45
+ return unless time_stuck > STUCK_THRESHOLD
46
+
47
+ # Show stuck notification
48
+ @notification_manager.agent_stuck(agent_id, role, last_activity, current_task)
49
+
50
+ # Prompt user for action with timeout
51
+ response = prompt_user_with_timeout(
52
+ "Agent '#{role}' stuck for #{format_duration(time_stuck)}. Restart? [y/N]",
53
+ timeout: RESPONSE_TIMEOUT,
54
+ default: 'n'
55
+ )
56
+
57
+ case response.downcase
58
+ when 'y', 'yes'
59
+ restart_agent(agent)
60
+ when 'k', 'kill'
61
+ kill_agent(agent)
62
+ when 'd', 'debug'
63
+ debug_agent(agent)
64
+ else
65
+ puts "Continuing to monitor agent '#{role}'...".colorize(:yellow)
66
+ end
67
+ end
68
+
69
+ def handle_agent_excessive_memory(agent)
70
+ return unless @interrupts_enabled
71
+
72
+ memory_mb = agent[:memory_mb]
73
+ return unless memory_mb > MEMORY_THRESHOLD
74
+
75
+ agent_id = agent[:id]
76
+ role = agent[:role]
77
+
78
+ @notification_manager.intervention_needed(
79
+ "Agent '#{role}' using #{memory_mb}MB memory",
80
+ agent_id,
81
+ [
82
+ "enhance-swarm restart #{agent_id}",
83
+ "enhance-swarm kill #{agent_id}",
84
+ "Continue monitoring"
85
+ ]
86
+ )
87
+
88
+ response = prompt_user_with_timeout(
89
+ "Agent '#{role}' using #{memory_mb}MB. Action? [r]estart/[k]ill/[c]ontinue",
90
+ timeout: RESPONSE_TIMEOUT,
91
+ default: 'c'
92
+ )
93
+
94
+ case response.downcase
95
+ when 'r', 'restart'
96
+ restart_agent(agent)
97
+ when 'k', 'kill'
98
+ kill_agent(agent)
99
+ else
100
+ puts "Continuing to monitor agent '#{role}'...".colorize(:yellow)
101
+ end
102
+ end
103
+
104
+ def handle_coordination_conflict(agents, conflict_type, details = {})
105
+ return unless @interrupts_enabled
106
+
107
+ case conflict_type
108
+ when :file_conflict
109
+ handle_file_conflict(agents, details)
110
+ when :dependency_deadlock
111
+ handle_dependency_deadlock(agents, details)
112
+ when :resource_contention
113
+ handle_resource_contention(agents, details)
114
+ end
115
+ end
116
+
117
+ def handle_critical_error(agent, error, context = {})
118
+ return unless @interrupts_enabled
119
+
120
+ agent_id = agent[:id]
121
+ role = agent[:role]
122
+
123
+ # Analyze error for suggested fixes
124
+ suggestions = analyze_error_for_suggestions(error, context)
125
+
126
+ @notification_manager.agent_failed(agent_id, role, error.message, suggestions)
127
+
128
+ if suggestions.any?
129
+ puts "\nError analysis complete. Choose an action:".colorize(:red)
130
+ suggestions.each_with_index do |suggestion, index|
131
+ puts " #{index + 1}. #{suggestion}".colorize(:yellow)
132
+ end
133
+ puts " c. Enter custom command".colorize(:blue)
134
+
135
+ response = prompt_user_with_timeout(
136
+ "Choose [1-#{suggestions.length}] or [c]ustom:",
137
+ timeout: RESPONSE_TIMEOUT,
138
+ default: '1'
139
+ )
140
+
141
+ execute_error_recovery(agent, response, suggestions)
142
+ end
143
+ end
144
+
145
+ # Enable/disable interrupts
146
+ def enable_interrupts!
147
+ @interrupts_enabled = true
148
+ puts "✅ Interrupts enabled - will prompt for stuck/failed agents".colorize(:green)
149
+ end
150
+
151
+ def disable_interrupts!
152
+ @interrupts_enabled = false
153
+ puts "🔇 Interrupts disabled - agents will run without intervention".colorize(:yellow)
154
+ end
155
+
156
+ def interrupts_enabled?
157
+ @interrupts_enabled
158
+ end
159
+
160
+ private
161
+
162
+ def monitor_for_interrupts(agents)
163
+ while @monitoring_active
164
+ agents.each do |agent|
165
+ next unless agent_needs_attention?(agent)
166
+
167
+ # Check for stuck agents
168
+ if agent_stuck?(agent)
169
+ handle_agent_stuck(agent)
170
+ end
171
+
172
+ # Check for memory issues
173
+ if agent_excessive_memory?(agent)
174
+ handle_agent_excessive_memory(agent)
175
+ end
176
+
177
+ # Check for process issues
178
+ unless process_healthy?(agent)
179
+ handle_process_issue(agent)
180
+ end
181
+ end
182
+
183
+ sleep(30) # Check every 30 seconds
184
+ end
185
+ rescue StandardError => e
186
+ Logger.error("Interrupt monitoring error: #{e.message}")
187
+ end
188
+
189
+ def agent_needs_attention?(agent)
190
+ agent_stuck?(agent) ||
191
+ agent_excessive_memory?(agent) ||
192
+ !process_healthy?(agent)
193
+ end
194
+
195
+ def agent_stuck?(agent)
196
+ return false unless agent[:last_activity]
197
+
198
+ Time.now - agent[:last_activity] > STUCK_THRESHOLD
199
+ end
200
+
201
+ def agent_excessive_memory?(agent)
202
+ return false unless agent[:memory_mb]
203
+
204
+ agent[:memory_mb] > MEMORY_THRESHOLD
205
+ end
206
+
207
+ def process_healthy?(agent)
208
+ return true unless agent[:pid]
209
+
210
+ begin
211
+ Process.kill(0, agent[:pid])
212
+ true
213
+ rescue Errno::ESRCH
214
+ false
215
+ rescue Errno::EPERM
216
+ true # Process exists but we can't signal it
217
+ end
218
+ end
219
+
220
+ def prompt_user_with_timeout(prompt, timeout: 30, default: nil)
221
+ puts prompt.colorize(:blue)
222
+
223
+ if default
224
+ puts "(Auto-selecting '#{default}' in #{timeout}s if no response)".colorize(:light_black)
225
+ end
226
+
227
+ # Set up timeout
228
+ response = nil
229
+ input_thread = Thread.new do
230
+ response = $stdin.gets&.chomp
231
+ end
232
+
233
+ # Wait for input or timeout
234
+ unless input_thread.join(timeout)
235
+ input_thread.kill
236
+ puts "\nTimeout reached, using default: '#{default}'".colorize(:yellow)
237
+ response = default
238
+ end
239
+
240
+ response || default || ''
241
+ end
242
+
243
+ def restart_agent(agent)
244
+ agent_id = agent[:id]
245
+ role = agent[:role]
246
+
247
+ puts "🔄 Restarting agent '#{role}'...".colorize(:yellow)
248
+
249
+ begin
250
+ # Kill existing process
251
+ if agent[:pid]
252
+ Process.kill('TERM', agent[:pid])
253
+ sleep(2)
254
+ Process.kill('KILL', agent[:pid]) rescue nil
255
+ end
256
+
257
+ # Clean up resources
258
+ cleanup_agent_resources(agent)
259
+
260
+ # Restart with same task
261
+ new_pid = spawn_agent_replacement(agent)
262
+
263
+ if new_pid
264
+ puts "✅ Agent '#{role}' restarted with PID #{new_pid}".colorize(:green)
265
+ @notification_manager.notify(:agent_completed, "Agent '#{role}' restarted successfully")
266
+ else
267
+ puts "❌ Failed to restart agent '#{role}'".colorize(:red)
268
+ end
269
+
270
+ rescue StandardError => e
271
+ puts "❌ Error restarting agent: #{e.message}".colorize(:red)
272
+ Logger.error("Failed to restart agent #{agent_id}: #{e.message}")
273
+ end
274
+ end
275
+
276
+ def kill_agent(agent)
277
+ agent_id = agent[:id]
278
+ role = agent[:role]
279
+
280
+ puts "🛑 Killing agent '#{role}'...".colorize(:red)
281
+
282
+ begin
283
+ if agent[:pid]
284
+ Process.kill('KILL', agent[:pid])
285
+ puts "✅ Agent '#{role}' terminated".colorize(:green)
286
+ end
287
+
288
+ cleanup_agent_resources(agent)
289
+ @notification_manager.notify(:agent_completed, "Agent '#{role}' terminated by user")
290
+
291
+ rescue StandardError => e
292
+ puts "❌ Error killing agent: #{e.message}".colorize(:red)
293
+ Logger.error("Failed to kill agent #{agent_id}: #{e.message}")
294
+ end
295
+ end
296
+
297
+ def debug_agent(agent)
298
+ agent_id = agent[:id]
299
+ role = agent[:role]
300
+
301
+ puts "🔍 Debugging agent '#{role}'...".colorize(:blue)
302
+
303
+ # Show agent details
304
+ puts "\nAgent Details:".colorize(:blue)
305
+ puts " ID: #{agent_id}"
306
+ puts " Role: #{role}"
307
+ puts " PID: #{agent[:pid]}"
308
+ puts " Last Activity: #{agent[:last_activity]}"
309
+ puts " Current Task: #{agent[:current_task] || 'Unknown'}"
310
+ puts " Memory: #{agent[:memory_mb]}MB" if agent[:memory_mb]
311
+
312
+ # Show recent logs
313
+ show_agent_logs(agent)
314
+
315
+ # Show worktree status
316
+ show_agent_worktree_status(agent)
317
+ end
318
+
319
+ def handle_file_conflict(agents, details)
320
+ conflicted_file = details[:file]
321
+ conflicting_agents = details[:agents] || agents.select { |a| a[:status] == 'active' }
322
+
323
+ @notification_manager.intervention_needed(
324
+ "File conflict detected: #{conflicted_file}",
325
+ nil,
326
+ [
327
+ "Pause conflicting agents",
328
+ "Merge changes manually",
329
+ "Restart with coordination"
330
+ ]
331
+ )
332
+
333
+ response = prompt_user_with_timeout(
334
+ "File conflict in #{conflicted_file}. Action? [p]ause/[m]erge/[r]estart",
335
+ timeout: RESPONSE_TIMEOUT,
336
+ default: 'p'
337
+ )
338
+
339
+ case response.downcase
340
+ when 'p', 'pause'
341
+ pause_conflicting_agents(conflicting_agents)
342
+ when 'm', 'merge'
343
+ initiate_manual_merge(conflicted_file, conflicting_agents)
344
+ when 'r', 'restart'
345
+ restart_with_coordination(conflicting_agents)
346
+ end
347
+ end
348
+
349
+ def handle_dependency_deadlock(agents, details)
350
+ @notification_manager.intervention_needed(
351
+ "Dependency deadlock detected between agents",
352
+ nil,
353
+ ["Restart with updated dependencies", "Manual intervention"]
354
+ )
355
+
356
+ # Implementation for dependency deadlock resolution
357
+ puts "🔄 Resolving dependency deadlock...".colorize(:yellow)
358
+ end
359
+
360
+ def handle_resource_contention(agents, details)
361
+ resource = details[:resource]
362
+
363
+ @notification_manager.intervention_needed(
364
+ "Resource contention for #{resource}",
365
+ nil,
366
+ ["Serialize access", "Increase resources"]
367
+ )
368
+ end
369
+
370
+ def analyze_error_for_suggestions(error, context)
371
+ suggestions = []
372
+ error_message = error.message.downcase
373
+
374
+ case error_message
375
+ when /timeout/
376
+ suggestions << "enhance-swarm restart #{context[:agent_id]} --timeout=300"
377
+ suggestions << "Check network connectivity"
378
+ when /permission denied/
379
+ suggestions << "Check file permissions"
380
+ suggestions << "Run with appropriate privileges"
381
+ when /no such file/
382
+ suggestions << "Verify file paths and dependencies"
383
+ suggestions << "Regenerate missing files"
384
+ when /memory|out of space/
385
+ suggestions << "enhance-swarm cleanup --all"
386
+ suggestions << "Increase available memory"
387
+ when /git/
388
+ suggestions << "Fix git repository state"
389
+ suggestions << "Reset to clean state"
390
+ else
391
+ suggestions << "enhance-swarm restart #{context[:agent_id]}"
392
+ suggestions << "Check logs for more details"
393
+ end
394
+
395
+ suggestions
396
+ end
397
+
398
+ def execute_error_recovery(agent, response, suggestions)
399
+ case response
400
+ when /^\d+$/
401
+ index = response.to_i - 1
402
+ if index >= 0 && index < suggestions.length
403
+ suggestion = suggestions[index]
404
+ puts "Executing: #{suggestion}".colorize(:blue)
405
+
406
+ if suggestion.start_with?('enhance-swarm')
407
+ execute_enhance_swarm_command(suggestion)
408
+ else
409
+ puts "Manual action required: #{suggestion}".colorize(:yellow)
410
+ end
411
+ end
412
+ when 'c', 'custom'
413
+ custom_command = prompt_user_with_timeout("Enter custom command:", timeout: 60)
414
+ if custom_command && !custom_command.empty?
415
+ execute_custom_recovery_command(custom_command, agent)
416
+ end
417
+ end
418
+ end
419
+
420
+ def execute_enhance_swarm_command(command)
421
+ # Parse and execute enhance-swarm commands
422
+ parts = command.split(' ')
423
+ if parts.first == 'enhance-swarm'
424
+ puts "This would execute: #{command}".colorize(:blue)
425
+ # In real implementation, this would call the appropriate CLI method
426
+ end
427
+ end
428
+
429
+ def execute_custom_recovery_command(command, agent)
430
+ puts "Executing custom recovery: #{command}".colorize(:blue)
431
+
432
+ begin
433
+ CommandExecutor.execute('bash', '-c', command)
434
+ puts "✅ Custom recovery command completed".colorize(:green)
435
+ rescue StandardError => e
436
+ puts "❌ Custom recovery failed: #{e.message}".colorize(:red)
437
+ end
438
+ end
439
+
440
+ def format_duration(seconds)
441
+ if seconds < 60
442
+ "#{seconds.round}s"
443
+ elsif seconds < 3600
444
+ "#{(seconds / 60).round}m"
445
+ else
446
+ "#{(seconds / 3600).round(1)}h"
447
+ end
448
+ end
449
+
450
+ def cleanup_agent_resources(agent)
451
+ # Clean up worktree, temp files, etc.
452
+ if agent[:worktree_path] && File.exist?(agent[:worktree_path])
453
+ puts "Cleaning up worktree: #{agent[:worktree_path]}".colorize(:yellow)
454
+ # Cleanup implementation
455
+ end
456
+ end
457
+
458
+ def spawn_agent_replacement(agent)
459
+ # Spawn a new agent with the same configuration
460
+ # This would integrate with the Orchestrator
461
+ puts "Spawning replacement agent...".colorize(:blue)
462
+ # Return new PID or false if failed
463
+ nil
464
+ end
465
+
466
+ def show_agent_logs(agent)
467
+ puts "\nRecent Activity:".colorize(:blue)
468
+ # Show recent log entries for this agent
469
+ puts " (Log viewing not implemented in this demo)"
470
+ end
471
+
472
+ def show_agent_worktree_status(agent)
473
+ puts "\nWorktree Status:".colorize(:blue)
474
+ if agent[:worktree_path]
475
+ puts " Path: #{agent[:worktree_path]}"
476
+ # Show git status, recent commits, etc.
477
+ else
478
+ puts " No worktree assigned"
479
+ end
480
+ end
481
+
482
+ def pause_conflicting_agents(agents)
483
+ puts "Pausing conflicting agents...".colorize(:yellow)
484
+ agents.each do |agent|
485
+ # Send pause signal to agents
486
+ puts " Paused: #{agent[:role]}"
487
+ end
488
+ end
489
+
490
+ def initiate_manual_merge(file, agents)
491
+ puts "Initiating manual merge for #{file}...".colorize(:blue)
492
+ puts "Please resolve conflicts and run: enhance-swarm resume"
493
+ end
494
+
495
+ def restart_with_coordination(agents)
496
+ puts "Restarting agents with improved coordination...".colorize(:blue)
497
+ agents.each do |agent|
498
+ restart_agent(agent)
499
+ end
500
+ end
501
+
502
+ def handle_process_issue(agent)
503
+ puts "Process issue detected for agent #{agent[:role]}".colorize(:red)
504
+ @notification_manager.agent_failed(
505
+ agent[:id],
506
+ agent[:role],
507
+ "Process terminated unexpectedly",
508
+ ["enhance-swarm restart #{agent[:id]}", "Check system resources"]
509
+ )
510
+ end
511
+ end
512
+ end