generated from coulomb/repo-seed
Record quality gate audit decisions
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
@@ -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 == []
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user