diff --git a/lib/crates/fabro-agent/src/agent_profile.rs b/lib/crates/fabro-agent/src/agent_profile.rs index 160424932..f717ded39 100644 --- a/lib/crates/fabro-agent/src/agent_profile.rs +++ b/lib/crates/fabro-agent/src/agent_profile.rs @@ -2,8 +2,8 @@ use crate::profiles::EnvContext; use crate::sandbox::Sandbox; use crate::skills::Skill; use crate::subagent::{ - make_close_agent_tool, make_send_input_tool, make_spawn_agent_tool, make_wait_tool, - SessionFactory, SubAgentManager, + SessionFactory, SubAgentManager, make_close_agent_tool, make_send_input_tool, + make_spawn_agent_tool, make_wait_tool, }; use crate::tool_registry::ToolRegistry; use fabro_llm::types::ToolDefinition; diff --git a/lib/crates/fabro-agent/src/cli.rs b/lib/crates/fabro-agent/src/cli.rs index 366376c4b..f6a0581fc 100644 --- a/lib/crates/fabro-agent/src/cli.rs +++ b/lib/crates/fabro-agent/src/cli.rs @@ -3,9 +3,9 @@ use crate::error::AbortReason; use crate::tools::WebFetchSummarizer; use crate::truncation; use crate::{ - subagent::{SessionFactory, SubAgentManager}, AgentEvent, AgentProfile, AnthropicProfile, GeminiProfile, LocalSandbox, OpenAiProfile, Sandbox, Session, SessionConfig, Turn, + subagent::{SessionFactory, SubAgentManager}, }; use clap::{Args, Parser}; use fabro_llm::client::Client; diff --git a/lib/crates/fabro-agent/src/lib.rs b/lib/crates/fabro-agent/src/lib.rs index 8744c13d2..96910227f 100644 --- a/lib/crates/fabro-agent/src/lib.rs +++ b/lib/crates/fabro-agent/src/lib.rs @@ -40,8 +40,8 @@ pub use memory::discover_memory; pub use profiles::{AnthropicProfile, EnvContext, GeminiProfile, OpenAiProfile}; pub use read_before_write_sandbox::ReadBeforeWriteSandbox; pub use sandbox::{ - format_lines_numbered, shell_quote, DirEntry, ExecResult, GrepOptions, Sandbox, SandboxEvent, - SandboxEventCallback, WorktreeConfig, WorktreeEvent, WorktreeEventCallback, WorktreeSandbox, + DirEntry, ExecResult, GrepOptions, Sandbox, SandboxEvent, SandboxEventCallback, WorktreeConfig, + WorktreeEvent, WorktreeEventCallback, WorktreeSandbox, format_lines_numbered, shell_quote, }; pub use session::Session; pub use skills::Skill; @@ -50,11 +50,11 @@ pub use subagent::{ }; pub use tool_registry::ToolRegistry; pub use tools::{ - make_edit_file_tool, make_glob_tool, make_grep_tool, make_read_file_tool, make_shell_tool, - make_shell_tool_with_config, make_write_file_tool, register_core_tools, WebFetchSummarizer, + WebFetchSummarizer, make_edit_file_tool, make_glob_tool, make_grep_tool, make_read_file_tool, + make_shell_tool, make_shell_tool_with_config, make_write_file_tool, register_core_tools, }; pub use truncation::{ - floor_char_boundary, truncate_lines, truncate_output, truncate_tool_output, TruncationMode, + TruncationMode, floor_char_boundary, truncate_lines, truncate_output, truncate_tool_output, }; pub use types::{AgentEvent, SessionEvent, SessionState, Turn}; diff --git a/lib/crates/fabro-agent/src/mcp_integration.rs b/lib/crates/fabro-agent/src/mcp_integration.rs index 29c90a830..51bebae86 100644 --- a/lib/crates/fabro-agent/src/mcp_integration.rs +++ b/lib/crates/fabro-agent/src/mcp_integration.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use fabro_llm::types::ToolDefinition; -use fabro_mcp::connection_manager::{call_result_to_string, McpConnectionManager}; +use fabro_mcp::connection_manager::{McpConnectionManager, call_result_to_string}; use crate::tool_registry::RegisteredTool; diff --git a/lib/crates/fabro-agent/src/profiles/anthropic.rs b/lib/crates/fabro-agent/src/profiles/anthropic.rs index f37abe76d..ddb0152a5 100644 --- a/lib/crates/fabro-agent/src/profiles/anthropic.rs +++ b/lib/crates/fabro-agent/src/profiles/anthropic.rs @@ -1,11 +1,11 @@ use crate::agent_profile::AgentProfile; use crate::config::SessionConfig; -use crate::profiles::assemble_system_prompt; use crate::profiles::BaseProfile; +use crate::profiles::assemble_system_prompt; use crate::sandbox::Sandbox; use crate::skills::Skill; use crate::tool_registry::ToolRegistry; -use crate::tools::{make_edit_file_tool, register_core_tools, WebFetchSummarizer}; +use crate::tools::{WebFetchSummarizer, make_edit_file_tool, register_core_tools}; use fabro_model::Provider; use super::EnvContext; diff --git a/lib/crates/fabro-agent/src/profiles/gemini.rs b/lib/crates/fabro-agent/src/profiles/gemini.rs index f9a47d6a4..0dd2e652e 100644 --- a/lib/crates/fabro-agent/src/profiles/gemini.rs +++ b/lib/crates/fabro-agent/src/profiles/gemini.rs @@ -1,13 +1,13 @@ use crate::agent_profile::AgentProfile; use crate::config::SessionConfig; -use crate::profiles::assemble_system_prompt; use crate::profiles::BaseProfile; +use crate::profiles::assemble_system_prompt; use crate::sandbox::Sandbox; use crate::skills::Skill; use crate::tool_registry::ToolRegistry; use crate::tools::{ - make_edit_file_tool, make_list_dir_tool, make_read_many_files_tool, register_core_tools, - WebFetchSummarizer, + WebFetchSummarizer, make_edit_file_tool, make_list_dir_tool, make_read_many_files_tool, + register_core_tools, }; use fabro_model::Provider; diff --git a/lib/crates/fabro-agent/src/profiles/mod.rs b/lib/crates/fabro-agent/src/profiles/mod.rs index 283b00112..742099aa0 100644 --- a/lib/crates/fabro-agent/src/profiles/mod.rs +++ b/lib/crates/fabro-agent/src/profiles/mod.rs @@ -7,7 +7,7 @@ pub use gemini::GeminiProfile; pub use openai::OpenAiProfile; use crate::sandbox::Sandbox; -use crate::skills::{format_skills_prompt_section, Skill}; +use crate::skills::{Skill, format_skills_prompt_section}; use crate::tool_registry::ToolRegistry; use fabro_model::Provider; diff --git a/lib/crates/fabro-agent/src/profiles/openai.rs b/lib/crates/fabro-agent/src/profiles/openai.rs index 7ddc4384b..8113ea4ea 100644 --- a/lib/crates/fabro-agent/src/profiles/openai.rs +++ b/lib/crates/fabro-agent/src/profiles/openai.rs @@ -1,11 +1,11 @@ use crate::agent_profile::AgentProfile; use crate::config::SessionConfig; -use crate::profiles::assemble_system_prompt; use crate::profiles::BaseProfile; +use crate::profiles::assemble_system_prompt; use crate::sandbox::Sandbox; use crate::skills::Skill; use crate::tool_registry::ToolRegistry; -use crate::tools::{register_core_tools, WebFetchSummarizer}; +use crate::tools::{WebFetchSummarizer, register_core_tools}; use crate::v4a_patch::make_apply_patch_tool; use fabro_model::Provider; diff --git a/lib/crates/fabro-agent/src/sandbox.rs b/lib/crates/fabro-agent/src/sandbox.rs index 706ec106c..9efecd005 100644 --- a/lib/crates/fabro-agent/src/sandbox.rs +++ b/lib/crates/fabro-agent/src/sandbox.rs @@ -1,7 +1,7 @@ // Re-export all sandbox types from fabro-sandbox. pub use fabro_sandbox::{ - format_lines_numbered, shell_quote, DirEntry, ExecResult, GrepOptions, Sandbox, SandboxEvent, - SandboxEventCallback, WorktreeConfig, WorktreeEvent, WorktreeEventCallback, WorktreeSandbox, + DirEntry, ExecResult, GrepOptions, Sandbox, SandboxEvent, SandboxEventCallback, WorktreeConfig, + WorktreeEvent, WorktreeEventCallback, WorktreeSandbox, format_lines_numbered, shell_quote, }; // Re-export the delegate_sandbox! macro at crate root so existing diff --git a/lib/crates/fabro-agent/src/session.rs b/lib/crates/fabro-agent/src/session.rs index e4f8ac08c..0adcb3a5e 100644 --- a/lib/crates/fabro-agent/src/session.rs +++ b/lib/crates/fabro-agent/src/session.rs @@ -11,7 +11,7 @@ use crate::memory::discover_memory; use crate::profiles::EnvContext; use crate::sandbox::Sandbox; use crate::skills::{ - default_skill_dirs, discover_skills, expand_skill, make_use_skill_tool, ExpandedInput, Skill, + ExpandedInput, Skill, default_skill_dirs, discover_skills, expand_skill, make_use_skill_tool, }; use crate::subagent::{SubAgentEventCallback, SubAgentManager}; use crate::tool_execution::execute_tool_calls; @@ -30,7 +30,7 @@ use futures::StreamExt; use std::collections::{HashMap, VecDeque}; use std::sync::{Arc, Mutex}; use std::time::SystemTime; -use tokio::sync::{broadcast, Mutex as AsyncMutex}; +use tokio::sync::{Mutex as AsyncMutex, broadcast}; use tokio::time; use tokio_util::sync::CancellationToken; use tracing::{debug, info, warn}; @@ -264,7 +264,9 @@ impl Session { info!(pid, port, "MCP server process launched in sandbox"); // Wait for the server to start listening on the port - let poll_cmd = format!("for i in $(seq 1 30); do ss -tln | grep -q ':{port} ' && echo ready && exit 0; sleep 1; done; echo timeout"); + let poll_cmd = format!( + "for i in $(seq 1 30); do ss -tln | grep -q ':{port} ' && echo ready && exit 0; sleep 1; done; echo timeout" + ); let poll_result = sandbox .exec_command(&poll_cmd, 60_000, None, None, None) .await @@ -781,7 +783,7 @@ impl Session { return Err(self.emit_llm_error(SdkError::Stream { message: "Stream ended without a Finish event (after retries)".into(), source: None, - })) + })); } }; @@ -983,8 +985,8 @@ mod tests { use fabro_llm::error::{ProviderErrorDetail, ProviderErrorKind}; use fabro_llm::provider::{ProviderAdapter, StreamEventStream}; use fabro_llm::types::{Request, Response, Role, StreamEvent, ToolDefinition}; - use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; + use std::sync::atomic::{AtomicUsize, Ordering}; #[derive(Clone)] enum ScriptedStreamCall { @@ -1244,18 +1246,26 @@ mod tests { events.push(event); } - assert!(events - .iter() - .any(|e| matches!(e.event, AgentEvent::SessionStarted))); - assert!(events - .iter() - .any(|e| matches!(e.event, AgentEvent::UserInput { .. }))); - assert!(events - .iter() - .any(|e| matches!(e.event, AgentEvent::AssistantMessage { .. }))); - assert!(events - .iter() - .any(|e| matches!(e.event, AgentEvent::SessionEnded))); + assert!( + events + .iter() + .any(|e| matches!(e.event, AgentEvent::SessionStarted)) + ); + assert!( + events + .iter() + .any(|e| matches!(e.event, AgentEvent::UserInput { .. })) + ); + assert!( + events + .iter() + .any(|e| matches!(e.event, AgentEvent::AssistantMessage { .. })) + ); + assert!( + events + .iter() + .any(|e| matches!(e.event, AgentEvent::SessionEnded)) + ); } #[tokio::test] diff --git a/lib/crates/fabro-agent/src/subagent.rs b/lib/crates/fabro-agent/src/subagent.rs index bbe8407c7..6b8105665 100644 --- a/lib/crates/fabro-agent/src/subagent.rs +++ b/lib/crates/fabro-agent/src/subagent.rs @@ -520,10 +520,12 @@ mod tests { let session = make_session(vec![text_response("Hello")]).await; let result = manager.spawn(session, "Do something".into(), 2); assert!(result.is_err()); - assert!(result - .unwrap_err() - .to_string() - .contains("Maximum subagent depth")); + assert!( + result + .unwrap_err() + .to_string() + .contains("Maximum subagent depth") + ); } #[tokio::test] @@ -674,9 +676,11 @@ mod tests { manager.close(&agent_id).unwrap(); let captured = events.lock().unwrap(); - assert!(captured - .iter() - .any(|e| matches!(e, AgentEvent::SubAgentClosed { depth: 2, .. }))); + assert!( + captured + .iter() + .any(|e| matches!(e, AgentEvent::SubAgentClosed { depth: 2, .. })) + ); } #[tokio::test] diff --git a/lib/crates/fabro-agent/src/tools.rs b/lib/crates/fabro-agent/src/tools.rs index a371e2c10..06c99cd78 100644 --- a/lib/crates/fabro-agent/src/tools.rs +++ b/lib/crates/fabro-agent/src/tools.rs @@ -1244,7 +1244,7 @@ mod tests { #[tokio::test] async fn web_fetch_prompt_with_summarizer_returns_llm_answer() { - use crate::test_support::{make_client, text_response, MockLlmProvider}; + use crate::test_support::{MockLlmProvider, make_client, text_response}; let provider = Arc::new(MockLlmProvider::new(vec![text_response( "Rust is a systems programming language focused on safety and performance.", @@ -1321,7 +1321,7 @@ mod tests { #[tokio::test] async fn web_fetch_summarizer_routes_to_specified_provider() { - use crate::test_support::{text_response, MockErrorProvider, MockLlmProvider}; + use crate::test_support::{MockErrorProvider, MockLlmProvider, text_response}; use fabro_llm::error::{ProviderErrorDetail, ProviderErrorKind, SdkError}; // "other_provider" is the default — it rejects all requests. diff --git a/lib/crates/fabro-agent/src/v4a_patch.rs b/lib/crates/fabro-agent/src/v4a_patch.rs index d90c4901d..750a82b3d 100644 --- a/lib/crates/fabro-agent/src/v4a_patch.rs +++ b/lib/crates/fabro-agent/src/v4a_patch.rs @@ -1,6 +1,6 @@ -use crate::sandbox::{format_lines_numbered, Sandbox}; +use crate::sandbox::{Sandbox, format_lines_numbered}; use crate::tool_registry::RegisteredTool; -use crate::truncation::{truncate_output, TruncationMode}; +use crate::truncation::{TruncationMode, truncate_output}; use fabro_llm::types::ToolDefinition; use std::sync::Arc; @@ -1310,10 +1310,11 @@ EOF"; assert!(result.contains("Moved file")); // Old path gone - assert!(env - .read_file("src/models/user.py", None, None) - .await - .is_err()); + assert!( + env.read_file("src/models/user.py", None, None) + .await + .is_err() + ); // New path has updated content let content = env @@ -1405,7 +1406,7 @@ def gamma(): use crate::config::SessionConfig; use crate::session::Session; use crate::test_support::{ - make_client, text_response, tool_call_response, MockLlmProvider, TestProfile, + MockLlmProvider, TestProfile, make_client, text_response, tool_call_response, }; use crate::tool_registry::ToolRegistry; diff --git a/lib/crates/fabro-api/src/demo/mod.rs b/lib/crates/fabro-api/src/demo/mod.rs index 4c33fef21..9cde66938 100644 --- a/lib/crates/fabro-api/src/demo/mod.rs +++ b/lib/crates/fabro-api/src/demo/mod.rs @@ -3,10 +3,10 @@ use std::sync::Arc; +use axum::Json; use axum::extract::{Path, Query, State}; use axum::http::StatusCode; use axum::response::{IntoResponse, Response}; -use axum::Json; use serde_json::json; use crate::error::ApiError; @@ -1966,53 +1966,81 @@ mod verifications { question: "Do we understand what this change is and why we're making it?", controls: &[ ControlDef { - name: "Motivation", slug: "motivation", + name: "Motivation", + slug: "motivation", description: "Origin of proposal identified", - type_: VerificationType::Ai, mode: VerificationMode::Active, - f1: Some(0.87), pass_at_1: Some(0.82), + type_: VerificationType::Ai, + mode: VerificationMode::Active, + f1: Some(0.87), + pass_at_1: Some(0.82), evaluations: &[P, P, F, P, P, P, P, F, P, P], run_status: VerificationResult::Pass, detail_description: "Verifies that every change traces back to a clear origin \u{2014} whether a ticket, RFC, customer request, or incident. Without documented motivation, reviewers lack context for evaluating whether the change is appropriate.", - checks: &["PR body or linked issue explains why the change is needed", "Commit messages reference a ticket or context", "No orphaned changes without traceable origin"], + checks: &[ + "PR body or linked issue explains why the change is needed", + "Commit messages reference a ticket or context", + "No orphaned changes without traceable origin", + ], pass_example: "PR links to JIRA-1234 and explains the user-facing pain point being resolved.", fail_example: "PR description is empty or says only 'fix stuff'.", recent_results: Some(MOTIVATION_RESULTS), }, ControlDef { - name: "Specifications", slug: "specifications", + name: "Specifications", + slug: "specifications", description: "Requirements written down", - type_: VerificationType::Ai, mode: VerificationMode::Active, - f1: Some(0.83), pass_at_1: Some(0.78), + type_: VerificationType::Ai, + mode: VerificationMode::Active, + f1: Some(0.83), + pass_at_1: Some(0.78), evaluations: &[P, F, P, P, P, F, P, P, P, P], run_status: VerificationResult::Pass, detail_description: "Checks that functional and non-functional requirements are written down before implementation begins. Specifications prevent scope creep and ensure everyone agrees on what done looks like.", - checks: &["Acceptance criteria listed in the issue or PR", "Edge cases documented", "Non-functional requirements (performance, security) stated when relevant"], + checks: &[ + "Acceptance criteria listed in the issue or PR", + "Edge cases documented", + "Non-functional requirements (performance, security) stated when relevant", + ], pass_example: "Issue includes acceptance criteria with three testable scenarios.", fail_example: "Issue body says 'implement the feature' with no acceptance criteria.", recent_results: None, }, ControlDef { - name: "Documentation", slug: "documentation", + name: "Documentation", + slug: "documentation", description: "Developer and user docs added", - type_: VerificationType::Ai, mode: VerificationMode::Active, - f1: Some(0.79), pass_at_1: Some(0.74), + type_: VerificationType::Ai, + mode: VerificationMode::Active, + f1: Some(0.79), + pass_at_1: Some(0.74), evaluations: &[P, P, P, F, P, P, F, P, P, F], run_status: VerificationResult::Pass, detail_description: "Ensures developer-facing and user-facing documentation is added or updated alongside code changes. Stale docs degrade team velocity and increase onboarding cost.", - checks: &["README or docs updated for new features", "API documentation reflects endpoint changes", "Inline comments for non-obvious logic"], + checks: &[ + "README or docs updated for new features", + "API documentation reflects endpoint changes", + "Inline comments for non-obvious logic", + ], pass_example: "New API endpoint has corresponding OpenAPI spec update and usage example in docs.", fail_example: "New CLI flag added with no mention in README or --help text.", recent_results: Some(DOCUMENTATION_RESULTS), }, ControlDef { - name: "Minimization", slug: "minimization", + name: "Minimization", + slug: "minimization", description: "No extraneous changes", - type_: VerificationType::Ai, mode: VerificationMode::Evaluate, - f1: Some(0.72), pass_at_1: Some(0.68), + type_: VerificationType::Ai, + mode: VerificationMode::Evaluate, + f1: Some(0.72), + pass_at_1: Some(0.68), evaluations: &[P, F, P, F, P, P, F, P, P, P], run_status: VerificationResult::Pass, detail_description: "Flags extraneous changes that inflate the diff \u{2014} formatting-only edits, unrelated refactors, or drive-by fixes. Keeping PRs focused improves review quality and reduces revert risk.", - checks: &["No unrelated formatting or whitespace changes", "Refactors separated from feature work", "Each commit addresses a single concern"], + checks: &[ + "No unrelated formatting or whitespace changes", + "Refactors separated from feature work", + "Each commit addresses a single concern", + ], pass_example: "PR touches only files directly related to the new caching layer.", fail_example: "PR adds a feature but also reformats 12 unrelated files.", recent_results: None, @@ -2024,40 +2052,60 @@ mod verifications { question: "Can a human or agent quickly read this and understand what it does?", controls: &[ ControlDef { - name: "Formatting", slug: "formatting", + name: "Formatting", + slug: "formatting", description: "Code layout matches standard", - type_: VerificationType::Automated, mode: VerificationMode::Active, - f1: Some(0.99), pass_at_1: Some(0.98), + type_: VerificationType::Automated, + mode: VerificationMode::Active, + f1: Some(0.99), + pass_at_1: Some(0.98), evaluations: &[P, P, P, P, P, P, P, P, P, P], run_status: VerificationResult::Pass, detail_description: "Validates that code layout conforms to the project's formatting standard (e.g., Prettier, rustfmt). Automated formatting removes subjective style debates from code review.", - checks: &["All files pass the project formatter", "No manual formatting overrides without justification"], + checks: &[ + "All files pass the project formatter", + "No manual formatting overrides without justification", + ], pass_example: "All changed files pass `prettier --check` and `rustfmt --check`.", fail_example: "Several files have inconsistent indentation that the formatter would fix.", recent_results: None, }, ControlDef { - name: "Linting", slug: "linting", + name: "Linting", + slug: "linting", description: "Linter issues resolved", - type_: VerificationType::Automated, mode: VerificationMode::Active, - f1: Some(0.98), pass_at_1: Some(0.97), + type_: VerificationType::Automated, + mode: VerificationMode::Active, + f1: Some(0.98), + pass_at_1: Some(0.97), evaluations: &[P, P, P, P, P, P, P, P, F, P], run_status: VerificationResult::Pass, detail_description: "Confirms that static analysis findings are resolved. Linter warnings left unaddressed accumulate into tech debt and mask real issues.", - checks: &["No new linter warnings introduced", "Existing warnings not suppressed without explanation", "Lint config not weakened"], + checks: &[ + "No new linter warnings introduced", + "Existing warnings not suppressed without explanation", + "Lint config not weakened", + ], pass_example: "ESLint and Clippy pass with zero warnings on changed files.", fail_example: "New `// eslint-disable-next-line` added to suppress a legitimate warning.", recent_results: None, }, ControlDef { - name: "Style", slug: "style", + name: "Style", + slug: "style", description: "House style applied", - type_: VerificationType::Ai, mode: VerificationMode::Active, - f1: Some(0.81), pass_at_1: Some(0.76), + type_: VerificationType::Ai, + mode: VerificationMode::Active, + f1: Some(0.81), + pass_at_1: Some(0.76), evaluations: &[P, F, P, P, P, P, F, P, P, P], run_status: VerificationResult::Pass, detail_description: "Evaluates whether the code follows the team's house style conventions beyond what automated formatters catch \u{2014} naming, file organization, import ordering, and idiomatic patterns.", - checks: &["Naming conventions followed (camelCase, snake_case as appropriate)", "Import ordering matches project convention", "Idiomatic patterns used for the language"], + checks: &[ + "Naming conventions followed (camelCase, snake_case as appropriate)", + "Import ordering matches project convention", + "Idiomatic patterns used for the language", + ], pass_example: "New TypeScript module uses camelCase variables, groups imports by source, and uses `Map` instead of plain objects for lookups.", fail_example: "Mix of camelCase and snake_case in the same module with random import ordering.", recent_results: None, @@ -2069,40 +2117,61 @@ mod verifications { question: "Will this behave correctly and safely under real-world conditions and failures?", controls: &[ ControlDef { - name: "Completeness", slug: "completeness", + name: "Completeness", + slug: "completeness", description: "Implementation covers requirements", - type_: VerificationType::Ai, mode: VerificationMode::Active, - f1: Some(0.76), pass_at_1: Some(0.71), + type_: VerificationType::Ai, + mode: VerificationMode::Active, + f1: Some(0.76), + pass_at_1: Some(0.71), evaluations: &[P, P, F, P, F, P, P, P, F, P], run_status: VerificationResult::Pass, detail_description: "Checks that the implementation fully covers the specified requirements. Partial implementations ship broken experiences and create follow-up tickets that could have been avoided.", - checks: &["All acceptance criteria addressed", "Edge cases handled", "Error states implemented"], + checks: &[ + "All acceptance criteria addressed", + "Edge cases handled", + "Error states implemented", + ], pass_example: "Feature handles all three specified user roles with appropriate permissions.", fail_example: "Only the happy path is implemented; error and empty states are missing.", recent_results: None, }, ControlDef { - name: "Defects", slug: "defects", + name: "Defects", + slug: "defects", description: "Potential or likely bugs remediated", - type_: VerificationType::AiAnalysis, mode: VerificationMode::Active, - f1: Some(0.84), pass_at_1: Some(0.79), + type_: VerificationType::AiAnalysis, + mode: VerificationMode::Active, + f1: Some(0.84), + pass_at_1: Some(0.79), evaluations: &[P, P, P, F, P, P, P, P, P, F], run_status: VerificationResult::Pass, detail_description: "Identifies potential or likely bugs through static analysis and AI review. Catching defects before merge is orders of magnitude cheaper than finding them in production.", - checks: &["No off-by-one errors in loops or slices", "Null/undefined handled at boundaries", "Race conditions considered in async code"], + checks: &[ + "No off-by-one errors in loops or slices", + "Null/undefined handled at boundaries", + "Race conditions considered in async code", + ], pass_example: "API handler validates input, handles missing fields gracefully, and returns appropriate HTTP status codes.", fail_example: "Array index accessed without bounds check; crashes on empty input.", recent_results: None, }, ControlDef { - name: "Performance", slug: "performance", + name: "Performance", + slug: "performance", description: "Hot path impact identified", - type_: VerificationType::Ai, mode: VerificationMode::Evaluate, - f1: Some(0.69), pass_at_1: Some(0.63), + type_: VerificationType::Ai, + mode: VerificationMode::Evaluate, + f1: Some(0.69), + pass_at_1: Some(0.63), evaluations: &[F, P, P, F, P, F, P, P, F, P], run_status: VerificationResult::Pass, detail_description: "Assesses whether the change impacts hot paths or introduces algorithmic regressions. Performance problems that ship to production are expensive to diagnose and fix.", - checks: &["No N+1 queries introduced", "Large collections not processed synchronously", "Caching considered for repeated expensive operations"], + checks: &[ + "No N+1 queries introduced", + "Large collections not processed synchronously", + "Caching considered for repeated expensive operations", + ], pass_example: "Database query uses a JOIN instead of N separate queries for related records.", fail_example: "Loop makes a separate HTTP call for each item in a 1000-element list.", recent_results: None, @@ -2114,40 +2183,61 @@ mod verifications { question: "Do we have trustworthy, automated evidence that it works and won't regress?", controls: &[ ControlDef { - name: "Test Coverage", slug: "test-coverage", + name: "Test Coverage", + slug: "test-coverage", description: "Production code exercised by unit tests", - type_: VerificationType::Analysis, mode: VerificationMode::Active, - f1: Some(0.95), pass_at_1: Some(0.93), + type_: VerificationType::Analysis, + mode: VerificationMode::Active, + f1: Some(0.95), + pass_at_1: Some(0.93), evaluations: &[P, P, P, P, P, P, F, P, P, P], run_status: VerificationResult::Pass, detail_description: "Measures whether production code is exercised by automated tests. Coverage gaps mean regressions can ship undetected.", - checks: &["New code has corresponding unit tests", "Coverage does not decrease", "Critical paths have integration tests"], + checks: &[ + "New code has corresponding unit tests", + "Coverage does not decrease", + "Critical paths have integration tests", + ], pass_example: "New service method has 6 unit tests covering happy path, error cases, and edge cases.", fail_example: "New 200-line module has zero test files.", recent_results: None, }, ControlDef { - name: "Test Quality", slug: "test-quality", + name: "Test Quality", + slug: "test-quality", description: "Tests are robust and clear", - type_: VerificationType::Ai, mode: VerificationMode::Evaluate, - f1: Some(0.71), pass_at_1: Some(0.65), + type_: VerificationType::Ai, + mode: VerificationMode::Evaluate, + f1: Some(0.71), + pass_at_1: Some(0.65), evaluations: &[P, F, F, P, P, F, P, F, P, P], run_status: VerificationResult::Fail, detail_description: "Evaluates whether tests are robust, readable, and actually verify behavior rather than implementation details. Low-quality tests give false confidence.", - checks: &["Tests verify behavior, not implementation", "Assertions are specific and meaningful", "Tests are independent and deterministic"], + checks: &[ + "Tests verify behavior, not implementation", + "Assertions are specific and meaningful", + "Tests are independent and deterministic", + ], pass_example: "Tests assert on API response shape and status codes, not on internal method call counts.", fail_example: "Tests mock every dependency and only verify that mocks were called.", recent_results: None, }, ControlDef { - name: "E2E Coverage", slug: "e2e-coverage", + name: "E2E Coverage", + slug: "e2e-coverage", description: "Browser automation exercises UX", - type_: VerificationType::Analysis, mode: VerificationMode::Active, - f1: Some(0.91), pass_at_1: Some(0.88), + type_: VerificationType::Analysis, + mode: VerificationMode::Active, + f1: Some(0.91), + pass_at_1: Some(0.88), evaluations: &[P, P, P, F, P, P, P, P, P, P], run_status: VerificationResult::Na, detail_description: "Checks that user-facing workflows are exercised by end-to-end browser automation. E2E tests catch integration issues that unit tests miss.", - checks: &["Critical user flows have Playwright/Cypress tests", "E2E tests run in CI", "No flaky E2E tests introduced"], + checks: &[ + "Critical user flows have Playwright/Cypress tests", + "E2E tests run in CI", + "No flaky E2E tests introduced", + ], pass_example: "New checkout flow has a Playwright test that completes a purchase end-to-end.", fail_example: "New multi-step wizard has no browser automation tests.", recent_results: None, @@ -2159,66 +2249,101 @@ mod verifications { question: "Will this be easy to modify or extend later without creating new risk?", controls: &[ ControlDef { - name: "Architecture", slug: "architecture", + name: "Architecture", + slug: "architecture", description: "Layering and dependency graph meets design", - type_: VerificationType::Analysis, mode: VerificationMode::Active, - f1: Some(0.88), pass_at_1: Some(0.84), + type_: VerificationType::Analysis, + mode: VerificationMode::Active, + f1: Some(0.88), + pass_at_1: Some(0.84), evaluations: &[P, P, P, P, F, P, P, P, P, P], run_status: VerificationResult::Pass, detail_description: "Validates that layering and dependency directions conform to the project's architectural design. Architectural violations compound over time and make systems harder to evolve.", - checks: &["Dependencies point inward (domain doesn't depend on infra)", "No circular dependencies introduced", "Module boundaries respected"], + checks: &[ + "Dependencies point inward (domain doesn't depend on infra)", + "No circular dependencies introduced", + "Module boundaries respected", + ], pass_example: "New repository implementation depends on domain interfaces, not the other way around.", fail_example: "Domain model imports directly from the HTTP framework package.", recent_results: None, }, ControlDef { - name: "Interfaces", slug: "interfaces", + name: "Interfaces", + slug: "interfaces", description: "", - type_: VerificationType::Ai, mode: VerificationMode::Disabled, - f1: None, pass_at_1: None, + type_: VerificationType::Ai, + mode: VerificationMode::Disabled, + f1: None, + pass_at_1: None, evaluations: &[], run_status: VerificationResult::Pass, detail_description: "Reviews public API surfaces for clarity, consistency, and backward compatibility. Interfaces are contracts \u{2014} once published, they're expensive to change.", - checks: &["Public API types are well-defined", "Breaking changes documented", "Consistent naming across endpoints"], + checks: &[ + "Public API types are well-defined", + "Breaking changes documented", + "Consistent naming across endpoints", + ], pass_example: "New endpoint follows existing naming and error format conventions.", fail_example: "New endpoint uses different error format than all other endpoints.", recent_results: None, }, ControlDef { - name: "Duplication", slug: "duplication", + name: "Duplication", + slug: "duplication", description: "Similar and identical code blocks identified", - type_: VerificationType::Analysis, mode: VerificationMode::Active, - f1: Some(0.96), pass_at_1: Some(0.94), + type_: VerificationType::Analysis, + mode: VerificationMode::Active, + f1: Some(0.96), + pass_at_1: Some(0.94), evaluations: &[P, P, P, P, P, P, P, F, P, P], run_status: VerificationResult::Pass, detail_description: "Detects similar or identical code blocks that could be consolidated. Duplication increases maintenance burden and creates inconsistency risk.", - checks: &["No copy-pasted logic across files", "Shared utilities used for common patterns", "Similar test setup consolidated"], + checks: &[ + "No copy-pasted logic across files", + "Shared utilities used for common patterns", + "Similar test setup consolidated", + ], pass_example: "Date formatting logic extracted into a shared utility used by 4 components.", fail_example: "Same 15-line validation function copy-pasted into three different handlers.", recent_results: None, }, ControlDef { - name: "Simplicity", slug: "simplicity", + name: "Simplicity", + slug: "simplicity", description: "Extra review for reducing complexity", - type_: VerificationType::Ai, mode: VerificationMode::Active, - f1: Some(0.74), pass_at_1: Some(0.69), + type_: VerificationType::Ai, + mode: VerificationMode::Active, + f1: Some(0.74), + pass_at_1: Some(0.69), evaluations: &[P, F, P, P, F, P, P, F, P, P], run_status: VerificationResult::Pass, detail_description: "Flags unnecessarily complex code that could be simplified without changing behavior. Simpler code is easier to review, debug, and extend.", - checks: &["No premature abstractions", "Control flow is straightforward", "Functions are focused and short"], + checks: &[ + "No premature abstractions", + "Control flow is straightforward", + "Functions are focused and short", + ], pass_example: "Conditional logic uses early returns instead of deeply nested if-else chains.", fail_example: "Three-level generic abstraction for a function called in one place.", recent_results: None, }, ControlDef { - name: "Dead Code", slug: "dead-code", + name: "Dead Code", + slug: "dead-code", description: "Unexecuted code and dependencies removed", - type_: VerificationType::Analysis, mode: VerificationMode::Active, - f1: Some(0.93), pass_at_1: Some(0.90), + type_: VerificationType::Analysis, + mode: VerificationMode::Active, + f1: Some(0.93), + pass_at_1: Some(0.90), evaluations: &[P, P, P, P, P, F, P, P, P, P], run_status: VerificationResult::Pass, detail_description: "Identifies unexecuted code paths and unused dependencies. Dead code misleads readers and bloats bundles.", - checks: &["No unreachable code paths", "Unused imports and variables removed", "Deprecated functions removed if no longer called"], + checks: &[ + "No unreachable code paths", + "Unused imports and variables removed", + "Deprecated functions removed if no longer called", + ], pass_example: "Old feature flag and its associated code paths removed after rollout completed.", fail_example: "Commented-out function left in file 'in case we need it later'.", recent_results: None, @@ -2230,53 +2355,81 @@ mod verifications { question: "Does this preserve or improve our security posture and avoid vulnerabilities?", controls: &[ ControlDef { - name: "Vulnerabilities", slug: "vulnerabilities", + name: "Vulnerabilities", + slug: "vulnerabilities", description: "Security issues are remediated", - type_: VerificationType::AiAnalysis, mode: VerificationMode::Active, - f1: Some(0.86), pass_at_1: Some(0.81), + type_: VerificationType::AiAnalysis, + mode: VerificationMode::Active, + f1: Some(0.86), + pass_at_1: Some(0.81), evaluations: &[P, P, F, P, P, P, P, P, F, P], run_status: VerificationResult::Pass, detail_description: "Scans for known security vulnerabilities using both AI analysis and static scanning tools. Shipping known vulnerabilities exposes users and the organization to risk.", - checks: &["No SQL injection or XSS vectors", "User input sanitized at boundaries", "Authentication/authorization checks present"], + checks: &[ + "No SQL injection or XSS vectors", + "User input sanitized at boundaries", + "Authentication/authorization checks present", + ], pass_example: "User input passed through parameterized queries; HTML output escaped.", fail_example: "Raw SQL string concatenation with user-supplied values.", recent_results: None, }, ControlDef { - name: "IaC Scanning", slug: "iac-scanning", + name: "IaC Scanning", + slug: "iac-scanning", description: "", - type_: VerificationType::Automated, mode: VerificationMode::Disabled, - f1: None, pass_at_1: None, + type_: VerificationType::Automated, + mode: VerificationMode::Disabled, + f1: None, + pass_at_1: None, evaluations: &[], run_status: VerificationResult::Pass, detail_description: "Validates infrastructure-as-code definitions against security best practices. Misconfigured infrastructure is a leading cause of data breaches.", - checks: &["No publicly accessible storage buckets", "Encryption at rest enabled", "Least-privilege IAM policies"], + checks: &[ + "No publicly accessible storage buckets", + "Encryption at rest enabled", + "Least-privilege IAM policies", + ], pass_example: "Terraform module creates S3 bucket with encryption, versioning, and private ACL.", fail_example: "CloudFormation template creates an RDS instance with no encryption and public accessibility.", recent_results: None, }, ControlDef { - name: "Dependency Alerts", slug: "dependency-alerts", + name: "Dependency Alerts", + slug: "dependency-alerts", description: "Known CVEs are patched", - type_: VerificationType::Analysis, mode: VerificationMode::Active, - f1: Some(0.97), pass_at_1: Some(0.95), + type_: VerificationType::Analysis, + mode: VerificationMode::Active, + f1: Some(0.97), + pass_at_1: Some(0.95), evaluations: &[P, P, P, P, P, P, P, P, P, F], run_status: VerificationResult::Pass, detail_description: "Checks that third-party dependencies are free from known CVEs. Vulnerable dependencies are an easy attack vector that automated tools can detect.", - checks: &["No dependencies with known critical CVEs", "Lock file updated to patched versions", "Unused dependencies removed"], + checks: &[ + "No dependencies with known critical CVEs", + "Lock file updated to patched versions", + "Unused dependencies removed", + ], pass_example: "Dependabot alert resolved by updating lodash from 4.17.20 to 4.17.21.", fail_example: "Package.json pins a version of axios with a known SSRF vulnerability.", recent_results: None, }, ControlDef { - name: "Security Controls", slug: "security-controls", + name: "Security Controls", + slug: "security-controls", description: "Organization standards applied", - type_: VerificationType::Ai, mode: VerificationMode::Active, - f1: Some(0.80), pass_at_1: Some(0.75), + type_: VerificationType::Ai, + mode: VerificationMode::Active, + f1: Some(0.80), + pass_at_1: Some(0.75), evaluations: &[P, P, F, P, P, F, P, P, P, P], run_status: VerificationResult::Pass, detail_description: "Verifies that organization-specific security standards are applied \u{2014} rate limiting, audit logging, CORS policies, and secret management.", - checks: &["Secrets not hardcoded in source", "Rate limiting on public endpoints", "Audit logging for sensitive operations"], + checks: &[ + "Secrets not hardcoded in source", + "Rate limiting on public endpoints", + "Audit logging for sensitive operations", + ], pass_example: "API key loaded from environment variable; rate limiter configured on login endpoint.", fail_example: "AWS credentials committed in a config file.", recent_results: None, @@ -2288,53 +2441,81 @@ mod verifications { question: "Is this changeset safe to ship to production immediately?", controls: &[ ControlDef { - name: "Compatibility", slug: "compatibility", + name: "Compatibility", + slug: "compatibility", description: "Breaking changes are avoided", - type_: VerificationType::Analysis, mode: VerificationMode::Active, - f1: Some(0.89), pass_at_1: Some(0.85), + type_: VerificationType::Analysis, + mode: VerificationMode::Active, + f1: Some(0.89), + pass_at_1: Some(0.85), evaluations: &[P, P, P, P, F, P, P, P, P, P], run_status: VerificationResult::Pass, detail_description: "Detects breaking changes in APIs, database schemas, or wire formats that could disrupt consumers. Breaking changes require coordination that surprises prevent.", - checks: &["No removed or renamed public API fields", "Database migrations are backward-compatible", "Wire format changes are additive"], + checks: &[ + "No removed or renamed public API fields", + "Database migrations are backward-compatible", + "Wire format changes are additive", + ], pass_example: "New field added to API response; no existing fields removed or renamed.", fail_example: "Column renamed in migration while old code is still deployed.", recent_results: None, }, ControlDef { - name: "Rollout / Rollback", slug: "rollout-rollback", + name: "Rollout / Rollback", + slug: "rollout-rollback", description: "Known rollback plan if deploy fails", - type_: VerificationType::Ai, mode: VerificationMode::Evaluate, - f1: Some(0.66), pass_at_1: Some(0.60), + type_: VerificationType::Ai, + mode: VerificationMode::Evaluate, + f1: Some(0.66), + pass_at_1: Some(0.60), evaluations: &[F, P, F, P, F, P, P, F, P, F], run_status: VerificationResult::Fail, detail_description: "Confirms that the change has a clear deployment plan and can be safely rolled back if issues arise. Every production deploy should be reversible.", - checks: &["Feature flag available for gradual rollout", "Database migration is reversible", "Rollback procedure documented"], + checks: &[ + "Feature flag available for gradual rollout", + "Database migration is reversible", + "Rollback procedure documented", + ], pass_example: "Feature behind a LaunchDarkly flag with 10% initial rollout and documented rollback steps.", fail_example: "Irreversible database migration with no rollback plan.", recent_results: Some(ROLLOUT_ROLLBACK_RESULTS), }, ControlDef { - name: "Observability", slug: "observability", + name: "Observability", + slug: "observability", description: "Logging, metrics, tracing instrumented", - type_: VerificationType::Ai, mode: VerificationMode::Evaluate, - f1: Some(0.73), pass_at_1: Some(0.67), + type_: VerificationType::Ai, + mode: VerificationMode::Evaluate, + f1: Some(0.73), + pass_at_1: Some(0.67), evaluations: &[P, F, P, F, P, P, F, P, F, P], run_status: VerificationResult::Fail, detail_description: "Ensures that logging, metrics, and tracing are instrumented for new code paths. Without observability, production issues are invisible until users report them.", - checks: &["Structured logging for new operations", "Metrics emitted for key business events", "Distributed tracing propagated"], + checks: &[ + "Structured logging for new operations", + "Metrics emitted for key business events", + "Distributed tracing propagated", + ], pass_example: "New payment endpoint logs transaction IDs, emits latency metrics, and propagates trace context.", fail_example: "New background job has no logging or metrics; failures are silent.", recent_results: None, }, ControlDef { - name: "Cost", slug: "cost", + name: "Cost", + slug: "cost", description: "Tech ops costs estimated", - type_: VerificationType::Analysis, mode: VerificationMode::Evaluate, - f1: Some(0.78), pass_at_1: Some(0.72), + type_: VerificationType::Analysis, + mode: VerificationMode::Evaluate, + f1: Some(0.78), + pass_at_1: Some(0.72), evaluations: &[P, P, F, P, F, P, P, F, P, P], run_status: VerificationResult::Pass, detail_description: "Estimates the infrastructure and operational cost impact of the change. Unchecked cost growth erodes margins and can cause budget surprises.", - checks: &["New infrastructure resources sized appropriately", "No unbounded resource consumption", "Cost estimate provided for significant changes"], + checks: &[ + "New infrastructure resources sized appropriately", + "No unbounded resource consumption", + "Cost estimate provided for significant changes", + ], pass_example: "New Lambda function has memory limit set and estimated monthly cost noted in PR.", fail_example: "New service provisions a db.r5.4xlarge for a table with 100 rows.", recent_results: None, @@ -2346,66 +2527,101 @@ mod verifications { question: "Does this meet our regulatory, contractual, and policy obligations?", controls: &[ ControlDef { - name: "Change Control", slug: "change-control", + name: "Change Control", + slug: "change-control", description: "Separation of Duties policy met", - type_: VerificationType::Analysis, mode: VerificationMode::Active, - f1: Some(0.94), pass_at_1: Some(0.91), + type_: VerificationType::Analysis, + mode: VerificationMode::Active, + f1: Some(0.94), + pass_at_1: Some(0.91), evaluations: &[P, P, P, P, P, P, P, P, F, P], run_status: VerificationResult::Pass, detail_description: "Validates that separation-of-duties policies are met \u{2014} the author is not the sole reviewer, approvals are obtained, and the change went through the proper process.", - checks: &["PR has at least one approval from non-author", "Required reviewers have signed off", "No self-merging without policy exception"], + checks: &[ + "PR has at least one approval from non-author", + "Required reviewers have signed off", + "No self-merging without policy exception", + ], pass_example: "PR approved by two team members before merge; CI checks all green.", fail_example: "Author approved and merged their own PR with no other reviewers.", recent_results: None, }, ControlDef { - name: "AI Governance", slug: "ai-governance", + name: "AI Governance", + slug: "ai-governance", description: "AI involvement was acceptable", - type_: VerificationType::Analysis, mode: VerificationMode::Active, - f1: Some(0.85), pass_at_1: Some(0.80), + type_: VerificationType::Analysis, + mode: VerificationMode::Active, + f1: Some(0.85), + pass_at_1: Some(0.80), evaluations: &[P, P, P, F, P, P, P, P, P, P], run_status: VerificationResult::Pass, detail_description: "Checks that AI-generated or AI-assisted code meets the organization's governance requirements \u{2014} attribution, review depth, and acceptable use.", - checks: &["AI-generated code clearly attributed", "Human review of AI suggestions documented", "AI usage within acceptable-use policy"], + checks: &[ + "AI-generated code clearly attributed", + "Human review of AI suggestions documented", + "AI usage within acceptable-use policy", + ], pass_example: "PR notes that implementation was AI-assisted; human reviewer verified logic and tests.", fail_example: "Entire module generated by AI with no human review or attribution.", recent_results: None, }, ControlDef { - name: "Privacy", slug: "privacy", + name: "Privacy", + slug: "privacy", description: "PII is identified and handled to standards", - type_: VerificationType::Ai, mode: VerificationMode::Active, - f1: Some(0.77), pass_at_1: Some(0.72), + type_: VerificationType::Ai, + mode: VerificationMode::Active, + f1: Some(0.77), + pass_at_1: Some(0.72), evaluations: &[P, F, P, P, P, F, P, P, P, F], run_status: VerificationResult::Pass, detail_description: "Ensures that personally identifiable information (PII) is identified, classified, and handled according to privacy standards (GDPR, CCPA).", - checks: &["PII fields identified and documented", "Data retention policies applied", "Consent mechanisms in place for data collection"], + checks: &[ + "PII fields identified and documented", + "Data retention policies applied", + "Consent mechanisms in place for data collection", + ], pass_example: "New user profile endpoint masks email in logs and respects data deletion requests.", fail_example: "User email addresses logged in plaintext to application logs.", recent_results: None, }, ControlDef { - name: "Accessibility", slug: "accessibility", + name: "Accessibility", + slug: "accessibility", description: "Software meets accessibility requirements", - type_: VerificationType::Analysis, mode: VerificationMode::Active, - f1: Some(0.90), pass_at_1: Some(0.87), + type_: VerificationType::Analysis, + mode: VerificationMode::Active, + f1: Some(0.90), + pass_at_1: Some(0.87), evaluations: &[P, P, P, P, P, F, P, P, P, P], run_status: VerificationResult::Pass, detail_description: "Verifies that UI changes meet accessibility requirements (WCAG 2.1 AA). Inaccessible software excludes users and creates legal risk.", - checks: &["Semantic HTML elements used", "ARIA labels present on interactive elements", "Color contrast meets WCAG AA standards"], + checks: &[ + "Semantic HTML elements used", + "ARIA labels present on interactive elements", + "Color contrast meets WCAG AA standards", + ], pass_example: "New modal uses , has aria-labelledby, and focus is trapped within.", fail_example: "Custom dropdown built with
elements, no keyboard navigation, no ARIA roles.", recent_results: None, }, ControlDef { - name: "Licensing", slug: "licensing", + name: "Licensing", + slug: "licensing", description: "Supply chain meets IP policy", - type_: VerificationType::Analysis, mode: VerificationMode::Active, - f1: Some(0.96), pass_at_1: Some(0.93), + type_: VerificationType::Analysis, + mode: VerificationMode::Active, + f1: Some(0.96), + pass_at_1: Some(0.93), evaluations: &[P, P, P, P, P, P, P, P, P, P], run_status: VerificationResult::Pass, detail_description: "Ensures that all third-party dependencies comply with the organization's intellectual property policy. License violations can have severe legal consequences.", - checks: &["No GPL-licensed dependencies in proprietary code", "License file present for new dependencies", "Supply chain attestation where required"], + checks: &[ + "No GPL-licensed dependencies in proprietary code", + "License file present for new dependencies", + "Supply chain attestation where required", + ], pass_example: "New dependency uses MIT license; added to approved dependency list.", fail_example: "GPL-licensed library added to a closed-source commercial product.", recent_results: None, @@ -3241,8 +3457,8 @@ mod insights { } mod settings { - use fabro_config::server::*; use fabro_config::FabroSettings; + use fabro_config::server::*; pub fn server_settings() -> serde_json::Value { serde_json::to_value(FabroSettings { diff --git a/lib/crates/fabro-api/src/error.rs b/lib/crates/fabro-api/src/error.rs index 0278f0cff..e5c2b0ce7 100644 --- a/lib/crates/fabro-api/src/error.rs +++ b/lib/crates/fabro-api/src/error.rs @@ -1,6 +1,6 @@ +use axum::Json; use axum::http::StatusCode; use axum::response::{IntoResponse, Response}; -use axum::Json; use serde::Serialize; #[derive(Serialize)] diff --git a/lib/crates/fabro-api/src/github_webhooks.rs b/lib/crates/fabro-api/src/github_webhooks.rs index d359a2c66..e6ceb574d 100644 --- a/lib/crates/fabro-api/src/github_webhooks.rs +++ b/lib/crates/fabro-api/src/github_webhooks.rs @@ -1,8 +1,8 @@ +use axum::Router; use axum::body::Bytes; use axum::extract::State; use axum::http::{HeaderMap, StatusCode}; use axum::routing::post; -use axum::Router; use hmac::{Hmac, Mac}; use sha2::Sha256; use tokio::net::TcpListener; diff --git a/lib/crates/fabro-api/src/jwt_auth.rs b/lib/crates/fabro-api/src/jwt_auth.rs index 1d3d7b11d..f5834610e 100644 --- a/lib/crates/fabro-api/src/jwt_auth.rs +++ b/lib/crates/fabro-api/src/jwt_auth.rs @@ -277,7 +277,7 @@ impl FromRequestParts for AuthenticatedUser { AuthMode::Disabled => { return Ok(AuthenticatedUser { login: "demo".to_string(), - }) + }); } AuthMode::Strategies(strategies) => strategies, }; @@ -320,11 +320,11 @@ impl FromRequestParts for AuthenticatedUser { #[cfg(test)] mod tests { use super::*; + use axum::Router; use axum::body::Body; use axum::http::{Request, StatusCode}; use axum::response::IntoResponse; use axum::routing::get; - use axum::Router; use tower::ServiceExt; async fn protected_handler(_auth: AuthenticatedService) -> impl IntoResponse { diff --git a/lib/crates/fabro-api/src/lib.rs b/lib/crates/fabro-api/src/lib.rs index e2cf51524..55010be9c 100644 --- a/lib/crates/fabro-api/src/lib.rs +++ b/lib/crates/fabro-api/src/lib.rs @@ -6,8 +6,8 @@ pub mod jwt_auth; pub mod serve; pub mod server; pub mod server_config { - pub use fabro_config::server::*; pub use fabro_config::FabroSettings; + pub use fabro_config::server::*; } pub mod sessions; pub mod tls; diff --git a/lib/crates/fabro-api/src/serve.rs b/lib/crates/fabro-api/src/serve.rs index 16a510a43..57d783acf 100644 --- a/lib/crates/fabro-api/src/serve.rs +++ b/lib/crates/fabro-api/src/serve.rs @@ -15,9 +15,9 @@ use clap::Args; use fabro_config::FabroSettings; use crate::github_webhooks::WebhookManager; -use crate::jwt_auth::{decode_pem_env, resolve_auth_mode, AuthMode, AuthStrategy}; +use crate::jwt_auth::{AuthMode, AuthStrategy, decode_pem_env, resolve_auth_mode}; use crate::server::{build_router, create_app_state_with_options, spawn_scheduler}; -use crate::tls::{build_rustls_config, serve_tls, ClientAuth}; +use crate::tls::{ClientAuth, build_rustls_config, serve_tls}; use fabro_llm::client::Client as LlmClient; use fabro_sandbox::SandboxProvider; use fabro_workflows::pipeline::LlmSpec; @@ -197,7 +197,9 @@ pub async fn serve_command(args: ServeArgs, styles: &'static Styles) -> anyhow:: } } _ => { - warn!("Webhook config present but GITHUB_APP_WEBHOOK_SECRET or GITHUB_APP_PRIVATE_KEY not set; skipping webhook listener"); + warn!( + "Webhook config present but GITHUB_APP_WEBHOOK_SECRET or GITHUB_APP_PRIVATE_KEY not set; skipping webhook listener" + ); None } } diff --git a/lib/crates/fabro-api/src/server.rs b/lib/crates/fabro-api/src/server.rs index 9cf52cfc6..09edab51e 100644 --- a/lib/crates/fabro-api/src/server.rs +++ b/lib/crates/fabro-api/src/server.rs @@ -11,12 +11,12 @@ use axum::routing::{get, post}; use axum::{Json, Router}; use fabro_config::sandbox::SandboxSettings; use fabro_llm::client::Client as LlmClient; -use fabro_llm::generate::{generate, generate_object, GenerateParams}; +use fabro_llm::generate::{GenerateParams, generate, generate_object}; use fabro_llm::types::{ ContentPart, FinishReason, Message as LlmMessage, Request as LlmRequest, Response as LlmResponse, Role, StreamEvent, ToolChoice, ToolDefinition, Usage, }; -use fabro_retro::retro::{derive_retro, extract_stage_durations, Retro}; +use fabro_retro::retro::{Retro, derive_retro, extract_stage_durations}; use fabro_util::redact::redact_jsonl_line; use fabro_workflows::error::FabroError; use fabro_workflows::git::GitAuthor; @@ -27,9 +27,9 @@ use tokio::sync::oneshot; use tokio::sync::{Notify, OnceCell}; use tokio::task::spawn_blocking; use tokio::time::{sleep, timeout}; -use tokio_stream::wrappers::BroadcastStream; use tokio_stream::StreamExt; -use tower::{service_fn, ServiceExt}; +use tokio_stream::wrappers::BroadcastStream; +use tower::{ServiceExt, service_fn}; use tracing::{error, info}; @@ -37,7 +37,7 @@ use crate::demo; use crate::error::ApiError; use crate::jwt_auth::{AuthMode, AuthenticatedService, AuthenticatedUser}; use crate::sessions as sessions_mod; -use crate::sessions::{new_session_store, SessionStore}; +use crate::sessions::{SessionStore, new_session_store}; use fabro_interview::{Answer, Interviewer, QuestionType, WebInterviewer}; use fabro_retro::RetroExt; use fabro_workflows::context::Context; @@ -918,7 +918,7 @@ async fn get_questions( StatusCode::OK, Json(ListResponse::new(Vec::::new())), ) - .into_response() + .into_response(); } }; let pending = interviewer.pending_questions(); @@ -1027,7 +1027,7 @@ async fn get_events( Some(managed_run) => match &managed_run.event_tx { Some(tx) => tx.subscribe(), None => { - return ApiError::new(StatusCode::GONE, "Event stream closed.").into_response() + return ApiError::new(StatusCode::GONE, "Event stream closed.").into_response(); } }, None => return ApiError::not_found("Run not found.").into_response(), @@ -1410,7 +1410,7 @@ async fn create_completion( StatusCode::INTERNAL_SERVER_ERROR, format!("Failed to create LLM client: {e}"), ) - .into_response() + .into_response(); } }; @@ -1420,7 +1420,7 @@ async fn create_completion( Ok(s) => s, Err(e) => { return ApiError::new(StatusCode::BAD_GATEWAY, format!("LLM error: {e}")) - .into_response() + .into_response(); } }; @@ -1540,7 +1540,7 @@ async fn get_retro( /// Render DOT source to a styled SVG via `render_dot` on a blocking thread. pub(crate) async fn render_dot_svg(dot_source: &str) -> Response { - use fabro_graphviz::render::{render_dot, GraphFormat}; + use fabro_graphviz::render::{GraphFormat, render_dot}; let source = dot_source.to_owned(); match spawn_blocking(move || render_dot(&source, GraphFormat::Svg)).await { diff --git a/lib/crates/fabro-api/src/sessions.rs b/lib/crates/fabro-api/src/sessions.rs index ecec1d903..d9118790f 100644 --- a/lib/crates/fabro-api/src/sessions.rs +++ b/lib/crates/fabro-api/src/sessions.rs @@ -2,12 +2,12 @@ use std::collections::HashMap; use std::sync::atomic::{AtomicU64, Ordering}; use std::sync::{Arc, RwLock}; +use axum::Json; use axum::extract::{Path, Query, State}; use axum::http::StatusCode; use axum::response::sse::{Event, Sse}; use axum::response::{IntoResponse, Response}; -use axum::Json; -use fabro_llm::generate::{stream as llm_stream, GenerateParams}; +use fabro_llm::generate::{GenerateParams, stream as llm_stream}; use fabro_llm::types::{Message as LlmMessage, StreamEvent}; use tokio::sync::broadcast; use tokio_stream::wrappers::BroadcastStream; diff --git a/lib/crates/fabro-api/src/tls.rs b/lib/crates/fabro-api/src/tls.rs index 226c8db29..372ae5d1f 100644 --- a/lib/crates/fabro-api/src/tls.rs +++ b/lib/crates/fabro-api/src/tls.rs @@ -1,8 +1,8 @@ use std::path::Path; use std::sync::Arc; -use rustls::server::WebPkiClientVerifier; use rustls::ServerConfig; +use rustls::server::WebPkiClientVerifier; use rustls_pki_types::{CertificateDer, PrivateKeyDer}; use tokio::net::TcpListener; use tracing::error; diff --git a/lib/crates/fabro-api/tests/integration.rs b/lib/crates/fabro-api/tests/integration.rs index 87a8df2d4..aff7c4533 100644 --- a/lib/crates/fabro-api/tests/integration.rs +++ b/lib/crates/fabro-api/tests/integration.rs @@ -11,7 +11,7 @@ mod mtls_e2e { use fabro_api::jwt_auth::{AuthMode, AuthStrategy}; use fabro_api::server::{build_router, create_app_state}; use fabro_api::server_config::TlsSettings; - use fabro_api::tls::{build_rustls_config, ClientAuth}; + use fabro_api::tls::{ClientAuth, build_rustls_config}; use fabro_workflows::pipeline::LlmSpec; use tokio::net::TcpListener; @@ -429,11 +429,11 @@ mod server_lifecycle { use axum::http::{Request, StatusCode}; use fabro_api::server::{build_router, create_app_state_with_registry_factory}; use fabro_interview::Interviewer; + use fabro_workflows::handler::HandlerRegistry; use fabro_workflows::handler::agent::AgentHandler; use fabro_workflows::handler::exit::ExitHandler; use fabro_workflows::handler::human::HumanHandler; use fabro_workflows::handler::start::StartHandler; - use fabro_workflows::handler::HandlerRegistry; use fabro_workflows::pipeline::LlmSpec; use tower::ServiceExt; diff --git a/lib/crates/fabro-cli/src/cli_config.rs b/lib/crates/fabro-cli/src/cli_config.rs index e39efc9ea..4ae6d5f20 100644 --- a/lib/crates/fabro-cli/src/cli_config.rs +++ b/lib/crates/fabro-cli/src/cli_config.rs @@ -3,8 +3,8 @@ pub use fabro_config::cli::*; use std::path::Path; -use fabro_config::cli::load_cli_config; use fabro_config::FabroSettings; +use fabro_config::cli::load_cli_config; #[cfg(feature = "server")] use tracing::debug; diff --git a/lib/crates/fabro-cli/src/commands/asset/cp.rs b/lib/crates/fabro-cli/src/commands/asset/cp.rs index d0b982369..499a06b4c 100644 --- a/lib/crates/fabro-cli/src/commands/asset/cp.rs +++ b/lib/crates/fabro-cli/src/commands/asset/cp.rs @@ -1,9 +1,9 @@ use std::path::{Path, PathBuf}; -use anyhow::{bail, Context, Result}; +use anyhow::{Context, Result, bail}; use fabro_config::FabroSettingsExt; use fabro_store::RuntimeState; -use fabro_workflows::assets::{scan_assets, AssetEntry}; +use fabro_workflows::assets::{AssetEntry, scan_assets}; use fabro_workflows::run_lookup::{resolve_run, runs_base}; use crate::args::AssetCpArgs; diff --git a/lib/crates/fabro-cli/src/commands/config/mod.rs b/lib/crates/fabro-cli/src/commands/config/mod.rs index b72626a07..62f39850e 100644 --- a/lib/crates/fabro-cli/src/commands/config/mod.rs +++ b/lib/crates/fabro-cli/src/commands/config/mod.rs @@ -3,7 +3,7 @@ use std::path::Path; use crate::args::{ConfigCommand, ConfigNamespace, ConfigShowArgs}; use fabro_config::cli::load_cli_config; -use fabro_config::project::{discover_project_config, resolve_settings, ResolveSettingsInput}; +use fabro_config::project::{ResolveSettingsInput, discover_project_config, resolve_settings}; use fabro_config::{FabroConfig, FabroSettings}; pub fn dispatch(ns: ConfigNamespace) -> anyhow::Result<()> { diff --git a/lib/crates/fabro-cli/src/commands/doctor.rs b/lib/crates/fabro-cli/src/commands/doctor.rs index c38aaaa2e..56168189b 100644 --- a/lib/crates/fabro-cli/src/commands/doctor.rs +++ b/lib/crates/fabro-cli/src/commands/doctor.rs @@ -4,8 +4,8 @@ use std::process::Command; #[cfg(feature = "server")] use std::sync::LazyLock; -use base64::engine::general_purpose::STANDARD as BASE64_STANDARD; use base64::Engine as _; +use base64::engine::general_purpose::STANDARD as BASE64_STANDARD; #[cfg(feature = "server")] use fabro_config::server::{ApiAuthStrategy, AuthProvider}; use fabro_llm::client::Client as LlmClient; @@ -1177,11 +1177,7 @@ pub async fn run_doctor(verbose: bool, live: bool) -> i32 { report.render(&styles, verbose, None, Some(term_width)) ); - if report.has_errors() { - 1 - } else { - 0 - } + if report.has_errors() { 1 } else { 0 } } // --------------------------------------------------------------------------- @@ -1246,10 +1242,12 @@ mod tests { let live = vec![(Provider::Anthropic, Ok(()))]; let result = check_llm_providers(&statuses, Some(&live)); assert_eq!(result.status, CheckStatus::Pass); - assert!(result - .details - .iter() - .any(|d| d.text.contains("connectivity: OK"))); + assert!( + result + .details + .iter() + .any(|d| d.text.contains("connectivity: OK")) + ); } #[test] @@ -1466,10 +1464,12 @@ mod tests { }; let result = check_api(&status, None); assert!(result.details.iter().any(|d| d.text.contains("jwt"))); - assert!(result - .details - .iter() - .any(|d| d.text.contains("https://api.example.com"))); + assert!( + result + .details + .iter() + .any(|d| d.text.contains("https://api.example.com")) + ); } #[test] @@ -1481,10 +1481,12 @@ mod tests { let live = Ok(()); let result = check_api(&status, Some(&live)); assert_eq!(result.status, CheckStatus::Pass); - assert!(result - .details - .iter() - .any(|d| d.text.contains("Connectivity: OK"))); + assert!( + result + .details + .iter() + .any(|d| d.text.contains("Connectivity: OK")) + ); } #[test] @@ -1496,10 +1498,12 @@ mod tests { let live = Err("connection refused".to_string()); let result = check_api(&status, Some(&live)); assert_eq!(result.status, CheckStatus::Warning); - assert!(result - .details - .iter() - .any(|d| d.text.contains("connection refused"))); + assert!( + result + .details + .iter() + .any(|d| d.text.contains("connection refused")) + ); } // -- check_web -- @@ -1525,14 +1529,18 @@ mod tests { }; let result = check_web(&status, None); assert!(result.details.iter().any(|d| d.text.contains("github"))); - assert!(result - .details - .iter() - .any(|d| d.text.contains("https://arc.example.com"))); - assert!(result - .details - .iter() - .any(|d| d.text.contains("Allowed usernames: 3"))); + assert!( + result + .details + .iter() + .any(|d| d.text.contains("https://arc.example.com")) + ); + assert!( + result + .details + .iter() + .any(|d| d.text.contains("Allowed usernames: 3")) + ); } #[test] @@ -1545,10 +1553,12 @@ mod tests { let live = Ok(()); let result = check_web(&status, Some(&live)); assert_eq!(result.status, CheckStatus::Pass); - assert!(result - .details - .iter() - .any(|d| d.text.contains("Connectivity: OK"))); + assert!( + result + .details + .iter() + .any(|d| d.text.contains("Connectivity: OK")) + ); } #[test] @@ -1561,10 +1571,12 @@ mod tests { let live = Err("connection refused".to_string()); let result = check_web(&status, Some(&live)); assert_eq!(result.status, CheckStatus::Warning); - assert!(result - .details - .iter() - .any(|d| d.text.contains("connection refused"))); + assert!( + result + .details + .iter() + .any(|d| d.text.contains("connection refused")) + ); } } // mod server_tests (check_github_app, check_api, check_web) @@ -1893,20 +1905,24 @@ mod tests { fn crypto_jwt_configured_but_key_missing() { let result = check_crypto(&crypto_input(vec![ApiAuthStrategy::Jwt])); assert_eq!(result.status, CheckStatus::Error); - assert!(result - .details - .iter() - .any(|d| d.text.contains("FABRO_JWT_PUBLIC_KEY not set"))); + assert!( + result + .details + .iter() + .any(|d| d.text.contains("FABRO_JWT_PUBLIC_KEY not set")) + ); } #[test] fn crypto_mtls_configured_but_tls_not_set() { let result = check_crypto(&crypto_input(vec![ApiAuthStrategy::Mtls])); assert_eq!(result.status, CheckStatus::Error); - assert!(result - .details - .iter() - .any(|d| d.text.contains("[api.tls] not set"))); + assert!( + result + .details + .iter() + .any(|d| d.text.contains("[api.tls] not set")) + ); } #[test] @@ -1917,10 +1933,12 @@ mod tests { }; let result = check_crypto(&input); assert_eq!(result.status, CheckStatus::Error); - assert!(result - .details - .iter() - .any(|d| d.text.contains("Permission denied"))); + assert!( + result + .details + .iter() + .any(|d| d.text.contains("Permission denied")) + ); } #[test] @@ -1933,10 +1951,12 @@ mod tests { }; let result = check_crypto(&input); assert_eq!(result.status, CheckStatus::Error); - assert!(result - .details - .iter() - .any(|d| d.text.contains("JWT public key: invalid"))); + assert!( + result + .details + .iter() + .any(|d| d.text.contains("JWT public key: invalid")) + ); } #[test] @@ -1949,10 +1969,12 @@ mod tests { }; let result = check_crypto(&input); assert_eq!(result.status, CheckStatus::Error); - assert!(result - .details - .iter() - .any(|d| d.text.contains("JWT private key: invalid"))); + assert!( + result + .details + .iter() + .any(|d| d.text.contains("JWT private key: invalid")) + ); } #[test] @@ -1968,10 +1990,12 @@ mod tests { }; let result = check_crypto(&input); assert_eq!(result.status, CheckStatus::Pass); - assert!(result - .details - .iter() - .any(|d| d.text.contains("JWT public key: valid"))); + assert!( + result + .details + .iter() + .any(|d| d.text.contains("JWT public key: valid")) + ); } #[test] diff --git a/lib/crates/fabro-cli/src/commands/exec.rs b/lib/crates/fabro-cli/src/commands/exec.rs index 25282da98..b621bb663 100644 --- a/lib/crates/fabro-cli/src/commands/exec.rs +++ b/lib/crates/fabro-cli/src/commands/exec.rs @@ -1,7 +1,7 @@ use anyhow::Result; #[cfg(feature = "server")] use fabro_agent::cli::run_with_args_and_client; -use fabro_agent::cli::{run_with_args, AgentArgs}; +use fabro_agent::cli::{AgentArgs, run_with_args}; use fabro_config::mcp::McpServerEntry; use fabro_mcp::config::McpServerConfig; diff --git a/lib/crates/fabro-cli/src/commands/graph.rs b/lib/crates/fabro-cli/src/commands/graph.rs index 3f18a3552..efbb13052 100644 --- a/lib/crates/fabro-cli/src/commands/graph.rs +++ b/lib/crates/fabro-cli/src/commands/graph.rs @@ -4,11 +4,11 @@ use std::sync::LazyLock; use anyhow::bail; use fabro_config::cli::load_cli_config; -use fabro_config::project::{resolve_settings, resolve_workflow_path, ResolveSettingsInput}; +use fabro_config::project::{ResolveSettingsInput, resolve_settings, resolve_workflow_path}; use fabro_graphviz::render::render_dot; use fabro_util::terminal::Styles; use fabro_validate::Severity; -use fabro_workflows::operations::{validate, ValidateInput, WorkflowInput}; +use fabro_workflows::operations::{ValidateInput, WorkflowInput, validate}; use tracing::debug; use crate::args::{GraphArgs, GraphDirection}; diff --git a/lib/crates/fabro-cli/src/commands/install.rs b/lib/crates/fabro-cli/src/commands/install.rs index 0b8436ae7..3e39d4052 100644 --- a/lib/crates/fabro-cli/src/commands/install.rs +++ b/lib/crates/fabro-cli/src/commands/install.rs @@ -4,12 +4,12 @@ use std::net::SocketAddr; use std::path::Path; use std::process::{Command, Stdio}; -use anyhow::{bail, Context, Result}; +use anyhow::{Context, Result, bail}; use axum::extract::Query; use axum::response::Html; use axum::routing::get; -use base64::engine::general_purpose::STANDARD as BASE64_STANDARD; use base64::Engine as _; +use base64::engine::general_purpose::STANDARD as BASE64_STANDARD; use dialoguer::console::Term; use dialoguer::theme::ColorfulTheme; use dialoguer::{MultiSelect, Select}; diff --git a/lib/crates/fabro-cli/src/commands/llm/chat.rs b/lib/crates/fabro-cli/src/commands/llm/chat.rs index d6d305077..29392fa07 100644 --- a/lib/crates/fabro-cli/src/commands/llm/chat.rs +++ b/lib/crates/fabro-cli/src/commands/llm/chat.rs @@ -1,8 +1,8 @@ use anyhow::Result; use fabro_config::FabroSettings; -use fabro_llm::cli::{run_chat, ChatArgs}; +use fabro_llm::cli::{ChatArgs, run_chat}; #[cfg(feature = "server")] -use fabro_llm::cli::{run_chat_via_server, ServerConnection}; +use fabro_llm::cli::{ServerConnection, run_chat_via_server}; use crate::args::GlobalArgs; diff --git a/lib/crates/fabro-cli/src/commands/llm/prompt.rs b/lib/crates/fabro-cli/src/commands/llm/prompt.rs index f3289715f..f208537e6 100644 --- a/lib/crates/fabro-cli/src/commands/llm/prompt.rs +++ b/lib/crates/fabro-cli/src/commands/llm/prompt.rs @@ -1,8 +1,8 @@ use anyhow::Result; use fabro_config::FabroSettings; -use fabro_llm::cli::{run_prompt, PromptArgs}; +use fabro_llm::cli::{PromptArgs, run_prompt}; #[cfg(feature = "server")] -use fabro_llm::cli::{run_prompt_via_server, ServerConnection}; +use fabro_llm::cli::{ServerConnection, run_prompt_via_server}; use crate::args::GlobalArgs; diff --git a/lib/crates/fabro-cli/src/commands/model.rs b/lib/crates/fabro-cli/src/commands/model.rs index 4610334a8..13a659878 100644 --- a/lib/crates/fabro-cli/src/commands/model.rs +++ b/lib/crates/fabro-cli/src/commands/model.rs @@ -1,7 +1,7 @@ use anyhow::Result; #[cfg(feature = "server")] use fabro_llm::cli::ServerConnection; -use fabro_llm::cli::{run_models, ModelsCommand}; +use fabro_llm::cli::{ModelsCommand, run_models}; use crate::args::GlobalArgs; #[cfg(feature = "server")] diff --git a/lib/crates/fabro-cli/src/commands/pr/create.rs b/lib/crates/fabro-cli/src/commands/pr/create.rs index f07476b38..541992159 100644 --- a/lib/crates/fabro-cli/src/commands/pr/create.rs +++ b/lib/crates/fabro-cli/src/commands/pr/create.rs @@ -1,6 +1,6 @@ use std::path::Path; -use anyhow::{bail, Context, Result}; +use anyhow::{Context, Result, bail}; use fabro_config::FabroSettingsExt; use fabro_model::Catalog; use fabro_sandbox::daytona::detect_repo_info; diff --git a/lib/crates/fabro-cli/src/commands/preflight.rs b/lib/crates/fabro-cli/src/commands/preflight.rs index 84ad34264..af3f8c02b 100644 --- a/lib/crates/fabro-cli/src/commands/preflight.rs +++ b/lib/crates/fabro-cli/src/commands/preflight.rs @@ -5,18 +5,18 @@ use anyhow::bail; use fabro_agent::{DockerSandbox, DockerSandboxConfig, LocalSandbox, Sandbox}; use fabro_config::cli::load_cli_config; use fabro_config::project::{ - resolve_settings, resolve_workflow_path, resolve_working_directory, ResolveSettingsInput, + ResolveSettingsInput, resolve_settings, resolve_workflow_path, resolve_working_directory, }; use fabro_config::{FabroConfig, FabroSettings}; -use fabro_graphviz::graph::{is_llm_handler_type, Graph}; +use fabro_graphviz::graph::{Graph, is_llm_handler_type}; use fabro_llm::client::Client as LlmClient; use fabro_model::{Catalog, Provider}; -use fabro_sandbox::daytona::{detect_repo_info, DaytonaConfig, DaytonaSandbox}; -use fabro_sandbox::ssh::{GitCloneParams as SshGitCloneParams, SshConfig, SshSandbox}; use fabro_sandbox::SandboxProvider; +use fabro_sandbox::daytona::{DaytonaConfig, DaytonaSandbox, detect_repo_info}; +use fabro_sandbox::ssh::{GitCloneParams as SshGitCloneParams, SshConfig, SshSandbox}; use fabro_util::terminal::Styles; -use fabro_workflows::git::{sync_status, GitSyncStatus}; -use fabro_workflows::operations::{validate, ValidateInput, WorkflowInput}; +use fabro_workflows::git::{GitSyncStatus, sync_status}; +use fabro_workflows::operations::{ValidateInput, WorkflowInput, validate}; use crate::args::PreflightArgs; use crate::shared::github::build_github_app_credentials; diff --git a/lib/crates/fabro-cli/src/commands/repo/deinit.rs b/lib/crates/fabro-cli/src/commands/repo/deinit.rs index e4cb6f70f..5d43a334d 100644 --- a/lib/crates/fabro-cli/src/commands/repo/deinit.rs +++ b/lib/crates/fabro-cli/src/commands/repo/deinit.rs @@ -1,4 +1,4 @@ -use anyhow::{bail, Context, Result}; +use anyhow::{Context, Result, bail}; pub fn run_deinit() -> Result<()> { let repo_root = super::init::git_repo_root()?; diff --git a/lib/crates/fabro-cli/src/commands/repo/init.rs b/lib/crates/fabro-cli/src/commands/repo/init.rs index 20789e871..ddbf7d475 100644 --- a/lib/crates/fabro-cli/src/commands/repo/init.rs +++ b/lib/crates/fabro-cli/src/commands/repo/init.rs @@ -1,6 +1,6 @@ use std::path::PathBuf; -use anyhow::{bail, Context, Result}; +use anyhow::{Context, Result, bail}; use tokio::task::spawn_blocking; use crate::cli_config::load_cli_settings; diff --git a/lib/crates/fabro-cli/src/commands/run/attach.rs b/lib/crates/fabro-cli/src/commands/run/attach.rs index 4fddbb5a1..b57692b81 100644 --- a/lib/crates/fabro-cli/src/commands/run/attach.rs +++ b/lib/crates/fabro-cli/src/commands/run/attach.rs @@ -1,11 +1,11 @@ use std::io::{BufRead, BufReader, IsTerminal, Write}; use std::path::{Path, PathBuf}; use std::process::ExitCode; -use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; use std::time::{Duration, Instant}; -use anyhow::{bail, Result}; +use anyhow::{Result, bail}; use fabro_interview::{AnswerValue, ConsoleInterviewer}; use fabro_store::RuntimeState; @@ -490,7 +490,7 @@ mod tests { use fabro_util::terminal::Styles; use fabro_workflows::outcome::StageStatus; use fabro_workflows::records::Conclusion; - use fabro_workflows::run_status::{write_run_status, StatusReason}; + use fabro_workflows::run_status::{StatusReason, write_run_status}; fn no_color_styles() -> &'static Styles { Box::leak(Box::new(Styles::new(false))) diff --git a/lib/crates/fabro-cli/src/commands/run/cp.rs b/lib/crates/fabro-cli/src/commands/run/cp.rs index 9fc0b8711..4d047877d 100644 --- a/lib/crates/fabro-cli/src/commands/run/cp.rs +++ b/lib/crates/fabro-cli/src/commands/run/cp.rs @@ -1,10 +1,10 @@ use std::path::{Path, PathBuf}; -use anyhow::{bail, Context, Result}; +use anyhow::{Context, Result, bail}; use fabro_agent::sandbox::Sandbox; use fabro_config::FabroSettingsExt; -use fabro_sandbox::reconnect::reconnect; use fabro_sandbox::SandboxRecordExt; +use fabro_sandbox::reconnect::reconnect; use fabro_workflows::run_lookup::{resolve_run, runs_base}; use tokio::fs; use tracing::{debug, info}; diff --git a/lib/crates/fabro-cli/src/commands/run/create.rs b/lib/crates/fabro-cli/src/commands/run/create.rs index b09da535c..85811b18b 100644 --- a/lib/crates/fabro-cli/src/commands/run/create.rs +++ b/lib/crates/fabro-cli/src/commands/run/create.rs @@ -1,11 +1,11 @@ use std::path::PathBuf; use crate::args::RunArgs; -use fabro_config::project::{resolve_settings, ResolveSettingsInput}; +use fabro_config::project::{ResolveSettingsInput, resolve_settings}; use fabro_config::{FabroConfig, FabroSettings}; use fabro_util::terminal::Styles; use fabro_workflows::error::FabroError; -use fabro_workflows::operations::{create, CreateRunInput, WorkflowInput}; +use fabro_workflows::operations::{CreateRunInput, WorkflowInput, create}; use super::output::{print_diagnostics_from_error, print_workflow_report_from_persisted}; diff --git a/lib/crates/fabro-cli/src/commands/run/detached.rs b/lib/crates/fabro-cli/src/commands/run/detached.rs index abe80604d..d1f93d3a7 100644 --- a/lib/crates/fabro-cli/src/commands/run/detached.rs +++ b/lib/crates/fabro-cli/src/commands/run/detached.rs @@ -6,7 +6,7 @@ use fabro_interview::FileInterviewer; use fabro_store::RuntimeState; use fabro_workflows::event::EventEmitter; use fabro_workflows::git::GitAuthor; -use fabro_workflows::operations::{resume as resume_run, start as start_run, StartServices}; +use fabro_workflows::operations::{StartServices, resume as resume_run, start as start_run}; use crate::cli_config; use crate::shared; diff --git a/lib/crates/fabro-cli/src/commands/run/diff.rs b/lib/crates/fabro-cli/src/commands/run/diff.rs index 9a17d575a..ffa18adf6 100644 --- a/lib/crates/fabro-cli/src/commands/run/diff.rs +++ b/lib/crates/fabro-cli/src/commands/run/diff.rs @@ -1,10 +1,10 @@ use std::io::{self, IsTerminal, Write}; use std::path::Path; -use anyhow::{bail, Context, Result}; +use anyhow::{Context, Result, bail}; use fabro_config::FabroSettingsExt; -use fabro_sandbox::reconnect::reconnect; use fabro_sandbox::SandboxRecordExt; +use fabro_sandbox::reconnect::reconnect; use fabro_workflows::records::{StartRecord, StartRecordExt}; use fabro_workflows::run_lookup::{resolve_run, runs_base}; use fabro_workflows::sandbox_git::GIT_REMOTE; diff --git a/lib/crates/fabro-cli/src/commands/run/fork.rs b/lib/crates/fabro-cli/src/commands/run/fork.rs index f33861283..49d24db00 100644 --- a/lib/crates/fabro-cli/src/commands/run/fork.rs +++ b/lib/crates/fabro-cli/src/commands/run/fork.rs @@ -3,7 +3,7 @@ use anyhow::Result; use fabro_git_storage::gitobj::Store; use fabro_util::terminal::Styles; use fabro_workflows::operations::{ - build_timeline, find_run_id_by_prefix, fork, ForkRunInput, RewindTarget, + ForkRunInput, RewindTarget, build_timeline, find_run_id_by_prefix, fork, }; use git2::Repository; diff --git a/lib/crates/fabro-cli/src/commands/run/logs.rs b/lib/crates/fabro-cli/src/commands/run/logs.rs index 680c57b8d..e0aabac80 100644 --- a/lib/crates/fabro-cli/src/commands/run/logs.rs +++ b/lib/crates/fabro-cli/src/commands/run/logs.rs @@ -1,7 +1,7 @@ use std::io::{self, BufRead, IsTerminal, Write}; use std::path::Path; -use anyhow::{bail, Context, Result}; +use anyhow::{Context, Result, bail}; use chrono::{DateTime, Utc}; use fabro_config::FabroSettingsExt; use fabro_util::terminal::Styles; diff --git a/lib/crates/fabro-cli/src/commands/run/mod.rs b/lib/crates/fabro-cli/src/commands/run/mod.rs index d33245623..91b55f805 100644 --- a/lib/crates/fabro-cli/src/commands/run/mod.rs +++ b/lib/crates/fabro-cli/src/commands/run/mod.rs @@ -1,6 +1,6 @@ use anyhow::Result; -use fabro_config::cli::load_cli_config; use fabro_config::FabroSettingsExt; +use fabro_config::cli::load_cli_config; use fabro_util::terminal::Styles; use fabro_workflows::run_lookup::{resolve_run, runs_base}; diff --git a/lib/crates/fabro-cli/src/commands/run/output.rs b/lib/crates/fabro-cli/src/commands/run/output.rs index 3b41cd1d5..d5a22fac2 100644 --- a/lib/crates/fabro-cli/src/commands/run/output.rs +++ b/lib/crates/fabro-cli/src/commands/run/output.rs @@ -6,7 +6,7 @@ use fabro_store::RuntimeState; use fabro_util::terminal::Styles; use fabro_util::text::strip_goal_decoration; use fabro_workflows::asset_snapshot::collect_asset_paths; -use fabro_workflows::outcome::{format_cost, StageStatus}; +use fabro_workflows::outcome::{StageStatus, format_cost}; use fabro_workflows::pipeline::{Persisted, Validated}; use fabro_workflows::pull_request::PullRequestRecord; use fabro_workflows::records::{Checkpoint, CheckpointExt, Conclusion, ConclusionExt}; diff --git a/lib/crates/fabro-cli/src/commands/run/overrides.rs b/lib/crates/fabro-cli/src/commands/run/overrides.rs index a68ab9868..df6042888 100644 --- a/lib/crates/fabro-cli/src/commands/run/overrides.rs +++ b/lib/crates/fabro-cli/src/commands/run/overrides.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use anyhow::Result; use fabro_config::run::LlmConfig; -use fabro_config::{sandbox as sandbox_config, FabroConfig}; +use fabro_config::{FabroConfig, sandbox as sandbox_config}; use fabro_sandbox::SandboxProvider; use crate::args::{PreflightArgs, RunArgs}; diff --git a/lib/crates/fabro-cli/src/commands/run/preview.rs b/lib/crates/fabro-cli/src/commands/run/preview.rs index d28113a10..d0aaf7e2d 100644 --- a/lib/crates/fabro-cli/src/commands/run/preview.rs +++ b/lib/crates/fabro-cli/src/commands/run/preview.rs @@ -1,7 +1,7 @@ use anyhow::{Context, Result}; use fabro_config::FabroSettingsExt; -use fabro_sandbox::daytona::DaytonaSandbox; use fabro_sandbox::SandboxRecordExt; +use fabro_sandbox::daytona::DaytonaSandbox; use fabro_workflows::run_lookup::{resolve_run, runs_base}; use tracing::info; diff --git a/lib/crates/fabro-cli/src/commands/run/rewind.rs b/lib/crates/fabro-cli/src/commands/run/rewind.rs index 7a735dcc9..af4b23f9f 100644 --- a/lib/crates/fabro-cli/src/commands/run/rewind.rs +++ b/lib/crates/fabro-cli/src/commands/run/rewind.rs @@ -1,11 +1,11 @@ use anyhow::Context; use anyhow::Result; use cli_table::format::{Border, Separator}; -use cli_table::{print_stderr, Cell, CellStruct, Color, Style, Table}; +use cli_table::{Cell, CellStruct, Color, Style, Table, print_stderr}; use fabro_git_storage::gitobj::Store; use fabro_util::terminal::Styles; use fabro_workflows::operations::{ - build_timeline, find_run_id_by_prefix, rewind, RewindInput, RewindTarget, RunTimeline, + RewindInput, RewindTarget, RunTimeline, build_timeline, find_run_id_by_prefix, rewind, }; use git2::Repository; diff --git a/lib/crates/fabro-cli/src/commands/run/ssh.rs b/lib/crates/fabro-cli/src/commands/run/ssh.rs index ed9de411c..e07258b20 100644 --- a/lib/crates/fabro-cli/src/commands/run/ssh.rs +++ b/lib/crates/fabro-cli/src/commands/run/ssh.rs @@ -1,7 +1,7 @@ -use anyhow::{bail, Context, Result}; +use anyhow::{Context, Result, bail}; use fabro_config::FabroSettingsExt; -use fabro_sandbox::daytona::DaytonaSandbox; use fabro_sandbox::SandboxRecordExt; +use fabro_sandbox::daytona::DaytonaSandbox; use fabro_workflows::run_lookup::{resolve_run, runs_base}; use tracing::info; diff --git a/lib/crates/fabro-cli/src/commands/run/start.rs b/lib/crates/fabro-cli/src/commands/run/start.rs index 9cd6002ac..d8ed145b5 100644 --- a/lib/crates/fabro-cli/src/commands/run/start.rs +++ b/lib/crates/fabro-cli/src/commands/run/start.rs @@ -1,13 +1,13 @@ use std::path::Path; -use anyhow::{anyhow, Result}; +use anyhow::{Result, anyhow}; use chrono::Utc; use fabro_config::FabroSettingsExt; use fabro_workflows::records::{RunRecord, RunRecordExt}; use super::launcher::{ - launcher_log_path, launcher_record_path, remove_launcher_record, write_launcher_record, - LauncherRecord, + LauncherRecord, launcher_log_path, launcher_record_path, remove_launcher_record, + write_launcher_record, }; /// Spawn a detached engine process for the given run directory. diff --git a/lib/crates/fabro-cli/src/commands/run/wait.rs b/lib/crates/fabro-cli/src/commands/run/wait.rs index 71eb92a02..b37ed4746 100644 --- a/lib/crates/fabro-cli/src/commands/run/wait.rs +++ b/lib/crates/fabro-cli/src/commands/run/wait.rs @@ -1,6 +1,6 @@ use std::io::Write; -use anyhow::{bail, Result}; +use anyhow::{Result, bail}; use fabro_config::FabroSettingsExt; use fabro_util::terminal::Styles; use fabro_workflows::records::{Conclusion, ConclusionExt}; diff --git a/lib/crates/fabro-cli/src/commands/runs/list.rs b/lib/crates/fabro-cli/src/commands/runs/list.rs index 8b3c0e907..d4dbb9dc8 100644 --- a/lib/crates/fabro-cli/src/commands/runs/list.rs +++ b/lib/crates/fabro-cli/src/commands/runs/list.rs @@ -3,12 +3,12 @@ use std::path::Path; use anyhow::Result; use chrono::Utc; use cli_table::format::{Border, Separator}; -use cli_table::{print_stdout, Cell, CellStruct, Color, Style, Table}; +use cli_table::{Cell, CellStruct, Color, Style, Table, print_stdout}; use fabro_config::FabroSettingsExt; use fabro_util::terminal::Styles; use fabro_util::text::strip_goal_decoration; -use fabro_workflows::run_lookup::{filter_runs, runs_base, scan_runs, StatusFilter}; +use fabro_workflows::run_lookup::{StatusFilter, filter_runs, runs_base, scan_runs}; use fabro_workflows::run_status::RunStatus; use crate::args::RunsListArgs; diff --git a/lib/crates/fabro-cli/src/commands/runs/mod.rs b/lib/crates/fabro-cli/src/commands/runs/mod.rs index 37390c616..30eb94e3d 100644 --- a/lib/crates/fabro-cli/src/commands/runs/mod.rs +++ b/lib/crates/fabro-cli/src/commands/runs/mod.rs @@ -19,11 +19,7 @@ pub async fn dispatch(cmd: RunsCommands) -> Result<()> { } pub(super) fn short_run_id(id: &str) -> &str { - if id.len() > 12 { - &id[..12] - } else { - id - } + if id.len() > 12 { &id[..12] } else { id } } #[cfg(test)] diff --git a/lib/crates/fabro-cli/src/commands/runs/rm.rs b/lib/crates/fabro-cli/src/commands/runs/rm.rs index c1f202088..11987bf2d 100644 --- a/lib/crates/fabro-cli/src/commands/runs/rm.rs +++ b/lib/crates/fabro-cli/src/commands/runs/rm.rs @@ -1,13 +1,13 @@ use std::path::Path; -use anyhow::{bail, Context, Result}; +use anyhow::{Context, Result, bail}; use fabro_config::FabroSettingsExt; use fabro_sandbox::SandboxRecordExt; use tracing::warn; use fabro_sandbox::reconnect::reconnect as reconnect_sandbox; use fabro_workflows::run_lookup::{resolve_run, runs_base}; -use fabro_workflows::run_status::{write_run_status, RunStatus}; +use fabro_workflows::run_status::{RunStatus, write_run_status}; use crate::args::RunsRemoveArgs; use crate::cli_config::load_cli_settings; diff --git a/lib/crates/fabro-cli/src/commands/secret/get.rs b/lib/crates/fabro-cli/src/commands/secret/get.rs index c9b5b96c0..43c4e701e 100644 --- a/lib/crates/fabro-cli/src/commands/secret/get.rs +++ b/lib/crates/fabro-cli/src/commands/secret/get.rs @@ -1,4 +1,4 @@ -use anyhow::{bail, Result}; +use anyhow::{Result, bail}; use crate::args::SecretGetArgs; use fabro_config::dotenv; diff --git a/lib/crates/fabro-cli/src/commands/secret/list.rs b/lib/crates/fabro-cli/src/commands/secret/list.rs index 06197ac2d..b638c47e4 100644 --- a/lib/crates/fabro-cli/src/commands/secret/list.rs +++ b/lib/crates/fabro-cli/src/commands/secret/list.rs @@ -1,4 +1,4 @@ -use anyhow::{bail, Result}; +use anyhow::{Result, bail}; use crate::args::SecretListArgs; use fabro_config::dotenv; diff --git a/lib/crates/fabro-cli/src/commands/secret/rm.rs b/lib/crates/fabro-cli/src/commands/secret/rm.rs index bb6f7fca2..4bbdaae1b 100644 --- a/lib/crates/fabro-cli/src/commands/secret/rm.rs +++ b/lib/crates/fabro-cli/src/commands/secret/rm.rs @@ -1,4 +1,4 @@ -use anyhow::{bail, Result}; +use anyhow::{Result, bail}; use crate::args::SecretRmArgs; use fabro_config::dotenv; diff --git a/lib/crates/fabro-cli/src/commands/skill/install.rs b/lib/crates/fabro-cli/src/commands/skill/install.rs index cc6ae52da..4e2d4dae5 100644 --- a/lib/crates/fabro-cli/src/commands/skill/install.rs +++ b/lib/crates/fabro-cli/src/commands/skill/install.rs @@ -1,6 +1,6 @@ use std::path::Path; -use anyhow::{bail, Result}; +use anyhow::{Result, bail}; use tracing::{debug, info}; use crate::args::{SkillDir, SkillInstallArgs, SkillScope}; diff --git a/lib/crates/fabro-cli/src/commands/system/df.rs b/lib/crates/fabro-cli/src/commands/system/df.rs index c7aa804c5..fc491e1f7 100644 --- a/lib/crates/fabro-cli/src/commands/system/df.rs +++ b/lib/crates/fabro-cli/src/commands/system/df.rs @@ -3,7 +3,7 @@ use std::path::Path; use anyhow::Result; use chrono::{DateTime, Utc}; use cli_table::format::{Border, Justify, Separator}; -use cli_table::{print_stdout, Cell, CellStruct, Style, Table}; +use cli_table::{Cell, CellStruct, Style, Table, print_stdout}; use fabro_config::FabroSettingsExt; use fabro_workflows::run_lookup::{logs_base, runs_base, scan_runs}; @@ -199,11 +199,7 @@ fn df_from(args: &DfArgs, data_dir: &Path, runs_base: &Path, logs_base: &Path) - } fn short_run_id(id: &str) -> &str { - if id.len() > 12 { - &id[..12] - } else { - id - } + if id.len() > 12 { &id[..12] } else { id } } fn truncate_str(s: &str, max_len: usize) -> String { diff --git a/lib/crates/fabro-cli/src/commands/system/prune.rs b/lib/crates/fabro-cli/src/commands/system/prune.rs index 651be4cc1..e41814669 100644 --- a/lib/crates/fabro-cli/src/commands/system/prune.rs +++ b/lib/crates/fabro-cli/src/commands/system/prune.rs @@ -1,11 +1,11 @@ use std::path::Path; -use anyhow::{bail, Context, Result}; +use anyhow::{Context, Result, bail}; use chrono::Utc; use fabro_config::FabroSettingsExt; use tracing::{debug, info}; -use fabro_workflows::run_lookup::{filter_runs, runs_base, scan_runs, StatusFilter}; +use fabro_workflows::run_lookup::{StatusFilter, filter_runs, runs_base, scan_runs}; use crate::args::RunsPruneArgs; use crate::cli_config::load_cli_settings; diff --git a/lib/crates/fabro-cli/src/commands/upgrade.rs b/lib/crates/fabro-cli/src/commands/upgrade.rs index 8a4474d4f..d0b61da8b 100644 --- a/lib/crates/fabro-cli/src/commands/upgrade.rs +++ b/lib/crates/fabro-cli/src/commands/upgrade.rs @@ -2,7 +2,7 @@ use std::fs; use std::io::{IsTerminal, Write}; use std::path::{Path, PathBuf}; -use anyhow::{bail, Context, Result}; +use anyhow::{Context, Result, bail}; use semver::Version; use sha2::{Digest, Sha256}; use tracing::debug; diff --git a/lib/crates/fabro-cli/src/commands/validate.rs b/lib/crates/fabro-cli/src/commands/validate.rs index bd49182b7..1bb9510c3 100644 --- a/lib/crates/fabro-cli/src/commands/validate.rs +++ b/lib/crates/fabro-cli/src/commands/validate.rs @@ -1,10 +1,10 @@ use anyhow::bail; -use fabro_config::cli::load_cli_config; -use fabro_config::project::{resolve_settings, resolve_workflow_path, ResolveSettingsInput}; use fabro_config::FabroConfig; +use fabro_config::cli::load_cli_config; +use fabro_config::project::{ResolveSettingsInput, resolve_settings, resolve_workflow_path}; use fabro_util::terminal::Styles; use fabro_validate::Severity; -use fabro_workflows::operations::{validate, ValidateInput, WorkflowInput}; +use fabro_workflows::operations::{ValidateInput, WorkflowInput, validate}; use crate::args::ValidateArgs; use crate::shared::{print_diagnostics, relative_path}; diff --git a/lib/crates/fabro-cli/src/commands/workflow/create.rs b/lib/crates/fabro-cli/src/commands/workflow/create.rs index 9a4f2dab3..71ad67add 100644 --- a/lib/crates/fabro-cli/src/commands/workflow/create.rs +++ b/lib/crates/fabro-cli/src/commands/workflow/create.rs @@ -1,6 +1,6 @@ use std::path::Path; -use anyhow::{bail, Context, Result}; +use anyhow::{Context, Result, bail}; use fabro_config::project::{discover_project_config, resolve_fabro_root}; diff --git a/lib/crates/fabro-cli/src/commands/workflow/list.rs b/lib/crates/fabro-cli/src/commands/workflow/list.rs index c772effa1..49e97ee89 100644 --- a/lib/crates/fabro-cli/src/commands/workflow/list.rs +++ b/lib/crates/fabro-cli/src/commands/workflow/list.rs @@ -1,9 +1,9 @@ -use anyhow::{bail, Result}; +use anyhow::{Result, bail}; use fabro_util::terminal::Styles; use fabro_config::project::{ - discover_project_config, list_workflows_detailed, resolve_fabro_root, WorkflowInfo, - WorkflowSource, + WorkflowInfo, WorkflowSource, discover_project_config, list_workflows_detailed, + resolve_fabro_root, }; use crate::args::WorkflowListArgs; diff --git a/lib/crates/fabro-cli/src/logging.rs b/lib/crates/fabro-cli/src/logging.rs index affcefdb6..f8a71e759 100644 --- a/lib/crates/fabro-cli/src/logging.rs +++ b/lib/crates/fabro-cli/src/logging.rs @@ -1,7 +1,7 @@ use anyhow::{Context, Result}; use fabro_util::run_log; use tracing_appender::rolling; -use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; +use tracing_subscriber::{EnvFilter, fmt, layer::SubscriberExt, util::SubscriberInitExt}; pub fn init_tracing(debug: bool, config_log_level: Option<&str>, log_prefix: &str) -> Result<()> { let default_level = if debug { diff --git a/lib/crates/fabro-cli/src/main.rs b/lib/crates/fabro-cli/src/main.rs index eb6d26dd8..4d31a1964 100644 --- a/lib/crates/fabro-cli/src/main.rs +++ b/lib/crates/fabro-cli/src/main.rs @@ -7,7 +7,7 @@ mod shared; mod sleep_inhibitor; use anyhow::Result; -use args::{Commands, GlobalArgs, RunCommands, LONG_VERSION}; +use args::{Commands, GlobalArgs, LONG_VERSION, RunCommands}; use clap::Parser; use fabro_telemetry::{git, panic as tel_panic, sanitize, sender}; use fabro_util::terminal::Styles; diff --git a/lib/crates/fabro-cli/src/shared/github.rs b/lib/crates/fabro-cli/src/shared/github.rs index 19c93c78c..79b176e39 100644 --- a/lib/crates/fabro-cli/src/shared/github.rs +++ b/lib/crates/fabro-cli/src/shared/github.rs @@ -1,5 +1,5 @@ -use base64::engine::general_purpose::STANDARD as BASE64_STANDARD; use base64::Engine as _; +use base64::engine::general_purpose::STANDARD as BASE64_STANDARD; use fabro_github::GitHubAppCredentials; pub(crate) fn build_github_app_credentials(app_id: Option<&str>) -> Option { diff --git a/lib/crates/fabro-cli/src/shared/provider_auth.rs b/lib/crates/fabro-cli/src/shared/provider_auth.rs index 711a64e15..4e8a51528 100644 --- a/lib/crates/fabro-cli/src/shared/provider_auth.rs +++ b/lib/crates/fabro-cli/src/shared/provider_auth.rs @@ -6,7 +6,7 @@ use dialoguer::theme::ColorfulTheme; use dialoguer::{Confirm, Password}; use fabro_config::dotenv::{merge_env, write_env_file as write_env}; use fabro_llm::client::Client as LlmClient; -use fabro_llm::generate::{generate, GenerateParams}; +use fabro_llm::generate::{GenerateParams, generate}; use fabro_model::Provider; use fabro_util::terminal::Styles; use tokio::task::spawn_blocking; diff --git a/lib/crates/fabro-cli/src/shared/utilities.rs b/lib/crates/fabro-cli/src/shared/utilities.rs index ed92a731f..e4c6dfab2 100644 --- a/lib/crates/fabro-cli/src/shared/utilities.rs +++ b/lib/crates/fabro-cli/src/shared/utilities.rs @@ -1,7 +1,7 @@ use std::path::Path; use std::time::Duration; -use anyhow::{bail, Result}; +use anyhow::{Result, bail}; use cli_table::Color; use fabro_util::terminal::Styles; use fabro_validate::{Diagnostic, Severity}; @@ -70,11 +70,7 @@ pub fn tilde_path(path: &Path) -> String { } pub fn color_if(use_color: bool, color: Color) -> Option { - if use_color { - Some(color) - } else { - None - } + if use_color { Some(color) } else { None } } pub fn split_run_path(s: &str) -> Option<(&str, &str)> { diff --git a/lib/crates/fabro-cli/tests/cli.rs b/lib/crates/fabro-cli/tests/cli.rs index 2d3f52ae8..49a38c248 100644 --- a/lib/crates/fabro-cli/tests/cli.rs +++ b/lib/crates/fabro-cli/tests/cli.rs @@ -1,6 +1,6 @@ use assert_cmd::Command; -use fabro_config::mcp::McpTransport; use fabro_config::FabroSettings; +use fabro_config::mcp::McpTransport; use fabro_store::RuntimeState; use predicates::prelude::*; @@ -1450,9 +1450,11 @@ fn attach_supports_legacy_root_interview_paths() { assert!(run_dir.join("interview_request.json").exists()); assert!(run_dir.join("interview_response.json").exists()); - assert!(!RuntimeState::new(&run_dir) - .interview_response_path() - .exists()); + assert!( + !RuntimeState::new(&run_dir) + .interview_response_path() + .exists() + ); } // Bug 4: attach should respect the verbose flag from run.json. @@ -1594,14 +1596,16 @@ fn config_show_workflow_name_applies_run_overlay_and_deep_merges() { .find(|hook| hook.name.as_deref() == Some("shared")) .expect("shared hook"); assert_eq!(shared_hook.command.as_deref(), Some("echo run")); - assert!(cfg - .hooks - .iter() - .any(|hook| hook.name.as_deref() == Some("project"))); - assert!(cfg - .hooks - .iter() - .any(|hook| hook.name.as_deref() == Some("run-only"))); + assert!( + cfg.hooks + .iter() + .any(|hook| hook.name.as_deref() == Some("project")) + ); + assert!( + cfg.hooks + .iter() + .any(|hook| hook.name.as_deref() == Some("run-only")) + ); match &cfg.mcp_servers["shared"].transport { McpTransport::Stdio { command, .. } => assert_eq!(command, &vec!["echo", "run"]), diff --git a/lib/crates/fabro-config/src/dotenv.rs b/lib/crates/fabro-config/src/dotenv.rs index e51e73b2c..a032694c7 100644 --- a/lib/crates/fabro-config/src/dotenv.rs +++ b/lib/crates/fabro-config/src/dotenv.rs @@ -2,7 +2,7 @@ use std::path::{Path, PathBuf}; -use anyhow::{bail, Context, Result}; +use anyhow::{Context, Result, bail}; /// Return the path to `~/.fabro/.env`. pub fn env_file_path() -> Result { diff --git a/lib/crates/fabro-config/src/project.rs b/lib/crates/fabro-config/src/project.rs index c7e2a60e6..a37f5a89a 100644 --- a/lib/crates/fabro-config/src/project.rs +++ b/lib/crates/fabro-config/src/project.rs @@ -1,11 +1,11 @@ use std::path::{Path, PathBuf}; -use anyhow::{bail, Context}; +use anyhow::{Context, bail}; use serde::{Deserialize, Serialize}; +use crate::FabroSettings; use crate::config::FabroConfig; use crate::run; -use crate::FabroSettings; pub use fabro_types::settings::project::ProjectFabroSettings; const CONFIG_FILENAME: &str = "fabro.toml"; diff --git a/lib/crates/fabro-config/src/run.rs b/lib/crates/fabro-config/src/run.rs index 55d4b9dec..a097b4b17 100644 --- a/lib/crates/fabro-config/src/run.rs +++ b/lib/crates/fabro-config/src/run.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use std::path::{Path, PathBuf}; -use anyhow::{bail, Context}; +use anyhow::{Context, bail}; use serde::{Deserialize, Serialize}; use tracing::debug; diff --git a/lib/crates/fabro-core/src/error.rs b/lib/crates/fabro-core/src/error.rs index 9b97c71d4..f29bee80f 100644 --- a/lib/crates/fabro-core/src/error.rs +++ b/lib/crates/fabro-core/src/error.rs @@ -43,7 +43,9 @@ pub enum CoreError { Cancelled, #[error("blocked: {message}")] Blocked { message: String }, - #[error("node \"{node_id}\" visited {visits} times ({limit_source} limit {limit}); run is stuck in a cycle")] + #[error( + "node \"{node_id}\" visited {visits} times ({limit_source} limit {limit}); run is stuck in a cycle" + )] VisitLimitExceeded { node_id: String, visits: usize, @@ -177,10 +179,12 @@ mod tests { assert!(!CoreError::NodeNotFound { id: "x".into() }.is_retryable()); assert!(!CoreError::Cancelled.is_retryable()); assert!(!CoreError::NoStartNode.is_retryable()); - assert!(!CoreError::Blocked { - message: "no".into() - } - .is_retryable()); + assert!( + !CoreError::Blocked { + message: "no".into() + } + .is_retryable() + ); assert!(!CoreError::Other("err".into()).is_retryable()); } } diff --git a/lib/crates/fabro-core/src/executor.rs b/lib/crates/fabro-core/src/executor.rs index 0d7180047..12a1715bc 100644 --- a/lib/crates/fabro-core/src/executor.rs +++ b/lib/crates/fabro-core/src/executor.rs @@ -1,5 +1,5 @@ -use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Instant; use tokio_util::sync::CancellationToken; diff --git a/lib/crates/fabro-core/src/lifecycle.rs b/lib/crates/fabro-core/src/lifecycle.rs index 67ba92296..667bae801 100644 --- a/lib/crates/fabro-core/src/lifecycle.rs +++ b/lib/crates/fabro-core/src/lifecycle.rs @@ -266,7 +266,7 @@ mod tests { use std::sync::{Arc, Mutex}; use super::*; - use crate::test_fixtures::{linear_graph, TestGraph, TestNode}; + use crate::test_fixtures::{TestGraph, TestNode, linear_graph}; /// A lifecycle that records which callbacks were called. struct RecordingLifecycle { diff --git a/lib/crates/fabro-core/src/stall.rs b/lib/crates/fabro-core/src/stall.rs index e1184497d..83ee3fc05 100644 --- a/lib/crates/fabro-core/src/stall.rs +++ b/lib/crates/fabro-core/src/stall.rs @@ -1,5 +1,5 @@ -use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Duration; use tokio::sync::Notify; diff --git a/lib/crates/fabro-core/src/test_fixtures.rs b/lib/crates/fabro-core/src/test_fixtures.rs index 79ef70b5b..1e85074f4 100644 --- a/lib/crates/fabro-core/src/test_fixtures.rs +++ b/lib/crates/fabro-core/src/test_fixtures.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use std::sync::atomic::{AtomicU32, Ordering}; use std::sync::Arc; +use std::sync::atomic::{AtomicU32, Ordering}; use async_trait::async_trait; diff --git a/lib/crates/fabro-db/src/lib.rs b/lib/crates/fabro-db/src/lib.rs index 382dfbaf7..e796670b3 100644 --- a/lib/crates/fabro-db/src/lib.rs +++ b/lib/crates/fabro-db/src/lib.rs @@ -4,8 +4,8 @@ pub mod workflow_run; use std::path::Path; use std::time::Duration; -use sqlx::sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePoolOptions}; use sqlx::SqlitePool; +use sqlx::sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePoolOptions}; use tracing::debug; pub use migrate::initialize_db; diff --git a/lib/crates/fabro-devcontainer/src/features.rs b/lib/crates/fabro-devcontainer/src/features.rs index d3fd1e3d2..217257762 100644 --- a/lib/crates/fabro-devcontainer/src/features.rs +++ b/lib/crates/fabro-devcontainer/src/features.rs @@ -5,8 +5,8 @@ use tokio::fs; use tokio::process::Command; use tracing::info; -use crate::types::{FeatureMetadata, LifecycleCommand}; use crate::DevcontainerError; +use crate::types::{FeatureMetadata, LifecycleCommand}; /// A resolved feature layer ready to be inserted into a Dockerfile. #[derive(Debug, Clone)] @@ -1123,9 +1123,11 @@ mod tests { let resolved = resolve_features(&features, tmp.path(), None).await.unwrap(); assert_eq!(resolved.layers.len(), 1); assert_eq!(resolved.layers[0].dir_name, "node"); - assert!(resolved.layers[0] - .dockerfile_snippet - .contains("export VERSION=\"20\"")); + assert!( + resolved.layers[0] + .dockerfile_snippet + .contains("export VERSION=\"20\"") + ); } #[test] diff --git a/lib/crates/fabro-devcontainer/src/lib.rs b/lib/crates/fabro-devcontainer/src/lib.rs index 33b14f63d..87769566b 100644 --- a/lib/crates/fabro-devcontainer/src/lib.rs +++ b/lib/crates/fabro-devcontainer/src/lib.rs @@ -83,7 +83,9 @@ pub enum DevcontainerError { #[error("variable substitution error: {0}")] Variable(String), - #[error("base Dockerfile contains COPY or ADD instructions that reference build context files, which is not supported by Daytona snapshots: {0}")] + #[error( + "base Dockerfile contains COPY or ADD instructions that reference build context files, which is not supported by Daytona snapshots: {0}" + )] UnsupportedCopyAdd(String), } diff --git a/lib/crates/fabro-devcontainer/src/types.rs b/lib/crates/fabro-devcontainer/src/types.rs index 6e416d907..042c5ea80 100644 --- a/lib/crates/fabro-devcontainer/src/types.rs +++ b/lib/crates/fabro-devcontainer/src/types.rs @@ -301,9 +301,10 @@ mod tests { }"#; let meta: FeatureMetadata = serde_json::from_str(json).unwrap(); assert_eq!(meta.depends_on.len(), 2); - assert!(meta - .depends_on - .contains_key("ghcr.io/devcontainers/features/common-utils:1")); + assert!( + meta.depends_on + .contains_key("ghcr.io/devcontainers/features/common-utils:1") + ); assert_eq!( meta.depends_on.get("ghcr.io/devcontainers/features/node:1"), Some(&serde_json::json!({"version": "20"})) diff --git a/lib/crates/fabro-devcontainer/tests/e2e.rs b/lib/crates/fabro-devcontainer/tests/e2e.rs index 34ceb649b..64a82f785 100644 --- a/lib/crates/fabro-devcontainer/tests/e2e.rs +++ b/lib/crates/fabro-devcontainer/tests/e2e.rs @@ -242,9 +242,11 @@ async fn remote_env_excluded_from_dockerfile() { .unwrap(); // containerEnv IS in the Dockerfile - assert!(config - .dockerfile - .contains("ENV DEBIAN_FRONTEND=noninteractive")); + assert!( + config + .dockerfile + .contains("ENV DEBIAN_FRONTEND=noninteractive") + ); // remoteEnv is NOT in the Dockerfile assert!(!config.dockerfile.contains("EDITOR=code")); @@ -340,9 +342,11 @@ async fn local_feature_refs_resolved() { .unwrap(); // Base image preserved - assert!(config - .dockerfile - .contains("FROM mcr.microsoft.com/devcontainers/base:ubuntu")); + assert!( + config + .dockerfile + .contains("FROM mcr.microsoft.com/devcontainers/base:ubuntu") + ); // Feature install.sh snippets are in the Dockerfile assert!(config.dockerfile.contains("node-feature")); @@ -381,9 +385,11 @@ async fn feature_container_env_merged() { // Feature containerEnv values baked into Dockerfile assert!(config.dockerfile.contains("ENV NODE_INSTALLED=true")); - assert!(config - .dockerfile - .contains("ENV NODE_PATH=/usr/local/lib/node_modules")); + assert!( + config + .dockerfile + .contains("ENV NODE_PATH=/usr/local/lib/node_modules") + ); assert!(config.dockerfile.contains("ENV PYTHON_INSTALLED=true")); assert!(config.dockerfile.contains("ENV BASE_UTILS_INSTALLED=true")); diff --git a/lib/crates/fabro-devcontainer/tests/integration.rs b/lib/crates/fabro-devcontainer/tests/integration.rs index 1bedf35af..df7fa7af7 100644 --- a/lib/crates/fabro-devcontainer/tests/integration.rs +++ b/lib/crates/fabro-devcontainer/tests/integration.rs @@ -13,9 +13,11 @@ async fn resolve_image_only() { .await .unwrap(); - assert!(config - .dockerfile - .contains("FROM mcr.microsoft.com/devcontainers/base:ubuntu")); + assert!( + config + .dockerfile + .contains("FROM mcr.microsoft.com/devcontainers/base:ubuntu") + ); assert_eq!(config.remote_user.as_deref(), Some("vscode")); assert_eq!(config.forwarded_ports, vec![3000, 80, 9090]); assert_eq!( @@ -34,9 +36,11 @@ async fn resolve_image_only() { assert!(matches!(&config.on_create_commands[0], Command::Shell(s) if s == "setup.sh")); // containerEnv baked into Dockerfile - assert!(config - .dockerfile - .contains("ENV DEBIAN_FRONTEND=noninteractive")); + assert!( + config + .dockerfile + .contains("ENV DEBIAN_FRONTEND=noninteractive") + ); assert_eq!( config .container_env @@ -151,9 +155,11 @@ async fn resolve_subdirectory_mode() { .await .unwrap(); - assert!(config - .dockerfile - .contains("FROM mcr.microsoft.com/devcontainers/python:3.12")); + assert!( + config + .dockerfile + .contains("FROM mcr.microsoft.com/devcontainers/python:3.12") + ); assert_eq!(config.remote_user.as_deref(), Some("vscode")); assert_eq!(config.workspace_folder, "/workspaces/subdirectory-mode"); } @@ -165,9 +171,11 @@ async fn resolve_subdirectory_multiple_picks_alphabetical_first() { .unwrap(); // "alpha" sorts before "beta", so alpha's config is used - assert!(config - .dockerfile - .contains("FROM mcr.microsoft.com/devcontainers/base:ubuntu")); + assert!( + config + .dockerfile + .contains("FROM mcr.microsoft.com/devcontainers/base:ubuntu") + ); assert_eq!(config.remote_user.as_deref(), Some("alpha-user")); } @@ -178,9 +186,11 @@ async fn resolve_subdirectory_standard_wins_over_subdirs() { .unwrap(); // Standard .devcontainer/devcontainer.json takes priority over subdirectory format - assert!(config - .dockerfile - .contains("FROM mcr.microsoft.com/devcontainers/base:ubuntu")); + assert!( + config + .dockerfile + .contains("FROM mcr.microsoft.com/devcontainers/base:ubuntu") + ); assert_eq!(config.remote_user.as_deref(), Some("standard-user")); } @@ -191,9 +201,11 @@ async fn generated_dockerfile_is_well_formed() { .unwrap(); // Should start with the generated header - assert!(config - .dockerfile - .contains("# Generated by fabro-devcontainer")); + assert!( + config + .dockerfile + .contains("# Generated by fabro-devcontainer") + ); // Should have the base image assert!(config.dockerfile.contains("FROM")); // Should end with a newline diff --git a/lib/crates/fabro-git-storage/src/branchstore.rs b/lib/crates/fabro-git-storage/src/branchstore.rs index e312a1228..2b8429d7e 100644 --- a/lib/crates/fabro-git-storage/src/branchstore.rs +++ b/lib/crates/fabro-git-storage/src/branchstore.rs @@ -1,8 +1,8 @@ use git2::{Oid, Signature}; use tracing::{debug, warn}; -use crate::gitobj::{FileMode, Store, TreeEntries}; use crate::Result; +use crate::gitobj::{FileMode, Store, TreeEntries}; /// Metadata about a commit, returned by `log`. #[derive(Debug)] diff --git a/lib/crates/fabro-git-storage/src/snapshot.rs b/lib/crates/fabro-git-storage/src/snapshot.rs index c755ab1db..b93fd9fb1 100644 --- a/lib/crates/fabro-git-storage/src/snapshot.rs +++ b/lib/crates/fabro-git-storage/src/snapshot.rs @@ -4,8 +4,8 @@ use std::path::PathBuf; use git2::{Oid, Signature}; use tracing::{debug, warn}; -use crate::gitobj::{FileMode, Store, TreeEntries}; use crate::Result; +use crate::gitobj::{FileMode, Store, TreeEntries}; /// Options for writing a snapshot. pub struct WriteOptions<'a> { @@ -388,10 +388,11 @@ mod tests { .unwrap(), b"new content" ); - assert!(snap - .read_file(result.commit_oid, "to_delete.txt") - .unwrap() - .is_none()); + assert!( + snap.read_file(result.commit_oid, "to_delete.txt") + .unwrap() + .is_none() + ); } // -- write embeds in-memory metadata -- diff --git a/lib/crates/fabro-github/src/lib.rs b/lib/crates/fabro-github/src/lib.rs index 18e9c0eb7..550bb4912 100644 --- a/lib/crates/fabro-github/src/lib.rs +++ b/lib/crates/fabro-github/src/lib.rs @@ -91,7 +91,7 @@ pub fn parse_github_owner_repo(url: &str) -> Result<(String, String), String> { /// /// The JWT is valid for 10 minutes with a 60-second clock skew allowance. pub fn sign_app_jwt(app_id: &str, private_key_pem: &str) -> Result { - use jsonwebtoken::{encode, Algorithm, EncodingKey, Header}; + use jsonwebtoken::{Algorithm, EncodingKey, Header, encode}; use serde::Serialize; #[derive(Serialize)] @@ -556,12 +556,12 @@ pub async fn get_authenticated_app( 401 => { return Err("GitHub App authentication failed. \ Check that app_id and GITHUB_APP_PRIVATE_KEY are correct." - .to_string()) + .to_string()); } status => { return Err(format!( "Unexpected status {status} fetching GitHub App info" - )) + )); } } @@ -670,13 +670,13 @@ pub async fn get_pull_request( 404 => { return Err(format!( "Pull request #{number} not found in {owner}/{repo}" - )) + )); } 401 | 403 => { return Err(format!( "Authentication failed fetching pull request ({})", resp.status() - )) + )); } status => { let body = resp.text().await.unwrap_or_default(); diff --git a/lib/crates/fabro-graphviz/src/parser/grammar.rs b/lib/crates/fabro-graphviz/src/parser/grammar.rs index f8d16ac77..73b0acf4a 100644 --- a/lib/crates/fabro-graphviz/src/parser/grammar.rs +++ b/lib/crates/fabro-graphviz/src/parser/grammar.rs @@ -1,3 +1,4 @@ +use nom::IResult; use nom::branch::alt; use nom::bytes::complete::tag; use nom::character::complete::{char, multispace0}; @@ -5,7 +6,6 @@ use nom::combinator::opt; use nom::error::{Error, ParseError}; use nom::multi::{many0, separated_list0}; use nom::sequence::{delimited, preceded, tuple}; -use nom::IResult; use crate::parser::ast::{ AstValue, AttrBlock, DotGraph, EdgeStmt, NodeStmt, Statement, SubgraphStmt, diff --git a/lib/crates/fabro-graphviz/src/parser/mod.rs b/lib/crates/fabro-graphviz/src/parser/mod.rs index d1080c612..45f390d9e 100644 --- a/lib/crates/fabro-graphviz/src/parser/mod.rs +++ b/lib/crates/fabro-graphviz/src/parser/mod.rs @@ -179,9 +179,11 @@ mod tests { }"#; let graph = parse(input).unwrap(); assert!(graph.nodes["plan"].classes.contains(&"loop-a".to_string())); - assert!(graph.nodes["implement"] - .classes - .contains(&"loop-a".to_string())); + assert!( + graph.nodes["implement"] + .classes + .contains(&"loop-a".to_string()) + ); } #[test] diff --git a/lib/crates/fabro-hooks/src/executor.rs b/lib/crates/fabro-hooks/src/executor.rs index 200d2000a..3bee8130a 100644 --- a/lib/crates/fabro-hooks/src/executor.rs +++ b/lib/crates/fabro-hooks/src/executor.rs @@ -5,10 +5,10 @@ use std::sync::{Arc, LazyLock}; use std::time::Instant; use async_trait::async_trait; -use fabro_agent::tool_registry::ToolContext; use fabro_agent::Sandbox; +use fabro_agent::tool_registry::ToolContext; use fabro_llm::client::Client as LlmClient; -use fabro_llm::generate::{generate_object, GenerateParams}; +use fabro_llm::generate::{GenerateParams, generate_object}; use fabro_llm::types::{Message, Request, ToolResult}; use fabro_util::env::{Env, SystemEnv}; use tokio::process::Command as TokioCommand; diff --git a/lib/crates/fabro-llm/src/cli.rs b/lib/crates/fabro-llm/src/cli.rs index 63ee14c95..e923c2577 100644 --- a/lib/crates/fabro-llm/src/cli.rs +++ b/lib/crates/fabro-llm/src/cli.rs @@ -4,11 +4,11 @@ use dialoguer::console::Term; use dialoguer::theme::ColorfulTheme; use std::time::Duration; -use anyhow::{bail, Context, Result}; +use anyhow::{Context, Result, bail}; use clap::{Args, Subcommand}; use cli_table::format::{Border, Justify, Separator}; -use cli_table::{print_stdout, Cell, CellStruct, Color, Style, Table}; -use futures::{stream, StreamExt}; +use cli_table::{Cell, CellStruct, Color, Style, Table, print_stdout}; +use futures::{StreamExt, stream}; use serde::Deserialize; use tokio::task; use tokio::time; @@ -118,11 +118,7 @@ fn format_speed(tps: Option) -> String { } fn color_if(use_color: bool, color: Color) -> Option { - if use_color { - Some(color) - } else { - None - } + if use_color { Some(color) } else { None } } fn model_row(model: &Model, use_color: bool) -> Vec { diff --git a/lib/crates/fabro-llm/src/error.rs b/lib/crates/fabro-llm/src/error.rs index 612f314f9..dc22bd39a 100644 --- a/lib/crates/fabro-llm/src/error.rs +++ b/lib/crates/fabro-llm/src/error.rs @@ -291,7 +291,7 @@ pub fn error_from_status_code( return SdkError::RequestTimeout { message: detail.message, source: None, - } + }; } 413 => ProviderErrorKind::ContextLength, 429 => ProviderErrorKind::RateLimit, @@ -349,7 +349,7 @@ pub fn error_from_grpc_status( return SdkError::RequestTimeout { message: detail.message, source: None, - } + }; } _ => ProviderErrorKind::Server, }; @@ -899,102 +899,132 @@ mod tests { fn failover_eligible_transient_provider_errors() { let detail = || Box::new(ProviderErrorDetail::new("error", "openai")); - assert!(SdkError::Provider { - kind: ProviderErrorKind::RateLimit, - detail: detail(), - } - .failover_eligible()); + assert!( + SdkError::Provider { + kind: ProviderErrorKind::RateLimit, + detail: detail(), + } + .failover_eligible() + ); - assert!(SdkError::Provider { - kind: ProviderErrorKind::Server, - detail: detail(), - } - .failover_eligible()); + assert!( + SdkError::Provider { + kind: ProviderErrorKind::Server, + detail: detail(), + } + .failover_eligible() + ); - assert!(SdkError::Provider { - kind: ProviderErrorKind::QuotaExceeded, - detail: detail(), - } - .failover_eligible()); + assert!( + SdkError::Provider { + kind: ProviderErrorKind::QuotaExceeded, + detail: detail(), + } + .failover_eligible() + ); } #[test] fn failover_eligible_transient_non_provider_errors() { - assert!(SdkError::RequestTimeout { - message: "timed out".into(), - source: None, - } - .failover_eligible()); + assert!( + SdkError::RequestTimeout { + message: "timed out".into(), + source: None, + } + .failover_eligible() + ); - assert!(SdkError::Network { - message: "refused".into(), - source: None, - } - .failover_eligible()); + assert!( + SdkError::Network { + message: "refused".into(), + source: None, + } + .failover_eligible() + ); - assert!(SdkError::Stream { - message: "broken".into(), - source: None, - } - .failover_eligible()); + assert!( + SdkError::Stream { + message: "broken".into(), + source: None, + } + .failover_eligible() + ); } #[test] fn failover_not_eligible_deterministic_errors() { let detail = || Box::new(ProviderErrorDetail::new("error", "openai")); - assert!(!SdkError::Provider { - kind: ProviderErrorKind::Authentication, - detail: detail(), - } - .failover_eligible()); + assert!( + !SdkError::Provider { + kind: ProviderErrorKind::Authentication, + detail: detail(), + } + .failover_eligible() + ); - assert!(!SdkError::Provider { - kind: ProviderErrorKind::InvalidRequest, - detail: detail(), - } - .failover_eligible()); + assert!( + !SdkError::Provider { + kind: ProviderErrorKind::InvalidRequest, + detail: detail(), + } + .failover_eligible() + ); - assert!(!SdkError::Provider { - kind: ProviderErrorKind::ContextLength, - detail: detail(), - } - .failover_eligible()); + assert!( + !SdkError::Provider { + kind: ProviderErrorKind::ContextLength, + detail: detail(), + } + .failover_eligible() + ); - assert!(!SdkError::Provider { - kind: ProviderErrorKind::ContentFilter, - detail: detail(), - } - .failover_eligible()); + assert!( + !SdkError::Provider { + kind: ProviderErrorKind::ContentFilter, + detail: detail(), + } + .failover_eligible() + ); } #[test] fn failover_not_eligible_non_provider_errors() { - assert!(!SdkError::Configuration { - message: "bad".into(), - source: None, - } - .failover_eligible()); + assert!( + !SdkError::Configuration { + message: "bad".into(), + source: None, + } + .failover_eligible() + ); - assert!(!SdkError::Abort { - message: "cancelled".into() - } - .failover_eligible()); + assert!( + !SdkError::Abort { + message: "cancelled".into() + } + .failover_eligible() + ); - assert!(!SdkError::InvalidToolCall { - message: "bad".into() - } - .failover_eligible()); + assert!( + !SdkError::InvalidToolCall { + message: "bad".into() + } + .failover_eligible() + ); - assert!(!SdkError::NoObjectGenerated { - message: "none".into() - } - .failover_eligible()); + assert!( + !SdkError::NoObjectGenerated { + message: "none".into() + } + .failover_eligible() + ); - assert!(!SdkError::UnsupportedToolChoice { - message: "nope".into() - } - .failover_eligible()); + assert!( + !SdkError::UnsupportedToolChoice { + message: "nope".into() + } + .failover_eligible() + ); } #[test] diff --git a/lib/crates/fabro-llm/src/generate.rs b/lib/crates/fabro-llm/src/generate.rs index d697f9788..bf7945af0 100644 --- a/lib/crates/fabro-llm/src/generate.rs +++ b/lib/crates/fabro-llm/src/generate.rs @@ -2,18 +2,18 @@ use crate::client::Client; use crate::error::SdkError; use crate::provider::StreamEventStream; use crate::retry::retry; -use crate::tools::{execute_all_tools_with_repair, RepairToolCallFn, Tool}; +use crate::tools::{RepairToolCallFn, Tool, execute_all_tools_with_repair}; use crate::types::{ FinishReason, GenerateResult, Message, ObjectStreamEvent, ReasoningEffort, Request, Response, ResponseFormat, ResponseFormatType, RetryPolicy, StepResult, StreamEvent, TimeoutConfig, ToolCall, ToolChoice, ToolDefinition, Usage, }; use fabro_util::backoff::BackoffPolicy; -use futures::{future, stream, Stream, StreamExt}; +use futures::{Stream, StreamExt, future, stream}; use std::pin::Pin; use std::sync::Arc; use std::task::{Context, Poll}; -use tokio::sync::{mpsc, OnceCell}; +use tokio::sync::{OnceCell, mpsc}; use tokio::time; use tokio_stream::wrappers::ReceiverStream; use tokio_util::sync::CancellationToken; @@ -1111,8 +1111,8 @@ mod tests { use crate::client::Client; use crate::provider::ProviderAdapter; use crate::types::{ContentPart, Role}; - use futures::stream; use futures::StreamExt; + use futures::stream; use std::collections::HashMap; use std::sync::atomic::{AtomicU32, Ordering}; diff --git a/lib/crates/fabro-llm/src/providers/anthropic.rs b/lib/crates/fabro-llm/src/providers/anthropic.rs index 42694ac24..a54de80e4 100644 --- a/lib/crates/fabro-llm/src/providers/anthropic.rs +++ b/lib/crates/fabro-llm/src/providers/anthropic.rs @@ -1,8 +1,8 @@ -use base64::{engine::general_purpose::STANDARD as BASE64_STANDARD, Engine}; +use base64::{Engine, engine::general_purpose::STANDARD as BASE64_STANDARD}; use futures::stream; -use crate::error::{error_from_status_code, SdkError}; -use crate::provider::{validate_tool_choice, ProviderAdapter, StreamEventStream}; +use crate::error::{SdkError, error_from_status_code}; +use crate::provider::{ProviderAdapter, StreamEventStream, validate_tool_choice}; use crate::providers::common::{ self as common, extract_system_prompt, parse_error_body, parse_rate_limit_headers, parse_retry_after, send_and_read_response, diff --git a/lib/crates/fabro-llm/src/providers/common.rs b/lib/crates/fabro-llm/src/providers/common.rs index 541c68fe6..8cd9d71d9 100644 --- a/lib/crates/fabro-llm/src/providers/common.rs +++ b/lib/crates/fabro-llm/src/providers/common.rs @@ -1,6 +1,6 @@ -use base64::{engine::general_purpose::STANDARD as BASE64_STANDARD, Engine}; +use base64::{Engine, engine::general_purpose::STANDARD as BASE64_STANDARD}; -use crate::error::{error_from_status_code, SdkError}; +use crate::error::{SdkError, error_from_status_code}; use crate::types::{Message, RateLimitInfo, Role}; use reqwest::header::HeaderMap; use tokio::time; diff --git a/lib/crates/fabro-llm/src/providers/fabro_server.rs b/lib/crates/fabro-llm/src/providers/fabro_server.rs index 8e01ac144..30f3e005d 100644 --- a/lib/crates/fabro-llm/src/providers/fabro_server.rs +++ b/lib/crates/fabro-llm/src/providers/fabro_server.rs @@ -1,4 +1,4 @@ -use crate::error::{error_from_status_code, SdkError}; +use crate::error::{SdkError, error_from_status_code}; use crate::provider::{ProviderAdapter, StreamEventStream}; use crate::providers::common::LineReader; use crate::types::{FinishReason, Message, Request, Response, StreamEvent, Usage}; diff --git a/lib/crates/fabro-llm/src/providers/gemini.rs b/lib/crates/fabro-llm/src/providers/gemini.rs index 2fd6279db..15c1444c0 100644 --- a/lib/crates/fabro-llm/src/providers/gemini.rs +++ b/lib/crates/fabro-llm/src/providers/gemini.rs @@ -1,11 +1,11 @@ -use base64::{engine::general_purpose::STANDARD as BASE64_STANDARD, Engine}; +use base64::{Engine, engine::general_purpose::STANDARD as BASE64_STANDARD}; use futures::stream; use crate::error::{ - error_from_grpc_status, error_from_status_code, ProviderErrorDetail, ProviderErrorKind, - SdkError, + ProviderErrorDetail, ProviderErrorKind, SdkError, error_from_grpc_status, + error_from_status_code, }; -use crate::provider::{validate_tool_choice, ProviderAdapter, StreamEventStream}; +use crate::provider::{ProviderAdapter, StreamEventStream, validate_tool_choice}; use crate::providers::common::{ self as common, extract_system_prompt, parse_error_body, parse_rate_limit_headers, parse_retry_after, diff --git a/lib/crates/fabro-llm/src/providers/openai.rs b/lib/crates/fabro-llm/src/providers/openai.rs index 9662da49e..da3f1e741 100644 --- a/lib/crates/fabro-llm/src/providers/openai.rs +++ b/lib/crates/fabro-llm/src/providers/openai.rs @@ -1,8 +1,8 @@ -use base64::{engine::general_purpose::STANDARD as BASE64_STANDARD, Engine}; -use futures::{stream, StreamExt}; +use base64::{Engine, engine::general_purpose::STANDARD as BASE64_STANDARD}; +use futures::{StreamExt, stream}; -use crate::error::{error_from_status_code, SdkError}; -use crate::provider::{validate_tool_choice, ProviderAdapter, StreamEventStream}; +use crate::error::{SdkError, error_from_status_code}; +use crate::provider::{ProviderAdapter, StreamEventStream, validate_tool_choice}; use crate::providers::common::{ self as common, parse_error_body, parse_rate_limit_headers, parse_retry_after, send_and_read_response, diff --git a/lib/crates/fabro-llm/src/providers/openai_compatible.rs b/lib/crates/fabro-llm/src/providers/openai_compatible.rs index 37b8c35e5..80a1dbea1 100644 --- a/lib/crates/fabro-llm/src/providers/openai_compatible.rs +++ b/lib/crates/fabro-llm/src/providers/openai_compatible.rs @@ -1,7 +1,7 @@ -use futures::{stream, StreamExt}; +use futures::{StreamExt, stream}; -use crate::error::{error_from_status_code, ProviderErrorDetail, ProviderErrorKind, SdkError}; -use crate::provider::{validate_tool_choice, ProviderAdapter, StreamEventStream}; +use crate::error::{ProviderErrorDetail, ProviderErrorKind, SdkError, error_from_status_code}; +use crate::provider::{ProviderAdapter, StreamEventStream, validate_tool_choice}; use crate::providers::common::{ parse_error_body, parse_rate_limit_headers, parse_retry_after, send_and_read_response, }; diff --git a/lib/crates/fabro-llm/src/retry.rs b/lib/crates/fabro-llm/src/retry.rs index bd063cb17..7d899aa8f 100644 --- a/lib/crates/fabro-llm/src/retry.rs +++ b/lib/crates/fabro-llm/src/retry.rs @@ -65,8 +65,8 @@ mod tests { use super::*; use crate::types::RetryPolicy; use fabro_util::backoff::BackoffPolicy; - use std::sync::atomic::{AtomicU32, Ordering}; use std::sync::Arc; + use std::sync::atomic::{AtomicU32, Ordering}; fn fast_backoff() -> BackoffPolicy { BackoffPolicy { diff --git a/lib/crates/fabro-llm/src/tools.rs b/lib/crates/fabro-llm/src/tools.rs index 2f19c0128..38e0c2a49 100644 --- a/lib/crates/fabro-llm/src/tools.rs +++ b/lib/crates/fabro-llm/src/tools.rs @@ -409,11 +409,13 @@ mod tests { let results = execute_all_tools_with_repair(&tool_refs, &calls, &[], None, None).await; assert_eq!(results.len(), 1); assert!(results[0].is_error); - assert!(results[0] - .content - .as_str() - .unwrap() - .contains("validation failed")); + assert!( + results[0] + .content + .as_str() + .unwrap() + .contains("validation failed") + ); } #[tokio::test] @@ -460,11 +462,13 @@ mod tests { execute_all_tools_with_repair(&tool_refs, &calls, &[], None, Some(&repair)).await; assert_eq!(results.len(), 1); assert!(results[0].is_error); - assert!(results[0] - .content - .as_str() - .unwrap() - .contains("repair failed")); + assert!( + results[0] + .content + .as_str() + .unwrap() + .contains("repair failed") + ); } // --- args_type_name --- diff --git a/lib/crates/fabro-mcp/src/client.rs b/lib/crates/fabro-mcp/src/client.rs index 6ac42648a..96f2e6e52 100644 --- a/lib/crates/fabro-mcp/src/client.rs +++ b/lib/crates/fabro-mcp/src/client.rs @@ -2,13 +2,13 @@ use std::process::Stdio; use std::sync::Arc; use std::time::Duration; -use anyhow::{anyhow, Result}; +use anyhow::{Result, anyhow}; use reqwest::header::{HeaderMap, HeaderName, HeaderValue}; use rmcp::model::{CallToolRequestParams, CallToolResult}; -use rmcp::service::{serve_client, RoleClient, RunningService}; +use rmcp::service::{RoleClient, RunningService, serve_client}; +use rmcp::transport::StreamableHttpClientTransport; use rmcp::transport::child_process::TokioChildProcess; use rmcp::transport::streamable_http_client::StreamableHttpClientTransportConfig; -use rmcp::transport::StreamableHttpClientTransport; use tokio::process::Command; use tokio::sync::Mutex; use tokio::time; diff --git a/lib/crates/fabro-mcp/src/config.rs b/lib/crates/fabro-mcp/src/config.rs index 186f0d8b3..7e89a84c7 100644 --- a/lib/crates/fabro-mcp/src/config.rs +++ b/lib/crates/fabro-mcp/src/config.rs @@ -1,4 +1,4 @@ pub use fabro_config::mcp::{ - default_startup_timeout_secs, default_tool_timeout_secs, McpServerConfig, McpServerEntry, - McpTransport, + McpServerConfig, McpServerEntry, McpTransport, default_startup_timeout_secs, + default_tool_timeout_secs, }; diff --git a/lib/crates/fabro-model/src/catalog.rs b/lib/crates/fabro-model/src/catalog.rs index 917aa7ca0..720c0a078 100644 --- a/lib/crates/fabro-model/src/catalog.rs +++ b/lib/crates/fabro-model/src/catalog.rs @@ -261,9 +261,11 @@ mod tests { #[test] fn builtin_closest_no_match() { let haiku = Catalog::builtin().get("claude-haiku-4-5").unwrap(); - assert!(Catalog::builtin() - .closest(Provider::OpenAi, haiku) - .is_none()); + assert!( + Catalog::builtin() + .closest(Provider::OpenAi, haiku) + .is_none() + ); } #[test] diff --git a/lib/crates/fabro-model/src/provider.rs b/lib/crates/fabro-model/src/provider.rs index 5ca290adc..5ab0c93ff 100644 --- a/lib/crates/fabro-model/src/provider.rs +++ b/lib/crates/fabro-model/src/provider.rs @@ -257,8 +257,10 @@ mod tests { #[test] fn every_provider_has_at_least_one_env_var() { - assert!(Provider::ALL - .iter() - .all(|p| !p.api_key_env_vars().is_empty())); + assert!( + Provider::ALL + .iter() + .all(|p| !p.api_key_env_vars().is_empty()) + ); } } diff --git a/lib/crates/fabro-openai-oauth/examples/login.rs b/lib/crates/fabro-openai-oauth/examples/login.rs index 0715abfcb..70402ebdb 100644 --- a/lib/crates/fabro-openai-oauth/examples/login.rs +++ b/lib/crates/fabro-openai-oauth/examples/login.rs @@ -1,4 +1,4 @@ -use fabro_openai_oauth::{extract_account_id, run_browser_flow, DEFAULT_CLIENT_ID, DEFAULT_ISSUER}; +use fabro_openai_oauth::{DEFAULT_CLIENT_ID, DEFAULT_ISSUER, extract_account_id, run_browser_flow}; #[tokio::main] async fn main() { diff --git a/lib/crates/fabro-openai-oauth/src/lib.rs b/lib/crates/fabro-openai-oauth/src/lib.rs index 301de2a6f..b7f867a8d 100644 --- a/lib/crates/fabro-openai-oauth/src/lib.rs +++ b/lib/crates/fabro-openai-oauth/src/lib.rs @@ -2,8 +2,8 @@ use axum::extract::Query; use axum::http::StatusCode; use axum::response::Html; use axum::routing::get; -use base64::engine::general_purpose::URL_SAFE_NO_PAD; use base64::Engine; +use base64::engine::general_purpose::URL_SAFE_NO_PAD; use serde::Deserialize; use sha2::{Digest, Sha256}; use tokio::net::TcpListener; diff --git a/lib/crates/fabro-sandbox/src/daytona/mod.rs b/lib/crates/fabro-sandbox/src/daytona/mod.rs index 7dbe3c1bb..bc6430349 100644 --- a/lib/crates/fabro-sandbox/src/daytona/mod.rs +++ b/lib/crates/fabro-sandbox/src/daytona/mod.rs @@ -5,8 +5,8 @@ use std::time::Instant; use crate::sandbox::resolve_path; use crate::shell_quote; use crate::{ - format_lines_numbered, DirEntry, ExecResult, GrepOptions, Sandbox, SandboxEvent, - SandboxEventCallback, + DirEntry, ExecResult, GrepOptions, Sandbox, SandboxEvent, SandboxEventCallback, + format_lines_numbered, }; use async_trait::async_trait; use daytona_sdk::api_types::SignedPortPreviewUrl; @@ -1132,8 +1132,8 @@ impl Sandbox for DaytonaSandbox { /// Uses base64 encoding (matching the TypeScript/Python/Ruby Daytona SDKs) /// to avoid shell escaping issues with quotes and special characters. fn wrap_bash_command(command: &str) -> String { - use base64::engine::general_purpose::STANDARD; use base64::Engine; + use base64::engine::general_purpose::STANDARD; let encoded = STANDARD.encode(command); format!("sh -c \"echo '{encoded}' | base64 -d | sh\"") } diff --git a/lib/crates/fabro-sandbox/src/docker.rs b/lib/crates/fabro-sandbox/src/docker.rs index d23674f51..4276129b7 100644 --- a/lib/crates/fabro-sandbox/src/docker.rs +++ b/lib/crates/fabro-sandbox/src/docker.rs @@ -1,8 +1,9 @@ use crate::{ - format_lines_numbered, DirEntry, ExecResult, GrepOptions, Sandbox, SandboxEvent, - SandboxEventCallback, + DirEntry, ExecResult, GrepOptions, Sandbox, SandboxEvent, SandboxEventCallback, + format_lines_numbered, }; use async_trait::async_trait; +use bollard::Docker; use bollard::container::LogOutput; use bollard::container::{ Config, CreateContainerOptions, RemoveContainerOptions, StartContainerOptions, @@ -11,7 +12,6 @@ use bollard::container::{ use bollard::exec::{CreateExecOptions, StartExecResults}; use bollard::image::CreateImageOptions; use bollard::models::HostConfig; -use bollard::Docker; use futures::StreamExt; use std::collections::HashMap; use std::time::Instant; diff --git a/lib/crates/fabro-sandbox/src/exe/mod.rs b/lib/crates/fabro-sandbox/src/exe/mod.rs index d10282979..6abd6c8c5 100644 --- a/lib/crates/fabro-sandbox/src/exe/mod.rs +++ b/lib/crates/fabro-sandbox/src/exe/mod.rs @@ -7,8 +7,8 @@ use std::time::Instant; use crate::shell_quote; use crate::ssh_common; use crate::{ - format_lines_numbered, DirEntry, ExecResult, GrepOptions, Sandbox, SandboxEvent, - SandboxEventCallback, + DirEntry, ExecResult, GrepOptions, Sandbox, SandboxEvent, SandboxEventCallback, + format_lines_numbered, }; use async_trait::async_trait; use tokio_util::sync::CancellationToken; diff --git a/lib/crates/fabro-sandbox/src/lib.rs b/lib/crates/fabro-sandbox/src/lib.rs index a69f7ed89..1e83d9d34 100644 --- a/lib/crates/fabro-sandbox/src/lib.rs +++ b/lib/crates/fabro-sandbox/src/lib.rs @@ -35,8 +35,8 @@ pub mod daytona; pub mod test_support; pub use sandbox::{ - format_lines_numbered, git_push_via_exec, setup_git_via_exec, shell_quote, DirEntry, - ExecResult, GitRunInfo, GrepOptions, Sandbox, SandboxEvent, SandboxEventCallback, + DirEntry, ExecResult, GitRunInfo, GrepOptions, Sandbox, SandboxEvent, SandboxEventCallback, + format_lines_numbered, git_push_via_exec, setup_git_via_exec, shell_quote, }; pub use read_guard::ReadBeforeWriteSandbox; diff --git a/lib/crates/fabro-sandbox/src/local.rs b/lib/crates/fabro-sandbox/src/local.rs index a03f88f61..4d72bc206 100644 --- a/lib/crates/fabro-sandbox/src/local.rs +++ b/lib/crates/fabro-sandbox/src/local.rs @@ -1,6 +1,6 @@ use crate::{ - format_lines_numbered, DirEntry, ExecResult, GrepOptions, Sandbox, SandboxEvent, - SandboxEventCallback, + DirEntry, ExecResult, GrepOptions, Sandbox, SandboxEvent, SandboxEventCallback, + format_lines_numbered, }; use async_trait::async_trait; use std::path::{Path, PathBuf}; diff --git a/lib/crates/fabro-sandbox/src/read_guard.rs b/lib/crates/fabro-sandbox/src/read_guard.rs index e04d64b51..7fec91299 100644 --- a/lib/crates/fabro-sandbox/src/read_guard.rs +++ b/lib/crates/fabro-sandbox/src/read_guard.rs @@ -100,8 +100,8 @@ crate::delegate_sandbox! { #[cfg(test)] mod tests { use super::*; - use crate::test_support::MockSandbox; use crate::GrepOptions; + use crate::test_support::MockSandbox; use std::collections::HashMap; fn mock_with_files(files: HashMap) -> MockSandbox { diff --git a/lib/crates/fabro-sandbox/src/reconnect.rs b/lib/crates/fabro-sandbox/src/reconnect.rs index 885777842..e432cee32 100644 --- a/lib/crates/fabro-sandbox/src/reconnect.rs +++ b/lib/crates/fabro-sandbox/src/reconnect.rs @@ -1,7 +1,7 @@ use std::path::PathBuf; #[allow(unused_imports)] -use anyhow::{bail, Context, Result}; +use anyhow::{Context, Result, bail}; #[cfg(feature = "daytona")] use crate::daytona::DaytonaSandbox; diff --git a/lib/crates/fabro-sandbox/src/sprites/mod.rs b/lib/crates/fabro-sandbox/src/sprites/mod.rs index e894d2fdc..0428b2d2c 100644 --- a/lib/crates/fabro-sandbox/src/sprites/mod.rs +++ b/lib/crates/fabro-sandbox/src/sprites/mod.rs @@ -5,8 +5,8 @@ use std::path::Path; use std::time::Instant; use crate::{ - format_lines_numbered, DirEntry, ExecResult, GrepOptions, Sandbox, SandboxEvent, - SandboxEventCallback, + DirEntry, ExecResult, GrepOptions, Sandbox, SandboxEvent, SandboxEventCallback, + format_lines_numbered, }; use async_trait::async_trait; use serde::{Deserialize, Serialize}; diff --git a/lib/crates/fabro-sandbox/src/ssh/mod.rs b/lib/crates/fabro-sandbox/src/ssh/mod.rs index 96b5170b2..7ab00e694 100644 --- a/lib/crates/fabro-sandbox/src/ssh/mod.rs +++ b/lib/crates/fabro-sandbox/src/ssh/mod.rs @@ -8,8 +8,8 @@ use crate::sandbox::resolve_path; use crate::shell_quote; use crate::ssh_common; use crate::{ - format_lines_numbered, DirEntry, ExecResult, GrepOptions, Sandbox, SandboxEvent, - SandboxEventCallback, + DirEntry, ExecResult, GrepOptions, Sandbox, SandboxEvent, SandboxEventCallback, + format_lines_numbered, }; use async_trait::async_trait; use tokio::fs; diff --git a/lib/crates/fabro-sandbox/src/ssh_common.rs b/lib/crates/fabro-sandbox/src/ssh_common.rs index 8e71770c0..511b059ec 100644 --- a/lib/crates/fabro-sandbox/src/ssh_common.rs +++ b/lib/crates/fabro-sandbox/src/ssh_common.rs @@ -3,11 +3,11 @@ use std::time::Instant; use async_trait::async_trait; -use base64::engine::general_purpose::STANDARD; use base64::Engine; +use base64::engine::general_purpose::STANDARD; use tokio::sync::OnceCell; -use crate::{shell_quote, SandboxEvent}; +use crate::{SandboxEvent, shell_quote}; /// Output from an SSH command execution. pub struct SshOutput { diff --git a/lib/crates/fabro-sandbox/src/worktree.rs b/lib/crates/fabro-sandbox/src/worktree.rs index 399cac110..a1185354e 100644 --- a/lib/crates/fabro-sandbox/src/worktree.rs +++ b/lib/crates/fabro-sandbox/src/worktree.rs @@ -4,7 +4,7 @@ use std::path::Path; use std::sync::Arc; use tokio_util::sync::CancellationToken; -use crate::{shell_quote, DirEntry, ExecResult, GrepOptions, Sandbox}; +use crate::{DirEntry, ExecResult, GrepOptions, Sandbox, shell_quote}; /// Git command prefix that disables background maintenance. const GIT: &str = "git -c maintenance.auto=0 -c gc.auto=0"; diff --git a/lib/crates/fabro-slack/src/blocks.rs b/lib/crates/fabro-slack/src/blocks.rs index ab3df0930..904085a9d 100644 --- a/lib/crates/fabro-slack/src/blocks.rs +++ b/lib/crates/fabro-slack/src/blocks.rs @@ -1,5 +1,5 @@ use fabro_interview::{Question, QuestionType}; -use serde_json::{json, Value}; +use serde_json::{Value, json}; fn text_block(text: &str) -> Value { json!({ @@ -105,10 +105,12 @@ mod tests { let section = &blocks_json[0]; assert_eq!(section["type"], "section"); - assert!(section["text"]["text"] - .as_str() - .unwrap() - .contains("Approve this PR?")); + assert!( + section["text"]["text"] + .as_str() + .unwrap() + .contains("Approve this PR?") + ); let actions = &blocks_json[1]; assert_eq!(actions["type"], "actions"); @@ -237,9 +239,11 @@ mod tests { let submit_elements = submit_block["elements"].as_array().unwrap(); assert_eq!(submit_elements[0]["type"], "button"); assert_eq!(submit_elements[0]["text"]["text"], "Submit"); - assert!(submit_elements[0]["action_id"] - .as_str() - .unwrap() - .contains("q-5")); + assert!( + submit_elements[0]["action_id"] + .as_str() + .unwrap() + .contains("q-5") + ); } } diff --git a/lib/crates/fabro-slack/src/client.rs b/lib/crates/fabro-slack/src/client.rs index ca72b0529..32887c45d 100644 --- a/lib/crates/fabro-slack/src/client.rs +++ b/lib/crates/fabro-slack/src/client.rs @@ -1,5 +1,5 @@ use reqwest::Client; -use serde_json::{json, Value}; +use serde_json::{Value, json}; use tracing::debug; const SLACK_API_BASE: &str = "https://slack.com/api"; diff --git a/lib/crates/fabro-slack/src/connection.rs b/lib/crates/fabro-slack/src/connection.rs index 01ebd0286..fd67a31c7 100644 --- a/lib/crates/fabro-slack/src/connection.rs +++ b/lib/crates/fabro-slack/src/connection.rs @@ -6,8 +6,8 @@ use tokio::time::sleep; use tokio_tungstenite::tungstenite::Message; use tracing::{debug, error, info, warn}; -use crate::client::{parse_wss_url, SlackApiError, SlackClient}; -use crate::dispatch::{dispatch, DispatchAction}; +use crate::client::{SlackApiError, SlackClient, parse_wss_url}; +use crate::dispatch::{DispatchAction, dispatch}; use crate::socket::{SocketAck, SocketEnvelope}; use crate::threads::ThreadRegistry; diff --git a/lib/crates/fabro-slack/src/dispatch.rs b/lib/crates/fabro-slack/src/dispatch.rs index 1c8ce974b..7afe56c27 100644 --- a/lib/crates/fabro-slack/src/dispatch.rs +++ b/lib/crates/fabro-slack/src/dispatch.rs @@ -1,7 +1,7 @@ use fabro_interview::Answer; use crate::interaction; -use crate::socket::{classify_envelope, SocketEnvelope, SocketEventKind}; +use crate::socket::{SocketEnvelope, SocketEventKind, classify_envelope}; use crate::threads::{self, ThreadRegistry}; #[derive(Debug)] diff --git a/lib/crates/fabro-store/src/memory.rs b/lib/crates/fabro-store/src/memory.rs index 8962adf38..81743ab00 100644 --- a/lib/crates/fabro-store/src/memory.rs +++ b/lib/crates/fabro-store/src/memory.rs @@ -1,16 +1,16 @@ use std::collections::{BTreeMap, BTreeSet, HashMap}; -use std::sync::atomic::{AtomicU32, Ordering}; use std::sync::Arc; +use std::sync::atomic::{AtomicU32, Ordering}; use async_trait::async_trait; use bytes::Bytes; use chrono::{DateTime, Utc}; use futures::Stream; -use serde::de::DeserializeOwned; use serde::Serialize; -use tokio::sync::{mpsc, Mutex}; -use tokio_stream::wrappers::UnboundedReceiverStream; +use serde::de::DeserializeOwned; +use tokio::sync::{Mutex, mpsc}; use tokio_stream::StreamExt as _; +use tokio_stream::wrappers::UnboundedReceiverStream; use crate::keys; use crate::{ diff --git a/lib/crates/fabro-store/src/slate/catalog.rs b/lib/crates/fabro-store/src/slate/catalog.rs index a66afa0f6..8c2d5b2b3 100644 --- a/lib/crates/fabro-store/src/slate/catalog.rs +++ b/lib/crates/fabro-store/src/slate/catalog.rs @@ -3,8 +3,8 @@ use std::sync::Arc; use chrono::{DateTime, Utc}; use futures::TryStreamExt; -use object_store::path::Path; use object_store::ObjectStore; +use object_store::path::Path; use crate::{CatalogRecord, ListRunsQuery, Result}; diff --git a/lib/crates/fabro-store/src/slate/mod.rs b/lib/crates/fabro-store/src/slate/mod.rs index 9bb10e528..0133db4b6 100644 --- a/lib/crates/fabro-store/src/slate/mod.rs +++ b/lib/crates/fabro-store/src/slate/mod.rs @@ -7,10 +7,10 @@ use std::sync::Arc; use async_trait::async_trait; use chrono::{DateTime, Utc}; use futures::TryStreamExt; -use object_store::path::Path; use object_store::ObjectStore; -use slatedb::config::DbReaderOptions; +use object_store::path::Path; use slatedb::DbReader; +use slatedb::config::DbReaderOptions; use tokio::sync::Mutex; use crate::keys; @@ -544,11 +544,13 @@ mod tests { .unwrap(); assert!(store.open_run("run-1").await.unwrap().is_some()); - assert!(store - .list_runs(&ListRunsQuery::default()) - .await - .unwrap() - .is_empty()); + assert!( + store + .list_runs(&ListRunsQuery::default()) + .await + .unwrap() + .is_empty() + ); store.repair_catalog().await.unwrap(); let listed = store.list_runs(&ListRunsQuery::default()).await.unwrap(); @@ -624,11 +626,13 @@ mod tests { .unwrap(); assert!(store.open_run("run-1").await.unwrap().is_none()); - assert!(store - .list_runs(&ListRunsQuery::default()) - .await - .unwrap() - .is_empty()); + assert!( + store + .list_runs(&ListRunsQuery::default()) + .await + .unwrap() + .is_empty() + ); } #[tokio::test] diff --git a/lib/crates/fabro-store/src/slate/run_store.rs b/lib/crates/fabro-store/src/slate/run_store.rs index e95ddeced..3261346eb 100644 --- a/lib/crates/fabro-store/src/slate/run_store.rs +++ b/lib/crates/fabro-store/src/slate/run_store.rs @@ -7,10 +7,10 @@ use async_trait::async_trait; use bytes::Bytes; use chrono::{DateTime, Utc}; use futures::Stream; -use serde::de::DeserializeOwned; use serde::Serialize; +use serde::de::DeserializeOwned; use slatedb::{CloseReason, DbRead, ErrorKind}; -use tokio::sync::{mpsc, Mutex}; +use tokio::sync::{Mutex, mpsc}; use tokio::time; use tokio_stream::wrappers::UnboundedReceiverStream; diff --git a/lib/crates/fabro-telemetry/src/buffer.rs b/lib/crates/fabro-telemetry/src/buffer.rs index caf717afb..ace625d65 100644 --- a/lib/crates/fabro-telemetry/src/buffer.rs +++ b/lib/crates/fabro-telemetry/src/buffer.rs @@ -63,7 +63,7 @@ mod tests { use super::*; use crate::event::User; use serde_json::json; - use std::sync::{mpsc, Arc, Mutex}; + use std::sync::{Arc, Mutex, mpsc}; fn make_track(event: &str) -> Track { Track { diff --git a/lib/crates/fabro-telemetry/src/context.rs b/lib/crates/fabro-telemetry/src/context.rs index a21acab8b..347f28e3d 100644 --- a/lib/crates/fabro-telemetry/src/context.rs +++ b/lib/crates/fabro-telemetry/src/context.rs @@ -1,4 +1,4 @@ -use serde_json::{json, Value}; +use serde_json::{Value, json}; pub fn build_context() -> Value { json!({ diff --git a/lib/crates/fabro-telemetry/src/sender.rs b/lib/crates/fabro-telemetry/src/sender.rs index 457b2af80..e53e4d495 100644 --- a/lib/crates/fabro-telemetry/src/sender.rs +++ b/lib/crates/fabro-telemetry/src/sender.rs @@ -1,7 +1,7 @@ use std::path::Path; -use base64::engine::general_purpose::STANDARD; use base64::Engine; +use base64::engine::general_purpose::STANDARD; use uuid::Uuid; use crate::event::Track; diff --git a/lib/crates/fabro-telemetry/src/spawn.rs b/lib/crates/fabro-telemetry/src/spawn.rs index 0d02a64b6..c5ea4b979 100644 --- a/lib/crates/fabro-telemetry/src/spawn.rs +++ b/lib/crates/fabro-telemetry/src/spawn.rs @@ -23,7 +23,7 @@ pub fn spawn_detached(args: &[&str], env: &[(&str, &str)]) { #[cfg(unix)] fn spawn_detached_unix(args: &[&str], env: &[(&str, &str)]) { - use fork::{fork, setsid, Fork}; + use fork::{Fork, fork, setsid}; // Flush stdout/stderr before forking so the child process doesn't inherit // buffered data that would be flushed again on child exit, causing diff --git a/lib/crates/fabro-tracker/src/github.rs b/lib/crates/fabro-tracker/src/github.rs index 5e0e15f8a..4973ef644 100644 --- a/lib/crates/fabro-tracker/src/github.rs +++ b/lib/crates/fabro-tracker/src/github.rs @@ -2,10 +2,10 @@ use async_trait::async_trait; use tokio::sync::OnceCell; use fabro_github::{ - create_installation_access_token_for_projects, sign_app_jwt, GitHubAppCredentials, + GitHubAppCredentials, create_installation_access_token_for_projects, sign_app_jwt, }; -use crate::{execute_graphql_request, Issue, Tracker}; +use crate::{Issue, Tracker, execute_graphql_request}; /// Execute a GitHub GraphQL request and return the response JSON. async fn execute_github_graphql( diff --git a/lib/crates/fabro-tracker/src/lib.rs b/lib/crates/fabro-tracker/src/lib.rs index fa7df360b..6912f3cff 100644 --- a/lib/crates/fabro-tracker/src/lib.rs +++ b/lib/crates/fabro-tracker/src/lib.rs @@ -4,7 +4,7 @@ pub mod github; pub mod linear; pub use github::GitHubTracker; -pub use linear::{LinearConfig, LinearTracker, LINEAR_API_ENDPOINT}; +pub use linear::{LINEAR_API_ENDPOINT, LinearConfig, LinearTracker}; /// Shared GraphQL execution used by both provider modules. /// diff --git a/lib/crates/fabro-tracker/src/linear.rs b/lib/crates/fabro-tracker/src/linear.rs index 1238af464..a786805be 100644 --- a/lib/crates/fabro-tracker/src/linear.rs +++ b/lib/crates/fabro-tracker/src/linear.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use async_trait::async_trait; use serde_json::Value; -use crate::{execute_graphql_request, BlockerRef, Issue, Tracker}; +use crate::{BlockerRef, Issue, Tracker, execute_graphql_request}; pub const LINEAR_API_ENDPOINT: &str = "https://api.linear.app/graphql"; diff --git a/lib/crates/fabro-types-derive/src/lib.rs b/lib/crates/fabro-types-derive/src/lib.rs index 9df23a86b..0a212437f 100644 --- a/lib/crates/fabro-types-derive/src/lib.rs +++ b/lib/crates/fabro-types-derive/src/lib.rs @@ -1,6 +1,6 @@ use proc_macro::TokenStream; use quote::quote; -use syn::{parse_macro_input, Data, DeriveInput, Fields}; +use syn::{Data, DeriveInput, Fields, parse_macro_input}; #[proc_macro_derive(Combine)] pub fn derive_combine(input: TokenStream) -> TokenStream { diff --git a/lib/crates/fabro-types/src/lib.rs b/lib/crates/fabro-types/src/lib.rs index 92621a0b0..5c1a85aca 100644 --- a/lib/crates/fabro-types/src/lib.rs +++ b/lib/crates/fabro-types/src/lib.rs @@ -18,7 +18,7 @@ pub mod usage; pub use checkpoint::Checkpoint; pub use conclusion::{Conclusion, StageSummary}; pub use failure_signature::FailureSignature; -pub use graph::{is_llm_handler_type, shape_to_handler_type, AttrValue, Edge, Graph, Node}; +pub use graph::{AttrValue, Edge, Graph, Node, is_llm_handler_type, shape_to_handler_type}; pub use node_status::NodeStatusRecord; pub use outcome::{FailureCategory, FailureDetail, NodeResult, Outcome, OutcomeMeta, StageStatus}; pub use retro::{ diff --git a/lib/crates/fabro-types/src/settings/mod.rs b/lib/crates/fabro-types/src/settings/mod.rs index b81fe9b0c..287f6d921 100644 --- a/lib/crates/fabro-types/src/settings/mod.rs +++ b/lib/crates/fabro-types/src/settings/mod.rs @@ -16,8 +16,8 @@ pub use cli::{ }; pub use hook::{HookConfig, HookDefinition, HookEvent, HookType, TlsMode}; pub use mcp::{ - default_startup_timeout_secs, default_tool_timeout_secs, McpServerConfig, McpServerEntry, - McpTransport, + McpServerConfig, McpServerEntry, McpTransport, default_startup_timeout_secs, + default_tool_timeout_secs, }; pub use project::ProjectFabroSettings; pub use run::{ diff --git a/lib/crates/fabro-validate/src/rules.rs b/lib/crates/fabro-validate/src/rules.rs index a95dffd7d..a62b1c722 100644 --- a/lib/crates/fabro-validate/src/rules.rs +++ b/lib/crates/fabro-validate/src/rules.rs @@ -2,8 +2,8 @@ use std::collections::{HashSet, VecDeque}; use std::str::FromStr; use fabro_graphviz::condition::parse_condition; -use fabro_graphviz::graph::{is_llm_handler_type, AttrValue, Graph}; -use fabro_graphviz::stylesheet::{parse_stylesheet, Selector}; +use fabro_graphviz::graph::{AttrValue, Graph, is_llm_handler_type}; +use fabro_graphviz::stylesheet::{Selector, parse_stylesheet}; use crate::{Diagnostic, LintRule, Severity}; diff --git a/lib/crates/fabro-workflows/src/condition.rs b/lib/crates/fabro-workflows/src/condition.rs index 1f93536a8..5fbcdee2c 100644 --- a/lib/crates/fabro-workflows/src/condition.rs +++ b/lib/crates/fabro-workflows/src/condition.rs @@ -4,8 +4,8 @@ /// `parse_condition` and provides runtime evaluation against `Outcome`/`Context`. use fabro_graphviz::condition::{Clause, ConditionExpr, Op}; -use crate::context::keys; use crate::context::Context; +use crate::context::keys; use crate::outcome::Outcome; // --------------------------------------------------------------------------- diff --git a/lib/crates/fabro-workflows/src/error.rs b/lib/crates/fabro-workflows/src/error.rs index bce5e246d..5a8545d77 100644 --- a/lib/crates/fabro-workflows/src/error.rs +++ b/lib/crates/fabro-workflows/src/error.rs @@ -434,10 +434,12 @@ mod tests { fn is_retryable_terminal_errors() { assert!(!FabroError::Parse("bad".to_string()).is_retryable()); assert!(!FabroError::Validation("bad".to_string()).is_retryable()); - assert!(!FabroError::ValidationFailed { - diagnostics: vec![] - } - .is_retryable()); + assert!( + !FabroError::ValidationFailed { + diagnostics: vec![] + } + .is_retryable() + ); assert!(!FabroError::Stylesheet("bad".to_string()).is_retryable()); assert!(!FabroError::Checkpoint("bad".to_string()).is_retryable()); } @@ -1489,10 +1491,12 @@ mod tests { source: None, }); let outcome = err.to_fail_outcome(); - assert!(outcome - .failure_reason() - .unwrap() - .contains("connection refused")); + assert!( + outcome + .failure_reason() + .unwrap() + .contains("connection refused") + ); } #[test] @@ -1687,10 +1691,12 @@ mod tests { // Verify wire format assert_eq!(v["type"], "handler"); - assert!(v["data"]["message"] - .as_str() - .unwrap() - .contains("connection refused")); + assert!( + v["data"]["message"] + .as_str() + .unwrap() + .contains("connection refused") + ); assert_eq!(v["data"]["failure_class"], "transient_infra"); // Round-trip diff --git a/lib/crates/fabro-workflows/src/event.rs b/lib/crates/fabro-workflows/src/event.rs index 6d4d37157..2893e95fb 100644 --- a/lib/crates/fabro-workflows/src/event.rs +++ b/lib/crates/fabro-workflows/src/event.rs @@ -1,7 +1,7 @@ use std::io::Write; use std::path::{Path, PathBuf}; -use std::sync::atomic::{AtomicI64, Ordering}; use std::sync::Arc; +use std::sync::atomic::{AtomicI64, Ordering}; use anyhow::{Context, Result}; use chrono::{SecondsFormat, Utc}; diff --git a/lib/crates/fabro-workflows/src/git.rs b/lib/crates/fabro-workflows/src/git.rs index 51a2791de..82e2d2dad 100644 --- a/lib/crates/fabro-workflows/src/git.rs +++ b/lib/crates/fabro-workflows/src/git.rs @@ -7,7 +7,7 @@ use git2::{Repository, Signature}; use crate::error::{FabroError, Result}; use crate::records::{Checkpoint, RunRecord, StartRecord}; -use tokio::task::{spawn_blocking, JoinError}; +use tokio::task::{JoinError, spawn_blocking}; use tokio::time::timeout; /// Branch prefix for workflow run branches (e.g. `fabro/run/{run_id}`). diff --git a/lib/crates/fabro-workflows/src/graph/routing.rs b/lib/crates/fabro-workflows/src/graph/routing.rs index 60dc77fce..2cdf5dde2 100644 --- a/lib/crates/fabro-workflows/src/graph/routing.rs +++ b/lib/crates/fabro-workflows/src/graph/routing.rs @@ -192,11 +192,7 @@ fn weighted_random<'a>(edges: &[&'a GvEdge]) -> Option<&'a GvEdge> { .iter() .map(|e| { let w = e.weight(); - if w <= 0 { - 1.0 - } else { - w as f64 - } + if w <= 0 { 1.0 } else { w as f64 } }) .collect(); let total: f64 = weights.iter().sum(); diff --git a/lib/crates/fabro-workflows/src/handler/command.rs b/lib/crates/fabro-workflows/src/handler/command.rs index 19d3c4ba5..61b3da41b 100644 --- a/lib/crates/fabro-workflows/src/handler/command.rs +++ b/lib/crates/fabro-workflows/src/handler/command.rs @@ -2,8 +2,8 @@ use std::path::Path; use async_trait::async_trait; -use crate::context::keys; use crate::context::Context; +use crate::context::keys; use crate::error::FabroError; use crate::outcome::{Outcome, OutcomeExt}; use crate::run_dir::{node_dir, visit_from_context}; @@ -547,10 +547,12 @@ mod tests { .unwrap(); assert_eq!(outcome.status, StageStatus::Success); let command_output = outcome.context_updates.get(keys::COMMAND_OUTPUT).unwrap(); - assert!(command_output - .as_str() - .unwrap() - .contains("hello from python")); + assert!( + command_output + .as_str() + .unwrap() + .contains("hello from python") + ); } #[tokio::test] @@ -597,10 +599,12 @@ mod tests { .await .unwrap(); assert_eq!(outcome.status, StageStatus::Fail); - assert!(outcome - .failure_reason() - .unwrap() - .contains("Invalid language")); + assert!( + outcome + .failure_reason() + .unwrap() + .contains("Invalid language") + ); } #[tokio::test] diff --git a/lib/crates/fabro-workflows/src/handler/fan_in.rs b/lib/crates/fabro-workflows/src/handler/fan_in.rs index 79cfc9a66..56e742c5c 100644 --- a/lib/crates/fabro-workflows/src/handler/fan_in.rs +++ b/lib/crates/fabro-workflows/src/handler/fan_in.rs @@ -4,8 +4,8 @@ use std::sync::Arc; use async_trait::async_trait; use fabro_agent::Sandbox; -use crate::context::keys; use crate::context::Context; +use crate::context::keys; use crate::error::FabroError; use crate::event::EventEmitter; use crate::outcome::{Outcome, OutcomeExt}; @@ -521,10 +521,12 @@ mod tests { .await .unwrap(); assert_eq!(outcome.status, StageStatus::Fail); - assert!(outcome - .failure_reason() - .unwrap() - .contains("all candidates failed")); + assert!( + outcome + .failure_reason() + .unwrap() + .contains("all candidates failed") + ); } #[tokio::test] diff --git a/lib/crates/fabro-workflows/src/handler/human.rs b/lib/crates/fabro-workflows/src/handler/human.rs index 9f9947475..8f07adb56 100644 --- a/lib/crates/fabro-workflows/src/handler/human.rs +++ b/lib/crates/fabro-workflows/src/handler/human.rs @@ -4,8 +4,8 @@ use std::time::Instant; use async_trait::async_trait; -use crate::context::keys; use crate::context::Context; +use crate::context::keys; use crate::error::FabroError; use crate::event::{EventEmitter, WorkflowRunEvent}; use crate::millis_u64; diff --git a/lib/crates/fabro-workflows/src/handler/llm/api.rs b/lib/crates/fabro-workflows/src/handler/llm/api.rs index 0328f511a..cd02fb1d3 100644 --- a/lib/crates/fabro-workflows/src/handler/llm/api.rs +++ b/lib/crates/fabro-workflows/src/handler/llm/api.rs @@ -4,9 +4,9 @@ use std::sync::{Arc, Mutex}; use async_trait::async_trait; use fabro_agent::{ - subagent::{SessionFactory, SubAgentManager}, AgentEvent, AgentProfile, AnthropicProfile, GeminiProfile, OpenAiProfile, Sandbox, Session, SessionConfig, Turn, + subagent::{SessionFactory, SubAgentManager}, }; use fabro_llm::client::Client; use fabro_llm::types::{Message, Request, Usage}; @@ -21,8 +21,8 @@ use crate::context::keys::Fidelity; use crate::context::{Context, WorkflowContext}; use crate::error::FabroError; use crate::event::{EventEmitter, WorkflowRunEvent}; -use crate::outcome::compute_stage_cost; use crate::outcome::StageUsage; +use crate::outcome::compute_stage_cost; use fabro_graphviz::graph::Node; fn build_profile(model: &str, provider: Provider) -> Box { @@ -578,7 +578,7 @@ impl CodergenBackend for AgentApiBackend { } Err(fabro_agent::AgentError::Llm(err)) => return Err(FabroError::Llm(err)), Err(fabro_agent::AgentError::Aborted(_)) => { - return Err(FabroError::Cancelled) + return Err(FabroError::Cancelled); } Err(other) => { return Err(FabroError::handler(format!( @@ -588,11 +588,7 @@ impl CodergenBackend for AgentApiBackend { } } - if succeeded { - Ok(()) - } else { - Err(last_err) - } + if succeeded { Ok(()) } else { Err(last_err) } } Err(fabro_agent::AgentError::Llm(sdk_err)) => Err(FabroError::Llm(sdk_err)), Err(fabro_agent::AgentError::Aborted(_)) => Err(FabroError::Cancelled), diff --git a/lib/crates/fabro-workflows/src/handler/llm/cli.rs b/lib/crates/fabro-workflows/src/handler/llm/cli.rs index bc9322333..d3c2485b7 100644 --- a/lib/crates/fabro-workflows/src/handler/llm/cli.rs +++ b/lib/crates/fabro-workflows/src/handler/llm/cli.rs @@ -3,8 +3,8 @@ use std::path::Path; use std::sync::Arc; use async_trait::async_trait; -use fabro_agent::sandbox::ExecResult; use fabro_agent::Sandbox; +use fabro_agent::sandbox::ExecResult; use fabro_model::Provider; use tokio::fs; use tokio::time::sleep; @@ -13,8 +13,8 @@ use super::super::agent::{CodergenBackend, CodergenResult}; use crate::context::Context; use crate::error::FabroError; use crate::event::{EventEmitter, WorkflowRunEvent}; -use crate::outcome::compute_stage_cost; use crate::outcome::StageUsage; +use crate::outcome::compute_stage_cost; use fabro_graphviz::graph::Node; /// Maps a provider to its corresponding CLI tool metadata. @@ -201,7 +201,9 @@ pub fn cli_command_for_provider(provider: Provider, model: &str, prompt_file: &s Provider::Gemini => format!("cat {prompt_file} | gemini -o json --yolo{model_flag}"), // --dangerously-skip-permissions: bypass all permission checks (required for non-interactive use). // CLAUDECODE= unset to allow running inside a Claude Code session. - Provider::Anthropic => format!("cat {prompt_file} | CLAUDECODE= claude -p --verbose --output-format stream-json --dangerously-skip-permissions{model_flag}"), + Provider::Anthropic => format!( + "cat {prompt_file} | CLAUDECODE= claude -p --verbose --output-format stream-json --dangerously-skip-permissions{model_flag}" + ), } } @@ -1005,10 +1007,12 @@ mod tests { let result = ensure_cli(AgentCli::Claude, Provider::Anthropic, &sandbox, &emitter).await; assert!(result.is_err()); - assert!(result - .unwrap_err() - .to_string() - .contains("install exited with code")); + assert!( + result + .unwrap_err() + .to_string() + .contains("install exited with code") + ); } // -- Cycle 1: cli_command_for_provider -- diff --git a/lib/crates/fabro-workflows/src/handler/llm/mod.rs b/lib/crates/fabro-workflows/src/handler/llm/mod.rs index 364561966..9e7570560 100644 --- a/lib/crates/fabro-workflows/src/handler/llm/mod.rs +++ b/lib/crates/fabro-workflows/src/handler/llm/mod.rs @@ -3,4 +3,4 @@ pub mod cli; pub mod preamble; pub use api::AgentApiBackend; -pub use cli::{parse_cli_response, AgentCliBackend, BackendRouter}; +pub use cli::{AgentCliBackend, BackendRouter, parse_cli_response}; diff --git a/lib/crates/fabro-workflows/src/handler/llm/preamble.rs b/lib/crates/fabro-workflows/src/handler/llm/preamble.rs index bd706cf96..79823b4a1 100644 --- a/lib/crates/fabro-workflows/src/handler/llm/preamble.rs +++ b/lib/crates/fabro-workflows/src/handler/llm/preamble.rs @@ -5,7 +5,7 @@ use crate::context::keys; use crate::context::{Context, WorkflowContext}; use crate::outcome::Outcome; use crate::outcome::OutcomeExt; -use fabro_graphviz::graph::{is_llm_handler_type, Graph, Node}; +use fabro_graphviz::graph::{Graph, Node, is_llm_handler_type}; const COMPACT_OUTPUT_MAX_LINES: usize = 25; const SUMMARY_HIGH_OUTPUT_MAX_LINES: usize = 50; diff --git a/lib/crates/fabro-workflows/src/handler/manager_loop.rs b/lib/crates/fabro-workflows/src/handler/manager_loop.rs index ae1c7c8a9..5c760ec2e 100644 --- a/lib/crates/fabro-workflows/src/handler/manager_loop.rs +++ b/lib/crates/fabro-workflows/src/handler/manager_loop.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use std::path::{Path, PathBuf}; -use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Duration; use async_trait::async_trait; @@ -11,7 +11,7 @@ use crate::condition::evaluate_condition; use crate::context::keys; use crate::context::{Context, WorkflowContext}; use crate::error::FabroError; -use crate::operations::{validate, ValidateInput, WorkflowInput}; +use crate::operations::{ValidateInput, WorkflowInput, validate}; use crate::outcome::{Outcome, OutcomeExt, StageStatus}; use crate::pipeline; use crate::pipeline::types::Initialized; @@ -147,7 +147,7 @@ impl Handler for SubWorkflowHandler { Err(e) => { return Ok(Outcome::fail_classify(format!( "Failed to parse child pipeline: {e}" - ))) + ))); } }; @@ -293,9 +293,9 @@ impl Handler for SubWorkflowHandler { #[cfg(test)] mod tests { use super::*; + use crate::handler::HandlerRegistry; use crate::handler::exit::ExitHandler; use crate::handler::start::StartHandler; - use crate::handler::HandlerRegistry; use fabro_graphviz::graph::AttrValue; fn make_services() -> EngineServices { @@ -335,11 +335,13 @@ mod tests { .await .unwrap(); assert_eq!(outcome.status, StageStatus::Success); - assert!(outcome - .notes - .as_deref() - .unwrap() - .contains("Child completed")); + assert!( + outcome + .notes + .as_deref() + .unwrap() + .contains("Child completed") + ); assert!( dir.path().join("nodes/manager_1/child").exists(), "child logs should default to first-visit directory naming" @@ -366,10 +368,12 @@ mod tests { .await .unwrap(); assert_eq!(outcome.status, StageStatus::Fail); - assert!(outcome - .failure_reason() - .unwrap() - .contains("No child workflow source")); + assert!( + outcome + .failure_reason() + .unwrap() + .contains("No child workflow source") + ); } #[tokio::test] @@ -396,10 +400,12 @@ mod tests { .await .unwrap(); assert_eq!(outcome.status, StageStatus::Fail); - assert!(outcome - .failure_reason() - .unwrap() - .contains("Failed to parse child pipeline")); + assert!( + outcome + .failure_reason() + .unwrap() + .contains("Failed to parse child pipeline") + ); } #[tokio::test] @@ -621,11 +627,13 @@ mod tests { .await .unwrap(); assert_eq!(outcome.status, StageStatus::Success); - assert!(outcome - .notes - .as_deref() - .unwrap() - .contains("Stop condition satisfied")); + assert!( + outcome + .notes + .as_deref() + .unwrap() + .contains("Stop condition satisfied") + ); } #[test] @@ -784,14 +792,18 @@ mod tests { // Engine-internal keys do NOT propagate assert!(!outcome.context_updates.contains_key("internal.run_id")); assert!(!outcome.context_updates.contains_key("graph.goal")); - assert!(!outcome - .context_updates - .keys() - .any(|k| k.starts_with("thread."))); - assert!(!outcome - .context_updates - .keys() - .any(|k| k.starts_with("current"))); + assert!( + !outcome + .context_updates + .keys() + .any(|k| k.starts_with("thread.")) + ); + assert!( + !outcome + .context_updates + .keys() + .any(|k| k.starts_with("current")) + ); } #[tokio::test] diff --git a/lib/crates/fabro-workflows/src/handler/mod.rs b/lib/crates/fabro-workflows/src/handler/mod.rs index 12dfee2fe..c8ab63672 100644 --- a/lib/crates/fabro-workflows/src/handler/mod.rs +++ b/lib/crates/fabro-workflows/src/handler/mod.rs @@ -24,7 +24,7 @@ use crate::error::FabroError; use crate::event::EventEmitter; use crate::outcome::{Outcome, OutcomeExt}; use crate::sandbox_git::GitState; -use fabro_graphviz::graph::{shape_to_handler_type, Graph, Node}; +use fabro_graphviz::graph::{Graph, Node, shape_to_handler_type}; use fabro_hooks::{HookContext, HookDecision, HookRunner}; use fabro_interview::Interviewer; diff --git a/lib/crates/fabro-workflows/src/handler/parallel.rs b/lib/crates/fabro-workflows/src/handler/parallel.rs index 523675229..9becfa16f 100644 --- a/lib/crates/fabro-workflows/src/handler/parallel.rs +++ b/lib/crates/fabro-workflows/src/handler/parallel.rs @@ -15,7 +15,7 @@ use crate::hook_context::set_hook_node; use crate::millis_u64; use crate::outcome::{FailureCategory, FailureDetail, Outcome, OutcomeExt, StageStatus}; use crate::run_dir::{node_dir, visit_from_context}; -use crate::sandbox_git::{git_checkpoint, git_merge_ff_only, git_remove_worktree, GIT_REMOTE}; +use crate::sandbox_git::{GIT_REMOTE, git_checkpoint, git_merge_ff_only, git_remove_worktree}; use fabro_graphviz::graph::{AttrValue, Graph, Node}; use fabro_hooks::{HookContext, HookEvent}; use tokio::fs; diff --git a/lib/crates/fabro-workflows/src/handler/prompt.rs b/lib/crates/fabro-workflows/src/handler/prompt.rs index 40c2da3a8..c761a8024 100644 --- a/lib/crates/fabro-workflows/src/handler/prompt.rs +++ b/lib/crates/fabro-workflows/src/handler/prompt.rs @@ -13,7 +13,7 @@ use fabro_graphviz::graph::{Graph, Node}; use tokio::fs; use super::agent::{ - expand_variables, extract_status_fields, truncate, CodergenBackend, CodergenResult, + CodergenBackend, CodergenResult, expand_variables, extract_status_fields, truncate, }; use super::{EngineServices, Handler}; @@ -188,9 +188,11 @@ mod tests { .get(crate::context::keys::LAST_STAGE), Some(&serde_json::json!("classify")) ); - assert!(outcome - .context_updates - .contains_key(crate::context::keys::LAST_RESPONSE)); + assert!( + outcome + .context_updates + .contains_key(crate::context::keys::LAST_RESPONSE) + ); assert_eq!( outcome .context_updates diff --git a/lib/crates/fabro-workflows/src/lifecycle/artifact.rs b/lib/crates/fabro-workflows/src/lifecycle/artifact.rs index 5c9ecbaaf..fb027b033 100644 --- a/lib/crates/fabro-workflows/src/lifecycle/artifact.rs +++ b/lib/crates/fabro-workflows/src/lifecycle/artifact.rs @@ -8,7 +8,7 @@ use fabro_core::lifecycle::{AttemptContext, AttemptResultContext, RunLifecycle}; use fabro_core::outcome::NodeResult; use fabro_core::state::RunState; -use crate::artifact::{offload_large_values, sync_artifacts_to_env, ArtifactStore}; +use crate::artifact::{ArtifactStore, offload_large_values, sync_artifacts_to_env}; use crate::asset_snapshot::collect_assets; use crate::event::{EventEmitter, RunNoticeLevel, WorkflowRunEvent}; use crate::graph::WorkflowGraph; diff --git a/lib/crates/fabro-workflows/src/lifecycle/disk.rs b/lib/crates/fabro-workflows/src/lifecycle/disk.rs index 838a3eca2..a2d4cb0a5 100644 --- a/lib/crates/fabro-workflows/src/lifecycle/disk.rs +++ b/lib/crates/fabro-workflows/src/lifecycle/disk.rs @@ -17,7 +17,7 @@ use crate::outcome::StageUsage; use crate::records::{Checkpoint, CheckpointExt}; use crate::run_dir::{write_node_status, write_start_record}; use crate::run_options::RunOptions; -use crate::run_status::{write_run_status, RunStatus}; +use crate::run_status::{RunStatus, write_run_status}; use fabro_graphviz::graph::types::Graph as GvGraph; type WfRunState = RunState>; diff --git a/lib/crates/fabro-workflows/src/lifecycle/event.rs b/lib/crates/fabro-workflows/src/lifecycle/event.rs index 3677dab6a..c7a3f6499 100644 --- a/lib/crates/fabro-workflows/src/lifecycle/event.rs +++ b/lib/crates/fabro-workflows/src/lifecycle/event.rs @@ -18,7 +18,7 @@ use crate::event::{EventEmitter, WorkflowRunEvent}; use crate::graph::WorkflowGraph; use crate::graph::WorkflowNode; use crate::outcome::{ - stage_usage_to_llm, FailureCategory, FailureDetail, Outcome, StageStatus, StageUsage, + FailureCategory, FailureDetail, Outcome, StageStatus, StageUsage, stage_usage_to_llm, }; use fabro_graphviz::graph::types::Node as GvNode; @@ -295,11 +295,7 @@ impl RunLifecycle for EventLifecycle { .values() .filter_map(|o| o.usage.as_ref()?.cost) .sum(); - if sum > 0.0 { - Some(sum) - } else { - None - } + if sum > 0.0 { Some(sum) } else { None } }; let run_usage = state .node_outcomes diff --git a/lib/crates/fabro-workflows/src/lifecycle/git.rs b/lib/crates/fabro-workflows/src/lifecycle/git.rs index e5d0f1d9a..1a7b6d658 100644 --- a/lib/crates/fabro-workflows/src/lifecycle/git.rs +++ b/lib/crates/fabro-workflows/src/lifecycle/git.rs @@ -11,8 +11,8 @@ use fabro_core::state::RunState; use crate::artifact::ArtifactStore; use crate::event::{EventEmitter, RunNoticeLevel, WorkflowRunEvent}; -use crate::git::scan_node_files; use crate::git::MetadataStore; +use crate::git::scan_node_files; use crate::graph::WorkflowGraph; use crate::graph::WorkflowNode; use crate::outcome::{Outcome, StageStatus, StageUsage}; diff --git a/lib/crates/fabro-workflows/src/node_handler.rs b/lib/crates/fabro-workflows/src/node_handler.rs index a840e2dd5..06b149992 100644 --- a/lib/crates/fabro-workflows/src/node_handler.rs +++ b/lib/crates/fabro-workflows/src/node_handler.rs @@ -14,7 +14,7 @@ use crate::context::Context; use crate::graph::WorkflowGraph; use crate::graph::WorkflowNode; -use crate::handler::{dispatch_handler, format_panic_message, EngineServices}; +use crate::handler::{EngineServices, dispatch_handler, format_panic_message}; use crate::outcome::{Outcome, StageStatus}; use crate::retry::build_retry_policy; use crate::run_dir; @@ -143,8 +143,8 @@ mod tests { use fabro_core::lifecycle::NoopLifecycle; use fabro_core::outcome::StageStatus; use fabro_core::state::RunState; - use fabro_graphviz::graph::types::{Edge, Graph, Node}; use fabro_graphviz::graph::AttrValue; + use fabro_graphviz::graph::types::{Edge, Graph, Node}; use super::*; use crate::graph::WorkflowGraph; diff --git a/lib/crates/fabro-workflows/src/operations/create.rs b/lib/crates/fabro-workflows/src/operations/create.rs index 4313629ac..a74009160 100644 --- a/lib/crates/fabro-workflows/src/operations/create.rs +++ b/lib/crates/fabro-workflows/src/operations/create.rs @@ -12,11 +12,11 @@ use crate::pipeline::types::PersistOptions; use crate::pipeline::{self, Persisted, TransformOptions, Validated}; use crate::records::RunRecord; use crate::run_lookup::default_runs_base; -use crate::run_status::{write_run_status, RunStatus}; -use crate::transforms::{expand_vars, Transform}; +use crate::run_status::{RunStatus, write_run_status}; +use crate::transforms::{Transform, expand_vars}; use fabro_sandbox::daytona::detect_repo_info; -use super::source::{resolve_workflow, ResolveWorkflowInput, WorkflowInput}; +use super::source::{ResolveWorkflowInput, WorkflowInput, resolve_workflow}; const RUN_CONFIG_FILE: &str = "workflow.toml"; @@ -320,7 +320,7 @@ mod tests { use super::*; use fabro_graphviz::graph::AttrValue; - use crate::operations::{validate, ValidateInput}; + use crate::operations::{ValidateInput, validate}; use crate::run_status::RunStatusRecordExt; fn validate_dot(dot_source: &str, settings: FabroSettings) -> Validated { @@ -593,12 +593,14 @@ mod tests { created.persisted.run_record().settings.goal.as_deref(), Some("override goal") ); - assert!(created - .persisted - .run_record() - .settings - .pull_request - .is_none()); + assert!( + created + .persisted + .run_record() + .settings + .pull_request + .is_none() + ); assert_eq!( created.persisted.run_record().workflow_slug.as_deref(), Some("slug") diff --git a/lib/crates/fabro-workflows/src/operations/fork.rs b/lib/crates/fabro-workflows/src/operations/fork.rs index 65eeffa07..e81e4d92f 100644 --- a/lib/crates/fabro-workflows/src/operations/fork.rs +++ b/lib/crates/fabro-workflows/src/operations/fork.rs @@ -3,11 +3,11 @@ use fabro_git_storage::branchstore::BranchStore; use fabro_git_storage::gitobj::Store; use git2::{Oid, Signature}; -use crate::git::{push_run_branches, MetadataStore, RUN_BRANCH_PREFIX}; +use crate::git::{MetadataStore, RUN_BRANCH_PREFIX, push_run_branches}; use crate::records::RunRecord; use crate::records::StartRecord; -use super::rewind::{build_timeline, RewindTarget, TimelineEntry}; +use super::rewind::{RewindTarget, TimelineEntry, build_timeline}; #[derive(Debug, Clone)] pub struct ForkRunInput { diff --git a/lib/crates/fabro-workflows/src/operations/mod.rs b/lib/crates/fabro-workflows/src/operations/mod.rs index 2bdc2f048..5a69ba328 100644 --- a/lib/crates/fabro-workflows/src/operations/mod.rs +++ b/lib/crates/fabro-workflows/src/operations/mod.rs @@ -9,13 +9,13 @@ mod test_support; mod validate; pub use crate::pipeline::{DevcontainerSpec, LlmSpec, SandboxEnvSpec, SandboxSpec}; -pub use create::{create, CreateRunInput, CreatedRun}; -pub use fork::{fork, ForkRunInput}; +pub use create::{CreateRunInput, CreatedRun, create}; +pub use fork::{ForkRunInput, fork}; pub use resume::resume; pub use rewind::{ - build_timeline, find_run_id_by_prefix, rewind, RewindInput, RewindTarget, RunTimeline, - TimelineEntry, + RewindInput, RewindTarget, RunTimeline, TimelineEntry, build_timeline, find_run_id_by_prefix, + rewind, }; pub use source::WorkflowInput; -pub use start::{start, StartServices, Started}; -pub use validate::{validate, ValidateInput}; +pub use start::{StartServices, Started, start}; +pub use validate::{ValidateInput, validate}; diff --git a/lib/crates/fabro-workflows/src/operations/resume.rs b/lib/crates/fabro-workflows/src/operations/resume.rs index 589eceec4..442fd6d23 100644 --- a/lib/crates/fabro-workflows/src/operations/resume.rs +++ b/lib/crates/fabro-workflows/src/operations/resume.rs @@ -7,7 +7,7 @@ use crate::outcome::StageStatus; use crate::records::{Checkpoint, CheckpointExt, Conclusion, ConclusionExt}; use crate::run_status::{self, RunStatus, RunStatusRecordExt}; -use super::start::{execute_persisted_run, StartServices, Started}; +use super::start::{StartServices, Started, execute_persisted_run}; /// Resume a workflow run from its checkpoint. Errors if no checkpoint is found. pub async fn resume(run_dir: &Path, services: StartServices) -> Result { diff --git a/lib/crates/fabro-workflows/src/operations/rewind.rs b/lib/crates/fabro-workflows/src/operations/rewind.rs index 81663f46b..97748a387 100644 --- a/lib/crates/fabro-workflows/src/operations/rewind.rs +++ b/lib/crates/fabro-workflows/src/operations/rewind.rs @@ -1,12 +1,12 @@ use std::collections::HashMap; use std::str::FromStr; -use anyhow::{bail, Context, Result}; +use anyhow::{Context, Result, bail}; use fabro_git_storage::branchstore::{BranchStore, CommitInfo}; use fabro_git_storage::gitobj::Store; use git2::{Oid, Repository, Signature}; -use crate::git::{push_run_branches, MetadataStore, RUN_BRANCH_PREFIX}; +use crate::git::{MetadataStore, RUN_BRANCH_PREFIX, push_run_branches}; use crate::records::{Checkpoint, RunRecord}; use fabro_graphviz::graph::Graph; use fabro_graphviz::parser; diff --git a/lib/crates/fabro-workflows/src/operations/source.rs b/lib/crates/fabro-workflows/src/operations/source.rs index 7562bada4..9228474e3 100644 --- a/lib/crates/fabro-workflows/src/operations/source.rs +++ b/lib/crates/fabro-workflows/src/operations/source.rs @@ -1,7 +1,7 @@ use std::path::{Path, PathBuf}; use anyhow::Context; -use fabro_config::{project as project_config, FabroSettings}; +use fabro_config::{FabroSettings, project as project_config}; use fabro_util::path::expand_tilde; #[derive(Clone, Debug)] diff --git a/lib/crates/fabro-workflows/src/operations/start.rs b/lib/crates/fabro-workflows/src/operations/start.rs index f47fad353..b89120c98 100644 --- a/lib/crates/fabro-workflows/src/operations/start.rs +++ b/lib/crates/fabro-workflows/src/operations/start.rs @@ -5,8 +5,8 @@ use std::sync::{Arc, Mutex}; use std::time::{Duration, Instant}; use chrono::Utc; -use fabro_config::sandbox::WorktreeMode; use fabro_config::FabroSettings; +use fabro_config::sandbox::WorktreeMode; use fabro_config::{project as project_config, run as run_config, sandbox as sandbox_config}; use fabro_interview::{AutoApproveInterviewer, Interviewer}; use fabro_model::{Catalog, FallbackTarget, Provider}; @@ -16,23 +16,23 @@ use serde::Serialize; use crate::context::Context; use crate::error::FabroError; use crate::event::{ - append_progress_event, EventEmitter, ProgressLogger, RunNoticeLevel, WorkflowRunEvent, + EventEmitter, ProgressLogger, RunNoticeLevel, WorkflowRunEvent, append_progress_event, }; use crate::git::GitAuthor; use crate::handler::HandlerRegistry; use crate::outcome::{Outcome, StageStatus}; use crate::pipeline::{ - self, build_conclusion, classify_engine_result, persist_terminal_outcome, DevcontainerSpec, - FinalizeOptions, Finalized, InitOptions, LlmSpec, Persisted, PullRequestOptions, RetroOptions, - SandboxEnvSpec, SandboxSpec, + self, DevcontainerSpec, FinalizeOptions, Finalized, InitOptions, LlmSpec, Persisted, + PullRequestOptions, RetroOptions, SandboxEnvSpec, SandboxSpec, build_conclusion, + classify_engine_result, persist_terminal_outcome, }; use crate::records::{Checkpoint, Conclusion, ConclusionExt, RunRecord, RunRecordExt}; use crate::run_options::{GitCheckpointOptions, LifecycleOptions, RunOptions}; use crate::run_status::{self, RunStatus, RunStatusRecordExt, StatusReason}; use fabro_config::run::PullRequestSettings; use fabro_retro::retro::Retro; -use fabro_sandbox::daytona::detect_repo_info; use fabro_sandbox::daytona::DaytonaConfig; +use fabro_sandbox::daytona::detect_repo_info; use fabro_sandbox::ssh::{GitCloneParams as SshGitCloneParams, SshConfig}; use tokio::runtime::Handle; @@ -711,9 +711,9 @@ mod tests { use super::*; use crate::context::Context; use crate::event::EventEmitter; + use crate::handler::HandlerRegistry; use crate::handler::exit::ExitHandler; use crate::handler::start::StartHandler; - use crate::handler::HandlerRegistry; use crate::operations::resume; use crate::records::CheckpointExt; diff --git a/lib/crates/fabro-workflows/src/operations/validate.rs b/lib/crates/fabro-workflows/src/operations/validate.rs index 18a0d2dcf..70f49eb04 100644 --- a/lib/crates/fabro-workflows/src/operations/validate.rs +++ b/lib/crates/fabro-workflows/src/operations/validate.rs @@ -7,7 +7,7 @@ use crate::pipeline::Validated; use crate::transforms::Transform; use super::create::preprocess_and_validate; -use super::source::{resolve_workflow, ResolveWorkflowInput, WorkflowInput}; +use super::source::{ResolveWorkflowInput, WorkflowInput, resolve_workflow}; pub struct ValidateInput { pub workflow: WorkflowInput, diff --git a/lib/crates/fabro-workflows/src/pipeline/execute.rs b/lib/crates/fabro-workflows/src/pipeline/execute.rs index e1c89e6b6..a85441579 100644 --- a/lib/crates/fabro-workflows/src/pipeline/execute.rs +++ b/lib/crates/fabro-workflows/src/pipeline/execute.rs @@ -100,7 +100,9 @@ pub async fn execute(init: Initialized) -> Executed { cp.restart_failure_signatures.clone(), ); if cp.context_values.get(context::keys::INTERNAL_FIDELITY) - == Some(&serde_json::json!(context::keys::Fidelity::Full.to_string())) + == Some(&serde_json::json!( + context::keys::Fidelity::Full.to_string() + )) { lifecycle.set_degrade_fidelity_on_resume(true); } diff --git a/lib/crates/fabro-workflows/src/pipeline/execute/tests.rs b/lib/crates/fabro-workflows/src/pipeline/execute/tests.rs index d0c1fc355..61ebb04a0 100644 --- a/lib/crates/fabro-workflows/src/pipeline/execute/tests.rs +++ b/lib/crates/fabro-workflows/src/pipeline/execute/tests.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use std::path::{Path, PathBuf}; -use std::sync::atomic::{AtomicBool, AtomicU32, Ordering}; use std::sync::Arc; +use std::sync::atomic::{AtomicBool, AtomicU32, Ordering}; use std::time::Duration; use async_trait::async_trait; diff --git a/lib/crates/fabro-workflows/src/pipeline/finalize.rs b/lib/crates/fabro-workflows/src/pipeline/finalize.rs index ee586ab66..c793472c7 100644 --- a/lib/crates/fabro-workflows/src/pipeline/finalize.rs +++ b/lib/crates/fabro-workflows/src/pipeline/finalize.rs @@ -3,11 +3,11 @@ use std::sync::Arc; use crate::error::FabroError; use crate::event::{EventEmitter, RunNoticeLevel, WorkflowRunEvent}; -use crate::git::{scan_node_files, MetadataStore}; +use crate::git::{MetadataStore, scan_node_files}; use crate::outcome::{Outcome, OutcomeExt, StageStatus}; use crate::records::{Checkpoint, CheckpointExt, Conclusion, ConclusionExt, StageSummary}; use crate::run_options::RunOptions; -use crate::run_status::{write_run_status, RunStatus, StatusReason}; +use crate::run_status::{RunStatus, StatusReason, write_run_status}; use crate::sandbox_git::git_push_host; use fabro_hooks::{HookContext, HookEvent, HookRunner}; use fabro_retro::retro::extract_stage_durations; diff --git a/lib/crates/fabro-workflows/src/pipeline/initialize.rs b/lib/crates/fabro-workflows/src/pipeline/initialize.rs index 775351069..2f0e4bd01 100644 --- a/lib/crates/fabro-workflows/src/pipeline/initialize.rs +++ b/lib/crates/fabro-workflows/src/pipeline/initialize.rs @@ -18,7 +18,7 @@ use crate::error::FabroError; use crate::event::{EventEmitter, RunNoticeLevel, WorkflowRunEvent}; use crate::git::{self, GitSyncStatus, MetadataStore}; use crate::handler::llm::{AgentApiBackend, AgentCliBackend, BackendRouter}; -use crate::handler::{default_registry, HandlerRegistry}; +use crate::handler::{HandlerRegistry, default_registry}; use crate::run_options::{GitCheckpointOptions, RunOptions}; use fabro_sandbox::daytona::DaytonaSandbox; use fabro_sandbox::docker::DockerSandboxConfig; @@ -542,11 +542,12 @@ async fn resolve_devcontainer(options: &mut InitOptions) -> Result<(), FabroErro let shell_commands = match command { fabro_devcontainer::Command::Shell(shell) => vec![shell.clone()], fabro_devcontainer::Command::Args(args) => { - vec![args - .iter() - .map(|arg| try_quote(arg).unwrap_or_else(|_| arg.into()).to_string()) - .collect::>() - .join(" ")] + vec![ + args.iter() + .map(|arg| try_quote(arg).unwrap_or_else(|_| arg.into()).to_string()) + .collect::>() + .join(" "), + ] } fabro_devcontainer::Command::Parallel(commands) => commands.values().cloned().collect(), }; @@ -606,11 +607,7 @@ fn write_sandbox_record( let working_directory = sandbox.working_directory().to_string(); let identifier = { let info = sandbox.sandbox_info(); - if info.is_empty() { - None - } else { - Some(info) - } + if info.is_empty() { None } else { Some(info) } }; let record = match spec { diff --git a/lib/crates/fabro-workflows/src/pipeline/mod.rs b/lib/crates/fabro-workflows/src/pipeline/mod.rs index 32f83c5f3..0fb99092d 100644 --- a/lib/crates/fabro-workflows/src/pipeline/mod.rs +++ b/lib/crates/fabro-workflows/src/pipeline/mod.rs @@ -18,7 +18,7 @@ pub use initialize::initialize; pub use parse::parse; pub(crate) use persist::persist; pub use pull_request::{ - build_pr_body, maybe_open_pull_request, pull_request, AutoMergeOptions, PullRequestRecord, + AutoMergeOptions, PullRequestRecord, build_pr_body, maybe_open_pull_request, pull_request, }; pub use retro::{retro, run_retro}; pub use transform::transform; diff --git a/lib/crates/fabro-workflows/src/pipeline/pull_request.rs b/lib/crates/fabro-workflows/src/pipeline/pull_request.rs index a260317e2..ef5f2ecb3 100644 --- a/lib/crates/fabro-workflows/src/pipeline/pull_request.rs +++ b/lib/crates/fabro-workflows/src/pipeline/pull_request.rs @@ -4,14 +4,14 @@ use fabro_config::run::MergeStrategy; use serde::{Deserialize, Serialize}; use tracing::{debug, info}; -use fabro_github::{self as github_app, ssh_url_to_https, GitHubAppCredentials}; +use fabro_github::{self as github_app, GitHubAppCredentials, ssh_url_to_https}; use fabro_graphviz::parser; -use fabro_llm::generate::{generate, GenerateParams}; +use fabro_llm::generate::{GenerateParams, generate}; use fabro_retro::RetroExt; use fabro_util::text::strip_goal_decoration; use crate::event::{EventEmitter, RunNoticeLevel, WorkflowRunEvent}; -use crate::outcome::{format_cost as outcome_format_cost, StageStatus}; +use crate::outcome::{StageStatus, format_cost as outcome_format_cost}; use crate::records::{Conclusion, ConclusionExt, RunRecord, RunRecordExt}; use fabro_retro::retro::Retro; use tokio::fs::read_to_string; @@ -361,7 +361,9 @@ pub async fn build_pr_body( } else { plan.as_str() }; - format!("Goal: {goal}\n\nPlan:\n```\n{truncated_plan}\n```\n\nDiff:\n```\n{truncated_diff}\n```") + format!( + "Goal: {goal}\n\nPlan:\n```\n{truncated_plan}\n```\n\nDiff:\n```\n{truncated_diff}\n```" + ) } else { format!("Goal: {goal}\n\nDiff:\n```\n{truncated_diff}\n```") }; diff --git a/lib/crates/fabro-workflows/src/pipeline/retro.rs b/lib/crates/fabro-workflows/src/pipeline/retro.rs index e143c3cbf..4158d16ed 100644 --- a/lib/crates/fabro-workflows/src/pipeline/retro.rs +++ b/lib/crates/fabro-workflows/src/pipeline/retro.rs @@ -1,9 +1,9 @@ use std::sync::Arc; use fabro_agent::SessionEvent; -use fabro_retro::retro::{derive_retro, extract_stage_durations, Retro}; -use fabro_retro::retro_agent::{dry_run_narrative, run_retro_agent}; use fabro_retro::RetroExt; +use fabro_retro::retro::{Retro, derive_retro, extract_stage_durations}; +use fabro_retro::retro_agent::{dry_run_narrative, run_retro_agent}; use crate::event::WorkflowRunEvent; use crate::records::{Checkpoint, CheckpointExt}; @@ -285,11 +285,13 @@ mod tests { assert!(retro.is_some()); let seen = seen.lock().unwrap(); - assert!(seen - .iter() - .any(|event| matches!(event, WorkflowRunEvent::RetroStarted))); - assert!(seen - .iter() - .any(|event| matches!(event, WorkflowRunEvent::RetroCompleted { .. }))); + assert!( + seen.iter() + .any(|event| matches!(event, WorkflowRunEvent::RetroStarted)) + ); + assert!( + seen.iter() + .any(|event| matches!(event, WorkflowRunEvent::RetroCompleted { .. })) + ); } } diff --git a/lib/crates/fabro-workflows/src/pipeline/validate.rs b/lib/crates/fabro-workflows/src/pipeline/validate.rs index f5fe62eec..2f68d63f1 100644 --- a/lib/crates/fabro-workflows/src/pipeline/validate.rs +++ b/lib/crates/fabro-workflows/src/pipeline/validate.rs @@ -67,9 +67,11 @@ mod tests { let (graph, source, diagnostics) = validated.into_parts(); assert_eq!(graph.name, "Test"); assert_eq!(source, dot); - assert!(diagnostics - .iter() - .all(|d| d.severity != fabro_validate::Severity::Error)); + assert!( + diagnostics + .iter() + .all(|d| d.severity != fabro_validate::Severity::Error) + ); } #[test] diff --git a/lib/crates/fabro-workflows/src/pull_request.rs b/lib/crates/fabro-workflows/src/pull_request.rs index 679015837..af5c5bd15 100644 --- a/lib/crates/fabro-workflows/src/pull_request.rs +++ b/lib/crates/fabro-workflows/src/pull_request.rs @@ -1,3 +1,3 @@ pub use crate::pipeline::{ - build_pr_body, maybe_open_pull_request, AutoMergeOptions, PullRequestRecord, + AutoMergeOptions, PullRequestRecord, build_pr_body, maybe_open_pull_request, }; diff --git a/lib/crates/fabro-workflows/src/run_lookup.rs b/lib/crates/fabro-workflows/src/run_lookup.rs index 9130ce757..aebb83d89 100644 --- a/lib/crates/fabro-workflows/src/run_lookup.rs +++ b/lib/crates/fabro-workflows/src/run_lookup.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use std::path::{Path, PathBuf}; -use anyhow::{bail, Context, Result}; +use anyhow::{Context, Result, bail}; use chrono::{DateTime, Utc}; use serde::Serialize; diff --git a/lib/crates/fabro-workflows/src/run_options.rs b/lib/crates/fabro-workflows/src/run_options.rs index 401245f7f..d15e8a0d6 100644 --- a/lib/crates/fabro-workflows/src/run_options.rs +++ b/lib/crates/fabro-workflows/src/run_options.rs @@ -1,10 +1,10 @@ use std::collections::HashMap; use std::path::PathBuf; -use std::sync::atomic::AtomicBool; use std::sync::Arc; +use std::sync::atomic::AtomicBool; -use fabro_config::run::PullRequestSettings; use fabro_config::FabroSettings; +use fabro_config::run::PullRequestSettings; use crate::git::GitAuthor; diff --git a/lib/crates/fabro-workflows/src/sandbox_git.rs b/lib/crates/fabro-workflows/src/sandbox_git.rs index 566205c45..7639bedac 100644 --- a/lib/crates/fabro-workflows/src/sandbox_git.rs +++ b/lib/crates/fabro-workflows/src/sandbox_git.rs @@ -4,7 +4,7 @@ use fabro_agent::Sandbox; use fabro_git_storage::trailerlink::{self, Trailer}; use crate::asset_snapshot; -use crate::git::{blocking_push_with_timeout, push_ref, GitAuthor}; +use crate::git::{GitAuthor, blocking_push_with_timeout, push_ref}; use fabro_sandbox::daytona::detect_repo_info; /// Captured git state for a workflow run, shared with handlers. diff --git a/lib/crates/fabro-workflows/src/transforms/mod.rs b/lib/crates/fabro-workflows/src/transforms/mod.rs index 8ed5ab6f7..15ae8b670 100644 --- a/lib/crates/fabro-workflows/src/transforms/mod.rs +++ b/lib/crates/fabro-workflows/src/transforms/mod.rs @@ -13,9 +13,9 @@ pub mod stylesheet; mod stylesheet_application; pub mod variable_expansion; -pub use file_inlining::{resolve_file_ref, FileInliningTransform}; +pub use file_inlining::{FileInliningTransform, resolve_file_ref}; pub use graph_merge::GraphMergeTransform; pub use model_resolution::ModelResolutionTransform; pub use preamble::PreambleTransform; pub use stylesheet_application::StylesheetApplicationTransform; -pub use variable_expansion::{expand_vars, VariableExpansionTransform}; +pub use variable_expansion::{VariableExpansionTransform, expand_vars}; diff --git a/lib/crates/fabro-workflows/src/transforms/stylesheet.rs b/lib/crates/fabro-workflows/src/transforms/stylesheet.rs index 45b3468c2..e8a92ede3 100644 --- a/lib/crates/fabro-workflows/src/transforms/stylesheet.rs +++ b/lib/crates/fabro-workflows/src/transforms/stylesheet.rs @@ -1,5 +1,5 @@ use fabro_graphviz::graph::{AttrValue, Graph}; -pub use fabro_graphviz::stylesheet::{parse_stylesheet, Rule, Selector, Stylesheet}; +pub use fabro_graphviz::stylesheet::{Rule, Selector, Stylesheet, parse_stylesheet}; /// Recognized stylesheet properties. const STYLESHEET_PROPERTIES: &[&str] = diff --git a/lib/crates/fabro-workflows/src/transforms/stylesheet_application.rs b/lib/crates/fabro-workflows/src/transforms/stylesheet_application.rs index c95e9bf01..6d44471f7 100644 --- a/lib/crates/fabro-workflows/src/transforms/stylesheet_application.rs +++ b/lib/crates/fabro-workflows/src/transforms/stylesheet_application.rs @@ -1,7 +1,7 @@ use fabro_graphviz::graph::Graph; -use super::stylesheet::{apply_stylesheet, parse_stylesheet}; use super::Transform; +use super::stylesheet::{apply_stylesheet, parse_stylesheet}; /// Applies the `model_stylesheet` graph attribute to resolve LLM properties for each node. pub struct StylesheetApplicationTransform; diff --git a/lib/crates/fabro-workflows/tests/daytona_integration.rs b/lib/crates/fabro-workflows/tests/daytona_integration.rs index 7a1f2f2ab..306ed2980 100644 --- a/lib/crates/fabro-workflows/tests/daytona_integration.rs +++ b/lib/crates/fabro-workflows/tests/daytona_integration.rs @@ -11,8 +11,8 @@ use fabro_agent::Sandbox; use fabro_config::FabroSettings; use fabro_graphviz::graph::{AttrValue, Edge, Graph, Node}; use fabro_llm::provider::Provider; -use fabro_sandbox::daytona::{DaytonaConfig, DaytonaSandbox, DaytonaSnapshotConfig}; use fabro_sandbox::SandboxRecordExt; +use fabro_sandbox::daytona::{DaytonaConfig, DaytonaSandbox, DaytonaSnapshotConfig}; use fabro_store::RuntimeState; use fabro_workflows::artifact::sync_artifacts_to_env; use fabro_workflows::context::Context; @@ -1737,8 +1737,8 @@ async fn daytona_toolbox_idle_diagnostic() { #[tokio::test] #[ignore] async fn daytona_cp_upload_download_round_trip() { - use fabro_sandbox::reconnect::reconnect; use fabro_sandbox::SandboxRecord; + use fabro_sandbox::reconnect::reconnect; // 1. Create and initialize a real Daytona sandbox let env = create_env().await; diff --git a/lib/crates/fabro-workflows/tests/integration.rs b/lib/crates/fabro-workflows/tests/integration.rs index 8f36c2619..d9eff5e33 100644 --- a/lib/crates/fabro-workflows/tests/integration.rs +++ b/lib/crates/fabro-workflows/tests/integration.rs @@ -12,7 +12,7 @@ use fabro_interview::{ }; use fabro_llm::provider::Provider; use fabro_store::RuntimeState; -use fabro_validate::{validate, validate_or_raise, Severity}; +use fabro_validate::{Severity, validate, validate_or_raise}; use fabro_workflows::context::Context; use fabro_workflows::error::{FabroError, FailureSignatureExt}; use fabro_workflows::event::{EventEmitter, WorkflowRunEvent}; @@ -22,8 +22,8 @@ use fabro_workflows::handler::conditional::ConditionalHandler; use fabro_workflows::handler::default_registry; use fabro_workflows::handler::exit::ExitHandler; use fabro_workflows::handler::human::HumanHandler; -use fabro_workflows::handler::llm::cli::{parse_cli_response, AgentCliBackend, BackendRouter}; use fabro_workflows::handler::llm::AgentApiBackend; +use fabro_workflows::handler::llm::cli::{AgentCliBackend, BackendRouter, parse_cli_response}; use fabro_workflows::handler::manager_loop::SubWorkflowHandler; use fabro_workflows::handler::start::StartHandler; use fabro_workflows::handler::wait::WaitHandler; @@ -32,7 +32,7 @@ use fabro_workflows::outcome::{Outcome, OutcomeExt, StageStatus}; use fabro_workflows::records::{Checkpoint, CheckpointExt}; use fabro_workflows::run_options::{GitCheckpointOptions, RunOptions}; use fabro_workflows::stylesheet::{apply_stylesheet, parse_stylesheet}; -use fabro_workflows::test_support::{run_graph_with_hooks, WorkflowRunner}; +use fabro_workflows::test_support::{WorkflowRunner, run_graph_with_hooks}; use fabro_workflows::transform::{ StylesheetApplicationTransform, Transform, VariableExpansionTransform, }; @@ -220,9 +220,11 @@ async fn end_to_end_linear_pipeline() { let checkpoint = Checkpoint::load(&checkpoint_path).expect("checkpoint should load"); assert!(checkpoint.completed_nodes.contains(&"start".to_string())); - assert!(checkpoint - .completed_nodes - .contains(&"codergen_step".to_string())); + assert!( + checkpoint + .completed_nodes + .contains(&"codergen_step".to_string()) + ); // Codergen handler writes prompt.md, response.md, status.json let stage_dir = dir.path().join("nodes").join("codergen_step"); @@ -2012,27 +2014,41 @@ async fn event_streaming_lifecycle() { engine.run(&graph, &run_options).await.expect("run"); let collected = events.lock().unwrap(); - assert!(collected - .iter() - .any(|e| matches!(e, WorkflowRunEvent::WorkflowRunStarted { .. }))); - assert!(collected - .iter() - .any(|e| matches!(e, WorkflowRunEvent::StageStarted { name, .. } if name == "start"))); - assert!(collected - .iter() - .any(|e| matches!(e, WorkflowRunEvent::StageCompleted { name, .. } if name == "start"))); - assert!(collected - .iter() - .any(|e| matches!(e, WorkflowRunEvent::StageStarted { name, .. } if name == "task"))); - assert!(collected - .iter() - .any(|e| matches!(e, WorkflowRunEvent::StageCompleted { name, .. } if name == "task"))); - assert!(collected - .iter() - .any(|e| matches!(e, WorkflowRunEvent::CheckpointCompleted { .. }))); - assert!(collected - .iter() - .any(|e| matches!(e, WorkflowRunEvent::WorkflowRunCompleted { .. }))); + assert!( + collected + .iter() + .any(|e| matches!(e, WorkflowRunEvent::WorkflowRunStarted { .. })) + ); + assert!( + collected + .iter() + .any(|e| matches!(e, WorkflowRunEvent::StageStarted { name, .. } if name == "start")) + ); + assert!( + collected + .iter() + .any(|e| matches!(e, WorkflowRunEvent::StageCompleted { name, .. } if name == "start")) + ); + assert!( + collected + .iter() + .any(|e| matches!(e, WorkflowRunEvent::StageStarted { name, .. } if name == "task")) + ); + assert!( + collected + .iter() + .any(|e| matches!(e, WorkflowRunEvent::StageCompleted { name, .. } if name == "task")) + ); + assert!( + collected + .iter() + .any(|e| matches!(e, WorkflowRunEvent::CheckpointCompleted { .. })) + ); + assert!( + collected + .iter() + .any(|e| matches!(e, WorkflowRunEvent::WorkflowRunCompleted { .. })) + ); // WorkflowRunStarted first, WorkflowRunCompleted last assert!(matches!( collected.first().unwrap(), @@ -2150,10 +2166,12 @@ async fn tool_handler_e2e() { .context_values .get("command.output") .expect("command.output should exist"); - assert!(command_output - .as_str() - .unwrap() - .contains("hello-from-script")); + assert!( + command_output + .as_str() + .unwrap() + .contains("hello-from-script") + ); } #[tokio::test] @@ -2510,12 +2528,16 @@ async fn scenario_ship_a_feature() { assert!(cp.completed_nodes.contains(&"review".to_string())); let collected = events.lock().unwrap(); - assert!(collected - .iter() - .any(|e| matches!(e, WorkflowRunEvent::WorkflowRunStarted { .. }))); - assert!(collected - .iter() - .any(|e| matches!(e, WorkflowRunEvent::WorkflowRunCompleted { .. }))); + assert!( + collected + .iter() + .any(|e| matches!(e, WorkflowRunEvent::WorkflowRunStarted { .. })) + ); + assert!( + collected + .iter() + .any(|e| matches!(e, WorkflowRunEvent::WorkflowRunCompleted { .. })) + ); } #[tokio::test] @@ -2968,11 +2990,13 @@ async fn manager_loop_stop_condition_satisfied_e2e() { let cp = Checkpoint::load(&dir.path().join("checkpoint.json")).unwrap(); let manager_outcome = cp.node_outcomes.get("manager").expect("manager outcome"); assert_eq!(manager_outcome.status, StageStatus::Success); - assert!(manager_outcome - .notes - .as_deref() - .unwrap() - .contains("Stop condition satisfied")); + assert!( + manager_outcome + .notes + .as_deref() + .unwrap() + .contains("Stop condition satisfied") + ); // Overall pipeline succeeds because manager succeeded assert_eq!(outcome.status, StageStatus::Success); } @@ -3045,10 +3069,12 @@ async fn manager_loop_max_cycles_exceeded_e2e() { let cp = Checkpoint::load(&dir.path().join("checkpoint.json")).unwrap(); let manager_outcome = cp.node_outcomes.get("manager").expect("manager outcome"); assert_eq!(manager_outcome.status, StageStatus::Fail); - assert!(manager_outcome - .failure_reason() - .unwrap() - .contains("Max cycles")); + assert!( + manager_outcome + .failure_reason() + .unwrap() + .contains("Max cycles") + ); // Pipeline reached exit with goal gates satisfied — per spec, SUCCESS. assert_eq!(outcome.status, StageStatus::Success); } @@ -3554,27 +3580,33 @@ async fn integration_smoke_plan_implement_review_done() { assert!(cp.completed_nodes.contains(&"review".to_string())); // Verify prompt.md and response.md exist - assert!(dir - .path() - .join("nodes") - .join("plan") - .join("prompt.md") - .exists()); - assert!(dir - .path() - .join("nodes") - .join("plan") - .join("response.md") - .exists()); + assert!( + dir.path() + .join("nodes") + .join("plan") + .join("prompt.md") + .exists() + ); + assert!( + dir.path() + .join("nodes") + .join("plan") + .join("response.md") + .exists() + ); // Verify events let collected = events.lock().unwrap(); - assert!(collected - .iter() - .any(|e| matches!(e, WorkflowRunEvent::WorkflowRunStarted { .. }))); - assert!(collected - .iter() - .any(|e| matches!(e, WorkflowRunEvent::WorkflowRunCompleted { .. }))); + assert!( + collected + .iter() + .any(|e| matches!(e, WorkflowRunEvent::WorkflowRunStarted { .. })) + ); + assert!( + collected + .iter() + .any(|e| matches!(e, WorkflowRunEvent::WorkflowRunCompleted { .. })) + ); } // =========================================================================== @@ -5969,10 +6001,10 @@ mod real_llm { use fabro_graphviz::graph::{AttrValue, Edge, Graph}; use fabro_interview::AutoApproveInterviewer; use fabro_workflows::event::EventEmitter; + use fabro_workflows::handler::HandlerRegistry; use fabro_workflows::handler::exit::ExitHandler; use fabro_workflows::handler::human::HumanHandler; use fabro_workflows::handler::start::StartHandler; - use fabro_workflows::handler::HandlerRegistry; use fabro_workflows::outcome::StageStatus; use fabro_workflows::records::{Checkpoint, CheckpointExt}; use fabro_workflows::run_options::RunOptions; @@ -7080,9 +7112,11 @@ fn subgraph_class_derived_from_label() { // Nodes inside subgraph receive derived class "loop-a" assert!(graph.nodes["plan"].classes.contains(&"loop-a".to_string())); - assert!(graph.nodes["implement"] - .classes - .contains(&"loop-a".to_string())); + assert!( + graph.nodes["implement"] + .classes + .contains(&"loop-a".to_string()) + ); // Nodes outside subgraph do not get the class assert!(!graph.nodes["start"].classes.contains(&"loop-a".to_string())); @@ -7103,9 +7137,11 @@ fn subgraph_class_derivation_strips_special_chars() { let graph = parse(input).expect("parsing should succeed"); // "Code Review!!!" -> lowercase "code review!!!" -> spaces to hyphens "code-review!!!" // -> strip non-alphanumeric except hyphens -> "code-review" - assert!(graph.nodes["reviewer"] - .classes - .contains(&"code-review".to_string())); + assert!( + graph.nodes["reviewer"] + .classes + .contains(&"code-review".to_string()) + ); } #[test] @@ -8074,10 +8110,12 @@ async fn hook_json_block_with_reason() { let result = engine.run(&graph, &run_options).await; assert!(result.is_err()); - assert!(result - .unwrap_err() - .to_string() - .contains("forbidden by policy")); + assert!( + result + .unwrap_err() + .to_string() + .contains("forbidden by policy") + ); } // --- Sandbox field tests --- @@ -9791,10 +9829,12 @@ async fn cli_backend_run_writes_provider_used_json() { assert_eq!(provider_json["mode"], "cli"); assert_eq!(provider_json["provider"], "anthropic"); assert_eq!(provider_json["model"], "claude-opus-4-6"); - assert!(provider_json["command"] - .as_str() - .unwrap() - .contains("claude")); + assert!( + provider_json["command"] + .as_str() + .unwrap() + .contains("claude") + ); } // -- BackendRouter e2e: delegates to correct backend -- diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 000000000..f3e454b61 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,2 @@ +edition = "2024" +style_edition = "2024"