Repository navigation
Conversation
Checkpoint capture commits a turn end as one batch: up to three checkpoint.captured events and the run's terminal run.updated. Thread PR discovery forced a fresh GitHub lookup for each of them, so one turn end cost up to four GraphQL calls for the same branch and head. A rollback cost one per stale checkpoint. The terminal run update is now the only finished-turn trigger. It also covers rollbacks through rolled_back, which they commit with their checkpoints. Closes pingdotgg#33744 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Author
|
Note 🤖 Claude Opus 5.5 responding on behalf of Michael Decisions made while building this PR:
|
The turn-end test now drives the real GitManager over a local repository and counts the pull request list requests a fake GitHub host receives, then checks the thread stays linked to the discovered pull request. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The regression test now runs the real GitHub driver and source control registry behind the real GitManager. Only the network and the gh CLI are fakes: an in-memory GitHub answers each GraphQL request and records it. On main a finished turn sends GitHub 4 requests and a rollback 2; with the fix each sends 1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
One finished agent turn reads its branch's pull request from GitHub up to four times, about a second apart, for the same branch and head. A rollback reads it once per stale checkpoint. Every T3 server a user runs shares their per-user GitHub budget with their own
ghand every agent, so servers with many short turns burn through it faster.Closes #33744
Change
Checkpoint capture commits a turn end as one batch: up to three
checkpoint.capturedevents (thread start, baseline, the run's own) and the run's terminalrun.updated.ThreadPullRequestServicequeued arefresh: truelookup for each of them, and each refresh skips the branch lookup cache, so each one was its own GraphQL call.Now the terminal
run.updatedis the only finished-turn trigger, checked with the sharedisTerminalRunStatus. That addsrolled_back, which rollback commits together with its stale checkpoints, so a rollback still refreshes once.checkpoint.capturedno longer forces a lookup. The one-minute sweep and the cache lengths are unchanged.A rollback reads once per rolled-back run, because rollback commits one terminal
run.updatedper run. Rollbacks are rare and user-started, so they get no extra coalescing. A stopped turn still reads twice: itsrun.updated(cancelled or interrupted) lands once when it stops and again when its checkpoint is captured.Scope and approval
A very small, focused fix of an obvious bug: one finished turn should read its pull request once. It changes which orchestration events trigger PR discovery in one service, plus its tests. It leaves the deliberate one-minute sweep and PR cache lengths from #21372 alone. The larger share of background PR reads on servers with many subagent threads is #19657, which #19665 addresses; this PR doesn't overlap with it.
Merge risk: low, two-way door. Capture and rollback commit every checkpoint together with its run's terminal update, so no turn end loses its refresh; the worst case is a badge that waits for the one-minute sweep.
Verification
CI passed on e1dc23c and is pending on 1df3b55, which changes only the test file.
Live run. I ran
Replay (dev)turns against an isolated dev server (vp run dev --no-seed, its own.t3) on a thread in a worktree on this PR's branch. Then I countedlistPullRequestsByHeadGraphQL calls underThreadPullRequestServiceV2.synchronizeinserver.trace.ndjsonafter each turn ended:listPullRequestsByHeadafter the turn endsOn this PR, the thread's first turn also read once after it ended, from
Orchestrator.handleRunUpdate. The three reads during thread creation and worktree setup, before the turn starts, come fromthread.createdandthread.metadata-updated. This PR leaves them alone.At 1df3b55 I then ran one more turn and rolled it back on the same thread, counting GraphQL calls between the domain events in the dev database:
listPullRequestsByHeadcheckpoint.captured, thenrun.updatedcompletedcheckpoint.captured, thenrun.updatedrolled_backThe rollback kept the files ("Revert and keep changes"), because a shared worktree refuses a file restore. Its
thread.metadata-updatedpass was answered from the lookup cache without a request.Tests.
reads the branch pull request from the host once for $commitinThreadPullRequestService.test.ts. It runs the realThreadPullRequestService,GitManager, source control registry and GitHub driver over a temp git repository whose origin names GitHub. Only the network and theghCLI are fakes: an in-memory GitHub answers the GraphQL lookups and records every request it receives. The test delivers a finished turn's commit and a rollback's commit after the startup sweep has drained, and asserts that GitHub received one request and the thread stays linked to the pull request. OnmainGitHub receives 4 and 2 requests; with the fix, 1 each.checkpoint.capturedas the turn-end trigger now use the terminalrun.updated.vp test run src/orchestration-v2/ThreadPullRequestService.test.ts: 13 passed.vp run check:changed: format, lint, knip, graphql, typecheck (3 packages) and tests pass.Decisions
run.updated. This replaces the per-thread coalescing proposed in #33744, which depended on worker schedulingIf-None-MatchInvolvement: no grilling rounds, a design review and three code review rounds by GPT-6.1 Sol, live-run proof captured.
Created with Claude Opus 5.5 in Claude Code, running in T3 Code.
🤖 Generated with Claude Code