Whole-tree audit. Every symbol was checked against core, the plugin
monorepo and all eight third-party plugins in plugins.json first.
- Deprecate (removal 3.10.0) plugin-facing methods nothing calls:
LogoDownloader bulk download, ConfigManager backup/secret wrappers,
APIHelper extras, BackgroundDataService poll API, PluginManager /
PluginStateManager info readers, and a few CacheManager, FontManager,
BaseOddsManager, DynamicTeamResolver methods and PluginTestCase.
plugin_api_usage.py learns their receiver names; DEPRECATIONS doc
regenerated.
- Remove core-internal dead code: CacheMetrics, Vegas status/stats
plumbing, sync "new cycle" message (followers ignore unknown types),
unused operation types, test-only PluginCatalog readers, IPC to_dict
and ping, _parse_form_value, CacheStrategyProtocol, ErrorAggregator
callbacks, duplicate web response helpers.
- Web UI: drop never-mounted json-file-manager.js, the example widget,
utils/error_handler.js, four uncalled PluginAPI methods, and 29
escapeHtml shims (call window.LEDEscape directly). Public globals,
BaseWidget and widget names unchanged.
- Remove six one-off scripts (owner decision) and the unused markupsafe
and pytest-mock pins.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Vegas: a live-priority pause was only lifted from inside run_frame(),
which returns before that check while paused, so the ticker never came
back until a restart. run_iteration() now resumes it (the controller
only calls it when nothing preempts Vegas); start()/stop() clear the
pause state. Iteration length is timed with the monotonic clock.
- Dim schedule: a per-day disabled day now updates the minute-gate cache,
so brightness no longer flips back to dim within each minute.
- On-demand: a second request no longer overwrites the rotation resume
index with the first request's mode.
- Render pipeline: reset() drops the prepared group and deferred queue,
and a prefetch in flight across a reset discards its result.
- Sync: stop() removes the status file (and the controller's cleanup now
calls it), standalone removes a stale one at startup, and writes use a
unique mkstemp temp file.
- render_gate.swap_releases_gil() delegates to frame_timing.
- Stale docstrings/comments corrected.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
DisplayManager.offscreen() gives a thread its own canvas, so Vegas renders every plugin's ticker content on its prefetch thread instead of pausing the scroll for canvas-bound plugins on the render thread. A render gate (src/common/render_gate.py, vegas_scroll.prefetch_gate, on by default with the GIL-releasing binding) lets the prefetch thread run Python only while the render thread waits in SwapOnVSync: on hdpi, frames 2+ refreshes late fell eightfold and late frames overall from 0.90% to 0.60%. See docs/OFFSCREEN_RENDERING.md.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>