capability_crate_writer/
grower_crate_writer.rs

1// ---------------- [ File: capability-crate-writer/src/grower_crate_writer.rs ]
2crate::ix!();
3
4error_tree!{
5    pub enum GrowerModelWriteSkillTreeError {
6        Default,
7    }
8}
9
10pub trait SkillTreeCrateWriter {
11
12    type Error;
13
14    fn skill_tree_write_crate_text(&self) -> Result<String,Self::Error>;
15}
16
17impl SkillTreeCrateWriter for GrowerModel {
18    type Error = GrowerModelWriteSkillTreeError;
19
20    fn skill_tree_write_crate_text(&self) -> Result<String, Self::Error> {
21        use std::collections::{HashMap, HashSet, VecDeque};
22
23        info!("model = {:#?}", self);
24
25        // -------------------------------------------------------------------------
26        // Build a name‑to‑node map and discover *root* nodes (those that are never
27        // referenced as a child).  We also record quick‑lookup helper sets.
28        // -------------------------------------------------------------------------
29        let all_nodes = self.core_string_skeleton().top_down_nodes();
30
31        let mut node_map          = HashMap::<String, CoreSkeletalNode>::new();
32        let mut referenced_childs = HashSet::<String>::new();
33        let mut leaf_holder_names = HashSet::<String>::new();
34        let mut dispatch_names    = HashSet::<String>::new();
35
36        for n in all_nodes {
37            match &n {
38                CoreSkeletalNode::Dispatch(d) => {
39                    dispatch_names.insert(d.name().clone());
40                    referenced_childs.extend(d.children().iter().map(|c| c.name().clone()));
41                }
42                CoreSkeletalNode::Aggregate(a) => {
43                    referenced_childs.extend(a.children().iter().map(|c| c.name().clone()));
44                }
45                CoreSkeletalNode::LeafHolder(lh) => {
46                    leaf_holder_names.insert(lh.name().clone());
47                }
48            }
49            node_map.insert(n.name().clone(), n);
50        }
51
52        let mut roots: Vec<String> = node_map
53            .keys()
54            .filter(|name| !referenced_childs.contains(*name))
55            .cloned()
56            .collect();
57        roots.sort(); // deterministic root ordering
58        trace!(?roots, "identified crate‑emission roots");
59
60        // -------------------------------------------------------------------------
61        // Crate preamble
62        // -------------------------------------------------------------------------
63        let mut crate_text = String::new();
64        crate_text.push_str(
65            r#"// SPDX-License-Identifier: GPL-3.0-only
66// This crate was generated by `capability` (GPLv3 licensed).
67// This generated crate is explicitly licensed under GPLv3.
68
69#![allow(unused_imports)]
70#![allow(unused_variables)]
71
72use std::fmt::Debug;
73use serde::{Serialize, Deserialize};
74use std::hash::Hash;
75use tracing::*;
76use variant_builder_macro::*;
77use rand_construct::*;
78use ai_descriptor::*;
79use derive_builder::*;
80use getset::*;
81
82"#,
83        );
84
85        let mut entrypoint_type = roots[0].to_string();
86
87        let root_is_dispatch = matches!(
88            node_map.get(&entrypoint_type),
89            Some(CoreSkeletalNode::Dispatch(_))
90        );
91
92        let top_name = if root_is_dispatch {
93            format!("{entrypoint_type}Top")
94        } else {
95            entrypoint_type.clone()
96        };
97
98        let top_snake = top_name.to_snake_case();
99        let top_kebab = top_name.to_kebab_case();
100
101    crate_text.push_str(&formatdoc!(r#"
102#[cfg(test)]
103mod {top_snake}_test_suite {{
104    use super::*;
105    use traced_test::*;
106    use tracing_setup::*;
107
108    #[traced_test]
109    fn random_instantiation_test() {{
110        type This = {top_name};
111        let item = This::random();
112        println!("------------------------[random-{top_kebab}]");
113        (0..120).for_each(|_| println!("{{}}\n", This::random().ai()));
114        //assert!(false); // uncomment this assertion to see the results
115    }}
116}}
117
118"#));
119
120        if root_is_dispatch {
121
122            info!("installing dispatch abstraction layer to the top");
123
124            let inner_field   = entrypoint_type.to_snake_case();   // `adaptive_brainwave_phase_locking`
125
126            let child = node_map.get(&entrypoint_type).expect("child must exist when building variants");
127
128            let header_text = match child {
129                CoreSkeletalNode::Dispatch(dchild) => dchild.descriptor(),
130                CoreSkeletalNode::Aggregate(a) => a.descriptor(),
131                CoreSkeletalNode::LeafHolder(lh) => lh.descriptor(),
132            };
133
134            crate_text.push_str(&formatdoc! {r#"
135                #[derive(VariantBuilder,Debug, Clone, ItemWithFeatures, RandConstruct, Hash, PartialEq, Eq)]
136                pub enum {top_name} {{
137                    #[default]
138                    #[ai(wrap = "ItemWithFeatures")]
139                    #[nested_builder]
140                    #[ai(header_prefix="{header_text} ")]
141                    {entrypoint_type}({entrypoint_type}),
142                }}
143
144                "#});
145
146                // replace the “entry point” used in the test module
147                crate_text = crate_text.replace(
148                    &format!("type This = {entrypoint_type};"),
149                    &format!("type This = {top_name};"),
150                );
151        }
152
153        info!("about to emit nodes");
154
155        // -------------------------------------------------------------------------
156        // Utility: descriptor lookup for leaves
157        // -------------------------------------------------------------------------
158        fn leaf_descriptor_for(
159            leaf_holder_name: &str,
160            leaf_name:        &str,
161            expansions:       &AnnotatedLeafHolderExpansions,
162        ) -> String {
163            for holder in expansions.annotated_leaf_holders() {
164                if holder.leaf_holder_name() == leaf_holder_name {
165                    for ann in holder.annotated_leaves() {
166                        if ann.leaf_name() == leaf_name {
167                            return ann.leaf_descriptor().to_string();
168                        }
169                    }
170                }
171            }
172            format!("No descriptor found for leaf '{leaf_name}'.")
173        }
174
175        // -------------------------------------------------------------------------
176        // Breadth‑first emission — preserves *parent‑variant order* at each level
177        // -------------------------------------------------------------------------
178        let mut emitted = HashSet::<String>::new();
179
180        #[instrument(level = "trace", skip_all)]
181        fn emit_node(
182            name:               &str,
183            node_map:           &HashMap<String, CoreSkeletalNode>,
184            leaf_holder_names:  &HashSet<String>,
185            dispatch_names:     &HashSet<String>,
186            emitted:            &mut HashSet<String>,
187            crate_text:         &mut String,
188            model:              &GrowerModel,
189        ) {
190            if !emitted.insert(name.to_string()) {
191                trace!(node = name, "already emitted — skipping");
192                return;
193            }
194
195            let node = match node_map.get(name) {
196                Some(n) => n,
197                None => {
198                    warn!(node = name, "child referenced but not found in map");
199                    return;
200                }
201            };
202
203            debug!("emit_node, passed preliminary checks");
204
205            match node {
206                // ------------------------------------------------------------------ DISPATCH
207                CoreSkeletalNode::Dispatch(d) => {
208                    let mut variants = String::new();
209
210                    for (idx, ch) in d.children().iter().enumerate() {
211
212                        let child = node_map.get(ch.name())
213                            .expect("child must exist when building variants");
214
215                        if idx == 0 {
216                            variants.push_str("#[default]\n");
217                        }
218
219                        match child {
220                            // ───── nested dispatch ────────────────────────────────
221                            CoreSkeletalNode::Dispatch(dchild) => {
222                                variants.push_str("    #[ai(wrap = \"ItemWithFeatures\")]\n");
223                                variants.push_str("    #[nested_builder]\n");
224                                variants.push_str(&format!(
225                                        "    #[ai(header_prefix = \"{} \")]\n",
226                                        dchild.descriptor()
227                                ));
228                            }
229                            // ───── aggregate struct ───────────────────────────────
230                            CoreSkeletalNode::Aggregate(_) => {
231                                variants.push_str("    #[ai(wrap = \"ItemWithFeatures\")]\n");
232                            }
233                            // ───── leaf holder – simple feature list ──────────────
234                            CoreSkeletalNode::LeafHolder(lh) => {
235                                variants.push_str("    #[no_builder]\n");
236                                variants.push_str(&format!(
237                                        "    #[ai(\"{}\")]\n",
238                                        lh.descriptor()
239                                ));
240                            }
241                        }
242
243                        // common line that actually declares the variant
244                        variants.push_str(&format!("    {}({}),\n", ch.name(), ch.name()));
245                    }
246
247                    crate_text.push_str(&formatdoc!(
248                        r#"
249                        #[derive(VariantBuilder, Debug, Clone, ItemWithFeatures, RandConstruct, Hash, PartialEq, Eq)]
250                        pub enum {ename} {{
251                            {variants}
252                        }}
253
254                        "#,
255                        ename    = d.name(),
256                        variants = variants.trim_end(),
257                    ));
258                }
259
260                // ---------------------------------------------------------------- AGGREGATE
261                CoreSkeletalNode::Aggregate(a) => {
262                    let mut fields = String::new();
263                    let mut found_opt_child = false;
264
265                    for ch in a.children() {
266
267                        let field_name = ch.name().to_case(Case::Snake);
268
269                        let child = node_map.get(ch.name())
270                            .expect("child must exist when building variants");
271
272                        let child_descriptor = match child {
273                            CoreSkeletalNode::Dispatch(dchild) => dchild.descriptor(),
274                            CoreSkeletalNode::Aggregate(a) => a.descriptor(),
275                            CoreSkeletalNode::LeafHolder(lh) => lh.descriptor(),
276                        };
277
278                        if *ch.optional() {
279                            let p = *ch.probability() as f64 / 100.0;
280
281                            let opt_header = match found_opt_child {
282                                true  => "No ",
283                                false => "Specifically contains no ",
284                            };
285
286                            fields.push_str(&format!(
287                                r#"
288    #[ai(feature_if_none="{opt_header}'{child}' module.")]
289    #[ai(feature_prefix_if_some="{child_descriptor} ")]
290    #[rand_construct(psome={prob})]
291    {field}: Option<{child}>,"#,
292                                child = ch.name(),
293                                prob  = p,
294                                field = field_name,
295                            ));
296
297                            found_opt_child = true;
298
299                        } else {
300                            fields.push_str(&format!(
301                                r#"
302    #[ai("{child_descriptor}")]
303    {field}: {child},"#,
304                                child = ch.name(),
305                                field = field_name,
306                            ));
307
308                        }
309                    }
310
311                    crate_text.push_str(&formatdoc!(
312                        r#"
313                        #[derive(Builder, Debug, Clone, ItemWithFeatures, RandConstruct, Default, Hash, PartialEq, Eq, Getters)]
314                        #[builder(pattern="owned", setter(into))]
315                        #[ai("{desc}")]
316                        pub struct {sname} {{
317                            {fields}
318                        }}
319
320                        "#,
321                        desc   = a.descriptor(),
322                        sname  = a.name(),
323                        fields = fields.trim_end(),
324                    ));
325                }
326
327                // -------------------------------------------------------------- LEAF‑HOLDER
328                CoreSkeletalNode::LeafHolder(lh) => {
329                    let mut variants = String::new();
330                    for (idx, leaf) in lh.leaves().iter().enumerate() {
331                        if idx == 0 {
332                            variants.push_str("#[default]\n");
333                        }
334                        let ld = leaf_descriptor_for(
335                            lh.name(),
336                            leaf,
337                            model.annotated_leaf_holder_expansions(),
338                        );
339                        variants.push_str(&format!(
340                            "    #[ai(\"{ld}\")]\n    {leaf},\n",
341                            ld   = ld,
342                            leaf = leaf
343                        ));
344                    }
345
346                    crate_text.push_str(&formatdoc!(
347                        r#"
348                        #[derive(Debug, Clone, ItemFeature, RandConstruct, Default, Hash, PartialEq, Eq)]
349                        pub enum {ename} {{
350                            {variants}
351                        }}
352
353                        "#,
354                        ename    = lh.name(),
355                        variants = variants.trim_end(),
356                    ));
357                }
358            }
359        }
360
361        // -------------------------- breadth‑first traversal --------------------------
362        let mut queue: VecDeque<String> = roots.into_iter().collect();
363        while let Some(current) = queue.pop_front() {
364
365            debug!("processing {:#?}", current);
366
367            emit_node(
368                &current,
369                &node_map,
370                &leaf_holder_names,
371                &dispatch_names,
372                &mut emitted,
373                &mut crate_text,
374                self,
375            );
376
377            debug!("emit_node terminated");
378
379            if let Some(node) = node_map.get(&current) {
380                match node {
381                    CoreSkeletalNode::Dispatch(d) => {
382                        debug!("processing Dispatch node {:#?}", d);
383                        for ch in d.children() {
384                            if !emitted.contains(ch.name()) {
385                                queue.push_back(ch.name().clone());
386                            }
387                        }
388                    }
389                    CoreSkeletalNode::Aggregate(a) => {
390                        debug!("processing Aggregate node {:#?}", a);
391                        for ch in a.children() {
392                            if !emitted.contains(ch.name()) {
393                                queue.push_back(ch.name().clone());
394                            }
395                        }
396                    }
397                    CoreSkeletalNode::LeafHolder(lh) => {
398                        debug!("processing LeafHolder node {:#?}", lh);
399                    }
400                }
401            }
402        }
403
404        Ok(crate_text)
405    }
406}
407
408#[cfg(test)]
409mod grower_model_tests {
410    use super::*;
411
412    #[traced_test]
413    async fn basic_smoke() -> Result<(),GrowerModelWriteSkillTreeError> {
414
415        let mut map = HashMap::<&'static str, &[&'static str]>::default();
416
417        map.insert("foxes", &[
418            "fox-advanced-social-group-coordination-and-complex-cooperative-task-execution",
419            "fox-performance-conditioning-for-speed-and-endurance",
420            "fox-advanced-performance-design-and-precision-task-choreography-mastery",
421            "fox-initial-directional-cue-response-training-to-basic-verbal-and-hand-gestures",
422            "fox-basic-den-and-resting-area-familiarization-and-conditioning",
423            "fox-basic-target-following-over-short-distances-and-simple-pathways",
424            "fox-social-group-coordination-and-cooperative-task-conditioning",
425            "fox-simple-habitat-maintenance-and-comfort-management-awareness",
426            "fox-long-duration-station-holding-and-task-performance-under-significant-distractions",
427            "fox-positive-food-reward-conditioning-with-precise-delivery-timing",
428            "fox-performance-prop-interaction-techniques",
429            "fox-soft-vocal-tone-and-human-voice-conditioning-for-trust-building",
430            "fox-positive-reinforcement-training-techniques",
431            "fox-object-manipulation-under-forest-conditions",
432            "fox-advanced-object-manipulation-in-forest-settings",
433            "fox-basic-station-area-familiarization-and-short-duration-conditioning",
434            "fox-target-tracking-through-variable-terrain",
435            "fox-positive-food-association-conditioning-with-human-interaction",
436            "fox-basic-agility-and-precision-foot-placement-training-over-low-obstacles",
437            "fox-social-performance-cue-responsiveness",
438            "fox-station-duration-extension-up-to-3-minutes-under-controlled-distractions",
439            "fox-stress-reduction-and-socialization-methods",
440            "fox-highly-precise-target-following-and-navigation-through-challenging-and-variable-environments",
441            "fox-controlled-introduction-to-minimal-environmental-distractions-and-stimuli",
442            "fox-complex-directional-cue-response-with-combined-visual-verbal-and-tactile-signals",
443            "fox-target-identification-and-tracking-skills",
444            "fox-advanced-territorial-navigation-resource-management-and-boundary-recognition-training",
445            "fox-intermediate-agility-course-navigation-with-complex-terrain-and-obstacles",
446            "fox-agility-and-performance-cue-mastery",
447            "fox-advanced-object-manipulation-tool-use-and-complex-task-performance-conditioning",
448            "fox-station-duration-training-starting-from-15-to-45-seconds",
449            "fox-simple-social-presence-conditioning-with-multiple-handlers-and-conspecifics",
450            "fox-extended-target-following-and-navigation-over-complex-and-variable-terrain",
451            "fox-gradual-human-presence-desensitization-through-controlled-proximity-management",
452            "fox-adaptive-responsiveness-to-sophisticated-multi-modal-command-sequences",
453            "fox-initial-observation-of-stress-and-relaxation-body-language-signals",
454            "fox-simple-object-touch-retrieval-and-target-response-conditioning",
455            "fox-controlled-conditioning-to-low-intensity-environmental-distractions",
456            "fox-precision-object-manipulation-placement-and-sequential-task-training",
457            "fox-comprehensive-emotional-and-stress-state-monitoring-for-optimal-engagement",
458            "fox-agility-course-vertical-scaling",
459            "fox-basic-grooming-health-inspection-and-handling-desensitization",
460            "fox-responsiveness-conditioning-to-subtle-human-body-language-and-gesture-cues",
461            "fox-positive-reward-frequency-and-type-optimization-for-task-complexity",
462            "fox-initial-scent-familiarization-and-positive-object-association",
463            "fox-comprehensive-problem-solving-adaptive-behavior-and-task-sequencing-conditioning",
464            "fox-extended-grooming-handling-and-comprehensive-health-examination-conditioning",
465            "fox-group-social-coordination-techniques",
466            "fox-advanced-agility-course-precision-training",
467            "fox-extended-performance-of-complex-sequential-behavioral-tasks-with-memory-retention",
468            "fox-controlled-introduction-to-basic-hand-proximity-and-gentle-touch",
469            "fox-basic-eye-contact-duration-awareness-and-conditioning",
470            "fox-group-social-cue-training",
471            "fox-agility-course-navigation-with-complex-obstacles",
472            "fox-advanced-object-discrimination-training",
473            "fox-targeted-enrichment-exercise-regimens",
474            "fox-controlled-conditioning-to-moderate-environmental-and-social-distractions",
475            "fox-social-hierarchy-performance-management",
476        ]);
477
478        map.insert("real-estate", &[
479            "real-estate-72-hour-clause-contingent-sale-risk-management",
480            "real-estate-abstract-of-title-verification-and-analysis",
481            "real-estate-acceleration-clause-default-risk-management",
482            "real-estate-accession-property-rights-clarification",
483            "real-estate-acreage-measurement-and-land-valuation",
484            "real-estate-ad-valorem-property-tax-management",
485            "real-estate-adjustable-rate-mortgage-risk-mitigation",
486            "real-estate-adjusted-basis-capital-gain-calculation",
487            "real-estate-adverse-possession-property-rights-defense",
488            "real-estate-affordable-housing-investment-and-social-impact-strategy",
489            "real-estate-agency-transaction-representation-management",
490            "real-estate-agent-transaction-facilitation-management",
491            "real-estate-air-rights-acquisition-and-utilization",
492            "real-estate-alluvion-and-accretion-property-boundary-management",
493            "real-estate-american-land-title-association-compliance",
494            "real-estate-amortizing-loan-management-and-strategy",
495            "real-estate-anchor-store-commercial-investment-strategy",
496            "real-estate-annexation-and-zoning-impact-management",
497            "real-estate-annual-percentage-rate-cost-assessment",
498            "real-estate-anti-money-laundering-compliance-and-risk-management",
499            "real-estate-apartment-investment-analysis-and-management",
500            "real-estate-appraisal-property-valuation-strategy",
501            "real-estate-appraisal-standards-professional-compliance",
502            "real-estate-appraised-value-assessment-and-validation",
503            "real-estate-appurtenant-easement-rights-and-valuation",
504            "real-estate-arms-length-transaction-principle-compliance",
505            "real-estate-arrears-debt-collection-and-management",
506            "real-estate-asking-price-negotiation-strategy",
507            "real-estate-asset-identification-and-financial-resource-management",
508            "real-estate-assignment-law-contractual-rights-transfer",
509            "real-estate-assumption-of-mortgage-transaction-management",
510            "real-estate-attorney-at-law-transaction-and-legal-protection",
511            "real-estate-attorney-in-fact-financial-authority-management",
512            "real-estate-avulsion-property-boundary-risk-management",
513            "real-estate-balance-sheet-preparation-and-financial-reporting",
514            "real-estate-balloon-mortgage-structure-and-risk-management",
515            "real-estate-bargain-and-sale-deed-risk-clarification",
516            "real-estate-benchmarking-investment-performance-management",
517            "real-estate-beneficiary-rights-and-management",
518            "real-estate-bequest-property-transfer-and-legacy-planning",
519            "real-estate-bilateral-contract-management-and-enforcement",
520            "real-estate-bill-of-sale-documentation-and-transfer-management",
521            "real-estate-blanket-loan-portfolio-financing-strategy",
522            "real-estate-blockchain-title-transfer-and-risk-management",
523            "real-estate-boiler-insurance-coverage-and-risk-management",
524            "real-estate-bona-fide-purchaser-rights-and-protection",
525            "real-estate-book-value-calculation-and-valuation-management",
526            "real-estate-boot-property-exchange-and-tax-management",
527            "real-estate-boundary-determination-and-dispute-resolution",
528            "real-estate-bpo-standards-and-guidelines-compliance",
529            "real-estate-broker-transaction-integrity-management",
530            "real-estate-brokerage-market-access-management",
531            "real-estate-brokers-price-opinion-valuation-and-compliance",
532            "real-estate-bubble-market-risk-awareness",
533        ]);
534
535        map.insert("zoosemiosis", &[
536            "zoosemiotic-danger-safety-alarm-calls-and-predator-response-training",
537            "zoosemiotic-danger-safety-context-driven-symbolic-learning-and-adaptation",
538            "zoosemiotic-danger-safety-cross-species-threat-recognition-and-signaling",
539            "zoosemiotic-danger-safety-minimal-ambiguity-and-rapid-sign-processing-training",
540            "zoosemiotic-danger-safety-risk-assessment-and-group-vigilance-pattern-recognition",
541            "zoosemiotic-family-social-bonds-cooperation-conflict-and-reconciliation-pattern-training",
542            "zoosemiotic-family-social-bonds-minimal-symbolic-density-in-social-maintenance-signals",
543            "zoosemiotic-family-social-bonds-parent-offspring-signaling-patterns",
544            "zoosemiotic-family-social-bonds-social-affiliation-and-hierarchy-sign-recognition",
545            "zoosemiotic-food-nourishment-cross-species-competition-and-cooperation-signals",
546            "zoosemiotic-food-nourishment-foraging-and-feeding-sign-pattern-recognition",
547            "zoosemiotic-food-nourishment-group-coordination-in-hunting-and-gathering",
548            "zoosemiotic-food-nourishment-resource-availability-and-minimal-sign-density-calibration",
549            "zoosemiotic-food-nourishment-symbolic-social-learning-and-cultural-transmission",
550            "zoosemiotic-life-death-affiliative-behavior-during-distress-events",
551            "zoosemiotic-life-death-alarm-signal-pattern-analysis",
552            "zoosemiotic-life-death-alarm-signal-pattern-analysis2",
553            "zoosemiotic-life-death-minimal-energy-signaling-and-survival-patterns",
554            "zoosemiotic-life-death-ritualized-behavior-and-social-learning-calibration",
555            "zoosemiotic-life-death-symbolic-recognition-in-animal-behavior",
556            "zoosemiotic-motion-rest-cross-species-symbolic-motion-pattern-calibration",
557            "zoosemiotic-motion-rest-group-movement-coordination-and-minimal-energy-signals",
558            "zoosemiotic-motion-rest-locomotion-patterns-and-symbolic-social-signals",
559            "zoosemiotic-motion-rest-predator-and-prey-chase-pattern-symbol-recognition",
560            "zoosemiotic-motion-rest-resting-state-and-social-relaxation-sign-recognition",
561            "zoosemiotic-sun-moon-circadian-rhythm-and-signal-pattern-calibration",
562            "zoosemiotic-sun-moon-cross-species-temporal-signaling-optimization",
563            "zoosemiotic-sun-moon-minimal-density-energy-expenditure-calibration",
564            "zoosemiotic-sun-moon-nocturnal-and-diurnal-behavior-pattern-recognition",
565            "zoosemiotic-sun-moon-seasonal-migration-and-navigation-signal-analysis",
566            "zoosemiotic-time-space-cross-species-territorial-dispute-resolution-signals",
567            "zoosemiotic-time-space-home-range-recognition-and-spatial-symbolic-cognition",
568            "zoosemiotic-time-space-minimal-density-symbolic-navigation-training",
569            "zoosemiotic-time-space-navigation-patterns-and-migratory-route-symbols",
570            "zoosemiotic-time-space-territorial-signaling-and-boundary-recognition",
571        ]);
572
573        map.insert("owl", &[
574            "owl-adaptive-responsiveness-to-highly-sophisticated-multi-modal-command-sequences",
575            "owl-advanced-flight-pattern-choreography",
576            "owl-advanced-object-manipulation-and-complex-task-performance-conditioning",
577            "owl-advanced-performance-design-and-precision-flight-choreography-mastery",
578            "owl-advanced-problem-solving-adaptive-behavior-and-flight-sequencing-conditioning",
579            "owl-basic-eye-contact-duration-awareness-and-conditioning",
580            "owl-basic-flight-agility-and-navigation-conditioning-over-low-level-obstacles",
581            "owl-basic-health-inspection-handling-and-equipment-desensitization",
582            "owl-basic-observation-of-stress-and-relaxation-body-language-signals",
583            "owl-basic-station-area-familiarization-and-short-duration-conditioning",
584            "owl-basic-target-following-over-short-distances-and-simple-flight-paths",
585        ]);
586
587        map.insert("adaptive-technology", &[
588            "active-camouflage-metamaterial-optical-field-adaptation-training",
589            "adaptive-biomechanical-control-algorithm-human-integration-calibration",
590            "adaptive-camouflage-field-integrated-microelectronics-optimization",
591            "adaptive-composite-armor-dynamic-stiffness-response-calibration",
592            "adaptive-drone-network-minimal-communication-latency-calibration",
593            "adaptive-exoskeleton-predictive-biomechanical-interface-training",
594            "adaptive-medical-response-minimal-human-intervention-calibration",
595            "adaptive-reaction-control-micro-scale-thruster-precision",
596            "adaptive-thermal-management-for-high-energy-portable-devices",
597            "additive-manufacturing-complex-metamaterial-precision-training",
598            "advanced-augmented-reality-hud-and-sensor-fusion-training",
599            "advanced-cryostasis-vitrification-and-cellular-integrity-preservation",
600            "advanced-field-medical-kit-ai-driven-autonomous-diagnosis",
601            "advanced-gravitational-field-manipulation-and-frame-dragging-control",
602            "advanced-materials-flexible-armor-and-metamaterial-engineering",
603            "advanced-medical-biofoam-hemostatic-and-tissue-regeneration",
604            "advanced-microfusion-direct-electrical-energy-conversion",
605            "ai-driven-nanomachine-coordination-and-autonomous-repair-training",
606            "antigravity-device-minimal-gravitational-distortion-calibration",
607            "autonomous-adaptive-combat-vehicle-sensor-degradation-tolerance",
608            "autonomous-nanoscale-molecular-manufacturing-training",
609            "autonomous-robotic-assembly-complex-structures-optimization",
610            "autonomous-vehicle-combat-decision-making-and-tactical-autonomy",
611            "biocompatible-neural-implant-long-term-stability-calibration",
612            "biomechanical-predictive-algorithms-for-armor-mobility-optimization",
613            "compact-directed-energy-weapon-miniaturization-and-efficiency-training",
614            "compact-fusion-reactor-energy-density-and-confinement-optimization",
615            "compact-life-support-environmental-control-system-calibration",
616            "compact-particle-accelerator-miniaturization-and-field-control",
617            "composite-material-integrity-under-extreme-condition-calibration",
618            "cryopreservation-vitrification-cellular-integrity-optimization",
619            "distributed-autonomous-vehicle-communication-robustness-calibration",
620            "drone-swarm-tactical-coordination-and-autonomous-control",
621            "dynamic-structural-health-monitoring-system-feedback-calibration",
622            "exoskeleton-neural-integration-with-minimal-latency-optimization",
623            "functional-metamaterial-cloaking-infrared-and-radar-invisibility-calibration",
624            "hard-light-field-generation-with-electromagnetic-force-feedback",
625            "high-density-information-storage-and-quantum-state-encoding",
626            "high-density-neuromorphic-computing-architecture-calibration",
627            "high-density-ultracapacitor-energy-release-and-storage-optimization",
628            "high-efficiency-electromagnetic-propulsion-and-energy-transfer",
629            "high-efficiency-plasma-generation-portable-device-optimization",
630            "high-energy-rifle-containment-field-density-calibration",
631            "high-frequency-directed-energy-field-density-calibration",
632            "high-temperature-superconducting-magnet-field-density-calibration",
633            "high-temperature-superconductor-miniaturization-and-field-density-calibration",
634            "hybrid-electric-propellant-thruster-miniaturization-and-efficiency-calibration",
635            "hybrid-quantum-classical-computational-architecture-integration",
636            "individual-precision-controlled-aerobraking-and-landing-algorithms",
637            "individual-scale-precision-heat-shielding-for-reentry-training",
638            "infantry-scale-electromagnetic-cloaking-field-optimization",
639            "instantaneous-neural-encoding-and-decoding-algorithms",
640            "integrated-eye-tracking-and-real-time-object-recognition",
641            "integrated-holographic-display-resolution-and-accuracy-calibration",
642            "low-latency-neural-feedback-for-combat-enhancement-training",
643            "low-power-edge-computing-sensor-fusion-density-optimization",
644            "micro-fusion-reactor-prototype-net-positive-energy-output-calibration",
645            "micro-scale-thermal-management-for-high-density-devices",
646            "microfluidic-on-demand-drug-synthesis-and-delivery-precision",
647            "microfluidic-on-demand-pharmaceutical-synthesis-precision-calibration",
648            "miniature-thruster-reaction-control-and-aerodynamic-calibration",
649        ]);
650
651        map.insert("electronic-music", &[
652            "adaptive-ambient-space-design",
653            "adaptive-attack-release-envelope",
654            "adaptive-attack-release-tail-modeling",
655            "adaptive-binaural-beat-generation",
656            "adaptive-binaural-room-modeling",
657            "adaptive-biofeedback-frequency-design",
658            "adaptive-bowed-string-harmonics",
659            "adaptive-brainwave-phase-locking",
660            "adaptive-build-break-energy-control",
661            "adaptive-chop-density-control",
662            "adaptive-crossfade-loop-blending",
663        ]);
664
665        map.insert("river-town", &[
666            "alleyway-agility",
667            "amphibious-combat-tactics",
668            "animal-flow",
669            "aquatic-grappling",
670            "balance",
671            "bar-fighting",
672            "boxing",
673            "breakdancing",
674            "breathwork",
675            "bushcraft",
676            "calisthenics",
677            "camouflage",
678            "canoeing",
679            "capoeira",
680            "close-quarters-combat",
681            "cobblestone-street-running",
682            "cold-water-conditioning",
683            "docs",
684            "evasion",
685            "fire-environment-qigong",
686            "fishing",
687            "forest-based-archery",
688            "forest-orienteering",
689            "forest-slacklining",
690            "guerrilla-combat-tactics",
691            "gymnastics",
692            "historic-meditation",
693            "historic-urban-bushcraft",
694            "historical-archery",
695            "historical-european-martial-arts",
696            "historical-site-yoga",
697            "hydrotherapy",
698            "ice-fishing",
699            "improvised-combat",
700            "jedi-mind-tricks",
701            "judo",
702            "knife-fighting",
703            "knife-throwing",
704            "krav-maga",
705            "lockpicking",
706            "love",
707            "medieval-calisthenics",
708            "meditation",
709            "mouvement-naturel",
710            "natural-movement",
711            "parkour",
712            "patch-bay",
713            "pilates",
714            "primitive-fish-trapping",
715            "primitive-hunting",
716            "qigong",
717            "quigong",
718            "rafting",
719            "river-crossing-techniques",
720            "river-running",
721            "river-swimming",
722            "riverbank-bushcraft",
723            "riverside-balance-training",
724            "riverside-yoga",
725            "rooftop-traversal",
726            "sanskrit-yoga",
727            "snow-love",
728            "snow-love-building",
729            "snow-love-building-advanced",
730            "snow-love-building-masterful",
731            "snow-love-campfire",
732            "spearfishing",
733            "stealth-movement",
734            "swiftwater-parkour",
735            "swiftwater-rescue",
736            "tai-chi",
737            "target",
738            "trail-running",
739            "trapping",
740            "tree-climbing",
741            "urban-entry-techniques",
742            "urban-foraging",
743            "urban-historical-parkour",
744            "urban-slacklining",
745            "urban-stealth",
746            "waterborne-archery",
747            "watercraft-construction",
748            "whitewater-kayaking",
749            "wilderness-first-aid",
750            "woodland-yoga",
751            "yoga-sanskrit",
752        ]);
753
754        let generated_skill_tree_workspaces_dir = "generated-skill-tree-workspaces";
755
756        let do_these = [
757            //"zoosemiosis",
758            //"foxes",
759            "river-town",
760        ];
761
762        for (workspace_key, workspace_set) in map.iter() {
763
764            if !do_these.is_empty() && !do_these.contains(workspace_key) {
765                continue;
766            }
767      
768            let mut set_members = vec![];
769
770            for name in workspace_set.iter() {
771                if let Ok(model)
772                    = GrowerModel::load_from_file(format!("../patch-bay/{name}.json"))
773                    .await 
774                {
775                    let crate_text = model.skill_tree_write_crate_text()?;
776
777                    let cargo_toml_text = formatdoc!{
778                    r#"
779                    [package]
780                    name = "{name}"
781                    license = "GPL-3.0-only"
782                    license-text = "LICENSE"
783                    authors = ["klebs6 <tpk3.mx@gmail.com>"]
784                    version = "0.1.0"
785                    edition = "2024"
786                    description = "Skill tree crate for the {name} system."
787                    keywords = ["grower", "skill", "tree", "simulation", "generator"]
788                    categories = ["simulation"]
789
790                    [dependencies]
791                    ai-descriptor.workspace         = true
792                    ai-descriptor-derive.workspace  = true
793                    export-magic.workspace          = true
794                    once_cell.workspace             = true
795                    rand.workspace                  = true
796                    derive_builder.workspace        = true
797                    getset.workspace                = true
798                    tracing.workspace               = true
799                    tracing-setup.workspace         = true
800                    traced-test.workspace           = true
801                    serde.workspace                 = true
802                    variant-builder-macro.workspace = true
803                    rand-construct.workspace        = true
804                    "#};
805
806                    let license_text = formatdoc!{
807                        r#"Licensed under GPLv3. Downstream generation byproducts inherit GPLv3."#
808                    };
809
810                    std::fs::create_dir_all(format!("../{generated_skill_tree_workspaces_dir}/{workspace_key}/{name}/src")).expect("expected create dir success");
811
812                    std::fs::write(format!("../{generated_skill_tree_workspaces_dir}/{workspace_key}/{name}/src/lib.rs"), crate_text).expect("we expected to be able to write this file");
813                    std::fs::write(format!("../{generated_skill_tree_workspaces_dir}/{workspace_key}/{name}/Cargo.toml"), cargo_toml_text).expect("we expected to be able to write the Cargo.toml");
814                    std::fs::write(format!("../{generated_skill_tree_workspaces_dir}/{workspace_key}/{name}/LICENSE"), license_text).expect("we expected to be able to write the SPPL license file");
815
816                    set_members.push(name);
817
818                } else {
819                    warn!("expected to unpack this file ../patch-bay/{name}.json");
820                }
821            }
822
823            let workspace_cargo_toml_text = formatdoc! {
824                r#"
825                [workspace]
826                members = [
827                {members}
828                ]
829
830                [workspace.dependencies]
831                ai-descriptor         = {{ version = "0.11.0", path = "/Users/kleb/bethesda/work/repo/klebs-general/ai-descriptor" }}
832                ai-descriptor-derive  = {{ version = "0.6.0", path  = "/Users/kleb/bethesda/work/repo/klebs-general/ai-descriptor-derive" }}
833                derive_builder        = "0.20.2"
834                export-magic          = "0.3.6"
835                getset                = "0.1.4"
836                once_cell             = "1.20.2"
837                rand                  = "0.8.5"
838                rand-construct        = {{ version = "0.14.0", path = "/Users/kleb/bethesda/work/repo/klebs-general/rand-construct" }}
839                serde                 = "1.0.219"
840                traced-test           = {{ version = "1.0.3", path  = "/Users/kleb/bethesda/work/repo/klebs-general/traced-test" }}
841                tracing               = "0.1.41"
842                tracing-setup         = {{ version = "1.0.3", path  = "/Users/kleb/bethesda/work/repo/klebs-general/tracing-setup" }}
843                variant-builder-macro = {{ version = "0.3.0", path  = "/Users/kleb/bethesda/work/repo/klebs-general/variant-builder-macro" }}
844                "#,
845                members = set_members
846                    .iter()
847                    .map(|name| format!("    \"{name}\""))
848                    .collect::<Vec<_>>()
849                    .join(",\n")
850            };
851
852            let workspace_makefile_text = formatdoc! {
853                r#"
854                .PHONY: build active test run test_all
855                ENTRYPOINT := {workspace_key}
856
857                #RUSTFLAGS := "-Awarnings -Z time-passes"
858                RUSTFLAGS  := -Awarnings RUST_BACKTRACE=1
859                #CARGO     := env CARGO_MSG_LIMIT=15 CARGO_BUILD_JOBS=12 NUM_JOBS=12 cargo 
860                CARGO      := MAKEFLAGS= env CARGO_BUILD_JOBS=12 NUM_JOBS=12 cargo 
861                BUILD      := build --verbose
862                RUN        := run
863                TEST       := test
864
865                ACTIVE_PACKAGE := {first_package_name}
866
867                DEFAULT := test_all
868                #DEFAULT := test
869                #DEFAULT := build
870
871                #FEATURES := --features "enable_stress_test"
872                FEATURES := --features ""
873
874                default: $(DEFAULT)
875
876                #NOCAPTURE := --nocapture
877                #NOCAPTURE := 
878
879                #----------------------------------------------[here are our rules]
880
881                run:
882                    RUSTFLAGS=$(RUSTFLAGS) $(CARGO) run -p $(ACTIVE_PACKAGE) --bin $(ENTRYPOINT) $(FEATURES)
883
884                build:
885                    RUSTFLAGS=$(RUSTFLAGS) $(CARGO) $(BUILD) $(FEATURES)
886
887                active:
888                    RUSTFLAGS=$(RUSTFLAGS) $(CARGO) $(BUILD) -p $(ACTIVE_PACKAGE) $(FEATURES)
889
890                test:
891                    RUST_MIN_STACK=8388608 RUST_LOG=trace RUSTFLAGS=$(RUSTFLAGS) $(CARGO) $(TEST) -p $(ACTIVE_PACKAGE) -- $(NOCAPTURE)
892
893                test_all:
894                    RUSTFLAGS=$(RUSTFLAGS) $(CARGO) $(TEST) --workspace -- $(NOCAPTURE)
895                "#,
896                    first_package_name = set_members[0],
897                    workspace_key = workspace_key
898            }.replace("\n    ", "\n\t");  // replaces 4 spaces at start of lines with a tab
899
900            std::fs::write(format!("../{generated_skill_tree_workspaces_dir}/{workspace_key}/Cargo.toml"), workspace_cargo_toml_text).expect("we expected to be able to write the workspace Cargo.toml");
901            std::fs::write(format!("../{generated_skill_tree_workspaces_dir}/{workspace_key}/Makefile"), workspace_makefile_text).expect("we expected to be able to write the workspace Makefile");
902        }
903
904        Ok(())
905    }
906}
907
908/*
909#[derive(
910    Debug,
911    Clone,
912    PartialEq,
913    Getters,
914    Builder,
915    Serialize,
916    Deserialize,
917    SaveLoad,
918)]
919#[builder(pattern = "owned", setter(into))]
920#[getset(get = "pub")]
921pub struct GrowerModel {
922    grower_inputs:                         GrowerInputs,
923
924    #[serde(alias="maybe_ungrown_justified_grower_tree_configuration")]
925    justified_grower_tree_configuration:   JustifiedGrowerTreeConfiguration,
926
927    #[serde(alias="maybe_ungrown_justified_string_skeleton")]
928    justified_string_skeleton:             JustifiedStringSkeleton,
929
930    #[serde(alias="maybe_ungrown_stripped_string_skeleton")]
931    stripped_string_skeleton:              StrippedStringSkeleton,
932
933    #[serde(alias="maybe_ungrown_core_string_skeleton")]
934    core_string_skeleton:                  CoreStringSkeleton,
935
936    #[serde(alias="maybe_ungrown_annotated_leaf_holder_expansions")]
937    annotated_leaf_holder_expansions:      AnnotatedLeafHolderExpansions,
938}
939*/