Skip to content

Commit 11f381f

Browse files
BunsDevclaude
andcommitted
chore: clear 53 pre-existing clippy warnings to unblock -D warnings
Slice 8 (verification gate). After this commit `cargo clippy --workspace --all-targets -- -D warnings` passes for the first time in this repo. Mechanical fixes via `cargo clippy --fix` (28 warnings cleared): redundant closures, expression auto-borrow, `if` collapse, `for` loop conversion, derivable `Default` impl, `Default` on StreamAccumulator, casting to same type, redundant `is_some` patterns, etc. Hand-applied fixes (25 warnings cleared): * core/src/lib.rs: - Replace `let mut cfg = Config::default(); cfg.field = ...` in 3 tests with struct-update syntax (matches AGENTS.md rule: no field-assignment-after-default). - `sessions.sort_by(...)` → `sessions.sort_by_key(...)`. - Collapse two identical `if` branches into a single condition in the AcceptEdits PermissionMode arm. - Same in the pricing model_router for `-free` / `free/` / `is_free_upstream_model` paths. * core/src/system_prompt.rs: - Rename `OutputStyle::from_str` → `from_label` so it no longer collides with the std `FromStr` trait method (its infallible "fallback to Default" semantics would violate the FromStr contract). - Replace `let mut parts = Vec::new(); parts.push(...);` with a single `vec![...]` literal. * cli/src/main.rs: - Reformat the `/coven-code models` doc list to drop the overindentation clippy now warns about (4 entries). - `loop { match try_recv() { Ok(t) => ..., Err(_) => break } }` → `while let Ok(t) = try_recv() { ... }`. * tui/src/message_copy.rs: - Replace `if line.starts_with("```") { ... line[3..] ... }` with `if let Some(rest) = line.strip_prefix("```")`. * query/src/lib.rs: - Collapse `if let ContentBlock::ToolUse {...}` into the outer `match` arm pattern. * query/src/lib.rs and cli/src/main.rs: - `#[allow(clippy::too_many_arguments)]` with a comment justifying it on `run_query_loop` (9 args) and `run_interactive` (12 args). Both have distinct domain-level inputs that a config struct would just re-shuffle without improving readability. Workspace tests still 1525 passing, 0 failing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 95cac7f commit 11f381f

7 files changed

Lines changed: 166 additions & 167 deletions

File tree

