From 04c581a4413d54c62df44e92e6a3d280c3042748 Mon Sep 17 00:00:00 2001 From: Brummel Date: Sat, 27 Jun 2026 00:33:10 +0200 Subject: [PATCH] refactor(0080): relocate FamilySelection/SelectionMode to aura-analysis (refs #136) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The last trading-domain types still defined in aura-engine's report module — the selection-provenance types FamilySelection and SelectionMode — move to aura-analysis, finishing the #136 goal of getting the trading types out of the engine. aura-analysis is the only non-cyclic home that removes them from the engine: RunManifest.selection: Option needs the type and the engine already depends on aura-analysis; aura-registry and aura-cli reach them unchanged via aura-engine's re-export (report.rs pub-re-exports them, lib.rs untouched). Their tests stay in report.rs (one round-trips through RunManifest, which stays in the engine) and reach the types via the re-export. Behaviour-preserving (C1): full suite 665/0 unchanged incl. the C18 goldens, clippy clean, only report.rs and aura-analysis/src/lib.rs change. Staying in the engine (trace-coupled, deferred to the World/C21 layer, not #136): RunManifest, RunReport, summarize. The aura-registry Metric/metric_cmp vocabulary stays in the registry by design — the registry is the trading selection layer, not the domain-free engine (the deflation statistics branch on metric identity, irreducibly domain). See the #136 thread for the rationale. --- crates/aura-analysis/src/lib.rs | 43 ++++++++++++++++++++++++++++++ crates/aura-engine/src/report.rs | 45 +------------------------------- 2 files changed, 44 insertions(+), 44 deletions(-) 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.