diff --git a/crates/aura-cli/src/main.rs b/crates/aura-cli/src/main.rs index f4b6990..2f0731b 100644 --- a/crates/aura-cli/src/main.rs +++ b/crates/aura-cli/src/main.rs @@ -3998,6 +3998,69 @@ mod tests { let _ = std::fs::remove_dir_all(&dir); } + #[test] + fn reproduce_re_derives_the_member_stop_regime_not_the_default() { + // Property: reproduce re-runs each member under the SAME stop regime the member + // was minted with (its manifest stamps stop_length/stop_k) — the stop defines + // the risk unit R and is part of the member's identity (C1). A family minted + // under a NON-default vol-stop regime (a campaign risk-regime cell, or wf/mc/ + // generalize with --stop-length/--stop-k) must still reproduce bit-identically; + // silently re-running it under the default Vol{3,2.0} reports a spurious DIVERGED. + let dir = std::env::temp_dir().join(format!("aura-repro-stop-{}", std::process::id())); + let _ = std::fs::remove_dir_all(&dir); + std::fs::create_dir_all(&dir).expect("temp dir"); + let reg = Registry::open(dir.join("runs.jsonl")); + + let env = project::Env::std(); + let data = DataSource::Synthetic; + // A CLOSED blueprint (both SMA knobs bound): its wrapped param_space is empty, so + // the stop regime is the ONLY dimension that can differ between mint and reproduce + // — isolating the defect to the hardcoded reproduce-side stop. + let closed = load_closed_r_sma(); + let doc = blueprint_to_json(&closed).expect("serializes"); + let reload = || blueprint_from_json(&doc, &|t| std_vocabulary(t)).expect("loads"); + let topo = topology_hash(&reload()); + let space = blueprint_axis_probe(&doc, &env).param_space(); + let pip = data.pip_size(); + let window = data.full_window(&env); + + // Mint one member under a NON-default vol-stop regime (default is length=3, k=2.0). + // run_blueprint_member stamps stop_length=8/stop_k=4.0 into the manifest params. + let non_default = StopRule::Vol { length: 8, k: 4.0 }; + let report = run_blueprint_member( + reload(), + &[], + &space, + data.run_sources(&env), + window, + 0, + pip, + &topo, + &env, + non_default, + ); + + // persist exactly as the sweep/campaign paths do: store the blueprint, append the family. + let canonical = blueprint_to_json(&reload()).unwrap(); + reg.put_blueprint(&topo, &canonical).expect("store blueprint"); + let id = reg + .append_family("stoprepro", FamilyKind::Sweep, &[report]) + .expect("append"); + + // reproduce: the member re-derives bit-identically only if reproduce honours the + // manifest's recorded stop regime — currently DIVERGED because reproduce hardcodes + // the default Vol{3,2.0} for both the param-space probe and the member re-run. + let rep = reproduce_family_in(®, &id, &data, &env); + assert_eq!(rep.outcomes.len(), 1, "one member reproduced"); + assert!( + rep.outcomes.iter().all(|(_, ok)| *ok), + "the non-default-stop member re-derives bit-identically: {:?}", + rep.outcomes + ); + + let _ = std::fs::remove_dir_all(&dir); + } + #[test] fn reproduce_family_re_derives_every_mc_member_bit_identically() { let dir = std::env::temp_dir().join(format!("aura-repro-mc-{}", std::process::id()));