src-rust/crates/api/src/lib.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -394,20 +394,15 @@ pub mod client {
394394
use super::*;
395395

396396
/// Provider selection for API calls.
397-
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
397+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
398398
pub enum Provider {
399399
/// Use Anthropic's API
400+
#[default]
400401
Anthropic,
401402
/// Use OpenAI Codex via OAuth
402403
Codex,
403404
}
404405

405-
impl Default for Provider {
406-
fn default() -> Self {
407-
Provider::Anthropic
408-
}
409-
}
410-
411406
/// Configuration for the HTTP client.
412407
#[derive(Debug, Clone)]
413408
pub struct ClientConfig {
@@ -1118,6 +1113,12 @@ enum PartialBlock {
11181113
},
11191114
}
11201115

1116+
impl Default for StreamAccumulator {
1117+
fn default() -> Self {
1118+
Self::new()
1119+
}
1120+
}
1121+
11211122
impl StreamAccumulator {
11221123
pub fn new() -> Self {
11231124
Self {

src-rust/crates/cli/src/main.rs

Lines changed: 28 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,7 +1028,7 @@ async fn main() -> anyhow::Result<()> {
10281028
// but we guard with a std::sync::OnceLock internally).
10291029
{
10301030
static SWARM_INIT: std::sync::OnceLock<()> = std::sync::OnceLock::new();
1031-
SWARM_INIT.get_or_init(|| claurst_query::init_team_swarm_runner());
1031+
SWARM_INIT.get_or_init(claurst_query::init_team_swarm_runner);
10321032
}
10331033

10341034
// Build the full tool list: built-ins from cc-tools plus AgentTool from cc-query
@@ -1266,14 +1266,14 @@ fn models_dev_cache_path() -> PathBuf {
12661266
/// Implementation of the `coven-code models` subcommand.
12671267
///
12681268
/// Flags:
1269-
/// * `--refresh` — force-fetch from models.dev (ignoring the 5-minute
1270-
/// freshness window), then list.
1271-
/// * `--verbose` — also print release date, status, modalities,
1272-
/// cache pricing, and capability flags.
1273-
/// * `--json` — emit the registry as a JSON object keyed by
1274-
/// `provider/model` (suitable for piping into `jq`).
1275-
/// * `<provider>` — first non-flag arg filters by provider id
1276-
/// (e.g. `coven-code models openai`).
1269+
/// * `--refresh` — force-fetch from models.dev (ignoring the 5-minute
1270+
/// freshness window), then list.
1271+
/// * `--verbose` — also print release date, status, modalities,
1272+
/// cache pricing, and capability flags.
1273+
/// * `--json` — emit the registry as a JSON object keyed by
1274+
/// `provider/model` (suitable for piping into `jq`).
1275+
/// * `<provider>` — first non-flag arg filters by provider id
1276+
/// (e.g. `coven-code models openai`).
12771277
async fn run_models_command(args: &[String]) -> anyhow::Result<()> {
12781278
let mut refresh = false;
12791279
let mut verbose = false;
@@ -1324,14 +1324,14 @@ async fn run_models_command(args: &[String]) -> anyhow::Result<()> {
13241324
// Stable order: provider id, then by descending release_date so newest
13251325
// models appear first.
13261326
entries.sort_by(|a, b| {
1327-
(&*a.info.provider_id)
1327+
(*a.info.provider_id)
13281328
.cmp(&*b.info.provider_id)
13291329
.then_with(|| {
13301330
let rd_a = a.release_date.as_deref().unwrap_or("");
13311331
let rd_b = b.release_date.as_deref().unwrap_or("");
13321332
rd_b.cmp(rd_a)
13331333
})
1334-
.then_with(|| (&*a.info.id).cmp(&*b.info.id))
1334+
.then_with(|| (*a.info.id).cmp(&*b.info.id))
13351335
});
13361336

13371337
if as_json {
@@ -2037,6 +2037,13 @@ fn permission_request_from_core(
20372037
}
20382038
}
20392039

2040+
// Allowed: this is the main interactive-mode bootstrap. Its inputs are all
2041+
// distinct, separately-constructed services (config, settings, HTTP client,
2042+
// tool registry, tool execution context, query loop knobs, etc.) and
2043+
// bundling them behind a struct would force every test and CLI mode to
2044+
// construct that struct just to call this function. The count is a feature
2045+
// of how the TUI is wired together, not a code-smell.
2046+
#[allow(clippy::too_many_arguments)]
20402047
async fn run_interactive(
20412048
config: Config,
20422049
settings: claurst_core::config::Settings,
@@ -3270,14 +3277,8 @@ async fn run_interactive(
32703277
}
32713278
Some('p') => {
32723279
let mut settings =
3273-
match claurst_core::config::Settings::load_sync(
3274-
) {
3275-
Ok(s) => s,
3276-
Err(_) => {
3277-
claurst_core::config::Settings::default(
3278-
)
3279-
}
3280-
};
3280+
claurst_core::config::Settings::load_sync(
3281+
).unwrap_or_default();
32813282
if let Some(path) = selected_path.as_deref() {
32823283
let pattern = format!("{}*", path);
32833284
let _ = manager.add_persistent_allow_path(
@@ -3342,13 +3343,13 @@ async fn run_interactive(
33423343
session.updated_at = chrono::Utc::now();
33433344
}
33443345
}
3345-
Event::Paste(data) => {
3346+
Event::Paste(data)
33463347
// Cmd+V paste on macOS / Ctrl+Shift+V on Linux (via bracketed paste)
33473348
if !app.is_streaming
33483349
&& app.permission_request.is_none()
33493350
&& !app.history_search_overlay.visible
33503351
&& app.history_search.is_none()
3351-
{
3352+
=> {
33523353
if app.key_input_dialog.visible {
33533354
// Paste into API key input dialog
33543355
for ch in data.chars() {
@@ -3359,7 +3360,6 @@ async fn run_interactive(
33593360
app.prompt_input.paste(&data);
33603361
}
33613362
}
3362-
}
33633363
Event::Mouse(mouse) => {
33643364
app.handle_mouse_event(mouse);
33653365
}
@@ -3657,14 +3657,13 @@ async fn run_interactive(
36573657
Ok(msgs) if !msgs.is_empty() => {
36583658
for msg in &msgs {
36593659
since_id = Some(msg.id.clone());
3660-
if msg.role == "user" {
3661-
if poll_tx
3660+
if msg.role == "user"
3661+
&& poll_tx
36623662
.send(msg.content.clone())
36633663
.await
36643664
.is_err()
3665-
{
3666-
return;
3667-
}
3665+
{
3666+
return;
36683667
}
36693668
}
36703669
}
@@ -3854,13 +3853,8 @@ async fn run_interactive(
38543853

38553854
// Drain CLAUDE_STATUS_COMMAND results (most recent wins)
38563855
if status_cmd_str.is_some() {
3857-
loop {
3858-
match status_cmd_rx.try_recv() {
3859-
Ok(text) => {
3860-
app.status_line_override = if text.is_empty() { None } else { Some(text) };
3861-
}
3862-
Err(_) => break,
3863-
}
3856+
while let Ok(text) = status_cmd_rx.try_recv() {
3857+
app.status_line_override = if text.is_empty() { None } else { Some(text) };
38643858
}
38653859
}
38663860

src-rust/crates/core/src/lib.rs

Lines changed: 30 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -790,21 +790,17 @@ pub mod config {
790790
/// Budget allocation strategy between manager and executor agents.
791791
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
792792
#[serde(tag = "type", rename_all = "snake_case")]
793+
#[derive(Default)]
793794
pub enum BudgetSplitPolicy {
794795
/// Shared pool — no split (default).
796+
#[default]
795797
SharedPool,
796798
/// Manager gets manager_pct% of total budget.
797799
Percentage { manager_pct: u8 },
798800
/// Hard USD caps per role.
799801
FixedCaps { manager_usd: f64, executor_usd: f64 },
800802
}
801803

802-
impl Default for BudgetSplitPolicy {
803-
fn default() -> Self {
804-
BudgetSplitPolicy::SharedPool
805-
}
806-
}
807-
808804
/// Configuration for manager-executor agent architecture.
809805
#[derive(Debug, Clone, Serialize, Deserialize)]
810806
pub struct ManagedAgentConfig {
@@ -1236,7 +1232,7 @@ pub mod config {
12361232
}
12371233

12381234
/// Configuration for a file formatter tool.
1239-
#[derive(Debug, Clone, Serialize, Deserialize)]
1235+
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12401236
pub struct FormatterConfig {
12411237
/// Command to run, e.g. `["prettier", "--write"]`.
12421238
pub command: Vec<String>,
@@ -1247,16 +1243,6 @@ pub mod config {
12471243
pub disabled: bool,
12481244
}
12491245

1250-
impl Default for FormatterConfig {
1251-
fn default() -> Self {
1252-
Self {
1253-
command: Vec::new(),
1254-
extensions: Vec::new(),
1255-
disabled: false,
1256-
}
1257-
}
1258-
}
1259-
12601246
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12611247
pub struct ProjectSettings {
12621248
#[serde(default)]
@@ -1374,7 +1360,7 @@ pub mod config {
13741360
pub fn effective_output_style(&self) -> crate::system_prompt::OutputStyle {
13751361
self.output_style
13761362
.as_deref()
1377-
.map(crate::system_prompt::OutputStyle::from_str)
1363+
.map(crate::system_prompt::OutputStyle::from_label)
13781364
.unwrap_or_default()
13791365
}
13801366

@@ -2831,9 +2817,7 @@ pub mod permissions {
28312817
match self.mode {
28322818
PermissionMode::BypassPermissions => PermissionDecision::Allow,
28332819
PermissionMode::AcceptEdits => {
2834-
if request.tool_name == "Edit" {
2835-
PermissionDecision::Allow
2836-
} else if request.is_read_only {
2820+
if request.tool_name == "Edit" || request.is_read_only {
28372821
PermissionDecision::Allow
28382822
} else {
28392823
PermissionDecision::Deny
@@ -3373,25 +3357,20 @@ pub mod history {
33733357
}
33743358

33753359
let mut sessions = vec![];
3376-
match tokio::fs::read_dir(&dir).await {
3377-
Ok(mut entries) => {
3378-
while let Ok(Some(entry)) = entries.next_entry().await {
3379-
let path = entry.path();
3380-
if path.extension().and_then(|s| s.to_str()) == Some("json") {
3381-
if let Ok(content) = tokio::fs::read_to_string(&path).await {
3382-
if let Ok(session) =
3383-
serde_json::from_str::<ConversationSession>(&content)
3384-
{
3385-
sessions.push(session);
3386-
}
3360+
if let Ok(mut entries) = tokio::fs::read_dir(&dir).await {
3361+
while let Ok(Some(entry)) = entries.next_entry().await {
3362+
let path = entry.path();
3363+
if path.extension().and_then(|s| s.to_str()) == Some("json") {
3364+
if let Ok(content) = tokio::fs::read_to_string(&path).await {
3365+
if let Ok(session) = serde_json::from_str::<ConversationSession>(&content) {
3366+
sessions.push(session);
33873367
}
33883368
}
33893369
}
33903370
}
3391-
Err(_) => {}
33923371
}
33933372

3394-
sessions.sort_by(|a, b| b.updated_at.cmp(&a.updated_at));
3373+
sessions.sort_by_key(|s| std::cmp::Reverse(s.updated_at));
33953374
sessions
33963375
}
33973376

@@ -3582,9 +3561,10 @@ pub mod cost {
35823561
/// Pick pricing based on model name substring matching.
35833562
pub fn for_model(model: &str) -> Self {
35843563
// Check for free models first (those with "-free" suffix, "free/" prefix, or upstream-prefixed free model)
3585-
if model.ends_with("-free") || model.starts_with("free/") {
3586-
Self::FREE
3587-
} else if is_free_upstream_model(model) {
3564+
if model.ends_with("-free")
3565+
|| model.starts_with("free/")
3566+
|| is_free_upstream_model(model)
3567+
{
35883568
Self::FREE
35893569
} else if model.contains("opus") {
35903570
Self::OPUS
@@ -4003,7 +3983,7 @@ pub mod oauth {
40033983

40043984
let profile = AccountProfile {
40053985
id: id.clone(),
4006-
label: label.map(|l| slugify_profile_id(l)),
3986+
label: label.map(slugify_profile_id),
40073987
email: self.email.clone(),
40083988
account_id: self.account_uuid.clone(),
40093989
organization_uuid: self.organization_uuid.clone(),
@@ -4403,8 +4383,10 @@ mod tests {
44034383

44044384
#[test]
44054385
fn test_config_effective_model_override() {
4406-
let mut cfg = crate::config::Config::default();
4407-
cfg.model = Some("claude-haiku-4-5-20251001".to_string());
4386+
let cfg = crate::config::Config {
4387+
model: Some("claude-haiku-4-5-20251001".to_string()),
4388+
..crate::config::Config::default()
4389+
};
44084390
assert_eq!(cfg.effective_model(), "claude-haiku-4-5-20251001");
44094391
}
44104392

@@ -4419,8 +4401,10 @@ mod tests {
44194401

44204402
#[test]
44214403
fn test_config_effective_max_tokens_override() {
4422-
let mut cfg = crate::config::Config::default();
4423-
cfg.max_tokens = Some(8192);
4404+
let cfg = crate::config::Config {
4405+
max_tokens: Some(8192),
4406+
..crate::config::Config::default()
4407+
};
44244408
assert_eq!(cfg.effective_max_tokens(), 8192);
44254409
}
44264410

@@ -4431,8 +4415,10 @@ mod tests {
44314415
let orig = std::env::var("ANTHROPIC_API_KEY").ok();
44324416
std::env::remove_var("ANTHROPIC_API_KEY");
44334417

4434-
let mut cfg = crate::config::Config::default();
4435-
cfg.api_key = Some("sk-ant-config-key".to_string());
4418+
let cfg = crate::config::Config {
4419+
api_key: Some("sk-ant-config-key".to_string()),
4420+
..crate::config::Config::default()
4421+
};
44364422
assert_eq!(cfg.resolve_api_key(), Some("sk-ant-config-key".to_string()));
44374423

44384424
if let Some(k) = orig {

src-rust/crates/core/src/system_prompt.rs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,13 @@ impl OutputStyle {
110110
}
111111

112112
/// Parse from a string (case-insensitive).
113-
pub fn from_str(s: &str) -> Self {
113+
///
114+
/// Named `from_label` (not `from_str`) so clippy doesn't confuse this
115+
/// with the `std::str::FromStr` trait method: this parser is infallible
116+
/// and falls back to `Self::Default` for unknown inputs, which would be
117+
/// a contract violation if it implemented `FromStr` (where the
118+
/// associated `Err` type is supposed to surface parse failures).
119+
pub fn from_label(s: &str) -> Self {
114120
match s.to_lowercase().as_str() {
115121
"explanatory" => Self::Explanatory,
116122
"learning" => Self::Learning,
@@ -250,20 +256,17 @@ pub fn build_system_prompt(opts: &SystemPromptOptions) -> String {
250256
SystemPromptPrefix::detect(opts.is_non_interactive, opts.has_append_system_prompt)
251257
});
252258

253-
let mut parts: Vec<String> = Vec::new();
254-
255259
// ------------------------------------------------------------------ //
256260
// CACHEABLE sections (before the dynamic boundary) //
257261
// ------------------------------------------------------------------ //
258-
259-
// 1. Attribution header
260-
parts.push(prefix.attribution_text().to_string());
261-
262-
// 2. Core capabilities
263-
parts.push(CORE_CAPABILITIES.to_string());
264-
265-
// 3. Tool use guidelines
266-
parts.push(TOOL_USE_GUIDELINES.to_string());
262+
let mut parts: Vec<String> = vec![
263+
// 1. Attribution header
264+
prefix.attribution_text().to_string(),
265+
// 2. Core capabilities
266+
CORE_CAPABILITIES.to_string(),
267+
// 3. Tool use guidelines
268+
TOOL_USE_GUIDELINES.to_string(),
269+
];
267270

268271
// 4. Executing actions with care
269272
parts.push(ACTIONS_SECTION.to_string());
@@ -634,9 +637,9 @@ mod tests {
634637

635638
#[test]
636639
fn test_output_style_from_str() {
637-
assert_eq!(OutputStyle::from_str("concise"), OutputStyle::Concise);
638-
assert_eq!(OutputStyle::from_str("FORMAL"), OutputStyle::Formal);
639-
assert_eq!(OutputStyle::from_str("unknown"), OutputStyle::Default);
640+
assert_eq!(OutputStyle::from_label("concise"), OutputStyle::Concise);
641+
assert_eq!(OutputStyle::from_label("FORMAL"), OutputStyle::Formal);
642+
assert_eq!(OutputStyle::from_label("unknown"), OutputStyle::Default);
640643
}
641644

642645
#[test]

0 commit comments

Comments
 (0)