Issue picker walks up to root, then descends sub-issue tree#449
Merged
Conversation
Fixes #433. The old picker iterated directly-assigned issues and asked "are all sub-issues closed" — which couldn't tell whether an assigned issue was actually next in its parent's order, and couldn't claim unassigned children that should land first. New picker: 1. For each assigned candidate, walk upward via `.parent` (via `gh.get_issue_node`) to the root ancestor. Dedupe roots. 2. Rank roots: milestone-present first, then creation order of the first assigned descendant. 3. Descend each root in GitHub sub-issue order: - child assigned to us → recurse - child unassigned → claim (assign self) + recurse - child assigned to someone else → blocked, skip branch - leaf with no open children → pick it 4. If every open child at a level is blocked, the whole subtree is blocked; move to next root. Claiming the unassigned chain on the way down means once a leaf's PR merges, each ancestor naturally becomes the next pick as its other children close out. Also adds a generic `_graphql_paginate` helper so GraphQL connections (issues, subIssues) walk every page instead of silently truncating at the first 30/50 nodes. `find_issues` and `get_sub_issues` now use it; `get_issue_node` hydrates via `get_sub_issues` when the embedded first page has more. New API surface: - `GitHub.get_sub_issues(owner, repo, number)` — paginated children - `GitHub.get_issue_node(owner, repo, number)` — picker-shaped issue - `GitHub.add_assignee(repo, number, login)` — claim an issue 100% coverage, 1688 tests passing.
rhencke
approved these changes
Apr 14, 2026
FidoCanCode
added a commit
that referenced
this pull request
Apr 14, 2026
Resolves conflicts from #449 (issue picker) landing on main: - kennel/github.py: GH class retained (collapsed-client plan), dropped the now-obsolete GitHub wrapper class from main. New methods from #449 (find_issues with cursor pagination, get_sub_issues, get_issue_node, add_assignee) are already on GH. - tests/test_github.py: dropped wrapper delegation tests for the removed GitHub class; kept the direct GH-class tests for the new methods.
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.
Summary
The old picker iterated directly-assigned issues and asked "are all sub-issues closed?" — which couldn't tell whether an assigned issue was actually next in its parent's order, and couldn't claim unassigned children that should land first.
New picker:
Claiming the unassigned chain on the way down means once a leaf's PR merges, each ancestor naturally becomes the next pick as its other children close out.
Also adds a generic `_graphql_paginate` helper so GraphQL connections (issues, subIssues) walk every page instead of silently truncating at the first 30/50 nodes.
Fixes #433
New API
Test plan
no more grabbing the parent when a child should land first