File size: 6,292 Bytes
27cdb3e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
"""
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 <module>\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",
        ),
    ]