QA review found a blocker in PR 171: wc:seed_knockout is not safely idempotent after scoring starts. WorldCup2026KnockoutSeed#seed_games! finds existing games by home/away pair but unconditionally writes game.status = "scheduled" on every reseed (app/services/world_cup2026_knockout_seed.rb:177-181). Admin scoring marks games completed, and Contest#games_by_phase buckets completed games by status, so a repeated post-deploy reseed can reopen a completed knockout game as active/scheduled. Preserve existing status/scores for existing games, only default scheduled on new rows, and add a regression test proving completed knockout games stay completed after reseed.
Created
Jun 27, 22:16
Started
Jun 29, 06:30
Completed
Jun 29, 13:38
DevOps handoff
Type
Feature
Shape
ui+db
Worktree Slug
world-cup-knockout-matches
Repositories
turf-monster
Release Slug
—
Branch
feat/world-cup-knockout-matches
Pull Request
https://github.com/amcritchie/turf-monster/pull/171Acceptance Criteria
Expected Test Plan
Checks Run
Agent Context
Mr. McRitchie asked to build Turf Monster remaining matches for the elimination round of the World Cup. Interpret as adding official/current FIFA World Cup knockout/elimination fixtures to Turf Monster and ensuring contest-facing UI can use those slates. Verify current fixture source before hard-coding any dates, teams, or placeholder advancement labels.
Stage Timeline
Who handled each stage, the time it took (measured), and the model / tokens / cost reported (best-effort) — plus who's on it right now. — means the agent didn't report that metric.
Conversation
QA review feedback, agent handoffs, and follow-up notes for this task.
https://mcritchie.studio/tasks/world-cup-knockout-matches PR: https://github.com/amcritchie/turf-monster/pull/171 Branch: feat/world-cup-knockout-matches Local review: http://localhost:3103 Worktree: /Users/alex/projects/turf-monster/.worktrees/world-cup-knockout-matches Implemented idempotent 2026 World Cup knockout seeding with six elimination slates, 32 official knockout fixtures, unresolved bracket-slot placeholder teams, contest generator coverage, docs, and e2e coverage. FIFA source: https://api.fifa.com/api/v3/calendar/matches?language=en&idSeason=285023&count=200 Checks: [unit] knockout seed test; [component] contest knockout slates controller test; [integration] focused seed/controller test run; [e2e] knockout-slates Playwright chromium; [full-suite@5aad9e5c293ab6b80ededaad7f974ab59b738301] bin/rails test green; [rubocop@5aad9e5c293ab6b80ededaad7f974ab59b738301] bin/rubocop clean. DoR passed from the Turf Monster worktree.
Primary review blocked. Product acceptance is not met because the live FIFA FDCP source now resolves several Round of 32 teams that WorldCup2026KnockoutSeed still seeds as placeholders: M79 should be MEX-ECU not MEX-3CEFHI, M80 should be ENG-COD not 1L-3EHIJK, M82 should be BEL-SEN not BEL-3AEHIJ, M83 should be POR-CRO not 2K-2L, and M87 should be COL-GHA not 1K-3DEIJL. Update the knockout fixtures, docs, and assertions against https://api.fifa.com/api/v3/calendar/matches?language=en&idSeason=285023&count=200, keeping placeholders only for truly unresolved slots. DoR is also not merge-ready: bin/dor-check reports the recorded full-suite and RuboCop certifications are stale for older commit 5aad9e5 while PR HEAD is 9d5b4b2; rerun bin/full-suite-check world-cup-knockout-matches or record an explicit justified bypass after the fixture update. Finally, PR 171 is still marked draft in GitHub; mark it ready before re-submitting for deploy-lane merge. Evidence from review: targeted bin/rails test test/services/world_cup2026_knockout_seed_test.rb test/controllers/contest_knockout_slates_test.rb passed locally; GitHub CI checks were green, but those do not satisfy the current task DoR fingerprint.
https://mcritchie.studio/tasks/world-cup-knockout-matches Rework complete for QA blocker. PR: https://github.com/amcritchie/turf-monster/pull/171 Branch: feat/world-cup-knockout-matches Head: b2f38e7 Update World Cup knockout fixtures Local review: http://localhost:3103 Addressed current FIFA FDCP source changes: M79 MEX-ECU, M80 ENG-COD, M82 BEL-SEN, M83 POR-CRO, M84 ESP-AUT, M85 SUI-ALG, M87 COL-GHA. Removed stale group/third-place placeholder labels from active placeholders and added reseed cleanup for obsolete unselected placeholder matchups/games/teams. Placeholder count is now 32 advancement slots. Proof: focused Rails test passed (5 runs, 47 assertions); focused RuboCop clean; worktree db:seed converged to final 112 teams with Round of 32 obsolete placeholders absent; Playwright knockout e2e passed; full-suite-check passed at fingerprint a708295abb3717c0b598d05a3c18012acd9e5bf0 (2009 runs, 9275 assertions, 0 failures, 0 errors, 5 skips; 526 RuboCop files clean); dor-check passed at committed HEAD. PR is no longer draft.
PR 171 cannot advance: run and record full-suite/RuboCop evidence against the latest head after b2f38e7, or an approved bypass, and add a narrow idempotent devops.post_deploy_cmd for the db/seeds.rb WorldCup2026KnockoutSeed data change so QA/prod actually seed the knockout slates; do not use bare db:seed.
https://mcritchie.studio/tasks/world-cup-knockout-matches Rework complete for QA blocker activity-516. PR: https://github.com/amcritchie/turf-monster/pull/171 Branch: feat/world-cup-knockout-matches Head: ba99ca0 Add knockout seed deploy task Local review: http://localhost:3103 Added narrow idempotent post-deploy task `bin/rails wc:seed_knockout` and recorded it in devops.post_deploy_cmd so QA/prod can seed only WorldCup2026KnockoutSeed data without running bare db:seed. Added focused rake-task coverage and documented the deploy command. Proof: focused Rails tests passed (6 runs, 64 assertions); focused RuboCop clean; worktree `bin/rails wc:seed_knockout` passed; full-suite-check passed at fingerprint 95e00e53edd3c309c99022ce5a30198cd54de28d (2025 runs, 9366 assertions, 0 failures, 0 errors, 5 skips; 527 RuboCop files clean); dor-check passed; GitHub CI passed (scan_ruby, scan_js, lint, test, playwright shards 1-3). PR is ready for review.
Current FIFA FDCP data has Match 73 resolved with Canada advancing, so WorldCup2026KnockoutSeed::FIXTURES should seed Match 90 as CAN vs W75 instead of W73 vs W75. Please update the persisted knockout seed data, adjust the focused seed expectations so resolved advancement placeholders are removed when FIFA has a real team, rerun the focused seed/task/controller/E2E checks, and update the PR handoff evidence.
Blocker rework complete for PR 171. Task https://mcritchie.studio/tasks/world-cup-knockout-matches; PR https://github.com/amcritchie/turf-monster/pull/171; branch feat/world-cup-knockout-matches at eeec6715ff4930e1f1e4e79481e60862b534688e; local http://localhost:3103. Current FIFA FDCP check shows Match 73 RSA 0-CAN 1 and Match 90 CAN vs W75; seed now removes obsolete W73 placeholders, creates Match 90 as CAN-W75, and reports 31 advancement placeholders. Evidence: focused seed/task/controller tests green, wc:seed_knockout proof Match 90 CAN-W75 and W73 absent, Playwright E2E green locally, full suite/rubocop certified at 1d82409ce7ce083358beac7362d0fb4f4a9ee616, GitHub CI run 28347891587 all green. Post-deploy command remains bin/rails wc:seed_knockout.
The PR seeds and exposes semifinal, third-place, and final slates with only 4/2/2 matchups, but Turf Totals still requires exactly 6 picks everywhere: Contest#picks_required, Entry#assert_enterable!, and the entry UI gates. The generator can create contests for those slates, but users can never enter them. Rework the slate exposure or pick-count behavior so every generated contest slate is actually playable, then re-review.
Blocker rework complete for PR 171. Task https://mcritchie.studio/tasks/world-cup-knockout-matches; PR https://github.com/amcritchie/turf-monster/pull/171; branch feat/world-cup-knockout-matches at 243676d517e1fd378f517319c4c5c76df6f1b2c6; local http://localhost:3103. Fix: Turf Totals pick requirement now caps at available slate matchup count, so standard/full knockout slates remain 6 picks, semi-finals require 4 picks, and third-place/final require 2 picks. Generator now displays picks required, auth/help/landing copy follows dynamic pick counts, and seeded final-slate contests are covered as enterable with every available matchup. Evidence: focused Rails 71 runs/287 assertions green; wc:seed_knockout proof final and third-place 2 picks, semis 4, Round of 32 6; local knockout Playwright green; full-suite/rubocop certified at 6bff88ab5b3185145e26f41476af92b16d1c3c9f; GitHub CI run 28349860356 all green. Post-deploy command remains bin/rails wc:seed_knockout.
Scout report: merge-ready - No blockers found; PR is ready for Avi merge review. Reporter: avi-scout Outcome: merge-ready Findings: - Fixture data matches FIFA API for matches 73-104, including CAN vs W75. - Short knockout slate pick counts are enforced across backend and UI paths. Questions: - none Checks: - Reviewed PR diff, task metadata, post-deploy command, GitHub checks, FIFA API comparison, and focused local tests.
Scout report: merge-ready - Primary review found no blockers. Reporter: shannon Outcome: merge-ready Findings: - FIFA FDCP fixture constants match matches 73-104, including RSA-CAN and CAN-W75. - Short knockout slate pick counts are wired through contest model, board config, and entry gates. - Non-blocker: older internal backlog docs still mention fixed six picks. Questions: - none Checks: - Reviewed task metadata, PR body, diff, docs, tests, DOR, CI, and git diff hygiene.
Scout report: request-changes - Light backend review found knockout reseed can reopen completed games. Reporter: carl Outcome: request-changes Findings: - WorldCup2026KnockoutSeed#seed_games! unconditionally resets existing game.status to scheduled on each reseed. - Admin completion and live contest buckets depend on completed status remaining intact after scoring starts. - Because wc:seed_knockout is the declared post-deploy command, repeated deploy/reseed can move completed knockout games back to active/scheduled. Questions: - none Checks: - Reviewed task metadata, PR diff, CI, focused tests, release overlap, seed idempotency, and scoring/lifecycle code paths.
QA review found a blocker in PR 171: wc:seed_knockout is not safely idempotent after scoring starts. WorldCup2026KnockoutSeed#seed_games! finds existing games by home/away pair but unconditionally writes game.status = "scheduled" on every reseed (app/services/world_cup2026_knockout_seed.rb:177-181). Admin scoring marks games completed, and Contest#games_by_phase buckets completed games by status, so a repeated post-deploy reseed can reopen a completed knockout game as active/scheduled. Preserve existing status/scores for existing games, only default scheduled on new rows, and add a regression test proving completed knockout games stay completed after reseed.
Blocker rework complete for PR 171. Task https://mcritchie.studio/tasks/world-cup-knockout-matches; PR https://github.com/amcritchie/turf-monster/pull/171; branch feat/world-cup-knockout-matches at 005d6eab00c895eb552964bf1cc7f0e3f59c8f20; local http://localhost:3103. Fix: WorldCup2026KnockoutSeed now assigns scheduled status only for newly-created games, preserving existing completed status and scores across repeated wc:seed_knockout runs. Regression added for completed Match 73 remaining completed after reseed. Evidence: focused Rails 72 runs/290 assertions green; wc:seed_knockout proof completed Match 73 preserved RSA 0-CAN 1; local knockout Playwright green; full-suite/rubocop certified at f35e42d256914f8481c80a14b7e6ec196a782dc9; GitHub CI run 28353300868 all green. Post-deploy command remains bin/rails wc:seed_knockout.
Sealed-bid sizing
Edit →Alex (PM)
—
Avi (PO)
—
Dev
SMALL
Actual
XL
We emailed a one-tap sign-in link to . It expires shortly and can only be used once.
No email? Check spam, or close this and try again.