KI-Konzil/backend/tests/test_run_store.py
Claude 797f02c74d
Implement Phase 1: LangGraph backend MVP
Sets up the full backend foundation for CouncilOS:

- CouncilState TypedDict with all required fields and LangGraph reducers
- Three agent nodes: master_agent (drafts), critic_agent (scores + routes),
  writer_agent (final polish)
- LangGraph graph with cyclic rework loop: Master → Critic → (score < 8:
  back to Master | score ≥ 8: Writer → END)
- Safety valve: MAX_ITERATIONS=5 prevents infinite loops
- FastAPI app with REST endpoints (POST /api/councils/run, GET /api/councils/run/{id})
  and WebSocket endpoint (/ws/council/{run_id}) for real-time agent status events
- In-memory RunStore for Phase 1 (PostgreSQL-backed in Phase 3)
- pytest test suite: state, routing logic, critic parser, agent nodes, API endpoints
- .env.example, .gitignore, docker-compose.yml, Dockerfile

https://claude.ai/code/session_01RfMpt3TbMjZEtK3CAyP5iQ
2026-02-20 16:33:39 +00:00

55 lines
1.8 KiB
Python

"""Tests for the in-memory RunStore."""
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
from api.run_store import RunStore
class TestRunStore:
def setup_method(self):
self.store = RunStore()
def test_create_and_get(self):
self.store.create("run-1", "Test topic")
run = self.store.get("run-1")
assert run is not None
assert run["run_id"] == "run-1"
assert run["input_topic"] == "Test topic"
assert run["status"] == "pending"
def test_get_nonexistent_returns_none(self):
assert self.store.get("nonexistent") is None
def test_update_status(self):
self.store.create("run-2", "Topic")
self.store.update("run-2", {"status": "running"})
assert self.store.get("run-2")["status"] == "running"
def test_update_nonexistent_is_noop(self):
"""Updating a non-existent run should not raise."""
self.store.update("ghost-run", {"status": "running"})
def test_delete(self):
self.store.create("run-3", "Topic")
self.store.delete("run-3")
assert self.store.get("run-3") is None
def test_delete_nonexistent_is_noop(self):
self.store.delete("ghost-run")
def test_update_partial_fields(self):
self.store.create("run-4", "Topic")
self.store.update("run-4", {"status": "completed", "final_draft": "Result text"})
run = self.store.get("run-4")
assert run["status"] == "completed"
assert run["final_draft"] == "Result text"
assert run["input_topic"] == "Topic" # original field preserved
def test_multiple_runs_independent(self):
self.store.create("run-a", "Topic A")
self.store.create("run-b", "Topic B")
self.store.update("run-a", {"status": "running"})
assert self.store.get("run-b")["status"] == "pending"