Sub-issue of #146 . PRP 3 milestones M7 (AttackSelect / S05) + M8 (DefenseSelect / S06) + M9 (Phase transitions + TurnState wiring) . Reference: `PRPs/cardshed-03-experience-prp.md` lines 844–913.
Scope
M7 — AttackSelect
`docs/SCREENS/attack-select.md` (Stitch)
`apps/ui/src/features/table/AttackSelect.tsx` — uses `getLegalActions(state, attackerId)` to highlight playable cards; selecting calls `validateAttack(selected, hand)` to enable/disable Send
Dispatch `{ kind: "Attack", playerId, cardIds }`
M8 — DefenseSelect
`docs/SCREENS/defense-select.md` (Stitch)
`apps/ui/src/features/table/DefenseSelect.tsx` + `components/{PendingAttackPanel,BeatPairButton}.tsx`
For each unbeaten attack, on hover highlight counter cards where `canBeat(attack, counter, trump) === true`
Dispatch `{ kind: "Beat", ... }` and `{ kind: "Stop", ... }` (with confirm when partial)
M9 — Phase transitions
`apps/ui/src/components/PhaseTransitionOverlay.tsx` — render the 6 `TurnState` values with distinct affordances; aria-live polite for screen readers
Acceptance
Common bugs (from PRP 3)
Re-implementing `validateAttack` or `canBeat` in the UI (FORBIDDEN — import + call)
Submitting on Enter without explicit confirm — allow mis-clicks
Allowing Stop without confirm at partial-defence point — destructive
Missing the `Resolving` branch (contradiction T10 — Catalog UI + detail view + MCP + E2E dogfood #10 )
Blocking input during transition without a timeout — soft-lock risk
Complexity
M + M + S = ~10–15 hours.
Sub-issue of #146. PRP 3 milestones M7 (AttackSelect / S05) + M8 (DefenseSelect / S06) + M9 (Phase transitions + TurnState wiring). Reference: `PRPs/cardshed-03-experience-prp.md` lines 844–913.
Scope
M7 — AttackSelect
M8 — DefenseSelect
M9 — Phase transitions
Acceptance
Common bugs (from PRP 3)
Complexity
M + M + S = ~10–15 hours.