soma-som-core 0.1.0

Universal soma(som) structural primitives — Quad / Tree / Ring / Genesis / Fingerprint / TemporalLedger / CrossingRecord
Documentation
// SPDX-License-Identifier: LGPL-3.0-only
#![allow(missing_docs)]

//! Domain vocabulary for all six SOMA units.
//!
//! ## Spec traceability
//! - Spec §5.1: FU — "Who Am I?" (Table 2)
//! - Spec §5.2: MU — "What Is Up?" (Table 3)
//! - Spec §5.3: CU — "What Comes Next?" (Table 4)
//! - Spec §5.4: OU — "Who Are You?" (Table 5)
//! - Spec §5.5: SU — "Where Are We?" (Table 6)
//! - Spec §5.6: HU — "When Do What?" (Table 7)
//!
//! The domain terms are the 72 SOM key positions of the structural skeleton.
//! Position within the Quad structure (R, P, T) and within the layer chain
//! (Data, Server, Client, Interface) carries semantic meaning.

use crate::types::{Element, Layer, UnitId};

/// A domain vocabulary term: the human-readable name at a specific
/// (unit, layer, element) position.
#[derive(Debug, Clone, Copy)]
pub struct VocabTerm {
    pub unit: UnitId,
    pub layer: Layer,
    pub element: Element,
    pub term: &'static str,
}

/// Get the domain vocabulary term for a specific position.
///
/// Returns the human-readable term from the spec's unit vocabulary tables.
pub fn domain_term(unit: UnitId, layer: Layer, element: Element) -> &'static str {
    use Element::*;
    use Layer::*;
    use UnitId::*;

    match (unit, layer, element) {
        // FU — "Who Am I?" (Spec §5.1, Table 2)
        (FU, Data, Root) => "Root",
        (FU, Data, Pointer) => "Quad",
        (FU, Data, Tree) => "Tree",
        (FU, Server, Root) => "Space",
        (FU, Server, Pointer) => "Vector",
        (FU, Server, Tree) => "Map",
        (FU, Client, Root) => "Type",
        (FU, Client, Pointer) => "Node",
        (FU, Client, Tree) => "Relation",
        (FU, Interface, Root) => "Reference",
        (FU, Interface, Pointer) => "Value",
        (FU, Interface, Tree) => "Set",

        // MU — "What Is Up?" (Spec §5.2, Table 3)
        (MU, Data, Root) => "World",
        (MU, Data, Pointer) => "Update",
        (MU, Data, Tree) => "Queue",
        (MU, Server, Root) => "Engine",
        (MU, Server, Pointer) => "Change",
        (MU, Server, Tree) => "Pool",
        (MU, Client, Root) => "Flow",
        (MU, Client, Pointer) => "Sequence",
        (MU, Client, Tree) => "Language",
        (MU, Interface, Root) => "Grammar",
        (MU, Interface, Pointer) => "Expression",
        (MU, Interface, Tree) => "Dictionary",

        // CU — "What Comes Next?" (Spec §5.3, Table 4)
        (CU, Data, Root) => "Service",
        (CU, Data, Pointer) => "Operation",
        (CU, Data, Tree) => "Routine",
        (CU, Server, Root) => "Commitment",
        (CU, Server, Pointer) => "Expectation",
        (CU, Server, Tree) => "Future",
        (CU, Client, Root) => "Collective",
        (CU, Client, Pointer) => "Anticipation",
        (CU, Client, Tree) => "Prediction",
        (CU, Interface, Root) => "Condition",
        (CU, Interface, Pointer) => "Suggestion",
        (CU, Interface, Tree) => "Knowledge",

        // OU — "Who Are You?" (Spec §5.4, Table 5)
        (OU, Data, Root) => "Session",
        (OU, Data, Pointer) => "Key",
        (OU, Data, Tree) => "Member",
        (OU, Server, Root) => "Governance",
        (OU, Server, Pointer) => "Identity",
        (OU, Server, Tree) => "Group",
        (OU, Client, Root) => "Hierarchy",
        (OU, Client, Pointer) => "Person",
        (OU, Client, Tree) => "Organisation",
        (OU, Interface, Root) => "Location",
        (OU, Interface, Pointer) => "Account",
        (OU, Interface, Tree) => "Profile",

        // SU — "Where Are We?" (Spec §5.5, Table 6)
        (SU, Data, Root) => "Scene",
        (SU, Data, Pointer) => "Item",
        (SU, Data, Tree) => "Perspective",
        (SU, Server, Root) => "Layout",
        (SU, Server, Pointer) => "View",
        (SU, Server, Tree) => "Content",
        (SU, Client, Root) => "Application",
        (SU, Client, Pointer) => "Model",
        (SU, Client, Tree) => "Collection",
        (SU, Interface, Root) => "Body",
        (SU, Interface, Pointer) => "Widget",
        (SU, Interface, Tree) => "Specification",

        // HU — "When Do What?" (Spec §5.6, Table 7)
        (HU, Data, Root) => "Cycle",
        (HU, Data, Pointer) => "Action",
        (HU, Data, Tree) => "History",
        (HU, Server, Root) => "Actor",
        (HU, Server, Pointer) => "Event",
        (HU, Server, Tree) => "Series",
        (HU, Client, Root) => "Pipe",
        (HU, Client, Pointer) => "Control",
        (HU, Client, Tree) => "Selection",
        (HU, Interface, Root) => "Stream",
        (HU, Interface, Pointer) => "Input",
        (HU, Interface, Tree) => "Definition",
    }
}

/// Get all 72 domain vocabulary terms in canonical position order.
pub fn all_terms() -> Vec<VocabTerm> {
    let mut terms = Vec::with_capacity(72);
    for &unit in &UnitId::ALL {
        for &layer in &Layer::ALL {
            for &element in &Element::ALL {
                terms.push(VocabTerm {
                    unit,
                    layer,
                    element,
                    term: domain_term(unit, layer, element),
                });
            }
        }
    }
    terms
}

// inline: exercises module-private items via super::*
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn all_72_terms_populated() {
        let terms = all_terms();
        assert_eq!(terms.len(), 72);
        for term in &terms {
            assert!(!term.term.is_empty(), "Empty term at {term:?}");
        }
    }

    #[test]
    fn all_terms_are_unique() {
        let terms = all_terms();
        // Terms are NOT globally unique — "Root" appears in FU.Data.Root
        // but the (unit, layer, element) tuple IS unique.
        let mut positions: Vec<(UnitId, Layer, Element)> =
            terms.iter().map(|t| (t.unit, t.layer, t.element)).collect();
        let orig_len = positions.len();
        positions.sort();
        positions.dedup();
        assert_eq!(positions.len(), orig_len);
    }

    #[test]
    fn fu_data_root_is_root() {
        // FU's Data layer holds the primordial Quad structure (Spec §5.1)
        assert_eq!(domain_term(UnitId::FU, Layer::Data, Element::Root), "Root");
        assert_eq!(
            domain_term(UnitId::FU, Layer::Data, Element::Pointer),
            "Quad"
        );
        assert_eq!(domain_term(UnitId::FU, Layer::Data, Element::Tree), "Tree");
    }

    #[test]
    fn ou_server_pointer_is_identity() {
        // OU: the trust anchor — Identity is at Server.Pointer (Spec §5.4)
        assert_eq!(
            domain_term(UnitId::OU, Layer::Server, Element::Pointer),
            "Identity"
        );
    }
}