import json from pathlib import Path import pytest import app.narrate as narrate import app.npc as npc VALID = json.loads((Path(__file__).parent / "fixtures" / "canon_log_valid.json").read_text()) @pytest.mark.live def test_narrator_returns_real_prose(): """Hits the real Ollama (OLLAMA_BASE_URL). Proves the wire end-to-end: prompt assembly → model → non-empty prose. Not asserted: tag content (nondeterministic). Run with: pytest --run-live """ text = narrate.run(VALID) assert isinstance(text, str) assert len(text.strip()) > 40 # real prose, not a blip @pytest.mark.live def test_live_npc_speak_fenn(): """Hits the real Ollama (OLLAMA_BASE_URL). Proves the /npc/speak wire end-to-end against the authored "fenn" NPC: persona + knowledge digest → model → non-empty in-voice prose. Not asserted: tag content (nondeterministic). Run with: pytest --run-live """ log = { "player": { "name": "Aldric", "race_id": "human", "calling_id": "sellsword", "luck_descriptor": "the dice are kind", }, "location": {"id": "greywater_docks", "name": "Greywater Docks"}, "party": [], "recent_events": [], "established_facts": [], "active_quests": [], "humiliations": [], } available = [ "offer_quest(find_the_ledger)", "reveal(varrell_twins)", "reveal(fenns_debt)", "adjust_disposition", "refuse", "end_conversation", "become_hostile", ] prose = npc.run(log, "fenn", 0, available, "I heard you lost something. What happened?") assert isinstance(prose, str) assert len(prose.strip()) > 40 # real prose, not a blip # No Luck numbers/mechanics leaked into NPC dialogue (§7). assert "luck" not in prose.lower()