From af6e091ef3906be17cb4a8538dec66edc6844d7a Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Fri, 6 Mar 2026 10:48:07 -0500 Subject: [PATCH] Rename final.json to conclusion.json and RunFinal to Conclusion Co-Authored-By: Claude Opus 4.6 --- crates/arc-workflows/src/cli/run.rs | 4 +- crates/arc-workflows/src/cli/runs.rs | 16 +++---- .../src/{run_final.rs => conclusion.rs} | 42 +++++++++---------- crates/arc-workflows/src/lib.rs | 2 +- docs/execution/observability.mdx | 2 +- 5 files changed, 33 insertions(+), 33 deletions(-) rename crates/arc-workflows/src/{run_final.rs => conclusion.rs} (71%) diff --git a/crates/arc-workflows/src/cli/run.rs b/crates/arc-workflows/src/cli/run.rs index 7a582336c..2ceb201be 100644 --- a/crates/arc-workflows/src/cli/run.rs +++ b/crates/arc-workflows/src/cli/run.rs @@ -712,14 +712,14 @@ pub async fn run_command( Ok(o) => (o.status.to_string(), o.failure_reason().map(String::from)), Err(e) => ("fail".to_string(), Some(e.to_string())), }; - let run_final = crate::run_final::RunFinal { + let conclusion = crate::conclusion::Conclusion { timestamp: Utc::now(), status, duration_ms: run_duration_ms, failure_reason, final_git_commit_sha: last_git_sha.lock().unwrap().clone(), }; - let _ = run_final.save(&logs_dir.join("final.json")); + let _ = conclusion.save(&logs_dir.join("conclusion.json")); } // Finish progress bars before printing summary diff --git a/crates/arc-workflows/src/cli/runs.rs b/crates/arc-workflows/src/cli/runs.rs index 91c2cddac..689dbda21 100644 --- a/crates/arc-workflows/src/cli/runs.rs +++ b/crates/arc-workflows/src/cli/runs.rs @@ -139,10 +139,10 @@ pub fn scan_runs(base: &Path) -> Result> { } fn read_status(run_dir: &Path) -> String { - let final_path = run_dir.join("final.json"); - if final_path.exists() { - if let Ok(run_final) = crate::run_final::RunFinal::load(&final_path) { - return run_final.status; + let conclusion_path = run_dir.join("conclusion.json"); + if conclusion_path.exists() { + if let Ok(conclusion) = crate::conclusion::Conclusion::load(&conclusion_path) { + return conclusion.status; } "unknown".to_string() } else if run_dir.join("run.pid").exists() { @@ -307,7 +307,7 @@ mod tests { base: &Path, dir_name: &str, manifest: Option, - final_json: Option, + conclusion_json: Option, pid_file: bool, ) -> PathBuf { let dir = base.join(dir_name); @@ -319,10 +319,10 @@ mod tests { ) .unwrap(); } - if let Some(f) = final_json { + if let Some(c) = conclusion_json { fs::write( - dir.join("final.json"), - serde_json::to_string_pretty(&f).unwrap(), + dir.join("conclusion.json"), + serde_json::to_string_pretty(&c).unwrap(), ) .unwrap(); } diff --git a/crates/arc-workflows/src/run_final.rs b/crates/arc-workflows/src/conclusion.rs similarity index 71% rename from crates/arc-workflows/src/run_final.rs rename to crates/arc-workflows/src/conclusion.rs index b881ac0cd..e4bcfa927 100644 --- a/crates/arc-workflows/src/run_final.rs +++ b/crates/arc-workflows/src/conclusion.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; use crate::error::{ArcError, Result}; #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct RunFinal { +pub struct Conclusion { pub timestamp: DateTime, pub status: String, pub duration_ms: u64, @@ -16,19 +16,19 @@ pub struct RunFinal { pub final_git_commit_sha: Option, } -impl RunFinal { +impl Conclusion { pub fn save(&self, path: &Path) -> Result<()> { let json = serde_json::to_string_pretty(self) - .map_err(|e| ArcError::Checkpoint(format!("run_final serialize failed: {e}")))?; + .map_err(|e| ArcError::Checkpoint(format!("conclusion serialize failed: {e}")))?; std::fs::write(path, json)?; Ok(()) } pub fn load(path: &Path) -> Result { let data = std::fs::read_to_string(path)?; - let run_final: Self = serde_json::from_str(&data) - .map_err(|e| ArcError::Checkpoint(format!("run_final deserialize failed: {e}")))?; - Ok(run_final) + let conclusion: Self = serde_json::from_str(&data) + .map_err(|e| ArcError::Checkpoint(format!("conclusion deserialize failed: {e}")))?; + Ok(conclusion) } } @@ -36,8 +36,8 @@ impl RunFinal { mod tests { use super::*; - fn sample_run_final() -> RunFinal { - RunFinal { + fn sample_conclusion() -> Conclusion { + Conclusion { timestamp: Utc::now(), status: "success".to_string(), duration_ms: 12345, @@ -49,11 +49,11 @@ mod tests { #[test] fn save_and_load_roundtrip() { let dir = tempfile::tempdir().unwrap(); - let path = dir.path().join("final.json"); + let path = dir.path().join("conclusion.json"); - let run_final = sample_run_final(); - run_final.save(&path).unwrap(); - let loaded = RunFinal::load(&path).unwrap(); + let conclusion = sample_conclusion(); + conclusion.save(&path).unwrap(); + let loaded = Conclusion::load(&path).unwrap(); assert_eq!(loaded.status, "success"); assert_eq!(loaded.duration_ms, 12345); @@ -66,7 +66,7 @@ mod tests { #[test] fn load_nonexistent_file() { - let result = RunFinal::load(Path::new("/nonexistent/final.json")); + let result = Conclusion::load(Path::new("/nonexistent/conclusion.json")); assert!(result.is_err()); } @@ -76,23 +76,23 @@ mod tests { let path = dir.path().join("bad.json"); std::fs::write(&path, "not json").unwrap(); - let result = RunFinal::load(&path); + let result = Conclusion::load(&path); assert!(result.is_err()); } #[test] fn optional_fields_omitted_when_none() { let dir = tempfile::tempdir().unwrap(); - let path = dir.path().join("final.json"); + let path = dir.path().join("conclusion.json"); - let run_final = RunFinal { + let conclusion = Conclusion { timestamp: Utc::now(), status: "fail".to_string(), duration_ms: 500, failure_reason: None, final_git_commit_sha: None, }; - run_final.save(&path).unwrap(); + conclusion.save(&path).unwrap(); let raw: serde_json::Value = serde_json::from_str(&std::fs::read_to_string(&path).unwrap()).unwrap(); @@ -103,17 +103,17 @@ mod tests { #[test] fn failure_reason_present() { let dir = tempfile::tempdir().unwrap(); - let path = dir.path().join("final.json"); + let path = dir.path().join("conclusion.json"); - let run_final = RunFinal { + let conclusion = Conclusion { timestamp: Utc::now(), status: "fail".to_string(), duration_ms: 100, failure_reason: Some("timeout".to_string()), final_git_commit_sha: None, }; - run_final.save(&path).unwrap(); - let loaded = RunFinal::load(&path).unwrap(); + conclusion.save(&path).unwrap(); + let loaded = Conclusion::load(&path).unwrap(); assert_eq!(loaded.failure_reason.as_deref(), Some("timeout")); } diff --git a/crates/arc-workflows/src/lib.rs b/crates/arc-workflows/src/lib.rs index 664f15090..6e1ea6d42 100644 --- a/crates/arc-workflows/src/lib.rs +++ b/crates/arc-workflows/src/lib.rs @@ -20,7 +20,7 @@ pub mod parser; pub mod preamble; pub mod retro; pub mod retro_agent; -pub mod run_final; +pub mod conclusion; pub mod stylesheet; pub mod transform; pub mod validation; diff --git a/docs/execution/observability.mdx b/docs/execution/observability.mdx index ecb16aaaf..fedacb2c7 100644 --- a/docs/execution/observability.mdx +++ b/docs/execution/observability.mdx @@ -190,7 +190,7 @@ Each run's logs directory contains a standard set of files: | `live.json` | Last event snapshot (overwritten during run) | | `checkpoint.json` | Final execution state | | `retro.json` | Retrospective (if retro generation is enabled) | -| `final.json` | Terminal status (`completed`, `failed`, `canceled`) | +| `conclusion.json` | Terminal status (`completed`, `failed`, `canceled`) | ### Inspecting stages and turns