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
- Prerequisite chain —
isAvailable()checks full prerequisite DAG using DFS. - Auto-chain — on completion, if
chainNextIdis set and prerequisites met, quest log auto-starts next quest. - Time limit —
tick()checks elapsed time; exceeds limit → marks quest failed, firesquest:failed. - OTel —
quest.completions_totalcounter;quest.active_countgauge.
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.