geoit 0.0.2

Exact geometric algebra with governed multivectors
Documentation
use crate::algebra::mv::Mv;
use crate::governance::governance::Governance;
use crate::governance::phase::Phase;
use crate::governance::predicate::Predicate;
use crate::governance::profile::GeneratorProfile;
use crate::governance::reading::{ExtractionError, ReadingRules};
use crate::governance::rule::ProofTerm;
use crate::scalar::Scalar;
use std::sync::Arc;

/// A governed multivector: an Mv verified against a Governance,
/// carrying its proof of satisfaction, phase, profile, and extraction rules.
///
/// Created by `govern()` or `NamedGovernance::govern()`.
/// All fields are immutable — a Geoit is a certified fact.
///
/// Uses `Arc<Governance>` for efficient sharing. Multiple Geoits
/// verified against the same Governance share one copy.
/// For serialization, use `.snapshot()` to get an owned `GeoitSnapshot`.
#[derive(Clone, Debug)]
pub struct Geoit {
    pub(crate) mv: Mv,
    pub(crate) governance: Arc<Governance>,
    pub(crate) predicate: Predicate,
    pub(crate) phase: Phase,
    pub(crate) readings: ReadingRules,
    /// v0.0.2: Generator participation profile (dimensional analysis).
    pub(crate) profile: GeneratorProfile,
    /// v0.0.2: Proof term recording why this Geoit is valid.
    pub(crate) proof: ProofTerm,
}

impl Geoit {
    /// The underlying multivector.
    pub fn mv(&self) -> &Mv {
        &self.mv
    }

    /// The governance this Geoit was verified against.
    pub fn governance(&self) -> &Governance {
        &self.governance
    }

    /// The satisfaction proof.
    pub fn predicate(&self) -> &Predicate {
        &self.predicate
    }

    /// The geometric phase (Commitment, Evaluation, or Deliberation).
    pub fn phase(&self) -> Phase {
        self.phase
    }

    /// v0.0.2: Generator participation profile.
    pub fn profile(&self) -> &GeneratorProfile {
        &self.profile
    }

    /// v0.0.2: The proof term recording why this Geoit is valid.
    pub fn proof(&self) -> &ProofTerm {
        &self.proof
    }

    /// Whether all constraints are satisfied.
    pub fn is_satisfied(&self) -> bool {
        self.predicate.is_satisfied()
    }

    /// Whether any coefficient was promoted to BigRat during validation.
    pub fn has_overflow(&self) -> bool {
        self.predicate.has_overflow()
    }

    /// Read a single parameter by index.
    /// # Errors
    /// Returns `ExtractionError` if the index is out of range or extraction fails.
    pub fn read(&self, param_index: usize) -> Result<Scalar, ExtractionError> {
        self.readings.read(&self.mv, param_index)
    }

    /// Read all parameters.
    /// # Errors
    /// Returns `ExtractionError` if any extraction fails.
    pub fn read_all(&self) -> Result<Vec<Scalar>, ExtractionError> {
        self.readings.apply(&self.mv)
    }

    /// Convert to a self-contained `GeoitSnapshot` for serialization.
    /// Clones the shared Governance into an owned copy.
    pub fn snapshot(&self) -> GeoitSnapshot {
        GeoitSnapshot {
            mv: self.mv.clone(),
            governance: (*self.governance).clone(),
            predicate: self.predicate.clone(),
            phase: self.phase,
            readings: self.readings.clone(),
            profile: self.profile,
            proof: self.proof.clone(),
        }
    }
}

impl std::fmt::Display for Geoit {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "Geoit({}, {:?}, {})",
            self.mv.display_with(&self.governance.sig),
            self.phase,
            if self.is_satisfied() {
                "satisfied"
            } else {
                "FAILED"
            }
        )
    }
}

/// A self-contained governed multivector for serialization and `.gge` emission.
#[derive(Clone, Debug)]
pub struct GeoitSnapshot {
    pub mv: Mv,
    pub governance: Governance,
    pub predicate: Predicate,
    pub phase: Phase,
    pub readings: ReadingRules,
    pub profile: GeneratorProfile,
    pub proof: ProofTerm,
}

impl GeoitSnapshot {
    /// Convert to a shared `Geoit` by wrapping the Governance in an Arc.
    pub fn into_geoit(self) -> Geoit {
        Geoit {
            mv: self.mv,
            governance: Arc::new(self.governance),
            predicate: self.predicate,
            phase: self.phase,
            readings: self.readings,
            profile: self.profile,
            proof: self.proof,
        }
    }

    /// Convert to a shared `Geoit` using an existing Arc'd Governance.
    pub fn into_geoit_with(self, governance: Arc<Governance>) -> Geoit {
        Geoit {
            mv: self.mv,
            governance,
            predicate: self.predicate,
            phase: self.phase,
            readings: self.readings,
            profile: self.profile,
            proof: self.proof,
        }
    }
}

impl std::fmt::Display for GeoitSnapshot {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "GeoitSnapshot({}, {:?}, {})",
            self.mv.display_with(&self.governance.sig),
            self.phase,
            if self.predicate.is_satisfied() {
                "satisfied"
            } else {
                "FAILED"
            }
        )
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::scalar::Rat;

    #[test]
    fn geoit_read() {
        let mv = Mv::from_rat_terms(&[(0b001, Rat::from(3)), (0b010, Rat::from(4))]);
        let gov = Arc::new(Governance {
            sig: crate::algebra::signature::Signature::new(0, 0, 2).unwrap(),
            derived_gens: vec![],
            geom_classes: vec![],
            constructions: vec![],
            probe: None,
            transform_rules: vec![],
        });
        let geoit = Geoit {
            mv,
            governance: gov,
            predicate: Predicate::new(0, &[], &[], vec![], vec![], false),
            phase: Phase::Commitment,
            readings: ReadingRules {
                extractions: vec![
                    crate::governance::reading::ExtractionMap::Coefficient(0b001),
                    crate::governance::reading::ExtractionMap::Coefficient(0b010),
                ],
            },
            profile: GeneratorProfile::EMPTY,
            proof: ProofTerm::Checked { class_index: 0 },
        };
        assert_eq!(geoit.read(0).unwrap(), Scalar::from(3i64));
        assert_eq!(geoit.read(1).unwrap(), Scalar::from(4i64));
        assert!(geoit.read(2).is_err());
    }

    #[test]
    fn snapshot_roundtrip() {
        let mv = Mv::from_rat_terms(&[(0b001, Rat::from(7))]);
        let gov = Arc::new(Governance {
            sig: crate::algebra::signature::Signature::new(0, 0, 2).unwrap(),
            derived_gens: vec![],
            geom_classes: vec![],
            constructions: vec![],
            probe: None,
            transform_rules: vec![],
        });
        let geoit = Geoit {
            mv: mv.clone(),
            governance: gov,
            predicate: Predicate::new(0, &[], &[], vec![], vec![], false),
            phase: Phase::Commitment,
            readings: ReadingRules {
                extractions: vec![],
            },
            profile: GeneratorProfile::EMPTY,
            proof: ProofTerm::Checked { class_index: 0 },
        };

        let snap = geoit.snapshot();
        assert_eq!(snap.mv, mv);
        assert_eq!(snap.phase, Phase::Commitment);

        let geoit2 = snap.into_geoit();
        assert_eq!(geoit2.mv(), &mv);
        assert_eq!(geoit2.phase(), Phase::Commitment);
    }
}