from typing import Any, Dict, List, Optional
from dataclasses import dataclass, field

@dataclass
class Run:
    """
    Atomic unit of evaluation - represents one input-output pair.
    
    This is the core contract that all evaluation operates on.
    """
    
    # Required fields
    id: str
    input: Any
    output: Any

    # Optional fields
    reference: Optional[Any] = None
    metadata: Dict[str, Any] = field(default_factory=dict)
    timestamps: Dict[str, float] = field(default_factory=dict)
    metrics: Optional[Dict[str, float]] = None
    tags: List[str] = field(default_factory=list)
    split: Optional[str] = None

    def __post_init__(self):
        """Validate the Run after initialization"""
        if not self.id:
            raise ValueError("Run.id cannot be empty")


