Skip to content

feat: Google Tasks reminders for Gmail accounts (CONTRACT EDIT FOR OWNER REVIEW) - #62

Closed
urnlahzer wants to merge 1 commit into
mainfrom
feat/google-tasks-reminders
Closed

urnlahzer wants to merge 1 commit into
mainfrom
feat/google-tasks-reminders

Conversation

@urnlahzer

Copy link
Copy Markdown
Owner

What

PR-3 of docs/plans/2026-09-27-google-provider-and-shared-registration.md: a reviewed loop from a Gmail account can be turned into a Google Tasks task, with the same confirmation-first flow as Microsoft To Do. PR-4 (both providers connected at once) follows.

Behaviour

  • Google Tasks records a date only and raises no alert. The draft says so, and the chosen time is written into the task's notes together with the opaque OpenLoops reference. Microsoft To Do behaviour and copy are unchanged.
  • The adapter checks that the signed-in Google account is the scanned account before sending anything, uses the account's first task list as the default, creates one task, and reports success only on HTTP 200 with a usable id. Anything else after dispatch is the uncertain outcome that asks you to check Google Tasks before retrying; no automatic retry.
  • Completion and status checks go to the same list and task. A 401 clears only the Google session.
  • Reminder records carry their provider (wire tags 4/5 from PR-1), so a Google record can never be sent to Microsoft Graph and vice versa; the sync job groups records by provider.

Verification

  • cargo fmt --all -- --check; clippy -D warnings on both crates: clean
  • cargo test -p openloops-graph --features live-connection: 198 passed
  • cargo test -p openloops-desktop --features native-ui -- --test-threads=1: 459 passed, 0 failed, 3 ignored
  • Cargo.lock unchanged; public-repo gate passed on the staged files
  • tools/check-reminder-adapter-boundary.ps1: P0-REMINDER-CROSS-CONTRACT-001 passes with the re-pinned ADR hash; only the pre-existing P0-REMINDER-INVENTORY-001 fails, as on main
  • Read-only Opus review, then an Opus implementer fix pass (Codex was out of quota); findings listed in the commit message

Contract edit for owner review: docs/adr/ADR-009-reminder-adapters.md gains an additive amendment recording the Google Tasks adapter and the marker placement both adapters use (free-text body: To Do body.content, Google Tasks notes; never title or due). The ADR's existing text says the raw marker travels only in a "proven opaque field"; neither service offers one, and the Microsoft adapter already used the body before this PR. The amendment records that, without claiming either field is proven. contracts/*.json untouched.

Not yet exercised live

No task has been created against a real Google account; loopback tests pin the request and response shapes. Smoke test after merge with the owner's Gmail test user: create a reminder from a Gmail loop, confirm the task appears in Google Tasks with the date and the notes line, then mark it done and confirm the card reconciles.

🤖 Generated with Claude Code

https://claude.ai/code/session_01YCesN8ZHnhqa6n3rWFThas

…NER REVIEW)

PR-3 of docs/plans/2026-09-27-google-provider-and-shared-registration.md.

Contract edit: docs/adr/ADR-009-reminder-adapters.md gains an additive amendment recording
the Google Tasks adapter and the marker placement both adapters actually use (free-text body:
To Do body.content, Google Tasks notes; never title or due). The reminder checker's ADR hash
literal is re-pinned; P0-REMINDER-CROSS-CONTRACT-001 passes; the pre-existing
P0-REMINDER-INVENTORY-001 failure is unchanged; contracts/*.json untouched.

- graph live/google/tasks.rs: create / complete / check_status against the Google Tasks API
  over the per-provider Google session with the tasks scope. create verifies the signed-in
  account matches the scanned account before any request, takes the first task list as the
  default, posts one task (title, needsAction, a date-only `due`, notes carrying the chosen
  reminder time and the opaque OpenLoops reference) and reports Created only on HTTP 200 with
  a usable id; anything after dispatch without that is the same uncertain outcome the
  Microsoft adapter uses. Every request is origin-confined, bounded, redirect-free, one
  request per attempt. A 401 clears only the Google session slot.
- graph live/provider.rs: create_reminder / complete_reminder / reminder_status dispatch on
  the AccountConfig variant; the Microsoft arms call reminders.rs unchanged.
- desktop: reminder drafts, dispatch, completion and the sync job route by the record's
  provider through account_config(provider); reminder_sync_checks groups by provider so one
  job serves both; the PR-2b "later release" guard is gone; outcome texts name Google Tasks
  for Google records and are unchanged for Microsoft.
- ui: the review draft reads reminder-service and reminder-time-note; for Google the note
  states that Google Tasks saves the date only and does not alert, and that the chosen time
  is written into the task's notes.

Review fixes (Opus read-only review, Opus implementer): `due` is the user's LOCAL calendar
date (an evening pick west of UTC no longer lands on the next day); a 401 on the completion
PATCH clears the Google session and never re-sends; Microsoft copy restored byte-identical
and pinned by tests; Google screens name Google Tasks everywhere ("To Do" / "Google Tasks"
short names keep Microsoft strings unchanged); one shared local-time formatter with UTC
offset; a list response without `items` is an empty list; reminder paths build the Microsoft
config without mail-loading shared/group inputs (reminder_account_config); sync planning
extracted to reminder_sync_jobs() and tested for both providers; facade and adapter guards
reject cross-provider requests; POST non-200 and post-dispatch transport failures are
Uncertain; the PATCH test asserts method and exact body.

Verified: cargo fmt --check; clippy -D warnings (graph live-connection, desktop
native-ui,ui-screenshot); graph 198 passed; desktop 459 passed, 0 failed, 3 ignored;
Cargo.lock unchanged; public-repo gate on staged files.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YCesN8ZHnhqa6n3rWFThas
@urnlahzer

Copy link
Copy Markdown
Owner Author

Closing without merge: #63 (feat/dual-provider-review) was stacked on this branch and was squash-merged first, so main (53a4871) already contains every change from this PR. Verified: git diff origin/main bf63168 is empty (main's tree equals the PR-4 tip, whose parent is this PR's commit ccb8e4b), the ADR-009 amendment appears once on main, and tools/check-reminder-adapter-boundary.ps1 passes P0-REMINDER-CROSS-CONTRACT-001 on main (only the pre-existing P0-REMINDER-INVENTORY-001 fails, as before).

Owner note: the ADR-009 contract edit described in this PR's body therefore landed through #63, whose title did not carry the "CONTRACT EDIT FOR OWNER REVIEW" flag. Please review the "Amendment (2026-10-04): Google Tasks adapter and marker placement" section of docs/adr/ADR-009-reminder-adapters.md on main.

@urnlahzer urnlahzer closed this Oct 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant