Files
yvgude--lean-ctx/rust/tests/power_user_worksession.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

766 lines
22 KiB
Rust

#![allow(clippy::await_holding_lock)]
use serde_json::json;
fn setup_project() -> (tempfile::TempDir, lean_ctx::engine::ContextEngine) {
let dir = tempfile::tempdir().expect("tempdir");
let project = dir.path().join("project");
std::fs::create_dir_all(&project).expect("create project");
std::fs::create_dir_all(project.join("src")).expect("create src");
std::fs::write(
project.join("src/main.rs"),
r#"fn main() {
let config = load_config();
println!("Running with {:?}", config);
}
fn load_config() -> Config {
Config { debug: false, port: 8080 }
}
#[derive(Debug)]
struct Config {
debug: bool,
port: u16,
}
fn helper_a() -> String {
"hello".to_string()
}
fn helper_b(x: i32) -> i32 {
x * 2
}
"#,
)
.expect("write main.rs");
std::fs::write(
project.join("src/lib.rs"),
r#"pub mod utils;
pub fn greet(name: &str) -> String {
format!("Hello, {name}!")
}
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
"#,
)
.expect("write lib.rs");
std::fs::create_dir_all(project.join("src/utils")).expect("create utils");
std::fs::write(
project.join("src/utils/mod.rs"),
r#"pub fn format_bytes(n: u64) -> String {
if n < 1024 {
format!("{n} B")
} else if n < 1024 * 1024 {
format!("{:.1} KB", n as f64 / 1024.0)
} else {
format!("{:.1} MB", n as f64 / (1024.0 * 1024.0))
}
}
"#,
)
.expect("write utils/mod.rs");
std::fs::write(
project.join("Cargo.toml"),
r#"[package]
name = "test-project"
version = "0.1.0"
edition = "2021"
"#,
)
.expect("write Cargo.toml");
std::fs::write(
project.join("README.md"),
"# Test Project\nA sample project.\n",
)
.expect("write README.md");
let data_dir = dir.path().join("data");
std::fs::create_dir_all(&data_dir).expect("create data dir");
unsafe {
std::env::set_var("LEAN_CTX_DATA_DIR", data_dir.to_string_lossy().to_string());
}
let engine = lean_ctx::engine::ContextEngine::with_project_root(&project);
(dir, engine)
}
// ── Phase 1: Setup & Orientation ───────────────────────────
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn phase1_session_task_and_overview() {
let _lock = lean_ctx::core::data_dir::test_env_lock();
let (_dir, engine) = setup_project();
let out = engine
.call_tool_text(
"ctx_session",
Some(json!({"action": "task", "content": "Implement caching layer"})),
)
.await
.expect("session task");
assert!(
out.contains("task") || out.contains("Task") || out.contains("set"),
"task output: {out}"
);
let overview = engine
.call_tool_text("ctx_overview", None)
.await
.expect("overview");
assert!(
overview.contains("src") || overview.contains("project"),
"overview should contain project structure: {overview}"
);
unsafe {
std::env::remove_var("LEAN_CTX_DATA_DIR");
}
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn phase1_tree_depth() {
let _lock = lean_ctx::core::data_dir::test_env_lock();
let (_dir, engine) = setup_project();
let tree = engine
.call_tool_text("ctx_tree", Some(json!({"depth": 3})))
.await
.expect("tree");
assert!(tree.contains("src"), "tree should show src: {tree}");
assert!(
tree.contains("Cargo.toml") || tree.contains("main.rs"),
"tree should show files: {tree}"
);
unsafe {
std::env::remove_var("LEAN_CTX_DATA_DIR");
}
}
// ── Phase 2: Codebase Research (Read Modes) ────────────────
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn phase2_read_full_and_cache_stub() {
let _lock = lean_ctx::core::data_dir::test_env_lock();
let (_dir, engine) = setup_project();
let project = _dir.path().join("project");
let main_path = project.join("src/main.rs").to_string_lossy().to_string();
let full1 = engine
.call_tool_text("ctx_read", Some(json!({"path": main_path, "mode": "full"})))
.await
.expect("full read 1");
assert!(
full1.contains("load_config"),
"full read should contain fn body: {full1}"
);
let full2 = engine
.call_tool_text("ctx_read", Some(json!({"path": main_path, "mode": "full"})))
.await
.expect("full read 2");
assert!(
full2.len() <= full1.len(),
"re-read should be stub or same size (full1={}, full2={})",
full1.len(),
full2.len()
);
unsafe {
std::env::remove_var("LEAN_CTX_DATA_DIR");
}
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn phase2_read_signatures() {
let _lock = lean_ctx::core::data_dir::test_env_lock();
let (_dir, engine) = setup_project();
let project = _dir.path().join("project");
let main_path = project.join("src/main.rs").to_string_lossy().to_string();
let sigs = engine
.call_tool_text(
"ctx_read",
Some(json!({"path": main_path, "mode": "signatures"})),
)
.await
.expect("signatures read");
assert!(
sigs.contains("fn main") || sigs.contains("load_config") || sigs.contains("helper_a"),
"signatures should contain fn names: {sigs}"
);
unsafe {
std::env::remove_var("LEAN_CTX_DATA_DIR");
}
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn phase2_read_map() {
let _lock = lean_ctx::core::data_dir::test_env_lock();
let (_dir, engine) = setup_project();
let project = _dir.path().join("project");
let lib_path = project.join("src/lib.rs").to_string_lossy().to_string();
let map = engine
.call_tool_text("ctx_read", Some(json!({"path": lib_path, "mode": "map"})))
.await
.expect("map read");
assert!(!map.is_empty(), "map should not be empty");
unsafe {
std::env::remove_var("LEAN_CTX_DATA_DIR");
}
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn phase2_read_lines_range() {
let _lock = lean_ctx::core::data_dir::test_env_lock();
let (_dir, engine) = setup_project();
let project = _dir.path().join("project");
let main_path = project.join("src/main.rs").to_string_lossy().to_string();
let lines = engine
.call_tool_text(
"ctx_read",
Some(json!({"path": main_path, "mode": "lines:1-5"})),
)
.await
.expect("lines read");
assert!(
lines.contains("fn main"),
"lines 1-5 should contain fn main: {lines}"
);
unsafe {
std::env::remove_var("LEAN_CTX_DATA_DIR");
}
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn phase2_read_auto() {
let _lock = lean_ctx::core::data_dir::test_env_lock();
let (_dir, engine) = setup_project();
let project = _dir.path().join("project");
let main_path = project.join("src/main.rs").to_string_lossy().to_string();
let auto = engine
.call_tool_text("ctx_read", Some(json!({"path": main_path, "mode": "auto"})))
.await
.expect("auto read");
assert!(!auto.is_empty(), "auto mode should return content");
unsafe {
std::env::remove_var("LEAN_CTX_DATA_DIR");
}
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn phase2_read_aggressive() {
let _lock = lean_ctx::core::data_dir::test_env_lock();
let (_dir, engine) = setup_project();
let project = _dir.path().join("project");
let main_path = project.join("src/main.rs").to_string_lossy().to_string();
let aggressive = engine
.call_tool_text(
"ctx_read",
Some(json!({"path": main_path, "mode": "aggressive"})),
)
.await
.expect("aggressive read");
assert!(
!aggressive.is_empty(),
"aggressive mode should return content"
);
unsafe {
std::env::remove_var("LEAN_CTX_DATA_DIR");
}
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn phase2_read_diff_after_edit() {
let _lock = lean_ctx::core::data_dir::test_env_lock();
let (_dir, engine) = setup_project();
let project = _dir.path().join("project");
let main_path = project.join("src/main.rs").to_string_lossy().to_string();
let _ = engine
.call_tool_text("ctx_read", Some(json!({"path": main_path, "mode": "full"})))
.await
.expect("initial read");
let content = std::fs::read_to_string(project.join("src/main.rs")).unwrap();
let modified = content.replace("debug: false", "debug: true");
std::fs::write(project.join("src/main.rs"), &modified).unwrap();
let diff = engine
.call_tool_text("ctx_read", Some(json!({"path": main_path, "mode": "diff"})))
.await
.expect("diff read");
assert!(
diff.contains("debug")
|| diff.contains("changed")
|| diff.contains("modified")
|| diff.contains("true"),
"diff should show changes: {diff}"
);
unsafe {
std::env::remove_var("LEAN_CTX_DATA_DIR");
}
}
// ── Phase 3: Code Search ───────────────────────────────────
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn phase3_search_regex() {
let _lock = lean_ctx::core::data_dir::test_env_lock();
let (_dir, engine) = setup_project();
let out = engine
.call_tool_text("ctx_search", Some(json!({"pattern": "fn main"})))
.await
.expect("search");
assert!(
out.contains("main") || out.contains("src/main.rs"),
"search should find fn main: {out}"
);
unsafe {
std::env::remove_var("LEAN_CTX_DATA_DIR");
}
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn phase3_search_with_path_filter() {
let _lock = lean_ctx::core::data_dir::test_env_lock();
let (_dir, engine) = setup_project();
let out = engine
.call_tool_text(
"ctx_search",
Some(json!({"pattern": "pub fn", "path": "src/utils"})),
)
.await
.expect("search with path");
assert!(
out.contains("format_bytes"),
"filtered search should find format_bytes: {out}"
);
unsafe {
std::env::remove_var("LEAN_CTX_DATA_DIR");
}
}
// ── Phase 4: Shell & Execution ─────────────────────────────
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn phase4_shell_echo() {
let _lock = lean_ctx::core::data_dir::test_env_lock();
let (_dir, engine) = setup_project();
let out = engine
.call_tool_text(
"ctx_shell",
Some(json!({"command": "echo hello-from-shell"})),
)
.await
.expect("shell echo");
assert!(
out.contains("hello-from-shell"),
"shell should contain echo output: {out}"
);
unsafe {
std::env::remove_var("LEAN_CTX_DATA_DIR");
}
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn phase4_shell_raw_mode() {
let _lock = lean_ctx::core::data_dir::test_env_lock();
let (_dir, engine) = setup_project();
let out = engine
.call_tool_text(
"ctx_shell",
Some(json!({"command": "echo raw-test-value", "raw": true})),
)
.await
.expect("shell raw");
assert!(
out.contains("raw-test-value"),
"raw shell should contain output: {out}"
);
unsafe {
std::env::remove_var("LEAN_CTX_DATA_DIR");
}
}
// ── Phase 5: Edit & Iteration ──────────────────────────────
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn phase5_edit_and_verify() {
let _lock = lean_ctx::core::data_dir::test_env_lock();
let (_dir, engine) = setup_project();
let project = _dir.path().join("project");
let lib_path = project.join("src/lib.rs").to_string_lossy().to_string();
let edit_result = engine
.call_tool_text(
"ctx_edit",
Some(json!({
"path": lib_path,
"old_string": "pub fn greet(name: &str) -> String {\n format!(\"Hello, {name}!\")\n}",
"new_string": "pub fn greet(name: &str) -> String {\n format!(\"Hi there, {name}!\")\n}",
})),
)
.await
.expect("edit");
assert!(
edit_result.contains("applied")
|| edit_result.contains("ok")
|| edit_result.contains("✓")
|| edit_result.contains("success")
|| !edit_result.is_empty(),
"edit should succeed: {edit_result}"
);
let content = std::fs::read_to_string(project.join("src/lib.rs")).unwrap();
assert!(
content.contains("Hi there"),
"file should contain edited text"
);
unsafe {
std::env::remove_var("LEAN_CTX_DATA_DIR");
}
}
// ── Phase 6: Context Management ────────────────────────────
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn phase6_compress_and_cache_status() {
let _lock = lean_ctx::core::data_dir::test_env_lock();
let (_dir, engine) = setup_project();
let project = _dir.path().join("project");
let main_path = project.join("src/main.rs").to_string_lossy().to_string();
let _ = engine
.call_tool_text("ctx_read", Some(json!({"path": main_path, "mode": "full"})))
.await
.expect("prime cache");
let compress = engine.call_tool_text("ctx_compress", None).await;
match compress {
Ok(out) => assert!(!out.is_empty(), "compress should return output"),
Err(e) => {
let msg = e.to_string();
assert!(
msg.contains("timeout") || msg.contains("timed out"),
"compress unexpected error: {msg}"
);
}
}
let cache = engine
.call_tool_text("ctx_cache", Some(json!({"action": "status"})))
.await
.expect("cache status");
let cache_lower = cache.to_lowercase();
assert!(
cache_lower.contains("cache")
|| cache_lower.contains("entries")
|| cache_lower.contains("file"),
"cache status should show info: {cache}"
);
unsafe {
std::env::remove_var("LEAN_CTX_DATA_DIR");
}
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn phase6_ledger_status() {
let _lock = lean_ctx::core::data_dir::test_env_lock();
let (_dir, engine) = setup_project();
let ledger = engine
.call_tool_text("ctx_ledger", Some(json!({"action": "status"})))
.await
.expect("ledger status");
assert!(!ledger.is_empty(), "ledger status should return output");
unsafe {
std::env::remove_var("LEAN_CTX_DATA_DIR");
}
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn phase6_dedup() {
let _lock = lean_ctx::core::data_dir::test_env_lock();
let (_dir, engine) = setup_project();
let project = _dir.path().join("project");
let main_path = project.join("src/main.rs").to_string_lossy().to_string();
let lib_path = project.join("src/lib.rs").to_string_lossy().to_string();
let _ = engine
.call_tool_text("ctx_read", Some(json!({"path": main_path, "mode": "full"})))
.await
.unwrap();
let _ = engine
.call_tool_text("ctx_read", Some(json!({"path": lib_path, "mode": "full"})))
.await
.unwrap();
let dedup = engine
.call_tool_text("ctx_dedup", None)
.await
.expect("dedup");
assert!(!dedup.is_empty(), "dedup should return output");
unsafe {
std::env::remove_var("LEAN_CTX_DATA_DIR");
}
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn phase6_plan() {
let _lock = lean_ctx::core::data_dir::test_env_lock();
let (_dir, engine) = setup_project();
let plan = engine
.call_tool_text(
"ctx_plan",
Some(json!({"task": "Add a caching layer to the Config struct"})),
)
.await
.expect("plan");
assert!(!plan.is_empty(), "plan should return output");
unsafe {
std::env::remove_var("LEAN_CTX_DATA_DIR");
}
}
// ── Phase 7: Knowledge & Session ───────────────────────────
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn phase7_knowledge_remember_and_recall() {
let _lock = lean_ctx::core::data_dir::test_env_lock();
let (_dir, engine) = setup_project();
let remember = engine
.call_tool_text(
"ctx_knowledge",
Some(json!({
"action": "remember",
"category": "architecture",
"key": "cache_strategy",
"value": "LRU with zstd compression, 128MB limit",
})),
)
.await
.expect("knowledge remember");
assert!(!remember.is_empty(), "remember should return confirmation");
let recall = engine
.call_tool_text(
"ctx_knowledge",
Some(json!({"action": "recall", "category": "architecture"})),
)
.await
.expect("knowledge recall");
assert!(
recall.contains("cache_strategy") || recall.contains("LRU"),
"recall should contain remembered fact: {recall}"
);
unsafe {
std::env::remove_var("LEAN_CTX_DATA_DIR");
}
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn phase7_knowledge_timeline_and_rooms() {
let _lock = lean_ctx::core::data_dir::test_env_lock();
let (_dir, engine) = setup_project();
let _ = engine
.call_tool_text(
"ctx_knowledge",
Some(json!({
"action": "remember",
"category": "decisions",
"key": "db_choice",
"value": "PostgreSQL for persistence",
})),
)
.await
.expect("remember decision");
let timeline = engine
.call_tool_text(
"ctx_knowledge",
Some(json!({"action": "timeline", "category": "decisions"})),
)
.await
.expect("timeline");
assert!(!timeline.is_empty(), "timeline should return entries");
let rooms = engine
.call_tool_text("ctx_knowledge", Some(json!({"action": "rooms"})))
.await
.expect("rooms");
assert!(
rooms.contains("decisions"),
"rooms should list the decisions category: {rooms}"
);
unsafe {
std::env::remove_var("LEAN_CTX_DATA_DIR");
}
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn phase7_session_finding_and_decision() {
let _lock = lean_ctx::core::data_dir::test_env_lock();
let (_dir, engine) = setup_project();
let finding = engine
.call_tool_text(
"ctx_session",
Some(json!({
"action": "finding",
"content": "Config struct lacks validation for port range",
})),
)
.await
.expect("session finding");
assert!(!finding.is_empty(), "finding should return confirmation");
let decision = engine
.call_tool_text(
"ctx_session",
Some(json!({
"action": "decision",
"content": "Use builder pattern for Config validation",
})),
)
.await
.expect("session decision");
assert!(!decision.is_empty(), "decision should return confirmation");
unsafe {
std::env::remove_var("LEAN_CTX_DATA_DIR");
}
}
// ── Phase 8: Multi-Agent Coordination ──────────────────────
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn phase8_agent_register_and_diary() {
let _lock = lean_ctx::core::data_dir::test_env_lock();
let (_dir, engine) = setup_project();
let reg = engine
.call_tool_text(
"ctx_agent",
Some(json!({
"action": "register",
"name": "backend-agent",
"role": "Implements API endpoints",
})),
)
.await
.expect("agent register");
assert!(!reg.is_empty(), "register should return confirmation");
let diary = engine
.call_tool_text(
"ctx_agent",
Some(json!({
"action": "diary",
"category": "progress",
"content": "Completed Config struct refactoring",
})),
)
.await
.expect("agent diary");
assert!(!diary.is_empty(), "diary should return confirmation");
unsafe {
std::env::remove_var("LEAN_CTX_DATA_DIR");
}
}
// ── Phase 9: Metrics & Verification ────────────────────────
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn phase9_metrics() {
let _lock = lean_ctx::core::data_dir::test_env_lock();
let (_dir, engine) = setup_project();
let project = _dir.path().join("project");
let main_path = project.join("src/main.rs").to_string_lossy().to_string();
let _ = engine
.call_tool_text("ctx_read", Some(json!({"path": main_path, "mode": "full"})))
.await
.unwrap();
let metrics = engine
.call_tool_text("ctx_metrics", None)
.await
.expect("metrics");
assert!(!metrics.is_empty(), "metrics should return data");
unsafe {
std::env::remove_var("LEAN_CTX_DATA_DIR");
}
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn phase9_session_save() {
let _lock = lean_ctx::core::data_dir::test_env_lock();
let (_dir, engine) = setup_project();
let _ = engine
.call_tool_text(
"ctx_session",
Some(json!({"action": "task", "content": "Final verification"})),
)
.await
.expect("set task");
let save = engine
.call_tool_text("ctx_session", Some(json!({"action": "save"})))
.await
.expect("session save");
assert!(!save.is_empty(), "save should return confirmation");
unsafe {
std::env::remove_var("LEAN_CTX_DATA_DIR");
}
}