161 lines
12 KiB
Markdown
161 lines
12 KiB
Markdown
# 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** |
|