diff --git a/crates/aura-analysis/src/lib.rs b/crates/aura-analysis/src/lib.rs index e9a2fe3..30d90a5 100644 --- a/crates/aura-analysis/src/lib.rs +++ b/crates/aura-analysis/src/lib.rs @@ -9,6 +9,49 @@ use aura_core::{Scalar, Timestamp}; +/// Which selection objective produced the record (additive provenance, C23). +/// `Argmax` is the bare-best pick (cycle 0076), deflated for the number of trials. +/// `PlateauMean` / `PlateauWorst` (cycle 0077) argmax the neighbourhood-smoothed +/// surface instead, so peak-vs-plateau runs stay distinguishable on this field. +#[derive(Clone, Copy, Debug, PartialEq, serde::Serialize, serde::Deserialize)] +pub enum SelectionMode { + Argmax, + PlateauMean, + PlateauWorst, +} + +/// Selection-provenance for a sweep winner. The selection RULE (`mode`) and its +/// ANNOTATION are orthogonal: `Argmax` carries the trials-deflation annotation +/// (`deflated_score` / `overfit_probability` / `n_resamples` / `block_len` / +/// `seed`); `Plateau*` carries the smoothing annotation (`neighbourhood_score` / +/// `n_neighbours`). Each annotation is `Option`, present iff its rule produced the +/// record; all are additive — recorded, never re-ranking (C23). A legacy line +/// (pre-0077) carries the deflation scalars as bare values that deserialize to +/// `Some` (serde default), so it still loads (C14/C18). +#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct FamilySelection { + pub selection_metric: String, + pub n_trials: usize, + pub raw_winner_metric: f64, + pub mode: SelectionMode, + // deflation annotation (present iff mode == Argmax with a deflation run) + #[serde(default, skip_serializing_if = "Option::is_none")] + pub deflated_score: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub overfit_probability: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub n_resamples: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub block_len: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub seed: Option, + // plateau annotation (present iff mode is Plateau*) + #[serde(default, skip_serializing_if = "Option::is_none")] + pub neighbourhood_score: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub n_neighbours: Option, +} + /// Summary metrics reduced from a run's recorded streams — the `-> metrics` /// half of C12's atomic sim unit. Pure function of the recorded streams. #[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)] diff --git a/crates/aura-engine/src/report.rs b/crates/aura-engine/src/report.rs index 725eb6d..b7ca5a9 100644 --- a/crates/aura-engine/src/report.rs +++ b/crates/aura-engine/src/report.rs @@ -19,52 +19,9 @@ use std::collections::HashMap; // at the engine boundary, so it stays here. pub use aura_analysis::{ derive_position_events, expected_max_of_normals, inv_norm_cdf, r_metrics_from_rs, summarize_r, - PositionAction, PositionEvent, RMetrics, RunMetrics, + FamilySelection, PositionAction, PositionEvent, RMetrics, RunMetrics, SelectionMode, }; -/// Which selection objective produced the record (additive provenance, C23). -/// `Argmax` is the bare-best pick (cycle 0076), deflated for the number of trials. -/// `PlateauMean` / `PlateauWorst` (cycle 0077) argmax the neighbourhood-smoothed -/// surface instead, so peak-vs-plateau runs stay distinguishable on this field. -#[derive(Clone, Copy, Debug, PartialEq, serde::Serialize, serde::Deserialize)] -pub enum SelectionMode { - Argmax, - PlateauMean, - PlateauWorst, -} - -/// Selection-provenance for a sweep winner. The selection RULE (`mode`) and its -/// ANNOTATION are orthogonal: `Argmax` carries the trials-deflation annotation -/// (`deflated_score` / `overfit_probability` / `n_resamples` / `block_len` / -/// `seed`); `Plateau*` carries the smoothing annotation (`neighbourhood_score` / -/// `n_neighbours`). Each annotation is `Option`, present iff its rule produced the -/// record; all are additive — recorded, never re-ranking (C23). A legacy line -/// (pre-0077) carries the deflation scalars as bare values that deserialize to -/// `Some` (serde default), so it still loads (C14/C18). -#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)] -pub struct FamilySelection { - pub selection_metric: String, - pub n_trials: usize, - pub raw_winner_metric: f64, - pub mode: SelectionMode, - // deflation annotation (present iff mode == Argmax with a deflation run) - #[serde(default, skip_serializing_if = "Option::is_none")] - pub deflated_score: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub overfit_probability: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub n_resamples: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub block_len: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub seed: Option, - // plateau annotation (present iff mode is Plateau*) - #[serde(default, skip_serializing_if = "Option::is_none")] - pub neighbourhood_score: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub n_neighbours: Option, -} - /// The reproducible run descriptor (C18). **Caller-supplied**: the engine /// cannot introspect a git commit, an RNG seed, or a broker label — the World /// that bootstraps and runs the harness fills these in.