"""ASV benchmarks for the validation-gated apply pipeline. Measures the performance of: - ApplyResult model construction - Validation count extraction - apply_with_validation_gate() with mock lifecycle """ from __future__ import annotations import sys from pathlib import Path from typing import Any from unittest.mock import MagicMock try: from cleveragents.application.services.plan_apply_service import ( ApplyOutcome, ApplyResult, PlanApplyService, ) from cleveragents.domain.models.core.change import ( ChangeEntry, ChangeOperation, SpecChangeSet, ) from cleveragents.domain.models.core.plan import ( PlanPhase, PlanTimestamps, ProcessingState, ) except ModuleNotFoundError: sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src")) from cleveragents.application.services.plan_apply_service import ( ApplyOutcome, ApplyResult, PlanApplyService, ) from cleveragents.domain.models.core.change import ( ChangeEntry, ChangeOperation, SpecChangeSet, ) from cleveragents.domain.models.core.plan import ( PlanPhase, PlanTimestamps, ProcessingState, ) _PLAN_ID = "01BENCHPLAN0000000000001" def _make_plan( *, changeset_id: str = "CS001", validation_summary: dict[str, Any] | None = None, ) -> MagicMock: plan = MagicMock() plan.identity.plan_id = _PLAN_ID plan.phase = PlanPhase.EXECUTE plan.processing_state = ProcessingState.COMPLETE plan.changeset_id = changeset_id plan.validation_summary = validation_summary plan.is_terminal = False plan.error_details = None plan.timestamps = PlanTimestamps() return plan def _make_changeset(n: int = 10) -> SpecChangeSet: cs = SpecChangeSet(plan_id=_PLAN_ID) for i in range(n): cs.add_change( ChangeEntry( plan_id=_PLAN_ID, resource_id="RES001", tool_name="builtin/bench-tool", operation=ChangeOperation.MODIFY, path=f"src/mod_{i:04d}.py", before_hash=f"b{i}", after_hash=f"a{i}", ) ) return cs def _make_service(plan: MagicMock, changeset: SpecChangeSet) -> PlanApplyService: lifecycle = MagicMock() lifecycle.get_plan.return_value = plan lifecycle.complete_apply.return_value = plan lifecycle.commit_plan = MagicMock() store = MagicMock() store.get.return_value = changeset return PlanApplyService(lifecycle_service=lifecycle, changeset_store=store) class ApplyResultSuite: """Benchmark ApplyResult model construction.""" def time_result_construction_applied(self) -> None: ApplyResult( outcome=ApplyOutcome.APPLIED, plan_id=_PLAN_ID, message="applied ok", files_changed=10, validations_total=5, validations_passed=5, validations_failed=0, ) def time_result_construction_constrained(self) -> None: ApplyResult( outcome=ApplyOutcome.CONSTRAINED, plan_id=_PLAN_ID, message="blocked", validations_total=5, validations_passed=3, validations_failed=2, ) class ApplyValidationCountSuite: """Benchmark validation count extraction.""" def setup(self) -> None: self.summary: dict[str, Any] = { "total": 100, "required_passed": 80, "required_failed": 20, } self.empty_summary: dict[str, Any] | None = None def time_extract_counts(self) -> None: PlanApplyService._extract_validation_counts(self.summary) def time_extract_counts_none(self) -> None: PlanApplyService._extract_validation_counts(self.empty_summary) class ApplyGateSuite: """Benchmark the full apply_with_validation_gate flow.""" def setup(self) -> None: cs = _make_changeset(20) self.plan_pass = _make_plan( changeset_id=cs.changeset_id, validation_summary={ "total": 5, "required_passed": 5, "required_failed": 0, }, ) self.plan_fail = _make_plan( changeset_id=cs.changeset_id, validation_summary={ "total": 5, "required_passed": 3, "required_failed": 2, }, ) self.svc_pass = _make_service(self.plan_pass, cs) self.svc_fail = _make_service(self.plan_fail, cs) def time_apply_gate_pass(self) -> None: self.svc_pass.apply_with_validation_gate(_PLAN_ID) def time_apply_gate_fail(self) -> None: self.svc_fail.apply_with_validation_gate(_PLAN_ID)