Skip to content

test(memory-sync/github): assert involves: query qualifier#2664

Merged
M3gA-Mind merged 1 commit into
tinyhumansai:mainfrom
obchain:test/2418-github-involves-query-regression
May 26, 2026
Merged

test(memory-sync/github): assert involves: query qualifier#2664
M3gA-Mind merged 1 commit into
tinyhumansai:mainfrom
obchain:test/2418-github-involves-query-regression

Conversation

@obchain
Copy link
Copy Markdown
Contributor

@obchain obchain commented May 26, 2026

Summary

  • Adds regression coverage for the involves:{login} GitHub Search-Issues qualifier introduced in feat(composio): promote GitHub from catalog-only to native memory provider #2413 — the qualifier itself shipped with that PR, but no test asserted it, so it could silently regress to the narrower assignee:{login} scope and lose author / mention / commenter coverage.
  • Extracts the inline query builder from GitHubProvider::sync() into a free function (build_search_query) so the qualifier contract is unit-testable without spinning up the full sync pipeline.
  • No behaviour change: the query string produced is identical (involves:{login} ± updated:>{cursor}).

Problem

src/openhuman/memory_sync/composio/providers/github/provider.rs built the search query inline inside sync():

let query = match &state.cursor {
    Some(cursor) => format!("involves:{login} updated:>{cursor}"),
    None => format!("involves:{login}"),
};

There was no unit test asserting either the involves: qualifier or the cursor clause, even though involves: (vs. assignee:) is the core privacy / coverage contract of the provider:

  • assignee:{login} returns only items the user is explicitly assigned to — typical of PM dev orgs, narrow for OSS contributors.
  • involves:{login} is GitHub's logical-OR over author, assignee, mentions, and commenter — matches the GitHub Notifications mental model.

Without test coverage, a refactor or a "small simplification" could quietly drop back to assignee: and ship undetected. Issue #2418 calls this out explicitly:

No existing unit test asserts the query string itself, so the change shouldn't ripple — though adding a small test would be a nice add.

Solution

  1. Extract the inline match into pub(super) fn build_search_query(login: &str, cursor: Option<&str>) -> String at the bottom of provider.rs. Call site in sync() becomes a single line.
  2. Add four unit tests in tests.rs:
    • build_search_query_uses_involves_qualifier_without_cursor — exact string match on the cursor-less variant.
    • build_search_query_does_not_fall_back_to_assignee_qualifier — explicit negative assertion guarding against regression to assignee:.
    • build_search_query_appends_updated_clause_when_cursor_present — exact string match on the cursor variant.
    • build_search_query_interpolates_login_verbatim — covers non-trivial logins with hyphens / underscores / digits.
  3. The block comment above the new tests links the assertions back to Expand GitHub memory sync from assignee-only to GitHub's involves: qualifier (covers author + assignee + mentions + commenter) #2418 so future readers know why the negative test exists.

Visibility is pub(super) so only the sibling tests.rs module can reach it — no expansion of the provider's public API.

Submission Checklist

  • Tests added or updated (happy path + at least one failure / edge case) per Testing Strategy — four new build_search_query_* tests in src/openhuman/memory_sync/composio/providers/github/tests.rs, covering both the cursor-less / with-cursor branches and the explicit negative assignee: regression guard.
  • Diff coverage ≥ 80% — every changed line is either the new build_search_query function (covered by all four new tests) or the one-line call site that those tests exercise indirectly via the contract they pin.
  • Coverage matrix updated — N/A: behaviour-only change (no new feature row; this is regression coverage for the existing GitHub memory provider already listed in the matrix).
  • All affected feature IDs from the matrix are listed in the PR description under ## Related — N/A: no new feature IDs introduced; the existing GitHub Composio Memory Provider feature is unchanged in behaviour.
  • No new external network dependencies introduced (mock backend used per Testing Strategy) — pure unit tests on a string-building function; no network, no mock backend needed.
  • Manual smoke checklist updated if this touches release-cut surfaces (docs/RELEASE-MANUAL-SMOKE.md) — N/A: no user-visible surface touched.
  • Linked issue closed via Closes #NNN in the ## Related section — Closes #2418 below.

Impact

  • Runtime / platform: none — the produced query string is byte-identical to the previous inline match.
  • Performance: negligible — one extra function call per sync pass (already inside an async I/O loop).
  • Security / privacy: unchanged — the involves: qualifier still returns only items GitHub itself authorises for the connected user.
  • Migration / compatibility: none.

Related


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

Keep this section for AI-authored PRs. For human-only PRs, mark each field N/A.

Linear Issue

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

Commit & Branch

  • Branch: N/A
  • Commit SHA: N/A

Validation Run

  • pnpm --filter openhuman-app format:check — N/A: pure Rust change, no frontend files touched.
  • pnpm typecheck — N/A: pure Rust change, no TypeScript touched.
  • Focused tests: cargo test --lib openhuman::memory_sync::composio::providers::github::tests — 25/25 passed locally, including the 4 new build_search_query_* regression tests.
  • Rust fmt/check (if changed): cargo fmt --check clean; cargo check clean against changed files.
  • Tauri fmt/check (if changed): N/A: no app/src-tauri/ files touched.

Validation Blocked

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

Behavior Changes

  • Intended behavior change: N/A
  • User-visible effect: N/A

Parity Contract

  • Legacy behavior preserved: N/A
  • Guard/fallback/dispatch parity checks: N/A

Locks in the `involves:{login}` GitHub Search-Issues qualifier so the
periodic sync cannot silently regress to the narrower `assignee:{login}`
scope and drop author / mention / commenter coverage for users who are
rarely explicitly assigned.

Extracts the inline query builder into `build_search_query` so the
contract can be exercised without spinning up the full sync pipeline.

Closes tinyhumansai#2418.
@obchain obchain requested a review from a team May 26, 2026 06:36
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 26, 2026

📝 Walkthrough

Walkthrough

The GitHub provider's search-query construction is refactored by extracting inline state.cursor matching logic into a dedicated build_search_query helper function. The sync method now calls this helper instead of building the involves:{login} and optional updated:>{cursor} query inline. Unit tests verify correct qualifier selection and cursor-based pagination clause appending.

Changes

GitHub Search Query Builder Extraction

Layer / File(s) Summary
Query builder function with cursor support
src/openhuman/memory_sync/composio/providers/github/provider.rs
Introduces build_search_query(login, cursor) that returns involves:{login} optionally appended with updated:>{cursor} when a cursor is provided.
Sync method refactoring to use query builder
src/openhuman/memory_sync/composio/providers/github/provider.rs
The sync method now calls build_search_query(&login, state.cursor.as_deref()) instead of constructing the search query inline with a match expression.
Query builder unit tests
src/openhuman/memory_sync/composio/providers/github/tests.rs
Adds import and comprehensive unit tests verifying query construction with and without cursor, ensuring involves: qualifier is used and login is interpolated correctly without fallback to narrower assignee: qualifier.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • tinyhumansai/openhuman#2413: Both PRs modify the GitHub memory provider's search-query construction for pagination, with this PR extracting and testing the query-building logic.

Suggested labels

rust-core, working

Poem

🐰 A query, once tangled inline, now lives in a helper so fine,
With cursors and login combined, the involves: clause shines.
Tests affirm every case with care—no assignee anywhere!
Refactored with grace, a cleaner place. hop hop

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the primary change: adding regression test coverage for the involves: query qualifier in the GitHub memory sync provider.
Linked Issues check ✅ Passed The PR fulfills issue #2418's coding objectives: refactors the query builder to use involves: and adds unit tests asserting the involves: qualifier and updated: cursor behavior.
Out of Scope Changes check ✅ Passed All changes are directly related to issue #2418's scope: extracting the query builder into a testable function and adding unit tests to assert involves: qualifier behavior.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot added rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. working A PR that is being worked on by the team. labels May 26, 2026
Copy link
Copy Markdown
Contributor

@M3gA-Mind M3gA-Mind left a comment

Choose a reason for hiding this comment

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

Clean extraction + targeted regression coverage. A few notes:

What's correct

build_search_query — the extraction is exact. state.cursor.as_deref() correctly converts Option<String>Option<&str> matching the function signature. pub(super) is the right visibility — visible to tests.rs, not exported further.

Tests — four tests covering: cursor-less exact match, explicit negative guard against assignee: regression, cursor-present exact match, and a non-trivial login (hyphens/underscores/digits). The negative assertion in test 2 is intentionally redundant with test 1 — having it spelt out explicitly is the point, so a future reader knows why the assignee: guard exists.

Nit

build_search_query_interpolates_login_verbatim uses assert!(query.contains(...)) rather than an exact equality check. If the format string ever gains extra tokens (e.g. a sort clause), the test keeps passing silently. Low risk given the function is a two-branch match on a format string, but an exact assert_eq! would be tighter.

No concerns

No behaviour change — the produced query string is byte-identical to the original inline match. Closes #2418. CI green, no conflicts.

LGTM.

@M3gA-Mind M3gA-Mind merged commit 844a26c into tinyhumansai:main May 26, 2026
36 of 41 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. working A PR that is being worked on by the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expand GitHub memory sync from assignee-only to GitHub's involves: qualifier (covers author + assignee + mentions + commenter)

2 participants