Files
cleveragents-core/benchmarks/phase_reversion_bench.py
T
CoreRasurae 80f1664a0d
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 23s
CI / lint (pull_request) Successful in 3m20s
CI / typecheck (pull_request) Successful in 3m54s
CI / security (pull_request) Successful in 4m13s
CI / quality (pull_request) Successful in 4m17s
CI / integration_tests (pull_request) Successful in 9m21s
CI / unit_tests (pull_request) Successful in 9m42s
CI / docker (pull_request) Successful in 14s
CI / e2e_tests (pull_request) Successful in 12m1s
CI / coverage (pull_request) Successful in 11m41s
CI / status-check (pull_request) Successful in 1s
CI / build (push) Successful in 26s
CI / lint (push) Successful in 3m19s
CI / quality (push) Successful in 3m41s
CI / typecheck (push) Successful in 3m56s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 4m2s
CI / integration_tests (push) Successful in 9m3s
CI / unit_tests (push) Successful in 9m24s
CI / docker (push) Successful in 1m9s
CI / e2e_tests (push) Successful in 13m51s
CI / coverage (push) Successful in 11m25s
CI / status-check (push) Successful in 1s
CI / benchmark-publish (push) Failing after 24m52s
CI / benchmark-regression (pull_request) Failing after 37m6s
test(integration): workflow example 7 — CI/CD integration, automated PR review and fix (ci profile)
Implemented Robot Framework integration test suite validating the CI/CD
workflow (Specification Example 7). Tests cover ci-profile configuration
(automation-profile, format, log level), idempotent resource and project
registration with duplicate-detection assertions, three validation tools
(ci-lint, ci-typecheck, ci-tests) registration and resource attachment
via ToolRegistryService, action creation with typed arguments and
invariants per spec Step 2, plan lifecycle with phase-by-phase completion
through all phases (strategize, execute, apply) until terminal applied
state, and JSON output structure verification including plan_id, phase,
state, action, projects, and arguments fields.

Post-review fixes applied (round 1):
- H1: Fix truncated invariant #2 text to match spec line 39051
- H2: Fix definition_of_done to match spec's 5-bullet-point format
- M1: Register all 3 spec validations (ci-lint, ci-typecheck, ci-tests)
- M3: Add branch property to resource registration per spec Step 3
- M4: Replace phantom resource_id with real registered resource
- M5: Add projects and arguments field assertions to JSON output test
- M7: Replace 'polling-based' with 'phase-by-phase' in docs/comments
- L1: Use timezone-aware datetime (timezone.utc)
- L2: Use tempfile for resource path instead of hardcoded /tmp
- L3: Clarify json_output() docstring to reflect as_cli_dict() scope
- L4: Tighten attachment count assertion from >= 1 to == 1 (now == 3)

Post-review fixes applied (round 2):
- M2: Use Setup Test Environment With Database Isolation for pabot safety
- L1: Replace remaining hardcoded /tmp paths with tempfile (validation_attach,
  resource_idempotent duplicate registration)
- L2: Fix stale 'Polling-based' comment missed in round 1
- L5: Align action description with spec line 39027
- M1/L3/L6: Document automation_profile propagation gap in use_action()
  with TODO for when production code wires the field onto Plan
- L4: Add comment explaining local actor name deviation from spec

Includes CHANGELOG update describing the integration test scope.

ISSUES CLOSED: #771
2026-03-26 21:42:37 +00:00

150 lines
4.8 KiB
Python

