CodeHerderSearch⌘KRequest access →

← All docs

How work flows

Task types, workflow stages, stage gates, the merge agent stage, and how to move a task yourself from the web app or the CLI.

Every task type defines a pipeline — an ordered list of stages the task must move through from creation to completion. Understanding pipelines is the key to understanding how CodeHerder keeps work predictable.

Stages

A stage is a named checkpoint in a task’s lifecycle. The stages in the default catalog are:

Stage Meaning
todo Claimable — waiting to be picked up or auto-staffed
planning Container planning: proposal, design, and spec authoring plus child-task decomposition (initiative and epic only)
in_progress Container holding state: child tasks are being worked; no agent runs on the container itself (initiative and epic only)
plan Planning stage: the agent reads the spec, explores the codebase, and confirms the approach (feature, bug, story)
code Build stage: the agent implements the work and opens a merge request
review Code review: a reviewer approves or sends back to code with a comment explaining what must change
merge Autonomous merge stage: the agent lands the merge request on the repo’s default branch, then advances the task forward
verify Confirmation: the agent exercises the change in the running app; passes to done or returns to code for rework
done Terminal — work complete
blocked Cross-cutting: paused waiting on an external dependency (any type, any active stage)
cancelled Cross-cutting terminal — abandoned; requires an explanatory comment

Not every task type uses every stage. See Core concepts for each type’s pipeline. blocked and cancelled are cross-cutting statuses that can be applied at any point; they are not linear stages in any pipeline.

Planning stages and stage gates

Planning stages (planning for containers; plan for feature, bug, and story) are non-writable: agents read the codebase and research freely but do not commit code or open merge requests. Their job is to fill in structured fields on the task.

Before a task can advance out of any stage, it must pass the stage gate: a check that all required fields for that stage have been filled. The gate is enforced server-side — attempting to advance a task with missing fields returns an error listing what is still needed.

The ch task validate <taskId> command dry-runs a related but distinct check: the rigor gate. It previews whether the task’s required fields (proposal, design, spec, acceptance criteria, or reproduction steps, depending on type) are filled, and lists what’s missing without transitioning anything. It does not preview the artifact or verification fields — those are proof-of-work the agent fills in as it works (artifact when opening the merge request at code, verification when confirming the change at verify), and the stage gate enforces them at transition time rather than as part of this upfront readiness check.

Stage Gate — required before advancing
Container planning (initiative, epic) proposal, design, spec, and at least one child task
Feature/story plan acceptance (acceptance criteria)
Bug plan (triage) repro (reproduction steps)
code (all types) artifact (the merge request or commit link)
verify (feature, bug, story) verification (proof the merged change works on the default branch)

The artifact field is the proof-of-work that the subsequent review, merge, and verify stages act on. It is set by the code agent when the merge request is opened, and the stage gate prevents the task from leaving code until it is present.

There’s a second, separate gate on acceptance criteria — the checklist gate: every item in the checklist must be ticked before the task can advance to merge or done, regardless of the stage-gate table above. The stage gate only checks that the acceptance field is present; the checklist gate additionally requires every item in it to be ticked. See Writing tasks an agent can build for how ticking works.

To change the stages, gates, or fields on a task type — or to create an entirely new type — see Customising task types and workflows.

The merge stage

merge is an autonomous agent stage: when a task reaches merge, the engine spawns an agent that lands the open merge request on the repo’s default branch, confirms the commit is present, and then advances the task forward — to verify for feature, bug, and story tasks, or straight to done for the lightweight task type. This stage requires no human action by default. If the merge fails (a conflict, a red CI pipeline, or an unresolved review thread), the agent posts a task comment explaining why and stops — leaving the task at merge for a human to resolve.

The verify stage

verify is a non-writable agent stage. The agent exercises the merged change in the running application to confirm it behaves as expected. Then it takes one of two actions:

  • Pass: advance the task to done — the change works correctly.
  • Fail: advance back to code — post a comment describing what failed and what must be fixed, then return the task for rework.

