neon-sprawl/docs/plans/E7M1-prototype-backlog.md

19 KiB
Raw Blame History

E7.M1 — Prototype story backlog (QuestStateMachine)

Working backlog for Epic 7 — Slice 1 (quest core and persistence). Decomposition and contracts: E7.M1 — QuestStateMachine.

Full-stack policy: Epics deliver playable game features. Every player-visible story has a client Linear issue created in this same decomposition pass — not an undocumented follow-up. Reference: E5M3 (paired server+client).

Labels (Linear): every issue E7.M1; add server or client + Story as listed.

Precursor (do not re-scope): E5.M3 encounter complete grants contract_handoff_token + records EncounterCompleteEvent (NEO-107) — prototype quest credit stand-in until E7.M2 QuestRewardBundle router lands. NEO-43 MissionRewardSkillXpGrant is the future skill-XP apply helper for E7.M2; E7.M1 tracks quest state only (no duplicate item grants on quest complete in Slice 1).

Upstream (must be landed): E3.M1 gather on interact (NEO-63); E3.M2 craft POST (NEO-70); E5.M3 encounter wiring + progress GET (NEO-106, NEO-108). E3S5 client economy HUD (NEO-72NEO-75).

Prototype quest spine (frozen in E7M1-01): three solo onboarding quests + one multi-step chain quest (vision minimum 35 onboarding + one integrated chain). Solo only — no party credit (quest_scope_and_party.md).

Linear issues (created): attach docs/plans/NEO-*-implementation-plan.md on the story branch when work starts.

Slug Layer Linear
E7M1-01 server NEO-112
E7M1-02 server NEO-113
E7M1-03 server NEO-114
E7M1-04 server NEO-115
E7M1-05 server NEO-116
E7M1-06 server NEO-117
E7M1-07 server NEO-118
E7M1-08 server NEO-119
E7M1-09 server NEO-120
E7M1-10 server NEO-121
E7M1-11 client NEO-122
E7M1-12 client NEO-123

Dependency graph in Linear: E7M1-02 blocked by E7M1-01. E7M1-03 blocked by E7M1-02. E7M1-04 blocked by E7M1-03. E7M1-05 blocked by E7M1-03. E7M1-06 blocked by E7M1-05. E7M1-07 blocked by E7M1-06. E7M1-08 blocked by E7M1-07. E7M1-09 blocked by E7M1-06 (may parallel E7M1-08). E7M1-10 blocked by E7M1-07. E7M1-11 blocked by E7M1-08 and E7M1-09. E7M1-12 blocked by E7M1-11.

Board order: estimates 112 matching slug order (E7M1-01 = 1 … E7M1-12 = 12). On the Epic 7 project board, sort by Estimate (ascending).


Story order (recommended)

Order Slug Layer Depends on
1 E7M1-01 server E3.M1/E3.M2/E5.M3 content ids frozen
2 E7M1-02 server E7M1-01
3 E7M1-03 server E7M1-02
4 E7M1-04 server E7M1-03
5 E7M1-05 server E7M1-03
6 E7M1-06 server E7M1-05
7 E7M1-07 server E7M1-06
8 E7M1-08 server E7M1-07
9 E7M1-09 server E7M1-06
10 E7M1-10 server E7M1-07
11 E7M1-11 client E7M1-08, E7M1-09
12 E7M1-12 client E7M1-11

Downstream (separate modules): E7.M2 idempotent QuestRewardBundle apply + consume EncounterCompleteEvent; E7.M3 faction ledger (pre-production); E8.M1 party-credit quests.


Kickoff decisions (decomposition defaults)

Topic Decision Rationale
Quest count 3 onboarding + 1 multi-step chain (4 total) Vision prototype minimum; readable manual QA
Party mode Solo only quest_scope_and_party.md; E8.M1 not landed
Accept flow POST …/quests/{questId}/accept Explicit start; boot does not auto-grant all quests
Objective advance Server hooks on gather/craft/encounter success Client displays GET snapshot only (client_server_authority.md)
Objective kinds (v1) gather_item, craft_recipe, encounter_complete, inventory_has_item Covers gather→craft→combat chain without custom scripting VM
Chain quest 4 sequential steps in one QuestDef Single HUD row with step index; epic “integrated chain”
Prerequisites prerequisiteQuestIds enforced on accept Gather and combat intros parallel (no prereq); refine requires gather intro; chain requires all three intros
Rewards (Slice 1) State-only completion; no duplicate item/XP grants Loot stays on gather/craft/encounter paths; E7.M2 owns bundles
Token handoff Chain final step inventory_has_item contract_handoff_token Uses E5.M3 encounter loot; no consume mutation in Slice 1
Idempotency Once per player per quest id complete Slice 1 AC: no duped quest completion
Store In-memory IPlayerQuestStateStore (+ optional Postgres migration) Matches encounter prototype stores
HTTP read GET /game/players/{id}/quest-progress Client HUD without local objective math
HUD fidelity Prototype Labels / debug panels (not final art) NEO-110 / NEO-122 precedent

E7M1-01 — Prototype QuestDef catalog + schemas + CI

