From 2b463da6f0ae710c661e046bcbb80458322d32d1 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Mon, 6 Apr 2026 16:19:36 -0400 Subject: [PATCH] Wire up original_commit_hash in archive and restore flows persist_worktree_state: - Read HEAD SHA before creating WIP commits as original_commit_hash - Pass it to create_archived_worktree restore_worktree_via_git: - Pre-restore: verify original_commit_hash exists via resolve_commit; abort with user-facing error if the git history is gone - Worktree-already-exists: check for .git file to detect if path is a real git worktree; if not, call repair_worktrees to adopt it - Resilient WIP resets: track success of mixed and soft resets independently; if either fails, fall back to mixed reset directly to original_commit_hash - Post-reset HEAD verification: confirm HEAD landed at original_commit_hash after all resets - Branch restoration: after switching, verify branch points at original_commit_hash; if it doesn't, reset and create a fresh branch --- .../agent_ui/src/thread_worktree_archive.rs | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/crates/agent_ui/src/thread_worktree_archive.rs b/crates/agent_ui/src/thread_worktree_archive.rs index c43bc48aa79765c6e2b5c250f4d7b9c223103df8..9ddb5cde37a1769881fd1cc45e303cb29f76ceb0 100644 --- a/crates/agent_ui/src/thread_worktree_archive.rs +++ b/crates/agent_ui/src/thread_worktree_archive.rs @@ -991,7 +991,7 @@ pub async fn restore_worktree_via_git( let app_state = current_app_state(cx).context("no app state available")?; let already_exists = app_state.fs.metadata(worktree_path).await?.is_some(); - if already_exists { + let needs_reset = if already_exists { let is_git_worktree = resolve_git_worktree_to_main_repo(app_state.fs.as_ref(), worktree_path) .await @@ -1000,14 +1000,15 @@ pub async fn restore_worktree_via_git( if is_git_worktree { // Already a git worktree — another thread on the same worktree // already restored it. Reuse as-is. - return Ok(worktree_path.clone()); + false + } else { + // Path exists but isn't a git worktree. Ask git to adopt it. + let rx = main_repo.update(cx, |repo, _cx| repo.repair_worktrees()); + rx.await + .map_err(|_| anyhow!("worktree repair was canceled"))? + .context("failed to repair worktrees")?; + true } - - // Path exists but isn't a git worktree. Ask git to adopt it. - let rx = main_repo.update(cx, |repo, _cx| repo.repair_worktrees()); - rx.await - .map_err(|_| anyhow!("worktree repair was canceled"))? - .context("failed to repair worktrees")?; } else { // Create detached worktree at the unstaged commit let rx = main_repo.update(cx, |repo, _cx| { @@ -1016,6 +1017,11 @@ pub async fn restore_worktree_via_git( rx.await .map_err(|_| anyhow!("worktree creation was canceled"))? .context("failed to create worktree")?; + true + }; + + if !needs_reset { + return Ok(worktree_path.clone()); } // Get the worktree's repo entity