File size: 3,187 Bytes
b92d20c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6139c83
b92d20c
 
6139c83
2d2c6e4
 
 
b92d20c
 
 
 
 
 
 
 
 
 
6139c83
 
b92d20c
 
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
from __future__ import annotations

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

from pydantic import BaseModel, Field

from openenv.core import Action, Observation, State


class ReviewFinding(BaseModel):
    title: str = Field(..., min_length=5, description="Short review finding title.")
    file_path: str = Field(..., min_length=3, description="File containing the issue.")
    line_hint: Optional[str] = Field(
        default=None,
        description="Approximate line or symbol reference, for example 'line 18' or 'process_refund'.",
    )
    severity: Literal["low", "medium", "high", "critical"] = Field(
        ..., description="Estimated impact of the issue."
    )
    rationale: str = Field(
        ...,
        min_length=20,
        description="Why this matters in production and what behavior is affected.",
    )
    recommendation: str = Field(
        ...,
        min_length=12,
        description="Concrete fix suggestion that an engineer could act on.",
    )


class ReviewArtifact(BaseModel):
    artifact_id: str
    kind: Literal["file", "test", "log", "policy", "ticket"]
    title: str
    preview: str
    opened: bool = False
    content: Optional[str] = None


class CodeReviewAction(Action):
    action_type: Literal["open_artifact", "submit_review"] = Field(
        ..., description="Open more evidence or submit review findings."
    )
    artifact_id: Optional[str] = Field(
        default=None, description="Artifact id for open_artifact actions."
    )
    findings: List[ReviewFinding] = Field(
        default_factory=list,
        description="Structured review findings when action_type is submit_review.",
    )
    note: Optional[str] = Field(
        default=None, description="Optional short note about why the action was chosen."
    )


class CodeReviewObservation(Observation):
    task_id: str
    difficulty: Literal["easy", "medium", "hard"]
    title: str
    objective: str
    summary: str
    step_limit: int
    opened_artifacts: List[ReviewArtifact] = Field(default_factory=list)
    available_artifacts: List[ReviewArtifact] = Field(default_factory=list)
    recent_events: List[str] = Field(default_factory=list)
    last_action_error: Optional[str] = None
    score: float = Field(default=0.05, gt=0.0, lt=1.0)
    # Step-level signals (populated by environment)
    done: bool = Field(default=False, description="Whether the episode has ended.")
    reward: float = Field(default=0.05, description="Reward earned on this step.")
    metadata: Dict[str, Any] = Field(
        default_factory=dict, description="Extra per-step metadata."
    )


class CodeReviewState(State):
    episode_id: Optional[str] = None
    task_id: Optional[str] = None
    difficulty: Optional[str] = None
    title: Optional[str] = None
    step_count: int = 0
    opened_artifact_ids: List[str] = Field(default_factory=list)
    submitted_findings: List[ReviewFinding] = Field(default_factory=list)
    cumulative_reward: float = Field(default=0.05, gt=0.0, lt=1.0)
    score: float = Field(default=0.05, gt=0.0, lt=1.0)
    last_action_error: Optional[str] = None
    task_metadata: Dict[str, Any] = Field(default_factory=dict)