fix(cli): aura run refuses an unrunnable blueprint cleanly, not by panic (#282)
Two user-authorable blueprint shapes crashed `aura run` with an internal .expect instead of the CLI's clean aura: refusal register: - a tap wire pointing out of range: run_signal_r's compile now handles CompileError (TapWireOutOfRange) as an aura: refusal + exit 1, naming that the blueprint does not compile to a runnable harness. - an exposed output not named bias: a pre-check in dispatch_run (the single loaded-blueprint call site, before the free-knob axis probe that welds the hardcoded bias port and would itself panic) refuses with a message telling the user aura run expects a strategy with a bias output and listing what the blueprint exposes. The sweep path (run_blueprint_member) is untouched. Surfaced by the measurement-milestone fieldtest as the sharp edge of raw-index tap authoring (#284 tracks the name-addressed tap op that removes the miscount class at the source). closes #282
This commit is contained in:
@@ -1748,9 +1748,10 @@ fn run_signal_r(
|
|||||||
let (tx_req, _rx_req) = mpsc::channel();
|
let (tx_req, _rx_req) = mpsc::channel();
|
||||||
let (sources, window, pip_size) = resolve_run_data(&data, env, &binding);
|
let (sources, window, pip_size) = resolve_run_data(&data, env, &binding);
|
||||||
let wrapped = wrap_r(signal, tx_eq, tx_ex, tx_r, tx_req, StopRule::Vol { length: R_SMA_STOP_LENGTH, k: R_SMA_STOP_K }, false, pip_size, &binding, None);
|
let wrapped = wrap_r(signal, tx_eq, tx_ex, tx_r, tx_req, StopRule::Vol { length: R_SMA_STOP_LENGTH, k: R_SMA_STOP_K }, false, pip_size, &binding, None);
|
||||||
let mut flat = wrapped
|
let mut flat = wrapped.compile_with_params(params).unwrap_or_else(|e| {
|
||||||
.compile_with_params(params)
|
eprintln!("aura: this blueprint does not compile to a runnable harness: {e:?}");
|
||||||
.expect("signal binds + wraps to a valid harness");
|
std::process::exit(1);
|
||||||
|
});
|
||||||
// Bind each declared tap to a fresh `Recorder` + channel, before bootstrap
|
// Bind each declared tap to a fresh `Recorder` + channel, before bootstrap
|
||||||
// — `flat.taps` already carries the signal's declared taps hoisted to the
|
// — `flat.taps` already carries the signal's declared taps hoisted to the
|
||||||
// root. Dedup is the caller's per `TapBindError::DuplicateBind`'s doc (the
|
// root. Dedup is the caller's per `TapBindError::DuplicateBind`'s doc (the
|
||||||
@@ -3585,6 +3586,25 @@ fn dispatch_run(a: RunCmd, env: &project::Env) {
|
|||||||
eprintln!("aura: {path}: {msg}");
|
eprintln!("aura: {path}: {msg}");
|
||||||
std::process::exit(2);
|
std::process::exit(2);
|
||||||
});
|
});
|
||||||
|
// `wrap_r` (below, via `run_signal_r` AND the axis probe right here) welds
|
||||||
|
// the loaded signal by its hardcoded `"bias"` output port (the R-evaluator
|
||||||
|
// contract). A signal exposing any other output shape (a measurement-only
|
||||||
|
// blueprint) would otherwise only surface as `blueprint_axis_probe`'s
|
||||||
|
// `wrap_r` call panicking on `BuildError::UnknownOutPort` a few lines
|
||||||
|
// down — refuse here instead, before that probe runs.
|
||||||
|
if !signal.output().iter().any(|o| o.name == "bias") {
|
||||||
|
let exposed: Vec<&str> = signal.output().iter().map(|o| o.name.as_str()).collect();
|
||||||
|
eprintln!(
|
||||||
|
"aura: `aura run` expects a strategy with a bias output; this blueprint \
|
||||||
|
exposes {}",
|
||||||
|
if exposed.is_empty() {
|
||||||
|
"no outputs".to_string()
|
||||||
|
} else {
|
||||||
|
exposed.join(", ")
|
||||||
|
}
|
||||||
|
);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
// Refuse an open (free-knob) blueprint at the dispatch boundary, mirroring
|
// Refuse an open (free-knob) blueprint at the dispatch boundary, mirroring
|
||||||
// `blueprint_mc_family`'s closed-guard: `run` bootstraps over the EMPTY point, so a
|
// `blueprint_mc_family`'s closed-guard: `run` bootstraps over the EMPTY point, so a
|
||||||
// free knob would panic in `compile_with_params` — reject it clean instead (#176).
|
// free knob would panic in `compile_with_params` — reject it clean instead (#176).
|
||||||
|
|||||||
Reference in New Issue
Block a user