Rename Arc to Fabro in user-facing strings, comments, and tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Bryan Helmkamp 2026-03-13 20:43:21 -04:00
parent 707c5fbfe3
commit 20bfbb939f
No known key found for this signature in database
20 changed files with 64 additions and 60 deletions

View file

@ -1,11 +1,11 @@
digraph Hello {
graph [goal="Say hello and demonstrate a basic arc workflow"]
graph [goal="Say hello and demonstrate a basic Fabro workflow"]
rankdir=LR
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
greet [label="Greet", prompt="Say hello! Introduce yourself and explain that this is a test of the arc workflow engine."]
greet [label="Greet", prompt="Say hello! Introduce yourself and explain that this is a test of the fabro workflow engine."]
start -> greet -> exit
}

View file

@ -160,7 +160,7 @@ pub async fn serve_command(args: ServeArgs, styles: &'static Styles) -> anyhow::
eprintln!(
"{}",
styles.bold.apply_to(format!(
"Arc server listening on {}",
"Fabro server listening on {}",
styles.cyan.apply_to(&addr)
)),
);

View file

@ -565,7 +565,7 @@ pub fn check_api(status: &ApiStatus, live_result: Option<&Result<(), String>>) -
);
CheckResult {
name: "Arc API".to_string(),
name: "Fabro API".to_string(),
status: check_status,
summary: status.base_url.clone(),
details,
@ -609,7 +609,7 @@ pub fn check_web(status: &WebStatus, live_result: Option<&Result<(), String>>) -
);
CheckResult {
name: "Arc Web".to_string(),
name: "Fabro Web".to_string(),
status: check_status,
summary: status.url.clone(),
details,

View file

@ -63,13 +63,13 @@ root = \"fabro/\"
std::fs::write(
&dot_path,
r#"digraph Hello {
graph [goal="Say hello and demonstrate a basic arc workflow"]
graph [goal="Say hello and demonstrate a basic Fabro workflow"]
rankdir=LR
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
greet [label="Greet", prompt="Say hello! Introduce yourself and explain that this is a test of the arc workflow engine."]
greet [label="Greet", prompt="Say hello! Introduce yourself and explain that this is a test of the Fabro workflow engine."]
start -> greet -> exit
}
@ -101,7 +101,7 @@ root = \"fabro/\"
console::Style::new()
.cyan()
.bold()
.apply_to("arc run hello")
.apply_to("fabro run hello")
);
check_github_app_installation().await;
@ -126,7 +126,7 @@ async fn check_github_app_installation() {
eprintln!(
" {}",
dim.apply_to(
"Run `git remote add origin <url>` then `arc install` to set up the GitHub App"
"Run `git remote add origin <url>` then `fabro install` to set up the GitHub App"
)
);
return;
@ -156,7 +156,10 @@ async fn check_github_app_installation() {
None => {
eprintln!(
"\n Run {} to set up the GitHub App",
console::Style::new().cyan().bold().apply_to("arc install")
console::Style::new()
.cyan()
.bold()
.apply_to("fabro install")
);
return;
}

View file

@ -116,7 +116,7 @@ fn generate_mtls_certs(dir: &Path) -> Result<()> {
"-days",
"3650",
"-subj",
"/CN=Arc CA",
"/CN=Fabro CA",
],
"generate CA cert",
)?;
@ -426,7 +426,7 @@ async fn setup_github_app(arc_dir: &Path, s: &Styles) -> Result<Vec<(String, Str
<html>
<head>
<meta charset="utf-8">
<title>Arc Setup</title>
<title>Fabro Setup</title>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0; background: #f6f8fa; color: #1f2328; }
.card { text-align: center; background: #fff; border: 1px solid #d1d9e0; border-radius: 12px; padding: 48px; max-width: 420px; }
@ -883,7 +883,7 @@ pub async fn run_install() -> Result<()> {
eprintln!(" To start Arc, run these commands:");
eprintln!();
eprintln!(" arc serve");
eprintln!(" fabro serve");
eprintln!(" cd apps/fabro-web && npx react-router dev");
eprintln!();
}
@ -891,7 +891,8 @@ pub async fn run_install() -> Result<()> {
// Verify setup
let env_path = arc_dir.join(".env");
let run_doctor =
tokio::task::spawn_blocking(|| prompt_confirm("Run arc doctor to verify?", true)).await??;
tokio::task::spawn_blocking(|| prompt_confirm("Run fabro doctor to verify?", true))
.await??;
if run_doctor {
// Reload .env so doctor sees the values we just wrote
@ -903,7 +904,7 @@ pub async fn run_install() -> Result<()> {
eprintln!();
eprintln!(
" Setup complete! Go to your project and run {} to get started.",
s.bold_cyan.apply_to("arc init")
s.bold_cyan.apply_to("fabro init")
);
Ok(())
}

View file

@ -99,9 +99,9 @@ enum Command {
#[arg(long)]
dry_run: bool,
},
/// Initialize a new arc project
/// Initialize a new project
Init,
/// Set up the Arc environment (LLMs, certs, GitHub)
/// Set up the Fabro environment (LLMs, certs, GitHub)
Install,
/// List workflow runs
#[command(hide = true)]
@ -457,7 +457,7 @@ async fn main_inner() -> (String, Result<()>) {
vec![],
);
client.register_provider(adapter).await.map_err(|e| {
anyhow::anyhow!("Failed to register arc server adapter: {e}")
anyhow::anyhow!("Failed to register fabro server adapter: {e}")
})?;
fabro_agent::cli::run_with_args_and_client(
args,

View file

@ -153,7 +153,7 @@ impl ExeSandbox {
}
/// Create an `ExeSandbox` from a pre-connected data-plane SSH runner.
/// Used for reconnection (e.g. `arc cp`) when the VM already exists.
/// Used for reconnection (e.g. `fabro cp`) when the VM already exists.
pub fn from_existing(data_ssh: Box<dyn SshRunner>) -> Self {
let data_cell = tokio::sync::OnceCell::new();
let _ = data_cell.set(data_ssh);

View file

@ -4,7 +4,7 @@ use crate::providers::common::LineReader;
use crate::types::{FinishReason, Message, Request, Response, StreamEvent, Usage};
use tracing::{debug, error};
/// Provider adapter that routes LLM requests through an arc server's
/// Provider adapter that routes LLM requests through an fabro server's
/// `/completions` endpoint, delegating to whatever real provider the server
/// is configured with.
pub struct Adapter {
@ -91,12 +91,12 @@ async fn send_request(
})?;
let status = http_resp.status();
debug!(status = %status, "Arc server response received");
debug!(status = %status, "Fabro server response received");
if !status.is_success() {
let status_code = status.as_u16();
let body = http_resp.text().await.unwrap_or_default();
error!(status = %status_code, body = %body, "Arc server request failed");
error!(status = %status_code, body = %body, "Fabro server request failed");
return Err(error_from_status_code(
status_code,
body,
@ -122,7 +122,7 @@ impl ProviderAdapter for Adapter {
async fn complete(&self, request: &Request) -> Result<Response, SdkError> {
let url = format!("{}/completions", self.base_url);
debug!(base_url = %url, provider = %self.provider_name, "Sending completion to arc server");
debug!(base_url = %url, provider = %self.provider_name, "Sending completion to fabro server");
let body = build_body(request, false)?;
let http_resp = send_request(&self.client, &url, &body, &self.provider_name).await?;
@ -159,7 +159,7 @@ impl ProviderAdapter for Adapter {
async fn stream(&self, request: &Request) -> Result<StreamEventStream, SdkError> {
let url = format!("{}/completions", self.base_url);
debug!(base_url = %url, provider = %self.provider_name, "Sending completion to arc server");
debug!(base_url = %url, provider = %self.provider_name, "Sending completion to fabro server");
let body = build_body(request, true)?;
let http_resp = send_request(&self.client, &url, &body, &self.provider_name).await?;

View file

@ -106,7 +106,7 @@ impl SshSandbox {
}
/// Create an `SshSandbox` from a pre-connected SSH runner.
/// Used for reconnection (e.g. `arc cp`) when the host is already known.
/// Used for reconnection (e.g. `fabro cp`) when the host is already known.
pub fn from_existing(ssh: Box<dyn SshRunner>, config: SshConfig) -> Self {
let ssh_cell = tokio::sync::OnceCell::new();
let _ = ssh_cell.set(ssh);

View file

@ -84,7 +84,7 @@ mod tests {
#[test]
fn repository_identifier_returns_hash_in_arc_repo() {
// We're running inside the arc repo, so this should return a real hash
// We're running inside the fabro repo, so this should return a real hash
let id = repository_identifier();
assert_ne!(id, "no_repo");
assert_ne!(id, "no_remote");

View file

@ -7,7 +7,7 @@ const SEGMENT_API_URL: &str = "https://api.segment.io/v1/track";
const SEGMENT_WRITE_KEY: Option<&str> = option_env!("SEGMENT_WRITE_KEY");
/// Serializes the track event to a temp file and spawns a detached subprocess
/// (`arc __send_analytics <path>`) to deliver it. This ensures the event is
/// (`fabro __send_analytics <path>`) to deliver it. This ensures the event is
/// sent even if the parent CLI process exits immediately.
///
/// No-ops if the SEGMENT_WRITE_KEY was not set at compile time.

View file

@ -53,7 +53,7 @@ fn load_pr_record(base: &Path, run_id: &str) -> Result<(PullRequestRecord, PathB
let content = std::fs::read_to_string(&pr_path).with_context(|| {
format!(
"No pull_request.json found in run directory. \
Create one first with: arc pr create {run_id}"
Create one first with: fabro pr create {run_id}"
)
})?;
let record: PullRequestRecord =
@ -495,7 +495,7 @@ mod tests {
let err = load_pr_record(tmp.path(), "abc123").unwrap_err();
let msg = err.to_string();
assert!(msg.contains("pull_request.json"), "got: {msg}");
assert!(msg.contains("arc pr create"), "got: {msg}");
assert!(msg.contains("fabro pr create"), "got: {msg}");
}
#[test]

View file

@ -201,7 +201,7 @@ pub fn is_retro_enabled() -> bool {
}
}
/// Resolve the arc root directory from a config file path and its config.
/// Resolve the fabro root directory from a config file path and its config.
/// The returned path is the directory containing `fabro.toml` joined with the `root` value.
pub fn resolve_fabro_root(config_path: &Path, config: &ProjectConfig) -> PathBuf {
let project_dir = config_path

View file

@ -736,7 +736,7 @@ pub async fn run_command(
None
};
// Wrap emitter in Arc now so we can share it with exec env callbacks
// Wrap emitter in Fabro now so we can share it with exec env callbacks
let emitter = Arc::new(emitter);
let sandbox: Arc<dyn Sandbox> = match sandbox_provider {
@ -830,7 +830,7 @@ pub async fn run_command(
.expect("progress lock poisoned")
.set_working_directory(sandbox.working_directory().to_string());
// Persist sandbox connection info for `arc cp`
// Persist sandbox connection info for `fabro cp`
{
let sandbox_info_opt = {
let info = sandbox.sandbox_info();
@ -1192,7 +1192,7 @@ pub async fn run_command(
};
let run_duration_ms = run_start.elapsed().as_millis() as u64;
// Restore cwd (worktree is kept for `arc cp` access; pruned separately)
// Restore cwd (worktree is kept for `fabro cp` access; pruned separately)
let _ = std::env::set_current_dir(&original_cwd);
{
@ -1790,7 +1790,7 @@ async fn run_from_branch(
.await;
let run_duration_ms = run_start.elapsed().as_millis() as u64;
// Restore cwd (worktree is kept for `arc cp` access; pruned separately)
// Restore cwd (worktree is kept for `fabro cp` access; pruned separately)
let _ = std::env::set_current_dir(&original_cwd);
let _ = sandbox.cleanup().await;

View file

@ -578,7 +578,7 @@ provider = "daytona"
auto_stop_interval = 60
[sandbox.daytona.labels]
project = "arc"
project = "fabro"
[sandbox.daytona.snapshot]
name = "my-snapshot"
@ -594,7 +594,7 @@ dockerfile = "FROM rust:1.85-slim-bookworm\nRUN apt-get update"
let daytona = sandbox.daytona.unwrap();
assert_eq!(daytona.auto_stop_interval, Some(60));
let labels = daytona.labels.unwrap();
assert_eq!(labels["project"], "arc");
assert_eq!(labels["project"], "fabro");
let snapshot = daytona.snapshot.unwrap();
assert_eq!(snapshot.name, "my-snapshot");
@ -1234,7 +1234,7 @@ goal = "test"
graph = "w.dot"
[sandbox.daytona.labels]
project = "arc"
project = "fabro"
env = "from_task"
"#,
)
@ -1261,7 +1261,7 @@ env = "from_task"
};
cfg.apply_defaults(&defaults);
let labels = cfg.sandbox.unwrap().daytona.unwrap().labels.unwrap();
assert_eq!(labels["project"], "arc");
assert_eq!(labels["project"], "fabro");
assert_eq!(labels["team"], "platform");
assert_eq!(labels["env"], "from_task");
}

View file

@ -189,7 +189,7 @@ impl DaytonaSandbox {
}
/// Create a `DaytonaSandbox` from an already-existing Daytona SDK sandbox.
/// Used for reconnection (e.g. `arc cp`).
/// Used for reconnection (e.g. `fabro cp`).
#[must_use]
pub fn from_existing(client: daytona_sdk::Client, sdk_sandbox: daytona_sdk::Sandbox) -> Self {
let sandbox_cell = tokio::sync::OnceCell::new();
@ -694,7 +694,7 @@ impl Sandbox for DaytonaSandbox {
Err(e) if self.github_app.is_none() => {
let err = format!(
"Git clone failed: {e}. If this is a private repository, \
configure a GitHub App with `arc install` and install it \
configure a GitHub App with `fabro install` and install it \
for your organization."
);
self.emit(SandboxEvent::GitCloneFailed {

View file

@ -117,13 +117,13 @@ fn format_retro_section(retro: &Retro) -> String {
parts.join("\n")
}
/// Format the Arc Details section of the PR body.
/// Format the Fabro Details section of the PR body.
///
/// Renders a cost/duration table in a collapsible `<details>` block, and
/// optionally a DOT graph in another `<details>` block.
fn format_arc_details_section(conclusion: &Conclusion, dot_source: Option<&str>) -> String {
let mut parts = Vec::new();
parts.push("### Arc Details".to_string());
parts.push("### Fabro Details".to_string());
parts.push(String::new());
// Cost table
@ -263,7 +263,7 @@ fn assemble_pr_body(
}
/// Build a complete PR body by combining LLM-generated narrative with
/// programmatic sections (plan, retro, arc details).
/// programmatic sections (plan, retro, fabro details).
pub async fn build_pr_body(
diff: &str,
goal: &str,
@ -569,7 +569,7 @@ mod tests {
let conclusion = make_test_conclusion();
let section = format_arc_details_section(&conclusion, None);
assert!(section.contains("### Arc Details"));
assert!(section.contains("### Fabro Details"));
assert!(section.contains("Ran 3 stages in 2m 30s for $0.42"));
assert!(section.contains("| plan | 45s | $0.12 | 0 |"));
assert!(section.contains("| implement | 1m 30s | $0.25 | 0 |"));
@ -652,7 +652,7 @@ mod tests {
"This is the narrative.\n\n### Plan Summary\n\n* Step 1\n* Step 2",
Some("Full plan text here"),
"### Retro\n\n* 3 stages completed",
"### Arc Details\n\n<details>...</details>",
"### Fabro Details\n\n<details>...</details>",
);
assert!(body.contains("This is the narrative."));
@ -660,7 +660,7 @@ mod tests {
assert!(body.contains("<details>\n<summary>Full plan</summary>"));
assert!(body.contains("````md\nFull plan text here\n````"));
assert!(body.contains("### Retro"));
assert!(body.contains("### Arc Details"));
assert!(body.contains("### Fabro Details"));
}
#[test]
@ -669,13 +669,13 @@ mod tests {
"Narrative only.",
None,
"### Retro\n\n* stats",
"### Arc Details\n\n<details>...</details>",
"### Fabro Details\n\n<details>...</details>",
);
assert!(body.contains("Narrative only."));
assert!(!body.contains("Full plan"));
assert!(body.contains("### Retro"));
assert!(body.contains("### Arc Details"));
assert!(body.contains("### Fabro Details"));
}
#[test]
@ -686,7 +686,7 @@ mod tests {
assert!(body.contains("Full plan"));
// Empty sections should not produce extra headers
assert!(!body.contains("### Retro"));
assert!(!body.contains("### Arc Details"));
assert!(!body.contains("### Fabro Details"));
}
#[test]
@ -705,7 +705,7 @@ mod tests {
let arc_details = format_arc_details_section(&conclusion, None);
let body = assemble_pr_body("Narrative.", None, "", &arc_details);
assert!(body.contains("### Arc Details"));
assert!(body.contains("### Fabro Details"));
assert!(body.contains("Ran 3 stages"));
assert!(!body.contains("### Retro"));
}
@ -719,7 +719,7 @@ mod tests {
let body = assemble_pr_body("Narrative.", None, &retro_section, &arc_details);
assert!(body.contains("### Retro"));
assert!(body.contains("### Arc Details"));
assert!(body.contains("### Fabro Details"));
}
// ── parse_dot_summary tests ─────────────────────────────────────────

View file

@ -935,12 +935,12 @@ impl LintRule for StylesheetModelKnownRule {
rule: self.name().to_string(),
severity: Severity::Warning,
message: format!(
"Unknown model '{}' in stylesheet rule '{label}'. Run `arc model list` to see available models",
"Unknown model '{}' in stylesheet rule '{label}'. Run `fabro model list` to see available models",
decl.value
),
node_id: None,
edge: None,
fix: Some("Use a model ID from `arc model list`".to_string()),
fix: Some("Use a model ID from `fabro model list`".to_string()),
});
}
}

View file

@ -1,4 +1,4 @@
//! E2E tests for `arc cp` against local and Docker sandbox backends.
//! E2E tests for `fabro cp` against local and Docker sandbox backends.
//!
//! Local tests run without `#[ignore]` (no external dependencies).
//! Docker tests require a Docker daemon and are marked `#[ignore]`.

View file

@ -1419,7 +1419,7 @@ async fn daytona_clone_private_repo_with_github_app_iat() {
);
}
// Verify this is actually the arc repo
// Verify this is actually the fabro repo
let result = env
.exec_command("git remote get-url origin", 10_000, None, None, None)
.await
@ -1441,7 +1441,7 @@ async fn daytona_clone_public_repo_gets_credentials() {
let creds = load_github_app_credentials();
// Directly test resolve_clone_credentials against a repo in an org where the app is installed
let (username, password) = fabro_github::resolve_clone_credentials(&creds, "brynary", "arc")
let (username, password) = fabro_github::resolve_clone_credentials(&creds, "fabro-sh", "fabro")
.await
.unwrap();
@ -1749,7 +1749,7 @@ async fn daytona_toolbox_idle_diagnostic() {
env.cleanup().await.unwrap();
}
/// E2E test for `arc cp` against a live Daytona sandbox.
/// E2E test for `fabro cp` against a live Daytona sandbox.
///
/// Creates a sandbox, saves a SandboxRecord, reconnects via `cp::reconnect`,
/// uploads a file, downloads it back, and verifies the round-trip.
@ -1769,7 +1769,7 @@ async fn daytona_cp_upload_download_round_trip() {
"sandbox_info() should return the Daytona sandbox name"
);
// 2. Build a SandboxRecord (same as `arc run` would persist)
// 2. Build a SandboxRecord (same as `fabro run` would persist)
let record = SandboxRecord {
provider: "daytona".to_string(),
working_directory: env.working_directory().to_string(),
@ -1791,7 +1791,7 @@ async fn daytona_cp_upload_download_round_trip() {
let reconnected = reconnect(&loaded).await.expect("reconnect should succeed");
// 5. Upload: write a local file, then upload it to the sandbox
let upload_content = b"hello from arc cp e2e test\n";
let upload_content = b"hello from fabro cp e2e test\n";
let local_upload = tmp.path().join("upload.txt");
std::fs::write(&local_upload, upload_content).unwrap();
@ -1810,7 +1810,7 @@ async fn daytona_cp_upload_download_round_trip() {
.await
.unwrap();
assert!(
remote_content.contains("hello from arc cp e2e test"),
remote_content.contains("hello from fabro cp e2e test"),
"expected uploaded content in sandbox, got: {remote_content}"
);