"""Ephemeral workspace dirs and dataset staging for agent runs. Each runner allocates `runs////` so concurrent runs don't collide and post-mortems are always recoverable from disk. """ from __future__ import annotations import datetime as dt from pathlib import Path def make_workspace(agent: str, task: str, root: Path | None = None) -> Path: root = Path(root) if root else Path.cwd() / "runs" ts = dt.datetime.now().strftime("%Y%m%d-%H%M%S") ws = root / agent / task / ts ws.mkdir(parents=True, exist_ok=False) return ws def stage_dataset(src_dir: Path, dst_dir: Path, files: list[str]) -> None: """Symlink each `files[i]` from src_dir into dst_dir. Symlinks (vs copies) keep large CSVs on the cache disk; the agent reads from src via the link transparently. """ dst_dir.mkdir(parents=True, exist_ok=True) for f in files: s = src_dir / f if not s.exists(): raise SystemExit(f"Missing dataset file: {s}") d = dst_dir / f if d.is_symlink() or d.exists(): d.unlink() d.symlink_to(s.resolve())