Files
cleveragents-core/features/actor_compiler_coverage.feature
T
freemo c47e6445d0
CI / quality (pull_request) Successful in 19s
CI / lint (pull_request) Successful in 22s
CI / benchmark-publish (pull_request) Has been skipped
CI / security (pull_request) Successful in 33s
CI / build (pull_request) Successful in 26s
CI / typecheck (pull_request) Successful in 1m0s
CI / integration_tests (pull_request) Successful in 4m56s
CI / unit_tests (pull_request) Successful in 15m11s
CI / docker (pull_request) Successful in 1m33s
CI / benchmark-regression (pull_request) Successful in 20m55s
CI / coverage (pull_request) Successful in 33m42s
CI / lint (push) Successful in 13s
CI / build (push) Successful in 15s
CI / quality (push) Successful in 17s
CI / security (push) Successful in 28s
CI / typecheck (push) Successful in 32s
CI / benchmark-regression (push) Has been skipped
CI / integration_tests (push) Successful in 3m3s
CI / benchmark-publish (push) Successful in 10m8s
CI / unit_tests (push) Successful in 12m42s
CI / docker (push) Successful in 39s
CI / coverage (push) Has been cancelled
feat(actor): compile hierarchical actor configs to LangGraph
Add ActorCompiler module that translates GRAPH-type ActorConfigSchema
definitions into LangGraph NodeConfig/Edge structures with LSP binding
metadata. Includes subgraph resolution with cross-actor cycle detection,
entry/exit validation, and CompilationMetadata for diagnostics.

New files:
- src/cleveragents/actor/compiler.py: Core compiler with compile_actor()
- features/actor_compiler.feature: 13 Behave scenarios
- features/steps/actor_compiler_steps.py: Step definitions
- robot/actor_compiler.robot: 4 Robot smoke tests
- benchmarks/actor_compiler_bench.py: ASV performance benchmarks
- docs/reference/actor_compiler.md: Compilation pipeline reference

Modified:
- src/cleveragents/actor/__init__.py: Export compiler types
- vulture_whitelist.py: Whitelist new public API

ISSUES CLOSED: #158
2026-02-24 17:57:18 +00:00

193 lines
12 KiB
Gherkin

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"