# E1.M4 — Prototype story backlog (AbilityInputScaffold) Working backlog for **Epic 1 — Slice 3** ([interaction, targeting, ability input](../decomposition/epics/epic_01_core_player_runtime.md#epic-1-slice-3)). Decomposition and contracts: [E1.M4 — AbilityInputScaffold](../decomposition/modules/E1_M4_AbilityInputScaffold.md). **Labels (Linear):** every issue **`E1.M4`**; add **`Epic 1`** / Slice 3 as your team prefers. **Precursor (do not re-scope):** selection and targeting authority live in **E1.M3** ([E1.M3 module](../decomposition/modules/E1_M3_InteractionAndTargetingLayer.md)); combat accept/deny remains authoritative in **E5.M1**. **Linear issues (created):** attach `docs/plans/NEO-*-implementation-plan.md` on the same branch as implementation work. | Slug | Linear | |------|--------| | E1M4-01 | [NEO-29](https://linear.app/neon-sprawl/issue/NEO-29/e1m4-01-hotbarloadout-v1-contract-baseline-persistence-path) | | E1M4-02 | [NEO-31](https://linear.app/neon-sprawl/issue/NEO-31/e1m4-02-input-to-abilitycastrequest-path) | | E1M4-03 | [NEO-28](https://linear.app/neon-sprawl/issue/NEO-28/e1m4-03-combat-acceptdeny-integration-reason-code-ux) | | E1M4-04 | [NEO-32](https://linear.app/neon-sprawl/issue/NEO-32/e1m4-04-cooldownsnapshot-sync-slot-presentation) | | E1M4-05 | [NEO-30](https://linear.app/neon-sprawl/issue/NEO-30/e1m4-05-slice-3-telemetry-hooks-for-cast-funnel) | **Dependency graph in Linear:** E1M4-02 blocked by E1M4-01. E1M4-03 blocked by E1M4-02 and minimum E5.M1 accept/deny response contract. E1M4-04 blocked by E1M4-03. E1M4-05 blocked by E1M4-02 and E1M4-03. --- ## Story order (recommended) | Order | Slug | Depends on | |-------|------|------------| | 1 | **E1M4-01** | E1.M3 target lock shape, existing prototype auth/session APIs | | 2 | **E1M4-02** | E1M4-01, E1.M3 target selection flow | | 3 | **E1M4-03** | E1M4-02, E5.M1 accept/deny contract | | 4 | **E1M4-04** | E1M4-03 | | 5 | **E1M4-05** | E1M4-02, E1M4-03 | --- ### E1M4-01 — `HotbarLoadout` v1 contract + baseline persistence path **Goal:** Define a versioned `HotbarLoadout` shape and minimal server-owned read/write flow so clients can bind slots and recover the same loadout on reconnect. **In scope** - Server DTO/API surface (prototype JSON v1) for loadout fetch/update with explicit slot index and ability id fields. - Client load/apply path for initial hotbar hydration. - Validation for slot bounds and unknown ability ids with non-empty reason codes on deny. **Out of scope** - Final account-vs-character policy hardening beyond a documented prototype choice. - Cooldown timing and cast execution. **Acceptance criteria** - [ ] A player can bind at least two slots and retrieve the same bindings after reconnect/reload. - [ ] Invalid slot/ability input is rejected with a stable machine-readable reason code. - [ ] Module docs and per-story implementation plan describe the chosen prototype persistence policy. **Implementation note (NEO-29):** Prototype policy is **per-player** loadout key, persisted via **Postgres when configured** with **in-memory fallback**. --- ### E1M4-02 — Input to `AbilityCastRequest` path (hotbar activation) **Goal:** Wire hotbar input to a real `AbilityCastRequest` payload that includes selected target context from E1.M3. **In scope** - Client input binding (slot key or click) to request emission. - Request payload includes at least slot, ability id, and selected target id (if any). - Integration tests or harness coverage for request formation and send triggers. **Out of scope** - Final combat resolution semantics and cooldown rendering. **Acceptance criteria** - [ ] Pressing a bound slot emits one cast request with expected payload fields. - [ ] Request target context uses last acknowledged target state (not camera-only local guess). - [ ] Unbound slots do not emit requests and expose clear local feedback/logging. --- ### E1M4-03 — Combat accept/deny integration + reason-code UX **Goal:** Consume authoritative cast accept/deny responses from E5.M1 and reconcile client presentation when casts are rejected. **In scope** - Handle accept and deny responses in the cast path. - Surface deny reasons in agreed prototype UX surface (debug panel, toast, or combat log). - Reconcile optimistic UI state on deny. **Out of scope** - Rich final combat feedback package and VFX. **Acceptance criteria** - [ ] Denied casts render a player-visible reason path for at least `invalid_target` and `out_of_range`. - [ ] Successful casts transition to post-request state without conflicting local rollback behavior. - [ ] Denial contract and reason list are documented in plan/module docs to prevent drift. --- ### E1M4-04 — `CooldownSnapshot` sync + slot presentation **Goal:** Add cooldown snapshot contract and hook slot presentation to server cooldown truth. **In scope** - Define `CooldownSnapshot` prototype fields and source route/update mechanism. - Update hotbar slot state (ready, cooling down, remaining time display or indicator). - Gate repeated cast attempts during active cooldown with synchronized behavior. **Out of scope** - Final polished animation treatments for cooldown visuals. **Acceptance criteria** - [ ] After a successful cast, affected slot shows cooling state until cooldown completes. - [ ] Client cannot repeatedly fire a cooling ability without receiving deny/guard behavior. - [ ] Cooldown UI recovers correctly after reconnect by rehydrating snapshot state. --- ### E1M4-05 — Slice 3 telemetry hooks for cast funnel **Goal:** Complete Slice 3 telemetry hook sites for `ability_cast_requested` and `ability_cast_denied` with reason metadata and TODO alignment for E9.M1 schema. **In scope** - Add/verify hook locations in client/server cast flow for requested/denied events. - Include payload notes for ability id, slot id, target context, and deny reason. - Document temporary `TODO(E9.M1)` status where catalog/schema integration is pending. **Out of scope** - Production telemetry ingest pipelines, dashboards, and retention policy work. **Acceptance criteria** - [ ] Hook names match Epic 1 Slice 3 telemetry vocabulary. - [ ] Denied cast hook carries a non-empty reason code. - [ ] Module docs reference where hooks are emitted and what remains deferred to E9.M1. --- ## After this backlog - Track delivery in the created Linear issues and keep dependency links synchronized if scope changes. - For each issue kickoff, add `docs/plans/{NEO-XX}-implementation-plan.md` and keep decisions synchronized during implementation. - Add `docs/manual-qa/{NEO-XX}.md` for user-visible stories when implementation lands. ## Related docs - [E1_M4_AbilityInputScaffold.md](../decomposition/modules/E1_M4_AbilityInputScaffold.md) - [E1_M3_InteractionAndTargetingLayer.md](../decomposition/modules/E1_M3_InteractionAndTargetingLayer.md) - [E5_M1_CombatRulesEngine.md](../decomposition/modules/E5_M1_CombatRulesEngine.md) - [epic_01_core_player_runtime.md](../decomposition/epics/epic_01_core_player_runtime.md)