What is not specified
The four things the contract deliberately leaves out, what the implementation has beyond it, and two documents that are history rather than standards.
An absence in a contract is a decision, and each of these is written down so that nobody reads it as an oversight.
A WebSocket for Runners
The original proposal had one, carrying a new-submission event. This Server has none.
A Runner polls the claim endpoint, which is simpler, survives a dropped connection with no reconnection logic, and cannot deliver a job twice.
Reintroducing a socket would be an optimisation of when a Runner learns there is work, never of how it takes it. The Client has a socket; a Runner does not.
And that optimisation is already taken. A claim the Server
holds open tells a Runner about work the instant it
exists, with every reason above intact: one claim, one job, no second delivery,
and no reconnection logic — a dropped long poll is a request to make again
rather than a connection to restore. What a socket was measured to be worth
before that existed is 0.44% of the time jobs spend waiting, because 93 in
every 100 wait for a Runner to be free rather than to be told. The gain is on a
quiet installation, where it is the whole of the delay.
Key rotation
There is none, by decision. Revocation is permanent and a new key is a new registration — with a new approval by a person.
An implementation should not build a rotation path against this contract. A leaked key is handled by revoking it and letting the machine come back as a new identity.
Token scopes beyond the Runner itself
A token authorizes this Runner's own surface and nothing else. It is not a session, it does not carry roles, and it cannot reach anything a person signed into the panel may do — including the approval endpoint that admitted it.
The package format
The contract carries the bytes without reading them. standard-io@1 has its own
package format specification; another problem type may define its own.
This is the same rule as problemType being matched by string equality: the
Server does not know what a package contains, so a new problem type needs no
Server release. A Runner implementing a type of its own defines the format that
type reads.
What the implementation has and the contract does not
Trials. A trial is a package to time — run this package's own model solutions and say what they cost — on its own table and its own claim path, with no submission, no attempt, no problem version, no verdict and no score.
The reference implementation speaks three trial calls:
POST /api/v1/runner/trials/claim
POST /api/v1/runner/trials/{trialId}/lease
POST /api/v1/runner/trials/{trialId}/reportThe accepted contract v1.1 does not describe them. It mentions a trial only in
passing, in §9.3, where a Server may not reach closed while one is running.
How the reference implementation divides its attention between the two claim
paths — trials only when there is no marking to do — is on
Problem types.
Trials are optional, and a Runner that ignores them is a conforming Runner
Nothing in the contract obliges an implementation to claim a trial, and a Runner that never calls those paths simply never measures a package.
Because they are outside v1.1, treat their shapes as the implementation's rather than as a standard: they may move in a way the specified surface may not.
A smaller one, on the same terms: a report may name its attachments inline rather than through the attach call, which Files describes. The contract specifies the attach call.
Two documents that are history, not standards
The contract was written down from a Server that already ran. Two earlier
documents — a 2025-03-27 proposal and a copy of it kept as a record — describe a
surface no Server ever served: /runner/auth/init, /files/create,
/runner/submission, /runner/result. They also left twenty-one questions
open, among them atomic reservation, leasing, idempotency, approval, replay
protection and cancellation; every one of those is answered by the pages in this
section, and by code that runs.
If you are handed either, the giveaway is a path from that list. Nothing here serves one.