Skip to content

feat: Quest & Objective Tracking (spec #29) #30

@Fortinbra

Description

@Fortinbra

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/quests command
  • DungeonMaster.Shared — quest DTOs

New interfaces in DungeonMaster.Core

  • IQuestService — CRUD and objective progress updates

Integration points with existing systems


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

  • Hidden
  • Active
  • Completed
  • Failed

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}/quests
  • POST /api/campaigns/{id}/quests — DM-only
  • PATCH /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

  1. Given a DM creates a quest with two objectives
    When the API returns
    Then the quest appears in /quests with both objectives

  2. Given a DM marks an objective complete
    When PATCH is called
    Then the objective is flagged as complete

Edge cases

  1. Given a quest is hidden
    When /quests is called by a player
    Then it is not returned

  2. Given all objectives are complete
    When CompleteQuestAsync runs
    Then quest status transitions to Completed

Error / failure cases

  1. Given an invalid objective ID
    When PATCH is called
    Then the API returns 404 Not Found

  2. Given a non-DM user attempts to create a quest
    When POST /quests is called
    Then the API returns 403 Forbidden


Acceptance Criteria

Functional

  • Quests can be created, updated, completed, or failed
  • Objectives track completion status
  • /quests command 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


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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestspecSpecification work

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions