From ae809af85f6687ae21d7e2f7140aa88354c446cc Mon Sep 17 00:00:00 2001 From: main Date: Fri, 20 Mar 2026 21:40:07 -0400 Subject: Add tabbed navigator and managed libgrid UI --- crates/fidget-spinner-store-sqlite/src/lib.rs | 67 +++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'crates/fidget-spinner-store-sqlite/src/lib.rs') diff --git a/crates/fidget-spinner-store-sqlite/src/lib.rs b/crates/fidget-spinner-store-sqlite/src/lib.rs index 3680471..283f5d3 100644 --- a/crates/fidget-spinner-store-sqlite/src/lib.rs +++ b/crates/fidget-spinner-store-sqlite/src/lib.rs @@ -490,6 +490,22 @@ pub struct FrontierOpenProjection { pub open_experiments: Vec, } +#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +pub struct FrontierMetricPoint { + pub experiment: ExperimentSummary, + pub hypothesis: HypothesisSummary, + pub value: f64, + pub verdict: FrontierVerdict, + pub closed_at: OffsetDateTime, +} + +#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +pub struct FrontierMetricSeries { + pub frontier: FrontierRecord, + pub metric: MetricKeySummary, + pub points: Vec, +} + pub struct ProjectStore { project_root: Utf8PathBuf, state_root: Utf8PathBuf, @@ -1381,6 +1397,57 @@ impl ProjectStore { }) } + pub fn frontier_metric_series( + &self, + frontier: &str, + key: &NonEmptyText, + include_rejected: bool, + ) -> Result { + let frontier = self.resolve_frontier(frontier)?; + let definition = self + .metric_definition(key)? + .ok_or_else(|| StoreError::UnknownMetricDefinition(key.clone()))?; + let mut points = self + .load_experiment_records(Some(frontier.id), None, true)? + .into_iter() + .filter(|record| record.status == ExperimentStatus::Closed) + .filter_map(|record| { + let outcome = record.outcome.clone()?; + if !include_rejected && outcome.verdict == FrontierVerdict::Rejected { + return None; + } + let metric = all_metrics(&outcome) + .into_iter() + .find(|metric| metric.key == *key)?; + Some((record, outcome, metric.value)) + }) + .map(|(record, outcome, value)| { + Ok(FrontierMetricPoint { + closed_at: outcome.closed_at, + experiment: self.experiment_summary_from_record(record.clone())?, + hypothesis: self.hypothesis_summary_from_record( + self.hypothesis_by_id(record.hypothesis_id)?, + )?, + value, + verdict: outcome.verdict, + }) + }) + .collect::, StoreError>>()?; + points.sort_by_key(|point| point.closed_at); + Ok(FrontierMetricSeries { + metric: MetricKeySummary { + key: definition.key.clone(), + unit: definition.unit, + objective: definition.objective, + visibility: definition.visibility, + description: definition.description, + reference_count: self.metric_reference_count(Some(frontier.id), key)?, + }, + frontier, + points, + }) + } + pub fn metric_keys(&self, query: MetricKeysQuery) -> Result, StoreError> { let frontier_id = query .frontier -- cgit v1.2.3