# 105 — Move alert evaluation onto the profile actor ## Summary Alert rules are profile-scoped and read metric buckets (`alert_states: HashMap` lives on the single actor's stack frame today), so per [[0001-actor-split]]'s resolved decision, alert evaluation moves with metric computation. Depends on [[104-move-metric-computation-to-profile-actor]] landing first — alert evaluation reads the metric buckets that ticket moves onto `ProfileSnapshot`. ## Where - `src/engine/handle.rs:141` — `let mut alert_states: HashMap = HashMap::new();`, currently a local in the single actor's `run()` loop. - `src/engine/handle.rs`'s `Ingest` arm — today, right after `write.mutate(...)` publishes, the actor does `write.peek()` and calls `alerts::evaluate_alerts(&rules, &mut alert_states, &guard, sequence, timestamp, &text)`, then spawns `alerts::deliver_for_rule` for each fired alert. This whole block moves to wherever the profile actor's per-line processing lives (the watch-wake loop from ticket 103/104). - `src/engine/alerts.rs:139` (`AlertRuntimeState`), `:241` (`evaluate_alerts`), `:384` (`deliver_for_rule`) — signatures take the rules list and a `&EngineSnapshot`-shaped guard; check whether `evaluate_alerts` needs to change its snapshot parameter type to `ProfileSnapshot` (likely yes, since it reads bucket data that now lives there) or whether it can stay snapshot-shape-agnostic via whatever trait/accessor bucket-reading already uses. - Settings access for alert rules/ntfy config (`src/engine/handle.rs:170-177`, `settings.lock().unwrap()`) — this stays available to the profile actor the same way (it's a `SettingsHandle` clone, not primary-actor state), so no primary dependency here. ## Scope - Move `alert_states` ownership to the profile actor's task-local state. - Move the post-publish `evaluate_alerts` call and `deliver_for_rule` spawn to fire from the profile actor's per-line processing, reading `ProfileSnapshot` (post-metric-computation) instead of the primary's `EngineSnapshot`. - Update `evaluate_alerts`'s signature in `src/engine/alerts.rs` if it needs to accept a different snapshot type; keep its actual evaluation logic unchanged — this ticket is a relocation, not a rewrite of alert semantics. - Out of scope: any change to alert rule semantics, ntfy delivery, or the `AlertRuntimeState` model itself — purely which actor owns and drives evaluation.