magus v0.4.3 is out. See what's new
¶ View generated markdown
8 min read

magus-job

Fork a job, take it, return it with its result, and verify that result

Synopsis

magus job <fork|apply|exec|exit|wait|watch|run|rm|prune|pause|resume> [flags]

Description

Delegated work on the shell's own lifecycle. A JOB is the unit of work; a LEASE is the grant one holder has on it: its write and read paths, plus the one check it runs. A job is not a run: `magus run` executes a target with no job involved, while a job's check and the server's maintenance each cause runs.

Two channels write the job store. The client MCP tool (magus\job) is an agent's, this verb is a person's, and they reach the same store and the same rules. One author per JOB is the property that matters, and the store enforces it: a session holding a lease may record the base it landed on, shrink its own write paths, end its own job in fail or no_return, and fork a child of itself inside its own paths. Everything else, widening a boundary and verifying a job included, is refused by name.

Jobs are kept per repository rather than per checkout, so a session forking in one worktree and a holder working in another see the same set.

fork declares one job, from flags for the one-job case or from a JSON record on --stdin. It replaces the job it names rather than merging into it, which is the difference between a person declaring what a job IS and an agent advancing one field of a live one. Every path flag is repeatable or comma-separated, and an empty segment is refused rather than dropped. There is no --state: this declares a new job, and one nobody has taken is declared.

exec takes a job in this checkout. It records the base this tree actually landed on beside the checkpoint the job was handed, with the divergence between them as a fact rather than a refusal. The guard hook binds the caller when it lets exec through, keyed on the session and subagent its agent host names, so a subagent's exec never binds its parent; a host that names neither binds the checkout. A caller holding a job still declared or running is refused another; once its job has exited or ended, the next exec takes the next job.

exit returns a job with its result, FILED ONTO THE JOB so whoever waits on it reads the same record from any checkout. The run behind the result's output ref is resolved in the holder's own checkout and its record filed alongside, because an output store belongs to a cache dir and nobody else can reopen it. Do the work first, then file the result: it is a record of what happened, not a form to fill in while you are still deciding what to do. With no --stdin the job is abandoned and recorded no_return, which is not the same as returning it and failing.

wait verifies what comes back. It reads the filed result and verifies EVIDENCE, not claims: every changed path inside the declared write paths and outside the denied ones, a change set that is not empty on a job that writes, descendants the store carries, and every declared goal held: a recorded passing run for a check, the diff since the checkpoint and the knowledge graph for paths and symbols. Evidence must have been captured after the job was declared, so an old green run cannot satisfy new work. A target's own run policy bounds its execution; wait does not add a competing wall-clock timeout. There is no field for whether the holder thinks it passed. A job that verifies is recorded pass. Exit 1 is a status, naming every rule that failed; exit 2 is magus unable to answer, which is a result that would not decode, nothing filed and nothing piped in, or a job that would not write. Whether the work is GOOD stays the reading of whoever forked it.

run submits one of the server's own jobs, the housekeeping magus does for itself, and returns. It is a no-op when no server is running, so a VCS hook can call it unconditionally.

apply upserts jobs' specs from -f <file|->, the way kubectl apply reads a manifest: the record is the whole spec, and the job keeps its state, holder and registration, where a re-fork would hand a taken job out again. Only the orchestrator widens; a holder may apply only the release of its own paths.

rm removes one row that should never have been written. prune ENDS every job nobody is working, as exit would abandon it, and keeps each row as the record.

pause holds jobs' holders off the machine budget: their next magus run is refused until resume. A run already holding the budget finishes. A job's weight, in (0,1] on its record, leans its runs' retries ahead of other waiters; it is a lean, never a place in a queue.

Reading is elsewhere, on the verbs that read everywhere else: magus ls jobs lists them and magus describe job prints one job's terms.

job fork options

