();
if value < reject_threshold {
+ #[allow(clippy::cast_possible_truncation)]
return (value % upper) as usize;
}
}
@@ -1418,7 +1420,7 @@ Allowlist Telegram username (without '@') or numeric user ID.",
if self.mention_only && is_group {
let bot_username = self.bot_username.lock();
if let Some(ref bot_username) = *bot_username {
- if !Self::contains_bot_mention(&text, bot_username) {
+ if !Self::contains_bot_mention(text, bot_username) {
return None;
}
} else {
@@ -1453,7 +1455,7 @@ Allowlist Telegram username (without '@') or numeric user ID.",
let content = if self.mention_only && is_group {
let bot_username = self.bot_username.lock();
let bot_username = bot_username.as_ref()?;
- Self::normalize_incoming_content(&text, bot_username)?
+ Self::normalize_incoming_content(text, bot_username)?
} else {
text.to_string()
};
@@ -1561,7 +1563,7 @@ Allowlist Telegram username (without '@') or numeric user ID.",
if i + 1 < len && bytes[i] == b'*' && bytes[i + 1] == b'*' {
if let Some(end) = line[i + 2..].find("**") {
let inner = Self::escape_html(&line[i + 2..i + 2 + end]);
- line_out.push_str(&format!("{inner}"));
+ write!(line_out, "{inner}").unwrap();
i += 4 + end;
continue;
}
@@ -1569,7 +1571,7 @@ Allowlist Telegram username (without '@') or numeric user ID.",
if i + 1 < len && bytes[i] == b'_' && bytes[i + 1] == b'_' {
if let Some(end) = line[i + 2..].find("__") {
let inner = Self::escape_html(&line[i + 2..i + 2 + end]);
- line_out.push_str(&format!("{inner}"));
+ write!(line_out, "{inner}").unwrap();
i += 4 + end;
continue;
}
@@ -1579,7 +1581,7 @@ Allowlist Telegram username (without '@') or numeric user ID.",
if let Some(end) = line[i + 1..].find('*') {
if end > 0 {
let inner = Self::escape_html(&line[i + 1..i + 1 + end]);
- line_out.push_str(&format!("{inner}"));
+ write!(line_out, "{inner}").unwrap();
i += 2 + end;
continue;
}
@@ -1589,7 +1591,7 @@ Allowlist Telegram username (without '@') or numeric user ID.",
if bytes[i] == b'`' && (i == 0 || bytes[i - 1] != b'`') {
if let Some(end) = line[i + 1..].find('`') {
let inner = Self::escape_html(&line[i + 1..i + 1 + end]);
- line_out.push_str(&format!("{inner}"));
+ write!(line_out, "{inner}").unwrap();
i += 2 + end;
continue;
}
@@ -1605,9 +1607,8 @@ Allowlist Telegram username (without '@') or numeric user ID.",
if url.starts_with("http://") || url.starts_with("https://") {
let text_html = Self::escape_html(text_part);
let url_html = Self::escape_html(url);
- line_out.push_str(&format!(
- "{text_html}"
- ));
+ write!(line_out, "{text_html}")
+ .unwrap();
i = after_bracket + 1 + paren_end + 1;
continue;
}
@@ -1619,7 +1620,7 @@ Allowlist Telegram username (without '@') or numeric user ID.",
if i + 1 < len && bytes[i] == b'~' && bytes[i + 1] == b'~' {
if let Some(end) = line[i + 2..].find("~~") {
let inner = Self::escape_html(&line[i + 2..i + 2 + end]);
- line_out.push_str(&format!("{inner}"));
+ write!(line_out, "{inner}").unwrap();
i += 4 + end;
continue;
}
@@ -1648,14 +1649,14 @@ Allowlist Telegram username (without '@') or numeric user ID.",
for line in joined.split('\n') {
let trimmed = line.trim();
if trimmed.starts_with("```") {
- if !in_code_block {
- in_code_block = true;
- code_buf.clear();
- } else {
+ if in_code_block {
in_code_block = false;
let escaped = code_buf.trim_end_matches('\n');
// Telegram HTML parse mode supports and , but not class attributes.
- final_out.push_str(&format!("{escaped}
\n"));
+ writeln!(final_out, "{escaped}
").unwrap();
+ code_buf.clear();
+ } else {
+ in_code_block = true;
code_buf.clear();
}
} else if in_code_block {
@@ -1667,10 +1668,7 @@ Allowlist Telegram username (without '@') or numeric user ID.",
}
}
if in_code_block && !code_buf.is_empty() {
- final_out.push_str(&format!(
- "{}
\n",
- code_buf.trim_end()
- ));
+ writeln!(final_out, "{}
", code_buf.trim_end()).unwrap();
}
final_out.trim_end_matches('\n').to_string()
@@ -2901,7 +2899,7 @@ mod tests {
"update_id": 1,
"message": {
"message_id": 99,
- "chat": { "id": -100123456 }
+ "chat": { "id": -100_123_456 }
}
});
@@ -4016,7 +4014,10 @@ mod tests {
#[test]
fn telegram_split_many_short_lines() {
- let msg: String = (0..1000).map(|i| format!("line {i}\n")).collect();
+ let msg: String = (0..1000)
+ .map(|i| format!("line {i}\n"))
+ .collect::>()
+ .concat();
let parts = split_message_for_telegram(&msg);
for part in &parts {
assert!(
@@ -4369,7 +4370,7 @@ mod tests {
/// Skipped automatically when `GROQ_API_KEY` is not set.
/// Run: `GROQ_API_KEY= cargo test --lib -- telegram::tests::e2e_live_voice_transcription_and_reply_cache --ignored`
#[tokio::test]
- #[ignore]
+ #[ignore = "requires GROQ_API_KEY"]
async fn e2e_live_voice_transcription_and_reply_cache() {
if std::env::var("GROQ_API_KEY").is_err() {
eprintln!("GROQ_API_KEY not set — skipping live voice transcription test");
diff --git a/src/channels/wati.rs b/src/channels/wati.rs
index 6e3037027..78903bc6b 100644
--- a/src/channels/wati.rs
+++ b/src/channels/wati.rs
@@ -335,7 +335,7 @@ mod tests {
"text": "Hello from WATI!",
"waId": "1234567890",
"fromMe": false,
- "timestamp": 1705320000u64
+ "timestamp": 1_705_320_000_u64
});
let msgs = ch.parse_webhook_payload(&payload);
@@ -344,7 +344,7 @@ mod tests {
assert_eq!(msgs[0].content, "Hello from WATI!");
assert_eq!(msgs[0].channel, "wati");
assert_eq!(msgs[0].reply_target, "+1234567890");
- assert_eq!(msgs[0].timestamp, 1705320000);
+ assert_eq!(msgs[0].timestamp, 1_705_320_000);
}
#[test]
@@ -381,7 +381,7 @@ mod tests {
"message": { "body": "Alt field test" },
"wa_id": "1234567890",
"from_me": false,
- "timestamp": 1705320000u64
+ "timestamp": 1_705_320_000_u64
});
let msgs = ch.parse_webhook_payload(&payload);
@@ -396,11 +396,11 @@ mod tests {
let payload = serde_json::json!({
"text": "Test",
"waId": "1234567890",
- "timestamp": 1705320000u64
+ "timestamp": 1_705_320_000_u64
});
let msgs = ch.parse_webhook_payload(&payload);
- assert_eq!(msgs[0].timestamp, 1705320000);
+ assert_eq!(msgs[0].timestamp, 1_705_320_000);
}
#[test]
@@ -409,11 +409,11 @@ mod tests {
let payload = serde_json::json!({
"text": "Test",
"waId": "1234567890",
- "timestamp": 1705320000000u64
+ "timestamp": 1_705_320_000_000_u64
});
let msgs = ch.parse_webhook_payload(&payload);
- assert_eq!(msgs[0].timestamp, 1705320000);
+ assert_eq!(msgs[0].timestamp, 1_705_320_000);
}
#[test]
@@ -426,7 +426,7 @@ mod tests {
});
let msgs = ch.parse_webhook_payload(&payload);
- assert_eq!(msgs[0].timestamp, 1736942400);
+ assert_eq!(msgs[0].timestamp, 1_736_942_400);
}
#[test]
diff --git a/src/config/mod.rs b/src/config/mod.rs
index 2dcae5ebc..ed540dc83 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -20,7 +20,7 @@ pub use schema::{
WebFetchConfig, WebSearchConfig, WebhookConfig,
};
-pub fn name_and_presence(channel: &Option) -> (&'static str, bool) {
+pub fn name_and_presence(channel: Option<&T>) -> (&'static str, bool) {
(T::name(), channel.is_some())
}
diff --git a/src/config/schema.rs b/src/config/schema.rs
index 02df1002f..3ee73c5c8 100644
--- a/src/config/schema.rs
+++ b/src/config/schema.rs
@@ -537,7 +537,7 @@ fn parse_skills_prompt_injection_mode(raw: &str) -> Option Self {
- Self {
- open_skills_enabled: false,
- open_skills_dir: None,
- prompt_injection_mode: SkillsPromptInjectionMode::default(),
- }
- }
-}
-
/// Multimodal (image) handling configuration (`[multimodal]` section).
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct MultimodalConfig {
@@ -2076,20 +2066,12 @@ impl Default for HooksConfig {
}
}
-#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
+#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema)]
pub struct BuiltinHooksConfig {
/// Enable the command-logger hook (logs tool calls for auditing).
pub command_logger: bool,
}
-impl Default for BuiltinHooksConfig {
- fn default() -> Self {
- Self {
- command_logger: false,
- }
- }
-}
-
// ── Autonomy / Security ──────────────────────────────────────────
/// Autonomy and security policy configuration (`[autonomy]` section).
@@ -2774,7 +2756,7 @@ pub struct CustomTunnelConfig {
struct ConfigWrapper(std::marker::PhantomData);
impl ConfigWrapper {
- fn new(_: &Option) -> Self {
+ fn new(_: Option<&T>) -> Self {
Self(std::marker::PhantomData)
}
}
@@ -2850,81 +2832,81 @@ impl ChannelsConfig {
pub fn channels_except_webhook(&self) -> Vec<(Box, bool)> {
vec![
(
- Box::new(ConfigWrapper::new(&self.telegram)),
+ Box::new(ConfigWrapper::new(self.telegram.as_ref())),
self.telegram.is_some(),
),
(
- Box::new(ConfigWrapper::new(&self.discord)),
+ Box::new(ConfigWrapper::new(self.discord.as_ref())),
self.discord.is_some(),
),
(
- Box::new(ConfigWrapper::new(&self.slack)),
+ Box::new(ConfigWrapper::new(self.slack.as_ref())),
self.slack.is_some(),
),
(
- Box::new(ConfigWrapper::new(&self.mattermost)),
+ Box::new(ConfigWrapper::new(self.mattermost.as_ref())),
self.mattermost.is_some(),
),
(
- Box::new(ConfigWrapper::new(&self.imessage)),
+ Box::new(ConfigWrapper::new(self.imessage.as_ref())),
self.imessage.is_some(),
),
(
- Box::new(ConfigWrapper::new(&self.matrix)),
+ Box::new(ConfigWrapper::new(self.matrix.as_ref())),
self.matrix.is_some(),
),
(
- Box::new(ConfigWrapper::new(&self.signal)),
+ Box::new(ConfigWrapper::new(self.signal.as_ref())),
self.signal.is_some(),
),
(
- Box::new(ConfigWrapper::new(&self.whatsapp)),
+ Box::new(ConfigWrapper::new(self.whatsapp.as_ref())),
self.whatsapp.is_some(),
),
(
- Box::new(ConfigWrapper::new(&self.linq)),
+ Box::new(ConfigWrapper::new(self.linq.as_ref())),
self.linq.is_some(),
),
(
- Box::new(ConfigWrapper::new(&self.wati)),
+ Box::new(ConfigWrapper::new(self.wati.as_ref())),
self.wati.is_some(),
),
(
- Box::new(ConfigWrapper::new(&self.nextcloud_talk)),
+ Box::new(ConfigWrapper::new(self.nextcloud_talk.as_ref())),
self.nextcloud_talk.is_some(),
),
(
- Box::new(ConfigWrapper::new(&self.email)),
+ Box::new(ConfigWrapper::new(self.email.as_ref())),
self.email.is_some(),
),
(
- Box::new(ConfigWrapper::new(&self.irc)),
+ Box::new(ConfigWrapper::new(self.irc.as_ref())),
self.irc.is_some()
),
(
- Box::new(ConfigWrapper::new(&self.lark)),
+ Box::new(ConfigWrapper::new(self.lark.as_ref())),
self.lark.is_some(),
),
(
- Box::new(ConfigWrapper::new(&self.feishu)),
+ Box::new(ConfigWrapper::new(self.feishu.as_ref())),
self.feishu.is_some(),
),
(
- Box::new(ConfigWrapper::new(&self.dingtalk)),
+ Box::new(ConfigWrapper::new(self.dingtalk.as_ref())),
self.dingtalk.is_some(),
),
(
- Box::new(ConfigWrapper::new(&self.qq)),
+ Box::new(ConfigWrapper::new(self.qq.as_ref())),
self.qq
.as_ref()
.is_some_and(|qq| qq.receive_mode == QQReceiveMode::Websocket)
),
(
- Box::new(ConfigWrapper::new(&self.nostr)),
+ Box::new(ConfigWrapper::new(self.nostr.as_ref())),
self.nostr.is_some(),
),
(
- Box::new(ConfigWrapper::new(&self.clawdtalk)),
+ Box::new(ConfigWrapper::new(self.clawdtalk.as_ref())),
self.clawdtalk.is_some(),
),
]
@@ -2933,7 +2915,7 @@ impl ChannelsConfig {
pub fn channels(&self) -> Vec<(Box, bool)> {
let mut ret = self.channels_except_webhook();
ret.push((
- Box::new(ConfigWrapper::new(&self.webhook)),
+ Box::new(ConfigWrapper::new(self.webhook.as_ref())),
self.webhook.is_some(),
));
ret
@@ -5116,7 +5098,7 @@ async fn sync_directory(path: &Path) -> Result<()> {
dir.sync_all()
.await
.with_context(|| format!("Failed to fsync directory metadata: {}", path.display()))?;
- return Ok(());
+ Ok(())
}
#[cfg(not(unix))]
diff --git a/src/gateway/api.rs b/src/gateway/api.rs
index 8f8d304df..83c3e512d 100644
--- a/src/gateway/api.rs
+++ b/src/gateway/api.rs
@@ -575,6 +575,7 @@ fn mask_vec_secrets(values: &mut [String]) {
}
}
+#[allow(clippy::ref_option)]
fn restore_optional_secret(value: &mut Option, current: &Option) {
if value.as_deref().is_some_and(is_masked_secret) {
*value = current.clone();
@@ -699,7 +700,7 @@ fn restore_masked_sensitive_fields(
¤t.storage.provider.config.db_url,
);
- for (name, agent) in incoming.agents.iter_mut() {
+ for (name, agent) in &mut incoming.agents {
if let Some(current_agent) = current.agents.get(name) {
restore_optional_secret(&mut agent.api_key, ¤t_agent.api_key);
}
diff --git a/src/gateway/ws.rs b/src/gateway/ws.rs
index 32a81d4e2..79fee5105 100644
--- a/src/gateway/ws.rs
+++ b/src/gateway/ws.rs
@@ -71,8 +71,7 @@ async fn handle_socket(mut socket: WebSocket, state: AppState) {
while let Some(msg) = socket.recv().await {
let msg = match msg {
Ok(Message::Text(text)) => text,
- Ok(Message::Close(_)) => break,
- Err(_) => break,
+ Ok(Message::Close(_)) | Err(_) => break,
_ => continue,
};
diff --git a/src/hardware/mod.rs b/src/hardware/mod.rs
index 67407a734..a1fa82314 100644
--- a/src/hardware/mod.rs
+++ b/src/hardware/mod.rs
@@ -109,7 +109,7 @@ pub fn handle_command(cmd: crate::HardwareCommands, _config: &Config) -> Result<
let _ = &cmd;
println!("Hardware discovery requires the 'hardware' feature.");
println!("Build with: cargo build --features hardware");
- return Ok(());
+ Ok(())
}
#[cfg(all(
diff --git a/src/main.rs b/src/main.rs
index 484000cec..a87f1b78d 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -794,8 +794,7 @@ async fn main() -> Result<()> {
}
match cli.command {
- Commands::Onboard { .. } => unreachable!(),
- Commands::Completions { .. } => unreachable!(),
+ Commands::Onboard { .. } | Commands::Completions { .. } => unreachable!(),
Commands::Agent {
message,
diff --git a/src/memory/hygiene.rs b/src/memory/hygiene.rs
index 697cfeffa..83b5b4896 100644
--- a/src/memory/hygiene.rs
+++ b/src/memory/hygiene.rs
@@ -324,6 +324,7 @@ fn memory_date_from_filename(filename: &str) -> Option {
NaiveDate::parse_from_str(date_part, "%Y-%m-%d").ok()
}
+#[allow(clippy::incompatible_msrv)]
fn date_prefix(filename: &str) -> Option {
if filename.len() < 10 {
return None;
diff --git a/src/observability/runtime_trace.rs b/src/observability/runtime_trace.rs
index 0bcdd55bf..e3ca98146 100644
--- a/src/observability/runtime_trace.rs
+++ b/src/observability/runtime_trace.rs
@@ -22,7 +22,6 @@ pub enum RuntimeTraceStorageMode {
impl RuntimeTraceStorageMode {
fn from_raw(raw: &str) -> Self {
match raw.trim().to_ascii_lowercase().as_str() {
- "none" => Self::None,
"rolling" => Self::Rolling,
"full" => Self::Full,
_ => Self::None,
diff --git a/src/onboard/wizard.rs b/src/onboard/wizard.rs
index b410ba6a5..eb0bf7979 100644
--- a/src/onboard/wizard.rs
+++ b/src/onboard/wizard.rs
@@ -2028,7 +2028,7 @@ fn resolve_interactive_onboarding_mode(
" Existing config found at {}. Select setup mode",
config_path.display()
))
- .items(&options)
+ .items(options)
.default(1)
.interact()?;
@@ -5863,7 +5863,7 @@ mod tests {
apply_provider_update(
&mut config,
"anthropic".to_string(),
- "".to_string(),
+ String::new(),
"claude-sonnet-4-5-20250929".to_string(),
None,
);
diff --git a/src/peripherals/mod.rs b/src/peripherals/mod.rs
index 8c3a59a8d..484edfa1b 100644
--- a/src/peripherals/mod.rs
+++ b/src/peripherals/mod.rs
@@ -24,8 +24,6 @@ pub mod uno_q_setup;
#[cfg(all(feature = "peripheral-rpi", target_os = "linux"))]
pub mod rpi;
-pub use traits::Peripheral;
-
use crate::config::{Config, PeripheralBoardConfig, PeripheralsConfig};
#[cfg(feature = "hardware")]
use crate::tools::HardwareMemoryMapTool;
@@ -228,6 +226,7 @@ pub async fn create_peripheral_tools(config: &PeripheralsConfig) -> Result Result>> {
Ok(Vec::new())
}
diff --git a/src/providers/bedrock.rs b/src/providers/bedrock.rs
index d58220e4a..9fbdc7447 100644
--- a/src/providers/bedrock.rs
+++ b/src/providers/bedrock.rs
@@ -710,12 +710,12 @@ impl BedrockProvider {
let after_semi = &rest[semi + 1..];
if let Some(b64) = after_semi.strip_prefix("base64,") {
let format = match mime {
- "image/jpeg" | "image/jpg" => "jpeg",
"image/png" => "png",
"image/gif" => "gif",
"image/webp" => "webp",
_ => "jpeg",
};
+
blocks.push(ContentBlock::Image(ImageWrapper {
image: ImageBlock {
format: format.to_string(),
diff --git a/src/providers/gemini.rs b/src/providers/gemini.rs
index b4a030517..31ab5becc 100644
--- a/src/providers/gemini.rs
+++ b/src/providers/gemini.rs
@@ -1375,8 +1375,8 @@ mod tests {
fn oauth_refresh_form_omits_client_credentials_when_missing() {
let form = build_oauth_refresh_form("refresh-token", None, None);
let map: std::collections::HashMap<_, _> = form.into_iter().collect();
- assert!(map.get("client_id").is_none());
- assert!(map.get("client_secret").is_none());
+ assert!(!map.contains_key("client_id"));
+ assert!(!map.contains_key("client_secret"));
}
#[test]
@@ -1802,7 +1802,7 @@ mod tests {
let creds: GeminiCliOAuthCreds = serde_json::from_str(json).unwrap();
assert_eq!(creds.access_token.as_deref(), Some("ya29.test-token"));
assert_eq!(creds.refresh_token.as_deref(), Some("1//test-refresh"));
- assert_eq!(creds.expiry_date, Some(4102444800000));
+ assert_eq!(creds.expiry_date, Some(4_102_444_800_000));
assert!(creds.expiry.is_none());
}
@@ -1821,7 +1821,7 @@ mod tests {
assert_eq!(creds.id_token.as_deref(), Some("header.payload.sig"));
assert_eq!(creds.client_id.as_deref(), Some("test-client-id"));
assert_eq!(creds.client_secret.as_deref(), Some("test-client-secret"));
- assert_eq!(creds.expiry_date, Some(4102444800000));
+ assert_eq!(creds.expiry_date, Some(4_102_444_800_000));
}
#[test]
diff --git a/src/providers/openai_codex.rs b/src/providers/openai_codex.rs
index 3036bf9ff..464d7bf90 100644
--- a/src/providers/openai_codex.rs
+++ b/src/providers/openai_codex.rs
@@ -281,7 +281,6 @@ fn clamp_reasoning_effort(model: &str, effort: &str) -> String {
return match effort {
"low" | "medium" | "high" => effort.to_string(),
"minimal" => "low".to_string(),
- "xhigh" => "high".to_string(),
_ => "high".to_string(),
};
}
diff --git a/src/security/leak_detector.rs b/src/security/leak_detector.rs
index 6849630d3..fba74bbb7 100644
--- a/src/security/leak_detector.rs
+++ b/src/security/leak_detector.rs
@@ -311,7 +311,7 @@ mod tests {
assert!(patterns.iter().any(|p| p.contains("Stripe")));
assert!(redacted.contains("[REDACTED"));
}
- _ => panic!("Should detect Stripe key"),
+ LeakResult::Clean => panic!("Should detect Stripe key"),
}
}
@@ -324,7 +324,7 @@ mod tests {
LeakResult::Detected { patterns, .. } => {
assert!(patterns.iter().any(|p| p.contains("AWS")));
}
- _ => panic!("Should detect AWS key"),
+ LeakResult::Clean => panic!("Should detect AWS key"),
}
}
@@ -342,7 +342,7 @@ MIIEowIBAAKCAQEA0ZPr5JeyVDonXsKhfq...
assert!(patterns.iter().any(|p| p.contains("private key")));
assert!(redacted.contains("[REDACTED_PRIVATE_KEY]"));
}
- _ => panic!("Should detect private key"),
+ LeakResult::Clean => panic!("Should detect private key"),
}
}
@@ -356,7 +356,7 @@ MIIEowIBAAKCAQEA0ZPr5JeyVDonXsKhfq...
assert!(patterns.iter().any(|p| p.contains("JWT")));
assert!(redacted.contains("[REDACTED_JWT]"));
}
- _ => panic!("Should detect JWT"),
+ LeakResult::Clean => panic!("Should detect JWT"),
}
}
@@ -369,7 +369,7 @@ MIIEowIBAAKCAQEA0ZPr5JeyVDonXsKhfq...
LeakResult::Detected { patterns, .. } => {
assert!(patterns.iter().any(|p| p.contains("PostgreSQL")));
}
- _ => panic!("Should detect database URL"),
+ LeakResult::Clean => panic!("Should detect database URL"),
}
}
diff --git a/src/security/prompt_guard.rs b/src/security/prompt_guard.rs
index 56c29a7af..ac5bbaf0d 100644
--- a/src/security/prompt_guard.rs
+++ b/src/security/prompt_guard.rs
@@ -114,7 +114,9 @@ impl PromptGuard {
// Normalize score to 0.0-1.0 range (max possible is 6.0, one per category)
let normalized_score = (total_score / 6.0).min(1.0);
- if !detected_patterns.is_empty() {
+ if detected_patterns.is_empty() {
+ GuardResult::Safe
+ } else {
match self.action {
GuardAction::Block if max_score > self.sensitivity => {
GuardResult::Blocked(format!(
@@ -125,8 +127,6 @@ impl PromptGuard {
}
_ => GuardResult::Suspicious(detected_patterns, normalized_score),
}
- } else {
- GuardResult::Safe
}
}
diff --git a/src/skills/audit.rs b/src/skills/audit.rs
index 45b10a646..e8883e571 100644
--- a/src/skills/audit.rs
+++ b/src/skills/audit.rs
@@ -200,12 +200,12 @@ fn audit_manifest_file(root: &Path, path: &Path, report: &mut SkillAuditReport)
.push(format!("{rel}: tools[{idx}] is missing a command field."));
}
- if kind.eq_ignore_ascii_case("script") || kind.eq_ignore_ascii_case("shell") {
- if command.is_some_and(|value| value.trim().is_empty()) {
- report
- .findings
- .push(format!("{rel}: tools[{idx}] has an empty {kind} command."));
- }
+ if (kind.eq_ignore_ascii_case("script") || kind.eq_ignore_ascii_case("shell"))
+ && command.is_some_and(|value| value.trim().is_empty())
+ {
+ report
+ .findings
+ .push(format!("{rel}: tools[{idx}] has an empty {kind} command."));
}
}
}
diff --git a/src/skills/mod.rs b/src/skills/mod.rs
index a97d520c8..9d84055fc 100644
--- a/src/skills/mod.rs
+++ b/src/skills/mod.rs
@@ -238,7 +238,7 @@ fn open_skills_enabled_from_sources(
env_override: Option<&str>,
) -> bool {
if let Some(raw) = env_override {
- if let Some(enabled) = parse_open_skills_enabled(&raw) {
+ if let Some(enabled) = parse_open_skills_enabled(raw) {
return enabled;
}
if !raw.trim().is_empty() {
diff --git a/src/tools/screenshot.rs b/src/tools/screenshot.rs
index c58a3587c..3b8133b88 100644
--- a/src/tools/screenshot.rs
+++ b/src/tools/screenshot.rs
@@ -150,6 +150,7 @@ impl ScreenshotTool {
}
/// Read the screenshot file and return base64-encoded result.
+ #[allow(clippy::incompatible_msrv)]
async fn read_and_encode(output_path: &std::path::Path) -> anyhow::Result {
// Check file size before reading to prevent OOM on large screenshots
const MAX_RAW_BYTES: u64 = 1_572_864; // ~1.5 MB (base64 expands ~33%)
diff --git a/src/tools/shell.rs b/src/tools/shell.rs
index 0793a2955..8b0f88bc8 100644
--- a/src/tools/shell.rs
+++ b/src/tools/shell.rs
@@ -120,6 +120,7 @@ impl Tool for ShellTool {
})
}
+ #[allow(clippy::incompatible_msrv)]
async fn execute(&self, args: serde_json::Value) -> anyhow::Result {
let command = extract_command_argument(&args)
.ok_or_else(|| anyhow::anyhow!("Missing 'command' parameter"))?;
diff --git a/tests/config_persistence.rs b/tests/config_persistence.rs
index 079b9dfc6..d70010eba 100644
--- a/tests/config_persistence.rs
+++ b/tests/config_persistence.rs
@@ -1,3 +1,4 @@
+#![allow(clippy::field_reassign_with_default)]
//! TG2: Config Load/Save Round-Trip Tests
//!
//! Prevents: Pattern 2 — Config persistence & workspace discovery bugs (13% of user bugs).
diff --git a/tests/config_schema.rs b/tests/config_schema.rs
index 6627312c0..e56ab6751 100644
--- a/tests/config_schema.rs
+++ b/tests/config_schema.rs
@@ -1,3 +1,4 @@
+#![allow(clippy::field_reassign_with_default)]
//! Config Schema Boundary Tests
//!
//! Validates: config defaults, backward compatibility, invalid input rejection,
diff --git a/tests/gemini_fallback_oauth_refresh.rs b/tests/gemini_fallback_oauth_refresh.rs
index 612c44818..fde98dbea 100644
--- a/tests/gemini_fallback_oauth_refresh.rs
+++ b/tests/gemini_fallback_oauth_refresh.rs
@@ -4,7 +4,9 @@
//! 1. Primary provider (OpenAI Codex) fails
//! 2. Fallback to Gemini is triggered
//! 3. Gemini OAuth tokens are expired (we manually expire them)
+//!
//! Then:
+//!
//! - Gemini provider's warmup() automatically refreshes the tokens
//! - The fallback request succeeds
//!
diff --git a/tests/openai_codex_vision_e2e.rs b/tests/openai_codex_vision_e2e.rs
index 68dc10232..fcf902820 100644
--- a/tests/openai_codex_vision_e2e.rs
+++ b/tests/openai_codex_vision_e2e.rs
@@ -12,7 +12,7 @@
//! Run manually: `cargo test provider_vision -- --ignored --nocapture`
use anyhow::Result;
-use zeroclaw::providers::{ChatMessage, ChatRequest, Provider, ProviderRuntimeOptions};
+use zeroclaw::providers::{ChatMessage, ChatRequest, ProviderRuntimeOptions};
/// Tests that provider supports vision input.
///
diff --git a/tests/provider_schema.rs b/tests/provider_schema.rs
index f92c5062a..adffd0d83 100644
--- a/tests/provider_schema.rs
+++ b/tests/provider_schema.rs
@@ -292,7 +292,7 @@ fn provider_construction_with_different_auth_styles() {
#[test]
fn chat_messages_maintain_role_sequence() {
- let history = vec![
+ let history = [
ChatMessage::system("You are helpful"),
ChatMessage::user("What is Rust?"),
ChatMessage::assistant("Rust is a systems programming language"),
@@ -309,7 +309,7 @@ fn chat_messages_maintain_role_sequence() {
#[test]
fn chat_messages_with_tool_calls_maintain_sequence() {
- let history = vec![
+ let history = [
ChatMessage::system("You are helpful"),
ChatMessage::user("Search for Rust"),
ChatMessage::assistant("I'll search for that"),