- #1 (correctness): processQualifyingEvent regrouped event_results by placement
using the live group size as the tie count. The "Process Qualifying Points"
button could run mid-bracket and average four placement-3 QF winners down to
7 QP instead of their 9 floor. processQualifyingEvent now delegates bracket
events to processQualifyingBracketEvent (structural tie spans) and skips the
live-count regroup. finalize-bracket simplified to call processQualifyingEvent.
- #2: reprocess-bracket on a finalized qualifying season re-runs
finalizeQualifyingPoints so the deleted final placements are restored.
- #3: replace direct Drizzle deletes in the route with the existing
deleteParticipantResultsBySportsSeasonId model helper.
- #4: extract shared writeEventResultsQP helper; assignCs2EliminationQP and
processQualifyingBracketEvent both use it instead of duplicating the
upsert + recalculateParticipantQP loop.
- #5: extract scoreQualifyingBracket route helper for the repeated branch.
- #6: document that qualifying brackets intentionally skip the fantasy
Recent Scores feed (they surface via QP standings + Discord); scope the
set-winner Discord notification to the entered match.
Adds a regression test locking the structural-tieCount contract (9 QP, not 7).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QVLqaYGXCeSYYqTHZmbRZi