jobs
The jobs namespace — 10 functions.
globals/jobs/find
jobs.find(name: string) -> JobHandle?
Look up a registered job by name. Returns a JobHandle or nil for anonymous / unknown names. Single FFI crossing — returns the id directly, no registry snapshot.
Parameters
namestring— Job name supplied tojobs.register.
Returns JobHandle? — JobHandle or nil.
local job = jobs.find("animation_blend_main")
globals/jobs/inspect
jobs.inspect(target: JobHandle | string) -> JobInfo?
Return a snapshot row by job handle or by name without retrieving a full handle. Single FFI crossing — pulls only the matching row.
Parameters
targetJobHandle | string— JobHandle, or job name string.
Returns JobInfo? — Snapshot row or nil.
local info = jobs.inspect("animation_blend_main")
globals/jobs/list
jobs.list(phase: string?) -> { JobInfo }
List registered job summaries. Pass a phase name to filter to a single phase. Single FFI crossing — only the requested rows cross the bridge.
Parameters
phasestring(optional) — Optional phase filter — nil returns every job.
Returns { JobInfo } — Array of JobInfo rows.
local rows = jobs.list("main")
globals/jobs/register
jobs.register(descriptor: table) -> JobHandle?
Register a substrate job. Returns a JobHandle on success, nil on validation failure. Dispatches by executor.kind:\n - "kernel" / "stub" → standard __jobs.register (JSON-only descriptor).\n - "luau" → __jobs.register_luau(descriptor, executor.run) so the Luau function survives the JSON crossing as a stable registry ref. The dispatcher invokes the run closure once per frame; the closure captures any bindings/buffers it needs.\n - "compute" → the shader reference resolves to its registration key, and the job queues one dispatch per frame.\n\norigin is auto-filled with the VFS path of the calling script unless the descriptor already supplies one — surfaced under /zero/runtime/jobs/<phase>/<key>/origin.txt for agent traceability. Single FFI crossing — auto-origin runs Rust-side via lua_getinfo, no separate stack-inspection trip.
Parameters
descriptortable— Job declaration with theJobDescriptorshape —name?,phase,reads?,writes?,executor,ordering?,pure?,origin?,metadata?. Param is typed astablerather thanJobDescriptorbecause the LSP doesn't yet narrow string literals to their literal types in record fields, so aJobDescriptorannotation rejects the tagged-unionexecutordiscriminator on every call site (literalkind = "kernel"infers askind: string, doesn't subtypeKernelExecutor.kind: "kernel"). Runtime validation in__jobs.registerenforces the actual structure; see theJobDescriptortype alias above for the canonical shape.
Returns JobHandle? — JobHandle or nil.
local job = jobs.register({ phase = "main", executor = { kind = "kernel", kernel = "copy_buffer" }, reads = {{resource={kind="buffer",id=src.id},mode="r"}}, writes = {{resource={kind="buffer",id=dst.id},mode="w"}} })
local job = jobs.register({ phase = "main", executor = { kind = "luau", run = function() print("tick") end } })
local job = jobs.register({ phase = "main", executor = { kind = "compute", shader = asset.resolve("carve", "computeShader"), buffers = { "heights" }, workgroups = { 64 } } })
typed/builtin//modules/jobs/jobhandle_cancel
jobhandle_cancel(self: JobHandle) -> boolean
Cancel the job — drops one refcount, last drop unregisters and the dispatcher stops invoking it. Symmetric with vfs.remove("/runtime/jobs/<phase>/<id>").
Parameters
selfJobHandle— JobHandle returned byjobs.register.
Returns boolean — True if the substrate still tracked the job at call time.
job:cancel()
typed/builtin//modules/jobs/jobhandle_info
jobhandle_info(self: JobHandle) -> JobInfo?
Latest snapshot row for this job (id, name, phase, status, origin, metadata, reads, writes…). Single FFI crossing — pulls only this job's row, not the full registry.
Parameters
selfJobHandle— JobHandle returned byjobs.register.
Returns JobInfo? — Snapshot row or nil if the job is no longer tracked.
local info = job:info(); print(info.origin)
typed/builtin//modules/jobs/jobhandle_pause
jobhandle_pause(self: JobHandle) -> boolean
Pause the job — skipped on subsequent ticks but stays registered.
Parameters
selfJobHandle— JobHandle returned byjobs.register.
Returns boolean — True if the substrate still tracked the job.
local job = jobs.register({...}); job:pause()
typed/builtin//modules/jobs/jobhandle_resume
jobhandle_resume(self: JobHandle) -> boolean
Resume a paused or errored job (clears Errored → Pending).
Parameters
selfJobHandle— JobHandle returned byjobs.register.
Returns boolean — True if the substrate still tracked the job.
job:resume()
typed/builtin//modules/jobs/jobhandle_status
jobhandle_status(self: JobHandle) -> JobStatus?
Read the job's current scheduler status.
Parameters
selfJobHandle— JobHandle returned byjobs.register.
Returns JobStatus? — "pending" / "running" / "errored", or nil if the id is no longer tracked.
local s = job:status() -- "pending"
typed/builtin//modules/jobs/jobhandle_valid
jobhandle_valid(self: JobHandle) -> boolean
Whether the substrate still tracks this job (false after :cancel/:destroy).
Parameters
selfJobHandle— JobHandle returned byjobs.register.
Returns boolean — True if the underlying job is still registered.
if not job:valid() then return end