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

magus-queue

Merge approved changes through a speculative, partitioned merge queue

Synopsis

magus queue <describe|ls|plan|validate|apply> [flags]

Description

A speculative, partitioned merge queue. A queue run has three steps, each with the rights it needs and no more.

plan reads the changes carrying merge intent (a mergequeue.changes/v1 document on stdin or --changes, as ls prints it), checks each one's approval at its head, finds which changes are stacked on which, drops what conflicts with the base on its own, and splits the rest into partitions whose affected sets are disjoint. It writes a mergequeue.plan/v1 document.

validate runs the changes' code and needs read access only. Per partition it builds candidates base+A, base+A+B and so on onto each other, regenerates generated files on each, runs --gate on them, and writes a mergequeue.verdict/v1 per change to --verdicts the moment that change is decided.

apply holds the write credential and runs no change's code. It rebuilds each green change's candidate itself and merges it through the provider, with the change's own merge method, as soon as everything beneath it has merged. Its <source> is the directory validate wrote, or run:<run>, the artifacts of a validation run as the provider names it (github: <owner>/<name>/runs/<id>).

The checkout is the one at the global --root (default: the current directory), and every relative path resolves against it. The provider is a built-in name (github) or a Buzz script. Every verb prints JSONL events (mergequeue.event/v1) on stdout; ls and describe print their document instead. The global --dry-run makes apply report what would merge and call nothing on the provider.

queue describe options

--app app
`app` apply writes with, as the provider names it (github: a GitHub App's slug[:App ID], required with a --status-context)
--base branch
`branch` the queue merges into
--provider provider
`provider`: a built-in name (github) or a .buzz file
--remote remote (default: origin)
Name of the configured `remote` changes and the base are fetched from
--status-context string (default: merge-queue)
Commit status the queue posts, whose wiring is described; empty describes what the provider supports and reads no setup
--vcs backend (default: git)
Version control `backend` of the checkout at --root

queue ls options

--base branch
`branch` the queue merges into
--provider provider
`provider`: a built-in name (github) or a .buzz file
--remote remote (default: origin)
Name of the configured `remote` changes and the base are fetched from
--vcs backend (default: git)
Version control `backend` of the checkout at --root

queue plan options

--changes document (default: -)
The mergequeue.changes/v1 `document`, or - for stdin
--depth int (default: 3)
Candidates of one partition that validate at once
--facts command
`command` and its arguments, run with no shell and the fact asked for appended, answering what a change affects and which files are generated, for a build tool other than magus; without it the magus workspace at --root answers
--out file
`file` the mergequeue.plan/v1 document is written to
--parallel int
Changes admitted at once; 0 is one per CPU
--provider provider
`provider` approval at each head is checked with
--remote remote (default: origin)
Name of the configured `remote` changes and the base are fetched from
--target target (default: ci)
magus `target` the affected set is computed for; not with --facts
--vcs backend (default: git)
Version control `backend` of the checkout at --root

queue validate options

--facts command
`command` and its arguments, run with no shell and the fact asked for appended, answering what a change affects and which files are generated, for a build tool other than magus; without it the magus workspace at --root answers
--gate command
`command` and its arguments, run with no shell in each candidate's checkout with the change's affected projects appended; exit 0 is green
--only change
Validate this one `change`; the changes beneath it in its partition are merged under it but not gated
--parallel int
Candidates built or gated at once across every partition; 0 is one per CPU
--regenerate command
`command` and its arguments, run with no shell in a candidate with the change's affected projects appended and the generated files to rewrite listed on stdin
--remote remote (default: origin)
Name of the configured `remote` changes and the base are fetched from
--remote-cache-read
Let hooks read magus's remote cache from the GitHub Actions cache service through a loopback proxy that forwards lookups upstream with the runner's ACTIONS_RUNTIME_TOKEN and refuses every write; hooks get a stand-in token, cache.remote.trusted_keys, and remote writes off. Refused without the runner's credentials or a trusted key
--scratch-env NAME=DIR
`NAME=DIR` sets NAME to DIR in the candidate's scratch directory for every hook, so the cache it names is the candidate's own; repeatable
--stdin
Read the mergequeue.plan/v1 document from stdin; required
--target target (default: ci)
magus `target` the affected set is computed for; not with --facts
--vcs backend (default: git)
Version control `backend` of the checkout at --root
--verdicts directory
`directory` the plan and the verdicts are written to, one entry per change; apply reads it as its <source>

queue apply options

--app app
`app` whose credential the provider writes with, as the provider names it (github: a GitHub App's slug[:App ID], required). apply refuses to start when the base requires --status-context from another integration (MGS3019)
--base branch
`branch` the queue merges into; a plan naming another is refused (MGS3028), and a run: source must have run on it
--committer string
"Name <email>" committing each update commit, overriding the provider's committer; with neither, a change needing one waits and apply stops
--facts command
`command` and its arguments, run with no shell and the fact asked for appended, answering what a change affects and which files are generated, for a build tool other than magus; without it the magus workspace at --root answers
--interval duration (default: 10s)
How often <source> is read while following it
--once
Apply what <source> holds now and stop, rather than following it until it is complete
--provider provider
`provider`: a built-in name (github) or a .buzz file
--regenerate command
The base's own regeneration `command` and its arguments, run with no shell and the projects that regenerate them appended as arguments and the generated files to rewrite on stdin, only where the build tool proves the change touches none of its code; elsewhere apply checks the bundle validation left; no credential reaches it
--remote remote (default: origin)
Name of the configured `remote` changes and the base are fetched from
--reproduce-gate command
The `command` validate's --gate is given, shown on each kick-back validation decided so its author can run it again; apply never runs it, and never takes it from a verdict
--reproduce-regenerate command
The `command` validate's --regenerate is given, shown beside --reproduce-gate
--scratch-env NAME=DIR
`NAME=DIR` sets NAME to DIR in the rebuild's scratch directory for the regeneration, so the cache it names is that rebuild's own; repeatable
--status-context string (default: merge-queue)
Commit status the queue posts; branch protection requires it
--target target (default: ci)
magus `target` the affected set is computed for; not with --facts
--vcs backend (default: git)
Version control `backend` of the checkout at --root
--workflow definition
`definition` a run: source must have run, started by an event that runs the base's own copy of it (github: .github/workflows/queue.yaml); required with a run: source, whose uploads are otherwise refused (MGS3027)

Subcommands

describe
Ask the provider what it supports on a base and what wiring the queue up still takes; prints the steps to run, or a mergequeue.capabilities/v1 document with -o json
ls
Ask the provider for the changes carrying merge intent; prints a mergequeue.changes/v1 document
plan
Check approval, find stacks, drop what conflicts with the base, and partition by affected set
validate
Build and gate a candidate per change, writing each verdict the moment it is decided (read access only)
apply
Rebuild and merge the green verdicts <source> holds as they arrive (holds the write credential; runs no change's code)

Examples

Print the commands that wire the queue up

magus queue describe --provider github --base main

Print the commands that move it onto your own GitHub App

magus queue describe --provider github --base main --app acme-magus-queue

The same for a private app whose App ID GitHub hides

magus queue describe --provider github --base main --app acme-magus-queue:2034567

List what carries merge intent

magus queue ls --provider github --base main > changes.json

Plan it

magus queue plan --provider github --out plan.json < changes.json

Validate every candidate

magus queue validate --stdin --verdicts verdicts --gate 'magus run ci' < plan.json

Merge the green ones as they arrive

magus queue apply --provider github --base main verdicts

Merge from a validation run's artifacts

magus queue apply --provider github --base main --workflow .github/workflows/queue.yaml run:acme/widgets/runs/7

Plan with a provider of your own

magus queue plan --provider providers/gitlab.buzz --out plan.json < changes.json

See Also

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

generatedinternal/cli/registry.goclimagus queuemerge queuestacked changespull requestsci
Last updated (9bdea423)
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. See workspace.

Project

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

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. See targets.

Op

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

Spell

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

Ward

A coded diagnostic that inspects a resolved op and nudges or blocks an anti-pattern before it runs. See wards.

Buzz

The language magusfiles are written in (the .buzz engine). See engines.

Cache

The content-addressed store magus consults before running a target, so unchanged work is skipped. See cache.

Affected

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

Service

A long-running or shared process magus manages across runs, distinct from a one-shot target. See services.

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. See server.

Server

The background process a person starts with magus server start. It serves MCP, the console, background jobs and the warm knowledge graph, and adopts nested magus calls into one pool. See server.

CI

An ordinary magusfile-defined target you compose yourself with magus\needs - magus does not hardcode its stages. Magus.RunCI treats it specially only in that it strips the rw charm, it is the anchor magus affected ci keys off, and a selected scope with no project declaring it is a load error rather than a silent no-op. See targets.

Remote cache

A CI-only backend that shares content-addressed artifacts across runners: a cold machine replays a build another runner already did instead of rebuilding. Every remote artifact must be signed by a trusted key. See remote.

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. See knowledge.

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.

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 server, for its own maintenance. The store records; the agent guard is what reads those facts back when grading a write. See doctrine.

A job is not a run. magus run build web is a run, and no job exists for it. A job causes runs: its check executes as one, and a server job records the invocation of its last one. Jobs are listed with magus ls jobs and in the console's Jobs view; runs are listed in the Runs view.

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.

Conventions

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