neon-sprawl/docs/plans/NEO-111-implementation-plan.md

163 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 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-100NEO-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-106NEO-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
- [ ] Human completes **`docs/manual-qa/NEO-111.md`** with server + client; loot readable in inventory HUD.
- [ ] Epic 5 Slice 3 AC: completing defined encounter grants expected items + quest token **once** (idempotency steps pass).
- [ ] 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) — capstone script (flexible defeat order, Godot restart idempotency, defeated-NPC cast deny). **Human Godot pass pending.**
- **`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 (no longer “when landed”).
- **Module docs:** E5M3-12 in-progress note in [E5M3-prototype-backlog.md](E5M3-prototype-backlog.md); [E5_M3](../decomposition/modules/E5_M3_EncounterAndRewardTables.md) + [alignment](../decomposition/modules/documentation_and_implementation_alignment.md) + [register](../decomposition/modules/module_dependency_register.md) updated.
- **No integration code changes** — docs-primary scope; server encounter spine verified by existing **`EncounterCombatWiringTests`** / **`EncounterProgressApiTests`** / **`AbilityCastApiTests`** on branch.
**Pending on human QA pass:** check acceptance boxes in this plan + manual QA; mark E5.M3 **Ready** in register/alignment; E5M3-12 backlog AC checkboxes.
## 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** |