fix(aura-research, aura-cli, aura-runner): milestone-fieldtest bugs — the unwired ramp hole + three diagnostics

RED-first fixes for the four M42 A/B findings. campaign introspect
--unwired now drills into a present-but-empty presentation section
exactly as it drills into data, listing persist_taps/emit as open slots
— the miss caused three of the cold start's five dead ends (the process
sibling has no analogous nested-required shape, verified). The override
panic catch wraps known non-diagnostic payloads (capacity overflow) in
domain prose while passing real constructor messages through
byte-identical; a kind-mismatched override renders as prose naming
path, expected and got kinds with a write-this example instead of the
ParamKindMismatch debug struct; chart's unknown-handle refusal names
the current trace surface (exec --tap / presentation.persist_taps)
instead of the retired --trace flag.

closes #319
This commit is contained in:
2026-07-26 00:37:28 +02:00
parent e6b60bf680
commit 77ad0465cb
5 changed files with 183 additions and 8 deletions
+20 -2
View File
@@ -430,7 +430,8 @@ fn render_chart_by_kind(
eprintln!(
"aura: no recorded run or family '{name}' under runs/traces \
(check the handle a sweep/walk-forward/campaign run printed for a typo — \
re-running with this handle as `--trace` will not create it)"
a trace is produced by `aura exec --tap <NODE.FIELD>=<FOLD>` on a blueprint \
or a campaign's `presentation.persist_taps` section, not by naming a handle here)"
);
std::process::exit(1);
}
@@ -1069,6 +1070,23 @@ document declares its persisted taps itself"
}
}
/// Bug 2 (#319 fieldtest cycle 2): `catch_member_panic`'s payload is either a
/// node's own constructor message (e.g. `Sma::new`'s "SMA length must be >= 1")
/// — already a real diagnostic, rendered verbatim (existing tests pin it
/// byte-identical) — or a raw library/allocator panic string that names no
/// domain rule of any node at all (a negative length overflows the ring-buffer
/// allocation before the SMA's own check ever runs). The latter is not a
/// diagnostic; wrap only the known non-diagnostic payloads in prose that
/// tells the caller what actually happened, keeping the raw string as
/// parenthetical detail rather than the whole message.
fn panic_refusal_prose(msg: &str) -> String {
if msg == "capacity overflow" {
format!("param value out of domain for this node (panic: {msg}) — check the param's valid range")
} else {
msg.to_string()
}
}
/// The `exec` blueprint leg (#319): a synthetic single run of a fully-bound
/// blueprint envelope, composed 1:1 from `dispatch_run`'s `.json`-branch
/// building blocks — same intake gate, same shape dispatch (a `bias` output
@@ -1199,7 +1217,7 @@ fn exec_blueprint_leg(path: &str, overrides: &[String], tap: &[String], env: &au
run_signal_r(signal, &params, RunData::Synthetic, 0, env, tap_plan)
})
.unwrap_or_else(|msg| {
eprintln!("aura: {msg}");
eprintln!("aura: {}", panic_refusal_prose(&msg));
std::process::exit(1);
});
println!("{}", report.to_json());