# NEO-74 — Manual QA checklist | Field | Value | |-------|-------| | Key | NEO-74 | | Title | E3.M2: Client craft UI + recipe list (E3S5-03) | | Linear | https://linear.app/neon-sprawl/issue/NEO-74/e3m2-client-craft-ui-recipe-list-e3s5-03 | | Plan | `docs/plans/NEO-74-implementation-plan.md` | | Branch | `NEO-74-e3m2-client-craft-ui-recipe-list` | ## Preconditions - Server running with default dev player (`dev-local-1`); craft HTTP landed (NEO-70); recipe defs GET landed (NEO-68); inventory HUD (NEO-72) and gather/skill HUD (NEO-73) working. ## Checklist 1. Start server: `cd server/NeonSprawl.Server && dotnet run`. 2. Run Godot main scene (**F5**). Confirm **`SkillProgressionLabel`** shows **`salvage`** and **`refine`** rows after boot. 3. Scroll the recipe panel in **Economy HUD** (`BodyScroll/Body/CraftRecipePanel`) — **eight** prototype recipes with **Craft** buttons. **Refine Scrap (Standard)** is the first row (NEO-122 layout). 4. On a fresh player (empty bag), click **Craft** on **`refine_scrap_standard`**. **`CraftFeedbackLabel`** (in **`HudRootScroll`**) shows **`Craft: denied — insufficient_materials`**. Press **I** — inventory unchanged. 5. Gather **≥5** **`scrap_metal_bulk`** (see [NEO-73 manual QA](NEO-73.md) **R** at resource nodes). 6. Click **Craft** on **`refine_scrap_standard`**. **`CraftFeedbackLabel`** shows **`Craft: +1 …`** (refined plate output). **`InventoryLabel`** updates without **I**. **`refine`** xp increases on **`SkillProgressionLabel`**. 7. Gather **≥1** more scrap if needed; ensure **≥2** **`refined_plate_stock`** and **≥1** **`scrap_metal_bulk`** in bag (craft **`refine_scrap_standard`** again or gather). 8. Click **Craft** on **`make_field_stim_mk0`**. Success feedback shows **`field_stim_mk0`** output; bag lists consumable; **`refine`** xp increases again. 9. Optional deny spot-check: with a full bag, attempt a craft whose output cannot fit — expect **`Craft: denied — inventory_full`**. ## Notes - Craft quantity is fixed at **1** per button (no spinner in this story). - Success copy comes from POST **`outputsGranted`**; inventory and skill rows refresh via GET after success only. - **NEO-122 layout:** debug feedback labels live in **`HudRootScroll`**; economy block (recipes, inventory, skills) is pinned bottom-left — scroll economy **`BodyScroll`** for inventory/skills below recipes.