[GM Workbench] Session prep sheet generator (B4) #158

Closed
opened 2026-07-15 22:04:34 +00:00 by claude-bot · 1 comment
Contributor

Motivation / Context

The report ranks the session prep sheet as the single highest-differentiation Workbench tool (§6): "reads your actual campaign state" — beat notes, recent session summaries, open threads, and arcs — to produce a structured prep draft no generic generator site can replicate, because none of them have access to this campaign's history. This is deliberately the last Phase 1/2 tool: it's the most complex (multi-source context assembly, prose-heavy output, review-before-save) and benefits from every other piece of the foundation already existing.

Per §3, Group B: generates a strong start, 3-5 potential scenes, secrets & clues, and NPCs likely to appear (linked to their lore entries), plus loose ends from the last session.

Approach

  • Register a session_prep tool in GENERATOR_TOOLS (generation_service.py, #136), flagged for Celery execution (sync_allowed=False) — this is exactly the "prose-heavy tool" case the report calls out for async handling (§5.1): multi-source context assembly plus a long structured output will exceed the "must be async" latency threshold on a local Ollama box.
  • Context assembly, using the context builders from #136 (§5.3):
    • Session.beat_notes for the upcoming session (existing GM free-text notes).
    • recent_sessions_context(db, campaign_id, n) — last 1-2 session summaries, following the pattern already used in issue #23's design and update_campaign_storyline.
    • threads_context(db, campaign_id) — open PlotThreads and arc statuses.
  • Generation: modeled on the existing Celery draft task generate_lore_entry_draftrun_lore_entry_draft_generation (webapp/backend/app/tasks/reminder_tasks.py:2018, 2051-2124) with a pending → ready/failed lifecycle written into GenerationResult (#138). Output structure: strong start (1-2 sentences), 3-5 potential scenes, secrets & clues, NPCs likely to appear (each cross-referenced to an existing LoreEntry via lore_context matching where possible), loose ends carried from the last session.
  • Review-then-save: this tool's save path is draft-style review, not immediate write — per the report, it "never auto-overwrites GM notes; append or replace with confirmation." Reuse the draft-review UX pattern (WikiDraftReview.jsx-style old-vs-new comparison, edit, iterate) adapted for Session.beat_notes as the target field rather than a LoreEntry.body. On approval, the GM explicitly chooses append or replace.
  • Frontend: given the async lifecycle, the panel polls generation status (same polling pattern WikiDraftReview.jsx already uses for draft generation) and presents the review UI once ready.

Dependencies

  • #134 (LLM core), #136 (workbench endpoint + tool registry + context builders, including recent_sessions_context), #138 (scratchpad + async status lifecycle) — Phase 0 foundation, required in full since this tool exercises every builder and the async path.
  • Benefits from, but does not strictly require, #153 (Workbench UX reorganization) — can ship with its own minimal async-polling panel first and migrate into the unified GeneratorPanel later, same as issues 4/6/7.
  • No dependency on #23 (session title suggestions) — different trigger (prep-time vs. transcript-approval) and different target field, but both follow the same "never make the GM wait" prefetch/async philosophy the report calls out; no code sharing required.

Out of scope

  • Shop/tavern inventory (A5) and portrait/token image prompts (D1) — the report explicitly queues these behind the prep sheet as further Phase 2 tools, not built in this issue.
  • Auto-applying the generated prep sheet to beat_notes without GM review — never allowed; always append-or-replace-with-confirmation.
  • Statblocks or backstory for NPCs surfaced as "likely to appear" — those NPCs are cross-referenced links to existing lore entries only; if new backstory content is desired, the GM uses A2 or #130 separately.

Acceptance criteria

  • session_prep tool registered, POST /api/campaigns/{campaign_id}/workbench/session_prep/generate runs async via Celery, GM-only.
  • Generation reads beat_notes, recent session summaries, and open threads/arcs, and produces strong start / 3-5 scenes / secrets & clues / linked NPCs / loose ends.
  • Status transitions pending → ready/failed are visible via the GenerationResult history/status endpoint from #138.
  • The save path requires explicit GM review and an explicit append-or-replace choice; nothing auto-writes to Session.beat_notes.
  • NPCs surfaced in the prep sheet link to existing LoreEntry rows where a match exists in campaign lore.
## Motivation / Context The report ranks the session prep sheet as the single highest-differentiation Workbench tool (§6): "reads your actual campaign state" — beat notes, recent session summaries, open threads, and arcs — to produce a structured prep draft no generic generator site can replicate, because none of them have access to *this* campaign's history. This is deliberately the last Phase 1/2 tool: it's the most complex (multi-source context assembly, prose-heavy output, review-before-save) and benefits from every other piece of the foundation already existing. Per §3, Group B: generates a strong start, 3-5 potential scenes, secrets & clues, and NPCs likely to appear (linked to their lore entries), plus loose ends from the last session. ## Approach - Register a `session_prep` tool in `GENERATOR_TOOLS` (`generation_service.py`, #136), flagged for Celery execution (`sync_allowed=False`) — this is exactly the "prose-heavy tool" case the report calls out for async handling (§5.1): multi-source context assembly plus a long structured output will exceed the "must be async" latency threshold on a local Ollama box. - **Context assembly**, using the context builders from #136 (§5.3): - `Session.beat_notes` for the upcoming session (existing GM free-text notes). - `recent_sessions_context(db, campaign_id, n)` — last 1-2 session summaries, following the pattern already used in issue #23's design and `update_campaign_storyline`. - `threads_context(db, campaign_id)` — open `PlotThread`s and arc statuses. - **Generation**: modeled on the existing Celery draft task `generate_lore_entry_draft` → `run_lore_entry_draft_generation` (`webapp/backend/app/tasks/reminder_tasks.py:2018, 2051-2124`) with a `pending → ready/failed` lifecycle written into `GenerationResult` (#138). Output structure: strong start (1-2 sentences), 3-5 potential scenes, secrets & clues, NPCs likely to appear (each cross-referenced to an existing `LoreEntry` via `lore_context` matching where possible), loose ends carried from the last session. - **Review-then-save**: this tool's save path is draft-style review, not immediate write — per the report, it "**never auto-overwrites GM notes**; append or replace with confirmation." Reuse the draft-review UX pattern (`WikiDraftReview.jsx`-style old-vs-new comparison, edit, iterate) adapted for `Session.beat_notes` as the target field rather than a `LoreEntry.body`. On approval, the GM explicitly chooses append or replace. - Frontend: given the async lifecycle, the panel polls generation status (same polling pattern `WikiDraftReview.jsx` already uses for draft generation) and presents the review UI once `ready`. ## Dependencies - **#134** (LLM core), **#136** (workbench endpoint + tool registry + context builders, including `recent_sessions_context`), **#138** (scratchpad + async status lifecycle) — Phase 0 foundation, required in full since this tool exercises every builder and the async path. - Benefits from, but does not strictly require, **#153** (Workbench UX reorganization) — can ship with its own minimal async-polling panel first and migrate into the unified `GeneratorPanel` later, same as issues 4/6/7. - No dependency on #23 (session title suggestions) — different trigger (prep-time vs. transcript-approval) and different target field, but both follow the same "never make the GM wait" prefetch/async philosophy the report calls out; no code sharing required. ## Out of scope - Shop/tavern inventory (A5) and portrait/token image prompts (D1) — the report explicitly queues these behind the prep sheet as further Phase 2 tools, not built in this issue. - Auto-applying the generated prep sheet to `beat_notes` without GM review — never allowed; always append-or-replace-with-confirmation. - Statblocks or backstory for NPCs surfaced as "likely to appear" — those NPCs are cross-referenced links to existing lore entries only; if new backstory content is desired, the GM uses A2 or #130 separately. ## Acceptance criteria - `session_prep` tool registered, `POST /api/campaigns/{campaign_id}/workbench/session_prep/generate` runs async via Celery, GM-only. - Generation reads `beat_notes`, recent session summaries, and open threads/arcs, and produces strong start / 3-5 scenes / secrets & clues / linked NPCs / loose ends. - Status transitions `pending → ready/failed` are visible via the `GenerationResult` history/status endpoint from #138. - The save path requires explicit GM review and an explicit append-or-replace choice; nothing auto-writes to `Session.beat_notes`. - NPCs surfaced in the prep sheet link to existing `LoreEntry` rows where a match exists in campaign lore.
Author
Contributor

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

The first async Workbench tool. session_prep (sync_allowed=False) runs on the #136 Celery path, assembling context from the upcoming session's beat notes + recent_sessions_context + threads_context + lore_context, and producing {strong_start, scenes[], secrets_and_clues[], npcs[{name,note}], loose_ends[]} (tolerant parser). session_id is a str/UUID param so it round-trips through row.params to the worker.

  • New polling primitive GET /workbench/history/{result_id} (GM-only).
  • Frontend SessionPrepGenerator: pick an upcoming session → generate (pending) → poll until ready/failed → render the sheet with NPCs linked to matching wiki entries → append or replace into beat_notes (existing PATCH) after explicit GM review. Never auto-writes.
  • fetchWorkbenchResult uses cache: false so the client's 15s GET dedup cache doesn't hide the pending → ready transition from the poller.

All acceptance criteria met (async lifecycle visible via history/status; reads beat_notes + recent summaries + threads; explicit append-or-replace review; NPCs link to existing lore). No new models/migrations.

Verified: backend 719 passed (incl. new test_workbench_session_prep.py), frontend 379 passed, ruff + eslint clean, build OK. Not yet exercised against a live LLM on dev — that's pending your dev testing.

Done — merged to `feat/v3.10-gm-workbench` via PR #221. The first **async** Workbench tool. `session_prep` (`sync_allowed=False`) runs on the #136 Celery path, assembling context from the upcoming session's **beat notes** + `recent_sessions_context` + `threads_context` + `lore_context`, and producing `{strong_start, scenes[], secrets_and_clues[], npcs[{name,note}], loose_ends[]}` (tolerant parser). `session_id` is a str/UUID param so it round-trips through `row.params` to the worker. - New polling primitive `GET /workbench/history/{result_id}` (GM-only). - Frontend `SessionPrepGenerator`: pick an upcoming session → generate (pending) → poll until ready/failed → render the sheet with NPCs linked to matching wiki entries → **append or replace** into `beat_notes` (existing PATCH) after explicit GM review. **Never auto-writes.** - `fetchWorkbenchResult` uses `cache: false` so the client's 15s GET dedup cache doesn't hide the `pending → ready` transition from the poller. All acceptance criteria met (async lifecycle visible via history/status; reads beat_notes + recent summaries + threads; explicit append-or-replace review; NPCs link to existing lore). No new models/migrations. Verified: backend 719 passed (incl. new `test_workbench_session_prep.py`), frontend 379 passed, ruff + eslint clean, build OK. **Not yet exercised against a live LLM on dev** — that's 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#158
No description provided.