diff --git a/crates/aura-cli/examples/r_sma.json b/crates/aura-cli/examples/r_sma.json new file mode 100644 index 0000000..cbdc8c7 --- /dev/null +++ b/crates/aura-cli/examples/r_sma.json @@ -0,0 +1 @@ +{"format_version":1,"blueprint":{"name":"sma_signal","nodes":[{"primitive":{"type":"SMA","name":"fast","bound":[{"pos":0,"name":"length","kind":"I64","value":{"I64":2}}]}},{"primitive":{"type":"SMA","name":"slow","bound":[{"pos":0,"name":"length","kind":"I64","value":{"I64":4}}]}},{"primitive":{"type":"Sub"}},{"primitive":{"type":"Bias","name":"bias","bound":[{"pos":0,"name":"scale","kind":"F64","value":{"F64":0.5}}]}}],"edges":[{"from":0,"to":2,"slot":0,"from_field":0},{"from":1,"to":2,"slot":1,"from_field":0},{"from":2,"to":3,"slot":0,"from_field":0}],"input_roles":[{"name":"price","targets":[{"node":0,"slot":0},{"node":1,"slot":0}],"source":"F64"}],"output":[{"node":3,"field":0,"name":"bias"}]}} \ No newline at end of file diff --git a/crates/aura-cli/examples/r_sma_open.json b/crates/aura-cli/examples/r_sma_open.json new file mode 100644 index 0000000..52ec036 --- /dev/null +++ b/crates/aura-cli/examples/r_sma_open.json @@ -0,0 +1 @@ +{"format_version":1,"blueprint":{"name":"sma_signal","nodes":[{"primitive":{"type":"SMA","name":"fast"}},{"primitive":{"type":"SMA","name":"slow"}},{"primitive":{"type":"Sub"}},{"primitive":{"type":"Bias","name":"bias","bound":[{"pos":0,"name":"scale","kind":"F64","value":{"F64":0.5}}]}}],"edges":[{"from":0,"to":2,"slot":0,"from_field":0},{"from":1,"to":2,"slot":1,"from_field":0},{"from":2,"to":3,"slot":0,"from_field":0}],"input_roles":[{"name":"price","targets":[{"node":0,"slot":0},{"node":1,"slot":0}],"source":"F64"}],"output":[{"node":3,"field":0,"name":"bias"}]}} \ No newline at end of file diff --git a/crates/aura-cli/src/main.rs b/crates/aura-cli/src/main.rs index 210909c..c291a89 100644 --- a/crates/aura-cli/src/main.rs +++ b/crates/aura-cli/src/main.rs @@ -6416,6 +6416,37 @@ mod tests { std::fs::write("tests/fixtures/sma_signal_open.json", json).expect("write fixture"); } + /// Regenerates the shipped r-sma demo examples (crates/aura-cli/examples/) from + /// the current builder. Ignored by default; run with `--ignored` after a signal + /// change so the byte-fidelity proof stays green. (#159 copy+prove.) + #[test] + #[ignore = "regenerates the committed r-sma example blueprints"] + fn emit_r_sma_examples() { + std::fs::create_dir_all("examples").expect("create examples dir"); + let closed = blueprint_to_json(&sma_signal(Some(2), Some(4))).expect("serializes"); + std::fs::write("examples/r_sma.json", closed).expect("write closed example"); + let open = blueprint_to_json(&sma_signal(None, None)).expect("serializes"); + std::fs::write("examples/r_sma_open.json", open).expect("write open example"); + } + + /// The shipped examples under crates/aura-cli/examples/ ARE the builder's + /// serialization — the load-bearing proof the demo copy is identical to the + /// original, captured while the builder is alive (#159 copy+prove). Cut 1b's + /// builder deletion + synth-site swap rest on this. + #[test] + fn shipped_r_sma_examples_are_byte_identical_to_the_builder() { + assert_eq!( + include_str!("../examples/r_sma.json"), + blueprint_to_json(&sma_signal(Some(2), Some(4))).expect("serializes"), + "closed example drifted from sma_signal(2,4) — re-run emit_r_sma_examples --ignored", + ); + assert_eq!( + include_str!("../examples/r_sma_open.json"), + blueprint_to_json(&sma_signal(None, None)).expect("serializes"), + "open example drifted from sma_signal(None,None) — re-run emit_r_sma_examples --ignored", + ); + } + /// The cycle-1 keystone (C1): a signal serialized → loaded back through the /// public `blueprint_from_json` path runs bit-identically to its Rust-built /// twin — same metrics, same traces, same topology_hash. diff --git a/crates/aura-cli/tests/cli_run.rs b/crates/aura-cli/tests/cli_run.rs index ed0904d..002f87a 100644 --- a/crates/aura-cli/tests/cli_run.rs +++ b/crates/aura-cli/tests/cli_run.rs @@ -5460,3 +5460,27 @@ fn mc_dissolved_seed_changes_the_bootstrap_draw_not_the_pooled_series() { "a different --seed must move the resampled E[R] mean: {v42} vs {v7}" ); } + +/// `aura run` on the shipped closed example reproduces the built-in r-sma grade +/// (#159): the example is the proven data successor to `--harness r-sma`. Survives +/// the Cut-1b builder deletion (depends only on the example + generic run path). +#[test] +fn shipped_r_sma_example_reproduces_the_builtin_grade() { + let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura")) + .args(["run", "examples/r_sma.json"]) + .output() + .expect("spawn aura run example"); + assert_eq!( + out.status.code(), + Some(0), + "exit: {:?} stderr={}", + out.status, + String::from_utf8_lossy(&out.stderr) + ); + let stdout = String::from_utf8(out.stdout).expect("utf-8"); + // the same metrics r_sma_single_run_output_golden pins for --harness r-sma + assert!(stdout.contains("\"expectancy_r\":1.2710005136982836"), "{stdout}"); + assert!(stdout.contains("\"sqn\":3.141496526818299"), "{stdout}"); + assert!(stdout.contains("\"total_pips\":0.34185000000002036"), "{stdout}"); + assert!(stdout.contains("\"n_trades\":3"), "{stdout}"); +} diff --git a/crates/aura-cli/tests/graph_construct.rs b/crates/aura-cli/tests/graph_construct.rs index 69b2211..d9aa9ca 100644 --- a/crates/aura-cli/tests/graph_construct.rs +++ b/crates/aura-cli/tests/graph_construct.rs @@ -407,6 +407,13 @@ fn fixture(name: &str) -> String { format!("{}/tests/fixtures/{name}", env!("CARGO_MANIFEST_DIR")) } +/// The absolute path of a demo blueprint shipped in the public examples/ +/// gallery (#159 copy+prove) — distinct from `fixture()`, which reads the +/// internal tests/fixtures/ copies the emitter builds from. +fn example(name: &str) -> String { + format!("{}/examples/{name}", env!("CARGO_MANIFEST_DIR")) +} + /// The id extracted from a `registered blueprint {id} ({path})` line. /// Prefix-tolerant across the #194 convention change (the display form dropped /// the glued `content:` prefix): the id is bare either way. @@ -688,3 +695,39 @@ fn graph_params_accepts_an_op_script_matching_its_envelope() { assert_eq!(op_code, Some(0), "params on op-script exits 0: {op_out} {op_err}"); assert_eq!(op_out, env_out, "op-script and envelope agree on the raw axis namespace"); } + +/// Property (#159): the shipped closed example (`examples/r_sma.json`) is +/// genuinely closed, not merely byte-identical to the builder — `graph +/// introspect --params` on it reports zero unbound params. The Cut-1 +/// byte-fidelity proof (`shipped_r_sma_examples_are_byte_identical_to_the_builder`, +/// main.rs) only pins the example's bytes to the builder's serialization; it says +/// nothing about whether that serialization is actually closed. This pins the +/// "closed" claim the demo makes to its audience. +#[test] +fn shipped_r_sma_example_is_genuinely_closed() { + let dir = temp_cwd("example-closed-params"); + let (stdout, stderr, code) = + run_in(&dir, &["graph", "introspect", "--params", &example("r_sma.json")]); + assert_eq!(code, Some(0), "stdout: {stdout} stderr: {stderr}"); + assert_eq!(stdout, "", "the closed example must leave zero params unbound"); +} + +/// Property (#159): the shipped open example (`examples/r_sma_open.json`) is a +/// usable sweep-axis template from its public gallery location, not just a +/// byte-identical artifact — `graph introspect --params` lists exactly the two +/// unbound SMA lengths, in lowering order, matching the raw axis namespace the +/// internal `sma_signal_open.json` fixture prints (#196). The byte-fidelity +/// proof only checks the example's bytes match the builder; this checks the +/// shipped copy is actually introspectable/bindable from where a consumer runs +/// it. +#[test] +fn shipped_r_sma_open_example_lists_its_axis_namespace() { + let dir = temp_cwd("example-open-params"); + let (stdout, stderr, code) = + run_in(&dir, &["graph", "introspect", "--params", &example("r_sma_open.json")]); + assert_eq!(code, Some(0), "stdout: {stdout} stderr: {stderr}"); + assert_eq!( + stdout, "fast.length:I64\nslow.length:I64\n", + "the raw open params, in order, from the public gallery copy" + ); +}