KeiSeiKit-1.0/_primitives/_rust/kei-frustration-loop/tests/auto_train_threshold.rs
Parfii-bot 0be354a920 KeiSeiKit-public — clean state
Single-commit clean baseline after security scrub of niche-tells,
project codenames, internal jargon, and contributor-email leaks.

Contents:
- 100 Rust crates (_primitives/_rust/)
- 37 agent manifests (_manifests/) + generated specs (_generated/)
- 67 user-invocable skills (skills/)
- 33 hooks (hooks/)
- Composition blocks (_blocks/)
- Documentation (docs/, README.md)
- TS adapter packages (_ts_packages/)
- Assembler (_assembler/)
- Roles (_roles/)
- Templates (_templates/)
- Forgejo CI (.forgejo/)

Author: Denis Parfionovich <info@greendragon.info>

License: see LICENSE.
2026-05-01 12:09:03 +08:00

122 lines
4.3 KiB
Rust

//! Threshold trigger logic. Populate N-1 feedback rows → assert
//! `should_retrain == false`. Add one more → assert `true`. Then run the
//! actual `auto_train` and verify a new firmware file was written.
use kei_frustration_loop::auto_train::{auto_train, resolve_threshold, should_retrain};
use kei_frustration_loop::feedback::{append_feedback, Feedback, Label};
use std::fs;
use tempfile::TempDir;
fn make_fb(i: usize) -> Feedback {
Feedback {
hit_id: format!("hit-{i}"),
message: format!("опять делаешь не так — повторяю вот так {i}"),
label: Label::Correct,
category: "repeat-signal".to_string(),
ts: 1_700_000_000 + i as u64,
user: "test-user".to_string(),
}
}
#[test]
fn threshold_flips_at_exactly_n() {
let dir = TempDir::new().unwrap();
let path = dir.path().join("test.feedback.jsonl");
let n = 5usize;
// N-1 rows ⇒ should_retrain == false.
for i in 0..(n - 1) {
append_feedback(&path, &make_fb(i)).unwrap();
}
assert!(
!should_retrain(&path, n).unwrap(),
"expected false at N-1 rows"
);
// Add one more ⇒ should_retrain == true.
append_feedback(&path, &make_fb(n - 1)).unwrap();
assert!(
should_retrain(&path, n).unwrap(),
"expected true at N rows"
);
}
#[test]
fn auto_train_under_threshold_is_no_op() {
let dir = TempDir::new().unwrap();
let traces = dir.path().join("traces");
fs::create_dir_all(&traces).unwrap();
fs::write(traces.join("a.txt"), "hello world").unwrap();
let fb = dir.path().join("fb.jsonl");
let out = dir.path().join("user.firmware.gz");
append_feedback(&fb, &make_fb(0)).unwrap();
let r = auto_train(&traces, &fb, &out, 10).unwrap();
assert!(!r.trained, "should not train under threshold");
assert_eq!(r.feedback_count, 1);
assert_eq!(r.threshold, 10);
assert!(!out.exists(), "no firmware should be written");
}
#[test]
fn auto_train_over_threshold_writes_firmware() {
let dir = TempDir::new().unwrap();
let traces = dir.path().join("traces");
fs::create_dir_all(&traces).unwrap();
fs::write(
traces.join("seed.txt"),
"the quick brown fox jumps over the lazy dog repeatedly ",
)
.unwrap();
let fb = dir.path().join("fb.jsonl");
let out = dir.path().join("user.firmware.gz");
let n = 3usize;
for i in 0..n {
append_feedback(&fb, &make_fb(i)).unwrap();
}
let r = auto_train(&traces, &fb, &out, n).unwrap();
assert!(r.trained, "should train at threshold ({n} rows)");
assert!(r.corpus_size > 0);
assert!(out.exists(), "firmware file must be written");
}
// `resolve_threshold_*` assertions are merged into one test because they
// share global env state (`KEI_FRUSTRATION_THRESHOLD`). Splitting them
// across `#[test]` functions causes a parallel-execution race in which
// `cli_wins_over_env` sets the var while `uses_default` reads it — the
// v1 worktree has the same race; we close it here without altering the
// behavioural assertions themselves.
#[test]
fn resolve_threshold_default_env_and_cli_priority() {
// 1. Default path: env var unset → DEFAULT_THRESHOLD (20).
std::env::remove_var("KEI_FRUSTRATION_THRESHOLD");
let t_default = resolve_threshold(None);
assert_eq!(t_default, 20, "default threshold must be 20");
// 2. Env var overrides default when CLI is None.
std::env::set_var("KEI_FRUSTRATION_THRESHOLD", "7");
let t_env = resolve_threshold(None);
assert_eq!(t_env, 7, "env var must override default when CLI is None");
// 3. CLI override beats env override.
let t_cli = resolve_threshold(Some(99));
std::env::remove_var("KEI_FRUSTRATION_THRESHOLD");
assert_eq!(t_cli, 99);
}
#[test]
fn auto_train_returns_threshold_in_report() {
// Sanity test: `auto_train` echoes the threshold back unchanged in the
// `TrainReport`, regardless of feedback count or trained flag.
let dir = TempDir::new().unwrap();
let traces = dir.path().join("traces");
fs::create_dir_all(&traces).unwrap();
let fb = dir.path().join("fb.jsonl");
let out = dir.path().join("user.firmware.gz");
let r = auto_train(&traces, &fb, &out, 42).unwrap();
assert_eq!(r.threshold, 42, "threshold echoed verbatim");
assert_eq!(r.feedback_count, 0, "no feedback yet");
assert!(!r.trained);
}