Files
2026-07-13 13:12:33 +08:00

144 lines
4.6 KiB
Python

from __future__ import annotations
import pytest
from opensquilla.memory.dream_factory import _session_lock_for
from opensquilla.scheduler.dream_handler import make_memory_dream_handler
from opensquilla.scheduler.types import CronJob
@pytest.mark.asyncio
async def test_memory_dream_handler_skips_without_building_dream() -> None:
def build_dream(agent_id: str) -> object:
raise AssertionError(f"dream should not be built for {agent_id}")
handler = make_memory_dream_handler(build_dream, should_skip=lambda: "disabled")
result = await handler(
CronJob(
id="dream-main",
name="memory_dream:main",
payload={"agent_id": "main"},
)
)
assert result.summary == "dream skipped: disabled"
assert result.delivery_status == "skipped"
def test_dream_factory_uses_public_turn_runner_lock_surface() -> None:
class _Runner:
def __init__(self) -> None:
self.keys: list[str] = []
self.lock = object()
def get_session_lock(self, key: str) -> object:
self.keys.append(key)
return self.lock
def _get_session_lock(self, _key: str) -> object:
raise AssertionError("private lock surface should not be used")
runner = _Runner()
assert _session_lock_for(runner, "main") is runner.lock
assert runner.keys == ["memory_dream:main"]
@pytest.mark.asyncio
async def test_post_dream_hook_invoked_on_successful_run() -> None:
"""When build_dream succeeds the hook fires with the same agent_id."""
class _StubDream:
def __init__(self, agent_id: str) -> None:
self.agent_id = agent_id
async def run(self) -> object:
class _R:
files_processed = 0
evidence_status = "ok"
apply_status = "ok"
return _R()
captured: list[tuple[str, str]] = []
async def hook(agent_id: str, dream_summary: str) -> None:
captured.append((agent_id, dream_summary))
handler = make_memory_dream_handler(
build_dream=lambda aid: _StubDream(aid),
post_dream_hook=hook,
)
result = await handler(CronJob(id="dream-x", payload={"agent_id": "agent-x"}))
assert result.summary.startswith("dream agent=agent-x")
assert captured == [("agent-x", result.summary)]
@pytest.mark.asyncio
async def test_post_dream_hook_exception_does_not_poison_handler_result() -> None:
"""Hook failure logs an exception but the dream's HandlerResult
must still reflect the successful dream — observability cannot
convert a working dream into a failed one."""
class _StubDream:
async def run(self) -> object:
class _R:
files_processed = 1
evidence_status = "ok"
apply_status = "ok"
return _R()
async def hook(_agent_id: str, _dream_summary: str) -> None:
raise RuntimeError("auto_propose blew up")
handler = make_memory_dream_handler(
build_dream=lambda _aid: _StubDream(),
post_dream_hook=hook,
)
result = await handler(CronJob(id="dream-y", payload={"agent_id": "main"}))
assert result.summary.startswith("dream agent=main")
assert "blew up" not in result.summary
@pytest.mark.asyncio
async def test_post_dream_hook_not_called_when_dream_skipped() -> None:
"""Predicate-skip path short-circuits before the hook would fire."""
fired = False
async def hook(_agent_id: str, _dream_summary: str) -> None:
nonlocal fired
fired = True
def build(_aid: str) -> object:
raise AssertionError("dream should not be built when skipped")
handler = make_memory_dream_handler(
build_dream=build,
should_skip=lambda: "disabled",
post_dream_hook=hook,
)
result = await handler(CronJob(id="dream-z", payload={"agent_id": "main"}))
assert result.delivery_status == "skipped"
assert fired is False
@pytest.mark.asyncio
async def test_memory_dream_handler_kill_switch_skips_before_guard(
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setenv("OPENSQUILLA_MEMORY_DREAM_DISABLED", "1")
def build_dream(agent_id: str) -> object:
raise AssertionError(f"dream should not be built for {agent_id}")
def should_skip() -> str | None:
raise AssertionError("kill switch should short-circuit the guard")
handler = make_memory_dream_handler(build_dream, should_skip=should_skip)
result = await handler(CronJob(id="dream-main", payload={"agent_id": "main"}))
assert result.summary == "dream skipped: kill_switch"
assert result.delivery_status == "skipped"