diff options
Diffstat (limited to 'makima/src/llm')
| -rw-r--r-- | makima/src/llm/phase_guidance.rs | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/makima/src/llm/phase_guidance.rs b/makima/src/llm/phase_guidance.rs index 379bdca..712e8bb 100644 --- a/makima/src/llm/phase_guidance.rs +++ b/makima/src/llm/phase_guidance.rs @@ -112,6 +112,8 @@ pub struct TaskInfo { pub status: String, } +use crate::db::models::PhaseConfig; + /// Get phase deliverables configuration (legacy, defaults to "simple" contract type) pub fn get_phase_deliverables(phase: &str) -> PhaseDeliverables { get_phase_deliverables_for_type(phase, "simple") @@ -126,6 +128,90 @@ pub fn get_phase_deliverables_for_type(phase: &str, contract_type: &str) -> Phas } } +/// Get phase deliverables from a custom PhaseConfig +/// This is used for contracts with custom templates +pub fn get_phase_deliverables_from_config(phase: &str, config: &PhaseConfig) -> PhaseDeliverables { + // Check if this phase exists in the config + let phase_exists = config.phases.iter().any(|p| p.id == phase); + if !phase_exists { + return PhaseDeliverables { + phase: phase.to_string(), + deliverables: vec![], + requires_repository: false, + requires_tasks: false, + guidance: format!("Phase '{}' is not defined in this contract template", phase), + }; + } + + // Get deliverables for this phase from the config + let deliverables: Vec<Deliverable> = config + .deliverables + .get(phase) + .map(|defs| { + defs.iter() + .map(|d| Deliverable { + id: d.id.clone(), + name: d.name.clone(), + priority: match d.priority.as_str() { + "recommended" => DeliverablePriority::Recommended, + "optional" => DeliverablePriority::Optional, + _ => DeliverablePriority::Required, + }, + description: format!("{} deliverable", d.name), + }) + .collect() + }) + .unwrap_or_default(); + + // Determine if repository is required (typically for execute-like phases) + let requires_repository = phase == "execute" || phase == "plan"; + + // Determine if tasks are required (typically for execute phase) + let requires_tasks = phase == "execute"; + + // Find the phase name for better guidance + let phase_name = config + .phases + .iter() + .find(|p| p.id == phase) + .map(|p| p.name.clone()) + .unwrap_or_else(|| phase.to_string()); + + let guidance = if deliverables.is_empty() { + format!("Complete the {} phase. No specific deliverables are required.", phase_name) + } else { + let deliverable_names: Vec<_> = deliverables.iter().map(|d| d.name.clone()).collect(); + format!( + "Complete the {} phase by producing the following deliverables: {}", + phase_name, + deliverable_names.join(", ") + ) + }; + + PhaseDeliverables { + phase: phase.to_string(), + deliverables, + requires_repository, + requires_tasks, + guidance, + } +} + +/// Get phase deliverables, checking custom config first, then falling back to built-in types +pub fn get_phase_deliverables_with_config( + phase: &str, + contract_type: &str, + phase_config: Option<&PhaseConfig>, +) -> PhaseDeliverables { + // If we have a custom phase config, use it + if let Some(config) = phase_config { + return get_phase_deliverables_from_config(phase, config); + } + + // Otherwise, fall back to built-in contract types + get_phase_deliverables_for_type(phase, contract_type) +} + /// Get deliverables for 'simple' contract type fn get_simple_type_deliverables(phase: &str) -> PhaseDeliverables { match phase { |
