Add Google Calendar sync support#418
Conversation
roborev: Combined Review (
|
roborev: Combined Review (
|
roborev: Combined Review (
|
Squashed branch commits: - feat(vector): support scoped embedding builds - fix(vector): enqueue synctech sms imports - fix(search): honor message_type filter in local FTS query path - feat(store): add SetMessageMetadata and GetSourcesByTypeAndAccount - feat(gmail): add NewRateLimiterWithCapacity + Calendar operations - feat(gcal): add read-only Google Calendar API v3 client - feat(oauth): add Calendar scopes + parameterize scope escalation - feat(calsync): calendar sync orchestration (full + incremental) - feat(build-cache): exclude calendar events from the email Parquet - feat(config): add [[gcal]] calendar sync configuration - feat(cli): add add-calendar and sync-calendar commands + daemon scheduling - docs(gcal): document calendar sync commands and [[gcal]] config - test(gcal): loopback integration test + testify-helper compliance - fix(calsync): address adversarial review findings (data integrity) - docs(calsync): correct incrementalCalendar header comment - fix(oauth): never delete the existing token before re-consent; harden headless add-calendar - fix(store): dedupe recipients to prevent UNIQUE-constraint sync abort - fix(calsync): bounded full sync must not set incremental baseline; series title from master - docs(gcal): add Google Calendar usage guide and surface the feature - docs(gcal): clarify Calendar auth setup - docs(gcal): add user-facing release notes - fix(gcal): address PR readiness blockers - fix(gcal): stabilize calendar-only cache freshness - fix(gcal): count deleted hidden cache rows - fix: address PR readiness regressions - fix: preserve OAuth and message type scopes - fix: close review gaps in scoped sync and search - test: gate SQLite FTS failure regression - fix: preserve Calendar OAuth scopes - docs: preserve grants in headless Calendar setup - docs: seed tokens before headless Calendar consent - fix: forward remote message type searches - fix: avoid stale Calendar resume tokens - fix: version Calendar resume checkpoints Co-authored-by: Wes McKinney <wesmckinn+git@gmail.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
3d3c4fa to
16482cb
Compare
Calendar date bounds are only applied by the full Calendar sync path, so a registered account with stored cursors must not silently run incremental sync when --after or --before is present. Treating bounded sync as full preserves the user's requested window instead of reporting success with ignored limits. Remote CLI search already has server-side support for message_type filters through query syntax, so --message-type should be serialized into message_type: terms instead of being rejected before the request leaves the client. Generated with Codex (GPT-5) Co-authored-by: Codex <codex@openai.com>
roborev: Combined Review (
|
Calendar-only onboarding should not request Gmail scopes unless there is an existing Gmail or legacy token to preserve during re-consent. Keeping the scope choice tied to the stored token avoids over-granting new Calendar accounts while still protecting existing Gmail grants. Bounded and limited calendar sync options only affect the full-sync path, so the CLI now treats any of them as full-only. Incremental sync also reapplies the configured calendar selection from stored source metadata so prior all-calendar registrations do not keep reader calendars syncing under the default selection. Calendar event persistence now treats FTS indexing like other import paths: the durable message/body/raw/recipient writes stay authoritative, and an FTS failure is logged for later repair instead of wedging cursor advancement. Generated with Codex (GPT-5) Co-authored-by: Codex <codex@openai.com>
roborev: Combined Review (
|
The review-fix commit left two CI-only regressions: the calendar option test crossed the testify-helper package-call threshold, and the pgvector test schema declared message_type twice so the live Postgres lane failed before exercising backend behavior. Keeping these test fixtures valid lets CI cover the Calendar and pgvector changes instead of failing during setup. Validation: ran the pgvector-tagged CI package set against a temporary pgvector/pgvector:pg16 container. Generated with Codex (GPT-5) Co-authored-by: Codex <codex@openai.com>
Calendar-only add-calendar should not request Gmail scopes, but the shared OAuth authorize path still validated new grants through Gmail profile. A Calendar-only token cannot call that endpoint, so new Calendar accounts could fail before their token was saved. Calendar grants now validate through the Calendar primary calendar endpoint, while Gmail-capable grants keep the existing Gmail profile validation. The Calendar OAuth manager also derives its configured reauth scopes from stored grants so Drive or other non-Gmail scopes survive replacement consent. Generated with Codex (GPT-5) Co-authored-by: Codex <codex@openai.com>
roborev: Combined Review (
|
find_similar_messages bypassed the hybrid engine's scoped-index guard by calling the vector backend directly. With a message-type-scoped embedding index, MCP clients could ask an unscoped nearest-neighbor question and receive results from a partial corpus as if the index covered every message. The tool now exposes an explicit message_type filter and validates that filter with the same build-scope rules used by hybrid search before dispatching backend ANN work. This keeps scoped indexes from serving ambiguous similar-message queries while preserving the direct backend path for valid filtered requests. Validation: ran the pgvector-tagged vector/scheduler/CLI package set against a temporary pgvector/pgvector:pg16 container. Generated with Codex (GPT-5) Co-authored-by: Codex <codex@openai.com>
find_similar_messages now shares the same active-generation freshness contract as hybrid search. A direct ActiveGeneration lookup could serve a scoped or otherwise stale active generation after vector configuration changed, which made the previous scoped-index guard depend on current config while the backend still searched the old index. ResolveActiveForFingerprint keeps the MCP similar-search path from answering with vectors built under a different model, preprocessing policy, or embed scope. The tests now construct matching generations for valid similar-search cases and cover the stale-generation rejection before backend search runs. Validation: ran the pgvector-tagged vector/scheduler/CLI package set against a temporary pgvector/pgvector:pg16 container. Generated with Codex (GPT-5) Co-authored-by: Codex <codex@openai.com>
Summary
Testing