import json from pathlib import Path from app.prompts import render_digest, system_prompt VALID = json.loads((Path(__file__).parent / "fixtures" / "canon_log_valid.json").read_text()) def test_system_prompt_strips_the_header(): body = system_prompt("narrator") assert isinstance(body, str) and body.strip() != "" # The human-facing markdown title above the '---' is not part of the prompt. assert "# Narrator prompt" not in body def test_digest_has_the_narrative_context(): d = render_digest(VALID) assert "Location: the Greywater docks" in d assert "Arrived at Greywater by barge before dawn" in d assert "Established facts:" in d assert "the harbourmaster is named Oda Fenn" in d assert "Companions present: Brannoc Thane, Cadwyn Vell" in d assert "Active quest: The Missing Ledger — Find who took Fenn's ledger" in d assert "Fortune: Fortune spits on you" in d assert "Player: Aldric, a human sellsword" in d assert d.rstrip().endswith("Describe the scene as it is now.") def test_digest_omits_raw_numbers_and_ids(): d = render_digest(VALID) # §7/§2: no disposition integers, no ids, no schema_version leak into the prompt. assert "disposition" not in d assert "40" not in d and "15" not in d # the deserter dispositions assert "brannoc_thane" not in d # ids stay out; names only assert "schema_version" not in d def test_narrator_body_is_authored(): body = system_prompt.__wrapped__("narrator") # bypass lru_cache in case of prior load assert "TBD" not in body assert "[FACT:" in body # the tag instruction is present assert "second person" in body # the core task is present def _with_player(**player) -> dict: log = json.loads(json.dumps(VALID)) # deep copy — VALID is module-level and shared log["player"] = {"luck_descriptor": "the dice are kind", **player} return log def test_digest_names_the_race_and_the_calling(): out = render_digest(_with_player(name="Aldric", race_id="beastfolk", calling_id="cutpurse")) assert "Aldric, a beastfolk cutpurse" in out def test_digest_says_an_elf_not_a_elf(): out = render_digest(_with_player(name="Aldric", race_id="elf", calling_id="sellsword")) assert "an elf sellsword" in out def test_digest_does_not_leak_a_snake_case_id(): out = render_digest(_with_player(name="Aldric", race_id="human", calling_id="hedge_mage")) assert "hedge_mage" not in out, "the model must never read a raw snake_case id" assert "hedge-mage" in out def test_render_npc_digest_includes_all_sections(): from app import prompts 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": ["a gull screamed"], "established_facts": ["the eastern bridge is out"], "active_quests": [], "humiliations": [], } out = prompts.render_npc_digest( log, persona="A harried clerk.", knowledge=["The ledger is gone."], disposition=-10, available_moves=["reveal(varrell_twins)", "refuse"], utterance="What happened here?", ) assert "A harried clerk." in out assert "-10" in out assert "The ledger is gone." in out assert "reveal(varrell_twins)" in out assert "Greywater Docks" in out assert "the eastern bridge is out" in out assert out.rstrip().endswith('What happened here?"') # utterance last