# NEO-111 — Manual QA checklist | Field | Value | |-------|-------| | Key | NEO-111 | | Title | E5M3-12: Playable encounter clear capstone (Godot) | | Linear | https://linear.app/neon-sprawl/issue/NEO-111/e5m3-12-playable-encounter-clear-capstone-godot | | Plan | `docs/plans/NEO-111-implementation-plan.md` | | Branch | `NEO-111-playable-encounter-clear-capstone` | ## Preconditions - **Fresh dev player:** stop any running server, then start a new instance so in-memory **`dev-local-1`** NPC HP, encounter progress, inventory, and gig XP reset. - **No Bruno/curl** for this checklist — defeat chain uses Godot **Tab** + **1** only. - NEO-110 encounter HUD, NEO-106 combat wiring, and NEO-108 encounter-progress GET landed on `main`. - **`Economy HUD`** toggle **on** for inventory verification. ## Archetype reference (defeat order flexible) | Archetype | Instance id | Marker | Pulses to defeat | |-----------|-------------|--------|------------------| | Melee | `prototype_npc_melee` | orange west **`(-3, -3)`** | 4 | | Ranged | `prototype_npc_ranged` | purple SE **`(3, 3)`** | 4 | | Elite | `prototype_npc_elite` | gold origin **`(0, 0)`** | 8 | Player casts **`prototype_pulse`** (**25** damage, ~**3 s** cooldown). Defeat all three in **any order** — server tracks an order-independent subset. ## Expected encounter HUD progression | After | `EncounterProgressLabel` | `EncounterCompleteLabel` | |-------|--------------------------|---------------------------| | Boot (no engagement) | `prototype_combat_pocket: not started (0/3)` | `Loot: —` | | 1st NPC defeated | `prototype_combat_pocket: 1/3` | `Loot: —` | | 2nd NPC defeated | `prototype_combat_pocket: 2/3` | `Loot: —` | | 3rd NPC defeated | `prototype_combat_pocket: completed (3/3)` | `scrap_metal_bulk ×10` and `contract_handoff_token ×1` (display names when item defs loaded) | | After Godot restart (idempotency) | still **`completed (3/3)`** | unchanged grant lines | ## Expected inventory after completion On a fresh server restart the bag starts empty. After the third defeat, **`InventoryLabel`** should show at least: | Item id | Quantity | |---------|----------| | `scrap_metal_bulk` | **10** | | `contract_handoff_token` | **1** | Record these quantities before idempotency steps. ## Expected gig XP after three defeats **`GigXpLabel`** should show **`breach: L1 · 75 xp`** (NEO-44: **25** gig XP per defeat × **3**). No further gig XP increase during idempotency steps. ## Checklist ### Boot + encounter clear 1. Start server: `cd server/NeonSprawl.Server && dotnet run`. 2. Run Godot main scene (**F5**). Confirm boot lines: **`Encounter: … not started (0/3)`** and **`Loot: —`** on **`EncounterProgressLabel`** / **`EncounterCompleteLabel`** (combat HUD block, below **`PlayerCombatHpLabel`**). 3. Defeat **first** prototype NPC (any archetype): walk to marker, **Tab** lock, press **1** until **`Cast: … — defeated!`**. Verify **`EncounterProgressLabel`** shows **`1/3`** (may lag one GET behind cast — wait ~1 s). 4. Defeat **second** prototype NPC (either remaining archetype): lock, cast until defeated. Verify **`2/3`**. 5. Defeat **third** prototype NPC: lock, cast until defeated (**8** pulses for Elite). Verify **`completed (3/3)`** and **`EncounterCompleteLabel`** lists **`scrap_metal_bulk ×10`** and **`contract_handoff_token ×1`** (or raw ids if defs still loading). 6. Open **`Economy HUD`** body: **`InventoryLabel`** shows **`scrap_metal_bulk`** (**10**) and **`contract_handoff_token`** (**1**) without pressing **I** (auto-refresh on completion GET). 7. Verify **`GigXpLabel`** shows **`breach: L1 · 75 xp`**. ### Idempotency 8. **Record** inventory quantities for **`scrap_metal_bulk`** and **`contract_handoff_token`** from step 6. 9. **Godot restart (re-login):** stop Godot run (**Shift+F5** or stop button); **F5** again **without** stopping the server. After boot hydrate, verify **`EncounterProgressLabel`** still **`completed (3/3)`** and **`EncounterCompleteLabel`** grant lines unchanged. 10. Verify **`InventoryLabel`** quantities **match step 8** — no duplicate loot. 11. Lock a **defeated** NPC (**Tab** at its marker); press **1**. Verify **`CastFeedbackLabel`** shows **`ability_cast_denied: target_defeated`**; encounter HUD and inventory **unchanged** from steps 9–10. 12. Verify **`GigXpLabel`** still **`breach: L1 · 75 xp`** — no extra gig XP from idempotency casts. ### Regression 13. **`CastFeedbackLabel`** still shows readable deny reasons (NEO-28 / NEO-98). 14. Component encounter HUD detail: [NEO-110 manual QA](NEO-110.md). Component NPC combat: [NEO-98 manual QA](NEO-98.md). ## Notes - Defeat order may differ from the archetype table — only **0/3 → 3/3** progression is asserted. - Capstone baseline prefers **server restart** over mid-session fixture POST. - **`POST /game/__dev/combat-targets-fixture`** is **out of scope** for idempotency — it clears encounter progress/completion alongside NPC HP reset ([server README — dev combat-target fixture](../../server/README.md#dev-combat-target-fixture-brunomanual-qa)). - Slice 3 Epic AC: completing **`prototype_combat_pocket`** grants expected items + quest token **once** ([epic_05 Slice 3](../../decomposition/epics/epic_05_pve_combat.md#epic-5-slice-3)). ## Acceptance - [x] Steps 1–14 completable in one session without Bruno/curl. - [x] Progress label shows **1/3**, **2/3**, then **completed (3/3)** after three defeats (any order). - [x] Loot label and inventory show **`scrap_metal_bulk` ×10** + **`contract_handoff_token` ×1**; quantities unchanged after Godot restart + defeated-NPC casts. - [x] Epic 5 Slice 3 AC satisfied in Godot.