API reference

Tasks

A job's tasks: one per manifest task and shard, with their lease, result and artifacts.

GET/v1/ci/jobs/{id}/tasks/{task}

Get a task

One task with its lease and artifacts; ?warnings=1 pages its warning list.

Permission: ci:jobs.read

Parameters

NameTypeRequiredDescription
idpathstringRequiredThe job's ID.
taskpathstringRequiredThe task's name, as the manifest names it (test, apps/web:test).
cursorquerystringOptional
limitquerystringOptional
warningsquerystringOptional

Response200 OK

approvalobject or null
: the task's approval gate; a gated task stays queued until it is approved
approval.approversarray of strings
user:<id> and role:<name>; empty means any person holding ci:approvals.approve
approval.commentstring or null
approval.decided_atstring (date-time) or null
approval.decided_bystring or null
approval.expires_atstring (date-time)Required
approval.reachedbooleanRequired
the task's dependencies have succeeded: an approval starts it at once
approval.sod_exceptionboolean
the requester decided their own gate under the policy's approval_self: record
approval.statestringRequired
One of pending, approved, rejected, expired
artifact_countintegerRequired
blocked_bystring or null
on a skipped task, the dependency whose end skipped it (build, build[1/2])
cachestringRequired
how a task met the task cache: served without a run, looked up and run, recorded after the run, or never keyed (cache: false, cache: { results: false } or --no-cache)One of hit, miss, write, none
cache_hitboolean
the task did not run: its key matched a recorded success; cached_from names it
cache_notestring or null
why the task was neither answered from the cache nor recorded in it, when the cell knows a reason beyond "these inputs never passed": the manifest keeps it out, or the run changed a tracked path. ciresk ci explain-miss compares a miss with the last recorded run of the task
cached_failureobject or null
the task did not run: its key failed cleanly in the named run and never passed, so it ended with that run's exit code, tests and first failure; --no-cache runs it
cached_failure.job_idstringRequired
uuidv7 rendered as job_<32 hex>
cached_failure.task_idstringRequired
uuidv7 rendered as tsk_<32 hex>
cached_fromobject or null
the run a cache hit stands on: the job and task whose success was recorded under the key, so a hit names where its verdict, log, junit and artifacts come from
cached_from.job_idstringRequired
uuidv7 rendered as job_<32 hex>
cached_from.task_idstringRequired
uuidv7 rendered as tsk_<32 hex>
cached_targetsobject or null
a task split into per-target units: how many targets reused a recorded verdict
cached_targets.hitintegerRequired
cached_targets.ofintegerRequired
cold_startstring or null
how warm the member was when it took the lease: warm was online before the job was submitted, started came online after it (the factory started it for the queue), first_after_boot was online before but this is its first lease since its bootOne of warm, started, first_after_boot
cost_unitsinteger or null
duration_msinteger or null
exit_codeinteger or null
expected_msinteger or null
how long the planner expects the task to run, from the repository's history or the kind default; shorter tasks lease first within a job
finished_atstring (date-time) or null
first_failureobject or null
the first failing line the worker saw, present from the moment it was seen
first_failure.atstring (date-time)Required
the worker's clock when the line was seen
first_failure.excerptarray of stringsRequired
first_failure.kindstringRequired
what the first failing line of a task's log was: a compiler diagnostic, a test runner's failed case, a panic or uncaught exception, or nothing matched before a non-zero exitOne of compiler, test, panic, exit
first_failure.linestringRequired
the matched line, trimmed
first_failure.locationstring or null
path:line[:col] when the line or its excerpt names one
first_failure.shardstring or null
k/N when the task is a shard
first_failure.taskstringRequired
the namespaced task name
first_failure.toolstringRequired
the detector rule that matched: rustc, nextest, tsc, pytest, shell for an exit,...
fit_atstring (date-time) or null
flaky_inputsarray of strings
the targets (or the task's name for its whole key) whose identical inputs both passed and failed on record: reported, never quarantined
has_junitbooleanRequired
labelsmap of any
what the queue matches a worker on: os and arch only when the submit or the manifest set them, toolchains, workspace_warm, and the manifest's own labels
leased_atstring (date-time) or null
log_bytesintegerRequired
matrixmap of string
: the matrix cell's values, axis to value, so a client groups a task's cells; empty for a task without a matrix
namestringRequired
no_eligible_workerstring or null
why a queued task matches no online worker, counted per mismatch (os, arch, trust); absent once a worker could take it
prepared_atstring (date-time) or null
queued_atstring (date-time) or null
the phase marks of the current attempt (Neon item 4, Task::timeline): queued at submission; fit_at when an eligible member first existed for it; leased_at; prepared_at when the worker had the workspace ready; cold_start how warm the member was at the lease
ready_atstring (date-time) or null
when the task became leasable: its submission for a root task, the moment its last dependency succeeded for a dependant
refusalsarray of objects
the members that handed the task back for a reason of their own, oldest first
refusals[].atstring (date-time)Required
refusals[].reasonstringRequired
the worker's infra_error.code
refusals[].workerstringRequired
the member's registered name (worker-6)
refusals[].worker_idstringRequired
uuidv7 rendered as wrk_<32 hex>
requeued_atstring (date-time) or null
when a lease of it was last given back and it queued again: its next lease's wait starts here
shardstring or null
k/N
slotsinteger or null
the worker slots the task's lease weighs, ceil(resources.memory / memory_per_slot) on the worker that took it; absent until leased
started_atstring (date-time) or null
statestringRequired
One of queued, leased, running, succeeded, failed, cancelled, timed_out, infra_error, skipped
terminationstring or null
why the task stopped short of its own exit, or why it went back to the queue: oom, timeout, cancelled, worker_shutdown, lease_lost, or a host infra code; absent while nothing ended it. on a queued, leased or running task it names the previous attempt's end
warningsobject or null
the warnings the worker collected from the task's log, bounded; present once the task reported
warnings.by_kindarray of objects
warnings.by_kind[].countintegerRequired
warnings.by_kind[].kindstringRequired
warnings.firstarray of objects
at most 20, in the order they were seen
warnings.first[].filestring or null
warnings.first[].kindstringRequired
warnings.first[].lineinteger or null
warnings.first[].lintstring or null
warnings.first[].messagestringRequired
the first line of the warning, trimmed, at most 512 bytes
warnings.totalintegerRequired
every occurrence the collector saw, repeats included
warnings.uniqueintegerRequired
distinct (kind, file, lint) the collector kept, at most 200 per task
worker_idstring or null
uuidv7 rendered as wrk_<32 hex>
artifactsarray of objects
artifacts[].digeststringRequired
sha-256 digest as sha256:<64 hex>
artifacts[].expires_atstring (date-time)Required
artifacts[].media_typestringRequired
artifacts[].namestringRequired
artifacts[].size_bytesintegerRequired
artifacts[].taskstringRequired
artifacts[].urlstringRequired
presigned
attemptintegerRequired
infra_errorobject or null
infra_error.codestringRequired
infra_error.messagestringRequired
leasestring or null
uuidv7 rendered as lease_<32 hex>
warnings_pageobject or null
one page of the task's full warning list, only when asked ?warnings=1
warnings_page.next_cursorstring or null
warnings_page.totalintegerRequired
warnings_page.uniqueintegerRequired
warnings_page.warningsarray of objectsRequired
warnings_page.warnings[].filestring or null
warnings_page.warnings[].kindstringRequired
warnings_page.warnings[].lineinteger or null
warnings_page.warnings[].lintstring or null
warnings_page.warnings[].messagestringRequired
the first line of the warning, trimmed, at most 512 bytes
curl "$CIRESK_API/v1/ci/jobs/job_0109badfc220cd056b2c0e862ac73d40/tasks/test" \
  -H "Authorization: Bearer $CIRESK_KEY"
POST/v1/ci/jobs/{id}/tasks/{task}/first-failure

Report a task's first failure

The first failing line of a task, from its worker, ahead of the log.

Permission: ci:workers.report

Parameters

NameTypeRequiredDescription
idpathstringRequiredThe job's ID.
taskpathstringRequiredThe task's name, as the manifest names it (test, apps/web:test).

Request body

atstring (date-time)Required
excerptarray of stringsRequired
at most 40 lines around line
kindstringRequired
what the first failing line of a task's log was: a compiler diagnostic, a test runner's failed case, a panic or uncaught exception, or nothing matched before a non-zero exitOne of compiler, test, panic, exit
lease_idstringRequired
uuidv7 rendered as lease_<32 hex>
linestringRequired
locationstring or null
toolstringRequired

Response201 Created

recordedbooleanRequired
false when the task already had one: a repeat after a lost answer changes nothing
curl -X POST "$CIRESK_API/v1/ci/jobs/job_0109badfc220cd056b2c0e862ac73d40/tasks/test/first-failure" \
  -H "Authorization: Bearer $CIRESK_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "at": "2026-10-20T14:04:12Z",
    "excerpt": [
      "acme/platform"
    ],
    "kind": "compiler",
    "lease_id": "lease_01778d67b48ee630f44b3f03ab6254a8",
    "line": "test manifest::parses_nested_manifests ... FAILED",
    "location": "acme/platform",
    "tool": "acme/platform"
  }'
