from repo_registry.acceptance import ( blocking_quality_gate_outcomes, evaluate_candidate_capability_quality, evaluate_candidate_graph_quality, quality_gate_outcome_dicts, ) from repo_registry.core.models import ( AnalysisRun, CandidateAbility, CandidateCapability, CandidateFeature, CandidateGraph, Repository, SourceReference, ) from repo_registry.core.service import RegistryService from repo_registry.repo_ingestion.git import GitIngestionService from repo_registry.storage.sqlite import RegistryStore def source_ref(path="src/app.py", kind="source"): return SourceReference( fact_id=1, path=path, kind=kind, name=path, line=1, ) def provider_routing_capability(): return CandidateCapability( id=10, name="Route LLM Requests Across Providers", description="Routes provider requests.", inputs=[], outputs=[], confidence=0.9, status="candidate", source_refs=[source_ref("src/providers.py")], confidence_label="high", primary_class="llm-integration", attributes=["utility-owned"], features=[ CandidateFeature( id=20, name="HTTP API surface", type="API", location="src/app.py", confidence=0.8, status="candidate", source_refs=[source_ref("src/app.py")], confidence_label="high", primary_class="API", ) ], ) def test_quality_gates_flag_known_provider_routing_failure(): outcomes = evaluate_candidate_capability_quality(provider_routing_capability()) outcome_ids = {outcome.criterion_id for outcome in outcomes} assert {"RREG-QC-002", "RREG-QC-003"} <= outcome_ids assert all(outcome.outcome != "approve" for outcome in outcomes) assert blocking_quality_gate_outcomes(outcomes) def test_quality_gates_flag_circular_scope_evidence(): capability = CandidateCapability( id=11, name="Map Repository Scope", description="Uses generated scope.", inputs=[], outputs=[], confidence=0.8, status="candidate", source_refs=[source_ref("SCOPE.md", "generated-scope")], confidence_label="high", primary_class="scope-generation", attributes=["utility-owned"], ) outcomes = evaluate_candidate_capability_quality(capability) assert outcomes[0].criterion_id == "RREG-QC-005" assert outcomes[0].outcome == "rejected" def test_quality_gate_outcomes_are_serializable_for_assessment_artifacts(): graph = CandidateGraph( repository=Repository( id=1, name="Repo", url=".", description=None, branch="main", status="indexed", ), analysis_run=AnalysisRun( id=1, repository_id=1, snapshot_id=None, status="completed", started_at="2026-05-15T00:00:00Z", completed_at="2026-05-15T00:00:01Z", error_message=None, scanner_version="deterministic-v1", ), abilities=[ CandidateAbility( id=1, name="Support Repo", description="Support repo.", confidence=0.8, status="candidate", source_refs=[], capabilities=[provider_routing_capability()], ) ], ) payload = quality_gate_outcome_dicts(evaluate_candidate_graph_quality(graph)) assert payload assert payload[0]["criteria_version"] == "repo-scoping-quality-criteria/v1" def test_legacy_trusted_auto_approval_skips_quality_gate_blocked_capability(tmp_path): store = RegistryStore(tmp_path / "registry.sqlite3") store.initialize() service = RegistryService(store, ingestion=GitIngestionService(tmp_path / "checkouts")) safe, reason = service._trusted_auto_approve_capability_decision( provider_routing_capability() ) assert safe is False assert "quality gates require review" in reason assert "RREG-QC-002" in reason def test_analysis_records_deterministic_gate_review_decision(tmp_path): source = tmp_path / "provider-repo" source.mkdir() (source / "README.md").write_text("# Provider Repo\n", encoding="utf-8") (source / "providers.py").write_text( "provider_registry = {'openrouter': OpenRouterAdapter}\n", encoding="utf-8", ) store = RegistryStore(tmp_path / "registry.sqlite3") store.initialize() service = RegistryService(store, ingestion=GitIngestionService(tmp_path / "checkouts")) repository = service.register_repository(name="Provider Repo", url=str(source)) summary = service.analyze_repository(repository.id, use_llm_assistance=False) decisions = service.list_review_decisions(repository.id, summary.analysis_run.id) gate_decision = next( decision for decision in decisions if decision.action == "quality_gate_evaluation" ) assert gate_decision.reviewer_type == "deterministic-gate" assert "RREG-QC-002" in gate_decision.criterion_ids assert gate_decision.criteria_version == "repo-scoping-quality-criteria/v1" assert "without approving registry truth" in gate_decision.rationale assert service.ability_map(repository.id).abilities == [] override = service.record_quality_gate_override( repository.id, summary.analysis_run.id, criterion_id="RREG-QC-002", element_type="capability", element_id=10, reason="Curator confirmed this repo now owns provider routing.", notes="Future criteria update may be needed.", ) assert override.action == "quality_gate_override" assert override.reviewer_type == "human" assert override.decision_kind == "override" assert override.criterion_ids == ["RREG-QC-002"] assert override.rationale == "Curator confirmed this repo now owns provider routing."