"""ASV benchmarks for phase reversion state machine.
Measures the performance of:
- Plan.can_revert_to() validation
- PlanLifecycleService.revert_plan() overhead
- PlanLifecycleService.try_auto_revert_from_apply() overhead
- Decision recording during reversion
- Reversion loop guard check overhead
"""
from __future__ import annotations
import sys
from pathlib import Path
try:
from cleveragents.application.services.plan_lifecycle_service import (
PlanLifecycleService,
)
from cleveragents.config.settings import Settings
from cleveragents.domain.models.core.plan import (
AutomationProfileProvenance,
AutomationProfileRef,
PlanPhase,
ProcessingState,
)
except ModuleNotFoundError:
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
from cleveragents.application.services.plan_lifecycle_service import (
PlanLifecycleService,
)
from cleveragents.config.settings import Settings
from cleveragents.domain.models.core.plan import (
AutomationProfileProvenance,
AutomationProfileRef,
PlanPhase,
ProcessingState,
)
def _make_service() -> PlanLifecycleService:
return PlanLifecycleService(settings=Settings())
def _create_plan_in_execute(
service: PlanLifecycleService,
action_name: str = "local/bench-action",
profile: str = "manual",
) -> str:
service.create_action(
name=action_name,
description="Benchmark action",
definition_of_done="Tests pass",
strategy_actor="local/strategist",
execution_actor="local/executor",
)
plan = service.use_action(action_name)
plan.automation_profile = AutomationProfileRef(
profile_name=profile,
provenance=AutomationProfileProvenance.PLAN,
)
plan_id = plan.identity.plan_id
service.start_strategize(plan_id)
service.complete_strategize(plan_id)
service.execute_plan(plan_id)
return plan_id
class CanRevertToSuite:
"""Benchmark Plan.can_revert_to() validation."""
def setup(self) -> None:
service = _make_service()
plan_id = _create_plan_in_execute(service, "local/bench-can-revert")
self.plan = service.get_plan(plan_id)
def time_can_revert_to_valid(self) -> None:
self.plan.can_revert_to(PlanPhase.STRATEGIZE)
def time_can_revert_to_invalid(self) -> None:
self.plan.can_revert_to(PlanPhase.APPLY)
class RevertPlanSuite:
"""Benchmark PlanLifecycleService.revert_plan() overhead."""
def setup(self) -> None:
self.service = _make_service()
self.counter = 0
def time_revert_plan(self) -> None:
self.counter += 1
name = f"local/bench-revert-{self.counter}"
plan_id = _create_plan_in_execute(self.service, name)
self.service.revert_plan(plan_id, PlanPhase.STRATEGIZE, reason="benchmark")
class AutoRevertSuite:
"""Benchmark auto-reversion from constrained apply."""
def setup(self) -> None:
self.service = _make_service()
self.counter = 0
def time_auto_revert_from_apply(self) -> None:
self.counter += 1
name = f"local/bench-auto-{self.counter}"
self.service.create_action(
name=name,
description="Benchmark action",
definition_of_done="Tests pass",
strategy_actor="local/strategist",
execution_actor="local/executor",
)
plan = self.service.use_action(name)
plan.automation_profile = AutomationProfileRef(
profile_name="ci",
provenance=AutomationProfileProvenance.PLAN,
)
plan_id = plan.identity.plan_id
self.service.start_strategize(plan_id)
# complete_strategize auto-progresses to EXECUTE with "ci" profile
self.service.complete_strategize(plan_id)
plan = self.service.get_plan(plan_id)
if plan.phase != PlanPhase.EXECUTE:
self.service.execute_plan(plan_id)
self.service.start_execute(plan_id)
# complete_execute auto-progresses to APPLY with "ci" profile
self.service.complete_execute(plan_id)
self.service.start_apply(plan_id)
self.service.constrain_apply(plan_id, "benchmark constraint")
self.service.try_auto_revert_from_apply(plan_id, "benchmark")
class LoopGuardSuite:
"""Benchmark loop guard check overhead."""
def setup(self) -> None:
self.service = _make_service()
plan_id = _create_plan_in_execute(self.service, "local/bench-guard")
self.plan = self.service.get_plan(plan_id)
def time_loop_guard_under_limit(self) -> None:
self.plan.reversion_count = 2
self.plan.can_revert_to(PlanPhase.STRATEGIZE)
def time_loop_guard_at_limit(self) -> None:
self.plan.reversion_count = 3
self.plan.can_revert_to(PlanPhase.STRATEGIZE)