POST/v1/ci/jobs/{id}/tasks/{task}/partials

Report a shard's passed tests

The tests a running shard of an archive task passed, from its worker.

Permission: ci:workers.report

Parameters

NameTypeRequiredDescription
idpathstringRequiredThe job's ID.
taskpathstringRequiredThe task's name, as the manifest names it (test, apps/web:test).

Request body

lease_idstringRequired
uuidv7 rendered as lease_<32 hex>
passedarray of objectsRequired
passed[].binary_idstringRequired
nextest's binary id: ciresk-ci-core, ciresk-kepler-api::integration, xtask::bin/xtask
passed[].signaturestring or null
the standard base64 ed25519 signature of the worker's claim over these passes under the crate's test key (CacheClaim with Claimed::passes): the api records passes only under a claim that verifies, and answers them only while it does; absent from older workers, whose passes are not recorded
passed[].testsarray of stringsRequired
producerobject or null
the worker build the claims name, which ci.cache.revoke refuses by release or parser
producer.parserstringRequired
producer.releasestringRequired

Response201 Created

recordedintegerRequired
the tests recorded; a binary whose crate the plan does not test records nothing
curl -X POST "$CIRESK_API/v1/ci/jobs/job_0109badfc220cd056b2c0e862ac73d40/tasks/test/partials" \
  -H "Authorization: Bearer $CIRESK_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "lease_id": "lease_01778d67b48ee630f44b3f03ab6254a8",
    "passed": [
      {
        "binary_id": "ciresk-ci-core",
        "signature": "CacheClaim",
        "tests": [
          "manifest::parses_nested_manifests"
        ]
      }
    ],
    "producer": {
      "parser": "acme/platform",
      "release": "acme/platform"
    }
  }'
