Files
temp/src/cleveragents/actor/role_validation.py
aditya 2764fcef5c fix(actor,preflight,tests): resolve PR #975 review findings and stabilize full-suite coverage runs
Address review-driven fixes across actor schema, preflight guardrails, docs/examples,
and Behave/Robot coverage: unify preflight warning behavior with shared role-warning logic,
resolve actor-name to config payloads in production preflight flow, harden response_format
validation/coercion edge cases, extract duplicated helper logic, and expand negative-path
test coverage. Also fix cross-scenario patcher leakage in step modules to eliminate
full-run-only coverage failures.
2026-03-18 06:58:39 +00:00

90 lines
2.9 KiB
Python

"""Role-aware compatibility helpers for actor configurations."""
from __future__ import annotations
import logging
from enum import StrEnum
logger = logging.getLogger(__name__)
class RoleHint(StrEnum):
"""Optional role hint used for role-aware compatibility checks."""
STRATEGY = "strategy"
EXECUTION = "execution"
ESTIMATION = "estimation"
INVARIANT_RECONCILIATION = "invariant_reconciliation"
REVIEW = "review"
def _coerce_role_hint(value: object) -> RoleHint | None:
"""Coerce role hint values from raw payloads into ``RoleHint``.
Accepts enum values directly and string inputs case-insensitively.
Returns ``None`` for non-string/unrecognized values.
"""
if isinstance(value, RoleHint):
return value
if isinstance(value, str):
try:
return RoleHint(value.lower())
except ValueError:
logger.warning("Unrecognized role_hint value in actor config: %r", value)
return None
return None
def _coerce_context_view(value: object) -> str | None:
"""Coerce context_view values while preserving unrecognized strings."""
if value is None:
return None
if isinstance(value, str):
normalized = value.lower()
if normalized in {"strategist", "executor", "reviewer", "full"}:
return normalized
return value
enum_value = getattr(value, "value", None)
if isinstance(enum_value, str):
return enum_value.lower()
return None
def actor_role_warnings(config: object) -> list[str]:
"""Return non-fatal role compatibility warnings for actor configs."""
if isinstance(config, dict):
role_hint = _coerce_role_hint(config.get("role_hint"))
context_view = _coerce_context_view(config.get("context_view"))
response_format = config.get("response_format")
if not isinstance(response_format, dict):
nested = config.get("config")
if isinstance(nested, dict) and isinstance(
nested.get("response_format"), dict
):
response_format = nested.get("response_format")
else:
response_format = None
else:
role_hint = _coerce_role_hint(getattr(config, "role_hint", None))
context_view = _coerce_context_view(getattr(config, "context_view", None))
response_format = getattr(config, "response_format", None)
if role_hint != RoleHint.ESTIMATION:
return []
warnings: list[str] = []
if not isinstance(response_format, dict) or not response_format:
warnings.append(
"Estimation actors should define 'response_format' for structured output."
)
if context_view not in (None, "strategist"):
warnings.append(
"Estimation actors should use context_view 'strategist' "
"for planning context."
)
return warnings
__all__ = ["RoleHint", "actor_role_warnings"]