1. 03 Jul, 2026 11 commits
  2. 25 Jun, 2026 3 commits
  3. 23 Jun, 2026 5 commits
    • Mahmoud Aglan's avatar
      fix: draw offer race condition + add multiplayer logging · 9b2a459c
      Mahmoud Aglan authored
      Root cause: draw offers stored in game_state were lost when a
      concurrent move write did read→merge→write (non-atomic). Now uses
      PostgreSQL jsonb || operator via merge_game_state() RPC for atomic
      merges.
      
      Also adds:
      - mp_log table for server-side multiplayer event logging
      - Frontend sessionStorage logging (sessionStorage.mp_log) for
        debugging draw offers, moves, and poll events
      - Logging on match_created, move, resign, draw_accepted, game_state_merge
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      9b2a459c
    • Mahmoud Aglan's avatar
      test: add chess sync verification test with move+resign proof · 2f9d7d84
      Mahmoud Aglan authored
      Screenshots confirm: moves sync to opponent board, resign shows
      victory screen. Both directions verified via Puppeteer + API.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      2f9d7d84
    • Mahmoud Aglan's avatar
      fix: chess moves/resign silently failing — non-existent columns · b3109e7a
      Mahmoud Aglan authored
      The `matches` table has no `last_activity` or `ended_at` columns.
      PostgREST rejects the entire PATCH when ANY column doesn't exist,
      causing every move update and resignation to silently fail.
      
      - Remove `last_activity` from handleGameMove (column doesn't exist)
      - Change `ended_at` to `completed_at` in handleResign, handleDraw,
        handleComplete (correct column name per DB schema)
      
      This was the root cause of zero sync in multiplayer chess.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      b3109e7a
    • Mahmoud Aglan's avatar
      fix: bulletproof matchmaking queue across all games · 1c145579
      Mahmoud Aglan authored
      - Add dequeue handler to backgammon-match.php (was missing)
      - Add 90-second stale entry cleanup to ludo/domino/backgammon queues
      - Add atomic opponent claiming (conditional update) to prevent race conditions
      - Fix client queue.js to route dequeue to correct game endpoint
      - Register unmountQueue for proper cleanup when exiting search screen
      - Remove json_encode on jsonb fields in backgammon (prevent double-encoding)
      
      Fixes: self-matching, ghost queue entries, and race condition where two
      players simultaneously claim the same opponent.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      1c145579
    • Mahmoud Aglan's avatar
      fix: eliminate jsonb double-encoding that broke multiplayer sync · 6517bd2d
      Mahmoud Aglan authored
      The root cause: PHP's json_encode() was used on jsonb fields before
      passing to SupabaseClient->insert/update, which json_encodes the entire
      payload. This double-encoded game_state into a JSON string scalar.
      
      When the match_heartbeat RPC did `jsonb_string || jsonb_object`,
      PostgreSQL created an array instead of merging, corrupting game_state.
      The polling logic then couldn't find move_count or last_move in the
      array, so moves never synced between players.
      
      Fix: pass PHP arrays directly for all jsonb columns (game_state, moves,
      positions, scores, winners, hands, boneyard). The Supabase client
      handles encoding once at the HTTP layer.
      
      Also: when reading game_state back from the DB, handle the case where
      PostgREST returns it as a decoded array/object (not a string) since
      jsonb columns are deserialized automatically.
      
      Affected: chess, ludo, domino — all multiplayer match creation and
      move/state updates.
      Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
      6517bd2d
  4. 22 Jun, 2026 1 commit
  5. 21 Jun, 2026 4 commits
  6. 20 Jun, 2026 8 commits
  7. 19 Jun, 2026 8 commits