pub mod cleanup;
pub mod command;
pub mod error;
mod fsutil;
pub mod record;
pub mod salt;
pub mod summary;
pub mod writer;
pub use cleanup::{run_cleanup, CleanupReport};
pub use command::SummaryCommand;
pub use error::{EvaluationError, EvaluationResult};
pub use record::{EvaluationRecord, EVALUATION_SCHEMA_VERSION};
pub use summary::{summarize, EvaluationSummary, SummaryQuery, SUMMARY_SCHEMA_VERSION};
pub use writer::{EvaluationPolicy, EvaluationRecorder, ObservationInput, ObservedPair};
#[cfg(test)]
mod separation_tests {
use super::*;
use crate::config::defaults::{cleanup_old_logs, get_log_file_path, log_root_path};
use std::fs;
use std::path::Path;
struct Roots {
_base: tempfile::TempDir,
state_base_dir: String,
log_root: std::path::PathBuf,
evaluation_root: std::path::PathBuf,
}
fn roots() -> Roots {
let base = tempfile::tempdir().expect("state base");
let state_base_dir = base.path().display().to_string();
Roots {
log_root: log_root_path(Some(&state_base_dir)).expect("log root"),
evaluation_root: crate::config::defaults::evaluation_root_path(Some(&state_base_dir))
.expect("evaluation root"),
state_base_dir,
_base: base,
}
}
fn write_evaluation_record(root: &Path, project: &str, date: &str, bytes: usize) {
let dir = root.join("parallel_dependency").join(project);
fs::create_dir_all(&dir).expect("evaluation dir");
fs::write(dir.join(format!("{date}.jsonl")), vec![b'x'; bytes]).expect("record");
}
#[test]
fn the_evaluation_root_is_a_sibling_of_the_log_root_not_a_descendant() {
let roots = roots();
assert_ne!(roots.evaluation_root, roots.log_root);
assert!(
!roots.evaluation_root.starts_with(&roots.log_root),
"evaluation records must not live under the log root"
);
assert!(
!roots.log_root.starts_with(&roots.evaluation_root),
"logs must not live under the evaluation root"
);
assert_eq!(
roots.evaluation_root.parent(),
roots.log_root.parent(),
"both are owned by the same state root"
);
}
#[test]
fn the_log_file_a_writer_selects_is_never_inside_the_evaluation_root() {
let roots = roots();
let repo_root = tempfile::tempdir().expect("repo root");
let log_file = get_log_file_path(Some(&roots.state_base_dir), Some(repo_root.path()))
.expect("log file path");
assert!(log_file.starts_with(&roots.log_root));
assert!(!log_file.starts_with(&roots.evaluation_root));
}
#[test]
fn ordinary_log_retention_cannot_delete_an_evaluation_record() {
let roots = roots();
let repo_root = tempfile::tempdir().expect("repo root");
let slug = crate::config::defaults::generate_project_slug(repo_root.path());
let log_dir = roots.log_root.join(&slug);
fs::create_dir_all(&log_dir).expect("log dir");
let stale_log = log_dir.join("2020-01-01.log");
fs::write(&stale_log, b"old diagnostics").expect("log");
write_evaluation_record(&roots.evaluation_root, &slug, "2020-01-01", 32);
let deleted = cleanup_old_logs(Some(&roots.state_base_dir), Some(repo_root.path()), 7)
.expect("log cleanup");
assert_eq!(
deleted, 1,
"the stale log is the only thing log cleanup owns"
);
assert!(!stale_log.exists());
assert!(
roots
.evaluation_root
.join("parallel_dependency")
.join(&slug)
.join("2020-01-01.jsonl")
.is_file(),
"log retention must not reach an evaluation record"
);
}
#[test]
fn evaluation_retention_cannot_delete_an_ordinary_log() {
let roots = roots();
let slug = "proj-abcd1234";
let log_dir = roots.log_root.join(slug);
fs::create_dir_all(&log_dir).expect("log dir");
let stale_log = log_dir.join("2020-01-01.log");
fs::write(&stale_log, vec![b'x'; 4_096]).expect("log");
let decoy = log_dir.join("2020-01-01.jsonl");
fs::write(&decoy, vec![b'x'; 4_096]).expect("decoy");
write_evaluation_record(&roots.evaluation_root, slug, "2020-01-01", 32);
let report = run_cleanup(
&roots.evaluation_root,
EvaluationPolicy {
retention_days: 1,
max_total_bytes: 1,
},
None,
chrono::Utc::now().date_naive(),
)
.expect("evaluation cleanup");
assert_eq!(report.considered, 1, "only its own record is inventoried");
assert_eq!(report.removed(), 1);
assert!(
stale_log.is_file(),
"evaluation cleanup must not reach logs"
);
assert!(decoy.is_file(), "not even a log named like a record");
}
#[test]
fn cflx_logs_never_surfaces_an_evaluation_record() {
let roots = roots();
let repo_root = tempfile::tempdir().expect("repo root");
let slug = crate::config::defaults::generate_project_slug(repo_root.path());
let today = chrono::Local::now().format("%Y-%m-%d").to_string();
let log_dir = roots.log_root.join(&slug);
fs::create_dir_all(&log_dir).expect("log dir");
fs::write(
log_dir.join(format!("{today}.log")),
"INFO operator diagnostics line\n",
)
.expect("log");
let evaluation_dir = roots
.evaluation_root
.join("parallel_dependency")
.join(&slug);
fs::create_dir_all(&evaluation_dir).expect("evaluation dir");
fs::write(
evaluation_dir.join(format!("{today}.jsonl")),
"{\"marker\":\"EVALUATION-ONLY-MARKER\"}\n",
)
.expect("record");
let options = crate::log_viewer::LogViewerOptions {
print_path: false,
last: Some(100),
follow: false,
today: true,
project: Some(slug.clone()),
repo_root: Some(repo_root.path().to_path_buf()),
state_base_dir: Some(roots.state_base_dir.clone()),
};
let mut out = Vec::new();
crate::log_viewer::run_logs_command(&options, &mut out).expect("viewer must succeed");
let rendered = String::from_utf8(out).expect("UTF-8");
assert!(
rendered.contains("operator diagnostics line"),
"the viewer must still show ordinary logs: {rendered}"
);
assert!(
!rendered.contains("EVALUATION-ONLY-MARKER"),
"no evaluation record may reach `cflx logs`: {rendered}"
);
let selection = crate::log_viewer::resolve_log_selection(&options).expect("selection");
assert!(selection.selected_file.starts_with(&roots.log_root));
assert!(!selection.selected_file.starts_with(&roots.evaluation_root));
}
#[cfg(feature = "web-monitoring")]
#[test]
fn the_tui_and_web_log_ring_has_no_filesystem_source_to_leak_from() {
use crate::web::remote_control_api::projection::Projection;
let roots = roots();
write_evaluation_record(&roots.evaluation_root, "proj-abcd1234", "2026-09-18", 256);
assert!(roots.evaluation_root.exists(), "the store is populated");
let projection = Projection::new();
let (logs, _, _) = projection.logs();
assert!(
logs.is_empty(),
"the log ring is fed by events, never by the evaluation root"
);
projection.apply_log(crate::events::LogEntry::info("operator diagnostics"));
let (logs, _, _) = projection.logs();
assert_eq!(logs.len(), 1);
assert_eq!(logs[0].message, "operator diagnostics");
}
#[test]
fn a_disabled_policy_leaves_the_state_root_without_any_evaluation_entry() {
use crate::config::{
JudgeCommandsConfig, OrchestratorConfig, ParallelDependencyJudgeConfig,
};
let roots = roots();
let repo_root = tempfile::tempdir().expect("repo root");
let config = OrchestratorConfig {
state_base_dir: Some(roots.state_base_dir.clone()),
judge_commands: Some(JudgeCommandsConfig {
parallel_dependency: Some(ParallelDependencyJudgeConfig {
command: vec!["jev".to_string()],
model: "jev-1.13.0".to_string(),
timeout_ms: None,
max_input_bytes: None,
max_output_bytes: None,
yes_threshold: None,
mode: None,
evaluation: None,
}),
}),
..Default::default()
};
assert!(EvaluationRecorder::from_config(&config, repo_root.path()).is_none());
assert!(
!roots.evaluation_root.exists(),
"a disabled policy must create no directory, salt, or record"
);
}
#[test]
fn deleting_the_whole_evaluation_root_is_always_permitted_and_leaves_logs_intact() {
let roots = roots();
let slug = "proj-abcd1234";
write_evaluation_record(&roots.evaluation_root, slug, "2026-09-18", 64);
let log_dir = roots.log_root.join(slug);
fs::create_dir_all(&log_dir).expect("log dir");
fs::write(log_dir.join("2026-09-18.log"), b"diagnostics").expect("log");
fs::remove_dir_all(&roots.evaluation_root).expect("the root must be removable");
assert!(!roots.evaluation_root.exists());
assert!(log_dir.join("2026-09-18.log").is_file());
let summary = summarize(
&roots.evaluation_root,
&SummaryQuery {
purpose: "parallel_dependency".to_string(),
since: None,
project: None,
},
)
.expect("summary over a deleted root must succeed");
assert_eq!(summary.valid_records(), 0);
let report = run_cleanup(
&roots.evaluation_root,
EvaluationPolicy {
retention_days: 30,
max_total_bytes: 1024,
},
None,
chrono::Utc::now().date_naive(),
)
.expect("cleanup over a deleted root must succeed");
assert_eq!(report.considered, 0);
assert!(
!roots.evaluation_root.exists(),
"neither reader recreates it"
);
}
}