Skip to content

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

Open

Description

@ElioNeto

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:

  1. External contributors open issues but rarely get assigned (assignee is a maintainer action). Their own issue history doesn't reach Memory Tree.
  2. Reviewers / commenters participate in issues without being assigned.
  3. @-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::sync builds the search query with involves:<viewer_login> instead of assignee:<viewer_login>.
  • Unit-level update: no test should break (the query string isn't asserted in tests.rs; it's an opaque arg to GITHUB_SEARCH_ISSUES).
  • Manual sanity check: gh api 'search/issues?q=involves:<your_login>+is:issue&per_page=2' returns at least as many items as assignee:<your_login> for the same user.
  • Diff coverage ≥ 80% — change is ~1 line, no new branches.
  • Documentation note inside provider.rs explaining the qualifier choice and linking to GitHub's involves docs.

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 keeps is: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 (/notifications endpoint). Different sync model, separate provider.

Related

Activity

  1. ElioNeto commented on May 25, 2026

    @ElioNeto
    OwnerAuthor

    Comment by @justinhsu1477 on 2026-05-21T06:39:25Z

    Quick live measurement against my own account (per the "not yet measured" line in the body table):

    Qualifier total_count
    assignee:justinhsu1477 is:issue 0
    author:justinhsu1477 is:issue 12
    involves:justinhsu1477 is:issue 12

    For my own account involves equals author — no commenter / mentions / assignee activity 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:

    If a user matches the "pure issue creator" pattern (opens issues but doesn't comment on others'), migrating their query from assignee: to involves: won't visibly increase their Memory Tree footprint. That's expected, not a regression.

    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.

  2. ElioNeto commented on May 25, 2026

    @ElioNeto
    OwnerAuthor

    Comment by @obchain on 2026-05-21T08:52:12Z

    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.

  3. ElioNeto commented on May 25, 2026

    @ElioNeto
    OwnerAuthor

    Comment by @justinhsu1477 on 2026-05-21T09:23:28Z

    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!(...) inside GitHubProvider::sync() (you'll see it once tinyhumansai#2413's provider.rs is 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 the involves: qualifier wouldn't hurt.

    Happy to review when you open it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions