Repo: motir-core. One PR. Carved out of MOTIR-2611 by its 2026-08-10 re-plan — it was that card's AC 5, and it is the one deliverable of that card the correction leaves entirely intact.
origin/main @ 816eb501Three checks already guard the sandbox release. None of them reads what is INSIDE the published artifact on a stranger's behalf:
| lane / job | what it asks | credential | blind to |
|---|---|---|---|
sandbox-images.yml → sandbox-published (:255) | pull every digest, run motir --version | docker/login-action (:261) | asks as the PUBLISHER; --version is a number, not a command set |
sandbox-images.yml → sandbox-public (:320) | can a stranger pull it at all | none — by construction | says nothing about CONTENT |
sandbox-staleness.yml (MOTIR-2131) | is main far ahead of the newest cli-v* | none (reads git) | never pulls anything |
So the question "does the command the docs tell a reader to run exist in the image they are told to pull?" is asked by nothing. That is not hypothetical: MOTIR-2131 shipped a :claude whose CLI predated motir login while /docs/sandbox promised it, and it stayed green for five days.
lib/apiDocs/sandbox.ts annotates each step with the commands that step tells the reader to run — cliCommands: ['login'] (:267), ['link'] (:289), ['doctor'] (:310). That array is the expected set; deriving the assertion from it means a future step that names a new command is covered the day it is written, with no second list to keep in sync.
packages/cli/sandbox/smoke/assert-commands.mjs — same shape as its two siblings (assert-public.mjs, assert-current.mjs): zero dependencies, runnable from any shell, a header comment stating why it exists. Given an image ref, it resolves the manifest, runs the image's motir help, and asserts every command in the expected set appears as a top-level command. Take the expected set from SANDBOX_GUIDE's cliCommands so the docs remain the single source.sandbox-commands job to .github/workflows/sandbox-images.yml, gated on publish like sandbox-public is, that runs it against the just-published tags. It holds NO credential: no docker/login-action, no packages: permission, no Authorization header — the anonymity is the point, and assert-public.mjs's header explains why at length. Model the job on sandbox-public, not on sandbox-published.assert-public.mjs does: the probe must be shown able to FAIL (a known-absent command name) before its pass means anything.packages/cli/test/sandboxCommands.test.ts, mirroring sandboxCurrent.test.ts) and extend the workflow-wiring guard (packages/cli/test/sandboxCi.test.ts) to assert the new job carries no login step and no packages: scope — the guard is what stops a later edit from quietly re-crediting it.packages/cli/sandbox/smoke/assert-commands.mjs exists, exits 0 when the image's motir help lists every expected command, non-zero when one is missing, and sends no Authorization header on any request.lib/apiDocs/sandbox.ts's cliCommands, not restated — adding a cliCommands entry to a guide step changes what the job asserts, proven by a test.sandbox-commands job exists in .github/workflows/sandbox-images.yml, runs only when publish is true, and contains no docker/login-action step and no packages: permission — asserted by packages/cli/test/sandboxCi.test.ts, not only by reading the YAML.packages/cli/test/sandboxCommands.test.ts covers: all-present, one-missing, control-broken, and malformed motir help output.ghcr.io/moooon-b-v/motir-sandbox:claude with its output quoted — it must PASS today (0.2.0 has login), which is what makes it a regression guard rather than a bug report..github/workflows/sandbox-images.yml — sandbox-published (:255, logged in) and sandbox-public (:320, credential-free); the latter is the model.packages/cli/sandbox/smoke/assert-public.mjs — the header explains the publisher-vs-consumer distinction and the control-first discipline; copy both.packages/cli/sandbox/smoke/assert-current.mjs + .github/workflows/sandbox-staleness.yml — the script-plus-thin-caller arrangement to mirror.packages/cli/test/sandboxCurrent.test.ts, packages/cli/test/sandboxCi.test.ts — the unit-test and wiring-guard patterns.lib/apiDocs/sandbox.ts — cliCommands at :267 / :289 / :310.Cutting any tag — that is MOTIR-2611's sibling release card. Changing the guide's prose — that is MOTIR-2611 itself.