Repository navigation
Description
What happened
A thread watched a GitHub PR with watch_pull_request. The base branch requires two checks: a quick lint job, and an aggregate E2E job that has needs: on several E2E runner jobs. Once the lint job passed, T3 woke the thread with "All 1 required check passed". The runners were still going, and the required aggregate job didn't exist on the commit yet, so the message was false.
The next sweep sends a second wake once the aggregate job appears, so the watch itself recovers. The problem is that first message: an agent that trusts it can report the PR as done, or merge it, before a required check has run.
Diagnosis
For GitHub, T3 learns which checks are required only from isRequired on the check contexts already on the commit (toCheckEntries in gitHubPullRequestJson.ts). A required check from branch protection or a ruleset that hasn't been created yet doesn't show up at all. So in evaluatePullRequestWatch (apps/server/src/orchestration-v2/pullRequestWatch.ts), required holds only the lint check, passedNow is true, and the thread gets a checks-passed wake with required: true.
GitHub only creates a job that has needs: when it starts. That means any workflow whose required check is an aggregate "all tests passed" job, a common setup, hits this.
The Forgejo provider already reads the branch's required checks (forgejoRequiredChecks.ts). GitHub could do the same: read the base branch's required checks (GraphQL baseRef.refUpdateRule.requiredStatusCheckContexts, or REST GET /repos/{owner}/{repo}/rules/branches/{branch}) and treat any that haven't been created yet as pending.
Steps to reproduce
- In a GitHub repo, protect the base branch with two required checks: a quick job
A, and a jobDonewithneeds: [slow], whereslowruns for a few minutes. - Open a PR and call
watch_pull_requeston it. - Wait until
Ahas passed whileslowis still running. - The next sweep wakes the thread with "All 1 required check passed", although
Doneis required and hasn't started.
Version
0.1.6-nightly.20261030.3940
Environment
Linux x64, desktop app with its local server, Claude agent, github.com, classic branch protection with two required checks.
Evidence
- About three minutes after the push, a sweep woke the thread with "All 1 required check passed" while the E2E runners were still going.
- The required aggregate job started about 30 seconds later, after the runners finished.
- The branch protection's required checks were the aggregate E2E job and the lint job.Related issues
#23712 (fixed: missing final wake after an early required-check pass). This issue is about the early wake's message, not a missing wake.
Fix applied or workaround
After a "required checks passed" wake, look at the full check list and keep the watch on until every check on the head has finished.
Filed by
Triaged and drafted by Claude Opus 5.5 (claude-opus-5-5) in Claude Code inside T3 Code.
Activity
BartWaardenburg commentedon Nov 5, 2026
Another case: the ruleset requires
CIandAction checks passed. Both are summary jobs withneeds:.Action checks passedfinished first, and T3 woke the thread with "All 1 required check passed" whileCIdid not exist yet. Auto-merge then merged 4 seconds afterCIpassed, before the next sweep. So the second wake never came, and with #25160 the thread saw nothing more. When the watch reads the required checks of the ruleset (GET /repos/{owner}/{repo}/rules/branches/{branch}), it fixes this case.