Add codereview_env/graders/arch_grader.py
Browse files
codereview_env/graders/arch_grader.py
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import List
|
| 2 |
+
from codereview_env.models import Scenario, ActionRecord, Category, ActionType, Verdict
|
| 3 |
+
from codereview_env.graders.grader_utils import find_best_match
|
| 4 |
+
|
| 5 |
+
def grade_architectural_review(scenario: Scenario, history: List[ActionRecord]) -> float:
|
| 6 |
+
"""Grade architectural review: 0.6 * issue_score + 0.2 * verdict_score + 0.2 * quality_score."""
|
| 7 |
+
critical_issues = scenario.ground_truth_issues
|
| 8 |
+
flagged_actions = [r for r in history if r.category == Category.ARCHITECTURE]
|
| 9 |
+
|
| 10 |
+
# 1. Issue Detection (0.6)
|
| 11 |
+
found_count = 0
|
| 12 |
+
already_matched = set()
|
| 13 |
+
quality_bonus = 0.0
|
| 14 |
+
|
| 15 |
+
for action in flagged_actions:
|
| 16 |
+
match = find_best_match(action, critical_issues, already_matched)
|
| 17 |
+
if match:
|
| 18 |
+
found_count += 1
|
| 19 |
+
already_matched.add(match.id)
|
| 20 |
+
# Quality: + bonus if body is descriptive (> 80 chars)
|
| 21 |
+
if len(action.body) > 80:
|
| 22 |
+
quality_bonus += 0.05
|
| 23 |
+
|
| 24 |
+
issue_score = (found_count / len(critical_issues)) if critical_issues else 1.0
|
| 25 |
+
|
| 26 |
+
# 2. Verdict Correctness (0.2)
|
| 27 |
+
verdict_score = 0.0
|
| 28 |
+
final_action = history[-1] if history else None
|
| 29 |
+
if final_action and final_action.action_type in (ActionType.APPROVE, ActionType.REQUEST_CHANGES):
|
| 30 |
+
# Check against the first required verdict in GT
|
| 31 |
+
required_verdicts = [gt.required_verdict for gt in critical_issues if gt.required_verdict]
|
| 32 |
+
if required_verdicts and final_action.verdict == required_verdicts[0]:
|
| 33 |
+
verdict_score = 1.0
|
| 34 |
+
elif not required_verdicts and final_action.verdict == Verdict.LGTM:
|
| 35 |
+
verdict_score = 1.0
|
| 36 |
+
|
| 37 |
+
# 3. Final weighted calculation
|
| 38 |
+
score = 0.6 * issue_score + 0.2 * verdict_score + min(0.2, quality_bonus)
|
| 39 |
+
return round(min(1.0, score), 4)
|