Skip to main content

dirtydata_intent/
attribution.rs

1use serde::{Deserialize, Serialize};
2use dirtydata_core::types::{StableId, IntentId, PatchId, Timestamp};
3use dirtydata_core::patch::Patch;
4
5/// 音の「犯人」を追跡する
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct SoundTrace {
8    pub sample_index: u64,
9    pub node_id: StableId,
10    pub parameter_name: String,
11    pub value: f32,
12    pub attribution: Attribution,
13}
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct Attribution {
17    pub intent_id: Option<IntentId>,
18    pub intent_description: Option<String>,
19    pub patch_id: PatchId,
20    pub source: String,
21    pub timestamp: Timestamp,
22    pub commit_hash: Option<String>, // if available
23}
24
25pub struct Attributor;
26
27impl Attributor {
28    /// 特定のノードの特定のパラメータに最後に影響を与えたパッチを探す
29    pub fn trace_parameter(
30        node_id: StableId,
31        param_name: &str,
32        patches: &[Patch],
33    ) -> Option<Attribution> {
34        // 後ろから(最新から)探す
35        for patch in patches.iter().rev() {
36            for op in &patch.operations {
37                match op {
38                    dirtydata_core::patch::Operation::ModifyConfig { node_id: id, delta } if *id == node_id => {
39                        if delta.contains_key(param_name) {
40                            return Some(Attribution {
41                                intent_id: patch.intent_ref,
42                                intent_description: None, // Need IntentState to look this up
43                                patch_id: patch.identity,
44                                source: format!("{:?}", patch.source),
45                                timestamp: patch.timestamp,
46                                commit_hash: None, // Could be stored in Patch metadata
47                            });
48                        }
49                    }
50                    _ => {}
51                }
52            }
53        }
54        None
55    }
56}