Skip to content

Run a delivery window

A delivery window drains your approved backlog for a set time. Orbit starts backlog tasks in parallel until the window closes; work already in flight finishes. Starting a window returns a run ID, not finished work, so check each task’s status before you treat it as delivered.

A second machine can drain the same workspace as a replica (orbit run auto --pull <selector>) while the owner keeps landing authority. See Set Up a Distributed Drain.

Each step shows the dashboard or agent route first and the CLI as the fallback.

The task pilot fills in each task’s context_files (the files and directories it will work in) and assesses its complexity. It does not approve or dispatch anything.

  • Agent: ask your agent to pilot the proposed tasks.

  • Dashboard: in Automation → Jobs, click Run ▸ on task_pilot_pipeline. To pilot new and edited tasks automatically, turn on the task_pilot routine in Automation → Routines. It is off by default and runs on the host scheduler clock.

  • CLI:

    Terminal window
    # Tasks that need a pilot.
    orbit run task-pilot --wait
    orbit run task-pilot "$TASK_ID" "$OTHER_TASK_ID" --wait # exact tasks

Without task IDs, the pilot picks up proposed and backlog tasks whose context_files is empty or whose complexity is unassessed. It skips a task it already found to have no in-workspace targets while that assessment is fresh; editing the task’s description, criteria, status, or source makes it eligible again, and naming its ID always audits it again.

When preparation selects no tasks, the run skips agent dispatch and applies an empty result collection successfully, retaining any held-task skip details. For a nonempty selection, at least one pilot partition must succeed before apply runs; valid partitions can still apply when a sibling pilot fails.

Before you approve, check the pilot run (in Runs) and the selectors it applied (the task’s context files in Tasks). From the CLI:

Terminal window
orbit run history -j task_pilot_pipeline
orbit run show "$PILOT_RUN_ID"
orbit task show "$TASK_ID" --fields status,context_files

Approving a proposed task moves it to backlog, where a window can start it. The task pilot alone does not approve work; approve tasks individually or authorize a local drain to approve qualifying proposals.

  • Dashboard: in Tasks, click Approve on the task under Awaiting approval.

  • Agent: tell your agent which tasks to approve.

  • CLI:

    Terminal window
    orbit task update "$TASK_ID" --approve --note "Pilot context reviewed."

Do not approve a task that is already in backlog. Once its pilot has applied the context it needs, it is ready.

To authorize approval throughout a local window:

Terminal window
orbit run auto --for 4h --approve-proposed

While the window is open, the drain pilots proposed tasks with the no-diff-expected tag, or with context files and an assessed complexity. It approves those with no duplicate, already-landed, conflict or warning finding, including tasks filed while the window is open. Each pilot runs in the background, so backlog work keeps starting meanwhile, and the drain admits what a pilot approved as soon as it finishes. Tasks tagged no-auto-approve stay proposed until a human approves them. Other held tasks also stay proposed; orbit run show and orbit run readiness report approval counts and hold reasons. A warnings hold also names each finding: under Approved: in orbit run show, and as findings (kind and the finding’s first line) on each held task in orbit run readiness --json. The dashboard shows that same text on the live window’s approval hold. Each approval’s history note names the drain run.

--approve-proposed is off by default and conflicts with --pull, since only the owner approves work. Approval still respects dependencies, file locks, and crew restrictions when the drain admits a task. Add --complete separately if the window should also finish delivery.

Readiness is a read-only snapshot of what a window would start now and why the rest would wait. It reserves and submits nothing, so an eligible task is not guaranteed to start.

  • Dashboard: the Tasks dock’s Drain tab shows what a window started now would admit and how many tasks are eligible or waiting. The task list’s Backlog card sorts the backlog into Eligible now, Waiting on locks, Waiting on capacity, and Waiting, other, and each row’s tooltip names what it waits on. Locks held in the Tasks dock shows held locks (orbit task locks list).

  • CLI, for the reason behind each task:

    Terminal window
    orbit run readiness
    orbit run readiness --concurrency 8
    orbit run readiness "$TASK_ID" --json

    With no --concurrency, the ceiling is the live local drain’s, including a later orbit run concurrency --set, otherwise a live pull drain’s, otherwise 5. --json names that choice as capacity.limit_source (run_input, run_control, pull_run_input, pull_run_control, or default). Text adds a Leaf ceiling: line only when the pull drain supplies the ceiling.

Common reasons a backlog task waits:

  • Unsatisfied dependencies.

  • An active file lock. Two tasks whose selectors overlap cannot run at once. orbit task locks contention shows which files the backlog collides on, which is what really limits your parallelism.

  • surface_reserved: a critical or high-priority task ahead of it in the queue is waiting on file locks, and this task overlaps the files it needs. It waits so the higher-priority task gets each lock as it frees, instead of losing it to smaller tasks one lock at a time. It starts once that task starts. Unrelated work is not held.

  • awaiting_footprint or awaiting_exclusive_slot: the task has no context_files, so it holds no file lock and could collide with anything. A drain with more than one slot waits for the task pilot to fill them in, then starts the task only when nothing else is running. File such tasks as proposed and let the pilot prepare them before promoting them.

  • crew_not_allowed, when you preview a crew restriction or a running window has one.

  • pilot_duplicate or pilot_already_landed: the latest applied task-pilot assessment found duplicate work or work already landed. This also holds tasks filed directly into backlog. Read the finding in the task comments. Run task-pilot again to reassess it; a new assessment without either finding releases the hold. To approve the work anyway or clear a mistaken finding, append an explicit human decision from your CLI:

    Terminal window
    orbit task update "$TASK_ID" \
    --comment 'task-pilot-admission: approve-anyway'
    # Or clear a mistaken finding:
    orbit task update "$TASK_ID" \
    --comment 'task-pilot-admission: clear'

    The first line must match exactly; put any explanation on later lines. Both decisions release the current assessment’s admission hold while preserving its audit evidence. A later pilot assessment supersedes the decision. Ordinary edits, unrelated comments, and agent-authored decisions do not release it. All other admission checks still apply.

  • native_os_required: the pilot found native-host evidence requirements this host cannot satisfy. Route to a capable host, re-scope the criteria, or record an evidenced human task-pilot-admission: clear or approve-anyway decision. This decision stays valid across later pilot passes with the same criteria digest, OS requirement set and machine requirement; requirement order does not matter. Changed criteria or requirements supersede it. A new assessment still supersedes operator-validation and host-operational decisions.

  • delivery_job_unavailable: the task’s delivery:<job> tag selects a plugin delivery job whose plugin is disabled or uninstalled, or that does not declare the drain’s ship mode. The detail names the plugin. Enable it or remove the tag.

  • pr_forge_remote_missing: the workspace ships through pull requests, but no Git remote of the checkout names a network host (only a local bare repository, say), so pr_open could never succeed. The detail names the remotes. Run orbit workspace ship-mode local, add a remote on the forge host, or tag the task delivery:task_local_pipeline to deliver it locally. orbit doctor reports the same verdict on its forge-remote row.

  • local_route_before_pr: review.timing is before_pr and this workspace ships locally, or the task’s delivery:task_local_pipeline tag routes it locally. Before-PR review holds pull-request creation and does not run on the local-only route, so the task stays in the backlog instead of failing after dispatch. The detail names whether the global or workspace config set it. Set review.timing to off, or ship through the PR route. orbit doctor names the same combination.

  • local_route_before_landing: the same hold for review.timing at before_landing, which reviews an open pull request before it lands; a local delivery opens none. Set review.timing to off, or ship through the PR route.

Neither approval nor the drain bypasses dependencies or locks, so a window may end with some tasks still in the backlog.

  • Dashboard: on Drain → Start, pick a Window length (one pass, or 1h to 24h), set Parallel tasks, and turn on Mark shipped tasks done to complete them (off stops at review). Optionally turn on Approve qualifying proposals (--approve-proposed) or Auto-fix PR blockers to repair the window’s blocked PRs. Click Start … window and confirm. See Auto-drain.

  • Agent: ask for a window and say how long, how many tasks at once, and whether to complete them.

  • CLI:

    Terminal window
    orbit run auto --for 3h
    orbit run auto --for 3h --concurrency 8
    orbit run auto --for 3h --complete

