Skip to content

feat(resign): resign lifecycle — Escape resigns with confirmation#12

Merged
snk-js merged 3 commits into
masterfrom
feat/resign
Jul 7, 2026
Merged

feat(resign): resign lifecycle — Escape resigns with confirmation#12
snk-js merged 3 commits into
masterfrom
feat/resign

Conversation

@snk-js

@snk-js snk-js commented Jul 7, 2026

Copy link
Copy Markdown
Owner

Closes the "Escape leaves the board without resigning" gap from docs/08.

What

  • Server: resignGame (participant + active checks; opponent wins) broadcasting a new game_over delta on MATCH:<gameId>; POST /api/games/[id]/resign
  • Protocol: MatchDelta = move_applied | game_over(reason:'resign')
  • Client: game_over handling with won/resigned toasts; Escape during an active match now opens a confirm modal ("Leaving the board resigns the match") → resign → back to lobby. No match / finished match: Escape just leaves and clears the game store.
  • e2e: match suite resigns leftover actives at start (strict precondition restored) and covers resign 200 → opponent receives game_over with the right winner → post-game moves & repeat resigns 409 → /api/games/current null for both players.

Verified

54 unit tests + full pnpm e2e green; match suite is now fully repeatable (cleans up after itself). CI runs on this PR.

Manual check

Mid-game press Escape → confirm → you're in the lobby, opponent gets "You won — your opponent resigned."

🤖 Generated with Claude Code

snk-js and others added 3 commits July 6, 2026 23:15
- service: resignGame (participant + active checks; opponent wins) →
  broadcasts a new game_over delta on MATCH:<gameId>
- route: POST /api/games/[id]/resign (401/403/404/409 mapping)
- protocol: MatchDelta becomes move_applied | game_over(reason:'resign')
- client: matchDeltaHandler handles game_over (won/resigned toasts);
  App.svelte Escape in an ACTIVE match opens a confirm modal ('leaving
  the board resigns the match') → resign → clear game → lobby; when no
  match or already finished, Escape just leaves and clears the store
- e2e: match suite now resigns leftover actives at start (restores the
  strict no-active-game precondition) and covers the full scenario:
  resign 200, opponent gets game_over(resign) with the right winner,
  post-game moves/repeat resigns 409, /api/games/current null for both

54 unit tests + full e2e suite green; match e2e repeatable (leaves no
active games behind).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
tsconfig.json extends ./.svelte-kit/tsconfig.json, generated by
svelte-kit sync. On a clean CI checkout that file is absent, so vitest's
Vite 5 fails resolving the extends (locally it only worked because prior
dev/build runs left .svelte-kit behind). A `pretest` hook doesn't fire —
pnpm has enable-pre-post-scripts off — so inline the sync into the test
script, matching the existing `check` script.

Verified: rm -rf .svelte-kit && pnpm test -> 54 passed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@snk-js snk-js merged commit 4eed10a into master Jul 7, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant