generated from coulomb/repo-seed
Updated by fix-consistency on 2026-05-15: - update .custodian-brief.md for repo-scoping
74 lines
2.2 KiB
Python
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
|