Skip to content

feat(server): snooze a thread until its pull request needs attention - #6

Open
flamboh wants to merge 1 commit into
mainfrom
t3code/attention-snooze-server
Open

flamboh wants to merge 1 commit into
mainfrom
t3code/attention-snooze-server

Conversation

@flamboh

@flamboh flamboh commented Oct 7, 2026

Copy link
Copy Markdown
Owner

Note

🤖 Claude Opus 5.5 on behalf of Oliver

Important

Bottom of a three-PR stack on this fork: server → web → mobile. Review in that order. The upstream PR will be a single squashed PR pointing back here.

Problem

An external contributor's pull requests often sit ready for days, waiting on a maintainer. Since pingdotgg#16204, a watched thread stays in Working, and agents are told to unwatch when they hand work back. That leaves two bad options: keep the thread visible while nothing is actionable, or unwatch and miss the maintainer's feedback when it arrives.

Fix

A thread can now be snoozed until its pull request needs attention: a snooze with no wake time, held by the thread's PR watches.

  • Entry points: a thread.snooze-until-attention command for clients, and an always-available MCP tool, snooze_until_pull_request_needs_attention. The tool uses the same writesThread access as watch_pull_request, respects Stop, and passes refusal reasons back to the agent. Both call PullRequestWatchReactor.snoozeUntilAttention.
  • Snapshot at snooze time: the snooze reads each linked PR from the host and starts its watch from that state. What the PR already shows never wakes the thread, and nothing that changes afterwards is missed. If a PR can't be read, the snooze is refused.
  • Waking: a failed check, required checks passing, outside comments or reviews, a conflict, give-up or comment-loop exhaustion all wake the agent as today. The thread returns to Working and the watch carries on as a normal watch. Waking it yourself ends the snooze and keeps the watch.
  • Merge or close: the thread settles regardless of sidebarAutoSettleOnMerge, with no reopening message. If the agent is mid-turn, it settles after the turn. If another linked PR is still open, the snooze ends instead.
  • No one-way doors: unwatch, Stop, unlink, settle and archive all end the snooze. Automatic settlement and usage-limit recovery never touch an attention snooze.
  • Check cadence: PRs watched only by attention-snoozed threads are checked every 10 minutes; shared ones stay at 2.
  • Opt-in agent guidance: the setting snoozePullRequestsAwaitingReview (off by default) tells agents, through the runtime instructions and watch wake text, to use the tool when a PR only waits on someone else's review. When it's off, nothing suggests the tool.
  • Representation: snoozedUntilNeedsAttention: true with snoozedUntil: null, plus the capability threadSnoozeUntilAttention so clients can gate the feature.
  • Docs: docs/user/source-control.md.

Validation

  • Ten adversarial review rounds with GPT-6.1-Sol against the acceptance criteria and for correctness, fixed with Claude Opus 5.5, until a round came back with no findings. Each fix added a regression test.
  • Focused tests: runtimeLayer, pullRequestWatch, ThreadStop, ThreadSettlementService, ProjectionSettlement, PR toolkit handlers, RuntimeInstructions, McpToolAccess, and ProviderSessionManager. Typecheck passes for contracts, shared, client-runtime, server, web and mobile.

Implemented by Claude Opus 5.5 subagents through the T3 Code orchestrator, reviewed by GPT-6.1-Sol (Codex), and coordinated by Claude Opus 5.5 in Claude Code within T3 Code.

A thread whose pull request waits on someone else can now be snoozed with no
wake time, held by pull request watches. The new thread.snooze-until-attention
command and the agent's snooze_until_pull_request_needs_attention tool both go
through PullRequestWatchReactor.snoozeUntilAttention. It reads each open linked
pull request from its host and dispatches the snooze with watches primed from
that read, the way a watch pass records it. Nothing the pull request already
shows (failing checks, required checks that passed, a conflict) wakes the
thread, and anything that changes afterwards does. A watch already on keeps its
start, remark cursor, and wake count, so comments after its last read still wake
it. The snooze is refused when no linked pull request is open, when one cannot
be read, or when the thread's linked pull requests or their watches changed
while the host was read. It follows the snooze rules, and an agent's call that
lands after the user pressed Stop is refused, like watch_pull_request. A watch
pass that began before a snooze primed a pull request reports nothing about it,
caches no read of it, and does not count a failed read of it against the watch,
so a stale read cannot replace what the snooze recorded, settle the thread on a
close the pull request has since undone, let the next pass skip it, or end the
watch early. The snooze's own read starts the failure count over, the way a
pass's successful read does.

A later watch wake brings the thread back and the watch continues. Merging or
closing the last watched pull request settles the thread instead of sending the
closed note, unless the thread's link snapshots show another linked pull request
open, such as one that reopened after its watch ended and so is not watched
again. Then the snooze ends with the watch and the agent hears of the close as
usual. The orchestrator decides this under the thread lock. While the thread is
still at work, the watch reactor leaves the watch and snooze in place and
settles it on the first pass after the turn ends.
A merge is final, so that pass does not read the host again; a closed pull
request can reopen, so each pass reads it again first. Any other way the last
watch ends (unwatch, Stop, unlink, settle, archive) ends the snooze, so it can
never outlive what could wake it. Waking or pinning the thread clears it too,
and a subagent made under such a thread does not inherit it. Usage-limit
recovery respects it: the worker's automatic arming records the recovery without
replacing the snooze, and an armed continuation waits until the snooze ends.

Pull requests only such threads watch are checked every 10 minutes. With the new
snoozePullRequestsAwaitingReview setting, agents are told to snooze instead of
unwatching when a pull request only waits on review: in the shared runtime
instructions when the thread attaches to a provider session, and in watch wakes.

Servers advertise the threadSnoozeUntilAttention capability for the command and
the setting, because servers from before it already advertise threadSnooze.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL labels Oct 7, 2026
@github-actions

Copy link
Copy Markdown

Thread transfer impact

⚠️ The latest CI run did not produce a thread transfer result for 91256f4.

This comment will update automatically after the next completed run.

This branch has not been deployed

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

Labels

size:XXL vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant