Found reviewing #117.
get_latest_panel_payload returns the wire's signals` dict raw:
signals = body.get("signals") or {}
...
"signals": signals,
Nothing projects it, so _alarm_if_all_dropped — which can only ever see what a projection dropped — is blind to it. It guards the two feed projections only.
Nothing server-side reads sentiment_score. The browser does:
Number(s.sentiment_score).toFixed(2) // -> "NaN" if the key is missing
So a producer rename of sentiment_score renders NVDA NaN in every chip with no drop, no exception, no degraded badge, no ERROR log. The feed keeps building (it reads headline/url/source/published), so the drift alarm cannot fire. That is the 2026-07-14 title/link outage one field over, and the score -> sentiment_score rename passed within inches of it.
Pre-existing; not introduced by #117. Fixed in #120.
Found reviewing #117.
get_latest_panel_payloadreturns the wire'ssignals` dict raw:Nothing projects it, so
_alarm_if_all_dropped— which can only ever see what a projection dropped — is blind to it. It guards the two feed projections only.Nothing server-side reads
sentiment_score. The browser does:So a producer rename of
sentiment_scorerendersNVDA NaNin every chip with no drop, no exception, nodegradedbadge, no ERROR log. The feed keeps building (it readsheadline/url/source/published), so the drift alarm cannot fire. That is the 2026-07-14title/linkoutage one field over, and thescore->sentiment_scorerename passed within inches of it.Pre-existing; not introduced by #117. Fixed in #120.