Skip to content

fix(server): follow branch drift in dedicated worktrees so PRs link to their thread - #5159

Merged
t3dotgg merged 1 commit into
mainfrom
t3code/diagnose-pr-linking-failure
Aug 1, 2026
Merged

fix(server): follow branch drift in dedicated worktrees so PRs link to their thread#5159
t3dotgg merged 1 commit into
mainfrom
t3code/diagnose-pr-linking-failure

Conversation

@t3dotgg

@t3dotgg t3dotgg commented Aug 1, 2026

Copy link
Copy Markdown
Member

Problem

When an agent (or the user) runs a plain `git checkout -b` inside a thread's dedicated worktree and files a PR from the new branch, the PR never links to the thread. The thread's recorded `branch` only updates through T3 commands (creation, first-turn auto-rename), so it goes stale — and since #4460 the client only attributes PR state to a thread when the checked-out branch exactly equals the recorded one. Stale metadata silently orphans the PR, and (via #5151) also re-enables inactivity auto-settle for threads that actually have an open PR.

This happened in the wild: a thread recorded `t3code/ios-background-websocket-reconnect`, the agent branched off to `t3code/mobile-reconnect-hardening` mid-thread and filed #5154 from it, and the link never formed.

Solution

Keep #4460's strict matching and fix the stale data instead: after each turn completes, the CheckpointReactor already refreshes local git status for the session cwd. Use that fresh status to detect drift — if the checked-out branch differs from the thread's recorded branch and the worktree belongs to exactly that thread, dispatch a `thread.meta.update` adopting the checked-out branch. The command's existing `expectedBranch` compare-and-swap drops the update if the recorded branch moved concurrently.

Guards: shared cwds are never touched (that's where #4460's protection matters), detached HEAD and temporary `t3code/` placeholder checkouts are ignored, and threads with no recorded branch are left alone.

No schema changes, no client changes, no new polling — one server-side hook on an existing refresh path.

Tests

Three focused cases in `CheckpointReactor.test.ts`: adopts drift on a dedicated worktree, refuses when the worktree is shared, refuses temporary placeholder checkouts.


Diagnosed and implemented by Claude Fable 5 (claude-fable-5, 1m context) running in Claude Code.


Note

Medium Risk
Changes thread metadata on an existing turn-completion path with compare-and-swap guards; wrong adoption could mis-link PRs, but shared-worktree and temporary-branch guards limit blast radius.

Overview
When an agent or user checks out a different branch inside a thread’s dedicated worktree (outside T3’s branch commands), the thread’s stored branch can stay stale. That breaks PR↔thread linking and related behavior that only matches when checkout equals recorded branch.

CheckpointReactor now uses the local git status already refreshed on turn.completed. If the checked-out ref differs from the thread’s recorded branch, it dispatches thread.meta.update with expectedBranch so concurrent renames are ignored. Adoption only runs when the session cwd is that thread’s sole worktree; shared worktrees, detached HEAD, and temporary t3code/<hex> placeholder branches are skipped.

Tests extend the harness and add three cases: adopt on dedicated worktree, no adopt when worktree is shared, no adopt for temporary placeholder checkouts.

Reviewed by Cursor Bugbot for commit 2566f5c. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Follow branch drift in dedicated worktrees so PRs link to their thread

  • After a turn.completed event, CheckpointReactor now calls a new followWorktreeBranchDrift helper that compares the checked-out branch (from local git status) against the thread's recorded branch.
  • When the two differ, the helper dispatches a thread.meta.update with expectedBranch (CAS semantics) to adopt the drifted branch, allowing PRs on the new branch to link back to the thread.
  • The helper skips adoption if the ref is null, temporary, or shared by multiple threads, or if the worktree path doesn't match.
  • New tests in CheckpointReactor.test.ts cover drift adoption, shared-worktree suppression, and temporary-ref suppression.

Macroscope summarized 2566f5c.

…o their thread

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a70c37c2-69d2-408e-a93e-efe3e7eaa763

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Aug 1, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 2566f5c. Configure here.

isTemporaryWorktreeBranch(thread.branch)
) {
return;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Temp branch blocks drift adopt

Medium Severity

followWorktreeBranchDrift returns early when the thread’s recorded branch is still a temporary placeholder, even if the checkout is already a real branch. The PR only calls for ignoring temporary checkouts, and expectedBranch already drops a stale adopt if first-turn rename wins the race. When rename fails and the agent has already branched, this leave the recorded branch stuck and the PR unlinked on the server path.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 2566f5c. Configure here.

@macroscopeapp

macroscopeapp Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR adds new runtime behavior for tracking branch drift in worktrees, with an unresolved review comment identifying a potential logic bug where temporary placeholder branches may prevent drift adoption. Both the new feature scope and the open concern warrant human review.

You can customize Macroscope's approvability policy. Learn more.

@t3dotgg
t3dotgg merged commit 0ad91b6 into main Aug 1, 2026
17 checks passed
@t3dotgg
t3dotgg deleted the t3code/diagnose-pr-linking-failure branch August 1, 2026 03:19
github-actions Bot added a commit to omarcresp/t3code-flake that referenced this pull request Aug 1, 2026
## What's Changed
* fix(server): follow branch drift in dedicated worktrees so PRs link to their thread by @t3dotgg in pingdotgg/t3code#5159


**Full Changelog**: pingdotgg/t3code@v0.0.32-nightly.20260801.969...v0.0.32-nightly.20260801.970

Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.32-nightly.20260801.970
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). 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