capability_stripped_string_skeleton/grower_stripped_string_skeleton.rs
1// ---------------- [ File: capability-stripped-string-skeleton/src/grower_stripped_string_skeleton.rs ]
2crate::ix!();
3
4/// We want to create a stripped version of our `StringSkeleton`, called a *StrippedStringSkeleton*.
5///
6/// The StrippedStringSkeleton should contain a flattened list of all nodes in the model tree.
7///
8/// Each entry in `items` corresponds to one `StrippedNodeData`, referencing children by name if
9/// any exist.
10///
11/// The `StrippedStringSkeleton` differs from the `StringSkeleton` in the following way:
12/// - `StringSkeleton` represents the full payload.
13/// - In certain cases, we need something lighter. `StrippedStringSkeleton` fills this niche.
14/// - In a typical system flow, we maintain the StringSkeleton elsewhere and, although it is more computationally intensive, we can refer to it when necessary.
15///
16/// Here we need simply the bare scaffold.
17///
18/// In this structure, we do not need parameter selection justification/confidence levels.
19///
20/// Here we want to track each node by name with its children and its kind
21/// {Dispatch,Aggregate,LeafHolder}
22///
23/// - The role of this data structure is to immediately and directly indicate the shape of the
24/// model scaffold. The shape of this tree should be *exactly* the same as the StringSkeleton.
25///
26/// Here we should keep intact the information about whether or not a branch is optional.
27///
28/// Here we track the selection-probability field associated with each branch.
29/// We use this probability field to make decisions during randomization about which model paths to traverse and how frequently.
30/// The probability field should be set based on domain knowledge about the concrete domain represented by the tree.
31///
32/// ### Example Output Format
33///
34/// Below is an **example** for illustration only (note how it avoids referencing a specific domain and uses placeholders instead):
35///
36/// ```json
37/// [
38/// {
39/// "name": "CoreModule",
40/// "kind": "Aggregate",
41/// "descriptor": "Collects baseline components essential for broad functionality.",
42/// "children": [
43/// {
44/// "name": "InitializationBlock",
45/// "optional": false,
46/// "probability": 1.0
47/// },
48/// {
49/// "name": "LifecycleHooks",
50/// "optional": false,
51/// "probability": 1.0
52/// }
53/// ]
54/// },
55/// {
56/// "name": "InitializationBlock",
57/// "kind": "Dispatch",
58/// "descriptor": "Switches among methods for setting initial parameters or states.",
59/// "children": [
60/// {
61/// "name": "ParameterSetup",
62/// "optional": false,
63/// "probability": 1.0
64/// },
65/// {
66/// "name": "ResourceProvision",
67/// "optional": false,
68/// "probability": 1.0
69/// }
70/// ]
71/// },
72/// {
73/// "name": "ParameterSetup",
74/// "kind": "LeafHolder",
75/// "descriptor": "Defines various ways to assign base parameters before use.",
76/// "n_leaves": 9
77/// },
78/// {
79/// "name": "ResourceProvision",
80/// "kind": "LeafHolder",
81/// "descriptor": "Outlines techniques for supplying necessary resources or data.",
82/// "n_leaves": 9,
83/// "capstone": true
84/// },
85/// {
86/// "name": "LifecycleHooks",
87/// "kind": "LeafHolder",
88/// "descriptor": "Houses event triggers or callback methods tied to major milestones.",
89/// "n_leaves": 9
90/// }
91/// ]
92/// ```
93///
94/// When generating this structure, please keep the following information in mind:
95/// 1. Output your final stripped skeleton **as an array of JSON objects**, one per node.
96/// 2. For each node:
97/// - Provide its `name`, `kind`, `descriptor`, and if non-leaf, its `children`.
98/// - For leaf nodes, provide `n_leaves` and `capstone` if applicable.
99/// 3. Make sure **descriptors** are domain-focused and remain cohesive when read in a hierarchy from root to leaf.
100/// 4. No fields other than the ones mentioned: **no** confidence, **no** justification, **no** extraneous data.
101///
102/// By following these guidelines, your descriptors will naturally form a coherent mini-narrative for any domain you apply them to.
103///
104#[derive(Hash,SaveLoad,PartialEq,Eq,AiJsonTemplate,Serialize,Deserialize,Getters, Setters, Builder, Debug, Clone)]
105#[getset(get = "pub", set = "pub")]
106pub struct StrippedStringSkeleton {
107
108 /// This field holds *verbatim* the lower-kebab-case target-name belonging to the tree grow process.
109 #[builder(default = "\"target\".to_string()")]
110 #[serde(default)]
111 target_name: String,
112
113 /// The complete list of nodes in the scaffold.
114 ///
115 /// We require that the full shape of the original StringSkeleton is maintained, including all of its nodes and branches to full depth.
116 #[builder(default)]
117 items: Vec<StrippedNodeData>,
118}
119
120#[derive(Hash,SaveLoad,PartialEq,Eq,AiJsonTemplate,Serialize,Deserialize,Getters, Setters, Builder, Debug, Clone)]
121#[getset(get = "pub", set = "pub")]
122pub struct StrippedNodeData {
123
124 /// The node’s official UpperCamelCase identifier
125 ///
126 #[builder(default)]
127 name: String,
128
129 #[builder(default)]
130 kind: SkillTreeNodeKind,
131
132 /// If this node is a LeafHolder, then `n_leaves` is an integer denoting how many leaves it contains.
133 ///
134 /// `n_leaves` is a measure of the models representational power at this level of the tree.
135 ///
136 /// `n_leaves` indicates how many states within the domain we can access at this level.
137 ///
138 #[builder(default)]
139 n_leaves: Option<usize>,
140
141 /// If this node is a capstone node in the original data structure, we set `capstone` to *true*.
142 ///
143 /// 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.
144 ///
145 #[builder(default)]
146 capstone: Option<bool>,
147
148 /// `children` is an array referencing the structural child nodes of this node.
149 /// Each child object has:
150 /// - **name** (the child’s official UpperCamelCase identifier)
151 /// - **optional** (a boolean indicating whether in our domain model, this path through the tree is *optional*)
152 /// - **probability** (float in `[0..1]` -- represents a likelihood that this path is chosen in our domain)
153 ///
154 #[builder(default)]
155 children: Option<Vec<NamedChildSpec>>,
156}
157
158/// To make this selection, categorize each type of node in our skill tree scaffold.
159#[derive(PartialOrd,Ord,Hash,SaveLoad,AiJsonTemplate,Serialize,Deserialize,Default,Debug, Eq, PartialEq, Clone)]
160pub enum SkillTreeNodeKind {
161
162 /// This variant is used for enumerations branching into distinct paths.
163 #[default]
164 Dispatch,
165
166 /// This variant is used for grouping child nodes into a combined structure.
167 Aggregate,
168
169 /// This variant is used for the final leaf-holder nodes (without children).
170 LeafHolder,
171}
172
173/// To generate this structure, describe a single child entry beneath a `Dispatch` or `Aggregate` node.
174/// This description includes:
175/// - `name`: A unique identifier (written in UpperCamelCase, no punctuation).
176/// - `optional`: Indicates if this branch can be skipped.
177/// - `probability`: The relative likelihood of including this child.
178#[derive(Hash,SaveLoad,PartialEq,Eq,AiJsonTemplate,Serialize,Deserialize,Getters, Setters, Builder, Debug, Clone)]
179#[getset(get = "pub", set = "pub")]
180pub struct NamedChildSpec {
181
182 /// Official name of the child node (UpperCamelCase).
183 #[builder(default)]
184 name: String,
185
186 /// Whether this branch is optional.
187 #[builder(default)]
188 optional: bool,
189
190 /// Probability from 0 to 100 for inclusion of this child.
191 ///
192 /// Values over the maximum will be clipped.
193 #[builder(default)]
194 probability: u8,
195}