Skip to content

Sport scoreboards: favorite live boost + team exclusion - #170

Merged
ChuckBuilds merged 4 commits into
mainfrom
sports/favorite-live-boost-and-exclude
Jul 6, 2026
Merged

Sport scoreboards: favorite live boost + team exclusion#170
ChuckBuilds merged 4 commits into
mainfrom
sports/favorite-live-boost-and-exclude

Conversation

@ChuckBuilds

@ChuckBuilds ChuckBuilds commented Jul 2, 2026

Copy link
Copy Markdown
Owner

Summary

Addresses user feedback: with both "favorites only" and "show all live" disabled, live games got no favorite-aware treatment at all — it behaved identically to "show all live" with zero prioritization. Adds two new per-league config levers to baseball, basketball, football, hockey, soccer, and lacrosse scoreboards:

  • favorite_live_boost (integer, 1-5, default 2): your favorite's live game is always queued first whenever the live rotation refreshes, and gets N turns for every 1 turn other live games get, via a Smooth Weighted Round-Robin schedule (evenly spaced, not clumped). boost=1 reproduces today's exact rotation order — zero behavior change for anyone who doesn't touch the setting. Never interrupts a game already on screen mid-turn.
  • exclude_teams: hide specific teams from both the live rotation and recent/final scores (spoiler protection for delayed viewing) — takes precedence over every other filter, including show_all_live.

Each plugin bumped to its next minor version with a changelog entry; plugins.json synced.

Draft — open to iterate before merge.

Test plan

  • python3 -m py_compile on every touched .py file across all 6 plugins
  • JSON validity on every touched config_schema.json/manifest.json/plugins.json
  • scripts/check_module_collisions.py — no cross-plugin collisions
  • New/extended test suites per plugin (exclude-wins-over-favorites, exclude-wins-over-show_all_live, boost=1 regression parity, boost=2 even-spacing distribution) — all passing: baseball 4/4, basketball 10/10, football 14/14, hockey 9/9, lacrosse 7/7, soccer 17/17 (7 original + 10 new)
  • LEDMatrix/scripts/check_plugin.py safety harness — PASS on all 7 matrix sizes × all modes for every one of the 6 plugins

🤖 Generated with Claude Code

https://claude.ai/code/session_01KEZK1P1Q1fu5pcuVrkrCFZ

Summary by CodeRabbit

  • New Features
    • Added per-league team exclusion (spoiler protection) and favorite live rotation boosting (exclude_teams, filtering.favorite_live_boost) across multiple scoreboard plugins.
  • Bug Fixes
    • Excluded teams are now consistently hidden from live, recent, and final views (when supported), with higher priority than favorites.
    • Live rotation was updated to spread favorite games more evenly instead of clumping.
  • Documentation
    • Updated READMEs and configuration schemas with the new filtering/rotation options and precedence rules.
  • Tests
    • Added regression coverage for exclusion and boosted live-rotation behavior.
  • Chores
    • Bumped plugin versions and updated release notes.

…l sport plugins

Adds two new per-league config levers to baseball, basketball, football,
hockey, soccer, and lacrosse scoreboards, addressing user feedback that
disabling both "favorites only" and "show all live" gave live games no
favorite-aware treatment at all:

- favorite_live_boost (1-5, default 2): favorite's live game is always
  queued first when the live rotation refreshes and gets N turns for
  every 1 turn other live games get, via a Smooth Weighted Round-Robin
  schedule. Boost=1 reproduces today's exact behavior (no regression for
  users who don't touch it).
- exclude_teams: hide specific teams from both live rotation and
  recent/final scores (spoiler protection for delayed viewing), taking
  precedence over every other filter.

Each plugin bumped to its next minor version; plugins.json synced.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KEZK1P1Q1fu5pcuVrkrCFZ
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fd76d228-cda4-4f9f-8138-5599c3d663c9

📥 Commits

Reviewing files that changed from the base of the PR and between 00775c9 and ad90266.

📒 Files selected for processing (7)
  • plugins/baseball-scoreboard/config_schema.json
  • plugins/basketball-scoreboard/sports.py
  • plugins/basketball-scoreboard/test_favorite_live_boost.py
  • plugins/football-scoreboard/sports.py
  • plugins/football-scoreboard/test_favorite_live_boost.py
  • plugins/soccer-scoreboard/sports.py
  • plugins/soccer-scoreboard/test_live_mode_targeting.py
🚧 Files skipped from review as they are similar to previous changes (5)
  • plugins/basketball-scoreboard/test_favorite_live_boost.py
  • plugins/baseball-scoreboard/config_schema.json
  • plugins/soccer-scoreboard/test_live_mode_targeting.py
  • plugins/soccer-scoreboard/sports.py
  • plugins/basketball-scoreboard/sports.py

📝 Walkthrough

Walkthrough

This PR adds exclude_teams and favorite_live_boost across six scoreboard plugins, wiring the new configuration through schemas, managers, live/recent filtering, weighted rotation, manifests, documentation, and regression tests. plugins.json also advances the published versions and timestamps for the affected plugins.

Changes

Exclude Teams and Favorite Live Boost Feature

Layer / File(s) Summary
Plugin registry version bumps
plugins.json
Updated latest_version and last_updated for baseball, basketball, football, hockey, lacrosse, and soccer scoreboard entries.
Baseball scoreboard: exclude_teams and rotation boost
plugins/baseball-scoreboard/config_schema.json, manager.py, sports.py, manifest.json, README.md, test_favorite_live_boost.py
Adds exclude_teams/favorite_live_boost schema properties for mlb/milb/ncaa_baseball, forwards them via manager, implements weighted rotation and exclusion filtering in SportsLive/SportsRecent, bumps manifest, documents behavior, and adds regression tests.
Basketball scoreboard: exclude_teams and rotation boost
plugins/basketball-scoreboard/README.md, config_schema.json, manager.py, manifest.json, sports.py, test_favorite_live_boost.py
Adds the new filtering config across nba/wnba/ncaam/ncaaw, with exclusion-first live/recent filtering, weighted live rotation, manifest updates, docs, and regression tests.
Football scoreboard: exclude_teams and rotation boost
plugins/football-scoreboard/README.md, config_schema.json, manager.py, manifest.json, sports.py, test_favorite_live_boost.py
Adds the new filtering config for nfl/ncaa_fb, with exclusion-first live/recent filtering, weighted live rotation helpers, manifest updates, docs, and regression tests.
Hockey scoreboard: exclude_teams and rotation boost
plugins/hockey-scoreboard/README.md, config_schema.json, game_filter.py, manager.py, manifest.json, sports.py, test_favorite_live_boost.py
Adds the new filtering config for nhl/ncaa_mens/ncaa_womens, including game-mode exclusion checks, weighted live rotation, manifest updates, docs, and regression tests.
Lacrosse scoreboard: exclude_teams and rotation boost
plugins/lacrosse-scoreboard/README.md, config_schema.json, manager.py, manifest.json, sports.py, test_favorite_live_boost.py
Adds the new filtering config for ncaa_mens/ncaa_womens, including SWRR live rotation, exclusion filtering, manifest updates, docs, and regression tests.
Soccer scoreboard: exclude_teams and rotation boost
plugins/soccer-scoreboard/README.md, config_schema.json, manager.py, manifest.json, sports.py, test_live_mode_targeting.py
Adds the new filtering config for predefined and custom leagues, including stateful SWRR live rotation, exclusion wiring, manifest updates, docs, and regression coverage.

Estimated code review effort: 4 (Complex) | ~75 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change set: new favorite live boost and team exclusion across scoreboards.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sports/favorite-live-boost-and-exclude

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codacy-production

codacy-production Bot commented Jul 2, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 214 complexity

Metric Results
Complexity 214

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@ChuckBuilds

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

