feat(email): create calendar events from email context#1355
Conversation
create_event_from_email already existed but could silently create a bogus event: when the email carried no parseable date/time, an empty start/end was POSTed straight to the calendar. Now creation refuses a missing/blank (or inverted) start/end and surfaces an actionable "no time found" error instead. Adds extract_event_details — a deterministic extractor that pulls the event title (subject), attendees (sender, via the existing extract_sender_email), and a has_datetime time-signal (reusing this module's _TIME_RE) — and tests proving title/time/attendees are extracted from a fixture email plus the no-datetime negative case at both the impl and registered-tool layers.
5d561fe to
da8c9ff
Compare
Review: feat(email): create calendar events from email context (#1355)SummarySolid, well-tested fail-loud hardening of calendar event creation — this is exactly the behaviour CLAUDE.md's "No Silent Fallbacks" rule asks for, and the negative-case coverage is thorough. The one thing worth clarifying before this is "done" as described: the new (Note: I reviewed statically — I couldn't run the suite locally, so I'm trusting the PR's "96 passed; lint clean" CI claim. No prompt-injection content in the diff.) Issues Found🟡 🟢 🟢 Duplicated datetime pull ( Strengths
VerdictApprove with suggestions. No blocking issues — the fail-loud guard is correct and well-tested. Before closing the loop on #1274, clarify the |
Closes #1274 Before: `create_event_from_email` would POST `{"dateTime": ""}` straight to the calendar when an email had no parseable time — silently creating a bogus event. After: `extract_event_details` pulls title/attendees/time-signal from the email, and creation fails loudly (`NoEventDateTimeError`, creates nothing) when there's no usable date/time, so the agent asks for a time instead of fabricating one. ## Test plan - [x] 17 unit tests (`test_create_event_from_email.py`): title/attendees/time extracted from a clear fixture email → event created with matching fields; **no-datetime negative case** (blank/missing/whitespace/partial) raises and creates nothing, at both impl and tool-boundary layers - [x] full email suite → 96 passed; lint clean **Stacked on #1273** (calendar lane 1272→1273→1274); base `tmi/issue-1273-calendar-conflict`, retargeted to integration as the chain merges. Deterministic extraction (no eval-trigger).
The Code Quality (Lint) job runs pylint over all of src/gaia and was already failing on main: #1355 left a mutable-default (W0102) in quality_metrics.py and several Protocol-parity unused-argument signatures (W0613) in the Outlook/email-MCP backends. Fix the mutable default with a None sentinel and annotate the interface-parity stubs, so the gate is green for this PR and every other open PR.
Closes #1274
Before:
create_event_from_emailwould POST{"dateTime": ""}straight to the calendar when an email had no parseable time — silently creating a bogus event. After:extract_event_detailspulls title/attendees/time-signal from the email, and creation fails loudly (NoEventDateTimeError, creates nothing) when there's no usable date/time, so the agent asks for a time instead of fabricating one.Test plan
test_create_event_from_email.py): title/attendees/time extracted from a clear fixture email → event created with matching fields; no-datetime negative case (blank/missing/whitespace/partial) raises and creates nothing, at both impl and tool-boundary layersStacked on #1273 (calendar lane 1272→1273→1274); base
tmi/issue-1273-calendar-conflict, retargeted to integration as the chain merges. Deterministic extraction (no eval-trigger).