aidp 0.9.6 → 0.11.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 (100) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +194 -25
  3. data/lib/aidp/analyze/error_handler.rb +4 -2
  4. data/lib/aidp/{analysis → analyze}/kb_inspector.rb +93 -89
  5. data/lib/aidp/analyze/prioritizer.rb +3 -2
  6. data/lib/aidp/analyze/progress.rb +2 -1
  7. data/lib/aidp/analyze/ruby_maat_integration.rb +7 -3
  8. data/lib/aidp/analyze/runner.rb +73 -11
  9. data/lib/aidp/{analysis → analyze}/seams.rb +1 -1
  10. data/lib/aidp/analyze/steps.rb +10 -8
  11. data/lib/aidp/{analysis → analyze}/tree_sitter_grammar_loader.rb +11 -5
  12. data/lib/aidp/{analysis → analyze}/tree_sitter_scan.rb +21 -15
  13. data/lib/aidp/cli/checkpoint_command.rb +98 -0
  14. data/lib/aidp/cli/first_run_wizard.rb +83 -103
  15. data/lib/aidp/cli/jobs_command.rb +270 -36
  16. data/lib/aidp/cli/terminal_io.rb +3 -3
  17. data/lib/aidp/cli.rb +411 -69
  18. data/lib/aidp/config.rb +5 -8
  19. data/lib/aidp/debug_logger.rb +4 -4
  20. data/lib/aidp/debug_mixin.rb +11 -4
  21. data/lib/aidp/execute/checkpoint.rb +282 -0
  22. data/lib/aidp/execute/checkpoint_display.rb +221 -0
  23. data/lib/aidp/execute/progress.rb +2 -1
  24. data/lib/aidp/execute/prompt_manager.rb +62 -0
  25. data/lib/aidp/execute/runner.rb +67 -20
  26. data/lib/aidp/execute/steps.rb +36 -27
  27. data/lib/aidp/execute/work_loop_runner.rb +308 -0
  28. data/lib/aidp/execute/workflow_selector.rb +50 -26
  29. data/lib/aidp/harness/condition_detector.rb +4 -4
  30. data/lib/aidp/harness/config_schema.rb +40 -0
  31. data/lib/aidp/harness/config_validator.rb +3 -6
  32. data/lib/aidp/harness/configuration.rb +35 -1
  33. data/lib/aidp/harness/enhanced_runner.rb +25 -4
  34. data/lib/aidp/harness/error_handler.rb +103 -28
  35. data/lib/aidp/harness/provider_factory.rb +6 -1
  36. data/lib/aidp/harness/provider_manager.rb +273 -19
  37. data/lib/aidp/harness/runner.rb +14 -6
  38. data/lib/aidp/harness/simple_user_interface.rb +6 -4
  39. data/lib/aidp/harness/status_display.rb +118 -106
  40. data/lib/aidp/harness/test_runner.rb +83 -0
  41. data/lib/aidp/harness/ui/enhanced_tui.rb +7 -5
  42. data/lib/aidp/harness/ui/enhanced_workflow_selector.rb +22 -4
  43. data/lib/aidp/harness/ui/error_handler.rb +7 -2
  44. data/lib/aidp/harness/ui/frame_manager.rb +61 -39
  45. data/lib/aidp/harness/ui/job_monitor.rb +2 -0
  46. data/lib/aidp/harness/ui/navigation/main_menu.rb +27 -16
  47. data/lib/aidp/harness/ui/navigation/menu_item.rb +1 -0
  48. data/lib/aidp/harness/ui/navigation/menu_state.rb +1 -0
  49. data/lib/aidp/harness/ui/navigation/submenu.rb +1 -0
  50. data/lib/aidp/harness/ui/navigation/workflow_selector.rb +2 -0
  51. data/lib/aidp/harness/ui/progress_display.rb +26 -7
  52. data/lib/aidp/harness/ui/question_collector.rb +2 -0
  53. data/lib/aidp/harness/ui/spinner_group.rb +2 -0
  54. data/lib/aidp/harness/ui/spinner_helper.rb +1 -1
  55. data/lib/aidp/harness/ui/status_manager.rb +4 -2
  56. data/lib/aidp/harness/ui/status_widget.rb +20 -9
  57. data/lib/aidp/harness/ui/workflow_controller.rb +27 -9
  58. data/lib/aidp/harness/user_interface.rb +338 -330
  59. data/lib/aidp/jobs/background_runner.rb +278 -0
  60. data/lib/aidp/message_display.rb +48 -0
  61. data/lib/aidp/provider_manager.rb +13 -7
  62. data/lib/aidp/providers/anthropic.rb +101 -18
  63. data/lib/aidp/providers/base.rb +51 -1
  64. data/lib/aidp/providers/codex.rb +248 -0
  65. data/lib/aidp/providers/cursor.rb +39 -48
  66. data/lib/aidp/providers/gemini.rb +26 -16
  67. data/lib/aidp/providers/github_copilot.rb +263 -0
  68. data/lib/aidp/providers/opencode.rb +38 -47
  69. data/lib/aidp/version.rb +1 -1
  70. data/lib/aidp/workflows/definitions.rb +357 -0
  71. data/lib/aidp/workflows/selector.rb +171 -0
  72. data/lib/aidp.rb +16 -4
  73. data/templates/planning/generate_llm_style_guide.md +119 -0
  74. metadata +43 -31
  75. data/lib/aidp/analyze/progress_visualizer.rb +0 -314
  76. /data/templates/{ANALYZE/02_ARCHITECTURE_ANALYSIS.md → analysis/analyze_architecture.md} +0 -0
  77. /data/templates/{ANALYZE/05_DOCUMENTATION_ANALYSIS.md → analysis/analyze_documentation.md} +0 -0
  78. /data/templates/{ANALYZE/04_FUNCTIONALITY_ANALYSIS.md → analysis/analyze_functionality.md} +0 -0
  79. /data/templates/{ANALYZE/01_REPOSITORY_ANALYSIS.md → analysis/analyze_repository.md} +0 -0
  80. /data/templates/{ANALYZE/06_STATIC_ANALYSIS.md → analysis/analyze_static_code.md} +0 -0
  81. /data/templates/{ANALYZE/03_TEST_ANALYSIS.md → analysis/analyze_tests.md} +0 -0
  82. /data/templates/{ANALYZE/07_REFACTORING_RECOMMENDATIONS.md → analysis/recommend_refactoring.md} +0 -0
  83. /data/templates/{ANALYZE/06a_tree_sitter_scan.md → analysis/scan_with_tree_sitter.md} +0 -0
  84. /data/templates/{EXECUTE/11_STATIC_ANALYSIS.md → implementation/configure_static_analysis.md} +0 -0
  85. /data/templates/{EXECUTE/14_DOCS_PORTAL.md → implementation/create_documentation_portal.md} +0 -0
  86. /data/templates/{EXECUTE/10_IMPLEMENTATION_AGENT.md → implementation/implement_features.md} +0 -0
  87. /data/templates/{EXECUTE/13_DELIVERY_ROLLOUT.md → implementation/plan_delivery.md} +0 -0
  88. /data/templates/{EXECUTE/15_POST_RELEASE.md → implementation/review_post_release.md} +0 -0
  89. /data/templates/{EXECUTE/09_SCAFFOLDING_DEVEX.md → implementation/setup_scaffolding.md} +0 -0
  90. /data/templates/{EXECUTE/02A_ARCH_GATE_QUESTIONS.md → planning/ask_architecture_questions.md} +0 -0
  91. /data/templates/{EXECUTE/00_PRD.md → planning/create_prd.md} +0 -0
  92. /data/templates/{EXECUTE/08_TASKS.md → planning/create_tasks.md} +0 -0
  93. /data/templates/{EXECUTE/04_DOMAIN_DECOMPOSITION.md → planning/decompose_domain.md} +0 -0
  94. /data/templates/{EXECUTE/01_NFRS.md → planning/define_nfrs.md} +0 -0
  95. /data/templates/{EXECUTE/05_CONTRACTS.md → planning/design_apis.md} +0 -0
  96. /data/templates/{EXECUTE/02_ARCHITECTURE.md → planning/design_architecture.md} +0 -0
  97. /data/templates/{EXECUTE/06_THREAT_MODEL.md → planning/design_data_model.md} +0 -0
  98. /data/templates/{EXECUTE/03_ADR_FACTORY.md → planning/generate_adrs.md} +0 -0
  99. /data/templates/{EXECUTE/12_OBSERVABILITY_SLOS.md → planning/plan_observability.md} +0 -0
  100. /data/templates/{EXECUTE/07_TEST_PLAN.md → planning/plan_testing.md} +0 -0
@@ -1,15 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "tty-prompt"
4
+ require "tty-cursor"
4
5
 
5
6
  module Aidp
6
7
  module Harness
7
8
  # Handles user interaction and feedback collection
8
9
  class UserInterface
10
+ include Aidp::MessageDisplay
11
+
9
12
  def initialize(prompt: TTY::Prompt.new)
10
13
  @input_history = []
11
14
  @file_selection_enabled = false
12
15
  @prompt = prompt
16
+ @cursor = TTY::Cursor
13
17
  @control_mutex = Mutex.new
14
18
  @pause_requested = false
15
19
  @stop_requested = false
@@ -36,7 +40,7 @@ module Aidp
36
40
  if default
37
41
  return default
38
42
  elsif required
39
- puts "❌ This field is required. Please provide a response."
43
+ display_message("❌ This field is required. Please provide a response.", type: :error)
40
44
  next
41
45
  else
42
46
  return nil
@@ -82,7 +86,7 @@ module Aidp
82
86
 
83
87
  # Validate response if required
84
88
  if question_data[:required] != false && (response.nil? || response.to_s.strip.empty?)
85
- puts "❌ This question is required. Please provide a response."
89
+ display_message("❌ This question is required. Please provide a response.", type: :error)
86
90
  redo
87
91
  end
88
92
 
@@ -99,11 +103,11 @@ module Aidp
99
103
 
100
104
  # Display feedback context
101
105
  def display_feedback_context(context)
102
- puts "\n📋 Context:"
103
- puts "-" * 30
106
+ display_message("\n📋 Context:", type: :highlight)
107
+ display_message("-" * 30, type: :muted)
104
108
 
105
109
  if context[:type]
106
- puts "Type: #{context[:type]}"
110
+ display_message("Type: #{context[:type]}", type: :info)
107
111
  end
108
112
 
109
113
  if context[:urgency]
@@ -113,23 +117,23 @@ module Aidp
113
117
  "low" => "🟢"
114
118
  }
115
119
  urgency_emoji = urgency_emojis[context[:urgency]] || "ℹ️"
116
- puts "Urgency: #{urgency_emoji} #{context[:urgency].capitalize}"
120
+ display_message("Urgency: #{urgency_emoji} #{context[:urgency].capitalize}", type: :info)
117
121
  end
118
122
 
119
123
  if context[:description]
120
- puts "Description: #{context[:description]}"
124
+ display_message("Description: #{context[:description]}", type: :info)
121
125
  end
122
126
 
123
127
  if context[:agent_output]
124
- puts "\nAgent Output:"
125
- puts context[:agent_output]
128
+ display_message("\nAgent Output:", type: :info)
129
+ display_message(context[:agent_output], type: :info)
126
130
  end
127
131
  end
128
132
 
129
133
  # Display question presentation header
130
134
  def display_question_presentation_header(questions, context)
131
- puts "\n🤖 Agent needs your feedback:"
132
- puts "=" * 60
135
+ display_message("\n🤖 Agent needs your feedback:", type: :highlight)
136
+ display_message("=" * 60, type: :muted)
133
137
 
134
138
  # Display question overview
135
139
  display_question_overview(questions)
@@ -139,8 +143,8 @@ module Aidp
139
143
  display_context_summary(context)
140
144
  end
141
145
 
142
- puts "\n📝 Questions to answer:"
143
- puts "-" * 40
146
+ display_message("\n📝 Questions to answer:", type: :info)
147
+ display_message("-" * 40, type: :muted)
144
148
  end
145
149
 
146
150
  # Display question overview
@@ -151,23 +155,23 @@ module Aidp
151
155
 
152
156
  question_types = questions.map { |q| q[:type] || "text" }.uniq
153
157
 
154
- puts "📊 Overview:"
155
- puts " Total questions: #{total_questions}"
156
- puts " Required: #{required_questions}"
157
- puts " Optional: #{optional_questions}"
158
- puts " Question types: #{question_types.join(", ")}"
158
+ display_message("📊 Overview:", type: :info)
159
+ display_message(" Total questions: #{total_questions}", type: :info)
160
+ display_message(" Required: #{required_questions}", type: :info)
161
+ display_message(" Optional: #{optional_questions}", type: :info)
162
+ display_message(" Question types: #{question_types.join(", ")}", type: :info)
159
163
 
160
164
  # Estimate completion time
161
165
  estimated_time = estimate_completion_time(questions)
162
- puts " Estimated time: #{estimated_time}"
166
+ display_message(" Estimated time: #{estimated_time}", type: :info)
163
167
  end
164
168
 
165
169
  # Display context summary
166
170
  def display_context_summary(context)
167
- puts "\n📋 Context Summary:"
171
+ display_message("\n📋 Context Summary:", type: :info)
168
172
 
169
173
  if context[:type]
170
- puts " Type: #{context[:type]}"
174
+ display_message(" Type: #{context[:type]}", type: :info)
171
175
  end
172
176
 
173
177
  if context[:urgency]
@@ -177,11 +181,11 @@ module Aidp
177
181
  "low" => "🟢"
178
182
  }
179
183
  urgency_emoji = urgency_emojis[context[:urgency]] || "ℹ️"
180
- puts " Urgency: #{urgency_emoji} #{context[:urgency].capitalize}"
184
+ display_message(" Urgency: #{urgency_emoji} #{context[:urgency].capitalize}", type: :info)
181
185
  end
182
186
 
183
187
  if context[:description]
184
- puts " Description: #{context[:description]}"
188
+ display_message(" Description: #{context[:description]}", type: :info)
185
189
  end
186
190
  end
187
191
 
@@ -230,9 +234,9 @@ module Aidp
230
234
  required = question_data[:required] != false
231
235
 
232
236
  # Display question header
233
- puts "\n" + "=" * 60
234
- puts "📝 Question #{question_number} of #{total_questions}"
235
- puts "=" * 60
237
+ display_message("\n" + "=" * 60, type: :muted)
238
+ display_message("📝 Question #{question_number} of #{total_questions}", type: :highlight)
239
+ display_message("=" * 60, type: :muted)
236
240
 
237
241
  # Display question text with formatting
238
242
  display_question_text(question_text, question_type)
@@ -243,7 +247,7 @@ module Aidp
243
247
  # Display question instructions
244
248
  display_question_instructions(question_type, options, default_value, required)
245
249
 
246
- puts "\n" + "-" * 60
250
+ display_message("\n" + "-" * 60, type: :muted)
247
251
  end
248
252
 
249
253
  # Display question text with formatting
@@ -260,96 +264,96 @@ module Aidp
260
264
  }
261
265
  type_emoji = type_emojis[question_type] || "❓"
262
266
 
263
- puts "#{type_emoji} #{question_text}"
267
+ display_message("#{type_emoji} #{question_text}", type: :info)
264
268
  end
265
269
 
266
270
  # Display question metadata
267
271
  def display_question_metadata(question_type, expected_input, options, default_value, required)
268
- puts "\n📋 Question Details:"
272
+ display_message("\n📋 Question Details:", type: :info)
269
273
 
270
274
  # Question type
271
- puts " Type: #{question_type.capitalize}"
275
+ display_message(" Type: #{question_type.capitalize}", type: :info)
272
276
 
273
277
  # Expected input
274
278
  if expected_input != "text"
275
- puts " Expected input: #{expected_input}"
279
+ display_message(" Expected input: #{expected_input}", type: :info)
276
280
  end
277
281
 
278
282
  # Options
279
283
  if options && !options.empty?
280
- puts " Options: #{options.length} available"
284
+ display_message(" Options: #{options.length} available", type: :info)
281
285
  end
282
286
 
283
287
  # Default value
284
288
  if default_value
285
- puts " Default: #{default_value}"
289
+ display_message(" Default: #{default_value}", type: :info)
286
290
  end
287
291
 
288
292
  # Required status
289
293
  status = required ? "Required" : "Optional"
290
294
  status_emoji = required ? "🔴" : "🟢"
291
- puts " Status: #{status_emoji} #{status}"
295
+ display_message(" Status: #{status_emoji} #{status}", type: :info)
292
296
  end
293
297
 
294
298
  # Display question instructions
295
299
  def display_question_instructions(question_type, options, default_value, required)
296
- puts "\n💡 Instructions:"
300
+ display_message("\n💡 Instructions:", type: :info)
297
301
 
298
302
  case question_type
299
303
  when "text"
300
- puts " • Enter your text response"
301
- puts " • Use @ for file selection if needed"
302
- puts " • Press Enter when done"
304
+ display_message(" • Enter your text response", type: :info)
305
+ display_message(" • Use @ for file selection if needed", type: :info)
306
+ display_message(" • Press Enter when done", type: :info)
303
307
  when "choice"