ChuckBuilds and others added 2 commits July 2, 2026 23:21
Pre-existing manifest.json had "dependencies": {} but the plugin store's
manifest schema requires an array of strings. Unrelated to this PR's
feature work, but surfaced by CI's manifest-schema validation once this
plugin's manifest changed for the version bump.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KEZK1P1Q1fu5pcuVrkrCFZ
Flagged by Codacy static analysis (F401) on PR #170.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KEZK1P1Q1fu5pcuVrkrCFZ
@ChuckBuilds
ChuckBuilds marked this pull request as ready for review July 3, 2026 11:39
@ChuckBuilds

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
plugins/football-scoreboard/sports.py (1)

1525-1549: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

exclude_teams spoiler-protection is bypassed in the default (no-favorites) recent-games path.

The new exclude filter is only applied inside _select_recent_games_for_display (lines 1542-1549), but that method is only called when self.show_favorite_teams_only and self.favorite_teams (line 1715). When that condition is false — the schema default, and the most common configuration — team_games is built directly from processed_games (lines 1725-1734) with no exclude check anywhere in update(). Excluded teams will still appear in recent/final scores in this (default) case, contradicting the documented behavior ("hides selected teams from both live rotation and recent/final scores... takes precedence over all other filters").

Compare with plugins/lacrosse-scoreboard/sports.py lines 1611-1616, which applies the exclude check unconditionally while building processed_games, before any favorites branching — that is the correct pattern.

🐛 Suggested fix: filter unconditionally when building processed_games
                if is_eligible:
                    game_time = game.get("start_time_utc")
                    if (
                        game_time
                        and game_time >= recent_cutoff
                        and game.get("home_abbr") not in self.exclude_teams
                        and game.get("away_abbr") not in self.exclude_teams
                    ):
                        processed_games.append(game)

(applied around the existing eligibility check, mirroring the lacrosse plugin's implementation)

Also applies to: 1715-1734

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/football-scoreboard/sports.py` around lines 1525 - 1549, The
exclude_teams spoiler filter is only applied inside
_select_recent_games_for_display, but update() can build team_games directly
from processed_games when no favorites are enabled, so excluded teams still leak
into recent/final scores. Move the exclusion check into the main processed_games
construction path in update() (the same eligibility block that appends games),
and keep _select_recent_games_for_display consistent with that behavior so
exclude_teams takes precedence in all paths, similar to the lacrosse plugin’s
unconditional filtering.
🧹 Nitpick comments (4)
plugins/lacrosse-scoreboard/manager.py (1)

719-724: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Consider clamping favorite_live_boost to its documented 1–5 range.

resolve_value returns whatever raw value is in config (including flat/legacy keys) with no bounds check. A misconfigured value (0, negative, or a string) flows straight into manager_config["favorite_live_boost"] and on into the SWRR scheduling logic, which likely assumes a positive integer weight.

♻️ Proposed defensive clamp
         exclude_teams = resolve_value(["teams", "exclude_teams"], ["exclude_teams"], [])
-        favorite_live_boost = resolve_value(["teams", "favorite_live_boost"], ["favorite_live_boost"], 2)
+        favorite_live_boost = resolve_value(["teams", "favorite_live_boost"], ["favorite_live_boost"], 2)
+        try:
+            favorite_live_boost = max(1, min(5, int(favorite_live_boost)))
+        except (TypeError, ValueError):
+            favorite_live_boost = 2
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/lacrosse-scoreboard/manager.py` around lines 719 - 724, The
`favorite_live_boost` value resolved in `manager.py` is passed through without
validation, so clamp it to the documented 1–5 range before storing it in
`manager_config["favorite_live_boost"]`. Update the config handling near
`resolve_value` usage in the teams settings block to coerce invalid or
non-integer inputs to a safe default and ensure the downstream SWRR weighting
logic only receives a positive bounded integer.
plugins/soccer-scoreboard/test_live_mode_targeting.py (1)

53-53: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Solid coverage of _is_favorite_game and _swrr_advance, with an acknowledged gap.

Assertions correctly exercise the real SportsLive methods (not reimplementations) via a bare namespace object, and the boost=1/boost>1/single-game/empty-list cases all match hand-traced expected output. The in-file comment (lines 154-158) already flags that the exclude_teams branch inside SportsLive.update() itself isn't covered here since it needs the full ESPN fetch pipeline mocked.

Want me to draft a test that mocks _fetch_data/_extract_game_details (similar to lacrosse-scoreboard/test_favorite_live_boost.py's _make_live_manager pattern) to close that gap?

Also applies to: 148-240

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/soccer-scoreboard/test_live_mode_targeting.py` at line 53, The test
coverage is missing the exclude_teams branch inside SportsLive.update, so add a
focused test that drives update() through the real method while mocking the ESPN
pipeline. Use SportsLive as the target, and stub _fetch_data and
_extract_game_details (similar to the _make_live_manager pattern in the lacrosse
tests) so you can return controlled game data and verify the exclusion behavior
without hitting live fetches. Ensure the new test exercises update()’s
exclude_teams handling directly and asserts the filtered result.
plugins/basketball-scoreboard/manifest.json (1)

21-26: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Changelog field name inconsistent with football plugin's convention.

This entry uses notes for the changelog description, but football-scoreboard's manifest.json (same PR, same feature) uses changes for its equivalent entry — and changes was already football's established convention prior to this PR. If any shared tooling renders per-plugin release notes from this array, inconsistent field names across plugins will silently drop this entry's description for basketball.

♻️ Suggested fix for naming consistency
     {
       "released": "2026-07-02",
       "version": "1.6.0",
-      "notes": "Add exclude_teams (hide specific teams from live rotation and recent/final scores — spoiler protection) and filtering.favorite_live_boost (tune how much more often your favorite's live game appears in rotation vs other live games) per league.",
+      "changes": "Add exclude_teams (hide specific teams from live rotation and recent/final scores — spoiler protection) and filtering.favorite_live_boost (tune how much more often your favorite's live game appears in rotation vs other live games) per league.",
       "ledmatrix_min": "2.0.0"
     },
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/basketball-scoreboard/manifest.json` around lines 21 - 26, The
basketball-scoreboard manifest release entry uses an inconsistent changelog
field name, so align it with the established convention used by
football-scoreboard. Update the release object in manifest.json to use the same
changelog property name as the other plugin’s manifest (the one consumed by
shared release-note tooling), keeping the description text unchanged. This
should be fixed in the manifest entry containing released, version, and
ledmatrix_min so per-plugin release notes continue to render consistently.
plugins/basketball-scoreboard/test_favorite_live_boost.py (1)

72-116: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

exclude_teams tests exercise a reimplementation, not the real filtering code path.

filter_decision() duplicates the inclusion logic from SportsLive.update() rather than calling it. Cases 1-4 only validate this mirrored copy, so a future change to the real branch order/precedence in update() (lines 2621-2650 in sports.py) wouldn't be caught here. Baseball's and lacrosse's equivalent test files instead build a SportsLive instance, stub _fetch_data, and call live.update() directly — giving true regression coverage of the production code path with comparable setup effort.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/basketball-scoreboard/test_favorite_live_boost.py` around lines 72 -
116, The exclude_teams tests are validating a copied filter_decision helper
instead of the real SportsLive.update() logic, so they won’t catch regressions
in the production branch order. Update this test file to instantiate a
SportsLive via make_live_manager, stub _fetch_data as needed, and exercise
live.update() directly like the baseball and lacrosse tests, then assert against
the resulting live state for the same exclude_teams scenarios.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@plugins/baseball-scoreboard/config_schema.json`:
- Around line 628-641: The `show_all_live` schema block in `config_schema.json`
is missing its closing brace, causing `favorite_live_boost` to be nested under a
boolean property instead of being a sibling under `filtering`. Fix the `milb`
and `ncaa_baseball` schema entries by closing `show_all_live` before defining
`favorite_live_boost`, matching the existing `mlb.filtering` structure. Make
sure the `favorite_live_boost` property remains directly under the same
`filtering` object so it is exposed at the path read by the runtime config
lookup.

---

Outside diff comments:
In `@plugins/football-scoreboard/sports.py`:
- Around line 1525-1549: The exclude_teams spoiler filter is only applied inside
_select_recent_games_for_display, but update() can build team_games directly
from processed_games when no favorites are enabled, so excluded teams still leak
into recent/final scores. Move the exclusion check into the main processed_games
construction path in update() (the same eligibility block that appends games),
and keep _select_recent_games_for_display consistent with that behavior so
exclude_teams takes precedence in all paths, similar to the lacrosse plugin’s
unconditional filtering.

---

Nitpick comments:
In `@plugins/basketball-scoreboard/manifest.json`:
- Around line 21-26: The basketball-scoreboard manifest release entry uses an
inconsistent changelog field name, so align it with the established convention
used by football-scoreboard. Update the release object in manifest.json to use
the same changelog property name as the other plugin’s manifest (the one
consumed by shared release-note tooling), keeping the description text
unchanged. This should be fixed in the manifest entry containing released,
version, and ledmatrix_min so per-plugin release notes continue to render
consistently.

In `@plugins/basketball-scoreboard/test_favorite_live_boost.py`:
- Around line 72-116: The exclude_teams tests are validating a copied
filter_decision helper instead of the real SportsLive.update() logic, so they
won’t catch regressions in the production branch order. Update this test file to
instantiate a SportsLive via make_live_manager, stub _fetch_data as needed, and
exercise live.update() directly like the baseball and lacrosse tests, then
assert against the resulting live state for the same exclude_teams scenarios.

In `@plugins/lacrosse-scoreboard/manager.py`:
- Around line 719-724: The `favorite_live_boost` value resolved in `manager.py`
is passed through without validation, so clamp it to the documented 1–5 range
before storing it in `manager_config["favorite_live_boost"]`. Update the config
handling near `resolve_value` usage in the teams settings block to coerce
invalid or non-integer inputs to a safe default and ensure the downstream SWRR
weighting logic only receives a positive bounded integer.

In `@plugins/soccer-scoreboard/test_live_mode_targeting.py`:
- Line 53: The test coverage is missing the exclude_teams branch inside
SportsLive.update, so add a focused test that drives update() through the real
method while mocking the ESPN pipeline. Use SportsLive as the target, and stub
_fetch_data and _extract_game_details (similar to the _make_live_manager pattern
in the lacrosse tests) so you can return controlled game data and verify the
exclusion behavior without hitting live fetches. Ensure the new test exercises
update()’s exclude_teams handling directly and asserts the filtered result.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2d04654b-79a0-4084-abf2-178756ca29a2

📥 Commits

Reviewing files that changed from the base of the PR and between a7dafcd and 00775c9.

📒 Files selected for processing (38)
  • plugins.json
  • plugins/baseball-scoreboard/README.md
  • plugins/baseball-scoreboard/config_schema.json
  • plugins/baseball-scoreboard/manager.py
  • plugins/baseball-scoreboard/manifest.json
  • plugins/baseball-scoreboard/sports.py
  • plugins/baseball-scoreboard/test_favorite_live_boost.py
  • plugins/basketball-scoreboard/README.md
  • plugins/basketball-scoreboard/config_schema.json
  • plugins/basketball-scoreboard/manager.py
  • plugins/basketball-scoreboard/manifest.json
  • plugins/basketball-scoreboard/sports.py
  • plugins/basketball-scoreboard/test_favorite_live_boost.py
  • plugins/football-scoreboard/README.md
  • plugins/football-scoreboard/config_schema.json
  • plugins/football-scoreboard/manager.py
  • plugins/football-scoreboard/manifest.json
  • plugins/football-scoreboard/sports.py
  • plugins/football-scoreboard/test_favorite_live_boost.py
  • plugins/hockey-scoreboard/README.md
  • plugins/hockey-scoreboard/config_schema.json
  • plugins/hockey-scoreboard/game_filter.py
  • plugins/hockey-scoreboard/manager.py
  • plugins/hockey-scoreboard/manifest.json
  • plugins/hockey-scoreboard/sports.py
  • plugins/hockey-scoreboard/test_favorite_live_boost.py
  • plugins/lacrosse-scoreboard/README.md
  • plugins/lacrosse-scoreboard/config_schema.json
  • plugins/lacrosse-scoreboard/manager.py
  • plugins/lacrosse-scoreboard/manifest.json
  • plugins/lacrosse-scoreboard/sports.py
  • plugins/lacrosse-scoreboard/test_favorite_live_boost.py
  • plugins/soccer-scoreboard/README.md
  • plugins/soccer-scoreboard/config_schema.json
  • plugins/soccer-scoreboard/manager.py
  • plugins/soccer-scoreboard/manifest.json
  • plugins/soccer-scoreboard/sports.py
  • plugins/soccer-scoreboard/test_live_mode_targeting.py

Comment thread plugins/baseball-scoreboard/config_schema.json
Critical: baseball-scoreboard config_schema.json had a missing closing
brace, nesting favorite_live_boost inside show_all_live's boolean schema
for milb/ncaa_baseball - it was never actually exposed as a real config
field for those two leagues (silently fell back to default 2 always).

Major: football-scoreboard's exclude_teams spoiler-protection filter was
only applied inside _select_recent_games_for_display, which is skipped
entirely when show_favorite_teams_only is False (the schema default) -
excluded teams' final scores still leaked through in that default path.
Moved the filter to where processed_games is built so both branches
inherit it; added a regression test that fails without the fix.

Test-quality: extracted the inline live-game inclusion branch in
basketball-scoreboard and soccer-scoreboard into a _classify_live_game()
method (matching football's existing pattern) so their exclude_teams
tests exercise the real production code path instead of a hand-copied
reimplementation. Added direct test coverage for soccer's exclude branch
that was previously only covered by code review.

Investigated and consciously skipped two lower-priority nitpicks:
- basketball's manifest.json "notes" vs football's "changes" changelog
  field name: verified repo-wide "notes" is the dominant convention (10
  plugins) and "changes" is football's own pre-existing outlier, so no
  change needed.
- lacrosse manager.py favorite_live_boost clamping: sports.py already
  clamps it defensively before use, so a second clamp in manager.py
  would be redundant.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KEZK1P1Q1fu5pcuVrkrCFZ
@ChuckBuilds

Copy link
Copy Markdown
Owner Author

Addressed CodeRabbit's findings in ad90266:

🔴 Critical (fixed)baseball-scoreboard/config_schema.json: missing closing brace nested favorite_live_boost inside show_all_live's boolean schema for milb/ncaa_baseball, so it was never actually exposed as a config field for those leagues. Fixed for both.

🟠 Major (fixed)football-scoreboard/sports.py: exclude_teams spoiler protection was only applied inside _select_recent_games_for_display, which is skipped when show_favorite_teams_only=False (the default). Moved the filter to where processed_games is built so both branches inherit it. Added a regression test that fails without the fix (confirmed by reverting locally and re-running).

Nitpicks:

  • Extracted the inline live-inclusion branch in basketball-scoreboard and soccer-scoreboard into a _classify_live_game() method (matching football's existing pattern) so their exclude_teams tests exercise the real production code path instead of a hand-copied mirror. Soccer's previously-acknowledged "needs full ESPN pipeline mock" gap is now closed with direct unit tests against the extracted method.
  • Investigated but did not apply two suggestions after verifying against the full repo history:
    • basketball-scoreboard manifest's "notes" field: repo-wide, "notes" is used in 10 plugins vs "changes" in just football (a pre-existing outlier unique to that plugin, confirmed via git show main). Renaming basketball would reduce consistency, not improve it.
    • lacrosse-scoreboard/manager.py boost clamping: sports.py already clamps favorite_live_boost to 1-5 with a try/except fallback before use, so a second clamp in manager.py would be redundant.

All six plugins' test suites re-run and passing, manifest-schema validation passing for all six, module-collision check clean, and the plugin safety harness re-verified for every plugin touched in this round.

@ChuckBuilds

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@ChuckBuilds
ChuckBuilds merged commit 6e4df1e into main Jul 6, 2026
4 checks passed
@ChuckBuilds
ChuckBuilds deleted the sports/favorite-live-boost-and-exclude branch July 6, 2026 14:30
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