fix(aura-cli): exec --override refuses out-of-domain values and the wrapped form
RED-first fixes for the two field-test bugs on the new flag's blueprint leg, both formerly exit-101 panics. An out-of-domain override value now renders the node constructor's own message as a prose refusal, exit 1 — the single-run bootstrap rides the same catch mechanism the campaign path's #272 per-cell containment uses (a campaign-leg pin confirms the identical value was already contained there, exit 3, unchanged). The retired wrapped axis form refuses before the params zip with a did-you-mean naming the raw node.param namespace and the discovery verb, mirroring the campaign leg's existing prose family. refs #319
This commit is contained in:
@@ -513,6 +513,61 @@ fn exec_override_duplicate_path_refuses_with_usage_not_a_panic() {
|
||||
assert!(out.contains("--override"), "stdout/stderr: {out}");
|
||||
}
|
||||
|
||||
/// BUG B1 (fieldtest, #319 exec --override leg): an out-of-domain override
|
||||
/// value on a bound param panics deep in the node's own constructor
|
||||
/// (`Sma::new`'s `assert!`) instead of refusing — the campaign leg contains
|
||||
/// the identical value as a #272 per-cell fault (exit 3, see
|
||||
/// `aura_sweep_synthetic_member_panic_is_contained`); the single-run leg has
|
||||
/// no cell containment, so the panic must be caught at the dispatch boundary
|
||||
/// and rendered as a runtime-class refusal (exit 1, C14 partition) instead of
|
||||
/// an uncaught exit-101 panic.
|
||||
#[test]
|
||||
fn exec_override_out_of_domain_value_refuses_not_panics() {
|
||||
let (out, code) = run_code(&["exec", "examples/r_sma.json", "--override", "fast.length=0"]);
|
||||
assert_ne!(code, Some(101), "must not panic: {out}");
|
||||
assert_eq!(code, Some(1), "stdout/stderr: {out}");
|
||||
assert!(!out.contains("panicked at"), "no raw panic report reaches the consumer: {out}");
|
||||
assert!(
|
||||
out.contains("SMA length must be >= 1"),
|
||||
"the refusal must name the node's own domain rule: {out}"
|
||||
);
|
||||
}
|
||||
|
||||
/// BUG B1 twin: a negative override value overflows the SMA's ring-buffer
|
||||
/// allocation (`length as usize` on a negative `i64` wraps to a huge
|
||||
/// capacity) — same fault class, different panic message, same required
|
||||
/// treatment (refuse, exit 1, never 101).
|
||||
#[test]
|
||||
fn exec_override_negative_value_refuses_not_panics() {
|
||||
let (out, code) = run_code(&["exec", "examples/r_sma.json", "--override", "fast.length=-3"]);
|
||||
assert_ne!(code, Some(101), "must not panic: {out}");
|
||||
assert_eq!(code, Some(1), "stdout/stderr: {out}");
|
||||
assert!(!out.contains("panicked at"), "no raw panic report reaches the consumer: {out}");
|
||||
assert!(out.contains("capacity overflow"), "stdout/stderr: {out}");
|
||||
}
|
||||
|
||||
/// BUG B2 (fieldtest, #319 exec --override leg): the retired pre-#328
|
||||
/// WRAPPED override form (`<rootname>.<node>.<param>`) panics at the
|
||||
/// params-zip `.expect` in `exec_blueprint_leg` instead of refusing:
|
||||
/// `override_paths` accepts an exact wrapped name too (by design, for
|
||||
/// resolving an already-validated set) so the wrapped token "resolves" there,
|
||||
/// but the zip below looks the ORIGINAL token up by its raw-translated key,
|
||||
/// missing it. Refuse before the zip, mirroring the campaign leg's own
|
||||
/// did-you-mean refusal for the same retired form
|
||||
/// (`RefFault::AxisNotInParamSpace`).
|
||||
#[test]
|
||||
fn exec_override_wrapped_form_path_refuses_not_panics() {
|
||||
let (out, code) =
|
||||
run_code(&["exec", "examples/r_sma.json", "--override", "sma_signal.fast.length=1"]);
|
||||
assert_ne!(code, Some(101), "must not panic: {out}");
|
||||
assert_eq!(code, Some(1), "stdout/stderr: {out}");
|
||||
assert!(!out.contains("panicked at"), "no raw panic report reaches the consumer: {out}");
|
||||
assert!(
|
||||
out.contains("did you mean") && out.contains("fast.length"),
|
||||
"the refusal must name the raw candidate: {out}"
|
||||
);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Task 4: `--override` on the campaign leg.
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -564,6 +619,43 @@ fn exec_campaign_override_reaches_the_member_manifests_raw() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Cross-check (fieldtest B1, #319): the campaign leg's existing #272
|
||||
/// containment already covers an out-of-domain OVERRIDE value, not just a
|
||||
/// document-declared axis value. `bias.scale` is bound-only (not one of
|
||||
/// `campaign_doc_json_for`'s own axes), so `--override bias.scale=-1.0`
|
||||
/// injects a single-value axis of a value the `Bias` node's own constructor
|
||||
/// rejects (`Bias::new` asserts `scale > 0.0`) — must stay the deliberate
|
||||
/// per-cell exit 3, never 101. Pinned here since no existing test drove an
|
||||
/// out-of-domain VALUE through `--override` specifically (only through a
|
||||
/// document's own axis values, e.g. `aura_sweep_synthetic_member_panic_is_contained`).
|
||||
#[test]
|
||||
fn exec_campaign_override_out_of_domain_value_is_contained() {
|
||||
let (dir, _fixture) = fresh_project_with_data();
|
||||
let runs_dir = dir.join("runs");
|
||||
std::fs::remove_dir_all(&runs_dir).ok();
|
||||
let _cleanup = ScratchGuard(vec![
|
||||
ScratchPath::Dir(runs_dir.clone()),
|
||||
ScratchPath::File(dir.join("ovpanic.process.json")),
|
||||
ScratchPath::File(dir.join("ovpanic.campaign.json")),
|
||||
]);
|
||||
let bp_id = seed_blueprint(&dir, "exec-override-panic-seed");
|
||||
let proc_id = register_process_doc(&dir, "ovpanic.process.json", SWEEP_ONLY_PROCESS_DOC);
|
||||
let doc = campaign_doc_json_for("SYMA", &bp_id, &proc_id, (1709251200000, 1719791999999));
|
||||
write_doc(&dir, "ovpanic.campaign.json", &doc);
|
||||
|
||||
let (out, code) =
|
||||
run_code_in(&dir, &["exec", "ovpanic.campaign.json", "--override", "bias.scale=-1.0"]);
|
||||
assert!(
|
||||
out.lines().any(|l| l.contains("aura: warning: ") && l.contains("Bias scale must be > 0")),
|
||||
"the member fault surfaces as one class-marked warning naming the fault: {out}"
|
||||
);
|
||||
assert!(!out.contains("panicked at"), "no raw panic report reaches the consumer: {out}");
|
||||
assert_eq!(
|
||||
code, Some(3),
|
||||
"a contained member fault is the deliberate failed-cells exit 3, never 101: {out}"
|
||||
);
|
||||
}
|
||||
|
||||
/// An override path colliding with a document-declared axis (`fast.length`,
|
||||
/// declared by `campaign_doc_json_for`) refuses: an override overrides a
|
||||
/// bound value, never an axis.
|
||||
|
||||
Reference in New Issue
Block a user