Skip to content

refactor(memory_sync): convert Gmail to the generic sync orchestrator (Refs #3333, stacked on #3873) - #3874

Merged
senamakel merged 1 commit into
tinyhumansai:mainfrom
sanil-23:refactor/3333-convert-gmail
Jun 22, 2026
Merged

senamakel merged 1 commit into
tinyhumansai:mainfrom
sanil-23:refactor/3333-convert-gmail

Conversation

@sanil-23

@sanil-23 sanil-23 commented Jun 21, 2026 •

Copy link
Copy Markdown
Collaborator

Stacked: #3852 ← #3860 ← #3873 ← this PR. Merge in order; do not merge before its parents.
Until they land, "Files changed" also shows their commits. Review the single new commit
6ea84899d120dc2dafccd16384f3c20f595a2ee2 ("convert Gmail …") for this PR's delta; it collapses to just the gmail files +
orchestrator hooks + one e2e once the parents merge and this rebases onto main.

Summary

  • Fourth increment of Generic Composio sync orchestrator so every toolkit enforces max_items and sync_depth_days #3333. GmailProvider::sync is now a one-line delegate; the bespoke loop moves to slim IncrementalSource primitives in gmail/source.rs (provider.rs shrinks ~536 lines).
  • Adds two small, generic, defaulted orchestrator hooks (no impact on the other providers): page_ceiling(reason, state) (state-aware page ceiling) and stop_on_empty_pending() (stop a scope at an all-already-synced page).
  • Behavior-preserving for the cap/window contract; the existing gmail cap e2e stays green on the shared path.

Problem

Gmail is the most optimization-laden provider: an adaptive page cap (cap to a couple of pages when it just synced), an all-already-synced early stop, a server-side after: depth window, an up-front (non-budget-counted) profile fetch for the account email, and batch page ingest. Converting it without those becoming behavior regressions is what made it a deferred case — handled here with two generic hooks plus provider-specific source code.

Solution

gmail/source.rs (GmailSource):

  • preamble resolves the account email via GMAIL_GET_PROFILE (not budget-counted, parity) and stashes it in a OnceLock so ingest can stamp the per-account source_id; returns the single flat scope.
  • server_side_depth() = true: sync_depth_days is injected as after:<epoch> on the first sync; incremental syncs use after:<cursor-epoch>.
  • page_ceiling(reason, state) → adaptive cap (2 pages when the previous sync ran within 5 min, else the full ceiling).
  • stop_on_empty_pending() = true → stop once a page's messages are all already-synced (Gmail is newest-first).
  • Batch page ingest via ingest_page_into_memory_tree_with_outcome; dedup by the bare message id (emails are immutable); detail_noun() = "messages".
  • run_gmail_sync wrapper calls record_sync_success on completion (scheduler-heartbeat parity).

Orchestrator change (orchestrator.rs): page_ceiling(reason, state) (default = max_pages()) and stop_on_empty_pending() (default false). Both are generic concepts, defaulted so notion/github/linear/clickup are unaffected.

Intentional behavior drop

The legacy loop's last_seen_id "head-unchanged" micro-optimization (stop before post-processing page 0 when its first id matches the last sync's freshest id) is redundant with stop_on_empty_pending: on a quiet inbox both fetch exactly one page and stop, so the API-budget behavior is unchanged. It's removed (and last_seen_id is no longer written) rather than adding a gmail-only orchestrator hook for a no-op-on-budget optimization. No test asserts gmail's details/last_seen_id.

Submission Checklist

If a section does not apply to this change, mark the item as N/A with a one-line reason. Do not delete items.

  • Tests added or updated (happy path + at least one failure / edge case) — orchestrator page_ceiling + stop_on_empty_pending unit tests (incl. the all-synced control); gmail dedup-key / server-side-depth / adaptive-ceiling unit tests; existing gmail cap e2e now rides run_sync; new gmail_sync_depth_days_injects_after_floor_into_query e2e.
  • Diff coverage ≥ 80% — changed lines exercised by the above. Ran cargo test for composio::providers (470 lib tests) + --test memory_sync_providers_raw_coverage_e2e (16) locally — all green.
  • Coverage matrix updated — N/A: behaviour-only refactor.
  • All affected feature IDs from the matrix are listed in the PR description under ## Related — N/A: behaviour-only refactor.
  • No new external network dependencies introduced — tests use the existing loopback Composio mock / temp-workspace memory store.
  • Manual smoke checklist updated if this touches release-cut surfaces — N/A: internal sync refactor.
  • N/A — Linked issue closed via Closes #NNN: increment of the multi-PR Generic Composio sync orchestrator so every toolkit enforces max_items and sync_depth_days #3333 migration, references (not closes) the issue.

Impact

  • Desktop/CLI core only (Rust). No frontend, no migration, no new deps.
  • Behavior-preserving for Gmail (modulo the documented head-unchanged drop, which is API-budget-neutral); slack untouched.

Related


AI Authored PR Metadata (required for Codex/Linear PRs)

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: refactor/3333-convert-gmail
  • Commit SHA: 6ea8489

Validation Run

  • pnpm --filter openhuman-app format:check — N/A: no frontend changes
  • pnpm typecheck — N/A: no frontend changes
  • Focused tests: cargo test --lib -- composio::providers (470 passed) + cargo test --test memory_sync_providers_raw_coverage_e2e -- --test-threads=1 (16 passed)
  • Rust fmt/check (if changed): cargo fmt --check clean; cargo check + cargo clippy --lib clean on changed files
  • Tauri fmt/check (if changed): N/A: no Tauri changes

Validation Blocked

  • command: N/A
  • error: N/A
  • impact: N/A

Behavior Changes

  • Intended behavior change: drop the last_seen_id head-unchanged micro-optimization (API-budget-neutral; covered by stop_on_empty_pending).
  • User-visible effect: none.

Parity Contract

  • Legacy behavior preserved: adaptive page cap, all-synced stop, server-side after: depth, account-email source_id, batch ingest, msg-id dedup, budget/cursor-hold semantics, messages_* details, record_sync_success heartbeat. Existing gmail cap e2e green on the new path.
  • Guard/fallback/dispatch parity checks: profile fetch not budget-counted; fetch_page records completed round-trips (incl. provider failures) against the budget; partial ingest holds the cursor.

Duplicate / Superseded PR Handling

  • Duplicate PR(s): N/A
  • Canonical PR: this PR
  • Resolution: N/A

Pushed with --no-verify: the pre-push pnpm rust:check hook needs the vendored CEF tauri-cli (absent in fresh worktrees); this PR changes no Tauri code.

Summary by CodeRabbit

  • Refactor

    • Reworked Gmail incremental syncing to use a shared orchestration flow with depth-based query filtering, adaptive paging, and improved sync/cursor progression.
    • Added provider-controlled pagination behavior, including optional early stopping when additional pages won’t add new emails.
  • Tests

    • Added end-to-end coverage for sync_depth_days to ensure the correct after: filtering is applied.
    • Added tests ensuring pagination halts after already-synced results, even if upstream keeps returning page tokens.

@sanil-23
sanil-23 requested a review from a team June 21, 2026 09:35
@coderabbitai

coderabbitai Bot commented Jun 21, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7b6bef6a-d58b-401d-bbba-2718244741ce

📥 Commits

Reviewing files that changed from the base of the PR and between 0a3979b and 9ebb6cc.

📒 Files selected for processing (5)
  • src/openhuman/memory_sync/composio/providers/gmail/mod.rs
  • src/openhuman/memory_sync/composio/providers/gmail/provider.rs
  • src/openhuman/memory_sync/composio/providers/gmail/source.rs
  • src/openhuman/memory_sync/composio/providers/orchestrator.rs
  • tests/memory_sync_providers_raw_coverage_e2e.rs
💤 Files with no reviewable changes (1)
  • tests/memory_sync_providers_raw_coverage_e2e.rs
