"""Pydantic schemas for flow proposals (Knowledge Flywheel / Review Queue).""" from __future__ import annotations from typing import Optional, Any from uuid import UUID from datetime import datetime from pydantic import BaseModel, Field class FlowProposalSummary(BaseModel): """Compact proposal for list views.""" id: UUID proposal_type: str title: str description: str | None = None problem_domain: str | None = None confidence_score: float supporting_session_count: int status: str target_flow_id: UUID | None = None # Exactly one source is set: source_session_id (FlowPilot ai_session) XOR # l1_session_id (L1 ai_build walk). Both are nullable on the model. source_session_id: UUID | None = None l1_session_id: UUID | None = None created_at: datetime model_config = {"from_attributes": True} class FlowProposalDetail(FlowProposalSummary): """Full proposal detail with flow data.""" proposed_flow_data: dict[str, Any] proposed_diff: dict[str, Any] | None = None supporting_session_ids: list[str] = [] reviewer_notes: str | None = None reviewed_by: UUID | None = None reviewed_at: datetime | None = None class ReviewProposalRequest(BaseModel): """Review action on a proposal.""" action: str = Field(..., pattern="^(approve|reject|modify|dismiss)$") reviewer_notes: str | None = None modified_flow_data: dict[str, Any] | None = None # Only for "modify" class FlowProposalStats(BaseModel): """Dashboard stats for the review queue.""" pending_count: int approved_this_week: int rejected_this_week: int auto_reinforced_this_week: int top_domains: list[dict[str, Any]] = [] # [{domain, count}]