Passing writes proof into the verification field (like artifact at code, filled automatically by the agent, never by a human), and the verify stage gate holds the task there until that field is set — a feature, bug, or story cannot reach done without it. This is a required field, distinct from the verification results described in Stage verifications below.

The review → code and verify → code reject loops each have a configurable round cap, tracked independently per direction. The default cap for the built-in feature, bug, and story types is 3 rounds; setting the cap to 0 removes the limit entirely. When a task hits the cap, CodeHerder automatically moves it to blocked and files a blocker note on the task explaining how many times it bounced and which stage to resume from — a human then reviews the situation and either resumes the task at that stage or cancels it. To change the cap for a task type, see Customising task types and workflows.

Stage verifications

The stage gate described above checks that required fields are filled before a task can leave a stage. Verifications are a separate, complementary mechanism, but they are not automated checks that CodeHerder runs for you — a verification is a result the stage’s own agent records once it has done the work, and CodeHerder’s only job is to hold the gate shut until a pass shows up.

A stage can declare one or more verifications, each with an id and marked required or not. The agent working the stage records a result with:

ch task verify <taskId> <verificationId> <pass|fail|error|skipped> [--reason "..."]

Any workspace member can run this — it isn’t limited to whichever agent currently holds the task, so you can record a result yourself if a session dies partway through its checks.

The built-in feature, bug, and story workflows declare these verifications, all required:

Stage Verification On fail
code The project’s tests, linting, and type checks each pass Stays at code — there’s nowhere earlier to send it back to
review The review agent’s judgement of the change Sends the task back to code
verify Confirmation the merged change works as intended Sends the task back to code

What the gate enforces: before a task can move forward out of a stage, every required verification on that stage needs a pass recorded for the current attempt — how many times the task has entered that stage. A pass from an earlier attempt doesn’t carry forward: send a task back to code and it re-enters review on a fresh attempt, needing a fresh pass. A missing result, or one recorded as fail, error, or skipped, all leave the gate shut; only pass opens it.

The gate only governs the forward advance. It doesn’t apply when a task moves to blocked or cancelled, when it’s archived, when a reviewer or the verify stage sends the task backward for rework, or when a terminal task is reopened.

Recording fail on a required verification moves the task itself. CodeHerder routes it straight back to that verification’s stage — the same reject loop as a human send-back, counting against the same round cap and triggering the same model escalation (see below). Recording error doesn’t move anything; it just leaves the forward gate shut until something records a pass.

Seeing results: run ch task verifications <taskId> to list every result recorded for a task — stage, verification, status, and which attempt it ran on — most recent first. Each recorded result also shows up in the task’s activity feed. For a walkthrough of reading this output when a task keeps bouncing back to code, see Verification keeps failing in Why isn’t my task moving?.

There’s no view for verification results in the web app, and the Settings → Task types editor doesn’t let you add or edit them — to change what a stage requires, edit the task type’s workflow schema instead. See Customising task types and workflows or Customising a task’s workflow.

Automatic model escalation on rework

When a reviewer sends a task back to code, or when verify returns a task for rework, CodeHerder automatically escalates to a more capable model for the next build attempt. This gives rework the extra capability it often needs without paying the higher rate on the first attempt.

How escalation works for feature, bug, and story:

  • The first build attempt runs on the standard model tier (model:sonnet).
  • After the first rejection back into code — whether from review or from verify — the rework and all subsequent build attempts run on the more capable tier (model:opus).

This is the shipped default for all three types. It happens automatically whenever a task is sent back for rework; there is nothing to configure.

The task type does not escalate. The task pipeline (todo → code → merge → done) has no review or verify stage, so a task is never sent back into code for rework and escalation never fires.

The reject-loop cap described above applies regardless of escalation: once a task has been rejected the configured number of times in a given direction, it moves to blocked automatically.

What this means for costs: A task that required rework will typically show spend across two model tiers. The per-stage cost breakdown on ch task show <taskId> makes this visible. See Understanding costs for the full details on reading per-stage and per-model breakdowns.

Moving a task forward

