neon-sprawl/docs/plans/NEO-132-implementation-plan.md

166 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 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-124NEO-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-124NEO-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** |