feat(narrative): add god_mode.inject_event handler
This commit is contained in:
parent
16b7ef7521
commit
f91dd00f37
|
|
@ -0,0 +1,28 @@
|
||||||
|
"""God Mode intervention handlers.
|
||||||
|
|
||||||
|
All handlers mutate on-disk JSON under narrative/ and return the result.
|
||||||
|
Each intervention is logged to world_state.event_log for auditability.
|
||||||
|
"""
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from app.services.narrative.story_store import StoryStore
|
||||||
|
from app.services.narrative.world_state import WorldStateStore
|
||||||
|
|
||||||
|
|
||||||
|
def _current_round(sim_dir: str) -> int:
|
||||||
|
"""Return the 'current' round: last translated beat's round + 1, or 1."""
|
||||||
|
beats = StoryStore(sim_dir).get_all_beats()
|
||||||
|
if not beats:
|
||||||
|
return 1
|
||||||
|
return beats[-1].get("round", 0) + 1
|
||||||
|
|
||||||
|
|
||||||
|
def inject_event(sim_dir: str, description: str, round_num: Optional[int] = None) -> dict:
|
||||||
|
"""Append a user-described event to the world event log."""
|
||||||
|
world = WorldStateStore(sim_dir)
|
||||||
|
round_val = round_num if round_num is not None else _current_round(sim_dir)
|
||||||
|
return world.append_event({
|
||||||
|
"type": "god_mode_injection",
|
||||||
|
"description": description,
|
||||||
|
"round": round_val,
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
import pytest
|
||||||
|
from app.services.narrative.god_mode import inject_event
|
||||||
|
from app.services.narrative.story_store import StoryStore
|
||||||
|
from app.services.narrative.world_state import WorldStateStore
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def temp_sim_dir():
|
||||||
|
with tempfile.TemporaryDirectory() as d:
|
||||||
|
sim_dir = os.path.join(d, "sim_test")
|
||||||
|
os.makedirs(sim_dir)
|
||||||
|
yield sim_dir
|
||||||
|
|
||||||
|
|
||||||
|
def test_inject_event_appends_to_log(temp_sim_dir):
|
||||||
|
evt = inject_event(temp_sim_dir, description="A storm arrives.", round_num=5)
|
||||||
|
assert evt["description"] == "A storm arrives."
|
||||||
|
assert evt["round"] == 5
|
||||||
|
assert evt["id"] == "evt_1"
|
||||||
|
assert evt["type"] == "god_mode_injection"
|
||||||
|
|
||||||
|
log = WorldStateStore(temp_sim_dir).load()["event_log"]
|
||||||
|
assert len(log) == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_inject_event_defaults_round_to_beats_plus_one(temp_sim_dir):
|
||||||
|
store = StoryStore(temp_sim_dir)
|
||||||
|
store.append_beat({"round": 3, "prose": "beat 3"})
|
||||||
|
|
||||||
|
evt = inject_event(temp_sim_dir, description="auto round")
|
||||||
|
assert evt["round"] == 4
|
||||||
|
|
||||||
|
|
||||||
|
def test_inject_event_defaults_round_to_one_when_no_beats(temp_sim_dir):
|
||||||
|
evt = inject_event(temp_sim_dir, description="first event")
|
||||||
|
assert evt["round"] == 1
|
||||||
Loading…
Reference in New Issue