Replay candidates
A replay candidate is a work station's block as someone wants to try it,
proposed to be replayed on the station's past
tasks. It is never applied to the line. It is written through the resource
API, which spotlight replay propose
calls. It has no Terraform resource and is not part of an export.
| Kind | Endpoint | Terraform | Address |
|---|---|---|---|
replay-candidate | /api/resources/lines/{lineId}/stations/{stationKey}/replay-candidates | none | <team key>/<line key>/<station key>/<name> |
See Resource API for the operations, headers and errors every kind shares.
Example
{
"name": "Higher effort",
"station": {
"key": "implementation",
"name": "Implementation",
"kind": "work",
"harness": "claude-code",
"effort": "xhigh",
"prompt": "Implement the task.",
"check": "npm test",
"diffs": true,
"passesTo": ["code-review"]
}
}Endpoints
| Operation | Endpoint | Description |
|---|---|---|
| propose (create) | POST /api/resources/lines/{lineId}/stations/{stationKey}/replay-candidates | Needs Idempotency-Key. Returns 201. |
| read | GET /api/resources/replay-candidates/{id} | |
| withdraw (delete) | DELETE /api/resources/replay-candidates/{id} | Needs If-Match. Replays that ran the candidate keep their results. |
| import | GET /api/resources/workspaces/{workspaceId}/replay-candidates/import?address=<address> | |
| list | GET /api/resources/workspaces/{workspaceId}/replay-candidates | The proposed candidates of every team the caller may read. With ?station=<team key>/<line key>/<station key>, only that station's. |
There is no update. A candidate never changes; a changed config is a new candidate.
Proposing and withdrawing need plan; reading, importing and listing need
read. Either way, the caller must be able to read the station's team: a
person on the team or an owner or admin of the workspace, or a workspace token
of the workspace. See
Team outcomes. Each
proposal and withdrawal is recorded as a
configuration change
of the kind replay-candidate.
Fields
| Field | Type | Default | Description |
|---|---|---|---|
name | string | required | Tells the candidate from the station's other candidates. 1 to 100 characters, with no space at either end and no /. A name starting Live config, Planned change or With the answer, in any case, is refused: they name the snapshots Spotlight takes to replay as a baseline, the changes replay checks replay, and the replays with the answer Spotlight starts. Used once per station. |
station | object | required | The station block to replay under, in the shape of one entry of a line's stations. See Station fields. Its key must be the station's key. |
teamId | string | read-only | The station's team. |
lineId | string | read-only | The station's line. |
stationId | string | read-only | The station, as the Replays API names it. |
stationAddress | string | read-only | The station as <team key>/<line key>/<station key>. |
kind | string | read-only | proposed. live marks a snapshot of the station's config Spotlight takes to replay as a baseline; the list and import never return one. Candidates a search proposes, planned changes a replay check replays, and the configs replays with the answer replay are not this resource: reading them is answered 404. |
fingerprint | string | read-only | The config fingerprint a replay under the candidate runs with. |
changedFrom | object | read-only | fingerprint: the station's live config fingerprint when the candidate was proposed. changes: what the candidate changes from it, each { part, name, kind, was, now }, worded as in Config. Fixed at proposal. |
createdAt | string | read-only | When it was proposed, as an RFC 3339 time. |
part is one of prompt, harness, model, effort, profile, image,
repository, skill, tool, decisions, memories or judge, and kind
one of added, removed or changed. was and now are null where a value
is not shown, as for prompts, skills and rubrics.
Checks
The block is checked as the line would be with the station replaced: by every
rule of spotlight_line, against the line as
it is when the candidate is proposed. A problem is returned with 422 at the
path station.<field>, as in station.judge.rubric.
| Message | Path | Cause |
|---|---|---|
is a station block, as a line holds it | station | station is not an object. |
keeps the station's key, <key> | station.key | key names another station. |
names a harness a runner can start | station.harness | The block runs no harness Spotlight can start. |
Candidate name must be 1 to 100 characters. | name | name is empty or too long. |
Candidate name cannot start or end with a space. | name | name starts or ends with a space. |
Candidate name cannot contain /. | name | name holds /. |
Candidate name cannot start with the reserved prefix "Live config". | name | name starts with Live config. |
Candidate name cannot start with the reserved prefix "Planned change". | name | name starts with Planned change. |
Candidate name cannot start with the reserved prefix "With the answer". | name | name starts with With the answer. |
Errors
| Status | Type | Cause |
|---|---|---|
404 | not-found | No such line, station or candidate the caller may see. |
409 | already-exists | The station already has a candidate by that name. Import it instead. |
409 | in-use | Withdrawing a candidate while a replay of it is under way: Candidate <id> is being replayed. Please stop its replays first. Withdrawing a live snapshot: Candidate <id> is the baseline of the live config. Deleting its replay set removes it. Withdrawing a candidate a search or a replay check made: Candidate <id> belongs to a search or a check. Spotlight removes it together with that search or check. |
409 | moved-on | If-Match names a version that is no longer current. |
422 | invalid | A field is wrong. An import address not in its form: Candidate address must be team, line and station keys, then name, as in core/delivery/build/Shorter prompt. A list station not in its form: Station address must be team, line and station keys, as in core/delivery/build. Received: <value>. |