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