Repository navigation
Expand GitHub memory sync from assignee-only to GitHub's involves: qualifier (covers author + assignee + mentions + commenter) #59
Description
Original issue tinyhumansai#2418 by @justinhsu1477 on 2026-05-21T06:24:53Z
Summary
The initial GitHub Memory Provider (tinyhumansai#2413, in review) scopes the periodic sync to assignee:<viewer_login> — issues explicitly assigned to the connected user. That covers manager / dev-handoff workflows but misses three large slices of real-world GitHub usage:
- External contributors open issues but rarely get assigned (assignee is a maintainer action). Their own issue history doesn't reach Memory Tree.
- Reviewers / commenters participate in issues without being assigned.
- @-mention recipients are de facto involved but never appear in the assignee filter.
Expanding the search query to GitHub's involves:<viewer_login> qualifier — a superset of author, assignee, mentions, and commenter — covers all four naturally and matches the mental model of "issues I'm involved with" that the GitHub Notifications inbox already presents.
Problem
Verified live against my own GitHub account (justinhsu1477):
| Query | Issue count returned |
|---|---|
assignee:justinhsu1477 is:issue |
0 |
author:justinhsu1477 is:issue |
11 |
involves:justinhsu1477 is:issue |
(superset of the above; not yet measured) |
Concrete consequence: under the current MVP query in tinyhumansai#2413, I — the author of the GitHub provider — would see zero issues in Memory Tree after connecting, because nobody on the OpenHuman project assigned my issues to me. That's a meaningful gap between "what the user expects to see" and "what the provider syncs".
For users who DO have assignee-driven workflows (typical PM dev orgs), the current behaviour is correct. But for the much larger class of GitHub users — OSS contributors, reviewers, community participants — the assignee-only scope under-delivers.
Solution
Change one line in src/openhuman/composio/providers/github/provider.rs::sync():
// Today (PR #2413):
let query = format!("is:issue assignee:{viewer_login} sort:updated-desc");
// Proposed:
let query = format!("is:issue involves:{viewer_login} sort:updated-desc");involves: is documented at https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests#search-by-a-user-thats-involved-in-an-issue-or-pull-request as "the issue or pull request involves a certain user. The involves qualifier is a logical OR between the author, assignee, mentions, and commenter qualifiers".
Privacy posture stays intact
The change is strictly broader within "things the connected user has standing in" — every result is an issue the user authored, was assigned to, was @-mentioned in, or commented on. Other teammates' private issues that the user has no relationship with stay out of scope, same as today.
The qualifier is still constructed inside the provider, never accepted from a caller — privacy boundary unchanged.
Volume bounds
GitHub Search caps results at 1000 regardless of qualifier. The existing daily request budget (500 calls/day) and MAX_PAGES_PER_SYNC = 20 already cap total work. involves: will pull more issues per pass than assignee: for active users, but the rate limits don't change.
For active OSS contributors who'd hit the 1000-cap, a follow-up could add a created_at:>=<N days ago> cutoff, but that's a separate decision once we have real usage data.
Acceptance criteria
-
GitHubProvider::syncbuilds the search query withinvolves:<viewer_login>instead ofassignee:<viewer_login>. - Unit-level update: no test should break (the query string isn't asserted in
tests.rs; it's an opaque arg toGITHUB_SEARCH_ISSUES). - Manual sanity check:
gh api 'search/issues?q=involves:<your_login>+is:issue&per_page=2'returns at least as many items asassignee:<your_login>for the same user. - Diff coverage ≥ 80% — change is ~1 line, no new branches.
- Documentation note inside
provider.rsexplaining the qualifier choice and linking to GitHub'sinvolvesdocs.
Out of scope (further follow-ups)
- Settings UI for custom query qualifiers (e.g. "only sync issues from specific repos"). Belongs to a UI ticket if/when the orchestration around per-provider config matures.
- Pull-request ingest.
involves:would still only return issues because the query keepsis:issue; PRs as memory documents need their own provider design (different content shape, different states). created_at:>=<cutoff>window. Only worth adding once real-world usage shows the 1000-cap being hit.- Notifications-based ingest (
/notificationsendpoint). Different sync model, separate provider.
Related
- Parent provider: feat(composio): promote GitHub from catalog-only to native memory provider tinyhumansai/openhuman#2413 (MVP — uses
assignee:). - Parent issue: Add GitHub as a Composio memory provider (joining gmail / notion / slack / clickup / linear) tinyhumansai/openhuman#2408 (Add GitHub as a Composio memory provider).
- Sibling providers using equivalent scoping patterns:
composio/providers/linear/usesassigneefilter (Linear has noinvolves:equivalent — different SaaS, narrower API).composio/providers/clickup/usesassignees: [user_id]filter.
- GitHub Search syntax docs: https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests.
Activity
ElioNeto commentedon May 25, 2026
Quick live measurement against my own account (per the "not yet measured" line in the body table):
total_countassignee:justinhsu1477 is:issueauthor:justinhsu1477 is:issueinvolves:justinhsu1477 is:issueFor my own account
involvesequalsauthor— nocommenter/mentions/assigneeactivity to broaden the set. The proposal still stands for the typical user profile (maintainers, reviewers, PM workflows where mention / commenter / assignee activity dominates), but the corner case is worth flagging for whoever picks this up:The architectural benefit — sync covers issues the user authored, was assigned to, commented on, or was mentioned in — still holds; we just can't promise "more issues for everyone" as a side effect.
ElioNeto commentedon May 25, 2026
Picking this one up. Will open the follow-up the moment tinyhumansai#2413 lands on main so the diff stays a tight one-liner on top of the new provider.
ElioNeto commentedon May 25, 2026
Thanks @obchain — appreciate the pickup, and 👍 on the sequencing call (waiting for tinyhumansai#2413 to land keeps the diff a clean one-liner).
When you're in the code: the relevant line is the
query = format!(...)insideGitHubProvider::sync()(you'll see it once tinyhumansai#2413'sprovider.rsis on main). No existing unit test asserts the query string itself, so the change shouldn't ripple — though adding a small assertion that locks in theinvolves:qualifier wouldn't hurt.Happy to review when you open it.