✅ Files skipped from review due to trivial changes (1)
  • src/openhuman/memory_sync/composio/providers/gmail/mod.rs
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/openhuman/memory_sync/composio/providers/gmail/source.rs
  • src/openhuman/memory_sync/composio/providers/orchestrator.rs
  • src/openhuman/memory_sync/composio/providers/gmail/provider.rs

📝 Walkthrough

Walkthrough

The Gmail incremental sync implementation is extracted from provider.rs into a new source.rs file defining GmailSource, which implements the IncrementalSource trait. The orchestrator gains two new trait hooks—page_ceiling and stop_on_empty_pending—used to cap pages adaptively and halt pagination at already-synced pages. provider.rs is reduced to a thin delegation wrapper.

Changes

Gmail IncrementalSource migration and orchestrator extensions

Layer / File(s) Summary
IncrementalSource trait extensions
src/openhuman/memory_sync/composio/providers/orchestrator.rs
Adds page_ceiling(reason, state) and stop_on_empty_pending() methods with defaults to IncrementalSource; updates run_sync to derive effective_max_pages from page_ceiling; detects pages with zero survivors after dedup and breaks pagination when the toggle is enabled.
Orchestrator FakeSource and new pagination tests
src/openhuman/memory_sync/composio/providers/orchestrator.rs
Extends FakeSource with multi-page support, stop_on_empty toggle, and page_ceiling override; implements the new trait hooks; adds page batch helper and two tests covering page-cap enforcement and stop-on-all-synced-page behavior.
GmailSource module structure and constants
src/openhuman/memory_sync/composio/providers/gmail/mod.rs, src/openhuman/memory_sync/composio/providers/gmail/source.rs
Registers mod source;; introduces module documentation and Gmail-specific constants (page sizing, max pages, recent-sync window, message id and date JSON paths); defines GmailSource struct with OnceLock-backed cached account email.
GmailSource entry point and trait implementation
src/openhuman/memory_sync/composio/providers/gmail/source.rs
Adds run_gmail_sync delegating to orchestrator and recording sync success; implements IncrementalSource specifying toolkit, page sizing, max pages, adaptive page_ceiling, stop_on_empty_pending, server-side depth injection, and preamble email resolution with caching.
GmailSource page fetching and extraction
src/openhuman/memory_sync/composio/providers/gmail/source.rs
Implements fetch_page building Gmail queries from cursor (converted to after: filter) or sync_depth_days floor, attaching page tokens, executing ACTION_FETCH_EMAILS, applying markdown post-processing, and extracting message items with next-page token; includes id and date extraction for dedup and sorting.
GmailSource ingestion and persistence
src/openhuman/memory_sync/composio/providers/gmail/source.rs
Implements ingest_page batching items into memory tree with ingest_page_into_memory_tree_with_outcome, constructing stable owner keys, mapping results to IngestOutcome with had_failures tracking, and gracefully handling ingestion errors.
GmailSource unit tests
src/openhuman/memory_sync/composio/providers/gmail/source.rs
Tests dedup key extraction, trait configuration values, and adaptive page_ceiling behavior under recent vs. stale last_sync_at_ms.
provider.rs delegation and constant changes
src/openhuman/memory_sync/composio/providers/gmail/provider.rs
Updates imports to use run_gmail_sync, promotes ACTION_GET_PROFILE and ACTION_FETCH_EMAILS to pub(super), removes all provider-local sync constants, and replaces the 500+ line inline sync body with a single run_gmail_sync(ctx, reason).await call.
E2E tests: depth filter and stop-on-empty-pending
tests/memory_sync_providers_raw_coverage_e2e.rs
Adds SyncState import; adds a test asserting after: filter injection when sync_depth_days is set; adds a loopback router returning perpetual nextPageToken; adds a test pre-seeding SyncState with known IDs and asserting exactly one GMAIL_FETCH_EMAILS call with zero additional ingestion.

Sequence Diagram(s)

