From 4ee215cadaa28fd335d5ab2d306740574d5b8b32 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Sat, 14 Mar 2026 12:20:07 -0400 Subject: [PATCH] Rename arc/ to fabro/ in git branch prefixes and workflow paths Complete the rebrand by replacing hardcoded "arc/run/" branch prefixes with a RUN_BRANCH_PREFIX constant ("fabro/run/") and updating fabro init to create workflows under fabro/workflows/ instead of arc/workflows/. Co-Authored-By: Claude Opus 4.6 (1M context) --- AGENTS.md | 2 +- docs/reference/cli.mdx | 2 +- files-internal/demo/14-search-imagegen.toml | 2 +- lib/crates/fabro-cli/src/init.rs | 6 ++--- lib/crates/fabro-workflows/src/cli/pr.rs | 14 ++++++------ lib/crates/fabro-workflows/src/cli/rewind.rs | 18 ++++++++++----- lib/crates/fabro-workflows/src/cli/run.rs | 11 +++++----- .../fabro-workflows/src/daytona_sandbox.rs | 4 ++-- lib/crates/fabro-workflows/src/engine.rs | 2 +- lib/crates/fabro-workflows/src/git.rs | 5 ++++- .../fabro-workflows/src/handler/parallel.rs | 2 +- .../fabro-workflows/src/pull_request.rs | 6 ++--- .../tests/daytona_integration.rs | 2 +- .../fabro-workflows/tests/integration.rs | 22 +++++++++---------- 14 files changed, 55 insertions(+), 43 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 5eb689b35..52d923704 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -82,5 +82,5 @@ When interpolating values into shell command strings (in `fabro-exe` and `fabro- ## Testing workflows -- `fabro run ` — run a workflow by name (resolves `arc/workflows//workflow.toml`), e.g. `fabro run repl` +- `fabro run ` — run a workflow by name (resolves `fabro/workflows//workflow.toml`), e.g. `fabro run repl` - Use `--no-retro` to skip the retro step and finish faster diff --git a/docs/reference/cli.mdx b/docs/reference/cli.mdx index 7491bd966..6463bb2e3 100644 --- a/docs/reference/cli.mdx +++ b/docs/reference/cli.mdx @@ -41,7 +41,7 @@ Launch a workflow from a `.fabro` workflow file or `.toml` task config. ```bash fabro run fabro run run.toml -fabro run --run-branch arc/run/abc123 +fabro run --run-branch fabro/run/abc123 ``` | Argument / Flag | Description | diff --git a/files-internal/demo/14-search-imagegen.toml b/files-internal/demo/14-search-imagegen.toml index e4ab2c1d9..dd217f77e 100644 --- a/files-internal/demo/14-search-imagegen.toml +++ b/files-internal/demo/14-search-imagegen.toml @@ -13,7 +13,7 @@ name = "imagegen-tools-v3" cpu = 4 memory = 8 disk = 10 -dockerfile = { path = "../../arc/workflows/imagegen/Dockerfile.imagegen" } +dockerfile = { path = "../../fabro/workflows/imagegen/Dockerfile.imagegen" } [assets] include = ["output/**"] diff --git a/lib/crates/fabro-cli/src/init.rs b/lib/crates/fabro-cli/src/init.rs index 0894e0e5e..3f6c6f64a 100644 --- a/lib/crates/fabro-cli/src/init.rs +++ b/lib/crates/fabro-cli/src/init.rs @@ -54,7 +54,7 @@ root = \"fabro/\" eprintln!(" {} {}", green.apply_to("✔"), dim.apply_to("fabro.toml")); // Create hello workflow directory - let workflow_dir = repo_root.join("arc/workflows/hello"); + let workflow_dir = repo_root.join("fabro/workflows/hello"); std::fs::create_dir_all(&workflow_dir) .with_context(|| format!("failed to create {}", workflow_dir.display()))?; @@ -79,7 +79,7 @@ root = \"fabro/\" eprintln!( " {} {}", green.apply_to("✔"), - dim.apply_to("arc/workflows/hello/workflow.fabro") + dim.apply_to("fabro/workflows/hello/workflow.fabro") ); // Create workflow.toml @@ -92,7 +92,7 @@ root = \"fabro/\" eprintln!( " {} {}", green.apply_to("✔"), - dim.apply_to("arc/workflows/hello/workflow.toml") + dim.apply_to("fabro/workflows/hello/workflow.toml") ); eprintln!( diff --git a/lib/crates/fabro-workflows/src/cli/pr.rs b/lib/crates/fabro-workflows/src/cli/pr.rs index d60a8e7d5..3b89a82ce 100644 --- a/lib/crates/fabro-workflows/src/cli/pr.rs +++ b/lib/crates/fabro-workflows/src/cli/pr.rs @@ -449,7 +449,7 @@ mod tests { owner: "owner".to_string(), repo: "repo".to_string(), base_branch: "main".to_string(), - head_branch: "arc/run/abc".to_string(), + head_branch: "fabro/run/abc".to_string(), title: "Fix the thing".to_string(), }; fs::write( @@ -544,7 +544,7 @@ mod tests { owner: "owner".to_string(), repo: "repo".to_string(), base_branch: "main".to_string(), - head_branch: "arc/run/ccc".to_string(), + head_branch: "fabro/run/ccc".to_string(), title: "Another fix".to_string(), }; fs::write( @@ -690,7 +690,7 @@ mod tests { "start_time": "2026-01-01T12:00:00Z", "node_count": 1, "edge_count": 0, - "run_branch": "arc/run/abc123" + "run_branch": "fabro/run/abc123" }), None, Some("diff content"), @@ -718,7 +718,7 @@ mod tests { "start_time": "2026-01-01T12:00:00Z", "node_count": 1, "edge_count": 0, - "run_branch": "arc/run/abc123" + "run_branch": "fabro/run/abc123" }), Some(serde_json::json!({ "timestamp": "2026-01-01T12:01:00Z", @@ -781,7 +781,7 @@ mod tests { "start_time": "2026-01-01T12:00:00Z", "node_count": 1, "edge_count": 0, - "run_branch": "arc/run/abc123" + "run_branch": "fabro/run/abc123" }), Some(serde_json::json!({ "timestamp": "2026-01-01T12:01:00Z", @@ -813,7 +813,7 @@ mod tests { "start_time": "2026-01-01T12:00:00Z", "node_count": 1, "edge_count": 0, - "run_branch": "arc/run/abc123" + "run_branch": "fabro/run/abc123" }), Some(serde_json::json!({ "timestamp": "2026-01-01T12:01:00Z", @@ -845,7 +845,7 @@ mod tests { "start_time": "2026-01-01T12:00:00Z", "node_count": 1, "edge_count": 0, - "run_branch": "arc/run/abc123" + "run_branch": "fabro/run/abc123" }), Some(serde_json::json!({ "timestamp": "2026-01-01T12:01:00Z", diff --git a/lib/crates/fabro-workflows/src/cli/rewind.rs b/lib/crates/fabro-workflows/src/cli/rewind.rs index 75675644e..090436054 100644 --- a/lib/crates/fabro-workflows/src/cli/rewind.rs +++ b/lib/crates/fabro-workflows/src/cli/rewind.rs @@ -137,7 +137,7 @@ fn backfill_run_shas(store: &Store, run_id: &str, timeline: &mut [TimelineEntry] return; } - let run_branch = format!("arc/run/{run_id}"); + let run_branch = format!("{}{run_id}", crate::git::RUN_BRANCH_PREFIX); let sig = match Signature::now("Fabro", "noreply@fabro.sh") { Ok(s) => s, Err(_) => return, @@ -333,7 +333,7 @@ pub fn execute_rewind( ); // Move run branch ref - let run_branch = format!("arc/run/{run_id}"); + let run_branch = format!("{}{run_id}", crate::git::RUN_BRANCH_PREFIX); match &entry.run_commit_sha { Some(sha) => { let oid = @@ -341,7 +341,11 @@ pub fn execute_rewind( store .update_ref(&run_branch, oid) .map_err(|e| anyhow::anyhow!("failed to update run branch ref: {e}"))?; - eprintln!("Rewound run branch arc/run/{run_id} to {}", &sha[..8]); + eprintln!( + "Rewound run branch {}{run_id} to {}", + crate::git::RUN_BRANCH_PREFIX, + &sha[..8] + ); } None => { eprintln!( @@ -442,7 +446,11 @@ pub fn rewind_command(args: &RewindArgs, styles: &Styles) -> Result<()> { execute_rewind(&store, &run_id, entry, !args.no_push)?; - eprintln!("\nTo resume: fabro run --run-branch arc/run/{}", run_id); + eprintln!( + "\nTo resume: fabro run --run-branch {}{}", + crate::git::RUN_BRANCH_PREFIX, + run_id + ); Ok(()) } @@ -814,7 +822,7 @@ mod tests { let sig = test_sig(); // Create a run branch with some commits - let run_branch = "arc/run/run-2"; + let run_branch = "fabro/run/run-2"; let empty_tree = store.write_empty_tree().unwrap(); let run_c1 = store .write_commit(empty_tree, &[], "run commit 1", &sig) diff --git a/lib/crates/fabro-workflows/src/cli/run.rs b/lib/crates/fabro-workflows/src/cli/run.rs index aa64981cd..2af8a063d 100644 --- a/lib/crates/fabro-workflows/src/cli/run.rs +++ b/lib/crates/fabro-workflows/src/cli/run.rs @@ -1477,7 +1477,7 @@ fn setup_worktree( run_id: &str, ) -> anyhow::Result<(PathBuf, PathBuf, String, String)> { let base_sha = crate::git::head_sha(original_cwd).map_err(|e| anyhow::anyhow!("{e}"))?; - let branch_name = format!("arc/run/{run_id}"); + let branch_name = format!("{}{run_id}", crate::git::RUN_BRANCH_PREFIX); crate::git::create_branch(original_cwd, &branch_name).map_err(|e| anyhow::anyhow!("{e}"))?; let worktree_path = run_dir.join("worktree"); @@ -1525,7 +1525,7 @@ async fn setup_remote_git( } let base_sha = sha_result.stdout.trim().to_string(); - let branch_name = format!("arc/run/{run_id}"); + let branch_name = format!("{}{run_id}", crate::git::RUN_BRANCH_PREFIX); // Create and checkout a run branch let checkout_cmd = format!("git checkout -b {branch_name}"); @@ -1557,12 +1557,13 @@ async fn run_from_branch( run_defaults: RunDefaults, github_app: Option, ) -> anyhow::Result<()> { - // Extract run_id from branch name: "arc/run/{run_id}" -> "{run_id}" + // Extract run_id from branch name: "fabro/run/{run_id}" -> "{run_id}" let run_id = run_branch - .strip_prefix("arc/run/") + .strip_prefix(crate::git::RUN_BRANCH_PREFIX) .ok_or_else(|| { anyhow::anyhow!( - "invalid run branch format: expected 'arc/run/', got '{run_branch}'" + "invalid run branch format: expected '{}', got '{run_branch}'", + crate::git::RUN_BRANCH_PREFIX, ) })? .to_string(); diff --git a/lib/crates/fabro-workflows/src/daytona_sandbox.rs b/lib/crates/fabro-workflows/src/daytona_sandbox.rs index 9e08d24f7..ec302354e 100644 --- a/lib/crates/fabro-workflows/src/daytona_sandbox.rs +++ b/lib/crates/fabro-workflows/src/daytona_sandbox.rs @@ -162,7 +162,7 @@ pub struct DaytonaSandbox { run_id: Option, /// Explicit branch to clone. When set, overrides the branch detected by /// `detect_repo_info` — avoids cloning a local-only worktree branch - /// (e.g. `arc/run/...`) that was never pushed to origin. + /// (e.g. `fabro/run/...`) that was never pushed to origin. clone_branch: Option, } @@ -570,7 +570,7 @@ impl Sandbox for DaytonaSandbox { match detect_repo_info(&cwd) { Ok((detected_url, detected_branch)) => { // Use explicit clone_branch if provided (avoids cloning a local-only - // worktree branch like arc/run/... that hasn't been pushed). + // worktree branch like fabro/run/... that hasn't been pushed). let branch = self.clone_branch.clone().or(detected_branch); // Daytona clones over HTTPS with token auth, so rewrite SSH URLs. let url = ssh_url_to_https(&detected_url); diff --git a/lib/crates/fabro-workflows/src/engine.rs b/lib/crates/fabro-workflows/src/engine.rs index 3c9ab8dae..631852ed9 100644 --- a/lib/crates/fabro-workflows/src/engine.rs +++ b/lib/crates/fabro-workflows/src/engine.rs @@ -764,7 +764,7 @@ pub struct RunConfig { pub host_repo_path: Option, /// SHA of the commit the worktree branched from. pub base_sha: Option, - /// Git branch name for the run (e.g. `arc/run/{run_id}`). + /// Git branch name for the run (e.g. `fabro/run/{run_id}`). pub run_branch: Option, /// Metadata branch name for git-native checkpoint storage (e.g. `refs/fabro/{run_id}`). pub meta_branch: Option, diff --git a/lib/crates/fabro-workflows/src/git.rs b/lib/crates/fabro-workflows/src/git.rs index a608fb231..562e7b348 100644 --- a/lib/crates/fabro-workflows/src/git.rs +++ b/lib/crates/fabro-workflows/src/git.rs @@ -8,6 +8,9 @@ use git2::{Repository, Signature}; use crate::checkpoint::Checkpoint; use crate::error::{FabroError, Result}; +/// Branch prefix for workflow run branches (e.g. `fabro/run/{run_id}`). +pub const RUN_BRANCH_PREFIX: &str = "fabro/run/"; + /// Resolved git author identity for checkpoint commits. #[derive(Debug, Clone, PartialEq)] pub struct GitAuthor { @@ -340,7 +343,7 @@ pub fn scan_node_files(run_dir: &Path) -> Vec<(String, Vec)> { /// Git-native metadata storage for pipeline runs. /// /// Stores checkpoint data, manifests, and graph DOT on an orphan branch -/// (`arc/{run_id}`) so that runs can be resumed from git alone. +/// (`fabro/{run_id}`) so that runs can be resumed from git alone. pub struct MetadataStore { repo_path: std::path::PathBuf, author: GitAuthor, diff --git a/lib/crates/fabro-workflows/src/handler/parallel.rs b/lib/crates/fabro-workflows/src/handler/parallel.rs index 91a0c59c4..8ecc3cc1e 100644 --- a/lib/crates/fabro-workflows/src/handler/parallel.rs +++ b/lib/crates/fabro-workflows/src/handler/parallel.rs @@ -294,7 +294,7 @@ impl Handler for ParallelHandler { let branch_key = &target_id; let visit = crate::engine::visit_from_context(&branch_context); let branch_name = format!( - "arc/run/parallel/{}/{}/pass{}/{}", + "fabro/run/parallel/{}/{}/pass{}/{}", gs.run_id, crate::git::sanitize_ref_component(&node.id), visit, diff --git a/lib/crates/fabro-workflows/src/pull_request.rs b/lib/crates/fabro-workflows/src/pull_request.rs index 62fe4e57f..a8f0edf31 100644 --- a/lib/crates/fabro-workflows/src/pull_request.rs +++ b/lib/crates/fabro-workflows/src/pull_request.rs @@ -861,7 +861,7 @@ mod tests { owner: "owner".to_string(), repo: "repo".to_string(), base_branch: "main".to_string(), - head_branch: "arc/run/abc".to_string(), + head_branch: "fabro/run/abc".to_string(), title: "Fix the thing".to_string(), }; record.save(&path).unwrap(); @@ -873,7 +873,7 @@ mod tests { assert_eq!(content["owner"], "owner"); assert_eq!(content["repo"], "repo"); assert_eq!(content["base_branch"], "main"); - assert_eq!(content["head_branch"], "arc/run/abc"); + assert_eq!(content["head_branch"], "fabro/run/abc"); assert_eq!(content["title"], "Fix the thing"); } @@ -888,7 +888,7 @@ mod tests { &creds, "https://github.com/owner/repo.git", "main", - "arc/run/123", + "fabro/run/123", "Fix bug", "", "claude-sonnet-4-20250514", diff --git a/lib/crates/fabro-workflows/tests/daytona_integration.rs b/lib/crates/fabro-workflows/tests/daytona_integration.rs index f33507048..6b7d12b8f 100644 --- a/lib/crates/fabro-workflows/tests/daytona_integration.rs +++ b/lib/crates/fabro-workflows/tests/daytona_integration.rs @@ -492,7 +492,7 @@ async fn setup_daytona_git(sandbox: &dyn Sandbox) -> (String, String, String) { let base_sha = sha_result.stdout.trim().to_string(); let run_id = ulid::Ulid::new().to_string(); - let branch_name = format!("arc/run/{run_id}"); + let branch_name = format!("fabro/run/{run_id}"); let checkout_cmd = format!("git checkout -b {branch_name}"); let checkout_result = sandbox diff --git a/lib/crates/fabro-workflows/tests/integration.rs b/lib/crates/fabro-workflows/tests/integration.rs index d7d024ec0..b520e029a 100644 --- a/lib/crates/fabro-workflows/tests/integration.rs +++ b/lib/crates/fabro-workflows/tests/integration.rs @@ -10632,7 +10632,7 @@ async fn git_checkpoint_host_emits_events_and_diff_patch() { String::from_utf8_lossy(&out.stdout).trim().to_string() }; std::process::Command::new("git") - .args(["branch", "arc/run/test-docker", "HEAD"]) + .args(["branch", "fabro/run/test-docker", "HEAD"]) .current_dir(repo.path()) .output() .unwrap(); @@ -10640,7 +10640,7 @@ async fn git_checkpoint_host_emits_events_and_diff_patch() { std::process::Command::new("git") .args(["worktree", "add"]) .arg(&worktree_path) - .arg("arc/run/test-docker") + .arg("fabro/run/test-docker") .current_dir(repo.path()) .output() .unwrap(); @@ -10693,7 +10693,7 @@ async fn git_checkpoint_host_emits_events_and_diff_patch() { git_checkpoint_enabled: true, host_repo_path: Some(worktree_path.clone()), base_sha: Some(base_sha.clone()), - run_branch: Some("arc/run/test-docker".to_string()), + run_branch: Some("fabro/run/test-docker".to_string()), meta_branch: None, labels: std::collections::HashMap::new(), checkpoint_exclude_globs: Vec::new(), @@ -10822,7 +10822,7 @@ async fn git_checkpoint_host_writes_shadow_branch() { String::from_utf8_lossy(&out.stdout).trim().to_string() }; std::process::Command::new("git") - .args(["branch", &format!("arc/run/{run_id}"), "HEAD"]) + .args(["branch", &format!("fabro/run/{run_id}"), "HEAD"]) .current_dir(repo.path()) .output() .unwrap(); @@ -10830,7 +10830,7 @@ async fn git_checkpoint_host_writes_shadow_branch() { std::process::Command::new("git") .args(["worktree", "add"]) .arg(&worktree_path) - .arg(format!("arc/run/{run_id}")) + .arg(format!("fabro/run/{run_id}")) .current_dir(repo.path()) .output() .unwrap(); @@ -10885,7 +10885,7 @@ async fn git_checkpoint_host_writes_shadow_branch() { git_checkpoint_enabled: true, host_repo_path: Some(worktree_path.clone()), base_sha: Some(base_sha), - run_branch: Some(format!("arc/run/{run_id}")), + run_branch: Some(format!("fabro/run/{run_id}")), meta_branch: Some(meta_branch), labels: std::collections::HashMap::new(), checkpoint_exclude_globs: Vec::new(), @@ -10995,7 +10995,7 @@ async fn parallel_git_branching_host_e2e() { String::from_utf8_lossy(&out.stdout).trim().to_string() }; let run_id = "par-git-test"; - let run_branch = format!("arc/run/{run_id}"); + let run_branch = format!("fabro/run/{run_id}"); std::process::Command::new("git") .args(["branch", &run_branch, "HEAD"]) .current_dir(repo.path()) @@ -11205,7 +11205,7 @@ async fn parallel_git_branching_host_e2e() { ); // 10. Verify parallel branch refs still exist (for debugging) - let branch_ref_a = format!("arc/run/parallel/{run_id}/fan-out/pass1/branch-a"); + let branch_ref_a = format!("fabro/run/parallel/{run_id}/fan-out/pass1/branch-a"); let ref_check = std::process::Command::new("git") .args(["rev-parse", "--verify", &branch_ref_a]) .current_dir(repo.path()) @@ -11292,7 +11292,7 @@ async fn git_checkpoint_host_skips_empty_diff_patch() { String::from_utf8_lossy(&out.stdout).trim().to_string() }; std::process::Command::new("git") - .args(["branch", "arc/run/empty-diff", "HEAD"]) + .args(["branch", "fabro/run/empty-diff", "HEAD"]) .current_dir(repo.path()) .output() .unwrap(); @@ -11300,7 +11300,7 @@ async fn git_checkpoint_host_skips_empty_diff_patch() { std::process::Command::new("git") .args(["worktree", "add"]) .arg(&worktree_path) - .arg("arc/run/empty-diff") + .arg("fabro/run/empty-diff") .current_dir(repo.path()) .output() .unwrap(); @@ -11350,7 +11350,7 @@ async fn git_checkpoint_host_skips_empty_diff_patch() { git_checkpoint_enabled: true, host_repo_path: Some(worktree_path.clone()), base_sha: Some(base_sha.clone()), - run_branch: Some("arc/run/empty-diff".to_string()), + run_branch: Some("fabro/run/empty-diff".to_string()), meta_branch: None, labels: std::collections::HashMap::new(), checkpoint_exclude_globs: Vec::new(),