pub struct SecondOpinionInfo {
pub tried: Vec<String>,
pub promoted_by: Option<String>,
pub base_status: String,
pub base_iteration_count: usize,
pub rung_iteration_counts: Vec<usize>,
pub total_iteration_count: usize,
}Expand description
The second-opinion ladder’s record: which rungs ran, which (if any) was promoted, and what the base solve did before any of it (gh #850).
§Why the base solve’s numbers are the point
On a promotion the reported status and statistics.iteration_count both
become the promoted rung’s, and nothing else in the report says the base
solver failed. That makes a lost solve indistinguishable from a faster
one, and it is worse than a gap in the evidence: it produces positive
evidence for the wrong conclusion.
The case that exposed it is square_flowsheet_resto, where v0.10.0’s
base solver converged in 116 iterations and HEAD’s does not converge at all
— RestorationFailed at 131 — with the answer coming from a ladder rung
(start_point_perturbation=1e-2) added in the same release, which promotes
at 54. scripts/sweep-fixtures.sh read that as 116 -> 54, a 2× win.
The cost is understated on top of that: statistics.iteration_count is the
promoted rung’s alone, so the fixture’s true cost is 131 + 54, 3.4× what
the report says. Self::total_iteration_count is the honest number.
This is the same shape of invisibility the sweep’s engine column was added to close, and CLAUDE.md’s rule applies verbatim: a line whose only moving field is “solved directly” → “promoted from a rung” is a trajectory change, and is as reportable as a moved iteration count.
Fields§
§tried: Vec<String>Rung labels actually run, in order.
promoted_by: Option<String>The rung whose re-solve was promoted, or None when the original
verdict survived every rung and shipped unchanged.
base_status: StringThe verdict the ladder was opened on, before any rung ran.
base_iteration_count: usizeIterations the base solve spent. Not included in
statistics.iteration_count when a rung was promoted.
rung_iteration_counts: Vec<usize>Iterations each rung in tried spent, in the same order.
total_iteration_count: usizeBase plus every rung: what the solve actually cost.
Trait Implementations§
Source§impl Clone for SecondOpinionInfo
impl Clone for SecondOpinionInfo
Source§fn clone(&self) -> SecondOpinionInfo
fn clone(&self) -> SecondOpinionInfo
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for SecondOpinionInfo
impl Debug for SecondOpinionInfo
Source§impl<'de> Deserialize<'de> for SecondOpinionInfo
impl<'de> Deserialize<'de> for SecondOpinionInfo
Source§fn deserialize<__D>(
__deserializer: __D,
) -> Result<SecondOpinionInfo, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(
__deserializer: __D,
) -> Result<SecondOpinionInfo, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
Source§impl Serialize for SecondOpinionInfo
impl Serialize for SecondOpinionInfo
Source§fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
Auto Trait Implementations§
impl Freeze for SecondOpinionInfo
impl RefUnwindSafe for SecondOpinionInfo
impl Send for SecondOpinionInfo
impl Sync for SecondOpinionInfo
impl Unpin for SecondOpinionInfo
impl UnsafeUnpin for SecondOpinionInfo
impl UnwindSafe for SecondOpinionInfo
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
impl<T, U> Imply<T> for U
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more