capability-example 0.1.0

A framework for managing skill tree growth and configuration using automated and manual strategies, ideal for AI-driven environments.
Documentation
// ---------------- [ File: capability-example/src/manual_flow_try_to_fix_missing_field.rs ]
crate::ix!();

/// Called when validation of the partial model fails with a known "missing partial" error.
/// We query the `FlowStrategy` to see if it can fill in the missing piece automatically or by prompting the user.
#[instrument(level = "trace", skip_all)]
pub async fn manual_flow_try_to_fix_missing_field<S: GrowerFlowStrategy>(
    strategy:      &S,
    partial_model: &mut PartiallyGrownModel,
    grower_inputs: &GrowerInputs,
    error:         &GrowerModelGenerationInvalidPartial,
    cli:           &ManualGrowerFlowCliArgs,

) -> Result<(), ManualGrowerFlowError> {

    match error {

        GrowerModelGenerationInvalidPartial::MissingJustifiedGrowerTreeConfiguration => {
            // We call the strategy's "fill_justified_tree_configuration" method
            if let Some(config) = strategy
                .fill_justified_tree_configuration(partial_model, grower_inputs)
                .await?
            {
                partial_model.set_maybe_ungrown_justified_grower_tree_configuration(Some(config));
                let path = cli.calculate_partial_path(grower_inputs);
                partial_model.save_to_file(&path).await?;
            } else {
                // The strategy returned None => we do not fill it => bail out
                return Err(ManualGrowerFlowError::FillJustifiedTreeConfigurationError);
            }
        }

        GrowerModelGenerationInvalidPartial::MissingJustifiedStringSkeleton => {
            let tree_conf = partial_model
                .maybe_ungrown_justified_grower_tree_configuration()
                .as_ref()
                .expect("validate() wouldn't let us get here if that was also missing");
            if let Some(skel) = strategy
                .fill_justified_string_skeleton(partial_model, grower_inputs, tree_conf)
                .await?
            {
                partial_model.set_maybe_ungrown_justified_string_skeleton(Some(skel));
                let path = cli.calculate_partial_path(grower_inputs);
                partial_model.save_to_file(&path).await?;
            } else {
                return Err(ManualGrowerFlowError::FillJustifiedStringSkeletonError);
            }
        }

        GrowerModelGenerationInvalidPartial::MissingStrippedStringSkeleton => {
            // We can actually fill this automatically ourselves (like in the old code),
            // but let's illustrate how we might delegate to the strategy for consistency:
            let justified_skel = partial_model
                .maybe_ungrown_justified_string_skeleton()
                .as_ref()
                .expect("We wouldn't get here if that was missing");
            let stripped = StrippedStringSkeleton::from(justified_skel.clone());
            partial_model.set_maybe_ungrown_stripped_string_skeleton(Some(stripped));

            let path = cli.calculate_partial_path(grower_inputs);
            partial_model.save_to_file(&path).await?;
            // No strategy call needed if we do it ourselves, or we could do it in strategy
        }

        GrowerModelGenerationInvalidPartial::MissingCoreStringSkeleton => {
            let tree_conf = partial_model
                .maybe_ungrown_justified_grower_tree_configuration()
                .as_ref()
                .expect("We wouldn't get here if that was missing");
            let stripped_skel = partial_model
                .maybe_ungrown_stripped_string_skeleton()
                .as_ref()
                .expect("We wouldn't get here if that was missing");
            if let Some(core) = strategy
                .fill_core_string_skeleton(partial_model, grower_inputs, tree_conf, stripped_skel)
                .await?
            {
                partial_model.set_maybe_ungrown_core_string_skeleton(Some(core));
                let path = cli.calculate_partial_path(grower_inputs);
                partial_model.save_to_file(&path).await?;
            } else {
                return Err(ManualGrowerFlowError::FillMissingCoreStringSkeletonError);
            }
        }

        GrowerModelGenerationInvalidPartial::MissingAnnotatedLeafHolderExpansions => {
            let tree_conf = partial_model
                .maybe_ungrown_justified_grower_tree_configuration()
                .as_ref()
                .expect("We wouldn't get here if that was missing");
            let core_skel = partial_model
                .maybe_ungrown_core_string_skeleton()
                .as_ref()
                .expect("We wouldn't get here if that was missing");
            if let Some(ann) = strategy
                .fill_annotated_leaf_holder_expansions(
                    partial_model,
                    grower_inputs,
                    tree_conf,
                    core_skel,
                )
                .await?
            {
                partial_model.set_maybe_ungrown_annotated_leaf_holder_expansions(Some(ann));
                let path = cli.calculate_partial_path(grower_inputs);
                partial_model.save_to_file(&path).await?;
            } else {
                return Err(ManualGrowerFlowError::FillMissingAnnotatedLeafHolderError);
            }
        }
    }

    Ok(())
}