112 lines
4.5 KiB
Rust
112 lines
4.5 KiB
Rust
//! Every verified example still verifies.
|
|
//!
|
|
//! The corpus is what the agent is shown as "a graph that works". An entry that stopped
|
|
//! building — a widget renamed, a port retyped, a parameter's range narrowed — would teach
|
|
//! the model something false with the authority of a proven example. So each entry is
|
|
//! re-proven here: parsed, checked, compiled with cargo, run, compared across tiers, and
|
|
//! held to the stages its `proof:` line claims passed (a claim of `tiers` is a claim that
|
|
//! the comparison RAN and agreed, not that it was skipped).
|
|
|
|
use flowrs_core::graph::corpus;
|
|
use flowrs_core::graph::verify::{self, Native, Stage, Status};
|
|
use flowrs_core::graph::widget::builtin_registry;
|
|
|
|
fn cargo_available() -> bool {
|
|
if std::process::Command::new("cargo")
|
|
.arg("-V")
|
|
.output()
|
|
.is_ok()
|
|
{
|
|
return true;
|
|
}
|
|
assert_eq!(
|
|
std::env::var("FLOWRS_ALLOW_MISSING_CARGO").as_deref(),
|
|
Ok("1"),
|
|
"agent_corpus: no cargo on PATH; the corpus cannot be proven without it \
|
|
(set FLOWRS_ALLOW_MISSING_CARGO=1 to skip on purpose)"
|
|
);
|
|
false
|
|
}
|
|
|
|
#[test]
|
|
fn every_corpus_entry_builds_and_passes_what_it_claims() {
|
|
if !cargo_available() {
|
|
eprintln!("SKIP agent_corpus: no cargo (FLOWRS_ALLOW_MISSING_CARGO=1)");
|
|
return;
|
|
}
|
|
let reg = builtin_registry();
|
|
let tc = Native::default();
|
|
let mut failures = Vec::new();
|
|
// Which entries' tier agreement holds the whole program, and which holds it node by node.
|
|
let (mut whole, mut per_widget): (Vec<&str>, Vec<&str>) = (Vec::new(), Vec::new());
|
|
for e in corpus::entries() {
|
|
let parsed = match e.parse() {
|
|
Ok(p) => p,
|
|
Err(err) => {
|
|
failures.push(format!("{}: does not parse: {err:?}", e.slug));
|
|
continue;
|
|
}
|
|
};
|
|
let v = verify::check_graph(None, &parsed.graph, &parsed.origin, reg, &tc, &e.expect);
|
|
if !v.verified() {
|
|
failures.push(format!("{}: not verified\n{}", e.slug, v.feedback()));
|
|
continue;
|
|
}
|
|
for stage in &e.proof {
|
|
match v.status(*stage) {
|
|
Some(Status::Passed(_)) => {}
|
|
other => failures.push(format!(
|
|
"{}: claims {} passed, it is {other:?}",
|
|
e.slug,
|
|
stage.label()
|
|
)),
|
|
}
|
|
}
|
|
// An entry with test vectors must claim the tests it has.
|
|
if !e.expect.values.is_empty() && !e.proof.contains(&Stage::Tests) {
|
|
failures.push(format!(
|
|
"{}: has test vectors but does not claim `tests`",
|
|
e.slug
|
|
));
|
|
}
|
|
if let Some(Status::Passed(note)) = v.status(Stage::Tiers) {
|
|
if note.contains("widget node(s) agree") {
|
|
per_widget.push(e.slug);
|
|
} else {
|
|
whole.push(e.slug);
|
|
}
|
|
// A graph on flowrs-dsp (its filters, its spectra) is held whole: the oscillator, the
|
|
// filter and the spectrum run together, not node by node. (A test record's graph is
|
|
// compared per widget: the editor holds a record as JSON text, the program as a struct.)
|
|
let dsp = parsed.graph.to_rust().is_ok_and(|p| {
|
|
p.lines()
|
|
.any(|l| l.starts_with("// Cargo.toml needs:") && l.contains("flowrs_dsp"))
|
|
});
|
|
if dsp && !note.contains("the whole program, built against") {
|
|
failures.push(format!(
|
|
"{}: built on flowrs-dsp, but its tiers held only per widget: {note}",
|
|
e.slug
|
|
));
|
|
}
|
|
}
|
|
println!("{:<22} {}", e.slug, v.stage_line());
|
|
}
|
|
println!("tiers held whole: {whole:?}\ntiers held per widget: {per_widget:?}");
|
|
assert!(failures.is_empty(), "\n{}", failures.join("\n\n"));
|
|
}
|
|
|
|
/// The corpus must cover what the lessons teach and what the agent edits most: at least
|
|
/// the size it shipped with, and at least one entry proven all the way to tier agreement
|
|
/// from each of the language primitives, the widget library, and a held-wire loop.
|
|
#[test]
|
|
fn the_corpus_covers_primitives_widgets_and_loops_to_tier_agreement() {
|
|
let all = corpus::entries();
|
|
assert!(all.len() >= 19, "{}", all.len());
|
|
let tiers = |slug: &str| {
|
|
corpus::get(slug)
|
|
.unwrap_or_else(|| panic!("{slug}"))
|
|
.proof
|
|
.contains(&Stage::Tiers)
|
|
};
|
|
assert!(tiers("sum_to_5") && tiers("float_sum") && tiers("held_counter"));
|
|
}
|