""" Single source of truth for required packages across all task difficulties. Add new entries here when implementing medium and hard scenarios. """ PACKAGES: dict[str, list[str]] = { "easy": ["flask", "numpy", "pandas", "requests", "pydantic"], "medium": ["flask", "numpy", "pandas", "requests", "pydantic"], # install always passes; failures are in Dockerfile + .env.ci "hard": ["flask", "numpy", "pandas", "requests", "pydantic"], # install failure is from a numpy version conflict, not a missing package } def get_packages(task: str) -> list[str]: """Return the required package list for a given task difficulty.""" if task not in PACKAGES: raise ValueError(f"Unknown task: {task!r}. Valid tasks: {list(PACKAGES)}") return PACKAGES[task] def get_packages_set(task: str) -> set[str]: """Return required packages as a set (used for O(1) lookup in stage_runner).""" return set(get_packages(task))