One scheduled task, one cluster at a time. The expensive parts, listing and querying, are batched per cluster, and the part that must never repeat, announcing, is guarded by an atomic claim.
Batched
Three queries per cluster: period burn, 5-minute burn and 1-hour burn, matched back to each SLO by label. Cost no longer grows with the number of SLOs.
One runner
The scheduler runs the task on one replica at a time. The claim covers the remaining case, a timed-out run still going when the next one starts.
Who gets it
Everyone, by default. Set recentActivity.slo.recipients to owner to send to the app's catalog owner instead; an app with no owner still broadcasts.