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

The Go proverbs, beyond Go

magus is written in Go, and the Go proverbs are the shortest statement I know of how I want code written. Most of them are not about Go. They hold for the Buzz in a magusfile, the TypeScript in the console, and the shell in a hook template, so this page reads each one against the whole tree.

  • Clear is better than clever. The rule under every other one; it has its own page.
  • The bigger the interface, the weaker the abstraction. A swappable part is a small interface built only where a second implementation exists (WithVCSDriver, WithCacheBackend). The same holds for a spell's op, a CLI verb and an MCP tool: a wide one promises less about each call.
  • Make the zero value useful. A caller that passes no option to magus.Open gets the ordinary workspace, and each option changes one thing. The default is still said out loud where it matters (No silent defaults).
  • Errors are values. Don't just check errors, handle them gracefully. An error carries what happened and what to do next. In TypeScript the console returns errors as values too, and its only throw is unreachable(x: never).
  • Don't panic. A panic is for a broken invariant, never for input a caller could have sent.
  • Reflection is never clear. A type Buzz needs is mirrored by a generator at build time, never reflected at run time, so the cost and the shape are both visible in the tree.
  • Cgo is not Go; syscall must always be guarded with build tags. A platform fast path lives in its own file behind a build tag, beside the portable version it must agree with.
  • With the unsafe package there are no guarantees. Reached for only with a benchmark and an // optimization: comment beside it.
  • Gofmt's style is no one's favorite, yet gofmt is everyone's favorite. Every language here has one formatter and nobody relitigates it: gofmt, dprint, Biome.
  • Don't communicate by sharing memory; share memory by communicating. Concurrency is not parallelism. Jobs share a file by a declared claim, not by racing on it (ADR 0010).
  • Documentation is for users. A doc comment states the contract a caller needs without the source; the comment budget inside a function body is close to zero.
  • A little copying is better than a little dependency. It has its own page.

Enforced by

  • gofmt, dprint and Biome run as format targets, and the drift gate fails an unformatted file.
  • The benchbeside analyzer holds // optimization: comments to a benchmark.
  • gochecknoinits fails a new init().
  • The rest live in review today. A linter for the interface size (interfacebloat), and an import rule that keeps reflect and unsafe to an allowlist, are candidates listed in Where this is strained.

Good

The SDK swaps a part through one small interface and one option:

ws, err := magus.Open(ctx, root, magus.WithVCSDriver(driver))

Bad

type Store interface {
    Get(key string) ([]byte, error)
    Put(key string, value []byte) error
    List(prefix string) ([]string, error)
    Watch(prefix string) (<-chan Event, error)
    Compact() error
    Stats() Stats
    Close() error
}

Seven methods for a caller that needs one. Every new implementation has to fake six it never uses, and the interface no longer says what any single caller depends on.

See also

designprinciplecodego
Last updated (2df714e8)
Glossary

Workspace

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

Magusfile

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

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.

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.

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. Concurrency 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.

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.

Conventions

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