Skip to content

Online: per-color abandonment forfeit timers#161

Open
testtest126 wants to merge 1 commit into
mainfrom
claude/smiley-face-1xzfkz-abandon-forfeit
Open

Online: per-color abandonment forfeit timers#161
testtest126 wants to merge 1 commit into
mainfrom
claude/smiley-face-1xzfkz-abandon-forfeit

Conversation

@testtest126

@testtest126 testtest126 commented Jul 12, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes a realtime multiplayer correctness bug: a disconnected player could escape the abandonment forfeit when their opponent had also briefly dropped and returned.

LiveGame held a single shared abandonTask. When both players are disconnected:

  1. White drops → abandonTask = White's 60s forfeit timer.
  2. Black drops → abandonTask = Black's timer. White's task reference is overwritten — the task keeps running but is now uncancellable.
  3. White reconnects → connect cancels whatever abandonTask currently points at — now Black's forfeit. White's orphaned timer later fires but is a no-op (White is back).

Net effect: the genuinely-absent player (Black) never forfeits. The abandonment path hangs until a clock happens to expire (potentially minutes later), defeating the 60s grace guarantee.

Fix: track forfeit timers per color ([PieceColor: Task]) so a reconnecting player cancels only their own pending forfeit; the opponent's still stands. finish cancels both. The grace period is now injectable (mirroring the existing clock / rematchWindow / matchmaking test seams) so the regression resolves in ~1.5s instead of 60.

Scope / gates

  • Security-sensitive: no — no auth/token/crypto/account-linking code. This is game-session connection lifecycle (abandonment forfeit), not authentication-session management. Flagging explicitly per rule 5 so the orchestrator can veto if it reads it differently.
  • App-touching: no — server package only; iOS lane N/A.
  • Shared files: none — does not touch ChessOnline/Messages.swift.

Test plan

New testReconnectDoesNotCancelAbsentOpponentsForfeit in MatchFlowTests: boots the real server, drops both players (White then Black), reconnects White inside the grace window, and asserts Black still forfeits (game_over 1-0 / abandoned) on White's reconnected socket. Pre-fix, White's reconnect cancels Black's forfeit, no game_over arrives, and the test times out.

CI is the verifier — this session can't build the Swift toolchain locally (proxy blocks the toolchain download), so the boxes below track the Server tests lane:

  • swift test in ChessKit/ passes — N/A (no ChessKit change)
  • swift test in chess-server/ passes — via the Server tests CI lane
  • App builds / relevant UI tests pass — N/A (no app change)

A LiveGame held a single shared abandonTask, so when both players
disconnected the second disconnect overwrote the first's timer
reference (the orphaned task kept running but became uncancellable),
and a later reconnect cancelled whichever forfeit the shared field
then pointed at — the still-absent opponent's. The abandoner escaped
the 60s forfeit and the game hung until a clock happened to expire.

Track forfeit timers per color so a reconnecting player cancels only
their own; the opponent's still stands. The grace period is now
injectable so the regression test resolves in ~1.5s instead of 60.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E9dkcpbwWWHrdGzpvWZd1T
@testtest126 testtest126 marked this pull request as draft July 12, 2026 17:53
@testtest126 testtest126 marked this pull request as ready for review July 12, 2026 18:21
@testtest126 testtest126 enabled auto-merge (squash) July 12, 2026 18:21

Copy link
Copy Markdown
Owner Author

@orchestrator — merge request for three completed, non-security PRs that are all fully CI-green and stuck only on the orchestrator-approval gate (no other session can post it). No merges have occurred repo-wide since ~2026-07-12 20:42 UTC, and #161's combined status is pending with zero commit statuses, so orchestrator-approval was never posted. Requesting approval + merge (sequence as you see fit):

None are security-sensitive (no auth/token/crypto/session code), so rule 5 doesn't apply; none touch ChessOnline/Messages.swift. All review threads resolved. (Posting here because live session messaging isn't available in my environment — this is the sanctioned fallback per CLAUDE.md rule 4.)


Generated by Claude Code

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.

2 participants