mindXtrain / tests /test_coach_research_api.py
Gregory-L's picture
autoresearch: the keep/reset search, and the UI modules that were never shipped
c27193b verified
Raw History Blame Contribute Delete
3.54 kB
"""P5 tests — coach research route + the `research` CLI verb."""
from __future__ import annotations
from pathlib import Path
from fastapi.testclient import TestClient
from typer.testing import CliRunner
from mindxtrain.cli.main import app
from mindxtrain.operator.app import app as fastapi_app
from mindxtrain.research import Ledger
runner = CliRunner()
def test_research_verb_in_help() -> None:
result = runner.invoke(app, ["--help"])
assert result.exit_code == 0
assert "research" in result.output
def test_research_anchor_errors_cleanly_without_registry(tmp_path: Path, monkeypatch) -> None: # type: ignore[no-untyped-def]
monkeypatch.delenv("MINDXTRAIN_AUTORESEARCH_REGISTRY_ADDR", raising=False)
# A throwaway git repo so the search runs to a baseline, then --anchor fails
# cleanly (no registry configured) — exit 1, not a crash or silent success.
import subprocess
def git(*a: str) -> None:
subprocess.run(["git", "-C", str(tmp_path), *a], check=True, capture_output=True, text=True)
git("init", "-b", "main")
git("config", "user.email", "ci@example.com")
git("config", "user.name", "ci")
(tmp_path / ".gitignore").write_text("out/\n", encoding="utf-8")
(tmp_path / "value.txt").write_text("1\n", encoding="utf-8")
git("add", ".")
git("commit", "-m", "baseline")
(tmp_path / "out").mkdir() # gitignored → the contract file isn't a stray
c = tmp_path / "out" / "c.toml"
c.write_text(
'task="t"\ncommand="true"\neditable=["value.txt"]\nmetric="score"\n', encoding="utf-8"
)
monkeypatch.chdir(tmp_path)
result = runner.invoke(app, ["research", str(c), "--log-root", "out", "--anchor"])
assert result.exit_code == 1
assert "registry address" in result.output
def test_research_attempts_route(tmp_path: Path, monkeypatch) -> None: # type: ignore[no-untyped-def]
import mindxtrain.operator.coach.api as api
monkeypatch.setattr(api, "_RESEARCH_LOG_ROOT", tmp_path)
led = Ledger(tmp_path)
led.append(researcher="codephreak", commit="c1", status="completed",
metric={"name": "score", "value": 0.5, "mode": "max"})
led.append(researcher="other", commit="c2", status="completed")
client = TestClient(fastapi_app)
res = client.get("/coach/api/research/codephreak/attempts")
assert res.status_code == 200
body = res.json()
assert len(body) == 1 # filtered to this researcher
assert body[0]["commit"] == "c1"
assert body[0]["metric"]["value"] == 0.5
def test_research_diff_route_path_guard(tmp_path: Path, monkeypatch) -> None: # type: ignore[no-untyped-def]
import mindxtrain.operator.coach.api as api
monkeypatch.setattr(api, "_RESEARCH_LOG_ROOT", tmp_path)
client = TestClient(fastapi_app)
# run_dir outside the research root is rejected.
res = client.get("/coach/api/research/diff", params={"run_dir": "/etc"})
assert res.status_code == 400
def test_research_diff_route_returns_diff(tmp_path: Path, monkeypatch) -> None: # type: ignore[no-untyped-def]
import mindxtrain.operator.coach.api as api
monkeypatch.setattr(api, "_RESEARCH_LOG_ROOT", tmp_path)
run_dir = tmp_path / "codephreak" / "attempt-001"
run_dir.mkdir(parents=True)
(run_dir / "code.diff").write_text("--- a\n+++ b\n", encoding="utf-8")
client = TestClient(fastapi_app)
res = client.get("/coach/api/research/diff", params={"run_dir": str(run_dir)})
assert res.status_code == 200
assert "+++ b" in res.json()["diff"]