Skip to content

fix(tournament): preserve historical withdrawal state - #58

Merged
sayed710 merged 4 commits into
mainfrom
gemini/tournament-withdrawal-history
Sep 23, 2026
Merged

sayed710 merged 4 commits into
mainfrom
gemini/tournament-withdrawal-history

Conversation

@sayed710

@sayed710 sayed710 commented Sep 20, 2026 •

Copy link
Copy Markdown
Owner

Summary

Preserves historical tournament withdrawal state so Tournament.standingsAfterRound(roundIndex) reports the withdrawn flag truthfully as it actually was at that round, rather than retroactively applying a participant's eventual withdrawal to earlier rounds where they were actively competing.

Isolation & Foundation Alignment

Changes

  1. Per-Player Withdrawal Round Tracking:
    • Captured in Tournament aggregate before forfeits and before synchronous round advancement in tryAdvance().
    • Preserves 0-based round index at time of withdrawal.
    • Idempotent: repeated withdraw() calls never move the withdrawal round forward.
  2. Historical Standings Evaluation:
    • Tournament.standingsAfterRound(roundIndex) evaluates withdrawal status as of roundIndex: active players report withdrawn: false.
    • Tournament.standings() continues to report current withdrawal status unchanged.
  3. Additive Snapshot Contract & Legacy Backward Compatibility:
    • TournamentSnapshot extended with optional withdrawalRounds?: readonly (readonly [string, number])[].
    • Legacy snapshots lacking withdrawalRounds restore cleanly and preserve legacy observable semantics (reporting withdrawn = true across all historical rounds) without requiring database migrations.
  4. ADR-0143:
    • Added docs/adr/0143-tournament-withdrawal-history.md.

Summary by CodeRabbit

  • New Features
    • Historical tournament standings now show players as withdrawn starting with the round in which they withdrew.
    • Withdrawal history is preserved when tournament snapshots are saved and restored.
    • Existing snapshots without withdrawal history remain supported with their prior behavior.
  • Bug Fixes
    • Withdrawals now record the correct round before forfeits or advancement.
    • Repeated withdrawals preserve the original withdrawal round.
  • Documentation
    • Added documentation describing tournament withdrawal history behavior.

@sayed710

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 20, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: acb3015f-f28d-4b58-ac8a-22b18890b2a0

📥 Commits

Reviewing files that changed from the base of the PR and between 8872a6d and 7aaee8d.

📒 Files selected for processing (5)
  • docs/PROJECT_STATE.md
  • docs/adr/0143-tournament-withdrawal-history.md
  • packages/tournament/src/tournament.ts
  • packages/tournament/test/snapshot.test.ts
  • packages/tournament/test/tournament.test.ts

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The tournament records each in-play withdrawal round. Historical standings apply withdrawal status from that round onward. Snapshots preserve optional withdrawal-round metadata, while snapshots without it retain legacy behavior.

Changes

Withdrawal history

Layer / File(s) Summary
Withdrawal tracking and historical standings
packages/tournament/src/tournament.ts, packages/tournament/test/tournament.test.ts
The tournament records the first in-play withdrawal round and applies withdrawal status only from that round onward. Registration withdrawals do not create withdrawal history. Tests cover round-robin and Swiss behavior, forfeits, bye scoring, and final-round withdrawals.
Snapshot persistence and compatibility
packages/tournament/src/tournament.ts, packages/tournament/test/snapshot.test.ts, packages/tournament/test/tournament.test.ts, docs/adr/0143-tournament-withdrawal-history.md, docs/PROJECT_STATE.md
Snapshots serialize and restore optional withdrawal-round data, and omit the field when it is empty. Restoration validates provided entries. Snapshots without the field retain legacy behavior. Tests cover restoration, metadata validation, and snapshot isolation. The ADR and project state document the contract and behavior.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant Player
  participant Tournament
  participant HistoricalStandings
  participant Snapshot
  Player->>Tournament: withdraw during play
  Tournament->>Tournament: record current round
  HistoricalStandings->>Tournament: request standings for a round
  Tournament-->>HistoricalStandings: apply withdrawal-round status
  Tournament->>Snapshot: serialize withdrawal-round metadata
Loading

