Return assignees from list_issues - #3064
Open
tgockel wants to merge 1 commit into
Open
Conversation
The list_issues GraphQL fragment never selected assignees, so the tool could not report who an issue was assigned to. Its nearest field, user, is the issue author, which callers conflate with the assignee. Answering "is anything unassigned?" therefore cost one list_issues call plus one issue_read per candidate, and a truncated sweep invites a fabricated answer drawn from the author instead. Add an assignees selection to IssueFragment, flatten it to logins in fragmentToMinimalIssue, and add "assignees" to listIssuesItemFieldEnum so it is selectable through fields. GitHub caps issue assignees at 10, so first: 100 cannot truncate; it also matches the page size already used for assignees in copilot.go. Drop omitempty from MinimalIssue.Assignees and initialize the slice in both converters so an unassigned issue serializes as [] rather than an absent key, which is what lets a caller identify unassigned issues from a single response. This also affects issue_read, the other MinimalIssue consumer, which now reports "assignees": [] instead of omitting the key.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The list_issues GraphQL fragment never selected assignees, so the tool could not report who an issue was assigned to. Its nearest field, user, is the issue author, which callers conflate with the assignee. Answering "is anything unassigned?" therefore cost one list_issues call plus one issue_read per candidate, and a truncated sweep invites a fabricated answer drawn from the author instead.
Add an assignees selection to IssueFragment, flatten it to logins in fragmentToMinimalIssue, and add "assignees" to listIssuesItemFieldEnum so it is selectable through fields. GitHub caps issue assignees at 10, so first: 100 cannot truncate; it also matches the page size already used for assignees in copilot.go.
Drop omitempty from MinimalIssue.Assignees and initialize the slice in both converters so an unassigned issue serializes as [] rather than an absent key, which is what lets a caller identify unassigned issues from a single response. This also affects issue_read, the other MinimalIssue consumer, which now reports "assignees": [] instead of omitting the key.
Summary
Adds
assigneestolist_issues, so the tool can report who each issue is assigned to. Previously the GraphQL fragment behindlist_issuesnever selected assignees, and the field was absent from the tool'sfieldsenum.Why
list_issueshad no way to return assignment data. Itsfieldsenum offerednumber, title, body, state, user, labels, comments, created_at, updated_at, field_values— anduseris the issue author, which callers conflate with the assignee.This was an asymmetry between the two conversion paths rather than a deliberate omission. Both produce a
MinimalIssue: the REST path (convertToMinimalIssue, backingissue_read) populatedAssignees; the GraphQL path (fragmentToMinimalIssue, backinglist_issues) never touched it. The enum was correct as documented — it lists only what the fragment actually populates — so the gap was upstream, in the query.The cost was concrete: answering "is anything unassigned?" required one
list_issuescall plus oneissue_readper candidate. On a 29-issue repository that is a 29-request sweep for a single question, and a sweep that gets truncated invites an answer fabricated from theuserfield instead.Fixes #
What changed
pkg/github/issues.go—IssueFragmentgains anassignees(first: 100){nodes{login}}selection. All fourlist_issuesquery variants embedIssueQueryFragment, so one edit covers the labels/since/both permutations.pkg/github/minimal_types.go—fragmentToMinimalIssueflattens assignees to logins, matching the shapeissue_readalready emits.pkg/github/minimal_types.go—"assignees"added tolistIssuesItemFieldEnum, and the invariant comment above it now records thatuseris the author whileassigneesis who it's assigned to.pkg/github/minimal_types.go—MinimalIssue.Assigneesdropsomitempty, and both converters initialize the slice non-nil, so an unassigned issue serializes as[]. Both changes are required:omitemptyalone drops the empty array, and dropping it without the init yieldsnull.githubv4mockmatches the serialized query byte-for-byte).pkg/github/__toolsnaps__/list_issues.snap— regenerated; one added enum entry.MCP impact
list_issuesaccepts a new"assignees"value infieldsand returns it per issue. Becauseissue_readsharesMinimalIssue, it is also affected: an unassigned issue now reports"assignees": []rather than omitting the key. No field was removed or renamed.Prompts tested (tool changes only)
Verified through the tool handler in unit tests (assigned, unassigned,
fields-selected, andfields-omitted cases), and the new GraphQL selection was run against the live API.githubv4mockwill happily match a query GitHub would reject, so mocks alone don't prove the selection is valid. A 100-issue sample returned 21 issues with assignees, max 2 each.Security / limits
No new data class or scope: assignee logins are already returned by
issue_read,search_issues, andlist_pull_requests, andassigneesrequires no permission beyond what listing issues already needs. Response growth is a short array of logins per issue, opt-out viafields. GitHub caps issue assignees at 10, soassignees(first: 100)cannot truncate; that page size matches the existingassignees(first: 100)selections incopilot.go.Tool renaming
deprecated_tool_aliases.goLint & tests
./script/lint./script/testDocs