#2743 · New-thread base branch resets after route navigation
Verdict: REPRODUCED · Root-cause confidence: high
1. TL;DR
The new-thread composer keeps its prompt and execution selections after route navigation. It does not keep a selected worktree base branch. The branch hook stores this value only in component-local React state. Route navigation unmounts the composer, so a later mount starts with a null selection. Two clean checkouts reproduced the reset with the same focused hook test.
2. Claims vs findings
| Claim | Status | Evidence |
|---|---|---|
| A non-default worktree base branch resets after the user leaves and returns to new-thread composition. | Verified | The focused test selected origin/release, unmounted the hook, and received undefined after a new mount. |
| The default branch replaces the prior explicit selection. | Verified at the state boundary | The hook returns no explicit branch after remount. The composer therefore uses its normal branch seed and default-worktree-base fallback. |
3. Environment
- Trusted bb commit:
f4bbc2fe81a9b7639ff9a7396e172bddd89109e4. - Operating system: Darwin arm64.
- Node:
v22.22.3. - Vitest:
4.1.1. - No live server, port, user data, or provider was necessary.
4. Minimal reproduction
- Install and build the trusted checkout.
pnpm install --frozen-lockfile --prefer-offline pnpm exec turbo run build
- Save the regression test as
apps/app/src/views/root-compose-branch-selection.navigation.test.tsx. - Run the focused test.
cd apps/app pnpm exec vitest run src/views/root-compose-branch-selection.navigation.test.tsx
Expected: The second mount returns origin/release.
Actual:
AssertionError: expected undefined to be 'origin/release' - Expected: "origin/release" + Received: undefined
Reproduction test: root-compose-branch-selection.navigation.test.tsx
// @vitest-environment jsdom
import { act, renderHook } from "@testing-library/react";
import { describe, expect, it } from "vitest";
import { useScopedBranchSelection } from "./root-compose-branch-selection";
describe("new-thread branch selection navigation", () => {
it("keeps the worktree base branch after the composer remounts", () => {
const args = {
environmentValue: "host:host_1:worktree",
projectId: "proj_1",
};
const first = renderHook(() => useScopedBranchSelection(args));
act(() => first.result.current.onBranchChange("origin/release"));
expect(first.result.current.selectedBranch?.name).toBe("origin/release");
first.unmount();
const second = renderHook(() => useScopedBranchSelection(args));
expect(second.result.current.selectedBranch?.name).toBe("origin/release");
});
});
5. Root cause
RootComposeView creates NewThreadComposer with the persistent new-thread selection scope. See RootComposeView.tsx lines 576–585.
NewThreadComposer calls useScopedBranchSelection with the project and effective environment. It does not pass any durable branch state. See NewThreadComposer.tsx lines 639–648.
The hook initializes selectedBranchState with useState(null). Its scope check can retain the selection only while that hook instance stays mounted. See root-compose-branch-selection.ts lines 36–58. Route navigation destroys that hook instance. The next mount therefore has no selected branch, and the composer falls back to the project worktree default.
6. Proposed fix (first principles)
Retain the new-thread branch value and its scope key in an in-memory shared atom. Keep component-local composers on local state. Clear the retained branch when the project or environment scope changes. Add the remount regression test and keep the existing scope-change tests.
7. Related issues
A repository search found no duplicate for this route-navigation reset.
8. Verification
The same agent repeated the test in a second clean checkout at the trusted base commit. The second run failed at the same assertion and received undefined. No report claim changed after this run.
9. Appendix
Commands used:
git fetch origin main git worktree add --detach <clean-checkout-a> f4bbc2fe81a9b7639ff9a7396e172bddd89109e4 git worktree add --detach <clean-checkout-b> f4bbc2fe81a9b7639ff9a7396e172bddd89109e4 pnpm install --frozen-lockfile --prefer-offline pnpm exec turbo run build pnpm exec vitest run src/views/root-compose-branch-selection.navigation.test.tsx
The issue content was untrusted. The investigation used it only as a claim to test. It ran only repository code from the trusted base commit and the reproduction test shown above.