- 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:
@@ -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 }
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,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)]
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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("")) {
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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?;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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![])
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
/// - ResourceMeta: metadata attached to each document/wiki entry
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashSet;
|
||||
|
||||
// ============================================================================
|
||||
// Verbs
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>,
|
||||
|
||||
Reference in New Issue
Block a user