# NEO-86 — Manual QA checklist

| 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 |
| Plan | `docs/plans/NEO-86-implementation-plan.md` |
| Branch | `NEO-86-playable-combat-capstone` |

## Preconditions

- **Fresh dev player:** stop any running server, then start a new instance so in-memory **`dev-local-1`** dummy HP and gig XP reset.
- **No Bruno/curl seeding** for this checklist — hotbar pulse bind is automatic (NEO-85 dev bootstrap).
- NEO-85 combat HUD and NEO-44 gig progression GET landed on the same branch or `main`.

## Combat math

| Cast # | Expected `CastFeedbackLabel` | `CombatTargetHpLabel` |
|--------|------------------------------|------------------------|
| 1 | `Cast: 25 dmg → 75 HP` | `75/100` |
| 2 | `Cast: 25 dmg → 50 HP` | `50/100` |
| 3 | `Cast: 25 dmg → 25 HP` | `25/100` |
| 4 | `Cast: 25 dmg → 0 HP — defeated!` | `0/100 (defeated)` |
| 5 | `ability_cast_denied: target_defeated` | unchanged defeated |

Respect ~3s **`prototype_pulse`** cooldown between casts.

## Checklist

1. Start server: `cd server/NeonSprawl.Server && dotnet run`.
2. Run Godot main scene (**F5**). Confirm **`Economy HUD`** toggle is **on**; **`GigXpLabel`** shows **`breach: L1 · 0 xp`** after boot hydrate.
3. Walk to orange **Dummy α** west of spawn **`(-3, -3)`** (flat lock ring on ground).
4. Press **Tab** to lock **`prototype_target_alpha`** — dummy **brightens**; **`CombatTargetHpLabel`** shows **`Target HP: prototype_target_alpha 100/100`** (or **`…`** briefly until GET completes).
5. Press **1** (hotbar slot 1 → index 0) four times with cooldown between hits. Verify cast feedback and HP label step per table above.
6. After the lethal hit, **`GigXpLabel`** updates to **`breach: L1 · 25 xp`** (event-driven GET refresh).
7. Press **1** again on the defeated dummy: **`CastFeedbackLabel`** shows **`ability_cast_denied: target_defeated`**; gig XP stays **25**.
8. Press **Esc** to clear lock: **`CombatTargetHpLabel`** shows **`Target HP: — (no lock)`**; combat feedback labels remain readable.
9. Uncheck **`Economy HUD`** — gig row hides with inventory/skills/recipes; check again — gig row repopulates.
10. Regression: cast without lock still shows **`ability_cast_denied: invalid_target`** on **`CastFeedbackLabel`** (NEO-28).

## Notes

- Shared Postgres dev DB may retain prior gig XP totals — capstone baseline prefers **server restart** on in-memory mode.
- Optional mid-session dummy-only reset (Development host): `POST /game/__dev/combat-targets-fixture` — see [NEO-85 manual QA](NEO-85.md).
- Component-level combat HUD regression: [NEO-85 manual QA](NEO-85.md).

## Acceptance

- [ ] Steps 1–10 completable in one session without Bruno/curl.
- [ ] **`prototype_target_alpha`** shows defeated state in HUD after step 5.
- [ ] **`breach`** gig XP **25** visible in Godot after step 6.
- [ ] No silent cast failures — every deny shows readable reason on **`CastFeedbackLabel`**.
