Files
suaveplan/openspec/changes/enterprise-gaming-quest/proposal.md
2026-05-27 23:29:53 +01:00

4.8 KiB

OpenSpec Change: enterprise-gaming-quest

  • Change ID: enterprise-gaming-quest
  • Package: @suaveplan/quest
  • Category: gaming/narrative
  • Target path: gaming/narrative/quest
  • Status: PROPOSED
  • Date: 2026-04-24
  • Reference spec: /mnt/s/web/suaveplan/enterprise/quest.md

Summary

Deliver @suaveplan/quest on the genesis branch from scratch at enterprise quality. The package provides a quest/mission system with multi-objective tracking, quest chains, rewards, and event-driven triggers. A QuestDefinition describes objectives (kill, collect, reach, talk, craft), prerequisites, and rewards; a QuestLog per player tracks active/completed quests with objective progress; a QuestEventHandler listens for game events and advances objectives automatically. Genesis adds Zod definition schemas, structured errors, OTel quest-completion counter, injectable clock, and 100% coverage.


Current-state audit (genesis)

Package does not exist on genesis yet — fresh build.


Available workspace deps on genesis

Package Role
@suaveplan/error (workspace:^) QuestError; QUEST.* codes
@suaveplan/types (workspace:^) Clock, IdGenerator
@suaveplan/events (workspace:^) Quest lifecycle events + game-event listener
zod (catalog:forms) QuestDefinition schema
@opentelemetry/api (catalog:observability) Quest completion counter

Public API surface

type ObjectiveType = 'kill' | 'collect' | 'reach' | 'talk' | 'craft' | 'custom'

interface ObjectiveDefinition {
  id: string
  type: ObjectiveType
  description: string
  targetId?: string       // NPC/item/location id
  required: number        // quantity or count
  optional?: boolean
}

interface RewardDefinition {
  xp?: number
  gold?: number
  items?: { itemId: string; quantity: number }[]
  unlocksQuestId?: string
}

interface QuestDefinition {
  id: string
  title: string
  description: string
  objectives: ObjectiveDefinition[]
  rewards: RewardDefinition
  prerequisites?: string[]   // quest IDs that must be completed
  chainNextId?: string       // auto-starts after completion
  timeLimit?: number         // seconds; undefined = no limit
}

function createQuestRegistry(): QuestRegistry
interface QuestRegistry {
  register(def: QuestDefinition): void
  get(id: string): QuestDefinition | undefined
}

function createQuestLog(playerId: string, registry: QuestRegistry, options?: QuestLogOptions): QuestLog

interface QuestLog {
  startQuest(questId: string): void
  abandonQuest(questId: string): void
  advanceObjective(questId: string, objectiveId: string, amount?: number): void
  isComplete(questId: string): boolean
  isAvailable(questId: string): boolean
  getActive(): QuestInstance[]
  getCompleted(): QuestInstance[]
  tick(dt: number): void   // for time-limit tracking
}

interface QuestInstance {
  readonly questId: string
  readonly progress: Map<string, number>
  readonly startedAt: number
  readonly isComplete: boolean
  readonly isFailed: boolean
}

// Event-driven advancement
function createQuestEventHandler(log: QuestLog, mapping: QuestEventMapping): QuestEventHandler

type QuestEventMapping = Map<string, { questId: string; objectiveId: string; amount?: number }[]>

interface QuestEventHandler {
  onEvent(eventName: string, payload?: unknown): void
}

Error codes

type QuestErrorCode =
  | 'QUEST_NOT_FOUND'
  | 'QUEST_ALREADY_ACTIVE'
  | 'QUEST_PREREQUISITES_NOT_MET'
  | 'QUEST_OBJECTIVE_NOT_FOUND'
  | 'QUEST_ALREADY_COMPLETED'
  | 'QUEST_TIMED_OUT'

New additions for genesis

  1. Prerequisite chain — isAvailable() checks full prerequisite DAG using DFS.
  2. Auto-chain — on completion, if chainNextId is set and prerequisites met, quest log auto-starts next quest.
  3. Time limit — tick() checks elapsed time; exceeds limit → marks quest failed, fires quest:failed.
  4. OTel — quest.completions_total counter; quest.active_count gauge.

File layout

gaming/narrative/quest/
  package.json
  tsconfig.json
  vitest.config.ts
  src/
    index.ts
    error-codes.ts
    constants/index.ts
    types/common.ts
    types/common.md
    core/
      quest-registry/
        quest-registry.ts
        quest-registry.md
        quest-registry.test.ts
        index.ts
      quest-log/
        quest-log.ts
        quest-log.md
        quest-log.types.ts
        quest-log.test.ts
        index.ts
      event-handler/
        event-handler.ts
        event-handler.md
        event-handler.types.ts
        event-handler.test.ts
        index.ts
  tests/
    integration.test.ts

Impact

Downstream: @suaveplan/progression listens for quest:completed events to award XP. Prerequisites: @suaveplan/error, @suaveplan/types, @suaveplan/events.