--brief-format string
The format a brief to this job's worker takes, markdown or buzz; unset, magus.yaml's agents.brief_format decides
--check <target> <project> [-- args]
The one check this job runs, as <target> <project> [-- args] (the `magus run` is implied)
--checkout string
Make a new checkout of this repository for the job at this directory, outside the workspace; the job owns it, and magus removes it once the job ends unless it holds work
--checkpoint magus vcs checkpoint -o name
The working state this job is handed, as magus vcs checkpoint -o name prints it
--criteria string
What this job is for and what done means, as prose; the machine-checkable half is --check, and the goals a --stdin record declares
--deny-paths string
A path this job may not write, carved out of its write paths; repeatable or comma-separated
--depends-on string
A job this one waits on; repeatable or comma-separated
--fix
Make every edit a problem's fix names without judgment (add a write path, a goal or the integrator's waiver), validating again until none is left, and list only the problems that remain
--model string
The model tier, or the model, the work was matched to; unset, the workspace's matrix or default chooses the tier
--parent string
The job this one is forked from
--read-only
A job that gathers evidence and writes nothing
--read-paths string
A path whose projects this job may read; repeatable or comma-separated (additive: the written paths are readable already)
--schema
Print the JSON schema a job must satisfy, and exit
--stdin
Read one job as JSON on stdin instead of taking it from flags
--timeout duration
Deny this job's writes once this long has passed since the fork (e.g. 45m, 2h); unset means no bound, unless magus.yaml sets jobs.default_timeout
--write-paths <file>#<declaration>
A path this job may write, or <file>#<declaration> to claim one declaration of a file (a path holding a literal # is spelled `./a#b.md` or `a\#b.md`); repeatable or comma-separated

job apply options

-f -
The records to apply: a file, or - for stdin; one JSON job, a JSON array, or one job per line
--fix
Make every edit a problem's fix names without judgment, as job fork --fix does, before applying the records

job exec options

--slots int (default: 1)
With --timeout: the machine budget slots the command takes while it runs
--timeout duration
Run the command after -- and stop its whole process group once this long has passed (e.g. 20m); exits 124 at the deadline

job exit options

--schema
Print the JSON schema a result must satisfy, and exit
--stdin
Read this job's result from stdin; without it the job is abandoned

job wait options

--evidence <goal>
Grade check goal <goal> against the run `<ref>` recorded in THIS checkout instead of the job's own; `check` names the job's check. The changed paths must read the same here as in the job's checkout; repeatable
--integration
Grade only the job's check goals against the runs the --stdin result names in THIS checkout, and record that beside its state
--schema
Print the JSON schema a result must satisfy, and exit
--stdin
Read the result from stdin instead of from the job, for one that was never filed

job rm options

--force
Remove a row that already ended, destroying the record of what happened

job prune options

--all
Also end a job a holder took and nobody touched within jobs.stale_after

Subcommands

fork
Declare one job, from flags or a JSON record on stdin
apply
Upsert jobs' specs from a file or stdin, keeping each job's state
exec
Take the lease on a job here, and record the base this checkout landed on
exit
Return a job with its result, or abandon it
wait
Verify the result a job was exited with
watch
Follow what a job's holder is doing, until interrupted
run
Submit one of the server's own jobs and return
rm
Remove one job from the plan
prune
End every job nobody is working
pause
Hold jobs' holders off the machine budget until resumed
resume
Lift the pause on jobs

Examples

Declare a job

magus job fork session-load/core --write-paths internal/sessions/sessions.go --check 'test internal/sessions'

Declare it from a record

magus job fork --stdin < job.json

Take it in this checkout

magus job exec session-load/core

Bound a long command

magus job exec --timeout 20m -- rg -l TODO ~/src

Return it with its result

magus job exit session-load/core --stdin < result.json

Verify what came back

magus job wait session-load/core

Print the result schema

magus job exit --schema

Submit a server job

magus job run sync-graph

Change a live job's spec, keeping its state

magus job apply -f job.json

Preview that change

magus job apply -f job.json --dry-run

Grade a job's checks in a merged tree

magus job wait session-load/core --integration --stdin < evidence.json

See which jobs a prune would end

magus job prune --dry-run

Hold a job's runs off the budget, then let them back

magus job pause session-load/core && magus job resume session-load/core

See Also

