Detects which tasks can run in parallel by analyzing dependency graphs. Used by maestro and PRD generation.
Tasks form a DAG (Directed Acyclic Graph) where edges represent dependencies. Tasks at the same topological level have no dependencies on each other and can run in parallel.
- Build DAG: Create adjacency list from task
dependsOnfields - Compute in-degrees: Count incoming edges per node
- Level assignment: BFS from zero-in-degree nodes, assigning levels
- Group by level: Tasks at the same level form a parallel batch
function detectBatches(tasks):
// Build graph
graph = {}
inDegree = {}
for task in tasks:
graph[task.id] = []
inDegree[task.id] = 0
for task in tasks:
for dep in task.dependsOn:
graph[dep].push(task.id)
inDegree[task.id] += 1
// BFS level detection
queue = [t for t in tasks if inDegree[t.id] == 0]
level = 0
batches = []
while queue not empty:
batches[level] = queue.copy()
nextQueue = []
for taskId in queue:
for neighbor in graph[taskId]:
inDegree[neighbor] -= 1
if inDegree[neighbor] == 0:
nextQueue.push(neighbor)
queue = nextQueue
level += 1
return batches
From todo items with dependency fields:
T-1: Setup models (no deps)
T-2: API endpoints (depends: T-1)
T-3: UI scaffolding (no deps)
T-4: Form components (depends: T-3)
T-5: Integration (depends: T-2, T-4)
T-6: Tests (depends: T-5)
T-7: Test fixtures (no deps)
DAG:
T-1 → T-2 ─┐
├→ T-5 → T-6
T-3 → T-4 ─┘
T-7
Batches:
Batch 1: [T-1, T-3, T-7] ← parallel, no deps
Batch 2: [T-2, T-4] ← parallel, deps satisfied by Batch 1
Batch 3: [T-5] ← depends on Batch 2
Batch 4: [T-6] ← depends on Batch 3
Each batch must fit within 70% of available context window budget to leave room for verification and error handling.
available = contextWindowSize * 0.70
batchBudget = sum(task.estimatedTokens for task in batch)
if batchBudget > available:
split batch into sub-batches that fit
When a batch exceeds budget:
- Sort tasks by
estimatedTokensdescending - Greedily pack into sub-batches within budget
- Maintain dependency constraints (sub-batches at same level, no cross-deps)
If a cycle is detected (task A depends on B, B depends on A):
- Report the cycle as an error
- List the involved tasks
- Ask for human resolution
- Do NOT proceed with execution
Tasks with no dependencies AND no dependents:
- Include in Batch 1
- These can run anytime; earliest is best
A single task exceeding 70% budget:
- Flag as a candidate for breakdown
- Suggest splitting into subtasks
- If user confirms, proceed as-is but warn about context risk
If a task references a dependency that does not exist:
- Warn about the missing dependency
- Treat the dependency as satisfied (proceed)
- Log the inconsistency
Use this format in plans:
## Execution Plan
Batch 1 (parallel) ─── [T-1] [T-3] [T-7] ──── ~25k tokens
│ │
Batch 2 (parallel) ─── [T-2] [T-4] ──── ~40k tokens
│ │
Batch 3 (sequential) ── [T-5] ────────── ──── ~20k tokens
│
Batch 4 (parallel) ─── [T-6] [T-8] ────── ──── ~15k tokens
Total: ~100k tokens | Est. context windows: 2
Maestro uses batch detection to:
- Plan execution: Determine which agents to spawn in parallel
- Manage context: Track token budget across batches
- Order work: Execute batches sequentially, tasks within batches in parallel
- Checkpoint: Save state between batches for L-threads
for batch in batches:
// Spawn all tasks in batch in ONE message
parallel: [Task(implementer, task) for task in batch]
// Wait for all to complete
// Verify batch results
// Checkpoint if L-thread
// Proceed to next batch