diff --git a/crates/arc-workflows/src/cli/run.rs b/crates/arc-workflows/src/cli/run.rs index a18895b62..3baeb6e75 100644 --- a/crates/arc-workflows/src/cli/run.rs +++ b/crates/arc-workflows/src/cli/run.rs @@ -622,35 +622,38 @@ pub async fn run_command(args: RunArgs, styles: &'static Styles) -> anyhow::Resu let _ = retro.save(&logs_dir); // Run retro agent session (execution_env still alive via _cleanup_guard) - if !dry_run_mode { - if let Ok(client) = arc_llm::client::Client::from_env().await { - match crate::retro_agent::run_retro_agent( - &execution_env, - &logs_dir, - &client, - provider_enum, - &model, - ) - .await - { - Ok(narrative) => { - retro.apply_narrative(narrative); - let _ = retro.save(&logs_dir); - eprintln!( - "{dim}Retro saved to {}/retro.json{reset}", - logs_dir.display(), - dim = styles.dim, - reset = styles.reset, - ); - } - Err(e) => { - eprintln!( - "{dim}Retro agent skipped: {e}{reset}", - dim = styles.dim, - reset = styles.reset, - ); - } - } + let narrative_result = if dry_run_mode { + Ok(crate::retro_agent::dry_run_narrative()) + } else if let Ok(client) = arc_llm::client::Client::from_env().await { + crate::retro_agent::run_retro_agent( + &execution_env, + &logs_dir, + &client, + provider_enum, + &model, + ) + .await + } else { + Err(anyhow::anyhow!("No LLM client available")) + }; + + match narrative_result { + Ok(narrative) => { + retro.apply_narrative(narrative); + let _ = retro.save(&logs_dir); + eprintln!( + "{dim}Retro saved to {}/retro.json{reset}", + logs_dir.display(), + dim = styles.dim, + reset = styles.reset, + ); + } + Err(e) => { + eprintln!( + "{dim}Retro agent skipped: {e}{reset}", + dim = styles.dim, + reset = styles.reset, + ); } } } diff --git a/crates/arc-workflows/src/retro_agent.rs b/crates/arc-workflows/src/retro_agent.rs index 37d0fd3f7..1b76a980a 100644 --- a/crates/arc-workflows/src/retro_agent.rs +++ b/crates/arc-workflows/src/retro_agent.rs @@ -190,6 +190,19 @@ pub async fn run_retro_agent( Ok(narrative) } +/// Return a placeholder narrative for dry-run mode. Exercises the full +/// derive → apply_narrative → save path without making LLM calls. +pub fn dry_run_narrative() -> RetroNarrative { + RetroNarrative { + smoothness: crate::retro::SmoothnessRating::Smooth, + intent: "[dry-run] No LLM analysis performed".to_string(), + outcome: "[dry-run] Pipeline completed in simulated mode".to_string(), + learnings: vec![], + friction_points: vec![], + open_items: vec![], + } +} + fn build_profile(provider: Provider, model: &str) -> Box { match provider { Provider::OpenAi => Box::new(OpenAiProfile::new(model)),