Skip to main content

dirtydata_observer/
divergence.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3use dirtydata_core::types::{StableId, Hash, Timestamp};
4
5/// 世界がズレた瞬間を記録する
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct DivergencePoint {
8    pub sample_index: u64,
9    pub node_id: StableId,
10    pub node_name: String,
11    pub port_idx: usize,
12    pub expected_value: [f32; 2],
13    pub actual_value: [f32; 2],
14    pub diff_magnitude: f32,
15}
16
17/// Divergence Map — オーディオのリアリティにおける分岐の地図
18#[derive(Debug, Clone, Serialize, Deserialize, Default)]
19pub struct DivergenceMap {
20    pub points: Vec<DivergencePoint>,
21    pub golden_hash: Option<Hash>,
22    pub actual_hash: Option<Hash>,
23    pub first_divergence_index: Option<u64>,
24    pub timestamp: Timestamp,
25    pub metadata: HashMap<String, String>,
26}
27
28impl DivergenceMap {
29    pub fn new() -> Self {
30        Self {
31            timestamp: Timestamp::now(),
32            ..Default::default()
33        }
34    }
35
36    pub fn add_point(&mut self, point: DivergencePoint) {
37        if self.first_divergence_index.is_none() {
38            self.first_divergence_index = Some(point.sample_index);
39        }
40        self.points.push(point);
41    }
42
43    pub fn is_diverged(&self) -> bool {
44        !self.points.is_empty()
45    }
46}
47
48/// 因果比較 — A/B 比較を超えた、変更の影響分析
49#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct CausalAnalysis {
51    pub parameter_delta: Vec<(StableId, String, f32, f32)>, // node, param, val_a, val_b
52    pub divergence_magnitude_db: f32,
53    pub peak_divergence_sample: u64,
54    pub transient_impact: f32, // Simplified for now
55}
56
57impl CausalAnalysis {
58    pub fn from_divergence(map: &DivergenceMap) -> Self {
59        let max_mag = map.points.iter().map(|p| p.diff_magnitude).fold(0.0, f32::max);
60        let peak_sample = map.points.iter().find(|p| p.diff_magnitude >= max_mag).map(|p| p.sample_index).unwrap_or(0);
61        
62        Self {
63            parameter_delta: Vec::new(), // Populate this from Graph diff
64            divergence_magnitude_db: 20.0 * max_mag.log10().max(-100.0),
65            peak_divergence_sample: peak_sample,
66            transient_impact: max_mag * 1.5, // Dummy heuristic
67        }
68    }
69}