The window length bounds only when new work may start; a task in flight when it expires still finishes. Parallel tasks (--concurrency, default 5) is not a batch size: the drain refills each free slot from the whole backlog.

--auto-concurrency shadow|enforce selects forecast-based admission for this window: shadow records what the forecast would admit, while enforce uses measured CPU and memory profiles to fit new work within host capacity. The concurrency ceiling still applies. Omit the flag to use the host’s configured mode.

Mark shipped tasks done (--complete) authorizes this window to move every task it ships from review to done, including tasks admitted later in the window. It never approves proposed tasks. In the dashboard it needs an operator session. See Completing work with --complete.

--auto-fix lets the window repair the pull requests it opened when a required check fails or the branch conflicts with its base. It is off by default. In the dashboard, check Auto-fix PR blockers when starting a window; this requires an operator session on the owner machine and is disabled on pull replicas. Completion and proposed-task approval remain separate choices. The receipt reports whether repair was enabled. From the CLI:

Terminal window
orbit run auto --for 4h --auto-fix
orbit run auto --for 4h --auto-fix --complete

The drain keeps watching each PR. Pending checks wait. A failed required check or a conflict goes to the existing repair step, which runs as a crew from workflow.purpose_crews.auto_fix, else workflow.low_complexity_crews (narrowed by --allow-crew). The repair then passes your required validation and is pushed, and the drain checks the new head. Approvals, permissions, admin rules, unknown status and optional-check failures launch no agent. Each PR gets at most one repair per head and blocker, and three in total; the attempts are recorded in the task’s history. --auto-fix never merges. Add --complete to also merge and finish tasks. See System work.

To follow the window, open its run from the Drain card header; the run detail lists the child runs it started. A task in progress has View run on its row. From the CLI, record the returned ID as $AUTO_RUN_ID:

Terminal window
orbit run show "$AUTO_RUN_ID"
orbit run trace "$AUTO_RUN_ID" # run tree with child run IDs
orbit run logs "$CHILD_RUN_ID"
orbit task show "$TASK_ID" --fields status,job_run_id,comments

A task’s submitted run is not its status; check the task itself.

--allow-crew limits one drain to the crews you name, for example when a provider is down, rate-limited, or out of budget. Ask your agent or use the CLI, or toggle Allowed crews on Drain → Start.

Terminal window
orbit run auto --for 4h --allow-crew opus,sonnet
# Preview what readiness would skip.
orbit run readiness --allow-crew opus,sonnet
  • For this run only. Without it, the drain runs every crew. No configuration is changed. An unknown or empty crew name fails before anything is dispatched.
  • Enforced throughout. Every activity in the run is checked against the crew that actually resolved, including a recovery crew drawn from a complexity pool. The check permits the named crews and aliases with the same effective provider, model, and provider account. A crew with its own env has a separate account and must be explicitly allowed even when its provider and model match. The allowlist gates the crew that normal precedence picks; it never picks one.
  • Skips, never remaps. A task whose crew is excluded stays in backlog, and readiness reports it as crew_not_allowed, also without --allow-crew while the window runs. The dashboard’s Drain card lists the window’s allowed crews and the tasks they leave out. There is no automatic fallback to another provider. To move the task, change its crew in Tasks or with orbit task update <id> --crew <name>.
  • Leaves other work alone. Work another invocation already started keeps running.

To change how many tasks a live drain keeps in flight, retune it rather than cancel it. Ask your agent or use the CLI; the dashboard has no retune control.

Terminal window
# Show the current ceiling and who last set it.
orbit run show "$AUTO_RUN_ID"
orbit run concurrency "$AUTO_RUN_ID" --set 7
# Reduce the ceiling after a provider rate limit.
orbit run concurrency "$AUTO_RUN_ID" --set 3 --reason 'provider rate limited'

