aidp 0.25.0 → 0.27.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 (71) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +45 -6
  3. data/lib/aidp/analyze/error_handler.rb +11 -0
  4. data/lib/aidp/cli/checkpoint_command.rb +198 -0
  5. data/lib/aidp/cli/config_command.rb +71 -0
  6. data/lib/aidp/cli/enhanced_input.rb +2 -0
  7. data/lib/aidp/cli/first_run_wizard.rb +8 -7
  8. data/lib/aidp/cli/harness_command.rb +102 -0
  9. data/lib/aidp/cli/jobs_command.rb +3 -3
  10. data/lib/aidp/cli/mcp_dashboard.rb +4 -3
  11. data/lib/aidp/cli/models_command.rb +662 -0
  12. data/lib/aidp/cli/providers_command.rb +223 -0
  13. data/lib/aidp/cli.rb +35 -456
  14. data/lib/aidp/daemon/runner.rb +2 -2
  15. data/lib/aidp/debug_mixin.rb +2 -9
  16. data/lib/aidp/execute/async_work_loop_runner.rb +2 -1
  17. data/lib/aidp/execute/checkpoint_display.rb +38 -37
  18. data/lib/aidp/execute/interactive_repl.rb +2 -1
  19. data/lib/aidp/execute/prompt_manager.rb +4 -4
  20. data/lib/aidp/execute/work_loop_runner.rb +253 -56
  21. data/lib/aidp/execute/workflow_selector.rb +2 -2
  22. data/lib/aidp/harness/config_loader.rb +20 -11
  23. data/lib/aidp/harness/config_manager.rb +5 -5
  24. data/lib/aidp/harness/config_schema.rb +30 -8
  25. data/lib/aidp/harness/configuration.rb +105 -4
  26. data/lib/aidp/harness/enhanced_runner.rb +24 -15
  27. data/lib/aidp/harness/error_handler.rb +26 -5
  28. data/lib/aidp/harness/filter_strategy.rb +45 -0
  29. data/lib/aidp/harness/generic_filter_strategy.rb +63 -0
  30. data/lib/aidp/harness/model_cache.rb +269 -0
  31. data/lib/aidp/harness/model_discovery_service.rb +259 -0
  32. data/lib/aidp/harness/model_registry.rb +201 -0
  33. data/lib/aidp/harness/output_filter.rb +136 -0
  34. data/lib/aidp/harness/provider_manager.rb +18 -3
  35. data/lib/aidp/harness/rspec_filter_strategy.rb +82 -0
  36. data/lib/aidp/harness/runner.rb +5 -0
  37. data/lib/aidp/harness/test_runner.rb +165 -27
  38. data/lib/aidp/harness/thinking_depth_manager.rb +223 -7
  39. data/lib/aidp/harness/ui/enhanced_tui.rb +4 -1
  40. data/lib/aidp/logger.rb +35 -5
  41. data/lib/aidp/providers/adapter.rb +2 -4
  42. data/lib/aidp/providers/anthropic.rb +141 -128
  43. data/lib/aidp/providers/base.rb +98 -2
  44. data/lib/aidp/providers/capability_registry.rb +0 -1
  45. data/lib/aidp/providers/codex.rb +49 -67
  46. data/lib/aidp/providers/cursor.rb +71 -59
  47. data/lib/aidp/providers/gemini.rb +44 -60
  48. data/lib/aidp/providers/github_copilot.rb +2 -66
  49. data/lib/aidp/providers/kilocode.rb +24 -80
  50. data/lib/aidp/providers/opencode.rb +24 -80
  51. data/lib/aidp/safe_directory.rb +10 -3
  52. data/lib/aidp/setup/wizard.rb +345 -8
  53. data/lib/aidp/storage/csv_storage.rb +9 -3
  54. data/lib/aidp/storage/file_manager.rb +8 -2
  55. data/lib/aidp/storage/json_storage.rb +9 -3
  56. data/lib/aidp/version.rb +1 -1
  57. data/lib/aidp/watch/build_processor.rb +40 -1
  58. data/lib/aidp/watch/change_request_processor.rb +659 -0
  59. data/lib/aidp/watch/plan_generator.rb +93 -14
  60. data/lib/aidp/watch/plan_processor.rb +71 -8
  61. data/lib/aidp/watch/repository_client.rb +85 -20
  62. data/lib/aidp/watch/review_processor.rb +3 -3
  63. data/lib/aidp/watch/runner.rb +37 -0
  64. data/lib/aidp/watch/state_store.rb +46 -1
  65. data/lib/aidp/workflows/guided_agent.rb +3 -3
  66. data/lib/aidp/workstream_executor.rb +5 -2
  67. data/lib/aidp.rb +4 -0
  68. data/templates/aidp-development.yml.example +2 -2
  69. data/templates/aidp-production.yml.example +3 -3
  70. data/templates/aidp.yml.example +53 -0
  71. metadata +14 -1
@@ -8,17 +8,18 @@ module Aidp
8
8
  class CheckpointDisplay
9
9
  include Aidp::MessageDisplay
10
10
 
11
- def initialize
11
+ def initialize(prompt: nil)
12
12
  @pastel = Pastel.new
13
+ @prompt = prompt || TTY::Prompt.new
13
14
  end
14
15
 
15
16
  # Display a checkpoint during work loop iteration
16
17
  def display_checkpoint(checkpoint_data, show_details: false)
17
18
  return unless checkpoint_data
18
19
 
19
- puts
20
- puts @pastel.bold("📊 Checkpoint - Iteration #{checkpoint_data[:iteration]}")
21
- puts @pastel.dim("─" * 60)
20
+ @prompt.say("")
21
+ @prompt.say(@pastel.bold("📊 Checkpoint - Iteration #{checkpoint_data[:iteration]}"))
22
+ @prompt.say(@pastel.dim("─" * 60))
22
23
 
23
24
  display_metrics(checkpoint_data[:metrics])
24
25
  display_status(checkpoint_data[:status])
@@ -27,52 +28,52 @@ module Aidp
27
28
  display_trends(checkpoint_data[:trends]) if checkpoint_data[:trends]
28
29
  end
29
30
 
30
- puts @pastel.dim("─" * 60)
31
- puts
31
+ @prompt.say(@pastel.dim("─" * 60))
32
+ @prompt.say("")
32
33
  end
33
34
 
34
35
  # Display progress summary with trends
35
36
  def display_progress_summary(summary)
36
37
  return unless summary
37
38
 
38
- puts
39
- puts @pastel.bold("📈 Progress Summary")
40
- puts @pastel.dim("=" * 60)
39
+ @prompt.say("")
40
+ @prompt.say(@pastel.bold("📈 Progress Summary"))
41
+ @prompt.say(@pastel.dim("=" * 60))
41
42
 
42
43
  current = summary[:current]
43
- puts "Step: #{@pastel.cyan(current[:step_name])}"
44
- puts "Iteration: #{current[:iteration]}"
45
- puts "Status: #{format_status(current[:status])}"
46
- puts
44
+ @prompt.say("Step: #{@pastel.cyan(current[:step_name])}")
45
+ @prompt.say("Iteration: #{current[:iteration]}")
46
+ @prompt.say("Status: #{format_status(current[:status])}")
47
+ @prompt.say("")
47
48
 
48
- puts @pastel.bold("Current Metrics:")
49
+ @prompt.say(@pastel.bold("Current Metrics:"))
49
50
  display_metrics(current[:metrics])
50
51
 
51
52
  if summary[:trends]
52
- puts
53
- puts @pastel.bold("Trends:")
53
+ @prompt.say("")
54
+ @prompt.say(@pastel.bold("Trends:"))
54
55
  display_trends(summary[:trends])
55
56
  end
56
57
 
57
58
  if summary[:quality_score]
58
- puts
59
+ @prompt.say("")
59
60
  display_quality_score(summary[:quality_score])
60
61
  end
61
62
 
62
- puts @pastel.dim("=" * 60)
63
- puts
63
+ @prompt.say(@pastel.dim("=" * 60))
64
+ @prompt.say("")
64
65
  end
65
66
 
66
67
  # Display checkpoint history as a table
67
68
  def display_checkpoint_history(history, limit: 10)
68
69
  return if history.empty?
69
70
 
70
- puts
71
- puts @pastel.bold("📜 Checkpoint History (Last #{[limit, history.size].min})")
72
- puts @pastel.dim("=" * 80)
71
+ @prompt.say("")
72
+ @prompt.say(@pastel.bold("📜 Checkpoint History (Last #{[limit, history.size].min})"))
73
+ @prompt.say(@pastel.dim("=" * 80))
73
74
 
74
75
  # Table header
75
- puts format_table_row([
76
+ @prompt.say(format_table_row([
76
77
  "Iteration",
77
78
  "Time",
78
79
  "LOC",
@@ -80,15 +81,15 @@ module Aidp
80
81
  "Quality",
81
82
  "PRD Progress",
82
83
  "Status"
83
- ], header: true)
84
- puts @pastel.dim("-" * 80)
84
+ ], header: true))
85
+ @prompt.say(@pastel.dim("-" * 80))
85
86
 
86
87
  # Table rows
87
88
  history.last(limit).each do |checkpoint|
88
89
  metrics = checkpoint[:metrics]
89
90
  timestamp = Time.parse(checkpoint[:timestamp]).strftime("%H:%M:%S")
90
91
 
91
- puts format_table_row([
92
+ @prompt.say(format_table_row([
92
93
  checkpoint[:iteration].to_s,
93
94
  timestamp,
94
95
  metrics[:lines_of_code].to_s,
@@ -96,11 +97,11 @@ module Aidp
96
97
  "#{metrics[:code_quality]}%",
97
98
  "#{metrics[:prd_task_progress]}%",
98
99
  format_status(checkpoint[:status])
99
- ])
100
+ ]))
100
101
  end
101
102
 
102
- puts @pastel.dim("=" * 80)
103
- puts
103
+ @prompt.say(@pastel.dim("=" * 80))
104
+ @prompt.say("")
104
105
  end
105
106
 
106
107
  # Display inline progress indicator (for work loop)
@@ -124,15 +125,15 @@ module Aidp
124
125
  private
125
126
 
126
127
  def display_metrics(metrics)
127
- puts " Lines of Code: #{@pastel.yellow(metrics[:lines_of_code].to_s)}"
128
- puts " Test Coverage: #{format_percentage_with_color(metrics[:test_coverage])}"
129
- puts " Code Quality: #{format_percentage_with_color(metrics[:code_quality])}"
130
- puts " PRD Task Progress: #{format_percentage_with_color(metrics[:prd_task_progress])}"
131
- puts " File Count: #{metrics[:file_count]}"
128
+ @prompt.say(" Lines of Code: #{@pastel.yellow(metrics[:lines_of_code].to_s)}")
129
+ @prompt.say(" Test Coverage: #{format_percentage_with_color(metrics[:test_coverage])}")
130
+ @prompt.say(" Code Quality: #{format_percentage_with_color(metrics[:code_quality])}")
131
+ @prompt.say(" PRD Task Progress: #{format_percentage_with_color(metrics[:prd_task_progress])}")
132
+ @prompt.say(" File Count: #{metrics[:file_count]}")
132
133
  end
133
134
 
134
135
  def display_status(status)
135
- puts " Overall Status: #{format_status(status)}"
136
+ @prompt.say(" Overall Status: #{format_status(status)}")
136
137
  end
137
138
 
138
139
  def format_status(status)
@@ -156,7 +157,7 @@ module Aidp
156
157
  arrow = trend_arrow(trend_data[:direction])
157
158
  change = format_change(trend_data[:change], trend_data[:change_percent])
158
159
 
159
- puts " #{metric_name}: #{arrow} #{change}"
160
+ @prompt.say(" #{metric_name}: #{arrow} #{change}")
160
161
  end
161
162
  end
162
163
 
@@ -185,7 +186,7 @@ module Aidp
185
186
  :red
186
187
  end
187
188
 
188
- puts " Quality Score: #{@pastel.send(color, "#{score.round(2)}%")}"
189
+ @prompt.say(" Quality Score: #{@pastel.send(color, "#{score.round(2)}%")}")
189
190
  end
190
191
 
191
192
  def format_percentage(value)
@@ -29,6 +29,7 @@ module Aidp
29
29
  @config = config
30
30
  @options = options
31
31
  @prompt = options[:prompt] || TTY::Prompt.new
32
+ @async_runner_class = options[:async_runner_class] || AsyncWorkLoopRunner
32
33
  @async_runner = nil
33
34
  @repl_macros = ReplMacros.new
34
35
  @output_display_thread = nil
@@ -38,7 +39,7 @@ module Aidp
38
39
 
39
40
  # Start work loop and enter interactive REPL
40
41
  def start_work_loop(step_name, step_spec, context = {})
41
- @async_runner = AsyncWorkLoopRunner.new(
42
+ @async_runner = @async_runner_class.new(
42
43
  @project_dir,
43
44
  @provider_manager,
44
45
  @config,
@@ -17,20 +17,20 @@ module Aidp
17
17
 
18
18
  attr_reader :optimizer, :last_optimization_stats
19
19
 
20
- def initialize(project_dir, config: nil)
20
+ def initialize(project_dir, config: nil, optimizer: nil)
21
21
  @project_dir = project_dir
22
22
  @aidp_dir = File.join(project_dir, ".aidp")
23
23
  @prompt_path = File.join(@aidp_dir, PROMPT_FILENAME)
24
24
  @archive_dir = File.join(project_dir, ARCHIVE_DIR)
25
25
  @config = config
26
- @optimizer = nil
26
+ @optimizer = optimizer
27
27
  @last_optimization_stats = nil
28
28
 
29
29
  # Ensure .aidp directory exists
30
30
  FileUtils.mkdir_p(@aidp_dir)
31
31
 
32
- # Initialize optimizer if enabled
33
- if config&.respond_to?(:prompt_optimization_enabled?) && config.prompt_optimization_enabled?
32
+ # Initialize optimizer if enabled and not provided
33
+ if @optimizer.nil? && config&.respond_to?(:prompt_optimization_enabled?) && config.prompt_optimization_enabled?
34
34
  @optimizer = Aidp::PromptOptimization::Optimizer.new(
35
35
  project_dir: project_dir,
36
36
  config: config.prompt_optimization_config