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
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
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
-
Given a session with a populated event log
When the DM requests summary generation
Then an AI summary is stored and returned
-
Given a summary exists
When the DM edits and saves
Then the summary text updates with source = HumanEdited
Edge cases
-
Given the session already has a summary
When regenerate is called
Then a new summary replaces the old one
-
Given no summary exists
When GET /summary is called
Then the API returns 204 No Content
Error / failure cases
-
Given Ollama is down
When generation is requested
Then the API returns 502 Bad Gateway
-
Given a non-DM attempts to edit
When PUT /summary is called
Then the API returns 403 Forbidden
Acceptance Criteria
Functional
Non-functional
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
Feature Spec: Session Playback & Campaign Summaries
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
Architecture Notes (The Doctor)
Projects / layers touched
DungeonMaster.Core— summary entities + service interfacesDungeonMaster.Infrastructure— Ollama summary generator + persistenceDungeonMaster.Api— summary endpointsDungeonMaster.Web— summary editor pageDungeonMaster.Bot— summary post to DiscordNew interfaces in
DungeonMaster.CoreISessionSummaryService— generate, fetch, and edit summariesISessionSummaryRepository— persistence abstractionIntegration points with existing systems
Domain Model
Entities
SessionSummarySessionId(Guid FK)SummaryText(string, markdown)Source(SummarySource enum)CreatedAt(DateTimeOffset)UpdatedAt(DateTimeOffset?)Enums
SummarySourceAiGeneratedHumanEditedService Interfaces (CQRS)
API Contract (Rory)
Endpoints
POST /api/sessions/{id}/summary— generate (or regenerate) summaryGET /api/sessions/{id}/summary— fetch summaryPUT /api/sessions/{id}/summary— DM editUI Specification (Clara)
Page / component breakdown
/sessions/{id}/summary) — view/edit summaryBlazor component list
SessionSummaryPagePages/Sessions/SessionSummaryPage.razor/.razor.csSummaryEditorComponents/Summaries/SummaryEditor.razor/.razor.csSummaryHistoryPanelComponents/Summaries/SummaryHistoryPanel.razor/.razor.csTheme / styling requirements
var(--color-surface)for editor backgroundvar(--spacing-md)for editor paddingvar(--color-primary)for save buttonNLP / AI Behaviour (Missy)
Trigger
Summary generation when
POST /api/sessions/{id}/summaryis called.Context sent to Ollama
Expected behaviour
Edge cases in AI behaviour
Test Scenarios (Danny)⚠️ COMPLETE BEFORE IMPLEMENTATION
Happy path
Given a session with a populated event log
When the DM requests summary generation
Then an AI summary is stored and returned
Given a summary exists
When the DM edits and saves
Then the summary text updates with source = HumanEdited
Edge cases
Given the session already has a summary
When regenerate is called
Then a new summary replaces the old one
Given no summary exists
When GET
/summaryis calledThen the API returns
204 No ContentError / failure cases
Given Ollama is down
When generation is requested
Then the API returns
502 Bad GatewayGiven a non-DM attempts to edit
When PUT
/summaryis calledThen the API returns
403 ForbiddenAcceptance Criteria
Functional
Non-functional
Dependencies
Agent Work Breakdown
Definition of Done