capability-stripped-string-skeleton 0.1.0

Provides a streamlined representation of a skill tree structure, focusing on a lightweight, stripped-down version that retains essential hierarchical relationships without the full complexity of the original structure.
Documentation
// ---------------- [ File: capability-stripped-string-skeleton/src/grower_stripped_string_skeleton.rs ]
crate::ix!();

/// We want to create a stripped version of our `StringSkeleton`, called a *StrippedStringSkeleton*. 
///
/// The StrippedStringSkeleton should contain a flattened list of all nodes in the model tree.
///
/// Each entry in `items` corresponds to one `StrippedNodeData`, referencing children by name if
/// any exist.
///
/// The `StrippedStringSkeleton` differs from the `StringSkeleton` in the following way:
/// - `StringSkeleton` represents the full payload.
/// - In certain cases, we need something lighter. `StrippedStringSkeleton` fills this niche.
/// - In a typical system flow, we maintain the StringSkeleton elsewhere and, although it is more computationally intensive, we can refer to it when necessary. 
///
/// Here we need simply the bare scaffold. 
///
/// In this structure, we do not need parameter selection justification/confidence levels.
///
/// Here we want to track each node by name with its children and its kind
/// {Dispatch,Aggregate,LeafHolder}
///
/// - The role of this data structure is to immediately and directly indicate the shape of the
/// model scaffold. The shape of this tree should be *exactly* the same as the StringSkeleton.
///
/// Here we should keep intact the information about whether or not a branch is optional.
///
/// Here we track the selection-probability field associated with each branch.
/// We use this probability field to make decisions during randomization about which model paths to traverse and how frequently.
/// The probability field should be set based on domain knowledge about the concrete domain represented by the tree.
///
/// ### Example Output Format
/// 
/// Below is an **example** for illustration only (note how it avoids referencing a specific domain and uses placeholders instead):
/// 
/// ```json
/// [
///   {
///     "name": "CoreModule",
///     "kind": "Aggregate",
///     "descriptor": "Collects baseline components essential for broad functionality.",
///     "children": [
///       {
///         "name": "InitializationBlock",
///         "optional": false,
///         "probability": 1.0
///       },
///       {
///         "name": "LifecycleHooks",
///         "optional": false,
///         "probability": 1.0
///       }
///     ]
///   },
///   {
///     "name": "InitializationBlock",
///     "kind": "Dispatch",
///     "descriptor": "Switches among methods for setting initial parameters or states.",
///     "children": [
///       {
///         "name": "ParameterSetup",
///         "optional": false,
///         "probability": 1.0
///       },
///       {
///         "name": "ResourceProvision",
///         "optional": false,
///         "probability": 1.0
///       }
///     ]
///   },
///   {
///     "name": "ParameterSetup",
///     "kind": "LeafHolder",
///     "descriptor": "Defines various ways to assign base parameters before use.",
///     "n_leaves": 9
///   },
///   {
///     "name": "ResourceProvision",
///     "kind": "LeafHolder",
///     "descriptor": "Outlines techniques for supplying necessary resources or data.",
///     "n_leaves": 9,
///     "capstone": true
///   },
///   {
///     "name": "LifecycleHooks",
///     "kind": "LeafHolder",
///     "descriptor": "Houses event triggers or callback methods tied to major milestones.",
///     "n_leaves": 9
///   }
/// ]
/// ```
///
/// When generating this structure, please keep the following information in mind:
/// 1. Output your final stripped skeleton **as an array of JSON objects**, one per node.
/// 2. For each node:
///    - Provide its `name`, `kind`, `descriptor`, and if non-leaf, its `children`.
///    - For leaf nodes, provide `n_leaves` and `capstone` if applicable.
/// 3. Make sure **descriptors** are domain-focused and remain cohesive when read in a hierarchy from root to leaf.
/// 4. No fields other than the ones mentioned: **no** confidence, **no** justification, **no** extraneous data.
/// 
/// By following these guidelines, your descriptors will naturally form a coherent mini-narrative for any domain you apply them to. 
/// 
#[derive(Hash,SaveLoad,PartialEq,Eq,AiJsonTemplate,Serialize,Deserialize,Getters, Setters, Builder, Debug, Clone)]
#[getset(get = "pub", set = "pub")]
pub struct StrippedStringSkeleton {

    /// This field holds *verbatim* the lower-kebab-case target-name belonging to the tree grow process.
    #[builder(default = "\"target\".to_string()")]
    #[serde(default)]
    target_name: String,

    /// The complete list of nodes in the scaffold. 
    ///
    /// We require that the full shape of the original StringSkeleton is maintained, including all of its nodes and branches to full depth.
    #[builder(default)]
    items: Vec<StrippedNodeData>,
}

#[derive(Hash,SaveLoad,PartialEq,Eq,AiJsonTemplate,Serialize,Deserialize,Getters, Setters, Builder, Debug, Clone)]
#[getset(get = "pub", set = "pub")]
pub struct StrippedNodeData {

    /// The node’s official UpperCamelCase identifier
    ///
    #[builder(default)]
    name: String,

    #[builder(default)]
    kind: SkillTreeNodeKind,

    /// If this node is a LeafHolder, then `n_leaves` is an integer denoting how many leaves it contains.
    ///
    /// `n_leaves` is a measure of the models representational power at this level of the tree.
    ///
    /// `n_leaves` indicates how many states within the domain we can access at this level.
    ///
    #[builder(default)]
    n_leaves: Option<usize>,

    /// If this node is a capstone node in the original data structure, we set `capstone` to *true*.
    ///
    /// It may be left out (ie, set to `None`) if this node is not a capstone or if this field is not specified in the model.
    ///
    #[builder(default)]
    capstone: Option<bool>,

    /// `children` is an array referencing the structural child nodes of this node.
    /// Each child object has:
    ///  - **name** (the child’s official UpperCamelCase identifier)
    ///  - **optional** (a boolean indicating whether in our domain model, this path through the tree is *optional*)
    ///  - **probability** (float in `[0..1]` -- represents a likelihood that this path is chosen in our domain)
    ///
    #[builder(default)]
    children: Option<Vec<NamedChildSpec>>,
}

/// To make this selection, categorize each type of node in our skill tree scaffold.
#[derive(PartialOrd,Ord,Hash,SaveLoad,AiJsonTemplate,Serialize,Deserialize,Default,Debug, Eq, PartialEq, Clone)]
pub enum SkillTreeNodeKind {

    /// This variant is used for enumerations branching into distinct paths.
    #[default]
    Dispatch,

    /// This variant is used for grouping child nodes into a combined structure.
    Aggregate,

    /// This variant is used for the final leaf-holder nodes (without children).
    LeafHolder,
}

/// To generate this structure, describe a single child entry beneath a `Dispatch` or `Aggregate` node.
/// This description includes:
/// - `name`: A unique identifier (written in UpperCamelCase, no punctuation).
/// - `optional`: Indicates if this branch can be skipped.
/// - `probability`: The relative likelihood of including this child.
#[derive(Hash,SaveLoad,PartialEq,Eq,AiJsonTemplate,Serialize,Deserialize,Getters, Setters, Builder, Debug, Clone)]
#[getset(get = "pub", set = "pub")]
pub struct NamedChildSpec {

    /// Official name of the child node (UpperCamelCase).
    #[builder(default)]
    name: String,

    /// Whether this branch is optional.
    #[builder(default)]
    optional: bool,

    /// Probability from 0 to 100 for inclusion of this child. 
    ///
    /// Values over the maximum will be clipped.
    #[builder(default)]
    probability: u8,
}