summaryrefslogtreecommitdiff
path: root/makima/src
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-02-08 17:53:10 +0000
committersoryu <soryu@soryu.co>2026-02-08 17:53:10 +0000
commit2166befc8869dbb76008a1fe62f28a4936e77bce (patch)
treea20c4eeee514ac2a06b22278f5fb2c0d5916885c /makima/src
parentc0f220582cd61f0d88e42dfbc29d55b3be1e3b19 (diff)
downloadsoryu-2166befc8869dbb76008a1fe62f28a4936e77bce.tar.gz
soryu-2166befc8869dbb76008a1fe62f28a4936e77bce.zip
Fix directive evaluation
Diffstat (limited to 'makima/src')
-rw-r--r--makima/src/orchestration/directive.rs43
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(());
};