Files
cleveragents-core/robot/helper_plan_preflight_guardrails.py
T
aditya 2764fcef5c
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 16s
CI / build (pull_request) Successful in 25s
CI / quality (pull_request) Successful in 34s
CI / typecheck (pull_request) Successful in 39s
CI / security (pull_request) Successful in 52s
CI / unit_tests (pull_request) Successful in 2m51s
CI / integration_tests (pull_request) Successful in 3m41s
CI / docker (pull_request) Successful in 56s
CI / e2e_tests (pull_request) Successful in 3m56s
CI / coverage (pull_request) Successful in 6m28s
CI / benchmark-regression (pull_request) Successful in 38m39s
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

162 lines
5.4 KiB
Python

"""Helper script for Robot Framework plan preflight guardrails tests."""
from __future__ import annotations
import os
import sys
import tempfile
from pathlib import Path
from typing import Any
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
from cleveragents.application.services.plan_preflight_guardrail import (
PlanPreflightGuardrail,
PreflightCheckName,
PreflightRejection,
)
def _test_all_pass() -> None:
"""All 7 pre-flight checks pass with fully populated registries."""
guardrail = PlanPreflightGuardrail()
with tempfile.NamedTemporaryFile(delete=False, suffix=".txt") as tmp:
pass
try:
report = guardrail.run_all_checks(
action_name="test-action",
action_registry={"test-action": {"name": "test-action"}},
actor_registry={
"strategy": "s",
"execution": "e",
"estimation": "est",
"invariant_reconciliation": "ir",
},
tool_names=("tool-a",),
tool_registry={"tool-a": {}},
automation_profile={"name": "auto"},
require_checkpoints=False,
resource_paths=(tmp.name,),
validation_names=("v1",),
validation_registry={"v1": {}},
)
assert report.all_passed
assert len(report.results) == 7
print("all-pass-ok")
finally:
os.unlink(tmp.name)
def _test_action_missing() -> None:
"""PreflightRejection raised when action is missing."""
guardrail = PlanPreflightGuardrail()
try:
guardrail.run_all_checks(
action_name="no-such-action",
action_registry={},
actor_registry={
"strategy": "s",
"execution": "e",
"estimation": "est",
"invariant_reconciliation": "ir",
},
automation_profile={"name": "auto"},
)
raise AssertionError("Expected PreflightRejection")
except PreflightRejection as exc:
assert exc.check == PreflightCheckName.ACTION_SCHEMA
assert "not found" in str(exc)
print("action-missing-ok")
def _test_rollback_check() -> None:
"""Rollback feasibility check detects non-checkpointable tools."""
guardrail = PlanPreflightGuardrail()
result = guardrail.check_rollback_feasibility(
require_checkpoints=True,
tool_capabilities={"safe": True, "unsafe": False},
)
assert not result.passed
assert "unsafe" in result.message
# Skipped when not required
result2 = guardrail.check_rollback_feasibility(
require_checkpoints=False,
tool_capabilities={"unsafe": False},
)
assert result2.passed
assert "skipped" in result2.message
print("rollback-check-ok")
def _test_estimation_warning() -> None:
"""Preflight emits warning for estimation actor without response_format."""
guardrail = PlanPreflightGuardrail()
report = guardrail.run_all_checks(
action_name="test-action",
action_registry={"test-action": {"name": "test-action"}},
actor_registry={
"strategy": {"name": "local/strategist"},
"execution": {"name": "local/executor"},
"estimation": {
"name": "local/estimator",
"context_view": "strategist",
},
"invariant_reconciliation": {"name": "local/reconciler"},
},
tool_names=("tool-a",),
tool_registry={"tool-a": {}},
automation_profile={"name": "auto"},
require_checkpoints=False,
validation_names=("v1",),
validation_registry={"v1": {}},
)
assert report.all_passed
assert any("response_format" in warning.message for warning in report.warnings)
print("estimation-warning-ok")
def _test_estimation_context_view_warning() -> None:
"""Preflight emits warning for estimation actor with wrong context_view."""
guardrail = PlanPreflightGuardrail()
report = guardrail.run_all_checks(
action_name="test-action",
action_registry={"test-action": {"name": "test-action"}},
actor_registry={
"strategy": {"name": "local/strategist"},
"execution": {"name": "local/executor"},
"estimation": {
"name": "local/estimator",
"context_view": "executor",
"response_format": {"type": "object"},
},
"invariant_reconciliation": {"name": "local/reconciler"},
},
tool_names=("tool-a",),
tool_registry={"tool-a": {}},
automation_profile={"name": "auto"},
require_checkpoints=False,
validation_names=("v1",),
validation_registry={"v1": {}},
)
assert report.all_passed
assert any("context_view" in warning.message for warning in report.warnings)
print("estimation-context-view-warning-ok")
if __name__ == "__main__":
cmd = sys.argv[1] if len(sys.argv) > 1 else "all-pass"
dispatch: dict[str, Any] = {
"all-pass": _test_all_pass,
"action-missing": _test_action_missing,
"rollback-check": _test_rollback_check,
"estimation-warning": _test_estimation_warning,
"estimation-context-view-warning": _test_estimation_context_view_warning,
}
fn = dispatch.get(cmd)
if fn:
fn()
else:
print(f"Unknown command: {cmd}", file=sys.stderr)
sys.exit(1)