fix: zero compiler warnings + readiness endpoint
CI / CI (pull_request) Successful in 27m38s

- Fix all 106 warnings: unused imports, dead struct fields (_prefix),
  dead_code annotations on bin-only items in ingest_worker.rs
- Add GET /ready endpoint (readiness probe, checks DB)
- Keep GET /health lightweight (liveness, no DB check)
- Add ServiceMonitor for Prometheus scraping
- Add tracing-subscriber json feature for structured logs
- 760 tests passing, 0 warnings, 0 errors
This commit is contained in:
2026-09-16 08:33:21 +09:00
parent d476e8c612
commit 6d74ba5d93
49 changed files with 167 additions and 186 deletions
Generated
+13
View File
@@ -3986,6 +3986,16 @@ dependencies = [
"tracing-core",
]
[[package]]
name = "tracing-serde"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1"
dependencies = [
"serde",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.23"
@@ -3993,11 +4003,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319"
dependencies = [
"nu-ansi-term",
"serde",
"serde_json",
"sharded-slab",
"smallvec",
"thread_local",
"tracing-core",
"tracing-log",
"tracing-serde",
]
[[package]]
+1 -1
View File
@@ -27,7 +27,7 @@ anyhow = { workspace = true }
thiserror = { workspace = true }
clap = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
tracing-subscriber = { workspace = true, features = ["json"] }
time = { workspace = true }
actix-web = { workspace = true }
actix-rt = { workspace = true }
+2 -12
View File
@@ -1,15 +1,4 @@
/// Advanced Ranking: Temporal decay, popularity, diversity, and cross-encoder scoring
///
/// Provides sophisticated ranking strategies:
/// - Temporal decay: Older documents get lower scores
/// - Popularity: Frequently accessed docs get higher scores
/// - Diversity: Penalize redundant top results
/// - Cross-encoder: Pairwise document-query scoring
/// - Click-through rate (CTR): User feedback signals
use anyhow::Result;
use chrono::{DateTime, Utc, Duration};
use std::collections::HashMap;
use chrono::{DateTime, Utc};
/// Document with ranking features
#[derive(Debug, Clone)]
@@ -296,6 +285,7 @@ impl RankerStats {
#[cfg(test)]
mod tests {
use super::*;
use chrono::Duration;
#[test]
fn test_temporal_decay_recent() {
+4 -4
View File
@@ -74,7 +74,7 @@ impl ClientResponse {
/// Synthesis client SDK with JWT auth support + pod-aware routing
pub struct SynthesisClient {
base_url: String, // Resolved URL (internal or external)
external_url: String, // Fallback external URL
_external_url: String, // Fallback external URL
jwt_token: String, // JWT Bearer token for all requests
timeout_secs: u32,
is_pod: bool, // Running inside k8s pod?
@@ -102,7 +102,7 @@ impl SynthesisClient {
SynthesisClient {
base_url,
external_url,
_external_url: external_url,
jwt_token,
timeout_secs,
is_pod,
@@ -369,7 +369,7 @@ mod tests {
SynthesisClient::new("https://api.riotpiao.com".to_string(), "test-jwt-placeholder".to_string());
// Verify ConfigMap env vars respected
assert!(!client.external_url.is_empty());
assert!(!client._external_url.is_empty());
assert_eq!(client.timeout_secs, 45);
}
@@ -459,7 +459,7 @@ mod tests {
fn test_external_fallback_url() {
let client =
SynthesisClient::new("https://api.riotpiao.com".to_string(), "jwt".to_string());
assert_eq!(client.external_url, "https://api.riotpiao.com");
assert_eq!(client._external_url, "https://api.riotpiao.com");
}
#[test]
@@ -6,8 +6,6 @@ use async_trait::async_trait;
use jsonwebtoken::{decode, decode_header, DecodingKey, Validation, Algorithm};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::sync::Arc;
use tokio::sync::RwLock;
use super::provider::{AuthProvider, Claims, AuthError};
@@ -115,7 +113,7 @@ impl AuthProvider for AuthentikProvider {
// 2. Fetch JWKS to find public key
let jwks = self.fetch_jwks().await?;
let jwks_key = jwks.keys.iter()
let _jwks_key = jwks.keys.iter()
.find(|k| k.kid == kid)
.ok_or(AuthError::InvalidSignature)?;
@@ -5,7 +5,7 @@ use std::sync::{Arc, RwLock};
use std::time::{Duration, Instant};
use serde::{Deserialize, Serialize};
use reqwest::Client;
use tracing::{debug, warn, error};
use tracing::{debug, error};
#[derive(Clone, Debug)]
pub struct AuthentikServiceAccountConfig {
+1 -1
View File
@@ -4,7 +4,7 @@
/// 1. AuthGuard: Extract and validate token
/// 2. PermissionGuard: Check group membership and resource roles
use super::provider::{AuthProvider, Claims, AuthError};
use super::provider::{Claims, AuthError};
/// Extracts and validates Bearer token from request headers.
pub struct AuthGuard;
+3 -5
View File
@@ -25,14 +25,12 @@ use std::sync::Arc;
use mem_core::{GlobalTfIdfScorer, SemanticScorer};
use mem_ingest::wiki_link::WikiLinkGraph;
use crate::full_pipeline::{FullPipeline, PipelineConfig, PipelineResult, EnrichedChunk, PipelineMetrics};
use crate::full_pipeline::{FullPipeline, PipelineConfig, PipelineResult, EnrichedChunk};
use crate::rbac::{
AccessPolicy, PolicyProvider, AccessDecisionEngine, OidcClaims,
LegacyAccessDecision as AccessDecision,
PolicyProvider, AccessDecisionEngine, OidcClaims,
LegacyAuditLogger as AuditLogger,
LegacyNoOpAuditLogger as NoOpAuditLogger,
};
use crate::http_server::JwtClaims;
// JwtValidator removed (issue #56). Stub for compilation.
#[allow(dead_code)]
@@ -413,7 +411,7 @@ impl AuthorizedPipelineBuilder {
mod tests {
use super::*;
use std::collections::BTreeMap;
use crate::rbac::MockPolicyProvider;
use crate::rbac::{MockPolicyProvider, AccessPolicy};
fn create_test_vocab() -> Arc<BTreeMap<String, f32>> {
let mut vocab = BTreeMap::new();
+1 -15
View File
@@ -1,18 +1,4 @@
/// Phase 5: Chunk Metadata Index
///
/// Extract and index chunk metadata for improved scoring:
/// 1. Heading extraction (markdown hierarchy)
/// 2. Key term extraction (TF-IDF top terms)
/// 3. Category inference (error|solution|tool|concept)
/// 4. Metadata-based scoring boost
///
/// Benefits:
/// - Better semantic understanding (category context)
/// - Faster ranking (metadata pre-computed)
/// - Query intent matching (match query intent to chunk category)
use anyhow::Result;
use std::collections::{HashMap, HashSet};
use std::collections::HashMap;
/// Chunk category for scoring context
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+2 -13
View File
@@ -1,15 +1,4 @@
/// Phase 4: LLM Call Optimization
///
/// Reduce LLM calls by:
/// 1. Score thresholding: skip chunks < 0.6
/// 2. Budget-aware selection: select top-K within byte budget
/// 3. Deduplication: remove near-duplicate chunks (shingle-based)
/// 4. Ranking by value: prioritize high-confidence results
///
/// Target: 70-80% fewer LLM calls for typical queries
use anyhow::Result;
use std::collections::{HashMap, HashSet};
use std::collections::HashSet;
/// Chunk with selection metrics
#[derive(Debug, Clone)]
@@ -77,7 +66,7 @@ impl BudgetSelector {
.unwrap_or(std::cmp::Ordering::Equal)
});
let total_count = chunks.len();
let _total_count = chunks.len();
let mut selected = Vec::new();
let mut total_bytes = 0usize;
let mut rejected_count = 0;
+2 -4
View File
@@ -5,13 +5,11 @@
/// - T3.2: Semantic dedup (LLM-gated with pre-filter)
/// - T3.3: Audit logging + dry-run mode
use anyhow::{Result, anyhow};
use anyhow::Result;
use sqlx::{Pool, Postgres, Row};
use std::sync::Arc;
use std::collections::HashMap;
use tracing::{debug, info, warn};
use tracing::{debug, info};
use mem_core::edge::Edge;
// LlmCaller trait (moved from mem_ingest)
#[async_trait::async_trait]
pub trait LlmCaller: Send + Sync {
+3 -4
View File
@@ -14,15 +14,14 @@
/// - `PipelineResult`: comprehensive result with all metrics
use anyhow::Result;
use std::collections::HashMap;
use std::sync::Arc;
use mem_core::{GlobalTfIdfScorer, SemanticScorer};
use mem_ingest::wiki_link::WikiLinkGraph;
use crate::query_router::{QueryRouter, RouterConfig, RoutedResult, SelectedChunk};
use crate::chunk_metadata::{MetadataExtractor, MetadataBooster, ChunkMetadata, ChunkCategory, QueryIntent};
use crate::cache_alignment::{KvCacheAligner, CachedChunk, CacheLocalityAnalyzer, RetrievalProfiler, CacheMetrics};
use crate::query_router::{QueryRouter, RouterConfig};
use crate::chunk_metadata::{MetadataExtractor, MetadataBooster, ChunkCategory, QueryIntent};
use crate::cache_alignment::{KvCacheAligner, CachedChunk, RetrievalProfiler};
/// Unified pipeline configuration
#[derive(Debug, Clone)]
+3 -4
View File
@@ -5,14 +5,13 @@
use actix_web::{web, HttpRequest, HttpResponse};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use uuid::Uuid;
use chrono::Utc;
use crate::agent::{Agent, AgentConfig, AgentCapability, DefaultAgent};
use crate::agent::client_sdk::SynthesisClient;
use crate::handlers::response_builder;
use mem_store::agent_repo::{AgentRepository, AgentPrompt, AgentSkill, AgentDecision, RolePromptMapping};
use crate::metrics::{ERROR_AUTH_FAILURE_AGENT, ERROR_BAD_REQUEST_AGENT, ERROR_NOT_FOUND_AGENT, ERROR_UNEXPECTED_AGENT, ERROR_UNEXPECTED_TOTAL};
use mem_store::agent_repo::AgentRepository;
use crate::metrics::{ERROR_BAD_REQUEST_AGENT, ERROR_NOT_FOUND_AGENT, ERROR_UNEXPECTED_AGENT, ERROR_UNEXPECTED_TOTAL};
use tracing::{debug, info, error, warn};
/// Register agent request
@@ -94,7 +93,7 @@ pub async fn register_agent_handler(
};
// Persist agent config to database via agent_registry table
let agent_repo = AgentRepository::new(state.pool.clone());
let _agent_repo = AgentRepository::new(state.pool.clone());
// Verify project exists
let project_exists = sqlx::query("SELECT id FROM projects WHERE id = $1")
+1 -2
View File
@@ -5,10 +5,9 @@
use actix_web::{web, HttpRequest, HttpResponse};
use serde::{Deserialize, Serialize};
use serde_json::json;
use crate::http_server::AppState;
use crate::compaction::{compact_memory, CompactionMode, CompactionStats};
use crate::compaction::{CompactionMode, CompactionStats};
/// Compaction request parameters
#[derive(Debug, Deserialize, Clone)]
@@ -4,7 +4,6 @@
/// Rate limiting deferred to API gateway / riotpiao-rust-sdk (issue #56).
use actix_web::{HttpRequest, HttpResponse};
use serde_json::json;
use crate::http_server::AppState;
/// Result type for middleware operations
@@ -1,8 +1,6 @@
use actix_web::{web, HttpRequest, HttpResponse};
use actix_web::{HttpRequest, HttpResponse};
use chrono::{DateTime, Utc};
use serde_json::json;
use sqlx::PgPool;
use std::collections::HashMap;
use crate::auth::AuthGuard;
@@ -152,7 +152,7 @@ pub async fn rebuild(
/// GET /memory/rebuild/status
pub async fn rebuild_status(
req: HttpRequest,
pool: web::Data<PgPool>,
_pool: web::Data<PgPool>,
) -> HttpResponse {
// Verify auth
if let Err(e) = AuthGuard::extract_token(req.headers().get("Authorization").and_then(|v| v.to_str().ok()).unwrap_or("")) {
+1 -2
View File
@@ -4,11 +4,10 @@
use actix_web::{web, HttpRequest, HttpResponse};
use serde::{Deserialize, Serialize};
use serde_json::json;
use tracing::{debug, error, info};
use crate::http_server::AppState;
use crate::query::{SemanticRetriever, EntityResult, EdgeResult, HybridResult, CommunityDetector, CommunityDetectionResult, PathFinder, PathFindingResult, FacetedSearch, AvailableFacets, FacetFilters};
use crate::query::{SemanticRetriever, CommunityDetector, CommunityDetectionResult, PathFinder, PathFindingResult, FacetedSearch, AvailableFacets, FacetFilters};
/// Request for semantic entity search
#[derive(Debug, Deserialize)]
+3 -3
View File
@@ -14,8 +14,8 @@ use crate::http_server::AppState;
use crate::query::{
EntityLinker, MentionLink, AliasSuggestion, MergeSuggestion, CoreferenceCluster,
InferenceEngine, InferenceRule, InferredFact, ReasoningPath, TransitiveClosure,
QueryReasoner, SubQuery, Constraint, QuestionType, ReasonedAnswer,
Summarizer, SummarizationStrategy, Summary, KeyFact,
QueryReasoner,
Summarizer, SummarizationStrategy,
};
/// Request to link entities
@@ -145,7 +145,7 @@ pub async fn link_entities_handler(
let total = links.len() + unlinked.len();
let link_rate = if total > 0 {
(links.len() as f32 / total as f32)
links.len() as f32 / total as f32
} else {
0.0
};
+2 -2
View File
@@ -9,12 +9,12 @@
use actix_web::{web, HttpRequest, HttpResponse};
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};
use serde_json::Value;
use tracing::{debug, error, info};
use crate::http_server::AppState;
use crate::query::{
SemanticRetriever, EntityResult, EdgeResult, HybridResult,
SemanticRetriever,
CommunityDetector, CommunityDetectionResult,
PathFinder, PathFindingResult,
FacetedSearch, AvailableFacets, FacetFilters,
@@ -5,8 +5,8 @@
use actix_web::{web, HttpRequest, HttpResponse};
use serde::{Deserialize, Serialize};
use crate::query::{
EntityLinker, InferenceEngine, QueryReasoner, Summarizer,
SummarizationStrategy, MentionLink,
EntityLinker, InferenceEngine, Summarizer,
SummarizationStrategy,
};
use crate::handlers::response_builder;
use tracing::{debug, info, error};
+1 -3
View File
@@ -6,9 +6,7 @@
use actix_web::{web, HttpRequest, HttpResponse};
use serde::{Deserialize, Serialize};
use serde_json::json;
use tokio::sync::mpsc;
use futures_util::stream::{self, StreamExt};
use crate::query::visualize_types::{VisualizeRequest, ReactFlowNode, ReactFlowEdge, NodeData, EdgeData, NodeStyle};
use crate::query::visualize_types::VisualizeRequest;
use crate::query::bfs_graph_traversal::BfsConfig;
use crate::query::force_directed_layout::ForceDirectedLayout;
use crate::http_server::AppState;
+24 -4
View File
@@ -46,8 +46,8 @@ pub struct IngestRecord {
}
// RBAC removed for MVP - will add after core ingest/query working
use crate::handlers::{
QueryParams, QueryParamsError, SearchMethod, build_search_response,
LearnParams, LearnParamsError, build_learn_response,
QueryParams,
LearnParams, build_learn_response,
visualize_handler, visualize_stream_handler, compact_handler
};
@@ -182,6 +182,7 @@ fn has_capability(claims: &JwtClaims, required_capability: &str) -> bool {
}
/// Extract client identifier from claims for rate limiting
#[allow(dead_code)]
fn extract_rate_limit_key(claims: &JwtClaims) -> String {
// Use subject (user/service ID) as rate limit key
claims.sub.clone()
@@ -291,6 +292,7 @@ pub async fn start_server(port: u16, api_key: String, database_url: &str) -> Res
.app_data(state.clone())
.wrap(Logger::default())
.route("/health", web::get().to(health_check))
.route("/ready", web::get().to(readiness_check))
.route("/metrics", web::get().to(crate::metrics::metrics_handler))
.route("/memory/ingest", web::post().to(ingest_handler))
.route("/memory/ingest/{ingest_id}", web::get().to(ingest_status))
@@ -362,6 +364,24 @@ pub async fn health_check(state: web::Data<AppState>) -> HttpResponse {
HttpResponse::Ok().json(json!({"status": "ok", "uptime_seconds": uptime}))
}
/// GET /ready — readiness probe (checks DB)
pub async fn readiness_check(state: web::Data<AppState>) -> HttpResponse {
let uptime = state.start_time.elapsed().as_secs();
let db_start = std::time::Instant::now();
match sqlx::query("SELECT 1").execute(&state.pool).await {
Ok(_) => {
crate::metrics::DEP_DB_UP.set(1);
crate::metrics::DEP_DB_LATENCY.observe(db_start.elapsed().as_secs_f64());
HttpResponse::Ok().json(json!({"status": "ready", "uptime_seconds": uptime, "db": "ok"}))
}
Err(e) => {
crate::metrics::DEP_DB_UP.set(0);
crate::metrics::HEALTH_CHECK_FAILURES.inc();
HttpResponse::ServiceUnavailable().json(json!({"status": "not_ready", "uptime_seconds": uptime, "db": format!("error: {}", e)}))
}
}
}
/// POST /memory/ingest — queue an ingest job
pub async fn ingest_handler(
req: HttpRequest,
@@ -385,7 +405,7 @@ pub async fn ingest_handler(
}
};
let user_id = &claims.sub;
let _user_id = &claims.sub;
if !has_capability(&claims, "memory:write") {
INGEST_AUTH_FAILURES.inc();
INGEST_ERRORS_TOTAL.inc();
@@ -1008,7 +1028,7 @@ pub async fn vault_browser_handler(
/// Helper: Build file tree for a project
async fn vault_project_tree(
project: &str,
state: &web::Data<AppState>,
_state: &web::Data<AppState>,
) -> HttpResponse {
let vault_dir = std::env::var("MEM_HOME").unwrap_or_else(|_| "/data".to_string());
let project_path = format!("{}/vault/{}", vault_dir, project);
+3 -3
View File
@@ -43,7 +43,7 @@ pub struct RankedCandidate {
pub struct HybridRetriever {
tfidf_scorer: Arc<mem_core::GlobalTfIdfScorer>,
semantic_scorer: Arc<mem_core::SemanticScorer>,
pipeline: ScoringPipeline,
_pipeline: ScoringPipeline,
min_tfidf_threshold: f32,
prefilter_limit: usize,
rrf_tfidf_weight: f32,
@@ -62,7 +62,7 @@ impl HybridRetriever {
Self {
tfidf_scorer,
semantic_scorer,
pipeline,
_pipeline: pipeline,
min_tfidf_threshold: 0.3,
prefilter_limit: 50,
rrf_tfidf_weight: 0.4,
@@ -71,7 +71,7 @@ impl HybridRetriever {
}
/// Decide retrieval route based on query and context
pub fn route_query(&self, query: &str, has_wiki_scope: bool, is_reference_query: bool) -> RetrievalRoute {
pub fn route_query(&self, _query: &str, has_wiki_scope: bool, is_reference_query: bool) -> RetrievalRoute {
if is_reference_query {
RetrievalRoute::ReferenceOnly
} else if has_wiki_scope {
+15 -3
View File
@@ -1,5 +1,5 @@
use anyhow::Result;
use mem_store::{MemoryL1, VectorStore, ChunkL0, EntityRepoOps, EdgeRepoOps};
use mem_store::{VectorStore, ChunkL0};
use mem_llm::EmbeddingsClient;
use mem_ingest::ingest_pipeline::{IngestPipeline, Episode};
use mem_ingest::entity_extractor::{WikiLinkFallbackExtractor, LlmEntityExtractor};
@@ -8,16 +8,17 @@ use mem_ingest::contradiction_detector::ContradictionHandler;
use sqlx::PgPool;
use uuid::Uuid;
use std::sync::Arc;
use pgvector::Vector;
/// Job status enumeration — type-safe alternative to magic strings
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(dead_code)]
pub enum JobStatus {
Processing,
Done,
DoneWithErrors,
}
#[allow(dead_code)]
impl JobStatus {
pub fn as_str(&self) -> &'static str {
match self {
@@ -66,6 +67,7 @@ mod tests {
/// Structured logging context for ingest operations — ensures consistent field names across all logs
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct IngestLogContext {
pub ingest_id: String,
pub project: String,
@@ -73,6 +75,7 @@ pub struct IngestLogContext {
pub source: String,
}
#[allow(dead_code)]
impl IngestLogContext {
fn new(ingest_id: &str, project: &str, record_id: &str, source: &str) -> Self {
Self {
@@ -86,16 +89,19 @@ impl IngestLogContext {
/// Job status store trait — abstracts database persistence of job status (enables mocking)
#[async_trait::async_trait]
#[allow(dead_code)]
pub trait JobStatusStore: Send + Sync {
/// Update job status in storage
async fn update_status(&self, ingest_id: &str, status: JobStatus) -> Result<()>;
}
/// PostgreSQL implementation of JobStatusStore
#[allow(dead_code)]
pub struct PgJobStatusStore {
pool: PgPool,
}
#[allow(dead_code)]
impl PgJobStatusStore {
pub fn new(pool: PgPool) -> Self {
Self { pool }
@@ -116,6 +122,7 @@ impl JobStatusStore for PgJobStatusStore {
/// Ingest worker — processes queued records through entity/fact extraction pipeline
#[allow(dead_code)]
pub struct IngestWorker {
pool: PgPool,
vector_store: Arc<VectorStore>,
@@ -124,6 +131,7 @@ pub struct IngestWorker {
job_status_store: Arc<dyn JobStatusStore>,
}
#[allow(dead_code)]
impl IngestWorker {
/// Create worker with full ingest pipeline
pub fn new(
@@ -308,7 +316,7 @@ impl IngestWorker {
/// Process a single chunk
pub async fn process_chunk(&self, project: &str, query_id: &str, content: &str, source: &str) -> Result<()> {
let embedding = self.embeddings.embed_one(content).await?;
let _embedding = self.embeddings.embed_one(content).await?;
let chunk = ChunkL0 {
id: Uuid::new_v4(),
project: project.to_string(),
@@ -323,6 +331,7 @@ impl IngestWorker {
}
/// Extract wiki links from text (e.g., [[Kubernetes]] -> "Kubernetes")
#[allow(dead_code)]
fn extract_wiki_links(text: &str) -> Vec<String> {
let mut links = Vec::new();
let mut chars = text.chars().peekable();
@@ -348,6 +357,7 @@ fn extract_wiki_links(text: &str) -> Vec<String> {
/// Returns Ok(true) if saved, Ok(false) if skipped, Err if fatal error
/// Save entity with embeddings (RAG-006)
/// Embeds name + summary before persisting, so semantic search can find entities.
#[allow(dead_code)]
async fn save_entity_with_embedding(
pool: &PgPool,
embeddings: &EmbeddingsClient,
@@ -440,6 +450,7 @@ async fn save_entity_with_embedding(
/// Save edge with fact embedding (RAG-006)
/// Embeds fact text before persisting, so semantic search can find edges.
#[allow(dead_code)]
async fn save_edge_with_embedding(
pool: &PgPool,
embeddings: &EmbeddingsClient,
@@ -509,6 +520,7 @@ async fn save_edge_with_embedding(
// Legacy save functions kept for backward compatibility but unused
#[allow(dead_code)]
#[allow(dead_code)]
async fn save_edge_to_db(pool: &PgPool, edge: &mem_core::edge::Edge) -> Result<()> {
let result = sqlx::query(
"INSERT INTO memory_edge (id, project_id, source_id, target_id, relation_type, fact, t_valid, t_invalid, t_created, confidence)
+1 -1
View File
@@ -357,7 +357,7 @@ async fn cmd_verify(
check_db,
check_log,
log_dir,
format,
_format: format,
};
let verifier = verify::Verifier::new(database_url).await?;
+8 -7
View File
@@ -105,14 +105,14 @@ impl Histogram {
/// Labeled counter (key = label combination string)
pub struct LabeledCounter {
values: Mutex<HashMap<String, u64>>,
name: &'static str,
help: &'static str,
label_names: &'static [&'static str],
_name: &'static str,
_help: &'static str,
_label_names: &'static [&'static str],
}
impl LabeledCounter {
pub fn new(name: &'static str, help: &'static str, label_names: &'static [&'static str]) -> Self {
Self { values: Mutex::new(HashMap::new()), name, help, label_names }
Self { values: Mutex::new(HashMap::new()), _name: name, _help: help, _label_names: label_names }
}
pub fn inc(&self, labels: &[&str]) {
let key = labels.join(",");
@@ -613,16 +613,17 @@ pub fn render_metrics() -> String {
}
/// Render a labeled counter in Prometheus format
#[allow(dead_code)]
fn render_labeled_counter(out: &mut String, lc: &LabeledCounter) {
let map = lc.values.lock().unwrap();
if map.is_empty() { return; }
out.push_str(&format!("# HELP {} {}\n# TYPE {} counter\n", lc.name, lc.help, lc.name));
out.push_str(&format!("# HELP {} {}\n# TYPE {} counter\n", lc._name, lc._help, lc._name));
for (key, val) in map.iter() {
let parts: Vec<&str> = key.split(',').collect();
let labels: Vec<String> = lc.label_names.iter().zip(parts.iter())
let labels: Vec<String> = lc._label_names.iter().zip(parts.iter())
.map(|(name, val)| format!("{}=\"{}\"", name, val))
.collect();
out.push_str(&format!("{}{{{}}} {}\n", lc.name, labels.join(","), val));
out.push_str(&format!("{}{{{}}} {}\n", lc._name, labels.join(","), val));
}
}
+4 -4
View File
@@ -22,8 +22,8 @@ use crate::metrics;
#[derive(Debug, Clone)]
pub struct MetricsSnapshot {
counters: HashMap<&'static str, u64>,
gauges: HashMap<&'static str, u64>,
gauges_f64: HashMap<&'static str, f64>,
_gauges: HashMap<&'static str, u64>,
_gauges_f64: HashMap<&'static str, f64>,
histogram_counts: HashMap<&'static str, u64>,
}
@@ -126,7 +126,7 @@ impl MetricsSnapshot {
counters.insert("memory_db_queries_total", metrics::DB_QUERY_TOTAL.get());
counters.insert("memory_db_query_errors_total", metrics::DB_QUERY_ERRORS.get());
Self { counters, gauges, gauges_f64, histogram_counts }
Self { counters, _gauges: gauges, _gauges_f64: gauges_f64, histogram_counts }
}
/// Assert a counter increased by exactly `expected` since snapshot
@@ -316,7 +316,7 @@ mod tests {
let snap = MetricsSnapshot::capture();
assert!(snap.counters.contains_key("memory_ingest_requests_total"));
assert!(snap.counters.contains_key("memory_query_requests_total"));
assert!(snap.gauges.contains_key("memory_ingest_in_flight"));
assert!(snap._gauges.contains_key("memory_ingest_in_flight"));
assert!(snap.histogram_counts.contains_key("memory_ingest_duration_seconds"));
}
@@ -6,7 +6,6 @@
use anyhow::{anyhow, Result};
use sha2::{Digest, Sha256};
use sqlx::PgPool;
use uuid::Uuid;
use pgvector::Vector;
use std::sync::Arc;
// OpenSearchClient removed (issue #56). Stub for compilation.
+1 -1
View File
@@ -8,7 +8,7 @@
//! DRY: Reuses score types from mem_core
use serde::{Deserialize, Serialize};
use tracing::{debug, info};
use tracing::info;
/// Answer validation configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -3,9 +3,8 @@
/// Performs breadth-first search on memory_entity + memory_edge tables,
/// returning a subgraph for visualization.
use std::collections::{HashMap, VecDeque};
use std::collections::VecDeque;
use serde::{Deserialize, Serialize};
use chrono::{DateTime, Utc};
use sqlx::{Pool, Postgres, Row};
/// A node in the traversal result
+5 -5
View File
@@ -6,7 +6,7 @@
use std::collections::{HashMap, HashSet};
use sqlx::PgPool;
use serde::{Deserialize, Serialize};
use tracing::{debug, warn};
use tracing::debug;
/// Result of linking a text mention to an entity
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
@@ -89,12 +89,12 @@ pub struct CoreferenceCluster {
/// Entity Linking Engine
pub struct EntityLinker {
pool: PgPool,
_pool: PgPool,
}
impl EntityLinker {
pub fn new(pool: PgPool) -> Self {
EntityLinker { pool }
EntityLinker { _pool: pool }
}
/// Link mentions in text to existing entities
@@ -242,7 +242,7 @@ impl EntityLinker {
let mut result = Vec::new();
for (entity_id, mentions) in clusters {
if let Some(entity) = entities.iter().find(|e| e.id == entity_id) {
if let Some(_entity) = entities.iter().find(|e| e.id == entity_id) {
let unique_mentions: Vec<_> = mentions.iter().cloned().collect::<HashSet<_>>().into_iter().collect();
result.push(CoreferenceCluster {
entity_id: entity_id.clone(),
@@ -353,7 +353,7 @@ impl EntityLinker {
}
/// Fetch all entities for a project
async fn fetch_entities(&self, project_id: &str) -> Result<Vec<EntityInfo>, String> {
async fn fetch_entities(&self, _project_id: &str) -> Result<Vec<EntityInfo>, String> {
// Stub: would query database
// For now, return empty
Ok(vec![])
+1 -2
View File
@@ -6,7 +6,6 @@
use chrono::{DateTime, Timelike, Utc};
use serde::{Deserialize, Serialize};
use sqlx::{Pool, Postgres};
use std::collections::HashMap;
use tracing::{debug, info};
/// A single facet (filterable dimension)
@@ -88,7 +87,7 @@ impl FacetedSearch {
limit: usize,
) -> Result<AvailableFacets, String> {
let limit = limit.max(5).min(50);
let start_time = std::time::Instant::now();
let _start_time = std::time::Instant::now();
debug!("Discovering facets for {}, limit={}", search_type, limit);
@@ -4,7 +4,7 @@
/// node positions in 2D space suitable for React Flow visualization.
use serde::{Deserialize, Serialize};
use super::bfs_graph_traversal::{GraphData, TraversalNode, TraversalEdge};
use super::bfs_graph_traversal::{GraphData, TraversalNode};
/// 2D position (X, Y coordinates)
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
@@ -184,8 +184,8 @@ impl ForceDirectedLayout {
let dist = dist_sq.sqrt();
let force = charge / dist_sq;
let fx = (force * dx / dist);
let fy = (force * dy / dist);
let fx = force * dx / dist;
let fy = force * dy / dist;
(-fx, -fy) // Negative = repulsive
}
@@ -199,8 +199,8 @@ impl ForceDirectedLayout {
let displacement = dist - link_distance;
let force = 0.1 * displacement; // Spring constant
let fx = (force * dx / dist);
let fy = (force * dy / dist);
let fx = force * dx / dist;
let fy = force * dy / dist;
(fx, fy) // Positive = attractive
}
+5 -6
View File
@@ -8,7 +8,6 @@ use std::pin::Pin;
use std::future::Future;
use sqlx::PgPool;
use serde::{Deserialize, Serialize};
use tracing::{debug, warn};
/// Inference rule
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -91,13 +90,13 @@ pub struct ReachableEntity {
/// Inference Engine
pub struct InferenceEngine {
pool: PgPool,
_pool: PgPool,
rules: Vec<InferenceRule>,
}
impl InferenceEngine {
pub fn new(pool: PgPool, rules: Vec<InferenceRule>) -> Self {
InferenceEngine { pool, rules }
InferenceEngine { _pool: pool, rules }
}
/// Perform rule-based inference
@@ -287,8 +286,8 @@ impl InferenceEngine {
/// Fetch edges from entity
async fn fetch_entity_edges(
&self,
entity_id: &str,
project_id: &str,
_entity_id: &str,
_project_id: &str,
) -> Result<Vec<EdgeInfo>, String> {
// Stub: would query database
Ok(vec![])
@@ -359,7 +358,7 @@ impl InferenceEngine {
/// Internal edge info
struct EdgeInfo {
source_id: String,
_source_id: String,
target_id: String,
target_name: String,
relation_type: String,
+5 -5
View File
@@ -47,7 +47,7 @@ pub struct PathFindingResult {
/// Edge representation for path finding
#[derive(Debug, Clone)]
struct GraphEdge {
from_id: String,
_from_id: String,
to_id: String,
relation_type: String,
confidence: f32,
@@ -396,14 +396,14 @@ impl PathFinder {
// Normalize direction: always point forward from input entity
if source == entity_id {
GraphEdge {
from_id: source,
_from_id: source,
to_id: target,
relation_type: rel_type,
confidence: conf.max(0.0).min(1.0),
}
} else {
GraphEdge {
from_id: target,
_from_id: target,
to_id: source,
relation_type: format!("{}(reverse)", rel_type),
confidence: conf.max(0.0).min(1.0),
@@ -580,13 +580,13 @@ mod tests {
#[test]
fn test_edge_representation() {
let edge = GraphEdge {
from_id: "e1".to_string(),
_from_id: "e1".to_string(),
to_id: "e2".to_string(),
relation_type: "related".to_string(),
confidence: 0.85,
};
assert_eq!(edge.from_id, "e1");
assert_eq!(edge._from_id, "e1");
assert_eq!(edge.to_id, "e2");
assert!(edge.confidence >= 0.0 && edge.confidence <= 1.0);
}
+4 -6
View File
@@ -3,10 +3,8 @@
//! Complex question decomposition, multi-hop reasoning, constraint satisfaction,
//! and answer validation.
use std::collections::HashMap;
use sqlx::PgPool;
use serde::{Deserialize, Serialize};
use tracing::{debug, warn};
/// Question type/intent
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
@@ -108,12 +106,12 @@ pub struct ReasonedAnswer {
/// Query Reasoner
pub struct QueryReasoner {
pool: PgPool,
_pool: PgPool,
}
impl QueryReasoner {
pub fn new(pool: PgPool) -> Self {
QueryReasoner { pool }
QueryReasoner { _pool: pool }
}
/// Decompose complex question into sub-queries
@@ -122,7 +120,7 @@ impl QueryReasoner {
return Ok(vec![]);
}
let question_lower = question.to_lowercase();
let _question_lower = question.to_lowercase();
let question_type = self.classify_question(question);
let mut sub_queries = Vec::new();
@@ -399,7 +397,7 @@ impl QueryReasoner {
let mut explanation = format!("Found {} answer(s) through {} reasoning step(s): ", answers.len(), steps.len());
for (idx, step) in steps.iter().enumerate() {
for (_idx, step) in steps.iter().enumerate() {
explanation.push_str(&format!(
"Step {}: {} (confidence: {:.2}, {} constraints satisfied). ",
step.step_id,
@@ -9,7 +9,6 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use tracing::{debug, info};
/// Temporal query configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
-10
View File
@@ -1,13 +1,3 @@
/// Advanced Query Filtering: Scope, filtering, and refinement
///
/// Provides:
/// - Project scoping (memory isolation)
/// - Level filtering (L1, L2, Reference)
/// - Category filtering (Error, Solution, etc.)
/// - Time-based filtering (recency)
/// - Tag/keyword filtering
use anyhow::Result;
use std::collections::HashSet;
use chrono::{DateTime, Utc, Duration};
+3 -4
View File
@@ -11,12 +11,11 @@
use anyhow::Result;
use std::collections::HashMap;
use std::sync::Arc;
use mem_core::DocumentScorer;
use crate::hybrid_retrieval::{HybridRetriever, RetrievalRoute, WikiScopedFilter, RankedCandidate};
use crate::hybrid_retrieval::HybridRetriever;
use crate::chunk_optimizer::{ChunkOptimizer, OptimizableChunk, SelectionMetrics};
use crate::chunk_metadata::{MetadataExtractor, MetadataBooster, QueryIntent};
use crate::cache_alignment::{KvCacheAligner, CachedChunk, CacheLocalityAnalyzer, RetrievalProfiler};
use crate::cache_alignment::{KvCacheAligner, CachedChunk, RetrievalProfiler};
/// Complete query result with all metadata
#[derive(Debug, Clone)]
@@ -190,7 +189,7 @@ impl QueryOrchestrator {
// Step 8: Build optimized chunks with all metadata
let mut optimized_chunks = Vec::new();
for (i, chunk) in selected_opt.iter().enumerate() {
for (_i, chunk) in selected_opt.iter().enumerate() {
let slot = slots.iter().find(|(id, _)| id == &chunk.id).map(|(_, s)| *s).unwrap_or(0);
let metadata = MetadataExtractor::extract(&chunk.id, &chunk.text);
+4 -4
View File
@@ -15,9 +15,9 @@ use std::collections::HashMap;
use std::sync::Arc;
use mem_ingest::wiki_link::{WikiLinkGraph, WikiLinkParser};
use mem_core::{DocumentScorer, GlobalTfIdfScorer, SemanticScorer};
use mem_core::{GlobalTfIdfScorer, SemanticScorer};
use crate::hybrid_retrieval::{HybridRetriever, RetrievalRoute, WikiScopedFilter, RankedCandidate};
use crate::hybrid_retrieval::{HybridRetriever, RetrievalRoute, WikiScopedFilter};
use crate::chunk_optimizer::{ChunkOptimizer, OptimizableChunk, SelectionMetrics};
/// Query routing configuration
@@ -74,7 +74,7 @@ pub struct SelectedChunk {
/// Query Router: end-to-end Phase 3+4 pipeline
pub struct QueryRouter {
wiki_filter: WikiScopedFilter,
_wiki_filter: WikiScopedFilter,
retriever: HybridRetriever,
optimizer: ChunkOptimizer,
config: RouterConfig,
@@ -95,7 +95,7 @@ impl QueryRouter {
);
Self {
wiki_filter,
_wiki_filter: wiki_filter,
retriever,
optimizer,
config,
+1 -1
View File
@@ -11,7 +11,7 @@ use anyhow::Result;
use super::access_evaluator::{AccessEvaluator, FilterResult, HasResourceMeta};
use super::role_provider::RoleProvider;
use super::types::{AccessDecision, Claims, DenyReason, ResourceMeta, Verb};
use super::types::{AccessDecision, Claims, ResourceMeta, Verb};
// ============================================================================
// Audit Logger
+2 -2
View File
@@ -6,7 +6,7 @@
/// - OwnerScope: resource.owner == claims.sub?
/// - GroupScope: user in required groups?
use super::types::{AccessScope, Claims, DenyReason, OwnerConstraint, ResourceMeta, Visibility};
use super::types::{AccessScope, Claims, DenyReason, OwnerConstraint, ResourceMeta};
// ============================================================================
// Trait
@@ -247,7 +247,7 @@ impl Default for CompositeScopeChecker {
#[cfg(test)]
mod tests {
use super::*;
use crate::rbac::types::ResourceType;
use crate::rbac::types::{ResourceType, Visibility};
fn test_claims() -> Claims {
Claims::new("alice")
-1
View File
@@ -7,7 +7,6 @@
/// - ResourceMeta: metadata attached to each document/wiki entry
use serde::{Deserialize, Serialize};
use std::collections::HashSet;
// ============================================================================
// Verbs
+1 -2
View File
@@ -4,9 +4,8 @@
//! Uses LLM (Qwen-7B or similar) to judge if retrieved results are relevant.
//! Tracks precision, recall, F1 via Prometheus metrics.
use anyhow::Result;
use serde::{Deserialize, Serialize};
use tracing::{debug, error};
use tracing::debug;
use crate::metrics;
-10
View File
@@ -1,13 +1,3 @@
/// Result Compressor: Optimize response size without losing essential information
///
/// Strategies:
/// - Truncate long texts to summary
/// - Extract key sentences
/// - Remove redundant metadata
/// - Compress to multiple formats (JSON, msgpack, CBOR)
/// - Progressive disclosure (compact by default, expand on demand)
use anyhow::Result;
use serde::{Deserialize, Serialize};
/// Compression strategy
+8 -8
View File
@@ -1,10 +1,10 @@
use anyhow::{anyhow, Result};
use anyhow::Result;
use std::collections::{HashMap, HashSet};
use std::fs;
use std::path::{Path, PathBuf};
use serde::{Serialize, Deserialize};
use mem_store::{PgRepo, Level};
use mem_store::PgRepo;
/// Memory record from log
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -39,7 +39,7 @@ pub struct VerifyOpts {
pub check_db: bool,
pub check_log: bool,
pub log_dir: Option<PathBuf>,
pub format: OutputFormat,
pub _format: OutputFormat,
}
#[derive(Debug, Clone, Copy)]
@@ -69,13 +69,13 @@ pub struct VerificationResult {
}
pub struct Verifier {
repo: PgRepo,
_repo: PgRepo,
}
impl Verifier {
pub async fn new(db_url: &str) -> Result<Self> {
let repo = PgRepo::connect(db_url).await?;
Ok(Self { repo })
Ok(Self { _repo: repo })
}
/// Run all verifications
@@ -136,7 +136,7 @@ impl Verifier {
let mut evidence_gate_count = 0;
let mut evidence_records = 0;
for (line_num, memory) in memories.iter().enumerate() {
for (_line_num, memory) in memories.iter().enumerate() {
let sha = Self::memory_sha(&memory.text);
memory_map.insert(sha.clone(), memory);
level_map.insert(sha.clone(), memory.level.clone());
@@ -188,7 +188,7 @@ impl Verifier {
}
// Invariant 2: Every parent sha resolves to a memory that exists
for (sha, parents) in &memory_parents {
for (_sha, parents) in &memory_parents {
for parent_sha in parents {
if !memory_map.contains_key(parent_sha) {
violations.push(Violation {
@@ -206,7 +206,7 @@ impl Verifier {
// Invariant 3: Every evidence sha appears as a parent of at least one memory
for evidence_sha in &evidence_shas {
let mut is_cited = false;
for (sha, parents) in &memory_parents {
for (_sha, parents) in &memory_parents {
if parents.contains(evidence_sha) {
is_cited = true;
break;
+2 -2
View File
@@ -12,7 +12,7 @@ use mem_ingest::OptimizationMetrics;
/// Memory record from log (local copy for rebuild purposes)
#[derive(Debug, Clone, Serialize, Deserialize)]
struct MemoryRecord {
pub struct MemoryRecord {
pub level: String,
pub project: String,
pub query_id: Option<String>,
@@ -25,7 +25,7 @@ struct MemoryRecord {
/// Parent reference for provenance
#[derive(Debug, Clone, Serialize, Deserialize)]
struct MemoryParent {
pub struct MemoryParent {
pub source: String,
pub t: i32,
pub description: Option<String>,
+15
View File
@@ -0,0 +1,15 @@
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: poimen-memory
namespace: poimen
labels:
app.kubernetes.io/name: poimen-memory
spec:
selector:
matchLabels:
app.kubernetes.io/name: poimen-memory
endpoints:
- port: http
path: /metrics
interval: 30s