How it runs

Task DAG & dependencies

How goals become a dependency graph of tasks, how it executes with bounded concurrency, and how delegation and rework drain in one cycle.

Decomposition turns a goal into a task DAG — subtasks that can depend on earlier ones. The runtime executes in dependency order: a task runs only once the work it builds on is done, and that upstream output is fed into the assignee’s prompt — so agents build on each other instead of working blind.

The task record

Every task is a persisted record. The fields that drive coordination:

  • dependsOn — a task runs only once its upstream is done, and receives that output as context.
  • delegatedBy — records who handed a task down, so review routes back to the manager.
  • depth — bounds the delegate→integrate chain (maxDelegationDepth).
  • kind: 'integration' — marks the follow-up a manager runs to combine its reports’ work; an integration step never re-fans-out.
  • qualityFlag / score — persist the review outcome so downstream tasks and the operator can tell accepted-clean from accepted-below-the-bar.

Decomposition

The coordinator asks the lead to propose 2–N subtasks as a JSON plan, seeded with the meeting’s agreed decision so tasks implement the debated direction rather than restate the goal title. Then:

  1. Each assignee is resolved — an id or role maps to an existing agent; an unknown role hires a specialist (see Hiring). The plan may pick the hire’s brain. If no usable assignee is named, the fallback picks the least-loaded role-matched agent (not raw array position), keeping the lead free to coordinate.
  2. dependsOn step numbers are resolved to real task ids, keeping only backward references — so the graph is acyclic by construction. A dropped forward/self reference is audited (tasks.dep.dropped) so a clipped plan is visible.

If the model gives no usable plan (for example, the fake brain), decomposition falls back to one task per agent.

Execution order & concurrency

Tasks execute in dependency order with bounded concurrency (TASK_CONCURRENCY, default 4):

  • A node runs only once every in-batch dependency has completed. Out-of-batch deps are assumed satisfied (finished in a prior cycle).
  • A node that returns unfinished marks its dependents skipped this run — they don’t build on missing input.
  • Failure isolation: a node whose work throws is recorded blocked, never rejecting the batch, so one flaky agent can’t discard every sibling’s completed work. The batch always resolves with a partial result map.
  • Dispatch gate: once the cycle is aborted or over budget, new dispatches stop; in-flight nodes drain and the rest defer.

Independent tasks therefore run concurrently; dependent tasks wait and inherit their upstream’s output.

The intra-cycle drain

Delegation and rework create new board tasks during execution — which a single execution pass can’t see (its set of tasks is fixed when it starts). So the runtime wraps execution in a bounded drain loop: it repeatedly gathers every task that’s still runnable and hasn’t run yet this cycle, executes that batch, and repeats — up to maxDelegationDepth + 2 passes, stopping early once a pass completes nothing new (only rework or blocked tasks remain).

This makes a delegate → execute → integrate chain resolve within one cycle instead of costing one wall-clock tick per tree level. A task already run this cycle is never re-run — rework correctly waits for the next cycle.

Rework holds its dependents

A task sent back for review rework holds its dependents until it lands — downstream work never builds on output that’s still being fixed. When the task is finally accepted, its dependents unblock and inherit the corrected result.

Upstream context

When a dependent task runs, its prompt includes the results of the tasks it depends on. If a dependency was force-accepted below the quality bar, that context is prefixed with [ACCEPTED BELOW QUALITY BAR, score N] so the dependent can hedge rather than trust it blindly.