# Epic 3 — Slice 5: Client economy integration (prototype) Working backlog for **Epic 3 — Slice 5** ([client economy integration](../decomposition/epics/epic_03_crafting_economy.md#epic-3-slice-5)). Completes the **full stack** for gather → inventory → craft in the **Godot client** — not Bruno-only proof. **Policy (from decomposition):** Epics deliver **playable game features**, not server-only vertical slices. Slices 1–3 landed server + content + Bruno; **Slice 5** is the required client half. Slice 4 (E3.M4/M5 sinks) remains pre-production. **Labels (Linear):** every issue carries module label(s) **`E3.M1`** / **`E3.M2`** / **`E3.M3`** as listed; add **`client`** + **`Story`**. **Pattern:** Mirror [E1.M3 client pairing](../plans/E1M3-prototype-backlog.md#e1m3-02--client-tab-target--lock-ui-synced-to-server) — thin HTTP client nodes, `main.gd` wiring, HUD labels, GdUnit doubles, `docs/manual-qa/{KEY}.md`. **Upstream (server must be landed):** | Module | Minimum server stories | |--------|-------------------------| | **E3.M3** | [NEO-55](https://linear.app/neon-sprawl/issue/NEO-55) inventory GET/POST; [NEO-53](https://linear.app/neon-sprawl/issue/NEO-53) item defs (display names) | | **E3.M1** | [NEO-63](https://linear.app/neon-sprawl/issue/NEO-63) interact → gather; [NEO-60](https://linear.app/neon-sprawl/issue/NEO-60) resource-node defs (optional preview) | | **E3.M2** | [NEO-68](https://linear.app/neon-sprawl/issue/NEO-68) recipe defs GET; [NEO-70](https://linear.app/neon-sprawl/issue/NEO-70) craft POST | | **E2.M2** | [NEO-37](https://linear.app/neon-sprawl/issue/NEO-37) skill-progression GET (XP visibility) | **Linear issues (created):** attach `docs/plans/NEO-*-implementation-plan.md` on the same branch as implementation work. | Slug | Linear | |------|--------| | E3S5-01 | [NEO-72](https://linear.app/neon-sprawl/issue/NEO-72) | | E3S5-02 | [NEO-73](https://linear.app/neon-sprawl/issue/NEO-73) | | E3S5-03 | [NEO-74](https://linear.app/neon-sprawl/issue/NEO-74) | | E3S5-04 | [NEO-75](https://linear.app/neon-sprawl/issue/NEO-75) | **Dependency graph in Linear:** E3S5-02 (NEO-73) blocked by E3S5-01 (NEO-72) and [NEO-63](https://linear.app/neon-sprawl/issue/NEO-63). E3S5-03 (NEO-74) blocked by E3S5-01 (NEO-72), [NEO-68](https://linear.app/neon-sprawl/issue/NEO-68), and [NEO-70](https://linear.app/neon-sprawl/issue/NEO-70). E3S5-04 (NEO-75) blocked by E3S5-02 (NEO-73) and E3S5-03 (NEO-74). **Board order:** estimates **1–4** matching slug order. On the Epic 3 project board, sort by **Estimate** (ascending). --- ## Story order (recommended) | Order | Slug | Depends on | |-------|------|------------| | 1 | **E3S5-01** | [NEO-55](https://linear.app/neon-sprawl/issue/NEO-55), [NEO-53](https://linear.app/neon-sprawl/issue/NEO-53) | | 2 | **E3S5-02** | E3S5-01, [NEO-63](https://linear.app/neon-sprawl/issue/NEO-63) | | 3 | **E3S5-03** | E3S5-01, [NEO-68](https://linear.app/neon-sprawl/issue/NEO-68), [NEO-70](https://linear.app/neon-sprawl/issue/NEO-70) | | 4 | **E3S5-04** | E3S5-02, E3S5-03 | --- ## Kickoff decisions (decomposition defaults) | Topic | Decision | Rationale | |-------|----------|-----------| | HUD fidelity | **Prototype debug panels** (Labels / simple lists) — not final art | Matches NEO-24/NEO-28 cast/target HUD pattern; polish is pre-production | | Inventory refresh | **GET after mutating actions** (interact gather, craft POST) | Server is source of truth; no client-side stack math | | Craft UI scope | **List all prototype recipes** + single **Craft** button per row | No station placement, batch quantity slider, or drag-drop in Slice 5 | | Skill XP display | **Salvage + refine levels/XP** on HUD; refresh after gather/craft | Epic 2 Slice 3 AC + vision **progression gate** | | Gather wire | **Reuse `POST …/interact`** — no new gather HTTP on client | E3.M1 prototype contract; extend `interaction_request_client.gd` | | Authority | Client **displays only**; all mutations via existing server routes | [client_server_authority.md](../decomposition/modules/client_server_authority.md) | --- ### E3S5-01 — Client inventory snapshot HUD (E3.M3) **Goal:** Godot **`GET /game/players/{id}/inventory`** client + readable bag/equipment panel; boot hydrate + manual refresh entrypoint for later stories. **In scope** - `inventory_client.gd` (or equivalent): GET snapshot, parse v1 envelope, emit signal with slots/stacks. - HUD: `InventoryLabel` or scroll-friendly list under `UICanvas` showing **bag** + **equipment** rows (item id, quantity, slot kind). - Optional: resolve **`displayName`** via cached **`GET /game/world/item-definitions`** (NEO-53) for readable labels. - GdUnit: HTTP double, parse happy path + error path. - `client/README.md` section; input binding for **refresh** (e.g. **I**) if useful for QA. - `docs/manual-qa/NEO-72.md`. **Out of scope** - Drag-drop, split stacks, equip UX polish. - POST inventory mutations from UI (craft/gather stories own refresh triggers). **Acceptance criteria** - [ ] Boot (or first open) shows current server inventory for `dev_player_id`. - [ ] HUD lists all non-empty bag slots and equipment stub slot from GET body. - [ ] Failed GET surfaces visible error/warning (match interaction client pattern). --- ### E3S5-02 — Client gather feedback on interact (E3.M1) **Goal:** After successful **resource_node** interact, player **sees** inventory change and **salvage** XP movement — not Output-panel-only proof. **In scope** - Extend gather interact path: on `allowed=true` for resource nodes, call **inventory refresh** + **skill-progression GET** (`salvage` row). - Feedback line: e.g. `GatherFeedbackLabel` — “+N scrap_metal_bulk” (derive delta from before/after inventory or document server-truth refresh-only copy). - Map **`node_depleted`** deny to readable HUD message (not silent). - Wire all four prototype resource node ids (not only `prototype_resource_node_alpha`) if interact keys or targeting supports them; document bindings. - GdUnit: mock interact 200 → refresh invoked. - `docs/manual-qa/NEO-73.md`. **Out of scope** - New gather HTTP route; node respawn visuals; gather VFX. **Acceptance criteria** - [ ] In-range interact on fresh node updates inventory HUD without manual refresh. - [ ] Depleted node shows **`node_depleted`** (or agreed copy) on HUD. - [ ] **Salvage** skill level or XP visible and changes after successful gather (Epic 2 Slice 3 visibility). --- ### E3S5-03 — Client craft UI + recipe list (E3.M2) **Goal:** Player selects a prototype recipe and **`POST /game/players/{id}/craft`** from Godot; sees success/deny and updated inventory + **refine** XP. **In scope** - `recipe_definitions_client.gd`: GET world recipe defs (NEO-68). - `craft_client.gd`: POST `{ recipeId, quantity? }`; parse success/deny + `reasonCode`. - HUD: simple recipe list (id / displayName, inputs summary); **Craft** per row for qty **1**. - On success: refresh inventory + skill-progression (**refine**); show feedback line. - Deny paths documented in manual QA: insufficient materials, bag full, unknown recipe. - GdUnit: POST payload shape, deny parsing. - `docs/manual-qa/NEO-74.md`. **Out of scope** - Station/bench world objects; craft quantity spinner; recipe filtering by skill level. **Acceptance criteria** - [ ] Player can **`refine_scrap_standard`** and **`make_field_stim_mk0`** from UI when materials allow. - [ ] Denied craft shows **`reasonCode`** on HUD; inventory unchanged (verify via GET). - [ ] **Refine** skill XP visible and increases on successful craft. --- ### E3S5-04 — Playable gather→refine→make loop in client (capstone) **Goal:** Prove Epic 3 prototype acceptance **in Godot**: gather **`scrap_metal_bulk`** → **`refine_scrap_standard`** → **`make_field_stim_mk0`** without Bruno; satisfies vision **crafting loop** + **progression gate** smoke test. **In scope** - `main.gd` integration checklist: interact → inventory → craft panel flow documented in **`client/README.md`**. - **`docs/manual-qa/NEO-75.md`**: numbered session script (move to node, gather ×N, refine, make stim, verify consumable in bag). - Optional: toggle/collapse HUD sections so prototype scene stays usable (document layout). - Cross-link Epic 3 Slice 5 complete in module docs + alignment register when done. **Out of scope** - Quest UI (E7); combat consumable use (E5 follow-up); art pass. **Acceptance criteria** - [ ] Manual QA checklist completable by a human in one session with server + client running. - [ ] **`field_stim_mk0`** quantity ≥ 1 in inventory at end of script. - [ ] Epic 3 Slice 3 acceptance re-read: **player** (not Bruno) completes gather → refine → usable item. --- ## After this backlog - Epic 3 **prototype** is **full-stack complete** for gather/craft/inventory (Slices 1–3 server + Slice 5 client). - Slice 4 (**E3.M4** + **E3.M5**) sinks/policy remains **pre-production**. - Apply the same **server + client pairing** pattern when decomposing other epics (see [decomposition README](../decomposition/README.md#full-stack-epics)). - Track delivery in Linear; keep `blockedBy` synchronized if scope changes. ## Related docs - [epic_03_crafting_economy.md](../decomposition/epics/epic_03_crafting_economy.md) - [E3M1-prototype-backlog.md](E3M1-prototype-backlog.md), [E3M2-prototype-backlog.md](E3M2-prototype-backlog.md), [E3M3-prototype-backlog.md](E3M3-prototype-backlog.md) - [client_server_authority.md](../decomposition/modules/client_server_authority.md) - [neon_sprawl_vision.plan.md — Prototype Scope](../../neon_sprawl_vision.plan.md)