From 0cb5495ce9755529cfeec3dc0c9438c0a0ce8aa1 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Wed, 1 Apr 2026 20:57:24 -0700 Subject: [PATCH] Require store-backed metadata branch bootstrap --- .../fabro-workflow/src/lifecycle/git.rs | 9 +++---- lib/crates/fabro-workflow/src/test_support.rs | 24 +++++++++++++++++-- .../fabro-workflow/tests/it/integration.rs | 13 ---------- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/lib/crates/fabro-workflow/src/lifecycle/git.rs b/lib/crates/fabro-workflow/src/lifecycle/git.rs index 3c762d167..50a909a26 100644 --- a/lib/crates/fabro-workflow/src/lifecycle/git.rs +++ b/lib/crates/fabro-workflow/src/lifecycle/git.rs @@ -71,24 +71,21 @@ impl RunLifecycle for GitLifecycle { .await .ok() .flatten() - .and_then(|record| serde_json::to_vec_pretty(&record).ok()) - .or_else(|| std::fs::read(self.run_dir.join("run.json")).ok()); + .and_then(|record| serde_json::to_vec_pretty(&record).ok()); let start_json = self .run_store .get_start() .await .ok() .flatten() - .and_then(|record| serde_json::to_vec_pretty(&record).ok()) - .or_else(|| std::fs::read(self.run_dir.join("start.json")).ok()); + .and_then(|record| serde_json::to_vec_pretty(&record).ok()); let sandbox_json = self .run_store .get_sandbox() .await .ok() .flatten() - .and_then(|record| serde_json::to_vec_pretty(&record).ok()) - .or_else(|| std::fs::read(self.run_dir.join("sandbox.json")).ok()); + .and_then(|record| serde_json::to_vec_pretty(&record).ok()); let mut files: Vec<(&str, &[u8])> = Vec::new(); if let Some(ref data) = run_json { files.push(("run.json", data)); diff --git a/lib/crates/fabro-workflow/src/test_support.rs b/lib/crates/fabro-workflow/src/test_support.rs index a37d8a103..a37d31ba4 100644 --- a/lib/crates/fabro-workflow/src/test_support.rs +++ b/lib/crates/fabro-workflow/src/test_support.rs @@ -1,10 +1,12 @@ use std::collections::HashMap; +use std::path::PathBuf; use std::sync::Arc; use chrono::Utc; use fabro_agent::Sandbox; use fabro_graphviz::graph::Graph as GvGraph; -use fabro_store::{DiskProjectingRunStore, InMemoryStore, Store}; +use fabro_store::{DiskProjectingRunStore, InMemoryStore, RunStore, Store}; +use fabro_types::run::RunRecord; use crate::error::Result; use crate::event::EventEmitter; @@ -37,10 +39,11 @@ async fn initialized( options: InitializedOptions, ) -> Initialized { std::fs::create_dir_all(&run_options.run_dir).expect("failed to create run dir"); + let created_at = Utc::now(); let inner_store = InMemoryStore::default() .create_run( &run_options.run_id, - Utc::now(), + created_at, Some(run_options.run_dir.to_string_lossy().as_ref()), ) .await @@ -49,6 +52,23 @@ async fn initialized( inner_store, run_options.run_dir.clone(), )); + run_store + .put_run(&RunRecord { + run_id: run_options.run_id, + created_at, + settings: run_options.settings.clone(), + graph: graph.clone(), + workflow_slug: run_options.workflow_slug.clone(), + working_directory: PathBuf::from(sandbox.working_directory()), + host_repo_path: run_options + .host_repo_path + .as_ref() + .map(|path| path.display().to_string()), + base_branch: run_options.base_branch.clone(), + labels: run_options.labels.clone(), + }) + .await + .expect("failed to seed run record in run store"); let emitter = bound_emitter(run_options.run_id, &emitter); Initialized { graph: graph.clone(), diff --git a/lib/crates/fabro-workflow/tests/it/integration.rs b/lib/crates/fabro-workflow/tests/it/integration.rs index c67b40204..80159b514 100644 --- a/lib/crates/fabro-workflow/tests/it/integration.rs +++ b/lib/crates/fabro-workflow/tests/it/integration.rs @@ -10229,19 +10229,6 @@ async fn git_checkpoint_host_writes_shadow_branch() { let run_dir = tempfile::tempdir().unwrap(); // Write graph.fabro so init_run can read it std::fs::write(run_dir.path().join("graph.fabro"), "digraph {}").unwrap(); - // Write run.json so init_run stores it on the metadata branch - let run_record_json = serde_json::json!({ - "run_id": run_id, - "created_at": "2025-01-01T00:00:00Z", - "settings": {}, - "graph": { "name": "ShadowBranchTest", "nodes": {}, "edges": [], "attrs": {} }, - "working_directory": worktree_path.to_str().unwrap(), - }); - std::fs::write( - run_dir.path().join("run.json"), - serde_json::to_string(&run_record_json).unwrap(), - ) - .unwrap(); let emitter = EventEmitter::default(); let env: Arc =