test(cli): RED — empty --real window refusal misnames the symbol (#242)

An inverted or uncovered --from/--to window on a symbol the archive DOES
hold refuses via the symbol-absence message ("no local data for symbol")
instead of naming the window. RED pin:
run_real_empty_window_refusal_names_the_window_not_the_symbol
(archive-gated). Cause: probe_window routes both empty-in-window cases
through no_real_data although has_symbol already proved presence.

refs #242
This commit is contained in:
2026-07-12 18:07:42 +02:00
parent 72c0b8ad21
commit 394ac5e0ae
+49
View File
@@ -1189,6 +1189,55 @@ fn sweep_real_no_geometry_symbol_refuses_with_exit_1() {
const GER40_SEPT2024_FROM_MS: &str = "1725148800000";
const GER40_SEPT2024_TO_MS: &str = "1727740799999";
/// Property (#242): a `--real` window that holds no bars for a symbol that IS in
/// the archive refuses with a WINDOW-aware message — distinct from the genuinely
/// unknown-symbol refusal. GER40 is present (the covered Sept-2024 window runs),
/// so an *inverted* window (`--from` > `--to`) is empty by construction for any
/// archive — no bar can satisfy `from <= t <= to` — yet the symbol, its geometry,
/// and the month's file all exist. The refusal must name the requested window
/// rather than reuse the symbol-absence message "no local data for symbol", which
/// misattributes an empty WINDOW to a missing SYMBOL. Gated on the local archive;
/// skips cleanly when absent (the project's skip-on-no-data convention), so CI
/// without the archive stays green.
#[test]
fn run_real_empty_window_refusal_names_the_window_not_the_symbol() {
if !local_data_present() {
eprintln!("skip: no local data at {}", data_server::DEFAULT_DATA_PATH);
return;
}
// The covered Sept-2024 window, INVERTED (from > to): `has_symbol("GER40")` is
// window-independent and passes, and the month's file overlaps at date
// granularity, so the empty result is a WINDOW fact, not symbol absence.
let out = std::process::Command::new(BIN)
.args([
"run", "examples/r_sma.json",
"--real", "GER40",
"--from", GER40_SEPT2024_TO_MS, // inverted: from > to,
"--to", GER40_SEPT2024_FROM_MS, // so the in-window bar set is empty
])
.output()
.expect("spawn aura");
let stderr = String::from_utf8_lossy(&out.stderr);
// An empty --real window is still a refusal (exit 1 unchanged); only the
// message changes — the genuinely-unknown-symbol path keeps exit 1 too.
assert_eq!(
out.status.code(),
Some(1),
"an empty --real window still refuses with exit 1; stderr: {stderr}"
);
// The distinction (#242): the empty-window refusal NAMES the window and does
// NOT reuse the wholesale symbol-absence message for a symbol that is present.
assert!(
stderr.to_lowercase().contains("window"),
"empty-window refusal must name the requested window (GER40 IS present), got: {stderr}"
);
assert!(
!stderr.contains("no local data for symbol"),
"empty-window refusal must not reuse the symbol-absence message, got: {stderr}"
);
}
/// Characterization pin (grounding-check ratification for the risk-regime-axis
/// spec): the dissolved real-data sweep member manifest stamps its resolved stop
/// (`stop_length`/`stop_k`) — the default regime here. The R-path stop knobs are