Files
yvgude--lean-ctx/rust/tests/provider_wiring_proof.rs
T
wehub-resource-sync 26382a7ac6
CI / Clippy (push) Failing after 15m13s
CI / Test (ubuntu-latest) (push) Failing after 16m1s
CI / Test (macos-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Build (no embeddings / no ORT) (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Cookbook (Node) (push) Has been cancelled
CI / Pi Extension (Node) (push) Has been cancelled
CI / Rust SDK (lean-ctx-client) (push) Has been cancelled
CI / Embed SDK (lean-ctx-sdk) (push) Has been cancelled
CI / Python SDK (leanctx) (push) Has been cancelled
CI / Hermes Plugin (Python) (push) Has been cancelled
CI / SDK Conformance Matrix (push) Has been cancelled
CI / Coverage (push) Has been cancelled
CI / cargo-deny (push) Has been cancelled
CI / Adversarial Safety (push) Has been cancelled
CI / Benchmarks (push) Has been cancelled
CI / Output-Quality Gate (eval A/B) (push) Has been cancelled
CI / Documentation (push) Has been cancelled
CI / CI Green (push) Has been cancelled
JetBrains Plugin / Actionlint (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (rust) (push) Has been cancelled
JetBrains Plugin / Validation (push) Has been cancelled
JetBrains Plugin / Build (push) Has been cancelled
JetBrains Plugin / Test (push) Has been cancelled
Security Check / Security Scan (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:35:30 +08:00

546 lines
17 KiB
Rust

//! Wiring proof tests — verify that all provider pipeline connections
//! are actually functional, not just defined.
//!
//! Each test proves a specific connection point in the architecture:
//! Provider → Consolidation → BM25/Graph/Knowledge/Cache → Tool output
//!
//! These tests catch "functional silos" — code that exists but isn't
//! actually connected to the runtime.
use lean_ctx::core::bm25_index::{BM25Index, ChunkKind};
use lean_ctx::core::cache::SessionCache;
use lean_ctx::core::consolidation;
use lean_ctx::core::content_chunk::ContentChunk;
use lean_ctx::core::cross_source_edges;
use lean_ctx::core::cross_source_hints;
use lean_ctx::core::graph_index::IndexEdge;
use lean_ctx::core::knowledge::ProjectKnowledge;
use lean_ctx::core::knowledge_provider_extract;
use lean_ctx::core::providers::ContextProvider;
use lean_ctx::core::providers::mcp_bridge::McpBridgeProvider;
// ===========================================================================
// PROOF 1: consolidate() produces ALL artifact types (not just some)
// ===========================================================================
#[test]
fn proof_consolidate_produces_all_four_artifact_types() {
let chunks = vec![ContentChunk::from_provider(
"github",
"issues",
"1",
"Test bug",
ChunkKind::Issue,
"Bug in src/auth.rs".into(),
vec!["src/auth.rs".into()],
Some(serde_json::json!({"state": "open", "labels": ["bug"]})),
)];
let artifacts = consolidation::consolidate(&chunks);
assert!(
!artifacts.bm25_chunks.is_empty(),
"WIRING BROKEN: consolidate() produces no BM25 chunks"
);
assert!(
!artifacts.edges.is_empty(),
"WIRING BROKEN: consolidate() produces no graph edges"
);
assert!(
!artifacts.facts.is_empty(),
"WIRING BROKEN: consolidate() produces no knowledge facts"
);
assert!(
!artifacts.cache_entries.is_empty(),
"WIRING BROKEN: consolidate() produces no cache entries"
);
}
// ===========================================================================
// PROOF 2: apply_artifacts() actually writes to BM25 index
// ===========================================================================
#[test]
fn proof_apply_artifacts_writes_bm25() {
let chunks = vec![ContentChunk::from_provider(
"github",
"issues",
"42",
"Authentication crash",
ChunkKind::Issue,
"Auth crashes on login".into(),
vec![],
Some(serde_json::json!({"state": "open", "labels": ["bug"]})),
)];
let artifacts = consolidation::consolidate(&chunks);
let mut index = BM25Index::default();
let before = index.external_chunk_count();
consolidation::apply_artifacts(&artifacts, Some(&mut index), None, None);
let after = index.external_chunk_count();
assert!(
after > before,
"WIRING BROKEN: apply_artifacts did not write to BM25 (before={before}, after={after})"
);
let results = index.search("auth crashes login", 5);
assert!(
!results.is_empty(),
"WIRING BROKEN: BM25 search finds nothing after apply_artifacts"
);
}
// ===========================================================================
// PROOF 3: apply_artifacts() actually creates graph edges
// ===========================================================================
#[test]
fn proof_apply_artifacts_creates_graph_edges() {
let chunks = vec![ContentChunk::from_provider(
"github",
"issues",
"42",
"Auth bug",
ChunkKind::Issue,
"Bug in src/auth.rs".into(),
vec!["src/auth.rs".into()],
Some(serde_json::json!({"state": "open", "labels": ["bug"]})),
)];
let artifacts = consolidation::consolidate(&chunks);
let mut edges: Vec<IndexEdge> = Vec::new();
consolidation::apply_artifacts(&artifacts, None, Some(&mut edges), None);
assert!(
!edges.is_empty(),
"WIRING BROKEN: apply_artifacts did not create graph edges"
);
assert!(
edges
.iter()
.any(|e| e.to == "src/auth.rs" || e.from == "src/auth.rs"),
"WIRING BROKEN: edges don't reference the file from issue"
);
}
// ===========================================================================
// PROOF 4: Graph edges produce cross-source hints for ctx_read
// ===========================================================================
#[test]
fn proof_graph_edges_produce_hints_for_ctx_read() {
let chunks = vec![
ContentChunk::from_provider(
"github",
"issues",
"42",
"Auth bug",
ChunkKind::Issue,
"Bug in src/auth.rs".into(),
vec!["src/auth.rs".into()],
Some(serde_json::json!({"state": "open", "labels": ["bug"]})),
),
ContentChunk::from_provider(
"github",
"pull_requests",
"100",
"Fix auth",
ChunkKind::PullRequest,
"Fixes auth in src/auth.rs".into(),
vec!["src/auth.rs".into()],
Some(serde_json::json!({"state": "open"})),
),
];
let artifacts = consolidation::consolidate(&chunks);
let mut all_edges: Vec<IndexEdge> = Vec::new();
cross_source_edges::merge_edges(&mut all_edges, artifacts.edges);
let hints = cross_source_hints::hints_for_file("src/auth.rs", &all_edges, "/project");
assert!(
!hints.is_empty(),
"WIRING BROKEN: hints_for_file returns nothing for a file with linked issues"
);
assert!(
hints.iter().any(|h| h.source_uri.contains("42")),
"WIRING BROKEN: hints don't contain issue #42"
);
}
// ===========================================================================
// PROOF 5: Knowledge facts are extractable AND rememberable
// ===========================================================================
#[test]
fn proof_knowledge_facts_roundtrip() {
let chunks = vec![ContentChunk::from_provider(
"github",
"issues",
"42",
"Critical auth bug",
ChunkKind::Issue,
"Authentication fails on token refresh".into(),
vec!["src/auth.rs".into()],
Some(serde_json::json!({"state": "open", "labels": ["bug", "critical"]})),
)];
let facts = knowledge_provider_extract::extract_facts(&chunks);
assert!(
!facts.is_empty(),
"WIRING BROKEN: extract_facts produces no facts from provider chunks"
);
let mut knowledge = ProjectKnowledge::new("/tmp/wiring-proof-test");
let policy = lean_ctx::core::memory_policy::MemoryPolicy::default();
for fact in &facts {
knowledge.remember(
&fact.category,
&fact.key,
&fact.value,
"test-session",
fact.confidence,
&policy,
);
}
let recalled = knowledge.recall_by_category("known_bugs");
assert!(
!recalled.is_empty(),
"WIRING BROKEN: knowledge.recall_by_category returns nothing after remember()"
);
assert!(
recalled.iter().any(|f| f.value.contains("auth")),
"WIRING BROKEN: recalled facts don't match what was remembered"
);
}
// ===========================================================================
// PROOF 6: Session cache stores provider data with correct URIs
// ===========================================================================
#[test]
fn proof_cache_stores_provider_uris() {
let chunks = vec![ContentChunk::from_provider(
"github",
"issues",
"42",
"Auth bug",
ChunkKind::Issue,
"Bug description".into(),
vec![],
Some(serde_json::json!({"state": "open"})),
)];
let artifacts = consolidation::consolidate(&chunks);
let mut cache = SessionCache::new();
consolidation::apply_artifacts(&artifacts, None, None, Some(&mut cache));
let cached = cache.get("github://issues/42");
assert!(
cached.is_some(),
"WIRING BROKEN: cache.get() returns None for provider URI after apply_artifacts"
);
}
// ===========================================================================
// PROOF 7: BM25 search result formatting includes external attribution
// ===========================================================================
#[test]
fn proof_bm25_search_attributes_external_results() {
use lean_ctx::core::bm25_index::{SearchResult, format_search_results};
let results = vec![SearchResult {
chunk_idx: 0,
score: 0.9,
file_path: "github://issues/42".to_string(),
symbol_name: "Auth token expiry".to_string(),
kind: ChunkKind::Issue,
start_line: 0,
end_line: 0,
snippet: "Token expires too fast".to_string(),
}];
let formatted = format_search_results(&results, true);
assert!(
formatted.contains("[Issue]"),
"WIRING BROKEN: format_search_results doesn't show [Issue] for external results: {formatted}"
);
assert!(
formatted.contains("github://"),
"WIRING BROKEN: format_search_results doesn't show provider URI: {formatted}"
);
}
// ===========================================================================
// PROOF 8: MCP Bridge registration — HTTP and stdio both register
// ===========================================================================
#[test]
fn proof_mcp_bridge_http_registers_correctly() {
let bridge = McpBridgeProvider::new("my-kb", "http://localhost:8080");
assert_eq!(bridge.id(), "mcp:my-kb");
assert!(bridge.is_available());
assert!(bridge.supported_actions().contains(&"resources"));
assert!(bridge.supported_actions().contains(&"read_resource"));
}
#[test]
fn proof_mcp_bridge_stdio_registers_correctly() {
let bridge = McpBridgeProvider::new_stdio("local-server", "npx", &["my-mcp".into()]);
assert_eq!(bridge.id(), "mcp:local-server");
assert!(bridge.is_available());
let result = bridge.execute(
"resources",
&lean_ctx::core::providers::ProviderParams::default(),
);
assert!(
result.is_err(),
"Stdio bridge should error with clear message"
);
let err = result.unwrap_err();
assert!(
err.contains("stdio transport"),
"WIRING BROKEN: stdio error message unclear: {err}"
);
}
// ===========================================================================
// PROOF 9: Provider init registers from config
// ===========================================================================
#[test]
fn proof_init_registers_builtin_providers() {
lean_ctx::core::providers::init::init_builtin_providers();
let reg = lean_ctx::core::providers::registry::global_registry();
assert!(
reg.get("github").is_some(),
"WIRING BROKEN: GitHub provider not registered"
);
assert!(
reg.get("gitlab").is_some(),
"WIRING BROKEN: GitLab provider not registered"
);
assert!(
reg.get("jira").is_some(),
"WIRING BROKEN: Jira provider not registered"
);
assert!(
reg.get("postgres").is_some(),
"WIRING BROKEN: Postgres provider not registered"
);
}
// ===========================================================================
// PROOF 10: Config auto_index controls indexing behavior
// ===========================================================================
#[test]
fn proof_auto_index_config_default() {
let cfg = lean_ctx::core::config::Config::default();
assert!(
cfg.providers.auto_index,
"WIRING BROKEN: auto_index should default to true"
);
assert!(
cfg.providers.enabled,
"WIRING BROKEN: providers.enabled should default to true"
);
}
// ===========================================================================
// PROOF 11: End-to-end — provider data searchable after full pipeline
// ===========================================================================
#[test]
fn proof_end_to_end_provider_data_searchable() {
let chunks = vec![
ContentChunk::from_provider(
"github",
"issues",
"99",
"Memory leak in websocket handler",
ChunkKind::Issue,
"WebSocket connections leak memory when client disconnects abruptly".into(),
vec!["src/websocket.rs".into()],
Some(serde_json::json!({"state": "open", "labels": ["bug", "performance"]})),
),
ContentChunk::from_provider(
"jira",
"issues",
"PERF-42",
"Optimize database connection pooling",
ChunkKind::Ticket,
"Connection pool exhaustion under load".into(),
vec![],
Some(serde_json::json!({"state": "In Progress", "labels": ["performance"]})),
),
];
let artifacts = consolidation::consolidate(&chunks);
let mut index = BM25Index::default();
let mut edges: Vec<IndexEdge> = Vec::new();
let mut cache = SessionCache::new();
let result = consolidation::apply_artifacts(
&artifacts,
Some(&mut index),
Some(&mut edges),
Some(&mut cache),
);
// Search should find the websocket issue
let ws_results = index.search("websocket memory leak", 5);
assert!(
!ws_results.is_empty(),
"WIRING BROKEN: BM25 can't find 'websocket memory leak' after full pipeline"
);
// Search should find the Jira ticket
let db_results = index.search("database connection pool", 5);
assert!(
!db_results.is_empty(),
"WIRING BROKEN: BM25 can't find 'database connection pool' after full pipeline"
);
// Cross-source hints should work for the websocket file
let hints = cross_source_hints::hints_for_file("src/websocket.rs", &edges, "/project");
assert!(
!hints.is_empty(),
"WIRING BROKEN: No cross-source hints for src/websocket.rs after full pipeline"
);
// Knowledge should have extracted facts
let mut knowledge = ProjectKnowledge::new("/tmp/wiring-e2e-test");
let policy = lean_ctx::core::memory_policy::MemoryPolicy::default();
for fact in &artifacts.facts {
knowledge.remember(
&fact.category,
&fact.key,
&fact.value,
"test",
fact.confidence,
&policy,
);
}
let bugs = knowledge.recall_by_category("known_bugs");
assert!(
!bugs.is_empty(),
"WIRING BROKEN: No known_bugs facts after full pipeline"
);
// Cache should have entries
assert!(
result.cache_entries_stored > 0,
"WIRING BROKEN: No cache entries after full pipeline"
);
// Stats should be non-zero across ALL stores
assert!(
result.chunks_indexed > 0,
"WIRING BROKEN: chunks_indexed is 0"
);
assert!(
result.edges_created > 0,
"WIRING BROKEN: edges_created is 0"
);
assert!(
result.facts_extracted > 0,
"WIRING BROKEN: facts_extracted is 0"
);
}
// ===========================================================================
// PROOF 12: Multiple provider types produce distinct knowledge categories
// ===========================================================================
#[test]
fn proof_distinct_knowledge_categories_per_provider_type() {
let chunks = vec![
ContentChunk::from_provider(
"github",
"issues",
"1",
"Bug: crash on startup",
ChunkKind::Issue,
"App crashes".into(),
vec![],
Some(serde_json::json!({"state": "open", "labels": ["bug"]})),
),
ContentChunk::from_provider(
"github",
"issues",
"2",
"Feature: dark mode",
ChunkKind::Issue,
"Add dark mode".into(),
vec![],
Some(serde_json::json!({"state": "open", "labels": ["enhancement"]})),
),
ContentChunk::from_provider(
"github",
"pull_requests",
"10",
"Fix crash",
ChunkKind::PullRequest,
"Fixes the crash".into(),
vec![],
Some(serde_json::json!({"state": "merged"})),
),
ContentChunk::from_provider(
"postgres",
"schemas",
"users",
"public.users",
ChunkKind::DbSchema,
"CREATE TABLE users (id serial)".into(),
vec![],
None,
),
ContentChunk::from_provider(
"confluence",
"wikis",
"deploy",
"Deploy Guide",
ChunkKind::WikiPage,
"How to deploy".into(),
vec![],
None,
),
];
let facts = knowledge_provider_extract::extract_facts(&chunks);
let categories: std::collections::HashSet<&str> =
facts.iter().map(|f| f.category.as_str()).collect();
assert!(
categories.contains("known_bugs"),
"Missing known_bugs category"
);
assert!(
categories.contains("known_features"),
"Missing known_features category"
);
assert!(
categories.contains("recent_changes"),
"Missing recent_changes category"
);
assert!(
categories.contains("data_model"),
"Missing data_model category"
);
assert!(
categories.contains("documentation"),
"Missing documentation category"
);
}