Goal: Lock content shape and CI validation for four frozen quests before server load.

In scope

  • content/schemas/quest-def.schema.json, content/schemas/quest-step-def.schema.json, content/schemas/quest-objective-def.schema.json.
  • content/quests/prototype_quests.json — stable quest ids and step/objective graph (see module doc freeze table).
  • scripts/validate_content.py: schema validation, duplicate ids, exact four-quest allowlist, cross-ref itemId / recipeId / encounterId to frozen catalogs, prerequisiteQuestIds acyclic + known ids, objective kind enum.
  • Designer note in E7_M1 + content/README.md.

Out of scope

  • Server loader, runtime engine, HTTP, Godot.

Acceptance criteria

  • PR gate validates quest JSON against schema.
  • Exactly four prototype quest ids; duplicate id fails CI.
  • Every objective reference resolves to a frozen catalog id.
  • Stable id list documented in module doc freeze box.

Client counterpart: none (infrastructure-only).


E7M1-02 — Server quest catalog load (fail-fast)

Goal: Disk → host: startup load of content/quests/*.json with CI-parity validation.

In scope

  • Loader + catalog types under server/NeonSprawl.Server/Game/Quests/ (path finalized in plan).
  • Fail-fast on malformed files, duplicate ids, allowlist mismatch with CI, broken cross-refs (items, recipes, encounters).
  • Unit tests (AAA) for loader happy path and failure modes.
  • server/README.md section.

Out of scope

  • Injectable registry interface (E7M1-03), HTTP projection, runtime state machine.

Acceptance criteria

  • Host fails startup on invalid quest JSON (mirror CI rules).
  • Loader tests cover allowlist + cross-ref failures.

Client counterpart: none (infrastructure-only).


E7M1-03 — Injectable quest definition registry + DI

Goal: IQuestDefinitionRegistry with TryGet, startup registration from E7M1-02 catalog.

In scope

  • Interface + in-memory implementation; AddQuestDefinitionRegistry DI extension.
  • Unit tests: lookup known ids, unknown id returns false.
  • Wire in host startup alongside other content registries.

Out of scope

  • HTTP, player quest state.

Acceptance criteria

  • Registry resolves all four frozen quest ids at runtime.
  • Unknown quest id fails closed for downstream operations.

Client counterpart: none (infrastructure-only).


E7M1-04 — GET /game/world/quest-definitions

Goal: Versioned read-only projection of frozen quest defs for client display names and step summaries.

In scope

  • QuestDefinitionsWorldApi + DTOs in Game/Quests/.
  • Nested steps/objectives summary (ids, kinds, display copy — no server secrets).
  • Bruno folder bruno/neon-sprawl-server/quest-definitions/.
  • Integration tests (AAA).

Out of scope

  • Per-player progress (E7M1-08).

Acceptance criteria

  • GET returns all four prototype quests with stable JSON v1 envelope.
  • Bruno request documents example response shape.

Client counterpart: consumed by NEO-122 for display names (optional cache).


E7M1-05 — Player quest state store + QuestStepState persistence

Goal: Durable per-player quest rows: status (not_started / active / completed), current step index, per-step objective counters.

In scope

  • IPlayerQuestStateStore + in-memory implementation (registered in quest DI extension).
  • Optional Postgres migration V00X when DB configured (mirror encounter/inventory pattern).
  • QuestStepState / PlayerQuestProgressRow types aligned with module contracts.
  • Unit tests: accept transitions, idempotent complete mark.

Out of scope

  • Objective evaluation (E7M1-06), HTTP.

Acceptance criteria

  • Store supports read/update per (playerId, questId).
  • Completed quest cannot regress to active without explicit reset API (none in prototype).

Client counterpart: none (infrastructure-only).


E7M1-06 — QuestStateOperations (accept, step advance, complete)

Goal: Server-authoritative quest lifecycle without objective wiring yet.

In scope

  • QuestStateOperations.TryAccept, TryAdvanceStep, TryMarkComplete with structured reasonCode denials (unknown_quest, prerequisite_incomplete, already_completed, already_active).
  • Prerequisite enforcement from prerequisiteQuestIds.
  • Idempotent complete: second complete returns success without state change.
  • Unit tests (AAA) for accept order, prerequisite gate, idempotent complete.

Out of scope

  • Gather/craft/encounter hooks (E7M1-07); HTTP (E7M1-08/09).

Acceptance criteria

  • Accept fails when prerequisite quest not completed.
  • Complete is idempotent per player+quest.
  • Reason codes documented in server/README.md.

Client counterpart: NEO-120 exposes accept POST to Godot.


E7M1-07 — Quest objective wiring (gather, craft, encounter)

Goal: Advance active quest steps when server-side gather, craft, and encounter events succeed.

In scope

  • QuestObjectiveWiring (or equivalent) invoked from:
    • GatherOperations.TryGather success path — gather_item objectives.
    • CraftOperations.TryCraft success path — craft_recipe objectives.
    • EncounterCompletionOperations.TryCompleteAndGrant success path — encounter_complete objectives.
    • Inventory snapshot read for inventory_has_item (post-grant or on polling hook from accept).
  • Counter accumulation for quantity objectives (e.g. gather 3 scrap).
  • Auto TryAdvanceStep / TryMarkComplete when step objectives satisfied.
  • Integration tests: accept quest → simulate gather/craft/encounter → progress row advances.

Out of scope

  • Client-side objective tracking; item consume on turn-in; E7.M2 reward bundles.

Acceptance criteria

  • Active prototype_quest_gather_intro advances when scrap_metal_bulk gather succeeds.
  • Active prototype_quest_refine_intro advances on refine_scrap_standard craft success.
  • Active prototype_quest_combat_intro advances when prototype_combat_pocket completes.
  • Chain quest steps advance in order across mixed objective kinds.

Client counterpart: progress visible via NEO-122 GET HUD after mutations.


E7M1-08 — GET /game/players/{id}/quest-progress

Goal: Per-player quest progress snapshot for client HUD.

In scope

  • QuestProgressApi + DTOs: all known quests with status, current step index, objective progress counters, completion timestamp when applicable.
  • Known-player gate (mirror encounter-progress / skill-progression patterns).
  • Bruno bruno/neon-sprawl-server/quest-progress/.
  • Integration tests (AAA): accept → partial progress → complete rows.

Out of scope

  • Quest definition catalog (E7M1-04).

Acceptance criteria

  • GET returns stable v1 envelope for dev-local-1 player.
  • Completed quests show completed with step count at terminal step.

Client counterpart: NEO-122quest_progress_client.gd + HUD labels.


E7M1-09 — POST /game/players/{id}/quests/{questId}/accept

Goal: Player-initiated quest accept from Godot (prototype “quest giver” is HUD button or key binding).

In scope

  • QuestAcceptApi: POST accept; JSON body optional v1 {}; response includes updated progress row or deny payload.
  • Wire QuestStateOperations.TryAccept.
  • Bruno + integration tests: happy accept, prerequisite deny, duplicate accept.

Out of scope

  • Abandon/reset POST (defer unless capstone QA requires).

Acceptance criteria

  • Successful accept transitions row not_startedactive.
  • Deny returns structured reasonCode without mutation.

Client counterpart: NEO-122 — accept binding + feedback label.


E7M1-10 — Quest telemetry hook sites (comment-only)

Goal: Document and place comment-only hook sites for future E9.M1 catalog events quest_start, quest_step_complete, quest_complete.

In scope

  • Hook sites in QuestStateOperations / QuestObjectiveWiring at accept, step advance, and complete.
  • Reserved deny hook quest_accept_denied (optional comment).
  • server/README.md subsection; module doc note.

Out of scope

  • E9.M1 ingest pipeline; runtime telemetry emit.

Acceptance criteria

  • Hook sites exist at accept, step complete, quest complete paths.
  • Epic 7 Slice 1 telemetry vocabulary documented.

Client counterpart: none (infrastructure-only).


E7M1-11 — Client quest progress + accept HUD (Godot)

Goal: Godot GET …/quest-progress client + readable quest panel; accept via POST …/accept.

In scope

  • quest_progress_client.gd, optional quest_definitions_client.gd for display names.
  • HUD: QuestProgressLabel (active/completed summary), QuestAcceptFeedbackLabel (deny/success copy).
  • Boot hydrate + refresh after gather/craft/cast/encounter events (mirror encounter_progress_client.gd pattern).
  • Prototype accept bindings: e.g. keys Q / Shift+Q for next eligible quest accept (document in manual QA).
  • GdUnit: HTTP double, parse happy path + deny path.
  • client/README.md section.
  • docs/manual-qa/NEO-122.md.

Out of scope

  • Quest journal art, map pins, NPC dialog; final quest picker UI.

Acceptance criteria

  • Player sees quest status change after accept without Bruno.
  • Objective progress updates after gather/craft/encounter in Godot session.
  • Failed GET/accept surfaces visible HUD error (match interaction client pattern).

Client counterpart: this story is the client counterpart for E7M1-08/09.


E7M1-12 — Playable onboarding quest chain capstone (Godot)

Goal: Prove Epic 7 Slice 1 acceptance in Godot: complete all four prototype quests (gather → refine → combat → operator chain) without Bruno; satisfies vision quest loop gate.

In scope

  • docs/manual-qa/NEO-123.md: numbered single-session capstone — fresh server restart, accept onboarding quests in order, perform gather/craft/combat actions, verify chain quest prototype_quest_operator_chain completes when contract_handoff_token held.
  • client/README.md: End-to-end onboarding quest loop section — flow table; cross-links NEO-112NEO-122.
  • Module alignment on completion: E7_M1, documentation_and_implementation_alignment.md, module_dependency_register.md.

Out of scope

  • E7.M2 reward bundles; faction reputation; quest VFX; Bruno-only verification as prototype-complete proof.

Acceptance criteria

  • Human completes docs/manual-qa/NEO-123.md with server + client.
  • Epic 7 Slice 1 AC: 3 onboarding + 1 chain complete without duplicate completion on replay.
  • Re-read epic_07 Definition of Done for prototype minimums.

Client counterpart: this story is the Slice 1 client capstone.


Decomposition complete checklist