What protocol v1 rests on and does not repeat: Fossil as the medium, how a message is found in a post or a ticket change, who sent an artifact, verdicts, nodes, tools and versions. Protocol v1 itself, the messages and what a node does with them, is written as tables there. These sections were tested on fresh readers with the rest of the protocol (docs/battery/defs), and each ends with the values in README.md that justify it.
1. Fossil, the medium
Everything that must last is a Fossil artifact: posts, check-ins, tags, ticket changes. These are the evidence of what happened; a host's own log is for diagnosing problems, and may be lost. OCX treats Fossil as a network whose every message lasts:
- Sending is writing an artifact. Sync carries it to every clone; nothing is lost on the way.
- The hook acts on what arrives. Fossil runs the after-receive hook from its backoffice with the artifacts that arrived, and the hook acts on that list alone, reading the repository only to decide what it lists. A write made on the repository itself starts none, and needs none: the tool that wrote it acts on it at once. What the hook missed or failed on is found by a deliberate check, never swept up by a later arrival: the node's check answers the runs and stops (section 5), and a delivery a session missed is not given again.
- The answer is the acknowledgement, and it lasts. A request that has its answer is never acted on again, and what is still open is read from the repository, never kept anywhere else.
- Nothing is retracted. Stopping, correcting and replacing are new artifacts that point at old ones.
- Order comes from references and receipts, such as a reply naming the post it answers, never from clocks.
Each repository keeps a receipt for every artifact it receives: the time, the IP address it came from, and the Fossil user it was received from, by an authenticated sync, through its web page, or by a write on the repository itself, which has no address and records whatever user the writer names. So only a node, its tools and its host's administrators may write to a node's repository file. A repository does not copy its receipts to its clones, and a clone records everything it pulls as received from its own user, which holds setup there (Fossil 2.27, tried 2026-10-12): only the repository an artifact's writer sent it to knows who sent it. The user written inside an artifact is whatever its writer's clone said, and proves nothing by itself. Receipts are numbered as they arrive, and the artifacts of one receipt are taken by their record ids, as Fossil assigns them: that is the order this protocol means within a repository. Where readers on different repositories must agree, as on the latest verdict, the order is the server's (section 3).
Why: Demonstrability (artifacts are immutable, synced, readable later), Parsimony (no second store, no queue, no retries), Ax4 (every open request is found again after any failure).
2. Finding a message
An OCX message is a JSON block in a forum post of any mimetype, or in the
text a ticket change adds to its ticket's comment (its icomment field): a
fenced code block, its fences paired as Markdown (CommonMark) pairs them,
opened by a line that is exactly
```json or a bare ```.
Other text may come before or after it, and nodes ignore it; keep it short. A
block holds an OCX message when its JSON repeats no key and has an ocx key,
a whole number, naming a version the reader knows, whether or not the message
is valid or acted on. A post's or change's message is the first such block
carrying the newest protocol version the reader knows, read from the post's
first version: an edit is ignored, so to change a request, stop it and send
another. Several runs may share a thread or a ticket; each is answered on its
own. What each kind of message holds, and who may send it, is
protocol v1, section 3.
Why: Clarity (one envelope), Loose Coupling (anything that can write a post or a ticket change can send one).
3. Who sent it, and who may do what
The server is the repository people and nodes send their artifacts to, and that every clone syncs with; OCX's network has one. Who sent an artifact is the user the server received it from, by its receipt (section 1), with that user's capabilities on the server, inherited ones included, when the node decides.
- A node on the server reads its own receipts.
- A node on a clone, such as a build host's, asks the server with OCX's
receipttool (tools), over HTTPS, signed in as its node user, about each artifact it decides by, even one written straight into its own repository, but for its own reports; it answers the server's order too (section 1). The user named never changes, so the node may keep it. Until the server has received the artifact and answers, the node decides nothing about it.
If the server pulls from another repository at all, it pulls with Fossil's
--user naming a user of its own who holds no capability this protocol asks
for, so whatever it pulls allows nothing (Fossil 2.27, tried 2026-10-12). On a
node whose repository is a clone, a tool that writes as a person writes on the
server, through its web page, as that person.
So that the server gets every artifact from its writer, all a run writes
reaches it as the run's user, from the run's own clone, synced by its
process; all a node writes reaches it as the
node user, which never holds admin or setup; and OCX's post never writes an
OCX message. On a node, only the node, OCX's tools and the host's
administrators write to the repository itself, each tool naming the user it
signed in.
- A
runor astopmay be sent by any user holding admin or setup. The node acts on one only if a user holding admin or setup sent it. startedandendedare written only by the node, as its node user, and count only if that user sent them.- A post or ticket change is given to a session only if a user in the run's
hearssent it; a check-in, only if the run's own user did not send it. - Which verdicts count, section 4 says.
Who may read threads, tickets and check-ins is Fossil's own business, by its capabilities; OCX adds nothing to it.
Why: Demonstrability (every act is attributed by the repository its writer sent it to), Ax1 (what each user may cause is fixed before it acts, and an artifact no receipt vouches for allows nothing), Parsimony (Fossil's receipts on the server are the one record of who sent what; HISTORY.md decision 37).
4. Verdicts
A verdict is a tag on a check-in recording a judgement of it, pass or fail
with a reason and the objective it was judged against: audited for a person's
or an agent's, ci for a program's. Anyone may write one, with OCX's audit
or with fossil tag add, and it needs no run; but a verdict on your own
check-in never counts, nor an audited verdict that a node user sent.
Verdicts says how to write and count them.
Why: Ax2 (always judged against a named objective), Loose Coupling (a verdict needs no run, and any program may read one).
5. Nodes
A node is OCX acting on one repository on the host that runs its work: the
server's, with OCX's hook installed, or a clone, run by OCX's node tool. It
is named by its node user: a Fossil user of its own, which runs name
in their node, as which the node writes its reports, and as which a node on
another host syncs. Two hosts must never run as one node user, or both would
act on the same runs. A node user holds the least it needs, never admin or
setup: on the server's host, where the node writes into the repository itself
and Fossil checks no capability, none, and no one holds its password; on
another host, o to pull and i to push (Fossil 2.27, tried 2026-10-12). A
node runs a process as its run's user only if it holds that user's password:
the server's node sets a fresh one when it makes the run's workspace
(HISTORY.md decision 29), and a node on another host holds those its
administrator gave it, in a file only the node's account may read; it refuses
any other run. A run's user works for one node: the node of the first run,
in the server's order, that a user holding admin or setup sent naming it.
Every node refuses a run whose user works for another, so the server's node
never sets a new password on a user another node holds. A node runs one run at
a time for each user: another waits, unstarted, until that one ends. OCX's status
lists the limits a node enforces.
A node learns of an artifact only when the artifact reaches its repository. On
the repository's server, that is as soon as it arrives. A node on any other
host, such as a build host with its own clone, learns of a run only when it
pulls its clone, how often being its own choice, and acts on it once the server
says who sent it (section 3). On the server, Fossil tells the
node of each arrival through its after-receive hook; on a clone, OCX's node
tool pulls, and acts on what the pull brought as the hook acts on what Fossil
gives it, and nothing else. Each report it writes it sends to the server at
once, and goes on only once the server has received it from the node user. On
the server's node, a run written with OCX's create is acted on at once, by
create. A run written straight into a clone, such as a build
host's, reaches the server only as received from its node user, which sends no
runs, so the node refuses it: a build host's runs are sent to the server.
When a node starts, and whenever its administrator runs it again, such as
after the hook's log shows a run that failed, a deliberate check reads from
the repository every run that names the node, with its stops and reports,
and decides each that has no ended by the state table of
protocol v1, section 10: one whose process the node
no longer has in its care is answered lost, ending the process first if it
still runs; one in its care with a stop it may act on is ended; one with no
started is decided as if it had just arrived. Nothing runs the check in the
background. A process is in the node's care while the node's watcher of its
run holds it: from just before its workspace is made until its ended is
written.
Why: Ax4 (open runs are found again from the repository), Parsimony (the repository is the only state, and one user names a node and signs its reports), Loose Coupling (a build host joins by syncing a clone).
6. Tools
OCX's tools write these artifacts, and perform runs by hand, as a convenience,
never a requirement: the same artifacts written by other means, such as a
verdict with fossil tag add, count the same. OCX's tools
are create, which writes a run; run, which starts a manual run by hand;
attach, which joins a run's terminal; node, a node on another host;
receipt, which says who sent an artifact; and stop, post, audit and
status.
Why: Loose Coupling (the artifacts are the standard, and no tool is required).
7. Versions
Every OCX message carries "ocx": 1. What may be added to version 1, and what
never changes, is protocol v1, section 15. A
reader takes the block of the newest version it knows
(section 2), so one post may carry a block for each version.
Why: Loose Coupling (other programs can rely on the formats), Clarity (meanings cannot drift, and nothing asked is silently dropped).