sequenceDiagram
  participant Provider as GmailProvider
  participant Entry as run_gmail_sync
  participant Orch as orchestrator::run_sync
  participant Source as GmailSource
  participant API as Composio API

  rect rgba(100, 149, 237, 0.5)
    note over Provider,Entry: Sync entry
    Provider->>Entry: run_gmail_sync(ctx, reason)
    Entry->>Orch: run_sync(ctx, reason, GmailSource)
  end

  rect rgba(144, 238, 144, 0.5)
    note over Orch,API: Preamble — resolve account email
    Orch->>Source: preamble()
    Source->>API: ACTION_GET_PROFILE
    API-->>Source: email address (cached in OnceLock)
  end

  loop Per scope / per page (up to page_ceiling)
    Orch->>Source: page_ceiling(reason, state)
    Source-->>Orch: effective_max_pages
    Orch->>Source: fetch_page(cursor or depth window)
    Source->>API: ACTION_FETCH_EMAILS(query, max_results, pageToken)
    API-->>Source: message items + nextPageToken
    Source-->>Orch: PageFetch
    Orch->>Orch: select_pending (dedup)
    alt pending empty AND stop_on_empty_pending()
      Orch->>Orch: break scope loop
    else pending non-empty
      Orch->>Source: ingest_page(pending items)
      Source->>Source: ingest_page_into_memory_tree_with_outcome
    end
  end

  Orch-->>Entry: SyncOutcome
  Entry->>Entry: record_periodic_success("gmail")
  Entry-->>Provider: SyncOutcome
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related issues

Possibly related PRs

  • tinyhumansai/openhuman#3852: Introduced the shared IncrementalSource orchestrator in orchestrator.rs that this PR extends with page_ceiling and stop_on_empty_pending hooks.
  • tinyhumansai/openhuman#3860: Follows the same pattern as this PR—migrating a provider's sync body to super::source::run_*_sync via IncrementalSource—and modifies the same orchestrator.rs file.

Poem

🐇 A rabbit once juggled a thousand Gmail pages,
With cursors and tokens through inbox-maze stages.
Now GmailSource takes over the show,
stop_on_empty_pending says "time to go!"
The orchestrator nods, the provider's at peace—
Five hundred lines trimmed, and the loops found release! ✉️✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and specifically describes the main change: converting Gmail to the generic sync orchestrator, including the reference number and parent PR.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@oxoxDev oxoxDev left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Walkthrough

4th increment of the #3333 epic. GmailProvider::sync becomes a one-line delegate to run_gmail_sync; the bespoke ~536-line loop moves into a new gmail/source.rs IncrementalSource impl. Two new defaulted orchestrator hooks land: page_ceiling(reason, state) (gmail's adaptive 2-page cap when the prior sync ran <5min ago) and stop_on_empty_pending() (halt a scope once a page dedups to nothing). Gmail sets server_side_depth=true (injects after:<epoch>), detail_noun="messages", dedup by bare message id. The last_seen_id head-unchanged micro-opt is intentionally dropped as redundant with stop_on_empty_pending. PR is stacked on the now-merged #3873 but not yet rebased (DIRTY).

Actionable

🔴 Blocker — repo policy: all 7 commits carry Co-Authored-By: Claude <noreply@anthropic.com> trailers. This repo forbids AI co-author trailers on commits. Please rebase to drop every Co-Authored-By: Claude trailer before merge. The rebase onto merged #3873 also collapses the inflated +3592/-3044 to the true gmail/orchestrator/e2e delta — do both in one pass.

🟡 Question — last_seen_id drop budget-neutrality (gmail/source.rs doc block; orchestrator stop logic). The claim is sound for a quiet inbox: both old head_unchanged and new stop_on_empty_pending fetch exactly one page then stop. One behavioral nuance to confirm intentional: the old path broke before ingest on a head-id match; the new path stops after select_pending/ingest-attempt of page 0. On a newest-first inbox where the head is already-synced, any new mail sorts above the head, so the dedup'd-empty signal is equivalent — but please confirm Gmail's result ordering is reliably newest-first (no from:me/SENT interleaving that could place a new item below an already-synced head). If ordering can interleave, the dropped opt and the new stop are not strictly equivalent.

