Skip to content

Seed knockout round-1 games from group-stage standings - #52

Merged
ylynfatt merged 1 commit into
mainfrom
seed-knockout-from-groups
Jul 19, 2026
Merged

ylynfatt merged 1 commit into
mainfrom
seed-knockout-from-groups

Conversation

@ylynfatt

Copy link
Copy Markdown
Owner

Summary

Phase ③ of World Cup–style advancement (follows #48, #49). Answers "how do teams carry over from the group stage": the knockout stage page gains a Seed from group stage card for admins.

(Reopened as a fresh PR: the original #50 auto-closed when its stacked base branch knockout-entrant-slots was deleted on merge of #49. Same commit, now targeting main.)

  • SeedStageFromGroups action — the stage-to-stage analog of AdvanceBracketWinner:
    • preview() resolves every entrant slot against the source stage's current standings (group positions via the per-group calculator with all in-group tiebreakers; best_placed ranks via the cross-group ranking) — read-only.
    • execute() re-resolves and fills round-1 home/away in a transaction. Idempotent: re-running after a result correction overwrites the qualifiers — refused once any round-1 game has kicked off.
  • Review card on the stage page (admins only): all resolved matchups shown as Team (Winner Group A) v Team (Best-placed Phase 1: foundational cleanup of teams, games, and results #1), an amber warning while the source stage still has unfinished games, inline errors for unresolvable slots, and a confirm-guarded Apply seeding button posting to the new stages.seed-from-groups route.
  • Stage::previousGroupedStage() extracted to the model, shared by the seeder and the entrant builder's sourceStage prop.

Verified read-only against the real 2026 World Cup dev data: all 32 slots of the configured R32 resolve correctly.

Testing

  • 10 new feature tests: resolution correctness (both descriptor types), preview purity, idempotent re-seed after a result flip, kicked-off refusal, unresolvable-slot errors, missing-source error, page payload for owner vs guest, endpoint authorization
  • Full suite: 431 passed

🤖 Generated with Claude Code

Phase 3 of World Cup style advancement. A knockout stage with entrant
descriptors can now pull its real teams from the previous grouped
stage's standings — auto-resolved, admin-confirmed:

- SeedStageFromGroups action: preview() resolves every slot (group
  position via the per-group standings calculator, best_placed rank via
  the cross-group ranking) without writing; execute() fills round-1
  home/away in a transaction
- Idempotent re-seeding after result corrections, refused once any
  round-1 game has kicked off
- Stage page gains a "Seed from <stage>" review card for admins: every
  resolved matchup, an incomplete-source warning, unresolvable-slot
  errors inline, and an Apply/Re-apply confirm button
- Stage::previousGroupedStage() extracted and shared with the entrant
  builder's sourceStage lookup

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ylynfatt
ylynfatt merged commit eb577a6 into main Jul 19, 2026
1 check passed
@ylynfatt
ylynfatt deleted the seed-knockout-from-groups branch July 19, 2026 20:33
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