[Scheduling/GM] Per-occurrence titles for recurring series, with LLM suggestions from the previous session #191

Closed
opened 2026-07-17 23:04:45 +00:00 by claude-bot · 1 comment
Contributor

Motivation

Recurring session series (#98) currently apply one static title_template to every materialized occurrence, so all weeks read the same ("Weekly Game"). A GM running an ongoing campaign wants each week's session to have its own title (and ideally a short description) — and, after playing a session, would love LLM-suggested titles for next week based on what just happened, which they can accept or override.

Flow the GM wants:

  1. Play this week's session (it gets recorded/summarised via the existing audio → summary pipeline, or the GM writes notes).
  2. Afterwards, Quest Board offers a few suggested titles (and a short blurb) for the next occurrence in the series, generated from the previous session's summary/transcript/lore.
  3. The GM either accepts a suggestion or types their own, and the next materialized session is named accordingly.

Context / what exists to build on

  • Series + materialization: app/models/session_series.py, series_service.py, and the materialize_session_series Beat task (#98). Materialized sessions already have editable title (and description) columns on sessions — so per-occurrence manual titling is largely a UI affordance today; the new part is the suggestion generation and wiring it to "the next occurrence".
  • LLM name generation precedent: the GM Planning name generator (app/routers/services behind generateNameOptions / saveCanonicalName, frontend CampaignPlanning.jsx NameGeneratorPanel, api/planning.js) already generates candidate names from campaign context via the configured LLM (Ollama/API in Admin → Bot Settings). Reuse that pattern rather than inventing a new LLM path.
  • Previous-session signal: sessions.summary/transcript and campaign lore (lore_entries) are the natural inputs for "suggest next week's title from what just happened".
  • Trigger point: the session_summarised path / recap generation is the obvious place to compute suggestions for the next series occurrence (or compute lazily when the GM opens the upcoming session / series panel).

Rough spec

  1. Per-occurrence title/description: expose editing the title and a short description for an individual materialized occurrence in the series UI (SeriesManager / session detail) — distinct from the series title_template. Detached/edited occurrences keep their own title regardless of later series edits (respect the existing edit-scope model from #98).
  2. Suggestions endpoint: POST /api/sessions/{id}/title-suggestions (or under the series) that, given a session, uses the previous session in the same series (its summary/transcript, plus recent lore) to return N candidate {title, description} pairs via the configured LLM. Cache like the name generator does.
  3. UI: on the next upcoming series occurrence (and/or after a session is summarised), show "Suggested titles" with accept-or-edit, writing the chosen title/description onto that occurrence. GM-only.
  4. Fallbacks: no previous session / no summary / LLM not configured → offer manual entry only, no error.

Out of scope

  • Auto-applying a suggestion without GM confirmation (always GM-in-the-loop).
  • Non-series sessions (though the suggestion endpoint could later generalise).

Acceptance criteria

  • A GM can set a distinct title (+ short description) on an individual occurrence of a recurring series, and it survives series-level edits per #98's scope rules.
  • After a session with a summary, the GM sees LLM-suggested titles/descriptions for the next occurrence, sourced from that summary, and can accept one or type their own.
  • LLM-unconfigured / no-previous-summary degrades to manual entry with no error.

References

  • #98 (recurring series), series_service.py, materialize_session_series
  • GM Planning name generator (NameGeneratorPanel, generateNameOptions, api/planning.js) — the LLM-suggestion pattern to reuse
  • sessions.summary/transcript, audio_service summary pipeline, lore_entries

Suggested home: the v3.10.0 GM Workbench milestone (this is a generative session-prep feature) — or its own scheduling follow-up. Requested 2026-07-17.

## Motivation Recurring session series (#98) currently apply one static `title_template` to every materialized occurrence, so all weeks read the same ("Weekly Game"). A GM running an ongoing campaign wants each week's session to have its **own** title (and ideally a short description) — and, after playing a session, would love **LLM-suggested titles for next week** based on what just happened, which they can accept or override. Flow the GM wants: 1. Play this week's session (it gets recorded/summarised via the existing audio → summary pipeline, or the GM writes notes). 2. Afterwards, Quest Board offers a few **suggested titles** (and a short blurb) for the **next** occurrence in the series, generated from the previous session's summary/transcript/lore. 3. The GM either **accepts a suggestion** or **types their own**, and the next materialized session is named accordingly. ## Context / what exists to build on - **Series + materialization**: `app/models/session_series.py`, `series_service.py`, and the `materialize_session_series` Beat task (#98). Materialized sessions already have editable `title` (and `description`) columns on `sessions` — so per-occurrence *manual* titling is largely a UI affordance today; the new part is the **suggestion generation** and wiring it to "the next occurrence". - **LLM name generation precedent**: the GM Planning name generator (`app/routers`/`services` behind `generateNameOptions` / `saveCanonicalName`, frontend `CampaignPlanning.jsx` `NameGeneratorPanel`, `api/planning.js`) already generates candidate names from campaign context via the configured LLM (Ollama/API in Admin → Bot Settings). Reuse that pattern rather than inventing a new LLM path. - **Previous-session signal**: `sessions.summary`/`transcript` and campaign lore (`lore_entries`) are the natural inputs for "suggest next week's title from what just happened". - **Trigger point**: the `session_summarised` path / recap generation is the obvious place to compute suggestions for the next series occurrence (or compute lazily when the GM opens the upcoming session / series panel). ## Rough spec 1. **Per-occurrence title/description**: expose editing the `title` and a short `description` for an individual materialized occurrence in the series UI (`SeriesManager` / session detail) — distinct from the series `title_template`. Detached/edited occurrences keep their own title regardless of later series edits (respect the existing edit-scope model from #98). 2. **Suggestions endpoint**: `POST /api/sessions/{id}/title-suggestions` (or under the series) that, given a session, uses the previous session in the same series (its summary/transcript, plus recent lore) to return N candidate `{title, description}` pairs via the configured LLM. Cache like the name generator does. 3. **UI**: on the next upcoming series occurrence (and/or after a session is summarised), show "Suggested titles" with accept-or-edit, writing the chosen title/description onto that occurrence. GM-only. 4. **Fallbacks**: no previous session / no summary / LLM not configured → offer manual entry only, no error. ## Out of scope - Auto-applying a suggestion without GM confirmation (always GM-in-the-loop). - Non-series sessions (though the suggestion endpoint could later generalise). ## Acceptance criteria - A GM can set a distinct title (+ short description) on an individual occurrence of a recurring series, and it survives series-level edits per #98's scope rules. - After a session with a summary, the GM sees LLM-suggested titles/descriptions for the next occurrence, sourced from that summary, and can accept one or type their own. - LLM-unconfigured / no-previous-summary degrades to manual entry with no error. ## References - #98 (recurring series), `series_service.py`, `materialize_session_series` - GM Planning name generator (`NameGeneratorPanel`, `generateNameOptions`, `api/planning.js`) — the LLM-suggestion pattern to reuse - `sessions.summary`/`transcript`, `audio_service` summary pipeline, `lore_entries` _Suggested home: the **v3.10.0 GM Workbench** milestone (this is a generative session-prep feature) — or its own scheduling follow-up. Requested 2026-07-17._
Author
Contributor

Done — merged to feat/v3.10-gm-workbench via PR #223.

  • series_titles workbench tool (params {session_id}): a context builder folds the most recent prior summarised occurrence in the same series into the prompt → {suggestions: [{title, description}]}. Reuses the #136 engine (per "reuse the name generator pattern").
  • SessionResponse now exposes series_id + series_occurrence_date (additive; frontend response only — not the bot contract) so the UI can identify series occurrences.
  • SeriesTitleSuggester panel: pick an upcoming series occurrence → suggest → "Use this title" writes title+description onto the occurrence via the existing updateSession PATCH; an always-present manual entry is the fallback. Empty suggestions (no prior summary / LLM off) degrade to manual with no error.

Acceptance criteria:

  1. Per-occurrence title survives series edits — materialize_session_series inserts with on_conflict_do_nothing, so it never clobbers an edited title; SessionUpdate already carries title+description.
  2. After a summarised session, the GM sees LLM suggestions for the next occurrence sourced from that summary, and can accept or type their own.
  3. LLM-unconfigured / no-previous-summary degrades to manual entry, no error.

Interpretation note: surfaced as a workbench-style panel on the planning page (consistent with the rest of v3.10.0) rather than inline in SeriesManager — deeper inline series-UI integration is a possible follow-up. No new models/migrations.

Verified: backend 735 passed (incl. new test_workbench_series_titles.py), frontend 397 passed, ruff + eslint clean, build OK. Not yet exercised against a live LLM on dev — pending your dev testing.

Done — merged to `feat/v3.10-gm-workbench` via PR #223. - **`series_titles` workbench tool** (params `{session_id}`): a context builder folds the most recent *prior summarised* occurrence in the same series into the prompt → `{suggestions: [{title, description}]}`. Reuses the #136 engine (per "reuse the name generator pattern"). - **`SessionResponse` now exposes `series_id` + `series_occurrence_date`** (additive; frontend response only — not the bot contract) so the UI can identify series occurrences. - **`SeriesTitleSuggester`** panel: pick an upcoming series occurrence → suggest → "Use this title" writes title+description onto the occurrence via the existing `updateSession` PATCH; an always-present manual entry is the fallback. Empty suggestions (no prior summary / LLM off) degrade to manual with no error. **Acceptance criteria:** 1. ✅ Per-occurrence title survives series edits — `materialize_session_series` inserts with `on_conflict_do_nothing`, so it never clobbers an edited title; `SessionUpdate` already carries title+description. 2. ✅ After a summarised session, the GM sees LLM suggestions for the next occurrence sourced from that summary, and can accept or type their own. 3. ✅ LLM-unconfigured / no-previous-summary degrades to manual entry, no error. Interpretation note: surfaced as a workbench-style panel on the planning page (consistent with the rest of v3.10.0) rather than inline in `SeriesManager` — deeper inline series-UI integration is a possible follow-up. No new models/migrations. Verified: backend 735 passed (incl. new `test_workbench_series_titles.py`), frontend 397 passed, ruff + eslint clean, build OK. **Not yet exercised against a live LLM on dev** — pending your dev testing.
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rbrooks/Quest-Board#191
No description provided.