## Partial bracket scoring
- `processMatchResult`: new exported function that scores a single match
immediately (loser → final placement, winner → provisional floor).
Called from `set-winner` and `set-round-winners` so points are awarded
as soon as a winner is set, before the full round is complete.
- `set-winner`: passes `eventName` to `processMatchResult`.
- `set-round-winners`: batches side effects — calls `recalculateAffectedLeagues`
and `updateProbabilitiesAfterResult` once after the loop instead of per-match
(`skipSideEffects: true` per match).
## Code review fixes
- **ROUND_CONFIG** (S1): extracted a `RoundScoringConfig` lookup table +
`getRoundConfig()` helper, eliminating three parallel `if/else` chains in
`processPlayoffEvent`, `processMatchResult`, and `getGuaranteedMinimumPosition`.
AFL template overrides live in `TEMPLATE_ROUND_CONFIG` with an explanatory
comment about why the `bracketTemplateId` guard is required.
- **skipSideEffects** (C2): new param on `processMatchResult`; bracket server
uses it to batch standings/probability recalc in `set-round-winners`.
- **eventName** (W1): passed through `processMatchResult` → `recalculateAffectedLeagues`.
- **Round validation** (W2): `set-round-winners` now guards `match.round === round`
before processing each assignment.
- **Comments** (C3/S3/W3): added notes on non-scoring loser assumption,
`isScoring ?? true` default, and AFL Semi-Finals template requirement.
## PlayoffBracket eliminated-teams fix + tests
- Fixed `computeEliminatedByRound` to track participant *appearances* (not just
wins), so AFL QF losers who advance to Semi-Finals via double-chance are
correctly excluded from the QF eliminated list.
- Extracted the logic as an exported pure function for testability.
- Added 4 tests: standard elimination, AFL QF loser → SF win, AFL QF loser →
SF loss, and normal advancement not protecting a later loser.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Show leagues where user is a member regardless of team assignment
The homepage now uses a union query to show leagues where the user
either has a team in the current season OR is a commissioner. Previously,
commissioners without a team could not see their leagues on the homepage.
https://claude.ai/code/session_01E3ugKTfatkEc5TcDGXvHiW
* Fix stale empty state card title in home route
Update 'No Active Leagues' to 'No Leagues' to match the updated
description which is now about membership rather than active seasons.
https://claude.ai/code/session_01E3ugKTfatkEc5TcDGXvHiW
* Fix union import: use two queries with JS deduplication
drizzle-orm 0.36.x does not export a standalone union() function.
Replace with two awaited queries merged via a Map (dedup by id),
then sorted by createdAt descending in JS.
https://claude.ai/code/session_01E3ugKTfatkEc5TcDGXvHiW
---------
Co-authored-by: Claude <noreply@anthropic.com>