You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Defines the core Discord slash commands players use to drive gameplay (/adventure, /action, /look, /inventory, /status). Commands are thin handlers that delegate to Core services, which build narrative context and call INarrativeEngine (spec #13). The Dungeon Master (Human) retains approval/override authority via existing /dm commands and a session-level autopilot toggle.
Why it's needed
Players need a consistent, low-friction way to interact with the story. This spec establishes a standard command surface, persistent session context per campaign, and the narrative flow from player command → AI proposal → Human DM approval → Discord response.
Active session summary (last N narrative log entries)
Player character list (name, class, HP)
Active encounter summary (if any)
Last N PlayerCommand entries (most recent actions)
Expected behaviour
Tone: immersive fantasy, second person where appropriate
Max length: 2–4 short paragraphs
Output must be a proposal unless AutopilotEnabled = true
Must not reveal hidden DM notes or NPC secrets unless the DM already revealed them
Edge cases in AI behaviour
No active session: return a human-readable error and do not call Ollama
Empty context: default to a short scene-setting prompt
Autopilot off: always set RequiresHumanReview = true
Test Scenarios (Danny)⚠️ COMPLETE BEFORE IMPLEMENTATION
Happy path
Given an active session in a campaign When a player runs /look Then the bot calls INarrativeEngine.GenerateLocationDescriptionAsync and posts the approved narrative
Given autopilot is enabled for the session When a player runs /action Then the narrative response is posted immediately without DM approval
Edge cases
Given no active session for the campaign When a player runs /adventure Then the bot returns an error message and no AI call occurs
Given an active encounter When a player runs /status Then the response includes encounter status and current round/turn summary
Error / failure cases
Given an unauthenticated DM tries /dm autopilot on When the bot checks authorization Then the command is rejected with an ephemeral error
GivenINarrativeEngine is unavailable When a player runs /action Then the bot returns a friendly error and logs the failure
Acceptance Criteria
Functional
Slash commands /adventure, /action, /look, /inventory, /status are registered via Discord.Net interactions
Command handlers are thin and delegate to Core services
Narrative output flows through INarrativeEngine with Human DM approval gating
Session context is persisted per campaign with an autopilot flag
/dm autopilot toggles session auto-approval
Player commands are logged for audit and summary generation
Non-functional
Commands respond within 2 seconds under normal load
All Discord IDs are stored as bigint with ulong conversion
Feature Spec: Discord Gameplay Commands & Narrative Flow
Overview
What it does
Defines the core Discord slash commands players use to drive gameplay (
/adventure,/action,/look,/inventory,/status). Commands are thin handlers that delegate to Core services, which build narrative context and callINarrativeEngine(spec #13). The Dungeon Master (Human) retains approval/override authority via existing/dmcommands and a session-level autopilot toggle.Why it's needed
Players need a consistent, low-friction way to interact with the story. This spec establishes a standard command surface, persistent session context per campaign, and the narrative flow from player command → AI proposal → Human DM approval → Discord response.
Out of scope
Architecture Notes (The Doctor)
Projects / layers touched
DungeonMaster.Bot— Discord.Net interaction modules for gameplay commandsDungeonMaster.Core— session context, gameplay command orchestration, domain modelsDungeonMaster.Infrastructure— repositories for sessions/command logDungeonMaster.Api— session status endpoints for DM toolingDungeonMaster.Shared— DTOs for session status and command resultsNew interfaces in
DungeonMaster.CoreIGameplaySessionService— lifecycle + context access for active sessionsIGameplayCommandService— executes/adventure,/action,/look,/inventory,/statusISessionRepository— persistence for session stateIPlayerCommandRepository— append-only command log (for audit + replay)Data flow
Integration points with existing systems
INarrativeEngineIAiActionDispatcherproposals/statusreports active encounter status/inventoryreads from CharacterInventory when availableDomain Model
BaseEntity
All entities inherit
BaseEntitywithId,CreatedAt, andUpdatedAt.Entities
CampaignSessionCampaignId(Guid, required)DiscordChannelId(ulong, required)Status(SessionStatus enum)StartedAt(DateTimeOffset, required)EndedAt(DateTimeOffset?, optional)AutopilotEnabled(bool, default false)ActiveEncounterId(Guid?, optional)LastNarrativeLogId(Guid?, optional)SessionParticipantSessionId(Guid FK)PlayerCharacterId(Guid FK)DiscordUserId(ulong)IsDungeonMaster(bool)PlayerCommandSessionId(Guid FK)PlayerCharacterId(Guid FK)CommandType(GameplayCommandType enum)RawText(string, optional)IssuedAt(DateTimeOffset)Enums
SessionStatusActivePausedCompletedGameplayCommandTypeAdventureActionLookInventoryStatusRecords
Service Interfaces (CQRS)
API Contract (Rory)
Endpoints
POST /api/campaigns/{id}/sessionsCampaignSessionsnapshot404 Not Found(campaign),409 Conflict(session already active)GET /api/campaigns/{id}/sessions/activeCampaignSessionsnapshot or204 No ContentPUT /api/sessions/{id}/status{ "newStatus": "Active | Paused | Completed" }PUT /api/sessions/{id}/autopilot{ "enabled": true }Discord Commands (Rory — Bot Layer)
Player commands
/adventure— advances the story (NarrativeType.SceneDescription)/action {text}— player declares action; AI proposes response/look— describes current location or encounter/inventory— shows character loadout (from spec feat: Session Playback & Campaign Summaries (spec #26) #27 when available)/status— shows session state, active encounter, and last narrative timestampDM commands
/dm autopilot on|off— toggles session autopilot (mirrors API)NLP / AI Behaviour (Missy)
Trigger
Any
/adventure,/action, or/lookcommand with an active session.Context sent to Ollama
Expected behaviour
AutopilotEnabled = trueEdge cases in AI behaviour
RequiresHumanReview = trueTest Scenarios (Danny)⚠️ COMPLETE BEFORE IMPLEMENTATION
Happy path
Given an active session in a campaign
When a player runs
/lookThen the bot calls
INarrativeEngine.GenerateLocationDescriptionAsyncand posts the approved narrativeGiven autopilot is enabled for the session
When a player runs
/actionThen the narrative response is posted immediately without DM approval
Edge cases
Given no active session for the campaign
When a player runs
/adventureThen the bot returns an error message and no AI call occurs
Given an active encounter
When a player runs
/statusThen the response includes encounter status and current round/turn summary
Error / failure cases
Given an unauthenticated DM tries
/dm autopilot onWhen the bot checks authorization
Then the command is rejected with an ephemeral error
Given
INarrativeEngineis unavailableWhen a player runs
/actionThen the bot returns a friendly error and logs the failure
Acceptance Criteria
Functional
/adventure,/action,/look,/inventory,/statusare registered via Discord.Net interactionsINarrativeEnginewith Human DM approval gating/dm autopilottoggles session auto-approvalNon-functional
bigintwithulongconversionDungeonMaster.CoreDependencies
Agent Work Breakdown
Definition of Done
CampaignSessionpersisted with clear state transitions