test(cli): RED — sweep/walkforward must refuse --trace with a #224 pointer (#168)

The clap help promises "persists each member's taps" and the chart hint
recommends `aura sweep --trace`, but every blueprint-mode arm discards the flag
(run_blueprint_sweep's `let _ = persist`, the --real sugar's persist_taps: vec![])
— the surface advertises trace-recording the code drops. Pin the decided honest
behaviour: sweep/walkforward refuse --trace up front (exit 2, naming the flag and
pointing forward to the deferred trace feature #224), mirroring the aura run / mc
refusals.

refs #168
This commit is contained in:
2026-07-09 23:04:12 +02:00
parent f6d80486cd
commit 53bbcedeec
+56
View File
@@ -2730,6 +2730,62 @@ fn aura_sweep_loads_a_blueprint_and_persists_a_sweep_family() {
let _ = std::fs::remove_dir_all(&cwd);
}
/// Property (#168, refuse-don't-lie): `aura sweep`/`aura walkforward` must REFUSE
/// `--trace` with a forward-pointer to the deferred per-member-trace feature (#224),
/// never silently accept it. The clap help ("also persists each member's taps") and
/// the chart `NotFound` hint ("run `aura sweep --trace` first") advertise
/// trace-recording, but no blueprint-mode arm persists per-member taps —
/// `run_blueprint_sweep` reads `let _ = persist;` and the dissolved `--real` sugar
/// sets `persist_taps: vec![]` — so a bare accept makes the surface lie. This mirrors
/// the existing `aura run` / `aura mc` `--trace` refusals (exit 2, refuse-don't-guess).
/// Driven over the SYNTHETIC path (both open knobs bound, no `--real`), so the test is
/// autonomous: no recorded archive, no project. Today `sweep --trace` exits 0 (silent
/// accept) and `walkforward --trace` exits 2 with a GENERIC usage string (no #224) —
/// 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"));
for verb in ["sweep", "walkforward"] {
let cwd = temp_cwd(&format!("{verb}-trace-refusal"));
let out = Command::new(BIN)
.args([
verb,
&fixture,
"--axis",
"sma_signal.fast.length=2,4",
"--axis",
"sma_signal.slow.length=8,16",
"--trace",
"fam",
])
.current_dir(&cwd)
.output()
.expect("spawn aura <verb> --trace");
assert_eq!(
out.status.code(),
Some(2),
"`aura {verb} --trace` must be refused (exit 2); got {:?}, stderr: {}",
out.status,
String::from_utf8_lossy(&out.stderr),
);
let stderr = String::from_utf8_lossy(&out.stderr);
assert!(
stderr.contains("--trace"),
"`aura {verb}` refusal names the offending flag: {stderr}"
);
assert!(
stderr.contains("#224"),
"`aura {verb}` refusal points forward to the deferred trace feature (#224): {stderr}"
);
assert!(
out.stdout.is_empty(),
"`aura {verb} --trace` must emit no report on stdout: {}",
String::from_utf8_lossy(&out.stdout),
);
let _ = std::fs::remove_dir_all(&cwd);
}
}
/// Property (#158/#164, C18/C11/C12): a blueprint sweep content-addresses its topology
/// — the canonical blueprint is persisted ONCE under `runs/blueprints/<topology_hash>.json`,
/// keyed by the very SHA256 every member's manifest carries, holding exactly the bytes