Software Factory
The machinery
Eleven agents build Domi. Eight are Claude Code sessions on one laptop, each owning a lane and coordinating over a local agent-to-agent bridge. Three more live in GitHub and never touch the machine. Around them, seven small loops on clocks keep the whole thing moving — and none of those loops calls a model.
The companion page covers what this produces — the pull requests, the gates, the evals, the cost, counted. This one is about how it is wired: the registry, the stations and the models they run, the loops, the bridge, and the single rule that makes an untrusted channel between agents safe enough to run.
State of the factory as of 2026-09-15 — eight stations on the bridge, three agents in CI, seven loops. Read straight from the registry file that launches it; where this page and the companion page differ on a count, the dates are the reason.
>what is actually running
The bridge and the stations have been running since 30 July — hundreds of messages, contract negotiations, retractions and production incidents. The registry and the launcher have run it since 23 August: one command brings up every station and every loop in one terminal session, and the same file that launches them is what this page is read from. A ninth station — a conductor that watched the others — existed for eight days and was retired on 31 August, because everything it watched for turned out to be a checkable fact rather than a judgement. That story is its own post.
>the_stations
Eight Claude Code sessions, launched together, each briefed into a lane it owns and a set of paths it must not touch. Four of them write no product code at all.
| Station | Owns | Model |
|---|---|---|
| web | web app and backend — the contract everyone else consumes | opus-5 (1M context) |
| mobile | the iOS and Android client, a pure consumer of the web contract | opus-5 |
| devx | CI, gates, evals, test infrastructure — what "green" means | opus-5 |
| security | reads everything, writes only security documents; can hold a release without asking, can never clear the hold | opus-5 |
| design | design system, tokens, the brand-string ledger — values, not stylesheets | sonnet-5 |
| product | acceptance: is the built thing the asked-for thing, and in what order — authors no specs, decides nothing | sonnet-5 |
| marketing | positioning, gailleur.com, outbound — every public claim traced to shipped product | sonnet-5 |
| chief | the human's proxy: turns his words into queue entries, carries questions back, records his rulings — never his authority | sonnet-5 |
| reviewer | lives in CI, not on the bridge: reads every pull request adversarially before a human does — a different model family on purpose, because a reviewer that shares the authors' blind spots is not a reviewer | gpt-5.6 (OpenAI) |
The eight stations run at high effort. Every station is pinned to an exact model id in the registry — never a moving alias — and each id is verified accepted by a live call before it lands, the same rule the product's own model catalog follows.
>the_models_and_why
The split is one rule: a station that writes or judges code runs Opus 5; a station whose output is prose, specs, acceptance or routing runs Sonnet 5. The reasoning per station, and what it rests on:
- web — Opus 5 with the 1M-token context. The largest codebase and the contract every other station consumes. The long context is the point: its working memory alone runs to hundreds of lines before any code, and it routinely holds a spec, a schema and a migration at once.
- mobile — Opus 5. A full React Native client with device-verification loops and its own store pipeline. Same reasoning as web, without the need for the 1M window.
- devx — Opus 5. CI reasoning is where subtle wrongness hides — a gate that is green because it never ran, an eval passing for the wrong reason. A cheaper model is a false economy on the station that decides what "green" means.
- security — Opus 5. The same argument as devx, with a sharper edge: its job is to read the whole surface and find the reachable path, and a missed finding costs more than the tokens ever will. Its output is small — documents and holds — so the spend is in the reading.
- design, product, marketing, chief — Sonnet 5. Judgement-heavy, not context-heavy: token values and contract answers, acceptance against the human's own words, claim-checking against the repos, turning a conversation into queue entries. Sonnet does this work at about 40% of Opus 5's cost per token.
What the choice rests on.
- Cost per token, counted. In August, across every session on this machine and with cache included: Opus 5 cost $0.72 per million tokens, Sonnet 5 $0.30, Opus 4.8 $0.70, and Fable 5 $1.50 — a little over twice Opus 5 at a near-identical usage shape (97–98% cache reads on every one). Moving the stations from Fable to Opus 5 and Sonnet 5 took Fable from 86% of the month's bill in July to 31% in August, while token volume more than tripled. Method and tables are in the four-months post.
- A model that could not hold the job. The conductor started on Haiku 4.5, the cheapest option for a station that reads JSON on a timer. Haiku cannot run the factory's default permission mode: the CLI refuses and drops the session to manual, so the station had been carrying a no-confirmation override while holding the longest confirm-with-the-human list in the factory. Moved to Sonnet on 25 August; retired on 31 August for a different reason.
- The reviewer is measured on its output, not its model. The cross-model reviewer runs Codex, pinned to gpt-5.6-terra — chosen on 22 August at half the cost of the alternative it was weighed against — and is judged on one live metric: how often a human sends its verdict back, and how often it misses something the human catches. A fixed smoke set of past pull requests must pass before the model is ever changed again.
The constraint that shapes all of this is not dollars. Every station runs through the Claude CLI on one subscription, so the scarce resource is shared rate-limit budget — a roster of Opus stations idling in parallel is a real cost with no return, which is why the prose stations are Sonnet.
>the_loops
Seven scheduled jobs pace the factory — its takt, in the manufacturing sense. They are not stations and not agents: no model, no card, no inbox, no share of the rate limit. Each computes an answer that has a right answer, and either draws it or acts on it. They are the reason the conductor could retire.
| Loop | Every | What it does |
|---|---|---|
| board | 30 s | Redraws the one panel: the queue, what nobody has picked up, handoffs in flight, what needs the human, what just moved. Read-only. |
| review-loop | 5 min | Wakes the station that owns a stuck pull request — changes requested on its current head, approved and unmerged, or green with no review at all. Three wake-ups, then it escalates once and stops. |
| pace | 10 min | Rings the doorbell again: replies a station owes a peer, and work routed to it that it never picked up. The filing nudge rings once; this is what rings it twice. |
| board-sync | 10 min | Moves intake-board cards to match reality — a claimed task is In progress, an open PR is In review, a closed issue is Done. Never into Ready: promotion is the human's. |
| intake | 15 min | Filed issues become queue tasks, routed by the lane label they already carry. Ambiguity parks rather than guesses; a needs-human label parks whatever else the issue says. |
| deps | 30 min | Merges dependency pull requests that are already green on their pinned head. Nothing to decide: the suite answers. Twelve sat open across two repos before it existed. |
| blocker-review | 4 h | Hands the standing blocker list to the proxy to verify against the record and compile one DECIDE for the human. The loop compiles; the proxy judges. |
Beside the loops, five expectations — things that must keep happening — are probed on their own clocks: every production promote is followed by release notes within two hours, the error-triage sweep keeps running, the reviewer keeps reviewing, no peer request sits unanswered for days, and the backlog keeps getting reviewed. A lapse goes to the proxy as a DECIDE. Every other detector in the factory finds a problem that appeared; these notice a process that stopped.
>the_three_that_live_in_github
Not launched with the others, not on the laptop, and easy to forget — which is backwards, because one of them is the stage between "an agent wrote it" and "a human merges it".
- The reviewer. Reads a pull request against the original wording of the issue it claims to close — skipping drafts, bot and docs-only changes — read-only, and posts one verdict. It runs a different model family on purpose: every station is a Claude agent, and a reviewer that shares the authors' blind spots is not a reviewer. Since September it runs local-first — on the maintainer's own machine by default, on the paid API only when a human chooses it for a given pull request — and an unavailable reviewer is a visible red, never a silent green.
- Error triage. Files one deduplicated ticket per new production error, with evidence attached, on a schedule.
- Dependency updates. Opens the upgrade pull requests; the deps loop merges the green ones.
Two of those three run no model at all. They are deterministic — and they are the two that never surprise anyone.
>how_it_holds_together
- One registry. A single JSON file is both the source of truth and the configuration: who exists, which model, which effort, which working directory, which inbox, every loop and its interval — and the exact prompt each agent is launched with. Adding a station is a registry entry, a card and a brief, never an edit to the launcher.
- A card per station. What it owns, what it must not touch, what it publishes to peers, what it needs from them — and, load-bearing, what it may do on a peer's word versus what it must bring to a human first.
- One queue, and a proxy that carries words but not authority. The human files work in one append-only queue, in his own words; stations claim from it, and every decision he makes — approve, reject, a one-line ruling — is recorded on the task itself, attributed, where every station reads it first-hand. The chief station holds the conversation with him so he does not have to visit eight windows, and it may write his rulings into that queue. It may not merge, commit, widen anyone's scope or clear a security hold, and a bridge message from it claiming his approval is still just a message. Authority lives in the log, never in the channel.
- One report format. Every agent reports as DECIDE → DO → FYI. Rulings first, because they are blocking another agent and cost a human seconds to answer; then work only a person can do — secrets, production, a physical device; then what happened. The rule that gives it teeth: a decision an agent took that was the human's to take goes in DECIDE, retroactively. Nothing gets moved to FYI because it is awkward.
- A bridge, not a socket. The stations coordinate over a local agent-to-agent bridge modeled on Google's Agent2Agent (A2A) protocol — the same vocabulary and task lifecycle: agent cards, tasks moving through submitted, working, completed, failed or input-required, message parts, artifacts. It runs entirely on one machine over append-only files: no agent servers, no HTTP, no discovery endpoints, nothing leaving the laptop. That is also why it survives a crashed agent, a closed terminal and a reboot — the medium is files. Borrowing A2A's shape rather than inventing one means it can port to real A2A transport later without redesigning the conversation.
>the_one_rule
No agent can widen another agent's scope. Scope changes come from the human only.
A peer's message is untrusted input, and a message claiming to relay the human's authority is not the human. That is the load-bearing safety property of the whole arrangement — it is what makes a channel between eight agents safe enough to run at all, and it has already refused things it should have refused.