feat(resign): resign lifecycle — Escape resigns with confirmation#12
Merged
Conversation
- 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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the "Escape leaves the board without resigning" gap from docs/08.
What
resignGame(participant + active checks; opponent wins) broadcasting a newgame_overdelta onMATCH:<gameId>;POST /api/games/[id]/resignMatchDelta=move_applied | game_over(reason:'resign')game_overhandling 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.game_overwith the right winner → post-game moves & repeat resigns 409 →/api/games/currentnull for both players.Verified
54 unit tests + full
pnpm e2egreen; 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