diff --git a/crates/aura-cli/src/verb_sugar.rs b/crates/aura-cli/src/verb_sugar.rs index 188518f..dcad786 100644 --- a/crates/aura-cli/src/verb_sugar.rs +++ b/crates/aura-cli/src/verb_sugar.rs @@ -953,6 +953,40 @@ mod tests { assert_eq!(g.campaign.presentation.persist_taps, want); } + /// Property (#240): a dissolved `--trace` invocation's generated campaign + /// requests only the taps its own document can produce. Every generated + /// sugar campaign carries an empty cost section (`cost: vec![]`) by + /// construction, so the net-channel tap `net_r_equity` is unproducible and + /// must be excluded — the requested set is the tap vocabulary MINUS the net + /// channel, concretely `["equity", "exposure", "r_equity"]`. Pinned for + /// both trace-bearing translators (sweep + walkforward), which share the + /// one `persist_taps_from` seam; without this the executor later prints an + /// unreachable "add a cost block to the campaign document" remedy for a tap + /// the generator knowingly ordered but its own document cannot produce. + #[test] + fn dissolved_trace_requests_only_producible_taps_excluding_the_net_channel() { + let want = + vec!["equity".to_string(), "exposure".to_string(), "r_equity".to_string()]; + + let sax = axes(); + let mut si = inv(&sax, "probe", &["GER40"], None, "{\"bp\":1}"); + si.trace = true; + let s = translate_sweep(&si).unwrap(); + assert_eq!( + s.campaign.presentation.persist_taps, want, + "sweep --trace must request only producible taps: the generated cost section is empty, so net_r_equity is unproducible and must be dropped" + ); + + let wax = wf_axes(); + let mut wi = inv(&wax, "walkforward", &["GER40"], Some(VolStop { length: 14, k: 2.0 }), "{\"bp\":1}"); + wi.trace = true; + let w = translate_walkforward(&wi, "sqn_normalized", WF_W, SelectRule::Argmax).unwrap(); + assert_eq!( + w.campaign.presentation.persist_taps, want, + "walkforward --trace must request only producible taps: the generated cost section is empty, so net_r_equity is unproducible and must be dropped" + ); + } + #[test] fn translate_walkforward_diverging_regimes_do_not_collide_content_ids() { let ax = wf_axes();