Skip to content

feat: Session Playback & Campaign Summaries (spec #26) #27

@Fortinbra

Description

@Fortinbra

Feature Spec: Session Playback & Campaign Summaries

Field Value
Feature Session Playback & Campaign Summaries
Issue #TBD
Status Draft
Author The Doctor
Date 2026-04-10

Overview

What it does

Generates human-readable summaries of completed sessions using Ollama. Summaries are stored in the database, can be edited by the Human DM, and are optionally posted to Discord. A Blazor page allows viewing, editing, and regenerating summaries.

Why it's needed

Session recaps help players remember plot points, outcomes, and rewards. Automating the initial summary reduces DM workload while preserving human editing control.

Out of scope

  • Audio summaries or voice narration
  • Automatic scheduling of summaries
  • Multi-language translation

Architecture Notes (The Doctor)

Projects / layers touched

  • DungeonMaster.Core — summary entities + service interfaces
  • DungeonMaster.Infrastructure — Ollama summary generator + persistence
  • DungeonMaster.Api — summary endpoints
  • DungeonMaster.Web — summary editor page
  • DungeonMaster.Bot — summary post to Discord

New interfaces in DungeonMaster.Core

  • ISessionSummaryService — generate, fetch, and edit summaries
  • ISessionSummaryRepository — persistence abstraction

Integration points with existing systems


Domain Model

Entities

SessionSummary

  • SessionId (Guid FK)
  • SummaryText (string, markdown)
  • Source (SummarySource enum)
  • CreatedAt (DateTimeOffset)
  • UpdatedAt (DateTimeOffset?)

Enums

SummarySource

  • AiGenerated
  • HumanEdited

Service Interfaces (CQRS)

public interface ISessionSummaryService
{
    Task<SessionSummary> GenerateAsync(Guid sessionId, CancellationToken ct = default);
    Task<SessionSummary?> GetAsync(Guid sessionId, CancellationToken ct = default);
    Task<SessionSummary> UpdateAsync(Guid sessionId, string summaryText, CancellationToken ct = default);
    Task<SessionSummary> RegenerateAsync(Guid sessionId, CancellationToken ct = default);
}

API Contract (Rory)

Endpoints

  • POST /api/sessions/{id}/summary — generate (or regenerate) summary
  • GET /api/sessions/{id}/summary — fetch summary
  • PUT /api/sessions/{id}/summary — DM edit

UI Specification (Clara)

Page / component breakdown

  • SessionSummaryPage (/sessions/{id}/summary) — view/edit summary

Blazor component list

Component File Purpose
SessionSummaryPage Pages/Sessions/SessionSummaryPage.razor / .razor.cs Summary view/edit
SummaryEditor Components/Summaries/SummaryEditor.razor / .razor.cs Markdown editor with save
SummaryHistoryPanel Components/Summaries/SummaryHistoryPanel.razor / .razor.cs Shows generated timestamp/source

Theme / styling requirements

  • Use var(--color-surface) for editor background
  • Use var(--spacing-md) for editor padding
  • Use var(--color-primary) for save button

NLP / AI Behaviour (Missy)

Trigger

Summary generation when POST /api/sessions/{id}/summary is called.

Context sent to Ollama

Expected behaviour

  • Output markdown with headings: Overview, Key Events, Loot & XP
  • Tone: neutral, recap style (not second-person)
  • Max length: 500–800 words

Edge cases in AI behaviour

  • Empty event log: return a short "Session had no recorded events"
  • Ollama unavailable: return 502 and preserve existing summary

Test Scenarios (Danny) ⚠️ COMPLETE BEFORE IMPLEMENTATION

Happy path

  1. Given a session with a populated event log
    When the DM requests summary generation
    Then an AI summary is stored and returned

  2. Given a summary exists
    When the DM edits and saves
    Then the summary text updates with source = HumanEdited

Edge cases

  1. Given the session already has a summary
    When regenerate is called
    Then a new summary replaces the old one

  2. Given no summary exists
    When GET /summary is called
    Then the API returns 204 No Content

Error / failure cases

  1. Given Ollama is down
    When generation is requested
    Then the API returns 502 Bad Gateway

  2. Given a non-DM attempts to edit
    When PUT /summary is called
    Then the API returns 403 Forbidden


Acceptance Criteria

Functional

  • Summaries are generated from session event logs
  • Summaries can be edited by the Human DM
  • Summaries can be posted to Discord
  • API supports generate, fetch, and update operations

Non-functional

  • Summary generation completes within 10 seconds for 5k events
  • All summaries stored as markdown
  • UI uses CSS custom properties only

Dependencies


Agent Work Breakdown

Agent Task Depends On
The Doctor Approve spec
Danny Write failing tests from Test Scenarios Spec approved
Rory Implement summary services + API endpoints Danny's tests
Clara Implement summary UI Rory's API
Danny Confirm all tests pass All implementation

Definition of Done

  • Test Scenarios section completed and approved by The Doctor before implementation
  • All failing tests written by Danny before implementation (TDD)
  • All tests written and passing (xUnit + bUnit)
  • Code reviewed and approved by The Doctor
  • Summaries stored as markdown with source tracking
  • GitHub issue closed and linked to merged PR

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestspecSpecification work

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions