modcomms/backend/app/models/schemas.py
michael 3a5c3bcde3 Implement revision-aware proof analysis pipeline
When a subsequent revision of a proof is uploaded, the analysis now takes
place in context of the previous version's results. The system identifies:
- Resolved issues: fixed in the new revision
- Outstanding issues: still present from previous version
- New issues: introduced in the new revision

Key changes:
- Add resolvedIssues, outstandingIssues, newIssues fields to SubReview
- Add PreviousReviewContext model for passing previous review data
- Update all specialist agents to accept previous_review context
- Extend GeminiService with include_revision_fields parameter
- Add get_latest_version_review() repository method
- Update LeadAgent to synthesize cross-version context in summary
- Fetch previous analysis in WebSocket handler for revisions

First version analysis continues to work exactly as before with revision
fields set to null.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 10:04:16 -06:00

111 lines
2.7 KiB
Python
Executable file

from enum import Enum
from typing import Optional
from pydantic import BaseModel
class RagStatus(str, Enum):
"""RAG status for agent reviews."""
RED = "Red"
AMBER = "Amber"
GREEN = "Green"
ERROR = "Error"
class OverallStatus(str, Enum):
"""Overall status for the proof review."""
PASSED = "Passed"
FAILED = "Failed"
ANALYSIS_ERROR = "Analysis Error"
REQUIRES_MANUAL_LEGAL_REVIEW = "Requires Manual Legal Review"
class SubReview(BaseModel):
"""Individual agent review result."""
ragStatus: RagStatus
feedback: str
issues: list[str]
isFinancialPromotion: Optional[bool] = None
financialPromotionReason: Optional[str] = None
# Revision-aware fields (populated when analyzing version N > 1)
resolvedIssues: Optional[list[str]] = None
outstandingIssues: Optional[list[str]] = None
newIssues: Optional[list[str]] = None
class Config:
use_enum_values = True
class PreviousReviewContext(BaseModel):
"""Context from a previous version's review for revision-aware analysis."""
version: int
ragStatus: RagStatus
feedback: str
issues: list[str]
class Config:
use_enum_values = True
class AgentReview(BaseModel):
"""Complete review from all agents."""
legalAgentReview: SubReview
brandAgentReview: SubReview
channelBestPracticesAgentReview: SubReview
channelTechSpecsAgentReview: SubReview
leadAgentSummary: str
overallStatus: OverallStatus
financialPromotionReason: Optional[str] = None
class Config:
use_enum_values = True
# WebSocket message types
class AnalyzeRequest(BaseModel):
"""Request to analyze a proof via WebSocket."""
type: str # Should be "analyze"
file_data: str # Base64 encoded file
file_type: str # MIME type
is_wip: bool = False
class AgentStartedMessage(BaseModel):
"""Message sent when an agent starts processing."""
type: str = "agent_started"
agent_name: str
class AgentCompletedMessage(BaseModel):
"""Message sent when an agent completes."""
type: str = "agent_completed"
agent_name: str
review: SubReview
class Config:
use_enum_values = True
class SummaryMessage(BaseModel):
"""Message sent when summary is ready."""
type: str = "summary"
lead_agent_summary: str
overall_status: OverallStatus
financial_promotion_reason: Optional[str] = None
class Config:
use_enum_values = True
class CompleteMessage(BaseModel):
"""Message sent when analysis is complete."""
type: str = "complete"
result: AgentReview
class Config:
use_enum_values = True
class ErrorMessage(BaseModel):
"""Message sent when an error occurs."""
type: str = "error"
message: str