Files
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

101 lines
3.9 KiB
Rust
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! Golden test for the quality loop v1 (GL #494): an edit failure after a
//! compressed read must escalate the next auto read of that file to `full`,
//! and repeated failures must make the (ext × mode) pair risky so *other*
//! files of the same type stop being compressed with the failing mode.
//!
//! Single test in its own binary: it sets `LEAN_CTX_DATA_DIR` process-wide
//! before the edit-quality store's `OnceLock` is first touched.
use lean_ctx::core::auto_mode_resolver::{AutoModeContext, resolve};
use lean_ctx::tools::ctx_edit::{EditParams, record_outcome, run_io};
fn params_for(path: &str, old_string: &str) -> EditParams {
EditParams {
path: path.to_string(),
old_string: old_string.to_string(),
new_string: "fn replaced() {}".to_string(),
replace_all: false,
create: false,
expected_md5: None,
expected_size: None,
expected_mtime_ms: None,
backup: false,
backup_path: None,
evidence: false,
diff_max_lines: 50,
allow_lossy_utf8: false,
}
}
#[test]
fn edit_fail_after_map_read_escalates_and_penalizes() {
let tmp = tempfile::tempdir().unwrap();
// TODO: Audit that the environment access only happens in single-threaded code.
unsafe { std::env::set_var("LEAN_CTX_DATA_DIR", tmp.path()) };
let file = tmp.path().join("golden.rs");
std::fs::write(&file, "fn real_function() { 1 }\n".repeat(60)).unwrap();
let path = file.to_string_lossy().to_string();
// The agent quotes an old_string from a `map` rendering — the body was
// never in context, so the string is not on disk and the edit misses.
let params = params_for(&path, "fn imagined_from_map_view()");
let (text, effect) = run_io(&params, "map");
assert!(
text.contains("old_string not found"),
"expected a not-found failure, got: {text}"
);
record_outcome(&params, "map", &text, &effect);
// Golden: the NEXT auto read of the same file resolves to full…
let ctx = AutoModeContext {
path: &path,
token_count: 3000,
task: None,
cache: None,
};
let first = resolve(&ctx);
assert_eq!(first.mode, "full");
assert_eq!(first.source, "edit_fail_escalation");
// …and the escalation is one-shot.
let second = resolve(&ctx);
assert_ne!(second.source, "edit_fail_escalation");
// A second failure makes rs|map risky (2 fails, rate 1.0 >= 0.25):
// a DIFFERENT .rs file that would normally resolve to map now gets full.
let (text2, effect2) = run_io(&params, "map");
record_outcome(&params, "map", &text2, &effect2);
let other = tmp.path().join("other.rs");
std::fs::write(&other, "fn unrelated() { 2 }\n".repeat(60)).unwrap();
let other_path = other.to_string_lossy().to_string();
let other_ctx = AutoModeContext {
path: &other_path,
// > 6000 tokens so the deterministic size heuristic resolves a code file
// to `map` (#683 raised the map floor from 3000 → 6000). Only a non-full
// base mode can be escalated to `full` by the risky (rs × map) penalty.
token_count: 7000,
task: None,
cache: None,
};
let penalized = resolve(&other_ctx);
assert_eq!(penalized.mode, "full");
assert_eq!(penalized.source, "edit_quality_penalty");
// Successful edits on the failing pair recover it (hysteresis: rate
// must drop below 0.15 — 2 fails need 12+ successes).
for _ in 0..12 {
std::fs::write(&file, "fn real_function() { 1 }\n").unwrap();
let p = params_for(&path, "fn real_function() { 1 }");
let (t, e) = run_io(&p, "map");
assert!(!t.starts_with("ERROR"), "expected success, got: {t}");
record_outcome(&p, "map", &t, &e);
}
let recovered = resolve(&other_ctx);
assert_ne!(
recovered.source, "edit_quality_penalty",
"12 successes must clear the risky flag (2/14 < 0.15)"
);
}