Record quality gate audit decisions

This commit is contained in:
2026-05-15 16:21:19 +02:00
parent a4b39b3cb7
commit 1913793658
3 changed files with 62 additions and 3 deletions

View File

@@ -235,6 +235,16 @@ class RegistryService:
candidate_source = "deterministic" candidate_source = "deterministic"
candidates = normalize_candidate_drafts(candidates) candidates = normalize_candidate_drafts(candidates)
self.store.replace_candidate_graph(repository_id, completed_run.id, candidates) self.store.replace_candidate_graph(repository_id, completed_run.id, candidates)
gate_outcomes = evaluate_candidate_graph_quality(
self.store.get_candidate_graph(repository_id, completed_run.id)
)
if gate_outcomes:
self.store.create_review_decision(
repository_id,
completed_run.id,
action="quality_gate_evaluation",
notes=self._quality_gate_review_notes(gate_outcomes),
)
if "llm" in candidate_source: if "llm" in candidate_source:
log_operation( log_operation(
"llm_extraction_used", "llm_extraction_used",
@@ -282,6 +292,27 @@ class RegistryService:
facts=facts, facts=facts,
) )
def _quality_gate_review_notes(
self,
gate_outcomes,
) -> str:
criteria = ", ".join(
sorted({outcome.criterion_id for outcome in gate_outcomes})
)
outcome_counts: dict[str, int] = {}
for outcome in gate_outcomes:
outcome_counts[outcome.outcome] = outcome_counts.get(outcome.outcome, 0) + 1
outcomes = ", ".join(
f"{name}:{count}" for name, count in sorted(outcome_counts.items())
)
return (
f"criteria_version={active_quality_criteria_version()}; "
f"criteria={criteria}; outcomes={outcomes}; "
f"quality_gate_outcomes={len(gate_outcomes)}; "
"rationale=Deterministic quality gates flagged candidates for "
"review without approving registry truth."
)
def _generate_candidates( def _generate_candidates(
self, self,
repository: Repository, repository: Repository,

View File

@@ -138,3 +138,29 @@ def test_legacy_trusted_auto_approval_skips_quality_gate_blocked_capability(tmp_
assert safe is False assert safe is False
assert "quality gates require review" in reason assert "quality gates require review" in reason
assert "RREG-QC-002" 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 == []

View File

@@ -175,7 +175,7 @@ validated for rationale, criteria IDs, and evidence refs before being applied.
```task ```task
id: RREG-WP-0014-T05 id: RREG-WP-0014-T05
status: in_progress status: done
priority: high priority: high
state_hub_task_id: "0d12559a-831e-40ff-bf82-85f45b763f07" state_hub_task_id: "0d12559a-831e-40ff-bf82-85f45b763f07"
``` ```
@@ -193,11 +193,13 @@ Acceptance criteria:
edits/relinks". edits/relinks".
- Existing decisions remain readable through a migration or compatibility view. - Existing decisions remain readable through a migration or compatibility view.
Implementation note 2026-05-15: started the audit-trail compatibility view by Implementation note 2026-05-15: added the audit-trail compatibility view by
enriching listed review decisions with derived reviewer type, reviewer identity, enriching listed review decisions with derived reviewer type, reviewer identity,
policy version, criteria version, rationale, criterion IDs, evidence refs, policy version, criteria version, rationale, criterion IDs, evidence refs,
accepted-after-edits marker, and decision kind. Existing stored decisions still accepted-after-edits marker, and decision kind. Existing stored decisions still
use the same table and remain readable. use the same table and remain readable. Deterministic gate evaluations now
record aggregate `quality_gate_evaluation` review decisions with criteria IDs,
outcome counts, criteria version, and a rationale that no approval was applied.
## T06: Add Human Override And Criteria Refinement Flow ## T06: Add Human Override And Criteria Refinement Flow