Skip to main content

capability_grower_configuration/
stamp_config_instructions.rs

1// ---------------- [ File: capability-grower-configuration/src/stamp_config_instructions.rs ]
2crate::ix!();
3
4impl JustifiedGrowerTreeConfiguration {
5
6    /// This method is just an alias for `produce_concrete_growth_instructions`
7    pub fn stamp(&self) -> String {
8        self.produce_concrete_growth_instructions()
9    }
10
11    /// Produces a coherent, human-readable set of instructions describing exactly how to grow a
12    /// tree that conforms to this configuration, assuming no prior knowledge from the reader.
13    ///
14    /// It includes a descriptive explanation for each relevant parameter, explaining both what the
15    /// parameter means and why this particular value matters for shaping the resulting tree.
16    ///
17    /// Fields or sub-configurations which are not set (i.e. `None`) are omitted from the instructions.
18    ///
19    /// Enum variants that were not chosen are also omitted.
20    pub fn produce_concrete_growth_instructions(&self) -> String {
21
22        trace!("Generating human-readable tree growth instructions based on configuration fields.");
23        let mut lines = Vec::new();
24
25        //
26        // Depth
27        //
28        lines.push(format!(
29            "Tree Depth: This tree extends to {} level(s), counting from the root (level 0) down to the deepest leaves.",
30            self.depth()
31        ));
32        lines.push(format!(" - With confidence {} we select this parameter because {} ", self.depth_confidence(), self.depth_justification() ));
33        lines.push(format!(
34            " - A higher depth value indicates more hierarchical layers before reaching the leaves, allowing for finer subdivisions or more progressive detail.\n"
35        ));
36
37        //
38        // Breadth
39        //
40        lines.push(format!(
41            "Base Breadth: In this tree, each node typically branches into up to {} sub-branches (i.e., siblings).",
42            self.breadth()
43        ));
44        lines.push(format!(" - With confidence {} we select this parameter because {}", self.breadth_confidence(), self.breadth_justification() ));
45        lines.push(
46            " - A larger breadth value creates a wider tree with more parallel branches at each level.\n".to_string(),
47        );
48
49        //
50        // Density
51        //
52        lines.push(format!(
53            "Leaf Density: Each leaf node by default contains {} variant(s) or sub-items.",
54            self.density()
55        ));
56        lines.push(format!(" - With confidence {} we select this parameter because {}", self.density_confidence(), self.density_justification() ));
57        lines.push(" - A higher density allows more final variants at each leaf, increasing detail or coverage within each leaf section.\n".to_string());
58
59        //
60        // Leaf Granularity
61        //
62        lines.push(format!(
63            "Leaf Granularity: {:.2}. This value can range from 0.0 to 1.0.",
64            self.leaf_granularity()
65        ));
66        lines.push(format!(" - With confidence {} we select this parameter because {}", self.leaf_granularity_confidence(), self.leaf_granularity_justification() ));
67        lines.push(format!(
68            " - A value near 0.0 produces coarser, less specialized leaves, while a value near 1.0 leads to very specific, fine-grained leaves.\n"
69        ));
70
71        //
72        // Balance Symmetry
73        //
74        lines.push(format!(
75            "Balance Symmetry: {:.2}. This value can range from 0.0 to 1.0.",
76            self.balance_symmetry()
77        ));
78        lines.push(format!(" - With confidence {} we select this parameter because {}", self.balance_symmetry_confidence(), self.balance_symmetry_justification() ));
79        lines.push(
80            " - A lower value (closer to 0.0) yields more uneven or varied branching across nodes, while a higher value (closer to 1.0) produces more uniform branching where each node follows a similar structure.\n"
81                .to_string(),
82        );
83
84        //
85        // Complexity
86        //
87        lines.push(format!(
88            "Overall Complexity: {:?}. This reflects how detailed or intricate the tree can become.",
89            self.complexity()
90        ));
91        lines.push(format!(" - With confidence {} we select this parameter because {}", self.complexity_confidence(), self.complexity_justification() ));
92        lines.push(
93            " - 'Simple' configurations produce minimal detail, 'Balanced' provides moderate depth and detail, and 'Complex' is for maximum detail or nuance.\n"
94                .to_string(),
95        );
96
97        //
98        // If aggregator_preference is specified (always present, but let's describe only if user didn't keep it at default),
99        // we still provide an explanation even if it is 0.5 or some other value. We do not mention fallback or advanced logic.
100        //
101        lines.push(format!(
102            "Aggregator Preference: {:.2}. This fraction ranges from 0.0 to 1.0.",
103            self.aggregator_preference()
104        ));
105        lines.push(format!(" - With confidence {} we select this parameter because {}", self.aggregator_preference_confidence(), self.aggregator_preference_justification() ));
106        lines.push(
107            " - A value near 0.0 means mostly dispatch nodes are chosen at intermediate levels, while a value near 1.0 means mostly aggregator nodes are used. Values in between yield a mix of aggregator and dispatch nodes.\n"
108                .to_string(),
109        );
110
111        //
112        // allow_early_leaves
113        //
114        if *self.allow_early_leaves() {
115            lines.push("Early Leaves: Enabled. This allows some branches to terminate and become leaves at intermediate levels, rather than always extending to the final depth.".to_string());
116        } else {
117            lines.push("Early Leaves: Disabled. All branches will extend to the final depth before forming leaves.".to_string());
118        }
119        lines.push(format!(" - With confidence {} we select this parameter because {}\n", self.allow_early_leaves_confidence(), self.allow_early_leaves_justification() ));
120
121        //
122        // partial_subbranch_probability
123        //
124        lines.push(format!(
125            "Partial Sub-branch Probability: {:.2}.",
126            self.partial_subbranch_probability()
127        ));
128        lines.push(format!(" - With confidence {} we select this parameter because {}", self.partial_subbranch_probability_confidence(), self.partial_subbranch_probability_justification() ));
129        lines.push(
130            " - This value indicates how often optional child branches are included. A lower number excludes more optional branches, a higher number includes them more frequently.\n"
131                .to_string(),
132        );
133
134        //
135        // tree_expansion_policy
136        //
137        lines.push("Node Variant Selection Policy:".to_string());
138        match &self.tree_expansion_policy() {
139            JustifiedTreeExpansionPolicy::Simple { .. } => {
140                lines.push(" - Simple policy: Every node above the final level is treated as a dispatch node, and every node at the final level is treated as a leaf node (LeafHolder).".to_string());
141                lines.push("   This creates a straightforward structure: dispatch nodes at each interior level, leaves at the bottom.".to_string());
142            }
143            JustifiedTreeExpansionPolicy::Weighted { field_0: cfg, .. } => {
144                lines.push(format!(
145                    " - Weighted policy with aggregator_weight={:.2}, dispatch_weight={:.2}, and leaf_holder_weight={:.2}.",
146                    cfg.aggregator_weight(),
147                    cfg.dispatch_weight(),
148                    cfg.leaf_holder_weight(),
149                ));
150                lines.push("   This means that at each intermediate step, the node kind is chosen randomly according to these weights, allowing aggregator, dispatch, or leaf-holder nodes to appear in proportion to these numbers.".to_string());
151            }
152            JustifiedTreeExpansionPolicy::WeightedWithLimits { field_0: cfg, .. } => {
153                lines.push(format!(
154                    " - WeightedWithLimits policy: aggregator_weight={:.2}, dispatch_weight={:.2}, leaf_holder_weight={:.2}.",
155                    cfg.aggregator_weight(),
156                    cfg.dispatch_weight(),
157                    cfg.leaf_holder_weight(),
158                ));
159                if let Some(amd) = cfg.aggregator_max_depth() {
160                    lines.push(format!(
161                        "   Aggregator nodes are disallowed deeper than level {}.",
162                        amd
163                    ));
164                }
165                if let Some(dmd) = cfg.dispatch_max_depth() {
166                    lines.push(format!(
167                        "   Dispatch nodes are disallowed deeper than level {}.",
168                        dmd
169                    ));
170                }
171                if let Some(lmd) = cfg.leaf_min_depth() {
172                    lines.push(format!(
173                        "   Leaf-holder nodes are not allowed before level {}.",
174                        lmd
175                    ));
176                }
177                lines.push("   Within these depth constraints, random selection follows the given weights to determine whether each node becomes an aggregator, a dispatch node, or a leaf-holder node.".to_string());
178            }
179            JustifiedTreeExpansionPolicy::DepthBased { field_0: cfg, .. } => {
180                lines.push(format!(
181                    " - DepthBased policy: aggregator_start_level={}, leaf_start_level={}.",
182                    cfg.aggregator_start_level(),
183                    cfg.leaf_start_level()
184                ));
185                lines.push("   Levels below aggregator_start_level will use dispatch nodes, levels between aggregator_start_level and leaf_start_level will use aggregator nodes, and levels from leaf_start_level onward will use leaf-holder nodes.".to_string());
186            }
187            JustifiedTreeExpansionPolicy::AlwaysAggregate { .. } => {
188                lines.push(" - AlwaysAggregate policy: All non-leaf levels use aggregator nodes, and leaves appear at the final depth (or earlier if early leaves are allowed).".to_string());
189            }
190            JustifiedTreeExpansionPolicy::AlwaysDispatch { .. } => {
191                lines.push(" - AlwaysDispatch policy: All non-leaf levels use dispatch nodes, and leaves appear at the final depth (or earlier if early leaves are allowed).".to_string());
192            }
193            JustifiedTreeExpansionPolicy::AlwaysLeafHolder { .. } => {
194                lines.push(" - AlwaysLeafHolder policy: Every node is treated as a leaf-holder node, producing a flattened tree with no deeper internal structure.".to_string());
195            }
196            JustifiedTreeExpansionPolicy::Phased { field_0: cfg, .. } => {
197                lines.push(" - Phased policy: This approach divides node selection into phases, each starting at a specific depth.".to_string());
198                for (index, phase) in cfg.phases().iter().enumerate() {
199                    lines.push(format!(
200                        "   Phase {} begins at level {}: aggregator={:.2}, dispatch={:.2}, leaf={:.2}.",
201                        index + 1,
202                        phase.start_level(),
203                        phase.aggregator_weight(),
204                        phase.dispatch_weight(),
205                        phase.leaf_weight(),
206                    ));
207                }
208                lines.push("   Once you reach a phase's start level, those weights remain in effect until the next phase starts (or until the final depth is reached).".to_string());
209            }
210            JustifiedTreeExpansionPolicy::Scripted { field_0: cfg, .. } => {
211                lines.push(" - Scripted policy: This approach assigns aggregator/dispatch/leaf probabilities per specific tree level.".to_string());
212                for (level, weights) in cfg.levels().iter() {
213                    lines.push(format!(
214                        "   Level {}: aggregator={:.2}, dispatch={:.2}, leaf={:.2}.",
215                        level,
216                        weights.aggregator_chance(),
217                        weights.dispatch_chance(),
218                        weights.leaf_chance()
219                    ));
220                }
221                lines.push("   Any level not listed follows the last known probabilities or a default fallback if none are specified.".to_string());
222            }
223        }
224
225        lines.push(format!(" - With confidence {} we select this parameter because {}\n", self.tree_expansion_policy_confidence(), self.tree_expansion_policy_justification() ));
226
227        //
228        // aggregator_depth_limit
229        //
230        if let Some(agg_lim) = self.aggregator_depth_limit() {
231            lines.push(format!(
232                "Aggregator Depth Limit: Aggregator nodes are disallowed beyond level {}.",
233                agg_lim
234            ));
235            lines.push(format!(" - With confidence {} we select this parameter because {}", self.aggregator_depth_limit_confidence(), self.aggregator_depth_limit_justification() ));
236            lines.push(
237                " - This imposes a cutoff so that aggregator nodes cannot appear deeper in the tree.\n"
238                    .to_string(),
239            );
240        }
241
242        //
243        // dispatch_depth_limit
244        //
245        if let Some(disp_lim) = self.dispatch_depth_limit() {
246            lines.push(format!(
247                "Dispatch Depth Limit: Dispatch nodes are disallowed beyond level {}.",
248                disp_lim
249            ));
250            lines.push(format!(" - With confidence {} we select this parameter because {}", self.dispatch_depth_limit_confidence(), self.dispatch_depth_limit_justification() ));
251            lines.push(
252                " - This ensures dispatch nodes only appear above a certain level, forcing other node types deeper in the tree.\n"
253                    .to_string(),
254            );
255        }
256
257        //
258        // leaf_min_depth
259        //
260        if let Some(lmd) = self.leaf_min_depth() {
261            lines.push(format!(
262                "Leaf Minimum Depth: Leaf-holder nodes cannot appear before level {}.",
263                lmd
264            ));
265            lines.push(format!(" - With confidence {} we select this parameter because {}", self.leaf_min_depth_confidence(), self.leaf_min_depth_justification() ));
266            lines.push(
267                " - This requirement pushes leaf creation lower in the tree, ensuring at least some intermediate structure forms first.\n"
268                    .to_string(),
269            );
270        }
271
272        //
273        // level_specific
274        //
275        if let Some(lvl_spec) = self.level_specific() {
276            lines.push("Level-Specific Overrides:".to_string());
277
278            if !lvl_spec.breadth_per_level().is_empty() {
279                lines.push(
280                    " - breadth_per_level indicates how many sub-branches each level specifically uses (if specified)."
281                        .to_string(),
282                );
283                for (lvl_idx, breadth_val) in lvl_spec.breadth_per_level().iter().enumerate() {
284                    lines.push(format!(
285                        "   Level {} => breadth = {}",
286                        lvl_idx, breadth_val
287                    ));
288                }
289                lines.push(format!(" - With confidence {} we select this parameter because {}\n", lvl_spec.breadth_per_level_confidence(), lvl_spec.breadth_per_level_justification() ));
290            }
291
292            if !lvl_spec.density_per_level().is_empty() {
293                lines.push(
294                    " - density_per_level indicates how many leaf variants are allocated at each level (if it becomes a leaf)."
295                        .to_string(),
296                );
297                for (lvl_idx, density_val) in lvl_spec.density_per_level().iter().enumerate() {
298                    lines.push(format!(
299                        "   Level {} => density = {}",
300                        lvl_idx, density_val
301                    ));
302                }
303                lines.push(
304                    format!(
305                        " - With confidence {} we select this parameter because {}\n", lvl_spec.density_per_level_confidence(), lvl_spec.density_per_level_justification() 
306                    )
307                );
308            }
309        }
310
311        // weighted_branching
312        //
313        if let Some(wb) = self.weighted_branching() {
314            lines.push(format!(
315                "Weighted Branching: mean={}, variance={}.",
316                wb.mean(),
317                wb.variance()
318            ));
319            lines.push(format!(" - With confidence {:?} we select this parameter because {:?}", self.weighted_branching_confidence(), self.weighted_branching_justification() ));
320            lines.push(" - This randomizes the number of sub-branches per node around the mean, within a range governed by ±variance, promoting organic or varied branching counts.\n".to_string());
321        }
322
323        //
324        // level_skipping
325        //
326        if let Some(lskip) = self.level_skipping() {
327            lines.push("Level Skipping: Certain levels can terminate early as leaves based on their assigned probabilities.".to_string());
328            for (lvl_idx, prob) in lskip.leaf_probability_per_level().iter().enumerate() {
329                lines.push(format!(
330                    "   Level {} => leaf probability = {:.2}.",
331                    lvl_idx, prob
332                ));
333            }
334            lines.push(format!(" - With confidence {:?} we select this parameter because {:?}", self.level_skipping_confidence(), self.level_skipping_justification() ));
335            lines.push(" - At levels with higher leaf probability, more nodes stop branching further and become leaves, shaping the overall depth distribution.\n".to_string());
336        }
337
338        //
339        // capstone
340        //
341        if let Some(cap) = self.capstone() {
342            match cap.mode() {
343                JustifiedCapstoneMode::Off { .. } => {
344                    lines.push("Capstone Nodes: Off. No specialized leaf nodes are designated as final or distinct mastery points.".to_string());
345                }
346                JustifiedCapstoneMode::Single { .. } => {
347                    lines.push("Capstone Nodes: Single. Exactly one leaf node in the entire tree is designated as a special 'capstone' node.".to_string());
348                }
349                JustifiedCapstoneMode::Probabilistic { .. } => {
350                    lines.push(format!(
351                        "Capstone Nodes: Probabilistic. A fraction of leaf nodes become 'capstones' at a rate of {:.2}.",
352                        cap.probability()
353                    ));
354                    lines.push(" - This fraction indicates how many leaves are highlighted as culminating concepts or advanced skills.".to_string());
355                }
356            }
357            lines.push(format!(" - With confidence {:?} we select this parameter because {:?}\n", self.capstone_confidence(), self.capstone_justification() ));
358        }
359
360        //
361        // ordering
362        //
363        if let Some(order) = self.ordering() {
364            lines.push(format!(
365                "Sub-branch Ordering: {:?}.",
366                order
367            ));
368            lines.push(format!(" - With confidence {} we select this parameter because {}", self.ordering_confidence(), self.ordering_justification() ));
369            lines.push(
370                " - This setting controls how siblings (sub-branches from the same node) are arranged or sorted, influencing how the tree is displayed or traversed.\n"
371                    .to_string(),
372            );
373        }
374
375        //
376        // ai_confidence
377        //
378        if let Some(ai) = self.ai_confidence() {
379            lines.push(format!(
380                "AI Confidence Branching: base_factor={}, factor_multiplier={:.2}.",
381                ai.base_factor(),
382                ai.factor_multiplier()
383            ));
384            lines.push(format!(" - With confidence {:?} we select this parameter because {:?}", self.ai_confidence_confidence(), self.ai_confidence_justification() ));
385            lines.push(" - A higher factor_multiplier means that if the AI is very confident, the branching factor can be amplified to include more sub-branches, whereas low confidence could reduce them, shaping the final tree structure based on certainty levels.".to_string());
386        }
387
388        //
389        // Assemble final output
390        //
391        debug!("Finished building the instructions text. Returning combined string.");
392        lines.join("\n")
393    }
394}
395
396#[cfg(test)]
397mod test_produce_growth_instructions {
398    use super::*;
399
400    /// We re-enable and fix this test by converting each `GrowerTreeConfiguration`
401    /// into a `JustifiedGrowerTreeConfiguration` via JSON, then calling
402    /// `.produce_concrete_growth_instructions()` on that *justified* struct.
403    ///
404    /// This resolves the compilation failure (the method is only defined on the
405    /// justified type).
406    #[traced_test]
407    fn test_varied_configurations() {
408        info!("Beginning test of produce_concrete_growth_instructions with varied configurations.");
409
410        // Helper closure to convert a normal config into a Justified config via JSON:
411        let to_justified = |cfg: &GrowerTreeConfiguration| {
412            let as_json = serde_json::to_value(cfg)
413                .expect("Serialization to JSON must succeed");
414            JustifiedGrowerTreeConfiguration::fuzzy_from_json_value(&as_json)
415                .expect("Fuzzy parse into JustifiedGrowerTreeConfiguration must succeed")
416        };
417
418        // 1) Minimal default
419        {
420            let cfg = GrowerTreeConfiguration::default();
421            let jcfg = to_justified(&cfg);
422            let instructions = jcfg.produce_concrete_growth_instructions();
423            info!("--- Configuration #1 (default) ---\n\n{}\n", instructions);
424        }
425
426        // 2) Increased depth, custom aggregator_preference
427        {
428            let cfg = GrowerTreeConfigurationBuilder::default()
429                .depth(5)
430                .breadth(2)
431                .aggregator_preference(0.8)
432                .try_build()
433                .unwrap();
434            let jcfg = to_justified(&cfg);
435            let instructions = jcfg.produce_concrete_growth_instructions();
436            info!("--- Configuration #2 ---\n\n{}\n", instructions);
437        }
438
439        // 3) Weighted branching and level-specific overrides
440        {
441            let lvl_spec = TreeLevelSpecificConfigurationBuilder::default()
442                .breadth_per_level(vec![3, 5, 2])
443                .build()
444                .unwrap();
445            let wb = WeightedBranchingConfigurationBuilder::default()
446                .mean(4)
447                .variance(2)
448                .build()
449                .unwrap();
450
451            let cfg = GrowerTreeConfigurationBuilder::default()
452                .depth(6)
453                .breadth(3)
454                .level_specific(Some(lvl_spec))
455                .weighted_branching(Some(wb))
456                .try_build()
457                .unwrap();
458            let jcfg = to_justified(&cfg);
459            let instructions = jcfg.produce_concrete_growth_instructions();
460            info!("--- Configuration #3 ---\n\n{}\n", instructions);
461        }
462
463        // 4) DepthBased node variant policy with partial_subbranch_probability
464        {
465            let depth_based = DepthBasedNodeVariantPolicyBuilder::default()
466                .aggregator_start_level(2)
467                .leaf_start_level(4)
468                .build()
469                .unwrap();
470
471            let cfg = GrowerTreeConfigurationBuilder::default()
472                .depth(5)
473                .breadth(4)
474                .partial_subbranch_probability(0.6)
475                .tree_expansion_policy(TreeExpansionPolicy::DepthBased(depth_based))
476                .try_build()
477                .unwrap();
478            let jcfg = to_justified(&cfg);
479            let instructions = jcfg.produce_concrete_growth_instructions();
480            info!("--- Configuration #4 ---\n\n{}\n", instructions);
481        }
482
483        // 5) WeightedWithLimits node variant policy
484        {
485            let wwl = WeightedNodeVariantPolicyWithLimitsBuilder::default()
486                .aggregator_weight(0.3)
487                .dispatch_weight(0.3)
488                .leaf_holder_weight(0.4)
489                .aggregator_max_depth(Some(2))
490                .dispatch_max_depth(Some(4))
491                .leaf_min_depth(Some(3))
492                .build()
493                .unwrap();
494
495            let cfg = GrowerTreeConfigurationBuilder::default()
496                .depth(6)
497                .tree_expansion_policy(TreeExpansionPolicy::WeightedWithLimits(wwl))
498                .try_build()
499                .unwrap();
500            let jcfg = to_justified(&cfg);
501            let instructions = jcfg.produce_concrete_growth_instructions();
502            info!("--- Configuration #5 ---\n\n{}\n", instructions);
503        }
504
505        // 6) Phased node variant policy
506        {
507            let phase1 = NodeVariantPhaseRangeBuilder::default()
508                .start_level(0)
509                .aggregator_weight(0.1)
510                .dispatch_weight(0.7)
511                .leaf_weight(0.2)
512                .build()
513                .unwrap();
514            let phase2 = NodeVariantPhaseRangeBuilder::default()
515                .start_level(3)
516                .aggregator_weight(0.4)
517                .dispatch_weight(0.2)
518                .leaf_weight(0.4)
519                .build()
520                .unwrap();
521
522            let phased_policy = PhasedNodeVariantPolicyBuilder::default()
523                .phases(vec![phase1, phase2])
524                .build()
525                .unwrap();
526
527            let cfg = GrowerTreeConfigurationBuilder::default()
528                .depth(6)
529                .tree_expansion_policy(TreeExpansionPolicy::Phased(phased_policy))
530                .try_build()
531                .unwrap();
532            let jcfg = to_justified(&cfg);
533            let instructions = jcfg.produce_concrete_growth_instructions();
534            info!("--- Configuration #6 ---\n\n{}\n", instructions);
535        }
536
537        // 7) Scripted node variant policy
538        {
539            let weights1 = NodeVariantLevelWeightsBuilder::default()
540                .aggregator_chance(0.2)
541                .dispatch_chance(0.5)
542                .leaf_chance(0.3)
543                .build()
544                .unwrap();
545            let weights2 = NodeVariantLevelWeightsBuilder::default()
546                .aggregator_chance(0.6)
547                .dispatch_chance(0.2)
548                .leaf_chance(0.2)
549                .build()
550                .unwrap();
551
552            let mut level_map = std::collections::HashMap::new();
553            level_map.insert(0_u8, weights1);
554            level_map.insert(3_u8, weights2);
555
556            let scripted = ScriptedNodeVariantPolicyBuilder::default()
557                .levels(level_map)
558                .build()
559                .unwrap();
560
561            let cfg = GrowerTreeConfigurationBuilder::default()
562                .depth(5)
563                .tree_expansion_policy(TreeExpansionPolicy::Scripted(scripted))
564                .try_build()
565                .unwrap();
566            let jcfg = to_justified(&cfg);
567            let instructions = jcfg.produce_concrete_growth_instructions();
568            info!("--- Configuration #7 ---\n\n{}\n", instructions);
569        }
570
571        // 8) AI confidence included
572        {
573            let ai_conf = AiTreeBranchingConfidenceConfigurationBuilder::default()
574                .base_factor(3)
575                .factor_multiplier(1.5)
576                .build()
577                .unwrap();
578            let cfg = GrowerTreeConfigurationBuilder::default()
579                .depth(4)
580                .breadth(3)
581                .ai_confidence(Some(ai_conf))
582                .try_build()
583                .unwrap();
584            let jcfg = to_justified(&cfg);
585            let instructions = jcfg.produce_concrete_growth_instructions();
586            info!("--- Configuration #8 ---\n\n{}\n", instructions);
587        }
588
589        // 9) Capstone configured as Single
590        {
591            let capstone = CapstoneGenerationConfigurationBuilder::default()
592                .mode(CapstoneMode::Single)
593                .probability(0.0)
594                .build()
595                .unwrap();
596
597            let cfg = GrowerTreeConfigurationBuilder::default()
598                .depth(5)
599                .capstone(Some(capstone))
600                .try_build()
601                .unwrap();
602            let jcfg = to_justified(&cfg);
603            let instructions = jcfg.produce_concrete_growth_instructions();
604            info!("--- Configuration #9 ---\n\n{}\n", instructions);
605        }
606
607        // 10) Full mix: Weighted branching, level skipping, capstone probabilistic, custom aggregator preference
608        {
609            let skip_cfg = LevelSkippingConfigurationBuilder::default()
610                .leaf_probability_per_level(vec![0.0, 0.2, 0.3, 0.7])
611                .build()
612                .unwrap();
613
614            let wb = WeightedBranchingConfigurationBuilder::default()
615                .mean(5)
616                .variance(2)
617                .build()
618                .unwrap();
619
620            let capstone = CapstoneGenerationConfigurationBuilder::default()
621                .mode(CapstoneMode::Probabilistic)
622                .probability(0.25)
623                .build()
624                .unwrap();
625
626            let cfg = GrowerTreeConfigurationBuilder::default()
627                .depth(6)
628                .breadth(4)
629                .density(3)
630                .leaf_granularity(0.9)
631                .balance_symmetry(0.4)
632                .aggregator_preference(0.2)
633                .level_skipping(Some(skip_cfg))
634                .weighted_branching(Some(wb))
635                .capstone(Some(capstone))
636                .try_build()
637                .unwrap();
638            let jcfg = to_justified(&cfg);
639            let instructions = jcfg.produce_concrete_growth_instructions();
640            info!("--- Configuration #10 ---\n\n{}\n", instructions);
641        }
642
643        info!("All varied configurations have been processed successfully.");
644    }
645}