- Add return type annotation (list[str]) to Config.validate()
- Add type annotations (msg: str, -> None) to logger convenience functions
- Add FileParser.is_supported() classmethod for checking file format support
- New Vue views: GodModeView (inject event, modify emotions with
preloaded current values, kill character with typed-name
confirmation) and WorldBuilderView (rules editor, locations with
cinematic atmosphere field, event log viewer)
- Shared sim-nav strip across Story/GodMode/World views
- Location schema extended with optional atmosphere field — a short
mood phrase that anchors the opening visual of every scene set there
- Translator's _format_world_locations surfaces atmosphere to the LLM
prompt so the field actually influences generation
- Routes added for /godmode/:simId and /world/:simId
Tests: 39/39 passing (added test_location_atmosphere_surfaces_in_prompt).
Frontend builds clean.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Six new endpoints under /api/narrative/*:
- GET /world/<sim_id> — full world state
- POST /world/<sim_id>/rules — replace rules list
- POST /world/<sim_id>/locations — upsert location
- POST /godmode/<sim_id>/inject-event — inject world event
- POST /godmode/<sim_id>/modify-emotion — overwrite emotions
- POST /godmode/<sim_id>/kill — kill character
Validation:
- 400 on missing required fields (description, character_id, rules)
- 400 on invalid round (must be non-negative int or null)
- 404 on character not found (from ValueError in handlers)
Smoke-tested via Flask test client — all 11 response codes correct.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- PROSE_PROMPT_TEMPLATE extended with world_rules, world_events,
world_locations, and event_enforcement substitution fields
- EVENT_ENFORCEMENT_STRENGTH set to "hard" — opening line MUST
reference the most recent world event (aligns with existing
punchy, cinematic voice)
- Character summaries now resolve location id → name for prompts
- translate_round loads world_state and filters dead characters
from both the roster and the action list before prose generation
- User-supplied strings (rules, events, locations) brace-escaped
before str.format() to prevent KeyError on stray { or }
Tests: 36/36 passing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Five endpoints under /api/narrative/*:
- GET /story/<sim_id> — full story so far
- GET /story/<sim_id>/round/<num> — single round
- POST /translate — translate a round on demand
- GET /characters/<sim_id> — roster with emotional state
- POST /characters/<sim_id>/init — bootstrap from OASIS profiles
Blueprint registered alongside existing graph/simulation/report
blueprints following the established pattern. Smoke-tested via Flask
test client.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
translate_round() ties together:
- reading the round's actions from actions.jsonl
- generating prose via the LLM
- updating per-character emotional state
- persisting the beat, characters, and file offset
Full test suite now at 19/19 passing across action mapper, character
engine, story store, and translator.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Module-level call_llm() wrapper (patchable by tests) drives
PROSE_PROMPT_TEMPLATE rendering with character summaries, actions,
previous beats, and user-selected tone. Prompt tuned for punchy,
cinematic, dialogue-heavy voice.
Tests: 5/5 passing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reads one round's worth of agent actions from the OASIS log file,
tracking file offset so callers can resume across translation calls.
Handles missing files, malformed JSON lines, and non-target rounds
gracefully.
Tests: 3/3 passing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Character profiles now track a six-dimension emotional state (anger,
fear, joy, sadness, trust, surprise) that evolves based on actions
taken. Initial deltas for all 13 OASIS actions chosen as a balanced
baseline (see module docstring for tuning guidance).
Tests: 5/5 passing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three JSON files per simulation under narrative/ subdir:
- story_beats.json: chronological story passages
- translator_state.json: per-platform file offsets
- characters.json: extended character profiles
Tests: 4/4 passing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New narrative package with action_mapper module that maps the 13 OASIS
action types (CREATE_POST, LIKE_POST, REPOST, etc.) to narrative verbs
and interpretations used when generating story prose.
Tests: 4/4 passing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Background threads (graph building, simulation prep, report generation,
profile generation) now inherit the requesting user's locale preference.
Previously these fell back to 'zh' because Flask request context was
unavailable in spawned threads.
Ensure poster_type stays PascalCase English and stance stays English enum
values regardless of language setting. Only natural language fields follow
the user's language preference.
The language instruction was causing LLM to change entity/relation naming
conventions. Now explicitly enforce PascalCase/UPPER_SNAKE_CASE for technical
identifiers while only applying language preference to description fields.
- Implemented `_get_report_id_for_simulation` to find the most recent report ID associated with a simulation ID by scanning the reports directory.
- Updated `get_simulation_history` to include the retrieved report ID in the response, enhancing the simulation data returned to the client.
- Updated simulation history retrieval to read project details directly from the Simulation file.
- Improved simulation configuration handling by reading simulation requirements from JSON.
- Added project file listing to the simulation history, displaying up to three associated files.
- Refined card layout in HistoryDatabase.vue to accommodate new file display features and improved responsiveness.