Files
activity-core/tests/test_kaizen_context_resolver.py
tegwick 517bf9c133 Add kaizen context resolver for scheduled agent fleet discovery.
Implement discover_kaizen_scheduled_repos and discover_kaizen_projects per
kaizen-agentic ADR-005 contract: State Hub roster, roster.yaml filter, schedule
validation, and prepare_command emission. Register kaizen/resolver/shell source
types with unit tests and runbook dry-run instructions.
2026-06-18 07:46:46 +02:00

195 lines
5.8 KiB
Python

from __future__ import annotations
from pathlib import Path
from typing import Any
import httpx
import pytest
import yaml
from activity_core.context_resolvers.kaizen import (
KaizenContextResolver,
discover_kaizen_scheduled_repos,
)
class DummyResponse:
def __init__(self, payload: Any, status_error: Exception | None = None) -> None:
self.payload = payload
self.status_error = status_error
def raise_for_status(self) -> None:
if self.status_error is not None:
raise self.status_error
def json(self) -> Any:
return self.payload
def _write_schedule(path: Path, agents: dict[str, Any]) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(
yaml.safe_dump(
{"version": "1", "timezone": "Europe/Berlin", "agents": agents},
sort_keys=False,
),
encoding="utf-8",
)
def test_discover_scheduled_repos_emits_enabled_coach(tmp_path, monkeypatch) -> None:
repo_root = tmp_path / "pilot-repo"
repo_root.mkdir()
_write_schedule(
repo_root / ".kaizen" / "schedule.yml",
{"coach": {"cadence": "daily", "cron": "15 * * * *", "enabled": True}},
)
def fake_get(url: str, **kwargs: Any) -> DummyResponse:
return DummyResponse(
[
{
"slug": "pilot-repo",
"domain_slug": "custodian",
"host_paths": {"testhost": str(repo_root)},
}
]
)
monkeypatch.setenv("STATE_HUB_URL", "http://hub.test")
monkeypatch.setenv("KAIZEN_RUNNER_HOST", "testhost")
monkeypatch.setattr(httpx, "get", fake_get)
result = discover_kaizen_scheduled_repos({})
assert len(result["scheduled_runs"]) == 1
run = result["scheduled_runs"][0]
assert run["repo"] == "pilot-repo"
assert run["agent"] == "coach"
assert run["enabled"] is True
assert "schedule prepare coach" in run["prepare_command"]
def test_discover_scheduled_repos_skips_disabled_coach(tmp_path, monkeypatch) -> None:
repo_root = tmp_path / "pilot-repo"
repo_root.mkdir()
_write_schedule(
repo_root / ".kaizen" / "schedule.yml",
{"coach": {"cadence": "daily", "enabled": False}},
)
monkeypatch.setenv("STATE_HUB_URL", "http://hub.test")
monkeypatch.setenv("KAIZEN_RUNNER_HOST", "testhost")
monkeypatch.setattr(
httpx,
"get",
lambda url, **kwargs: DummyResponse(
[{"slug": "pilot-repo", "host_paths": {"testhost": str(repo_root)}}]
),
)
result = discover_kaizen_scheduled_repos({})
assert result["scheduled_runs"] == []
def test_discover_scheduled_repos_skips_missing_schedule(tmp_path, monkeypatch) -> None:
repo_root = tmp_path / "no-schedule"
repo_root.mkdir()
monkeypatch.setenv("STATE_HUB_URL", "http://hub.test")
monkeypatch.setenv("KAIZEN_RUNNER_HOST", "testhost")
monkeypatch.setattr(
httpx,
"get",
lambda url, **kwargs: DummyResponse(
[{"slug": "no-schedule", "host_paths": {"testhost": str(repo_root)}}]
),
)
result = discover_kaizen_scheduled_repos({})
assert result["scheduled_runs"] == []
def test_discover_scheduled_repos_skips_invalid_schedule(tmp_path, monkeypatch) -> None:
repo_root = tmp_path / "bad-schedule"
schedule = repo_root / ".kaizen" / "schedule.yml"
schedule.parent.mkdir(parents=True)
schedule.write_text("version: '2'\nagents: {}\n", encoding="utf-8")
monkeypatch.setenv("STATE_HUB_URL", "http://hub.test")
monkeypatch.setenv("KAIZEN_RUNNER_HOST", "testhost")
monkeypatch.setattr(
httpx,
"get",
lambda url, **kwargs: DummyResponse(
[{"slug": "bad-schedule", "host_paths": {"testhost": str(repo_root)}}]
),
)
result = discover_kaizen_scheduled_repos({})
assert result["scheduled_runs"] == []
def test_discover_scheduled_repos_filters_by_roster_and_cadence(
tmp_path, monkeypatch
) -> None:
repo_a = tmp_path / "kaizen-agentic"
repo_b = tmp_path / "other-repo"
for root in (repo_a, repo_b):
_write_schedule(
root / ".kaizen" / "schedule.yml",
{
"coach": {"cadence": "daily", "enabled": True},
"optimization": {"cadence": "weekly", "enabled": True},
},
)
roster = tmp_path / "roster.yaml"
roster.write_text(
yaml.safe_dump(
{
"active": [
{"slug": "kaizen-agentic", "agents": ["coach"], "status": "active"}
]
}
),
encoding="utf-8",
)
monkeypatch.setenv("STATE_HUB_URL", "http://hub.test")
monkeypatch.setenv("KAIZEN_RUNNER_HOST", "testhost")
monkeypatch.setattr(
httpx,
"get",
lambda url, **kwargs: DummyResponse(
[
{"slug": "kaizen-agentic", "host_paths": {"testhost": str(repo_a)}},
{"slug": "other-repo", "host_paths": {"testhost": str(repo_b)}},
]
),
)
result = discover_kaizen_scheduled_repos(
{"roster": str(roster), "cadence": "daily"}
)
agents = {r["agent"] for r in result["scheduled_runs"]}
repos = {r["repo"] for r in result["scheduled_runs"]}
assert repos == {"kaizen-agentic"}
assert agents == {"coach"}
def test_hub_unreachable_raises(monkeypatch) -> None:
monkeypatch.setenv("STATE_HUB_URL", "http://hub.test")
def fail_get(url: str, **kwargs: Any) -> DummyResponse:
raise httpx.ConnectError("down")
monkeypatch.setattr(httpx, "get", fail_get)
with pytest.raises(RuntimeError, match="State Hub unreachable"):
discover_kaizen_scheduled_repos({})
def test_resolver_registry_alias() -> None:
resolver = KaizenContextResolver()
assert resolver.resolve("unknown_query", None, {}) == {}