feat(backend): system-aware LLM prompt context (#137) #208

Merged
claude-bot merged 1 commit from feat/137-system-aware-prompts into feat/v3.9-game-aware-systems 2026-07-18 17:25:18 +00:00
Contributor

Backend issue of the v3.9.0 Game-Aware Systems pillar. Targets the integration branch. Builds on #133.

Closes #137.

What

Replaces the bare free-text game_system interpolation in LLM prompts with the linked registry system's prompt_hint when a campaign is linked — richer, consistent system context for the model — while free-form/unlinked campaigns keep byte-identical prompts.

  • New helper game_system_service.resolve_system_prompt_context(db, campaign): unlinked → raw campaign.game_system (unchanged); linked → the system's prompt_hint (else short_name). Uses sqlalchemy.inspect().unloaded to check the relationship is loaded before touching it (avoids async MissingGreenlet), falling back to a DB fetch.
  • Call sites (callers now pass the resolved context; the pure functions keep their signatures):
    • summarise()process_audio (reminder_tasks) + canonical-name re-summarise (sessions).
    • generate_name_options() gains a system_key param + a per-system _NAME_CATEGORY_DESCRIPTION_HINTS_BY_SYSTEM override map (pf2e player_character/npc use ancestry/heritage/class terminology); wired through the session route, the planning cache, and the prefetch task. The prefetch task now resolves context inside its task_session() block (eager-loading game_system_ref) and captures system_key as a plain string before the session closes.
    • Lore-extraction prompt (lore_service), preserving the 'Unknown' fallback.

Verification (Docker, py3.12)

  • 632 backend tests pass (was 618; +14 in test_system_aware_prompts.py) — no regressions. Coverage: linked-dnd5e prompts contain the prompt_hint; free-form campaigns yield the unchanged legacy string; the pf2e per-category override fires only when linked.

Follow-ups flagged (out of scope here)

  • Two other raw-game_system prompt sites remain: the NPC-fleshout backstory/statblock prompts (reminder_tasks.py, which #142 touches next) and generate_session_title_suggestions. Left for #142 / a small follow-up rather than widened here.
  • No bot API change; BOT_CONTRACT_VERSION stays 1.

🤖 Generated with Claude Code

Backend issue of the **v3.9.0 Game-Aware Systems** pillar. Targets the integration branch. Builds on #133. Closes #137. ## What Replaces the bare free-text `game_system` interpolation in LLM prompts with the linked registry system's `prompt_hint` when a campaign is linked — richer, consistent system context for the model — while free-form/unlinked campaigns keep **byte-identical** prompts. - **New helper** `game_system_service.resolve_system_prompt_context(db, campaign)`: unlinked → raw `campaign.game_system` (unchanged); linked → the system's `prompt_hint` (else `short_name`). Uses `sqlalchemy.inspect().unloaded` to check the relationship is loaded before touching it (avoids async `MissingGreenlet`), falling back to a DB fetch. - **Call sites** (callers now pass the resolved context; the pure functions keep their signatures): - `summarise()` ← `process_audio` (reminder_tasks) + canonical-name re-summarise (sessions). - `generate_name_options()` gains a `system_key` param + a per-system `_NAME_CATEGORY_DESCRIPTION_HINTS_BY_SYSTEM` override map (pf2e player_character/npc use ancestry/heritage/class terminology); wired through the session route, the planning cache, and the prefetch task. The prefetch task now resolves context **inside** its `task_session()` block (eager-loading `game_system_ref`) and captures `system_key` as a plain string before the session closes. - Lore-extraction prompt (`lore_service`), preserving the `'Unknown'` fallback. ## Verification (Docker, py3.12) - **632 backend tests pass** (was 618; +14 in `test_system_aware_prompts.py`) — no regressions. Coverage: linked-dnd5e prompts contain the `prompt_hint`; free-form campaigns yield the unchanged legacy string; the pf2e per-category override fires only when linked. ## Follow-ups flagged (out of scope here) - Two other raw-`game_system` prompt sites remain: the NPC-fleshout backstory/statblock prompts (`reminder_tasks.py`, which **#142** touches next) and `generate_session_title_suggestions`. Left for #142 / a small follow-up rather than widened here. - No bot API change; `BOT_CONTRACT_VERSION` stays 1. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Add game_system_service.resolve_system_prompt_context(db, campaign): for a
campaign linked to the game system registry, resolve the linked system's
prompt_hint (falling back to short_name) instead of the bare free-text
game_system column; unlinked campaigns keep byte-identical prompts.

Wire it into the three LLM prompt-building call sites: session summarise
(audio_service.summarise, called from reminder_tasks.process_audio and
routers/sessions.py select_canonical_name), name-option generation
(audio_service.generate_name_options, called from routers/sessions.py,
routers/campaigns.py get_cached_name_options, and
tasks/planning_tasks.prefetch_name_options — each now also passes the
linked system's key as system_key), and lore extraction
(lore_service.generate_session_lore_proposals).

generate_name_options gains an optional system_key param plus a
per-system category-hint override map (pf2e player_character/npc example)
that only applies when a campaign is linked to that system.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
claude-bot merged commit e347aa2dcb into feat/v3.9-game-aware-systems 2026-07-18 17:25:18 +00:00
Sign in to join this conversation.
No description provided.