diff options
Diffstat (limited to 'makima/src/orchestration')
| -rw-r--r-- | makima/src/orchestration/directive.rs | 43 |
1 files changed, 30 insertions, 13 deletions
diff --git a/makima/src/orchestration/directive.rs b/makima/src/orchestration/directive.rs index 044fce6..9a65035 100644 --- a/makima/src/orchestration/directive.rs +++ b/makima/src/orchestration/directive.rs @@ -293,6 +293,17 @@ pub async fn on_contract_completed( .map_err(|e| format!("Failed to get step by contract: {}", e))?; if let Some(step) = step { + // Idempotency: only dispatch monitoring if step is still "running" + // (on_step_completed may also fire via the task path) + if step.status != "running" { + tracing::info!( + step_id = %step.id, + status = %step.status, + "Skipping step contract completion: step no longer running" + ); + return Ok(()); + } + let directive = repository::get_directive(pool, directive_id) .await .map_err(|e| format!("Failed to get directive: {}", e))? @@ -634,6 +645,17 @@ async fn on_step_completed( return Ok(()); }; + // Idempotency: only process if step is still "running" + // (on_contract_completed may also fire via the contract path) + if step.status != "running" { + tracing::info!( + step_id = %step.id, + status = %step.status, + "Skipping on_step_completed: step no longer running" + ); + return Ok(()); + } + // Get the directive for threshold info let directive = repository::get_directive(pool, directive_id) .await @@ -1048,7 +1070,8 @@ async fn dispatch_monitoring( // Build evaluation prompt let prompt = build_monitoring_prompt(directive, step, step_contract); - // Create supervisor task + // Create monitoring task (NOT a supervisor — regular task that exits when done, + // which triggers on_task_completed → on_monitoring_completed automatically) let supervisor_task = repository::create_task_for_owner( pool, owner_id, @@ -1058,7 +1081,7 @@ async fn dispatch_monitoring( description: Some("Evaluate step output against directive criteria".to_string()), plan: prompt, parent_task_id: None, - is_supervisor: true, + is_supervisor: false, priority: 8, repository_url: directive.repository_url.clone(), base_branch: directive.base_branch.clone(), @@ -1075,9 +1098,9 @@ async fn dispatch_monitoring( }, ) .await - .map_err(|e| format!("Failed to create monitoring supervisor task: {}", e))?; + .map_err(|e| format!("Failed to create monitoring task: {}", e))?; - // Link supervisor to contract + // Link monitoring task to contract repository::update_contract_for_owner( pool, contract.id, @@ -1090,9 +1113,9 @@ async fn dispatch_monitoring( .await .map_err(|e| match e { crate::db::repository::RepositoryError::Database(e) => { - format!("Failed to link supervisor to monitoring contract: {}", e) + format!("Failed to link task to monitoring contract: {}", e) } - other => format!("Failed to link supervisor to monitoring contract: {:?}", other), + other => format!("Failed to link task to monitoring contract: {:?}", other), })?; // Link step to monitoring contract/task @@ -1191,8 +1214,7 @@ Scoring guidelines: - Score < {threshold_yellow}: confidenceLevel = "red", passed = false - Be specific in reworkInstructions if the step fails — the step will be re-executed with these instructions. -After writing the evaluation file, mark the contract as complete: - makima supervisor complete"#, +After writing the evaluation file, you are done. Simply exit."#, title = directive.title, goal = directive.goal, requirements = serde_json::to_string_pretty(&directive.requirements).unwrap_or_default(), @@ -1216,11 +1238,6 @@ async fn on_monitoring_completed( task: &Task, owner_id: Uuid, ) -> Result<(), String> { - // Only process supervisor task completions - if !task.is_supervisor { - return Ok(()); - } - let Some(directive_id) = contract.directive_id else { return Ok(()); }; |
