01
Create — the RunSpec freezes
Dashboard, CLI, API trigger, webhook, or schedule — every entry point converges on one code path that freezes an immutable specification: model, system prompt, task, a full policy snapshot, budgets, the exact tool surface, and who invoked it. Nothing that governs the run can change afterwards.
02
Initialize — the workspace is prepared outside
The credentialed git fetch or copy happens control-plane-side, before the agent exists. The sandbox will only ever see a bind-mounted copy at /workspace; the original repository is never touched.
03
Provision — a fresh sandbox, no secrets
A disposable container from the harness's runner image. Its only credential is a per-session token — disguised as its model API key — and it has no network egress to use anything else.
04
Execute — the harness speaks one contract
Claude Agent SDK or Codex, behind the same HTTP runner contract: tool calls to /permission, message streams to /events, liveness to /heartbeat, the outcome to /result. Model calls ride the LLM facade, which meters usage as it streams.
05
Decide — one gate, every call
Budget, frozen tool surface, argument schema, trust tier, policy, approvals — in that order, for every tool call. Ask-a-human pauses the run; deny returns a tool error the model can react to; in autonomous mode the ask verdict rewrites to the policy fallback with both verdicts recorded.
06
Finish — a diff, a cost report, a ledger
The server is the single status writer. Terminal entry enqueues result deliveries — signed webhooks, GitHub comments and checks — decoupled from the run, so a dead receiver can never mutate one. What remains is reviewable: what changed, what it cost, and why each step was allowed.