Class: Aidp::Execute::WorkLoopRunner
- Inherits:
-
Object
- Object
- Aidp::Execute::WorkLoopRunner
- Includes:
- MessageDisplay
- Defined in:
- lib/aidp/execute/work_loop_runner.rb
Overview
Executes work loops for a single step using the fix-forward pattern Responsibilities:
-
Create initial PROMPT.md from templates and context
-
Loop: send PROMPT.md to agent, run tests/linters, check completion
-
Only send test/lint failures back to agent
-
Never rollback, only move forward through fixes
-
Track iteration count and state transitions
-
Record periodic checkpoints with metrics
Fix-Forward State Machine: READY → APPLY_PATCH → TEST → → DONE | FAIL → DIAGNOSE → NEXT_PATCH → READY
Constant Summary collapse
- STATES =
State machine states
{ ready: "READY", # Ready to start new iteration apply_patch: "APPLY_PATCH", # Agent applying changes test: "TEST", # Running tests and linters pass: "PASS", # Tests passed fail: "FAIL", # Tests failed diagnose: "DIAGNOSE", # Analyzing failures next_patch: "NEXT_PATCH", # Preparing next iteration done: "DONE" # Work complete }.freeze
- MAX_ITERATIONS =
Safety limit
50- CHECKPOINT_INTERVAL =
Record checkpoint every N iterations
5- STYLE_GUIDE_REMINDER_INTERVAL =
Re-inject LLM_STYLE_GUIDE every N iterations
5
Constants included from MessageDisplay
Instance Attribute Summary collapse
-
#current_state ⇒ Object
readonly
Returns the value of attribute current_state.
-
#iteration_count ⇒ Object
readonly
Returns the value of attribute iteration_count.
-
#project_dir ⇒ Object
readonly
Returns the value of attribute project_dir.
Instance Method Summary collapse
-
#execute_step(step_name, step_spec, context = {}) ⇒ Object
Execute a step using fix-forward work loop pattern Returns final result when step is complete Never rolls back - only moves forward through fixes.
-
#initialize(project_dir, provider_manager, config, options = {}) ⇒ WorkLoopRunner
constructor
A new instance of WorkLoopRunner.
Methods included from MessageDisplay
#display_message, included, #message_display_prompt
Constructor Details
#initialize(project_dir, provider_manager, config, options = {}) ⇒ WorkLoopRunner
Returns a new instance of WorkLoopRunner.
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/aidp/execute/work_loop_runner.rb', line 47 def initialize(project_dir, provider_manager, config, = {}) @project_dir = project_dir @provider_manager = provider_manager @config = config @prompt = [:prompt] || TTY::Prompt.new @prompt_manager = PromptManager.new(project_dir, config: config) @test_runner = Aidp::Harness::TestRunner.new(project_dir, config) @checkpoint = Checkpoint.new(project_dir) @checkpoint_display = CheckpointDisplay.new(prompt: @prompt) @guard_policy = GuardPolicy.new(project_dir, config.guards_config) @persistent_tasklist = PersistentTasklist.new(project_dir) @iteration_count = 0 @step_name = nil @options = @current_state = :ready @state_history = [] @deterministic_runner = DeterministicUnits::Runner.new(project_dir) @unit_scheduler = nil # Initialize thinking depth manager for intelligent model selection require_relative "../harness/thinking_depth_manager" @thinking_depth_manager = [:thinking_depth_manager] || Aidp::Harness::ThinkingDepthManager.new(config) @consecutive_failures = 0 @last_tier = nil end |
Instance Attribute Details
#current_state ⇒ Object (readonly)
Returns the value of attribute current_state.
41 42 43 |
# File 'lib/aidp/execute/work_loop_runner.rb', line 41 def current_state @current_state end |
#iteration_count ⇒ Object (readonly)
Returns the value of attribute iteration_count.
41 42 43 |
# File 'lib/aidp/execute/work_loop_runner.rb', line 41 def iteration_count @iteration_count end |
#project_dir ⇒ Object (readonly)
Returns the value of attribute project_dir.
41 42 43 |
# File 'lib/aidp/execute/work_loop_runner.rb', line 41 def project_dir @project_dir end |
Instance Method Details
#execute_step(step_name, step_spec, context = {}) ⇒ Object
Execute a step using fix-forward work loop pattern Returns final result when step is complete Never rolls back - only moves forward through fixes
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 |
# File 'lib/aidp/execute/work_loop_runner.rb', line 76 def execute_step(step_name, step_spec, context = {}) @step_name = step_name @iteration_count = 0 transition_to(:ready) Aidp.logger.info("work_loop", "Starting hybrid work loop execution", step: step_name, max_iterations: MAX_ITERATIONS) ("🔄 Starting hybrid work loop for step: #{step_name}", type: :info) (" Flow: Deterministic ↔ Agentic with fix-forward core", type: :info) display_work_context(step_name, context) display_guard_policy_status display_pending_tasks @unit_scheduler = WorkLoopUnitScheduler.new(units_config, project_dir: @project_dir) base_context = context.dup loop do unit = @unit_scheduler.next_unit break unless unit if unit.deterministic? result = @deterministic_runner.run(unit.definition, reason: "scheduled by work loop") @unit_scheduler.record_deterministic_result(unit.definition, result) next end enriched_context = base_context.merge( deterministic_outputs: @unit_scheduler.deterministic_context, previous_agent_summary: @unit_scheduler.last_agentic_summary ) agentic_payload = if unit.name == :decide_whats_next run_decider_agentic_unit(enriched_context) elsif unit.name == :diagnose_failures run_diagnose_agentic_unit(enriched_context) else run_primary_agentic_unit(step_spec, enriched_context) end @unit_scheduler.record_agentic_result( agentic_payload[:raw_result] || {}, requested_next: agentic_payload[:requested_next], summary: agentic_payload[:summary], completed: agentic_payload[:completed] ) return agentic_payload[:response] if agentic_payload[:terminate] end build_max_iterations_result end |