Class: Ace::Review::Molecules::FeedbackSynthesizer
- Inherits:
-
Object
- Object
- Ace::Review::Molecules::FeedbackSynthesizer
- Defined in:
- lib/ace/review/molecules/feedback_synthesizer.rb
Overview
Synthesizes feedback items from multiple review reports.
Reads ALL reports in a single LLM pass and outputs deduplicated FeedbackItems with reviewer arrays tracking which models found each issue.
Constant Summary collapse
- FALLBACK_SYSTEM_PROMPT =
Cached system prompt and prompt-path lookups to avoid repeated shell/file reads during test and command-heavy runs.
<<~PROMPT.freeze Synthesize feedback from code review reports into unique findings. For each unique issue found: 1. Track which reviewers identified it (by their model names) 2. Merge file references from all sources 3. Use the most comprehensive description 4. Mark consensus=true if 3+ reviewers agree Return valid JSON with this schema: { "findings": [ { "title": "Short title (max 60 chars)", "files": ["path/file.rb:10-20"], "reviewers": ["gemini-2.5-flash", "claude-3.5-sonnet"], "consensus": false, "priority": "high|medium|low|critical", "finding": "Description of the issue", "context": "Why this matters" } ] } IMPORTANT: - When only one report: extract all findings as-is with that reviewer - When multiple reports: deduplicate findings that describe the same issue - When multiple reviewers find the same issue, list ALL of them in reviewers array - Merge file arrays from all sources for each finding - Return ONLY the JSON, no markdown code fences PROMPT
- MAX_COMBINED_SIZE =
Maximum combined report size before truncation (characters)
200_000
Instance Attribute Summary collapse
-
#llm_executor ⇒ Object
readonly
Returns the value of attribute llm_executor.
Class Method Summary collapse
- .clear_prompt_cache! ⇒ Object
- .resolve_prompt_path_cached(prompt_name) ⇒ Object
- .system_prompt(prompt_name) ⇒ Object
Instance Method Summary collapse
-
#initialize(llm_executor: nil) ⇒ FeedbackSynthesizer
constructor
A new instance of FeedbackSynthesizer.
-
#synthesize(report_paths:, session_dir: nil, model: nil) ⇒ Hash
Synthesize feedback items from review reports.
Constructor Details
#initialize(llm_executor: nil) ⇒ FeedbackSynthesizer
Returns a new instance of FeedbackSynthesizer.
125 126 127 |
# File 'lib/ace/review/molecules/feedback_synthesizer.rb', line 125 def initialize(llm_executor: nil) @llm_executor = llm_executor || LlmExecutor.new end |
Instance Attribute Details
#llm_executor ⇒ Object (readonly)
Returns the value of attribute llm_executor.
123 124 125 |
# File 'lib/ace/review/molecules/feedback_synthesizer.rb', line 123 def llm_executor @llm_executor end |
Class Method Details
.clear_prompt_cache! ⇒ Object
92 93 94 95 96 97 98 99 |
# File 'lib/ace/review/molecules/feedback_synthesizer.rb', line 92 def clear_prompt_cache! system_prompt_cache_mutex.synchronize do @system_prompt_cache = {} end prompt_path_cache_mutex.synchronize do @prompt_path_cache = {} end end |
.resolve_prompt_path_cached(prompt_name) ⇒ Object
78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/ace/review/molecules/feedback_synthesizer.rb', line 78 def resolve_prompt_path_cached(prompt_name) prompt_path_cache[prompt_name] ||= begin nav_result = begin `ace-nav prompt://#{prompt_name} 2>/dev/null`.strip rescue "" end return nav_result unless nav_result.empty? File.join(__dir__, "../../../../handbook/prompts", prompt_name) end end |
.system_prompt(prompt_name) ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/ace/review/molecules/feedback_synthesizer.rb', line 64 def system_prompt(prompt_name) system_prompt_cache_mutex.synchronize do system_prompt_cache.fetch(prompt_name) do prompt_path = resolve_prompt_path_cached(prompt_name) if prompt_path && File.exist?(prompt_path) system_prompt_cache[prompt_name] = File.read(prompt_path) else system_prompt_cache[prompt_name] = FALLBACK_SYSTEM_PROMPT end end end end |
Instance Method Details
#synthesize(report_paths:, session_dir: nil, model: nil) ⇒ Hash
Synthesize feedback items from review reports
Unified process that handles single or multiple reports:
-
Single report: extracts findings directly
-
Multiple reports: deduplicates and tracks consensus across reviewers
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/ace/review/molecules/feedback_synthesizer.rb', line 139 def synthesize(report_paths:, session_dir: nil, model: nil) # Validate inputs return error_result("No report paths provided") if report_paths.nil? || report_paths.empty? # Create session dir if needed session_dir ||= create_temp_session_dir FileUtils.mkdir_p(session_dir) unless Dir.exist?(session_dir) # Read all reports reports = read_reports(report_paths) return error_result("No valid reports found") if reports.empty? # Synthesize (handles both single and multiple reports uniformly) synthesize_reports(reports, session_dir, model) rescue => e error_result("Synthesis failed: #{e.}", backtrace: e.backtrace.first(5)) end |