Spaces:
Running
Running
| """Council layer tests using the deterministic MockLLMClient.""" | |
| from __future__ import annotations | |
| import shutil | |
| from pathlib import Path | |
| import pytest | |
| from app.council.llm import MockLLMClient | |
| from app.council.runner import CACHE_ROOT, Council | |
| from app.council.specialists import SPECIALISTS | |
| from app.core.environment import StockerEnv | |
| def _clean_cache(tmp_path, monkeypatch): | |
| # Use a per-test cache dir so previous runs don't pollute. | |
| new_cache = tmp_path / "council" | |
| monkeypatch.setattr("app.council.runner.CACHE_ROOT", new_cache) | |
| yield | |
| if new_cache.exists(): | |
| shutil.rmtree(new_cache, ignore_errors=True) | |
| def test_seven_specialists_registered(): | |
| assert len(SPECIALISTS) == 7 | |
| names = [c.name for c in [cls(MockLLMClient()) for cls in SPECIALISTS]] | |
| assert sorted(names) == sorted([ | |
| "chart_pattern", "seasonal_trend", "indicator", "news", | |
| "forum_sentiment", "peer_commodity", "geopolitics", | |
| ]) | |
| def test_council_produces_valid_decision(): | |
| env = StockerEnv("task_easy") | |
| obs = env.reset().observation | |
| council = Council(client=MockLLMClient(), use_cache=False) | |
| decision = council.run(obs) | |
| assert len(decision.votes) == 7 | |
| for v in decision.votes: | |
| assert -1.0 <= v.signal <= 1.0 | |
| assert 0.0 <= v.confidence <= 1.0 | |
| assert v.rationale | |
| assert decision.action.side in ("buy", "sell", "hold") | |
| assert decision.action.quantity >= 0 | |
| def test_council_cache_round_trips(tmp_path): | |
| env = StockerEnv("task_easy") | |
| obs = env.reset().observation | |
| council = Council(client=MockLLMClient(), use_cache=True) | |
| d1 = council.run(obs) | |
| d2 = council.run(obs) | |
| # Same inputs -> identical decision | |
| assert d1.action.side == d2.action.side | |
| assert d1.action.quantity == d2.action.quantity | |
| assert [v.signal for v in d1.votes] == [v.signal for v in d2.votes] | |
| def test_council_drives_env_to_completion(): | |
| env = StockerEnv("task_easy") | |
| obs = env.reset().observation | |
| council = Council(client=MockLLMClient(), use_cache=False) | |
| done = False | |
| steps = 0 | |
| while not done and steps < 100: | |
| decision = council.run(obs) | |
| result = env.step(decision.action) | |
| obs = result.observation | |
| done = result.done | |
| steps += 1 | |
| assert done | |
| assert steps == env.state().total_steps | |