diff --git a/crates/aura-cli/src/main.rs b/crates/aura-cli/src/main.rs index a121dee..7de8078 100644 --- a/crates/aura-cli/src/main.rs +++ b/crates/aura-cli/src/main.rs @@ -3378,7 +3378,7 @@ fn dispatch_graph(a: GraphCmd, env: &project::Env) { } None if a.blueprint.is_none() => { let bp = blueprint_from_json( - include_str!("../examples/r_sma_open.json"), + include_str!("../examples/r_sma.json"), &|t| env.resolve(t), ) .expect("the shipped r-sma example reloads into a renderable blueprint"); @@ -4053,10 +4053,10 @@ mod tests { ) .expect("write examples/r_breakout.json"); std::fs::write( - "examples/r_breakout_open.json", + "tests/fixtures/r_breakout_open.json", blueprint_to_json(&r_breakout_signal(None)).expect("serialize open r_breakout"), ) - .expect("write examples/r_breakout_open.json"); + .expect("write tests/fixtures/r_breakout_open.json"); } /// The shipped examples are a faithful serialisation of the carved signal (#159 cut 2): @@ -4071,7 +4071,7 @@ mod tests { ); assert_eq!( blueprint_to_json(&r_breakout_signal(None)).expect("serialize open"), - include_str!("../examples/r_breakout_open.json"), + include_str!("../tests/fixtures/r_breakout_open.json"), ); } @@ -4104,10 +4104,10 @@ mod tests { ) .expect("write examples/r_meanrev.json"); std::fs::write( - "examples/r_meanrev_open.json", + "tests/fixtures/r_meanrev_open.json", blueprint_to_json(&r_meanrev_signal(None, None)).expect("serialize open r_meanrev"), ) - .expect("write examples/r_meanrev_open.json"); + .expect("write tests/fixtures/r_meanrev_open.json"); } /// Regenerates the shipped r_channel examples from the carved signal. Run by hand: @@ -4123,10 +4123,10 @@ mod tests { ) .expect("write examples/r_channel.json"); std::fs::write( - "examples/r_channel_open.json", + "tests/fixtures/r_channel_open.json", blueprint_to_json(&r_channel_signal(None)).expect("serialize open r_channel"), ) - .expect("write examples/r_channel_open.json"); + .expect("write tests/fixtures/r_channel_open.json"); } /// The shipped examples are a faithful serialisation of the carved signal @@ -4140,7 +4140,7 @@ mod tests { ); assert_eq!( blueprint_to_json(&r_channel_signal(None)).expect("serialize open"), - include_str!("../examples/r_channel_open.json"), + include_str!("../tests/fixtures/r_channel_open.json"), ); } @@ -4222,7 +4222,7 @@ mod tests { ); assert_eq!( blueprint_to_json(&r_meanrev_signal(None, None)).expect("open"), - include_str!("../examples/r_meanrev_open.json"), + include_str!("../tests/fixtures/r_meanrev_open.json"), ); } @@ -4718,7 +4718,7 @@ mod tests { /// Loads the shipped open r-sma example (both SMA lengths free) through the /// public `blueprint_from_json` path. fn load_open_r_sma() -> Composite { - blueprint_from_json(include_str!("../examples/r_sma_open.json"), &|t| std_vocabulary(t)) + blueprint_from_json(include_str!("../tests/fixtures/r_sma_open.json"), &|t| std_vocabulary(t)) .expect("loads") } @@ -5161,7 +5161,7 @@ mod tests { // wraps the signal (name "sma_signal") so the names are prefixed — // exactly what `--axis` binds. let env = project::Env::std(); - let open = include_str!("../examples/r_sma_open.json"); + let open = include_str!("../tests/fixtures/r_sma_open.json"); let space = blueprint_axis_probe(open, &env).param_space(); let names: Vec<&str> = space.iter().map(|p| p.name.as_str()).collect(); assert_eq!(names, ["sma_signal.fast.length", "sma_signal.slow.length"]); @@ -5174,9 +5174,10 @@ mod tests { #[test] fn blueprint_walkforward_family_refits_each_window() { - // The open fixture's two SMA lengths are re-fit per IS window over a 2x2 grid. + // The closed blueprint's two bound SMA lengths are re-fit per IS window over + // a 2x2 grid via the #246 bound-override reopen path (bound = overridable default). let env = project::Env::std(); - let doc = include_str!("../examples/r_sma_open.json"); + let doc = include_str!("../examples/r_sma.json"); let axes = vec![ ("sma_signal.fast.length".to_string(), vec![Scalar::i64(2), Scalar::i64(3)]), ("sma_signal.slow.length".to_string(), vec![Scalar::i64(4), Scalar::i64(6)]), diff --git a/crates/aura-cli/src/render.rs b/crates/aura-cli/src/render.rs index bad05e1..2a8b78c 100644 --- a/crates/aura-cli/src/render.rs +++ b/crates/aura-cli/src/render.rs @@ -236,7 +236,7 @@ mod tests { fn render_html_is_self_contained_and_embeds_the_model() { let env = crate::project::Env::std(); let bp = aura_engine::blueprint_from_json( - include_str!("../examples/r_sma_open.json"), + include_str!("../examples/r_sma.json"), &|t| env.resolve(t), ) .expect("the shipped r-sma example reloads into a renderable blueprint"); diff --git a/crates/aura-cli/examples/r_breakout_open.json b/crates/aura-cli/tests/fixtures/r_breakout_open.json similarity index 100% rename from crates/aura-cli/examples/r_breakout_open.json rename to crates/aura-cli/tests/fixtures/r_breakout_open.json diff --git a/crates/aura-cli/examples/r_channel_open.json b/crates/aura-cli/tests/fixtures/r_channel_open.json similarity index 100% rename from crates/aura-cli/examples/r_channel_open.json rename to crates/aura-cli/tests/fixtures/r_channel_open.json diff --git a/crates/aura-cli/examples/r_meanrev_open.json b/crates/aura-cli/tests/fixtures/r_meanrev_open.json similarity index 100% rename from crates/aura-cli/examples/r_meanrev_open.json rename to crates/aura-cli/tests/fixtures/r_meanrev_open.json diff --git a/crates/aura-cli/examples/r_sma_open.json b/crates/aura-cli/tests/fixtures/r_sma_open.json similarity index 100% rename from crates/aura-cli/examples/r_sma_open.json rename to crates/aura-cli/tests/fixtures/r_sma_open.json diff --git a/crates/aura-cli/tests/graph_construct.rs b/crates/aura-cli/tests/graph_construct.rs index 8a76d60..bbc3e28 100644 --- a/crates/aura-cli/tests/graph_construct.rs +++ b/crates/aura-cli/tests/graph_construct.rs @@ -471,7 +471,7 @@ fn graph_register_is_idempotent() { fn graph_params_lists_raw_axis_namespace() { let dir = temp_cwd("params"); let (stdout, stderr, code) = - run_in(&dir, &["graph", "introspect", "--params", &example("r_sma_open.json")]); + run_in(&dir, &["graph", "introspect", "--params", &fixture("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"); } @@ -512,7 +512,7 @@ fn graph_introspect_mode_guard_still_exits_two_on_zero_or_two_modes() { #[test] fn graph_params_by_content_id_matches_params_by_file() { let dir = temp_cwd("params-by-id"); - let bp = example("r_sma_open.json"); + let bp = fixture("r_sma_open.json"); let (reg_out, reg_err, reg_code) = run_in(&dir, &["graph", "register", &bp]); assert_eq!(reg_code, Some(0), "register: {reg_out} {reg_err}"); let id = registered_id(®_out); @@ -533,7 +533,7 @@ fn graph_params_by_content_id_matches_params_by_file() { #[test] fn graph_params_tolerates_content_prefix_on_target() { let dir = temp_cwd("params-content-prefix"); - let bp = example("r_sma_open.json"); + let bp = fixture("r_sma_open.json"); let (reg_out, reg_err, reg_code) = run_in(&dir, &["graph", "register", &bp]); assert_eq!(reg_code, Some(0), "register: {reg_out} {reg_err}"); let id = registered_id(®_out); @@ -744,7 +744,7 @@ fn shipped_r_sma_example_is_genuinely_closed() { assert_eq!(stdout, "", "the closed example must leave zero params unbound"); } -/// Property (#159): the shipped open example (`examples/r_sma_open.json`) is a +/// Property (#159): the open fixture (`tests/fixtures/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 @@ -753,10 +753,10 @@ fn shipped_r_sma_example_is_genuinely_closed() { /// shipped copy is actually introspectable/bindable from where a consumer runs /// it. #[test] -fn shipped_r_sma_open_example_lists_its_axis_namespace() { +fn open_r_sma_fixture_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")]); + run_in(&dir, &["graph", "introspect", "--params", &fixture("r_sma_open.json")]); assert_eq!(code, Some(0), "stdout: {stdout} stderr: {stderr}"); assert_eq!( stdout, "fast.length:I64\nslow.length:I64\n", @@ -764,6 +764,31 @@ fn shipped_r_sma_open_example_lists_its_axis_namespace() { ); } +/// Property (#248): the four `_open` blueprint twins were RELOCATED out of the +/// public gallery, not deleted — each stem is present under `tests/fixtures/` +/// (the internal sweep-axis fixture location) and absent from `examples/` (the +/// public, user-facing gallery). This is the acceptance criterion's core claim +/// ("`examples/` ships no `_open` variants") stated as a filesystem fact, so a +/// future example addition that reintroduces a twin — or a migration that moves +/// the reference but forgets the file — fails here even though every +/// `include_str!`/path-string call site already resolves. +#[test] +fn open_twins_are_relocated_from_examples_to_fixtures_not_deleted() { + let manifest_dir = env!("CARGO_MANIFEST_DIR"); + for stem in ["r_sma", "r_breakout", "r_meanrev", "r_channel"] { + let gallery_path = format!("{manifest_dir}/examples/{stem}_open.json"); + assert!( + !std::path::Path::new(&gallery_path).exists(), + "{stem}_open.json must not ship in the public examples/ gallery (#248)" + ); + let fixture_path = format!("{manifest_dir}/tests/fixtures/{stem}_open.json"); + assert!( + std::path::Path::new(&fixture_path).exists(), + "{stem}_open.json must survive relocated under tests/fixtures/ (#248)" + ); + } +} + /// Property (#159 cut 2): the shipped closed example (`examples/r_breakout.json`) is /// genuinely closed — `graph introspect --params` reports zero unbound params. #[test] @@ -775,14 +800,14 @@ fn shipped_r_breakout_example_is_genuinely_closed() { assert_eq!(stdout, "", "the closed example must leave zero params unbound"); } -/// Property (#159 cut 2): the shipped open example (`examples/r_breakout_open.json`) +/// Property (#159 cut 2): the open fixture (`tests/fixtures/r_breakout_open.json`) /// lists its ONE ganged channel axis (#61: the two rolling windows are structurally /// one knob). #[test] -fn shipped_r_breakout_open_example_lists_its_axis_namespace() { +fn open_r_breakout_fixture_lists_its_axis_namespace() { let dir = temp_cwd("r-breakout-example-open-params"); let (stdout, stderr, code) = - run_in(&dir, &["graph", "introspect", "--params", &example("r_breakout_open.json")]); + run_in(&dir, &["graph", "introspect", "--params", &fixture("r_breakout_open.json")]); assert_eq!(code, Some(0), "stdout: {stdout} stderr: {stderr}"); assert_eq!( stdout, "channel_length:I64\n", @@ -805,7 +830,7 @@ fn shipped_r_breakout_open_example_lists_its_axis_namespace() { /// member) would be caught here even if the internal builder-level /// equivalence still holds. #[test] -fn shipped_r_breakout_open_gang_axis_matches_the_closed_example() { +fn open_r_breakout_fixture_gang_axis_matches_the_closed_example() { let closed_dir = temp_cwd("r-breakout-gang-axis-closed"); let (closed_stdout, closed_stderr, closed_code) = run_in(&closed_dir, &["run", &example("r_breakout.json")]); assert_eq!(closed_code, Some(0), "closed run stderr: {closed_stderr}"); @@ -815,7 +840,7 @@ fn shipped_r_breakout_open_gang_axis_matches_the_closed_example() { let sweep_dir = temp_cwd("r-breakout-gang-axis-sweep"); let (sweep_stdout, sweep_stderr, sweep_code) = run_in( &sweep_dir, - &["sweep", &example("r_breakout_open.json"), "--axis", "r_breakout_signal.channel_length=3"], + &["sweep", &fixture("r_breakout_open.json"), "--axis", "r_breakout_signal.channel_length=3"], ); assert_eq!(sweep_code, Some(0), "sweep stderr: {sweep_stderr}"); let lines: Vec<&str> = sweep_stdout.lines().collect(); @@ -840,13 +865,13 @@ fn shipped_r_meanrev_example_is_genuinely_closed() { assert_eq!(stdout, "", "the closed example must leave zero params unbound"); } -/// Property (#159 cut 3): the shipped open example (`examples/r_meanrev_open.json`) +/// Property (#159 cut 3): the open fixture (`tests/fixtures/r_meanrev_open.json`) /// lists its raw axis namespace, in lowering (node-add) order. #[test] -fn shipped_r_meanrev_open_example_lists_its_axis_namespace() { +fn open_r_meanrev_fixture_lists_its_axis_namespace() { let dir = temp_cwd("r-meanrev-example-open-params"); let (stdout, stderr, code) = - run_in(&dir, &["graph", "introspect", "--params", &example("r_meanrev_open.json")]); + run_in(&dir, &["graph", "introspect", "--params", &fixture("r_meanrev_open.json")]); assert_eq!(code, Some(0), "stdout: {stdout} stderr: {stderr}"); assert_eq!( stdout, "window:I64\nband.factor:F64\n", @@ -863,7 +888,7 @@ fn shipped_r_meanrev_open_example_lists_its_axis_namespace() { /// param positions could silently mis-bind the co-present un-ganged axis /// instead (or vice-versa) even though each axis alone still resolves. #[test] -fn shipped_r_meanrev_open_gang_plus_plain_axis_matches_the_closed_example() { +fn open_r_meanrev_fixture_gang_plus_plain_axis_matches_the_closed_example() { let closed_dir = temp_cwd("r-meanrev-gang-axis-closed"); let (closed_stdout, closed_stderr, closed_code) = run_in(&closed_dir, &["run", &example("r_meanrev.json")]); assert_eq!(closed_code, Some(0), "closed run stderr: {closed_stderr}"); @@ -874,7 +899,7 @@ fn shipped_r_meanrev_open_gang_plus_plain_axis_matches_the_closed_example() { let (sweep_stdout, sweep_stderr, sweep_code) = run_in( &sweep_dir, &[ - "sweep", &example("r_meanrev_open.json"), + "sweep", &fixture("r_meanrev_open.json"), "--axis", "r_meanrev_signal.window=3", "--axis", "r_meanrev_signal.band.factor=2.0", ],