From 7c74c0a4174ad1e46cf80e16ea3e7ba2cbde3607 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Thu, 26 Mar 2026 13:07:15 -0400 Subject: [PATCH] fix: resume skips worktree creation and keeps sleep inhibitor alive Two bugs from the refactoring: 1. (High) On resume, run_command_impl would create a fresh worktree with skip_branch_creation=false, force-resetting the run branch and losing file changes from the original run. Fix: force workdir_strategy to LocalDirectory when resume=true. 2. (Low) Sleep inhibitor guard was created inside a #[cfg] block scope, so it was dropped before resume_command ran. Fix: use `let _guard = { ... }` pattern to keep it alive for the arm. Co-Authored-By: Claude Opus 4.6 (1M context) --- lib/crates/fabro-cli/src/commands/run.rs | 55 ++++++++++++++---------- lib/crates/fabro-cli/src/main.rs | 7 ++- 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/lib/crates/fabro-cli/src/commands/run.rs b/lib/crates/fabro-cli/src/commands/run.rs index 99d8c5edc..4d06502d2 100644 --- a/lib/crates/fabro-cli/src/commands/run.rs +++ b/lib/crates/fabro-cli/src/commands/run.rs @@ -1157,30 +1157,39 @@ async fn run_command_impl( // Only the Local provider supports git worktrees on the host. // Remote sandboxes (Daytona, Exe, SSH) clone from origin inside the sandbox. // Docker uses the bind-mounted host directory as-is. - let workdir_strategy = match sandbox_provider { - SandboxProvider::Local => { - let worktree_mode = resolve_worktree_mode(run_cfg.as_ref(), &run_defaults); - match worktree_mode { - sandbox_config::WorktreeMode::Always => WorkdirStrategy::LocalWorktree, - sandbox_config::WorktreeMode::Clean => { - if git_status.is_clean() { - WorkdirStrategy::LocalWorktree - } else { - WorkdirStrategy::LocalDirectory - } - } - sandbox_config::WorktreeMode::Dirty => { - if git_status.is_clean() { - WorkdirStrategy::LocalDirectory - } else { - WorkdirStrategy::LocalWorktree - } - } - sandbox_config::WorktreeMode::Never => WorkdirStrategy::LocalDirectory, - } + // Resume runs skip worktree creation — the engine runs in the original + // working directory and the checkpoint restores logical state. + let workdir_strategy = if resume { + match sandbox_provider { + SandboxProvider::Local | SandboxProvider::Docker => WorkdirStrategy::LocalDirectory, + _ => WorkdirStrategy::Cloud, + } + } else { + match sandbox_provider { + SandboxProvider::Local => { + let worktree_mode = resolve_worktree_mode(run_cfg.as_ref(), &run_defaults); + match worktree_mode { + sandbox_config::WorktreeMode::Always => WorkdirStrategy::LocalWorktree, + sandbox_config::WorktreeMode::Clean => { + if git_status.is_clean() { + WorkdirStrategy::LocalWorktree + } else { + WorkdirStrategy::LocalDirectory + } + } + sandbox_config::WorktreeMode::Dirty => { + if git_status.is_clean() { + WorkdirStrategy::LocalDirectory + } else { + WorkdirStrategy::LocalWorktree + } + } + sandbox_config::WorktreeMode::Never => WorkdirStrategy::LocalDirectory, + } + } + SandboxProvider::Docker => WorkdirStrategy::LocalDirectory, + _ => WorkdirStrategy::Cloud, } - SandboxProvider::Docker => WorkdirStrategy::LocalDirectory, - _ => WorkdirStrategy::Cloud, }; debug!( ?workdir_strategy, diff --git a/lib/crates/fabro-cli/src/main.rs b/lib/crates/fabro-cli/src/main.rs index 0ad42a9d7..f71c5fa28 100644 --- a/lib/crates/fabro-cli/src/main.rs +++ b/lib/crates/fabro-cli/src/main.rs @@ -965,11 +965,10 @@ async fn main_inner() -> (String, Result<()>) { let styles: &'static fabro_util::terminal::Styles = Box::leak(Box::new(fabro_util::terminal::Styles::detect_stderr())); #[cfg(feature = "sleep_inhibitor")] - { + let _sleep_guard = { let cli_config = cli_config::load_cli_config(None)?; - let _sleep_guard = - fabro_beastie::guard(cli_config.prevent_idle_sleep_enabled()); - } + fabro_beastie::guard(cli_config.prevent_idle_sleep_enabled()) + }; commands::resume::resume_command(args, styles).await?; } Command::Rewind(args) => {