test: red executable-spec for #269 — walkforward unknown-axis rejection as bare prose

The rejection must reach stderr as the prose payload alone — no
UnknownKnob(..) Debug frame around it. Fails on today's frame; the
prose fragments already pass, so the sole pinned defect is the frame.

refs #269
This commit is contained in:
2026-07-13 23:17:59 +02:00
parent e8b6878d3b
commit 3d422341eb
+55
View File
@@ -4604,6 +4604,61 @@ fn aura_walkforward_emits_an_unknown_axis_rejection_once() {
} }
} }
/// Property (#269): the walkforward verb's unknown-axis rejection reaches a
/// user's stderr as prose — the same register `aura sweep`'s boundary errors
/// adopted in #247 — never wrapped in the `UnknownKnob("…")` Rust `Debug`
/// frame. The walkforward path already carries a fully-prosed payload INSIDE
/// that wrapper (`axis <name>: names no param of this blueprint … — see …
/// --list-axes`), so the fix sheds the frame rather than authoring new prose:
/// the message that reaches stderr is exactly that payload, the axis named as
/// typed, exit still 2. Data-free — the axis is rejected at the resolution
/// pre-flight before any window runs, so no archive and no project are needed.
///
/// NB: this is the post-#269 contract. The two sibling tests above
/// (`aura_walkforward_over_a_blueprint_rejects_an_unknown_axis`,
/// `aura_walkforward_emits_an_unknown_axis_rejection_once`) still pin the
/// `UnknownKnob` substring — stale pins of the defective frame that the GREEN
/// slice repoints onto the prose fragment.
#[test]
fn walkforward_unknown_axis_rejection_renders_as_prose_not_a_debug_frame() {
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()
.expect("spawn aura walkforward (unknown axis)");
assert_eq!(
out.status.code(),
Some(2),
"an unknown axis stays a usage refusal (exit 2, not a panic): status={:?}",
out.status
);
let stderr = String::from_utf8(out.stderr).expect("utf-8");
// The headline — the whole defect: no Rust `Debug` frame reaches the user.
assert!(
!stderr.contains("UnknownKnob"),
"must not leak the `UnknownKnob(…)` Debug frame around the prose: {stderr}"
);
// The prose payload survives intact — the axis named as typed, the
// names-no-param wording, and the `--list-axes` pointer (the sweep
// sibling's register).
assert!(
stderr.contains("nope"),
"the prose names the offending axis exactly as typed: {stderr}"
);
assert!(
stderr.contains("names no param"),
"the prose carries the boundary payload wording: {stderr}"
);
assert!(
stderr.contains("--list-axes"),
"the prose points at the discovery surface, like the sweep sibling: {stderr}"
);
assert!(
!stderr.contains("panicked"),
"must reject cleanly, never panic: {stderr}"
);
}
/// E2E (acc 2): `aura mc <open blueprint.json>` is rejected with a named error + exit 2 /// E2E (acc 2): `aura mc <open blueprint.json>` is rejected with a named error + exit 2
/// (NOT a panic / exit 101) — MC binds no axis, so a free knob has no binder. /// (NOT a panic / exit 101) — MC binds no axis, so a free knob has no binder.
#[test] #[test]