Skip to main content

Roles have a home their agents keep, and agents work with git themselves

Mission Control stood between agents and their work: it checked projects out, moved branches and submodules, pushed and opened pull requests with the forge's token (ADR 0007, ADR 0016), and gave every run a home of its own that went with the task (ADR 0019), so an agent met each task with nothing but its instruction and skills. The same runtimes do markedly better work outside Mission Control, and the difference is not the model: it is a machine that persists, git and the forge's own CLI, and instruction files the agent keeps itself, which is what those runtimes are built for and what their training holds. Each abstraction of ours in that place was one the agent had to be taught and one we had to maintain. We decided that Mission Control orchestrates work and is not an agent runtime: each role has a home, a directory kept for as long as the role and mounted into every run of it, where its agents clone, keep worktrees, notes, tools and an AGENTS.md of their own, seeded once with conventions and theirs after that; the agent image ships git, gh and tea; a role reaches a forge with a token an owner gives it as an environment variable, or not at all; and Mission Control's tools shrink to what only it knows (tasks, handoffs, sign-off, messages, skills, images, Slack, the projects and their clone URLs) plus one that comes in, link_pull_request, with which an agent tells its task which pull requests are its work. The role instruction opens the first turn as a behavioural guard, not as the whole of the agent.

Considered Options​

  • Both models side by side, a role opting into either: rejected; two ways of working to instruct, test and keep, and the old one is the one we stop believing in. If this is wrong, it reverts: the code goes back, role homes are new directories, and the bare clones and run homes can be deleted.
  • A home per run, kept (ADR 0019 as it stands): what we had. Nothing an agent learned outlasted its task, and nothing it built was there next time.
  • A home per agent instance (a pool of named engineers, each with a machine): rejected for now; what should accumulate is what a role learns, and two runs of one role work in two worktrees as one person does on two branches.
  • Attaching pull requests by reference (the task id in a branch name or body, seen through webhooks): rejected. Webhooks are optional; a task may have several pull requests or none of its own; branch names follow the organization's convention, not ours; and inference misses rarely but badly where telling never does, which is what turning Linear's automatic linking off taught us. A pull request that mentions a task may be shown as a hint, never attached.
  • Mission Control's forge connection serving agents, or a token every role has: rejected; a forge token is a secret like any other (ADR 0002) and reaches a role only through an environment variable an owner gives it, so roles differ in their access and some have none. The organization's forge connection stays for Mission Control's own reading: pull request state, reviews, and the webhook.
  • Keeping the checkout and push tools for submodules' sake: rejected; git submodule and git worktree are what the model knows. ADR 0007's objection, a clone per task, is disk, and the agent manages its own.
  • A mc CLI in the image in place of the MCP server, with the run's token in its environment and its usage in --help, the shape gh and tea have: deferred as the next step; nothing here depends on which carries the tools.

Consequences​

  • Supersedes ADR 0007 and ADR 0016 wholly, and the per-run home of ADR 0019. The tools clone_project, checkout_branch, push_branch, open_pull_request, get_pull_request, review_pull_request and merge_pull_request go, with the pull_requests.comment and pull_requests.merge permissions, the shared bare clones, and the submodule and worktree machinery and its tests. Nothing in Mission Control depends on where a clone is or what a branch is called.
  • ADR 0017's guarantee becomes an instruction and the forge's rule. Agents are told to review with comments only and never to approve, request changes or merge; what the token can do is the forge's setting. Git's config is the role's own, in its home, rather than kept from it; what is still enforced is that git fails on missing credentials instead of prompting. GitHub refuses an author's own approval, which covers agents on a person's token; where agents have accounts of their own, protection must require a person's approval, not a count. Sign-off (ADR 0022) is unchanged: it guards task status, not the forge.
  • A token in a container is the role's whole access on that forge. Tokens given to roles should be fine-grained, scoped to the repositories and to contents and pull requests, and a role that does not change code gets none.
  • Task directories and conversation directories go. Where an agent keeps a task's or a conversation's files is its own business in its home; a conversation's agent is told its directory convention like any other. Nothing is removed when a task or conversation ends, so a home grows; the role tidies it, for which a routine (ADR 0010) fits.
  • Two runs of one role share the home at once. The seeded AGENTS.md says a worktree per task and the task id in branch names, as advice; a collision on a file is last write wins.
  • The runtime's own state lives in the home: sessions, memory, caches, installed tools. A continued run finds its session as before. Sessions of runs for different sponsors sit in one home, accepted within an organization. The sealed sign-in of ADR 0020 keeps its per-run directory and is linked into the home as it is now.
  • The home is under the data directory, so Docker and pods (ADR 0021) mount it like the run's directory. It is created with the role and removed with it.
  • A linked pull request is read with the organization's forge connection, which shows its state, reviews and whether it merged, and keeps it fresh through the webhook. A URL on a forge the organization has not connected is refused, rather than kept as a link that says nothing. A task carries several; one is on several tasks, as before.
  • The opening prompt shrinks: the role instruction, the task, and a working-in-mission-control skill reduced to conventions (push before handing on, name the branch in the handoff, link what you opened). The project list gives each project's clone URL and forge in place of a checkout.