Merge pull request #150 from ViPro-Technologies/NEO-111-playable-encounter-clear-capstone
NEO-111: Playable encounter clear capstone (Godot)pull/152/head
commit
47105ccd90
|
|
@ -225,6 +225,29 @@ Full capstone checklist: [`docs/manual-qa/NEO-86.md`](../docs/manual-qa/NEO-86.m
|
|||
|
||||
Full checklist: [`docs/manual-qa/NEO-110.md`](../docs/manual-qa/NEO-110.md).
|
||||
|
||||
## End-to-end encounter clear loop (NEO-111)
|
||||
|
||||
Epic 5 Slice 3 capstone — defeat all three prototype NPCs, receive loot + quest token **once**, verify inventory **in Godot** without Bruno.
|
||||
|
||||
**Flow:** fresh server restart → boot encounter HUD **0/3** → defeat ×3 (any order) → progress **1/3 → 2/3 → completed** → loot label + inventory → Godot restart idempotency.
|
||||
|
||||
| Step | Input / trigger | HUD / server outcome |
|
||||
|------|-----------------|----------------------|
|
||||
| Boot | Godot **F5** + fresh server | **`EncounterProgressLabel`** **`not started (0/3)`**; **`Loot: —`**; empty bag |
|
||||
| Engage | **Tab** + **1** on first NPC | Encounter activates on first damaging hit (NEO-106); progress **`1/3`** after defeat |
|
||||
| Second defeat | Lock + cast second NPC | **`2/3`**; loot still **`—`** |
|
||||
| Third defeat | Lock + cast third NPC | **`completed (3/3)`**; **`EncounterCompleteLabel`** lists grants; **`InventoryLabel`** auto-refreshes |
|
||||
| Idempotency | Stop Godot + **F5** (server still running) | Encounter still **`completed`**; inventory counts unchanged |
|
||||
| Re-cast defeated | **Tab** + **1** on defeated NPC | **`ability_cast_denied: target_defeated`**; no duplicate loot or gig XP |
|
||||
|
||||
**Cross-links:** [NEO-106](../docs/plans/NEO-106-implementation-plan.md) combat wiring · [NEO-108](../docs/plans/NEO-108-implementation-plan.md) encounter-progress GET · [NEO-110](../docs/manual-qa/NEO-110.md) HUD components · [NEO-98](../docs/manual-qa/NEO-98.md) NPC combat · [NEO-86](../docs/manual-qa/NEO-86.md) gig XP per defeat.
|
||||
|
||||
**Scripts:** `encounter_progress_client.gd`, `inventory_client.gd`, `ability_cast_client.gd`, `combat_targets_client.gd` — wired from `main.gd`.
|
||||
|
||||
**Preconditions:** **Server restart** before capstone run resets NPC HP, encounter progress, inventory, and gig XP.
|
||||
|
||||
Full capstone checklist: [`docs/manual-qa/NEO-111.md`](../docs/manual-qa/NEO-111.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).
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
uid://moi4320kc06
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
| **Module ID** | E5.M3 |
|
||||
| **Epic** | [Epic 5 — PvE Combat](../epics/epic_05_pve_combat.md) |
|
||||
| **Stage target** | Prototype |
|
||||
| **Status** | In Progress — Slice 3 backlog [E5M3-prototype-backlog.md](../../plans/E5M3-prototype-backlog.md): **E5M3-01** [NEO-100](https://linear.app/neon-sprawl/issue/NEO-100) catalog + CI landed · **E5M3-02** [NEO-101](https://linear.app/neon-sprawl/issue/NEO-101) server load landed · **E5M3-03** [NEO-102](https://linear.app/neon-sprawl/issue/NEO-102) registries landed · **E5M3-04** [NEO-103](https://linear.app/neon-sprawl/issue/NEO-103) HTTP read landed · **E5M3-05** [NEO-104](https://linear.app/neon-sprawl/issue/NEO-104) progress + completion stores landed · **E5M3-06** [NEO-105](https://linear.app/neon-sprawl/issue/NEO-105) completion grants landed · **E5M3-07** [NEO-106](https://linear.app/neon-sprawl/issue/NEO-106) combat wiring landed · **E5M3-09** [NEO-107](https://linear.app/neon-sprawl/issue/NEO-107) event record landed · **E5M3-08** [NEO-108](https://linear.app/neon-sprawl/issue/NEO-108) per-player GET landed · **E5M3-12** [NEO-111](https://linear.app/neon-sprawl/issue/NEO-111) |
|
||||
| **Status** | Ready — Slice 3 backlog [E5M3-prototype-backlog.md](../../plans/E5M3-prototype-backlog.md): **E5M3-01** [NEO-100](https://linear.app/neon-sprawl/issue/NEO-100) catalog + CI landed · **E5M3-02** [NEO-101](https://linear.app/neon-sprawl/issue/NEO-101) server load landed · **E5M3-03** [NEO-102](https://linear.app/neon-sprawl/issue/NEO-102) registries landed · **E5M3-04** [NEO-103](https://linear.app/neon-sprawl/issue/NEO-103) HTTP read landed · **E5M3-05** [NEO-104](https://linear.app/neon-sprawl/issue/NEO-104) progress + completion stores landed · **E5M3-06** [NEO-105](https://linear.app/neon-sprawl/issue/NEO-105) completion grants landed · **E5M3-07** [NEO-106](https://linear.app/neon-sprawl/issue/NEO-106) combat wiring landed · **E5M3-08** [NEO-108](https://linear.app/neon-sprawl/issue/NEO-108) per-player GET landed · **E5M3-09** [NEO-107](https://linear.app/neon-sprawl/issue/NEO-107) event record landed · **E5M3-10** [NEO-109](https://linear.app/neon-sprawl/issue/NEO-109) telemetry hooks landed · **E5M3-11** [NEO-110](https://linear.app/neon-sprawl/issue/NEO-110) client HUD landed · **E5M3-12** [NEO-111](https://linear.app/neon-sprawl/issue/NEO-111) playable capstone landed |
|
||||
| **Linear** | Label **`E5.M3`** · [E5M3-prototype-backlog.md](../../plans/E5M3-prototype-backlog.md) **E5M3-01** [NEO-100](https://linear.app/neon-sprawl/issue/NEO-100) · **E5M3-02** [NEO-101](https://linear.app/neon-sprawl/issue/NEO-101) · **E5M3-03** [NEO-102](https://linear.app/neon-sprawl/issue/NEO-102) · **E5M3-04** [NEO-103](https://linear.app/neon-sprawl/issue/NEO-103) · **E5M3-05** [NEO-104](https://linear.app/neon-sprawl/issue/NEO-104) · **E5M3-06** [NEO-105](https://linear.app/neon-sprawl/issue/NEO-105) · **E5M3-07** [NEO-106](https://linear.app/neon-sprawl/issue/NEO-106) · **E5M3-08** [NEO-108](https://linear.app/neon-sprawl/issue/NEO-108) · **E5M3-09** [NEO-107](https://linear.app/neon-sprawl/issue/NEO-107) · **E5M3-10** [NEO-109](https://linear.app/neon-sprawl/issue/NEO-109) · **E5M3-11** [NEO-110](https://linear.app/neon-sprawl/issue/NEO-110) · **E5M3-12** [NEO-111](https://linear.app/neon-sprawl/issue/NEO-111) |
|
||||
|
||||
## Purpose
|
||||
|
|
@ -100,6 +100,8 @@ The **first shipped encounter + reward spine** is **frozen** for prototype tunin
|
|||
|
||||
**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).
|
||||
|
||||
**Client capstone landed ([NEO-111](https://linear.app/neon-sprawl/issue/NEO-111)):** playable encounter clear loop in Godot — [`NEO-111.md`](../../manual-qa/NEO-111.md) single-session script (flexible defeat order, Godot restart idempotency); [client README — End-to-end encounter clear loop (NEO-111)](../../../client/README.md#end-to-end-encounter-clear-loop-neo-111). Plan: [NEO-111 implementation plan](../../plans/NEO-111-implementation-plan.md). **Epic 5 Slice 3 client capstone complete.**
|
||||
|
||||
## 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
|
|
@ -73,14 +73,14 @@ Fleshed-out scope, contracts, and integration notes live in **per-module documen
|
|||
|---|---|---|---|---|---|
|
||||
| E5.M1 | CombatRulesEngine | E1.M3, E2.M2 | CombatAction, CombatResolution, ThreatState | Prototype | Ready |
|
||||
| E5.M2 | NpcAiAndBehaviorProfiles | E5.M1 | NpcBehaviorDef, TelegraphEvent, AggroRule | Prototype | In Progress |
|
||||
| E5.M3 | EncounterAndRewardTables | E5.M1, E5.M2, E3.M3, E7.M2 | EncounterDef, RewardTable, EncounterCompleteEvent | Prototype | In Progress |
|
||||
| E5.M3 | EncounterAndRewardTables | E5.M1, E5.M2, E3.M3, E7.M2 | EncounterDef, RewardTable, EncounterCompleteEvent | Prototype | Ready |
|
||||
| E5.M4 | GroupCombatScaling | E5.M3, E8.M1 | ScalingProfile, PartySizeModifier, CombatDifficultyBand | Pre-production | Planned |
|
||||
|
||||
**E5.M1 note:** Epic 5 **Slice 1** backlog in Linear ([Epic 5 — PvE Combat and Encounter Content](https://linear.app/neon-sprawl/project/epic-5-pve-combat-and-encounter-content-cf3c94c3-5346-40e0-8aaf-281e846f2846)): [NEO-76](https://linear.app/neon-sprawl/issue/NEO-76) → [NEO-86](https://linear.app/neon-sprawl/issue/NEO-86); label **`E5.M1`**. Gig XP on defeat: **E5M1-10** [NEO-44](https://linear.app/neon-sprawl/issue/NEO-44). See [E5M1-prototype-backlog.md](../../plans/E5M1-prototype-backlog.md), [E5_M1_CombatRulesEngine.md](E5_M1_CombatRulesEngine.md). Builds on E1.M4 cast funnel (NEO-28/31/32); extends **`POST …/ability-cast`** with **`CombatResolution`**. **NEO-76 landed:** frozen four-ability catalog + CI ([NEO-76 plan](../../plans/NEO-76-implementation-plan.md)). **NEO-77 landed:** fail-fast server load of `content/abilities/*_abilities.json` ([NEO-77 plan](../../plans/NEO-77-implementation-plan.md)). **NEO-79 landed:** injectable **`IAbilityDefinitionRegistry`** + DI; hotbar/cast use **`TryNormalizeKnown`** ([NEO-79 plan](../../plans/NEO-79-implementation-plan.md)). **NEO-78 landed:** **`GET /game/world/ability-definitions`** — `AbilityDefinitionsWorldApi` + DTOs in `Game/Combat/` ([NEO-78 plan](../../plans/NEO-78-implementation-plan.md)); Bruno `bruno/neon-sprawl-server/ability-definitions/`. **NEO-80 landed:** **`ICombatEntityHealthStore`** / **`InMemoryCombatEntityHealthStore`** — lazy init (Slice 1 flat 100 HP; **superseded by [NEO-91 plan](../../plans/NEO-91-implementation-plan.md)** per-archetype catalog max HP + three NPC instance ids); DI via **`AddCombatEntityHealthStore()`** ([NEO-80 plan](../../plans/NEO-80-implementation-plan.md)); [server README — Combat entity health (NEO-80, NEO-91)](../../../server/README.md#combat-entity-health-neo-80-neo-91). **NEO-81 landed:** **`CombatOperations.TryResolve`** + **`CombatResult`** + **`CombatReasonCodes`** — defeated pre-check deny vocabulary (`target_defeated`, `unknown_ability`, `unknown_target`) ([NEO-81 plan](../../plans/NEO-81-implementation-plan.md)); [server README — Combat engine (NEO-81)](../../../server/README.md#combat-engine-neo-81). **NEO-82 landed:** **`AbilityCastApi`** invokes **`CombatOperations.TryResolve`** after E1.M4 gates; nested wire **`combatResolution`** on accept; per-ability catalog **`cooldownSeconds`** on successful resolve; **`target_defeated`** JSON cast deny without cooldown ([NEO-82 plan](../../plans/NEO-82-implementation-plan.md)); [server README — Ability cast (NEO-82)](../../../server/README.md#ability-cast-neo-31-neo-82); Bruno `bruno/neon-sprawl-server/ability-cast/` defeat spine. **NEO-83 landed:** **`GET /game/world/combat-targets`** — `CombatTargetsWorldApi` + DTOs; authoritative HP snapshot from **`ICombatEntityHealthStore`** for client HUD ([NEO-83 plan](../../plans/NEO-83-implementation-plan.md)); [server README — Combat targets snapshot (NEO-83)](../../../server/README.md#combat-targets-snapshot-neo-83); Bruno `bruno/neon-sprawl-server/combat-targets/`. **NEO-44 landed:** **`CombatDefeatGigXpGrant`** on cast **`targetDefeated`** — **25** gig XP to **`breach`** via **`IPlayerGigProgressionStore`** (V007); **`GET …/gig-progression`** ([NEO-44 plan](../../plans/NEO-44-implementation-plan.md)); [server README — Gig progression (NEO-44)](../../../server/README.md#gig-progression-snapshot-neo-44). **NEO-84 landed:** comment-only **`ability_used`** / **`enemy_defeat`** telemetry hook sites in **`CombatOperations.TryResolve`**; reserved **`encounter_start`** / **`player_death`** ([NEO-84 plan](../../plans/NEO-84-implementation-plan.md)); [server README — Combat telemetry hooks (NEO-84)](../../../server/README.md#combat-telemetry-hooks-neo-84). **NEO-85 landed:** client combat HUD — **`combat_targets_client.gd`**, **`CombatTargetHpLabel`**, **`CastFeedbackLabel`** resolution copy; event-driven **`GET /game/world/combat-targets`** refresh ([NEO-85 plan](../../plans/NEO-85-implementation-plan.md), [`NEO-85` manual QA](../../manual-qa/NEO-85.md)); [client README — Combat feedback + target HP HUD (NEO-85)](../../../client/README.md#combat-feedback--target-hp-hud-neo-85). **NEO-86 landed:** playable combat capstone — **`gig_progression_client.gd`**, **`GigXpLabel`**, defeat-triggered gig GET refresh; capstone manual QA [`NEO-86`](../../manual-qa/NEO-86.md) ([NEO-86 plan](../../plans/NEO-86-implementation-plan.md)); [client README — End-to-end combat loop (NEO-86)](../../../client/README.md#end-to-end-combat-loop-neo-86). **Epic 5 Slice 1 complete — register row Ready.**
|
||||
|
||||
**E5.M2 note:** Epic 5 **Slice 2** backlog in Linear ([Epic 5 — PvE Combat and Encounter Content](https://linear.app/neon-sprawl/project/epic-5-pve-combat-and-encounter-content-cf3c94c3-5346-40e0-8aaf-281e846f2846)): [NEO-87](https://linear.app/neon-sprawl/issue/NEO-87) → [NEO-98](https://linear.app/neon-sprawl/issue/NEO-98); label **`E5.M2`**. Client capstone **E5M2-12** [NEO-98](https://linear.app/neon-sprawl/issue/NEO-98). See [E5M2-prototype-backlog.md](../../plans/E5M2-prototype-backlog.md), [E5_M2_NpcAiAndBehaviorProfiles.md](E5_M2_NpcAiAndBehaviorProfiles.md). Upstream **E5.M1 Ready**. **NEO-87 landed:** frozen three-behavior catalog + CI ([NEO-87 plan](../../plans/NEO-87-implementation-plan.md)). **NEO-88 landed:** fail-fast server load of `content/npc-behaviors/*_npc_behaviors.json` ([NEO-88 plan](../../plans/NEO-88-implementation-plan.md)); [server README — NPC behavior catalog](../../../server/README.md#npc-behavior-catalog-contentnpc-behaviors-neo-88). **NEO-89 landed:** injectable **`INpcBehaviorDefinitionRegistry`** + DI ([NEO-89 plan](../../plans/NEO-89-implementation-plan.md)). **NEO-90 landed:** **`GET /game/world/npc-behavior-definitions`** — `NpcBehaviorDefinitionsWorldApi` + DTOs in `Game/Npc/` ([NEO-90 plan](../../plans/NEO-90-implementation-plan.md)); [server README — NPC behavior definitions (NEO-90)](../../../server/README.md#npc-behavior-definitions-neo-90); Bruno `bruno/neon-sprawl-server/npc-behavior-definitions/`. **NEO-91 landed:** **`PrototypeNpcRegistry`** + combat-target migration — three NPC instance ids, per-archetype catalog max HP ([NEO-91 plan](../../plans/NEO-91-implementation-plan.md)); [server README — Combat entity health (NEO-91)](../../../server/README.md#combat-entity-health-neo-80-neo-91). **NEO-92–NEO-96 landed:** aggro/threat, runtime state machine, **`GET …/npc-runtime-snapshot`**, player combat HP + NPC attack resolve, telemetry hooks ([NEO-92](../../plans/NEO-92-implementation-plan.md)–[NEO-96](../../plans/NEO-96-implementation-plan.md)). **NEO-97 landed:** client telegraph HUD ([NEO-97 plan](../../plans/NEO-97-implementation-plan.md), [`NEO-97` manual QA](../../manual-qa/NEO-97.md)). **NEO-98 landed:** playable NPC telegraph combat capstone ([NEO-98 plan](../../plans/NEO-98-implementation-plan.md), [`NEO-98` manual QA](../../manual-qa/NEO-98.md)); [client README — End-to-end NPC telegraph combat loop (NEO-98)](../../../client/README.md#end-to-end-npc-telegraph-combat-loop-neo-98). **Epic 5 Slice 2 complete — register row Ready.** Replaces **`prototype_target_alpha` / `beta`** with three NPC archetype instances; owns **`ThreatState`**, **`TelegraphEvent`**, session **`IPlayerCombatHealthStore`**.
|
||||
|
||||
**E5.M3 note:** Epic 5 **Slice 3** backlog in Linear ([Epic 5 — PvE Combat and Encounter Content](https://linear.app/neon-sprawl/project/epic-5-pve-combat-and-encounter-content-cf3c94c3-5346-40e0-8aaf-281e846f2846)): [NEO-100](https://linear.app/neon-sprawl/issue/NEO-100) → [NEO-111](https://linear.app/neon-sprawl/issue/NEO-111); label **`E5.M3`**. Client capstone **E5M3-12** [NEO-111](https://linear.app/neon-sprawl/issue/NEO-111). See [E5M3-prototype-backlog.md](../../plans/E5M3-prototype-backlog.md), [E5_M3_EncounterAndRewardTables.md](E5_M3_EncounterAndRewardTables.md). Upstream **E5.M2 Ready**, **E3.M3** inventory landed. Prototype spine: one encounter **`prototype_combat_pocket`** (defeat all three E5.M2 NPC ids) → reward table **`prototype_combat_pocket_clear`** ( **`scrap_metal_bulk` ×10**, **`contract_handoff_token` ×1** ); idempotent completion per player; per-defeat gig XP unchanged ([NEO-44](../../plans/NEO-44-implementation-plan.md)). **NEO-100 landed:** encounter + reward-table schemas, prototype catalogs, CI gates ([NEO-100 plan](../../plans/NEO-100-implementation-plan.md)). **NEO-101 landed:** fail-fast server load of `content/encounters/*_encounters.json` + `content/reward-tables/*_reward_tables.json` ([NEO-101 plan](../../plans/NEO-101-implementation-plan.md)); [server README — Encounter + reward-table catalogs (NEO-101)](../../../server/README.md#reward-table-catalog-contentreward-tables-neo-101). **NEO-102 landed:** injectable **`IEncounterDefinitionRegistry`** + **`IRewardTableDefinitionRegistry`** + DI ([NEO-102 plan](../../plans/NEO-102-implementation-plan.md)); [server README — Encounter + reward-table registries (NEO-102)](../../../server/README.md#reward-table-catalog-contentreward-tables-neo-101). **NEO-103 landed:** **`GET /game/world/encounter-definitions`** — `EncounterDefinitionsWorldApi` + nested **`rewardTable`** summary ([NEO-103 plan](../../plans/NEO-103-implementation-plan.md)); [server README — Encounter definitions (NEO-103)](../../../server/README.md#encounter-definitions-neo-103); Bruno `bruno/neon-sprawl-server/encounter-definitions/`. **NEO-104 landed:** **`IEncounterProgressStore`** + **`IEncounterCompletionStore`** + **`EncounterProgressOperations`** ([NEO-104 plan](../../plans/NEO-104-implementation-plan.md)); [server README — Encounter progress (NEO-104)](../../../server/README.md#encounter-progress--completion-stores-neo-104). **NEO-105 landed:** **`EncounterCompletionOperations`** + **`EncounterCompleteEvent`** result payload ([NEO-105 plan](../../plans/NEO-105-implementation-plan.md)); [server README — Encounter completion (NEO-105)](../../../server/README.md#encounter-completion--inventory-grants-neo-105). **NEO-106 landed:** **`EncounterCombatWiring`** on **`AbilityCastApi`** ([NEO-106 plan](../../plans/NEO-106-implementation-plan.md)); [server README — Encounter combat wiring (NEO-106)](../../../server/README.md#encounter-combat-wiring-neo-106). **NEO-107 landed:** **`IEncounterCompleteEventStore`** + E7.M2 hook stub ([NEO-107 plan](../../plans/NEO-107-implementation-plan.md)); [server README — Encounter complete event (NEO-107)](../../../server/README.md#encounter-complete-event-record-neo-107). **NEO-108 landed:** **`GET /game/players/{id}/encounter-progress`** — `EncounterProgressApi` + DTOs ([NEO-108 plan](../../plans/NEO-108-implementation-plan.md)); [server README — Per-player encounter progress (NEO-108)](../../../server/README.md#per-player-encounter-progress-neo-108); Bruno `bruno/neon-sprawl-server/encounter-progress/`. **NEO-109 landed:** comment-only **`encounter_start`**, **`encounter_complete`**, **`reward_attribution`**, **`encounter_complete_denied`** hook sites ([NEO-109 plan](../../plans/NEO-109-implementation-plan.md)); [server README — Encounter telemetry hooks (NEO-109)](../../../server/README.md#encounter-telemetry-hooks-neo-109). **NEO-110 landed:** client encounter progress + loot HUD — **`encounter_progress_client.gd`**, defeat-triggered GET ([NEO-110 plan](../../plans/NEO-110-implementation-plan.md), [`NEO-110` manual QA](../../manual-qa/NEO-110.md)); [client README — Encounter progress + loot HUD (NEO-110)](../../../client/README.md#encounter-progress--loot-hud-neo-110). **E5M3-12 client capstone outstanding** ([NEO-111](https://linear.app/neon-sprawl/issue/NEO-111)).
|
||||
**E5.M3 note:** Epic 5 **Slice 3** backlog in Linear ([Epic 5 — PvE Combat and Encounter Content](https://linear.app/neon-sprawl/project/epic-5-pve-combat-and-encounter-content-cf3c94c3-5346-40e0-8aaf-281e846f2846)): [NEO-100](https://linear.app/neon-sprawl/issue/NEO-100) → [NEO-111](https://linear.app/neon-sprawl/issue/NEO-111); label **`E5.M3`**. Client capstone **E5M3-12** [NEO-111](https://linear.app/neon-sprawl/issue/NEO-111). See [E5M3-prototype-backlog.md](../../plans/E5M3-prototype-backlog.md), [E5_M3_EncounterAndRewardTables.md](E5_M3_EncounterAndRewardTables.md). Upstream **E5.M2 Ready**, **E3.M3** inventory landed. Prototype spine: one encounter **`prototype_combat_pocket`** (defeat all three E5.M2 NPC ids) → reward table **`prototype_combat_pocket_clear`** ( **`scrap_metal_bulk` ×10**, **`contract_handoff_token` ×1** ); idempotent completion per player; per-defeat gig XP unchanged ([NEO-44](../../plans/NEO-44-implementation-plan.md)). **NEO-100 landed:** encounter + reward-table schemas, prototype catalogs, CI gates ([NEO-100 plan](../../plans/NEO-100-implementation-plan.md)). **NEO-101 landed:** fail-fast server load of `content/encounters/*_encounters.json` + `content/reward-tables/*_reward_tables.json` ([NEO-101 plan](../../plans/NEO-101-implementation-plan.md)); [server README — Encounter + reward-table catalogs (NEO-101)](../../../server/README.md#reward-table-catalog-contentreward-tables-neo-101). **NEO-102 landed:** injectable **`IEncounterDefinitionRegistry`** + **`IRewardTableDefinitionRegistry`** + DI ([NEO-102 plan](../../plans/NEO-102-implementation-plan.md)); [server README — Encounter + reward-table registries (NEO-102)](../../../server/README.md#reward-table-catalog-contentreward-tables-neo-101). **NEO-103 landed:** **`GET /game/world/encounter-definitions`** — `EncounterDefinitionsWorldApi` + nested **`rewardTable`** summary ([NEO-103 plan](../../plans/NEO-103-implementation-plan.md)); [server README — Encounter definitions (NEO-103)](../../../server/README.md#encounter-definitions-neo-103); Bruno `bruno/neon-sprawl-server/encounter-definitions/`. **NEO-104 landed:** **`IEncounterProgressStore`** + **`IEncounterCompletionStore`** + **`EncounterProgressOperations`** ([NEO-104 plan](../../plans/NEO-104-implementation-plan.md)); [server README — Encounter progress (NEO-104)](../../../server/README.md#encounter-progress--completion-stores-neo-104). **NEO-105 landed:** **`EncounterCompletionOperations`** + **`EncounterCompleteEvent`** result payload ([NEO-105 plan](../../plans/NEO-105-implementation-plan.md)); [server README — Encounter completion (NEO-105)](../../../server/README.md#encounter-completion--inventory-grants-neo-105). **NEO-106 landed:** **`EncounterCombatWiring`** on **`AbilityCastApi`** ([NEO-106 plan](../../plans/NEO-106-implementation-plan.md)); [server README — Encounter combat wiring (NEO-106)](../../../server/README.md#encounter-combat-wiring-neo-106). **NEO-107 landed:** **`IEncounterCompleteEventStore`** + E7.M2 hook stub ([NEO-107 plan](../../plans/NEO-107-implementation-plan.md)); [server README — Encounter complete event (NEO-107)](../../../server/README.md#encounter-complete-event-record-neo-107). **NEO-108 landed:** **`GET /game/players/{id}/encounter-progress`** — `EncounterProgressApi` + DTOs ([NEO-108 plan](../../plans/NEO-108-implementation-plan.md)); [server README — Per-player encounter progress (NEO-108)](../../../server/README.md#per-player-encounter-progress-neo-108); Bruno `bruno/neon-sprawl-server/encounter-progress/`. **NEO-109 landed:** comment-only **`encounter_start`**, **`encounter_complete`**, **`reward_attribution`**, **`encounter_complete_denied`** hook sites ([NEO-109 plan](../../plans/NEO-109-implementation-plan.md)); [server README — Encounter telemetry hooks (NEO-109)](../../../server/README.md#encounter-telemetry-hooks-neo-109). **NEO-110 landed:** client encounter progress + loot HUD — **`encounter_progress_client.gd`**, defeat-triggered GET ([NEO-110 plan](../../plans/NEO-110-implementation-plan.md), [`NEO-110` manual QA](../../manual-qa/NEO-110.md)); [client README — Encounter progress + loot HUD (NEO-110)](../../../client/README.md#encounter-progress--loot-hud-neo-110). **NEO-111 landed:** playable encounter clear capstone — [`NEO-111` manual QA](../../manual-qa/NEO-111.md); [client README — End-to-end encounter clear loop (NEO-111)](../../../client/README.md#end-to-end-encounter-clear-loop-neo-111); plan [NEO-111](../../plans/NEO-111-implementation-plan.md). **Epic 5 Slice 3 complete — register row Ready.**
|
||||
|
||||
### Epic 6 — PvP Security
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ Player casts **`prototype_pulse`** (**25** damage, ~**3 s** cooldown).
|
|||
|
||||
- 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).
|
||||
- Full three-NPC loop + idempotency capstone: [NEO-111 manual QA](NEO-111.md).
|
||||
- Component combat regression: [NEO-98 manual QA](NEO-98.md).
|
||||
|
||||
## Acceptance
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
# 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.
|
||||
|
|
@ -363,9 +363,11 @@ Working backlog for **Epic 5 — Slice 3** ([Epic 5 · Slice 3 — encounters an
|
|||
|
||||
**Acceptance criteria**
|
||||
|
||||
- [ ] Human completes script with server + client; loot readable in inventory HUD.
|
||||
- [ ] Epic 5 Slice 3 AC: completing defined encounter grants expected items + quest token **once**.
|
||||
- [ ] Re-read [epic_05 Definition of Done](../decomposition/epics/epic_05_pve_combat.md#epic-5-definition-of-done) for prototype minimums.
|
||||
- [x] Human completes script with server + client; loot readable in inventory HUD.
|
||||
- [x] Epic 5 Slice 3 AC: completing defined encounter grants expected items + quest token **once**.
|
||||
- [x] Re-read [epic_05 Definition of Done](../decomposition/epics/epic_05_pve_combat.md#epic-5-definition-of-done) for prototype minimums.
|
||||
|
||||
**Landed ([NEO-111](https://linear.app/neon-sprawl/issue/NEO-111)):** capstone manual QA [`NEO-111.md`](../manual-qa/NEO-111.md) + [client README — End-to-end encounter clear loop](../../client/README.md#end-to-end-encounter-clear-loop-neo-111); plan [NEO-111-implementation-plan.md](NEO-111-implementation-plan.md). **Epic 5 Slice 3 client capstone complete.**
|
||||
|
||||
**Client counterpart:** this issue (**NEO-111**).
|
||||
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@
|
|||
|
||||
## Implementation reconciliation (shipped)
|
||||
|
||||
**Manual QA:** [`docs/manual-qa/NEO-110.md`](../manual-qa/NEO-110.md) — passed (Godot defeat chain, progress **1/3 → 2/3 → completed**, loot + inventory). **PR #149** merged to `main`.
|
||||
|
||||
- **`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`**.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,160 @@
|
|||
# NEO-111 — Implementation plan
|
||||
|
||||
## Story reference
|
||||
|
||||
| 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 |
|
||||
| **Module** | [E5.M3 — EncounterAndRewardTables](../decomposition/modules/E5_M3_EncounterAndRewardTables.md) · Epic 5 Slice 3 · backlog **E5M3-12** |
|
||||
| **Branch** | `NEO-111-playable-encounter-clear-capstone` |
|
||||
| **Client deps** | [NEO-110](https://linear.app/neon-sprawl/issue/NEO-110) encounter progress + loot HUD (**Done**); E5.M1 cast + gig XP ([NEO-86](https://linear.app/neon-sprawl/issue/NEO-86)); E5.M2 NPC combat ([NEO-98](https://linear.app/neon-sprawl/issue/NEO-98)) |
|
||||
| **Server deps** | [NEO-106](https://linear.app/neon-sprawl/issue/NEO-106) combat wiring · [NEO-108](https://linear.app/neon-sprawl/issue/NEO-108) encounter-progress GET · [NEO-105](https://linear.app/neon-sprawl/issue/NEO-105) completion grants (**Done** on `main`) |
|
||||
| **Pattern** | Capstone integration — [NEO-98](NEO-98-implementation-plan.md) / [NEO-86](NEO-86-implementation-plan.md) docs + manual QA primary; minimal gap-fill only if capstone QA fails on `main` |
|
||||
| **Server counterpart** | NEO-100–NEO-109 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-98](NEO-98-implementation-plan.md) precedent. | **Adopted** — docs-primary |
|
||||
| **Session baseline** | Fresh server vs fixture POST? | **Fresh server restart** before Godot **F5** — resets NPC HP, encounter progress, inventory, and gig XP; zero Bruno/curl in main checklist. | **Adopted** — fresh restart; no Bruno/curl |
|
||||
| **Defeat order** | Fixed vs flexible order in script? | **Melee → Ranged → Elite** for script clarity. | **Flexible** — any order; script asserts **0/3 → 3/3** progression only |
|
||||
| **Idempotency check** | How to prove loot grants once? | **Godot stop + F5 restart** (server still running) + casts on defeated NPCs; inventory counts unchanged. Dev fixture POST clears encounter completion — **not** used. | **Adopted** — Godot restart + defeated-NPC casts |
|
||||
| **NEO-110 relationship** | Supersede component QA? | **NEO-111 supersedes as Slice 3 capstone**; keep [NEO-110](../manual-qa/NEO-110.md) as component-level regression (NEO-85 / NEO-86 pattern). | **Adopted** |
|
||||
|
||||
## Goal, scope, and out-of-scope
|
||||
|
||||
**Goal:** Prove Epic 5 Slice 3 acceptance **in Godot**: defeat all three E5.M2 NPCs, receive **`scrap_metal_bulk` ×10** + **`contract_handoff_token` ×1** **once**, verify inventory — without Bruno.
|
||||
|
||||
**In scope (from Linear + [E5M3-12](E5M3-prototype-backlog.md#e5m3-12--playable-encounter-clear-capstone-godot)):**
|
||||
|
||||
- **`docs/manual-qa/NEO-111.md`**: numbered **single-session** capstone script — fresh dev player, **flexible defeat order**, zero Bruno/curl steps in the main checklist; **idempotency** via Godot restart + casts on defeated NPCs.
|
||||
- **`client/README.md`**: **End-to-end encounter clear loop** section — integration flow table (boot → engage → defeat ×3 → loot → inventory → idempotency); cross-links NEO-106–NEO-110.
|
||||
- **Module alignment** (on story completion): update [`documentation_and_implementation_alignment.md`](../decomposition/modules/documentation_and_implementation_alignment.md) E5.M3 row, [E5_M3](../decomposition/modules/E5_M3_EncounterAndRewardTables.md) status note, and [E5M3-prototype-backlog.md](E5M3-prototype-backlog.md) E5M3-12 checkboxes; mark Epic 5 Slice 3 client capstone complete.
|
||||
- **Integration fixes only if capstone QA fails** on current `main` wiring (unexpected deny, HUD refresh gap, inventory drift, idempotency breach, etc.).
|
||||
|
||||
**Out of scope (from Linear + backlog):**
|
||||
|
||||
- Group scaling ([E5.M4](../decomposition/modules/E5_M4_GroupCombatScaling.md)), dynamic spawn ([E4.M2](../decomposition/modules/E4_M2_SpawnEcologyController.md)).
|
||||
- Final loot VFX art; encounter selection UI beyond frozen **`prototype_combat_pocket`**.
|
||||
- Bruno-only verification as prototype-complete proof.
|
||||
- New server HTTP routes or Godot HUD features beyond NEO-110.
|
||||
|
||||
## Acceptance criteria checklist
|
||||
|
||||
- [x] Human completes **`docs/manual-qa/NEO-111.md`** with server + client; loot readable in inventory HUD.
|
||||
- [x] Epic 5 Slice 3 AC: completing defined encounter grants expected items + quest token **once** (idempotency steps pass).
|
||||
- [x] Re-read [epic_05 Definition of Done](../decomposition/epics/epic_05_pve_combat.md#epic-5-definition-of-done) for prototype minimums.
|
||||
|
||||
## Implementation reconciliation (shipped)
|
||||
|
||||
**Manual QA:** [`docs/manual-qa/NEO-111.md`](../manual-qa/NEO-111.md) — passed (Godot defeat chain any order, **0/3 → completed**, loot + inventory, Godot restart idempotency).
|
||||
|
||||
- **`docs/manual-qa/NEO-111.md`** — single-session capstone checklist with idempotency + regression steps.
|
||||
- **`client/README.md`** — **End-to-end encounter clear loop (NEO-111)** section with flow table and cross-links.
|
||||
- **`docs/manual-qa/NEO-110.md`** — cross-link to NEO-111 capstone.
|
||||
- **`docs/plans/E5M3-prototype-backlog.md`**, **`E5_M3_EncounterAndRewardTables.md`**, **`documentation_and_implementation_alignment.md`**, **`module_dependency_register.md`** — E5M3-12 landed; E5.M3 **Ready**; Epic 5 Slice 3 client capstone complete.
|
||||
- **No integration code changes** — docs-primary scope; server encounter spine verified by existing **`EncounterCombatWiringTests`** / **`EncounterProgressApiTests`** / **`AbilityCastApiTests`**.
|
||||
|
||||
## Technical approach
|
||||
|
||||
### 1. Capstone manual QA script (`docs/manual-qa/NEO-111.md`)
|
||||
|
||||
**Preconditions:** Stop any running server; start fresh (`cd server/NeonSprawl.Server && dotnet run`) so in-memory **`dev-local-1`** NPC HP, encounter progress, inventory, and gig XP reset. Godot **F5** with **no** prior curl/Bruno seeding. **`Economy HUD`** toggle **on** for inventory verification.
|
||||
|
||||
**Archetype reference** (defeat order **flexible** — server tracks order-independent subset):
|
||||
|
||||
| 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** (from NEO-110; count is **`defeatedTargetIds.size()`**):
|
||||
|
||||
| After | `EncounterProgressLabel` | `EncounterCompleteLabel` |
|
||||
|-------|--------------------------|---------------------------|
|
||||
| Boot | `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` + `contract_handoff_token ×1` |
|
||||
| Idempotency (post-restart) | still **`completed (3/3)`** | unchanged grant lines |
|
||||
|
||||
**Main checklist spine:**
|
||||
|
||||
1. Start server + Godot **F5**; confirm boot encounter HUD **0/3**.
|
||||
2. Defeat **three** prototype NPCs in **any order** (Tab lock + **1** per archetype until **`— defeated!`**).
|
||||
3. After each defeat: verify **`EncounterProgressLabel`** advances **1/3 → 2/3 → completed (3/3)** (may lag one GET behind cast).
|
||||
4. On completion: **`EncounterCompleteLabel`** lists both grants; **`InventoryLabel`** shows **`scrap_metal_bulk`** and **`contract_handoff_token`** without pressing **I**.
|
||||
5. **Record inventory quantities** for both grant items (note baseline if bag had prior items from earlier sessions — fresh restart should be empty or known baseline).
|
||||
6. **Idempotency — Godot restart:** stop Godot run; **F5** again **without** stopping server. Verify encounter HUD still **`completed (3/3)`**; inventory quantities **unchanged** (no duplicate loot).
|
||||
7. **Idempotency — defeated NPC casts:** lock a defeated NPC; press **1** — **`CastFeedbackLabel`** shows **`ability_cast_denied: target_defeated`**; encounter + inventory unchanged.
|
||||
8. Regression: **`GigXpLabel`** shows **`breach`** XP increased per defeat during step 2 (NEO-86); no extra gig XP spike during idempotency steps.
|
||||
|
||||
**Notes section:** cross-link [NEO-110](../manual-qa/NEO-110.md) for HUD component detail; [NEO-98](../manual-qa/NEO-98.md) for NPC combat regression; explain why dev **`POST /game/__dev/combat-targets-fixture`** is **out of scope** (clears encounter completion — unsuitable for idempotency).
|
||||
|
||||
### 2. Client README (`client/README.md`)
|
||||
|
||||
Add **End-to-end encounter clear loop (NEO-111)** section after [Encounter progress + loot HUD (NEO-110)](../../client/README.md#encounter-progress--loot-hud-neo-110), mirroring NEO-98 / NEO-86 capstone sections:
|
||||
|
||||
- One-line Epic 5 Slice 3 capstone goal.
|
||||
- Flow table: fresh restart → boot → defeat ×3 (any order) → progress HUD → loot label → inventory → Godot restart idempotency.
|
||||
- Cross-links: NEO-106 combat wiring, NEO-108 GET, NEO-110 HUD components, NEO-98 NPC combat.
|
||||
- Pointer to **`docs/manual-qa/NEO-111.md`**.
|
||||
|
||||
### 3. Module / backlog alignment (on land)
|
||||
|
||||
When capstone QA passes:
|
||||
|
||||
- [E5M3-prototype-backlog.md](E5M3-prototype-backlog.md) — E5M3-12 AC checkboxes.
|
||||
- [E5_M3_EncounterAndRewardTables.md](../decomposition/modules/E5_M3_EncounterAndRewardTables.md) — module status **Ready**; Slice 3 client capstone note.
|
||||
- [documentation_and_implementation_alignment.md](../decomposition/modules/documentation_and_implementation_alignment.md) — E5.M3 row: NEO-111 landed; Epic 5 Slice 3 client capstone complete.
|
||||
- [module_dependency_register.md](../decomposition/modules/module_dependency_register.md) — E5.M3 **Ready** if all stories landed.
|
||||
|
||||
### 4. Integration fixes (conditional)
|
||||
|
||||
Run capstone QA on `main` (or branch with NEO-110 merged). If any step fails:
|
||||
|
||||
- Document failure in plan **Implementation reconciliation**.
|
||||
- Minimal fix in client or server; add/adjust automated test only when fix is non-trivial.
|
||||
- Re-run full capstone script before land.
|
||||
|
||||
## Files to add
|
||||
|
||||
| Path | Purpose |
|
||||
|------|---------|
|
||||
| `docs/plans/NEO-111-implementation-plan.md` | This plan. |
|
||||
| `docs/manual-qa/NEO-111.md` | Single-session Godot capstone script with idempotency steps. |
|
||||
|
||||
## Files to modify
|
||||
|
||||
| Path | Rationale |
|
||||
|------|-----------|
|
||||
| `client/README.md` | **End-to-end encounter clear loop (NEO-111)** section with flow table and cross-links. |
|
||||
| `docs/plans/E5M3-prototype-backlog.md` | E5M3-12 acceptance checkboxes when capstone lands. |
|
||||
| `docs/decomposition/modules/E5_M3_EncounterAndRewardTables.md` | Module status + capstone landed note. |
|
||||
| `docs/decomposition/modules/documentation_and_implementation_alignment.md` | E5.M3 row — NEO-111 capstone complete. |
|
||||
| `docs/decomposition/modules/module_dependency_register.md` | E5.M3 status **Ready** when slice complete. |
|
||||
|
||||
**Conditional (only if capstone QA fails):** client scripts (`main.gd`, `encounter_progress_client.gd`, …) or server encounter path — document paths in **Implementation reconciliation**.
|
||||
|
||||
## Tests
|
||||
|
||||
| Test file | What it covers |
|
||||
|-----------|----------------|
|
||||
| *(none planned at kickoff)* | Capstone is manual Godot verification; NEO-110 GdUnit tests cover encounter-progress GET client. |
|
||||
|
||||
**If integration fix required:** add or extend the smallest automated test that locks the fix (GdUnit for client parse/HUD helper; C# AAA for server deny/idempotency). Otherwise manual QA replaces automated coverage per [NEO-98](NEO-98-implementation-plan.md) precedent.
|
||||
|
||||
## Open questions / risks
|
||||
|
||||
| Item | Agent recommendation | Status |
|
||||
|------|----------------------|--------|
|
||||
| **NEO-110 on `main` at capstone run time** | Confirm NEO-110 merged before executing capstone QA; branch may need rebase onto `main`. | **adopted** — NEO-110 merged (PR #149) on branch |
|
||||
| **Inventory baseline on fresh restart** | Script instructs tester to note pre-grant bag state; fresh restart should yield empty or predictable baseline. | **adopted** |
|
||||
| **Concurrent GET lag on progress label** | Allow ~1 s after cast before asserting progress step (NEO-110 manual QA note). | **adopted** |
|
||||
| **Capstone QA scope expansion** | Kickoff was docs-primary; capstone QA may drive minimal integration fixes — document in **Implementation reconciliation**. | **deferred** |
|
||||
Loading…
Reference in New Issue