fix(events): null end_dt no longer matches events outside the window
services/events.py::list_events treated any event with end_dt IS NULL as perpetually matching, so a point-event created last week would be returned as "happening today" whenever the briefing or list_events tool queried today's window. That manifested as briefings claiming past events were scheduled for the current day. Split the null-end branch: point events now only match when start_dt falls within [date_from, date_to]. Events with an end_dt continue to use standard overlap logic. This bug affected both the legacy briefing synthesis and the agentic list_events tool path, since both call the same events service. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,7 @@ import uuid
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
from dateutil.rrule import rrulestr
|
||||
from sqlalchemy import or_, select
|
||||
from sqlalchemy import and_, or_, select
|
||||
|
||||
from fabledassistant.models import async_session
|
||||
from fabledassistant.models.event import Event
|
||||
@@ -85,19 +85,30 @@ async def list_events(
|
||||
dicts (same shape as Event.to_dict()).
|
||||
"""
|
||||
async with async_session() as session:
|
||||
# Match strategy:
|
||||
# - Recurring events: fetch all, expand via rrule below.
|
||||
# - Non-recurring with an end_dt: standard overlap — starts before
|
||||
# date_to and ends after date_from.
|
||||
# - Non-recurring with no end_dt: treat as a point event at
|
||||
# start_dt, include only if start_dt falls within the window.
|
||||
# (Previously this branch matched any event with a null end_dt,
|
||||
# returning all past events as "happening today".)
|
||||
result = await session.execute(
|
||||
select(Event).where(
|
||||
Event.user_id == user_id,
|
||||
# Base window: non-recurring events must overlap range;
|
||||
# recurring events always need to be fetched so they can be expanded.
|
||||
or_(
|
||||
Event.recurrence.isnot(None),
|
||||
Event.start_dt <= date_to,
|
||||
),
|
||||
or_(
|
||||
Event.end_dt.is_(None),
|
||||
Event.end_dt >= date_from,
|
||||
Event.recurrence.isnot(None),
|
||||
and_(
|
||||
Event.recurrence.is_(None),
|
||||
Event.start_dt <= date_to,
|
||||
or_(
|
||||
Event.end_dt >= date_from,
|
||||
and_(
|
||||
Event.end_dt.is_(None),
|
||||
Event.start_dt >= date_from,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
).order_by(Event.start_dt)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user