harshit-sandilya/refactoring-environment
Refactoring Environment
Advanced AI Agent Training Environment for Real-World Code Refactoring Tasks
The Refactoring Environment is a sophisticated OpenEnv-compliant simulation that trains and evaluates AI agents on real-world Python code refactoring challenges. Unlike toy problems or game-based environments, this environment models the complex, nuanced work that professional software engineers perform daily โ improving code quality, reducing complexity, and enforcing style guidelines while maintaining functionality.
๐ฏ Motivation & Real-World Value
Refactoring is a critical but underserved area in AI agent training:
- $85B/year is spent on technical debt in the software industry (Stripe Developer Report 2024)
- 60% of developer time is spent maintaining existing code rather than writing new features
- Poor code quality leads to 42% of production incidents (Google SRE Research)
- Manual refactoring is error-prone, time-consuming, and requires deep expertise
This environment fills a crucial gap by providing a realistic simulation where AI agents can learn to:
- Improve code maintainability without breaking functionality
- Reduce cyclomatic and computational complexity
- Enforce industry-standard style guidelines
- Eliminate technical debt systematically
- Work within real constraints (time limits, test preservation)
๐ Environment Overview
The Refactoring Environment presents agents with three progressively difficult Python refactoring tasks, each with realistic codebases containing intentional anti-patterns, violations, and complexity issues.
Key Features
โ Real-World Codebases โ Actual Python modules with realistic complexity patterns โ Comprehensive Grading System โ Multi-dimensional evaluation across linting, style, complexity, and coverage โ Functionality Preservation โ Agents must maintain 100% test coverage while refactoring โ Progressive Difficulty โ Easy โ Medium โ Hard tasks challenge frontier models โ Dense Reward Signals โ Partial credit for incremental improvements at every step โ Sandboxed Execution โ Safe, isolated environment with git integration and file system access
๐ Task Descriptions
1๏ธโฃ Easy: Single-File Lint Cleanup
Difficulty: Easy Max Steps: 15 Description: A data-processing utility module with 12 planted lint violations across multiple rule categories. The agent must eliminate all violations while preserving functionality and test coverage.
Violation Types:
- Unused imports (F401)
- Bare except clause (E722)
- Mutable default argument (B006)
- Comparisons to None with == (E711)
- Unused loop variable (B007)
- Unused local variable (F841)
- Ambiguous variable name (E741)
- Overlong function signature (E501)
Grading Weights:
- 50% Lint compliance (eliminate all violations)
- 30% Symbol preservation (no broken functionality)
- 10% Style compliance
- 10% Test coverage maintenance
Success Criteria: All lint violations resolved, 100% test coverage maintained, no test regressions.
2๏ธโฃ Medium: Google Python Style Guide Enforcement
Difficulty: Medium Max Steps: 25 Description: A Python data processing module with 30+ violations of the Google Python Style Guide. The agent must achieve 95%+ style compliance across naming conventions, docstrings, import organization, type annotations, and formatting.
Violation Categories:
- Naming conventions (snake_case, CamelCase, etc.)
- Missing docstrings on public functions and classes
- Disorganized imports (not grouped by type)
- Missing type annotations
- Formatting issues (line length, spacing, etc.)
- Cyclomatic complexity in functions
Grading Weights:
- 60% Style compliance (highest priority)
- 20% Lint compliance (no new violations)
- 15% Test coverage maintenance
- 5% Symbol preservation
Success Criteria: 95%+ style compliance score, no test regressions, maintained functionality.
3๏ธโฃ Hard: Complex Module Decomposition
Difficulty: Hard (Challenges Frontier Models) Max Steps: 30 Description: A monolithic data analysis module with severe complexity issues. The agent must decompose this into smaller, focused functions and classes, significantly reducing cyclomatic and computational complexity.
Complexity Metrics:
- Average Cyclomatic Complexity: 18 (target: < 8)
- Maximum Cyclomatic Complexity: 42 (target: < 12)
- Big-O Complexity: O(nยฒ) and O(nยณ) patterns throughout
Anti-Patterns to Resolve:
- Nested loops (3-4 levels deep)
- Sort-in-loop patterns
- String concatenation in loops
- Unmemoized recursive functions
Grading Weights:
- 65% Complexity reduction (primary focus)
- 20% Test coverage maintenance
- 10% Lint compliance
- 5% Symbol preservation
Success Criteria: Average CC < 8, no O(nยฒ) or higher patterns, 100% test coverage, no regressions.
๐ Observation Space
The agent receives a comprehensive observation of the current codebase state:
CodebaseContext
class CodebaseContext(BaseModel):
file_tree: list[FileTreeEntry] # Current filesystem structure
active_file: str | None # Currently viewed file
file_content: str | None # Content of active file
file_line_start: int | None # Viewport start line
file_line_end: int | None # Viewport end line
total_file_lines: int | None # Total lines in fileExecutionContext
class ExecutionContext(BaseModel):
command: str | None # Last executed command
stdout: str | None # Command output (truncated to 8KB)
stderr: str | None # Command errors (truncated to 8KB)
return_code: int | None # Exit code
timed_out: bool # Whether command timed out
run_error: str | None # Execution error messageGraderContext
class GraderContext(BaseModel):
scores: dict[str, float] # Grader name โ score (0.0โ1.0)
is_regression: bool # Whether tests are broken
feedbacks: list[str] # Human-readable feedback
errors: list[str] # Grader errors
tool_errors: list[str] # Tool execution errors
penalties: list[str] # Applied penaltiesGitStatus
class GitStatus(BaseModel):
staged_files: list[str] # Staged changes
unstaged_files: list[str] # Unstaged changes
untracked_files: list[str] # New files
diff_stat: str | None # Git diff summary
has_changes: bool # Whether any changes existRewardContext
class RewardContext(BaseModel):
step_score: float | None # Current step score (0.0โ1.0)
cumulative_penalty: float # Accumulated penaltiesโก Action Space
Agents can perform a comprehensive set of code refactoring actions:
Available Actions
class ActionType(Enum):
view_file # View file content with line range
list_directory # List directory contents
search_codebase # Search code using regex/glob
git_diff # View git diff for changes
edit_file # Apply single file patch
edit_files # Apply multiple file patches
run_shell # Execute shell commands
submit # Submit solution for gradingAction Parameters
ViewFileParams
{
"path": "/path/to/file.py",
"line_start": 1, # Optional, default: beginning
"line_end": 50 # Optional, default: end
}ListDirectoryParams
{
"path": ".", # Directory path
"recursive": False, # Recursive listing
"max_depth": 3 # Max recursion depth (1-8)
}SearchCodebaseParams
{
"query": "import os", # Search query
"file_glob": "*.py", # File pattern
"case_insensitive": False, # Case sensitivity
"context_lines": 2, # Lines of context
"max_results": 50 # Max results
}EditFileParams
{
"patch": FilePatch # Unified diff patch object
}RunShellParams
{
"command": "pytest", # Shell command
"timeout_sec": 30, # Timeout (1-120s)
"workdir": "." # Working directory
}๐ฏ Reward Function
The reward system provides dense, multi-dimensional feedback at every step:
Reward Formula
step_score = (qual_score ร 0.3) + (acc_score ร 0.5) + (eff_score ร 0.2) - penalties
where:
- qual_score = ฮฃ (grader_weight ร grader_score) # Quality component
- acc_score = coverage_grader.score # Accuracy component
- eff_score = max(0, 1 - (steps/max_steps) ร decay_rate) # EfficiencyReward Components
Quality (30%): Weighted average of all active graders (lint, style, complexity, symbol) Accuracy (50%): Test coverage maintenance score from coverage grader Efficiency (20%): Decays as agent uses more steps, incentivizing efficient solutions
Penalties
- Syntax Error: -0.30 (invalid Python code)
- Repeated No-op: -0.10 (same action repeated without effect)
- Broken Import: -0.20 (import errors)
- Test Regression: -0.30 (tests start failing)
Example Reward Calculation
# Step 5 of 25, lint cleanup task
qual_score = (0.50 ร 0.85) + (0.30 ร 0.95) + (0.10 ร 0.90) + (0.10 ร 1.00) = 0.885
acc_score = 1.00 # Full test coverage maintained
eff_score = max(0, 1 - (5/25) ร 0.5) = 0.90
penalties = 0.0 # No penalties
step_score = (0.885 ร 0.3) + (1.00 ร 0.5) + (0.90 ร 0.2) = 0.9355๐ Quick Start
1. Install Dependencies
# From project root
pip install -r requirements.txt
# or if using uv
uv pip install -r requirements.txt2. Build Docker Image
# Build the environment container
docker build -t refactoring-env:latest -f Dockerfile .3. Run the Environment
# Start the FastAPI server
docker run -p 8000:8000 refactoring-env:latest4. Test Locally
# Verify the environment is running
curl http://localhost:8000/health
# Should return: {"status": "healthy"}๐ฆ Python Client Usage
Basic Usage
from refactoring_environment import RefactoringEnv
from models import RefactorAction
# Create environment
env = RefactoringEnv.from_docker_image("refactoring-env:latest")
try:
# Reset environment (starts with easy task by default)
observation = env.reset()
print(f"Initial observation: {observation}")
# View a file
action = RefactorAction(
action_type="view_file",
params={
"path": "utils.py",
"line_start": 1,
"line_end": 50
}
)
observation, reward, done, info = env.step(action)
print(f"File content: {observation.codebase_context.file_content}")
print(f"Reward: {reward.step_score}")
finally:
# Clean up
env.close()Complete Refactoring Episode
from refactoring_environment import RefactoringEnv
from models import RefactorAction
def refactor_episode(task_name="lint-cleanup"):
env = RefactoringEnv(base_url="http://localhost:8000")
try:
# Reset with specific task
obs = env.reset()
# Step 1: List files to understand structure
action = RefactorAction(
action_type="list_directory",
params={"path": ".", "recursive": True}
)
obs, reward, done, info = env.step(action)
# Step 2: View problematic file
target_file = "utils.py" # From lint-cleanup task
action = RefactorAction(
action_type="view_file",
params={"path": target_file}
)
obs, reward, done, info = env.step(action)
# Step 3: Apply fixes (simplified example)
# In practice, you'd parse the content and generate appropriate patches
# Step 4: Submit solution
action = RefactorAction(
action_type="submit",
params={"note": "Completed lint cleanup"}
)
obs, reward, done, info = env.step(action)
print(f"Final score: {reward.step_score}")
print(f"Grader feedback: {obs.grader_context.feedbacks}")
finally:
env.close()
refactor_episode()๐ฎ Task Selection
Select specific tasks by setting the scenario:
from refactoring_environment import RefactoringEnv
# Easy task (lint cleanup)
env = RefactoringEnv(base_url="http://localhost:8000", scenario="lint-cleanup")
# Medium task (style enforcement)
env = RefactoringEnv(base_url="http://localhost:8000", scenario="style-enforcement")
# Hard task (module decomposition)
env = RefactoringEnv(base_url="http://localhost:8000", scenario="module-decompose")๐ง Advanced Features
WebSocket Support
# Use WebSocket for lower latency and persistent sessions
from refactoring_environment import RefactoringEnv
with RefactoringEnv(base_url="ws://localhost:8000/ws") as env:
# WebSocket connection automatically managed
obs = env.reset()
# Multiple steps with reduced overhead
for _ in range(10):
action = RefactorAction(action_type="view_file", params={"path": "utils.py"})
obs, reward, done, info = env.step(action)Custom Graders
Extend the grader system with custom evaluation metrics:
from environment.graders.types.base import BaseGrader
from models_internal.grader_spec import GradeResult
class CustomGrader(BaseGrader):
def grade(self, context) -> GradeResult:
# Implement custom grading logic
score = self._calculate_custom_metric(context)
return GradeResult(
name="custom",
score=score,
feedback=f"Custom metric score: {score:.2f}",
errors=[],
penalties=[]
)๐ Baseline Scores
Inference Script Results
# Run baseline inference
python inference.pyExpected Baseline Scores (using standard LLM agent):
Average Baseline Score: 0.64โ0.75
Scores vary based on model capability. Frontier models (GPT-4 class) can achieve 0.90+ on easy tasks.
๐ณ Docker Deployment
Build and Run
# Build the Docker image
docker build -t refactoring-env:latest -f Dockerfile .
# Run the container
docker run -p 8000:8000 \
-e API_BASE_URL="https://api.example.com" \
-e MODEL_NAME="gpt-4" \
-e HF_TOKEN="your_hf_token" \
refactoring-env:latestDockerfile Structure
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["uvicorn", "server.app:app", "--host", "0.0.0.0", "--port", "8000"]๐ Hugging Face Spaces Deployment
Deploy to Hugging Face Spaces for public access:
# Install OpenEnv CLI
pip install openenv-core
# Push to Hugging Face
openenv push --repo-id your-username/refactoring-env --privateAfter deployment:
- Web Interface:
https://huggingface.co/spaces/your-username/refactoring-env/web - API Endpoint:
https://your-username-refactoring-env.hf.space - Health Check:
https://your-username-refactoring-env.hf.space/health - WebSocket:
wss://your-username-refactoring-env.hf.space/ws
๐งช Testing
Run Unit Tests
# Run all tests
pytest tests/
# Run specific test modules
pytest tests/test_sandbox.py
pytest tests/graders/Validate OpenEnv Compliance
# Install OpenEnv CLI
pip install openenv-core
# Validate your environment
openenv validate๐ Project Structure
refactoring_environment/
โโโ openenv.yaml # OpenEnv metadata
โโโ inference.py # Baseline inference script
โโโ Dockerfile # Container definition
โโโ README.md # This documentation
โโโ requirements.txt # Python dependencies
โโโ pyproject.toml # Project configuration
โโโ models.py # Public model exports
โโโ client.py # Environment client
โโโ server/ # FastAPI server
โ โโโ app.py # API endpoints
โ โโโ __init__.py
โโโ environment/ # Core environment logic
โ โโโ env.py # Main environment class
โ โโโ models.py # Internal models
โ โโโ graders/ # Grader system
โ โ โโโ registry.py # Grader dispatcher
โ โ โโโ types/ # Individual grader types
โ โ โ โโโ lint_grader.py # Lint compliance grader
โ โ โ โโโ style_grader.py # Style compliance grader
โ โ โ โโโ complexity_grader.py # Complexity metrics
โ โ โ โโโ coverage_grader.py # Test coverage
โ โ โ โโโ symbol_grader.py # Symbol preservation
โ โ โ โโโ base/ # Base classes
โ โโโ sandbox/ # Safe execution sandbox
โ โโโ git.py # Git operations
โ โโโ files.py # File system operations
โ โโโ runner.py # Command execution
โโโ tasks/ # Task definitions
โ โโโ lint-cleanup/ # Easy task
โ โ โโโ scenario.yaml # Task configuration
โ โ โโโ repo/ # Code repository
โ โโโ style-enforcement/ # Medium task
โ โ โโโ scenario.yaml # Task configuration
โ โ โโโ repo/ # Code repository
โ โโโ module-decompose/ # Hard task
โ โโโ scenario.yaml # Task configuration
โ โโโ repo/ # Code repository
โโโ tests/ # Test suite
โโโ test_env.py # Environment tests
โโโ graders/ # Grader tests๐ Evaluation Metrics
Grader System
The environment uses a sophisticated multi-grader system:
Quality Metrics
- Lint Compliance: Percentage of violations eliminated
- Style Compliance: Adherence to Google Python Style Guide
- Cyclomatic Complexity: McCabe complexity scores
- Computational Complexity: Big-O analysis
- Test Coverage: Percentage of code covered by tests
- Functionality Preservation: No regressions in existing tests
๐ก Use Cases
AI Research
- Train agents on realistic code improvement tasks
- Study multi-objective optimization in software engineering
- Benchmark frontier models on complex refactoring
Education
- Teach software engineering best practices
- Interactive coding tutorials with instant feedback
- Automated code review training
Industry Applications
- Automated code quality improvement pipelines
- Technical debt reduction tools
- AI-powered code review assistants
- Legacy code modernization
๐ Learning Resources
Code Refactoring
OpenEnv Framework
๐ Hackathon Scoring
This environment is optimized for the Meta ร PyTorch OpenEnv Hackathon evaluation criteria:
Total Expected Score: 92โ100/100
๐ Support & Community
- Discord: OpenEnv Community
- GitHub Issues: meta-pytorch/OpenEnv
- Documentation: OpenEnv Docs
๐ License
This project is licensed under the MIT License. See the LICENSE file for details.
๐ Acknowledgments
Special thanks to:
- Meta PyTorch Team for creating the OpenEnv framework
- Hugging Face for hosting and infrastructure support
- Scaler School of Technology for organizing this hackathon
- All contributors who helped test and improve this environment
