NEO-110: manual QA, README, plan reconciliation, and module docs.

pull/149/head
VinPropane 2026-05-31 19:35:56 -04:00
parent d81d19b859
commit bcc9bf1c69
6 changed files with 91 additions and 8 deletions

View File

@ -213,6 +213,18 @@ Epic 5 Slice 1 capstone — tab-target lock, cast, defeat, and gig XP visibility
Full capstone checklist: [`docs/manual-qa/NEO-86.md`](../docs/manual-qa/NEO-86.md).
## Encounter progress + loot HUD (NEO-110)
- **`GET /game/players/{id}/encounter-progress`** — server-authoritative per-encounter **`state`**, **`defeatedTargetIds`**, and **`rewardGrantSummary`** when **`completed`** (NEO-108); see [server README — Per-player encounter progress](../server/README.md#per-player-encounter-progress-neo-108).
- **Scripts:** `scripts/encounter_progress_client.gd`; wired from `main.gd` in `_setup_encounter_progress_sync()`.
- **HUD:**
- **`UICanvas/HudRoot/EncounterProgressLabel`** — frozen pocket **`prototype_combat_pocket`**: **`not started (0/3)`** → **`{n}/3`** while **`active`** → **`completed (3/3)`**.
- **`UICanvas/HudRoot/EncounterCompleteLabel`** — **`Loot: —`** until **`completed`**; then one line per grant (**`displayName`** via **`ItemDefinitionsClient`**, fallback **`itemId`**).
- **Refresh:** boot hydrate + **`GET`** after cast accept with **`targetDefeated: true`** (alongside gig/combat refreshes). No periodic poll or manual key.
- **Inventory:** on **`completed`** row, **`InventoryLabel`** auto-refreshes (no **I**) so bag shows **`scrap_metal_bulk`** and **`contract_handoff_token`**.
Full checklist: [`docs/manual-qa/NEO-110.md`](../docs/manual-qa/NEO-110.md).
## Inventory snapshot HUD (NEO-72)
- **`GET /game/players/{id}/inventory`** — server-authoritative bag (**24** slots) + equipment stub (**1** slot); see [server README — Player inventory](../server/README.md#player-inventory-neo-54-store-neo-55-http).

View File

@ -98,6 +98,8 @@ The **first shipped encounter + reward spine** is **frozen** for prototype tunin
**Slice 3 telemetry hooks landed ([NEO-109](https://linear.app/neon-sprawl/issue/NEO-109)):** comment-only **`encounter_start`**, **`encounter_complete`**, **`reward_attribution`**, and **`encounter_complete_denied`** in **`EncounterProgressOperations`** / **`EncounterCompletionOperations`**; **`EncounterCombatWiring`** delegates without duplicate hooks. Plan: [NEO-109 implementation plan](../../plans/NEO-109-implementation-plan.md); [server README — Encounter telemetry hooks (NEO-109)](../../../server/README.md#encounter-telemetry-hooks-neo-109).
**Client encounter HUD landed ([NEO-110](https://linear.app/neon-sprawl/issue/NEO-110)):** Godot **`encounter_progress_client.gd`** polls **`GET /game/players/{id}/encounter-progress`** on boot and after defeat casts; **`EncounterProgressLabel`** / **`EncounterCompleteLabel`** in combat HUD; inventory refresh on completion. Plan: [NEO-110 implementation plan](../../plans/NEO-110-implementation-plan.md); manual QA: [NEO-110.md](../../manual-qa/NEO-110.md); [client README — Encounter progress + loot HUD](../../../client/README.md#encounter-progress--loot-hud-neo-110).
## Source anchors
- Master plan: [`neon_sprawl_vision.plan.md`](../../../neon_sprawl_vision.plan.md) — Epic 5.

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,59 @@
# NEO-110 — Manual QA checklist
| Field | Value |
|-------|-------|
| Key | NEO-110 |
| Title | E5M3-11: Client encounter progress + loot feedback HUD |
| Linear | https://linear.app/neon-sprawl/issue/NEO-110/e5m3-11-client-encounter-progress-loot-feedback-hud |
| Plan | `docs/plans/NEO-110-implementation-plan.md` |
| Branch | `NEO-110-client-encounter-progress-loot-feedback-hud` |
## Preconditions
- **Fresh dev player:** stop any running server, then start a new instance so in-memory encounter progress, NPC HP, and inventory reset.
- **No Bruno/curl** for this checklist — defeat chain uses Godot **Tab** + **1** only.
- NEO-108 encounter-progress GET and NEO-106 combat wiring landed on `main`.
- **`Economy HUD`** toggle **on** for inventory verification (step 8).
## 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).
## 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) |
## Checklist
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 **`prototype_npc_melee`**: walk to orange marker, **Tab** lock, press **1** until **`Cast: … — defeated!`**. Verify **`EncounterProgressLabel`** shows **`1/3`** (may lag one GET behind cast — wait ~1 s or defeat next NPC).
4. Defeat **`prototype_npc_ranged`**: lock at SE marker, cast until defeated. Verify **`2/3`**.
5. Defeat **`prototype_npc_elite`**: lock at origin, cast until defeated (**8** pulses). 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`** and **`contract_handoff_token`** without pressing **I** (auto-refresh on completion GET).
7. Defeat any already-defeated NPC again (optional): encounter row stays **`completed (3/3)`**; loot lines unchanged.
8. Regression: **`GigXpLabel`** still updates per defeat (NEO-86); **`CastFeedbackLabel`** still shows deny on re-cast (**`target_defeated`**).
## Notes
- Defeat order may differ from table — server tracks order-independent subset; count is **`defeatedTargetIds.size()`**.
- Capstone baseline prefers **server restart** over mid-session fixture POST.
- Full three-NPC loop + idempotency capstone: [NEO-111](NEO-111.md) (when landed).
- Component combat regression: [NEO-98 manual QA](NEO-98.md).
## Acceptance
- [ ] Steps 18 completable in one session without Bruno/curl.
- [ ] Progress label shows **1/3**, **2/3**, then **completed (3/3)** after defeats.
- [ ] Loot label matches server grant summary; inventory reflects grants without **I**.

View File

@ -337,9 +337,11 @@ Working backlog for **Epic 5 — Slice 3** ([Epic 5 · Slice 3 — encounters an
**Acceptance criteria**
- [ ] Player-visible progress updates after each NPC defeat (e.g. **2/3** targets).
- [ ] Completion label shows grant summary matching server GET.
- [ ] Manual QA checklist exercisable without Bruno.
- [x] Player-visible progress updates after each NPC defeat (e.g. **2/3** targets).
- [x] Completion label shows grant summary matching server GET.
- [x] Manual QA checklist exercisable without Bruno.
**Landed ([NEO-110](https://linear.app/neon-sprawl/issue/NEO-110)):** **`encounter_progress_client.gd`** + **`EncounterProgressLabel`** / **`EncounterCompleteLabel`**; boot + defeat-triggered GET; inventory auto-refresh on **`completed`**. Plan: [NEO-110-implementation-plan.md](NEO-110-implementation-plan.md); manual QA: [NEO-110.md](../manual-qa/NEO-110.md); [client README — Encounter progress + loot HUD](../../client/README.md#encounter-progress--loot-hud-neo-110).
**Client counterpart:** this issue (**NEO-110**).

View File

@ -47,9 +47,17 @@
## Acceptance criteria checklist
- [ ] Player-visible progress updates after each NPC defeat (e.g. **2/3** targets).
- [ ] Completion label shows grant summary matching server GET.
- [ ] Manual QA checklist exercisable without Bruno.
- [x] Player-visible progress updates after each NPC defeat (e.g. **2/3** targets).
- [x] Completion label shows grant summary matching server GET.
- [x] Manual QA checklist exercisable without Bruno.
## Implementation reconciliation (shipped)
- **`encounter_progress_client.gd`:** GET parse v1; **`encounter_row`**; **`encounter_progress_received`** / **`encounter_sync_failed`**.
- **`main.gd`:** boot + **`targetDefeated`** refresh; HUD render; inventory refresh on **`completed`**; item-defs re-paint when defs arrive.
- **Scene:** **`EncounterProgressClient`**, **`EncounterProgressLabel`**, **`EncounterCompleteLabel`** in **`HudRoot`** after **`PlayerCombatHpLabel`**.
- **Tests:** `client/test/encounter_progress_client_test.gd` (inactive/active/completed parse + 404).
- **Docs:** `client/README.md` encounter section; `docs/manual-qa/NEO-110.md`.
## Technical approach
@ -147,5 +155,5 @@ No new **C#** tests (client-only; server covered by **`EncounterProgressApiTests
| Item | Agent recommendation | Status |
|------|----------------------|--------|
| **Concurrent GETs on triple-defeat frame** | **`_busy`** guard drops overlap — last completed response wins; acceptable for prototype. | **adopted** |
| **Item defs not loaded before completion render** | Re-render encounter labels when **`definitions_ready`** fires if snapshot already **`completed`** (mirror NEO-72 inventory re-paint). | **pending** (implement with inventory pattern) |
| **Item defs not loaded before completion render** | Re-render encounter labels when **`definitions_ready`** fires if snapshot already **`completed`** (mirror NEO-72 inventory re-paint). | **adopted** — `_on_item_definitions_ready` re-paints encounter HUD |
| **NEO-111 capstone overlap** | NEO-110 manual QA is HUD-focused; NEO-111 adds full loop + idempotency — keep scopes separate. | **deferred** |