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', 'audit' => 'Audit the changed files for issue #%<issue>s. Run: git diff main --name-only', 'merge' => 'Create a PR, merge it, and close issue #%<issue>s', 'create_pr' => '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
19 20 21 22 23 24 25 26 27 |
# File 'lib/ocak/planner.rb', line 19 def build_step_prompt(role, issue_number, review_output) if role == 'fix' "Fix these review findings for issue ##{issue_number}:\n\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
46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/ocak/planner.rb', line 46 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]) parsed['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
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/ocak/planner.rb', line 29 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_json}" ) 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
60 61 62 63 64 65 66 |
# File 'lib/ocak/planner.rb', line 60 def sequential_batches(issues) issues.map.with_index do |i, idx| issue = i.dup issue['complexity'] ||= 'full' { 'batch' => idx + 1, 'issues' => [issue] } end end |