304
- puts " • Select from the numbered options below"
305
- puts " • Enter the number of your choice"
306
- puts " • Press Enter to confirm"
308
+ display_message(" • Select from the numbered options below", type: :info)
309
+ display_message(" • Enter the number of your choice", type: :info)
310
+ display_message(" • Press Enter to confirm", type: :info)
307
311
  when "confirmation"
308
- puts " • Enter 'y' or 'yes' for Yes"
309
- puts " • Enter 'n' or 'no' for No"
310
- puts " • Press Enter for default"
312
+ display_message(" • Enter 'y' or 'yes' for Yes", type: :info)
313
+ display_message(" • Enter 'n' or 'no' for No", type: :info)
314
+ display_message(" • Press Enter for default", type: :info)
311
315
  when "file"
312
- puts " • Enter file path directly"
313
- puts " • Use @ to browse and select files"
314
- puts " • File must exist and be readable"
316
+ display_message(" • Enter file path directly", type: :info)
317
+ display_message(" • Use @ to browse and select files", type: :info)
318
+ display_message(" • File must exist and be readable", type: :info)
315
319
  when "number"
316
- puts " • Enter a valid number"
317
- puts " • Use decimal point for decimals"
318
- puts " • Press Enter when done"
320
+ display_message(" • Enter a valid number", type: :info)
321
+ display_message(" • Use decimal point for decimals", type: :info)
322
+ display_message(" • Press Enter when done", type: :info)
319
323
  when "email"
320
- puts " • Enter a valid email address"
321
- puts " • Format: user@domain.com"
322
- puts " • Press Enter when done"
324
+ display_message(" • Enter a valid email address", type: :info)
325
+ display_message(" • Format: user@domain.com", type: :info)
326
+ display_message(" • Press Enter when done", type: :info)
323
327
  when "url"
324
- puts " • Enter a valid URL"
325
- puts " • Format: https://example.com"
326
- puts " • Press Enter when done"
328
+ display_message(" • Enter a valid URL", type: :info)
329
+ display_message(" • Format: https://example.com", type: :info)
330
+ display_message(" • Press Enter when done", type: :info)
327
331
  end
328
332
 
329
333
  # Additional instructions based on options
330
334
  if options && !options.empty?
331
- puts "\n📋 Available Options:"
335
+ display_message("\n📋 Available Options:", type: :info)
332
336
  options.each_with_index do |option, index|
333
337
  marker = (default_value && option == default_value) ? " (default)" : ""
334
- puts " #{index + 1}. #{option}#{marker}"
338
+ display_message(" #{index + 1}. #{option}#{marker}", type: :info)
335
339
  end
336
340
  end
337
341
 
338
342
  # Default value instructions
339
343
  if default_value
340
- puts "\n⚡ Quick Answer:"
341
- puts " • Press Enter to use default: #{default_value}"
344
+ display_message("\n⚡ Quick Answer:", type: :info)
345
+ display_message(" • Press Enter to use default: #{default_value}", type: :info)
342
346
  end
343
347
 
344
348
  # Required field instructions
345
349
  if required
346
- puts "\n⚠️ Required Field:"
347
- puts " • This question must be answered"
348
- puts " • Cannot be left blank"
350
+ display_message("\n⚠️ Required Field:", type: :info)
351
+ display_message(" • This question must be answered", type: :info)
352
+ display_message(" • Cannot be left blank", type: :info)
349
353
  else
350
- puts "\n✅ Optional Field:"
351
- puts " • This question can be skipped"
352
- puts " • Press Enter to leave blank"
354
+ display_message("\n✅ Optional Field:", type: :info)
355
+ display_message(" • This question can be skipped", type: :info)
356
+ display_message(" • Press Enter to leave blank", type: :info)
353
357
  end
354
358
  end
355
359
 
@@ -358,13 +362,13 @@ module Aidp
358
362
  progress_percentage = (current_index.to_f / total_questions * 100).round(1)
359
363
  progress_bar = generate_progress_bar(progress_percentage)
360
364
 
361
- puts "\n📊 Progress: #{progress_bar} #{progress_percentage}% (#{current_index}/#{total_questions})"
365
+ display_message("\n📊 Progress: #{progress_bar} #{progress_percentage}% (#{current_index}/#{total_questions})", type: :info)
362
366
 
363
367
  # Show estimated time remaining
364
368
  if current_index < total_questions
365
369
  remaining_questions = total_questions - current_index
366
370
  estimated_remaining = estimate_remaining_time(remaining_questions)
367
- puts "⏱️ Estimated time remaining: #{estimated_remaining}"
371
+ display_message("⏱️ Estimated time remaining: #{estimated_remaining}", type: :info)
368
372
  end
369
373
  end
370
374
 
@@ -391,34 +395,34 @@ module Aidp
391
395
 
392
396
  # Display question completion summary
393
397
  def display_question_completion_summary(responses, questions)
394
- puts "\n" + "=" * 60
395
- puts "✅ Question Completion Summary"
396
- puts "=" * 60
398
+ display_message("\n" + "=" * 60, type: :muted)
399
+ display_message("✅ Question Completion Summary", type: :success)
400
+ display_message("=" * 60, type: :muted)
397
401
 
398
402
  # Show completion statistics
399
403
  total_questions = questions.length
400
404
  answered_questions = responses.values.count { |v| !v.nil? && !v.to_s.strip.empty? }
401
405
  skipped_questions = total_questions - answered_questions
402
406
 
403
- puts "📊 Statistics:"
404
- puts " Total questions: #{total_questions}"
405
- puts " Answered: #{answered_questions}"
406
- puts " Skipped: #{skipped_questions}"
407
- puts " Completion rate: #{(answered_questions.to_f / total_questions * 100).round(1)}%"
407
+ display_message("📊 Statistics:", type: :info)
408
+ display_message(" Total questions: #{total_questions}", type: :info)
409
+ display_message(" Answered: #{answered_questions}", type: :info)
410
+ display_message(" Skipped: #{skipped_questions}", type: :info)
411
+ display_message(" Completion rate: #{(answered_questions.to_f / total_questions * 100).round(1)}%", type: :info)
408
412
 
409
413
  # Show response summary
410
- puts "\n📝 Response Summary:"
414
+ display_message("\n📝 Response Summary:", type: :info)
411
415
  responses.each do |key, value|
412
416
  question_number = key.gsub("question_", "")
413
417
  if value.nil? || value.to_s.strip.empty?
414
- puts " #{question_number}. [Skipped]"
418
+ display_message(" #{question_number}. [Skipped]", type: :muted)
415
419
  else
416
420
  display_value = (value.to_s.length > 50) ? "#{value.to_s[0..47]}..." : value.to_s
417
- puts " #{question_number}. #{display_value}"
421
+ display_message(" #{question_number}. #{display_value}", type: :info)
418
422
  end
419
423
  end
420
424
 
421
- puts "\n🚀 Continuing execution..."
425
+ display_message("\n🚀 Continuing execution...", type: :success)
422
426
  end
423
427
 
424
428
  # Display question information (legacy method for compatibility)
@@ -460,7 +464,7 @@ module Aidp
460
464
  "Required: No"
461
465
  end
462
466
 
463
- puts " #{info_parts.join(" | ")}"
467
+ display_message(" #{info_parts.join(" | ")}", type: :info)
464
468
  end
465
469
 
466
470
  # Get response for a specific question with enhanced validation
@@ -496,15 +500,15 @@ module Aidp
496
500
  def handle_input_error(error, question_data, retry_count = 0)
497
501
  max_retries = 3
498
502
 
499
- puts "\n🚨 Input Error:"
500
- puts " #{error.message}"
503
+ display_message("\n🚨 Input Error:", type: :error)
504
+ display_message(" #{error.message}", type: :error)
501
505
 
502
506
  if retry_count < max_retries
503
- puts "\n🔄 Retry Options:"
504
- puts " 1. Try again"
505
- puts " 2. Skip this question"
506
- puts " 3. Get help"
507
- puts " 4. Cancel all questions"
507
+ display_message("\n🔄 Retry Options:", type: :info)
508
+ display_message(" 1. Try again", type: :info)
509
+ display_message(" 2. Skip this question", type: :info)
510
+ display_message(" 3. Get help", type: :info)
511
+ display_message(" 4. Cancel all questions", type: :info)
508
512
 
