Fix resume command: clap constraints, sleep inhibitor, Docker sandbox

Add conflicts_with/requires to ResumeArgs checkpoint field so invalid
flag combos produce clap usage errors instead of runtime failures. Add
sleep_inhibitor guard to Command::Resume matching Run and Exec. Split
Docker out of Local match arm in prepare_from_checkpoint to create a
proper DockerSandbox instead of silently falling back to LocalSandbox.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Bryan Helmkamp 2026-03-21 14:38:59 -04:00
parent 161caf54b0
commit 2a791eab41
2 changed files with 18 additions and 3 deletions

View file

@ -6,7 +6,7 @@ use std::time::{Duration, Instant};
use anyhow::{bail, Context};
use clap::Args;
use fabro_agent::{Sandbox, WorktreeConfig, WorktreeSandbox};
use fabro_agent::{DockerSandbox, DockerSandboxConfig, Sandbox, WorktreeConfig, WorktreeSandbox};
use fabro_config::run::RunDefaults;
use fabro_graphviz::graph::Graph;
use fabro_interview::{AutoApproveInterviewer, ConsoleInterviewer, Interviewer};
@ -37,7 +37,7 @@ pub struct ResumeArgs {
pub run: Option<String>,
/// Resume from a checkpoint file (requires --workflow)
#[arg(long)]
#[arg(long, conflicts_with = "run", requires = "workflow")]
pub checkpoint: Option<PathBuf>,
/// Override workflow graph (required with --checkpoint)
@ -179,9 +179,22 @@ async fn prepare_from_checkpoint(
};
let sandbox: Arc<dyn Sandbox> = match sandbox_provider {
SandboxProvider::Local | SandboxProvider::Docker => {
SandboxProvider::Local => {
local_sandbox_with_callback(original_cwd.clone(), Arc::clone(&emitter))
}
SandboxProvider::Docker => {
let config = DockerSandboxConfig {
host_working_directory: original_cwd.to_string_lossy().to_string(),
..DockerSandboxConfig::default()
};
let mut env = DockerSandbox::new(config)
.map_err(|e| anyhow::anyhow!("Failed to create Docker environment: {e}"))?;
let emitter_cb = Arc::clone(&emitter);
env.set_event_callback(Arc::new(move |event| {
emitter_cb.emit(&fabro_workflows::event::WorkflowRunEvent::Sandbox { event });
}));
Arc::new(env)
}
#[cfg(feature = "exedev")]
SandboxProvider::Exe => {
let exe_config = super::run::resolve_exe_config(None, run_defaults);

View file

@ -920,6 +920,8 @@ async fn main_inner() -> (String, Result<()>) {
let styles: &'static fabro_util::terminal::Styles =
Box::leak(Box::new(fabro_util::terminal::Styles::detect_stderr()));
let cli_config = cli_config::load_cli_config(None)?;
#[cfg(feature = "sleep_inhibitor")]
let _sleep_guard = fabro_beastie::guard(cli_config.prevent_idle_sleep);
let github_app = build_github_app_credentials(cli_config.app_id());
let git_author = fabro_workflows::git::GitAuthor::from_options(
cli_config.git_author().and_then(|a| a.name.clone()),