Each case is a failure or a race, and what protocol v1 says comes of it, artifact by artifact, with the section that decides it. Together they pin down what the rules might otherwise leave to a reader, as codex's review of c28028fbd5 asked (stone, 2026-10-12). The specs name each case they show by its number, so a case keeps its number.
Crashes
- The node goes down before
started. It had checked the run out, and written nothing. When it starts again it finds the run with nostarted, and acts on it as if it had just arrived: it prepares it again, writesstartedand launches it. The program had never been launched, so it is launched once (10, nodes). - The node goes down after
started, whether before launching the program or while it ran. When it starts again it finds the run with astarted, noended, and no program in its care, and writesended,lost. It never launches the run again, so no program runs twice for one run, andlostsays it may have run in part, or not at all (10). - A session's watcher goes while its program runs on. The program is in
no care: nothing gives it its deliveries or collects its exit. When the
node next starts, its check ends the program and writes
ended,lost(nodes). - A manual run is waiting when the node goes down. When it starts again,
the run has no
started, and itsmanualis true: it goes on waiting for a person (nodes).
Starting
- The checkout fails. A run's step
{"step": "checkout", "of": "release-9"}names a branch the node's repository does not have, perhaps not yet synced. The node writesended,refused, with anotenaming the step and why, and nostarted. To try again, send a new run (11, row 10). - The program cannot be launched.
commandnamesmake, which the sandbox does not have.startedis written, the sandbox exits non-zero, and the run endsexitedwith that code (10). - A branch moves after the run starts. A run's checkout step names
dev. The node resolvesdevto a check-in, writesstartedwith it in full as the valuecheckout, and launches. A check-in landing ondeva minute later changes nothing: the process works on the check-in itsstartednames (5). - Two people start one manual run at once, each with OCX's
runtool at the node. Onestartedis written and one program launched; the other tool finds thestartedand is refused, writing nothing (tools).
Stopping
- Stopped before it starts. stone sends a run with
manualtrue, then astopfor it. The node writesended,stopped, and nostarted: the thread holdsrun,stop,ended. A laterruntool on it is refused, since it has anended(10). - Two stops. While a run runs, two admins each send a
stop. The node acts on the first it received: it ends the program and writesended,stopped. The second does nothing, and nothing answers it. - The program exits as a
stoparrives. Whichever the node meets first decides:ended,exited, the stop then doing nothing; orended,stopped. Never both, since a run gets oneended.
Delivery
- A busy session. Three posts from users in its
hearsarrive while its program is busy. They wait in its standard input, one JSON object to a line, in the order received, and it reads them when it is ready (8.1). - A missed signal. The hook does not run for a post a session should be given. Nothing gives it the post: the hook acts on what it is given, and a later arrival sweeps nothing up. The hook's log shows the hook run that failed, and the session may read its thread itself (9).
Refusing
- A key the node does not know. A run asks
{"limits": {"gpu": 1}}, or{"process": {"stdin": "file"}}, a key a later addition might define. The node refuses it,ended,refused, naming the key, before anystarted; it never runs it as if the key were not there (11, row 2; 15). - A program not on the host. A run's
commandnames/opt/gemini/bin/gemini, which the node's host does not have.startedis written, the process cannot be launched, and the run endsexitedwith a code other than 0, its kept log saying why (8.2, 12). - A forged run. A user holding only check-in (
i) pushes a forum post whose U card saysstone, holding a run forlab-1, a build host's node. lab-1 pulls it and asks the server who sent it: the server received it from that user, not from stone, so lab-1 answers itended,refused, and never decides it again (3, senders). - A forged report. A user who may post replies to a waiting run with an
ended,exited,exit0. The run's node user did not send it, so it does not count: the node still starts the run, and readers still see it waiting. On a build host the forgery arrives by pull, its receipt carries an address, so it is no report of the node's own, and the server says who sent it (3, 10). - A sandboxed agent asks to start a run. Through MCP, it asks OCX's
runtool to start a manual run that names the network. The agent's user holds neither admin nor setup, so the tool refuses, and nothing runs (tools).
Across hosts
- A run for a build host, sent from the browser. stone posts a run for
lab-1in the server's forum. lab-1 pulls it, and asks the server with OCX'sreceipt: stone sent it, and holds setup there. lab-1 starts it, and itsstartedandendedreach the server as received from lab-1 (senders). - The server cannot be reached. lab-1's sync brought a run, but its hook cannot ask the server who sent it. It decides nothing, neither starting nor refusing the run, and its log says so, for a deliberate check once the server answers.
- A run written on the build host itself. An administrator of lab-1's
host writes a run for lab-1 straight into lab-1's repository. It reaches
the server only as lab-1 syncs, received from lab-1, a node user, which
may send no runs; lab-1 answers it
ended,refused. A build host's runs are sent to the server. - A program on a build host speaks. A session on lab-1 posts its
progress with OCX's
post, which writes it in the run's own clone. It reaches the server as received from the run's user, so a session elsewhere whosehearsnames that user is given it, and the server never takes it for lab-1's. - A build host goes down around a launch. lab-1 launches a program only
once the server has received its
started. If it goes down before that, the program was never launched; when it starts again its ownstarted, written with no address, counts without asking, and it writesended,lost. If its disk is lost after the launch, a fresh clone pulls thestartedfrom the server, which says lab-1 sent it, so lab-1 writeslostand never launches the run again (10). - A post whose sender is not known yet. lab-1's sync brings posts A and then B for a session, and the server answers for B but not for A. The hook gives neither, since delivery stops at A, so nothing is passed over; its log says so (9).
- A run names a node user as its
user. An admin sends the server's node a run whoseuserislab-2, a build host's node user, named as thenodeof runs an admin sent. The node refuses it, so it never sets lab-2's password, nor lets a program write lab-2's reports (11, row 4). - Two runs for one user. Two runs for the same node both act as
builder. The node starts the first; the second waits, unstarted, until the first ends, so no workspace's password is reset under a running program (nodes). - A build host's node user passes a check-in. lab-1's host is taken
over, and writes an
auditedpasson a check-in as lab-1. lab-1 is a node user, so itsauditedverdict never counts, nor aciverdict, which counts only from the user of the run it names (verdicts).