magus(1), magus-ls(1), magus-describe(1), magus-where(1), magus-run(1), magus-affected(1), magus-x(1), magus-clean(1), magus-shell(1), magus-query(1), magus-refs(1), magus-explain(1), magus-path(1), magus-graph(1), magus-diff(1), magus-vcs(1), magus-session(1), magus-notes(1), magus-queue(1), magus-watch(1), magus-events(1), magus-server(1), magus-broker(1), magus-mcp(1), magus-status(1), magus-buzz(1), magus-spell(1), magus-agent(1), magus-init(1), magus-doctor(1), magus-config(1), magus-completion(1), magus-man(1), magus-self(1), magus-version(1)

generatedinternal/commands/registry.goclimagus jobjobjobsleaseagentsdelegation
Last updated (61fd39a7)
Earlier changes on this page (7)

Full history ↗ · Blame source ↗

Glossary

Workspace

The magus root directory that owns a set of projects and shared config; the unit magus operates over. Workspace in full.

Project

A directory magus recognizes as a unit of work (it has a magusfile); the unit of caching, scheduling, and dependency tracking. Project in full.

Target

A named operation (build, test, ...) you invoke with magus run <target>; it may compose a spell's tool-native operations and depend on other targets. Target in full.

Op

A single tool-native command a target composes (long form: operation); the middle of the work hierarchy (Spell to Op to Target). Op in full.

Spell

A language/runtime adapter (e.g. go, md) that maps generic targets onto a toolchain's real commands. Spell in full.

Manifest

The file that declares what a package is: its name, dependencies, entry points and tool config (go.mod, package.json, pyproject.toml, Cargo.toml). How the workspace builds, tests and lints the package belongs in the magusfile, not in the manifest's scripts. Manifest in full.

Buzz

The language magusfiles are written in (the .buzz engine). Buzz in full.

Cache

The content-addressed store magus consults before running a target, so unchanged work is skipped. Cache in full.

Affected

The set of projects touched by a change; magus affected <target> runs a target only over them. Affected in full.

Broker

The per-user background process that holds this host's capacity: the machine budget every run claims slots from, and the shared services runs keep warm. A run starts it on demand; broker: off in magus.yaml runs without one. Broker in full.

CI

An ordinary target you compose yourself with ctx.needs; magus does not hardcode its stages. It is the anchor magus affected ci keys off, and ci strips the rw charm. CI in full.

Slot

One unit of the pool's capacity. A target acquires the slots it needs to run (most take one) and releases them when it finishes; the pool tracks capacity (total slots), running (acquired), and queued (blocked). Slot in full.

Knowledge graph

The queryable graph of a workspace's spells, targets, docs, and code relationships; query it with magus query/explain/path. Knowledge graph in full.

MAGUS.md

The committed routing index at a workspace root, regenerated from the knowledge graph: it lists every node and points at the exact query for a given question, so it is the entry point an agent reads first. MAGUS.md in full.

Agent

A model working through an agent host such as Claude Code, Codex, Cursor or OpenCode. magus treats an agent as one more caller of its CLI, MCP tools and console, held to the same checks as a person. Agent in full.

Tool

An action a model can call through its host: a name, a description, a typed input and a result. magus serves its tools over MCP, each a read of the workspace model or a run of the CLI it already has. Tool in full.

Session

An agent host's conversation, by the id the host delivers to its hooks. magus never mints one: a record with no session is unattributed, and the OS user it carries says whose account ran it. Session in full.

Job

The unit of delegated work, and one row of the job store: what an orchestrating agent handed out, with its goal, the checkpoint it was cut against, the paths it may write or must not touch, and the one check it runs. A job's holder is either a session, for work an orchestrator handed out, or the daemon, for its own maintenance. The store records; the agent guard is what reads those facts back when grading a write. Job in full.

Run

One target executing under one magus invocation, such as magus run test web or magus affected ci. A run keeps its captured output behind an output reference. Every magus run is a run whether or not any job asked for it; see Job for how the two relate. Run in full.

Lease

The grant a holder takes on a job: the write and read paths that job declared, enforced in the checkout that took it with magus job exec. A job is the piece of work; a lease is permission over it. Lease in full.

Conventions

This page uses none of the site's convention markers. The full set is on the conventions page.