-
Notifications
You must be signed in to change notification settings - Fork 0
feat: Quest & Objective Tracking (spec #29) #30
Description
Feature Spec: Quest & Objective Tracking
| Field | Value |
|---|---|
| Feature | Quest & Objective Tracking |
| Issue | #TBD |
| Status | Draft |
| Author | The Doctor |
| Date | 2026-04-10 |
Overview
What it does
Introduces a quest system with objectives, progress tracking, and DM controls. Quests are tied to campaigns, expose active objectives to players via Discord, and integrate with the AI Action System for proposed objective completion.
Why it's needed
Quests provide narrative structure and player motivation. Objective tracking ensures the campaign has clear progress markers and supports automated session summaries.
Out of scope
- Branching quest chains with complex prerequisites
- Auto-generated quests from AI
- Cross-campaign quests
Architecture Notes (The Doctor)
Projects / layers touched
-
DungeonMaster.Core— quest entities + services -
DungeonMaster.Infrastructure— EF Core mappings + migrations -
DungeonMaster.Api— quest endpoints -
DungeonMaster.Web— quest UI -
DungeonMaster.Bot—/questscommand -
DungeonMaster.Shared— quest DTOs
New interfaces in DungeonMaster.Core
IQuestService— CRUD and objective progress updates
Integration points with existing systems
- Spec [SPEC] Narrative Engine (Ollama Integration) #13 (Narrative Engine): active quests included in narrative context
- Spec Spec #15: AI Action System #15 (AI Action System):
CompleteObjectiveActionproposals - Spec Audit: Specs #21–#29 Compliance + Next Directions #21 (Discord Commands):
/questscommand for players
Domain Model
Entities
Quest
CampaignId(Guid FK)Title(string)Description(string, markdown)Status(QuestStatus enum)Objectives(ICollection)
QuestObjective
QuestId(Guid FK)Description(string)IsComplete(bool)SortOrder(int)
Enums
QuestStatus
HiddenActiveCompletedFailed
Records
public sealed record QuestSummary(Guid Id, string Title, QuestStatus Status, IReadOnlyList<QuestObjectiveSummary> Objectives);Service Interfaces (CQRS)
public interface IQuestService
{
Task<Quest> CreateQuestAsync(Guid campaignId, Quest quest, CancellationToken ct = default);
Task<Quest?> GetQuestAsync(Guid questId, CancellationToken ct = default);
Task<IReadOnlyList<QuestSummary>> GetActiveQuestsAsync(Guid campaignId, CancellationToken ct = default);
Task UpdateObjectiveAsync(Guid questId, Guid objectiveId, bool isComplete, CancellationToken ct = default);
Task CompleteQuestAsync(Guid questId, CancellationToken ct = default);
Task FailQuestAsync(Guid questId, CancellationToken ct = default);
}API Contract (Rory)
Endpoints
GET /api/campaigns/{id}/questsPOST /api/campaigns/{id}/quests— DM-onlyPATCH /api/campaigns/{id}/quests/{questId}PATCH /api/campaigns/{id}/quests/{questId}/objectives/{objectiveId}
UI Specification (Clara)
Page / component breakdown
- QuestLog (
/campaigns/{id}/quests) — DM and player view
Blazor component list
| Component | File | Purpose |
|---|---|---|
QuestLog |
Pages/Quests/QuestLog.razor / .razor.cs |
Active/completed quest tabs |
QuestEditor |
Components/Quests/QuestEditor.razor / .razor.cs |
DM quest creation/edit |
ObjectiveList |
Components/Quests/ObjectiveList.razor / .razor.cs |
Objective checklist |
Theme / styling requirements
- Use
var(--color-success)for completed objectives - Use
var(--color-warning)for active quest badges - Use
var(--spacing-md)for quest cards
Discord Commands (Rory — Bot Layer)
/quests— displays active quests and objectives/objective complete {questId} {objectiveId}— DM-only manual completion
NLP / AI Behaviour (Missy)
Trigger
Any narrative generation when active quests exist or when CompleteObjectiveAction is proposed.
Context sent to Ollama
- Active quests and objective lists
- Recent quest-related events
Expected behaviour
- AI may propose objective completion but must not mark it complete without DM approval
- Must reference quest titles verbatim (no renaming)
Test Scenarios (Danny) ⚠️ COMPLETE BEFORE IMPLEMENTATION
Happy path
-
Given a DM creates a quest with two objectives
When the API returns
Then the quest appears in/questswith both objectives -
Given a DM marks an objective complete
When PATCH is called
Then the objective is flagged as complete
Edge cases
-
Given a quest is hidden
When/questsis called by a player
Then it is not returned -
Given all objectives are complete
When CompleteQuestAsync runs
Then quest status transitions to Completed
Error / failure cases
-
Given an invalid objective ID
When PATCH is called
Then the API returns404 Not Found -
Given a non-DM user attempts to create a quest
When POST/questsis called
Then the API returns403 Forbidden
Acceptance Criteria
Functional
- Quests can be created, updated, completed, or failed
- Objectives track completion status
-
/questscommand shows active quests - AI action proposals require DM approval
Non-functional
- Quest queries respond within 300 ms
- UI uses code-behind pattern and CSS custom properties only
- All quest text stored as markdown
Dependencies
- Spec [SPEC] Narrative Engine (Ollama Integration) #13: Narrative Engine
- Spec Spec #15: AI Action System #15: AI Action System
- Spec Audit: Specs #21–#29 Compliance + Next Directions #21: Discord Gameplay Commands
Agent Work Breakdown
| Agent | Task | Depends On |
|---|---|---|
| The Doctor | Approve spec | — |
| Danny | Write failing tests from Test Scenarios | Spec approved |
| Rory | Implement quest entities + services | Danny's tests |
| Clara | Implement quest 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
- EF Core migration created for quest tables
- GitHub issue closed and linked to merged PR