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
Triggers
Section titled “Triggers”| Event | Condition |
|---|---|
| Issue comment | /agents execute on a Feature issue with Ready label |
| PR merged | PR merged into a branch starting with feature/ (loop closure) |
| Workflow dispatch | feature_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.
Behavior
Section titled “Behavior”- Reacts to the trigger comment with 👀.
- Fetches the feature issue body and parses waves from it (supports YAML
waves:blocks and Markdown wave headers with task lists). - Ensures the feature branch
feature/{id}-{slug}exists. If not, creates it from the configured base branch and waits for visibility. Removesdraftlabel once branch is created. - Detects completed tasks by scanning merged PRs targeting the feature branch for
fixes/closes/resolves #Nreferences. - Updates task checkboxes
[x]/[ ]on the feature issue body based on completed tasks. - Computes wave states: a wave is
donewhen all its tasks have merged PRs; otherwisepending. - Finds the next ready wave: the first
pendingwave whose preceding waves are alldone.
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.
- Reacts with 👍.
Loop closure
Section titled “Loop closure”Task PR merged → PR merge event → Wave Orchestrator → next wave dispatchedWhen 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.
Duplicate dispatch prevention
Section titled “Duplicate dispatch prevention”Before dispatching a task, the orchestrator checks:
- Is the task already done (has a merged PR)?
- 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.
Required permissions
Section titled “Required permissions”permissions: contents: write issues: write pull-requests: write actions: write