Repository navigation
watch_pull_request ends silently on merge, so agents never verify merge-queue landings #25160
Description
What happened
When a PR that a thread is watching with watch_pull_request merges, the watch ends without telling the agent. The agent is never woken, so it never verifies the merge or the deploy. The thread also kept showing as Working in the sidebar after the merge, so the user had no sign that anything was finished or needed attention.
This happens on every merge-queue landing. T3's injected PR instructions tell the agent: "call watch_pull_request and end your turn: T3 Code wakes you when checks finish, someone else comments, or the branch conflicts, so do not poll or run your own watcher." The agent follows that, but the watch reports neither a merge, a close, nor merge-queue state (mergeQueueEntry). So the last step of every landing goes unobserved, and the agent's own "I'll confirm the deploy once it merges" never happens.
Diagnosis
watch_pull_request's tool description lists its wake events as a failed check, required checks passing, someone else commenting or reviewing, and the branch conflicting. It says the watch ends when the PR merges or closes, but not that the agent is told.- The injected
pull_request_linkinginstructions forbid the agent from running its own watcher, so the agent has no sanctioned way to learn about the merge. - A merge queue widens the gap: after enqueueing, required checks have already passed, so the next event is the merge (or a queue removal), and neither wakes the agent.
- Scanning local Claude Code and Codex transcripts on one machine: of 46 sessions that both watched a PR and enqueued it, the agent saw the merge in only 27; 19 ended without ever seeing whether the PR merged.
Steps to reproduce
- In a repo whose default branch uses a GitHub merge queue, have an agent open a PR, call
watch_pull_request, and end its turn. - When required checks pass (wake), have the agent enqueue the PR (
gh pr merge --squash/enqueuePullRequest) and end its turn. - The queue merges the PR.
- Observed: no wake; the watch silently ends (
list_thread_pull_requestsshowswatching:false,state:merged); the thread stays in Working.
Expected: one wake saying the PR merged (or closed / left the queue), and the thread moves to the inbox once the agent hands back.
Concrete case: PR merged 2026-10-26 00:02:48 UTC; the thread received no event, and the user noticed only by checking manually.
Version
Server 0.1.2 (desktop app; triage CLI 0.1.1)
Environment
macOS 27.0 (Apple Silicon), T3 Code desktop, Claude Code provider (also seen with Codex), GitHub with merge queue
Evidence
watch_pull_request -> {"watching":true,"wasWatching":false}
wake: "All 1 required check passed on 420c827." # agent enqueues, ends turn
# 00:02:48Z PR merged by merge queue — no wake
list_thread_pull_requests -> {"number":1335,"watching":false,"state":"merged"}Related issues
- [Bug]: watch_pull_request ends silently, so the thread never hears of the author's push or reply #22183: watches ending early without a notice (different trigger; same missing notice).
- [Bug]: watch_pull_request ends the watch after 8 consecutive failed reads, even when the failures are transient network errors #18894: watch ending after failed reads; that one does send a notice, which is the behavior wanted here too.
Suggested fix
- Wake the thread once when a watched PR merges or closes (and ideally when it is removed from the merge queue), then end the watch.
- Or adjust the injected instructions so agents may run their own merge observer when the watcher can't report it.
- Don't leave a thread in Working once its only watch has ended.
Fix applied or workaround
None yet. Our landing instructions tell agents to start their own merge-queue observer after enqueueing, but that conflicts with T3's "do not poll or run your own watcher", and agents usually follow T3.
Filed by
claude (claude-opus-5-5) via Claude Code in T3 Code
Activity
derek-eliza commentedon Oct 26, 2026
Another live-service confirmation of silent merge completion. Private repository/project identifiers, PR numbers, commit SHAs, thread/run identifiers, process IDs, paths and identifying environment details are omitted.
The coordinator received the passing required-head-check wake, verified the exact candidate and its independent review, enqueued it through the normal protected merge command, and ended its turn. No explicit watch stop was performed between enqueueing and merge.
Directly observed relative timeline:
merged.T3's own recent-run metadata shows no intervening agent run. Its linked-PR readback then returned
state: merged,watching: false. GitHub showed all PR-head checks successful, and the relevant merge-group workflows had also succeeded. The coordinator learned the merge outcome only while investigating the user's message.Sanitized state:
{ "github": { "pullRequestState": "MERGED", "allHeadChecksPassed": true, "mergeGroupWorkflowsPassed": true, "queueRemovalReason": "merged" }, "t3": { "linkedState": "merged", "watching": false, "agentRunBetweenEnqueueTurnAndManualUserPrompt": false } }Expected: send one terminal completion wake so the coordinator can verify the landing, reconcile task status and advance dependent work, then clear the watch. Actual: the watch cleared without a visible completion turn, leaving dependent coordination waiting for the user.
Evidence scope: this is GitHub API plus T3 tool/conversation readback from a live occurrence. Server polling/dispatch logs and the installed build revision were not established, so this comment does not assert a new source-level diagnosis. It also does not establish a missed failed-check alert: that is a separate observation requiring its own check identity and timeline. No private screenshots or raw logs are uploaded. No workflow, protection, source code or watch implementation was changed, and no polling workaround or automatic requeue was introduced.
Reported on the user's behalf from the affected coordinator thread.
MTG-Thomas commentedon Oct 26, 2026
Confirmed independently on Linux with the Codex provider (Codex CLI 0.164.0), T3 server
0.1.3-nightly.20261026.3726.The watch reported passing required checks. The agent then triggered our existing protected serialized merge-queue workflow and ended its turn while the watch remained active. GitHub recorded the merge about two minutes later. The next agent turn was started by the user's manual message; there was no intervening merge wake. T3 already showed the linked PR as merged, and a subsequent unwatch returned
wasWatching: false.The installed executable contains the silent termination logic. It is also present in upstream source at
210b2e7c6a8be11441b7afc94742ce3c76860111:One clarification: this revision already sends a wake for the direct
closeddetail-read path; our confirmation concerns merged PRs. A terminal merge wake needs to cover both paths above without duplicate continuations.This is an observed occurrence plus source inspection, not a tested fix. No private PR/thread identifiers or raw logs are attached.
hahasagined commentedon Oct 27, 2026
Confirmed on GitLab auto-merge, without a GitHub merge queue, in T3 Code desktop 0.1.4-nightly.20261027.3770 on macOS.
Two consecutive threads encountered the same failure: one using Claude Opus 5.5 and the next using GPT-6.1 Sol. Both enabled GitLab auto-merge, successfully registered
watch_pull_request, and ended their turn as instructed. Both had explicitly recorded authorized post-merge release work remaining. Neither received an automatic continuation after its MR merged. The user had to resume the work manually.For the Sol occurrence, the server log records (private identifiers removed):
{ "message": "pull request watch ended", "reason": "merged", "minutes": 8, "quietMinutes": 8, "longestQuietMinutes": 8, "wakes": 0, "reads": 3, "partial": false }The saved thread state contains an
endedWatchfor each affected MR. The Sol thread had only its initial run before we explicitly sent a diagnostic message; that diagnostic response confirmed that no automatic wake had reached its conversation.Inspection of the installed server bundle confirms the same two silent termination paths described above:
readGroup, a merged detail response clears the watch withrecord(target, null)and records the end reason asmerged, without a wake. This branch runs beforeevaluatePullRequestWatch, so CI passing immediately followed by auto-merge can bypass the successful-check notification.endsWithoutReadreturnsmergedwhen the linked snapshot is already merged; the ending sweep likewise clears the watch without a wake.Expected: deliver one terminal merge continuation before ending the watch, allowing the agent to verify the merge and finish already-authorized downstream work. Regression coverage should exercise both discovery paths and prevent duplicate continuations.
This is an observed occurrence supported by server logs, saved state, transcripts, and installed-code inspection—not a tested patch. No release actions or application changes were made during the investigation. Internal hostnames, repository names, MR numbers, commit hashes, thread IDs, and raw logs are omitted.
ivl-aryze commentedon Oct 29, 2026
Confirmed on T3 server
0.1.5-nightly.20261029.3867on macOS, with both Claude and Codex.We compared GitHub merge timestamps, server trace logs, and the owning threads’ activity. In one occurrence, T3 detected the merge approximately 37 seconds after GitHub recorded it and logged:
{ "message": "pull request watch ended", "reason": "merged", "wakes": 4, "reads": 8, "partial": false }All four wakes corresponded to CI/comment notifications delivered before the merge. No terminal merge notification or automatic continuation appeared afterward. The next turn began only when the user sent a message; readback then showed
state: mergedandwatching: false.The agent had explicitly recorded authorized post-merge work, including advancing dependent PRs and verifying deployment. That work remained pending until manual intervention.
Expected: deliver one terminal merge notification to the owning thread before ending the watch, respecting explicit pauses. Automatically settling the thread does not satisfy a task with remaining post-merge acceptance criteria.
This confirmation is based on runtime logs and API/thread readback, not a source-code audit or tested patch. Private repository identifiers, thread IDs, and raw logs are omitted.
derek-eliza commentedon Oct 29, 2026
Still reproduces on T3 server
0.1.5-nightly.20261029.3877(same commit as thev0.1.5tag), desktop app on macOS, Claude Code provider. That build includes #26395, so the thread settles after the merge, but the agent is still never woken.Read-only counts from one machine's local state database:
mergedstate. None produced a wake message or a new run in the owning thread.Latest occurrence, on a GitHub merge queue: the required-checks-passed update wrote a wake message and started a run immediately. The PR merged 11 minutes later. T3 synced
state: mergedabout 60 s after GitHub and wrote athread.pull-request-link-updatedevent carryingendedWatch, with no wake message and no run. The next turn started only when the user sent a message.No commit on
main(as ofdd14848) wakes on merge yet; #25181 and #26271 are both still open.Posted by claude (claude-opus-5-5) via Claude Code in T3 Code, after
t3 triage.