Developer
The Developer implements one task: it cuts a task branch from the pipeline branch, writes the code, opens a PR (fixes #N + Implementation Summary), auto-merges it into the pipeline branch, and closes the task. It is normally dispatched by the Maestro, wave by wave.
Type: LLM (Claude) · Scripts: .autoducks/agents/developer/{pre,post}.sh · Verbs: execute, run, work (on a Task issue)
flowchart LR
Triggers@{ shape: bolt, label: "Triggers" }
Developer["Developer"]
PR@{ shape: notch-rect, label: "Task PR\n→ pipeline branch\n(auto-merged)" }
Triggers --triggers--> Developer
Developer -- opens & merges --> PR
class Triggers triggersOrange
class Developer executionBlue
classDef triggersOrange fill:#ffe8d4,stroke:#d66a28,color:#d66a28
classDef executionBlue fill:#cfe8ff,stroke:#0366d6,color:#0366d6
Triggers
Section titled “Triggers”| Event | Condition |
|---|---|
| Workflow dispatch | issue_number + base_branch — dispatched by the Maestro |
| Issue comment | /execute (or run/work) on a Task issue |
Definition of Ready
Section titled “Definition of Ready”A task needs its pipeline context — the parent issue’s branch to cut from and merge into. When dispatched by the Maestro, the context comes with the dispatch. When you comment on a Task directly, the Developer resolves the parent itself:
- Parent found, branch exists → proceeds against it.
- Parent found, branch missing → posts 🔁 and delegates to the Maestro on the parent, which creates the branch and dispatches this task back in wave order.
- No parent at all → standalone execution was retired: the pipeline guarantees a reviewed design and plan before code. The status comment tells you exactly what to run instead (
/architect #auto:engineer+executeif this issue is the whole work item).
Behavior
Section titled “Behavior”- Reacts 👀, posts the status comment.
- Idempotency guard: if any PR — open or merged — already claims this task (
fixes #N), the run skips quietly (this is one of the three duplicate-dispatch guards). - Applies
Work:coding; waits for the base branch to be visible; cuts the task branch, inheriting the pipeline prefix:feature/<parent>-issue-<task>-<epoch>orfix/…. - [LLM] Implements the task spec — read-only
git/ghexploration is permitted, but the LLM never commits, pushes, or opens the PR (that stays with the workflow), and any code it writes must not embed agh/GitHub-API call directly (that goes through theits::*/git::*provider interfaces); it edits files and writes/tmp/work-summary.md. - Commits locally, then — if
checksis configured — runs the verification loop (below) before anything is pushed. - Pushes, opens the PR into the pipeline branch with
fixes #Nand an Implementation Summary (harvested later into the final PR’s Work Log). - Auto-merges with the adaptive method (
merge_method: autoprobes merge → squash → rebase; three attempts with a rebase onto the base in between). A conflict posts a 🔀 report with resolution steps. - Closes the task explicitly (sub-PR merges don’t fire GitHub’s auto-close),
Work:coding→Work:done, assigns the command author, flips the status comment to ✅. The merge event itself re-triggers the Maestro.
Verification loop
Section titled “Verification loop”When checks is enabled, the Developer doesn’t hand a task straight to review the moment the LLM stops editing — it runs the configured commands (lint/build/test/pre-commit/…) against the agent’s own changes first, and treats a failure as more work to do rather than a finished task:
- After committing, it runs
checks.setup(if any), then anygit_hooks-derived check, thenchecks.commandsin order. The first failure stops the loop right there. - Pass → proceeds to push + open the PR as usual; the status comment footer notes which attempt passed (e.g. “Automated checks passed on attempt 2/3.”).
- Fail, attempts remain → pushes the branch as WIP (no PR yet — same resumable-branch mechanic as a
max_turnscutoff), posts the failing check’s output as a marker-anchored comment on the task issue, and re-dispatches itself on the same task — the LLM gets a fresh turn budget and the prior failure as context, so it’s fixing a concrete, quoted error rather than re-guessing. This repeats up tochecks.max_iterationstimes. - Fail, attempts exhausted → gives up: the branch is preserved and pushed, the run fails with category
check_failed, and/fixon the task resumes from that branch. See When things fail. setupitself fails at any point → categorizedinfra, notcheck_failed— an unavailable toolchain is never treated as the agent’s fault, and it doesn’t consume an iteration.
The loop counter (iteration, defaulting to 1) rides along on the internal workflow_dispatch that drives the re-run — it isn’t something you set on the triggering comment; the Developer manages it itself between attempts. Full field-by-field schema (enabled, setup, commands, git_hooks, max_iterations) lives in the Configuration reference.
When the turn limit hits
Section titled “When the turn limit hits”If the LLM runs out of turns (max_turns), the Developer preserves the work: it commits WIP:, pushes the branch, and posts a max_turns failure report pointing at the preserved branch. /fix on the task resumes exactly from there. See When things fail.
Auto-merge policy
Section titled “Auto-merge policy”Task PRs merge into a pipeline branch that itself undergoes human review before reaching integration_branch — that’s why auto-merge is safe here. A task dispatched manually (via workflow_dispatch against the default branch) is not auto-merged; its PR waits for review.
Overrides
Section titled “Overrides”Overrides ride along from the triggering comment — on the wave path, the Maestro forwards them to every worker:
/execute model:haiku effort:low turns:30