0.23.1 — Architectural fix for dead TB/PM rows
Replaces 0.22.3's click-to-learn band-aid with a proper pre-verification cycle. TB and PM now get checked at warmer time using their non-destructive cache APIs and only verified-cached rows are advertised. RD stays best-effort because its API doesn't allow a clean check.
🔥 Warmer cache-verifies TB + PM every 3h (STREAM_CACHE_REFRESH_HOURS). Uses WARMER_TB_TOKEN / WARMER_PM_KEY env vars (cache state is global on both providers, so one key answers for everyone on the instance). Set either or both to enable.
🎯 /stream row builder advertises TB/PM rows only when the warmer marked them cached; skips verified-not-cached; falls back to denylist+optimistic for unverified.
🧱 Denylist factory — lib/provider-denylist.js backs per-provider denylists for RD/TB/PM with the same dual-TTL semantics (hard 30d, soft 24h).
🛡️ TB + PM source modules also self-denylist on click failures as a safety net for hashes the warmer hasn't reached.
🥊 Boxing tile cropping fixed — useDefaultArt: true on the boxing promotion (same knob F1 uses); per-event fighter portraits replaced by the clean league banner.
Upgrading: set WARMER_TB_TOKEN and/or WARMER_PM_KEY in .env before redeploying so verification activates immediately. Without them, the addon falls back to 0.22.3 behaviour (optimistic + denylist). After the first warmer cycle (~3h after deploy or trigger manually with npm run refresh-streams), TB/PM rows in Discover should noticeably stop including dead clicks.