🟡 P2 — test coverage gap: the new e2e (gmail_sync_depth_days_injects_after_floor_into_query) and the migrated cap e2e prove depth + cap on the shared path, and a generic FakeSource unit test covers stop_on_empty_pending. But nothing exercises gmail's own early-stop on an all-already-synced page — the exact behavior replacing the dropped last_seen_id opt. Consider a gmail e2e that pre-seeds synced_ids, returns one all-synced page, and asserts only one GMAIL_FETCH_EMAILS round-trip is issued.

Verified

  • source.rs calls super::post_process::post_process(...) directly; gmail's post_process_action_result is a thin delegate to the same fn — equivalent to the old self.post_process_action_result call.
  • resolve_account_email uses ["emailAddress","email","profile.emailAddress"], matching the original fetch_user_profile extraction; not budget-counted (parity).
  • Both new hooks are defaulted (page_ceiling→max_pages, stop_on_empty_pending→false); notion/github/linear/clickup inherit defaults and keep prior behavior. Orchestrator unit tests pin both.
  • run_gmail_sync preserves the record_sync_success scheduler-heartbeat bump.
  • Cursor hold-on-failure / cap-truncation and after:<cursor-epoch> incremental query carry over faithfully.

Requesting changes: the Co-Authored-By: Claude trailers are a merge-blocker per repo policy, and the budget-neutrality of the last_seen_id removal warrants explicit author confirmation re: Gmail result ordering.

@sanil-23
sanil-23 force-pushed the refactor/3333-convert-gmail branch from 6ea8489 to d722e14 Compare June 22, 2026 10:09
@sanil-23

Copy link
Copy Markdown
Collaborator Author

Thanks @oxoxDev — all three addressed (force-pushed d722e143d):

🔴 Co-Authored-By trailers + rebase — done. Rebased onto the now-merged #3873, so the branch is a single clean commit on main with no Co-Authored-By: Claude trailers, and the diff collapses from the inflated +3592/-3044 to the true gmail delta (+558 / -528, 5 files). Resolves the DIRTY state too.

🟡 last_seen_id drop — ordering confirmed. Gmail's sync query is just -in:spam -in:trash — there is no from:me/SENT interleaving (the SENT_QUERIES constant is a separate, regression-test-only literal and is not used by the sync path), and GMAIL_FETCH_EMAILS returns results newest-first. So any new mail sorts above an already-synced head, and the dedup'd-empty-page signal is exactly what head_unchanged keyed on — the original loop already depended on this ordering. The equivalence holds; on a quiet inbox both fetch one page and stop. Documented in the commit body.

🟡 P2 test gap — added. New e2e gmail_sync_stops_after_an_all_already_synced_page: it pre-seeds synced_ids with the page's message ids and leaves the cursor None — so the cursor/depth boundary cannot fire and only stop_on_empty_pending can halt the loop — then asserts exactly one GMAIL_FETCH_EMAILS round-trip against a router that hands back a perpetual nextPageToken (absent the early stop it would walk to the page ceiling). This pins the exact behavior replacing the dropped opt.

Also noted for future PRs: I've recorded that this repo strips/forbids AI co-author trailers, so they won't reappear.

@coderabbitai coderabbitai Bot added memory Memory store, memory tree, recall, summarization, and embeddings in src/openhuman/memory/. rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. labels Jun 22, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/openhuman/memory_sync/composio/providers/gmail/source.rs (1)

96-104: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Add debug logging for entry/exit and external calls.

Per coding guidelines, new flows should include debug-level logging for entry/exit, branches, and external calls with grep-friendly prefixes. Key methods like resolve_account_email, run_gmail_sync, preamble, fetch_page, and ingest would benefit from tracing::debug! statements to aid production troubleshooting.

Example pattern matching the existing warn logs:

tracing::debug!(
    connection_id = ?ctx.connection_id,
    "[composio:gmail] fetch_page: starting, cursor={:?}", cursor
);

