Follow up Linear triggers with Agent Sessions, team routing, and replies - #88
Follow up Linear triggers with Agent Sessions, team routing, and replies#88michaelmwu wants to merge 21 commits into
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d6439afaed
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@as-cto Could you review #88 when you have time? This is the single ready-for-review Linear follow-up after #59, and it includes the bounded causal history, corrected Linear cursor types, projectless team routing, reply-parent filtering, and connection-isolation regression coverage from your feedback. The focused regression set is green (60 tests). Thank you again for validating the earlier work against a real Linear workspace. |
d6439af to
31428bc
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 31428bcb33
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Reviewing #88 from a self-hosted deployment — thanks for the ping. Two things we'd like to align on, both about what a user actually sees in the session panel: 1. Live progress in the session. Today a session posts a single accept 2. Deduplicating a single delegation. A delegation emits both an Happy to test any of this against our deployment. |
|
Follow-up from our self-hosted deployment, this time a concrete bug report on the boot migration in this branch (head What happens. On first boot, whereas revisions produced by Second effect. Manual runs addressed by the original project slug resolve to the archived project and throw Workaround we use. Right after switching images, re-install every bundle by Suggested fix. Have the migration resolve Happy to test a patched build against our staging copy. |
|
Follow-up on the migration report above, after recovering a production hub running this branch. Re-installing the archived projects by What worked, verified on a copy of the database and then in production: Two small suggestions: |
|
@as-cto Confirmed both reproductions and fixed them in c96e134.
Added migration, embedded persistence, and manual-resolution regressions. Focused migration/manual/configuration tests (26), typecheck, lint, format check, and production build pass locally. Thank you for the staging reproduction. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c96e134a3d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7aece66b4c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
One more finding from production, on issue-comment replies (not agent sessions). Linear threads are one level deep: What we run now: the reply executor passes Happy to open PRs for any of these if useful. |
|
Thanks for c96e134 — we merged the current head ( As offered, the fixes we described above (thread-root replies, provider error forwarded to the agent,
It is one squashed commit with the per-topic history linked in the PR; glad to split it any way that suits the review. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4b408e017d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b40974bb91
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@as-cto Integrated voytravel#4 as fe71b2d with your authorship preserved. I also fixed the three current-head lifecycle findings in 3f84488: late idle completion now reports success, Stop survives trigger-revision changes, and multi-route stops emit one receipt-owned confirmation while stopping work in every routed project. The full combined suite passes (1,245 tests; 15 environment-gated skips), as do typecheck, lint, format, database drift, and build. Thank you for the production repros and contribution. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3f8448819b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@as-cto Closing the loop on your earlier session-panel questions: your voytravel#4 contribution is now integrated with authorship preserved, including session/comment delegation dedup and continuation behavior. I also confirmed that live incremental progress is a separate daemon/protocol concern: Hub currently receives lifecycle boundaries and final output, not truthful intermediate agent output to forward. I am deliberately keeping synthetic progress machinery out of this Linear follow-up rather than expanding an already broad PR. |
|
Two more findings from end-to-end runs against a real workspace on this branch ( 1. Comment history hydration always fails: 2. Session threads are comment threads, so a human reply in a session fires twice. This answers question 2 above, from observation: Linear materializes each agent-session activity as a comment in the issue thread (root posted by the Linear bot, "This thread is for an agent session with …", agent responses as comments authored by the app user). Consequences:
Fix we are testing, to be folded into voytravel#4: exclude comment threads whose root is one of |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3175743e81
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Small operational note, unrelated to Linear itself: every execution on this branch logs a 500 on |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 484ba990d4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| or( | ||
| isNull(schema.projectTriggerRoutes.resourceId), | ||
| eq( | ||
| schema.projectTriggerRoutes.resourceId, | ||
| resourceId === undefined ? "" : String(resourceId), | ||
| ), | ||
| ...(resourceIds.length === 0 | ||
| ? [] | ||
| : [inArray(schema.projectTriggerRoutes.resourceId, resourceIds)]), |
There was a problem hiding this comment.
Route stops to projects with active session work
When a project with an active Agent Session activates a revision containing no Linear trigger, activateProjectConfigurationRevision deletes its prior project_trigger_routes, so this current-route-only lookup returns no rows, records no_project_route, and never reaches the provider's early stop handler. The existing execution can therefore continue after the operator presses Stop; preserve a cancellation route or also locate projects with matching active session work independently of the current launch configuration.
AGENTS.md reference: AGENTS.md:L26-L26
Useful? React with 👍 / 👎.
|
Both findings above are now fixed and verified in production on our side; the commits are in voytravel#4 (details there), and the |
…tions, honor stop; reply under thread roots and fail runs on lost deliveries
Squashed from the per-topic branches we run in production on a self-hosted hub
(image lineage linear-v5/v6, built on this PR's head).
Session lifecycle
- idle deadline: an execution is only completed at its idle deadline once its
required outputs (linear.reply, required: true) were emitted; a session that
already replied is completed, not left open.
- explicit close: when a workflow ends without hub.reply, the hub posts a short
closing response itself instead of leaving the session open silently.
- questions: hub.reply accepts kind: "question" with options, delivered as a
Linear elicitation activity with a select signal; the session goes to
awaitingInput instead of complete. Choices are deduplicated.
- stop: the Linear stop signal no longer opens a run; it stops running and
undispatched executions (stopped_by_user / agent_session_stopped).
Issue comments
- replies are posted under the thread root (comment.parentId ?? comment.id):
Linear only accepts one level of nesting and rejects a parentId that is
itself a reply ("Parent comment must be a top level comment").
- the provider error is forwarded to the agent in the hub.reply tool error
("Provider said: ...") instead of being swallowed.
- new comment filter thread_with_app: true keeps a reply only when the app
already posted in that thread; complements replies_only.
- a comment run is superseded (superseded_by_agent_session) when the same
comment also opens an agent session, by commentId or sourceCommentId, so a
single delegation no longer fires two agents.
Executions
- a required output whose delivery attempts all failed ends the execution,
step and run as failed (output_delivery_failed) at finish_execution instead
of succeeded; on a session a short error activity is posted.
`PaseoIssueCommentHistory` declared `$issueId: String!` where the issue filter expects an `ID`. Linear rejected every request, so comment runs never received their thread history. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…supersede on prompted Linear materializes an agent session as a comment thread: the root is a bot comment, the user's prompts are their comments, and the app's responses are comments authored by the app user. After the first response every session thread therefore satisfied `thread_with_app`, so a reply there started both an agent-session run (prompted) and a comment run, and the user was answered twice. - `readCommentThread` now also returns the root comment ids of the issue's agent sessions, read in the same request through the comment's issue. The normalized comment event carries `threadIsAgentSession`, which `thread_with_app` treats as disqualifying; `replies_only` alone is unaffected. The provider logs the skipped comment at debug level. - A prompted agent session carries the comment behind the prompt as `agentSession.sourceCommentId` (read from the activity's `sourceCommentId`, nested `sourceComment`, or content). The provider supersedes the comment run started from that comment, as it already did for the comment that created a session. A prompt without a comment supersedes nothing. The webhook order observed in production is what justifies superseding on prompted too: for a reply in a session thread, Linear emits the comment webhook first and the prompted agent-session webhook about 100 ms later, so a comment run may already exist when the prompt is matched. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
484ba99 to
c207080
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c20708025f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| nodes { user { id } botActor { id } } | ||
| pageInfo { hasNextPage endCursor } | ||
| } | ||
| issue { agentSessions(first: 50) { nodes { comment { id } } } } |
There was a problem hiding this comment.
Paginate agent sessions before classifying the thread
When an issue has more than 50 Agent Sessions and the relevant thread root is outside this first page, agentSessionRootIds omits it and threadIsAgentSession is set to false. A thread_with_app comment trigger can then launch a duplicate run for a reply that Linear is already delivering as an Agent Session prompt; paginate this connection or query the root's session association directly before classifying the thread.
AGENTS.md reference: AGENTS.md:L24-L24
Useful? React with 👍 / 👎.
| and( | ||
| eq(schema.projects.id, schema.triggerRuns.projectId), | ||
| eq(schema.projects.organizationId, organizationId), | ||
| eq(schema.projects.status, "active"), |
There was a problem hiding this comment.
Include archived projects when routing session stops
When a project is archived while an Agent Session execution is still running, archiveProject removes its trigger routes without terminating that execution, and this status = active join also excludes its running trigger run from cancellation routing. The Stop webhook is therefore recorded as no_project_route and never reaches stopLinearAgentSession, allowing the daemon to keep working after the user presses Stop; cancellation lookup should include archived projects that still have matching live work.
AGENTS.md reference: AGENTS.md:L26-L26
Useful? React with 👍 / 👎.
| await options.client?.createAgentActivity({ | ||
| linearOrganizationId: event.organizationId, | ||
| agentSessionId, | ||
| content: { type: "response", body: "Stopped at your request." }, | ||
| }); |
There was a problem hiding this comment.
Deduplicate stop confirmations across concurrent retries
When Linear retries the same Stop delivery before the first handler finishes, receipt replay returns the accepted routes because agent_session_stopped is not persisted until match returns. Both invocations consequently reach this mutation, and the route-ownership check allows both because they share the same first route, producing duplicate “Stopped at your request” activities; claim the confirmation at receipt/session level before posting it.
Useful? React with 👍 / 👎.
This is the single follow-up to the Linear trigger implementation merged in #84. It supersedes closed #59 and packages the remaining Linear capabilities together. It also incorporates the production-tested Agent Session and delivery contribution from @as-cto in voytravel#4 while preserving commit authorship.
Included
Scope
This branch contains only the unmerged Linear follow-up work and remains cleanly mergeable with current main. It does not duplicate the initial Linear project-trigger implementation that landed in #84.
Validation
Current head 484ba99:
npm run typechecknpm run lintnpm run format:checknpm run db:checknpm run buildCI is running against this exact head.