Problem
The GraphQL layer already defines batch resolution queries:
BatchResolveForCreate
BatchResolveForUpdate
BatchResolveForSearch
These can resolve teams, projects, labels, milestones, and parent issues in a single GraphQL call. However, no command uses them. Instead, each resolver is called sequentially.
Current behavior
linearis issues create "title" --team Backend --assignee "Jane" --project API --labels "Bug,Critical" makes:
resolveTeamId() → 1 SDK call
resolveUserId() → 1-2 SDK calls
resolveProjectId() → 1 SDK call
resolveLabelIds() → 2 SDK calls (one per label)
createIssue() → 1 GraphQL mutation
Total: 6-7 sequential API calls where 1 batch query + 1 mutation would suffice.
Expected behavior
For issues create and issues update, use the existing batch queries to resolve all entity references in a single round-trip before executing the mutation.
Design considerations
This requires a new orchestration pattern. Options:
A. Command-level batch resolution
The command collects all identifiers, calls a single batch resolver, then passes UUIDs to the service. This breaks the "resolvers handle resolution" invariant slightly but is pragmatic.
B. New batch resolver module
A batch-resolver.ts that accepts all identifiers and returns all UUIDs. Commands call this instead of individual resolvers. Maintains layer separation.
C. Keep individual resolvers, add caching
Resolvers cache responses per-request. Less change but doesn't reduce API calls.
Recommendation: Option B — aligns with existing architecture.
Scope
issues create — use BatchResolveForCreate
issues update — use BatchResolveForUpdate
issues list --query with filters — use BatchResolveForSearch (if advanced search is added)
Acceptance criteria
Problem
The GraphQL layer already defines batch resolution queries:
BatchResolveForCreateBatchResolveForUpdateBatchResolveForSearchThese can resolve teams, projects, labels, milestones, and parent issues in a single GraphQL call. However, no command uses them. Instead, each resolver is called sequentially.
Current behavior
linearis issues create "title" --team Backend --assignee "Jane" --project API --labels "Bug,Critical"makes:resolveTeamId()→ 1 SDK callresolveUserId()→ 1-2 SDK callsresolveProjectId()→ 1 SDK callresolveLabelIds()→ 2 SDK calls (one per label)createIssue()→ 1 GraphQL mutationTotal: 6-7 sequential API calls where 1 batch query + 1 mutation would suffice.
Expected behavior
For
issues createandissues update, use the existing batch queries to resolve all entity references in a single round-trip before executing the mutation.Design considerations
This requires a new orchestration pattern. Options:
A. Command-level batch resolution
The command collects all identifiers, calls a single batch resolver, then passes UUIDs to the service. This breaks the "resolvers handle resolution" invariant slightly but is pragmatic.
B. New batch resolver module
A
batch-resolver.tsthat accepts all identifiers and returns all UUIDs. Commands call this instead of individual resolvers. Maintains layer separation.C. Keep individual resolvers, add caching
Resolvers cache responses per-request. Less change but doesn't reduce API calls.
Recommendation: Option B — aligns with existing architecture.
Scope
issues create— useBatchResolveForCreateissues update— useBatchResolveForUpdateissues list --querywith filters — useBatchResolveForSearch(if advanced search is added)Acceptance criteria
issues createwith multiple--flagsmakes ≤2 API calls (1 batch resolve + 1 mutation)issues updatewith multiple--flagsmakes ≤3 API calls (1 fetch context + 1 batch resolve + 1 mutation)