[Feature]: worker-start --spec — create the task and dispatch it in one call
- Dominant language
- TypeScript
- Stars
- 71.3k
- Forks
- 4.7k
- Avg merge
- 14h 54m
- Merged PRs (30d)
- 520
Description
### Problem or use case
Spawning one supervised worker takes two mutations today, and the split gets awkward exactly where the CLI is otherwise at its best.
`orca orchestration worker-start` already carries almost the whole spawn decision in one call: whether to make a worktree at all and which kind (`--worktree current | new-child | new-top-level | `), plus `--name`, `--repo`, `--base-branch`, `--display-name`, `--comment`, `--setup`, and the harness triple `--agent` / `--model` / `--effort`. That is genuinely good — one command, one receipt, one record shape.
The one thing it cannot carry is the work itself. The brief lives in a separate `orca orchestration task-create --spec ""`, whose only output an orchestrator wants is the `task_id` it immediately passes to `worker-start`. So the shape is always:
```bash
TASK=$(orca orchestration task-create --run "$RUN" \
--task-title "COSM-309 — wave tree builder" \
--spec "COSM-309" --json | jq -r '.result.task.id')
orca orchestration worker-start --run "$RUN" --task "$TASK" \
--worktree new-child --name cosm-309-wave-tree --base-branch local \
--agent claude --model claude-sonnet-5 --effort medium
```
Two mutations, one of them a pure id-shuttle. It is not fatal, but it has real costs:
- **It is not atomic.** If `task-create` succeeds and `worker-start` fails, an orphan task is left `ready` and never dispatched. That happened during our run — `task_ecf32e44143d` was created twice and the first copy is still sitting `ready`, dispatched to nobody. Nothing in `task-list` distinguishes "waiting for a worker" from "abandoned by a failed spawn".
- **It forces shell plumbing into what is otherwise a declarative call.** Every orchestrator ends up writing the same `jq -r '.result.task.id'` dance, and an agent driving the CLI has to hold the intermediate id across two tool calls.
- **The awkwardness is worst when the spec is short**, which is the case we think is correct. Our worker protocol treats the dispatched text as a *pointer* and the tracker ticket as the spec, so `--spec` is often a single token like `COSM-309`. Spending a whole extra mutation to register one token, purely to obtain an id for the next command, is hard to justify.
We measured that short-payload case and it is worth reporting, because it argues for making the one-command path the easy one. Dispatching with `--spec "COSM-334"` — a bare ticket id and nothing else — the agent started on its own and ran the whole loop unattended: claim, branch, test-first commits, gates, merge, in 13 min 43 s with zero intervention. The same day, two dispatches carrying full 5–7 KB markdown briefs both failed to start and needed manual rescue at the terminal. A one-line payload is a single atomic paste; a multi-kilobyte one is not. If the short payload is the reliable shape, the CLI should not make it the more expensive one to express.
### Proposed solution
Let `worker-start` create the task inline, as an alternative to `--task`:
```bash
orca orchestration worker-start \
--run "$RUN" \
--spec "COSM-309" \
[--task-title "COSM-309 — wave tree builder"] \
--worktree new-child --name cosm-309-wave-tree --base-branch local \
--agent claude --model claude-sonnet-5 --effort medium --json
```
Semantics we would expect:
- `--spec` and `--task` are mutually exclusive; passing both is an error, passing neither is an error. `--task-title` and `--display-name` stay optional and keep their current meaning.
- The task is created on the same Run the dispatch targets, exactly as `task-create --run` would.
- **The whole thing is one mutation.** If the spawn fails at any stage — worktree creation, setup, terminal, dispatch input — the task is not left behind as an orphan, or it is left in a state that says so. The existing failure contract still applies: exit 1 for `failed` / `outcome_unknown`, with `stage` / `failedStage` / `setup` / `effects` / `residualResources` / recovery commands in the JSON. The created task id should appear in `effects` so a caller can find it after a partial failure.
- The receipt gains the `taskId` it already returns, so nothing changes for callers that read the JSON.
- `--retry-request` should cover the composite the way it covers the current call, so an unknown-result retry cannot double-create the task.
`task-create` stays exactly as it is. Fan-out patterns that create a batch of tasks up front and dispatch them later are a real use case and should keep working unchanged. This is about the common one-task-one-worker path.
### Alternatives or additional context
**What we do today.** Shell command substitution with `jq`, as shown above. It works; it just means every orchestrator carries the same glue, and the orphan-on-partial-failure case is on the caller to notice and clean up.
**A smaller variant, if inlining the spec is unwanted.** Have `task-create` accept the dispatch flags and perform the dispatch itself — the same composite from the other end. We prefer extending `worker-start` because that is where all the placement and harness flags already live, and because `worker-start` already owns the rich failure contract that a composite needs.
**A narrower variant still.** Accept `--spec` only when it is a short pointer (say, one line under some limit) and require `task-create` for anything longer. We would rather not have that rule — it is surprising — but it would cover the case that motivated this request.
**Version.** Checked against Orca 1.4.176 (`orca status --json` → `runtime.appVersion`), capability `orchestration.worker-launch-preferences.v1` present. Every flag named above was read from `orca orchestration worker-start --help` and `orca orchestration task-create --help` on that build.
**Context.** This came out of a two-level nested-orchestrator run — a coordinator dispatching two orchestrators into child worktrees, each dispatching its own workers into child worktrees under it. `--worktree new-child` and the `parentWorktreeId` / `childWorktreeIds` / `lineage` fields made that tree easy to build and to watch from outside, which is why the remaining two-step is noticeable: it is the only part of the spawn that is not already one declarative call.
Contributor guide
Research direction
Start by reading the current `orca orchestration worker-start --help` and `task-create --help` behavior described in the issue, then trace the existing worker-start mutation and failure contract. Define the composite path around mutually exclusive `--spec`/`--task`, atomic task handling, retry behavior, and receipt output. Done means inline task creation dispatches successfully and partial failures report the task and recovery details without an orphaned task.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- cli
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100