fix(slack): real root cause — preserve all NotifierState fields across notify_* chain
Summary
This is the real root cause of the daily-brief spam (and the original trends spam). The Colima/virtiofs cache theory was a red herring — the previous anchor workarounds patched symptoms.
Four notify_* functions silently dropped state fields:
- notify_pending_approvals dropped notified_anomaly_run_ids, notified_trend_keys, last_trends_digest_at, last_daily_brief_date
- notify_latest_digest dropped same set
- notify_metric_anomalies dropped notified_trend_keys, last_trends_digest_at, last_daily_brief_date
- notify_readiness_change dropped same set
Since run_notifier chains these calls, by the time notify_daily_brief ran its dedup check last_daily_brief_date was already reset to '' — the brief re-posted every tick.
Fix
Replace every new_state construction with dataclasses.replace(state, ...) so unrelated fields carry through untouched.
Test plan
-
4 regression tests pin the invariant (38/38 pass) -
APEX Review semantic_reviewer @ 0.98 confidence flagged the pattern -
Confirm no more brief posts after deploy (monitor notifier logs)