""" Level 3 Scenarios — Multi-step fixes (3-5 steps). """ from __future__ import annotations from typing import List from scenarios.registry import Scenario def _success_venv_rebuilt(output: str) -> bool: """Check if the virtualenv was successfully rebuilt.""" o = output.lower() return ("successfully installed" in o or "requirement already satisfied" in o) and "flask" in o def _success_config_fixed(output: str) -> bool: """Check if the config was fixed and service restarted.""" o = output.lower() return "running on http://0.0.0.0" in o or "server running" in o or "success" in o def _success_migration_done(output: str) -> bool: """Check if the migration completed successfully.""" o = output.lower() return "upgrade" in o or "migration complete" in o or "success" in o def get_level3_scenarios() -> List[Scenario]: """Return all Level 3 (multi-step fix) scenarios.""" return [ Scenario( id="corrupt_venv", level=3, description="Virtual environment is broken, must delete + recreate + reinstall deps + verify.", initial_state={"files": {}, "env_vars": {}, "processes": []}, success_condition=_success_venv_rebuilt, hint_commands=[ "rm -rf /app/venv", "python3 -m venv /app/venv", "source /app/venv/bin/activate && pip install flask", "source /app/venv/bin/activate && python -c 'import flask; print(\"Success\")'", ], error_fingerprint=r"No module named|broken.*venv|bad interpreter", setup_commands=[ "mkdir -p /app", "python3 -m venv /app/venv", "rm -rf /app/venv/lib", "cat > /app/requirements.txt << 'PYEOF'\nflask>=2.0\nPYEOF", ], initial_error_log=( "$ source /app/venv/bin/activate && python -c 'import flask'\n" "Error: /app/venv/bin/python: bad interpreter: No such file or directory\n" "$ /app/venv/bin/pip install flask\n" "bash: /app/venv/bin/pip: No such file or directory\n" "The virtual environment appears to be broken.\n" ), verification_command="source /app/venv/bin/activate && python -c 'import flask; print(\"flask ok\")'", ), Scenario( id="wrong_config_restart", level=3, description="App config has wrong host binding. Edit config + restart service + verify.", initial_state={"files": {}, "env_vars": {}, "processes": []}, success_condition=_success_config_fixed, hint_commands=[ "sed -i 's/127.0.0.1/0.0.0.0/' /app/config.py", "kill $(lsof -t -i:8080) 2>/dev/null; true", "python /app/server.py &", ], error_fingerprint=r"Connection refused|config.*error|binding.*error", setup_commands=[ "pip install flask -q", "mkdir -p /app", "cat > /app/config.py << 'PYEOF'\nHOST = '127.0.0.1'\nPORT = 8080\nDEBUG = True\nPYEOF", "cat > /app/server.py << 'PYEOF'\nfrom flask import Flask\nfrom config import HOST, PORT\nimport sys\nsys.path.insert(0, '/app')\napp = Flask(__name__)\n@app.route('/')\ndef hello():\n return 'Server running'\nif __name__ == '__main__':\n print(f'Running on http://{HOST}:{PORT}')\n app.run(host=HOST, port=PORT)\nPYEOF", ], initial_error_log=( "$ curl http://0.0.0.0:8080/\n" "curl: (7) Failed to connect to 0.0.0.0 port 8080: Connection refused\n" "$ cat /app/config.py\n" "HOST = '127.0.0.1'\n" "PORT = 8080\n" "DEBUG = True\n" "The app binds to 127.0.0.1 only — not accessible externally.\n" ), verification_command="curl -s http://0.0.0.0:8080/", ), Scenario( id="db_migration_fail", level=3, description="SQLAlchemy migration fails — downgrade + fix model + re-migrate + verify.", initial_state={"files": {}, "env_vars": {}, "processes": []}, success_condition=_success_migration_done, hint_commands=[ "cat > /app/models.py << 'PYEOF'\nfrom sqlalchemy import Column, Integer, String, create_engine\nfrom sqlalchemy.orm import declarative_base\nBase = declarative_base()\nclass User(Base):\n __tablename__ = 'users'\n id = Column(Integer, primary_key=True)\n name = Column(String(100), nullable=False)\n email = Column(String(200), unique=True)\nPYEOF", "pip install sqlalchemy -q", "python /app/migrate.py", ], error_fingerprint=r"OperationalError|migration.*fail|sqlalchemy.*error", setup_commands=[ "pip install sqlalchemy -q", "mkdir -p /app", "cat > /app/models.py << 'PYEOF'\nfrom sqlalchemy import Column, Integer, String, create_engine\nfrom sqlalchemy.orm import declarative_base\nBase = declarative_base()\nclass User(Base):\n __tablename__ = 'users'\n id = Column(Integer, primary_key=True)\n name = Column(String(100), nullable=False)\n email = Column(INVALID_TYPE, unique=True)\nPYEOF", "cat > /app/migrate.py << 'PYEOF'\nimport sys\nsys.path.insert(0, '/app')\ntry:\n from models import Base\n from sqlalchemy import create_engine\n engine = create_engine('sqlite:///app.db')\n Base.metadata.create_all(engine)\n print('Migration complete - Success')\nexcept Exception as e:\n print(f'Migration failed: {e}')\n sys.exit(1)\nPYEOF", ], initial_error_log=( "$ python /app/migrate.py\n" "Traceback (most recent call last):\n" " File \"/app/models.py\", line 8, in \n" " email = Column(INVALID_TYPE, unique=True)\n" "NameError: name 'INVALID_TYPE' is not defined\n" "Migration failed.\n" ), verification_command="python /app/migrate.py", ), ]