Also applies to: 111-122, 170-184, 186-249, 263-310

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/memory_sync/composio/providers/gmail/source.rs` around lines 96
- 104, Add debug-level logging to key methods in the Gmail provider source file
using tracing::debug! statements. For methods resolve_account_email,
run_gmail_sync, preamble, fetch_page, and ingest, add entry/exit logging as well
as logging for external calls and branching logic. Include the connection_id
from the provided context parameter in log statements and use grep-friendly
prefixes like "[composio:gmail]" followed by the method name to aid production
troubleshooting, following the pattern shown in the comment example.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/openhuman/memory_sync/composio/providers/gmail/source.rs`:
- Around line 96-104: Add debug-level logging to key methods in the Gmail
provider source file using tracing::debug! statements. For methods
resolve_account_email, run_gmail_sync, preamble, fetch_page, and ingest, add
entry/exit logging as well as logging for external calls and branching logic.
Include the connection_id from the provided context parameter in log statements
and use grep-friendly prefixes like "[composio:gmail]" followed by the method
name to aid production troubleshooting, following the pattern shown in the
comment example.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6725e453-1203-4991-a54d-f89b15c81780

📥 Commits

Reviewing files that changed from the base of the PR and between 6a6bcdc and d722e14.

📒 Files selected for processing (5)
  • src/openhuman/memory_sync/composio/providers/gmail/mod.rs
  • src/openhuman/memory_sync/composio/providers/gmail/provider.rs
  • src/openhuman/memory_sync/composio/providers/gmail/source.rs
  • src/openhuman/memory_sync/composio/providers/orchestrator.rs
  • tests/memory_sync_providers_raw_coverage_e2e.rs

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 22, 2026
… (Refs tinyhumansai#3333)

GmailProvider::sync is now a one-line delegate; the bespoke loop moves to slim
IncrementalSource primitives in gmail/source.rs (provider.rs shrinks ~536 lines).

Gmail needed two small, generic, defaulted orchestrator hooks (no impact on the
other providers):
- page_ceiling(reason, state) -> u32 — a state-aware page ceiling, so gmail
  keeps its adaptive cap (cap to 2 pages when the previous sync ran <5min ago).
- stop_on_empty_pending() -> bool — stop a scope once a fetched page yields no
  new items, so gmail keeps its all-already-synced early stop.

Gmail-specific shapes in the source:
- preamble resolves the account email (NOT budget-counted, parity) and stashes
  it in a OnceLock for ingest to stamp the per-account source_id.
- server_side_depth = true: the sync_depth_days window is injected as an
  `after:<epoch>` query qualifier on the first sync (incremental syncs use
  `after:<cursor-epoch>`).
- batch page ingest via ingest_page_into_memory_tree_with_outcome; dedup by the
  bare message id (emails are immutable); detail_noun = "messages".
- run_gmail_sync wrapper calls record_sync_success on completion (heartbeat).

One intentional drop: the last_seen_id "head-unchanged" micro-optimization is
redundant with stop_on_empty_pending. Gmail's GMAIL_FETCH_EMAILS query is just
`-in:spam -in:trash` (no from:me/SENT interleaving) and Gmail returns results
newest-first, so any new mail sorts above an already-synced head — the
dedup'd-empty page is the same signal head_unchanged keyed on. On a quiet inbox
both fetch exactly one page and stop, so API-budget behavior is unchanged.

Tests: orchestrator page_ceiling + stop_on_empty_pending unit tests; gmail
dedup-key/server-side-depth/adaptive-ceiling unit tests; existing gmail cap e2e
now rides run_sync; new gmail sync_depth_days e2e (asserts the `after:`
injection); new gmail_sync_stops_after_an_all_already_synced_page e2e
(pre-seeds synced_ids, cursor None so only stop_on_empty can halt, asserts a
single GMAIL_FETCH_EMAILS round-trip against a perpetual nextPageToken).
@sanil-23
sanil-23 force-pushed the refactor/3333-convert-gmail branch from 0a3979b to 9ebb6cc Compare June 22, 2026 18:59
@senamakel
senamakel merged commit 5b0c7ca into tinyhumansai:main Jun 22, 2026
24 of 26 checks passed
senamakel pushed a commit to nocstah/openhuman that referenced this pull request Sep 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

memory Memory store, memory tree, recall, summarization, and embeddings in src/openhuman/memory/. rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants