magus v0.4.2 is out. See what's new
¶ View markdown source · ✎ Suggest an edit
4 min read

MGS3010: redundant gate deferred under load

A ci gate was not started. An identical-or-equivalent gate already passed for this branch on this machine, and starting another would queue it behind work the machine is already running - so magus refuses fast instead. A deferral is never a success: the command exits 75, and the refusal prints every input to its decision, so a reader can reconstruct and dispute it from the message alone:

[MGS3010] not running the ci gate for branch polish: it is redundant and this
  machine's build pool is saturated.
  green gate: run inv0193ab, branch polish, commit 2d15f62c, recorded
    2026-09-03T18:04:11Z (14m ago), fingerprint 4c1f22ab9e01
  delta since that gate, every file:
    docs/guides/setup.md: prose (matches "**/*.md" (built-in default))
    gen/knowledge-graph.json: generated (a declared output glob claims it)
    run.go: comment-only (only comments differ from the green gate's revision)
  machine pool: saturated: 8 of 8 slots held, 2 runs queued
  override: pass --no-redundancy-check to run it here anyway
  alternative: push; the pull request runs the identical check

This fires only when all three facts hold at once:

  • A green gate is on record for this branch. Every completed magus run ci and magus affected ci records its branch, commit, input fingerprint and verdict in the per-repository session store, which every worktree shares. The first gate on a branch always runs; so does any gate after a recorded failure - in both cases this feature says nothing at all.
  • The gate would re-verify what that one verified. Either the input fingerprint is identical (derived from the same per-step cache keys a real run mints - sources, tool versions, charms), or everything changed since the green gate's commit is low-risk: generated output magus owns (structural: declared output globs), prose (globs: markdown by default, configurable - see below), or comment-only edits (Go and Buzz through the lexers magus owns; other spelled languages through a declared comment/string syntax, string-aware and nesting-aware, with directive comments like //go:build or # type: always counting as code; a language with no declaration is always code, never comment-only). A merge commit in the range is never low-risk, however clean - a merge combines two verified histories into a tree neither gate saw, so it always re-gates.
  • The machine admission pool is saturated. The daemon that arbitrates the machine budget reports work queued or every slot held. On an idle machine the identical finding prints as an advisory - informative, never behavior-changing - and the gate runs anyway; with no daemon reachable there is no load signal and the check fails open the same way. The daemon is an accelerant, never a capability gate.

Exit 75 is EX_TEMPFAIL, the same convention as MGS3009: the refusal is about this machine's moment, not about the build. The refusal is also recorded in the session store as a deferred gate record pointing at the green gate it deferred to, so the decision stays interrogable after the fact.

Configuring the prose class

magus.project's gate_low_risk key declares the prose globs, following the same project-relative shape as review_required. magus ships **/*.md and **/*.markdown; any declaration replaces the defaults workspace-wide, and [] turns the prose class off. The per-path lines name the matching glob and whether it came from the defaults or a declaration, so each verdict reads straight back to the key that produced it. See workspace. The other two classes are deliberately not glob-configurable: generated stays structural and comment-only stays a mechanism, because a glob cannot assert either honestly.

Why

Parallel worktrees duplicate gates. Several agents iterating on one branch each run magus affected ci out of discipline, and on a loaded machine the duplicates queue behind each other verifying the same inputs - wall clock spent proving what the session store already proves. The record is per-repository and machine-wide precisely so one worktree's green gate is visible to its siblings.

Refusing only under load keeps the check honest: an idle machine loses nothing by re-verifying, so it merely says what it found and runs. And the named alternative is not "skip verification" but "verify where it is not redundant": the push triggers the pull request pipeline, which runs the identical check on shared runners.

Resolution

  1. Push. The pull request runs the same gate; that is the alternative the refusal exists to point at.

  2. Force the run. Pass --no-redundancy-check to magus run ci or magus affected ci to skip the check for this invocation.

  3. Let the machine drain. magus status names who holds the budget. Once the pool has room, the same command prints the finding as an advisory and runs.

  4. Dispute a classification. Every path line names the glob or mechanism that classified it. A glob doing the wrong work is yours to change: gate_low_risk in the declaring magusfile.

  5. Change something real. Any non-low-risk change in the delta makes the next gate run silently; the check never argues with a tree that differs meaningfully from the one it verified.

See also

  • MGS3009: the machine budget this check reads, and the exit-75 convention.
  • workspace: the gate_low_risk declaration.
  • Concurrency: the scopes magus coordinates on one machine.
  • Daemon and concurrency: the process that owns the budget, and why losing it fails open.
MGS3010cigateredundancyadmissiondaemonworktreesexit 75no-redundancy-checkgate_low_risk
Last updated (9920edf6)
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.

Magusfile

The magusfile.buzz that declares a project's targets (as export funs) and binds its spells. 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.

Charm

An execution modifier attached with : (lint:rw) that changes how a target runs, not which one; the built-in rw flips a check-only target to mutate in place, and ci always strips it. See charms.

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.

Daemon

The background magus host that owns shared state such as services and the warm knowledge graph. See daemon.

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.

Pool

The concurrency pool: the shared set of slots that caps how many targets run in parallel on one machine. Its capacity defaults to MAGUS_CONCURRENCY, then 4 on GitHub-hosted runners, then min(NumCPU, 8); magus status and the dashboard report it live. See daemon.

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). See daemon.

Concurrency

How many targets run at once. It is bounded by the pool's capacity and set with --concurrency, MAGUS_CONCURRENCY, or the concurrency config key. See daemon.

Queued

A target that wants a slot while the pool is full; it blocks first-in-first-out until a slot frees. The dashboard colors a sample with queued > 0 accordingly. See daemon.

Session

One magus process's recorded facts - the targets it finished, their outcomes, and the lease it acted as - kept in a repo-scoped store every worktree shares. magus session lists them; the store prunes itself by last-fact age.

Advisor

One read-only check from the advice suite: it reads the changeset through magus and writes one titled section of findings. The same advisors run as a pull request comment in CI and inside magus diff --impact locally.

Conventions

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