NEO-86: Add kickoff implementation plan for combat capstone.
Documents E5M1-12 Godot capstone scope: manual QA script, gig XP HUD client, end-to-end README, and module alignment after kickoff decisions.pull/122/head
parent
87ec781edc
commit
8190614350
|
|
@ -0,0 +1,159 @@
|
|||
# NEO-86 — Implementation plan
|
||||
|
||||
## Story reference
|
||||
|
||||
| Field | Value |
|
||||
|--------|--------|
|
||||
| **Key** | NEO-86 |
|
||||
| **Title** | E5M1-12: Playable tab-target combat capstone (Godot) |
|
||||
| **Linear** | https://linear.app/neon-sprawl/issue/NEO-86/e5m1-12-playable-tab-target-combat-capstone-godot |
|
||||
| **Module** | [E5.M1 — CombatRulesEngine](../decomposition/modules/E5_M1_CombatRulesEngine.md) · Epic 5 Slice 1 · backlog **E5M1-12** |
|
||||
| **Branch** | `NEO-86-playable-combat-capstone` |
|
||||
| **Server deps** | [NEO-82](https://linear.app/neon-sprawl/issue/NEO-82) cast + `combatResolution` (**Done**); [NEO-83](https://linear.app/neon-sprawl/issue/NEO-83) combat-targets GET (**Done**); [NEO-44](https://linear.app/neon-sprawl/issue/NEO-44) gig XP on defeat + GET (**Done**) |
|
||||
| **Client deps** | [NEO-85](https://linear.app/neon-sprawl/issue/NEO-85) combat feedback + target HP HUD (**Done**); E1.M4 cast funnel (NEO-28/31/32) (**Done**) |
|
||||
| **Pattern** | Capstone integration — [NEO-75](https://linear.app/neon-sprawl/issue/NEO-75) docs + manual QA primary; minimal client gap-fill for gig visibility |
|
||||
| **Server counterpart** | NEO-44 gig progression GET; 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 |
|
||||
|--------|----------|----------------------|--------|
|
||||
| **Gig XP visibility** | Include gig XP in the Godot capstone? | **`GigProgressionClient` + `GigXpLabel`** in economy HUD; refresh after defeat cast — NEO-44 landed; NEO-75 capstone is Godot-only (no Bruno/curl). | **User:** Godot gig label + client. |
|
||||
| **Implementation scope** | Docs-only vs client code? | **Docs + manual QA primary**; add gig client wiring; fix integration gaps only if capstone QA fails on `main`. | **User:** docs-first; code for gig row or QA failures. |
|
||||
| **Session baseline** | Fresh server vs fixture POST only? | **Fresh server restart** before Godot **F5** — resets in-memory dummy HP + gig XP baseline (NEO-75 / NEO-44 manual QA precedent). | **Adopted** (kickoff default). |
|
||||
|
||||
No other blocking decisions — combat loop HUD, hotbar pulse bootstrap, and event-driven combat-target refresh are landed in NEO-85; field names follow NEO-82 / NEO-44 server vocabulary.
|
||||
|
||||
## Goal, scope, and out-of-scope
|
||||
|
||||
**Goal:** Prove Epic 5 Slice 1 acceptance **in Godot**: tab-target lock, cast abilities, readable deny reasons, defeat **`prototype_target_alpha`**, and visible gig XP after defeat — without Bruno.
|
||||
|
||||
**In scope (from Linear + [E5M1-12](E5M1-prototype-backlog.md#e5m1-12--playable-tab-target-combat-capstone-godot)):**
|
||||
|
||||
- **`docs/manual-qa/NEO-86.md`**: numbered **single-session** capstone script — fresh dev player, Tab lock alpha, digit cast **`prototype_pulse`** until defeat, verify combat HUD + **`breach`** gig XP — **no Bruno/curl** steps.
|
||||
- **`client/README.md`**: **End-to-end combat loop** section — integration checklist (boot → Tab lock → cast → defeat → gig XP refresh chain); cross-links NEO-23/28/31/85.
|
||||
- **`GigProgressionClient`** + **`GigXpLabel`** — mirror **`SkillProgressionClient`** (NEO-37); boot hydrate + refresh when cast accept carries **`targetDefeated: true`**.
|
||||
- **Module alignment** (on story completion): update [`documentation_and_implementation_alignment.md`](../decomposition/modules/documentation_and_implementation_alignment.md) E5.M1 row + E5M1-12 backlog checkboxes; note Epic 5 Slice 1 client capstone complete.
|
||||
- **Integration fixes only if capstone QA fails** on current `main` wiring (unexpected deny, refresh gap, etc.).
|
||||
|
||||
**Out of scope (from Linear + backlog):**
|
||||
|
||||
- NPC AI (E5.M2), encounters/loot (E5.M3), group scaling.
|
||||
- Final combat VFX, floating damage numbers, player HP bar.
|
||||
- Full nine-gig catalog, hub swap, gig level curves.
|
||||
- Bruno-only verification as prototype-complete proof.
|
||||
|
||||
## Acceptance criteria checklist
|
||||
|
||||
- [ ] Human completes **`docs/manual-qa/NEO-86.md`** with server + client; **`prototype_target_alpha`** shows defeated state in HUD.
|
||||
- [ ] Epic 5 Slice 1 AC: combat readable in fixed isometric camera; no silent cast failures on deny.
|
||||
- [ ] **`breach`** gig XP visible in Godot after defeat (≥ **25** from fresh-server baseline).
|
||||
- [ ] Re-read [epic_05 Definition of Done](../decomposition/epics/epic_05_pve_combat.md#definition-of-done) for prototype minimums.
|
||||
|
||||
## Technical approach
|
||||
|
||||
### 1. Capstone manual QA script (`docs/manual-qa/NEO-86.md`)
|
||||
|
||||
**Preconditions:** Stop any running server; start fresh (`dotnet run`) so in-memory **`dev-local-1`** dummy HP and gig XP reset. Godot **F5** with **no** prior curl/Bruno seeding.
|
||||
|
||||
**Combat math** (from NEO-85 / NEO-82):
|
||||
|
||||
| Cast # | Expected cast feedback | Target HP label |
|
||||
|--------|------------------------|-----------------|
|
||||
| 1 | `Cast: 25 dmg → 75 HP` | `100/100` → `75/100` |
|
||||
| 2 | `→ 50 HP` | `50/100` |
|
||||
| 3 | `→ 25 HP` | `25/100` |
|
||||
| 4 | `→ 0 HP — defeated!` | `0/100 (defeated)` |
|
||||
| 5 | `ability_cast_denied: target_defeated` | unchanged defeated |
|
||||
|
||||
**Checklist outline:**
|
||||
|
||||
1. Start server + client; confirm **`Gig XP:`** row shows **`breach`** at **0** xp (boot hydrate).
|
||||
2. Walk to orange **Dummy α** near spawn; **Tab** lock **`prototype_target_alpha`** — dummy brightens; **`CombatTargetHpLabel`** shows **`100/100`**.
|
||||
3. Press **1** four times (respect ~3s pulse cooldown); verify **`CastFeedbackLabel`** + HP label step as above.
|
||||
4. Verify **`GigXpLabel`** shows **`breach`** **`xp` 25** after lethal hit (event-driven GET refresh).
|
||||
5. Press **1** again — deny feedback; gig XP unchanged.
|
||||
6. **Esc** clear lock — HP label **`— (no lock)`**; combat feedback labels remain readable.
|
||||
7. Regression spot-check: cast without lock → **`invalid_target`** deny on **`CastFeedbackLabel`**.
|
||||
|
||||
Document optional **`POST /game/__dev/combat-targets-fixture`** for mid-session dummy-only reset (NEO-85) — capstone baseline still prefers **server restart**.
|
||||
|
||||
### 2. Gig progression client (`gig_progression_client.gd`)
|
||||
|
||||
Mirror **`skill_progression_client.gd`**:
|
||||
|
||||
- **`GET {base}/game/players/{id}/gig-progression`** — injectable HTTP, **`_busy`** guard.
|
||||
- **`parse_progression_json(text)`** static — require **`schemaVersion` 1**, **`mainGigId`**, **`gigs`** array.
|
||||
- Signals: **`progression_received(snapshot: Dictionary)`**, **`progression_sync_failed(reason: String)`**.
|
||||
- **`gig_row(gig_id: String, snapshot: Dictionary = {}) -> Dictionary`** — lookup by **`id`**; uses cached snapshot when second arg omitted.
|
||||
|
||||
### 3. Gig XP HUD (`main.gd` + `main.tscn`)
|
||||
|
||||
- Add **`GigProgressionClient`** node (scene or runtime like **`CombatTargetsClient`**).
|
||||
- Add **`GigXpLabel`** under **`UICanvas/EconomyHudSection/Body/`** below **`SkillProgressionLabel`**, above **`CraftRecipePanel`** — respects NEO-75 collapse toggle.
|
||||
- **`_render_gig_xp_label()`** — format **`Gig XP:\nbreach: L1 · 25 xp`** (prototype fixed level **1** from server); **`Loading…`** / error lines match skill label pattern.
|
||||
- **Refresh triggers (event-driven):**
|
||||
- Boot: **`request_sync_from_server()`** in setup (parallel to skill progression).
|
||||
- **`cast_result_received`** when **`accepted`** and **`resolution.targetDefeated === true`** → gig progression sync (NEO-44 grant is server-side on that accept; GET reconciles HUD).
|
||||
- Do **not** refresh gig XP on every cast accept — only boot + defeat transition (minimize HTTP chatter).
|
||||
|
||||
### 4. README integration checklist
|
||||
|
||||
New **`## End-to-end combat loop (NEO-86)`** section after NEO-85 combat HUD subsection:
|
||||
|
||||
- Flow in prose: boot hotbar sync (auto pulse bind) → **Tab** lock dummy → digit cast → cast feedback + HP label refresh → defeat → gig XP refresh.
|
||||
- Cross-links: NEO-23 (targeting), NEO-28/31 (cast), NEO-85 (combat HUD), NEO-44 (server gig grant).
|
||||
- Pointer to **`docs/manual-qa/NEO-86.md`** as authoritative capstone script.
|
||||
- Note **`Economy HUD`** toggle hides gig row with other economy labels.
|
||||
|
||||
### 5. Module alignment (implementation batch or story end)
|
||||
|
||||
When acceptance criteria pass:
|
||||
|
||||
- **`documentation_and_implementation_alignment.md`**: E5.M1 — note **NEO-86 landed**, Epic 5 Slice 1 client capstone complete.
|
||||
- **`E5M1-prototype-backlog.md`**: E5M1-12 checkboxes + landed note.
|
||||
- **`E5_M1_CombatRulesEngine.md`**: E5M1-12 row if not already marked.
|
||||
|
||||
### 6. Integration fixes (conditional)
|
||||
|
||||
Run capstone QA on **`main`** wiring before gig client work; if any step fails, fix minimal **`main.gd`** / client bug in this branch and note in plan **Decisions**. Expected path: gig client + docs only.
|
||||
|
||||
## Files to add
|
||||
|
||||
| Path | Purpose |
|
||||
|------|---------|
|
||||
| `docs/plans/NEO-86-implementation-plan.md` | This plan. |
|
||||
| `docs/manual-qa/NEO-86.md` | Capstone single-session manual QA (zero Bruno/curl). |
|
||||
| `client/scripts/gig_progression_client.gd` | GET gig-progression snapshot; parse v1; **`gig_row`** helper. |
|
||||
| `client/scripts/gig_progression_client.gd.uid` | Godot uid companion (tracked). |
|
||||
| `client/test/gig_progression_client_test.gd` | GdUnit: parse snapshot; **`gig_row("breach")`**; HTTP error path. AAA layout. |
|
||||
| `client/test/gig_feedback_refresh_test.gd` | GdUnit: cast accept with **`targetDefeated`** triggers gig sync (spy harness). AAA layout. |
|
||||
|
||||
## Files to modify
|
||||
|
||||
| Path | Rationale |
|
||||
|------|-----------|
|
||||
| `client/scripts/main.gd` | Wire **`GigProgressionClient`**; **`_render_gig_xp_label`**; defeat-triggered gig refresh in **`_on_cast_result_received`**. |
|
||||
| `client/scenes/main.tscn` | Add **`GigProgressionClient`** node + **`GigXpLabel`** under economy HUD body. |
|
||||
| `client/README.md` | End-to-end combat loop section; gig XP row docs; capstone manual QA link. |
|
||||
| `docs/decomposition/modules/documentation_and_implementation_alignment.md` | E5.M1 row — NEO-86 landed + Slice 1 client capstone complete (on story completion). |
|
||||
| `docs/plans/E5M1-prototype-backlog.md` | E5M1-12 acceptance checkboxes + landed note (on story completion). |
|
||||
|
||||
## Tests
|
||||
|
||||
| Path | Change |
|
||||
|------|--------|
|
||||
| `client/test/gig_progression_client_test.gd` | **Add:** GET parse v1 with **`breach`** row; invalid schema → failure signal; 404 path. |
|
||||
| `client/test/gig_feedback_refresh_test.gd` | **Add:** cast accept with **`targetDefeated: true`** triggers **`GigProgressionClient.request_sync_from_server`**; deny / non-defeat accept does not. |
|
||||
|
||||
**Manual verification:** [`docs/manual-qa/NEO-86.md`](manual-qa/NEO-86.md) — server + Godot; full defeat spine + gig XP visibility without curl.
|
||||
|
||||
## Open questions / risks
|
||||
|
||||
| Question or risk | Agent recommendation | Status |
|
||||
|------------------|----------------------|--------|
|
||||
| **Gig refresh on every accept** | Refresh only on **`targetDefeated`** + boot — avoids redundant GETs on non-lethal hits. | **adopted** |
|
||||
| **Gig label inside economy collapse** | Place under **`EconomyHudSection/Body`** — hidden when economy HUD collapsed (NEO-75); combat labels stay visible. | **adopted** |
|
||||
| **Overlap with NEO-85 manual QA** | NEO-86 supersedes as capstone script; keep NEO-85 as component-level regression reference. | **adopted** |
|
||||
| **Postgres dev DB retains gig XP** | Capstone preconditions require **server restart**; document that shared Postgres may show prior totals. | **adopted** |
|
||||
| **Integration gap on `main`** | Run capstone dry-run first; fix only if QA fails. | **pending** (implementation) |
|
||||
Loading…
Reference in New Issue