Skip to content

Wave orchestrator

flowchart LR
  Triggers@{ shape: bolt, label: "Triggers" }
  WaveOrchestrator["Wave orchestrator"]
  Issue@{ shape: notch-rect, label: "Issue
type: Feature / labels: Ready" }
  ExecutionAgents@{ shape: processes, label: "Execution agents" }

  Triggers --triggers--> WaveOrchestrator
  WaveOrchestrator -. depends on .-> Issue
  WaveOrchestrator -- orchestrates --> ExecutionAgents

  class Triggers triggersOrange
  class WaveOrchestrator waveGreen
  class ExecutionAgents executionBlue

  classDef triggersOrange fill:#ffe8d4,stroke:#d66a28,color:#d66a28
  classDef waveGreen fill:#d4f8d4,stroke:#28a745,color:#28a745
  classDef executionBlue fill:#cfe8ff,stroke:#0366d6,color:#0366d6

The Wave Orchestrator is a pure bash state machine — no LLM invoked. It reads the task list from the feature issue, determines which tasks are done, and dispatches the next wave of execution agents.

Type: Bash (deterministic, no LLM)
Script: .autoducks/agents/waveOrchestrator/run.sh

EventCondition
Issue comment/agents execute on a Feature issue with Ready label
PR mergedPR merged into a branch starting with feature/ (loop closure)
Workflow dispatchfeature_issue number — manual trigger or loop closure callback

The PR-merge trigger is the loop closure mechanism: every time a task PR merges into the feature branch, the orchestrator re-runs to check wave state and dispatch the next wave.

  1. Reacts to the trigger comment with 👀.
  2. Fetches the feature issue body and parses waves from it (supports YAML waves: blocks and Markdown wave headers with task lists).
  3. Ensures the feature branch feature/{id}-{slug} exists. If not, creates it from the configured base branch and waits for visibility. Removes draft label once branch is created.
  4. Detects completed tasks by scanning merged PRs targeting the feature branch for fixes/closes/resolves #N references.
  5. Updates task checkboxes [x]/[ ] on the feature issue body based on completed tasks.
  6. Computes wave states: a wave is done when all its tasks have merged PRs; otherwise pending.
  7. Finds the next ready wave: the first pending wave whose preceding waves are all done.

If a next wave is found: 8. Dispatches execution agents in parallel for each undone task, skipping already-done or already-dispatched tasks (duplicate dispatch prevention). 9. Posts a summary comment listing dispatched and skipped tasks.

If all waves are done: 10. Creates the final feature PR (if it doesn’t exist) with Closes #task for every task and Closes #feature. Comments that the feature is ready for review.

If blocked (not all previous waves done): 11. Comments that orchestration is waiting for dependencies.

  1. Reacts with 👍.
Task PR merged → PR merge event → Wave Orchestrator → next wave dispatched

When a task PR is merged into the feature branch, the runtime fires a PR-merged event. The autoducks-wave.yml workflow (GitHub Actions runtime) listens for this and re-runs the orchestrator.

The orchestrator also attempts a non-fatal workflow dispatch call after each execution agent completes — this handles the case where the PR merge event is delayed or missed.

Before dispatching a task, the orchestrator checks:

  1. Is the task already done (has a merged PR)?
  2. Is there already a running workflow for this task?

This prevents the same task from being dispatched twice if the loop closure fires multiple times.

permissions:
contents: write
issues: write
pull-requests: write
actions: write