from pathlib import Path import pytest from content_build.emit import build_trees, check_secrecy, write_trees, dump_json from content_build.model import entry_from_raw from content_build.parse import parse_bible from content_build.resolve import resolve from content_build.errors import BuildError FIXTURE = Path(__file__).parent / "fixtures" / "valid" / "world.md" def _world(): raws = parse_bible(FIXTURE) return resolve([entry_from_raw(r) for r in raws]) def test_npc_skeleton_has_no_persona_client_side(): client, _ = build_trees(_world()) npc = client["npcs/tess.json"] assert "persona" not in npc and "body" not in npc assert npc["start_disposition"] == "cold" assert {"fact_id": "secret.big-twist", "gate": "never"} in npc["knows"] def test_persona_goes_server_side(): _, server = build_trees(_world()) assert server["npcs/tess.json"]["persona"].startswith("Tess") def test_secret_body_only_server_side(): client, server = build_trees(_world()) assert "topics/big-twist.json" in server assert server["topics/big-twist.json"]["body"].startswith("The twist") # client topic skeleton carries no body assert "body" not in client["topics/big-twist.json"] def test_canon_entity_body_ships_client_side(): client, _ = build_trees(_world()) assert client["canon/testburg.json"]["body"].startswith("A test town") assert client["canon/disposition-ladder.json"]["rungs"][0] == "hostile" def test_check_secrecy_passes_on_valid_world(): client, _ = build_trees(_world()) check_secrecy(client, _world()) # no raise def test_check_secrecy_fails_when_secret_body_reaches_client(): world = _world() client, _ = build_trees(world) # simulate a routing regression: a secrecy-4 body in a client record client["canon/leak.json"] = {"id": "secret.big-twist", "body": "leak"} with pytest.raises(BuildError): check_secrecy(client, world) def test_write_trees_serializes_deterministically(tmp_path): client, server = build_trees(_world()) write_trees(client, server, tmp_path / "world", tmp_path / "server") written = (tmp_path / "world" / "npcs" / "tess.json").read_text() assert written == dump_json(client["npcs/tess.json"])