6a860f2c13
expandRecurringEvents() iterates from the event's original start date, generating all occurrences within the requested window using the existing nextOccurrence() service (max 1000 iterations). The SQL query is extended to also fetch recurring events that started before the window. Event duration is preserved across instances. Virtual instances carry is_recurring_instance=1 and are shown with a repeat icon in the agenda view. /upcoming expands across a 90-day forward window. Closes BL-01. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>