diff --git a/lib/crates/fabro-api/src/server.rs b/lib/crates/fabro-api/src/server.rs index 5e55cf916..dad9d2d6d 100644 --- a/lib/crates/fabro-api/src/server.rs +++ b/lib/crates/fabro-api/src/server.rs @@ -626,6 +626,7 @@ async fn execute_run(state: Arc, run_id: String) { pull_request_enabled: false, pull_request_draft: true, asset_globs: Vec::new(), + workflow_slug: None, }; let result = tokio::select! { diff --git a/lib/crates/fabro-workflows/src/cli/run.rs b/lib/crates/fabro-workflows/src/cli/run.rs index a429d7a5e..4d80613da 100644 --- a/lib/crates/fabro-workflows/src/cli/run.rs +++ b/lib/crates/fabro-workflows/src/cli/run.rs @@ -326,6 +326,18 @@ pub async fn run_command( } }; + // Extract workflow slug from the workflow path argument. + // If bare name (no extension, e.g. "smoke"), use it directly. + // Otherwise derive from the parent directory of the resolved .toml path. + let workflow_slug: Option = if workflow_path.extension().is_none() { + Some(workflow_path.to_string_lossy().into_owned()) + } else { + workflow_path + .parent() + .and_then(|p| p.file_name()) + .map(|n| n.to_string_lossy().into_owned()) + }; + let directory = run_cfg .as_ref() .and_then(|c| c.work_dir.as_deref()) @@ -1180,6 +1192,7 @@ pub async fn run_command( .and_then(|c| c.assets.as_ref()) .map(|a| a.include.clone()) .unwrap_or_default(), + workflow_slug: workflow_slug.clone(), }; let run_start = Instant::now(); @@ -1786,6 +1799,7 @@ async fn run_from_branch( pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let run_start = Instant::now(); diff --git a/lib/crates/fabro-workflows/src/cli/runs.rs b/lib/crates/fabro-workflows/src/cli/runs.rs index 9d2162fca..472684edd 100644 --- a/lib/crates/fabro-workflows/src/cli/runs.rs +++ b/lib/crates/fabro-workflows/src/cli/runs.rs @@ -91,6 +91,8 @@ pub struct RunInfo { pub run_id: String, pub dir_name: String, pub workflow_name: String, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub workflow_slug: Option, pub status: RunStatus, pub start_time: String, pub labels: HashMap, @@ -130,6 +132,7 @@ pub fn scan_runs(base: &Path) -> Result> { let run_id = manifest.run_id; let workflow_name = manifest.workflow_name; + let workflow_slug = manifest.workflow_slug; let start_time_dt = manifest.start_time; let start_time = start_time_dt.to_rfc3339(); let labels = manifest.labels; @@ -140,6 +143,7 @@ pub fn scan_runs(base: &Path) -> Result> { run_id, dir_name, workflow_name, + workflow_slug, status, start_time, labels, @@ -161,6 +165,7 @@ pub fn scan_runs(base: &Path) -> Result> { run_id: dir_name.clone(), dir_name, workflow_name: "[no manifest]".to_string(), + workflow_slug: None, status: RunStatus::Unknown, start_time: mtime, labels: HashMap::new(), @@ -306,12 +311,18 @@ pub fn resolve_run(base: &Path, identifier: &str) -> Result { _ => {} } - // Step 2: try workflow name match, return most recent (runs are sorted newest-first). - // Supports both display names ("LegacyTool") and slugs ("legacy-tool") by comparing - // case-insensitively first, then with separators stripped (hyphens/underscores removed). + // Step 2: try workflow slug (exact, case-insensitive) then workflow name match. + // Returns the most recent run (runs are sorted newest-first). let id_lower = identifier.to_lowercase(); let id_collapsed = collapse_separators(&id_lower); let wf_match = runs.iter().filter(|r| !r.is_orphan).find(|r| { + // Exact slug match (case-insensitive) + if let Some(slug) = &r.workflow_slug { + if slug.to_lowercase() == id_lower { + return true; + } + } + // Fuzzy workflow name match (substring, separator-collapsed) let name_lower = r.workflow_name.to_lowercase(); name_lower.contains(&id_lower) || collapse_separators(&name_lower).contains(&id_collapsed) }); @@ -815,6 +826,7 @@ mod tests { run_id: "old".into(), dir_name: "d1".into(), workflow_name: "p".into(), + workflow_slug: None, status: RunStatus::Concluded(crate::outcome::StageStatus::Success), start_time: "2025-06-01T00:00:00Z".into(), labels: HashMap::new(), @@ -827,6 +839,7 @@ mod tests { run_id: "new".into(), dir_name: "d2".into(), workflow_name: "p".into(), + workflow_slug: None, status: RunStatus::Concluded(crate::outcome::StageStatus::Success), start_time: "2026-03-01T00:00:00Z".into(), labels: HashMap::new(), @@ -848,6 +861,7 @@ mod tests { run_id: "a".into(), dir_name: "d1".into(), workflow_name: "deploy-prod".into(), + workflow_slug: None, status: RunStatus::Concluded(crate::outcome::StageStatus::Success), start_time: "2026-01-01T00:00:00Z".into(), labels: HashMap::new(), @@ -860,6 +874,7 @@ mod tests { run_id: "b".into(), dir_name: "d2".into(), workflow_name: "test-suite".into(), + workflow_slug: None, status: RunStatus::Concluded(crate::outcome::StageStatus::Success), start_time: "2026-01-01T00:00:00Z".into(), labels: HashMap::new(), @@ -881,6 +896,7 @@ mod tests { run_id: "a".into(), dir_name: "d1".into(), workflow_name: "p".into(), + workflow_slug: None, status: RunStatus::Concluded(crate::outcome::StageStatus::Success), start_time: "2026-01-01T00:00:00Z".into(), labels: HashMap::from([("env".into(), "prod".into())]), @@ -893,6 +909,7 @@ mod tests { run_id: "b".into(), dir_name: "d2".into(), workflow_name: "p".into(), + workflow_slug: None, status: RunStatus::Concluded(crate::outcome::StageStatus::Success), start_time: "2026-01-01T00:00:00Z".into(), labels: HashMap::from([("env".into(), "staging".into())]), @@ -919,6 +936,7 @@ mod tests { run_id: "orphan".into(), dir_name: "d1".into(), workflow_name: "[no manifest]".into(), + workflow_slug: None, status: RunStatus::Unknown, start_time: "".into(), labels: HashMap::new(), @@ -1451,6 +1469,31 @@ mod tests { assert_eq!(info.run_id, "aaa111-full"); } + #[test] + fn resolve_run_matches_by_workflow_slug() { + let dir = tempfile::tempdir().unwrap(); + // Graph name is "Bar" but slug is "foo" — resolve_run("foo") should match via slug + make_run_dir( + dir.path(), + "20260101-AAA111", + Some(serde_json::json!({ + "run_id": "aaa111-full", + "workflow_name": "Bar", + "workflow_slug": "foo", + "goal": "", + "start_time": "2026-01-01T12:00:00Z", + "node_count": 1, + "edge_count": 0 + })), + None, + false, + ); + + let info = resolve_run(dir.path(), "foo").unwrap(); + assert_eq!(info.run_id, "aaa111-full"); + assert_eq!(info.workflow_slug.as_deref(), Some("foo")); + } + // === Step 1: end_time tests === #[test] diff --git a/lib/crates/fabro-workflows/src/engine.rs b/lib/crates/fabro-workflows/src/engine.rs index 631852ed9..8973f1864 100644 --- a/lib/crates/fabro-workflows/src/engine.rs +++ b/lib/crates/fabro-workflows/src/engine.rs @@ -300,6 +300,7 @@ fn write_manifest(run_dir: &Path, graph: &Graph, config: &RunConfig) -> crate::m base_sha: config.base_sha.clone(), labels: config.labels.clone(), base_branch: config.base_branch.clone(), + workflow_slug: config.workflow_slug.clone(), }; let _ = std::fs::create_dir_all(run_dir); let _ = manifest.save(&run_dir.join("manifest.json")); @@ -785,6 +786,8 @@ pub struct RunConfig { pub pull_request_draft: bool, /// Glob patterns for asset collection. Empty = no asset collection. pub asset_globs: Vec, + /// Workflow directory slug (e.g. "smoke" from `fabro/workflows/smoke/`). + pub workflow_slug: Option, } /// The workflow run execution engine. @@ -2795,6 +2798,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&g, &config).await.unwrap(); assert_eq!(outcome.status, StageStatus::Success); @@ -2824,6 +2828,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&g, &config).await.unwrap(); let checkpoint_path = dir.path().join("checkpoint.json"); @@ -2861,6 +2866,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&g, &config).await.unwrap(); @@ -2894,6 +2900,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&g, &config).await; assert!(result.is_err()); @@ -2923,6 +2930,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&g, &config).await.unwrap(); @@ -2965,6 +2973,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&g, &config).await.unwrap(); assert_eq!(outcome.status, StageStatus::Success); @@ -3031,6 +3040,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&g, &config).await.unwrap(); @@ -3124,6 +3134,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&g, &config).await.unwrap(); @@ -3160,6 +3171,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&g, &config).await.unwrap(); @@ -3191,6 +3203,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&g, &config).await.unwrap(); @@ -3222,6 +3235,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&g, &config).await.unwrap(); @@ -3257,6 +3271,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&g, &config).await.unwrap(); @@ -3420,6 +3435,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&g, &config).await.unwrap(); @@ -3466,6 +3482,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&g, &config).await.unwrap(); @@ -3530,6 +3547,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&g, &config).await.unwrap(); @@ -3597,6 +3615,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&g, &config).await; @@ -3668,6 +3687,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&g, &config).await; assert!(result.is_ok()); @@ -3728,6 +3748,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&g, &config).await.unwrap(); assert_eq!(outcome.status, StageStatus::Success); @@ -3789,6 +3810,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&g, &config).await.unwrap(); @@ -3825,6 +3847,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&g, &config).await.unwrap(); assert_eq!(outcome.status, StageStatus::Success); @@ -3857,6 +3880,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&g, &config).await; assert!(result.is_err()); @@ -3888,6 +3912,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&g, &config).await.unwrap(); assert_eq!(outcome.status, StageStatus::Success); @@ -3932,6 +3957,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; // Set cancel after a short delay (while the slow handler is running) @@ -4013,6 +4039,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&g, &config).await; assert!(result.is_err()); @@ -4047,6 +4074,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&g, &config).await; assert!(result.is_err()); @@ -4083,6 +4111,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&g, &config).await; assert!(result.is_err()); @@ -4124,6 +4153,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&g, &config).await; assert!(result.is_err()); @@ -4163,6 +4193,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&g, &config).await; assert!(result.is_err()); @@ -4199,6 +4230,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&g, &config).await; assert!(result.is_err()); @@ -4296,6 +4328,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; // The engine returns Err because the Fail outcome has no outgoing fail edge, @@ -4508,6 +4541,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&g, &config).await; assert!(result.is_err()); @@ -4547,6 +4581,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&g, &config).await; assert!(result.is_err()); @@ -4593,6 +4628,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&g, &config).await; assert!(result.is_err()); @@ -4679,6 +4715,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&g, &config).await; assert!(result.is_err()); @@ -4776,6 +4813,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&g, &config).await; assert!(result.is_err()); @@ -4850,6 +4888,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&g, &config).await.unwrap(); assert_eq!(outcome.status, StageStatus::Success); @@ -4911,6 +4950,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&g, &config).await.unwrap(); assert_eq!(outcome.status, StageStatus::Success); @@ -4973,6 +5013,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let _outcome = engine.run(&g, &config).await.unwrap(); @@ -5065,6 +5106,7 @@ mod tests { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&g, &config).await.unwrap(); diff --git a/lib/crates/fabro-workflows/src/handler/manager_loop.rs b/lib/crates/fabro-workflows/src/handler/manager_loop.rs index 3c3b41155..aef3542ee 100644 --- a/lib/crates/fabro-workflows/src/handler/manager_loop.rs +++ b/lib/crates/fabro-workflows/src/handler/manager_loop.rs @@ -159,6 +159,7 @@ impl Handler for SubWorkflowHandler { pull_request_enabled: false, pull_request_draft: true, asset_globs: Vec::new(), + workflow_slug: None, }; // Clone parent context for child; inject parent preamble diff --git a/lib/crates/fabro-workflows/src/manifest.rs b/lib/crates/fabro-workflows/src/manifest.rs index f4e508b1a..66df396fb 100644 --- a/lib/crates/fabro-workflows/src/manifest.rs +++ b/lib/crates/fabro-workflows/src/manifest.rs @@ -22,6 +22,8 @@ pub struct Manifest { pub labels: HashMap, #[serde(default, skip_serializing_if = "Option::is_none")] pub base_branch: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub workflow_slug: Option, } impl Manifest { @@ -50,6 +52,7 @@ mod tests { base_sha: Some("abc123".to_string()), labels: HashMap::from([("env".into(), "test".into())]), base_branch: None, + workflow_slug: None, } } @@ -88,6 +91,19 @@ mod tests { assert!(result.is_err()); } + #[test] + fn save_and_load_roundtrip_with_slug() { + let dir = tempfile::tempdir().unwrap(); + let path = dir.path().join("manifest.json"); + + let mut manifest = sample_manifest(); + manifest.workflow_slug = Some("smoke".to_string()); + manifest.save(&path).unwrap(); + let loaded = Manifest::load(&path).unwrap(); + + assert_eq!(loaded.workflow_slug.as_deref(), Some("smoke")); + } + #[test] fn labels_omitted_when_empty() { let dir = tempfile::tempdir().unwrap(); @@ -104,5 +120,6 @@ mod tests { assert!(raw.get("labels").is_none()); assert!(raw.get("run_branch").is_none()); assert!(raw.get("base_sha").is_none()); + assert!(raw.get("workflow_slug").is_none()); } } diff --git a/lib/crates/fabro-workflows/tests/daytona_integration.rs b/lib/crates/fabro-workflows/tests/daytona_integration.rs index 6b7d12b8f..15d67cd7d 100644 --- a/lib/crates/fabro-workflows/tests/daytona_integration.rs +++ b/lib/crates/fabro-workflows/tests/daytona_integration.rs @@ -406,6 +406,7 @@ async fn daytona_pipeline_artifact_offload_and_sync() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -603,6 +604,7 @@ async fn daytona_git_checkpoint_remote_emits_events() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -791,6 +793,7 @@ async fn daytona_parallel_git_branching_e2e() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -1170,6 +1173,7 @@ async fn daytona_git_checkpoint_with_shadow_branch() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -1312,6 +1316,7 @@ async fn daytona_asset_collection() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -1569,6 +1574,7 @@ async fn daytona_git_push_run_branch_to_origin() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine diff --git a/lib/crates/fabro-workflows/tests/integration.rs b/lib/crates/fabro-workflows/tests/integration.rs index b520e029a..8f3a2e88d 100644 --- a/lib/crates/fabro-workflows/tests/integration.rs +++ b/lib/crates/fabro-workflows/tests/integration.rs @@ -208,6 +208,7 @@ async fn end_to_end_linear_pipeline() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -353,6 +354,7 @@ async fn end_to_end_branching_pipeline() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -480,6 +482,7 @@ async fn end_to_end_human_gate_pipeline() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -597,6 +600,7 @@ async fn goal_gate_routes_to_retry_target_on_failure() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&graph, &config).await; @@ -724,6 +728,7 @@ async fn goal_gate_routes_to_retry_target_when_present() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -1042,6 +1047,7 @@ async fn retry_on_failure_then_succeed() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -1123,6 +1129,7 @@ async fn pipeline_with_many_nodes() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -1455,6 +1462,7 @@ async fn smoke_test_with_mock_codergen_backend() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -1562,6 +1570,7 @@ async fn end_to_end_parallel_fan_out_fan_in() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -1681,6 +1690,7 @@ async fn resume_from_checkpoint_completes_pipeline() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -1786,6 +1796,7 @@ async fn resume_from_checkpoint_preserves_goal_gate_outcomes() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; // This should succeed because goal gate for gated_work is satisfied @@ -1835,6 +1846,7 @@ async fn graph_goal_in_context() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -1876,6 +1888,7 @@ async fn event_streaming_lifecycle() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -1961,6 +1974,7 @@ async fn context_flow_between_stages() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -2019,6 +2033,7 @@ async fn tool_handler_e2e() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&graph, &config).await.expect("run"); assert_eq!(outcome.status, StageStatus::Success); @@ -2094,6 +2109,7 @@ async fn auto_approve_interviewer_e2e() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&graph, &config).await.expect("run"); assert_eq!(outcome.status, StageStatus::Success); @@ -2136,6 +2152,7 @@ async fn codergen_without_backend_simulated() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -2246,6 +2263,7 @@ async fn branching_loop_back_on_failure() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&graph, &config).await.expect("run"); assert_eq!(outcome.status, StageStatus::Success); @@ -2336,6 +2354,7 @@ async fn human_gate_loops_back() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&graph, &config).await.expect("run"); assert_eq!(outcome.status, StageStatus::Success); @@ -2399,6 +2418,7 @@ async fn scenario_ship_a_feature() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&graph, &config).await.expect("run"); assert_eq!(outcome.status, StageStatus::Success); @@ -2490,6 +2510,7 @@ async fn scenario_parallel_expert_review() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&graph, &config).await.expect("run"); assert_eq!(outcome.status, StageStatus::Success); @@ -2579,6 +2600,7 @@ async fn scenario_node_retries_on_retry_status() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&graph, &config).await.expect("run"); assert_eq!(outcome.status, StageStatus::Success); @@ -2646,6 +2668,7 @@ async fn scenario_loop_restart_resets_context() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&graph, &config).await.expect("run"); assert_eq!(outcome.status, StageStatus::Success); @@ -2719,6 +2742,7 @@ async fn scenario_bug_triage_router() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&graph, &config).await.expect("run"); assert_eq!(outcome.status, StageStatus::Success); @@ -2783,6 +2807,7 @@ async fn scenario_crash_recovery() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine .run_from_checkpoint(&graph, &config, &checkpoint) @@ -2897,6 +2922,7 @@ async fn manager_loop_stop_condition_satisfied_e2e() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&graph, &config).await.expect("run"); @@ -2979,6 +3005,7 @@ async fn manager_loop_max_cycles_exceeded_e2e() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&graph, &config).await.expect("run"); @@ -3120,6 +3147,7 @@ async fn conditional_branching_success_fail_paths() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&graph, &config).await.expect("run"); assert_eq!(outcome.status, StageStatus::Success); @@ -3178,6 +3206,7 @@ async fn edge_selection_condition_match_wins_over_weight() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -3230,6 +3259,7 @@ async fn edge_selection_weight_breaks_ties() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -3274,6 +3304,7 @@ async fn edge_selection_lexical_tiebreak() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -3337,6 +3368,7 @@ async fn context_updates_visible_across_nodes() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -3386,6 +3418,7 @@ async fn stylesheet_applies_model_override() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&graph, &config).await.expect("run"); assert_eq!(outcome.status, StageStatus::Success); @@ -3447,6 +3480,7 @@ async fn custom_handler_registration_and_execution() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -3523,6 +3557,7 @@ async fn integration_smoke_plan_implement_review_done() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&graph, &config).await.expect("run"); assert_eq!(outcome.status, StageStatus::Success); @@ -3632,6 +3667,7 @@ async fn manager_loop_runs_child_engine_e2e() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -3772,6 +3808,7 @@ async fn manager_loop_context_flows_e2e() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&graph, &config).await.expect("run"); @@ -3851,6 +3888,7 @@ async fn manager_loop_child_dotfile_e2e() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&graph, &config).await.expect("run"); @@ -3970,6 +4008,7 @@ async fn graph_merge_e2e_through_engine() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -4126,6 +4165,7 @@ async fn fidelity_default_is_compact() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -4188,6 +4228,7 @@ async fn fidelity_graph_default_applied() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -4246,6 +4287,7 @@ async fn fidelity_node_overrides_graph_default() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -4310,6 +4352,7 @@ async fn fidelity_edge_overrides_node_and_graph() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -4364,6 +4407,7 @@ async fn fidelity_full_produces_empty_preamble() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -4428,6 +4472,7 @@ async fn fidelity_truncate_preamble_minimal() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -4505,6 +4550,7 @@ async fn fidelity_summary_low_mode() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -4577,6 +4623,7 @@ async fn fidelity_summary_medium_mode() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -4649,6 +4696,7 @@ async fn fidelity_summary_high_mode() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -4714,6 +4762,7 @@ async fn fidelity_full_sets_thread_id_in_context() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -4790,6 +4839,7 @@ async fn fidelity_full_nodes_share_thread_id() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -4876,6 +4926,7 @@ async fn fidelity_resume_degrades_full_to_summary_high() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine .run_from_checkpoint(&graph, &config, &checkpoint) @@ -4978,6 +5029,7 @@ async fn fidelity_resume_degrade_only_affects_first_hop() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine .run_from_checkpoint(&graph, &config, &checkpoint) @@ -5067,6 +5119,7 @@ async fn fidelity_resume_no_degrade_when_not_full() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine .run_from_checkpoint(&graph, &config, &checkpoint) @@ -5114,6 +5167,7 @@ async fn fidelity_stored_in_checkpoint_context() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -5205,6 +5259,7 @@ async fn fidelity_precedence_multi_node_pipeline() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -5278,6 +5333,7 @@ async fn fidelity_compact_preamble_includes_completed_stages_and_context() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -5359,6 +5415,7 @@ async fn fidelity_summary_low_excludes_context_values_in_pipeline() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine_low .run(&graph_low, &config_low) @@ -5432,6 +5489,7 @@ async fn fidelity_summary_low_excludes_context_values_in_pipeline() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine_med .run(&graph_med, &config_med) @@ -5508,6 +5566,7 @@ async fn fidelity_thread_id_fallback_to_previous_node_in_pipeline() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -5567,6 +5626,7 @@ async fn fidelity_thread_id_from_node_class_in_pipeline() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -5629,6 +5689,7 @@ async fn fidelity_edge_thread_id_override_in_pipeline() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -5692,6 +5753,7 @@ async fn fidelity_full_without_explicit_thread_id_uses_previous_node() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -5765,6 +5827,7 @@ async fn fidelity_from_parsed_dot_pipeline() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -5818,6 +5881,7 @@ async fn fidelity_checkpoint_roundtrip_preserves_fidelity() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -5893,6 +5957,7 @@ async fn fidelity_node_thread_id_overrides_edge_thread_id_in_pipeline() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine.run(&graph, &config).await.expect("run"); @@ -5985,6 +6050,7 @@ async fn fidelity_resume_preserves_context_values_across_checkpoint() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine .run_from_checkpoint(&graph, &config, &checkpoint) @@ -6202,6 +6268,7 @@ mod real_llm { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = tokio::time::timeout( @@ -6322,6 +6389,7 @@ mod real_llm { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = tokio::time::timeout( @@ -6467,6 +6535,7 @@ mod real_llm { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = tokio::time::timeout( @@ -6580,6 +6649,7 @@ mod real_llm { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = tokio::time::timeout( @@ -6682,6 +6752,7 @@ async fn human_gate_freeform_only_routes_text() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -6819,6 +6890,7 @@ async fn human_gate_freeform_with_fixed_choice_match() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -6940,6 +7012,7 @@ async fn human_gate_freeform_fallback_on_unmatched_text() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -7075,6 +7148,7 @@ async fn human_gate_freeform_sets_allow_freeform_on_question() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -7190,6 +7264,7 @@ async fn human_gate_without_freeform_sets_allow_freeform_false() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -7456,6 +7531,7 @@ fn make_run_config(dir: &std::path::Path) -> RunConfig { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, } } @@ -8598,6 +8674,7 @@ async fn arc_e2e_with_real_llm() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -8732,6 +8809,7 @@ async fn run_fidelity_prompt_pipeline(fidelity: &str) -> String { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; engine @@ -8937,6 +9015,7 @@ async fn large_context_values_are_offloaded_to_artifact_store() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -9163,6 +9242,7 @@ async fn artifact_pointers_rewritten_for_remote_sandbox() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -9299,6 +9379,7 @@ async fn node_dir_uses_visit_count_on_revisit() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -10279,6 +10360,7 @@ async fn full_pipeline_with_cli_backend_node() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -10416,6 +10498,7 @@ async fn stylesheet_backend_property_routes_to_cli() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -10703,6 +10786,7 @@ async fn git_checkpoint_host_emits_events_and_diff_patch() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; // 5. Run pipeline @@ -10895,6 +10979,7 @@ async fn git_checkpoint_host_writes_shadow_branch() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; // 5. Run pipeline @@ -11095,6 +11180,7 @@ async fn parallel_git_branching_host_e2e() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; // 5. Run pipeline @@ -11360,6 +11446,7 @@ async fn git_checkpoint_host_skips_empty_diff_patch() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -11744,6 +11831,7 @@ async fn e2e_circuit_breaker_deterministic_self_loop() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&graph, &config).await; @@ -11797,6 +11885,7 @@ async fn e2e_circuit_breaker_custom_limit() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&graph, &config).await; @@ -11843,6 +11932,7 @@ async fn e2e_circuit_breaker_ignores_transient_failures() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&graph, &config).await; @@ -11896,6 +11986,7 @@ async fn e2e_circuit_breaker_different_reasons_separate_counters() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&graph, &config).await; @@ -11942,6 +12033,7 @@ async fn e2e_circuit_breaker_loop_restart() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&graph, &config).await; @@ -12010,6 +12102,7 @@ async fn e2e_failure_signature_persisted_in_context() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&graph, &config).await.unwrap(); @@ -12080,6 +12173,7 @@ async fn e2e_failure_signature_hint_overrides_reason_in_context() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let _outcome = engine.run(&graph, &config).await.unwrap(); @@ -12142,6 +12236,7 @@ async fn e2e_signature_maps_persist_in_checkpoint() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&graph, &config).await.unwrap(); @@ -12275,6 +12370,7 @@ async fn e2e_circuit_breaker_emits_events_before_abort() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&graph, &config).await; @@ -12348,6 +12444,7 @@ async fn e2e_circuit_breaker_does_not_fire_below_limit() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&graph, &config).await.unwrap(); @@ -12450,6 +12547,7 @@ async fn e2e_circuit_breaker_multi_stage_impl_verify_cycle() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&graph, &config).await; @@ -12553,6 +12651,7 @@ async fn e2e_loop_restart_blocked_for_deterministic_failure() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&graph, &config).await; @@ -12599,6 +12698,7 @@ async fn e2e_loop_restart_blocked_for_structural_failure() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&graph, &config).await; @@ -12645,6 +12745,7 @@ async fn e2e_loop_restart_blocked_for_budget_exhausted_failure() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&graph, &config).await; @@ -12691,6 +12792,7 @@ async fn e2e_loop_restart_blocked_for_canceled_failure() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&graph, &config).await; @@ -12734,6 +12836,7 @@ async fn e2e_loop_restart_blocked_for_compilation_loop_failure() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&graph, &config).await; @@ -12781,6 +12884,7 @@ async fn e2e_loop_restart_allowed_for_transient_infra() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&graph, &config).await; @@ -12891,6 +12995,7 @@ async fn e2e_stall_watchdog_triggers_from_dot_parsed_pipeline() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let result = engine.run(&graph, &config).await; @@ -12953,6 +13058,7 @@ async fn e2e_stall_watchdog_kept_alive_by_handler_events() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -13005,6 +13111,7 @@ async fn e2e_stall_watchdog_disabled_with_zero_timeout() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -13076,6 +13183,7 @@ async fn e2e_stall_watchdog_with_explicit_timeout_override() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let start = std::time::Instant::now(); @@ -13213,6 +13321,7 @@ async fn asset_collection_local_sandbox_success() { pull_request_enabled: false, pull_request_draft: false, asset_globs: vec!["test-results/**".to_string()], + workflow_slug: None, }; let outcome = engine @@ -13328,6 +13437,7 @@ async fn asset_collection_local_sandbox_on_failure() { pull_request_enabled: false, pull_request_draft: false, asset_globs: vec!["test-results/**".to_string()], + workflow_slug: None, }; let outcome = engine @@ -13425,6 +13535,7 @@ async fn asset_collection_docker_sandbox() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine @@ -13500,6 +13611,7 @@ async fn wait_timer_e2e() { pull_request_enabled: false, pull_request_draft: false, asset_globs: Vec::new(), + workflow_slug: None, }; let outcome = engine.run(&graph, &config).await.expect("run"); assert_eq!(outcome.status, StageStatus::Success);