Module: Ocak::StepExecution

Included in:
PipelineExecutor
Defined in:
lib/ocak/step_execution.rb

Overview

Individual step execution logic extracted from PipelineExecutor. Includers must provide @config, @skip_steps, post_step_comment, build_step_prompt methods.

Instance Method Summary collapse

Instance Method Details

#execute_step(step, issue_number, review_output, logger:, claude:, chdir:) ⇒ Object



40
41
42
43
44
45
46
47
48
49
# File 'lib/ocak/step_execution.rb', line 40

def execute_step(step, issue_number, review_output, logger:, claude:, chdir:)
  agent = step[:agent].to_s
  role = step[:role].to_s
  logger.info("--- Phase: #{role} (#{agent}) ---")
  post_step_comment(issue_number, "🔄 **Phase: #{role}** (#{agent})")
  prompt = build_step_prompt(role, issue_number, review_output)
  opts = { chdir: chdir }
  opts[:model] = step[:model].to_s if step[:model]
  claude.run_agent(agent.tr('_', '-'), prompt, **opts)
end

#handle_already_completed(idx, role, skip_steps, logger) ⇒ Object



27
28
29
30
31
32
# File 'lib/ocak/step_execution.rb', line 27

def handle_already_completed(idx, role, skip_steps, logger)
  return false unless skip_steps.include?(idx)

  logger.info("Skipping #{role} (already completed)")
  true
end

#record_skipped_step(issue_number, state, idx, agent, role, reason) ⇒ Object



34
35
36
37
38
# File 'lib/ocak/step_execution.rb', line 34

def record_skipped_step(issue_number, state, idx, agent, role, reason)
  post_step_comment(issue_number, "⏭️ **Skipping #{role}** — #{reason}")
  state[:report].record_step(index: idx, agent: agent, role: role, status: 'skipped', skip_reason: reason)
  state[:steps_skipped] += 1
end

#run_single_step(step, idx, issue_number, state, logger:, claude:, chdir:, mutex: nil) ⇒ Object

rubocop:disable Metrics/ParameterLists



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/ocak/step_execution.rb', line 7

def run_single_step(step, idx, issue_number, state, logger:, claude:, chdir:, mutex: nil) # rubocop:disable Metrics/ParameterLists
  role = step[:role].to_s
  agent = step[:agent].to_s

  return nil if handle_already_completed(idx, role, @skip_steps, logger)

  reason = skip_reason(step, state)
  if reason
    logger.info("Skipping #{role}#{reason}")
    record_skipped_step(issue_number, state, idx, agent, role, reason)
    return nil
  end

  result = execute_step(step, issue_number, state[:last_review_output], logger: logger, claude: claude,
                                                                        chdir: chdir)
  state[:report].record_step(index: idx, agent: agent, role: role, status: 'completed', result: result)
  ctx = StateManagement::StepContext.new(issue_number, idx, role, result, state, logger, chdir)
  record_step_result(ctx, mutex: mutex)
end

#skip_reason(step, state) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/ocak/step_execution.rb', line 51

def skip_reason(step, state)
  condition = step[:condition]

  return 'merge handled by MergeManager' if step[:role].to_s == 'merge' && @skip_merge
  return 'audit found blocking issues' if step[:role].to_s == 'merge' && @config.audit_mode && state[:audit_blocked]
  return 'manual review mode' if step[:role].to_s == 'merge' && @config.manual_review
  return 'fast-track issue (simple complexity)' if step[:complexity] == 'full' && state[:complexity] == 'simple'
  if condition == 'has_findings' && !state[:last_review_output]&.include?('🔴')
    return 'no blocking findings from review'
  end
  return 'no fixes were made' if condition == 'had_fixes' && !state[:had_fixes]

  nil
end