Suggested reviewers: hessiun710

Merge Risk: ⚪ Minimal · up to 7aaee

Historical tournament standings now show a player as withdrawn only from the round they withdrew, instead of applying it retroactively. This timing is kept through saves and restores, and older saved tournaments behave as before. No outstanding issues were found, and the change looks ready to merge.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: preserving historical tournament withdrawal state.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 3…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Preserve historical tournament withdrawal state

🐞 Bug fix 🧪 Tests 📝 Documentation 🕐 20-40 Minutes

Grey Divider

AI Description

• Records each participant’s withdrawal round before forfeits can advance tournament state.
• Computes historical standings from round-aware withdrawals while preserving current standings
 behavior.
• Extends snapshots compatibly and tests restoration, idempotency, legacy behavior, and isolation.
Diagram

sequenceDiagram
  actor C as Caller
  participant T as Tournament
  participant H as Withdrawal History
  participant S as Snapshot Contract
  participant E as Standings Computation
  C->>T: withdraw(playerId)
  T->>H: record current round
  T->>S: serialize withdrawal rounds
  S-->>T: restore metadata or omit
  C->>T: standingsAfterRound(round)
  T->>H: resolve status at round
  alt Round metadata exists
    H-->>T: compare withdrawal round
  else Legacy snapshot
    H-->>T: preserve withdrawn state
  end
  T->>E: filtered results and status
  E-->>T: standings rows
  T-->>C: historical standings
Loading
High-Level Assessment

The optional per-player withdrawal-round map is the best fit because it preserves precise temporal state with a small, additive snapshot change and no database migration. Deriving withdrawal timing from forfeited games would be unreliable, while event sourcing or a mandatory snapshot migration would add disproportionate complexity.

Files changed (4) +316 / -13

Bug fix (1) +34 / -13
tournament.tsTrack and apply round-specific withdrawal state +34/-13

Track and apply round-specific withdrawal state

• Adds optional withdrawal-round metadata to tournament snapshots and records each player’s first withdrawal round before forfeit side effects. Historical standings now derive withdrawn flags for the requested round, while legacy snapshots and current standings retain their existing behavior.

packages/tournament/src/tournament.ts

Tests (2) +217 / -0
snapshot.test.tsVerify withdrawal history survives snapshot restoration +22/-0

Verify withdrawal history survives snapshot restoration

• Adds snapshot round-trip coverage confirming withdrawal-round metadata is serialized and restored. Verifies historical and current standings remain accurate after restoration.

packages/tournament/test/snapshot.test.ts

tournament.test.tsCover historical withdrawal edge cases +195/-0

Cover historical withdrawal edge cases

• Tests round-aware standings, repeated withdrawals, registration-phase removal, legacy snapshots, synchronous advancement, and defensive snapshot copying. The cases protect both historical correctness and backward compatibility.

packages/tournament/test/tournament.test.ts

Documentation (1) +65 / -0
0143-tournament-withdrawal-history.mdDocument historical withdrawal-state semantics +65/-0

Document historical withdrawal-state semantics

• Records the decision to persist zero-based withdrawal rounds, capture them before synchronous advancement, and preserve legacy snapshot behavior. It also documents persistence, scoring, and pairing invariants.

docs/adr/0143-tournament-withdrawal-history.md

@qodo-code-review

qodo-code-review Bot commented Sep 20, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

Tip of the day
💡 Did you know, you can keep summaries lean with Finding overflow, which tucks the rest behind 'View more'

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Previous reviews

Review updated until commit 7aaee8d ⚖️ Balanced

Results up to commit 2c41683 ⚖️ Balanced


No changes from previous review

Grey Divider

Qodo Logo

@coderabbitai

coderabbitai Bot commented Sep 20, 2026 •

Copy link
Copy Markdown
⚠️ Action not completed

Already reviewed the last commit. Use @coderabbitai full review to rerun a review of the entire changeset.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@sayed710

Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@sayed710

Copy link
Copy Markdown
Owner Author

/review

@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 7aaee8d

@sayed710
sayed710 merged commit 20205c2 into main Sep 23, 2026
11 checks passed
@sayed710
sayed710 deleted the gemini/tournament-withdrawal-history branch September 23, 2026 18:24
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