509
513
  choice = @prompt.select("Choose an option:", {
510
514
  "Try again" => "1",
@@ -515,23 +519,23 @@ module Aidp
515
519
 
516
520
  case choice
517
521
  when "1"
518
- puts "🔄 Retrying..."
522
+ display_message("🔄 Retrying...", type: :info)
519
523
  :retry
520
524
  when "2"
521
- puts "⏭️ Skipping question..."
525
+ display_message("⏭️ Skipping question...", type: :warning)
522
526
  :skip
523
527
  when "3"
524
528
  show_question_help(question_data)
525
529
  :retry
526
530
  when "4"
527
- puts "❌ Cancelling all questions..."
531
+ display_message("❌ Cancelling all questions...", type: :error)
528
532
  :cancel
529
533
  else
530
- puts "❌ Invalid choice. Retrying..."
534
+ display_message("❌ Invalid choice. Retrying...", type: :error)
531
535
  :retry
532
536
  end
533
537
  else
534
- puts "\n❌ Maximum retries exceeded. Skipping question..."
538
+ display_message("\n❌ Maximum retries exceeded. Skipping question...", type: :error)
535
539
  :skip
536
540
  end
537
541
  end
@@ -540,74 +544,74 @@ module Aidp
540
544
  def show_question_help(question_data)
541
545
  question_type = question_data[:type] || "text"
542
546
 
543
- puts "\n📖 Help for #{question_type.capitalize} Question:"
544
- puts "=" * 50
547
+ display_message("\n📖 Help for #{question_type.capitalize} Question:", type: :info)
548
+ display_message("=" * 50, type: :muted)
545
549
 
546
550
  case question_type
547
551
  when "text"
548
- puts "• Enter any text response"
549
- puts "• Use @ for file selection if needed"
550
- puts "• Press Enter when done"
552
+ display_message("• Enter any text response", type: :info)
553
+ display_message("• Use @ for file selection if needed", type: :info)
554
+ display_message("• Press Enter when done", type: :info)
551
555
  when "choice"
552
- puts "• Select from the numbered options"
553
- puts "• Enter the number of your choice"
554
- puts "• Or type the option text directly"
556
+ display_message("• Select from the numbered options", type: :info)
557
+ display_message("• Enter the number of your choice", type: :info)
558
+ display_message("• Or type the option text directly", type: :info)
555
559
  when "confirmation"
556
- puts "• Enter 'y' or 'yes' for Yes"
557
- puts "• Enter 'n' or 'no' for No"
558
- puts "• Press Enter for default"
560
+ display_message("• Enter 'y' or 'yes' for Yes", type: :info)
561
+ display_message("• Enter 'n' or 'no' for No", type: :info)
562
+ display_message("• Press Enter for default", type: :info)
559
563
  when "file"
560
- puts "• Enter file path directly"
561
- puts "• Use @ to browse and select files"
562
- puts "• File must exist and be readable"
564
+ display_message("• Enter file path directly", type: :info)
565
+ display_message("• Use @ to browse and select files", type: :info)
566
+ display_message("• File must exist and be readable", type: :info)
563
567
  when "number"
564
- puts "• Enter a valid number"
565
- puts "• Use decimal point for decimals"
566
- puts "• Check range requirements"
568
+ display_message("• Enter a valid number", type: :info)
569
+ display_message("• Use decimal point for decimals", type: :info)
570
+ display_message("• Check range requirements", type: :info)
567
571
  when "email"
568
- puts "• Enter a valid email address"
569
- puts "• Format: user@domain.com"
570
- puts "• Check for typos"
572
+ display_message("• Enter a valid email address", type: :info)
573
+ display_message("• Format: user@domain.com", type: :info)
574
+ display_message("• Check for typos", type: :info)
571
575
  when "url"
572
- puts "• Enter a valid URL"
573
- puts "• Format: https://example.com"
574
- puts "• Include protocol (http:// or https://)"
576
+ display_message("• Enter a valid URL", type: :info)
577
+ display_message("• Format: https://example.com", type: :info)
578
+ display_message("• Include protocol (http:// or https://)", type: :info)
575
579
  end
576
580
 
577
- puts "\nPress Enter to continue..."
581
+ display_message("\nPress Enter to continue...", type: :info)
578
582
  @prompt.keypress("Press any key to continue...")
579
583
  end
580
584
 
581
585
  # Enhanced error handling and validation display
582
586
  def display_validation_error(validation_result, _input_type)
583
- puts "\n❌ Validation Error:"
584
- puts " #{validation_result[:error_message]}"
587
+ display_message("\n❌ Validation Error:", type: :error)
588
+ display_message(" #{validation_result[:error_message]}", type: :error)
585
589
 
586
590
  if validation_result[:suggestions].any?
587
- puts "\n💡 Suggestions:"
591
+ display_message("\n💡 Suggestions:", type: :info)
588
592
  validation_result[:suggestions].each do |suggestion|
589
- puts " • #{suggestion}"
593
+ display_message(" • #{suggestion}", type: :info)
590
594
  end
591
595
  end
592
596
 
593
597
  if validation_result[:warnings].any?
594
- puts "\n⚠️ Warnings:"
598
+ display_message("\n⚠️ Warnings:", type: :warning)
595
599
  validation_result[:warnings].each do |warning|
596
- puts " • #{warning}"
600
+ display_message(" • #{warning}", type: :warning)
597
601
  end
598
602
  end
599
603
 
600
- puts "\n🔄 Please try again..."
604
+ display_message("\n🔄 Please try again...", type: :info)
601
605
  end
602
606
 
603
607
  # Display validation warnings
604
608
  def display_validation_warnings(validation_result)
605
609
  if validation_result[:warnings].any?
606
- puts "\n⚠️ Warnings:"
610
+ display_message("\n⚠️ Warnings:", type: :warning)
607
611
  validation_result[:warnings].each do |warning|
608
- puts " • #{warning}"
612
+ display_message(" • #{warning}", type: :warning)
609
613
  end
610
- puts "\nPress Enter to continue or type 'fix' to correct..."
614
+ display_message("\nPress Enter to continue or type 'fix' to correct...", type: :info)
611
615
 
612
616
  input = @prompt.ask("")
613
617
  return input&.strip&.downcase == "fix"
@@ -652,10 +656,10 @@ module Aidp
652
656
  def get_choice_response(options, default_value, required)
653
657
  return nil if options.nil? || options.empty?
654
658
 
655
- puts "\n Available options:"
659
+ display_message("\n Available options:", type: :info)
656
660
  options.each_with_index do |option, index|
657
661
  marker = (default_value && option == default_value) ? " (default)" : ""
658
- puts " #{index + 1}. #{option}#{marker}"
662
+ display_message(" #{index + 1}. #{option}#{marker}", type: :info)
659
663
  end
660
664
 
661
665
  loop do
@@ -669,7 +673,7 @@ module Aidp
669
673
  if default_value
670
674
  return default_value
671
675
  elsif required
672
- puts "❌ Please make a selection."
676
+ display_message("❌ Please make a selection.", type: :error)
673
677
  next
674
678
  else
675
679
  return nil
@@ -749,7 +753,7 @@ module Aidp
749
753
  if default_value
750
754
  return default_value
751
755
  elsif required
752
- puts "❌ Please provide a file path."
756
+ display_message("❌ Please provide a file path.", type: :error)
753
757
  next
754
758
  else
755
759
  return nil
@@ -792,7 +796,7 @@ module Aidp
792
796
  if default_value
793
797
  return default_value
794
798
  elsif required
795
- puts "❌ Please provide a number."
799
+ display_message("❌ Please provide a number.", type: :error)
796
800
  next
797
801
  else
798
802
  return nil
@@ -820,7 +824,7 @@ module Aidp
820
824
  return Float(input.strip)
821
825
  end
822
826
  rescue ArgumentError
823
- puts "❌ Please enter a valid #{expected_input}."
827
+ display_message("❌ Please enter a valid #{expected_input}.", type: :error)
824
828
  next
825
829
  end
826
830
  end
@@ -839,7 +843,7 @@ module Aidp
839
843
  if default_value
840
844
  return default_value
841
845
  elsif required
842
- puts "❌ Please provide an email address."
846
+ display_message("❌ Please provide an email address.", type: :error)
843
847
  next
844
848
  else
845
849
  return nil
@@ -876,7 +880,7 @@ module Aidp
876
880
  if default_value
877
881
  return default_value
878
882
  elsif required
879
- puts "❌ Please provide a URL."
883
+ display_message("❌ Please provide a URL.", type: :error)
880
884
  next
881
885
  else
882
886
  return nil
@@ -1323,7 +1327,7 @@ module Aidp
1323
1327
 
1324
1328
  # Handle empty input
1325
1329
  if input.nil? || input.strip.empty?
1326
- puts "Please provide a response."
1330
+ display_message("Please provide a response.", type: :error)
1327
1331
  next
1328
1332
  end
1329
1333
 
@@ -1351,8 +1355,8 @@ module Aidp
1351
1355
  available_files = find_files_advanced(search_options)
1352
1356
 
1353
1357
  if available_files.empty?
1354
- puts "No files found matching '#{search_options[:term]}'. Please try again."
1355
- puts "💡 Try: @ (all files), @.rb (Ruby files), @config (files with 'config'), @lib/ (files in lib directory)"
1358
+ display_message("No files found matching '#{search_options[:term]}'. Please try again.", type: :warning)
1359
+ display_message("💡 Try: @ (all files), @.rb (Ruby files), @config (files with 'config'), @lib/ (files in lib directory)", type: :info)
1356
1360
  return nil
1357
1361
  end
1358
1362
 
@@ -1364,7 +1368,7 @@ module Aidp
1364
1368
 
1365
1369
  if selection && selection >= 0 && selection < available_files.size
1366
1370
  selected_file = available_files[selection]
1367
- puts "✅ Selected: #{selected_file}"
1371
+ display_message("✅ Selected: #{selected_file}", type: :success)
1368
1372
 
1369
1373
  # Show file preview if requested
1370
1374
  if search_options[:preview]
@@ -1376,7 +1380,7 @@ module Aidp
1376
1380
  # User wants to refine search
1377
1381
  handle_file_selection("@#{search_term}")
1378
1382
  else
1379
- puts "❌ Invalid selection. Please try again."
1383
+ display_message("❌ Invalid selection. Please try again.", type: :error)
1380
1384
  nil
1381
1385
  end
1382
1386
  end
@@ -1580,21 +1584,21 @@ module Aidp
1580
1584
 
1581
1585
  # Display advanced file selection menu
1582
1586
  def display_advanced_file_menu(files, search_options)
1583
- puts "\n📁 Available files:"
1584
- puts "Search: #{search_options[:term]} | Extensions: #{search_options[:extensions].join(", ")} | Directories: #{search_options[:directories].join(", ")}"
1585
- puts "-" * 80
1587
+ display_message("\n📁 Available files:", type: :info)
1588
+ display_message("Search: #{search_options[:term]} | Extensions: #{search_options[:extensions].join(", ")} | Directories: #{search_options[:directories].join(", ")}", type: :info)
1589
+ display_message("-" * 80, type: :muted)
1586
1590
 
1587
1591
  files.each_with_index do |file, index|
1588
1592
  file_info = get_file_info(file)
1589
- puts " #{index + 1}. #{file_info[:display_name]}"
1590
- puts " 📄 #{file_info[:size]} | 📅 #{file_info[:modified]} | 🏷️ #{file_info[:type]}"
1593
+ display_message(" #{index + 1}. #{file_info[:display_name]}", type: :info)
1594
+ display_message(" 📄 #{file_info[:size]} | 📅 #{file_info[:modified]} | 🏷️ #{file_info[:type]}", type: :muted)
1591
1595
  end
1592
1596
 
1593
- puts "\nOptions:"
1594
- puts " 0. Cancel"
1595
- puts " -1. Refine search"
1596
- puts " p. Preview selected file"
1597
- puts " h. Show help"
1597
+ display_message("\nOptions:", type: :info)
1598
+ display_message(" 0. Cancel", type: :info)
1599
+ display_message(" -1. Refine search", type: :info)
1600
+ display_message(" p. Preview selected file", type: :info)
1601
+ display_message(" h. Show help", type: :info)
1598
1602
  end
1599
1603
 
1600
1604
  # Get file information for display
@@ -1666,7 +1670,7 @@ module Aidp
1666
1670
  input = @prompt.ask("Select file (0-#{max_files}, -1=refine, p=preview, h=help): ")
1667
1671
 
1668
1672
  if input.nil? || input.strip.empty?
1669
- puts "Please enter a selection."
1673
+ display_message("Please enter a selection.", type: :error)
1670
1674
  next
1671
1675
  end
1672
1676
 
@@ -1678,7 +1682,7 @@ module Aidp
1678
1682
  show_file_selection_help
1679
1683
  next
1680
1684
  when "p", "preview"
1681
- puts "💡 Select a file number first, then use 'p' to preview it."
1685
+ display_message("💡 Select a file number first, then use 'p' to preview it.", type: :info)
1682
1686
  next
1683
1687
  end
1684
1688
 
@@ -1691,71 +1695,71 @@ module Aidp
1691
1695
  elsif selection.between?(1, max_files)
1692
1696
  return selection - 1 # Convert to 0-based index
1693
1697
  else
1694
- puts "Please enter a number between 0 and #{max_files}, or use -1, p, h."
1698
+ display_message("Please enter a number between 0 and #{max_files}, or use -1, p, h.", type: :error)
1695
1699
  end
1696
1700
  rescue ArgumentError
1697
- puts "Please enter a valid number or command (0-#{max_files}, -1, p, h)."
1701
+ display_message("Please enter a valid number or command (0-#{max_files}, -1, p, h).", type: :error)
1698
1702
  end
1699
1703
  end
1700
1704
  end
1701
1705
 
1702
1706
  # Show file selection help
1703
1707
  def show_file_selection_help
1704
- puts "\n📖 File Selection Help:"
1705
- puts "=" * 40
1706
-
1707
- puts "\n🔍 Search Examples:"
1708
- puts " @ - Show all files"
1709
- puts " @.rb - Show Ruby files only"
1710
- puts " @config - Show files with 'config' in name"
1711
- puts " @lib/ - Show files in lib directory"
1712
- puts " @spec preview - Show spec files with preview option"
1713
- puts " @.js case - Show JavaScript files (case sensitive)"
1714
-
1715
- puts "\n⌨️ Selection Commands:"
1716
- puts " 1-50 - Select file by number"
1717
- puts " 0 - Cancel selection"
1718
- puts " -1 - Refine search"
1719
- puts " p - Preview selected file"
1720
- puts " h - Show this help"
1721
-
1722
- puts "\n💡 Tips:"
1723
- puts " • Files are sorted by relevance and type"
1724
- puts " • Use extension filters for specific file types"
1725
- puts " • Use directory filters to limit search scope"
1726
- puts " • Preview option shows file content before selection"
1708
+ display_message("\n📖 File Selection Help:", type: :info)
1709
+ display_message("=" * 40, type: :muted)
1710
+
1711
+ display_message("\n🔍 Search Examples:", type: :info)
1712
+ display_message(" @ - Show all files", type: :info)
1713
+ display_message(" @.rb - Show Ruby files only", type: :info)
1714
+ display_message(" @config - Show files with 'config' in name", type: :info)
1715
+ display_message(" @lib/ - Show files in lib directory", type: :info)
1716
+ display_message(" @spec preview - Show spec files with preview option", type: :info)
1717
+ display_message(" @.js case - Show JavaScript files (case sensitive)", type: :info)
1718
+
1719
+ display_message("\n⌨️ Selection Commands:", type: :info)
1720
+ display_message(" 1-50 - Select file by number", type: :info)
1721
+ display_message(" 0 - Cancel selection", type: :info)
1722
+ display_message(" -1 - Refine search", type: :info)
1723
+ display_message(" p - Preview selected file", type: :info)
1724
+ display_message(" h - Show this help", type: :info)
1725
+
1726
+ display_message("\n💡 Tips:", type: :info)
1727
+ display_message(" • Files are sorted by relevance and type", type: :info)
1728
+ display_message(" • Use extension filters for specific file types", type: :info)
1729
+ display_message(" • Use directory filters to limit search scope", type: :info)
1730
+ display_message(" • Preview option shows file content before selection", type: :info)
1727
1731
  end
1728
1732
 
1729
1733
  # Show file preview
1730
1734
  def show_file_preview(file_path)
1731
- puts "\n📄 File Preview: #{file_path}"
1732
- puts "=" * 60
1735
+ display_message("\n📄 File Preview: #{file_path}", type: :highlight)
1736
+ display_message("=" * 60, type: :muted)
1733
1737
 
1734
1738
  begin
1735
1739
  content = File.read(file_path)
1736
1740
  lines = content.lines
1737
1741
 
1738
- puts "📊 File Info:"
1739
- puts " Size: #{format_file_size(File.size(file_path))}"
1740
- puts " Lines: #{lines.count}"
1741
- puts " Modified: #{File.mtime(file_path).strftime("%Y-%m-%d %H:%M:%S")}"
1742
- puts " Type: #{get_file_type(file_path)}"
1742
+ display_message("📊 File Info:", type: :info)
1743
+ display_message(" Size: #{format_file_size(File.size(file_path))}", type: :info)
1744
+ display_message(" Lines: #{lines.count}", type: :info)
1745
+ display_message(" Modified: #{File.mtime(file_path).strftime("%Y-%m-%d %H:%M:%S")}", type: :info)
1746
+ display_message(" Type: #{get_file_type(file_path)}", type: :info)
1743
1747
 
1744
- puts "\n📝 Content Preview (first 20 lines):"
1745
- puts "-" * 40
1748
+ display_message("\n📝 Content Preview (first 20 lines):", type: :info)
1749
+ display_message("-" * 40, type: :muted)
1746
1750
 
1747
1751
  lines.first(20).each_with_index do |line, index|
1748
- puts "#{(index + 1).to_s.rjust(3)}: #{line.chomp}"
1752
+ display_message("#{(index + 1).to_s.rjust(3)}: #{line.chomp}", type: :info)
1749
1753
  end
1750
1754
 
1751
1755
  if lines.count > 20
1752
- puts "... (#{lines.count - 20} more lines)"
1756
+ display_message("... (#{lines.count - 20} more lines)", type: :muted)
1753
1757
  end
1754
1758
  rescue => e
1755
- puts "❌ Error reading file: #{e.message}"
1759
+ display_message("❌ Error reading file: #{e.message}", type: :error)
1756
1760
  end
1757
1761
 
1758
- puts "\nPress Enter to continue..."
1762
+ display_message("\nPress Enter to continue...", type: :info)
1759
1763
  @prompt.keypress("Press any key to continue...")
1760
1764
  end
1761
1765
 
@@ -1783,17 +1787,17 @@ module Aidp
1783
1787
  when "n", "no"
1784
1788
  return false
1785
1789
  else
1786
- puts "Please enter 'y' or 'n'."
1790
+ display_message("Please enter 'y' or 'n'.", type: :error)
1787
1791
  end
1788
1792
  end
1789
1793
  end
1790
1794
 
1791
1795
  # Get choice from multiple options
1792
1796
  def get_choice(message, options, default: nil)
1793
- puts "\n#{message}"
1797
+ display_message("\n#{message}", type: :info)
1794
1798
  options.each_with_index do |option, index|
1795
1799
  marker = (default && index == default) ? " (default)" : ""
1796
- puts " #{index + 1}. #{option}#{marker}"
1800
+ display_message(" #{index + 1}. #{option}#{marker}", type: :info)
1797
1801
  end
1798
1802
 
1799
1803
  loop do
@@ -1801,7 +1805,7 @@ module Aidp
1801
1805
 
1802
1806
  if input.nil? || input.strip.empty?
1803
1807
  return default if default
1804
- puts "Please make a selection."
1808
+ display_message("Please make a selection.", type: :error)
1805
1809
  next
1806
1810
  end
1807
1811
 
@@ -1810,24 +1814,28 @@ module Aidp
1810
1814
  if choice.between?(1, options.size)
1811
1815
  return choice - 1 # Convert to 0-based index
1812
1816
  else
1813
- puts "Please enter a number between 1 and #{options.size}."
1817
+ display_message("Please enter a number between 1 and #{options.size}.", type: :error)
1814
1818
  end
1815
1819
  rescue ArgumentError
1816
- puts "Please enter a valid number."
1820
+ display_message("Please enter a valid number.", type: :error)
1817
1821
  end
1818
1822
  end
1819
1823
  end
1820
1824
 
1821
1825
  # Display progress message
1822
1826
  def show_progress(message)
1823
- print "\r#{message}".ljust(80)
1824
- $stdout.flush
1827
+ print_to_stderr(@cursor.clear_line, @cursor.column(1), message)
1825
1828
  end
1826
1829
 
1827
1830
  # Clear progress message
1828
1831
  def clear_progress
1829
- print "\r" + " " * 80 + "\r"
1830
- $stdout.flush
1832
+ print_to_stderr(@cursor.clear_line, @cursor.column(1))
1833
+ end
1834
+
1835
+ # Helper method to print to stderr with flush
1836
+ def print_to_stderr(*parts)
1837
+ parts.each { |part| $stderr.print part }
1838
+ $stderr.flush
1831
1839
  end
1832
1840
 
1833
1841
  # Get input history
@@ -1842,43 +1850,43 @@ module Aidp
1842
1850
 
1843
1851
  # Display interactive help
1844
1852
  def show_help
1845
- puts "\n📖 Interactive Prompt Help:"
1846
- puts "=" * 40
1847
-
1848
- puts "\n🔤 Input Types:"
1849
- puts " • Text: Free-form text input"
1850
- puts " • Choice: Select from predefined options"
1851
- puts " • Confirmation: Yes/No questions"
1852
- puts " • File: File path with @ browsing"
1853
- puts " • Number: Integer or decimal numbers"
1854
- puts " • Email: Email address format"
1855
- puts " • URL: Web URL format"
1856
-
1857
- puts "\n⌨️ Special Commands:"
1858
- puts " • @: Browse and select files"
1859
- puts " • Enter: Use default value (if available)"
1860
- puts " • Ctrl+C: Cancel operation"
1861
-
1862
- puts "\n📁 File Selection:"
1863
- puts " • Type @ to browse files"
1864
- puts " • Type @search to filter files"
1865
- puts " • Select by number or type 0 to cancel"
1866
-
1867
- puts "\n✅ Validation:"
1868
- puts " • Required fields must be filled"
1869
- puts " • Input format is validated automatically"
1870
- puts " • Invalid input shows error and retries"
1871
-
1872
- puts "\n💡 Tips:"
1873
- puts " • Use Tab for auto-completion"
1874
- puts " • Arrow keys for history navigation"
1875
- puts " • Default values are shown in prompts"
1853
+ display_message("\n📖 Interactive Prompt Help:", type: :info)
1854
+ display_message("=" * 40, type: :info)
1855
+
1856
+ display_message("\n🔤 Input Types:", type: :info)
1857
+ display_message(" • Text: Free-form text input", type: :info)
1858
+ display_message(" • Choice: Select from predefined options", type: :info)
1859
+ display_message(" • Confirmation: Yes/No questions", type: :info)
1860
+ display_message(" • File: File path with @ browsing", type: :info)
1861
+ display_message(" • Number: Integer or decimal numbers", type: :info)
1862
+ display_message(" • Email: Email address format", type: :info)
1863
+ display_message(" • URL: Web URL format", type: :info)
1864
+
1865
+ display_message("\n⌨️ Special Commands:", type: :info)
1866
+ display_message(" • @: Browse and select files", type: :info)
1867
+ display_message(" • Enter: Use default value (if available)", type: :info)
1868
+ display_message(" • Ctrl+C: Cancel operation", type: :info)
1869
+
1870
+ display_message("\n📁 File Selection:", type: :info)
1871
+ display_message(" • Type @ to browse files", type: :info)
1872
+ display_message(" • Type @search to filter files", type: :info)
1873
+ display_message(" • Select by number or type 0 to cancel", type: :info)
1874
+
1875
+ display_message("\n✅ Validation:", type: :info)
1876
+ display_message(" • Required fields must be filled", type: :info)
1877
+ display_message(" • Input format is validated automatically", type: :info)
1878
+ display_message(" • Invalid input shows error and retries", type: :info)
1879
+
1880
+ display_message("\n💡 Tips:", type: :info)
1881
+ display_message(" • Use Tab for auto-completion", type: :info)
1882
+ display_message(" • Arrow keys for history navigation", type: :info)
1883
+ display_message(" • Default values are shown in prompts", type: :info)
1876
1884
  end
1877
1885
 
1878
1886
  # Display question summary
1879
1887
  def display_question_summary(questions)
1880
- puts "\n📋 Question Summary:"
1881
- puts "-" * 30
1888
+ display_message("\n📋 Question Summary:", type: :info)
1889
+ display_message("-" * 30, type: :info)
1882
1890
 
1883
1891
  questions.each_with_index do |question_data, index|
1884
1892
  question_number = question_data[:number] || (index + 1)
@@ -1898,14 +1906,14 @@ module Aidp
1898
1906
  }
1899
1907
  type_emoji = type_emojis[question_type] || "❓"
1900
1908
 
1901
- puts " #{question_number}. #{type_emoji} #{question_text} (#{status})"
1909
+ display_message(" #{question_number}. #{type_emoji} #{question_text} (#{status})", type: :info)
1902
1910
  end
1903
1911
  end
1904
1912
 
1905
1913
  # Get user preferences for feedback collection
1906
1914
  def get_user_preferences
1907
- puts "\n⚙️ User Preferences:"
1908
- puts "-" * 25
1915
+ display_message("\n⚙️ User Preferences:", type: :info)
1916
+ display_message("-" * 25, type: :muted)
1909
1917
 
1910
1918
  preferences = {}
1911
1919
 
@@ -1967,14 +1975,14 @@ module Aidp
1967
1975
  # Show help if needed
1968
1976
  if should_show_help?(questions.first&.dig(:type), seen_types)
1969
1977
  show_help
1970
- puts "\nPress Enter to continue..."
1978
+ display_message("\nPress Enter to continue...", type: :info)
1971
1979
  @prompt.keypress("Press any key to continue...")
1972
1980
  end
1973
1981
 
1974
1982
  # Display question summary if verbose
1975
1983
  if @verbose_mode
1976
1984
  display_question_summary(questions)
1977
- puts "\nPress Enter to start answering questions..."
1985
+ display_message("\nPress Enter to start answering questions...", type: :info)
1978
1986
  @prompt.keypress("Press any key to continue...")
1979
1987
  end
1980
1988
 
@@ -1995,7 +2003,7 @@ module Aidp
1995
2003
  default_value = options[:default]
1996
2004
  required = options[:required] != false
1997
2005
 
1998
- puts "\n❓ #{question}"
2006
+ display_message("\n❓ #{question}", type: :info)
1999
2007
 
2000
2008
  case question_type
2001
2009
  when "text"
@@ -2013,8 +2021,8 @@ module Aidp
2013
2021
  def collect_batch_feedback(questions)
2014
2022
  responses = {}
2015
2023
 
2016
- puts "\n📝 Quick Feedback Collection:"
2017
- puts "=" * 35
2024
+ display_message("\n📝 Quick Feedback Collection:", type: :info)
2025
+ display_message("=" * 35, type: :muted)
2018
2026
 
2019
2027
  questions.each_with_index do |question_data, index|
2020
2028
  question_number = index + 1
@@ -2023,7 +2031,7 @@ module Aidp
2023
2031
  default_value = question_data[:default]
2024
2032
  required = question_data[:required] != false
2025
2033
 
2026
- puts "\n#{question_number}. #{question_text}"
2034
+ display_message("\n#{question_number}. #{question_text}", type: :info)
2027
2035
 
2028
2036
  response = get_quick_feedback(question_text, {
2029
2037
  type: question_type,
@@ -2035,7 +2043,7 @@ module Aidp
2035
2043
  responses["question_#{question_number}"] = response
2036
2044
  end
2037
2045
 
2038
- puts "\n✅ Batch feedback collected."
2046
+ display_message("\n✅ Batch feedback collected.", type: :success)
2039
2047
  responses
2040
2048
  end
2041
2049
 
@@ -2059,13 +2067,13 @@ module Aidp
2059
2067
  end
2060
2068
  end
2061
2069
 
2062
- puts "\n🎮 Control Interface Started"
2063
- puts " Press 'p' + Enter to pause"
2064
- puts " Press 'r' + Enter to resume"
2065
- puts " Press 's' + Enter to stop"
2066
- puts " Press 'h' + Enter for help"
2067
- puts " Press 'q' + Enter to quit control interface"
2068
- puts "=" * 50
2070
+ display_message("\n🎮 Control Interface Started", type: :success)
2071
+ display_message(" Press 'p' + Enter to pause", type: :info)
2072
+ display_message(" Press 'r' + Enter to resume", type: :info)
2073
+ display_message(" Press 's' + Enter to stop", type: :info)
2074
+ display_message(" Press 'h' + Enter for help", type: :info)
2075
+ display_message(" Press 'q' + Enter to quit control interface", type: :info)
2076
+ display_message("=" * 50, type: :muted)
2069
2077
  end
2070
2078
 
2071
2079
  # Stop the control interface
@@ -2077,7 +2085,7 @@ module Aidp
2077
2085
  end
2078
2086
  end
2079
2087
 
2080
- puts "\n🛑 Control Interface Stopped"
2088
+ display_message("\n🛑 Control Interface Stopped", type: :info)
2081
2089
  end
2082
2090
 
2083
2091
  # Check if pause is requested
@@ -2101,7 +2109,7 @@ module Aidp
2101
2109
  @pause_requested = true
2102
2110
  @resume_requested = false
2103
2111
  end
2104
- puts "\n⏸️ Pause requested..."
2112
+ display_message("\n⏸️ Pause requested...", type: :warning)
2105
2113
  end
2106
2114
 
2107
2115
  # Request stop
@@ -2111,7 +2119,7 @@ module Aidp
2111
2119
  @pause_requested = false
2112
2120
  @resume_requested = false
2113
2121
  end
2114
- puts "\n🛑 Stop requested..."
2122
+ display_message("\n🛑 Stop requested...", type: :error)
2115
2123
  end
2116
2124
 
2117
2125
  # Request resume
@@ -2120,7 +2128,7 @@ module Aidp
2120
2128
  @resume_requested = true
2121
2129
  @pause_requested = false
2122
2130
  end
2123
- puts "\n▶️ Resume requested..."
2131
+ display_message("\n▶️ Resume requested...", type: :success)
2124
2132
  end
2125
2133
 
2126
2134
  # Clear all control requests
@@ -2155,14 +2163,14 @@ module Aidp
2155
2163
 
2156
2164
  # Handle pause state
2157
2165
  def handle_pause_state
2158
- puts "\n⏸️ HARNESS PAUSED"
2159
- puts "=" * 50
2160
- puts "🎮 Control Options:"
2161
- puts " 'r' + Enter: Resume execution"
2162
- puts " 's' + Enter: Stop execution"
2163
- puts " 'h' + Enter: Show help"
2164
- puts " 'q' + Enter: Quit control interface"
2165
- puts "=" * 50
2166
+ display_message("\n⏸️ HARNESS PAUSED", type: :warning)
2167
+ display_message("=" * 50, type: :muted)
2168
+ display_message("🎮 Control Options:", type: :info)
2169
+ display_message(" 'r' + Enter: Resume execution", type: :info)
2170
+ display_message(" 's' + Enter: Stop execution", type: :info)
2171
+ display_message(" 'h' + Enter: Show help", type: :info)
2172
+ display_message(" 'q' + Enter: Quit control interface", type: :info)
2173
+ display_message("=" * 50, type: :muted)
2166
2174
 
2167
2175
  loop do
2168
2176
  input = @prompt.ask("Paused>")
@@ -2180,51 +2188,51 @@ module Aidp
2180
2188
  stop_control_interface
2181
2189
  break
2182
2190
  else
2183
- puts "❌ Invalid command. Type 'h' for help."
2191
+ display_message("❌ Invalid command. Type 'h' for help.", type: :error)
2184
2192
  end
2185
2193
  end
2186
2194
  end
2187
2195
 
2188
2196
  # Handle stop state
2189
2197
  def handle_stop_state
2190
- puts "\n🛑 HARNESS STOPPED"
2191
- puts "=" * 50
2192
- puts "Execution has been stopped by user request."
2193
- puts "You can restart the harness from where it left off."
2194
- puts "=" * 50
2198
+ display_message("\n🛑 HARNESS STOPPED", type: :error)
2199
+ display_message("=" * 50, type: :muted)
2200
+ display_message("Execution has been stopped by user request.", type: :info)
2201
+ display_message("You can restart the harness from where it left off.", type: :info)
2202
+ display_message("=" * 50, type: :muted)
2195
2203
  end
2196
2204
 
2197
2205
  # Handle resume state
2198
2206
  def handle_resume_state
2199
- puts "\n▶️ HARNESS RESUMED"
2200
- puts "=" * 50
2201
- puts "Execution has been resumed."
2202
- puts "=" * 50
2207
+ display_message("\n▶️ HARNESS RESUMED", type: :success)
2208
+ display_message("=" * 50, type: :muted)
2209
+ display_message("Execution has been resumed.", type: :info)
2210
+ display_message("=" * 50, type: :muted)
2203
2211
  end
2204
2212
 
2205
2213
  # Show control help
2206
2214
  def show_control_help
2207
- puts "\n📖 Control Interface Help"
2208
- puts "=" * 50
2209
- puts "🎮 Available Commands:"
2210
- puts " 'p' or 'pause' - Pause the harness execution"
2211
- puts " 'r' or 'resume' - Resume the harness execution"
2212
- puts " 's' or 'stop' - Stop the harness execution"
2213
- puts " 'h' or 'help' - Show this help message"
2214
- puts " 'q' or 'quit' - Quit the control interface"
2215
- puts ""
2216
- puts "📋 Control States:"
2217
- puts " Running - Harness is executing normally"
2218
- puts " Paused - Harness is paused, waiting for resume"
2219
- puts " Stopped - Harness has been stopped by user"
2220
- puts " Resumed - Harness has been resumed from pause"
2221
- puts ""
2222
- puts "💡 Tips:"
2223
- puts " • You can pause/resume/stop at any time during execution"
2224
- puts " • The harness will save its state when paused/stopped"
2225
- puts " • You can restart from where you left off"
2226
- puts " • Use 'h' for help at any time"
2227
- puts "=" * 50
2215
+ display_message("\n📖 Control Interface Help", type: :info)
2216
+ display_message("=" * 50, type: :muted)
2217
+ display_message("🎮 Available Commands:", type: :info)
2218
+ display_message(" 'p' or 'pause' - Pause the harness execution", type: :info)
2219
+ display_message(" 'r' or 'resume' - Resume the harness execution", type: :info)
2220
+ display_message(" 's' or 'stop' - Stop the harness execution", type: :info)
2221
+ display_message(" 'h' or 'help' - Show this help message", type: :info)
2222
+ display_message(" 'q' or 'quit' - Quit the control interface", type: :info)
2223
+ display_message("", type: :info)
2224
+ display_message("📋 Control States:", type: :info)
2225
+ display_message(" Running - Harness is executing normally", type: :info)
2226
+ display_message(" Paused - Harness is paused, waiting for resume", type: :info)
2227
+ display_message(" Stopped - Harness has been stopped by user", type: :info)
2228
+ display_message(" Resumed - Harness has been resumed from pause", type: :info)
2229
+ display_message("", type: :info)
2230
+ display_message("💡 Tips:", type: :info)
2231
+ display_message(" • You can pause/resume/stop at any time during execution", type: :info)
2232
+ display_message(" • The harness will save its state when paused/stopped", type: :info)
2233
+ display_message(" • You can restart from where you left off", type: :info)
2234
+ display_message(" • Use 'h' for help at any time", type: :info)
2235
+ display_message("=" * 50, type: :muted)
2228
2236
  end
2229
2237
 
2230
2238
  # Control interface main loop
@@ -2248,15 +2256,15 @@ module Aidp
2248
2256
  # Empty input, continue
2249
2257
  next
2250
2258
  else
2251
- puts "❌ Invalid command. Type 'h' for help."
2259
+ display_message("❌ Invalid command. Type 'h' for help.", type: :error)
2252
2260
  end
2253
2261
  rescue Interrupt
2254
- puts "\n🛑 Control interface interrupted. Stopping..."
2262
+ display_message("\n🛑 Control interface interrupted. Stopping...", type: :error)
2255
2263
  request_stop
2256
2264
  break
2257
2265
  rescue => e
2258
- puts "❌ Control interface error: #{e.message}"
2259
- puts " Type 'h' for help or 'q' to quit."
2266
+ display_message("❌ Control interface error: #{e.message}", type: :error)
2267
+ display_message(" Type 'h' for help or 'q' to quit.", type: :info)
2260
2268
  end
2261
2269
  end
2262
2270
 
@@ -2280,14 +2288,14 @@ module Aidp
2280
2288
  # Enable control interface
2281
2289
  def enable_control_interface
2282
2290
  @control_interface_enabled = true
2283
- puts "🎮 Control interface enabled"
2291
+ display_message("🎮 Control interface enabled", type: :success)
2284
2292
  end
2285
2293
 
2286
2294
  # Disable control interface
2287
2295
  def disable_control_interface
2288
2296
  @control_interface_enabled = false
2289
2297
  stop_control_interface
2290
- puts "🎮 Control interface disabled"
2298
+ display_message("🎮 Control interface disabled", type: :info)
2291
2299
  end
2292
2300
 
2293
2301
  # Get control status
@@ -2307,29 +2315,29 @@ module Aidp
2307
2315
  def display_control_status
2308
2316
  status = get_control_status
2309
2317
 
2310
- puts "\n🎮 Control Interface Status"
2311
- puts "=" * 40
2312
- puts "Enabled: #{status[:enabled] ? "✅ Yes" : "❌ No"}"
2313
- puts "Pause Requested: #{status[:pause_requested] ? "⏸️ Yes" : "▶️ No"}"
2314
- puts "Stop Requested: #{status[:stop_requested] ? "🛑 Yes" : "▶️ No"}"
2315
- puts "Resume Requested: #{status[:resume_requested] ? "▶️ Yes" : "⏸️ No"}"
2316
- puts "Control Thread: #{status[:control_thread_alive] ? "🟢 Active" : "🔴 Inactive"}"
2317
- puts "=" * 40
2318
+ display_message("\n🎮 Control Interface Status", type: :info)
2319
+ display_message("=" * 40, type: :muted)
2320
+ display_message("Enabled: #{status[:enabled] ? "✅ Yes" : "❌ No"}", type: :info)
2321
+ display_message("Pause Requested: #{status[:pause_requested] ? "⏸️ Yes" : "▶️ No"}", type: :info)
2322
+ display_message("Stop Requested: #{status[:stop_requested] ? "🛑 Yes" : "▶️ No"}", type: :info)
2323
+ display_message("Resume Requested: #{status[:resume_requested] ? "▶️ Yes" : "⏸️ No"}", type: :info)
2324
+ display_message("Control Thread: #{status[:control_thread_alive] ? "🟢 Active" : "🔴 Inactive"}", type: :info)
2325
+ display_message("=" * 40, type: :muted)
2318
2326
  end
2319
2327
 
2320
2328
  # Interactive control menu
2321
2329
  def show_control_menu
2322
- puts "\n🎮 Harness Control Menu"
2323
- puts "=" * 50
2324
- puts "1. Start Control Interface"
2325
- puts "2. Stop Control Interface"
2326
- puts "3. Pause Harness"
2327
- puts "4. Resume Harness"
2328
- puts "5. Stop Harness"
2329
- puts "6. Show Control Status"
2330
- puts "7. Show Help"
2331
- puts "8. Exit Menu"
2332
- puts "=" * 50
2330
+ display_message("\n🎮 Harness Control Menu", type: :info)
2331
+ display_message("=" * 50, type: :muted)
2332
+ display_message("1. Start Control Interface", type: :info)
2333
+ display_message("2. Stop Control Interface", type: :info)
2334
+ display_message("3. Pause Harness", type: :info)
2335
+ display_message("4. Resume Harness", type: :info)
2336
+ display_message("5. Stop Harness", type: :info)
2337
+ display_message("6. Show Control Status", type: :info)
2338
+ display_message("7. Show Help", type: :info)
2339
+ display_message("8. Exit Menu", type: :info)
2340
+ display_message("=" * 50, type: :muted)
2333
2341
 
2334
2342
  loop do
2335
2343
  choice = @prompt.ask("Select option (1-8): ")
@@ -2350,10 +2358,10 @@ module Aidp
2350
2358
  when "7"
2351
2359
  show_control_help
2352
2360
  when "8"
2353
- puts "👋 Exiting control menu..."
2361
+ display_message("👋 Exiting control menu...", type: :info)
2354
2362
  break
2355
2363
  else
2356
- puts "❌ Invalid option. Please select 1-8."
2364
+ display_message("❌ Invalid option. Please select 1-8.", type: :error)
2357
2365
  end
2358
2366
  end
2359
2367
  end
@@ -2361,17 +2369,17 @@ module Aidp
2361
2369
  # Quick control commands
2362
2370
  def quick_pause
2363
2371
  request_pause
2364
- puts "⏸️ Quick pause requested. Use 'r' to resume."
2372
+ display_message("⏸️ Quick pause requested. Use 'r' to resume.", type: :warning)
2365
2373
  end
2366
2374
 
2367
2375
  def quick_resume
2368
2376
  request_resume
2369
- puts "▶️ Quick resume requested."
2377
+ display_message("▶️ Quick resume requested.", type: :success)
2370
2378
  end
2371
2379
 
2372
2380
  def quick_stop
2373
2381
  request_stop
2374
- puts "🛑 Quick stop requested."
2382
+ display_message("🛑 Quick stop requested.", type: :error)
2375
2383
  end
2376
2384
 
2377
2385
  # Control interface with timeout
@@ -2390,7 +2398,7 @@ module Aidp
2390
2398
  handle_resume_state
2391
2399
  break
2392
2400
  elsif Time.now - start_time > timeout_seconds
2393
- puts "\n⏰ Control interface timeout reached. Continuing execution..."
2401
+ display_message("\n⏰ Control interface timeout reached. Continuing execution...", type: :warning)
2394
2402
  break
2395
2403
  elsif ENV["RACK_ENV"] == "test" || defined?(RSpec)
2396
2404
  sleep(0.1)
@@ -2402,11 +2410,11 @@ module Aidp
2402
2410
 
2403
2411
  # Emergency stop
2404
2412
  def emergency_stop
2405
- puts "\n🚨 EMERGENCY STOP INITIATED"
2406
- puts "=" * 50
2407
- puts "All execution will be halted immediately."
2408
- puts "This action cannot be undone."
2409
- puts "=" * 50
2413
+ display_message("\n🚨 EMERGENCY STOP INITIATED", type: :error)
2414
+ display_message("=" * 50, type: :muted)
2415
+ display_message("All execution will be halted immediately.", type: :error)
2416
+ display_message("This action cannot be undone.", type: :error)
2417
+ display_message("=" * 50, type: :muted)
2410
2418
 
2411
2419
  @control_mutex.synchronize do
2412
2420
  @stop_requested = true
@@ -2415,7 +2423,7 @@ module Aidp
2415
2423
  end
2416
2424
 
2417
2425
  stop_control_interface
2418
- puts "🛑 Emergency stop completed."
2426
+ display_message("🛑 Emergency stop completed.", type: :error)
2419
2427
  end
2420
2428
  end
2421
2429
  end