Wire up original_commit_hash in archive and restore flows

Richard Feldman created

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

Change summary

crates/agent_ui/src/thread_worktree_archive.rs | 22 ++++++++++++-------
1 file changed, 14 insertions(+), 8 deletions(-)

Detailed changes

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