summaryrefslogtreecommitdiff
path: root/makima/src/orchestration/directive.rs
diff options
context:
space:
mode:
Diffstat (limited to 'makima/src/orchestration/directive.rs')
-rw-r--r--makima/src/orchestration/directive.rs55
1 files changed, 48 insertions, 7 deletions
diff --git a/makima/src/orchestration/directive.rs b/makima/src/orchestration/directive.rs
index cb3983a..37cc5e7 100644
--- a/makima/src/orchestration/directive.rs
+++ b/makima/src/orchestration/directive.rs
@@ -46,7 +46,7 @@ impl DirectiveOrchestrator {
// Load memories if memory is enabled for this directive
let memories = if directive.memory_enabled {
- match repository::list_directive_memories(&self.pool, directive.id).await {
+ match repository::list_directive_memories(&self.pool, directive.id, None).await {
Ok(m) => m,
Err(e) => {
tracing::warn!(
@@ -98,6 +98,11 @@ impl DirectiveOrchestrator {
"Dispatching execution task for ready step"
);
+ // Resolve dependency steps to their task IDs for worktree continuation
+ let dep_tasks =
+ repository::get_step_dependency_tasks(&self.pool, &step.depends_on).await?;
+ let continue_from_task_id = dep_tasks.first().map(|d| d.task_id);
+
let task_plan = step
.task_plan
.as_deref()
@@ -105,7 +110,7 @@ impl DirectiveOrchestrator {
// Load memories if memory is enabled for this directive
let memory_context = if step.memory_enabled {
- match repository::list_directive_memories(&self.pool, step.directive_id).await {
+ match repository::list_directive_memories(&self.pool, step.directive_id, None).await {
Ok(memories) if !memories.is_empty() => {
format!("\n\nMEMORY CONTEXT (from previous planning/execution cycles):\n{}\n",
format_memories_for_prompt(&memories))
@@ -124,10 +129,37 @@ impl DirectiveOrchestrator {
String::new()
};
+ // Build merge instructions for additional dependencies (beyond the first)
+ let merge_preamble = if dep_tasks.len() > 1 {
+ use crate::daemon::worktree::{sanitize_name, short_uuid};
+ let merge_lines: Vec<String> = dep_tasks[1..]
+ .iter()
+ .map(|d| {
+ let branch = format!(
+ "makima/task-{}-{}",
+ sanitize_name(&d.task_name),
+ short_uuid(d.task_id)
+ );
+ format!("git merge origin/{} --no-edit", branch)
+ })
+ .collect();
+ format!(
+ "IMPORTANT — MERGE DEPENDENCY BRANCHES FIRST:\n\
+ This step continues from one dependency's worktree, but also depends on \
+ additional branches. Before starting work, run:\n\
+ ```\ngit fetch origin\n{}\n```\n\
+ Resolve any merge conflicts sensibly, then proceed.\n\n",
+ merge_lines.join("\n"),
+ )
+ } else {
+ String::new()
+ };
+
let plan = format!(
"You are executing a step in directive \"{directive_title}\".\n\n\
STEP: {step_name}\n\
DESCRIPTION: {description}\n\n\
+ {merge_preamble}\
INSTRUCTIONS:\n{task_plan}\n\
{memory_context}\
When done, the system will automatically mark this step as completed.\n\
@@ -135,6 +167,7 @@ impl DirectiveOrchestrator {
directive_title = step.directive_title,
step_name = step.step_name,
description = step.step_description.as_deref().unwrap_or("(none)"),
+ merge_preamble = merge_preamble,
task_plan = task_plan,
memory_context = memory_context,
);
@@ -148,6 +181,7 @@ impl DirectiveOrchestrator {
plan,
step.repository_url.as_deref(),
step.base_branch.as_deref(),
+ continue_from_task_id,
)
.await
{
@@ -281,7 +315,7 @@ impl DirectiveOrchestrator {
// Load memories if memory is enabled for this directive
let memories = if directive.memory_enabled {
- match repository::list_directive_memories(&self.pool, directive.id).await {
+ match repository::list_directive_memories(&self.pool, directive.id, None).await {
Ok(m) => m,
Err(e) => {
tracing::warn!(
@@ -374,6 +408,7 @@ impl DirectiveOrchestrator {
plan: String,
repo_url: Option<&str>,
base_branch: Option<&str>,
+ continue_from_task_id: Option<Uuid>,
) -> Result<(), anyhow::Error> {
let req = CreateTaskRequest {
contract_id: None,
@@ -389,7 +424,7 @@ impl DirectiveOrchestrator {
merge_mode: None,
target_repo_path: None,
completion_action: Some("branch".to_string()),
- continue_from_task_id: None,
+ continue_from_task_id,
copy_files: None,
checkpoint_sha: None,
branched_from_task_id: None,
@@ -454,7 +489,7 @@ impl DirectiveOrchestrator {
is_orchestrator: false,
target_repo_path: None,
completion_action: updated_task.completion_action.clone(),
- continue_from_task_id: None,
+ continue_from_task_id: updated_task.continue_from_task_id,
copy_files: None,
contract_id: None,
is_supervisor: false,
@@ -658,9 +693,10 @@ impl DirectiveOrchestrator {
fn format_memories_for_prompt(memories: &[DirectiveMemory]) -> String {
let mut out = String::new();
for memory in memories {
+ let cat = memory.category.as_deref().unwrap_or("other");
out.push_str(&format!(
- "- [{}] ({}): {}\n",
- memory.category, memory.source, memory.content
+ "- [{}] {}: {}\n",
+ cat, memory.key, memory.value
));
}
out
@@ -729,6 +765,11 @@ Submit steps:
Or batch:
makima directive batch-add-steps --json '[{{"name":"...","description":"...","taskPlan":"...","dependsOn":[],"orderIndex":0}}]'
+DEPENDENCY WORKTREE CONTINUATION:
+When a step has dependsOn, it automatically continues from the first dependency's worktree (inheriting
+committed and uncommitted changes). If there are multiple dependencies, the first provides the base worktree
+and additional dependency branches are merged in before work starts. Use this for incremental work chains.
+
IMPORTANT: Each step's taskPlan must be self-contained. The executing instance won't have your planning context.
"#,
title = directive.title,