Roles
- Worker. Plans, implements and ships one ticket as a green pull request. A worker never merges, never enables auto-merge and never approves its own plan.
- Coordinator. Dispatches tickets to workers, approves plans, merges green pull requests, closes tickets and tells the remaining workers what changed on
main. There is one coordinator at a time. A human, or an agent the human has explicitly designated as coordinator in its session, fills this role. Assume you are a worker unless you were told otherwise.
Worker lifecycle
- Pick a ticket. Take a ticket only if the coordinator assigned it to you, or if it is on the frontier: under
THE-531, labelledready-for-agent, not started, and every blocked-by ticket is Done. Prefer the coordinator’s order when one was given. - Claim it before any work. Re-read the ticket in Linear. If it is already In Progress or assigned to someone else, stop and pick another. Otherwise assign it, move it to In Progress, set the labels Agent phase =
planningand Agent runtime = your tool (Claude Code,CodexorConductor), and post a first commentAgent claim — runtime: <tool> · session: <session name or id> · branche: feature/the-<n>-… · démarré: <ISO date>, thenAgent status: planning — <what you are about to plan>. Re-read the ticket afterwards: if another claim appeared meanwhile, the older claim wins and you withdraw. - Branch. Create the Linear-suggested branch (
feature/the-<number>-…) from the latestorigin/main, in your own worktree. - Plan. Run the
plan-prskill for the ticket. Put the complete plan in the Linear comment, starting withAgent status: awaiting-approval — …(set Agent phase =awaiting-approval), because local plan files under the gitignoredplans/can disappear with a worktree. Push your branch before you stop: a worktree with no changes can be removed while you wait, so recreate it from the branch when you resume. Then stop and wait for the coordinator’s approval. Do not implement before it arrives. - Implement. After approval, set Agent phase =
implementing, postAgent status: implementing — …and build the approved plan test-first. A material change to the approved plan needs a new approval. - Ship. Run the
ship-pr-devskill: it verifies, reviews, opens the pull request and drives CI to green. Set Agent phase =shipping, postAgent status: shipping — …, and link the pull request on the ticket. If the pull request ships a user-visible capability, update the README’s “What works today” / “What comes next” lists anddocs/api-walkthrough.mdin the same pull request. - Rebase before hand-back. Rebase on the latest
origin/main, resolve conflicts, restamp your migration ifmake verifyreports it ordered beforemain, and get CI green on the final head. - Hand back. Set Agent phase =
ready-to-mergeand postAgent status: ready-to-merge — PR #<n>, head <sha>, CI greenwith the iteration record required byAGENTS.md. Leave the ticket In Progress; the coordinator closes it.
Agent status: released — <reason> so the ticket is free again.
If you are blocked, set Agent phase = blocked, post Agent status: blocked — <reason and what would unblock it> and stop.
Declaring your state
The Linear labels are the source of truth for where an agent is; the control tower reads them.
Keep exactly one label of each group on your ticket and change the phase label at every transition. Each transition also gets a comment starting with
Agent status: <phase> — <one-line summary>: the label says where you are, the comment says why and keeps the history.
Coordinator duties
-
Dispatch frontier tickets in parallel waves, following Linear blocked-by relations. The dashboard’s control tower (
/tour) ranks the frontier by critical path and flags collisions. - Approve plans by replying to the worker. Settle product decisions with the human; settle technical choices yourself and record them on the ticket.
-
Merge only when all of the following hold:
- the pull request is not a draft and its title follows Commitizen conventions;
- every check on the current head is green and GitHub reports it mergeable;
- the worker has handed back.
gh pr merge <n> --squash --match-head-commit <sha>. Merge one pull request at a time. -
After each merge:
- move the ticket to Done and remove its Agent phase label and make sure the pull request is linked;
- delete the branch and the worker’s worktree;
- tell every in-flight worker that
mainmoved, including any migration number or shared file that changed; - dispatch the tickets the merge unblocked.
Collision rules
- Migrations. Name new migrations
migrations/<UTC YYYYMMDDTHHMMZ>_<slug>.sql(make migration name=<slug>). Never add a numbered0xx_file; that set is closed. Readiness derives from the embedded set, so a migration touches no other file.make verifyfails if your new migration sorts before the latest migration onorigin/main; if that happens at your final rebase, rename your file to the current UTC time with thegit mvcommand it prints (ormake migration-restamp file=<name>.sql). Nothing else changes. - Shared files such as
internal/transport/httpapi/api.go,contracts/http/v0/openapi.yaml, generated transport code andscripts/local.py: keep edits small and localized, and regenerate generated code instead of hand-merging it. - Acceptance tests are order- and load-sensitive. Give new acceptance tests their own Organization or Corpus, and schedule ingestion-heavy tests after the timed scenarios in
scripts/local.py.