chore: satisfy workspace clippy gate
This commit is contained in:
parent
3588bbcf94
commit
ecad06f6d6
|
|
@ -731,7 +731,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::duration_suboptimal_units, clippy::too_many_lines)]
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn executable_decision_table_emits_retry_rebase_merge_escalate_cleanup_and_approval_events() {
|
||||
let engine = PolicyEngine::new(vec![
|
||||
PolicyRule::new(
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ impl Default for TridentConfig {
|
|||
}
|
||||
|
||||
/// Statistics from a Trident compaction run.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq)]
|
||||
pub struct TridentStats {
|
||||
pub superseded_count: usize,
|
||||
pub collapsed_chains: usize,
|
||||
|
|
@ -41,21 +41,6 @@ pub struct TridentStats {
|
|||
pub final_message_count: usize,
|
||||
}
|
||||
|
||||
impl Default for TridentStats {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
superseded_count: 0,
|
||||
collapsed_chains: 0,
|
||||
messages_collapsed: 0,
|
||||
clusters_found: 0,
|
||||
messages_clustered: 0,
|
||||
tokens_saved_estimate: 0,
|
||||
original_message_count: 0,
|
||||
final_message_count: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TridentStats {
|
||||
pub fn format_report(&self) -> String {
|
||||
let compression = if self.final_message_count > 0 {
|
||||
|
|
@ -192,7 +177,7 @@ fn stage1_supersede(messages: &[ConversationMessage]) -> (Vec<ConversationMessag
|
|||
|
||||
let mut obsolete_indices: BTreeSet<usize> = BTreeSet::new();
|
||||
|
||||
for (_path, ops) in &file_ops {
|
||||
for ops in file_ops.values() {
|
||||
if ops.len() < 2 {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -205,11 +190,7 @@ fn stage1_supersede(messages: &[ConversationMessage]) -> (Vec<ConversationMessag
|
|||
|
||||
if let Some(last_write) = last_write_idx {
|
||||
for op in ops {
|
||||
if op.op_type == FileOp::Read && op.index < last_write {
|
||||
obsolete_indices.insert(op.index);
|
||||
} else if (op.op_type == FileOp::Write || op.op_type == FileOp::Edit)
|
||||
&& op.index < last_write
|
||||
{
|
||||
if op.index < last_write {
|
||||
obsolete_indices.insert(op.index);
|
||||
}
|
||||
}
|
||||
|
|
@ -325,7 +306,7 @@ fn stage2_collapse(
|
|||
usage: None,
|
||||
});
|
||||
} else {
|
||||
result.extend(buffer.drain(..));
|
||||
result.append(&mut buffer);
|
||||
}
|
||||
buffer.clear();
|
||||
result.push(msg.clone());
|
||||
|
|
@ -476,7 +457,7 @@ fn stage3_cluster(
|
|||
}
|
||||
|
||||
let total_clustered: usize = cluster_assignments.len();
|
||||
let clusters_found = cluster_id as usize;
|
||||
let clusters_found = cluster_id;
|
||||
|
||||
let mut result: Vec<ConversationMessage> = Vec::new();
|
||||
let mut cluster_buffers: BTreeMap<usize, Vec<usize>> = BTreeMap::new();
|
||||
|
|
@ -677,7 +658,7 @@ fn truncate_text(text: &str, max_chars: usize) -> String {
|
|||
mod tests {
|
||||
use super::*;
|
||||
use crate::compact::CompactionConfig;
|
||||
use crate::session::{ContentBlock, ConversationMessage, MessageRole, Session};
|
||||
use crate::session::{ContentBlock, ConversationMessage, Session};
|
||||
|
||||
#[test]
|
||||
fn stage1_removes_obsolete_file_reads() {
|
||||
|
|
@ -736,7 +717,7 @@ mod tests {
|
|||
fn stage2_collapses_chatty_messages() {
|
||||
let mut messages = vec![];
|
||||
for i in 0..6 {
|
||||
messages.push(ConversationMessage::user_text(&format!("ok {i}")));
|
||||
messages.push(ConversationMessage::user_text(format!("ok {i}")));
|
||||
messages.push(ConversationMessage::assistant(vec![ContentBlock::Text {
|
||||
text: format!("got {i}"),
|
||||
}]));
|
||||
|
|
@ -767,9 +748,9 @@ mod tests {
|
|||
},
|
||||
]));
|
||||
messages.push(ConversationMessage::tool_result(
|
||||
&format!("read_{i}"),
|
||||
format!("read_{i}"),
|
||||
"read_file",
|
||||
&format!(r#"{{"path":"src/{i}.rs","content":"data {i}"}}"#),
|
||||
format!(r#"{{"path":"src/{i}.rs","content":"data {i}"}}"#),
|
||||
false,
|
||||
));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3452,11 +3452,7 @@ impl DiagnosticCheck {
|
|||
|
||||
fn json_value(&self) -> Value {
|
||||
// Derive a stable snake_case id from the check name for machine-readable keying (#704).
|
||||
let id = self
|
||||
.name
|
||||
.to_ascii_lowercase()
|
||||
.replace(' ', "_")
|
||||
.replace('-', "_");
|
||||
let id = self.name.to_ascii_lowercase().replace([' ', '-'], "_");
|
||||
let mut value = Map::from_iter([
|
||||
("id".to_string(), Value::String(id.clone())),
|
||||
(
|
||||
|
|
@ -6730,16 +6726,15 @@ fn run_resume_command(
|
|||
}
|
||||
SlashCommand::Plugins { action, target } => {
|
||||
// Only list is supported in resume mode (no runtime to reload)
|
||||
match action.as_deref() {
|
||||
Some(action @ ("install" | "uninstall" | "enable" | "disable" | "update")) => {
|
||||
// #777: use interactive_only: prefix + \n hint so #776's classify/split
|
||||
// emits error_kind:interactive_only + non-null hint instead of unknown+null.
|
||||
// Orchestrators can now detect this and switch to a live REPL instead of retrying.
|
||||
return Err(format!(
|
||||
"interactive_only: /plugins {action} requires a live session to reload the plugin runtime.\nStart `claw` and run `/plugins {action}` inside the REPL, or use `claw plugins {action}` as a direct CLI command."
|
||||
).into());
|
||||
}
|
||||
_ => {}
|
||||
if let Some(action @ ("install" | "uninstall" | "enable" | "disable" | "update")) =
|
||||
action.as_deref()
|
||||
{
|
||||
// #777: use interactive_only: prefix + \n hint so #776's classify/split
|
||||
// emits error_kind:interactive_only + non-null hint instead of unknown+null.
|
||||
// Orchestrators can now detect this and switch to a live REPL instead of retrying.
|
||||
return Err(format!(
|
||||
"interactive_only: /plugins {action} requires a live session to reload the plugin runtime.\nStart `claw` and run `/plugins {action}` inside the REPL, or use `claw plugins {action}` as a direct CLI command."
|
||||
).into());
|
||||
}
|
||||
let cwd = env::current_dir()?;
|
||||
let payload = plugins_command_payload_for(
|
||||
|
|
@ -7852,8 +7847,12 @@ impl LiveCli {
|
|||
let max_compact_rounds = 4;
|
||||
let preserve_schedule = [4, 2, 1, 0];
|
||||
|
||||
for round in 0..max_compact_rounds {
|
||||
let preserve = preserve_schedule[round];
|
||||
for (round, preserve) in preserve_schedule
|
||||
.iter()
|
||||
.copied()
|
||||
.enumerate()
|
||||
.take(max_compact_rounds)
|
||||
{
|
||||
println!(
|
||||
" Auto-compacting session (round {}/{}, preserving {} recent messages)...",
|
||||
round + 1,
|
||||
|
|
@ -8611,8 +8610,8 @@ impl LiveCli {
|
|||
let cwd = env::current_dir()?;
|
||||
// #803: reject flag-shaped tokens in list filter for BOTH text and JSON modes.
|
||||
// Previously the guard was JSON-only (#793); text mode silently returned empty success.
|
||||
if action.as_deref() == Some("list") {
|
||||
if let Some(filter) = target.as_deref() {
|
||||
if action == Some("list") {
|
||||
if let Some(filter) = target {
|
||||
if filter.starts_with('-') {
|
||||
if matches!(output_format, CliOutputFormat::Json) {
|
||||
// ROADMAP #817: this is a handled local inventory parse error.
|
||||
|
|
@ -10073,9 +10072,7 @@ fn sandbox_json_value(status: &runtime::SandboxStatus) -> serde_json::Value {
|
|||
// (#731: "not supported on macOS" is a degraded state, not a hard error;
|
||||
// filesystem_active:true means partial containment is working)
|
||||
// error = enabled but unsupported AND no filesystem sandbox either (nothing active)
|
||||
let top_status = if !status.enabled {
|
||||
"ok"
|
||||
} else if status.active {
|
||||
let top_status = if !status.enabled || status.active {
|
||||
"ok"
|
||||
} else if status.supported {
|
||||
"warn"
|
||||
|
|
@ -14008,39 +14005,37 @@ fn convert_messages(messages: &[ConversationMessage]) -> Vec<InputMessage> {
|
|||
let content = message
|
||||
.blocks
|
||||
.iter()
|
||||
.filter_map(|block| match block {
|
||||
ContentBlock::Text { text } => {
|
||||
Some(InputContentBlock::Text { text: text.clone() })
|
||||
}
|
||||
.map(|block| match block {
|
||||
ContentBlock::Text { text } => InputContentBlock::Text { text: text.clone() },
|
||||
ContentBlock::Thinking {
|
||||
thinking,
|
||||
signature,
|
||||
} => {
|
||||
// 保留 Thinking 块:OpenAI 兼容协议会把它转成 reasoning_content 字段
|
||||
// 回传给 DeepSeek V4(避免 400 "reasoning_content must be passed back" 错误)
|
||||
Some(InputContentBlock::Thinking {
|
||||
InputContentBlock::Thinking {
|
||||
thinking: thinking.clone(),
|
||||
signature: signature.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
ContentBlock::ToolUse { id, name, input } => Some(InputContentBlock::ToolUse {
|
||||
ContentBlock::ToolUse { id, name, input } => InputContentBlock::ToolUse {
|
||||
id: id.clone(),
|
||||
name: name.clone(),
|
||||
input: serde_json::from_str(input)
|
||||
.unwrap_or_else(|_| serde_json::json!({ "raw": input })),
|
||||
}),
|
||||
},
|
||||
ContentBlock::ToolResult {
|
||||
tool_use_id,
|
||||
output,
|
||||
is_error,
|
||||
..
|
||||
} => Some(InputContentBlock::ToolResult {
|
||||
} => InputContentBlock::ToolResult {
|
||||
tool_use_id: tool_use_id.clone(),
|
||||
content: vec![ToolResultContentBlock::Text {
|
||||
text: output.clone(),
|
||||
}],
|
||||
is_error: *is_error,
|
||||
}),
|
||||
},
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
(!content.is_empty()).then(|| InputMessage {
|
||||
|
|
|
|||
|
|
@ -1007,13 +1007,13 @@ fn inventory_commands_emit_structured_json_when_requested() {
|
|||
assert!(
|
||||
!plugins
|
||||
.as_object()
|
||||
.map_or(false, |o| o.contains_key("reload_runtime")),
|
||||
.is_some_and(|o| o.contains_key("reload_runtime")),
|
||||
"plugins list should not include reload_runtime"
|
||||
);
|
||||
assert!(
|
||||
!plugins
|
||||
.as_object()
|
||||
.map_or(false, |o| o.contains_key("target")),
|
||||
.is_some_and(|o| o.contains_key("target")),
|
||||
"plugins list should not include target"
|
||||
);
|
||||
// #703: structured summary replaces prose message
|
||||
|
|
@ -1706,13 +1706,13 @@ fn resumed_inventory_commands_emit_structured_json_when_requested() {
|
|||
assert!(
|
||||
!plugins
|
||||
.as_object()
|
||||
.map_or(false, |o| o.contains_key("reload_runtime")),
|
||||
.is_some_and(|o| o.contains_key("reload_runtime")),
|
||||
"plugins list should not include reload_runtime"
|
||||
);
|
||||
assert!(
|
||||
!plugins
|
||||
.as_object()
|
||||
.map_or(false, |o| o.contains_key("target")),
|
||||
.is_some_and(|o| o.contains_key("target")),
|
||||
"plugins list should not include target"
|
||||
);
|
||||
assert!(
|
||||
|
|
@ -2983,9 +2983,9 @@ fn flag_value_errors_have_error_kind_and_hint_756() {
|
|||
"invalid --reasoning-effort must be invalid_flag_value (#756): {parsed}"
|
||||
);
|
||||
assert!(
|
||||
parsed["hint"].as_str().map_or(false, |h| h.contains("low")
|
||||
|| h.contains("medium")
|
||||
|| h.contains("high")),
|
||||
parsed["hint"]
|
||||
.as_str()
|
||||
.is_some_and(|h| h.contains("low") || h.contains("medium") || h.contains("high")),
|
||||
"hint must mention valid values (#756): {parsed}"
|
||||
);
|
||||
|
||||
|
|
@ -3011,7 +3011,7 @@ fn flag_value_errors_have_error_kind_and_hint_756() {
|
|||
"missing --model value must be missing_flag_value (#756): {parsed2}"
|
||||
);
|
||||
assert!(
|
||||
parsed2["hint"].as_str().map_or(false, |h| !h.is_empty()),
|
||||
parsed2["hint"].as_str().is_some_and(|h| !h.is_empty()),
|
||||
"missing --model hint must be non-empty (#756): {parsed2}"
|
||||
);
|
||||
}
|
||||
|
|
@ -3255,7 +3255,7 @@ fn short_p_flag_swallows_no_flags_755() {
|
|||
"flag-like token after -p must be rejected as missing_prompt (#755): {parsed2}"
|
||||
);
|
||||
assert!(
|
||||
parsed2["hint"].as_str().map_or(false, |h| !h.is_empty()),
|
||||
parsed2["hint"].as_str().is_some_and(|h| !h.is_empty()),
|
||||
"missing_prompt hint must be non-empty (#755)"
|
||||
);
|
||||
}
|
||||
|
|
@ -3397,7 +3397,7 @@ fn config_unsupported_section_json_hint_741() {
|
|||
assert!(
|
||||
parsed["supported_sections"]
|
||||
.as_array()
|
||||
.map_or(false, |a| !a.is_empty()),
|
||||
.is_some_and(|a| !a.is_empty()),
|
||||
"config {section} JSON must include supported_sections (#741)"
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue