diff options
| author | soryu <soryu@soryu.co> | 2026-02-11 00:33:36 +0000 |
|---|---|---|
| committer | soryu <soryu@soryu.co> | 2026-02-11 00:33:36 +0000 |
| commit | 9bd6eacaa9ebe860842b5d5cfbf2b7d2d0293ab1 (patch) | |
| tree | 2b5dceee69f2390ab5f2c29c6fe39e091d7ca318 | |
| parent | 15b6e5fba161a194fe5427d7d29b0c4286423260 (diff) | |
| download | soryu-9bd6eacaa9ebe860842b5d5cfbf2b7d2d0293ab1.tar.gz soryu-9bd6eacaa9ebe860842b5d5cfbf2b7d2d0293ab1.zip | |
Fix DAG ordering
| -rw-r--r-- | makima/frontend/src/components/directives/DirectiveDAG.tsx | 40 | ||||
| -rw-r--r-- | makima/src/db/repository.rs | 6 | ||||
| -rw-r--r-- | makima/src/orchestration/directive.rs | 4 |
3 files changed, 20 insertions, 30 deletions
diff --git a/makima/frontend/src/components/directives/DirectiveDAG.tsx b/makima/frontend/src/components/directives/DirectiveDAG.tsx index f288a0d..27a80ac 100644 --- a/makima/frontend/src/components/directives/DirectiveDAG.tsx +++ b/makima/frontend/src/components/directives/DirectiveDAG.tsx @@ -16,37 +16,19 @@ interface Layer { function topoSort(steps: DirectiveStep[]): Layer[] { if (steps.length === 0) return []; - const stepMap = new Map(steps.map((s) => [s.id, s])); - const assigned = new Set<string>(); - const layers: Layer[] = []; - - // Iteratively find steps whose dependencies are all assigned - let remaining = [...steps]; - while (remaining.length > 0) { - const layer: DirectiveStep[] = []; - for (const step of remaining) { - const depsResolved = step.dependsOn.every( - (depId) => assigned.has(depId) || !stepMap.has(depId) - ); - if (depsResolved) { - layer.push(step); - } - } - - if (layer.length === 0) { - // Cycle detected or orphaned — push all remaining - layers.push({ steps: remaining }); - break; - } - - for (const s of layer) { - assigned.add(s.id); - } - layers.push({ steps: layer.sort((a, b) => a.orderIndex - b.orderIndex) }); - remaining = remaining.filter((s) => !assigned.has(s.id)); + // Group steps by orderIndex — each unique orderIndex is one execution phase + const byOrder = new Map<number, DirectiveStep[]>(); + for (const step of steps) { + const group = byOrder.get(step.orderIndex) ?? []; + group.push(step); + byOrder.set(step.orderIndex, group); } - return layers; + // Sort groups by ascending orderIndex + const sortedKeys = [...byOrder.keys()].sort((a, b) => a - b); + return sortedKeys.map((key) => ({ + steps: byOrder.get(key)!.sort((a, b) => a.name.localeCompare(b.name)), + })); } export function DirectiveDAG({ steps, onComplete, onFail, onSkip }: DirectiveDAGProps) { diff --git a/makima/src/db/repository.rs b/makima/src/db/repository.rs index 358ab48..7afbeea 100644 --- a/makima/src/db/repository.rs +++ b/makima/src/db/repository.rs @@ -5371,6 +5371,12 @@ pub async fn advance_directive_ready_steps( JOIN directive_steps ds ON ds.id = dep_id WHERE ds.status NOT IN ('completed', 'skipped') ) + AND NOT EXISTS ( + SELECT 1 FROM directive_steps prev + WHERE prev.directive_id = $1 + AND prev.order_index < directive_steps.order_index + AND prev.status NOT IN ('completed', 'skipped', 'failed') + ) RETURNING * "#, ) diff --git a/makima/src/orchestration/directive.rs b/makima/src/orchestration/directive.rs index 6121529..15cc7ed 100644 --- a/makima/src/orchestration/directive.rs +++ b/makima/src/orchestration/directive.rs @@ -641,7 +641,9 @@ For each step, define: - description: What to do and acceptance criteria - taskPlan: Full instructions for the Claude instance (include file paths, patterns to follow) - dependsOn: UUIDs of steps this depends on (use IDs from previous add-step responses) -- orderIndex: Execution order hint +- orderIndex: Execution phase number. Steps only start after ALL steps with a lower orderIndex complete. + Steps with the same orderIndex run in parallel. Use ascending values (0, 1, 2, ...) to create sequential phases. + Use dependsOn for fine-grained control within the same phase. Submit steps: makima directive add-step "Step Name" --description "..." --task-plan "..." |
