MotirBuilding in public
MOTIR · moooon
onMotir
You’re viewing a public project. Anyone can view it — no account needed. Sign in to submit, upvote, or comment on requests.View-only — you can’t edit work items
MOTIR-2611

The sandbox guide never tells the reader to `docker pull` — `docker run` reuses a stale `:claude`, so anyone who followed it before 2026-08-05 is still on a CLI with no `motir login` while step 4 tells them to run it

Done
Description

Repo: motir-core. One PR. Re-scoped 2026-08-10 by THE REPLAN ACTION. The original diagnosis on this card was false and has been replaced — see What the original card claimed, and what is actually true below. Its two salvageable deliverables were carved out: MOTIR-2612 (the credential-free content check, this card's old AC 5) and MOTIR-2613 (cutting cli-v0.2.1, now release hygiene rather than a fix).

The symptom this card still owns

A reader following /docs/sandbox types the step-4 command and gets:

node@…:/workspace$ motir login
Error: Unknown command "login".
Hint: Run `motir help` to see the available commands and topics.

That is real and reproducible. It is not caused by the published image lagging.

The actual mechanism (measured 2026-08-10)

The guide never tells anyone to pull. lib/apiDocs/sandbox.ts step 2 (start-the-container, rendersRunCommand: true) renders only docker run -it --name motir-sandbox … (the builder at :85–:92). Step 3's dev-container alternative pins "image": "${SANDBOX_IMAGE}:claude" in .devcontainer/devcontainer.json (:239). Step 1's prose even says "There is no build step — you pull" (:156) — but no rendered command anywhere in the guide is a docker pull.

docker run does not refresh a tag it already has locally. :claude is a MOVING tag: sandbox-images.yml publishes each profile as both a moving :<profile> and an immutable :<profile>-<version>. So the moving tag only ever reaches a reader who explicitly pulls it. VS Code's Dev Containers extension reuses a locally-present image the same way.

And exactly one published version produces that error. Installed from npm and run:

@motir/climotir -vtop-level login in motir help
0.1.0 (cli-v0.1.0, 2026-07-30)0.1.0NO
0.1.1 (cli-v0.1.1, 2026-08-05)0.1.1yes
0.2.0 (cli-v0.2.0, 2026-08-08)0.2.0yes

So a reader who ran the guide between 2026-07-30 and 2026-08-05 holds the cli-v0.1.0-era :claude permanently, and every later docker run — and every docker start -ai motir-sandbox, which the guide explicitly recommends (:208) — keeps serving it. /docs/sandbox has promised motir login that entire time.

What the original card claimed, and what is actually true

the card saidmeasured on origin/main @ 816eb501
"cli-v0.2.0's tree had no login"False. git show cli-v0.2.0:packages/cli/src/program.tsregister(program, 'login') at :95, logout at :114; commandCatalog.tspath: 'login' at :146. The very lines the card cited as main-only.
"52 commits ahead, 20 touching packages/cli"53 total, 4 touching packages/cli; git diff cli-v0.2.0 origin/main -- packages/cli/src/program.ts is 4 lines, both copy edits.
the published image cannot have loginFalse. :claude and :claude-0.2.0 are ONE index digest sha256:44d9022…, built 2026-08-08T21:43:35Z (amd64) / 22:02:39Z (arm64) by release run 31280497216 (success). Extracting /tmp/motir-cli.tgz from BOTH arch layers, installing it and running it gives 0.2.0 and lists login FIRST under SETUP COMMANDS. The anonymous token round trip succeeds, so it is public too.
motir -v0.2.0 and no loginImpossible from any published artifact — see the version table. The two readings in the report came from different containers.

Do this

  1. Add a rendered docker pull ghcr.io/moooon-b-v/motir-sandbox:<profile> to step 2, ahead of the docker run, from the same AGENT_PROFILES source that already fills the run command — so the pull and the run can never name different tags.
  2. Say, in step 2, that :claude MOVES and that docker run / docker start will not refresh it — a reader returning to an existing container needs docker pull and a fresh docker run with a new --name (or docker rm first), because the guide's own no---rm advice is what makes the stale container persist.
  3. Give the dev-container sub-step the same treatment: the devcontainer.json block, or the prose beside it, must tell the reader how to get a newer image (Dev Containers reuses a local one).
  4. Offer the immutable :<profile>-<version> tag as the reproducible alternative, and say which to choose — that pairing is what packages/cli/sandbox/README.md's published-images table exists for.
  5. Update en and zh catalogs for any new copy (the catalog-parity gate), and extend the docs-page tests that already cover step rendering.

Acceptance criteria

  1. /docs/sandbox step 2 renders a docker pull command whose image reference is derived from the same profile source as the docker run, proven by a test that changes the profile and sees both change.
  2. The page states that the profile tag moves and that docker run / docker start -ai will not fetch a newer image — in prose a reader meets before the run command, not in a footnote after it.
  3. The dev-container sub-step tells the reader how to obtain a newer image rather than silently reusing a local one.
  4. The immutable :<profile>-<version> form is documented with a stated reason to prefer it (reproducibility) over the moving tag.
  5. Every new copy string exists in both en and zh catalogs; the i18n parity check passes.
  6. The docs-page test suite covers the new command block and the new prose, and pnpm test passes for the changed files.
  7. The PR body's "How to test" walks the reader path: open /docs/sandbox, read step 2, confirm the pull command names the same tag as the run command for at least two different profiles.

Context refs

  • lib/apiDocs/sandbox.tsSANDBOX_IMAGE (:41), the run-command builder (:85–:92), step 2 start-the-container (:196), the "no build step — you pull" prose (:156), the dev-container block (:231–:260), step 4's cliCommands: ['login'] (:267).
  • app/(public)/docs/sandbox/page.tsxrendersRunCommand (:133) and sandboxRunCaption.
  • packages/cli/sandbox/README.md — the published-images table carrying the immutable per-version tags.
  • .github/workflows/sandbox-images.yml — the moving-:<profile> + immutable-:<profile>-<version> publishing scheme (header, :19–:22).

Out of scope

  • Cutting any tagMOTIR-2613. This card's fix works against the image already published.
  • The credential-free post-publish content checkMOTIR-2612 (this card's former AC 5).
  • The dev-container step's own cold-start defects (the palette it never says how to open, the file a GUI file manager refuses to create) — MOTIR-2608. This card touches that sub-step only to add the image-refresh instruction; whoever lands second rebases onto the first.
  • Step 4's prose needs no edit: its motir login claim is true of the currently published image, verified above.