diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx
index f5ea5bb1eba..70bbc296288 100644
--- a/apps/web/src/components/ChatView.tsx
+++ b/apps/web/src/components/ChatView.tsx
@@ -2112,12 +2112,13 @@ function ChatViewContent(props: ChatViewProps) {
worktreePath: activeThread?.worktreePath ?? null,
})
: null;
+ const gitStatusCwd = activeThread?.worktreePath ?? gitCwd;
const gitStatusQuery = useEnvironmentQuery(
- gitCwd === null
+ gitStatusCwd === null
? null
: vcsEnvironment.status({
environmentId,
- input: { cwd: gitCwd },
+ input: { cwd: gitStatusCwd },
}),
);
const keybindings = useAtomValue(primaryServerKeybindingsAtom);
@@ -2151,6 +2152,9 @@ function ChatViewContent(props: ChatViewProps) {
terminalUiLaunchContext?.threadId === activeThreadId ? terminalUiLaunchContext : null;
// Default true while loading to avoid toolbar flicker.
const isGitRepo = gitStatusQuery.data?.isRepo ?? true;
+ const initialDiffPanelGitScope =
+ gitStatusQuery.data?.hasWorkingTreeChanges === true ? "unstaged" : "branch";
+ const diffPanelGitStatusResolutionKey = gitStatusQuery.data ? "resolved" : "pending";
const terminalShortcutLabelOptions = useMemo(
() => ({
context: {
@@ -4968,7 +4972,12 @@ function ChatViewContent(props: ChatViewProps) {
/>
) : activeRightPanelSurface?.kind === "diff" ? (
-
+
) : activeRightPanelSurface?.kind === "plan" ? (
("stacked");
const [wordWrap, setWordWrap] = useState(settings.wordWrap);
const [diffIgnoreWhitespace, setDiffIgnoreWhitespace] = useState(settings.diffIgnoreWhitespace);
@@ -199,9 +205,6 @@ export default function DiffPanel({ mode = "inline", composerDraftTarget }: Diff
strict: false,
select: (params) => resolveThreadRouteRef(params),
});
- const diffSelection = useDiffPanelStore((state) =>
- selectThreadDiffPanelSelection(state.byThreadKey, routeThreadRef),
- );
const activeThreadId = routeThreadRef?.threadId ?? null;
const activeThread = useThread(routeThreadRef);
const activeProjectId = activeThread?.projectId ?? null;
@@ -229,6 +232,13 @@ export default function DiffPanel({ mode = "inline", composerDraftTarget }: Diff
})
: null,
);
+ const diffSelection = useDiffPanelStore((state) =>
+ selectThreadDiffPanelSelection(
+ state.byThreadKey,
+ routeThreadRef,
+ initialGitScope === "unstaged",
+ ),
+ );
const isGitRepo = gitStatusQuery.data?.isRepo ?? true;
const { turnDiffSummaries, inferredCheckpointTurnCountByTurnId } =
useTurnDiffSummaries(activeThread);
diff --git a/apps/web/src/diffPanelStore.test.ts b/apps/web/src/diffPanelStore.test.ts
index 64846e8e9f1..607b7c8d580 100644
--- a/apps/web/src/diffPanelStore.test.ts
+++ b/apps/web/src/diffPanelStore.test.ts
@@ -9,12 +9,26 @@ const THREAD_REF = scopeThreadRef(EnvironmentId.make("environment-1"), ThreadId.
describe("diffPanelStore", () => {
beforeEach(() => useDiffPanelStore.setState({ byThreadKey: {}, branchBaseRefByThreadKey: {} }));
- it("defaults each thread to branch changes with automatic base selection", () => {
+ it("defaults each thread to branch changes when the working tree is clean", () => {
expect(
selectThreadDiffPanelSelection(useDiffPanelStore.getState().byThreadKey, THREAD_REF),
).toEqual({ kind: "branch", baseRef: null });
});
+ it("defaults each thread to working changes when the working tree is dirty", () => {
+ expect(
+ selectThreadDiffPanelSelection(useDiffPanelStore.getState().byThreadKey, THREAD_REF, true),
+ ).toEqual({ kind: "unstaged" });
+ });
+
+ it("preserves an explicit scope selection when the working tree state changes", () => {
+ useDiffPanelStore.getState().selectGitScope(THREAD_REF, "branch");
+
+ expect(
+ selectThreadDiffPanelSelection(useDiffPanelStore.getState().byThreadKey, THREAD_REF, true),
+ ).toEqual({ kind: "branch", baseRef: null });
+ });
+
it("clears incompatible selection fields when changing scopes", () => {
const store = useDiffPanelStore.getState();
store.selectTurn(THREAD_REF, TurnId.make("turn-1"), "src/app.ts");
diff --git a/apps/web/src/diffPanelStore.ts b/apps/web/src/diffPanelStore.ts
index c946b286d1b..56b5ad23fec 100644
--- a/apps/web/src/diffPanelStore.ts
+++ b/apps/web/src/diffPanelStore.ts
@@ -11,6 +11,7 @@ export type DiffPanelSelection =
| { kind: "turn"; turnId: TurnId; filePath: string | null; revealRequestId: number };
const DEFAULT_SELECTION: DiffPanelSelection = { kind: "branch", baseRef: null };
+const DEFAULT_WORKING_TREE_SELECTION: DiffPanelSelection = { kind: "unstaged" };
interface DiffPanelStoreState {
byThreadKey: Record;
@@ -133,7 +134,11 @@ export const useDiffPanelStore = create()(
export function selectThreadDiffPanelSelection(
byThreadKey: Record,
ref: ScopedThreadRef | null | undefined,
+ hasWorkingTreeChanges = false,
): DiffPanelSelection {
if (!ref) return DEFAULT_SELECTION;
- return byThreadKey[scopedThreadKey(ref)] ?? DEFAULT_SELECTION;
+ return (
+ byThreadKey[scopedThreadKey(ref)] ??
+ (hasWorkingTreeChanges ? DEFAULT_WORKING_TREE_SELECTION : DEFAULT_SELECTION)
+ );
}