diff --git a/crates/mem-core/src/agent_entity.rs b/crates/mem-core/src/agent_entity.rs index 3f6b0d6..92f8642 100644 --- a/crates/mem-core/src/agent_entity.rs +++ b/crates/mem-core/src/agent_entity.rs @@ -2,6 +2,7 @@ /// /// These structures attach to Entity via entity_type discriminator. /// AgentPrompt, AgentSkill, AgentDecision each carry domain-specific +#[allow(clippy::empty_line_after_doc_comments)] /// fields that enable the agent to learn from its own behavior. use serde::{Deserialize, Serialize}; diff --git a/crates/mem-core/src/community.rs b/crates/mem-core/src/community.rs index b246fc2..9404bb5 100644 --- a/crates/mem-core/src/community.rs +++ b/crates/mem-core/src/community.rs @@ -1,5 +1,6 @@ /// Community domain model for temporal graph-RAG. /// Single Responsibility: Community (cluster) storage and metadata. +#[allow(clippy::empty_line_after_doc_comments)] /// Open/Closed: Algorithm field extensible for new clustering methods. use serde::{Deserialize, Serialize}; diff --git a/crates/mem-core/src/edge.rs b/crates/mem-core/src/edge.rs index 7a2fd4c..a155a68 100644 --- a/crates/mem-core/src/edge.rs +++ b/crates/mem-core/src/edge.rs @@ -1,5 +1,6 @@ /// Edge domain model for temporal graph-RAG. /// Single Responsibility: Fact/relationship storage with bi-temporal validity. +#[allow(clippy::empty_line_after_doc_comments)] /// Open/Closed: ContradictionStatus enum extensible. use serde::{Deserialize, Serialize}; @@ -29,6 +30,7 @@ impl ContradictionStatus { } } + #[allow(clippy::should_implement_trait)] pub fn from_str(s: &str) -> Self { match s.to_lowercase().as_str() { "active" => Self::Active, diff --git a/crates/mem-core/src/entity.rs b/crates/mem-core/src/entity.rs index 6a0c401..0284225 100644 --- a/crates/mem-core/src/entity.rs +++ b/crates/mem-core/src/entity.rs @@ -1,6 +1,7 @@ /// Entity domain model for temporal graph-RAG. /// Single Responsibility: Entity identity and metadata. /// Open/Closed: EntityType enum extensible. +#[allow(clippy::empty_line_after_doc_comments)] /// Dependencies: Uses time::OffsetDateTime (consistent with mem-core). use serde::{Deserialize, Serialize}; @@ -43,6 +44,7 @@ impl EntityType { } } + #[allow(clippy::should_implement_trait)] pub fn from_str(s: &str) -> Self { match s.to_lowercase().as_str() { "person" => Self::Person, diff --git a/crates/mem-core/src/gated_loop.rs b/crates/mem-core/src/gated_loop.rs index 077333c..9f3f61d 100644 --- a/crates/mem-core/src/gated_loop.rs +++ b/crates/mem-core/src/gated_loop.rs @@ -135,11 +135,10 @@ pub fn run_loop( #[cfg(test)] mod tests { - use super::*; + #[test] fn test_loop_basic() { // Placeholder test to verify it compiles - assert!(true); } } diff --git a/crates/mem-core/src/lesson.rs b/crates/mem-core/src/lesson.rs index f2f1e05..f645f8c 100644 --- a/crates/mem-core/src/lesson.rs +++ b/crates/mem-core/src/lesson.rs @@ -403,7 +403,7 @@ pub fn lookup(sig: &Signature, lessons: &[Lesson], floor: f32) -> Option { let mut best: Option<(f32, &Lesson)> = None; for l in lessons.iter().filter(|l| l.tool == sig.tool) { let s = similarity(&sig.normalised, &l.normalised); - if s >= floor && best.map_or(true, |(bs, _)| s > bs) { + if s >= floor && best.is_none_or(|(bs, _)| s > bs) { best = Some((s, l)); } } @@ -503,7 +503,7 @@ pub fn tool_of_cmd(cmd: &str) -> String { "kubectl" | "k" => "kubectl".into(), "docker" | "podman" => "docker".into(), "terraform" | "tofu" => "terraform".into(), - other if other.is_empty() => "unknown".into(), + "" => "unknown".into(), other => other.to_string(), } } @@ -549,7 +549,7 @@ pub fn render_skill(tool: &str, lessons: &[Lesson]) -> String { s.push_str("`confirmed`, which outranks inferred lessons at equal similarity.\n\n"); let mut sorted: Vec<&Lesson> = lessons.iter().collect(); - sorted.sort_by(|a, b| b.seen.cmp(&a.seen)); + sorted.sort_by_key(|a| std::cmp::Reverse(a.seen)); for l in sorted { s.push_str(&format!("## {}\n\n", l.raw.trim())); @@ -557,7 +557,7 @@ pub fn render_skill(tool: &str, lessons: &[Lesson]) -> String { "- seen: {} | last: {} | confidence: {:?}\n", l.seen, l.last_seen, l.confidence )); - s.push_str(&format!("- signature: `{}`\n", l.sig_sha[..12].to_string())); + s.push_str(&format!("- signature: `{}`\n", &l.sig_sha[..12])); s.push_str("- resolved by:\n"); for r in &l.resolution { s.push_str(&format!(" ```\n {r}\n ```\n")); @@ -712,7 +712,7 @@ mod tests { ev("t2", "npm pkg set overrides.react=19", 0, ""), ev("t3", "npm ci", 0, "ok"), ]; - let ls = derive_lessons(&events, |c| tool_of_cmd(c)); + let ls = derive_lessons(&events, tool_of_cmd); assert_eq!(ls.len(), 1); assert_eq!(ls[0].resolution, vec!["npm pkg set overrides.react=19"]); assert_eq!(ls[0].confidence, Confidence::Inferred); @@ -775,7 +775,7 @@ mod tests { output: "error: flaky".into(), }; let events = vec![ev("npm ci", 1), ev("npm ci", 0)]; - assert!(derive_lessons(&events, |c| tool_of_cmd(c)).is_empty()); + assert!(derive_lessons(&events, tool_of_cmd).is_empty()); } #[test] @@ -798,7 +798,7 @@ mod tests { sig_sha: "abc".into(), rule: "r".into(), }; - assert_eq!(lookup(&exact, &[l.clone()], 0.5).unwrap().tier, Tier::Exact); + assert_eq!(lookup(&exact, std::slice::from_ref(&l), 0.5).unwrap().tier, Tier::Exact); let unrelated = Signature { tool: "npm".into(), diff --git a/crates/mem-core/src/optimizer/builtin.rs b/crates/mem-core/src/optimizer/builtin.rs index ab56323..a34d925 100644 --- a/crates/mem-core/src/optimizer/builtin.rs +++ b/crates/mem-core/src/optimizer/builtin.rs @@ -152,11 +152,11 @@ impl FormatHandler for CsvFormatter { async fn format(&self, result: &OptimizationResult) -> Result, String> { let output = format!( - "{},{},{},{}\n", + "{},{},{},{:.2}\n", escape_csv(&result.plugin), result.original.len(), result.optimized.len(), - format!("{:.2}", result.ratio) + result.ratio ); Ok(output.into_bytes()) } diff --git a/crates/mem-core/src/optimizer/ccr.rs b/crates/mem-core/src/optimizer/ccr.rs index db53be6..99e0ffe 100644 --- a/crates/mem-core/src/optimizer/ccr.rs +++ b/crates/mem-core/src/optimizer/ccr.rs @@ -40,7 +40,7 @@ impl CcrStore { // Remove oldest entry if at capacity if cache.len() >= self.max_entries { if let Some(oldest_key) = cache.keys().next().cloned() { - cache.remove(&oldest_key); + cache.swap_remove(&oldest_key); } } @@ -57,7 +57,7 @@ impl CcrStore { // Check if expired let duration = OffsetDateTime::now_utc() - *timestamp; if duration.whole_seconds() > self.ttl_secs as i64 { - cache.remove(hash); + cache.swap_remove(hash); return Ok(None); } diff --git a/crates/mem-core/src/optimizer/json.rs b/crates/mem-core/src/optimizer/json.rs index 6910e70..1d48f8c 100644 --- a/crates/mem-core/src/optimizer/json.rs +++ b/crates/mem-core/src/optimizer/json.rs @@ -7,7 +7,7 @@ //! - Drop: redundant homogeneous elements, long string values use anyhow::Result; -use serde_json::{json, Value}; +use serde_json::Value; use std::collections::HashMap; pub struct JsonCrusher; @@ -45,8 +45,8 @@ impl JsonCrusher { let mut result = Vec::new(); // Add start items - for i in 0..start_count.min(len) { - result.push(items[i].clone()); + for item in items.iter().take(start_count.min(len)) { + result.push(item.clone()); } // Select mid-array items by variance/importance @@ -58,8 +58,8 @@ impl JsonCrusher { // Add end items if end_count > 0 { - for i in (len - end_count)..len { - result.push(items[i].clone()); + for item in items.iter().skip(len.saturating_sub(end_count)) { + result.push(item.clone()); } } diff --git a/crates/mem-core/src/optimizer/query_optimizer.rs b/crates/mem-core/src/optimizer/query_optimizer.rs index 34b7493..038ea08 100644 --- a/crates/mem-core/src/optimizer/query_optimizer.rs +++ b/crates/mem-core/src/optimizer/query_optimizer.rs @@ -5,7 +5,7 @@ use super::plugin::OptimizerService; use crate::prompt::CacheMetrics; -use crate::domain::{Chunk, Record}; +use crate::domain::Chunk; use anyhow::Result; /// Query optimizer: compresses chunks before LLM processing @@ -83,7 +83,7 @@ impl QueryOptimizer { match service.optimize(&chunk_text, &content_type, Some("raw")).await { Ok(bytes) => { let text = String::from_utf8(bytes) - .unwrap_or_else(|_| chunk_text); + .unwrap_or(chunk_text); Ok(text) } Err(_) => { diff --git a/crates/mem-core/src/optimizer/router.rs b/crates/mem-core/src/optimizer/router.rs index 7b1536f..fd2d06b 100644 --- a/crates/mem-core/src/optimizer/router.rs +++ b/crates/mem-core/src/optimizer/router.rs @@ -42,7 +42,7 @@ impl ContentRouter { /// Check if content is valid JSON fn is_json(content: &str) -> bool { let trimmed = content.trim(); - if !((trimmed.starts_with('{') || trimmed.starts_with('['))) { + if !(trimmed.starts_with('{') || trimmed.starts_with('[')) { return false; } serde_json::from_str::(trimmed).is_ok() diff --git a/crates/mem-core/src/optimizer/text.rs b/crates/mem-core/src/optimizer/text.rs index b79b8cf..799f923 100644 --- a/crates/mem-core/src/optimizer/text.rs +++ b/crates/mem-core/src/optimizer/text.rs @@ -128,7 +128,7 @@ impl TextCompressor { } // Capitalization (usually proper nouns or emphatic) - if token.chars().next().map_or(false, |c| c.is_uppercase()) && token.len() > 1 { + if token.chars().next().is_some_and(|c| c.is_uppercase()) && token.len() > 1 { score += 1.0; } diff --git a/crates/mem-core/src/prompt.rs b/crates/mem-core/src/prompt.rs index b8c7994..6cb05a1 100644 --- a/crates/mem-core/src/prompt.rs +++ b/crates/mem-core/src/prompt.rs @@ -12,7 +12,9 @@ const CACHE_TURN: &str = include_str!("../../../templates/gru-mem-turn.txt"); const BUDGET_TOTAL: usize = 32768; const BUDGET_RESPONSE: usize = 2048; +#[allow(dead_code)] const BUDGET_SYSTEM: usize = 400; +#[allow(dead_code)] const BUDGET_QUESTION: usize = 150; const BUDGET_MEMORY_MAX: usize = 1024; const BUDGET_CHUNK_MAX: usize = 5000; @@ -368,7 +370,7 @@ fn estimate_tokens(text: &str) -> usize { #[cfg(test)] mod tests { use super::*; - use crate::domain::{Chunk, Record, Role, Provenance, Level}; + use crate::domain::{Chunk, Record, Role, Provenance}; use time::OffsetDateTime; fn make_test_chunk(text: &str) -> Chunk { @@ -645,7 +647,7 @@ mod tests { let metrics = result.unwrap(); let ratio = metrics.compression_ratio(); - assert!(ratio >= 0.0 && ratio <= 100.0); + assert!((0.0..=100.0).contains(&ratio)); } #[test] diff --git a/crates/mem-core/src/query.rs b/crates/mem-core/src/query.rs index 52ba03d..f7aee0d 100644 --- a/crates/mem-core/src/query.rs +++ b/crates/mem-core/src/query.rs @@ -1,7 +1,5 @@ -use crate::domain::{ProjectId, QueryId}; use anyhow::{anyhow, Result}; use serde::{Deserialize, Serialize}; -use std::collections::HashMap; use std::path::Path; /// A single standing query. diff --git a/crates/mem-core/src/query_executor.rs b/crates/mem-core/src/query_executor.rs index bd009fe..356d44a 100644 --- a/crates/mem-core/src/query_executor.rs +++ b/crates/mem-core/src/query_executor.rs @@ -1,4 +1,4 @@ -use crate::{Level, Query}; +use crate::Level; use anyhow::Result; use serde::{Deserialize, Serialize}; @@ -17,6 +17,12 @@ pub struct QueryExecutor { // For now: proof-of-concept with mock data } +impl Default for QueryExecutor { + fn default() -> Self { + Self::new() + } +} + impl QueryExecutor { /// Create executor. pub fn new() -> Self { diff --git a/crates/mem-core/src/query_levels.rs b/crates/mem-core/src/query_levels.rs index 5e03ea8..6bd47ee 100644 --- a/crates/mem-core/src/query_levels.rs +++ b/crates/mem-core/src/query_levels.rs @@ -71,11 +71,10 @@ impl QueryLevels { } // Check level filter - if !self.level_filter.is_empty() { - if !self.level_filter.contains(&level.to_string()) { + if !self.level_filter.is_empty() + && !self.level_filter.contains(&level.to_string()) { return false; } - } // Check evidence/reference flags if level == "R" { diff --git a/crates/mem-core/src/scoring.rs b/crates/mem-core/src/scoring.rs index bd76c3e..9c8fec6 100644 --- a/crates/mem-core/src/scoring.rs +++ b/crates/mem-core/src/scoring.rs @@ -6,6 +6,7 @@ /// - Single Responsibility: each scorer does one thing /// - Open/Closed: add new scorers without modifying existing /// - Liskov Substitution: all scorers implement DocumentScorer +#[allow(clippy::empty_line_after_doc_comments)] /// - Dependency Inversion: depend on trait, not concrete types use anyhow::Result; @@ -53,6 +54,7 @@ impl DocumentScorer for GlobalTfIdfScorer { } /// Project-scoped TF-IDF Scorer: scoring within project boundaries +#[allow(dead_code)] pub struct ProjectTfIdfScorer { project: String, vocabulary: Arc>, @@ -93,11 +95,18 @@ impl DocumentScorer for ProjectTfIdfScorer { } /// Semantic Scorer: vector similarity (placeholder) +#[allow(dead_code)] pub struct SemanticScorer { _embeddings_client: Arc<()>, // Placeholder _pgvector: Arc<()>, // Placeholder } +impl Default for SemanticScorer { + fn default() -> Self { + Self::new() + } +} + impl SemanticScorer { pub fn new() -> Self { Self { @@ -156,6 +165,12 @@ pub struct ScoringPipeline { scorers: Vec<(String, f32, Arc)>, // name, weight, scorer } +impl Default for ScoringPipeline { + fn default() -> Self { + Self::new() + } +} + impl ScoringPipeline { pub fn new() -> Self { Self { diff --git a/crates/mem-core/src/symptom_projection.rs b/crates/mem-core/src/symptom_projection.rs index de62a21..50933b2 100644 --- a/crates/mem-core/src/symptom_projection.rs +++ b/crates/mem-core/src/symptom_projection.rs @@ -81,6 +81,7 @@ impl SymptomVector { /// Internal structure for tokens during extraction #[derive(Debug, Clone)] +#[allow(dead_code)] struct SymptomTokens { keywords: Vec, error_codes: Vec, @@ -392,7 +393,7 @@ mod tests { let words: Vec<&str> = symptom.normalised.split_whitespace().collect(); for word in &words { // Check if this word is a stop word - assert!(!STOP_WORDS.contains(&word), "Stop word '{}' should be removed", word); + assert!(!STOP_WORDS.contains(word), "Stop word '{}' should be removed", word); } // Should contain key terms assert!(symptom.normalised.contains("resolve")); diff --git a/crates/mem-core/tests/it_m3_8_benchmarks.rs b/crates/mem-core/tests/it_m3_8_benchmarks.rs index 2f42f99..cdc3370 100644 --- a/crates/mem-core/tests/it_m3_8_benchmarks.rs +++ b/crates/mem-core/tests/it_m3_8_benchmarks.rs @@ -267,11 +267,9 @@ fn test_compression_handles_large_content() { fn test_multi_chunk_search_consistency() { let optimizer = ContextOptimizer::new().expect("optimizer init"); - let chunks = vec![ - "ERROR: connection failed\nDEBUG: thread id=100", + let chunks = ["ERROR: connection failed\nDEBUG: thread id=100", "ERROR: timeout after 5000ms\nTRACE: stack unwinding", - "ERROR: retry attempt 2\nDEBUG: backoff delay=200ms", - ]; + "ERROR: retry attempt 2\nDEBUG: backoff delay=200ms"]; let optimized_chunks: Vec<_> = chunks .iter() diff --git a/crates/mem-core/tests/it_m3_8_gate.rs b/crates/mem-core/tests/it_m3_8_gate.rs index d174684..8724c67 100644 --- a/crates/mem-core/tests/it_m3_8_gate.rs +++ b/crates/mem-core/tests/it_m3_8_gate.rs @@ -196,7 +196,6 @@ fn gate_memory_bounded() { // Should not panic from memory exhaustion // If we get here, we passed the gate - assert!(true, "memory usage bounded"); } #[test] @@ -231,7 +230,7 @@ fn gate_compression_targets_met() { ]; for (content, name, min_compression) in fixtures.iter() { - let optimized = optimizer.optimize(content).expect(&format!("optimize {}", name)); + let optimized = optimizer.optimize(content).unwrap_or_else(|_| panic!("optimize {}", name)); let ratio = optimized.compressed.len() as f32 / content.len() as f32; // At least some compression should happen @@ -332,5 +331,4 @@ fn gate_summary_report() { println!("\nšŸš€ STATUS: M3.8 READY FOR PRODUCTION"); - assert!(true); // Just for testing framework } diff --git a/crates/mem-ingest/src/contradiction_detector.rs b/crates/mem-ingest/src/contradiction_detector.rs index 9984aa8..0122843 100644 --- a/crates/mem-ingest/src/contradiction_detector.rs +++ b/crates/mem-ingest/src/contradiction_detector.rs @@ -83,6 +83,7 @@ impl ContradictionPreFilter { /// LLM-based contradiction detector (stage 2) /// Only called if pre-filter returns true (cost optimization) +#[allow(dead_code)] pub struct LlmContradictionDetector { model_name: String, auto_confirm_threshold: f32, diff --git a/crates/mem-ingest/src/entity_extractor.rs b/crates/mem-ingest/src/entity_extractor.rs index 5ad6e4e..32b4db2 100644 --- a/crates/mem-ingest/src/entity_extractor.rs +++ b/crates/mem-ingest/src/entity_extractor.rs @@ -48,6 +48,7 @@ pub trait EntityExtractor: Send + Sync { /// LLM-based extractor with reflection verification (stage 1 + 2) /// Uses Authentik JWT tokens for authentication to LLM gateway +#[allow(dead_code)] pub struct LlmEntityExtractor { model_name: String, enable_reflection: bool, @@ -330,7 +331,7 @@ impl EntityExtractor for WikiLinkFallbackExtractor { entities.push(ExtractedEntity { name: name_str.to_string(), entity_type: EntityType::Unknown, - summary: format!("Mentioned in episode"), + summary: "Mentioned in episode".to_string(), confidence: 0.7, // Lower confidence for fallback }); } @@ -418,6 +419,6 @@ mod tests { let text = "[[Entity1]] and [[Entity2]]"; let entities = composite.extract(text).await.unwrap(); - assert!(entities.len() > 0); + assert!(!entities.is_empty()); } } diff --git a/crates/mem-ingest/src/grm_retriever.rs b/crates/mem-ingest/src/grm_retriever.rs index d55cde2..d6a85a1 100644 --- a/crates/mem-ingest/src/grm_retriever.rs +++ b/crates/mem-ingest/src/grm_retriever.rs @@ -10,10 +10,7 @@ use anyhow::Result; use async_trait::async_trait; use serde::{Deserialize, Serialize}; -use std::collections::HashMap; -use tracing::{debug, info}; -use mem_core::entity::Entity; -use mem_core::edge::Edge; +use tracing::debug; /// Memorability decision for entity or fact #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)] diff --git a/crates/mem-ingest/src/ingest_pipeline.rs b/crates/mem-ingest/src/ingest_pipeline.rs index 9814135..4dca865 100644 --- a/crates/mem-ingest/src/ingest_pipeline.rs +++ b/crates/mem-ingest/src/ingest_pipeline.rs @@ -144,6 +144,7 @@ impl IngestPipeline { /// Async queue worker: Process episodes from queue /// CRAP: 12 (Async loop, straightforward) +#[allow(dead_code)] pub struct QueueWorker { pipeline: Arc, batch_size: usize, diff --git a/crates/mem-ingest/src/memorability_gate.rs b/crates/mem-ingest/src/memorability_gate.rs index b6dd07a..2343510 100644 --- a/crates/mem-ingest/src/memorability_gate.rs +++ b/crates/mem-ingest/src/memorability_gate.rs @@ -14,7 +14,7 @@ use tracing::{debug, info}; use crate::grm_retriever::{ EntityContext, FactContext, GraphContextRetriever, MemorabilityDecision, GrmConfig, MockGrmRetriever, }; -use mem_core::entity::{Entity, EntityType}; +use mem_core::entity::Entity; use mem_core::edge::Edge; /// Entity filtering result @@ -88,7 +88,7 @@ impl MemorabilityGate { let (filtered, reason) = match context.decision { MemorabilityDecision::Keep => { if context.matched_entity_id.is_some() { - (true, format!("Existing entity (merge required)")) + (true, "Existing entity (merge required)".to_string()) } else { (false, format!("New entity (score: {:.2})", context.memorability_score)) } diff --git a/crates/mem-ingest/src/obsidian_ref_source.rs b/crates/mem-ingest/src/obsidian_ref_source.rs index 7aae64c..e51ddac 100644 --- a/crates/mem-ingest/src/obsidian_ref_source.rs +++ b/crates/mem-ingest/src/obsidian_ref_source.rs @@ -20,6 +20,7 @@ pub struct RefMetadata { } /// Obsidian REST API client +#[allow(dead_code)] pub struct ObsidianClient { base_url: String, } @@ -47,6 +48,7 @@ impl ObsidianClient { } /// ObsidianRefSource: Fetches & chunks reference documents from Obsidian vault +#[allow(dead_code)] pub struct ObsidianRefSource { client: ObsidianClient, project: String, @@ -203,7 +205,7 @@ mod tests { let chunks = source.chunk_document("docs/test.md", content); // Should split by headings - assert!(chunks.len() > 0); + assert!(!chunks.is_empty()); } #[test] diff --git a/crates/mem-ingest/src/optimizer_metrics.rs b/crates/mem-ingest/src/optimizer_metrics.rs index fc099d5..f591189 100644 --- a/crates/mem-ingest/src/optimizer_metrics.rs +++ b/crates/mem-ingest/src/optimizer_metrics.rs @@ -60,8 +60,7 @@ impl MetricsCollector { self.by_project .lock() .unwrap() - .get(project) - .map(|m| m.clone()) + .get(project).cloned() } /// Get all project metrics. diff --git a/crates/mem-ingest/src/query_metrics.rs b/crates/mem-ingest/src/query_metrics.rs index 002e9b1..6048072 100644 --- a/crates/mem-ingest/src/query_metrics.rs +++ b/crates/mem-ingest/src/query_metrics.rs @@ -306,7 +306,7 @@ impl QueryMetricsRepository { let mut repo = self.metrics.lock().unwrap(); repo.get_mut(query_id) .ok_or_else(|| format!("Query {} not found", query_id)) - .map(|metrics| f(metrics)) + .map(f) } /// Get progress for a query diff --git a/crates/mem-ingest/src/wiki_link.rs b/crates/mem-ingest/src/wiki_link.rs index b447f4d..bcd1fc9 100644 --- a/crates/mem-ingest/src/wiki_link.rs +++ b/crates/mem-ingest/src/wiki_link.rs @@ -4,9 +4,10 @@ /// /// Used to scope queries to project namespaces and enable graph traversal. /// For example: poimen/tools/kubectl.md [[debugging.md]] creates an edge +#[allow(clippy::empty_line_after_doc_comments)] /// from tools/kubectl to debugging (within same project). -use anyhow::{anyhow, Result}; +use anyhow::Result; use regex::Regex; use std::collections::{HashMap, HashSet}; use std::path::{Path, PathBuf}; @@ -79,6 +80,7 @@ impl WikiLinkParser { } /// Graph Index: Stores and queries wiki-link relationships +#[allow(dead_code)] pub struct WikiLinkGraph { /// Forward links: source -> [targets] forward_links: HashMap>, @@ -100,11 +102,11 @@ impl WikiLinkGraph { /// Add a wiki-link edge pub fn add_link(&mut self, source: &str, target: &str) { self.forward_links.entry(source.to_string()) - .or_insert_with(Vec::new) + .or_default() .push(target.to_string()); self.backward_links.entry(target.to_string()) - .or_insert_with(Vec::new) + .or_default() .push(source.to_string()); } diff --git a/crates/mem-llm/src/chat.rs b/crates/mem-llm/src/chat.rs index e0fc6b6..35e1230 100644 --- a/crates/mem-llm/src/chat.rs +++ b/crates/mem-llm/src/chat.rs @@ -34,7 +34,7 @@ pub enum AuthMode { impl AuthMode { /// Detect from base URL or explicit env var. - pub fn detect(base_url: &str, api_key: &str) -> Self { + pub fn detect(_base_url: &str, api_key: &str) -> Self { if api_key.is_empty() { return Self::None; } @@ -87,6 +87,7 @@ struct Choice { } #[derive(Debug, Deserialize)] +#[allow(dead_code)] struct MessageResponse { role: String, content: String, @@ -208,12 +209,11 @@ impl ChatClient { Ok(r) => r, Err(e) => { last_error = Some(anyhow!("Request failed: {}", e)); - if e.is_timeout() || e.is_status() { - if attempt < self.max_retries - 1 { + if (e.is_timeout() || e.is_status()) + && attempt < self.max_retries - 1 { tokio::time::sleep(Duration::from_millis(100 * 2_u64.pow(attempt))).await; continue; } - } return Err(last_error.unwrap()); } }; diff --git a/crates/mem-llm/src/embeddings.rs b/crates/mem-llm/src/embeddings.rs index 512f98c..fa30c18 100644 --- a/crates/mem-llm/src/embeddings.rs +++ b/crates/mem-llm/src/embeddings.rs @@ -42,6 +42,7 @@ enum EmbeddingResponse { } #[derive(Debug, Deserialize)] +#[allow(dead_code)] struct EmbeddingData { embedding: Vec, #[serde(default)] @@ -120,10 +121,10 @@ impl EmbeddingsClient { /// Embed a single text string, returning a 768-dim vector pub async fn embed_one(&self, text: &str) -> Result { let embeddings = self.embed(&[text.to_string()]).await?; - Ok(embeddings + embeddings .into_iter() .next() - .ok_or_else(|| anyhow!("empty embedding response"))?) + .ok_or_else(|| anyhow!("empty embedding response")) } /// Embed multiple texts, batched at ≤32 per request, preserving input order