From 153d6ff149461119002c8dffd070f51f1eb6af42 Mon Sep 17 00:00:00 2001 From: argenis de la rosa Date: Sat, 14 Feb 2026 15:36:19 -0500 Subject: [PATCH] fix: resolve clippy warnings and formatting issues for CI - Fix doc_markdown warnings in WhatsApp channel - Fix needless_pass_by_value in cron, health, migration, service modules - Fix match_same_arms in migration.rs - Fix too_many_lines in skills/mod.rs - Fix manual_let_else in tools/file_write.rs - Apply cargo fmt formatting fixes All 435 tests pass, clippy clean. --- src/channels/mod.rs | 2 +- src/channels/whatsapp.rs | 2 +- src/cron/mod.rs | 12 ++++++------ src/cron/scheduler.rs | 2 +- src/doctor/mod.rs | 29 +++++++++++------------------ src/health/mod.rs | 1 + src/main.rs | 8 ++++---- src/migration.rs | 6 +++--- src/security/secrets.rs | 5 ++++- src/service/mod.rs | 2 +- src/skills/mod.rs | 1 + src/tools/file_write.rs | 30 ++++++++++++------------------ 12 files changed, 46 insertions(+), 54 deletions(-) diff --git a/src/channels/mod.rs b/src/channels/mod.rs index e33ef81..cb15934 100644 --- a/src/channels/mod.rs +++ b/src/channels/mod.rs @@ -188,7 +188,7 @@ pub fn build_system_prompt( } } -/// Inject OpenClaw (markdown) identity files into the prompt +/// Inject `OpenClaw` (markdown) identity files into the prompt fn inject_openclaw_identity(prompt: &mut String, workspace_dir: &std::path::Path) { #[allow(unused_imports)] use std::fmt::Write; diff --git a/src/channels/whatsapp.rs b/src/channels/whatsapp.rs index bc038f0..e739239 100644 --- a/src/channels/whatsapp.rs +++ b/src/channels/whatsapp.rs @@ -2,7 +2,7 @@ use super::traits::{Channel, ChannelMessage}; use async_trait::async_trait; use uuid::Uuid; -/// WhatsApp channel — uses WhatsApp Business Cloud API +/// `WhatsApp` channel — uses `WhatsApp` Business Cloud API /// /// This channel operates in webhook mode (push-based) rather than polling. /// Messages are received via the gateway's `/whatsapp` webhook endpoint. diff --git a/src/cron/mod.rs b/src/cron/mod.rs index 572670d..cb7c87d 100644 --- a/src/cron/mod.rs +++ b/src/cron/mod.rs @@ -18,10 +18,11 @@ pub struct CronJob { pub last_status: Option, } -pub fn handle_command(command: super::CronCommands, config: Config) -> Result<()> { +#[allow(clippy::needless_pass_by_value)] +pub fn handle_command(command: super::CronCommands, config: &Config) -> Result<()> { match command { super::CronCommands::List => { - let jobs = list_jobs(&config)?; + let jobs = list_jobs(config)?; if jobs.is_empty() { println!("No scheduled tasks yet."); println!("\nUsage:"); @@ -33,8 +34,7 @@ pub fn handle_command(command: super::CronCommands, config: Config) -> Result<() for job in jobs { let last_run = job .last_run - .map(|d| d.to_rfc3339()) - .unwrap_or_else(|| "never".into()); + .map_or_else(|| "never".into(), |d| d.to_rfc3339()); let last_status = job.last_status.unwrap_or_else(|| "n/a".into()); println!( "- {} | {} | next={} | last={} ({})\n cmd: {}", @@ -52,14 +52,14 @@ pub fn handle_command(command: super::CronCommands, config: Config) -> Result<() expression, command, } => { - let job = add_job(&config, &expression, &command)?; + let job = add_job(config, &expression, &command)?; println!("✅ Added cron job {}", job.id); println!(" Expr: {}", job.expression); println!(" Next: {}", job.next_run.to_rfc3339()); println!(" Cmd : {}", job.command); Ok(()) } - super::CronCommands::Remove { id } => remove_job(&config, &id), + super::CronCommands::Remove { id } => remove_job(config, &id), } } diff --git a/src/cron/scheduler.rs b/src/cron/scheduler.rs index 973fbee..dce5891 100644 --- a/src/cron/scheduler.rs +++ b/src/cron/scheduler.rs @@ -66,7 +66,7 @@ async fn execute_job_with_retry( } if attempt < retries { - let jitter_ms = (Utc::now().timestamp_subsec_millis() % 250) as u64; + let jitter_ms = u64::from(Utc::now().timestamp_subsec_millis() % 250); time::sleep(Duration::from_millis(backoff_ms + jitter_ms)).await; backoff_ms = (backoff_ms.saturating_mul(2)).min(30_000); } diff --git a/src/doctor/mod.rs b/src/doctor/mod.rs index 62417ea..e858f7c 100644 --- a/src/doctor/mod.rs +++ b/src/doctor/mod.rs @@ -52,25 +52,21 @@ pub fn run(config: &Config) -> Result<()> { let scheduler_ok = scheduler .get("status") .and_then(serde_json::Value::as_str) - .map(|s| s == "ok") - .unwrap_or(false); + .is_some_and(|s| s == "ok"); let scheduler_last_ok = scheduler .get("last_ok") .and_then(serde_json::Value::as_str) .and_then(parse_rfc3339) - .map(|dt| Utc::now().signed_duration_since(dt).num_seconds()) - .unwrap_or(i64::MAX); + .map_or(i64::MAX, |dt| { + Utc::now().signed_duration_since(dt).num_seconds() + }); if scheduler_ok && scheduler_last_ok <= SCHEDULER_STALE_SECONDS { - println!( - " ✅ scheduler healthy (last ok {}s ago)", - scheduler_last_ok - ); + println!(" ✅ scheduler healthy (last ok {scheduler_last_ok}s ago)"); } else { println!( - " ❌ scheduler unhealthy/stale (status_ok={}, age={}s)", - scheduler_ok, scheduler_last_ok + " ❌ scheduler unhealthy/stale (status_ok={scheduler_ok}, age={scheduler_last_ok}s)" ); } } else { @@ -86,14 +82,14 @@ pub fn run(config: &Config) -> Result<()> { let status_ok = component .get("status") .and_then(serde_json::Value::as_str) - .map(|s| s == "ok") - .unwrap_or(false); + .is_some_and(|s| s == "ok"); let age = component .get("last_ok") .and_then(serde_json::Value::as_str) .and_then(parse_rfc3339) - .map(|dt| Utc::now().signed_duration_since(dt).num_seconds()) - .unwrap_or(i64::MAX); + .map_or(i64::MAX, |dt| { + Utc::now().signed_duration_since(dt).num_seconds() + }); if status_ok && age <= CHANNEL_STALE_SECONDS { println!(" ✅ {name} fresh (last ok {age}s ago)"); @@ -107,10 +103,7 @@ pub fn run(config: &Config) -> Result<()> { if channel_count == 0 { println!(" ℹ️ no channel components tracked in state yet"); } else { - println!( - " Channel summary: {} total, {} stale", - channel_count, stale_channels - ); + println!(" Channel summary: {channel_count} total, {stale_channels} stale"); } Ok(()) diff --git a/src/health/mod.rs b/src/health/mod.rs index 4fcd8b2..f3f35d8 100644 --- a/src/health/mod.rs +++ b/src/health/mod.rs @@ -67,6 +67,7 @@ pub fn mark_component_ok(component: &str) { }); } +#[allow(clippy::needless_pass_by_value)] pub fn mark_component_error(component: &str, error: impl ToString) { let err = error.to_string(); upsert_component(component, move |entry| { diff --git a/src/main.rs b/src/main.rs index 46fb1d8..34e5aed 100644 --- a/src/main.rs +++ b/src/main.rs @@ -169,9 +169,9 @@ enum Commands { #[derive(Subcommand, Debug)] enum MigrateCommands { - /// Import memory from an OpenClaw workspace into this ZeroClaw workspace + /// Import memory from an `OpenClaw` workspace into this `ZeroClaw` workspace Openclaw { - /// Optional path to OpenClaw workspace (defaults to ~/.openclaw/workspace) + /// Optional path to `OpenClaw` workspace (defaults to ~/.openclaw/workspace) #[arg(long)] source: Option, @@ -387,9 +387,9 @@ async fn main() -> Result<()> { Ok(()) } - Commands::Cron { cron_command } => cron::handle_command(cron_command, config), + Commands::Cron { cron_command } => cron::handle_command(cron_command, &config), - Commands::Service { service_command } => service::handle_command(service_command, &config), + Commands::Service { service_command } => service::handle_command(&service_command, &config), Commands::Doctor => doctor::run(&config), diff --git a/src/migration.rs b/src/migration.rs index ed160c7..2ce29ba 100644 --- a/src/migration.rs +++ b/src/migration.rs @@ -250,6 +250,7 @@ fn read_openclaw_markdown_entries(source_workspace: &Path) -> Result Option<(&str, &str)> { fn parse_category(raw: &str) -> MemoryCategory { match raw.trim().to_ascii_lowercase().as_str() { - "core" => MemoryCategory::Core, + "core" | "" => MemoryCategory::Core, "daily" => MemoryCategory::Daily, "conversation" => MemoryCategory::Conversation, - "" => MemoryCategory::Core, other => MemoryCategory::Custom(other.to_string()), } } @@ -350,7 +350,7 @@ fn pick_optional_column_expr(columns: &[String], candidates: &[&str]) -> Option< candidates .iter() .find(|candidate| columns.iter().any(|c| c == *candidate)) - .map(|s| s.to_string()) + .map(std::string::ToString::to_string) } fn pick_column_expr(columns: &[String], candidates: &[&str], fallback: &str) -> String { diff --git a/src/security/secrets.rs b/src/security/secrets.rs index 6022ebe..3940843 100644 --- a/src/security/secrets.rs +++ b/src/security/secrets.rs @@ -194,7 +194,10 @@ impl SecretStore { let _ = std::process::Command::new("icacls") .arg(&self.key_path) .args(["/inheritance:r", "/grant:r"]) - .arg(format!("{}:F", std::env::var("USERNAME").unwrap_or_default())) + .arg(format!( + "{}:F", + std::env::var("USERNAME").unwrap_or_default() + )) .output(); } diff --git a/src/service/mod.rs b/src/service/mod.rs index fc6bf51..eb933ad 100644 --- a/src/service/mod.rs +++ b/src/service/mod.rs @@ -6,7 +6,7 @@ use std::process::Command; const SERVICE_LABEL: &str = "com.zeroclaw.daemon"; -pub fn handle_command(command: super::ServiceCommands, config: &Config) -> Result<()> { +pub fn handle_command(command: &super::ServiceCommands, config: &Config) -> Result<()> { match command { super::ServiceCommands::Install => install(config), super::ServiceCommands::Start => start(config), diff --git a/src/skills/mod.rs b/src/skills/mod.rs index 0b108fc..34e15d8 100644 --- a/src/skills/mod.rs +++ b/src/skills/mod.rs @@ -239,6 +239,7 @@ fn copy_dir_recursive(src: &Path, dest: &Path) -> Result<()> { } /// Handle the `skills` CLI command +#[allow(clippy::too_many_lines)] pub fn handle_command(command: super::SkillCommands, workspace_dir: &Path) -> Result<()> { match command { super::SkillCommands::List => { diff --git a/src/tools/file_write.rs b/src/tools/file_write.rs index f147497..0760a29 100644 --- a/src/tools/file_write.rs +++ b/src/tools/file_write.rs @@ -69,15 +69,12 @@ impl Tool for FileWriteTool { tokio::fs::create_dir_all(parent).await?; } - let parent = match full_path.parent() { - Some(p) => p, - None => { - return Ok(ToolResult { - success: false, - output: String::new(), - error: Some("Invalid path: missing parent directory".into()), - }); - } + let Some(parent) = full_path.parent() else { + return Ok(ToolResult { + success: false, + output: String::new(), + error: Some("Invalid path: missing parent directory".into()), + }); }; // Resolve parent before writing to block symlink escapes. @@ -103,15 +100,12 @@ impl Tool for FileWriteTool { }); } - let file_name = match full_path.file_name() { - Some(name) => name, - None => { - return Ok(ToolResult { - success: false, - output: String::new(), - error: Some("Invalid path: missing file name".into()), - }); - } + let Some(file_name) = full_path.file_name() else { + return Ok(ToolResult { + success: false, + output: String::new(), + error: Some("Invalid path: missing file name".into()), + }); }; let resolved_target = resolved_parent.join(file_name);