Skip to main content

zeitgeist_protocol/
zeitgeist.rs

1//! Zeitgeist — the composite CRDT semilattice
2
3use serde::{Deserialize, Serialize};
4
5use crate::precision::PrecisionState;
6use crate::confidence::ConfidenceState;
7use crate::trajectory::TrajectoryState;
8use crate::consensus::ConsensusState;
9use crate::temporal::TemporalState;
10
11/// Alignment report returned by constraint checking
12#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
13pub struct AlignmentReport {
14    pub aligned: bool,
15    pub violations: Vec<String>,
16}
17
18/// The Zeitgeist — composite CRDT capturing five dimensions of agent alignment.
19///
20/// Merge is a CRDT semilattice operation:
21/// - Commutative: merge(a,b) == merge(b,a)
22/// - Associative: merge(merge(a,b),c) == merge(a,merge(b,c))
23/// - Idempotent: merge(a,a) == a
24#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
25pub struct Zeitgeist {
26    pub precision: PrecisionState,
27    pub confidence: ConfidenceState,
28    pub trajectory: TrajectoryState,
29    pub consensus: ConsensusState,
30    pub temporal: TemporalState,
31}
32
33impl Zeitgeist {
34    pub fn new(
35        precision: PrecisionState,
36        confidence: ConfidenceState,
37        trajectory: TrajectoryState,
38        consensus: ConsensusState,
39        temporal: TemporalState,
40    ) -> Self {
41        Self { precision, confidence, trajectory, consensus, temporal }
42    }
43
44    pub fn default() -> Self {
45        Self {
46            precision: PrecisionState::default(),
47            confidence: ConfidenceState::default(),
48            trajectory: TrajectoryState::default(),
49            consensus: ConsensusState::default(),
50            temporal: TemporalState::default(),
51        }
52    }
53
54    /// Merge two zeitgeists (CRDT semilattice).
55    /// Each sub-field merges independently with its own semilattice rule.
56    pub fn merge(&self, other: &Self) -> Self {
57        Self {
58            precision: self.precision.merge(&other.precision),
59            confidence: self.confidence.merge(&other.confidence),
60            trajectory: self.trajectory.merge(&other.trajectory),
61            consensus: self.consensus.merge(&other.consensus),
62            temporal: self.temporal.merge(&other.temporal),
63        }
64    }
65
66    /// Encode to CBOR bytes
67    pub fn encode(&self) -> Vec<u8> {
68        let mut buf = Vec::new();
69        ciborium::into_writer(self, &mut buf)
70            .expect("CBOR encoding should not fail for Zeitgeist");
71        buf
72    }
73
74    /// Decode from CBOR bytes
75    pub fn decode(data: &[u8]) -> Result<Self, String> {
76        ciborium::from_reader(data)
77            .map_err(|e| format!("CBOR decode error: {}", e))
78    }
79
80    /// Check alignment constraints across all five dimensions
81    pub fn check_alignment(&self) -> AlignmentReport {
82        let mut violations = Vec::new();
83        violations.extend(self.precision.check_alignment());
84        violations.extend(self.confidence.check_alignment());
85        violations.extend(self.trajectory.check_alignment());
86        violations.extend(self.consensus.check_alignment());
87        violations.extend(self.temporal.check_alignment());
88        let aligned = violations.is_empty();
89        AlignmentReport { aligned, violations }
90    }
91}