atlas-iac/testing/tests/test_hermes_herdr.py
2026-08-09 03:59:08 -03:00

237 lines
7.9 KiB
Python

"""Focused tests for Hermes-to-Herdr routing and the shared auth patch."""
from __future__ import annotations
import importlib.util
import sys
from pathlib import Path
import pytest
import yaml
SCRIPTS = Path(__file__).parents[2] / "services/hermes/scripts"
HERMES = Path(__file__).parents[2] / "services/hermes"
def _load(name: str):
spec = importlib.util.spec_from_file_location(name, SCRIPTS / f"{name}.py")
assert spec and spec.loader
module = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = module
spec.loader.exec_module(module)
return module
dispatch = _load("herdr_dispatch")
auth_patch = _load("patch_hermes_auth")
def test_herdr_plan_chooses_task_shape_and_caps_effort():
status = {
"routes": {
"codex-high": [
"openai-codex/gpt-5.6-sol",
"anthropic/claude-opus-5",
"custom/qwen2.5:14b-instruct-q4_0",
],
"claude-medium": [
"anthropic/claude-sonnet-5",
"openai-codex/gpt-5.6-terra",
],
}
}
implementation = dispatch.select_plan(status, "implementation", "high")
architecture = dispatch.select_plan(status, "architecture", "medium")
assert implementation["worker"] == "codex"
assert implementation["model"] == "gpt-5.6-sol"
assert architecture["worker"] == "claude"
assert architecture["model"] == "claude-sonnet-5"
with pytest.raises(ValueError, match="effort"):
dispatch.select_plan(status, "review", "max")
def test_claude_worker_waits_for_prompt_readiness(tmp_path: Path, monkeypatch):
herdr = tmp_path / "herdr"
herdr.touch()
project = tmp_path / "project"
project.mkdir()
calls = []
def fake_run(command, env):
calls.append(command)
if command[1:3] == ["workspace", "create"]:
return {"result": {"root_pane": {"pane_id": "w2:p1"}}}
return {"result": {"ok": True}}
monkeypatch.setattr(dispatch, "HERDR_BIN", herdr)
monkeypatch.setattr(dispatch, "_run", fake_run)
plan = {
"worker": "claude",
"model": "claude-haiku-4-5-20251001",
"effort": "low",
}
dispatch.launch_worker(plan, project, "review", "Check the implementation.")
ready = calls[-2]
assert ready[1:] == [
"pane",
"wait-output",
"w2:p1",
"--match",
"accept edits on",
"--source",
"recent",
"--lines",
"120",
"--timeout",
"120000",
]
prompt = calls[-1]
assert prompt[1:5] == [
"agent",
"prompt",
"claude-review",
"Check the implementation.",
]
assert prompt[-9:] == [
"--wait",
"--until",
"working",
"--until",
"done",
"--until",
"blocked",
"--timeout",
"15000",
]
def test_auth_patch_honors_explicit_shared_store(tmp_path: Path):
source = tmp_path / "auth.py"
destination = tmp_path / "patched" / "auth.py"
source.write_text(
"from pathlib import Path\nimport os\n\n"
"def _auth_file_path() -> Path:\n"
" path = get_hermes_home() / \"auth.json\"\n"
" return path\n",
encoding="utf-8",
)
auth_patch.patch(source, destination)
content = destination.read_text(encoding="utf-8")
assert 'os.environ.get("HERMES_AUTH_FILE"' in content
assert "Path(configured)" in content
def test_auth_patch_fails_closed_on_upstream_drift(tmp_path: Path):
source = tmp_path / "auth.py"
source.write_text("def changed():\n pass\n", encoding="utf-8")
with pytest.raises(RuntimeError, match="context changed"):
auth_patch.patch(source, tmp_path / "patched.py")
def test_agent_ttyd_defers_identity_to_owner_only_oauth_boundary():
deployment = yaml.safe_load((HERMES / "agent-deployment.yaml").read_text())
containers = deployment["spec"]["template"]["spec"]["containers"]
ttyd = next(container for container in containers if container["name"] == "herdr-tui")
command = ttyd["args"][0]
assert "--check-origin" in command
assert "--auth-header" not in command
oauth_documents = [
document
for document in yaml.safe_load_all((HERMES / "oauth2-proxy.yaml").read_text())
if document
]
oauth = next(
document
for document in oauth_documents
if document["kind"] == "Deployment"
and document["metadata"]["name"] == "oauth2-proxy-hermes-agent"
)
oauth_args = oauth["spec"]["template"]["spec"]["containers"][0]["args"]
assert "--authenticated-emails-file=/etc/oauth2-proxy/allowed-emails" in oauth_args
assert "--proxy-websockets=true" in oauth_args
network_documents = [
document
for document in yaml.safe_load_all((HERMES / "networkpolicy.yaml").read_text())
if document
]
isolation = next(
document
for document in network_documents
if document["kind"] == "NetworkPolicy"
and document["metadata"]["name"] == "hermes-agent-isolation"
)
ingress = isolation["spec"]["ingress"]
assert ingress == [
{
"from": [{"podSelector": {"matchLabels": {"app": "oauth2-proxy-hermes-agent"}}}],
"ports": [{"protocol": "TCP", "port": 7681}],
}
]
def test_agent_installs_hermes_integration_before_startup():
deployment = yaml.safe_load((HERMES / "agent-deployment.yaml").read_text())
pod = deployment["spec"]["template"]["spec"]
init_config = next(
container for container in pod["initContainers"] if container["name"] == "init-config"
)
assert "ln -s /opt/data /opt/data/home/.hermes" in init_config["command"][-1]
installer = next(
container
for container in pod["initContainers"]
if container["name"] == "install-herdr-integrations"
)
command = installer["command"][-1]
assert "herdr integration install codex" in command
assert "herdr integration install claude" in command
assert "herdr integration install hermes" in command
assert "|| true" not in command
containers = {container["name"]: container for container in pod["containers"]}
for name in ("herdr-tui", "herdr-server"):
env = {item["name"]: item["value"] for item in containers[name]["env"]}
assert "/opt/hermes/.venv/bin" in env["PATH"].split(":")
server_command = containers["herdr-server"]["command"][-1]
assert 'herdr pane process-info --pane "${pane}"' in server_command
assert 'herdr workspace close "${workspace}"' in server_command
assert 'item.get("label") == "coordinator"' in server_command
assert 'item["workspace_id"] != active' in server_command
assert 'herdr workspace close "${stale_workspace}"' in server_command
assert "herdr agent start coordinator" in server_command
assert "--kind hermes" in server_command
assert "--timeout 60000" in server_command
def test_agent_mounts_auto_router_into_both_hermes_runtimes():
deployment = yaml.safe_load((HERMES / "agent-deployment.yaml").read_text())
pod = deployment["spec"]["template"]["spec"]
containers = {container["name"]: container for container in pod["containers"]}
for name in ("hermes", "herdr-server"):
mounts = {
mount["mountPath"]: mount["name"]
for mount in containers[name]["volumeMounts"]
}
assert mounts["/opt/data/plugins/auto-router"] == "auto-router-plugin"
volume = next(
item for item in pod["volumes"] if item["name"] == "auto-router-plugin"
)
assert volume["configMap"]["name"] == "hermes-auto-router-plugin"
def test_agent_coordinator_has_a_long_running_tool_budget():
configmap = yaml.safe_load((HERMES / "agent-configmap.yaml").read_text())
config = yaml.safe_load(configmap["data"]["config.yaml"])
assert config["agent"]["max_turns"] == 180
assert config["tool_loop_guardrails"]["hard_stop_enabled"] is True