diff --git a/lib/crates/fabro-store/src/lib.rs b/lib/crates/fabro-store/src/lib.rs index ec6d12845..adb3bd993 100644 --- a/lib/crates/fabro-store/src/lib.rs +++ b/lib/crates/fabro-store/src/lib.rs @@ -15,9 +15,6 @@ pub use runtime::RuntimeState; pub use slate::{SlateRunStore, SlateStore}; pub use types::{CatalogRecord, EventEnvelope, EventPayload, NodeVisitRef, RunSummary}; -use fabro_types::{Outcome, StageUsage}; - -pub type NodeOutcomeRecord = Outcome>; pub type StoreHandle = Arc; #[derive(Debug, Default, Clone, PartialEq, Eq)] diff --git a/lib/crates/fabro-store/src/run_state.rs b/lib/crates/fabro-store/src/run_state.rs index 02d50c039..29de59a23 100644 --- a/lib/crates/fabro-store/src/run_state.rs +++ b/lib/crates/fabro-store/src/run_state.rs @@ -6,13 +6,11 @@ use chrono::{DateTime, Utc}; use serde::de::DeserializeOwned; use serde_json::Value; -use crate::{ - CatalogRecord, EventEnvelope, NodeOutcomeRecord, NodeVisitRef, Result, RunSummary, StoreError, -}; +use crate::{CatalogRecord, EventEnvelope, NodeVisitRef, Result, RunSummary, StoreError}; use fabro_types::{ Checkpoint, Conclusion, FailureSignature, NodeStatusRecord, Outcome, PullRequestRecord, Retro, - RunId, RunRecord, RunStatus, RunStatusRecord, SandboxRecord, StageStatus, StartRecord, - StatusReason, + RunId, RunRecord, RunStatus, RunStatusRecord, SandboxRecord, StageStatus, StageUsage, + StartRecord, StatusReason, }; #[derive(Debug, Clone, Default)] @@ -39,7 +37,7 @@ pub struct NodeState { pub prompt: Option, pub response: Option, pub status: Option, - pub outcome: Option, + pub outcome: Option>>, pub provider_used: Option, pub diff: Option, pub script_invocation: Option, @@ -309,10 +307,7 @@ impl RunState { (!goal.is_empty()).then(|| goal.to_string()) }); RunSummary { - run_id: catalog.run_id, - created_at: catalog.created_at, - db_prefix: catalog.db_prefix.clone(), - run_dir: catalog.run_dir.clone(), + catalog: catalog.clone(), workflow_name, workflow_slug: self.run.as_ref().and_then(|run| run.workflow_slug.clone()), goal, @@ -564,7 +559,7 @@ fn stage_visit( fn stage_outcome_from_properties( properties: &serde_json::Map, -) -> Result { +) -> Result>> { let status = StageStatus::from_str(&required_string(properties, "status")?) .map_err(|err| StoreError::InvalidEvent(format!("invalid stage status: {err}")))?; Ok(Outcome { @@ -582,7 +577,7 @@ fn stage_outcome_from_properties( } fn node_status_from_outcome( - outcome: &NodeOutcomeRecord, + outcome: &Outcome>, timestamp: DateTime, ) -> NodeStatusRecord { NodeStatusRecord { diff --git a/lib/crates/fabro-store/src/slate/mod.rs b/lib/crates/fabro-store/src/slate/mod.rs index ad9d64d2f..4ac1d497c 100644 --- a/lib/crates/fabro-store/src/slate/mod.rs +++ b/lib/crates/fabro-store/src/slate/mod.rs @@ -284,7 +284,7 @@ impl SlateStore { let summary = summary?; summaries.push(summary); } - summaries.sort_by(|a, b| b.created_at.cmp(&a.created_at)); + summaries.sort_by(|a, b| b.catalog.created_at.cmp(&a.catalog.created_at)); Ok(summaries) } @@ -656,7 +656,7 @@ mod tests { let summary = store.list_runs(&ListRunsQuery::default()).await.unwrap(); assert_eq!(summary.len(), 1); - assert_eq!(summary[0].run_id, test_run_id("run-1")); + assert_eq!(summary[0].catalog.run_id, test_run_id("run-1")); assert_eq!(summary[0].workflow_name, Some("night-sky".to_string())); assert_eq!(summary[0].goal, Some("map the constellations".to_string())); assert_eq!(summary[0].status, Some(RunStatus::Succeeded)); @@ -2020,7 +2020,7 @@ mod tests { let all = store.list_runs(&ListRunsQuery::default()).await.unwrap(); assert_eq!(all.len(), 2); - assert_eq!(all[0].run_id, test_run_id("run-late")); + assert_eq!(all[0].catalog.run_id, test_run_id("run-late")); assert_eq!(all[0].workflow_name, Some("night-sky".to_string())); assert_eq!(all[0].goal, Some("map the constellations".to_string())); assert_eq!( @@ -2040,6 +2040,6 @@ mod tests { .await .unwrap(); assert_eq!(filtered.len(), 1); - assert_eq!(filtered[0].run_id, test_run_id("run-late")); + assert_eq!(filtered[0].catalog.run_id, test_run_id("run-late")); } } diff --git a/lib/crates/fabro-store/src/types.rs b/lib/crates/fabro-store/src/types.rs index ed06f1fa3..9d286d4f3 100644 --- a/lib/crates/fabro-store/src/types.rs +++ b/lib/crates/fabro-store/src/types.rs @@ -22,10 +22,8 @@ pub struct CatalogRecord { #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct RunSummary { - pub run_id: RunId, - pub created_at: DateTime, - pub db_prefix: String, - pub run_dir: Option, + #[serde(flatten)] + pub catalog: CatalogRecord, pub workflow_name: Option, pub workflow_slug: Option, pub goal: Option, diff --git a/lib/crates/fabro-workflow/src/operations/rebuild_meta.rs b/lib/crates/fabro-workflow/src/operations/rebuild_meta.rs index e273784bf..f6ce009fc 100644 --- a/lib/crates/fabro-workflow/src/operations/rebuild_meta.rs +++ b/lib/crates/fabro-workflow/src/operations/rebuild_meta.rs @@ -185,9 +185,9 @@ pub async fn find_run_id_by_prefix_or_store( let current_repo_root = canonical_repo_root(repo)?; let mut matches = Vec::new(); for summary in fabro_store.list_runs(&ListRunsQuery::default()).await? { - if summary.run_id.to_string() == prefix { + if summary.catalog.run_id.to_string() == prefix { if summary.host_repo_path.is_none() { - return Ok(summary.run_id); + return Ok(summary.catalog.run_id); } let Some(host_repo_path) = summary.host_repo_path.as_deref() else { @@ -200,7 +200,7 @@ pub async fn find_run_id_by_prefix_or_store( continue; }; if host_repo_root == current_repo_root { - return Ok(summary.run_id); + return Ok(summary.catalog.run_id); } continue; } @@ -214,8 +214,10 @@ pub async fn find_run_id_by_prefix_or_store( let Ok(host_repo_root) = canonical_repo_root(&host_repo) else { continue; }; - if host_repo_root == current_repo_root && summary.run_id.to_string().starts_with(prefix) { - matches.push(summary.run_id); + if host_repo_root == current_repo_root + && summary.catalog.run_id.to_string().starts_with(prefix) + { + matches.push(summary.catalog.run_id); } } diff --git a/lib/crates/fabro-workflow/src/run_lookup.rs b/lib/crates/fabro-workflow/src/run_lookup.rs index c5c6481f5..f656482ef 100644 --- a/lib/crates/fabro-workflow/src/run_lookup.rs +++ b/lib/crates/fabro-workflow/src/run_lookup.rs @@ -124,7 +124,7 @@ pub async fn scan_runs_combined(store: &SlateStore, base: &Path) -> Result Result Option { - let run_dir = summary.run_dir.as_deref()?; + let run_dir = summary.catalog.run_dir.as_deref()?; let path = PathBuf::from(run_dir); if !path.exists() { return None; @@ -153,7 +153,7 @@ fn run_info_from_summary(summary: &fabro_store::RunSummary) -> Option { let dir_name = path .file_name() .map(|name| name.to_string_lossy().to_string())?; - let start_time_dt = summary.created_at; + let start_time_dt = summary.catalog.created_at; let start_time = summary.start_time.unwrap_or(start_time_dt); let end_time = if summary.status.is_some_and(RunStatus::is_terminal) { summary.duration_ms.and_then(|duration_ms| { @@ -164,7 +164,7 @@ fn run_info_from_summary(summary: &fabro_store::RunSummary) -> Option { }; Some(RunInfo { - run_id: summary.run_id, + run_id: summary.catalog.run_id, dir_name, workflow_name: summary .workflow_name