"""Helper script for Robot Framework decision DI wiring smoke tests. Usage: python robot/helper_decision_di.py Subcommands: resolve-service Verify DecisionService resolves from DI container record-integration Verify decision recording during lifecycle transitions """ from __future__ import annotations import os import sys from pathlib import Path from unittest.mock import create_autospec # Ensure src is importable when run from workspace root sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src")) from cleveragents.application.services.decision_service import DecisionService # noqa: I001 from cleveragents.application.services.plan_lifecycle_service import ( PlanLifecycleService, ) from cleveragents.infrastructure.database.unit_of_work import UnitOfWork # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- def _make_uow() -> UnitOfWork: """Create a UoW backed by an in-memory SQLite database.""" uow = UnitOfWork("sqlite:///:memory:") uow.init_database() return uow # --------------------------------------------------------------------------- # Subcommands # --------------------------------------------------------------------------- def _resolve_service() -> None: """Verify DecisionService can be instantiated from the container.""" os.environ["CLEVERAGENTS_DATABASE_URL"] = "sqlite:///:memory:" try: from cleveragents.application.container import get_container, reset_container reset_container() container = get_container() svc = container.decision_service() assert isinstance(svc, DecisionService), ( f"Expected DecisionService, got {type(svc).__name__}" ) # Verify it's a Factory (different instances per call) svc2 = container.decision_service() assert svc is not svc2, "Factory should return different instances" reset_container() finally: os.environ.pop("CLEVERAGENTS_DATABASE_URL", None) print("resolve-service-ok") def _record_integration() -> None: """Verify decision recording during plan lifecycle transitions.""" uow = _make_uow() from cleveragents.config.settings import Settings mock_settings = create_autospec(Settings, instance=True) mock_settings.database_url = "sqlite:///:memory:" mock_settings.async_enabled = False decision_svc = DecisionService(settings=mock_settings, unit_of_work=uow) lifecycle_svc = PlanLifecycleService( settings=mock_settings, unit_of_work=uow, decision_service=decision_svc, ) # Create action + plan lifecycle_svc.create_action( name="local/robot-di-test", description="Robot DI integration test", definition_of_done="Pass", strategy_actor="local/s", execution_actor="local/e", ) plan = lifecycle_svc.use_action("local/robot-di-test") plan_id = plan.identity.plan_id # Start strategize -> should record a strategy_choice decision lifecycle_svc.start_strategize(plan_id) decisions = decision_svc.list_decisions(plan_id) strategy_decisions = [ d for d in decisions if str(d.decision_type) == "strategy_choice" ] assert len(strategy_decisions) >= 1, ( f"Expected strategy_choice decision, got {len(strategy_decisions)}" ) # Complete strategize and progress to execute lifecycle_svc.complete_strategize(plan_id) plan = lifecycle_svc.get_plan(plan_id) from cleveragents.domain.models.core.plan import PlanPhase if plan.phase == PlanPhase.STRATEGIZE: lifecycle_svc.execute_plan(plan_id) # Start execute -> should record an implementation_choice decision lifecycle_svc.start_execute(plan_id) decisions = decision_svc.list_decisions(plan_id) impl_decisions = [ d for d in decisions if str(d.decision_type) == "implementation_choice" ] assert len(impl_decisions) >= 1, ( f"Expected implementation_choice decision, got {len(impl_decisions)}" ) print("record-integration-ok") # --------------------------------------------------------------------------- # Dispatcher # --------------------------------------------------------------------------- _COMMANDS = { "resolve-service": _resolve_service, "record-integration": _record_integration, } def main() -> None: if len(sys.argv) < 2: raise SystemExit(f"Usage: {sys.argv[0]} <{'|'.join(_COMMANDS)}>") command = sys.argv[1] handler = _COMMANDS.get(command) if handler is None: raise SystemExit(f"Unknown command: {command}") handler() if __name__ == "__main__": main()