Skip to content
Docs menu

campaigns

Campaigns (C3) — the founder's training loop as hub objects: a task on a robot with a budget, whose rounds lock a spec (one declared change, a hypothesis, gates with predictions), train through createRun, are gated and band-scanned in simulation, get a verdict from their locked gates and a decision. Three rules are enforced in code; only a signed-in person may override one, with a reason.

9 operations · 53 schemas

GET /v1/campaigns

List campaigns

listCampaigns · scope key:read

Campaigns visible to the caller (owner, org member or creator), newest first. No campaign is public: a campaign holds its owner's budget and runs.

Parameters

listCampaigns parameters
NameInTypeDescription
statusqueryCampaignStatus
robotquerystring

length ≤ 128

Only campaigns on this robot repo (owner/slug).

slugquerySlug

Only campaigns with this slug (one per owner).

limitqueryinteger

default 20 · ≥ 1 · ≤ 100

Page size.

cursorquerystring

length ≤ 512

Opaque cursor from the previous page's next_cursor.

Responses

listCampaigns responses
StatusDescriptionBody
200

A page of campaigns.

CampaignPage
401

Missing or invalid credentials.

Problemapplication/problem+json
422

Request failed validation.

Problemapplication/problem+json

POST /v1/campaigns

Start a campaign — a task on a robot, with a budget and the three rules

createCampaign · scope key:write

C3. A campaign is the unit of the founder's training loop: a task on a robot repo the caller can see, a budget, an optional declared root checkpoint, and rounds. Its task picks the default gate battery for every round (stand → the posture battery stand, walk / omni → watch while training and c_matrix for the band scan, recovery → recovery, custom → smoke). The three rules — one variable per round, resume only from a PASS checkpoint, a FAIL ends the lineage — are enforced on every round and cannot be switched off; a signed-in person may override one on one round, with a reason (createRoundWithOverride). Creating spends nothing: key:write.

Request body

application/json · required · CampaignCreate

createCampaign request body
FieldTypeDescription
namerequiredstring

length 1–120

slugSlug | null

Unique per owner; derived from name when null.

ownerHandle | null

The campaign's owner; defaults to the caller.

robotrequiredstring

length ≤ 128

The robot repo, owner/slug — one the caller can see.

taskrequiredCampaignTask
descriptionstring | null

length ≤ 2000

budget_usdrequirednumber

> 0 · ≤ 10000

Hard cap on what the campaign's rounds may spend (GPU as billed).

per_run_limit_usdnumber | null

≥ 0 · ≤ 10000

C3b — the most one round may cost and be auto-approved for an agent working inside this campaign. Null: the workspace's per-run limit (AGENT_AUTO_APPROVE_PER_RUN_USD, $3.00), stored on the campaign.

rootCheckpointRef | null

Responses

createCampaign responses
StatusDescriptionBody
201

Campaign created.

Campaign
401

Missing or invalid credentials.

Problemapplication/problem+json
403

Authenticated but not allowed (visibility, membership or scope).

Problemapplication/problem+json
409

State conflict (duplicate handle/slug, wrong repo kind, terminal job, ...).

Problemapplication/problem+json
422

Request failed validation.

Problemapplication/problem+json

GET /v1/campaigns/{campaign_id}

Get a campaign (its rounds, spend, and what waits on a person)

getCampaign · scope key:read

Parameters

getCampaign parameters
NameInTypeDescription
campaign_idrequiredpathstring

length 1–64

Campaign id (camp_...), or its slug when exactly one campaign the caller can see has it (two owners may share a slug: that is a 409 naming both ids).

Responses

getCampaign responses
StatusDescriptionBody
200

The campaign with every round, newest first.

Campaign
401

Missing or invalid credentials.

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json
409

State conflict (duplicate handle/slug, wrong repo kind, terminal job, ...).

Problemapplication/problem+json

PATCH /v1/campaigns/{campaign_id}

Rename, re-describe, change the budget of, or stop a campaign

updateCampaign · scope key:write

key:write, with two exceptions enforced in the handler: raising budget_usd or raising per_run_limit_usd (C3b) is a person's decision (a signed-in session; a key of any scope is 403). Together they are what lets an agent run rounds without asking — an agent that could raise either would have no limit at all. A key may lower them, rename the campaign, or stop it.

Parameters

updateCampaign parameters
NameInTypeDescription
campaign_idrequiredpathstring

length 1–64

Campaign id (camp_...), or its slug when exactly one campaign the caller can see has it (two owners may share a slug: that is a 409 naming both ids).

Request body

application/json · required · CampaignUpdate

updateCampaign request body
FieldTypeDescription
namestring | null

length 1–120

descriptionstring | null

length ≤ 2000

budget_usdnumber | null

> 0 · ≤ 10000

Lowering is key:write; raising is a signed-in person's decision (403 for a key).

per_run_limit_usdnumber | null

≥ 0 · ≤ 10000

C3b — lowering is key:write; raising is a signed-in person's decision (403 for a key).

statusstring | null

one of stopped

stopped ends the campaign: no new rounds.

Responses

updateCampaign responses
StatusDescriptionBody
200

The updated campaign.

Campaign
401

Missing or invalid credentials.

Problemapplication/problem+json
403

Authenticated but not allowed (visibility, membership or scope).

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json
409

State conflict (duplicate handle/slug, wrong repo kind, terminal job, ...).

Problemapplication/problem+json
422

Request failed validation.

Problemapplication/problem+json

POST /v1/campaigns/{campaign_id}/rounds

Lock a round's spec and start its training run

createRound · scope key:train

C3. The spec — one declared change (a summary and the resolved-config keys it covers), a hypothesis, what is not being done, tripwires, gates with their predictions, an iteration cap — is locked here and never edited; a gate added later is shown and not counted. Then the three rules are checked, in code, before anything is spent:

  • One variable. The change the recipe makes, predicted against the parent checkpoint's run (its resolved config, and its recipe), must lie inside the declared keys (a declared key covers itself and every path under it). run.* and a template's own bookkeeping never count. A round that stacks a sibling's change (same parent checkpoint) on its own is more than one variable. When the run's resolved config arrives, the same diff is recomputed on what it actually trained on; an undeclared key found then makes the round confounded.

  • Resume only from PASS. parent must be the campaign's declared root, or a checkpoint of one of its rounds whose verdict at that step is pass.

  • A FAIL ends the lineage. No checkpoint of a round whose verdict is fail or confounded, or whose lineage was stopped, may be a parent.

A violation is 422 with one errors[] entry per rule (type is rule.one_variable, rule.resume_from_pass or rule.fail_ends_lineage, msg names the keys or the verdict) and nothing is recorded. Only a signed-in person may override a rule, with a reason, through createRoundWithOverride; no key of any scope can.

Budget: the round's run is priced with estimateRun; when its maximum would take the campaign past budget_usd (spent from the ledger, plus what in-flight rounds may still spend) the answer is 409 naming the numbers — the request is well-formed, the campaign has no money left for it. A priced run's own budget_usd is capped at what remains, so the hub stops it there. Then the run is created through createRun's own path (so executor: modal, C1's parent_checkpoint_step and C2's gate behave exactly as there), with the campaign's task-aware gate when the recipe names none. Spends compute: key:train.

