# NEO-132 — Implementation plan ## Story reference | Field | Value | |--------|--------| | **Key** | NEO-132 | | **Title** | E7M2-09: Playable quest reward delivery capstone (Godot) | | **Linear** | https://linear.app/neon-sprawl/issue/NEO-132/e7m2-09-playable-quest-reward-delivery-capstone-godot | | **Module** | [E7.M2 — RewardAndUnlockRouter](../decomposition/modules/E7_M2_RewardAndUnlockRouter.md) · Epic 7 Slice 2 · backlog **E7M2-09** | | **Branch** | `NEO-132-playable-quest-reward-delivery-capstone` | | **Client deps** | [NEO-131](https://linear.app/neon-sprawl/issue/NEO-131) quest completion reward HUD (**Done** on `main`); [NEO-123](https://linear.app/neon-sprawl/issue/NEO-123) Slice 1 capstone flow; [NEO-122](https://linear.app/neon-sprawl/issue/NEO-122) quest progress HUD | | **Server deps** | [NEO-124](https://linear.app/neon-sprawl/issue/NEO-124)–[NEO-130](https://linear.app/neon-sprawl/issue/NEO-130) reward spine (**landed on `main`**) — catalog, delivery store, router, quest-state wiring, HTTP **`completionRewardSummary`** | | **Pattern** | Capstone integration — [NEO-123](NEO-123-implementation-plan.md) docs + manual QA primary; minimal gap-fill only if capstone QA fails on `main` | | **Blocked by** | [NEO-131](https://linear.app/neon-sprawl/issue/NEO-131) (**Done**) | | **Server counterpart** | NEO-124–NEO-130 server spine; Bruno-only verification is not prototype-complete per [full-stack epic decomposition](../../.cursor/rules/full-stack-epic-decomposition.md) | ## Kickoff clarifications | Topic | Question | Agent recommendation | Answer | |--------|----------|----------------------|--------| | **Implementation scope** | Docs-only vs client code? | **Docs + manual QA primary**; fix integration gaps only if capstone QA fails on `main` — [NEO-123](NEO-123-implementation-plan.md) precedent; NEO-131 deferred economy HUD refresh to this capstone. | **Adopted** — docs-primary | | **Capstone path** | Extend full NEO-123 vs shorter reward-focused path? | **Extend full NEO-123 four-quest flow** — add **`QuestRewardDeliveryLabel`** + economy HUD verification at each completion; covers skill-only, item+skill, and idempotency across all grant kinds in the freeze table. | **Adopted** — full NEO-123 extend | **Additional defaults (no kickoff question — settled by backlog / landed code):** - **Session baseline:** fresh **server restart** before Godot **F5** — resets in-memory quest progress, **`IRewardDeliveryStore`**, inventory, skill progression, encounter state, and resource-node depletion; zero Bruno/curl in main checklist. - **Economy HUD:** toggle **on** for inventory + skill verification (NEO-75 / NEO-123 precedent). - **Reward HUD:** transition-only paint per NEO-131 — boot with already-completed quests does not replay grant copy. - **Encounter loot vs quest bundles:** combat pocket **`scrap_metal_bulk` ×10** + **`contract_handoff_token` ×1** remain on **`EncounterCompleteLabel`** (NEO-110); quest completion bundles are skill XP and/or **`survey_drone_kit`** on **`QuestRewardDeliveryLabel`** (E7M2 freeze). - **Server changes:** none unless capstone QA exposes an authoritative bug (unlikely — covered by server reward router tests). ## Goal, scope, and out-of-scope **Goal:** Prove Epic 7 Slice 2 acceptance **in Godot**: quest completion grants items + skill XP **once**; idempotent on replay; satisfies [epic_07 Slice 2 AC](../decomposition/epics/epic_07_quest_faction.md#slice-2---reward-and-unlock-routing) and [Definition of Done](../decomposition/epics/epic_07_quest_faction.md#epic-7-definition-of-done). **In scope (from Linear + [E7M2-09](E7M2-prototype-backlog.md#e7m2-09--playable-quest-reward-delivery-capstone-godot)):** - **`docs/manual-qa/NEO-132.md`**: numbered **single-session** capstone — extend [NEO-123](../manual-qa/NEO-123.md) four-quest flow; at each quest **`completed`** transition verify **`QuestRewardDeliveryLabel`**, **`SkillProgressionLabel`**, and **`InventoryLabel`** (where applicable); **idempotency** via Godot restart + duplicate accept keys with economy counts unchanged. - **`client/README.md`**: **End-to-end quest reward loop (NEO-132)** section — integration flow table; cross-links NEO-124–NEO-131 and Slice 1 capstone. - **Module alignment** (on story completion): update [E7_M2](../decomposition/modules/E7_M2_RewardAndUnlockRouter.md) status, [documentation_and_implementation_alignment.md](../decomposition/modules/documentation_and_implementation_alignment.md) E7.M2 row, [module_dependency_register.md](../decomposition/modules/module_dependency_register.md) E7.M2 note, and [E7M2-prototype-backlog.md](E7M2-prototype-backlog.md) E7M2-09 checkboxes; mark Epic 7 Slice 2 client capstone complete. - **Integration fixes only if capstone QA fails** on current `main` wiring (economy HUD stale after quest completion, reward label gap, idempotency breach, etc.). **Out of scope (from Linear + backlog):** - Encounter loot migration; faction reputation; quest VFX art. - Bruno-only verification as prototype-complete proof. - New server HTTP routes or reward router logic beyond NEO-127/NEO-128. - Skill-definitions client; unlock/flag grant kinds (deferred pre-production). ## Acceptance criteria checklist - [ ] Human completes **`docs/manual-qa/NEO-132.md`** with server + client. - [ ] Epic 7 Slice 2 AC: idempotent reward delivery; replays cannot double-claim. - [ ] Re-read [epic_07 Slice 2 AC](../decomposition/epics/epic_07_quest_faction.md#slice-2---reward-and-unlock-routing). ## Implementation reconciliation (shipped) - **`docs/manual-qa/NEO-132.md`** — four-quest capstone extending NEO-123 with reward HUD + economy verification + idempotency steps. - **`client/README.md`** — **End-to-end quest reward loop (NEO-132)** section with flow table and cross-links. - **`client/scripts/quest_hud_controller.gd`** — **`quest_completion_reward_transition`** signal + **`_refresh_economy_hud()`** on in-session completion (inventory + skill GET). - **`client/scripts/main.gd`** — passes **`InventoryClient`** + **`SkillProgressionClient`** into quest HUD **`setup`**. - **`docs/manual-qa/NEO-123.md`**, **`docs/manual-qa/NEO-131.md`** — cross-links to NEO-132 capstone. - **`docs/plans/E7M2-prototype-backlog.md`**, **`E7_M2_RewardAndUnlockRouter.md`**, **`documentation_and_implementation_alignment.md`**, **`module_dependency_register.md`** — E7M2-09 landed; E7.M2 **Ready**; Epic 7 Slice 2 client capstone complete. ## Technical approach ### 1. Reward freeze reference (E7M2-01) | Quest id | Quest completion bundle (server) | Expected **`QuestRewardDeliveryLabel`** | Economy HUD asserts | |----------|----------------------------------|----------------------------------------|---------------------| | `prototype_quest_gather_intro` | `salvage` **+25** XP | `Salvage +25 XP` | **`SkillProgressionLabel`**: salvage XP increases by **25** | | `prototype_quest_combat_intro` | `salvage` **+25** XP | `Salvage +25 XP` | salvage XP **+25** (cumulative **50** after gather + combat) | | `prototype_quest_refine_intro` | `refine` **+25** XP | `Refine +25 XP` | refine XP **+25** | | `prototype_quest_operator_chain` | `survey_drone_kit` ×1 + `salvage` **+50** XP | `Survey Drone Kit ×1` + `Salvage +50 XP` | bag contains **`survey_drone_kit`**; salvage XP **+50** (cumulative **100** if all four completed in one session) | **Idempotency key (server):** `{playerId}:quest_complete:{questId}` — replay **`completed`** status skips router apply ([NEO-128](NEO-128-implementation-plan.md)). ### 2. Capstone manual QA script (`docs/manual-qa/NEO-132.md`) **Preconditions:** Same as [NEO-123](../manual-qa/NEO-123.md) — fresh server restart, Godot gameplay only, **`Economy HUD`** on. **Flow:** Inherit NEO-123 accept order (**Q** gather → **Shift+Q** combat → **Shift+Q** refine → **Shift+Q** operator chain), material math, and combat/gather anchors. **Extend** each completion step with: 1. **`QuestRewardDeliveryLabel`** — grant lines on in-session transition only (NEO-131). 2. **`SkillProgressionLabel`** — record salvage/refine XP after each completion (note baseline at boot). 3. **`InventoryLabel`** — after operator chain completion, assert **`survey_drone_kit`** present (display name when item defs loaded). **Idempotency (reward-specific):** 1. After all four quests **`completed`**, record final **`SkillProgressionLabel`** salvage/refine totals and bag rows (including **`survey_drone_kit`**). 2. **Godot restart** (server still running): reward label **`—`**; quest statuses still **`completed`**; economy counts **unchanged** from step 1. 3. **Duplicate accepts:** **Q** / **Shift+Q** deny per NEO-123; economy counts still unchanged. **Regression pointers:** [NEO-131](../manual-qa/NEO-131.md) component reward HUD, [NEO-123](../manual-qa/NEO-123.md) Slice 1 capstone, [NEO-110](../manual-qa/NEO-110.md) encounter loot independence. ### 3. Client README (`client/README.md`) Add **End-to-end quest reward loop (NEO-132)** section after [Quest completion reward HUD (NEO-131)](../../client/README.md#quest-completion-reward-hud-neo-131), mirroring NEO-123 capstone section: - One-line Epic 7 Slice 2 capstone goal. - Flow table: fresh restart → four-quest NEO-123 path → per-completion reward HUD + economy verification → idempotency. - Cross-links: NEO-124 catalog freeze, NEO-126 delivery store, NEO-127 router, NEO-129 HTTP summary, NEO-131 HUD, NEO-123 onboarding flow. - Pointer to **`docs/manual-qa/NEO-132.md`**. ### 4. Module / backlog alignment (on land) When capstone QA passes: - [E7M2-prototype-backlog.md](E7M2-prototype-backlog.md) — E7M2-09 AC checkboxes. - [E7_M2_RewardAndUnlockRouter.md](../decomposition/modules/E7_M2_RewardAndUnlockRouter.md) — module status **Ready**; Slice 2 client capstone note. - [documentation_and_implementation_alignment.md](../decomposition/modules/documentation_and_implementation_alignment.md) — E7.M2 row: NEO-132 landed; Epic 7 Slice 2 client capstone complete. - [module_dependency_register.md](../decomposition/modules/module_dependency_register.md) — E7.M2 **Ready** when capstone lands. ### 5. Integration fixes (conditional) Run capstone QA on `main` (or branch with NEO-131 merged). If any step fails: | Symptom | Likely fix surface | |---------|-------------------| | **`SkillProgressionLabel`** stale after combat intro complete | `main.gd` — add skill GET refresh on quest-progress GET when combat quest completes (defeat path currently refreshes encounter + quest only) | | **`InventoryLabel`** missing **`survey_drone_kit`** after operator chain | `main.gd` — refresh inventory on quest completion transition (operator chain completes via token check without new gather/craft) | | Reward label wrong/missing | `quest_hud_controller.gd` — unlikely if NEO-131 GdUnit passes | | Economy counts increase on Godot restart + replay | Server bug — file issue; client displays GET only | | Duplicate delivery on replay | Server **`IRewardDeliveryStore`** / router — file issue | Document any fix in **Implementation reconciliation** and add regression note to manual QA. ## Files to add | Path | Purpose | |------|---------| | `docs/plans/NEO-132-implementation-plan.md` | This plan. | | `docs/manual-qa/NEO-132.md` | Single-session four-quest capstone with reward HUD + economy verification + idempotency steps. | ## Files to modify | Path | Rationale | |------|-----------| | `client/README.md` | **End-to-end quest reward loop (NEO-132)** section with flow table and cross-links. | | `docs/manual-qa/NEO-123.md` | Cross-link to NEO-132 Slice 2 capstone; note reward/economy verification defers to NEO-132. | | `docs/manual-qa/NEO-131.md` | Cross-link to NEO-132 capstone as full-flow superset. | | `docs/plans/E7M2-prototype-backlog.md` | E7M2-09 AC checkboxes when capstone lands. | | `docs/decomposition/modules/E7_M2_RewardAndUnlockRouter.md` | Module status **Ready** + capstone landed note on completion. | | `docs/decomposition/modules/documentation_and_implementation_alignment.md` | E7.M2 row: NEO-132 landed; Slice 2 complete. | | `docs/decomposition/modules/module_dependency_register.md` | E7.M2 **Ready** when capstone lands. | **Conditional (only if capstone QA fails):** `client/scripts/main.gd` (economy HUD refresh on quest completion transition) — minimal gap-fill; document paths in reconciliation. ## Tests | Test file | What it covers | |-----------|----------------| | `client/test/quest_reward_hud_test.gd` | **Add:** `quest_completion_reward_transition` emitted on in-session completion; not emitted on boot-completed snapshot. | | *(server unchanged)* | Reward spine covered by **`RewardRouterOperationsTests`**, **`QuestStateOperationsTests`**, **`QuestProgressApiTests`**. Capstone proof is **`docs/manual-qa/NEO-132.md`** human QA. | ## Open questions / risks | Question / risk | Agent recommendation | Status | |-----------------|----------------------|--------| | **Economy HUD auto-refresh gaps** | Add **`quest_completion_reward_transition`** signal + **`main.gd`** inventory/skill refresh — combat and operator-chain paths lacked auto-refresh. | **adopted** | | **NEO-123 vs NEO-132 relationship** | NEO-132 **supersedes** as Slice 2 capstone for reward idempotency; keep NEO-123 as Slice 1 regression. | **adopted** | | **Manual I key in QA script** | Prefer asserting auto-refresh after each completion; use **I** only as documented workaround if docs-primary QA passes with manual refresh and auto-fix is out of scope. | **deferred** | | **Cumulative skill XP math** | Script records **delta** per completion from **`SkillProgressionLabel`**, not absolute totals — avoids coupling to unrelated XP sources. | **adopted** | | **Docs-only fails capstone** | Economy refresh hook landed proactively; capstone QA confirms end-to-end. | **adopted** |