Skip to content

No ordinary command builds; a missing or stale executable fails fast or answers through a release of the same generation, and only an explicit build builds

No ordinary command builds; a missing or stale executable fails fast or answers through a release of the same generation, and only an explicit build builds

majordomus://adr/adr-0224accepted launcherbuildenforcement

it references

  • put_in_force .ai/repo/ci/gates.yaml (file)
  • put_in_force adr-0172
  • supersedes adr-0172
  • put_in_force bin/majordomus-cli (implementation)
  • put_in_force lib/rust_bin.sh (implementation)
  • put_in_force every-capability-has-one-owner-and-the-cli-never-builds (intent)
  • put_in_force test/cases/3177_a_client_always_gets_a_server.sh (test)
  • put_in_force test/cases/3221_a_bare_session_start_joins_the_cluster.sh (test)

referenced by

Nothing in the layer names it. Backlinks are derived, so an empty list is an answer rather than an omission.

222. No ordinary command builds; a missing or stale executable fails fast or answers through a release of the same generation, and only an explicit build builds

Context

On 2026-10-22 a pre-push on a loaded machine sat forty minutes in one gate and then timed out at ninety, all of it queued behind the shared build lock, with the tree's executable already built: nine gates of .ai/repo/ci/gates.yaml run cargo run --manifest-path apps/majordomus-cli/Cargo.toml and ignore MAJORDOMUS_BIN. A critique of the same day counted at least eight entry paths that can start a cargo build or pass silently on a missing or stale executable: bin/majordomus handing words to bin/majordomus-cli, lib/plan.sh, every just recipe through the bridge, the git hooks (a stale executable is rebuilt there), bin/majordomus-mcp, test/lib.sh with a raw cargo build outside the disk floor and lock, the edit guard failing open, and those gates. ADR 0172 decided that a stale executable which can be rebuilt is rebuilt, and that the installed-release fallback serves mcp only; I3180 planned a background build on entering a checkout. The owner, the same day, after the architecture review recorded as intent every-capability-has-one-owner-and-the-cli-never-builds: "ADR 0172 is replaced, I3180 is cancelled".

Decision

  1. An ordinary command never starts a build. A missing or stale executable makes every command that does not declare a toolchain requirement either exit 12 naming the explicit build, or answer through a fallback (decision 2). Building is the explicit build command and the derive, nothing else; a gate, a hook, a recipe, a test harness and the MCP launcher call the tree's executable and never cargo run.
  2. A fallback is a release of the same generation. The installed release answers only when its build generation matches the tree (rule project.a-tool-that-cannot-match-the-tree-refuses); a version string is not a build. With a matching release every command may use it, not mcp alone, because it answers what the tree's own executable would.
  3. Every caller declares its outcome. Each caller class — hook gate, provider hook, mcp, entry, person — declares refuse, skip with a recorded line, or verified fallback for a missing or stale executable, and none passes silently.
  4. Entering a checkout never builds (rules entry-converges and envrc-is-an-adapter): I3180 is cancelled.
  5. Carried forward from ADR 0172, unchanged: a client always gets a server when one can be given; a bare session start is handed the repository's own first message (.ai/repo/prompts/session-start.md, share/shell/session-start.sh) with its opt-outs; and autonomy is bounded in that prompt, not assumed.

Consequences

  • A push stops compiling in its gates; a loaded machine queues one build per tree, not one per gate.
  • A contributor whose executable is stale is told the one command to run instead of waiting on a hidden build; a matching installed release keeps every client working.
  • I3957 carries the first slice: the launcher, lib/rust_bin.sh, test/lib.sh, the just bridge and the gates, proved by a case that counts cargo invocations across every path.

Where this comes from

canonical file
.ai/repo/adrs/0224-no-ordinary-command-builds.md
identity
adr-0224
also served as
MCP resource majordomus://adr/adr-0224 · majordomus entity show adr/adr-0224 · GET /api/v1/entity?uri=majordomus://adr/adr-0224
in the Cockpit
/cockpit/objects/adr/adr-0224

This page is generated from the file above by scripts/generate-site-data; editing the page changes nothing, editing the file changes every surface. The relations above are edges of docs/generated/graph.json, which the executable writes from the same index.

Searches the titles and descriptions of every page this site publishes.