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.
122 lines
4.3 KiB
Rust
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);
|
|
}
|