Dry run (K3). ?dry_run=true runs every check above on the same body and records nothing: 200 with a RoundPreview — the three rules as verdicts (the 422's own entries, never a second implementation), the variables against the parent, the run's price with the campaign's remaining budget as its cap, every published checkpoint of the parent run with whether it may be a parent and the rule's sentence when not, whether the template reads each hyperparameter, and — when the parent run published no checkpoint at all (every imported run today) — why it cannot be fine-tuned. A malformed body, an unknown parent and a campaign that cannot afford the round answer as createRound would. A web fine-tune is a round, so this is its preview before the spend.

Parameters

createRound parameters
NameInTypeDescription
campaign_idrequiredpathstring

length 1–64

Campaign id (camp_...), or its slug when exactly one campaign the caller can see has it (two owners may share a slug: that is a 409 naming both ids).

dry_runqueryboolean

default false

K3 — check everything and record nothing; 200 with a RoundPreview.

Request body

application/json · required · RoundCreate

createRound request body
FieldTypeDescription
namerequiredstring

length 1–120

The round's short name, e.g. "C2 arm A".

parentCheckpointRef | null

The checkpoint this round resumes from (null trains from scratch). Becomes the run's parent_run_id and recipe.parent_checkpoint_step.

specrequiredRoundSpec
reciperequiredRecipe
scanRoundScanRequest | null

Responses

createRound responses
StatusDescriptionBody
200

dry_run=true: what this round would be — nothing was recorded.

RoundPreview
201

Round created; its spec is locked and its run queued.

Round
401

Missing or invalid credentials.

Problemapplication/problem+json
403

Authenticated but not allowed (visibility, membership or scope).

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json
409

State conflict (duplicate handle/slug, wrong repo kind, terminal job, ...).

Problemapplication/problem+json
422

Request failed validation.

Problemapplication/problem+json
429

The account's or the key's daily GPU-hour quota (as on createRun).

Problemapplication/problem+json
503

A service this endpoint needs is not configured in this deployment (M0's boot guarantee: the API boots with zero secrets, and an endpoint that needs one says so instead of returning a stack trace).

Problemapplication/problem+json

POST /v1/campaigns/{campaign_id}/rounds/override

Start a round that breaks a rule — a person's decision, with a reason

createRoundWithOverride · scope session

C3. createRound, plus override: {rules, reason}. Session only: no API key of any scope may override a rule, so an agent can propose a round and never waive the rules it would break. rules must name exactly the rules this round violates (a rule named but not broken is 422: an override record says what was waived, never more), and reason is recorded with who and when on the round as an override chip. A round created with a one_variable override reads confounded whatever its gates say, and nothing resumes from it without another override. Budget, scope and every other check are createRound's.

Parameters

createRoundWithOverride parameters
NameInTypeDescription
campaign_idrequiredpathstring

length 1–64

Campaign id (camp_...), or its slug when exactly one campaign the caller can see has it (two owners may share a slug: that is a 409 naming both ids).

Request body

application/json · required · RoundOverrideCreate

createRoundWithOverride request body
FieldTypeDescription
namerequiredstring

length 1–120

parentCheckpointRef | null
specrequiredRoundSpec
reciperequiredRecipe
scanRoundScanRequest | null
overriderequiredRoundOverride

Responses

createRoundWithOverride responses
StatusDescriptionBody
201

Round created with its override record.

Round
401

Missing or invalid credentials.

Problemapplication/problem+json
403

Authenticated but not allowed (visibility, membership or scope).

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json
409

State conflict (duplicate handle/slug, wrong repo kind, terminal job, ...).

Problemapplication/problem+json
422

Request failed validation.

Problemapplication/problem+json
503

A service this endpoint needs is not configured in this deployment (M0's boot guarantee: the API boots with zero secrets, and an endpoint that needs one says so instead of returning a stack trace).

Problemapplication/problem+json

GET /v1/campaigns/{campaign_id}/rounds/{round_n}

Get a round — its locked spec, the verdict at a step, the variables, the decisions

getRound · scope key:read

The verdict is the round's locked gates evaluated on the measured results at step (default: the chosen step — the one a decision named, else the measured checkpoint with the most counted gates passing, the earliest on a tie). Measurements come from the round's band scan at that step, else from the gate its run got while training. The hub's own 0.85–1.15 band verdict for the same rollout is returned beside it (evaluation.band) as a measurement, never as the verdict.

Parameters

getRound parameters
NameInTypeDescription
campaign_idrequiredpathstring

length 1–64

Campaign id (camp_...), or its slug when exactly one campaign the caller can see has it (two owners may share a slug: that is a 409 naming both ids).

round_nrequiredpathinteger

≥ 1

The round's number within its campaign (1, 2, …).

stepqueryinteger

≥ 0

Evaluate the locked gates at this checkpoint step instead of the chosen one.

Responses

getRound responses
StatusDescriptionBody
200

The round.

Round
401

Missing or invalid credentials.

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json
409

State conflict (duplicate handle/slug, wrong repo kind, terminal job, ...).

Problemapplication/problem+json

POST /v1/campaigns/{campaign_id}/rounds/{round_n}/decision

Decide a round — shortlist, iterate, stop the lineage, or done

decideRound · scope key:write

per action: stop key:write · iterate key:train · shortlist session · done session

C3. The operation's floor is key:write and each action has its own scope, enforced in the handler (x-action-scopes): stop is key:write (ending a lineage spends nothing); iterate is key:train (it says "train the next round from step", which an agent may propose inside the campaign's budget); shortlist and done are session only — the two human gates, which no key of any scope, and therefore no agent, can pass. shortlist records the chosen checkpoints (candidates, steps of this round's run) and the A/B controls (any visible checkpoint, usually the parent), each with its verdict at that step; it starts nothing. C4: it plans the real-robot session (createTrialSession) — one trial per run, the control first and last, a run sheet each — and, when the device is known (device_id, or the only one of the owner's that accepts every contract) and no agent's shortlist follow-up will, files one consent request per trial; a person approves each on the consent page. iterate refuses a step whose verdict is not pass (the resume rule, stated before the next round is written). done closes the campaign. C3b: shortlist is refused (422, rule.separates_from_control) when the round's control — the checkpoint it started from, measured in its own band scan — also passes every locked gate, unless the person sends override naming that rule with a reason. Every decision is recorded with who, when, how and the verdict it was taken on. AG1: when an agent session's shortlist decision waits on this round, a shortlist here answers it (the note is reason), and the hub then runs the 20-seed band scan on the picks (or waits for the round's own scan when it already covers them) and files one device consent request per pick that still passes the locked gates, the note as each request's reason — never approved here (M13).

Parameters

decideRound parameters
NameInTypeDescription
campaign_idrequiredpathstring

length 1–64

Campaign id (camp_...), or its slug when exactly one campaign the caller can see has it (two owners may share a slug: that is a 409 naming both ids).

round_nrequiredpathinteger

≥ 1

The round's number within its campaign (1, 2, …).

Request body

application/json · required · RoundDecisionCreate

decideRound request body
FieldTypeDescription
actionrequiredRoundDecisionAction
reasonstring | null

length ≤ 1000

stepinteger | null

≥ 0

iterate: the checkpoint the next round resumes from (its verdict must be pass).

candidatesarray of integer

items ≤ 4

shortlist: steps of this round's run to trial on the robot.

controlsarray of CheckpointRef

items ≤ 2

shortlist: the A/B control(s), run first and last (usually the parent).

overrideRoundOverride | null

C3b, shortlist only — a person's override of separates_from_control, required (422, rule.separates_from_control) when, for any candidate step, the round's control passes every locked gate that step passes, and refused when none is so (an override names exactly the rules broken). Recorded on the round like a create-time override. The action is already session-only.

device_idId | null

C4, shortlist only — the device to trial the shortlist on. Default: the only one of the owner's devices that embodies the campaign's robot and accepts every checkpoint's contract; with none or several the trials are planned unfiled (fileTrialRequests names one later).

minutesinteger | null

≥ 1 · ≤ 240

C4, shortlist only — each trial's approval window (default 10).

Responses

decideRound responses
StatusDescriptionBody
200

The round, with the decision recorded.

Round
401

Missing or invalid credentials.

Problemapplication/problem+json
403

Authenticated but not allowed (visibility, membership or scope).

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json
409

State conflict (duplicate handle/slug, wrong repo kind, terminal job, ...).

Problemapplication/problem+json
422

Request failed validation.

Problemapplication/problem+json

POST /v1/campaigns/{campaign_id}/rounds/{round_n}/gates

Add a gate after the lock — shown, never counted

addRoundGate · scope key:write

C3. A round's spec is locked when it starts; what someone learns afterwards may still be worth measuring (the founder added a stand tilt gate to a round that had started). The gate is evaluated and shown beside the locked ones with added_after_lock_at set and counted: false: it never changes the verdict.

Parameters

addRoundGate parameters
NameInTypeDescription
campaign_idrequiredpathstring

length 1–64

Campaign id (camp_...), or its slug when exactly one campaign the caller can see has it (two owners may share a slug: that is a 409 naming both ids).

round_nrequiredpathinteger

≥ 1

The round's number within its campaign (1, 2, …).

Request body

application/json · required · RoundGate

addRoundGate request body
FieldTypeDescription
namerequiredstring

length 1–120

How the gate reads, e.g. "wz±0.20 tracking ≥ 50 %, opposite signs".

metricrequiredRoundGateMetric
oprequiredstring

one of < · <= · > · >=

thresholdrequirednumber
cellsarray of string

items ≤ 24

Battery cell names; empty means the whole checkpoint (pass_rate).

axisstring | null

one of vx · vy · yaw

tracking / tracking_gap: the axis; null means each cell's commanded axes.

predictedstring | null

length ≤ 80

The value predicted at the lock, as written (e.g. "≥ 50 % both", "20 / 20").

countedread-onlyboolean

Whether it counts toward the verdict — true only for gates locked with the spec.

added_after_lock_atread-onlystring (date-time) | null (date-time)

When a gate was added after the lock (addRoundGate); such a gate is never counted.

Responses

addRoundGate responses
StatusDescriptionBody
201

The round, with the gate added (not counted).

Round
401

Missing or invalid credentials.

Problemapplication/problem+json
403

Authenticated but not allowed (visibility, membership or scope).

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json
409

State conflict (duplicate handle/slug, wrong repo kind, terminal job, ...).

Problemapplication/problem+json
422

Request failed validation.

Problemapplication/problem+json

Schemas (53)

The schemas these operations reach before any other tag’s do. A type that links elsewhere is rendered on that tag’s page.

CampaignStatus

string

one of active · waiting · done · stopped

active — rounds may start; waiting — active, and a round's review waits on a decision (Campaign.waiting says which); done — a person closed it (decideRound {action: done}); stopped — stopped by updateCampaign. Neither done nor stopped takes new rounds.

CampaignPage

object

CampaignPage fields
FieldTypeDescription
itemsrequiredarray of Campaign
next_cursorstring | null

CampaignCreate

object

CampaignCreate fields
FieldTypeDescription
namerequiredstring

length 1–120

slugSlug | null

Unique per owner; derived from name when null.

ownerHandle | null

The campaign's owner; defaults to the caller.

robotrequiredstring

length ≤ 128

The robot repo, owner/slug — one the caller can see.

taskrequiredCampaignTask
descriptionstring | null

length ≤ 2000

budget_usdrequirednumber

> 0 · ≤ 10000

Hard cap on what the campaign's rounds may spend (GPU as billed).

per_run_limit_usdnumber | null

≥ 0 · ≤ 10000

C3b — the most one round may cost and be auto-approved for an agent working inside this campaign. Null: the workspace's per-run limit (AGENT_AUTO_APPROVE_PER_RUN_USD, $3.00), stored on the campaign.

rootCheckpointRef | null

Campaign

object

Campaign fields
FieldTypeDescription
idrequiredId
slugrequiredSlug
namerequiredstring
descriptionstring | null
ownerrequiredRepoOwner
created_byUserPublic | null
robotrequiredRepoRef
taskrequiredCampaignTask
statusrequiredCampaignStatus
rulesrequiredCampaignRules
rootCheckpointRef | null

The declared root checkpoint rounds may resume from without a PASS verdict of their own.

gate_defaultsrequiredCampaignGateDefaults
per_run_limit_usdnumber

C3b — the most one round may cost (its estimate's maximum) and still be approved by the campaign's rules, without a person, when an agent session attached to this campaign proposes it. Beside spend.remaining_usd: a proposal is auto-approved only when its cap is at or under this limit AND fits in what remains.

spendrequiredCampaignSpend
waitingCampaignWaiting | null
rounds_totalrequiredinteger
policy_on_robotCampaignPolicyOnRobot | null

C4 — the checkpoint a person most recently promoted after a real-robot trial (setTrialVerdict {promote}): the campaign's policy on the robot, and the baseline its next sessions' criteria are drafted from.

roundsarray of RoundSummary

Every round, newest first (getCampaign; omitted from list pages).

created_atrequiredstring (date-time)
updated_atrequiredstring (date-time)
finished_atstring (date-time) | null (date-time)

CampaignUpdate

object

CampaignUpdate fields
FieldTypeDescription
namestring | null

length 1–120

descriptionstring | null

length ≤ 2000

budget_usdnumber | null

> 0 · ≤ 10000

Lowering is key:write; raising is a signed-in person's decision (403 for a key).

per_run_limit_usdnumber | null

≥ 0 · ≤ 10000

C3b — lowering is key:write; raising is a signed-in person's decision (403 for a key).

statusstring | null

one of stopped

stopped ends the campaign: no new rounds.

RoundCreate

object

RoundCreate fields
FieldTypeDescription
namerequiredstring

length 1–120

The round's short name, e.g. "C2 arm A".

parentCheckpointRef | null

The checkpoint this round resumes from (null trains from scratch). Becomes the run's parent_run_id and recipe.parent_checkpoint_step.

specrequiredRoundSpec
reciperequiredRecipe
scanRoundScanRequest | null

RoundPreview

object

K3 — createRound?dry_run=true: what createRound would decide on this body, recording nothing.

RoundPreview fields
FieldTypeDescription
fine_tunablerequiredboolean

False when the parent run published no checkpoint the hub can resume from; not_fine_tunable says why and nothing else below is computed.

not_fine_tunablestring | null
rulesrequiredarray of RoundRuleVerdict

one_variable, resume_from_pass, fail_ends_lineage, in that order; empty when not fine-tunable.

variablesRoundVariables | null
estimateRunEstimate | null

The round's run priced as estimateRun prices it, its budget_usd capped at what the campaign has left.

checkpointsrequiredarray of RoundParentCheckpoint

Every published checkpoint of the parent run, newest first; empty for a round from scratch.

hyperparamsTemplateHyperparams | null
warningsrequiredarray of string

Round

object

Round fields
FieldTypeDescription
idrequiredId
campaign_idrequiredId
campaign_slugstring
nrequiredinteger
namerequiredstring
levelrequiredinteger
attemptrequiredinteger
statusrequiredRoundStatus
verdictrequiredRoundVerdictValue
lineagerequiredstring

one of open · stopped

parentRoundParent | null
specrequiredRoundSpec
variablesRoundVariables | null
overridesrequiredarray of RoundOverrideRecord
decisionsrequiredarray of RoundDecision
shortlistrequiredarray of RoundShortlistEntry
chosen_stepinteger | null
stepsarray of integer

Checkpoint steps with a finished measurement (scan, else gate).

step_verdictsarray of RoundStepVerdict

AG1 — the locked gates at every measured step, oldest first (not only the chosen one), so a round card, a run's checkpoint rows and a shortlist column all read the round's own verdict at each checkpoint. Named step_verdicts because steps above is already the list of step numbers.

evaluationrequiredRoundEvaluation
parent_evaluationRoundEvaluation | null

The same locked gates on the parent checkpoint's own measurement (the A/B control), when it has one.

controlRoundControl | null

C3b — the checkpoint the round started from, measured in this round's own band scan and judged by its locked gates.

scan_idstring | null
scanRoundScanRequest | null

The band scan this round asked for.

runRun | null
estimate_usd_maxnumber | null

What the run could cost at most when it was created (the reservation).

evidencestring | null
warningsarray of string

What the hub noticed and did not refuse (a declared key the recipe does not move, …).

tripwireTripwireState | null
trial_sessionsarray of RoundTrialSession

C4 — the real-robot sessions of this round's checkpoints, newest first: the order, each trial's status and verdict, whether the bracket held.

created_atrequiredstring (date-time)

RoundOverrideCreate

object

RoundCreate plus the person's override.

RoundOverrideCreate fields
FieldTypeDescription
namerequiredstring

length 1–120

parentCheckpointRef | null
specrequiredRoundSpec
reciperequiredRecipe
scanRoundScanRequest | null
overriderequiredRoundOverride

RoundDecisionCreate

object

RoundDecisionCreate fields
FieldTypeDescription
actionrequiredRoundDecisionAction
reasonstring | null

length ≤ 1000

stepinteger | null

≥ 0

iterate: the checkpoint the next round resumes from (its verdict must be pass).

candidatesarray of integer

items ≤ 4

shortlist: steps of this round's run to trial on the robot.

controlsarray of CheckpointRef

items ≤ 2

shortlist: the A/B control(s), run first and last (usually the parent).

overrideRoundOverride | null

C3b, shortlist only — a person's override of separates_from_control, required (422, rule.separates_from_control) when, for any candidate step, the round's control passes every locked gate that step passes, and refused when none is so (an override names exactly the rules broken). Recorded on the round like a create-time override. The action is already session-only.

device_idId | null

C4, shortlist only — the device to trial the shortlist on. Default: the only one of the owner's devices that embodies the campaign's robot and accepts every checkpoint's contract; with none or several the trials are planned unfiled (fileTrialRequests names one later).

minutesinteger | null

≥ 1 · ≤ 240

C4, shortlist only — each trial's approval window (default 10).

RoundGate

object

One gate of a round's spec: metric op threshold over cells, with the value predicted for it written down when the spec was locked. counted and added_after_lock_at are set by the hub.

RoundGate fields
FieldTypeDescription
namerequiredstring

length 1–120

How the gate reads, e.g. "wz±0.20 tracking ≥ 50 %, opposite signs".

metricrequiredRoundGateMetric
oprequiredstring

one of < · <= · > · >=

thresholdrequirednumber
cellsarray of string

items ≤ 24

Battery cell names; empty means the whole checkpoint (pass_rate).

axisstring | null

one of vx · vy · yaw

tracking / tracking_gap: the axis; null means each cell's commanded axes.

predictedstring | null

length ≤ 80

The value predicted at the lock, as written (e.g. "≥ 50 % both", "20 / 20").

countedread-onlyboolean

Whether it counts toward the verdict — true only for gates locked with the spec.

added_after_lock_atread-onlystring (date-time) | null (date-time)

When a gate was added after the lock (addRoundGate); such a gate is never counted.

CampaignTask

string

one of stand · walk · omni · recovery · custom

What the campaign trains, which picks its rounds' default gate battery (C3 — the C1 × C2 run judged a stand policy on a walking battery): stand → stand (upright, drift, tilt, joint asymmetry) while training and for the band scan; walk and omni → watch while training, c_matrix for the scan; recovery → recovery for both; custom → smoke for both. C3b: the stand battery is the zero-command cell plus three pushes calibrated to separate a trained stand from a network that outputs ~0 (lateral ±6 N·s and backward 4 N·s at 8 s, all scored on posture).

CheckpointRef

object

A checkpoint of a run — checkpoints/step_<step>/ of its output model repo.

CheckpointRef fields
FieldTypeDescription
run_idrequiredId
stepinteger | null

≥ 0

The checkpoint step. Null on a campaign's root means any published checkpoint of that run may be resumed from.

CampaignRules

object

Which rules the hub enforces on this campaign's rounds. All three are always true: they cannot be switched off for a campaign, only overridden on one round by a signed-in person with a reason.

CampaignRules fields
FieldTypeDescription
one_variablerequiredboolean
resume_from_passrequiredboolean
fail_ends_lineagerequiredboolean
separates_from_controlboolean

C3b — always true; checked at shortlist (see CampaignRuleName).

CampaignGateDefaults

object

The gate a round's run gets when its recipe names none, and the band scan it gets when it finishes — picked by the campaign's task.

CampaignGateDefaults fields
FieldTypeDescription
batteryrequiredstring

Battery gated while training (CheckpointGateSpec.battery).

every_stepsrequiredinteger
seedsrequiredinteger
delayrequiredinteger
scan_batteryrequiredstring

Battery of the band scan the hub queues when the run finishes.

scan_seedsrequiredinteger
videoVideoMode
scan_videoVideoMode

CampaignSpend

object

Money, from the ledger: spent_usd sums the terminal rows of the campaign's round runs; reserved_usd is what rounds still training may yet spend (their estimateRun maximum); remaining_usd = budget_usd − spent − reserved, never below 0. Gate and scan rollouts are counted, not priced (the hub does not bill sim time).

CampaignSpend fields
FieldTypeDescription
budget_usdrequirednumber
spent_usdrequirednumber
reserved_usdrequirednumber
remaining_usdrequirednumber
by_roundrequiredarray of CampaignRoundSpend
unpriced_rolloutsrequiredinteger

Gate and scan rollouts of the campaign's runs — sim time, never billed.

CampaignWaiting

object

What waits on a person, and since when.

CampaignWaiting fields
FieldTypeDescription
kindrequiredstring

one of decision

decision — a round's run finished and its review is measured; a person (or, for iterate / stop, an agent) decides it.

roundrequiredinteger
sincerequiredstring (date-time)
reasonrequiredstring

One sentence, e.g. "Round 3 is reviewed: 2 checkpoints PASS their locked gates."

CampaignPolicyOnRobot

object

C4 — the checkpoint a person promoted after a real-robot trial.

CampaignPolicyOnRobot fields
FieldTypeDescription
trial_idrequiredId
labelstring | null
model_reporequiredstring
run_idstring | null
stepinteger | null
devicestring | null
decided_atrequiredstring (date-time)
decided_byUserPublic | null

RoundSummary

object

One row of a campaign's round timeline.

RoundSummary fields
FieldTypeDescription
nrequiredinteger
namerequiredstring
levelrequiredinteger

Depth in the lineage — 1 for a round from scratch or from the root.

attemptrequiredinteger

Which attempt at this parent checkpoint (siblings count from 1).

statusrequiredRoundStatus
verdictrequiredRoundVerdictValue
gates_passedinteger
gates_totalinteger
chosen_stepinteger | null
parentRoundParent | null
lineagerequiredstring

one of open · stopped

changerequiredRoundChange
override_rulesarray of CampaignRuleName
variablesRoundVariables | null
evidencestring | null

One line generated from the verdict, the scan and any tripwire.

run_idstring | null
run_statusJobStatus | null
cost_usdnumber
pricedboolean
decisionRoundDecisionAction | null

The latest decision's action.

separatesboolean | null

C3b — Round.control.separates; false puts the round behind a person's override at shortlist.

trial_sessionsarray of RoundTrialSession

C4 — the real-robot sessions of this round's checkpoints, newest first: the order, each trial's status and verdict, whether the bracket held.

created_atrequiredstring (date-time)

RoundSpec

object

The founder's per-round spec, locked when the round starts (C3). locked_at / locked_by are set by the hub; nothing in it is ever edited afterwards.

RoundSpec fields
FieldTypeDescription
changerequiredRoundChange
hypothesisrequiredRoundHypothesis
not_doingarray of string

items ≤ 16

tripwiresarray of GateTripwire

items ≤ 8

Passed to the run's gate (CheckpointGateSpec.tripwires).

gatesrequiredarray of RoundGate

items 1–16

iteration_caprequiredinteger

≥ 1 · ≤ 100000

Iterations this round may train. Written into the template's own cap (max_iterations for ppo_isaac, iterations for stub_ppo / ppo_mujoco) when the recipe leaves it out; a recipe that sets a different one is 422.

locked_atread-onlystring (date-time) | null (date-time)
locked_byread-onlyUserPublic | null
locked_viaread-onlystring | null

one of person · key

RoundScanRequest

object

The band scan the hub queues when the round's run finishes (default: the campaign's gate_defaults.scan_battery × scan_seeds, on the run's own executor).

RoundScanRequest fields
FieldTypeDescription
batterystring | null

one of watch · smoke · c_matrix · robust · recovery · full · stand

seedsinteger | null

≥ 1 · ≤ 20

executorRolloutExecutor | null

RoundRuleVerdict

object

RoundRuleVerdict fields
FieldTypeDescription
rulerequiredCampaignRuleName
statusrequiredstring

one of pass · fail

msgrequiredstring

The 422 entry's msg when it fails; what was checked when it passes.

RoundVariables

object

The one-variable rule's arithmetic. basis: planned — computed at the start from the recipe against the parent checkpoint's run; resolved — recomputed on the run's own resolved config once it arrived; none — the round trains from scratch, so there is nothing to diff. changed lists every counted key that moved (bookkeeping excluded), undeclared those outside the declared change.

RoundVariables fields
FieldTypeDescription
basisrequiredstring

one of none · planned · resolved

declaredrequiredinteger

Keys the round declared.

foundrequiredinteger

Counted keys that changed.

changedrequiredarray of string
undeclaredrequiredarray of string
bookkeepingrequiredinteger

Keys that changed by construction (run.*, run ids, the iteration cap) and are not counted.

one_variablerequiredboolean
stacked_oninteger | null

The sibling round whose change this round stacks on its own, if it does.

comparisonstring | null

one of same_shape · cross_shape

L1 — resolved only: how the two configs were compared (RunConfigDiff.comparison). On cross_shape (an Isaac Lab child of an imported parent) only the mapped key pairs are counted; the keys either side has no record of are counted below, never as changes.

cannot_comparearray of string

L1 — declared keys under which the parent recorded nothing, so the rule can neither pass nor fail them ("cannot be compared"). They are not in undeclared and do not make the round confounded.

parent_has_no_recordinteger

≥ 0

L1 — cross_shape: this run's keys the parent's config has no counterpart for.

child_has_no_recordinteger

≥ 0

L1 — cross_shape: the parent's keys this run's config has no counterpart for.

groupsarray of RoundVariablesGroup

L1 — the counted changes by RL structure (RunConfig.groups' rule table), groups with a change only.

RoundParentCheckpoint

object

One published checkpoint of the parent run, judged as a parent of this round would be (resume_from_pass, fail_ends_lineage).

RoundParentCheckpoint fields
FieldTypeDescription
steprequiredinteger

≥ 0

can_be_parentrequiredboolean
reasonstring | null

The rule's own sentence when it cannot be a parent.

verdictstring | null

one of pending · pass · partial · fail · confounded

The round's verdict at this step on its locked gates, when the parent run is a round of this campaign.

cells_passedinteger | null

Cells that passed in the step's latest sim gate or band scan (getRunGates has each cell); null when unmeasured.

cells_totalinteger | null

TemplateHyperparams

object

Whether the template reads what the recipe sets. accepted: null — the hub does not know which hyperparameters this template reads (a trainer run by path). Only ppo_isaac takes overrides (Hydra config paths); a name the template does not read would be ignored by the trainer, so it is listed in ignored.

TemplateHyperparams fields
FieldTypeDescription
acceptedrequiredboolean | null
ignoredrequiredarray of string
readsarray of string | null

RoundStatus

string

one of training · scanning · review · decided · failed

training — the run is queued or running; scanning — the run ended and its band scan is being measured; review — measured, waiting on a decision; decided — a decision was recorded; failed — the run ended without a single checkpoint to judge.

RoundVerdictValue

string

one of pending · pass · partial · fail · confounded

The round's locked gates at the step: pass — every counted gate PASSes; partial — some do; fail — none does; confounded — the one-variable rule was broken (overridden at the start, or an undeclared key found in the resolved config), whatever the gates say; pending — nothing measured yet. An unmeasured gate never passes.

RoundParent

object

Where the round resumed from — a checkpoint and, when it has one, the round that produced it.

RoundParent fields
FieldTypeDescription
run_idrequiredstring
stepinteger | null
roundinteger | null
is_rootboolean

RoundOverrideRecord

object

RoundOverrideRecord fields
FieldTypeDescription
rulerequiredCampaignRuleName
reasonrequiredstring
byUserPublic | null
atrequiredstring (date-time)
detailrequiredstring

What the rule said when it was overridden, e.g. "parent R2 · step 700 is a partial (6 of 7)".

RoundDecision

object

RoundDecision fields
FieldTypeDescription
actionrequiredRoundDecisionAction
reasonstring | null
stepinteger | null
verdictRoundVerdictValue
byUserPublic | null
viarequiredstring

one of person · key

atrequiredstring (date-time)

RoundShortlistEntry

object

RoundShortlistEntry fields
FieldTypeDescription
rolerequiredstring

one of candidate · control

run_idrequiredstring
steprequiredinteger
verdictrequiredRoundVerdictValue
model_repostring | null

The run's output model repo; the checkpoint is checkpoints/step_<step>/ in it.

RoundStepVerdict

object

AG1 — the round's locked gates at one checkpoint (C3's evaluation, at every measured step, not only the chosen one).

RoundStepVerdict fields
FieldTypeDescription
steprequiredinteger
verdictrequiredRoundVerdictValue
sourcestring | null

one of scan · gate

rollout_idstring | null
seedsinteger | null
gates_passedrequiredinteger
gates_totalrequiredinteger
resultsrequiredarray of RoundGateResult
bandRoundBand | null

RoundEvaluation

object

RoundEvaluation fields
FieldTypeDescription
steprequiredinteger | null
sourcestring | null

one of scan · gate

Where the measurement came from — the round's band scan, or a gate while training.

run_idstring | null

The run whose checkpoint was measured (the parent's, for parent_evaluation).

rollout_idstring | null
batterystring | null
seedsinteger | null
verdictrequiredRoundVerdictValue
gates_passedrequiredinteger
gates_totalrequiredinteger

Counted gates.

resultsrequiredarray of RoundGateResult
hypothesisRoundGateResult | null
bandRoundBand | null

RoundControl

object

C3b — the control: the checkpoint the round started from, measured in the round's own band scan (same battery, seeds and conditions) and judged by the round's locked gates, beside the candidate. A parent control is its own rollout on the parent's model repo (it carries no run_id of this round, so it never enters the band); an untrained control is the scan's step-0 row. When it passes every locked gate the candidate passes — all of them, when the candidate passes all — separates is false, the round carries the warning "the gates do not separate candidate from control", and shortlisting it needs a person's override with a reason.

RoundControl fields
FieldTypeDescription
rolerequiredRoundControlRole
run_idstring | null

The run whose checkpoint is the control (the parent's, or this round's own).

stepinteger | null
model_repostring | null

The model repo holding it, owner/slug.

rollout_idstring | null

The rollout that measured it (a parent control's own scan rollout, or the scan's step-0 row).

statusrequiredRoundControlStatus
reasonstring | null

Why it is unavailable.

evaluationRoundEvaluation | null

The round's locked gates on the control's measurement (measured only).

separatesboolean | null

Against compared_step: true when the candidate passes a locked gate the control fails; false when the control passes every gate the candidate passes (always false when the control passes them all); null until both are measured, or when the candidate passes no gate at all.

compared_stepinteger | null

The candidate step separates compares against — the round's chosen step.

warningstring | null

The sentence that also appears in Round.warnings when separates is false.

RoundTrialSession

object

C4 — a real-robot session of this round's checkpoints, as the campaign row prints it.

RoundTrialSession fields
FieldTypeDescription
idrequiredId
statusrequiredTrialSessionStatus
devicestring | null
orderrequiredarray of TrialRef
bracket_holdsboolean | null
notestring | null

The first line of a candidate's notes, as filed.

created_atrequiredstring (date-time)

RoundOverride

object

RoundOverride fields
FieldTypeDescription
rulesrequiredarray of CampaignRuleName

items 1–3 · unique items

Exactly the rules this round breaks.

reasonrequiredstring

length 10–1000

Why, in the person's words — recorded on the round and shown with the chip.

RoundDecisionAction

string

one of shortlist · iterate · stop · done

shortlist (session) — the checkpoints for a real-robot trial; iterate (key:train) — train the next round from step; stop (key:write) — end this lineage; done (session) — close the campaign.

RoundGateMetric

string

one of alive · alive_rate · tracking · pass · pass_rate · tracking_gap · tilt_max_deg · asym_max_deg · drift_m · recover_s

What a gate reads from the measured cells at a step. Per listed cell: alive (seeds upright, a count), alive_rate (upright / seeds), tracking (measured / commanded on axis, or every commanded axis), pass (1 when the hub's band rule PASSes the cell, else 0), and the posture metrics (the median over the cell's seeds): tilt_max_deg, asym_max_deg, drift_m, and — on a push cell (C3b) — recover_s, the seconds from the push until the base stayed within 3° of upright and under 5 cm/s to the end (a seed that never settled counts the whole window left after the push). Every listed cell must satisfy the comparison. Over the checkpoint: pass_rate (PASS cells / cells, of the listed cells or all), and tracking_gap — |ratio₁ − ratio₂| of exactly two listed cells (the founder's left–right turn gap).

CampaignRoundSpend

object

CampaignRoundSpend fields
FieldTypeDescription
nrequiredinteger
cost_usdrequirednumber

The round's run as billed (the ledger); 0 while it runs, and for an unpriced run.

pricedrequiredboolean

False for a worker run — the owner's own machine, never billed.

reserved_usdnumber

What a round still training may spend at most (its estimate), 0 once it has ended.

RoundChange

object

The ONE change this round makes: a summary a person reads, and the resolved-config keys it covers (a key covers itself and every path under it, so env.events.push_robot covers env.events.push_robot.params.velocity_range.x[0]). One conceptual change may span several keys.

RoundChange fields
FieldTypeDescription
summaryrequiredstring

length 1–300

keysrequiredarray of string

items 1–32

CampaignRuleName

string

one of one_variable · resume_from_pass · fail_ends_lineage · separates_from_control

The three rules the hub enforces on every round (the founder's own): one_variable — one declared change per round, diffed against what the parent checkpoint was trained on; resume_from_pass — a round resumes only from a checkpoint whose verdict is PASS, or from the campaign's declared root; fail_ends_lineage — no checkpoint of a FAIL, confounded or stopped round is ever a parent, nor (C4) a checkpoint whose real-robot trial a person stopped (setTrialVerdict {stop}). C3b adds a fourth, checked when a round is shortlisted rather than when it starts: separates_from_control — a candidate whose round's control (the checkpoint the round started from, measured in its own band scan) passes every locked gate the candidate passes cannot be shortlisted, because its gates cannot tell what it learned from what it began with; a person may override it with a reason (RoundDecisionCreate.override).

RoundHypothesis

object

What the round expects and how to read it if it is wrong. test, when given, is evaluated and shown like a gate but never counted: a checkpoint can pass while its round's hypothesis fails, and the page keeps the two apart.

RoundHypothesis fields
FieldTypeDescription
claimrequiredstring

length 1–300

readingstring | null

length ≤ 300

The locked reading, e.g. "if it still collapses, the DR is not the cause".

testRoundGate | null

RoundVariablesGroup

object

RoundVariablesGroup fields
FieldTypeDescription
idrequiredRunConfigGroupId
namerequiredstring
changedrequiredinteger

≥ 0

undeclaredrequiredinteger

≥ 0

changes_contractboolean

K3 — the group is part of the policy's IO contract (actions, observations, the contract block): a change here makes a policy a robot registered for the parent's contract will refuse.

RoundGateResult

object

RoundGateResult fields
FieldTypeDescription
gaterequiredRoundGate
verdictrequiredGateVerdictOrNotCounted
passedboolean | null

For a gate that is not counted, whether its comparison held.

valuenumber | null

The value compared (the worst listed cell for a per-cell metric).

measuredstring | null

The measurement as a person reads it, e.g. "+80 % / +87 %", "19 / 20 · 105 %".

RoundBand

object

The hub's 0.85–1.15 band rule on the same rollout — a measurement shown beside the verdict.

RoundBand fields
FieldTypeDescription
gates_passedrequiredinteger
gates_totalrequiredinteger
alive_ratenumber | null

RoundControlRole

string

one of parent · untrained

parent — the parent checkpoint a resumed round started from (the parent run's own checkpoints/step_<step>/); untrained — for a round from scratch, the step-0 checkpoint its own run published (the weights before training, or after the trainer's first update where that is what it saves, as rsl_rl's model_0.pt is).

RoundControlStatus

string

one of planned · measuring · measured · unavailable

planned — the run has not ended, so nothing is queued yet; measuring — its rollout is queued or running; measured — the locked gates were evaluated on it; unavailable — it cannot be measured (reason says why: the template published no step-0 checkpoint, the scan was skipped, its rollout failed, …).

TrialSessionStatus

string

one of open · needs_verdict · decided

open — trials still to run; needs_verdict — a candidate waits on a person; decided — every candidate has a verdict (or never ran).

TrialRef

object

One trial as a session strip or a campaign row prints it.

TrialRef fields
FieldTypeDescription
idrequiredId
indexrequiredinteger

≥ 1

rolerequiredTrialRole
labelrequiredstring

The checkpoint as a person names it — R3 · 800, laika-walk · 700.

stepinteger | null
model_repostring | null
statusrequiredTrialStatus
tilt_mean_degnumber | null
tilt_max_degnumber | null
verdictTrialVerdictAction | null

GateVerdictOrNotCounted

string

one of PASS · FAIL · unmeasured · not_counted

A gate's result at a step: PASS / FAIL, unmeasured (the cells or the metric are not in the measurement — never a pass), or not_counted (a gate added after the lock; its measured value is still shown).

TrialRole

string

one of candidate · control

candidate — a checkpoint on trial, which takes a person's verdict; control — the checkpoint the robot already runs (usually the round's parent), run first and last to bracket the candidates. A control is measured, never judged.

TrialStatus

string

one of unfiled · awaiting_approval · denied · approved · running · refused · expired · needs_verdict · measured · decided · withdrawn

Derived on every read from the consent request, the approval, the driver's events, the log and the verdict — never stored. unfiled (no consent request yet), awaiting_approval, denied, approved (issued, the device has not started), running, refused (the device refused it before starting), expired (the window passed unused), needs_verdict (a candidate that ran and has no verdict), measured (a control that ran), decided, withdrawn (not filed: its checkpoint failed the scan it was waiting on).

TrialVerdictAction

string

one of promote · iterate · stop

promote — this checkpoint becomes the campaign's policy on the robot; iterate — back to sim, the next round drafted from the notes; stop — this checkpoint's lineage ends, like a FAIL.