"""Step definitions for exec_env_precedence.feature. Self-contained step file for the 6-level execution environment precedence chain. All imports are top-level and guarded. """ from __future__ import annotations from behave import then, when from cleveragents.application.services.execution_environment_resolver import ( ExecutionEnvironmentResolver, ) def _resolver() -> ExecutionEnvironmentResolver: return ExecutionEnvironmentResolver() # ── 6-Level Precedence Chain ───────────────────────────── @when( 'I resolve precedence with plan_env "{plan}" plan_priority "{pp}" ' 'project_env "{proj}" project_priority "{projp}" ' "devcontainer {dc}" ) def step_resolve_full( context: object, plan: str, pp: str, proj: str, projp: str, dc: str, ) -> None: context.prec_resolved = _resolver().resolve_with_precedence( plan_env=plan, plan_priority=pp, project_env=proj, project_priority=projp, devcontainer_available=dc.lower() == "true", ) @when( 'I resolve precedence with tool_env "{tool}" plan_env "{plan}" ' 'plan_priority "{pp}" devcontainer {dc}' ) def step_resolve_tool( context: object, tool: str, plan: str, pp: str, dc: str, ) -> None: context.prec_resolved = _resolver().resolve_with_precedence( tool_env=tool, plan_env=plan, plan_priority=pp, devcontainer_available=dc.lower() == "true", ) @when( 'I resolve precedence with project_env "{proj}" ' 'project_priority "{projp}" devcontainer {dc}' ) def step_resolve_proj(context: object, proj: str, projp: str, dc: str) -> None: context.prec_resolved = _resolver().resolve_with_precedence( project_env=proj, project_priority=projp, devcontainer_available=dc.lower() == "true", ) @when("I resolve precedence with devcontainer {dc}") def step_resolve_default(context: object, dc: str) -> None: context.prec_resolved = _resolver().resolve_with_precedence( devcontainer_available=dc.lower() == "true", ) @when( 'I resolve precedence with plan_env "{plan}" project_env "{proj}" devcontainer {dc}' ) def step_resolve_both_fb(context: object, plan: str, proj: str, dc: str) -> None: context.prec_resolved = _resolver().resolve_with_precedence( plan_env=plan, project_env=proj, devcontainer_available=dc.lower() == "true", ) @then('the precedence resolved environment should be "{expected}"') def step_check_resolved(context: object, expected: str) -> None: actual = context.prec_resolved.value assert actual == expected, f"Expected '{expected}', got '{actual}'" # ── Devcontainer helpers ───────────────────────────────── @when('I check has_devcontainer with types "{types}" for precedence') def step_has_dc(context: object, types: str) -> None: type_list = [t.strip() for t in types.split(",")] context.prec_has_dc = _resolver().has_devcontainer(type_list) @then("has_devcontainer should be {expected} for precedence") def step_has_dc_check(context: object, expected: str) -> None: assert context.prec_has_dc == (expected.lower() == "true") # ── ContextConfig priority field ───────────────────────── @when('I create a ContextConfig with priority "{priority}" for precedence') def step_ctx_config(context: object, priority: str) -> None: from cleveragents.domain.models.core.project import ContextConfig context.prec_ctx_config = ContextConfig( execution_environment="container", execution_env_priority=priority, ) @then('the context config priority should be "{priority}" for precedence') def step_ctx_config_check(context: object, priority: str) -> None: assert context.prec_ctx_config.execution_env_priority == priority # ── DAG walk ───────────────────────────────────────────── @when('I resolve with DAG walk from "{rid}" with devcontainer ancestor for precedence') def step_dag_with_dc(context: object, rid: str) -> None: context.prec_resolved = _resolver().resolve_with_dag( resource_id=rid, linked_resource_types={ rid: "fs-file", "res-dir": "fs-directory", "res-dc": "devcontainer-instance", }, parent_map={rid: ["res-dir"], "res-dir": ["res-dc"]}, ) @when( 'I resolve with DAG walk from "{rid}" without devcontainer ancestor for precedence' ) def step_dag_no_dc(context: object, rid: str) -> None: context.prec_resolved = _resolver().resolve_with_dag( resource_id=rid, linked_resource_types={ rid: "fs-file", "res-dir": "fs-directory", "res-checkout": "git-checkout", }, parent_map={rid: ["res-dir"], "res-dir": ["res-checkout"]}, ) # ── Container reference ────────────────────────────────── @when('I parse container ref "{ref}" for precedence') def step_parse_ref(context: object, ref: str) -> None: _, name = _resolver().parse_container_ref(ref) context.prec_ref_name = name @then('the container ref name should be "{name}" for precedence') def step_ref_name(context: object, name: str) -> None: assert context.prec_ref_name == name