Skip to content

Keep the image's Bundler defaults when roast strips BUNDLE_* for subprocesses - #46

Merged
pstrzalk merged 1 commit into
mainfrom
bundler-env-in-sandbox
Sep 3, 2026
Merged

pstrzalk merged 1 commit into
mainfrom
bundler-env-in-sandbox

Conversation

@pstrzalk

@pstrzalk pstrzalk commented Sep 3, 2026

Copy link
Copy Markdown
Owner

Why

PR #45 put the skeleton's gems in the image, and bundle check on a workspace now passes in the generator container and in a plain docker run --user 1000 of the sandbox image. It still failed inside every real sandbox run (project 36, 2026-09-03 22:08: all 116 gems "missing", fix agent reinstalls them, 97s and $0.07 per revision).

Cause: Bundler.with_unbundled_env, used by our verify step and by the roast gem when it spawns the code agent, deletes every BUNDLE_* variable, not only what bundle exec set. That takes the Dockerfile's BUNDLE_PATH and BUNDLE_WITHOUT with it. Without BUNDLE_PATH, Bundler looks under $GEM_HOME/gems instead of $BUNDLE_PATH/ruby/<abi>/gems and reports the whole lockfile missing; without BUNDLE_WITHOUT it wants the development group the image never installs. Reproduced on production:

env inside the sandbox image bundle check
as shipped satisfied
BUNDLE_* stripped every gem missing
only BUNDLE_PATH restored web-console, bindex missing

What

  • Dockerfile: the claude wrapper exports BUNDLE_PATH/BUNDLE_WITHOUT (image defaults, caller values win), so the agent and everything it runs resolve gems. The Bundler ENV block moves above the wrapper so it quotes the same values at build time.
  • VerifyRevision.with_clean_bundler_env: restores the same two keys from Bundler.original_env inside with_unbundled_env. The comment claiming Bundler keeps Dockerfile globals is gone.
  • AutoRemediate.shell: runs in that scrubbed env too. Under roast's bundle exec its bundle install recipe ran with BUNDLE_GEMFILE=<generator Gemfile>, "completed" in 0.6s against the generator's already-satisfied bundle, and fixed nothing, every revision.
  • Tests pin the restore, the dev no-op (no BUNDLE_PATH in the original env → nothing added), and that the parent env is untouched. CHANGELOG 1.5.2.

Verified

  • Wrapper generated with the Dockerfile's exact printf commands: sh -n clean; with BUNDLE_* stripped it exports /usr/local/bundle / development; a caller's value wins.
  • Bundler.unbundled_env drop confirmed locally (Bundler 4.0.9) and the failure/pass matrix above on production (Bundler 4.0.6).
  • Full suite 630 runs green, rubocop clean.

After merge

kamal deploy, then one change request on any project. Expected in kamal app logs --grep 'W2.4\|auto_remediate\|Cost (USD)': four [W2.4] PASS lines, no auto_remediate lines, two cost lines (code agent, docs agent).

🤖 Generated with Claude Code

https://claude.ai/code/session_0117StvHb26xv3MUepWHhcWy

… subprocesses

1.5.1 baked the skeleton's gems into the image, and `bundle check` on a
workspace passes in the generator container and in a plain `docker run` of the
sandbox image. It still failed inside every real sandbox run because
Bundler.with_unbundled_env — used by our verify step and by the roast gem when
it spawns the code agent — deletes EVERY BUNDLE_* variable, the Dockerfile's
BUNDLE_PATH and BUNDLE_WITHOUT included. Without BUNDLE_PATH Bundler looks
under $GEM_HOME/gems instead of $BUNDLE_PATH/ruby/<abi>/gems and reports the
whole lockfile missing; without BUNDLE_WITHOUT it wants the development group
the image never installs. Reproduced on production with `env -u` (all gems
missing), and the pass with the two restored.

- Dockerfile: the claude wrapper exports BUNDLE_PATH/BUNDLE_WITHOUT (image
  defaults, caller values win) so the agent and everything it runs resolve
  gems; the Bundler ENV block moves above the wrapper so it quotes the same
  values at build time.
- VerifyRevision.with_clean_bundler_env restores the same two keys from
  Bundler.original_env inside with_unbundled_env; the comment that claimed
  Bundler keeps Dockerfile globals is gone.
- AutoRemediate.shell runs in that scrubbed env too: under roast's `bundle
  exec` its `bundle install` recipe ran with BUNDLE_GEMFILE=<generator
  Gemfile>, "completed" in 0.6s against the generator's satisfied bundle, and
  fixed nothing, every revision.
- Tests pin the restore, the dev no-op, and that the parent env is untouched.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0117StvHb26xv3MUepWHhcWy
@pstrzalk
pstrzalk merged commit 4c7a9f9 into main Sep 3, 2026
4 checks passed
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.

2 participants