from pathlib import Path import pytest from autonomous_trainer.settings import PROJECT_ROOT, Settings from autonomous_trainer.tasks import load_task TASKS_DIR = PROJECT_ROOT / "examples" / "tasks" def _task_json(name: str) -> Path: """Resolve a task JSON: active set first, then the archive (retired families live in examples/tasks/archive/ but keep full test coverage).""" active = TASKS_DIR / name return active if active.exists() else TASKS_DIR / "archive" / name def _reference_workspace(name: str) -> dict[str, str]: """The files that make up a reference solution workspace — single owner, so the calculator and family fixtures can never validate different file sets.""" ref = PROJECT_ROOT / "examples" / f"reference_{name}" return { "environment.py": (ref / "environment.py").read_text(), "job.toml": (ref / "job.toml").read_text(), } # The generated task families, each with a JSON TaskSpec and a reference # workspace under examples/reference_/. calc_chain/multi_hop/ # string_pipeline are the multi-step tool-composition families (chained # dependent tool calls); ledger/dispatch/triage are the multi-tool agentic # persona families (5-20-call workflows across three tools each). GENERATED_FAMILIES = [ "lookup", "date_calc", "string_op", "aggregate", "calc_chain", "multi_hop", "string_pipeline", "ledger", "dispatch", "triage", ] @pytest.fixture def calculator_task(): return load_task("calculator") @pytest.fixture def reference_files() -> dict[str, str]: return _reference_workspace("calculator") @pytest.fixture def family_task(): """Load a generated family's JSON TaskSpec by name (parametrized by tests).""" def _load(family: str): return load_task(str(_task_json(f"{family}_v1_fast.json"))) return _load @pytest.fixture def family_reference_files(): """Read a generated family's reference environment.py + job.toml.""" return _reference_workspace @pytest.fixture def test_settings(tmp_path: Path) -> Settings: return Settings( runs_dir=tmp_path / "runs", max_agent_turns=16, max_submission_attempts=3, max_episode_usd=1.0, validation_timeout_s=240.0, )