Skip to content

all: switch wallfacer to the unified sandbox-agents image#6

Merged
changkun merged 1 commit intomainfrom
unified-sandbox
Apr 15, 2026
Merged

all: switch wallfacer to the unified sandbox-agents image#6
changkun merged 1 commit intomainfrom
unified-sandbox

Conversation

@changkun
Copy link
Copy Markdown
Owner

Summary

Cuts wallfacer over to the unified sandbox-agents image (latere-ai/images PR #2, released as v0.0.6+) and deletes the per-agent image-rewrite paths. The Claude vs. Codex sandbox type still matters at runtime — it just no longer maps to two distinct images.

Required: ship the latere-ai/images sandbox-agents release first. Until that GHCR image is published, make pull-images and the on-startup auto-pull will fail.

Behaviour changes

  • The runner injects WALLFACER_AGENT={claude,codex} into every sub-agent container so the unified entrypoint launches the right CLI.
  • All /home/claude/... and /home/codex/... mount targets become /home/agent/..., including the claude-config named volume, the codex auth bind-mount, and the dependency-cache volumes (npm, pip, cargo, go-build).
  • The codex auth mount now bind-mounts only ~/.codex/auth.json (read-only) instead of the whole ~/.codex/ directory. Codex 0.120+ writes config.toml at startup, so the in-container directory must remain writable; mounting only auth.json keeps host state untouched. (This is the same fix shipped in latere-ai/images PR [Fixed] Test (Codex) fails behind Clash/local proxy on macOS + Podman #2 for the standalone sandbox-codex image.)
  • wallfacer doctor reports a single sandbox image instead of two and no longer probes CODEX_SANDBOX_IMAGE separately.
  • GetImageStatus, PullImage, DeleteImage operate on the single image. The API still accepts a sandbox field for backward compatibility but ignores it.

Code cuts

Deleted as dead with the unified image:

  • cli.codexImageFromClaude
  • cli.resolveSandboxImageForExec
  • runner.sandboxImageForSandbox
  • runner.entrypointForSandbox
  • handler.testCodexImage
  • handler.fallbackCodexSandboxImage
  • The test families asserting their behaviour (TestCodexImageFromClaude, TestResolveSandboxImageForExec_*, TestSandboxImageForTest_CodexResolution, TestBuildBaseContainerSpecClaudeVsCodexImageDiffers rewritten to assert WALLFACER_AGENT injection instead of image divergence).

The sandbox.Type enum (Claude, Codex) is preserved unchanged — only image-name rewriting goes away. Per-activity sandbox routing (WALLFACER_SANDBOX_IMPLEMENTATION etc.) keeps its semantics; it now flows into WALLFACER_AGENT instead of choosing an image.

Build & docs

  • Default image: ghcr.io/latere-ai/sandbox-agents:latest.
  • Makefile: IMAGE, GHCR_IMAGE switched to sandbox-agents; CODEX_IMAGE, GHCR_CODEX_IMAGE deleted; pull-images pulls one image.
  • CLAUDE.md, docs/guide/getting-started.md, docs/guide/configuration.md, docs/internals/development.md, docs/internals/workspaces-and-config.md, docs/internals/api-and-transport.md, docs/internals/git-worktrees.md all document the unified image and the WALLFACER_AGENT dispatch contract.

Verification

  • go test ./... — 3714 tests pass across 46 packages.
  • make lint — clean (golangci-lint + Biome).
  • Local hand-test against the locally built sandbox-agents:test image earlier in this session confirmed Codex dispatch via WALLFACER_AGENT=codex returns a valid Claude-Code JSON envelope, and Claude dispatch honours CLAUDE_DEFAULT_MODEL.

Test plan

  • CI green on this branch.
  • Once the next latere-ai/images release publishes sandbox-agents:vX.Y.Z, run make build end-to-end on a clean machine to confirm the auto-pull picks up the right tag (the existing cli.SandboxTag ldflag plumbing still resolves via the GitHub API or build-time embed).
  • Run make e2e-lifecycle SANDBOX=claude and SANDBOX=codex against a running server to verify both dispatch paths complete a real task end-to-end.
  • Run make e2e-dependency-dag to confirm conflict resolution / autosync still work with the new image.

Follow-ups (not in this PR)

  • Teach the worker-reuse path (WALLFACER_TASK_WORKERS=true) to switch WALLFACER_AGENT mid-life so a single long-lived worker can serve different agent types across activities. Today each worker is still pinned to one agent type at create time, even though the image now supports both.
  • Tidy the UI for the single-image world (ui/js/images.js currently shows the entry under the legacy "Claude" header; could be relabelled "Sandbox").

Wallfacer used to maintain two parallel sandbox images
(sandbox-claude and sandbox-codex), choosing between them per task by
rewriting "sandbox-claude" → "sandbox-codex" in image names. The new
sandbox-agents image (latere-ai/images PR #2, released as v0.0.6+)
ships both Claude Code and Codex CLIs under a single `agent` user and
dispatches at startup via WALLFACER_AGENT. This change cuts
wallfacer over to that image and deletes the per-agent rewrite paths.

Behaviour changes:

- The runner injects WALLFACER_AGENT={claude,codex} into every sub-agent
  container so the unified entrypoint launches the right CLI.
- All `/home/claude/...` and `/home/codex/...` mount targets become
  `/home/agent/...`, including the claude-config named volume, the
  codex auth bind-mount, and the dependency-cache volumes.
- The codex auth mount now bind-mounts only `~/.codex/auth.json`
  (read-only) instead of the whole `~/.codex/` directory. Codex 0.120+
  writes config.toml at startup, so the in-container directory must
  remain writable; mounting only auth.json keeps host state untouched.
- `wallfacer doctor` reports a single sandbox image instead of two and
  no longer probes CODEX_SANDBOX_IMAGE separately.
- `GetImageStatus`, `PullImage`, `DeleteImage` operate on the single
  image; the API still accepts a `sandbox` field for backward
  compatibility but ignores it.

Code cuts:

- Deleted `cli.codexImageFromClaude`, `cli.resolveSandboxImageForExec`,
  `runner.sandboxImageForSandbox`, `runner.entrypointForSandbox`,
  `handler.testCodexImage`, `handler.fallbackCodexSandboxImage`, and
  the test families that asserted their behaviour. The Codex/Claude
  type enum is preserved — only image-name rewriting goes away.
- `Makefile` pulls and tags one image (`sandbox-agents`) instead of two.

Build & docs:

- Default image: `ghcr.io/latere-ai/sandbox-agents:latest`.
- README, CLAUDE.md, getting-started, configuration, development,
  workspaces-and-config, api-and-transport, and git-worktrees all
  document the unified image and the WALLFACER_AGENT dispatch contract.

Net: -601 / +298 lines across 32 files; full backend test suite
(3714 tests in 46 packages) passes; `make lint` clean.
@changkun changkun merged commit 69cbfce into main Apr 15, 2026
3 checks passed
@changkun changkun deleted the unified-sandbox branch April 15, 2026 17:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant