* feat: add March Madness plugin and tournament round logos
New dedicated March Madness plugin with scrolling tournament ticker:
- Fetches NCAA tournament data from ESPN scoreboard API
- Shows seeded matchups with team logos, live scores, and round separators
- Highlights upsets (higher seed beating lower seed) in gold
- Auto-enables during tournament window (March 10 - April 10)
- Configurable for NCAAM and NCAAW tournaments
- Vegas mode support via get_vegas_content()
Tournament round logo assets:
- MARCH_MADNESS.png, ROUND_64.png, ROUND_32.png
- SWEET_16.png, ELITE_8.png, FINAL_4.png, CHAMPIONSHIP.png
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(store): prevent bulk-update from stalling on bundled/in-repo plugins
Three related bugs caused the bulk plugin update to stall at 3/19:
1. Bundled plugins (e.g. starlark-apps, shipped with LEDMatrix rather
than the plugin registry) had no metadata file, so update_plugin()
returned False → API returned 500 → frontend queue halted.
Fix: check for .plugin_metadata.json with install_type=bundled and
return True immediately (these plugins update with LEDMatrix itself).
2. git config --get remote.origin.url (without --local) walked up the
directory tree and found the parent LEDMatrix repo's remote URL for
plugins that live inside plugin-repos/. This caused the store manager
to attempt a 60-second git clone of the wrong repo for every update.
Fix: use --local to scope the lookup to the plugin directory only.
3. hello-world manifest.json had a trailing comma causing JSON parse
errors on every plugin discovery cycle (fixed on devpi directly).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(march-madness): address PR #263 code review findings
- Replace self.is_enabled with BasePlugin.self.enabled in update(),
display(), and supports_dynamic_duration() so runtime toggles work
- Support quarter-based period labels for NCAAW (Q1..Q4 vs H1..H2),
detected via league key or status_detail content
- Use live refresh interval (60s) for cache max_age during live games
instead of hardcoded 300s
- Narrow broad except in _load_round_logos to (OSError, ValueError)
with a fallback except Exception using logger.exception for traces
- Remove unused `situation` local variable from _parse_event()
- Add numpy>=1.24.0 to requirements.txt (imported but was missing)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Chuck <chuck@example.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>