← all pages

The factory running · 02

Symphony, the dispatcher

Symphony is the runner that launches an agent session on a delegated ticket. It is not the brain — everything below the verb lives in the skill tree, the lane included — and what remains of it fits in three sentences, published here verbatim.

Three sentences, no branching

The prompt keeps exactly what a skill cannot know: which issue, which column, and the fact that nobody is watching. Then it calls the lane by name.

You are Symphony, dispatched unattended on Linear issue {{ issue.identifier }}, currently in column **{{ issue.state }}**. Never ask a human. $symphony-run.

The lane is a skill

Everything the prompt used to spell out — the column verbs, the one-sub-issue choreography, the branch and pull-request shape, the parking rules — is now symphony-run, a skill in the tree. The lane names skills and sequences them, so it is a client of the tree's interface, and it kept changing for reasons that were entirely the tree's: a stage folded into another stage, a new rule for the follow-ups an unattended run files. Each such change was two pull requests in two repos with two deploy paths and no version pin between them, and skew in either direction dispatches a run that names a skill which no longer exists. Moving the lane into the skill tree puts the caller in the same versioned unit as the interface it consumes; they now deploy together.

The lane itself is still one unconditional text: read your column, act accordingly, one session's worth of work, then stop. Re-dispatch is the loop. Follow-ups the run files are delegated to Symphony as they are created — no human is here to queue them, so triage is the gate.

What the lane does in each column

ColumnThe verbWhy
ShipLand it with $ship — merge, deploy, verifyShip is the human's delegation. The agent looks for no further approval, because the approval already happened when a person moved the card.
BacklogTriage — draft the ticket in full, then perform the route's transitionDelegating in Backlog is consent for the whole ride: a ticket that triages clean is implemented in the same run; blanks park it in Needs Decision or Needs Grilling, outside every active state.
Todo / In ProgressWork one sub-issue of the spec on its shared branch, then stopOne bite per session keeps every session in the smart zone; re-dispatch, not a bigger context, is the loop. Every sub-issue Done means the spec goes to Human Review.
Anything elseDiagnose and stopAn unknown column fails loud and safe. No verb is ever improvised from a state the lane does not name.

Note what is absent: the prompt never plans, never asks, and now never chooses either. Triage runs here too — one runner for every session, so failures retry and surface like any other run — but no fact about which skill runs when lives in this repo any more. Editing the prompt is no longer how a run's behaviour changes. What Slack gets each morning is a read-only report, not a runner.

The principle underneath: the lane names only states it has a verb for, and machinery is added against observed failures, never speculative ones. A board state no human touches is a state the process cannot explain.