Files
repo-scoping/src/repo_scoping/acceptance/agentic.py
tegwick 084159e51c chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-15:
  - update .custodian-brief.md for repo-scoping
2026-05-15 21:14:21 +02:00

74 lines
2.2 KiB
Python

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:
repository: Repository
candidate_graph: CandidateGraph
criteria_version: str
quality_gate_outcomes: list[QualityGateOutcome]
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) -> 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