May 12, 2026
Reconnecting Mail, Calendar, and Contacts
Mail, calendar, and contacts come back online as first-class abilities after a dead-code audit found their handlers unreachable since Phase 4.
Today’s job was fixing a silent regression: Chalie could talk to your inbox, calendar, and contacts at the protocol level, but the LLM had no way to reach any of it. A refactor a few phases back deleted the tool-registration layer those handlers depended on, and nothing failed loudly — the code just went dark. Three integrations sat wired up and completely unused.
The fix was to stop routing capabilities through a generic tool registry and give each one its own ability, discovered the same way every other tool in Chalie is discovered. Email got a proper ability with search, read, and send actions over IMAP/SMTP. Calendar got list_events, get_event, and update_event over CalDAV. Contacts got list and get over CardDAV. Each one delegates straight into the existing capability handler — the protocol work was already solid, it just needed a door back into the conversation. I like this pattern more than the old registry: abilities are self-describing, so the model finds them the normal way instead of through a side-channel lookup table.
The bigger fix was making sync happen without being asked. The subconscious worker — the background loop that already handles idle-time housekeeping — now drives capability sync directly: calendar every 10 minutes, contacts every 60. It runs on a simple counter outside the idle gate, so it doesn’t wait for you to be away from the keyboard. That distinction matters — a lot of what makes an assistant feel present rather than reactive is whether it’s already up to date when you ask, and that only happens if syncing is a background property of the system, not something bolted onto a request.
Cleaning this up also meant admitting what had rotted. Three call sites — the capabilities API, auth, and app bootstrap — were still importing the deleted tool registry and failing silently every time they ran. A 396-line test file that tested that dead code, entirely skipped, got deleted along with it. That’s the real cost of a quiet regression: not just missing functionality, but a widening layer of code that looks like coverage and isn’t. A same-day follow-up commit closed the loop — updating the architecture docs to reflect 17 abilities instead of 14, tightening the email schema so the model doesn’t misuse the subject field across search and send, and clearing a stray unused import the linter flagged.
None of this shipped a new user-facing capability today — mail, calendar, and contacts were always the plan. What shipped was making sure the plan actually runs. The next test is whether background sync holds up under real usage patterns, and whether the abilities give the model enough surface to be genuinely useful rather than just reachable.
-
Mail, calendar, and contacts reconnected as proper Ability subclasses, discovered through the standard find_tools mechanism
-
Email ability covers search, read, and send over IMAP/SMTP
-
Calendar ability covers list_events, get_event, and update_event over CalDAV; contacts covers list and get over CardDAV
-
Subconscious worker now drives background sync directly — calendar every 10 minutes, contacts every 60 — independent of the idle gate
-
Removed three silently-failing dead imports and a 396-line test file that covered only unreachable code