Group issue statuses the way the Linear app does - #271
Merged
Conversation
`issue mine --all-states` listed Canceled and Done first and Backlog and Todo
last -- the reverse of the app. The primary sort was
`workflowState: { order: "Descending" }`, copy-pasted across four call sites
covering `issue mine`, `issue query`, and `issue start`. The commit that added
it (592000f) recorded only "sorts by workflow state first"; no rationale for the
direction survives.
Simply flipping the direction would not have fixed it. Measured against the API,
`Ascending` returns Todo before Backlog, so neither direction matches a team's
configured order -- Linear sorts by an internal ranking, and `WorkflowStateSort`
offers no way to sort by position at all. The schema says what the app actually
does: position orders states "in ascending order of position within their type
group". So the key is (type group, position), and ordering has to happen
locally.
That distinction is load-bearing rather than pedantic. This workspace has an
"In Review" at position 1002 with type `started`; under a raw-position sort it
lands after "Duplicate" instead of beside "In Progress" -- which is exactly what
`linear team states` has been printing, the same bug reached through
`getWorkflowStates()`. Both now share one comparator.
`position` is selected on each issue's own state rather than looked up per team,
so there is no extra round trip and multi-team results are automatically
correct. It is only meaningful within a team, though, so the key is chosen once
per result set: a single-team listing sorts by type group then position, while a
multi-team one sorts by type group alone and leaves the server's priority order
standing inside each group. Ranking one team's positions against another's would
compare unrelated numbers, and deciding it per-pair would not even be transitive.
Two consequences worth flagging. The server sort is now `Ascending`, which under
`--limit` changes which issues are fetched, not just their order: previously a
truncated `--all-states` listing filled up with canceled issues before reaching
any open work. And a non-finite position now throws instead of being tolerated,
because a NaN comparator result reads as "equal" and would quietly degrade the
listing to some other order -- that guard caught two stale test fixtures the
moment it went in.
Search is untouched; it is relevance-ranked, and regrouping it by status would
destroy the ordering that is the point of the command.
schpetbot
force-pushed
the
issue-status-order
branch
from
August 31, 2026 22:30
59bc2cd to
e62606b
Compare
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.
Fixes the status ordering you reported in
issue mine. Closes CLI-32.What was wrong
issue mine --all-stateslisted Canceled → Done → Backlog → Todo — the reverse of the app:The cause was
workflowState: { order: "Descending" }, copy-pasted across four call sites coveringissue mine,issue query, andissue start. The commit that introduced it (592000f) recorded only "sorts by workflow state first"; no rationale for the direction survives.Why flipping the direction wasn't the fix
Measured against the live API,
Ascendingreturns Todo before Backlog — so neither direction matches a team's configured order. Linear sorts by an internal ranking, andWorkflowStateSortoffers no way to sort by position at all.The schema says what the app actually does: position orders states "in ascending order of position within their type group". So the key is (type group, position), and the ordering has to happen client-side.
That distinction is load-bearing. This workspace has an In Review at position 1002 with type
started— under a raw-position sort it lands afterDuplicateinstead of besideIn Progress. Which is exactly whatlinear team stateshas been printing:Same root cause reached through
getWorkflowStates(); both now share one comparator.Design notes
positionis selected on each issue's own state rather than looked up per team — no extra round trip, and multi-team results are automatically correct. But position is only meaningful within a team, so the key is chosen once per result set:Ranking one team's positions against another's compares unrelated numbers, and deciding it per-pair wouldn't even be transitive (
A(teamA,5)==B(teamB,0),B==C(teamA,0), yetA > C), which would break the comparator contract.Search is untouched — it's relevance-ranked, and regrouping by status would destroy the ordering that is the point of the command.
Two behavior changes worth a look
Ascending, which changes membership under--limit, not just order. Previously a truncated--all-stateslisting filled up with canceled issues before reaching any open work. It now keeps the most actionable ones. Since the API can't sort by position, it still decides which issues are fetched; the client only reorders them.NaNcompares as "equal", so it would quietly degrade a listing to some other order. That guard immediately caught two stale test fixtures.Verification
578 tests pass;
deno task check,deno lint,deno fmt --checkclean. New regression tests cover all seven type groups, the In Review case, a low-positioncanceledstate that must not jump to the top, an unrecognized future state type, and multi-team grouping.queryIncludes: "position"pins the GraphQL selection, since the mock echoes fixtures verbatim and a snapshot alone can't prove the query asked for the field.QA'd live against the workspace: default
issue mine,--all-states,--sort manual,--limittruncation,issue query --json(connection shape intact,state.positionadded),issue query --search --json(noposition, relevance preserved),issue start, andteam states.