Class: Aidp::Harness::Runner
- Inherits:
-
Object
- Object
- Aidp::Harness::Runner
- Includes:
- MessageDisplay
- Defined in:
- lib/aidp/harness/runner.rb
Overview
Main harness runner that orchestrates the execution loop
Constant Summary collapse
- STATES =
Harness execution states
{ idle: "idle", running: "running", paused: "paused", waiting_for_user: "waiting_for_user", waiting_for_rate_limit: "waiting_for_rate_limit", stopped: "stopped", completed: "completed", error: "error", needs_clarification: "needs_clarification" }.freeze
Constants included from MessageDisplay
MessageDisplay::COLOR_MAP, MessageDisplay::CRITICAL_TYPES
Instance Attribute Summary collapse
-
#clarification_questions ⇒ Object
readonly
Public accessors for testing and integration.
-
#completion_checker ⇒ Object
writeonly
Sets the attribute completion_checker.
-
#condition_detector ⇒ Object
Returns the value of attribute condition_detector.
-
#configuration ⇒ Object
Returns the value of attribute configuration.
-
#current_provider ⇒ Object
Returns the value of attribute current_provider.
-
#current_step ⇒ Object
Returns the value of attribute current_step.
-
#error_handler ⇒ Object
Returns the value of attribute error_handler.
-
#execution_log ⇒ Object
Returns the value of attribute execution_log.
-
#last_error ⇒ Object
readonly
Public accessors for testing and integration.
-
#mode ⇒ Object
Returns the value of attribute mode.
-
#non_interactive ⇒ Object
writeonly
Sets the attribute non_interactive.
-
#project_dir ⇒ Object
Returns the value of attribute project_dir.
-
#provider_manager ⇒ Object
Returns the value of attribute provider_manager.
-
#state ⇒ Object
Returns the value of attribute state.
-
#state_manager ⇒ Object
Returns the value of attribute state_manager.
-
#status_display ⇒ Object
Returns the value of attribute status_display.
-
#user_input ⇒ Object
Returns the value of attribute user_input.
-
#user_interface ⇒ Object
Returns the value of attribute user_interface.
-
#workflow_type ⇒ Object
writeonly
Sets the attribute workflow_type.
Instance Method Summary collapse
-
#detailed_status ⇒ Object
Get detailed status including all components.
-
#initialize(project_dir, mode = :analyze, options = {}) ⇒ Runner
constructor
A new instance of Runner.
-
#pause ⇒ Object
Pause the harness execution.
-
#resume ⇒ Object
Resume the harness execution.
-
#run ⇒ Object
Main execution method - runs the harness loop.
-
#status ⇒ Object
Get current harness status.
-
#stop ⇒ Object
Stop the harness execution.
Methods included from MessageDisplay
#display_message, included, #message_display_prompt, #quiet_mode?
Constructor Details
#initialize(project_dir, mode = :analyze, options = {}) ⇒ Runner
Returns a new instance of Runner.
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/aidp/harness/runner.rb', line 32 def initialize(project_dir, mode = :analyze, = {}) @project_dir = project_dir @mode = mode.to_sym @options = @state = STATES[:idle] @start_time = nil @current_step = nil @current_provider = nil @user_input = [:user_input] || {} # Include user input from workflow selection @execution_log = [] @last_error = nil @prompt = [:prompt] || TTY::Prompt.new # Store workflow configuration @selected_steps = [:selected_steps] @workflow_type = [:workflow_type] @non_interactive = [:non_interactive] || (@workflow_type == :watch_mode) # Initialize components @configuration = Configuration.new(project_dir) @state_manager = StateManager.new(project_dir, @mode) @provider_manager = ProviderManager.new(@configuration, prompt: @prompt) # Use ZFC-enabled condition detector # ZfcConditionDetector will create its own ProviderFactory if needed # Falls back to legacy pattern matching when ZFC is disabled @condition_detector = ZfcConditionDetector.new(@configuration) @user_interface = SimpleUserInterface.new @error_handler = ErrorHandler.new(@provider_manager, @configuration) @status_display = StatusDisplay.new @completion_checker = CompletionChecker.new(@project_dir, @workflow_type) @failure_reason = nil @failure_metadata = nil end |
Instance Attribute Details
#clarification_questions ⇒ Object (readonly)
Public accessors for testing and integration
26 27 28 |
# File 'lib/aidp/harness/runner.rb', line 26 def clarification_questions @clarification_questions end |
#completion_checker=(value) ⇒ Object (writeonly)
Sets the attribute completion_checker
30 31 32 |
# File 'lib/aidp/harness/runner.rb', line 30 def completion_checker=(value) @completion_checker = value end |
#condition_detector ⇒ Object
Returns the value of attribute condition_detector.
28 29 30 |
# File 'lib/aidp/harness/runner.rb', line 28 def condition_detector @condition_detector end |
#configuration ⇒ Object
Returns the value of attribute configuration.
28 29 30 |
# File 'lib/aidp/harness/runner.rb', line 28 def configuration @configuration end |
#current_provider ⇒ Object
Returns the value of attribute current_provider.
27 28 29 |
# File 'lib/aidp/harness/runner.rb', line 27 def current_provider @current_provider end |
#current_step ⇒ Object
Returns the value of attribute current_step.
27 28 29 |
# File 'lib/aidp/harness/runner.rb', line 27 def current_step @current_step end |
#error_handler ⇒ Object
Returns the value of attribute error_handler.
29 30 31 |
# File 'lib/aidp/harness/runner.rb', line 29 def error_handler @error_handler end |
#execution_log ⇒ Object
Returns the value of attribute execution_log.
27 28 29 |
# File 'lib/aidp/harness/runner.rb', line 27 def execution_log @execution_log end |
#last_error ⇒ Object (readonly)
Public accessors for testing and integration
26 27 28 |
# File 'lib/aidp/harness/runner.rb', line 26 def last_error @last_error end |
#mode ⇒ Object
Returns the value of attribute mode.
28 29 30 |
# File 'lib/aidp/harness/runner.rb', line 28 def mode @mode end |
#non_interactive=(value) ⇒ Object (writeonly)
Sets the attribute non_interactive
30 31 32 |
# File 'lib/aidp/harness/runner.rb', line 30 def non_interactive=(value) @non_interactive = value end |
#project_dir ⇒ Object
Returns the value of attribute project_dir.
28 29 30 |
# File 'lib/aidp/harness/runner.rb', line 28 def project_dir @project_dir end |
#provider_manager ⇒ Object
Returns the value of attribute provider_manager.
27 28 29 |
# File 'lib/aidp/harness/runner.rb', line 27 def provider_manager @provider_manager end |
#state ⇒ Object
Returns the value of attribute state.
28 29 30 |
# File 'lib/aidp/harness/runner.rb', line 28 def state @state end |
#state_manager ⇒ Object
Returns the value of attribute state_manager.
29 30 31 |
# File 'lib/aidp/harness/runner.rb', line 29 def state_manager @state_manager end |
#status_display ⇒ Object
Returns the value of attribute status_display.
29 30 31 |
# File 'lib/aidp/harness/runner.rb', line 29 def status_display @status_display end |
#user_input ⇒ Object
Returns the value of attribute user_input.
27 28 29 |
# File 'lib/aidp/harness/runner.rb', line 27 def user_input @user_input end |
#user_interface ⇒ Object
Returns the value of attribute user_interface.
29 30 31 |
# File 'lib/aidp/harness/runner.rb', line 29 def user_interface @user_interface end |
#workflow_type=(value) ⇒ Object (writeonly)
Sets the attribute workflow_type
30 31 32 |
# File 'lib/aidp/harness/runner.rb', line 30 def workflow_type=(value) @workflow_type = value end |
Instance Method Details
#detailed_status ⇒ Object
Get detailed status including all components
212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/aidp/harness/runner.rb', line 212 def detailed_status { harness: status, configuration: { default_provider: @configuration.default_provider, fallback_providers: @configuration.fallback_providers, max_retries: @configuration.harness_config[:max_retries] }, provider_manager: @provider_manager.status, error_stats: @error_handler.error_stats } end |
#pause ⇒ Object
Pause the harness execution
172 173 174 175 176 177 178 |
# File 'lib/aidp/harness/runner.rb', line 172 def pause return unless @state == STATES[:running] @state = STATES[:paused] log_execution("Harness paused by user") @status_display.show_paused_status end |
#resume ⇒ Object
Resume the harness execution
181 182 183 184 185 186 187 |
# File 'lib/aidp/harness/runner.rb', line 181 def resume return unless @state == STATES[:paused] @state = STATES[:running] log_execution("Harness resumed by user") @status_display.show_resumed_status end |
#run ⇒ Object
Main execution method - runs the harness loop
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/aidp/harness/runner.rb', line 69 def run @state = STATES[:running] @start_time = Time.now log_execution("Harness started", {mode: @mode, project_dir: @project_dir}) begin # Load existing state if resuming load_state if @state_manager.has_state? # Get the appropriate runner for the mode runner = get_mode_runner # Main execution loop loop do break if should_stop? # Check for pause conditions if should_pause? handle_pause_condition next end # Get next step to execute next_step = get_next_step(runner) break unless next_step # Execute the step execute_step(runner, next_step) # Update state update_state end # Mark as completed if we finished all steps AND all completion criteria are met if all_steps_completed?(runner) completion_status = @completion_checker.completion_status if completion_status[:all_complete] @state = STATES[:completed] log_execution("Harness completed successfully - all criteria met", completion_status) else log_execution("Steps completed but completion criteria not met", completion_status) ("\n⚠️ All steps completed but some completion criteria not met:", type: :warning) (completion_status[:summary], type: :info) # Ask user if they want to continue anyway if confirmation_prompt_allowed? if @user_interface.get_confirmation("Continue anyway? This may indicate issues that should be addressed.", default: false) @state = STATES[:completed] log_execution("Harness completed with user override") else mark_completion_failure(completion_status) @state = STATES[:error] log_execution("Harness stopped due to unmet completion criteria") end else ("⚠️ Non-interactive mode: cannot override failed completion criteria. Stopping run.", type: :warning) mark_completion_failure(completion_status) @state = STATES[:error] log_execution("Harness stopped due to unmet completion criteria in non-interactive mode") end end end rescue Aidp::Errors::ConfigurationError # Configuration errors should crash immediately (crash-early principle) # Re-raise without catching raise rescue => e @state = STATES[:error] @last_error = e log_execution("Harness error: #{e.}", {error: e.class.name, backtrace: e.backtrace&.first(5)}) handle_error(e) ensure # Save state before exiting - protect against exceptions during cleanup begin save_state rescue => e # Don't let state save failures kill the whole run or prevent cleanup Aidp.logger.error("harness", "Failed to save state during cleanup: #{e.}", error: e.class.name) @last_error ||= e # Only set if no previous error end begin cleanup rescue => e # Don't let cleanup failures propagate Aidp.logger.error("harness", "Failed during cleanup: #{e.}", error: e.class.name) end end result = {status: @state, message: } result[:reason] = @failure_reason if @failure_reason result[:failure_metadata] = @failure_metadata if @failure_metadata result[:clarification_questions] = @clarification_questions if @clarification_questions if @last_error result[:error] = @last_error. result[:error_class] = @last_error.class.name result[:backtrace] = @last_error.backtrace&.first(10) end result end |
#status ⇒ Object
Get current harness status
197 198 199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/aidp/harness/runner.rb', line 197 def status { state: @state, mode: @mode, current_step: @current_step, current_provider: @current_provider, start_time: @start_time, duration: @start_time ? Time.now - @start_time : 0, user_input_count: @user_input.size, execution_log_count: @execution_log.size, progress: @state_manager.progress_summary } end |
#stop ⇒ Object
Stop the harness execution
190 191 192 193 194 |
# File 'lib/aidp/harness/runner.rb', line 190 def stop @state = STATES[:stopped] log_execution("Harness stopped by user") @status_display.show_stopped_status end |