from pydantic import BaseModel, Field from typing import List, Optional, Dict, Any class StaticAnalysisIssue(BaseModel): tool: str = Field(..., description="Ruff, Bandit, ou Semgrep") file: str = Field(..., description="Chemin du fichier concerné") line: Optional[int] = None code: Optional[str] = Field(None, description="Identifiant de la règle (ex: S101, F401)") severity: str = Field(..., description="LOW, MEDIUM, HIGH, ERROR") message: str = Field(..., description="Description du problème") class RuntimeOutput(BaseModel): exit_code: int stdout: str stderr: str duration_seconds: float timeout_triggered: bool class QARawResults(BaseModel): """Données brutes extraites des outils techniques.""" is_executable: bool = Field(..., description="Est-ce que le code a pu se lancer sans erreur de syntaxe ?") runtime: Optional[RuntimeOutput] = None issues: List[StaticAnalysisIssue] = Field(default_factory=list) class QAEvaluation(BaseModel): """Structure finale renvoyée par le LLM (QA Agent) au format structuré.""" is_complete_and_safe: bool = Field(..., description="True si le code est prêt pour la prod, False s'il faut corriger") global_summary: str = Field(..., description="Résumé intelligible des forces et faiblesses du code") technical_feedback: List[str] = Field( default_factory=list, description="Instructions de correction ultra-précises destinées au Dev Agent" )