Repository navigation
Conversation
When a multiplayer game ends, the Game Over panel now shows each player's rating change, the feats and defeats earned that game, and a paged stat sheet for punches, big moments, and the token ledger. Each player may send one canned parting shot for their result and one comeback once the other player's shot lands. Rage Quit games keep their single reply instead. get_game_recap reads feats and ratings for a game's own players only, and the parting_shot action appends to the game state through commit_game_move so the four-line cap holds across devices. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 482fe80911
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const effectiveTurns = getEffectiveStatTurns(turns); | ||
|
|
||
| return { | ||
| ...scoreSwings(effectiveTurns, players), |
There was a problem hiding this comment.
Replay score removals when calculating historical leads
When a scored turn is subsequently punched or mulliganed, getEffectiveStatTurns excludes it entirely, so scoreSwings calculates a history in which that score never existed. For example, Alice scoring 20, Bob scoring 50, and Alice punching Bob before he rescores 10 produces zero lead changes and a biggest lead of Alice by 20; the actual game had two lead changes and Bob leading by 30. Replay submissions and their later removals chronologically for these historical metrics rather than using only the turns that survive in the final scorecard.
Useful? React with 👍 / 👎.
Move the recap migration after main's Glicko and feat migrations so it applies in order on the hosted database. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…a recap page The Game Over panel now tells one story: the result and margin, rating changes on the score cards, the three best highlights, the latest parting shot with one button to answer it, then Rematch and Recap. Lines are picked in a bottom sheet and sent with Send. The numbers moved to a scrollable Tale of the Tape page with mirrored bars, every feat, and head-to-head stats. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e1d2f33d1a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| data: { result_seen_at: null }, | ||
| match: { game_id: gameId, player_id: recipientId }, |
There was a problem hiding this comment.
Resurface new parting shots on games older than seven days
When a player sends a parting shot on a game completed more than seven days ago, clearing result_seen_at does not return it to the recipient's active list. get_unseen_game_results still requires game.completed_at > now() - interval '7 days' (supabase/schema.sql:537), and the lobby only resurfaces completed games with has_unseen_result. Consequently, these newly delivered messages remain under Completed Games, or disappear from the loaded list entirely if the game is outside the latest 25 completions. Since parting shots explicitly have no time limit, update the unseen-result lookup to recognize fresh post-game messages rather than relying solely on the original completion date.
Useful? React with 👍 / 👎.
Rendered by CI on Linux. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Summary
When a multiplayer game ends, the Game Over panel now recaps the game and gives both players a last word.
Implementation
20261023120000_add_end_game_recap.sql: theparting_shotaction type, andget_game_recap(target_game_id), which is participant-only.player_featsand other players' results stay closed to direct reads.schema.sqland the database types are updated to match.game-action: a newparting_shot { gameId, lineId }action appends tostate.partingShotsthroughcommit_game_move. Its version check keeps the cap race-safe across devices, as with Rage Quit replies.shared/partingShots.tsholds the lines and the rules for who can send what. It's mirrored intosupabase/functions/_shared, and a test keeps the two copies in step.shared/gameRecap.tsbuilds the stat sheet from turns and actions that participants can already read.src/ui/GameRecap.tsxrenders the recap;src/multiplayer/gameRecap.tsloads it once per finished game.docs/end-game-recap.mddescribes the feature.Independent of #122. With #122 merged, instant feats are already stored before the game ends; the recap reads them the same way.
Needs the migration applied and a
game-actiondeploy.Testing
npm run typecheck,npm run typecheck:edge,npm run test,npm run test:edge,npm run lintnpm run test:integration:supabase(48 passed): a new test covers the one-shot-plus-one-comeback cap, wrong-result and free-text lines being rejected,result_seen_atbeing reset, andget_game_recaprefusing non-participants.🤖 Generated with Claude Code