Files
cleveragents-core/benchmarks/permission_check_bench.py
T
freemo 583e6b7ea2
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 14s
CI / build (pull_request) Successful in 16s
CI / quality (pull_request) Successful in 17s
CI / security (pull_request) Successful in 36s
CI / typecheck (pull_request) Successful in 54s
CI / unit_tests (pull_request) Successful in 2m39s
CI / integration_tests (pull_request) Successful in 3m10s
CI / docker (pull_request) Successful in 40s
CI / coverage (pull_request) Successful in 5m0s
CI / lint (push) Successful in 14s
CI / build (push) Successful in 15s
CI / quality (push) Successful in 16s
CI / security (push) Successful in 34s
CI / typecheck (push) Successful in 35s
CI / benchmark-regression (push) Has been skipped
CI / unit_tests (push) Successful in 2m23s
CI / docker (push) Successful in 38s
CI / integration_tests (push) Successful in 3m8s
CI / coverage (push) Successful in 5m10s
CI / benchmark-publish (push) Successful in 16m26s
CI / benchmark-regression (pull_request) Successful in 30m12s
feat(correcting-plans): implement Predictive Error Prevention (Layer 4) with Error Pattern Database
Implement spec-mandated Layer 4 Predictive Error Prevention system:

- ErrorPattern domain model with pattern text, historical failures,
  preventive checks, frequency tracking, and keyword-based matching.
- ErrorPatternRepository with in-memory CRUD + context-matching query.
- ErrorPatternService with record_failure(), match_patterns(), and
  get_statistics() methods.
- Wire into plan execution via plan_lifecycle_service pre-execution hook.
- Add error pattern statistics to CLI diagnostics output.

Behave BDD: 11 scenarios covering recording, matching, formatting, stats.
Robot Framework: 3 integration smoke tests.
ASV benchmarks: pattern matching performance.

ISSUES CLOSED: #571
2026-03-08 21:53:21 -04:00

116 lines
3.6 KiB
Python

"""Benchmarks for the permission check enforcement baseline.
Measures the overhead of permission checks in both local mode
(fast-path) and server mode with varying numbers of role bindings.
"""
from __future__ import annotations
import os
from typing import ClassVar
from cleveragents.application.services.permission_service import (
PermissionService,
)
from cleveragents.domain.models.core.permission import (
ROLE_PERMISSIONS,
PermissionAction,
PermissionRole,
PermissionScope,
RoleBinding,
)
_SERVER_MODE_ENV = "CLEVERAGENTS_SERVER_MODE"
def _make_bindings(n: int) -> list[RoleBinding]:
"""Create *n* role bindings for distinct principals."""
return [
RoleBinding(
principal=f"user-{i}",
role=PermissionRole.EDITOR,
scope=PermissionScope.PROJECT,
scope_id="proj-bench",
)
for i in range(n)
]
class TimePermissionCheckLocal:
"""Benchmark permission checks in local mode (fast-path)."""
def setup(self) -> None:
os.environ.pop(_SERVER_MODE_ENV, None)
self.svc = PermissionService()
def time_local_check(self) -> None:
"""Single local-mode permission check."""
self.svc.check_permission(
principal="alice",
action=PermissionAction.WRITE,
scope=PermissionScope.PROJECT,
scope_id="proj-1",
)
def time_local_check_all_actions(self) -> None:
"""Check every action in local mode."""
for action in PermissionAction:
self.svc.check_permission(
principal="alice",
action=action,
scope=PermissionScope.PROJECT,
scope_id="proj-1",
)
class TimePermissionCheckServer:
"""Benchmark permission checks in server mode."""
params: ClassVar[list[int]] = [0, 10, 100]
param_names: ClassVar[list[str]] = ["num_bindings"]
def setup(self, num_bindings: int) -> None:
os.environ[_SERVER_MODE_ENV] = "true"
bindings = _make_bindings(num_bindings)
self.svc = PermissionService(bindings=bindings)
def teardown(self, num_bindings: int) -> None:
os.environ.pop(_SERVER_MODE_ENV, None)
def time_server_check_denied(self, num_bindings: int) -> None:
"""Permission check that results in denial (no matching binding)."""
self.svc.check_permission(
principal="nonexistent",
action=PermissionAction.WRITE,
scope=PermissionScope.PROJECT,
scope_id="proj-bench",
)
def time_server_check_allowed(self, num_bindings: int) -> None:
"""Permission check that matches the last binding.
When *num_bindings* is 0 no binding can match, so a denied
check is performed instead to avoid an empty benchmark body.
"""
principal = f"user-{num_bindings - 1}" if num_bindings > 0 else "nonexistent"
self.svc.check_permission(
principal=principal,
action=PermissionAction.READ,
scope=PermissionScope.PROJECT,
scope_id="proj-bench",
)
class TimeRolePermissionsLookup:
"""Benchmark ROLE_PERMISSIONS constant lookups."""
def time_lookup_all_roles(self) -> None:
"""Look up allowed actions for every role."""
for role in PermissionRole:
_ = ROLE_PERMISSIONS[role]
def time_check_action_in_role(self) -> None:
"""Check membership of an action in each role's permission set."""
for role in PermissionRole:
_ = PermissionAction.READ in ROLE_PERMISSIONS[role]