Feature: Actor compiler full coverage for node mapping, edge mapping, LSP bindings, and error paths As a CleverAgents developer I want every code path in the actor compiler module to be tested So that the compiler is reliable and regressions are caught early # ──────────────────────────────────────────────────────────── # Node type mapping (_map_node and _NODE_TYPE_MAP) # ──────────────────────────────────────────────────────────── Scenario: Compile a graph with all four node types mapped correctly Given a GRAPH actor config containing AGENT, TOOL, CONDITIONAL, and SUBGRAPH nodes When I compile the full-coverage actor config Then the compilation should succeed without errors And the compiled node "agent_node" should have LangGraph type "agent" And the compiled node "tool_node" should have LangGraph type "tool" And the compiled node "cond_node" should have LangGraph type "conditional" And the compiled node "sub_node" should have LangGraph type "subgraph" Scenario: Agent node config maps agent field to NodeConfig Given a GRAPH actor config with an agent node configured as "my_agent" When I compile the full-coverage actor config Then the compilation should succeed without errors And the compiled node "agent_node" should have agent set to "my_agent" Scenario: Conditional node config maps function field to NodeConfig Given a GRAPH actor config with a conditional node configured with function "route_fn" When I compile the full-coverage actor config Then the compilation should succeed without errors And the compiled node "cond_node" should have function set to "route_fn" Scenario: Tool node config maps tools list to NodeConfig Given a GRAPH actor config with a tool node configured with tools "lint,format" When I compile the full-coverage actor config Then the compilation should succeed without errors And the compiled node "tool_node" should have tools "lint" and "format" Scenario: Subgraph node config maps actor_ref to NodeConfig subgraph field Given a GRAPH actor config with a subgraph node referencing actor "workflows/child" When I compile the full-coverage actor config Then the compilation should succeed without errors And the compiled node "sub_node" should have subgraph set to "workflows/child" # ──────────────────────────────────────────────────────────── # Edge mapping (_map_edge) # ──────────────────────────────────────────────────────────── Scenario: Edge without condition compiles to null condition field Given a GRAPH actor config with an unconditional edge from "a" to "b" When I compile the full-coverage actor config Then the compilation should succeed without errors And the compiled edge from "a" to "b" should have a null condition Scenario: Edge with condition compiles to expression dict Given a GRAPH actor config with a conditional edge from "a" to "b" with condition "state.get('done')" When I compile the full-coverage actor config Then the compilation should succeed without errors And the compiled edge from "a" to "b" should have condition expression "state.get('done')" Scenario: Edge priority is recorded in compiled edge metadata Given a GRAPH actor config with an edge from "a" to "b" with priority 5 When I compile the full-coverage actor config Then the compilation should succeed without errors And the compiled edge from "a" to "b" should have metadata priority 5 # ──────────────────────────────────────────────────────────── # LSP binding extraction edge cases (_extract_lsp_bindings) # ──────────────────────────────────────────────────────────── Scenario: Non-list LSP bindings config value is safely ignored Given a GRAPH actor config where lsp_bindings is a string instead of a list When I compile the full-coverage actor config Then the compilation should succeed without errors And the compilation metadata should have 0 LSP bindings Scenario: Non-dict entry in LSP bindings list is skipped Given a GRAPH actor config where lsp_bindings contains a non-dict entry When I compile the full-coverage actor config Then the compilation should succeed without errors And the compilation metadata should have 0 LSP bindings Scenario: LSP binding with empty server name is skipped Given a GRAPH actor config where an LSP binding has an empty server name When I compile the full-coverage actor config Then the compilation should succeed without errors And the compilation metadata should have 0 LSP bindings Scenario: LSP binding with non-string server name is skipped Given a GRAPH actor config where an LSP binding has a numeric server name When I compile the full-coverage actor config Then the compilation should succeed without errors And the compilation metadata should have 0 LSP bindings Scenario: LSP binding with missing server name key is skipped Given a GRAPH actor config where an LSP binding is missing the server name key When I compile the full-coverage actor config Then the compilation should succeed without errors And the compilation metadata should have 0 LSP bindings Scenario: Multiple valid LSP bindings are extracted from a single node Given a GRAPH actor config with two valid LSP bindings on one node When I compile the full-coverage actor config Then the compilation should succeed without errors And the compilation metadata should have 2 LSP bindings And the LSP binding servers should include "local/pyright" and "local/ts" # ──────────────────────────────────────────────────────────── # Subgraph cycle detection edge cases (_detect_subgraph_cycles) # ──────────────────────────────────────────────────────────── Scenario: Subgraph node with empty actor_ref is skipped during cycle detection Given a GRAPH actor config with a subgraph node that has an empty actor_ref When I compile the full-coverage actor config with a resolver Then the compilation should succeed without errors Scenario: Resolver returning None for a referenced actor skips that node Given a GRAPH actor config with a subgraph referencing actor name "workflows/missing" And a cycle-detection resolver that returns None for all names When I compile the full-coverage actor config with a resolver Then the compilation should succeed without errors Scenario: Referenced actor that is not GRAPH type is skipped during cycle detection Given a GRAPH actor config with a subgraph referencing actor name "tools/helper" And a cycle-detection resolver where "tools/helper" is an LLM type actor When I compile the full-coverage actor config with a resolver Then the compilation should succeed without errors Scenario: Referenced actor with no route definition is skipped during cycle detection Given a GRAPH actor config with a subgraph referencing actor name "workflows/no-route" And a cycle-detection resolver where "workflows/no-route" is a GRAPH actor with no route When I compile the full-coverage actor config with a resolver Then the compilation should succeed without errors Scenario: Deep three-level subgraph cycle is detected Given a GRAPH actor config named "workflows/alpha" with subgraph ref to "workflows/beta" And a cycle-detection resolver where "workflows/beta" references "workflows/gamma" and "workflows/gamma" references "workflows/alpha" When I compile the full-coverage actor config with a resolver Then the compilation should fail with a SubgraphCycleError And the compilation error message should mention "cycle" # ──────────────────────────────────────────────────────────── # compile_actor error paths # ──────────────────────────────────────────────────────────── Scenario: Intra-graph cycle raises SubgraphCycleError during compilation Given a GRAPH actor config with a cyclic route that bypasses schema validation When I compile the full-coverage actor config Then the compilation should fail with a SubgraphCycleError And the compilation error message should mention "intra-graph" Scenario: Edge referencing missing from_node raises MissingNodeError Given a GRAPH actor config with an edge whose from_node does not exist in the node list When I compile the full-coverage actor config Then the compilation should fail with a MissingNodeError And the compilation error message should mention "from_node" Scenario: Edge referencing missing to_node raises MissingNodeError Given a GRAPH actor config with an edge whose to_node does not exist in the node list When I compile the full-coverage actor config Then the compilation should fail with a MissingNodeError And the compilation error message should mention "to_node" Scenario: Invalid entry node raises InvalidEntryExitError Given a GRAPH actor config whose entry node does not match any compiled node When I compile the full-coverage actor config Then the compilation should fail with an InvalidEntryExitError And the compilation error message should mention "Entry node" Scenario: Invalid exit node raises InvalidEntryExitError Given a GRAPH actor config whose exit node does not match any compiled node When I compile the full-coverage actor config Then the compilation should fail with an InvalidEntryExitError And the compilation error message should mention "Exit node" # ──────────────────────────────────────────────────────────── # Model defaults and result bundle # ──────────────────────────────────────────────────────────── Scenario: CompilationMetadata defaults to empty collections Given a freshly constructed CompilationMetadata with no arguments Then the metadata node_ids should be an empty list And the metadata tool_nodes should be an empty list And the metadata lsp_bindings should be an empty list And the metadata subgraph_refs should be an empty dict And the metadata entry_node should be an empty string And the metadata exit_nodes should be an empty list Scenario: CompiledActor preserves actor name and entry point from config Given a GRAPH actor config named "workflows/test" with entry "start" When I compile the full-coverage actor config Then the compilation should succeed without errors And the compiled actor name should be "workflows/test" And the compiled actor entry_point field should be "start"