Skip to content

feat: round-recap script + fix stuck-LIVE knockout poller gap - #141

Merged
dommango merged 2 commits into
mainfrom
worktree-round-recap-script
Jul 12, 2026
Merged

dommango merged 2 commits into
mainfrom
worktree-round-recap-script

Conversation

@dommango

@dommango dommango commented Jul 12, 2026 •

Copy link
Copy Markdown
Owner

Two related changes that came out of prepping the post-quarterfinals update email.

1. scripts/round-recap.ts — generalized recap for the update email

Read-only ops helper for drafting the per-round Knockout Challenge update email. Generalizes scripts/r32-recap.ts to any knockout round and folds in the standings block from scripts/challenge-progress.ts, so one run prints all three sections:

DATABASE_URL=... npx tsx scripts/round-recap.ts [ROUND]   # R32|R16|QF|SF|FINAL, default QF
  1. Round results — scorelines from Match/Result, ⚡ PENALTIES flag; skips non-FINAL.
  2. Next-round matchups — now-set pairings via resolveBracket(officialResults).
  3. Knockout Challenge progress — entrant count, top-10, perfect-R32 count, average score.

Additive; existing r32-recap.ts / challenge-progress.ts untouched. Reused for SF + Final.

2. lib/sports/poll.ts — fix knockout matches stranded LIVE past their window

shouldPollNow() only polled when a match's scheduledAt was within [now-155min, now+5min]. A knockout match whose full-time result lands after that window closes (extra time + shootout, long stoppages, or a lagging FT status) was stranded LIVE forever — the window closed before the finalizing poll ran, so FINAL was never fetched.

Observed live: QF match 100 froze at its in-play snapshot (2-1, LIVE) when its window closed ~2h35m after kickoff; every poll since returned skipped: "no match in live window", so scores + SF seeding stalled for ~13h.

Fix: add a backstop — keep polling any scored match (bronze 103 excluded; never finalized via the API) that has kicked off but isn't FINAL yet, for a generous grace period after kickoff. Self-terminating once it flips to FINAL.

Note: match 100 was finalized manually in prod (Argentina 2-1, authoritative MANUAL entry) to unblock the semifinals/recap immediately; this fix prevents recurrence for SF & Final.

Verification

  • npm run typecheck clean for changed files; npx vitest run lib/sports lib/pool → 416 passed.
  • Ran round-recap.ts QF against prod: all four QF final, SF = France v Spain / England v Argentina, standings recomputed (avg 22.9 → 25.9 after QF points applied).

🤖 Generated with Claude Code

dommango-sys added 2 commits July 12, 2026 10:54
Generalizes scripts/r32-recap.ts to any knockout round (R32/R16/QF/SF/FINAL,
default QF) and folds in the standings block from scripts/challenge-progress.ts,
so one run prints that round's scorelines, the next round's now-set matchups, and
Knockout Challenge standings/progress. Read-only ops helper for drafting the
per-round update email; reused for the remaining rounds (QF tonight, then SF, Final).

Run: DATABASE_URL=... npx tsx scripts/round-recap.ts [ROUND]
The score poller's shouldPollNow() only fetched when a match's scheduledAt fell
within [now-155min, now+5min]. A knockout match whose full-time result lands after
that window closes (extra time + shootout, long stoppages, or a lagging FT status
from the feed) was stranded LIVE forever: the window closed before the finalizing
poll ever ran, so the FINAL status was never fetched. Observed live — QF match 100
froze at its last in-play snapshot (2-1, LIVE) when its window closed ~2h35m after
kickoff, and every poll since returned skipped:"no match in live window".

Add a backstop: keep polling any scored match (bronze 103 excluded — never
finalized via the API) that has kicked off but isn't FINAL yet, for a generous
grace period after kickoff. Self-terminating once the match flips to FINAL.
@dommango dommango changed the title feat: generalized round-recap script for update emails feat: round-recap script + fix stuck-LIVE knockout poller gap Jul 12, 2026
@dommango
dommango marked this pull request as ready for review July 12, 2026 17:08
@dommango
dommango merged commit 0599978 into main Jul 12, 2026
1 check passed
@dommango
dommango deleted the worktree-round-recap-script branch July 12, 2026 17:08
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