Retuning keeps the run ID, deadline, completion authorization, and every child already dispatched. Cancelling and starting again mints a new run ID, restarts the window, and makes you restate --complete and --allow-crew.

  • Raising the ceiling fills the extra slots on the next admission pass, usually within a poll interval.
  • Lowering it pauses admissions until enough children finish. Tasks in flight are never cancelled or cut short.
  • The ceiling cannot exceed the leaf pipeline’s own active-run limit. A run that is not a drain, has not started, or has finished is refused.
  • --if-revision N applies the change only while the ceiling is still the one you read, so two operators cannot silently overwrite each other.

These are different actions.

Stop new admissions. Click Stop on the Drain card (it needs an operator session), or run orbit run auto --stop (no run ID needed). Children already started keep running under the completion authority they were admitted with, and the coordinator is not cancelled. Stopping again, or with no active window, does nothing. Other workspaces and jobs are untouched. orbit run show "$AUTO_RUN_ID" then reports who stopped admissions. --stop cannot be combined with flags that start a drain, including --for, --concurrency, --complete, --approve-proposed, or --allow-crew.

Cancel work in flight. Cancel each child you want to abandon: open it in Runs and click cancel, or:

Terminal window
orbit run trace "$AUTO_RUN_ID" # find the child run IDs
orbit run cancel "$CHILD_RUN_ID" --confirm

Cancelling a task leaf returns its task to backlog with the reason and keeps its candidate available to resume. Add --block to keep the task blocked for manual recovery instead.

A plain cancel of a local drain leaves its children running. Stop admissions first, then cancel only the children you want to abandon, or use orbit run cancel "$AUTO_RUN_ID" --confirm --force to stop the drain and all the task runs it started. A child whose stop cannot be confirmed is reported and makes the command exit 1.

Cancelling a pull drain is graceful: unlaunched claims return to the owner’s backlog while launched leaves finish and settle. --force stops those leaves too and returns their claims to the owner’s backlog once their stop is confirmed.

Ask your agent first. The orbit-orchestrate skill reads the run evidence, matches it to a known failure, and files a repair task when the code needs fixing.

By hand, find out why the run failed before you retry. Fix a real code, review, or dependency problem first; do not rerun blindly.

  1. Find the failure. In Runs, filter to Failed and open the run; it opens on the failed step and its error. From the CLI, orbit run history --failures groups failures by task and root cause; orbit run show "$AUTO_RUN_ID" lists the window’s failed children, and orbit run show or orbit run logs on a child gives the detail.

  2. Check recovery steps. A failure the agent declares itself goes through step recovery before the task is sent to blocked, so check those steps before deciding what a blocked task needs.

  3. Retry deliberately. A task blocked by its own failure stays blocked. Missing-launcher and transient-infrastructure blocks can instead be rechecked with orbit task recheck-blocked --confirm after their cause clears; transient recovery requires an authenticated published candidate and is bounded. Otherwise, once the cause is fixed, either:

    • click Resume on the failed run in Runs (orbit job resume <run-id>) to continue from its first unsuccessful step; or
    • move the task back to backlog with its status dropdown in Tasks (orbit task update "$TASK_ID" --status backlog) so a later window runs it again, resuming any saved candidate.

    orbit task show "$TASK_ID" prints the exact command on its Next: line. A show routed to another host prints the same line, and the dashboard task detail carries the same next_step.

A cancelled task leaf is already back in backlog by default, with its candidate resumable on the next delivery. If you cancelled with --block, return it to backlog when it is ready to run again.

Repair a cancelled owner-local published PR

Section titled “Repair a cancelled owner-local published PR”

Generic resume still refuses cancelled runs. When an owner-local task PR run was deliberately cancelled after publication and its task remains in review, an operator on the owning host can explicitly authorize remaining source work on that same task, branch and PR. This does not admit claimed leaves or foreign runs, and does not release a draft/evidence hold.

First make the canonical task description, criteria, plan and complete context selectors describe the work you now authorize. Restore any temporarily released selectors before inspection. The cancelled worker must have conclusively stopped; its successful host commit, prepare, sync, push and PR checkpoints, retained Git objects and exact local and remote branch must still be available. The PR must be open, unmerged and have automatic merge disabled. Unreadable or uncertain merge intent refuses admission.

