Add deterministic quality gate outcomes

This commit is contained in:
2026-05-15 15:37:00 +02:00
parent 7851eae42f
commit 83d5044ff4
11 changed files with 449 additions and 18 deletions

View File

@@ -12,7 +12,12 @@ from fastapi.responses import PlainTextResponse
from pydantic import Field
from pydantic_settings import BaseSettings, SettingsConfigDict
from repo_registry.acceptance import criteria_registry_dict, load_quality_criteria
from repo_registry.acceptance import (
criteria_registry_dict,
evaluate_candidate_graph_quality,
load_quality_criteria,
quality_gate_outcome_dicts,
)
from repo_registry.core.service import RegistryService
from repo_registry.llm_extraction import LLMCandidateExtractor, create_llm_connect_adapter
from repo_registry.repo_ingestion.git import GitIngestionService
@@ -121,6 +126,14 @@ def get_service(settings: Settings = Depends(get_settings)) -> RegistryService:
)
def candidate_graph_payload(graph) -> dict[str, object]:
payload = asdict(graph)
payload["quality_gate_outcomes"] = quality_gate_outcome_dicts(
evaluate_candidate_graph_quality(graph)
)
return payload
API_DESCRIPTION = (
"Register repositories, analyze their observable implementation facts, "
"curate reviewable scope graphs, and search approved repository characteristics."
@@ -525,7 +538,9 @@ def get_candidate_graph(
service: RegistryService = Depends(get_service),
) -> dict[str, object]:
try:
return asdict(service.candidate_graph(repository_id, analysis_run_id))
return candidate_graph_payload(
service.candidate_graph(repository_id, analysis_run_id)
)
except NotFoundError as exc:
raise HTTPException(status_code=404, detail=str(exc)) from exc
@@ -590,7 +605,7 @@ def reject_candidate_ability(
service: RegistryService = Depends(get_service),
) -> dict[str, object]:
try:
return asdict(
return candidate_graph_payload(
service.reject_candidate_ability(
repository_id,
analysis_run_id,
@@ -616,7 +631,7 @@ def reject_candidate_capability(
service: RegistryService = Depends(get_service),
) -> dict[str, object]:
try:
return asdict(
return candidate_graph_payload(
service.reject_candidate_capability(
repository_id,
analysis_run_id,
@@ -642,7 +657,7 @@ def reject_candidate_feature(
service: RegistryService = Depends(get_service),
) -> dict[str, object]:
try:
return asdict(
return candidate_graph_payload(
service.reject_candidate_feature(
repository_id,
analysis_run_id,
@@ -668,7 +683,7 @@ def reject_candidate_evidence(
service: RegistryService = Depends(get_service),
) -> dict[str, object]:
try:
return asdict(
return candidate_graph_payload(
service.reject_candidate_evidence(
repository_id,
analysis_run_id,
@@ -694,7 +709,7 @@ def edit_candidate_ability(
service: RegistryService = Depends(get_service),
) -> dict[str, object]:
try:
return asdict(
return candidate_graph_payload(
service.edit_candidate_ability(
repository_id,
analysis_run_id,
@@ -720,7 +735,7 @@ def edit_candidate_capability(
service: RegistryService = Depends(get_service),
) -> dict[str, object]:
try:
return asdict(
return candidate_graph_payload(
service.edit_candidate_capability(
repository_id,
analysis_run_id,
@@ -746,7 +761,7 @@ def relink_candidate_capability(
service: RegistryService = Depends(get_service),
) -> dict[str, object]:
try:
return asdict(
return candidate_graph_payload(
service.relink_candidate_capability(
repository_id,
analysis_run_id,
@@ -772,7 +787,7 @@ def relink_candidate_feature(
service: RegistryService = Depends(get_service),
) -> dict[str, object]:
try:
return asdict(
return candidate_graph_payload(
service.relink_candidate_feature(
repository_id,
analysis_run_id,
@@ -798,7 +813,7 @@ def relink_candidate_evidence(
service: RegistryService = Depends(get_service),
) -> dict[str, object]:
try:
return asdict(
return candidate_graph_payload(
service.relink_candidate_evidence(
repository_id,
analysis_run_id,
@@ -824,7 +839,7 @@ def merge_candidate_ability(
service: RegistryService = Depends(get_service),
) -> dict[str, object]:
try:
return asdict(
return candidate_graph_payload(
service.merge_candidate_ability(
repository_id,
analysis_run_id,
@@ -850,7 +865,7 @@ def merge_candidate_capability(
service: RegistryService = Depends(get_service),
) -> dict[str, object]:
try:
return asdict(
return candidate_graph_payload(
service.merge_candidate_capability(
repository_id,
analysis_run_id,
@@ -876,7 +891,7 @@ def merge_candidate_feature(
service: RegistryService = Depends(get_service),
) -> dict[str, object]:
try:
return asdict(
return candidate_graph_payload(
service.merge_candidate_feature(
repository_id,
analysis_run_id,
@@ -902,7 +917,7 @@ def merge_candidate_evidence(
service: RegistryService = Depends(get_service),
) -> dict[str, object]:
try:
return asdict(
return candidate_graph_payload(
service.merge_candidate_evidence(
repository_id,
analysis_run_id,

View File

@@ -638,10 +638,23 @@ class CandidateAbilityResponse(BaseModel):
capabilities: list[CandidateCapabilityResponse]
class QualityGateOutcomeResponse(BaseModel):
criteria_version: str
criterion_id: str
criterion_title: str
severity: str
outcome: str
element_type: str
element_id: int
element_name: str
reason: str
class CandidateGraphResponse(BaseModel):
repository: RepositoryResponse
analysis_run: AnalysisRunResponse
abilities: list[CandidateAbilityResponse]
quality_gate_outcomes: list[QualityGateOutcomeResponse] = Field(default_factory=list)
model_config = {
"json_schema_extra": {
@@ -698,6 +711,7 @@ class CandidateGraphResponse(BaseModel):
],
}
],
"quality_gate_outcomes": [],
}
]
}