diff --git a/engine/models.py b/engine/models.py index 4877273..7c3f8f6 100644 --- a/engine/models.py +++ b/engine/models.py @@ -1,115 +1,120 @@ +from __future__ import annotations + from dataclasses import dataclass, field from pathlib import Path -from typing import Literal +from typing import Any @dataclass(frozen=True) class ArtifactSpec: - include: list[str] = field(default_factory=list) - exclude: list[str] = field(default_factory=list) - max_files_per_iteration: int = 0 + include: list[str] + exclude: list[str] + max_files_per_iteration: int @dataclass(frozen=True) class MutationSpec: - mode: str = "" - allowed_file_types: list[str] = field(default_factory=list) - max_changed_lines: int = 0 + mode: str + allowed_file_types: list[str] + max_changed_lines: int @dataclass(frozen=True) class RunnerSpec: - command: str = "" - cwd: Path = Path(".") - timeout_seconds: int = 0 + command: str + cwd: str + timeout_seconds: int @dataclass(frozen=True) class ScorerParseSpec: - format: str = "" - score_field: str = "" - metrics_field: str = "" + format: str + score_field: str + metrics_field: str @dataclass(frozen=True) class ScorerSpec: - type: str = "" - command: str = "" - parse: ScorerParseSpec = field(default_factory=ScorerParseSpec) + type: str + command: str + parse: ScorerParseSpec @dataclass(frozen=True) class ObjectiveSpec: - primary_metric: str = "" - direction: Literal["maximize", "minimize"] = "maximize" + primary_metric: str + direction: str @dataclass(frozen=True) class ConstraintSpec: - metric: str = "" - op: str = "" - value: int | float = 0 + metric: str + op: str + value: Any @dataclass(frozen=True) class PolicySpec: - keep_if: str = "" - tie_breakers: list[str] = field(default_factory=list) - on_failure: str = "" + keep_if: str + tie_breakers: list[dict[str, str]] + on_failure: str @dataclass(frozen=True) class BudgetSpec: - max_iterations: int = 0 - max_failures: int = 0 + max_iterations: int + max_failures: int @dataclass(frozen=True) class LoggingSpec: - results_file: Path = Path() - candidate_dir: Path = Path() + results_file: str + candidate_dir: str @dataclass(frozen=True) class TaskSpec: - id: str = "" - description: str = "" - root_dir: Path = Path(".") - artifacts: ArtifactSpec = field(default_factory=ArtifactSpec) - mutation: MutationSpec = field(default_factory=MutationSpec) - runner: RunnerSpec = field(default_factory=RunnerSpec) - scorer: ScorerSpec = field(default_factory=ScorerSpec) - objective: ObjectiveSpec = field(default_factory=ObjectiveSpec) - constraints: list[ConstraintSpec] = field(default_factory=list) - policy: PolicySpec = field(default_factory=PolicySpec) - budget: BudgetSpec = field(default_factory=BudgetSpec) - logging: LoggingSpec = field(default_factory=LoggingSpec) + id: str + description: str + artifacts: ArtifactSpec + mutation: MutationSpec + runner: RunnerSpec + scorer: ScorerSpec + objective: ObjectiveSpec + constraints: list[ConstraintSpec] + policy: PolicySpec + budget: BudgetSpec + logging: LoggingSpec + root_dir: Path @dataclass(frozen=True) class BaselineSnapshot: - root_dir: Path = Path(".") - files: dict[str, str] = field(default_factory=dict) - - -@dataclass(frozen=True) -class ScoreResult: - score: float = 0.0 - metrics: dict[str, float | int] = field(default_factory=dict) - - -@dataclass(frozen=True) -class DecisionResult: - keep: bool = False - reason: str = "" - primary_metric: str = "" - primary_value: float = 0.0 + file_contents: dict[Path, str] + file_hashes: dict[Path, str] @dataclass(frozen=True) class RunResult: - task_id: str = "" - iteration: int = 0 - score: ScoreResult = field(default_factory=ScoreResult) - decision: DecisionResult = field(default_factory=DecisionResult) - baseline: BaselineSnapshot = field(default_factory=BaselineSnapshot) + command: str + cwd: Path + exit_code: int + runtime_seconds: float + stdout: str + stderr: str + + +@dataclass(frozen=True) +class ScoreResult: + primary_score: float + metrics: dict[str, Any] + raw_output: dict[str, Any] + + +@dataclass(frozen=True) +class DecisionResult: + status: str + reason: str + baseline_score: float | None + candidate_score: float | None + constraint_failures: list[str] = field(default_factory=list)