minerva 0.2.0

Causal ordering for distributed systems
use super::Composer;
use crate::metis::{Dotted, Retired, Rhapsody};

// Rhapsody-only GC through the facade. Keeping it out of the generic impl keeps
// the concrete extension visible without inventing a trait no other store calls.
impl Composer<Rhapsody> {
    /// Garbage-collects this composer's held rhapsody against `retired`, excising
    /// order tombstones removed and applied at every roster member; returns the
    /// count [`Rhapsody::condense`] excised.
    ///
    /// The facade closes the clone/[`try_new`](Dotted::try_new)/[`adopt`](Self::adopt)
    /// dance a hand-roller runs: pull the rhapsody,
    /// [`condense`](Rhapsody::condense) it, and rebuild the pair on the
    /// *untouched* context. Condense trims the skeleton coordinate only and never
    /// touches visibility or context, so the rebuilt pair's context still covers
    /// its store by construction; the coverage check therefore *cannot* fail, and
    /// the facade asserts that invariant rather than swallowing a refusal arm. The
    /// [`Retired`] witness carries the same standing-claims burden it carries at
    /// [`Rhapsody::condense`]: a bare [`DotSet`](crate::metis::DotSet) cannot
    /// reach this path.
    ///
    /// # Panics
    ///
    /// Never in practice: the rebuild's coverage check cannot fail because
    /// condense leaves visibility and context untouched, so a panic here would
    /// signal a mechanism bug, not a caller error.
    #[must_use]
    pub fn condense(&mut self, retired: &Retired) -> usize {
        let mut rhapsody = self.state.store().clone();
        let excised = rhapsody.condense(retired);
        let context = self.state.context().clone();
        self.state = Dotted::try_new(rhapsody, context)
            .expect("condense trims only the skeleton, so the context still covers the store");
        excised
    }
}