fix(thressgame-coverage): F1+F4 remediation (T58 RequestChoiceModal + coin-flip kind)

Final Verification Wave found two real blockers:
1. T58 RequestChoiceModal.tsx was marked complete but did NOT exist on disk.
2. request-choice locked 6-kind enum was shipped as 5 (missing 'coin-flip').

Remediation:
- Build RequestChoiceModal.tsx with role=dialog, aria-modal=true, ESC/backdrop close, kind-specific input UI for all 6 kinds (rps / coin-flip / piece / square / column / row); 4 tests
- Add 'coin-flip' to:
  - request-choice primitive paramsSchema enum
  - PendingChoice.kind union (schema.ts + util/pending-choices.ts)
  - WS protocol ChoiceKindSchema (server/protocol.ts)
  - choice-timeout.firstDefaultForKind (defaults to 'heads')
  - broadcast.isValidChoiceValue (accepts 'heads' | 'tails')
- AutoChoiceResolver: deterministic alternating heads/tails for coin-flip

T68 e2e tests remain .skip()'d pending UI integration (modal-into-GameView wiring + activate-descriptor UI) — a follow-up task. The sentinel test asserts the gap exists so when integration lands, skips lift in the documented order.

Tests: 2740 -> 2744 (+4). bun run check exit 0.
This commit is contained in:
Joey Yakimowich-Payne 2026-04-26 14:09:28 -06:00
commit 88581ff6a9
No known key found for this signature in database
17 changed files with 2248 additions and 10 deletions

View file

@ -218,7 +218,7 @@ async function snapshot(page: Page, label: string): Promise<void> {
}
/** Drag a piece (algebraic from/to) — see multiplayer.spec.ts. */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const _drag = async (page: Page, from: string, to: string): Promise<void> => {
await page
.locator(`[data-square="${from}"] [data-piece]`)