POST/v1/ci/jobs/{id}/tasks/{task}/report

Report a task's result

Permission: ci:workers.report

Parameters

NameTypeRequiredDescription
idpathstringRequiredThe job's ID.
taskpathstringRequiredThe task's name, as the manifest names it (test, apps/web:test).

Request body

artifactsarray of objects
artifacts[].digeststringRequired
sha-256 digest as sha256:<64 hex>
artifacts[].media_typestringRequired
artifacts[].namestringRequired
artifacts[].sizeintegerRequired
cacheobjectRequired
cache.auditedboolean
the task-level key hit and the audit ran the task anyway
cache.flakyboolean
the task's green stands on a flaky pass (CIR-722): a test of this run passed only on a retry, or the task-level hit it reports was recorded so; a split task names its units in units.flaky too
cache.fromobject or null
on a hit, the run the lookup named: the api copies its junit, warnings and artifacts onto this task and charges the hit rate
cache.from.job_idstringRequired
uuidv7 rendered as job_<32 hex>
cache.from.task_idstringRequired
uuidv7 rendered as tsk_<32 hex>
cache.holesobject or null
what the run's key-hole detectors found; absent from older workers and from a run no detector looked at
cache.holes.detectorsarray of stringsRequired
cache.holes.keysarray of objects
cache.holes.keys[].keystringRequired
sha-256 digest as sha256:<64 hex>
cache.holes.keys[].pathsarray of stringsRequired
repository-relative, sorted, at most [KeyHole::MAX_PATHS]
cache.holes.keys[].sourcestringRequired
dep_info (rustc's dep-info files: no verdict is recorded under the key) or trace (the audit's tracer: the verdict stands, the key's audit rate rises)
cache.holes.keys[].targetstring or null
the unit's target; None for the task-level key
cache.holes.keys[].totalintegerRequired
every path found, past the cap included
cache.keystring or null
sha-256 digest as sha256:<64 hex>
cache.namespacestring or null
cache.outcomestringRequired
how a task met the task cache: served without a run, looked up and run, recorded after the run, or never keyed (cache: false, cache: { results: false } or --no-cache)One of hit, miss, write, none
cache.producerobject or null
the worker build whose code decided what this report says about its keys, written on every row the report earns; absent from older workers
cache.producer.parserstringRequired
cache.producer.releasestringRequired
cache.publicobject or null
what the task took from the worker's public registry cache; absent from older workers and from a worker whose cache is off
cache.public.bytesintegerRequired
cache.public.hitsintegerRequired
cache.public.missesintegerRequired
cache.signaturesarray of objects
the worker's signed verdict claim for each key the run passed: the api records a verdict row only under a key named here whose claim verifies; empty from older workers
cache.signatures[].keystringRequired
sha-256 digest as sha256:<64 hex>
cache.signatures[].signaturestringRequired
cache.unitsobject or null
a task split into per-target units; absent from older workers and from a task that is one unit
cache.units.accountobject or null
a failed run's account of the units that ran: which passed and which failed, when the worker could tell for every one of them; absent otherwise and from older workers, and the api then records no unit of a failed run
cache.units.account.failedarray of stringsRequired
cache.units.account.passedarray of stringsRequired
cache.units.account.sourcestringRequired
what the account was read from: nextest (the junit and the run's Starting line) or units_file (the command's own CIRESK_UNITS_REPORT)
cache.units.auditarray of strings
cache.units.flakyarray of strings
the targets whose green stands on a flaky pass (CIR-722): a unit that ran and had a test pass only on nextest's retry (junit <flakyFailure>), or a hit served from a verdict recorded so. the api flags their verdict rows, observes them as flips and names them in the task's flaky_inputs
cache.units.hitarray of strings
cache.units.runarray of objects
cache.units.run[].keystringRequired
sha-256 digest as sha256:<64 hex>
cache.units.run[].targetstringRequired
cost_unitsintegerRequired
the api recomputes from workers.vcpus; a differing figure is logged
duration_msintegerRequired
ended_atstring (date-time)Required
exit_codeinteger or null
infra_errorobject or null
infra_error.codestringRequired
infra_error.messagestringRequired
junit_digeststring or null
sha-256 digest as sha256:<64 hex>
lease_idstringRequired
uuidv7 rendered as lease_<32 hex>
logobjectRequired
log.chunksintegerRequired
log.failed_rangesarray of objects
log.failed_ranges[].endintegerRequired
log.failed_ranges[].labelstring or null
log.failed_ranges[].startintegerRequired
log.total_bytesintegerRequired
nextobject or null
the poll this report stands for: after the report commits the api leases for this worker what fits and answers it in ReportResponse::leases; absent from an older worker
next.boot_to_online_msinteger or null
the worker's boot-to-online time, recorded on the lease for the cold start analysis
next.disk_free_bytesintegerRequired
next.first_lease_after_bootboolean
no lease since boot (Neon item 4): the lease is first_after_boot unless the member came online after the job
next.freeobject or null
see HeartbeatRequest::free; a zero in cpus or memory answers 204 at once
next.free.cpusintegerRequired
next.free.disk_bytesintegerRequired
next.free.memory_bytesintegerRequired
next.free.tmp_bytesintegerRequired
next.max_leasesinteger or null
how many leases one answer may carry, the worker's free slots; absent from an older worker: one
next.process_endedarray of strings
the phase beat process_ended: the leases this worker holds whose process exited and whose report has not landed; the api frees their slot, cpus and memory before it leases. absent from an older worker
next.slots_freeintegerRequired
next.wait_secsintegerRequired
next.warmarray of objects
next.warm[].base_digeststring or null
next.warm[].repo_idstringRequired
uuidv7 rendered as repo_<32 hex>
nextestobject or null
: the plan of a build row, or a shard's account; absent for every other task and from older workers
nextest.auditarray of strings
nextest.planstring
sha-256 digest as sha256:<64 hex>
nextest.servedarray of strings
nextest.unitsarray of objects
nextest.units[].build_keystringRequired
sha-256 digest as sha256:<64 hex>
nextest.units[].pieceobject or null
the crate's binaries as this run built them: a piece manifest the report names as an artefact, which the api records as an outputs row with the target under build_key; absent when a recorded piece was reused
nextest.units[].piece.bytesintegerRequired
the packed size of the piece's chunks, what its cache entry accounts under the quota
nextest.units[].piece.digeststringRequired
sha-256 digest as sha256:<64 hex>
nextest.units[].targetstringRequired
nextest.units[].test_keystringRequired
sha-256 digest as sha256:<64 hex>
nextest.rolestringRequired
One of shard
nextest.completeboolean
nextest.failedarray of strings
nextest.keysarray of strings
the test keys of the plan the shard ran; the report's signatures carry a verdict claim for each, under the shard's own task, so the shard that merges the group can record every crate's verdict
observed_inputsarray of objects
the files the task read, when the lease asked for trace_inputs and a tracer ran; sorted, deduplicated, declared outputs excluded; empty from older workers
observed_inputs[].digeststringRequired
sha-256 digest as sha256:<64 hex>
observed_inputs[].pathstringRequired
outcomestringRequired
One of succeeded, failed, timed_out, cancelled, infra_error
outputs_content_digeststring or null
sha-256 of the outputs tar before compression: what a dependant's key takes, so a compressor change keeps it; outputs_digest names the stored file. absent from older workers
outputs_digeststring or null
sha-256 digest as sha256:<64 hex>
prepared_atstring (date-time) or null
when the workspace was ready, the worker's clock; absent from older workers and from a task that failed before it
signalinteger or null
started_atstring (date-time)Required
terminationstring or null
why the task did not run to its own exit, when the worker knows: oom (the kernel killed a process of the task's cgroup), timeout, cancelled, worker_shutdown; absent from older workers and from a task that ended by itself
timings_digeststring or null
sha-256 digest as sha256:<64 hex>
toolchains_resolvedmap of string
tracerstring or null
the tracer and its format version, fanotify/1 or strace/1; part of the key
usageobject or null
the cgroup's measurement of the run; absent from older workers and from a plain launcher
usage.cpu_secondsnumber or null
usage.memoryobject or null
the cgroup's memory counters at the last reading: what tells a task stalled at its memory.high from a slow one; absent from older workers and from a plain launcher
usage.memory.frozen_msinteger or null
how long the member's freezer held the task under host memory pressure; the report's duration_ms leaves it out
usage.memory.high_bytesinteger or null
usage.memory.high_eventsinteger or null
memory.events high: how often the task went over memory.high and was throttled
usage.memory.max_eventsinteger or null
memory.events max: how often it hit memory.max
usage.memory.oom_killsinteger or null
usage.memory.pressure_full_avg10number or null
usage.memory.pressure_full_total_usinteger or null
usage.memory.pressure_some_avg10number or null
psi: the percent of the last 10 s some, or every, running process of the task waited on memory
usage.memory.pressure_some_total_usinteger or null
psi: the microseconds some, or every, running process waited on memory since the task began
usage.peak_anon_bytesinteger or null
the largest memory.stat anon the worker sampled: what the task needed. memory.peak counts the page cache too, which fills a cgroup to its memory.high whatever the task needs (eu1, 2026-10-25: a one-crate test-rust peaked at 21.6 GiB under a 24 GiB ask), so asks are learnt from this; absent from older workers
usage.peak_memory_bytesinteger or null
warningsobject or null
what the warnings collector kept: the unique list, at most 200, and the count of every occurrence; absent from older workers and from a task with none
warnings.totalintegerRequired
warnings.warningsarray of objectsRequired
warnings.warnings[].filestring or null
warnings.warnings[].kindstringRequired
warnings.warnings[].lineinteger or null
warnings.warnings[].lintstring or null
warnings.warnings[].messagestringRequired
the first line of the warning, trimmed, at most 512 bytes
workspaceobject or null
workspace.base_digeststring or null
workspace.idstring or null
uuidv7 rendered as ws_<32 hex>
workspace.slotinteger or null
the warm slot the task ran in, so the slot reuse of sticky routing is measurable from task rows; absent from older workers
workspace.statestringRequired
One of ready, in_use, dirty, evicting, gone

Response201 Created

job_statestringRequired
One of queued, leased, running, succeeded, failed, cancelled, timed_out, infra_error
leasesarray of objects
the leases ReportRequest::next found for this worker; absent when it asked for none, from a repeated report and from an older api
leases[].jobobjectRequired
leases[].job.actorstringRequired
leases[].job.base_digeststringRequired
leases[].job.base_refstringRequired
leases[].job.diffobject or null
a content-addressed blob the receiver fetches by presigned url
leases[].job.diff.digeststringRequired
sha-256 digest as sha256:<64 hex>
leases[].job.diff.downloadobjectRequired
a presigned get
leases[].job.diff.sizeintegerRequired
leases[].job.graphobject or null
the cell holds no graph for this root and the manifest has a task with this strategy: record one after the run, once per job
leases[].job.graph.dirstring
where the tool runs, repository-relative, "" for the root
leases[].job.graph.rootstringRequired
the root digest of a working tree: sha-256 of the root directory manifest
leases[].job.graph.strategystringRequired
One of cargo, pnpm, go, turbo, nx, files, none
leases[].job.graphsarray of objects
every graph the cell lacks for this root, one request per strategy the manifest declares (cargo, pnpm, go); graph carries the first of them for a worker from before this field
leases[].job.graphs[].dirstring
where the tool runs, repository-relative, "" for the root
leases[].job.graphs[].rootstringRequired
the root digest of a working tree: sha-256 of the root directory manifest
leases[].job.graphs[].strategystringRequired
One of cargo, pnpm, go, turbo, nx, files, none
leases[].job.idstringRequired
uuidv7 rendered as job_<32 hex>
leases[].job.kindstringRequired
check, test, build, lint or a manifest task id
leases[].job.manifest_digeststringRequired
sha-256 digest as sha256:<64 hex>
leases[].job.manifest_pathstring or null
the governing manifest's repository-relative path; absent means <cwd>/.ciresk/ci.yaml
leases[].job.org_idstring or null
tenants.org_id of tenant, the organisation dev names its sessions by: the worker records it on the warm root, so a dev session only ever pins or indexes its own org's generations; absent from an older api, and a root without it is never handed to a session
leases[].job.repoobjectRequired
leases[].job.repo.default_branchstring or null
the registration's default branch (ci.repos.create): a lease whose base_ref names it is what an overlay member's trunk follows; absent from an older api
leases[].job.repo.idstringRequired
uuidv7 rendered as repo_<32 hex>
leases[].job.repo.slugstringRequired
leases[].job.repo.urlstring or null
leases[].job.seed_packobject or null
the repository's seed pack, offered only to a job with a tree and no view; absent when the cell has none and from an older api
leases[].job.seed_pack.bytesintegerRequired
leases[].job.seed_pack.downloadobjectRequired
a presigned get
leases[].job.seed_pack.entriesintegerRequired
leases[].job.seed_pack.rootstringRequired
the tree the pack was built from; its root manifest is the pack's last entry, so a cas that holds the root was seeded already
leases[].job.sessionstring or null
leases[].job.targetsarray of stringsRequired
leases[].job.tenantstring or null
the owner of the tree's blobs, the partition of the worker's local cas
leases[].job.toolchainsmap of stringRequired
leases[].job.treeobject or null
the tree to materialise; diff stays until every worker reads tree
leases[].job.tree.bytesintegerRequired
leases[].job.tree.entriesintegerRequired
leases[].job.tree.rootstringRequired
the root digest of a working tree: sha-256 of the root directory manifest
leases[].job.truststringRequired
tiers, with no order on purpose (amendment 2026-10-27): trusted_ci is protected-branch automation and the cache writer every tier reads, trusted_interactive a person's own work, and neither is "below" the other, so every rule over tiers names the tiers it meansOne of untrusted, trusted_ci, trusted_interactive
leases[].job.viewobject or null
the requester's path view when it hides a prefix: the task runs in a fresh namespace on a tree of the readable paths only; absent for every other job
leases[].job.view.digeststringRequired
ViewSpec::digest: the entries only, so every key that carries it also carries the tenant
leases[].job.view.entriesarray of objectsRequired
leases[].job.view.policy_versionintegerRequired
leases[].job.workspaceobjectRequired
leases[].job.workspace.keeparray of strings
leases[].job.workspace.kindstringRequired
One of warm, ephemeral
leases[].job.workspace.prewarmboolean
the manifest's workspace.prewarm: an idle worker may refresh the repo's trunk
leases[].job.workspace.sparsearray of strings
leases[].leaseobjectRequired
leases[].lease.cold_startstring or null
how warm this member was for the queue (Neon item 4); absent from an older control planeOne of warm, started, first_after_boot
leases[].lease.expected_msinteger or null
the task's expected run: on a spot notice a lease whose remainder fits is finished, not handed back; absent from an older control plane
leases[].lease.expires_atstring (date-time)Required
leases[].lease.fencingintegerRequired
equals tasks.attempt; a report with an older fence is 409 lease_not_held
leases[].lease.heartbeat_secsintegerRequired
leases[].lease.idstringRequired
uuidv7 rendered as lease_<32 hex>
leases[].lease.warm_wait_msinteger or null
the task's warm wait: 0 means a warm slot pays nothing, so the task never waits for a restore. absent without both p50s and from an older control plane, which waits as before
leases[].lease.weightinteger
how many of the worker's slots this lease holds: ceil(resources.memory / memory_per_slot), at least one; an older control plane sends none, which is one
leases[].taskobjectRequired
run arrives with targets_arg already substituted
leases[].task.artifactsarray of strings
leases[].task.attemptintegerRequired
leases[].task.cacheobjectRequired
the namespaces this task reads and the one it may write, with the hmac write token
leases[].task.cache.bypassstring or null
why the worker computes the key but skips the lookup: no_cache for the job's --no-cache, results_off for the task's cache: { results: false }; absent means look up
leases[].task.cache.enabledbooleanRequired
leases[].task.cache.readarray of stringsRequired
leases[].task.cache.submit_missedstring or null
the submit key the api looked up when the task became ready and found no recorded success under: the worker reads no early key and asks once after the materialise. absent from an older api and whenever the api did not look up or found a row, which means as before
leases[].task.cache.writestring or null
leases[].task.cache.write_tokenstring or null
leases[].task.cwdstringRequired
leases[].task.depends_onarray of objects
leases[].task.depends_on[].content_digeststring or null
sha-256 of the outputs tar before compression: what the task's key takes for this dependency, and what the restore checks; absent from an older api and for a dependency recorded before it, where the key takes outputs_digest
leases[].task.depends_on[].downloadobject or null
a presigned get
leases[].task.depends_on[].namestringRequired
leases[].task.depends_on[].outputs_digeststring or null
sha-256 digest as sha256:<64 hex>
leases[].task.depends_on[].task_idstringRequired
uuidv7 rendered as tsk_<32 hex>
leases[].task.egress_strictboolean
decision 10: the manifest's egress: strict; the worker runs the task strict when this or the tenant's policy says so. absent from older control planes, which means the tenant's mode alone
leases[].task.envmap of stringRequired
leases[].task.global_inputsarray of strings
the manifest's globals.inputs: in every task's key whether or not the task declares inputs, so a lockfile change never hits a stale verdict; absent from older control planes, which means none
leases[].task.idstringRequired
uuidv7 rendered as tsk_<32 hex>
leases[].task.id_tokenobject or null
: the task's id token; absent when it asks for none, its job is untrusted, or from older apis
leases[].task.id_token.audiencestringRequired
leases[].task.id_token.expires_atstring (date-time)Required
leases[].task.id_token.tokenstringRequired
the signed jwt the task hands a relying party
leases[].task.id_token_refusedstring or null
: why the token the task asks for was refused; the worker fails the task before it runs
leases[].task.inputsarray of stringsRequired
leases[].task.knobsobject
what the derived tool knobs come from when the api trimmed the grant's memory below the manifest's from this run's history: the untrimmed request, so a trim moves the scope's caps and the fit, never a tool's parallelism or heap. absent when the grant is untrimmed and from older control planes: the knobs follow it
leases[].task.knobs.cpusinteger or null
whole cpus, CPUQuota of the scope and the -j every tool is handed
leases[].task.knobs.diskinteger or null
space the task writes to its workspace (a build directory); fitted against the data volume
leases[].task.knobs.memoryinteger or null
MemoryMax of the scope
leases[].task.knobs.tmpinteger or null
scratch space the task needs under TMPDIR; the worker refuses the run when the data volume has less than this free
leases[].task.logobject or null
the log token path of; absent from older control planes, which means the worker token
leases[].task.log.directboolean
: the worker puts sealed segments into the store itself (ci.logs.segment_url, then ci.logs.segment_commit) and sends no log bytes to the api; absent from an older control plane, which means every chunk through ci.logs.append
leases[].task.log.max_bytesintegerRequired
leases[].task.log.tokenstringRequired
leases[].task.namestringRequired
leases[].task.nextestobject or null
: the row is one half of a task that builds once and tests on shards; absent for every other task and from older control planes
leases[].task.nextest.rolestringRequired
which half of an archive task a row isOne of archive, shard
leases[].task.nextest.taskstringRequired
leases[].task.outputsarray of stringsRequired
leases[].task.pass_envarray of stringsRequired
leases[].task.pass_env_refusedarray of objects
the pass_env names whose secret scope this job is outside of: never in pass_env, and the worker fails the task naming each one instead of running it without them. absent from older control planes, which means none
leases[].task.pass_env_refused[].namestringRequired
leases[].task.pass_env_refused[].reasonstringRequired
leases[].task.prioritiesobject or null
the tests to start first, for a task with a junit report the cell has results of (CIR-722); absent from older control planes and for every other task
leases[].task.priorities.firstarray of objects
failed or flaky in a recent run and not passed since, most recent first
leases[].task.priorities.slowarray of objects
the slowest seen, slowest first
leases[].task.reportobjectRequired
leases[].task.report.junitstring or null
leases[].task.report.timingsboolean
leases[].task.resourcesobject
the grant: the manifest's resources with what it left unsaid filled from the task's history or the kind defaults; the scope's caps and the derived tool knobs come from it. absent from older control planes, which means the worker's limits
leases[].task.resources.cpusinteger or null
whole cpus, CPUQuota of the scope and the -j every tool is handed
leases[].task.resources.diskinteger or null
space the task writes to its workspace (a build directory); fitted against the data volume
leases[].task.resources.memoryinteger or null
MemoryMax of the scope
leases[].task.resources.tmpinteger or null
scratch space the task needs under TMPDIR; the worker refuses the run when the data volume has less than this free
leases[].task.runstringRequired
leases[].task.servicesmap of object
: the services the task runs beside it, by name, started before it in its own network namespace; leased only to a member labelled services: podman, absent for every other task and from older control planes
leases[].task.shardobject or null
a 1-based shard of a sharded task; rendered as k/N where the wire asks for a string
leases[].task.shard.countintegerRequired
leases[].task.shard.indexintegerRequired
leases[].task.timeout_secsintegerRequired
leases[].task.toolchainsmap of string or null
: a matrix cell's toolchains when an axis pins one, replacing the job's toolchains for this task; absent for every other task and from older control planes
leases[].task.trace_inputsboolean
: the worker traces the task's file reads and reports them as observed_inputs; absent from older control planes, which means off
remaining_tasksintegerRequired
task_statestringRequired
One of queued, leased, running, succeeded, failed, cancelled, timed_out, infra_error, skipped
curl -X POST "$CIRESK_API/v1/ci/jobs/job_0109badfc220cd056b2c0e862ac73d40/tasks/test/report" \
  -H "Authorization: Bearer $CIRESK_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "artifacts": [
      {
        "digest": "sha256:c21fa32a40d82233c44e76e6ae776b4d403ac1a564ca26de95a14c6bb47eaf49",
        "media_type": "application/zstd",
        "name": "target/dist/platform-api.tar.zst",
        "size": 18432000
      }
    ],
    "cache": {
      "audited": true,
      "flaky": true,
      "from": {
        "job_id": "job_0109badfc220cd056b2c0e862ac73d40",
        "task_id": "tsk_011ec0cc99550d0e90bc9fed5781decd"
      },
      "holes": {
        "detectors": [
          "acme/platform"
        ],
        "keys": [
          {
            "key": "sha256:11e0184e1acaf0c0f4c3a5e7be84998835bca8fed12b2d226b82a64811f0bd21",
            "paths": [
              ".ciresk/ci.yaml"
            ],
            "source": "tenant",
            "target": "platform-api",
            "total": 1
          }
        ]
      },
      "key": "sha256:11e0184e1acaf0c0f4c3a5e7be84998835bca8fed12b2d226b82a64811f0bd21",
      "namespace": "acme/platform",
      "outcome": "hit",
      "producer": {
        "parser": "acme/platform",
        "release": "acme/platform"
      },
      "public": {
        "bytes": 18432000,
        "hits": 2,
        "misses": 1
      },
      "signatures": [
        {
          "key": "sha256:11e0184e1acaf0c0f4c3a5e7be84998835bca8fed12b2d226b82a64811f0bd21",
          "signature": "acme/platform"
        }
      ],
      "units": {
        "account": {
          "failed": [
            "acme/platform"
          ],
          "passed": [
            "acme/platform"
          ],
          "source": "tenant"
        },
        "audit": [
          "acme/platform"
        ],
        "flaky": [
          "acme/platform"
        ],
        "hit": [
          "acme/platform"
        ],
        "run": [
          {
            "key": "sha256:11e0184e1acaf0c0f4c3a5e7be84998835bca8fed12b2d226b82a64811f0bd21",
            "target": "platform-api"
          }
        ]
      }
    },
    "cost_units": 1296,
    "duration_ms": 83000,
    "ended_at": "2026-10-20T14:12:41Z",
    "exit_code": 0,
    "infra_error": null,
    "junit_digest": "sha256:3a4023b488227ad5836b17135ab100254dba3d78ac557d2ff5f6fad1d131b1a9",
    "lease_id": "lease_01778d67b48ee630f44b3f03ab6254a8",
    "log": {
      "chunks": 1,
      "failed_ranges": [
        {
          "end": 1,
          "label": "linux",
          "start": 1
        }
      ],
      "total_bytes": 18432000
    },
    "next": {
      "boot_to_online_ms": 83000,
      "disk_free_bytes": 18432000,
      "first_lease_after_boot": true,
      "free": {
        "cpus": 1,
        "disk_bytes": 18432000,
        "memory_bytes": 68719476736,
        "tmp_bytes": 18432000
      },
      "max_leases": 1,
      "process_ended": [
        "lease_01d50b6f005647a6f46cd8e6ccc4a47a"
      ],
      "slots_free": 1,
      "wait_secs": 300,
      "warm": [
        {
          "base_digest": "feef45d804737fdf7a297e27e443d914551629de",
          "repo_id": "repo_0129354d7b6b4146ad16c315d960365b"
        }
      ]
    },
    "nextest": {
      "audit": [
        "acme/platform"
      ],
      "plan": "sha256:cc297ca49b911f870d7248af6418404d1405442c9c5606c92f3afaddf54c5f7e",
      "served": [
        "acme/platform"
      ],
      "units": [
        {
          "build_key": "sha256:f83f356cc2d6be112610d11a740763a25591d8ecfb25fcfd31feb9d471110b96",
          "piece": {
            "bytes": 18432000,
            "digest": "sha256:c21fa32a40d82233c44e76e6ae776b4d403ac1a564ca26de95a14c6bb47eaf49"
          },
          "target": "platform-api",
          "test_key": "sha256:557e7166fb6de8fbb6f4dd67eb058ff75b0961bd090d0da76be1a376fbbe72af"
        }
      ],
      "role": "archive"
    },
    "observed_inputs": [
      {
        "digest": "sha256:c21fa32a40d82233c44e76e6ae776b4d403ac1a564ca26de95a14c6bb47eaf49",
        "path": ".ciresk/ci.yaml"
      }
    ],
    "outcome": "succeeded",
    "outputs_content_digest": "sha256:768e5e03075620e8f68c621b8e19b0bb62dcf536a2e9e351439f581b4c282514",
    "outputs_digest": "sha256:7cf9d095df466528c49ea6cab229fb433ce465de3fd7407f998773542f070110",
    "prepared_at": "2026-10-20T14:04:12Z",
    "signal": 1,
    "started_at": "2026-10-20T14:04:19Z",
    "termination": "oom",
    "timings_digest": "sha256:2e117fc44cf3311c46b44aae4d21fbff16dd8f293c634912f5e2f731fdd8508c",
    "toolchains_resolved": {
      "rust": "acme/platform"
    },
    "tracer": "fanotify/1",
    "usage": {
      "cpu_seconds": 1.5,
      "memory": {
        "frozen_ms": 83000,
        "high_bytes": 18432000,
        "high_events": 1,
        "max_events": 1,
        "oom_kills": 1,
        "pressure_full_avg10": 1.5,
        "pressure_full_total_us": 1,
        "pressure_some_avg10": 1.5,
        "pressure_some_total_us": 1
      },
      "peak_anon_bytes": 18432000,
      "peak_memory_bytes": 18432000
    },
    "warnings": {
      "total": 1,
      "warnings": [
        {
          "file": "crates/core/src/manifest.rs",
          "kind": "check",
          "line": 212,
          "lint": "acme/platform",
          "message": "assertion failed: nested manifests merge root first"
        }
      ]
    },
    "workspace": {
      "base_digest": "feef45d804737fdf7a297e27e443d914551629de",
      "id": "ws_012011c5add7f80ffb87fb5416d433f9",
      "slot": 1,
      "state": "ready"
    }
  }'