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
144 lines
5.2 KiB
Rust
144 lines
5.2 KiB
Rust
//! End-to-end coverage for the `ctx_compose` task composer.
|
|
//!
|
|
//! The library unit tests only cover keyword extraction; these exercise the
|
|
//! full `handle()` path (semantic ranking + exact match + symbol body) and the
|
|
//! H1 hardening: the semantic stage must never stall the call beyond its budget.
|
|
|
|
use std::sync::Mutex;
|
|
use std::time::{Duration, Instant};
|
|
|
|
use lean_ctx::tools::CrpMode;
|
|
use lean_ctx::tools::ctx_compose;
|
|
|
|
/// `LEAN_CTX_COMPOSE_BUDGET_MS` is process-global; serialize tests that set it.
|
|
static ENV_GUARD: Mutex<()> = Mutex::new(());
|
|
|
|
fn write_corpus() -> tempfile::TempDir {
|
|
let dir = tempfile::tempdir().unwrap();
|
|
std::fs::write(
|
|
dir.path().join("auth.rs"),
|
|
"pub fn authenticate_user(token: &str) -> bool {\n \
|
|
validate_token(token) && !token.is_empty()\n}\n\n\
|
|
fn validate_token(token: &str) -> bool {\n token.len() > 8\n}\n",
|
|
)
|
|
.unwrap();
|
|
std::fs::write(
|
|
dir.path().join("config.rs"),
|
|
"pub fn parse_config(path: &str) -> String {\n \
|
|
std::fs::read_to_string(path).unwrap_or_default()\n}\n",
|
|
)
|
|
.unwrap();
|
|
dir
|
|
}
|
|
|
|
#[test]
|
|
fn compose_returns_all_sections_with_symbol_body() {
|
|
let _guard = ENV_GUARD
|
|
.lock()
|
|
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
|
// TODO: Audit that the environment access only happens in single-threaded code.
|
|
unsafe { std::env::remove_var("LEAN_CTX_COMPOSE_BUDGET_MS") };
|
|
let dir = write_corpus();
|
|
|
|
let (out, tokens) = ctx_compose::handle(
|
|
"how does authenticate_user validate the token",
|
|
&dir.path().to_string_lossy(),
|
|
CrpMode::Off,
|
|
);
|
|
|
|
assert!(out.contains("TASK:"), "must echo the task header");
|
|
assert!(
|
|
out.contains("## Ranked files (semantic)"),
|
|
"must contain the semantic ranking section"
|
|
);
|
|
assert!(
|
|
out.contains("## Exact matches"),
|
|
"must contain the exact-match section"
|
|
);
|
|
assert!(
|
|
out.contains("authenticate_user"),
|
|
"exact matches / symbol body must surface the queried symbol:\n{out}"
|
|
);
|
|
assert!(tokens > 0, "token count must be reported");
|
|
}
|
|
|
|
#[test]
|
|
fn compose_degrades_under_tight_budget_without_stalling() {
|
|
let _guard = ENV_GUARD
|
|
.lock()
|
|
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
|
// A 1 ms budget guarantees the semantic worker cannot finish in time, so the
|
|
// call must degrade gracefully instead of blocking on the (cold) build.
|
|
// TODO: Audit that the environment access only happens in single-threaded code.
|
|
unsafe { std::env::set_var("LEAN_CTX_COMPOSE_BUDGET_MS", "1") };
|
|
let dir = write_corpus();
|
|
|
|
let start = Instant::now();
|
|
let (out, _tokens) = ctx_compose::handle(
|
|
"how does authenticate_user validate the token",
|
|
&dir.path().to_string_lossy(),
|
|
CrpMode::Off,
|
|
);
|
|
let elapsed = start.elapsed();
|
|
// TODO: Audit that the environment access only happens in single-threaded code.
|
|
unsafe { std::env::remove_var("LEAN_CTX_COMPOSE_BUDGET_MS") };
|
|
|
|
// The exact-match + symbol stages are synchronous and index-backed, so the
|
|
// whole call should still return promptly even when ranking is deferred.
|
|
assert!(
|
|
elapsed < Duration::from_secs(10),
|
|
"tight budget must not stall the call (took {elapsed:?})"
|
|
);
|
|
assert!(
|
|
out.contains("## Ranked files (semantic)"),
|
|
"section header is always present"
|
|
);
|
|
assert!(
|
|
out.contains("## Exact matches"),
|
|
"exact matches remain authoritative under degradation"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn compose_rejects_empty_task() {
|
|
let _guard = ENV_GUARD
|
|
.lock()
|
|
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
|
let (out, tokens) = ctx_compose::handle(" ", "/tmp", CrpMode::Off);
|
|
assert!(out.starts_with("ERROR"));
|
|
assert_eq!(tokens, 0);
|
|
}
|
|
|
|
#[test]
|
|
fn compose_surfaces_associative_neighbours() {
|
|
let _guard = ENV_GUARD
|
|
.lock()
|
|
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
|
// TODO: Audit that the environment access only happens in single-threaded code.
|
|
unsafe { std::env::remove_var("LEAN_CTX_COMPOSE_BUDGET_MS") };
|
|
// Generous graph budget so the (tiny) index build never times out here.
|
|
// TODO: Audit that the environment access only happens in single-threaded code.
|
|
unsafe { std::env::set_var("LEAN_CTX_COMPOSE_GRAPH_BUDGET_MS", "8000") };
|
|
let dir = write_corpus();
|
|
|
|
// `authenticate_user` lives in auth.rs; config.rs is a same-dir sibling, so
|
|
// the graph connects them and spreading activation from the auth.rs seed
|
|
// must surface config.rs as an associative neighbour.
|
|
let (out, _tokens) = ctx_compose::handle(
|
|
"explain authenticate_user",
|
|
&dir.path().to_string_lossy(),
|
|
CrpMode::Off,
|
|
);
|
|
// TODO: Audit that the environment access only happens in single-threaded code.
|
|
unsafe { std::env::remove_var("LEAN_CTX_COMPOSE_GRAPH_BUDGET_MS") };
|
|
|
|
assert!(
|
|
out.contains("## Related (associative"),
|
|
"associative section should appear when the graph connects files:\n{out}"
|
|
);
|
|
assert!(
|
|
out.contains("config.rs"),
|
|
"the sibling neighbour should be surfaced via spreading activation:\n{out}"
|
|
);
|
|
}
|