from abc import ABC, abstractmethod from typing import Dict class BasePRWaiter(ABC): """Abstract base class for waiting on PR-specific conditions before analysis.""" @abstractmethod def wait_for_analysis_ready( self, github_client, pr_number: int, timeout: int = 600 ) -> Dict: """Wait for PR to be ready for analysis (e.g., CI comments, plan outputs).""" pass class BasePromptBuilder(ABC): """Abstract base class for building repo-specific prompts.""" @abstractmethod def build_prompt(self, pr_data: Dict) -> str: """Build analysis prompt with PR data.""" pass class BasePRAnalyzer(ABC): """Abstract base class for analyzing PRs.""" def __init__( self, github_client, llm_client, prompt_builder: BasePromptBuilder, pr_waiter: BasePRWaiter, ): self.github_client = github_client self.llm_client = llm_client self.prompt_builder = prompt_builder self.pr_waiter = pr_waiter def analyze_pr(self, pr_number: int, timeout: int = 600) -> str: """Full PR analysis workflow.""" # Wait for PR to be ready pr_data = self.pr_waiter.wait_for_analysis_ready( self.github_client, pr_number, timeout ) # Build prompt prompt = self.prompt_builder.build_prompt(pr_data) # Analyze with LLM analysis = self.llm_client.analyze_pr(prompt) # Post-process if needed return self.post_process_analysis(analysis) def post_process_analysis(self, analysis: str) -> str: """Override in subclasses for repo-specific post-processing.""" return analysis