Add delegate support for agent users on issues#172
Add delegate support for agent users on issues#172shanelindsay wants to merge 4 commits intoschpet:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds first-class agent delegation support to the linear issue create / linear issue update CLI commands by introducing a --delegate flag, resolving delegation to Linear’s delegateId, and enforcing that app users aren’t assigned via --assignee.
Changes:
- Add
--delegateflag to issue create/update and map it todelegateId(with validation that--assigneeis human-only and--delegateis app-only). - Extend user lookup to return
{ id, app, ... }so commands can distinguish app vs human users. - Update docs + snapshot tests and make the mock Linear server bind an ephemeral port to avoid test collisions.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
src/utils/linear.ts |
Introduces lookupUser() returning user metadata (incl. app) and rebuilds lookupUserId() on top of it. |
src/commands/issue/issue-create.ts |
Adds --delegate, validates human/app usage, and passes delegateId into issue creation input. |
src/commands/issue/issue-update.ts |
Adds --delegate, validates human/app usage, and passes delegateId into issue update input. |
test/utils/mock_linear_server.ts |
Switches mock server to bind an ephemeral port and records the actual port via onListen. |
test/commands/issue/issue-create.test.ts |
Adds snapshot coverage for delegate happy path + assignee app-user rejection; updates viewer mock fields. |
test/commands/issue/issue-update.test.ts |
Adds snapshot coverage for delegate happy path + assignee app-user rejection; updates viewer mock fields. |
test/commands/issue/__snapshots__/issue-create.test.ts.snap |
Updates help output and adds snapshots for new delegate/error cases. |
test/commands/issue/__snapshots__/issue-update.test.ts.snap |
Updates help output and adds snapshots for new delegate/error cases. |
docs/usage.md |
Documents the new --delegate flag usage for create/update. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| this.server = Deno.serve({ | ||
| hostname: "127.0.0.1", | ||
| port: 0, | ||
| onListen: ({ port }) => { | ||
| this.port = port | ||
| }, |
There was a problem hiding this comment.
The server is bound to hostname: "127.0.0.1", but getEndpoint() (later in this file) still uses http://localhost:.... On systems where localhost resolves to IPv6 first, clients may try ::1 and fail to connect. Consider returning http://127.0.0.1:${port}/graphql (or binding the server to localhost/::1) to keep the bind address and endpoint consistent.
| onListen: ({ port }) => { | ||
| this.port = port | ||
| }, | ||
| }, (request) => { |
There was a problem hiding this comment.
start() still relies on a fixed setTimeout later to wait for the server to be ready. Since you already use onListen, it would be more deterministic to await a promise resolved from onListen (and drop the arbitrary sleep) so tests are less flaky and start faster on slow CI runners.
src/commands/issue/issue-create.ts
Outdated
| if (!resolvedDelegate.app) { | ||
| throw new ValidationError( | ||
| `Cannot use --delegate with human user '${delegate}'`, | ||
| { | ||
| suggestion: | ||
| `Use --assignee ${delegate} to assign the issue to a human user.`, | ||
| }, | ||
| ) |
There was a problem hiding this comment.
The new validation that rejects using --delegate with a human user (!resolvedDelegate.app) isn’t covered by a snapshot test in this PR. Add a test case that passes --delegate with a non-app user and asserts the failure message/suggestion, similar to the new app-user rejection tests for --assignee.
src/commands/issue/issue-update.ts
Outdated
| if (!resolvedDelegate.app) { | ||
| throw new ValidationError( | ||
| `Cannot use --delegate with human user '${delegate}'`, | ||
| { | ||
| suggestion: | ||
| `Use --assignee ${delegate} to assign the issue to a human user.`, | ||
| }, | ||
| ) |
There was a problem hiding this comment.
The new validation that rejects using --delegate with a human user (!resolvedDelegate.app) isn’t covered by a snapshot test. Add an issue update test that uses --delegate with a human user and asserts the error + suggestion output, mirroring the new app-user rejection test for --assignee.
Summary
--delegatetolinear issue createandlinear issue updatedelegateIdinstead of overloadingassigneeId--assigneewith a clear suggestion to use--delegatedocs/usage.mdWhy
Linear now distinguishes between human assignees and agent delegates. Without explicit delegate support, assigning an app user can look accepted while not expressing the correct model. This change makes the CLI reflect that distinction directly.
Verification
mise x deno@2 -- deno task codegenmise x deno@2 -- deno lint src/commands/issue/issue-create.ts src/commands/issue/issue-update.ts src/utils/linear.ts test/utils/mock_linear_server.ts test/commands/issue/issue-create.test.ts test/commands/issue/issue-update.test.tsmise x deno@2 -- deno fmt --check src/commands/issue/issue-create.ts src/commands/issue/issue-update.ts src/utils/linear.ts test/utils/mock_linear_server.ts test/commands/issue/issue-create.test.ts test/commands/issue/issue-update.test.ts docs/usage.md test/commands/issue/__snapshots__/issue-create.test.ts.snap test/commands/issue/__snapshots__/issue-update.test.ts.snapmise x deno@2 -- deno test --allow-all --quiet test/commands/issue/issue-update.test.ts test/commands/issue/issue-create.test.tsNote
Repo-wide
deno task checkstill reports many pre-existing type errors outside this patch, so verification here is scoped to the touched area.