[Bug]: a new watch_pull_request reports checks that had already passed as news#22184

opened22d agobyEemanuel-mrkr

Before submitting

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

Area

apps/server

Steps to reproduce

  1. Open a GitHub PR whose required checks have all passed on the current head.
  2. In a thread, call watch_pull_request on it, and end the turn.

Seen on 2026-10-20 (UTC): the watch started at 05:52:53 on head 0410491, and CI on that head had passed hours earlier. At 05:53:25 the thread was woken with "checks passed". Nothing had changed: same head, same check runs. The agent spent a turn confirming it was "just CI going green again on the same commit".

Expected behavior

When a watch starts, the PR's current head, checks and reviews are its baseline. The thread wakes only for changes after that point.

Actual behavior

The first poll after the watch starts reports the existing state, "checks passed" here, as if it were new. Each new watch costs a turn on a possibly large thread (see #16829). It also teaches the agent to dismiss the first wake, which can be a real one.

Impact

Minor bug or occasional failure

Version or commit

T3 Code (Alpha) 0.0.68

Environment

macOS 27.0 (Apple Silicon), T3 Code desktop (Alpha), Claude Code provider, GitHub PR on github.com

Synced from GitHub

I'd like to work on this one.

I think I found the cause. When a PR is watched for the first time, Orchestrator.ts creates the watch with headSha: null, passed: false, passedChecks: []. The only time it seeds real state is from a previous watch's endedWatch. On the first poll, evaluatePullRequestWatch in pullRequestWatch.ts then sees headSha !== watch.headSha and !passed, so it reports checks-passed for checks that had already passed. Comments are already handled correctly, because remarksThrough: startedAt serves as their baseline.

Plan: treat the first evaluation of a fresh watch (one that has no recorded head yet) as the baseline. It records the head, the check results and whether the PR is conflicting, and wakes no one. Only later changes wake the thread. I'll add a test in the pullRequestWatch tests: start a watch on a PR whose checks already passed, then check that the first poll produces no wake and that a later push or failure still does.

One question first: should checks that are already failing when the watch starts still wake the thread once? You could argue the agent wants to know about those. Or should the baseline cover failures too, as this issue proposes?