Skip to content

[Bug]: A thread watching several pull requests gets one wake and one turn per pull request from the same pass #19183

Open

Description

@NikitaMGrimm

Note

🤖 Claude Opus 5.5 writing on behalf of NikitaMGrimm

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Related, not a duplicate: #16829 is about the cost of one wake on a large thread with a cold prompt cache. It lists "bursts within a few seconds coalesce into one wake" among its asks, with an example of three wakes for one pull request. This report is the case of one thread watching several pull requests.

Area

apps/server

Steps to reproduce

  1. In one thread, have the agent call watch_pull_request on several open pull requests. Mine watched 11.
  2. Cause news on several of them between two passes of the watcher. Editing the descriptions of several PRs that CodeRabbit has reviewed does it: the bot rewrites its summary comment on each one within a minute.
  3. Look at the thread's timeline after the next pass.

Expected behavior

One pass has one wake for a thread: a single message that lists what changed on each pull request the thread watches, and one agent turn that handles it.

Actual behavior

The pass queues one message per pull request, and each runs as its own turn. PullRequestWatchReactor reads all watched pull requests in one pass, then dispatches a separate thread.pull-request-watch.sync command, each carrying its own wake, for every thread and pull request pair.

From my thread, 11 to 13 October (times UTC, counted from the timeline's pr-watch notifications and the runs they started):

Count
Watch wakes, each its own turn 68
Passes that produced them 40
Passes with more than one wake 13, carrying 41 wakes
Turns if each pass sent one wake 40

The largest pass queued 7 wakes between 22:18:45.992 and 22:18:48.998 on 13 October, all "new comments" from the same bot. They ran as 7 consecutive turns ending at 22:19:33. Another pass queued 6 "checks failed" wakes after I added six watches.

The agent cannot treat them as one event. In that 7-wake pass it checked the other pull requests during the second turn, then answered the next four wakes with "same as the last one".

Impact

Minor bug or occasional failure

Each extra turn re-reads the thread's context, so the cost grows with the thread, which is the cost #16829 measures. It also fills the timeline with near-identical notifications and replies. It hits anyone who babysits several pull requests from one thread.

Version or commit

Current main at a01c48f. Seen on a build of v0.0.46-nightly.20261013.3080.

Environment

T3 Code server on Linux, used from the Windows desktop app. Claude Opus 5.5 through Claude Code. Pull requests on GitHub.

Logs or stack traces

requestedAt (UTC)     wakes  timeline notifications of that pass
10-11T19:00:28        4      #18308, #18310, #18309, #18311: checks failed
10-11T21:50:28        6      #16249, #16198, #16453, #16938, #17892, #15269: checks failed
10-12T12:42:58        3      #17892, #18310, #16249: checks failed
10-13T22:18:45        7      #16198, #16453, #16249, #18308, #15269, #17892, #18310: new comments

Workaround

None in the product. Watching fewer pull requests per thread avoids it.

Possible fix

Let thread.pull-request-watch.sync carry every watch of one thread that a pass has something to record for, with at most one wake whose text has a section per pull request. State and wake still commit together, the cadence and the per pull request state and comment limit stay as they are, and a wake about a single pull request reads as it does today. I have this working with tests on fix/pr-watch-combined-wake and can open a PR if the direction is right.

Activity

  1. juliusmarminge commented on Oct 21, 2026

    @juliusmarminge
    Member

    Attempted on Linux with the web dev server at main 70e5e384da, using isolated seeded state. One agent thread successfully armed two watches through watch_pull_request against the GitCafe mirror. At 22:31:53 UTC, both reads failed before any wake could be queued:

    PullRequestOperationError: GitCafe returned an unreadable response.
    SchemaError: Expected "unknown" | "conflicting"
    at ["merge"]["conflicts"]
    

    This blocks verification of the reported batching behavior here; it does not establish that the bug is fixed. The mirror variant also differs from the reported GitHub setup. No matching open duplicate found.

    Can you attach a fresh timeline or sanitized runtime excerpt from a current-main GitHub run showing multiple PR wakes with the same watcher pass, including the build SHA? Leaving this open pending that verification.

  2. NikitaMGrimm commented on Oct 21, 2026

    @NikitaMGrimm
    ContributorAuthor

    Note

    🤖 Claude Opus 5.5 writing on behalf of NikitaMGrimm

    Thanks for trying it. Here is a run against GitHub on current main.

    Build: main at b5a226e49c, web dev server on Linux, isolated seeded state, Claude Sonnet 5.5 as the agent.

    Setup: a private scratch repository with three open pull requests that each edit the same line. One agent thread armed watches on all three with watch_pull_request and ended its turn. I then pushed one commit to the default branch that conflicts with all three.

    The next watcher pass queued three separate wakes within 315 ms, one per pull request, and the agent ran three turns back to back:

    Time (UTC) Event
    23:22:58 Conflicting commit pushed to main
    23:23:05.323 Wake queued: "Update on pull request #1 … The branch now conflicts with main."
    23:23:05.438 Turn 1 starts
    23:23:05.476 Wake queued: "Update on pull request #2 … The branch now conflicts with main."
    23:23:05.638 Wake queued: "Update on pull request #3 … The branch now conflicts with main."
    23:23:07.310 Turn 1 ends, turn 2 starts at 23:23:07.636
    23:23:09.811 Turn 2 ends, turn 3 starts at 23:23:10.111
    23:23:12.194 Turn 3 ends
    The three wake messages, as stored in the thread
    [23:23:05.323Z] message:pr-watch:4a4d8bcd-…
    Update on pull request #1 (https://github.com/NikitaMGrimm/t3-pr-watch-repro/pull/1), which T3 Code is watching for you:
    - All 1 check passed on 091b0a3.
    - The branch now conflicts with main.
    
    Look into each item and act on it as your task requires. T3 Code keeps watching and wakes you on the next change, so end your turn when you are done. When you hand the work back to the user, call unwatch_pull_request first so the thread returns to their inbox.
    
    [23:23:05.476Z] message:pr-watch:87bf6b7f-…
    Update on pull request #2 (https://github.com/NikitaMGrimm/t3-pr-watch-repro/pull/2), which T3 Code is watching for you:
    - All 1 check passed on 54acc03.
    - The branch now conflicts with main.
    
    Look into each item and act on it as your task requires. […same closing…]
    
    [23:23:05.638Z] message:pr-watch:74e80c0c-…
    Update on pull request #3 (https://github.com/NikitaMGrimm/t3-pr-watch-repro/pull/3), which T3 Code is watching for you:
    - All 1 check passed on 081cc36.
    - The branch now conflicts with main.
    
    Look into each item and act on it as your task requires. […same closing…]
    

    The agent's three replies: "Pull request #1 updated: …", "Pull request #2 updated: …", "Pull request #3 updated: …".

    Here the cause was a single push to the base branch, which is a common way for several watched pull requests to change in the same pass. Each wake repeats the closing instructions and starts its own turn, so the cost grows with the number of watched pull requests.

    Separately, the GitCafe failure you hit looks like its own bug. GitCafePullRequestProvider accepts only "unknown" | "conflicting" for merge.conflicts, so a pull request without conflicts probably can't be read. I haven't checked what GitCafe returns in that case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions