You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Bug]: watch_pull_request wakes only on failures and all-required-passed, not on other check state changes #16924
I searched existing issues and did not find a duplicate.
I included enough detail to reproduce or investigate the problem.
Area
apps/server
Summary
watch_pull_request wakes the agent for only two kinds of check news: a check fails, or all required checks pass. Any other change in a check or commit status is silent. Examples are a non-required check turning green, a check starting again, or a status moving from pending to success. The agent cannot react to that news and stays asleep until the user steps in.
The watch should wake the agent on every change in check or status state, required or not.
Steps to reproduce
Open a pull request with required CI checks, a non-required review bot check (for example Greptile), and a required commit status that stays pending (for example a do-not-merge hold).
Call watch_pull_request.
Let CI pass and let the review bot check turn from pending to success.
Expected behavior
The agent is woken for each change, with the check name and its old and new state. The agent then decides what the change means for its task.
Actual behavior
No wake-up arrives. In evaluatePullRequestWatch (apps/server/src/orchestration-v2/pullRequestWatch.ts):
A check that changes to anything other than a failure produces no change, unless it completes the "all required checks passed" gate.
The gate never completes while any required check stays pending. So a green CI run or a green review bot is never reported.
Impact
The watch decides on the agent's behalf which check news matters. Every task that waits for a specific check, or for a set of checks that is not "all required", has to poll instead. The tool description tells agents not to poll.
Possible fix
Store the last known state of each check on the watch, not only failedChecks and passed. On each pass, report every check whose state changed since the last wake, grouped in one message, as the remarks are today. Keep the existing "checks failed" and "all required checks passed" lines as summaries on top.
Note
This AI-generated response on behalf of @tunnckoCore. Harness: ClaudeCode (via T3 Code). Model: Claude Opus 5.5
Another user reporting unreliable unattended PR follow-up with T3 Code on Linux using the Codex provider. Manual prompting was needed to get the agent to check and finish reporting the outcome.
For accuracy, in our recorded session the review notifications and “All 2 required checks passed” notification did arrive. The agent then enqueued the PR, called watch_pull_request again (watching: true, wasWatching: true), and ended its turn. GitHub merged the PR at 2026-10-14 22:16:37 UTC, but no merge wake is visible in the conversation before the user manually prompted the agent. A later cleanup call to unwatch_pull_request returned wasWatching: false.
This supports the broader need for reliable follow-up as a watched PR progresses, but does not establish that the check-state filtering described here caused our incident. We do not have the watcher's polling logs or a confirmed root cause. Posting on the user's behalf from the affected thread.
We confirmed a merge-completion variant of the unattended follow-up problem described in this earlier comment. This is a separate path from check-state filtering in evaluatePullRequestWatch, but it appears to explain that comment's post-merge symptom.
On Linux with the Codex provider, running 0.1.1-nightly.20261016.3203:
The agent watched a PR, queued it for merge, and ended its turn.
The repository's merge queue merged the PR at 2026-10-16 15:01:37 UTC.
At 15:01:59.789 UTC, the T3 server logged pull request watch ended, with reason: 'merged', minutes: 28, wakes: 2, reads: 14, and partial: false.
T3's linked-PR state became merged, with watching disabled. No completion wake reached the conversation; the next agent turn began only after a manual user message at 15:06:39 UTC.
We inspected the running compiled server and the matching branches in public source pinned at cfafb4bb54d244e4612f5681aad3832ea64cb0fb. There are two silent termination paths in apps/server/src/orchestration-v2/PullRequestWatchReactor.ts:
The closed-PR handler at line 345 supplies a wake. record only includes a wake in its dispatched command when that optional argument is provided. The merged paths remove the watch without constructing a completion message. If checks finish and automatic merge happens between polls, the terminal branch also returns before normal check-change evaluation.
The reproduction below runs those actual pinned source branches in isolation. It uses small in-memory stand-ins for Effect and the dispatch seam, so it verifies the arguments reaching record, including the missing wake. It does not exercise the real Effect scheduler, persisted message delivery, or a live GitHub merge. The incident and server log above are separate runtime evidence.
Tested with Node 22.23.3. Save as repro.cjs and run node repro.cjs. It downloads only the pinned public source file; no GitHub token or T3 server is needed. Alternatively, pass an existing copy of that source file as the first argument.
Observed output:
{"freshlyFetchedMerged":false,"cachedMergedSnapshot":false,"freshlyFetchedClosedControl":true}
REGRESSION: freshlyFetchedMerged clears the watch without a wake
REGRESSION: cachedMergedSnapshot clears the watch without a wake
The script exits 1 for the reproduced omission and 2 for a setup/source-loading error. Node may also print its experimental stripTypeScriptTypes warning.
The smallest fix appears to be a shared merged-completion handler that supplies a wake and clears the watch, used by both merged-state paths. Explicit stop, settlement, and stale-watch guards should remain intact. An integrated reactor regression should cover both paths, including automatic merge between check polls, and verify that a subsequent sweep does not send a duplicate completion wake.
Investigated and posted on the user's behalf by GPT-6.1 Sol through the Codex harness in T3 Code.
Activity
Kryckan commentedon Oct 15, 2026
Another user reporting unreliable unattended PR follow-up with T3 Code on Linux using the Codex provider. Manual prompting was needed to get the agent to check and finish reporting the outcome.
For accuracy, in our recorded session the review notifications and “All 2 required checks passed” notification did arrive. The agent then enqueued the PR, called watch_pull_request again (watching: true, wasWatching: true), and ended its turn. GitHub merged the PR at 2026-10-14 22:16:37 UTC, but no merge wake is visible in the conversation before the user manually prompted the agent. A later cleanup call to unwatch_pull_request returned wasWatching: false.
This supports the broader need for reliable follow-up as a watched PR progresses, but does not establish that the check-state filtering described here caused our incident. We do not have the watcher's polling logs or a confirmed root cause. Posting on the user's behalf from the affected thread.
MTG-Thomas commentedon Oct 16, 2026
We confirmed a merge-completion variant of the unattended follow-up problem described in this earlier comment. This is a separate path from check-state filtering in
evaluatePullRequestWatch, but it appears to explain that comment's post-merge symptom.On Linux with the Codex provider, running
0.1.1-nightly.20261016.3203:pull request watch ended, withreason: 'merged',minutes: 28,wakes: 2,reads: 14, andpartial: false.merged, with watching disabled. No completion wake reached the conversation; the next agent turn began only after a manual user message at 15:06:39 UTC.We inspected the running compiled server and the matching branches in public source pinned at
cfafb4bb54d244e4612f5681aad3832ea64cb0fb. There are two silent termination paths inapps/server/src/orchestration-v2/PullRequestWatchReactor.ts:record(target, null)without a wake argument.endsWithoutReadroutes it into the ending list, which also calls the same silent record operation at line 537.The closed-PR handler at line 345 supplies a wake.
recordonly includes a wake in its dispatched command when that optional argument is provided. The merged paths remove the watch without constructing a completion message. If checks finish and automatic merge happens between polls, the terminal branch also returns before normal check-change evaluation.The reproduction below runs those actual pinned source branches in isolation. It uses small in-memory stand-ins for Effect and the dispatch seam, so it verifies the arguments reaching
record, including the missing wake. It does not exercise the real Effect scheduler, persisted message delivery, or a live GitHub merge. The incident and server log above are separate runtime evidence.Tested with Node 22.23.3. Save as
repro.cjsand runnode repro.cjs. It downloads only the pinned public source file; no GitHub token or T3 server is needed. Alternatively, pass an existing copy of that source file as the first argument.Observed output:
The script exits 1 for the reproduced omission and 2 for a setup/source-loading error. Node may also print its experimental
stripTypeScriptTypeswarning.Runnable reproduction
The smallest fix appears to be a shared merged-completion handler that supplies a wake and clears the watch, used by both merged-state paths. Explicit stop, settlement, and stale-watch guards should remain intact. An integrated reactor regression should cover both paths, including automatic merge between check polls, and verify that a subsequent sweep does not send a duplicate completion wake.
Investigated and posted on the user's behalf by GPT-6.1 Sol through the Codex harness in T3 Code.