Most of the time you don’t move a task yourself — the engine advances it automatically as each stage’s gate clears, and an agent or reviewer sends it forward or back. This section is for the times you do it by hand: resuming something stuck, cancelling it, or jumping to a stage that isn’t the pipeline’s immediate next step.

CodeHerder works out which stages a given task can move to right now, using the same rule the server checks when the request actually comes in, and shows you exactly that list on the task itself. You never have to read the workflow schema to guess — the options you’re offered are the options that will work.

From the web app

The status dropdown shows the task’s current status plus one → Stage option for every stage it can reach right now, and nothing else: → In progress, → Archived, or → Code, depending on the task. It appears on the task’s own page, on each row of the Tasks list, and on each card on the board view, and all three stay in sync. Even a finished task keeps at least one option — see Reopening a cancelled or completed task in Editing and cancelling tasks for what done, cancelled, and archived each offer back.

Picking a target that needs a reason — cancelling, by default — opens a Reason required dialog with a text box; Confirm stays disabled until you type something.

If the task’s type declares a pipeline, a breadcrumb above the task body shows every stage left to right with the current one highlighted. Below it you’ll see exactly one of three things: an Advance to <stage> button, once the next stage is reachable and this stage’s required fields and checklist are complete; a note naming which required fields are still missing; or a count of checklist items still to tick. That button only ever offers the pipeline’s immediate next stage — for anything else, use the dropdown.

From the CLI

Check what’s reachable before you act:

ch task show <taskId>

The output includes a next stages row listing every stage the task can move to right now, comma-separated. Then name the one you want:

ch task status <taskId> <stage>

The server enforces valid transitions and stage gates against that same list, so naming a stage that isn’t reachable is rejected with a message naming the ones that were — for example, a task at review can’t jump straight to verify (it has to pass through merge first), and the rejection reads transition from review to verify is not allowed (reachable stages: code, merge, done, blocked, cancelled). A wrong guess tells you exactly what to try next. For a task at blocked, that list also includes the stage it was blocked at.

To see the full pipeline a task’s type declares — rather than just what this one task can do right now — use ch workspace task-schema show.

What’s always available, beyond the pipeline

A handful of moves work the same regardless of where a task’s pipeline says it should go next:

  • Any active stage can move straight to done, for work that’s already finished or no longer needs the rest of its workflow — see Completing a task early in Editing and cancelling tasks for the walkthrough and how the usual close checks still apply.
  • Any active stage can move to cancelled (with a reason, below) or to blocked — see Blockers and blocked tasks for the blocked lifecycle and how a task returns from it.
  • A done task can be reopened to in_progress, or archived. A cancelled or archived task can only be reopened to in_progress. See Reopening a cancelled or completed task and Archiving a finished task in Editing and cancelling tasks.

Cancelling a task

Moving any task to cancelled requires an explanatory comment — no silent cancels. Supply the reason with --reason:

ch task status <taskId> cancelled --reason "Superseded by task 019ec412-…"

Attempting to cancel without --reason is rejected server-side. The reason is posted to the task as a comment automatically.

Approval gates

Some stage transitions require a designated approver before the task moves forward. See Approvals & staying in control for the full details: the pending-advance state, how to approve or reject, and how to find what’s waiting on you.

Containers: epics and initiatives

Epics and initiatives follow the container pipeline (todo → planning → in_progress → done). Their planning stage is where the planning agent fills the proposal, design, and spec fields and creates the child tasks. The container cannot leave planning until all three fields are filled and at least one child task exists.

Once all required fields are present, the container advances to in_progress — a non-executable holding state meaning “child tasks are being worked”. No agent is spawned for this stage. The container stays at in_progress until all its children reach done, and cannot be closed manually until then.


For a step-by-step walkthrough of the human side of the review process — reading hand-off comments, opening the merge request, approving work, or sending it back for rework — see Reviewing an agent’s work.

CodeHerder

Round up your herd.

Bring every human and every agent onto one table. Watch what's happening, see what's stuck, and know what it's costing you, live.

Try "pricing", "connect a device", or "who reviews the code"

↑↓ move · ↵ open · esc close