File size: 3,909 Bytes
9b47159
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
"""
Typed Pydantic v2 models for action, observation, and state schemas.

All models follow the OpenEnv specification for RL environment interfaces.
"""

from __future__ import annotations

from enum import Enum
from typing import Any, Dict, List, Literal, Optional

from pydantic import BaseModel, Field


# -- Domain enumerations --

class BugType(str, Enum):
    """Supported bug categories for classification."""

    CRASH = "crash"
    UI = "ui"
    PERFORMANCE = "performance"
    SECURITY = "security"
    DATA_LOSS = "data_loss"
    COMPATIBILITY = "compatibility"


class Priority(str, Enum):
    """Severity levels ordered low to critical."""

    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"
    CRITICAL = "critical"


class SuggestedAction(str, Enum):
    """Recommended triage actions."""

    FIX_IMMEDIATELY = "fix_immediately"
    SCHEDULE_SPRINT = "schedule_sprint"
    NEEDS_MORE_INFO = "needs_more_info"
    WONTFIX = "wontfix"
    DUPLICATE = "duplicate"


# -- Domain constants --

DEVELOPERS: list[str] = ["Alice", "Bob", "Carol", "David", "Eve"]

DEVELOPER_SPECIALIZATIONS: Dict[str, List[str]] = {
    "Alice": ["crash", "performance", "data_loss"],
    "Bob": ["crash", "security"],
    "Carol": ["ui", "compatibility"],
    "David": ["security", "data_loss"],
    "Eve": ["ui", "performance", "compatibility"],
}

PRIORITY_ORDER: Dict[str, int] = {
    "low": 0,
    "medium": 1,
    "high": 2,
    "critical": 3,
}


# -- Action / Observation / State models --

class BugTriageAction(BaseModel):
    """Agent action submitted via the /step endpoint."""

    task_id: Literal["task_1", "task_2", "task_3"]
    bug_type: Optional[BugType] = None
    priority: Optional[Priority] = None
    assigned_developer: Optional[str] = None
    suggested_action: Optional[SuggestedAction] = None
    reasoning: Optional[str] = None
    confidence: Optional[float] = Field(
        default=None,
        ge=0.0,
        le=1.0,
        description=(
            "Optional agent confidence in [0.0, 1.0]. "
            "Enables confidence-calibration bonus/penalty in reward."
        ),
    )
    metadata: Dict[str, Any] = Field(default_factory=dict)

    model_config = {"use_enum_values": True}


class BugReport(BaseModel):
    """Structured representation of a software bug report."""

    bug_id: str
    title: str
    description: str
    logs: Optional[str] = None
    environment: Optional[str] = None
    reporter: Optional[str] = None
    created_at: Optional[str] = None
    metadata: Dict[str, Any] = Field(default_factory=dict)


class BugTriageObservation(BaseModel):
    """Observation returned by reset() and step()."""

    done: bool = False
    reward: float = 0.0
    task_id: str = ""
    bug_report: Optional[BugReport] = None
    available_developers: List[str] = Field(
        default_factory=lambda: list(DEVELOPERS)
    )
    step_number: int = 0
    feedback: str = ""
    grader_score: Optional[float] = None
    episode_id: Optional[str] = None
    metadata: Dict[str, Any] = Field(default_factory=dict)


class BugTriageState(BaseModel):
    """Episode-level metadata returned by the /state endpoint."""

    episode_id: Optional[str] = None
    step_count: int = 0
    task_id: str = ""
    bug_id: Optional[str] = None
    cumulative_reward: float = 0.0


# -- Request / Response models for FastAPI endpoints --

class ResetRequest(BaseModel):
    task_id: Literal["task_1", "task_2", "task_3"] = "task_1"


class StepRequest(BaseModel):
    episode_id: str
    action: BugTriageAction


class GraderRequest(BaseModel):
    episode_id: str
    task_id: Literal["task_1", "task_2", "task_3"]


class GraderResponse(BaseModel):
    task_id: str
    episode_id: str
    score: float
    breakdown: Dict[str, float]
    passed: bool


class BaselineResponse(BaseModel):
    baseline_model: str
    results: Dict[str, Dict[str, Any]]
    mean_score: float