2c929a0435
Drift-audit Group 8 (final item). _fire_reminders previously gated on the base row (reminder_sent_at IS NULL AND start_dt > now), so a recurring event reminded at most once ever — once the first occurrence passed, no future occurrence qualified. Now recurring events are evaluated every sweep against their next occurrence (rrulestr.after(now)), and reminder_sent_at stores the start of the occurrence last reminded about. Each new occurrence has a distinct marker, so it re-arms and fires exactly once per occurrence. One-shot events keep the classic NULL gate. Also adds the deleted_at filter so trashed events stop reminding. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>