use std::sync::Arc;
use opencrabs::brain::prompt_builder::{BrainLoader, RuntimeInfo};
use opencrabs::brain::provider::Provider;
use opencrabs::brain::tools::catalog::tool_access_prompt;
use opencrabs::config::Config;
use opencrabs::eval::compaction::CompactionDataset;
use opencrabs::eval::live::resolve_eval_providers;
use opencrabs::eval::panel::panel_from_providers;
use opencrabs::eval::produce::{eval_tool_set, produce_compaction_summary, produce_response};
use opencrabs::eval::runner::VarianceReport;
use opencrabs::eval::self_awareness::SelfAwarenessScenario;
#[tokio::main]
async fn main() {
let config = Config::load().expect("load config");
let providers = resolve_eval_providers(&config).await;
println!("Resolved {} eval provider(s):", providers.len());
for p in &providers {
println!(" - {} / {}", p.name(), p.default_model());
}
if providers.is_empty() {
eprintln!("No eval providers resolved — check agent.eval_providers and keys.toml.");
return;
}
let producer: Arc<dyn Provider> = providers[0].clone();
let producer_model = producer.default_model().to_string();
let panel = panel_from_providers(&providers);
let loader = BrainLoader::new(opencrabs::config::opencrabs_home());
let rt = RuntimeInfo {
model: Some(producer_model.clone()),
provider: Some(producer.name().to_string()),
working_directory: None,
};
let system_brain = loader.build_core_brain(Some(&rt));
let sys = Some(system_brain.as_str());
println!(
"\nProducer: {} / {} Judge panel: {} model(s) System brain: {} chars\n",
producer.name(),
producer_model,
panel.len(),
system_brain.len()
);
const K: usize = 5;
const CATASTROPHIC: f64 = 0.5;
let outlier_path = opencrabs::config::opencrabs_home().join("eval_outliers.md");
let ds = CompactionDataset::seed();
println!("== Compaction fidelity ({}), {K} runs ==", ds.name);
let (mut kw, mut pn) = (Vec::new(), Vec::new());
for i in 0..K {
let summary =
produce_compaction_summary(producer.as_ref(), &producer_model, &ds.messages(), sys)
.await;
let (k, p) = (
ds.keyword_scorecard(&summary).overall(),
ds.judge_scorecard(&panel, &summary).await.overall(),
);
println!(
" run {i}: {} chars keyword={k:.2} panel={p:.2}",
summary.len()
);
if p <= CATASTROPHIC {
save_outlier(&outlier_path, &ds.name, i, p, &summary);
}
kw.push(k);
pn.push(p);
}
report("compaction", &kw, &pn, CATASTROPHIC);
let tools = eval_tool_set();
let lazy_brain = format!("{system_brain}{}", tool_access_prompt());
let modes: [(&str, Option<&str>); 2] = [("non-lazy", sys), ("lazy", Some(lazy_brain.as_str()))];
for (mode, brain) in modes {
for sc in SelfAwarenessScenario::seeds() {
println!("\n== Self-awareness [{mode}] ({}), {K} runs ==", sc.name);
let (mut kw, mut pn) = (Vec::new(), Vec::new());
for i in 0..K {
let response = produce_response(
producer.as_ref(),
&producer_model,
&sc.prompt,
brain,
&tools,
)
.await;
let kw_card = sc.keyword_scorecard(&response);
let (k, p) = (
kw_card.overall(),
sc.judge_scorecard(&panel, &response).await.overall(),
);
println!(
" run {i}: {} chars keyword={k:.2} panel={p:.2}",
response.len()
);
if i == 0 {
println!(
" run0 head: {}",
response[..response.len().min(280)].replace('\n', " ")
);
for (q, v) in &kw_card.results {
println!(
" keyword [{}] {} — {}",
if v.yes { "PASS" } else { "FAIL" },
q.dimension,
v.explanation.as_deref().unwrap_or("")
);
}
}
if p <= CATASTROPHIC {
save_outlier(
&outlier_path,
&format!("{mode}:{}", sc.name),
i,
p,
&response,
);
}
kw.push(k);
pn.push(p);
}
report(
&format!("self-awareness:{mode}:{}", sc.name),
&kw,
&pn,
CATASTROPHIC,
);
}
}
println!(
"\nOutlier artifacts (if any) appended to {}",
outlier_path.display()
);
}
fn report(name: &str, keyword: &[f64], panel: &[f64], threshold: f64) {
println!(
" keyword {}",
VarianceReport::from_scores(keyword).render()
);
println!(" panel {}", VarianceReport::from_scores(panel).render());
println!(
" panel failure rate (<= {threshold:.2}): {:.0}% [{name}]",
VarianceReport::failure_rate(panel, threshold) * 100.0
);
}
fn save_outlier(path: &std::path::Path, dataset: &str, run: usize, score: f64, artifact: &str) {
let entry = format!(
"\n## {dataset} — run {run} — panel {score:.2} — {} chars\n\n{artifact}\n",
artifact.len()
);
use std::io::Write;
match std::fs::OpenOptions::new()
.create(true)
.append(true)
.open(path)
{
Ok(mut f) => {
if let Err(e) = f.write_all(entry.as_bytes()) {
eprintln!("failed to write outlier artifact: {e}");
}
}
Err(e) => eprintln!("failed to open outlier file {}: {e}", path.display()),
}
}