Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 84e1075176 | |||
| a895891ab1 | |||
| 479c6620e2 | |||
| a04fda3a4c | |||
| c31e946bb7 | |||
| 25b8354959 | |||
| 00cc2fe927 | |||
| 038e1702b3 | |||
| 1ebb94c1b8 | |||
| 4e6d5d4688 | |||
| 487431d97d | |||
| 6d3da424f4 |
@@ -554,6 +554,7 @@ fn placeholder_report(params: &[(String, Scalar)], window_ms: (i64, i64)) -> Run
|
||||
manifest: RunManifest {
|
||||
commit: String::new(),
|
||||
params: params.to_vec(),
|
||||
defaults: Vec::new(),
|
||||
window: (Timestamp(window_ms.0), Timestamp(window_ms.1)),
|
||||
seed: 0,
|
||||
broker: "faulted-member-placeholder".to_string(),
|
||||
|
||||
@@ -339,6 +339,7 @@ mod tests {
|
||||
manifest: RunManifest {
|
||||
commit: "test".to_string(),
|
||||
params: vec![],
|
||||
defaults: vec![],
|
||||
window: (Timestamp(0), Timestamp(1)),
|
||||
seed: 0,
|
||||
broker: "sim".to_string(),
|
||||
@@ -1019,6 +1020,7 @@ mod wf_tests {
|
||||
manifest: RunManifest {
|
||||
commit: "wf-fake".to_string(),
|
||||
params: params.to_vec(),
|
||||
defaults: Vec::new(),
|
||||
window: (Timestamp(window_ms.0), Timestamp(window_ms.1)),
|
||||
seed: 0,
|
||||
broker: "fake".to_string(),
|
||||
|
||||
@@ -58,6 +58,7 @@ fn planted_report(cell: &CellSpec, params: &[(String, Scalar)], window_ms: (i64,
|
||||
manifest: RunManifest {
|
||||
commit: "fake".to_string(),
|
||||
params: params.to_vec(),
|
||||
defaults: Vec::new(),
|
||||
window: (Timestamp(window_ms.0), Timestamp(window_ms.1)),
|
||||
seed: 0,
|
||||
broker: "fake".to_string(),
|
||||
|
||||
@@ -46,6 +46,7 @@ impl MemberRunner for FixedRunner {
|
||||
manifest: RunManifest {
|
||||
commit: "e2e".to_string(),
|
||||
params: vec![],
|
||||
defaults: vec![],
|
||||
window: (Timestamp(window_ms.0), Timestamp(window_ms.1)),
|
||||
seed: 0,
|
||||
broker: "test".to_string(),
|
||||
@@ -98,6 +99,7 @@ fn rankable_metrics_are_all_per_member_resolvable() {
|
||||
manifest: RunManifest {
|
||||
commit: "e2e".to_string(),
|
||||
params: vec![],
|
||||
defaults: vec![],
|
||||
window: (Timestamp(0), Timestamp(1)),
|
||||
seed: 0,
|
||||
broker: "test".to_string(),
|
||||
|
||||
@@ -1058,6 +1058,7 @@ mod tests {
|
||||
manifest: RunManifest {
|
||||
commit: "test".to_string(),
|
||||
params,
|
||||
defaults: Vec::new(),
|
||||
window: (Timestamp(0), Timestamp(0)),
|
||||
seed: 0,
|
||||
broker: "test".to_string(),
|
||||
|
||||
+71
-14
@@ -127,6 +127,7 @@ fn sim_optimal_manifest(
|
||||
RunManifest {
|
||||
commit: option_env!("AURA_COMMIT").unwrap_or("unknown").to_string(),
|
||||
params,
|
||||
defaults: Vec::new(),
|
||||
window,
|
||||
seed,
|
||||
broker: format!("sim-optimal(pip_size={pip_size})"),
|
||||
@@ -137,6 +138,24 @@ fn sim_optimal_manifest(
|
||||
}
|
||||
}
|
||||
|
||||
/// The wrap-prefixed BOUND-param defaults of `signal` (#249): every
|
||||
/// `bound_param_space()` entry as a `(<signal.name()>.<param>, value)` pair, in
|
||||
/// `bound_param_space()` order — the `RunManifest.defaults` field. Must be read
|
||||
/// off `signal` BEFORE it is consumed by `wrap_r`/reopening: an axis-reopened
|
||||
/// bound param has already left `bound_param_space()` by construction
|
||||
/// (`Composite::reopen` forgets the bound value), so a caller that reopens
|
||||
/// overrides before calling this naturally excludes them — no separate filter
|
||||
/// needed. Same prefixing rule as `wrapped_bound_names`, kept separate because
|
||||
/// that helper discards the value this one needs.
|
||||
fn wrapped_bound_defaults(signal: &Composite) -> Vec<(String, Scalar)> {
|
||||
let prefix = format!("{}.", signal.name());
|
||||
signal
|
||||
.bound_param_space()
|
||||
.into_iter()
|
||||
.map(|b| (format!("{prefix}{}", b.name), b.value))
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Map any byte outside the portable directory-name charset `[A-Za-z0-9._-]` to
|
||||
/// `_`. The single source of filesystem-portability for an on-disk path component
|
||||
/// (valid on Linux / Windows / macOS, also URL-path- and cloud-sync-safe). Used by
|
||||
@@ -1682,6 +1701,7 @@ fn run_signal_r(
|
||||
.iter()
|
||||
.map(|p| p.name.clone())
|
||||
.collect();
|
||||
let defaults = wrapped_bound_defaults(&signal); // read before `signal` is consumed below
|
||||
let (tx_eq, rx_eq) = mpsc::channel();
|
||||
let (tx_ex, rx_ex) = mpsc::channel();
|
||||
let (tx_r, rx_r) = mpsc::channel();
|
||||
@@ -1701,6 +1721,7 @@ fn run_signal_r(
|
||||
let named_params: Vec<(String, Scalar)> =
|
||||
names.into_iter().zip(params.iter().copied()).collect();
|
||||
let mut manifest = sim_optimal_manifest(named_params, window, seed, pip_size);
|
||||
manifest.defaults = defaults;
|
||||
manifest.broker = r_sma_broker_label(pip_size);
|
||||
manifest.topology_hash = Some(topo);
|
||||
manifest.project = env.provenance();
|
||||
@@ -1730,6 +1751,7 @@ fn run_blueprint_member(
|
||||
binding: &binding::ResolvedBinding,
|
||||
cost: &[aura_research::CostSpec],
|
||||
) -> RunReport {
|
||||
let defaults = wrapped_bound_defaults(&signal); // read before `signal` is consumed below
|
||||
let (tx_eq, rx_eq) = mpsc::channel();
|
||||
let (tx_ex, rx_ex) = mpsc::channel();
|
||||
let (tx_r, rx_r) = mpsc::channel();
|
||||
@@ -1770,6 +1792,7 @@ fn run_blueprint_member(
|
||||
named.push((format!("cost[{k}].{knob}"), Scalar::f64(v)));
|
||||
}
|
||||
let mut manifest = sim_optimal_manifest(named, window, seed, pip);
|
||||
manifest.defaults = defaults;
|
||||
manifest.broker = r_sma_broker_label(pip);
|
||||
manifest.topology_hash = Some(topo.to_string());
|
||||
manifest.project = env.provenance();
|
||||
@@ -2076,6 +2099,7 @@ fn axis_grid_probe_report() -> RunReport {
|
||||
manifest: RunManifest {
|
||||
commit: String::new(),
|
||||
params: Vec::new(),
|
||||
defaults: Vec::new(),
|
||||
window: (Timestamp(0), Timestamp(0)),
|
||||
seed: 0,
|
||||
broker: "wf-axis-preflight-placeholder".to_string(),
|
||||
@@ -3409,7 +3433,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");
|
||||
@@ -4084,10 +4108,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):
|
||||
@@ -4102,7 +4126,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"),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4135,10 +4159,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:
|
||||
@@ -4154,10 +4178,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
|
||||
@@ -4171,7 +4195,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"),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4253,7 +4277,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"),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4749,7 +4773,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")
|
||||
}
|
||||
|
||||
@@ -5192,7 +5216,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"]);
|
||||
@@ -5205,9 +5229,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)]),
|
||||
@@ -5527,6 +5552,38 @@ mod tests {
|
||||
assert!(!err.contains("UnknownKnob"), "must not leak the debug render: {err}");
|
||||
}
|
||||
|
||||
/// #249: an axis-reopened bound param flows through `params` ("what
|
||||
/// varied") and must NOT also appear in `defaults` ("what was held") — the
|
||||
/// two are disjoint by construction. Sweeping `fast.length` on the fully
|
||||
/// bound r_sma example leaves `slow.length`/`bias.scale` untouched (they
|
||||
/// stay in `defaults`), while `fast.length` moves to `params` and drops
|
||||
/// out of `defaults` entirely.
|
||||
#[test]
|
||||
fn sweep_override_excludes_the_reopened_default_from_the_manifest() {
|
||||
let env = project::Env::std();
|
||||
let closed = load_closed_r_sma();
|
||||
let doc = blueprint_to_json(&closed).expect("serializes");
|
||||
let axes = vec![("sma_signal.fast.length".to_string(), vec![Scalar::i64(2)])];
|
||||
let fam = blueprint_sweep_family(&doc, &axes, &DataSource::Synthetic, &env)
|
||||
.expect("a bound param is a default — the axis overrides it");
|
||||
assert_eq!(fam.points.len(), 1);
|
||||
let manifest = &fam.points[0].report.manifest;
|
||||
|
||||
let param_names: Vec<&str> = manifest.params.iter().map(|(n, _)| n.as_str()).collect();
|
||||
assert!(param_names.contains(&"sma_signal.fast.length"), "swept axis is a param: {param_names:?}");
|
||||
|
||||
let default_names: Vec<&str> = manifest.defaults.iter().map(|(n, _)| n.as_str()).collect();
|
||||
assert!(
|
||||
!default_names.contains(&"sma_signal.fast.length"),
|
||||
"the reopened default must not also appear in defaults: {default_names:?}"
|
||||
);
|
||||
assert_eq!(
|
||||
default_names,
|
||||
["sma_signal.slow.length", "sma_signal.bias.scale"],
|
||||
"the untouched bound params stay in defaults: {default_names:?}"
|
||||
);
|
||||
}
|
||||
|
||||
/// Property: an MC family's `aura reproduce` lines carry the member's own `seed=<N>`
|
||||
/// label. MC members hold no tuning params (the params-join is empty), so the line would
|
||||
/// otherwise print a BLANK member label; the seed is each draw's realization identity and
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -31,7 +31,7 @@ fn temp_cwd(name: &str) -> std::path::PathBuf {
|
||||
#[test]
|
||||
fn sweep_outside_project_refuses_and_leaves_no_store() {
|
||||
let cwd = temp_cwd("sweep-outside-project-refuses");
|
||||
let bp = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let bp = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args(["sweep", &bp, "--real", "GER40", "--axis", "sma_signal.fast.length=2,4"])
|
||||
.current_dir(&cwd)
|
||||
@@ -48,7 +48,7 @@ fn sweep_outside_project_refuses_and_leaves_no_store() {
|
||||
#[test]
|
||||
fn generalize_outside_project_refuses_and_leaves_no_store() {
|
||||
let cwd = temp_cwd("generalize-outside-project-refuses");
|
||||
let bp = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let bp = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args(["generalize", &bp, "--real", "GER40,USDJPY", "--axis", "sma_signal.fast.length=2"])
|
||||
.current_dir(&cwd)
|
||||
@@ -65,7 +65,7 @@ fn generalize_outside_project_refuses_and_leaves_no_store() {
|
||||
#[test]
|
||||
fn walkforward_outside_project_refuses_and_leaves_no_store() {
|
||||
let cwd = temp_cwd("walkforward-outside-project-refuses");
|
||||
let bp = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let bp = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args(["walkforward", &bp, "--real", "GER40", "--axis", "sma_signal.fast.length=2,4"])
|
||||
.current_dir(&cwd)
|
||||
@@ -82,7 +82,7 @@ fn walkforward_outside_project_refuses_and_leaves_no_store() {
|
||||
#[test]
|
||||
fn mc_outside_project_refuses_and_leaves_no_store() {
|
||||
let cwd = temp_cwd("mc-outside-project-refuses");
|
||||
let bp = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let bp = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args(["mc", &bp, "--real", "GER40", "--axis", "sma_signal.fast.length=2,4"])
|
||||
.current_dir(&cwd)
|
||||
@@ -117,6 +117,40 @@ fn run_prints_json_and_exits_zero() {
|
||||
assert!(line.contains("\"r\":{\"expectancy_r\":"), "got: {line}");
|
||||
}
|
||||
|
||||
/// Property (#249): a plain `aura run` on a fully bound blueprint records the
|
||||
/// untouched bound param values *directly in the outcome artifact*, so a raw
|
||||
/// reader of the manifest recovers the effective params without dereferencing
|
||||
/// the topology hash into the content-addressed store and re-implementing
|
||||
/// aura's merge semantics. The manifest carries a `defaults` field — the bound
|
||||
/// params merged inside `PrimitiveBuilder::build` below every record-writing
|
||||
/// layer — as wrap-prefixed `(name, Scalar)` pairs in `bound_param_space()`
|
||||
/// order (the same coordinate `--axis` uses). `params` keeps its "what varied"
|
||||
/// meaning: on a plain run nothing varied, so it stays `[]`, and every bound
|
||||
/// value lands in `defaults` instead of vanishing from the record.
|
||||
#[test]
|
||||
fn run_manifest_stamps_untouched_bound_defaults() {
|
||||
// The shipped r_sma.json is fully bound (fast.length=2, slow.length=4,
|
||||
// bias.scale=0.5); no axis re-opens any of them, so none flow through the
|
||||
// param space — today they appear in no outcome artifact ("params":[]).
|
||||
let out = Command::new(BIN).args(["run", "examples/r_sma.json"]).output().expect("spawn aura run");
|
||||
assert!(out.status.success(), "exit status: {:?}", out.status);
|
||||
let stdout = String::from_utf8(out.stdout).expect("utf-8 stdout");
|
||||
let line = stdout.trim_end();
|
||||
|
||||
// "what varied" is empty on a plain run — the bound defaults are NOT params.
|
||||
assert!(line.contains("\"params\":[]"), "params stays empty on a plain run: {line}");
|
||||
|
||||
// The untouched bound values are stamped in `defaults`, wrap-prefixed with
|
||||
// the blueprint name and ordered by `bound_param_space()` (node-declaration
|
||||
// order: fast, slow, bias), each a self-describing tagged Scalar (C14).
|
||||
assert!(
|
||||
line.contains(
|
||||
r#""defaults":[["sma_signal.fast.length",{"I64":2}],["sma_signal.slow.length",{"I64":4}],["sma_signal.bias.scale",{"F64":0.5}]]"#
|
||||
),
|
||||
"manifest must carry the untouched bound defaults: {line}",
|
||||
);
|
||||
}
|
||||
|
||||
/// Property: the RunManifest is self-identifying — its `commit` carries the
|
||||
/// real code identity that produced the run, not a placeholder. C8/C18 audit
|
||||
/// trail (this run = this commit): once runs are archived, `manifest.commit`
|
||||
@@ -545,6 +579,7 @@ fn chart_opens_a_sweep_trace_family_by_its_printed_handle() {
|
||||
let manifest = || RunManifest {
|
||||
commit: "c0ffee".to_string(),
|
||||
params: vec![("fast".to_string(), Scalar::f64(2.0))],
|
||||
defaults: vec![],
|
||||
window: (Timestamp(1), Timestamp(2)),
|
||||
seed: 0,
|
||||
broker: "sim-optimal(pip_size=1)".to_string(),
|
||||
@@ -679,6 +714,7 @@ fn chart_resolves_a_trace_family_by_its_chosen_campaign_name() {
|
||||
let manifest = || RunManifest {
|
||||
commit: "c0ffee".to_string(),
|
||||
params: vec![("fast".to_string(), Scalar::f64(2.0))],
|
||||
defaults: vec![],
|
||||
window: (Timestamp(1), Timestamp(2)),
|
||||
seed: 0,
|
||||
broker: "sim-optimal(pip_size=1)".to_string(),
|
||||
@@ -761,6 +797,7 @@ fn chart_by_campaign_name_refuses_when_the_name_is_ambiguous() {
|
||||
let manifest = || RunManifest {
|
||||
commit: "c0ffee".to_string(),
|
||||
params: vec![("fast".to_string(), Scalar::f64(2.0))],
|
||||
defaults: vec![],
|
||||
window: (Timestamp(1), Timestamp(2)),
|
||||
seed: 0,
|
||||
broker: "sim-optimal(pip_size=1)".to_string(),
|
||||
@@ -1031,7 +1068,7 @@ fn runs_families_list_and_per_family_rank_across_invocations() {
|
||||
// each a related set of 4 records (C18/C21 lineage), in the sibling family
|
||||
// store. `sweep` is blueprint-only now (#159 cut 4); the shipped open r-sma
|
||||
// example over a 2x2 axis grid stands in for the retired built-in default.
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
for _ in 0..2 {
|
||||
let out = Command::new(BIN)
|
||||
.args([
|
||||
@@ -1151,7 +1188,7 @@ fn local_data_present() -> bool {
|
||||
fn sweep_real_no_geometry_symbol_refuses_with_exit_1() {
|
||||
// not gated: the pip refusal happens before any data access.
|
||||
let (dir, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(BIN)
|
||||
.args(["sweep", &fixture, "--axis", "sma_signal.fast.length=2,4", "--real", "NONEXISTENT"])
|
||||
.current_dir(&dir).output().unwrap();
|
||||
@@ -1229,7 +1266,7 @@ fn sweep_real_blueprint_member_manifest_stamps_the_default_stop() {
|
||||
return;
|
||||
}
|
||||
let (dir, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(BIN)
|
||||
.args([
|
||||
"sweep", &fixture,
|
||||
@@ -1276,7 +1313,7 @@ fn sweep_real_blueprint_member_manifest_stamps_project_provenance() {
|
||||
return;
|
||||
}
|
||||
let (dir, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(BIN)
|
||||
.args([
|
||||
"sweep", &fixture,
|
||||
@@ -1370,7 +1407,7 @@ fn sweep_real_ohlc_channel_members_run_and_reproduce() {
|
||||
return;
|
||||
}
|
||||
let (dir, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_channel_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/tests/fixtures/r_channel_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let axes = std::process::Command::new(BIN)
|
||||
.args(["sweep", &fixture, "--list-axes"])
|
||||
.current_dir(&dir)
|
||||
@@ -1451,7 +1488,7 @@ fn sweep_real_blueprint_member_lines_pin_the_dissolved_contract() {
|
||||
return;
|
||||
}
|
||||
let (dir, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(BIN)
|
||||
.args([
|
||||
"sweep", &fixture,
|
||||
@@ -1689,7 +1726,7 @@ fn sweep_real_with_trace_writes_tap_series_to_disk() {
|
||||
return;
|
||||
}
|
||||
let (dir, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(BIN)
|
||||
.args([
|
||||
"sweep", &fixture,
|
||||
@@ -1747,7 +1784,7 @@ fn family_id_of_kind(dir: &Path, want: &str) -> String {
|
||||
/// silently re-run every member over the built-in synthetic showcase stream,
|
||||
/// which diverges from the stored real-data metrics on every member (observed:
|
||||
/// `reproduced 0/N bit-identically`, exit 1). Gated on the local GER40 archive
|
||||
/// (skip-on-no-data convention); uses the plain `r_sma_open.json` blueprint —
|
||||
/// (skip-on-no-data convention); uses the plain `r_sma.json` blueprint —
|
||||
/// no gang, no campaign-specific fixture — because the divergence is driven by
|
||||
/// `--real`, not by the minting path.
|
||||
#[test]
|
||||
@@ -1757,7 +1794,7 @@ fn reproduce_real_sweep_family_re_derives_bit_identically() {
|
||||
return;
|
||||
}
|
||||
let (dir, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let mint = Command::new(BIN)
|
||||
.args([
|
||||
"sweep", &fixture,
|
||||
@@ -1795,9 +1832,10 @@ fn reproduce_real_sweep_family_re_derives_bit_identically() {
|
||||
/// Property (C18/C1 reproduce guarantee, #246): the same reproduce guarantee holds
|
||||
/// when the swept axis names a BOUND param of a CLOSED starter blueprint, not an
|
||||
/// already-open one — `r_sma.json` (both `sma_signal.fast.length` and
|
||||
/// `sma_signal.slow.length` bound), the closed counterpart of the OPEN
|
||||
/// `r_sma_open.json` the walk-forward reproduce sibling
|
||||
/// (`aura_walkforward_over_a_blueprint_reproduces_bit_identically`) sweeps.
|
||||
/// `sma_signal.slow.length` bound), overriding only the `fast.length` axis and
|
||||
/// leaving `slow.length` bound — unlike the walk-forward reproduce sibling
|
||||
/// (`aura_walkforward_over_a_blueprint_reproduces_bit_identically`), which
|
||||
/// overrides both axes over the same closed blueprint.
|
||||
/// Modelled on that sibling (synthetic in-process walk-forward — no `--real`),
|
||||
/// NOT on `reproduce_real_sweep_family_re_derives_bit_identically`: a real-data
|
||||
/// mint routes through the campaign executor (`CliMemberRunner::run_member` +
|
||||
@@ -1911,7 +1949,7 @@ fn reproduce_real_walkforward_family_does_not_panic() {
|
||||
const WF_FROM_MS: &str = "1735689600000";
|
||||
const WF_TO_MS: &str = "1747353600000";
|
||||
let (dir, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let mint = Command::new(BIN)
|
||||
.args([
|
||||
"walkforward", &fixture,
|
||||
@@ -2115,7 +2153,7 @@ fn sweep_real_multi_column_blueprint_opens_high_and_low_columns() {
|
||||
#[test]
|
||||
fn aura_sweep_real_blueprint_refuses_a_raw_form_axis_name_before_data_access() {
|
||||
let dir = temp_cwd("sweep_real_rawname_refusal");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = Command::new(BIN)
|
||||
.args([
|
||||
"sweep", &fixture,
|
||||
@@ -2160,7 +2198,7 @@ fn aura_sweep_real_blueprint_subset_axes_refuses_without_store_litter() {
|
||||
return;
|
||||
}
|
||||
let (dir, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/tests/fixtures/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = Command::new(BIN)
|
||||
.args([
|
||||
"sweep", &fixture,
|
||||
@@ -2204,9 +2242,11 @@ fn aura_sweep_real_blueprint_subset_axes_refuses_without_store_litter() {
|
||||
/// comment. Modelled on `sweep_real_blueprint_member_lines_pin_the_dissolved_contract`
|
||||
/// (the dissolved-sweep e2e family `walkforward_dissolved_refuses_an_unknown_axis_name`
|
||||
/// belongs to): same store-reading assertions (`aura runs families`, one
|
||||
/// persisted `Sweep` family, member count), but over the CLOSED `r_sma.json`
|
||||
/// fixture (`sma_signal.fast.length`/`sma_signal.slow.length` both bound)
|
||||
/// instead of the OPEN `r_sma_open.json` every other real-data sweep pin uses.
|
||||
/// persisted `Sweep` family, member count), over the same `r_sma.json`
|
||||
/// fixture every other real-data sweep pin uses (`sma_signal.fast.length`/
|
||||
/// `sma_signal.slow.length` both bound) — the distinguishing property here
|
||||
/// is that the swept axis names an already-bound param, not that the
|
||||
/// fixture differs.
|
||||
#[test]
|
||||
fn sweep_dissolved_accepts_an_axis_over_a_bound_param() {
|
||||
if !local_data_present() {
|
||||
@@ -2245,6 +2285,89 @@ fn sweep_dissolved_accepts_an_axis_over_a_bound_param() {
|
||||
);
|
||||
}
|
||||
|
||||
/// Property (#246 override merge, exercised at scale by #248's open-twins
|
||||
/// migration): sweeping the CLOSED `examples/r_sma.json` (both SMA lengths
|
||||
/// bound to defaults 2/4) with `--axis` values that override BOTH bound
|
||||
/// lengths yields BIT-IDENTICAL per-member `total_pips` to sweeping the
|
||||
/// historical OPEN `tests/fixtures/r_sma_open.json` (both lengths genuinely
|
||||
/// unbound) over the same axis values. #248's migration replaced the "bind
|
||||
/// an open param" idiom with "override a bound param" at dozens of call
|
||||
/// sites across cli_run.rs/research_docs.rs/project_load.rs; if the override
|
||||
/// merge ever diverged from the historical bind path (e.g. a different
|
||||
/// position in the rebuilt param vector), every migrated seed/grade site
|
||||
/// would silently compile a DIFFERENT graph while still exiting 0 — no other
|
||||
/// test cross-checks the two idioms against each other. NOT gated — a
|
||||
/// synthetic sweep, no `--real`, so it is CI-safe on every machine.
|
||||
#[test]
|
||||
fn sweep_over_a_bound_override_matches_the_historical_open_bind() {
|
||||
let closed_dir = temp_cwd("bound-override-matches-open-closed");
|
||||
let closed_bp = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let closed_out = Command::new(BIN)
|
||||
.args([
|
||||
"sweep", &closed_bp,
|
||||
"--axis", "sma_signal.fast.length=2,4",
|
||||
"--axis", "sma_signal.slow.length=8,16",
|
||||
])
|
||||
.current_dir(&closed_dir)
|
||||
.output()
|
||||
.expect("spawn sweep over the closed blueprint's bound-override axes");
|
||||
assert!(
|
||||
closed_out.status.success(),
|
||||
"closed sweep exit: {:?}; stderr: {}",
|
||||
closed_out.status,
|
||||
String::from_utf8_lossy(&closed_out.stderr)
|
||||
);
|
||||
|
||||
let open_dir = temp_cwd("bound-override-matches-open-open");
|
||||
let open_bp = format!("{}/tests/fixtures/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let open_out = Command::new(BIN)
|
||||
.args([
|
||||
"sweep", &open_bp,
|
||||
"--axis", "sma_signal.fast.length=2,4",
|
||||
"--axis", "sma_signal.slow.length=8,16",
|
||||
])
|
||||
.current_dir(&open_dir)
|
||||
.output()
|
||||
.expect("spawn sweep over the open blueprint's unbound axes");
|
||||
assert!(
|
||||
open_out.status.success(),
|
||||
"open sweep exit: {:?}; stderr: {}",
|
||||
open_out.status,
|
||||
String::from_utf8_lossy(&open_out.stderr)
|
||||
);
|
||||
|
||||
let pips = |dir: &Path| -> Vec<f64> {
|
||||
let rank = Command::new(BIN)
|
||||
.args(["runs", "family", "sweep-0", "rank", "total_pips"])
|
||||
.current_dir(dir)
|
||||
.output()
|
||||
.expect("spawn rank");
|
||||
assert!(rank.status.success(), "rank exit: {:?}", rank.status);
|
||||
let out = String::from_utf8(rank.stdout).expect("utf-8");
|
||||
out.lines()
|
||||
.map(|l| {
|
||||
let key = "\"total_pips\":";
|
||||
let start = l.find(key).expect("line has total_pips") + key.len();
|
||||
let tail = &l[start..];
|
||||
let end = tail.find([',', '}']).expect("token end");
|
||||
tail[..end].parse().expect("total_pips is an f64")
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
let mut closed_pips = pips(&closed_dir);
|
||||
let mut open_pips = pips(&open_dir);
|
||||
closed_pips.sort_by(|a, b| a.partial_cmp(b).unwrap());
|
||||
open_pips.sort_by(|a, b| a.partial_cmp(b).unwrap());
|
||||
assert_eq!(
|
||||
closed_pips, open_pips,
|
||||
"bound-override and historical open-bind must compute bit-identical \
|
||||
member metrics for the same axis grid"
|
||||
);
|
||||
|
||||
let _ = std::fs::remove_dir_all(&closed_dir);
|
||||
let _ = std::fs::remove_dir_all(&open_dir);
|
||||
}
|
||||
|
||||
/// The synthetic seed-resweep `mc` is undefined over real bars (one realization ->
|
||||
/// identical members), so a bare `aura mc --real EURUSD` — with no R candidate — is
|
||||
/// REJECTED (usage on stderr, exit 2) at the binary boundary. The real path is
|
||||
@@ -2576,7 +2699,7 @@ fn generalize_grades_a_candidate_across_two_instruments() {
|
||||
const FROM_MS: &str = "1725148800000";
|
||||
const TO_MS: &str = "1727740799999";
|
||||
let (cwd, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", &fixture, "--real", "GER40,USDJPY",
|
||||
@@ -2622,7 +2745,7 @@ fn generalize_real_e2e_pins_the_exact_current_grade() {
|
||||
const FROM_MS: &str = "1725148800000";
|
||||
const TO_MS: &str = "1727740799999";
|
||||
let (cwd, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", &fixture, "--real", "GER40,USDJPY",
|
||||
@@ -2667,7 +2790,7 @@ fn generalize_real_e2e_pins_the_exact_current_grade() {
|
||||
/// blueprint, not just the historical r-sma candidate — the whole point of
|
||||
/// dropping `--strategy r-sma`/`--fast`/`--slow` for a positional blueprint +
|
||||
/// generic `--axis`. Every other generalize E2E test here still exercises
|
||||
/// `r_sma_open.json`, so a regression that silently special-cased r-sma paths
|
||||
/// `r_sma.json`, so a regression that silently special-cased r-sma paths
|
||||
/// back in (e.g. resolving axes against a hardcoded `sma_signal.*` namespace)
|
||||
/// would ship green there while breaking every other blueprint. This runs the
|
||||
/// unrelated r-breakout candidate (the ganged `channel_length` axis, no
|
||||
@@ -2679,7 +2802,7 @@ fn generalize_grades_a_non_r_sma_blueprint() {
|
||||
const FROM_MS: &str = "1725148800000";
|
||||
const TO_MS: &str = "1727740799999";
|
||||
let (cwd, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_breakout_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/tests/fixtures/r_breakout_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", &fixture, "--real", "GER40,USDJPY",
|
||||
@@ -2727,7 +2850,7 @@ fn walkforward_real_e2e_pins_the_exact_current_grade() {
|
||||
const FROM_MS: &str = "1735689600000";
|
||||
const TO_MS: &str = "1767225599000";
|
||||
let (cwd, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"walkforward", &fixture, "--real", "GER40",
|
||||
@@ -2773,7 +2896,7 @@ fn walkforward_real_e2e_pins_the_exact_current_grade() {
|
||||
/// sweepable blueprint through the campaign path, not just the historical r-sma
|
||||
/// candidate — the whole point of dropping `--strategy r-sma`/`--fast`/`--slow`
|
||||
/// for a positional blueprint + generic `--axis`. Every other walkforward E2E
|
||||
/// test here still exercises `r_sma_open.json`; a regression that silently
|
||||
/// test here still exercises `r_sma.json`; a regression that silently
|
||||
/// special-cased the refit's axis lookup back to a hardcoded `sma_signal.*`
|
||||
/// namespace (e.g. in `walkforward_summary_json_from_reports`'s per-axis
|
||||
/// `raw_matches_wrapped` search) would ship green there while breaking every
|
||||
@@ -2789,7 +2912,7 @@ fn walkforward_dissolves_a_non_r_sma_blueprint() {
|
||||
const FROM_MS: &str = "1735689600000";
|
||||
const TO_MS: &str = "1767225599000";
|
||||
let (cwd, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_breakout_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/tests/fixtures/r_breakout_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"walkforward", &fixture, "--real", "GER40",
|
||||
@@ -2828,7 +2951,7 @@ fn walkforward_dissolves_a_non_r_sma_blueprint() {
|
||||
#[test]
|
||||
fn walkforward_dissolved_refuses_a_multi_value_stop() {
|
||||
let cwd = temp_cwd("walkforward-multi-stop");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"walkforward", &fixture, "--real", "GER40",
|
||||
@@ -2853,7 +2976,7 @@ fn walkforward_dissolved_refuses_a_multi_value_stop() {
|
||||
#[test]
|
||||
fn walkforward_dissolved_accepts_select_plateau() {
|
||||
let (cwd, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"walkforward", &fixture, "--real", "GER40",
|
||||
@@ -2898,7 +3021,7 @@ fn walkforward_real_e2e_pins_the_exact_current_plateau_grade() {
|
||||
const FROM_MS: &str = "1735689600000";
|
||||
const TO_MS: &str = "1767225599000";
|
||||
let (cwd, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"walkforward", &fixture, "--real", "GER40",
|
||||
@@ -2954,7 +3077,7 @@ fn walkforward_real_e2e_pins_the_exact_current_plateau_grade() {
|
||||
#[test]
|
||||
fn walkforward_dissolved_defaults_a_single_omitted_knob() {
|
||||
let (cwd, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"walkforward", &fixture, "--real", "GER40",
|
||||
@@ -2988,7 +3111,7 @@ fn walkforward_dissolved_defaults_a_single_omitted_knob() {
|
||||
#[test]
|
||||
fn walkforward_dissolved_refuses_an_empty_real_symbol() {
|
||||
let cwd = temp_cwd("walkforward-empty-real");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"walkforward", &fixture, "--real", "",
|
||||
@@ -3012,7 +3135,7 @@ fn walkforward_dissolved_refuses_an_empty_real_symbol() {
|
||||
#[test]
|
||||
fn walkforward_dissolved_refuses_an_unknown_axis_name() {
|
||||
let cwd = temp_cwd("walkforward-unknown-axis");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"walkforward", &fixture, "--real", "GER40",
|
||||
@@ -3042,7 +3165,7 @@ fn walkforward_dissolved_refuses_an_unknown_axis_name() {
|
||||
#[test]
|
||||
fn walkforward_dissolved_refuses_an_unknown_select_token() {
|
||||
let cwd = temp_cwd("walkforward-bad-select");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"walkforward", &fixture, "--real", "GER40",
|
||||
@@ -3066,7 +3189,7 @@ fn walkforward_dissolved_refuses_an_unknown_select_token() {
|
||||
#[test]
|
||||
fn walkforward_dissolved_refuses_name_and_trace_together() {
|
||||
let cwd = temp_cwd("walkforward-name-and-trace");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"walkforward", &fixture, "--real", "GER40",
|
||||
@@ -3102,7 +3225,7 @@ fn walkforward_dissolves_through_the_campaign_path() {
|
||||
const FROM_MS: &str = "1735689600000";
|
||||
const TO_MS: &str = "1767225599000";
|
||||
let (cwd, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"walkforward", &fixture, "--real", "GER40",
|
||||
@@ -3193,7 +3316,7 @@ fn walkforward_stopless_defaults_the_regime_byte_identically_to_explicit_3_2() {
|
||||
const FROM_MS: &str = "1735689600000";
|
||||
const TO_MS: &str = "1767225599000";
|
||||
let (cwd, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
|
||||
// Stop-less: the two knobs are omitted entirely. This is the headline — today it
|
||||
// is refused at the argv boundary (exit 2, "requires --stop-length --stop-k");
|
||||
@@ -3279,7 +3402,7 @@ fn generalize_dissolves_through_the_campaign_path() {
|
||||
const FROM_MS: &str = "1725148800000";
|
||||
const TO_MS: &str = "1727740799999";
|
||||
let (cwd, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", &fixture, "--real", "GER40,USDJPY",
|
||||
@@ -3370,7 +3493,7 @@ fn generalize_repeated_identical_invocation_does_not_litter_the_store() {
|
||||
const FROM_MS: &str = "1725148800000";
|
||||
const TO_MS: &str = "1727740799999";
|
||||
let (cwd, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let invoke = || {
|
||||
std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
@@ -3425,7 +3548,7 @@ fn generalize_distinct_invocations_persist_distinct_campaign_documents() {
|
||||
const FROM_MS: &str = "1725148800000";
|
||||
const TO_MS: &str = "1727740799999";
|
||||
let (cwd, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let invoke = |fast: &str| {
|
||||
let fast_axis = format!("sma_signal.fast.length={fast}");
|
||||
std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
@@ -3478,7 +3601,7 @@ fn generalize_distinct_invocations_persist_distinct_campaign_documents() {
|
||||
#[test]
|
||||
fn generalize_without_explicit_window_resolves_a_shared_window_and_completes() {
|
||||
let (cwd, _g) = fresh_project_with_data();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", &fixture, "--real", "SYMA,SYMB",
|
||||
@@ -3519,7 +3642,7 @@ fn generalize_without_explicit_window_resolves_a_shared_window_and_completes() {
|
||||
#[test]
|
||||
fn generalize_without_explicit_window_resolves_the_intersection_of_all_symbols() {
|
||||
let (cwd, _g) = fresh_project_with_data();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
|
||||
// The resolved shared window persists verbatim in the generated campaign
|
||||
// document; read the (from_ms, to_ms) of the one whose `name` field matches.
|
||||
@@ -3604,7 +3727,7 @@ fn generalize_without_explicit_window_resolves_the_intersection_of_all_symbols()
|
||||
/// before any data access — so it asserts the arity refusal on any machine.
|
||||
#[test]
|
||||
fn generalize_refuses_a_single_instrument() {
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", &fixture, "--real", "GER40",
|
||||
@@ -3620,7 +3743,7 @@ fn generalize_refuses_a_single_instrument() {
|
||||
/// `check_r_metric` pre-check), so this asserts the R-only refusal on any machine.
|
||||
#[test]
|
||||
fn generalize_refuses_a_non_r_metric() {
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", &fixture, "--real", "GER40,USDJPY",
|
||||
@@ -3645,7 +3768,7 @@ fn generalize_refuses_a_non_r_metric() {
|
||||
/// check precedes any geometry/archive lookup, so it asserts on any machine.
|
||||
#[test]
|
||||
fn generalize_refuses_a_duplicate_instrument() {
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", &fixture, "--real", "GER40,GER40",
|
||||
@@ -3670,7 +3793,7 @@ fn generalize_refuses_a_duplicate_instrument() {
|
||||
/// into a multi-cell run whose generalization grade would be ill-defined.
|
||||
#[test]
|
||||
fn generalize_refuses_a_multi_value_axis() {
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", &fixture, "--real", "GER40,USDJPY",
|
||||
@@ -3694,7 +3817,7 @@ fn generalize_refuses_a_multi_value_axis() {
|
||||
/// sweep/walkforward "no axis" refusals. Data-free (fires before any archive access).
|
||||
#[test]
|
||||
fn generalize_refuses_no_axis() {
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", &fixture, "--real", "GER40,USDJPY",
|
||||
@@ -3718,7 +3841,7 @@ fn generalize_refuses_no_axis() {
|
||||
/// `aura sweep` enforces (`aura_sweep_real_blueprint_refuses_a_raw_form_axis_name_before_data_access`).
|
||||
#[test]
|
||||
fn generalize_refuses_an_unknown_axis_name() {
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", &fixture, "--real", "GER40,USDJPY",
|
||||
@@ -3755,7 +3878,7 @@ fn generalize_persists_a_discoverable_cross_instrument_family() {
|
||||
const FROM_MS: &str = "1725148800000";
|
||||
const TO_MS: &str = "1727740799999";
|
||||
let (cwd, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", &fixture, "--real", "GER40,USDJPY",
|
||||
@@ -3817,7 +3940,7 @@ fn generalize_family_members_are_attributed_to_the_right_instrument() {
|
||||
const FROM_MS: &str = "1725148800000";
|
||||
const TO_MS: &str = "1727740799999";
|
||||
let (cwd, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", &fixture, "--real", "GER40,USDJPY",
|
||||
@@ -3884,7 +4007,7 @@ fn generalize_family_members_stamp_project_provenance() {
|
||||
const FROM_MS: &str = "1725148800000";
|
||||
const TO_MS: &str = "1727740799999";
|
||||
let (cwd, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", &fixture, "--real", "GER40,USDJPY",
|
||||
@@ -3931,13 +4054,13 @@ fn generalize_family_members_stamp_project_provenance() {
|
||||
}
|
||||
}
|
||||
|
||||
/// `aura sweep <blueprint.json> --axis <name>=<csv> …` (#166): sweeps a loaded OPEN
|
||||
/// signal over its named param-space axes and persists a discoverable Sweep family.
|
||||
/// Both open knobs (fast/slow) must be bound by axes; the 2×2 grid yields 4 members.
|
||||
/// `aura sweep <blueprint.json> --axis <name>=<csv> …` (#166): sweeps a loaded CLOSED
|
||||
/// blueprint over its named bound-override axes and persists a discoverable Sweep family.
|
||||
/// Both bound knobs (fast/slow) must be re-opened by axes; the 2×2 grid yields 4 members.
|
||||
#[test]
|
||||
fn aura_sweep_loads_a_blueprint_and_persists_a_sweep_family() {
|
||||
let cwd = temp_cwd("blueprint-sweep");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = Command::new(BIN)
|
||||
.args([
|
||||
"sweep", &fixture,
|
||||
@@ -3970,7 +4093,7 @@ fn aura_sweep_loads_a_blueprint_and_persists_a_sweep_family() {
|
||||
/// both are the lying/pointer-less surface this pins.
|
||||
#[test]
|
||||
fn sweep_and_walkforward_refuse_trace_with_a_forward_pointer() {
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
for verb in ["sweep", "walkforward"] {
|
||||
let cwd = temp_cwd(&format!("{verb}-trace-refusal"));
|
||||
let out = Command::new(BIN)
|
||||
@@ -4024,7 +4147,7 @@ fn aura_sweep_persists_the_canonical_blueprint_keyed_by_topology_hash() {
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
let cwd = temp_cwd("blueprint-sweep-store");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = Command::new(BIN)
|
||||
.args([
|
||||
"sweep", &fixture,
|
||||
@@ -4075,12 +4198,13 @@ fn aura_sweep_persists_the_canonical_blueprint_keyed_by_topology_hash() {
|
||||
}
|
||||
|
||||
/// An `--axis` name that does not resolve against the loaded blueprint's param_space
|
||||
/// fails clean (a named BindError, non-zero exit), not a panic. The OPEN fixture has
|
||||
/// sweepable knobs, so a nonsense axis name (`nope`) is genuinely unknown — it names
|
||||
/// neither an open knob nor a bound param (#246: a bound name would re-open instead).
|
||||
/// fails clean (a named BindError, non-zero exit), not a panic. The CLOSED fixture has
|
||||
/// bound-override knobs, so a nonsense axis name (`nope`) is genuinely unknown — it names
|
||||
/// neither a re-openable bound param nor an already-open knob (#246: a bound name would
|
||||
/// re-open instead).
|
||||
#[test]
|
||||
fn aura_sweep_rejects_an_unknown_axis() {
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = Command::new(BIN)
|
||||
.args(["sweep", &fixture, "--axis", "nope=1,2", "--name", "f"])
|
||||
.output()
|
||||
@@ -4101,7 +4225,7 @@ fn aura_sweep_rejects_an_unknown_axis() {
|
||||
#[test]
|
||||
fn aura_reproduce_re_derives_a_persisted_sweep_family() {
|
||||
let cwd = temp_cwd("blueprint-reproduce");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let sweep = Command::new(BIN)
|
||||
.args([
|
||||
"sweep", &fixture,
|
||||
@@ -4142,7 +4266,7 @@ fn aura_reproduce_re_derives_a_persisted_sweep_family() {
|
||||
#[test]
|
||||
fn aura_reproduce_reports_a_diverged_member_and_exits_one() {
|
||||
let cwd = temp_cwd("blueprint-reproduce-diverge");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let sweep = Command::new(BIN)
|
||||
.args([
|
||||
"sweep", &fixture,
|
||||
@@ -4181,7 +4305,7 @@ fn aura_reproduce_reports_a_diverged_member_and_exits_one() {
|
||||
#[test]
|
||||
fn aura_reproduce_re_derives_a_persisted_sweep_bit_identically() {
|
||||
let cwd = temp_cwd("reproduce_roundtrip");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
|
||||
let sweep = std::process::Command::new(BIN)
|
||||
.args([
|
||||
@@ -4265,7 +4389,7 @@ fn aura_mc_over_a_blueprint_reproduces_bit_identically() {
|
||||
#[test]
|
||||
fn aura_walkforward_over_a_blueprint_reproduces_bit_identically() {
|
||||
let cwd = temp_cwd("blueprint-walkforward-reproduce");
|
||||
let bp = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let bp = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let run = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args(["walkforward", &bp, "--axis", "sma_signal.fast.length=2,3",
|
||||
"--axis", "sma_signal.slow.length=4,6", "--name", "wfr"])
|
||||
@@ -4290,7 +4414,7 @@ fn aura_walkforward_over_a_blueprint_reproduces_bit_identically() {
|
||||
#[test]
|
||||
fn aura_walkforward_over_a_blueprint_persists_a_family() {
|
||||
let cwd = temp_cwd("blueprint-walkforward-persist");
|
||||
let bp = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let bp = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args(["walkforward", &bp, "--axis", "sma_signal.fast.length=2,3",
|
||||
"--axis", "sma_signal.slow.length=4,6", "--name", "wfx"])
|
||||
@@ -4311,11 +4435,11 @@ fn aura_walkforward_over_a_blueprint_persists_a_family() {
|
||||
let _ = std::fs::remove_dir_all(&cwd);
|
||||
}
|
||||
|
||||
/// E2E (#173): an OPEN blueprint with no --axis (nothing to re-fit) is a usage
|
||||
/// E2E (#173): a CLOSED blueprint with no --axis (nothing to re-fit) is a usage
|
||||
/// error (exit 2), naming that >= 1 --axis is required.
|
||||
#[test]
|
||||
fn aura_walkforward_over_a_blueprint_rejects_no_axis() {
|
||||
let bp = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let bp = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args(["walkforward", &bp])
|
||||
.output()
|
||||
@@ -4353,7 +4477,7 @@ fn aura_walkforward_over_a_blueprint_rejects_malformed() {
|
||||
/// while leaving the malformed test green.
|
||||
#[test]
|
||||
fn aura_walkforward_over_a_blueprint_rejects_an_unknown_axis() {
|
||||
let bp = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let bp = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args(["walkforward", &bp, "--axis", "nope=1,2"])
|
||||
.output()
|
||||
@@ -4407,7 +4531,7 @@ fn aura_walkforward_emits_an_unknown_axis_rejection_once() {
|
||||
#[test]
|
||||
fn aura_mc_rejects_an_open_blueprint() {
|
||||
let cwd = temp_cwd("mc-blueprint-open-reject");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/tests/fixtures/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = Command::new(BIN)
|
||||
.args(["mc", &fixture, "--seeds", "4"])
|
||||
.current_dir(&cwd)
|
||||
@@ -4427,7 +4551,7 @@ fn aura_mc_rejects_an_open_blueprint() {
|
||||
#[test]
|
||||
fn aura_run_rejects_an_open_blueprint_without_panicking() {
|
||||
let cwd = temp_cwd("run-blueprint-open-reject");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/tests/fixtures/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = Command::new(BIN)
|
||||
.args(["run", &fixture])
|
||||
.current_dir(&cwd)
|
||||
@@ -4484,7 +4608,7 @@ fn aura_reproduce_rejects_an_unknown_family() {
|
||||
#[test]
|
||||
fn aura_reproduce_rejects_a_missing_stored_blueprint() {
|
||||
let cwd = temp_cwd("reproduce_missing_store");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let sweep = std::process::Command::new(BIN)
|
||||
.args([
|
||||
"sweep",
|
||||
@@ -4525,7 +4649,7 @@ fn aura_reproduce_rejects_a_missing_stored_blueprint() {
|
||||
/// user can discover then sweep or re-open without guessing.
|
||||
#[test]
|
||||
fn aura_sweep_list_axes_prints_prefixed_names() {
|
||||
let bp = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let bp = format!("{}/tests/fixtures/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args(["sweep", &bp, "--list-axes"])
|
||||
.output()
|
||||
@@ -4568,7 +4692,7 @@ fn aura_sweep_list_axes_closed_prints_bound_defaults() {
|
||||
/// and takes no other flags. A query cannot also seed a sweep.
|
||||
#[test]
|
||||
fn aura_sweep_list_axes_rejects_other_flags() {
|
||||
let bp = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let bp = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args(["sweep", &bp, "--list-axes", "--axis", "sma_signal.fast.length=2,3"])
|
||||
.output()
|
||||
@@ -4657,7 +4781,7 @@ fn aura_sweep_rejects_malformed_json_house_style() {
|
||||
#[test]
|
||||
fn aura_sweep_list_axes_names_round_trip_into_a_working_sweep() {
|
||||
let cwd = temp_cwd("blueprint-list-axes-roundtrip");
|
||||
let bp = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let bp = format!("{}/tests/fixtures/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
|
||||
// 1) discover the axis names + kinds (do NOT hardcode them) — this is what a user
|
||||
// reads. #246: the fixture now lists a BOUND param (`bias.scale`, F64) alongside
|
||||
@@ -4917,7 +5041,7 @@ fn mc_r_bootstrap_real_e2e_pins_the_exact_current_grade() {
|
||||
const FROM_MS: &str = "1735689600000";
|
||||
const TO_MS: &str = "1767225599000";
|
||||
let (cwd, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"mc", &fixture, "--real", "GER40",
|
||||
@@ -4959,7 +5083,7 @@ fn mc_r_bootstrap_real_e2e_pins_the_exact_current_grade() {
|
||||
/// blueprint through the campaign path, not just the historical r-sma candidate
|
||||
/// — the whole point of dropping `--strategy r-sma`/`--fast`/`--slow` for a
|
||||
/// positional blueprint + generic `--axis`. Every other mc E2E test here still
|
||||
/// exercises `r_sma_open.json`; a regression that silently special-cased the
|
||||
/// exercises `r_sma.json`; a regression that silently special-cased the
|
||||
/// pipeline's axis lookup back to a hardcoded `sma_signal.*` namespace would
|
||||
/// ship green there while breaking every other blueprint. This runs the
|
||||
/// unrelated r-breakout candidate (the ganged `channel_length` axis, no
|
||||
@@ -4974,7 +5098,7 @@ fn mc_dissolves_a_non_r_sma_blueprint() {
|
||||
const FROM_MS: &str = "1735689600000";
|
||||
const TO_MS: &str = "1767225599000";
|
||||
let (cwd, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_breakout_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/tests/fixtures/r_breakout_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"mc", &fixture, "--real", "GER40",
|
||||
@@ -5029,7 +5153,7 @@ fn mc_dissolves_through_the_campaign_path() {
|
||||
const FROM_MS: &str = "1735689600000";
|
||||
const TO_MS: &str = "1767225599000";
|
||||
let (cwd, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"mc", &fixture, "--real", "GER40",
|
||||
@@ -5133,7 +5257,7 @@ fn mc_real_fits_the_injected_roller_to_a_short_window() {
|
||||
return;
|
||||
}
|
||||
let (cwd, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
|
||||
// ~30 days, far shorter than the fixed 90+30-day roller, so the injected
|
||||
// walk_forward cannot fit unless it scales down to the window.
|
||||
@@ -5180,7 +5304,7 @@ fn mc_real_fits_the_injected_roller_to_a_short_window() {
|
||||
#[test]
|
||||
fn mc_dissolved_refuses_a_multi_value_stop() {
|
||||
let cwd = temp_cwd("mc-multi-stop");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"mc", &fixture, "--real", "GER40",
|
||||
@@ -5205,7 +5329,7 @@ fn mc_dissolved_refuses_a_multi_value_stop() {
|
||||
#[test]
|
||||
fn mc_dissolved_refuses_an_unknown_axis_name() {
|
||||
let cwd = temp_cwd("mc-unknown-axis");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"mc", &fixture, "--real", "GER40",
|
||||
@@ -5247,7 +5371,7 @@ fn mc_dissolved_seed_changes_the_bootstrap_draw_not_the_pooled_series() {
|
||||
const FROM_MS: &str = "1735689600000";
|
||||
const TO_MS: &str = "1767225599000";
|
||||
let (cwd, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let run = |seed: &str| {
|
||||
std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
@@ -5310,7 +5434,7 @@ fn walkforward_campaign_runs_an_arbitrary_blueprint() {
|
||||
const FROM_MS: &str = "1735689600000";
|
||||
const TO_MS: &str = "1767225599000";
|
||||
let (cwd, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_breakout_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/tests/fixtures/r_breakout_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"walkforward", &fixture, "--real", "GER40",
|
||||
@@ -5361,7 +5485,7 @@ fn mc_campaign_runs_an_arbitrary_blueprint() {
|
||||
const FROM_MS: &str = "1735689600000";
|
||||
const TO_MS: &str = "1767225599000";
|
||||
let (cwd, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_breakout_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/tests/fixtures/r_breakout_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"mc", &fixture, "--real", "GER40",
|
||||
@@ -5410,7 +5534,7 @@ fn generalize_campaign_runs_an_arbitrary_blueprint() {
|
||||
return;
|
||||
}
|
||||
let (cwd, _g) = fresh_project();
|
||||
let fixture = format!("{}/examples/r_meanrev_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/tests/fixtures/r_meanrev_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", &fixture, "--real", "GER40,USDJPY",
|
||||
@@ -5448,7 +5572,7 @@ fn generalize_campaign_runs_an_arbitrary_blueprint() {
|
||||
#[test]
|
||||
fn walkforward_campaign_refuses_missing_axis() {
|
||||
let cwd = temp_cwd("walkforward-campaign-no-axis");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args(["walkforward", &fixture, "--real", "GER40", "--stop-length", "14", "--stop-k", "2.0"])
|
||||
.current_dir(&cwd)
|
||||
@@ -5464,7 +5588,7 @@ fn walkforward_campaign_refuses_missing_axis() {
|
||||
#[test]
|
||||
fn mc_campaign_refuses_seeds_with_real() {
|
||||
let cwd = temp_cwd("mc-campaign-seeds-mix");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"mc", &fixture, "--real", "GER40", "--seeds", "3",
|
||||
@@ -5485,7 +5609,7 @@ fn mc_campaign_refuses_seeds_with_real() {
|
||||
#[test]
|
||||
fn walkforward_campaign_refuses_a_raw_form_axis_name() {
|
||||
let cwd = temp_cwd("walkforward-campaign-raw-axis");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"walkforward", &fixture, "--real", "GER40",
|
||||
@@ -5506,7 +5630,7 @@ fn walkforward_campaign_refuses_a_raw_form_axis_name() {
|
||||
#[test]
|
||||
fn mc_campaign_refuses_an_unknown_axis() {
|
||||
let cwd = temp_cwd("mc-campaign-unknown-axis");
|
||||
let fixture = format!("{}/examples/r_breakout_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_breakout.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"mc", &fixture, "--real", "GER40",
|
||||
@@ -5534,7 +5658,7 @@ fn mc_campaign_refuses_an_unknown_axis() {
|
||||
#[test]
|
||||
fn mc_campaign_refuses_missing_axis() {
|
||||
let cwd = temp_cwd("mc-campaign-no-axis");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args(["mc", &fixture, "--real", "GER40", "--stop-length", "14", "--stop-k", "2.0"])
|
||||
.current_dir(&cwd)
|
||||
@@ -5590,7 +5714,7 @@ fn shipped_r_sma_example_reproduces_the_builtin_grade() {
|
||||
#[test]
|
||||
fn probe_window_resolves_the_pinned_span_before_the_252_swap() {
|
||||
let (cwd, _g) = fresh_project_with_data();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let window_of = |name: &str| -> (i64, i64) {
|
||||
let dir = cwd.join("runs").join("campaigns");
|
||||
let path = std::fs::read_dir(&dir)
|
||||
@@ -5676,7 +5800,7 @@ fn probe_window_resolves_the_pinned_span_before_the_252_swap() {
|
||||
#[test]
|
||||
fn probe_window_still_refuses_a_hostless_zero_bar_window() {
|
||||
let (cwd, _g) = fresh_project_with_data();
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"sweep", &fixture, "--real", "SYMA",
|
||||
|
||||
Vendored
Vendored
Vendored
@@ -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",
|
||||
],
|
||||
|
||||
@@ -102,12 +102,12 @@ fn project_registry_anchors_at_discovered_root_not_invocation_cwd() {
|
||||
let sub = dir.join("src");
|
||||
let runs_dir = dir.join("runs");
|
||||
std::fs::remove_dir_all(&runs_dir).ok();
|
||||
let open_bp =
|
||||
format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let closed_bp =
|
||||
format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"sweep",
|
||||
&open_bp,
|
||||
&closed_bp,
|
||||
"--axis",
|
||||
"sma_signal.fast.length=2,4",
|
||||
"--axis",
|
||||
|
||||
@@ -314,15 +314,16 @@ fn campaign_validate_in_project_reports_referential_tier_end_to_end() {
|
||||
ScratchPath::File(dir.join("ref-bad.campaign.json")),
|
||||
]);
|
||||
|
||||
// Seed one real, content-addressed, open-param blueprint into the
|
||||
// project's own store via a real sweep (mirrors `project_load.rs`'s
|
||||
// anchor test).
|
||||
let open_bp = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
// Seed one real, content-addressed blueprint into the project's own
|
||||
// store via a real sweep over its bound params, which the axes reopen
|
||||
// as overridable defaults (#246) (mirrors `project_load.rs`'s anchor
|
||||
// test).
|
||||
let closed_bp = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let (sweep_out, sweep_code) = run_code_in(
|
||||
&dir,
|
||||
&[
|
||||
"sweep",
|
||||
&open_bp,
|
||||
&closed_bp,
|
||||
"--axis",
|
||||
"sma_signal.fast.length=2,4",
|
||||
"--axis",
|
||||
@@ -955,15 +956,16 @@ fn campaign_register_refuses_invalid_cost_section_and_writes_nothing() {
|
||||
);
|
||||
}
|
||||
|
||||
/// Seed one open-param blueprint into the built demo project's store via a
|
||||
/// real sweep and return its content id (the referential test's recipe).
|
||||
/// Seed one blueprint (its params bound, reopened by the sweep axes per
|
||||
/// #246) into the built demo project's store via a real sweep and return
|
||||
/// its content id (the referential test's recipe).
|
||||
fn seed_blueprint(dir: &Path, name: &str) -> String {
|
||||
let open_bp = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let closed_bp = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let (out, code) = run_code_in(
|
||||
dir,
|
||||
&[
|
||||
"sweep",
|
||||
&open_bp,
|
||||
&closed_bp,
|
||||
"--axis",
|
||||
"sma_signal.fast.length=2,4",
|
||||
"--axis",
|
||||
@@ -3176,8 +3178,8 @@ fn campaign_run_accepts_a_graph_register_seeded_strategy() {
|
||||
ScratchPath::File(dir.join("onramp.process.json")),
|
||||
ScratchPath::File(dir.join("onramp.campaign.json")),
|
||||
]);
|
||||
let open_bp = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let (reg_out, reg_code) = run_code_in(&dir, &["graph", "register", &open_bp]);
|
||||
let closed_bp = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let (reg_out, reg_code) = run_code_in(&dir, &["graph", "register", &closed_bp]);
|
||||
assert_eq!(reg_code, Some(0), "graph register failed: {reg_out}");
|
||||
let bp_id = reg_out
|
||||
.lines()
|
||||
|
||||
@@ -1763,6 +1763,7 @@ mod tests {
|
||||
manifest: RunManifest {
|
||||
commit: "test".to_string(),
|
||||
params: Vec::new(),
|
||||
defaults: Vec::new(),
|
||||
window: (Timestamp(0), Timestamp(0)),
|
||||
seed: 0,
|
||||
broker: "test".to_string(),
|
||||
|
||||
@@ -239,6 +239,7 @@ mod tests {
|
||||
manifest: RunManifest {
|
||||
commit: "test".to_string(),
|
||||
params: Vec::new(),
|
||||
defaults: Vec::new(),
|
||||
window,
|
||||
seed,
|
||||
broker: "test".to_string(),
|
||||
@@ -266,6 +267,7 @@ mod tests {
|
||||
manifest: RunManifest {
|
||||
commit: "t".to_string(),
|
||||
params: Vec::new(),
|
||||
defaults: Vec::new(),
|
||||
window: (Timestamp(0), Timestamp(0)),
|
||||
seed: i as u64,
|
||||
broker: "t".to_string(),
|
||||
|
||||
@@ -34,6 +34,16 @@ pub struct RunManifest {
|
||||
/// self-describing [`Scalar`], so the param's kind (an `i64` length vs an
|
||||
/// `f64` scale) survives into the record instead of collapsing to `f64`.
|
||||
pub params: Vec<(String, Scalar)>,
|
||||
/// The bound params this run did NOT vary — the wrap-prefixed
|
||||
/// `bound_param_space()` of the signal, EXCLUDING any bound param an axis
|
||||
/// reopened (those flow through `params` instead, #246). Complements
|
||||
/// `params` ("what varied") with "what was held": the two are disjoint by
|
||||
/// construction. Empty for every pre-#249 record. One-directional serde
|
||||
/// widening (C14/C18), identical idiom to `selection`/`instrument`/
|
||||
/// `topology_hash` — except a `Vec`, not an `Option`, so it always
|
||||
/// serializes (mirroring `params`), never skipped when empty.
|
||||
#[serde(default)]
|
||||
pub defaults: Vec<(String, Scalar)>,
|
||||
/// The data-window: inclusive `(from, to)` epoch-ns bounds (C12).
|
||||
pub window: (Timestamp, Timestamp),
|
||||
/// The RNG seed (C12 seed-as-input). `0` for a seed-free synthetic run.
|
||||
@@ -298,7 +308,7 @@ mod tests {
|
||||
#[test]
|
||||
fn runmanifest_without_selection_serialises_without_the_key() {
|
||||
let m = RunManifest {
|
||||
commit: "c".into(), params: vec![], window: (Timestamp(0), Timestamp(0)),
|
||||
commit: "c".into(), params: vec![], defaults: vec![], window: (Timestamp(0), Timestamp(0)),
|
||||
seed: 0, broker: "b".into(), selection: None, instrument: None,
|
||||
topology_hash: None,
|
||||
project: None,
|
||||
@@ -317,7 +327,7 @@ mod tests {
|
||||
#[test]
|
||||
fn runmanifest_instrument_round_trips_and_omits_when_none() {
|
||||
let with = RunManifest {
|
||||
commit: "c".into(), params: vec![], window: (Timestamp(0), Timestamp(0)),
|
||||
commit: "c".into(), params: vec![], defaults: vec![], window: (Timestamp(0), Timestamp(0)),
|
||||
seed: 0, broker: "b".into(), selection: None, instrument: Some("GER40".into()),
|
||||
topology_hash: None,
|
||||
project: None,
|
||||
@@ -328,7 +338,7 @@ mod tests {
|
||||
assert_eq!(back.instrument, Some("GER40".to_string()));
|
||||
|
||||
let without = RunManifest {
|
||||
commit: "c".into(), params: vec![], window: (Timestamp(0), Timestamp(0)),
|
||||
commit: "c".into(), params: vec![], defaults: vec![], window: (Timestamp(0), Timestamp(0)),
|
||||
seed: 0, broker: "b".into(), selection: None, instrument: None,
|
||||
topology_hash: None,
|
||||
project: None,
|
||||
@@ -370,7 +380,7 @@ mod tests {
|
||||
commit: Some("deadbeef".into()),
|
||||
};
|
||||
let m = RunManifest {
|
||||
commit: "c".into(), params: vec![], window: (Timestamp(0), Timestamp(0)),
|
||||
commit: "c".into(), params: vec![], defaults: vec![], window: (Timestamp(0), Timestamp(0)),
|
||||
seed: 0, broker: "b".into(), selection: None, instrument: None,
|
||||
topology_hash: None,
|
||||
project: Some(p.clone()),
|
||||
@@ -393,7 +403,7 @@ mod tests {
|
||||
neighbourhood_score: None, n_neighbours: None,
|
||||
};
|
||||
let m = RunManifest {
|
||||
commit: "c".into(), params: vec![], window: (Timestamp(0), Timestamp(0)),
|
||||
commit: "c".into(), params: vec![], defaults: vec![], window: (Timestamp(0), Timestamp(0)),
|
||||
seed: 0, broker: "b".into(), selection: Some(sel.clone()), instrument: None,
|
||||
topology_hash: None,
|
||||
project: None,
|
||||
@@ -531,6 +541,7 @@ mod tests {
|
||||
("sma_slow".to_string(), Scalar::i64(4)),
|
||||
("bias_scale".to_string(), Scalar::f64(0.5)),
|
||||
],
|
||||
defaults: vec![],
|
||||
window: (Timestamp(1), Timestamp(5)),
|
||||
seed: 0,
|
||||
broker: "sim-optimal(pip_size=0.0001)".to_string(),
|
||||
@@ -637,6 +648,7 @@ mod tests {
|
||||
("sma_slow".to_string(), Scalar::i64(4)),
|
||||
("bias_scale".to_string(), Scalar::f64(1.0)),
|
||||
],
|
||||
defaults: vec![],
|
||||
window: (Timestamp(1), Timestamp(6)),
|
||||
seed: 0,
|
||||
broker: "sim-optimal(pip_size=1.0)".to_string(),
|
||||
@@ -654,7 +666,7 @@ mod tests {
|
||||
};
|
||||
assert_eq!(
|
||||
report.to_json(),
|
||||
r#"{"manifest":{"commit":"abc123","params":[["sma_fast",{"I64":2}],["sma_slow",{"I64":4}],["bias_scale",{"F64":1.0}]],"window":[1,6],"seed":0,"broker":"sim-optimal(pip_size=1.0)"},"metrics":{"total_pips":12.0,"max_drawdown":1.0,"bias_sign_flips":1}}"#,
|
||||
r#"{"manifest":{"commit":"abc123","params":[["sma_fast",{"I64":2}],["sma_slow",{"I64":4}],["bias_scale",{"F64":1.0}]],"defaults":[],"window":[1,6],"seed":0,"broker":"sim-optimal(pip_size=1.0)"},"metrics":{"total_pips":12.0,"max_drawdown":1.0,"bias_sign_flips":1}}"#,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -669,6 +681,7 @@ mod tests {
|
||||
("sma_slow".to_string(), Scalar::i64(4)),
|
||||
("bias_scale".to_string(), Scalar::f64(1.0)),
|
||||
],
|
||||
defaults: vec![],
|
||||
window: (Timestamp(1), Timestamp(6)),
|
||||
seed: 0,
|
||||
broker: "sim-optimal(pip_size=1.0)".to_string(),
|
||||
@@ -693,6 +706,7 @@ mod tests {
|
||||
("sma_slow".to_string(), Scalar::i64(4)),
|
||||
("bias_scale".to_string(), Scalar::f64(1.0)),
|
||||
],
|
||||
defaults: vec![],
|
||||
window: (Timestamp(1), Timestamp(6)),
|
||||
seed: 0,
|
||||
broker: "sim-optimal(pip_size=1.0)".to_string(),
|
||||
|
||||
@@ -722,6 +722,7 @@ mod tests {
|
||||
manifest: RunManifest {
|
||||
commit: "test".to_string(),
|
||||
params: Vec::new(),
|
||||
defaults: Vec::new(),
|
||||
window: (Timestamp(0), Timestamp(0)),
|
||||
seed: 0,
|
||||
broker: "test".to_string(),
|
||||
@@ -877,6 +878,7 @@ mod tests {
|
||||
manifest: RunManifest {
|
||||
commit: point.iter().map(|c| c.i64().to_string()).collect::<Vec<_>>().join(","),
|
||||
params: Vec::new(),
|
||||
defaults: Vec::new(),
|
||||
window: (Timestamp(0), Timestamp(0)),
|
||||
seed: 0,
|
||||
broker: "test".to_string(),
|
||||
|
||||
@@ -288,6 +288,7 @@ mod tests {
|
||||
manifest: RunManifest {
|
||||
commit: "t".to_string(),
|
||||
params: Vec::new(),
|
||||
defaults: Vec::new(),
|
||||
window: (Timestamp(0), Timestamp(0)),
|
||||
seed: 0,
|
||||
broker: "t".to_string(),
|
||||
|
||||
@@ -99,6 +99,7 @@ fn run_point(point: &[Cell]) -> RunReport {
|
||||
manifest: RunManifest {
|
||||
commit: "list-sweep-e2e".to_string(),
|
||||
params: Vec::new(),
|
||||
defaults: Vec::new(),
|
||||
window: (Timestamp(0), Timestamp(0)),
|
||||
seed: 0,
|
||||
broker: "test".to_string(),
|
||||
|
||||
@@ -112,6 +112,7 @@ fn run_point(point: &[Cell]) -> RunReport {
|
||||
manifest: RunManifest {
|
||||
commit: "random-sweep-e2e".to_string(),
|
||||
params: Vec::new(),
|
||||
defaults: Vec::new(),
|
||||
window: (Timestamp(0), Timestamp(0)),
|
||||
seed: 0,
|
||||
broker: "test".to_string(),
|
||||
|
||||
@@ -63,6 +63,7 @@ fn run_point(server: &Arc<DataServer>, point: &[Cell], from: Timestamp, to: Time
|
||||
manifest: RunManifest {
|
||||
commit: "ger40-breakout-sweep".to_string(),
|
||||
params: vec![],
|
||||
defaults: vec![],
|
||||
window: (from, to),
|
||||
seed: 0,
|
||||
broker: "sim-optimal(pip_size=1)".to_string(),
|
||||
|
||||
@@ -73,6 +73,7 @@ fn run_point(
|
||||
manifest: RunManifest {
|
||||
commit: "ger40-breakout-wfo".to_string(),
|
||||
params: vec![],
|
||||
defaults: vec![],
|
||||
window: (from, to),
|
||||
seed: 0,
|
||||
broker: "sim-optimal(pip_size=1)".to_string(),
|
||||
|
||||
@@ -396,6 +396,7 @@ pub fn report_from_trace(trace: &[BarTrace], from: Timestamp, to: Timestamp) ->
|
||||
("entry_bar".to_string(), Scalar::i64(3)),
|
||||
("exit_bar".to_string(), Scalar::i64(5)),
|
||||
],
|
||||
defaults: vec![],
|
||||
window: (from, to),
|
||||
seed: 0,
|
||||
broker: "sim-optimal(pip_size=1)".to_string(),
|
||||
|
||||
@@ -65,6 +65,7 @@ fn run_point(server: &Arc<DataServer>, point: &[Cell], from: Timestamp, to: Time
|
||||
manifest: RunManifest {
|
||||
commit: "ger40-breakout-world".to_string(),
|
||||
params: vec![],
|
||||
defaults: vec![],
|
||||
window: (from, to),
|
||||
seed: 0,
|
||||
broker: "sim-optimal(pip_size=1)".to_string(),
|
||||
|
||||
@@ -86,6 +86,7 @@ fn run_sample_over(prices: Vec<(Timestamp, Scalar)>) -> RunReport {
|
||||
("sma_slow".to_string(), Scalar::i64(4)),
|
||||
("bias_scale".to_string(), Scalar::f64(0.5)),
|
||||
],
|
||||
defaults: vec![],
|
||||
window,
|
||||
seed: 0,
|
||||
broker: "sim-optimal(pip_size=0.0001)".to_string(),
|
||||
|
||||
@@ -86,6 +86,7 @@ fn run_sample(window: (Timestamp, Timestamp), source: Box<dyn Source>) -> RunRep
|
||||
("sma_slow".to_string(), Scalar::i64(4)),
|
||||
("bias_scale".to_string(), Scalar::f64(0.5)),
|
||||
],
|
||||
defaults: vec![],
|
||||
window,
|
||||
seed: 0,
|
||||
broker: "sim-optimal(pip_size=0.0001)".to_string(),
|
||||
|
||||
@@ -29,6 +29,8 @@ pub(crate) struct RunReportRead {
|
||||
struct RunManifestRead {
|
||||
commit: String,
|
||||
params: Vec<(String, ScalarRead)>,
|
||||
#[serde(default)]
|
||||
defaults: Vec<(String, ScalarRead)>,
|
||||
window: (Timestamp, Timestamp),
|
||||
seed: u64,
|
||||
broker: String,
|
||||
@@ -73,12 +75,14 @@ impl<'de> Deserialize<'de> for ScalarRead {
|
||||
impl From<RunReportRead> for RunReport {
|
||||
fn from(r: RunReportRead) -> Self {
|
||||
let RunManifestRead {
|
||||
commit, params, window, seed, broker, selection, instrument, topology_hash, project,
|
||||
commit, params, defaults, window, seed, broker, selection, instrument, topology_hash,
|
||||
project,
|
||||
} = r.manifest;
|
||||
RunReport {
|
||||
manifest: RunManifest {
|
||||
commit,
|
||||
params: params.into_iter().map(|(name, v)| (name, v.0)).collect(),
|
||||
defaults: defaults.into_iter().map(|(name, v)| (name, v.0)).collect(),
|
||||
window,
|
||||
seed,
|
||||
broker,
|
||||
|
||||
@@ -816,6 +816,7 @@ mod tests {
|
||||
manifest: RunManifest {
|
||||
commit: "c".to_string(),
|
||||
params: vec![("p".to_string(), Scalar::f64(1.0))],
|
||||
defaults: vec![],
|
||||
window: (Timestamp(1), Timestamp(2)),
|
||||
seed: 0,
|
||||
broker: "b".to_string(),
|
||||
@@ -1182,7 +1183,7 @@ mod tests {
|
||||
params: vec![],
|
||||
report: RunReport {
|
||||
manifest: RunManifest {
|
||||
commit: "c".into(), params: vec![], window: (Timestamp(0), Timestamp(0)),
|
||||
commit: "c".into(), params: vec![], defaults: vec![], window: (Timestamp(0), Timestamp(0)),
|
||||
seed: 0, broker: "b".into(), selection: None, instrument: None,
|
||||
topology_hash: None,
|
||||
project: None,
|
||||
|
||||
@@ -299,6 +299,7 @@ mod tests {
|
||||
RunManifest {
|
||||
commit: "c".to_string(),
|
||||
params: vec![("p".to_string(), Scalar::f64(1.0))],
|
||||
defaults: vec![],
|
||||
window: (Timestamp(1), Timestamp(5)),
|
||||
seed: 0,
|
||||
broker: "sim-optimal(pip_size=0.0001)".to_string(),
|
||||
|
||||
@@ -30,6 +30,7 @@ fn tiny_report() -> RunReport {
|
||||
manifest: RunManifest {
|
||||
commit: "c".to_string(),
|
||||
params: vec![],
|
||||
defaults: vec![],
|
||||
window: (Timestamp(1), Timestamp(2)),
|
||||
seed: 0,
|
||||
broker: "b".to_string(),
|
||||
|
||||
+14
-1
@@ -1032,7 +1032,8 @@ SQN comparability. Each swept member's manifest records the fixed R-defining par
|
||||
beside the floated knobs (reproducible from its own manifest, C18).
|
||||
[HISTORY — the built-in `--strategy` sweep surface was retired with the demos →
|
||||
blueprint-data (#159, cuts 1b-4); the rankable R sweep now runs as `aura sweep
|
||||
<blueprint.json> --axis …` over examples/r_sma_open.json.]
|
||||
<blueprint.json> --axis …` over r_sma_open.json (an example then; relocated to
|
||||
`crates/aura-cli/tests/fixtures/` by #248).]
|
||||
|
||||
**Realization (cycle 0067, #130 + #135).** **#130 (SQN100):** `RMetrics` gains
|
||||
`sqn_normalized = (mean_R/stdev_R)·√(min(n, 100))` — the n-normalized "SQN score"
|
||||
@@ -1210,6 +1211,18 @@ every hand-rolled usage line reads `Usage: aura <verb> …` (#179, cycle 0101);
|
||||
refusal diagnostics stay unprefixed (diagnostics are not usage lines). The
|
||||
machine-first help surface (JSON/manifest help, stdin op-scripts) stays on the
|
||||
#157/C21 track, not this cycle (settled as human/GNU convention compliance).
|
||||
**Amendment (2026-07-13, #249 — two artifact classes, two redundancy budgets).**
|
||||
The data layer the programmatic face emits is a public interface read raw (by
|
||||
humans and LLMs), and its records split into two classes with opposite
|
||||
redundancy budgets: **generated outcome records** (manifests, metrics, family
|
||||
reports) have a single writer at run time — redundancy there cannot drift and
|
||||
is deliberately spent on direct readability; **authored intent artifacts**
|
||||
(blueprints, op-scripts, campaign documents) are author-maintained — every
|
||||
redundancy is a drift site and stays out. Consequence shipped with #249: a run
|
||||
manifest stamps the untouched bound defaults (`defaults`, one-directionally
|
||||
widened beside `params`, which keeps its "what varied" reproduce semantics) so
|
||||
a raw reader of a fully-bound run no longer sees a misleading `"params": []`;
|
||||
the blueprint itself carries no such duplication.
|
||||
|
||||
### C15 — Resampling-as-node; sessions/calendars
|
||||
**Guarantee.** A resampler is a node (finer stream → coarser bar stream),
|
||||
|
||||
Reference in New Issue
Block a user