> ## Documentation Index
> Fetch the complete documentation index at: https://songbird.studiocollective.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Linear Automation

> How Songbird's column-driven Linear workflow turns board moves into agent actions — and how to work with it as a developer.

Songbird development is driven from a **Linear board**. Moving a card from one
column to the next isn't just bookkeeping — each move triggers an automated
action: an AI agent starts planning, reviewers fan out, an implementation
begins, a PR gets merged. This page explains the workflow end-to-end and how to
work with it as a human contributor.

The automation is a small Rust service called the **linear-orchestrator**. It
lives in its own repository
([`studiocollective/linear-orchestrator`](https://github.com/studiocollective/linear-orchestrator))
and runs as a background service that listens to Linear webhooks. You don't need
to run or deploy it to use it — you just move cards on the board.

## The mental model

> **A board column is a phase. Moving a card *forward* into a column runs that
> phase's action. The agent that owns the ticket does the work; the orchestrator
> just routes.**

Two consequences fall out of this that are worth internalizing up front:

* **Only forward moves trigger anything.** Dragging a card *backward* (Testing →
  Execution, Merged → Testing) or sideways never re-fires a phase. The
  orchestrator records the new position but stays quiet. This lets you freely
  pull a card back to fix something without spamming kickoff comments.
* **Agents are engaged by @mention.** The orchestrator drives an agent by
  posting a comment that @mentions it (a Linear profile link in a comment body
  *is* an @mention, which wakes that agent's session). So everything the
  automation does is visible in the issue's comment thread — there's no hidden
  channel.

## The board at a glance

| Column         | Phase action                                                                                                                                                                                                                |
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Todo**       | Unmanaged — nothing fires. Park work here until it's ready to plan.                                                                                                                                                         |
| **Blocked**    | Holding pen for a ticket with unresolved blockers. No action; it leaves automatically when unblocked. Sits just before Planning.                                                                                            |
| **Planning**   | @mentions the **primary agent** to draft a plan, run a conflict check against other in-flight work, and assess regression risk. **Auto-advances to Discussion** when the planner finishes (unless it asked you a question). |
| **Discussion** | Fans out a review request to each configured **reviewer agent** (distinct lenses), then asks the primary to weigh the feedback and revise the plan.                                                                         |
| **Execution**  | @mentions the primary to implement the plan — running an implementer and a test author in parallel.                                                                                                                         |
| **Testing**    | @mentions a test agent, **routed by content**: a Mac agent when the PR touches Mac-only surfaces, otherwise the default headless agent.                                                                                     |
| **Review**     | @mentions the primary to open the PR, get CI green, auto-review, and call out breaking changes.                                                                                                                             |
| **Merged**     | **Manual merge gate.** The orchestrator merges the linked PR *if* it's clean, otherwise bounces the card back to Review with the reason. Never auto-merges.                                                                 |

Columns not in this table (backlog states like `Idea`, `Researching`,
`Designed`, and terminal states like `Archived`, `Canceled`) are unmanaged — the
orchestrator ignores them.

## A ticket's life, step by step

### 1. Planning

Drag a ready ticket from **Todo → Planning**. The primary agent is @mentioned
and will:

1. **Read `AGENTS.md` / `CLAUDE.md`** and draft a plan as a checklist of build
   steps in the issue description. It's told to keep scope tight — build exactly
   what's asked, reuse existing helpers rather than duplicate, and avoid premature
   abstraction. If it needs a decision from you it asks in a comment and **stays
   in Planning** until you answer; otherwise it produces a self-contained plan.
2. **Run a conflict check.** It lists every other in-flight ticket (Planning
   through Review) and, for those with a PR, compares changed files against what
   this ticket will touch. If there's material overlap that would cause a merge
   conflict, it marks this issue **blocked by** that ticket, explains which files
   collide, and moves the card to **Blocked** (see below).
3. **Run a regression check.** It assesses the blast radius — which existing
   behavior, public APIs, shared modules, or downstream callers the change could
   break — and lists each risk with how it'll be guarded.

This is the stage to argue about *what* and *how* before any code exists.

### 2. Discussion

When the planner finishes its turn, the ticket **advances to Discussion
automatically** — you don't drag it (a planner that asked you a question stays
in Planning until you reply). The orchestrator then posts one review request per
configured reviewer, each with a
**distinct lens** so you get complementary critiques instead of the same note
twice:

* an **architecture & scope** lens (fit with existing patterns, scope creep,
  duplication, simpler/alternative approaches), and
* a **correctness & risk** lens (edge cases, concurrency, security, performance,
  test gaps, and regressions / breaking changes / affected consumers).

Reviewers are asked to **comment only, not take the ticket** — if a reviewer
agent assigns the issue to itself, the orchestrator reverts the assignee
automatically. After the fan-out, the primary is asked to reply to each critique
and revise the plan, weighing feedback on its merits (it owns the decision —
this avoids design-by-committee).

New comments from reviewers or teammates on a managed issue are **relayed** to
the primary so it keeps responding to feedback through the discussion.

### 3. Execution

Drag **Discussion → Execution**. The primary implements the plan by running
**two sub-agents in parallel**: an *implementer* writing production code and a
*test author* writing unit tests / scenarios / e2e (including regression tests
for the behavior the change touches). They keep implementation and test files
disjoint so the two streams don't collide, then reconcile and get the suite
green before opening the PR.

> If a card reaches Execution while it still has unresolved blockers, the
> orchestrator bounces it back to **Blocked** rather than letting conflicting
> work proceed.

### 4. Testing

Drag **Execution → Testing**. The orchestrator inspects the PR's changed files
and **routes to the right tester**:

* touches Mac-only surfaces (native audio, GL/WebGPU, the real Tauri app, plugin
  editors) → the **Mac agent** (Studio Claude), which can drive real hardware
  and capture screenshots;
* otherwise → the **default headless agent**.

The tester runs `./utils/validate`, the relevant scenario, and headless e2e /
agent-browser as needed, then uploads screenshots to the issue.

### 5. Review

Drag **Testing → Review**. The primary opens the PR with `verify-and-ship`, gets
CI green, auto-reviews, and is asked to **call out any breaking or behavior
changes in the PR description** so they're visible before merge.

### 6. Merged

Drag **Review → Merged** when you're satisfied. This is a **manual gate** — the
orchestrator merges the linked PR only if GitHub already considers it mergeable:

* a *required* (blocking) check failing or incomplete, merge conflicts, a
  branch behind base, or a draft → the card is **bounced back to Review** with
  the reason, and nothing is merged;
* only *non-required* (non-blocking) checks pending or failing → still merges
  (a non-blocking check isn't a blocker);
* clean and mergeable → merged via `gh`, with the result commented on the issue.

The orchestrator never enables GitHub auto-merge — the card drag *is* the
merge action.

## Blocked tickets & conflict avoidance

The whole point of the Planning conflict check is to keep two agents from
editing the same files on parallel branches and creating merge hell. When a
conflict is found:

1. The ticket is marked **blocked by** the conflicting ticket (a Linear
   relation), and the card moves to the **Blocked** column.
2. It sits in Blocked — a no-op holding pen — doing nothing.
3. When the **blocker merges**, the orchestrator automatically moves the
   dependent back to **Planning** (not straight to Execution) with a note to
   *rebase onto the latest and confirm the plan still holds* — because the merge
   may have changed the very code it conflicts on.

You can also set a `blockedBy` relation yourself; the same enforcement applies.

## Status labels

Independently of the columns, the orchestrator keeps a status label on every
issue with an active agent session, polled every 30s:

* **Working** — the agent is actively working.
* **Needs Input** — the agent is waiting on you (a question, an approval).

Watch for **Needs Input** to know when a ticket needs your attention.

## The prompts

Every action above is a comment built from a **prompt template**. Most are
tunable in the orchestrator's `config.toml` under `[prompts]`
(`planning`, `discussion`, `execution`, `testing`, `review`, `relay`) and
per-reviewer `prompt` fields — no code change needed. A few (the Blocked/Merged
notes and the bounce/unblock status lines) live in code. The canonical list of
every template is kept on the [TIV-69 issue](https://linear.app/tivr/issue/TIV-69);
propose wording changes there.

## Working with it: practical tips

* **Move cards forward to make things happen; move them back freely to fix
  things.** Backward moves never re-trigger a phase.
* **Talk to the agent in the issue thread.** During Planning/Discussion it's
  watching your comments and will respond. Be specific.
* **Don't drag straight to Merged to "save time."** It only merges a clean PR;
  a half-done one just bounces back to Review.
* **If a ticket is parked in Blocked, don't force it to Execution** — it'll
  bounce. Let the blocker merge (it auto-returns to Planning) or resolve the
  `blockedBy` relation.
* **Reviewers advise; the primary decides.** If you disagree with the synthesis,
  say so in the thread — the primary will re-weigh.

## Where the automation lives (for the curious)

|                     |                                                                                                                            |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| **Repo**            | [`studiocollective/linear-orchestrator`](https://github.com/studiocollective/linear-orchestrator) (separate from this one) |
| **Runtime**         | A Rust service behind a Linear webhook; column moves and comments arrive as events.                                        |
| **Engagement**      | Agents are driven purely by @mention comments — no private API between the orchestrator and the agents.                    |
| **Source of truth** | Linear (the board + relations) and GitHub (the PR). The orchestrator holds only dispatch bookkeeping.                      |

Implementation details, configuration, and deployment all live in that repo's
README and config. This page is the developer-facing "how the board behaves"
guide; the orchestrator repo is the "how it's built" guide.
