166 lines
14 KiB
Markdown
166 lines
14 KiB
Markdown
# 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** |
|