From the ticket to the merge request: who does what, on which model, and where the engineer steps in. One overview in a single graph, the agents one by one, then four detailed views in the order of a run.
The whole factory in one graph: a ticket comes in, a merge request comes out, and the factory corrects itself when a run went wrong. It reads left to right on two lines, and each arrow says what goes from one node to the next. In every diagram, hover an agent or a script to see what it does. The views below detail each part.
flowchart LR
oSwe1("Software Engineer
pastes the ticket URLs"):::swe
oVigie{"vigie
proposes tickets"}:::script
oConsole{"registry.ts
queue, conflicts,
run worktree"}:::script
oSched["Ticket scheduler
Sonnet"]:::agent
oGuard{"guard.mjs
checks every
tool call"}:::script
oPilot["Pilot /implement
Opus"]:::agent
oSwe2("Software Engineer
answers the questions"):::swe
oPlanner["Planner
Opus"]:::agent
oDev["Dev × N
Sonnet or Opus"]:::agent
oGate{"gate.mjs
typecheck, lint,
tests"}:::script
oOrch["Review orchestrator
Sonnet"]:::agent
oSenior["Senior reviewer
Opus or Sonnet"]:::agent
oDesigner["Designer
Sonnet"]:::agent
oQa["QA
Opus or Sonnet"]:::agent
oSwe1 -- "URL" --> oConsole
oVigie -- "tickets" --> oConsole
oConsole -. "batch" .-> oSched
oSched -. "order" .-> oConsole
oConsole -- "worktree, session" --> oPilot
oPilot -. "tool calls" .-> oGuard
oPilot -- "questions" --> oSwe2
oSwe2 -- "answers" --> oPilot
oPilot -- "ticket, criteria" --> oPlanner
oPlanner -- "plan" --> oDev
oDev -- "agent stops" --> oGate
oGate -- "fail" --> oDev
oGate -- "committed code" --> oSenior
oGate -. "large diff" .-> oOrch -. "sequences" .-> oSenior
oSenior -- "corrections" --> oDesigner -- "deviations" --> oQa
oQa -- "P0 / P1 : rework" --> oDev
classDef agent fill:#3a2210,stroke:#ff9d3c,stroke-width:1.6px,color:#c9cddb
classDef script fill:#12301f,stroke:#4ade80,stroke-width:1.6px,color:#c9cddb
classDef swe fill:#3a310a,stroke:#facc15,stroke-width:1.6px,color:#c9cddb
flowchart LR
oAccept{"acceptance-runtime.ts
criteria
coverage"}:::script
oMr["Pilot · Opus
opens the MR"]:::agent
oSwe3("Software Engineer
reviews and merges"):::swe
oWatch{"merge-watch.ts
watches the MR,
frees the queue"}:::script
oAudit{"self-improvement.ts
self-audit
of the run"}:::script
oImprove["Session /improve
Opus"]:::agent
oAuto{"auto-merge.ts
rules and checks"}:::script
oJudge["Session /judge-improvement
Opus"]:::agent
oRetry(("pending/
tried again")):::script
oAccept -- "coverage" --> oMr
oMr -- "merge request" --> oSwe3
oSwe3 -- "merge" --> oWatch
oMr -- "run ends" --> oAudit
oAudit -- "defect observed" --> oImprove
oImprove -- "branch" --> oAuto -- "passes" --> oJudge
oAuto -- "rejected" --> oRetry
oJudge -- "rejected" --> oRetry
oJudge -- "merge" --> oMain(("main"))
classDef agent fill:#3a2210,stroke:#ff9d3c,stroke-width:1.6px,color:#c9cddb
classDef script fill:#12301f,stroke:#4ade80,stroke-width:1.6px,color:#c9cddb
classDef swe fill:#3a310a,stroke:#facc15,stroke-width:1.6px,color:#c9cddb
Ten roles, all played by Claude Code. Click an agent to see its model and what it does.
A ticket arrives through pasted URLs or through the file vigie keeps up to date. The console decides when it may start, then opens a Claude Code session in a dedicated worktree.
flowchart LR
sweA("Software Engineer
pastes one or more ticket URLs"):::swe
vigie{"vigie
watches the forge,
writes ticket-proposals.json"}:::script
impl{"impl
starts the console
in the background"}:::script
proposals{"ticket-proposals.ts
reads the proposed tickets
every 5 s"}:::script
source{"ticket-source.ts
resolves each URL
to its checkout"}:::script
sweB("Software Engineer
picks the target repository
when no checkout is found"):::swe
registry{"registry.ts
queue,
one lock per ticket, slots"}:::script
analysis{"schedule-analysis.ts
opens the batch analysis,
validates output.json"}:::script
scheduler["Ticket scheduler
Sonnet"]:::agent
links{"ticket.ts
reads the blocking links
on the forge"}:::script
sweC("Software Engineer
forces, reorders
or cancels an entry"):::swe
order{"domain.ts
conflicts, dependencies,
start order"}:::script
impl -- "starts" --> registry
sweA -- "URL" --> source
vigie -- "file" --> proposals -- "tickets" --> source
source -. "no checkout" .-> sweB
sweB -. "target repository" .-> source
source -- "resolved ticket" --> registry
registry -- "2 tickets or more" --> analysis
analysis -- "batch" --> scheduler -- "overlaps" --> order
analysis --> links -- "dependencies" --> order
registry -- "single ticket" --> order
sweC -. "priority" .-> order
classDef agent fill:#3a2210,stroke:#ff9d3c,stroke-width:1.6px,color:#c9cddb
classDef script fill:#12301f,stroke:#4ade80,stroke-width:1.6px,color:#c9cddb
classDef swe fill:#3a310a,stroke:#facc15,stroke-width:1.6px,color:#c9cddb
flowchart LR
worktree{"run-worktrees.ts
creates the run worktree,
copies node_modules and .env"}:::script
seed{"runtime-recipe.ts
review-findings.ts
restores the recipe and the
recurring defects of the repository"}:::script
engine{"engine/claude-code.ts
starts claude
in a PTY"}:::script
sweD("Software Engineer
trusts the folder
when Claude Code asks"):::swe
pilot["Pilot /implement
Opus"]:::agent
worktree -- "worktree ready" --> seed -- "recipe, defects" --> engine
engine -. "trust?" .-> sweD -. "accepts" .-> pilot
engine -- "session" --> pilot
classDef agent fill:#3a2210,stroke:#ff9d3c,stroke-width:1.6px,color:#c9cddb
classDef script fill:#12301f,stroke:#4ade80,stroke-width:1.6px,color:#c9cddb
classDef swe fill:#3a310a,stroke:#facc15,stroke-width:1.6px,color:#c9cddb
The pilot owns git and the dialogue with the engineer, and never writes the ticket's code. The review is sized to the diff: three tiers, only one with an orchestrator.
flowchart TD p1["Pilot · Opus
1. reads the ticket, Figma,
attachments, lists the gaps"]:::agent swe2("Software Engineer
picks the base branch,
answers the blocking questions"):::swe p3["Pilot · Opus
2-3. writes the acceptance criteria,
creates the ticket branch"]:::agent planner["Planner
Opus"]:::agent p4["Pilot · Opus
writes a one-task plan
itself"]:::agent subgraph impl ["Step 5 · one task per agent"] direction TB dev["Dev × N
Sonnet, Opus for an L task
in parallel when files are disjoint"]:::agent gate{"gate.mjs
typecheck, lint, related tests
when the agent stops"}:::script p5["Pilot · Opus
reads gate-log.jsonl, runs the repository
checks, one commit per task"]:::agent dev --> gate gate -- "fail: sent back
once" --> dev gate -- "verdict" --> p5 p5 -- "next task" --> dev end sweQ("Software Engineer
settles a specification
question"):::swe p6["Pilot · Opus
6. starts the app, measures
the change in the browser"]:::agent snap{"code-snapshot.mjs
identifies the code
each piece of evidence measured"}:::script tier["Pilot · Opus
7. picks the review tier
from the diff"]:::agent subgraph t0 ["Tier 0 · under 30 lines"] direction TB s0["Senior reviewer
Sonnet, one pass"]:::agent q0["QA
Sonnet, focused pass
if the senior corrected"]:::agent s0 -.-> q0 end subgraph t1 ["Tier 1 · a few files"] direction TB s1["Senior reviewer
Sonnet"]:::agent d1["Designer
Sonnet, if the UI changes"]:::agent q1["QA
Sonnet"]:::agent r1["Dev rework
Sonnet, P0 and P1 only"]:::agent s1 --> d1 --> q1 q1 -. "P0 / P1" .-> r1 -. "focused QA pass" .-> q1 end subgraph t2 ["Tier 2 · large diff"] direction TB orch["Review orchestrator
Sonnet"]:::agent s2["Senior reviewer
Opus"]:::agent d2["Designer
Sonnet"]:::agent q2["QA
Opus"]:::agent r2["Dev rework
Sonnet"]:::agent orch --> s2 --> d2 --> q2 q2 -- "P0 / P1" --> r2 r2 -- "2 rework rounds at most" --> s2 q2 -- "review-summary.md" --> orch end accept{"acceptance-runtime.ts
derives the criteria coverage
and the review confidence (0 to 5),
writes acceptance-summary.md"}:::script p8["Pilot · Opus
8-9. pushes the branch, opens the MR,
publishes the consolidated review"]:::agent p10["Pilot · Opus
10. final report,
cleans .claude/tasks"]:::agent archive{"evidence-archive.ts
archives the evidence
before the cleanup"}:::script p1 --> swe2 --> p3 p3 -- "complex ticket" --> planner --> dev p3 -- "ticket simple" --> p4 --> dev dev -. "product question" .-> sweQ -.-> dev p5 -- "every task
has its report" --> p6 p6 --> tier snap -.-> p6 tier --> s0 tier --> s1 tier --> orch snap -.-> d1 snap -.-> d2 q0 --> accept s0 --> accept q1 --> accept orch --> accept accept --> p8 p8 -- "open P0 or inconclusive QA:
draft MR" --> p10 p10 --> archive classDef agent fill:#3a2210,stroke:#ff9d3c,stroke-width:1.6px,color:#c9cddb classDef script fill:#12301f,stroke:#4ade80,stroke-width:1.6px,color:#c9cddb classDef swe fill:#3a310a,stroke:#facc15,stroke-width:1.6px,color:#c9cddb
Every tool call of the session goes through the hooks before it reaches the console. The safety rules are decided there, not in a prompt.
flowchart LR session["Pilot and its agents
a tool call,
an agent stop"]:::agent emit{"emit.mjs
receives every hook,
sends it to the console"}:::script guard{"guard.mjs
refuses: destructive git, published secret,
wrong model, review too early"}:::script gate{"gate.mjs
typecheck, lint, tests
when Dev and Senior stop"}:::script bridge{"hook-bridge.ts
hooks.ts
applies the event
to the run state"}:::script monitor{"run-monitor.ts
run-health.ts
detects a stalled run,
opens an incident"}:::script artifacts{"artifacts.ts
copies the run documents
into the archive"}:::script usage{"engine/usage.ts
counts the tokens
in the transcripts"}:::script ui{"Next.js console
shows steps, agents,
questions, evidence"}:::script sweQ("Software Engineer
answers a question
asked by the pilot"):::swe sweI("Software Engineer
handles an incident,
sends an instruction, stops the run"):::swe session --> emit --> guard guard -- "refused" --> session guard -- "allowed" --> gate gate -- "fail: the agent
goes back once" --> session gate --> bridge --> ui session -. "written files" .-> artifacts --> ui session -. "transcripts" .-> usage --> ui bridge --> monitor --> ui ui -- "AskUserQuestion" --> sweQ -- "answer" --> session ui -- "incident" --> sweI --> session classDef agent fill:#3a2210,stroke:#ff9d3c,stroke-width:1.6px,color:#c9cddb classDef script fill:#12301f,stroke:#4ade80,stroke-width:1.6px,color:#c9cddb classDef swe fill:#3a310a,stroke:#facc15,stroke-width:1.6px,color:#c9cddb
The MR waits for the engineer's review, the queue is released at the merge, and the factory audits itself only when it observed something going wrong.
flowchart LR done["Pilot · Opus
MR open, final report"]:::agent metrics{"run-metrics-runtime.ts
tokens, durations, diff,
review confidence
in metrics.json"}:::script settle{"run-worktrees.ts
removes the worktree when the MR exists,
the tree is clean, HEAD is pushed"}:::script sweR("Software Engineer
reviews the MR,
merges it or asks for a change"):::swe reopen["Pilot · Opus
reopens the run"]:::agent devR["Dev rework
Sonnet"]:::agent review["Review
at the tier of the new diff"]:::agent watch{"merge-watch.ts
polls the forge every 60 s,
releases the waiting tickets"}:::script queue{"registry.ts
starts the next ticket"}:::script audit{"self-improvement.ts
writes the self-audit,
looks for proof of a defect"}:::script sweF("Software Engineer
leaves feedback
on the run"):::swe improve["Session /improve
Opus"]:::agent rebase["Session /rebase
Sonnet"]:::agent auto{"auto-merge.ts
protected files, size, tests,
checks rerun by the console"}:::script judge["Session /judge-improvement
Opus, read-only"]:::agent retry{"auto-merge.ts
discards the branch,
feedback back in pending/"}:::script restart{"impl restart
rebuilds and reloads the console
once no run works"}:::script done --> metrics --> settle done --> sweR sweR -- "change requested" --> reopen --> devR --> review --> sweR sweR -- "merge" --> watch --> queue done --> audit sweF --> audit audit -- "incident, failed criterion,
abnormal cost, feedback" --> improve audit -. "nothing observed:
no session" .-> stop(("end")) improve -- "main moved,
git alone cannot rebase" --> rebase --> auto improve --> auto auto -- "passes" --> judge auto -- "rejected" --> retry judge -- "rejected" --> retry retry -. "next run,
2 attempts at most" .-> improve judge -- "merge,
console/ or bin/ changed" --> restart classDef agent fill:#3a2210,stroke:#ff9d3c,stroke-width:1.6px,color:#c9cddb classDef script fill:#12301f,stroke:#4ade80,stroke-width:1.6px,color:#c9cddb classDef swe fill:#3a310a,stroke:#facc15,stroke-width:1.6px,color:#c9cddb