Skip to content

Bootstrap phase (v0.2): LLM-driven Docker env generation for any repo #1

Description

@adithya-s-k

Summary

Implement the bootstrap phase — the prerequisite for every sandbox-required pipeline (pr_mining, mutation, commit_mining, oss_instruct, equivalence_tests, cve_mining).

An LLM agent runs shell commands inside a long-lived Docker container, observes stdout, iterates until the repo builds and tests can run. Then we commit the container to an image, cache its digest, and reuse the image for every per-task synthesis later. Bootstrap runs once per (repo, ref).

This unlocks every full pipeline planned for v0.2+.

Design doc

See docs/BOOTSTRAP.md for the full design (2-phase architecture, cache strategy, spec changes, edge cases).

Approach

Two architectural calls:

  1. No external dep — RepoLaunch (Microsoft, MIT) was the obvious adoption candidate, but we wrote our own clean Apache-2.0 implementation using the same ReAct-style pattern. Acknowledgment + license posture documented in the module header.
  2. Two-phase architecture — Phase 1 (bootstrap, once per repo+ref, cached) → Phase 2 (per-task synthesis, reuses the cached image). Caching is content-addressed under ./envs/<owner>__<name>/<short_commit>/.

What ships in this PR

New module: src/repo2rlenv/bootstrap/

  • spec.pyBootstrapResult, LanguageHint enum
  • language.py — auto-detect Python / Node / Go / Rust / Java / C/C++ from repo files; per-language base image
  • docker.pyDockerSandbox long-lived container wrapper (uses docker cp not bind mount so commits capture the repo)
  • prompts.py — ReAct system prompt with explicit "SAVE_SETUP as soon as build + tests can RUN — test failures are fine" semantics
  • agent.py — ReAct loop with on_turn event callback for UI/logging consumers
  • cache.py — filesystem cache load/save
  • runner.pyensure_bootstrap() orchestrator (resolves auth, clones, builds, commits, caches)
  • ui.py — Rich-based Modal-style live display (header + steps table + stats footer + outcome panel)
  • __init__.py — public API with explicit acknowledgment header

Spec changes

  • New BootstrapSpec Pydantic model in spec/input.py wired into GenerationInput
  • Exported via spec/__init__.py

LLM cost tracking

  • LLMResponse now carries cost_usd, prompt_tokens, completion_tokens
  • Implementation uses litellm.completion_cost(response) — built-in model_cost map, no extra dep
  • Cost accumulates in AgentOutcome.total_cost_estimate_usd and BootstrapResult.llm_cost_estimate_usd

CLI

  • New `repo2rlenv bootstrap` subcommand with full Rich UI (auto-disabled in non-TTY / `--no-ui`)
  • Flags: `--repo --ref --access --llm --max-iterations --max-seconds --cache-dir --image-registry --platform --language --force --no-ui`

Tests (4 new files, 19 new tests; 57/57 total pass)

  • `test_bootstrap_spec.py` — Pydantic validation + integration into `GenerationInput`
  • `test_bootstrap_language.py` — file-marker-based language detection
  • `test_bootstrap_cache.py` — load/save round-trip, tolerates unknown future fields
  • `test_bootstrap_agent.py` — ReAct response parser + tool dispatch

Model rename

Updated all references from `claude-sonnet-4-5` to `claude-sonnet-4-6` (14 files: docs + tests + sample configs).

Misc

  • `.gitignore` — `envs/`, `envs-*/`, `.r2e_cache/` excluded
  • Removed `e2b` from runtime deps (was speculative; not used)
  • `rich` added as a runtime dep

Live verification

Bootstrapped `pallets/click` end-to-end on macOS + Docker Desktop:

Metric Value
Iterations 6
Wall time 88s
LLM cost $0.119 (claude-sonnet-4-6)
Image digest `local/r2e-bootstrap/pallets__click@sha256:...`
Smoke (`pytest --collect-only`) passes

Then integrated with Harbor: scaffolded a Harbor task via `harbor init --task` whose `environment/Dockerfile` is `FROM` our bootstrap image, ran `harbor run --path ... -a oracle` → Mean reward: 1.000 in 9s. Confirms our bootstrap images are first-class Harbor environments with zero adapter code.

Known follow-ups (out of scope for this PR)

  • Bump emitter `schema_version` to `"1.2"` to match Harbor's current task.toml schema
  • Enforce `BootstrapSpec.max_llm_spend_usd` as a guardrail (currently only declared)
  • Live GHCR push test (needs `gh auth refresh -s write:packages` first)
  • Wire into `pr_mining` (full sandbox-required pipeline) — separate issue/PR

Acceptance

  • 57/57 tests pass
  • Live bootstrap succeeds on a real public repo (pallets/click)
  • Image works in fresh container (`docker run` → repo at `/workspace`, pytest collects)
  • Harbor consumes the image: `harbor run -a oracle` → reward 1.0
  • Cost tracking returns non-zero
  • Cache hit on second run (idempotent)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions