Validate structured agentic review decisions

This commit is contained in:
2026-05-15 16:09:03 +02:00
parent 9a320a95ee
commit 92eaf52bb6
6 changed files with 331 additions and 10 deletions

View File

@@ -1,4 +1,10 @@
from repo_registry.acceptance.agentic import AgenticReviewer, AgenticReviewRequest
from repo_registry.acceptance.agentic import (
AgenticReviewer,
AgenticReviewDecision,
AgenticReviewRequest,
validate_agentic_review_decision,
validate_agentic_review_decisions,
)
from repo_registry.acceptance.criteria import (
active_quality_criteria_version,
criteria_registry_dict,
@@ -15,6 +21,7 @@ from repo_registry.acceptance.gates import (
__all__ = [
"active_quality_criteria_version",
"AgenticReviewDecision",
"AgenticReviewer",
"AgenticReviewRequest",
"blocking_quality_gate_outcomes",
@@ -25,4 +32,6 @@ __all__ = [
"evaluate_candidate_graph_quality",
"load_quality_criteria",
"quality_gate_outcome_dicts",
"validate_agentic_review_decision",
"validate_agentic_review_decisions",
]

View File

@@ -1,11 +1,23 @@
from __future__ import annotations
from dataclasses import dataclass
from typing import Any
from typing import Protocol
from repo_registry.acceptance.gates import QualityGateOutcome
from repo_registry.core.models import CandidateGraph, Repository
AGENTIC_REVIEW_ACTIONS = {
"approve",
"approve_with_edits",
"reject",
"downgrade",
"request_human_review",
"propose_edit",
"relink",
}
AGENTIC_APPROVAL_ACTIONS = {"approve", "approve_with_edits"}
@dataclass(frozen=True)
class AgenticReviewRequest:
@@ -16,9 +28,46 @@ class AgenticReviewRequest:
context: str
@dataclass(frozen=True)
class AgenticReviewDecision:
action: str
target_type: str
target_id: int
rationale: str
criterion_ids: list[str]
evidence_refs: list[str]
notes: str = ""
proposed_changes: dict[str, Any] | None = None
class AgenticReviewer(Protocol):
reviewer_id: str
policy_version: str
def review(self, request: AgenticReviewRequest) -> None:
"""Review a candidate graph and record decisions through the caller."""
def review(self, request: AgenticReviewRequest) -> list[AgenticReviewDecision]:
"""Review a candidate graph and return structured decisions."""
def validate_agentic_review_decision(decision: AgenticReviewDecision) -> None:
if decision.action not in AGENTIC_REVIEW_ACTIONS:
raise ValueError(f"unsupported agentic review action: {decision.action}")
if not decision.target_type:
raise ValueError("agentic review decision target_type is required")
if decision.target_id < 0:
raise ValueError("agentic review decision target_id must be non-negative")
if not decision.rationale.strip():
raise ValueError("agentic review decision rationale is required")
if not decision.criterion_ids:
raise ValueError("agentic review decision criterion_ids are required")
if decision.action in AGENTIC_APPROVAL_ACTIONS and not decision.evidence_refs:
raise ValueError(
"agentic approval requires evidence refs tied to the rationale"
)
def validate_agentic_review_decisions(
decisions: list[AgenticReviewDecision],
) -> list[AgenticReviewDecision]:
for decision in decisions:
validate_agentic_review_decision(decision)
return decisions