Run these public tool requests as the operator (a model session cannot confer this authority). Use a deployment whose orbit tool show orbit.workflow.run.resume schema advertises source_repair; the owner, worker and any long-lived client must be on the compatible executable generation and store schema before use. Existing resume callers need no new argument. This feature adds a version-1 binding and append-only repair ledger, with no store schema migration. Installation and client restart remain operator actions.

Terminal window
orbit tool run orbit.workflow.run.resume --input \
'{"id":"<cancelled-run-id>","source_repair":{"action":"inspect","task_id":"<task-id>"}}'

If the workspace has an exclusive claim, include its authorized claim_token as a top-level field in both requests; operator authority does not bypass it.

Inspection returns binding, current review, and prior reservations. Copy the entire returned binding object verbatim into a local request file; do not construct a head or digest yourself:

{
"id": "<cancelled-run-id>",
"source_repair": {
"action": "submit",
"task_id": "<task-id>",
"request_key": "published-source-repair-1",
"binding": { "<replace with the entire inspected binding>": "" },
"diagnosis": "Name the failing CI run/job or observed source defect, its published head, and the remaining source edits explicitly authorized."
}
}
Terminal window
orbit tool run orbit.workflow.run.resume --input-file source-repair-request.json

The binding pins the workspace, owner machine, source run and checkpoints, repository and origin URL, task meaning/tools/crew and footprint, PR, branch, published head and recorded base. A successful host rebase is authenticated by the complete prepare/sync/push/PR chain; the pre-rebase commit need not be an ancestor of the published head. Changed evidence or scope requires a fresh inspection; a changed payload under an existing request key is refused.

A request key contains 1–128 ASCII letters, digits, -, _, ., or :. Submission durably reserves the bounded per-PR repair budget before admitting one linked run. Repeat the identical request after a lost reply: it returns the same run without spawning another worker, even after that run stops. A new key cannot recharge the same head, and cancellation does not refund a reservation. The new attempt continues the saved candidate with today’s authorized task specification under normal footprint locks, crew/OS/capacity and build budget. It inherits no validation or review checkpoint and reruns required commands on the repaired source. It captures the current host’s review schedule: none for an after-landing coverage setup, or before-landing review on the published head when configured (before-PR configuration also retains its normal meaning). No configuration change or additional review gate is needed. Independent review uses that captured schedule; after-landing coverage remains the configured delivery-code-review automation.

The attempt always requests completion: review and auto_fix: false. Inspect its resulting PR and validation/review evidence before separately requesting completion or automatic repair authority. This operator diagnosis path does not depend on automatic CI annotation classification.

A host-specific or environmental failure that keeps recurring needs the host fixed, not another attempt.

A run stuck pending with no live worker holds its task reservations; cancel it in Runs or with orbit run cancel "$RUN_ID" --confirm. The stuck job runs runbook explains how to tell a stuck run from a slow one.

Then check the workspace and reclaim worktrees left by settled tasks:

Terminal window
orbit doctor
# Report what it would reap.
orbit gc worktrees
# Remove the settled worktrees.
orbit gc worktrees --confirm
# Free build output while keeping checkouts.
orbit gc worktrees --reclaim --confirm

orbit gc worktrees collects only worktrees whose task is done, rejected, or archived, and removes nothing without --confirm. On a replica it reads task status from the owner machine. --reclaim deletes declared worktree.reclaim paths (default ["target"]) only after terminal-run, worker, registration, confinement, symlink and Git content checks. The failed run’s checkout and unmatched evidence stay available for rescue. The scheduled sweep also reclaims declared output in every kept terminal worktree. To limit it by age or to one run, see the CLI reference.

The scheduled worktree_gc_pipeline run also prunes the checkout’s .orbit/tmp scratch directory: a top-level entry goes once nothing inside it has changed for 24 hours. Pass --input scratch_older_than_hours=<hours> to orbit run job worktree_gc_pipeline to change the window for a run. Entries a live process holds open or an active run names are skipped and reported.

A delivery window changes a lot of task state. To snapshot it somewhere you can restore from, see Publish and Restore Tasks. To operate across hosts, federated MCP setup explains how to select the owning workspace, without implying automatic failover.