Module: Ocak::Planner
- Included in:
- PipelineExecutor
- Defined in:
- lib/ocak/planner.rb
Overview
Batch planning logic extracted from PipelineRunner.
Constant Summary collapse
- STEP_PROMPTS =
{ 'implement' => 'Implement GitHub issue #%<issue>s', 'review' => 'Review the changes for GitHub issue #%<issue>s. Run: git diff main', 'verify' => 'Review the changes for GitHub issue #%<issue>s. Run: git diff main', 'security' => 'Security review changes for GitHub issue #%<issue>s. Run: git diff main', 'document' => 'Add documentation for changes in GitHub issue #%<issue>s', 'merge' => 'Create a PR, merge it, and close issue #%<issue>s' }.freeze
Instance Method Summary collapse
- #build_step_prompt(role, issue_number, review_output) ⇒ Object
- #parse_planner_output(output, issues, logger) ⇒ Object
- #plan_batches(issues, logger:, claude:) ⇒ Object
- #sequential_batches(issues) ⇒ Object
Instance Method Details
#build_step_prompt(role, issue_number, review_output) ⇒ Object
17 18 19 20 21 22 23 24 25 |
# File 'lib/ocak/planner.rb', line 17 def build_step_prompt(role, issue_number, review_output) if role == 'fix' "Fix these review findings for issue ##{issue_number}:\n\n<review_output>\n#{review_output}\n</review_output>" elsif STEP_PROMPTS.key?(role) format(STEP_PROMPTS[role], issue: issue_number) else "Run #{role} for GitHub issue ##{issue_number}" end end |
#parse_planner_output(output, issues, logger) ⇒ Object
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/ocak/planner.rb', line 44 def parse_planner_output(output, issues, logger) json_match = output.match(/\{[\s\S]*"batches"[\s\S]*\}/) if json_match parsed = JSON.parse(json_match[0]) batches = parsed['batches'] return sequential_batches(issues) unless batches.is_a?(Array) batches else logger.warn('Could not parse planner output, falling back to sequential') sequential_batches(issues) end rescue JSON::ParserError => e logger.warn("JSON parse error from planner: #{e.}") sequential_batches(issues) end |
#plan_batches(issues, logger:, claude:) ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/ocak/planner.rb', line 27 def plan_batches(issues, logger:, claude:) return sequential_batches(issues) if issues.size <= 1 issue_json = JSON.generate(issues.map { |i| { number: i['number'], title: i['title'] } }) result = claude.run_agent( 'planner', "Analyze these issues and output parallelization batches as JSON:\n\n<issue_data>\n#{issue_json}\n</issue_data>" ) unless result.success? logger.warn('Planner failed, falling back to sequential') return sequential_batches(issues) end parse_planner_output(result.output, issues, logger) end |
#sequential_batches(issues) ⇒ Object
61 62 63 64 65 66 67 |
# File 'lib/ocak/planner.rb', line 61 def sequential_batches(issues) issues.map.with_index do |i, idx| issue = i.dup issue['complexity'] ||= 'full' { 'batch' => idx + 1, 'issues' => [issue] } end end |