Files
cleveragents-core/features/actor_v3_schema.feature
T
hurui200320 d512123d1c
CI / lint (pull_request) Successful in 48s
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 54s
CI / quality (pull_request) Successful in 1m52s
CI / typecheck (pull_request) Successful in 1m57s
CI / security (pull_request) Successful in 1m58s
CI / helm (pull_request) Successful in 27s
CI / push-validation (pull_request) Successful in 21s
CI / integration_tests (pull_request) Successful in 6m43s
CI / unit_tests (pull_request) Successful in 9m4s
CI / docker (pull_request) Successful in 1m42s
CI / coverage (pull_request) Successful in 11m45s
CI / e2e_tests (pull_request) Successful in 3m22s
CI / status-check (pull_request) Successful in 3s
CI / benchmark-publish (push) Failing after 44s
CI / build (push) Successful in 49s
CI / lint (push) Successful in 1m8s
CI / helm (push) Successful in 38s
CI / quality (push) Successful in 1m25s
CI / security (push) Successful in 1m26s
CI / typecheck (push) Successful in 1m30s
CI / push-validation (push) Successful in 23s
CI / e2e_tests (push) Successful in 3m52s
CI / integration_tests (push) Successful in 4m8s
CI / coverage (push) Successful in 12m30s
CI / unit_tests (push) Successful in 6m32s
CI / docker (push) Successful in 1m39s
CI / status-check (push) Successful in 3s
fix(actor): support v3 Actor YAML schema in CLI registration and execution
The actor CLI was ignoring the v3 ActorConfigSchema format, preventing
spec-compliant actors with type/route/skills/lsp fields from being
registered or executed.  Three components were fixed:

ActorConfiguration.from_blob() now detects v3 format (top-level "type"
key with value llm/graph/tool) and extracts provider from the model
string, falling through to v2 extraction when v3 does not match.

ActorRegistry.add() now routes v3 YAML through full ActorConfigSchema
validation, persists description/skills/lsp in the config blob, and
compiles graph actors with compile_actor() storing metadata.  Legacy v2
YAML continues through the original path unchanged.

ReactiveConfigParser._build() now synthesises reactive agents and graph
routes from v3 actor data so that agents actor run can execute v3 actors
through the existing ReactiveCleverAgentsApp pipeline.

ISSUES CLOSED: #6283
2026-04-27 05:00:54 +00:00

246 lines
12 KiB
Gherkin

Feature: v3 Actor YAML schema support in CLI and registry
As a developer using v3 actor YAML configs
I want the CLI and registry to validate, persist, and execute v3 schema actors
So that spec-compliant actors with skills, LSP bindings, and LangGraph routes work
Scenario: ActorConfiguration.from_blob extracts provider and model from v3 LLM YAML
Given a v3 LLM actor blob with model "gpt-4"
When I call ActorConfiguration.from_blob with the v3 blob
Then the configuration should have provider "custom"
And the configuration should have model "gpt-4"
Scenario: ActorConfiguration.from_blob infers provider from model with slash
Given a v3 LLM actor blob with model "openai/gpt-4"
When I call ActorConfiguration.from_blob with the v3 blob
Then the configuration should have provider "openai"
And the configuration should have model "openai/gpt-4"
Scenario: ActorConfiguration.from_blob infers custom provider for slash-prefixed model
Given a v3 LLM actor blob with model "/gpt-4"
When I call ActorConfiguration.from_blob with the v3 blob
Then the configuration should have provider "custom"
And the configuration should have model "/gpt-4"
Scenario: ActorConfiguration.from_blob builds graph descriptor for graph actors
Given a v3 graph actor blob with a route block
When I call ActorConfiguration.from_blob with the v3 blob
Then the configuration should have a graph_descriptor with type "graph"
Scenario: ActorConfiguration.from_blob falls through to v2 for legacy YAML
Given a v2 actor blob with agents and routes
When I call ActorConfiguration.from_blob with the v2 blob
Then the configuration should have provider "openai"
And the configuration should have model "gpt-4"
Scenario: ActorRegistry.add validates v3 LLM actor YAML
Given a mock actor service for v3 testing
And a v3 LLM actor YAML text
When I call ActorRegistry.add with the v3 YAML
Then the actor should be persisted with v3 fields in config_blob
And the persisted config_blob should contain skills
And the persisted config_blob should contain lsp bindings
Scenario: ActorRegistry.add rejects v3 YAML without required description
Given a mock actor service for v3 testing
And a v3 actor YAML text missing description
When I call ActorRegistry.add with the invalid v3 YAML
Then a ValidationError should be raised mentioning description
Scenario: ActorRegistry.add validates and compiles v3 graph actor
Given a mock actor service for v3 testing
And a v3 graph actor YAML text with route
When I call ActorRegistry.add with the v3 graph YAML
Then the actor should be persisted with compiled metadata
And the graph_descriptor should contain route information
Scenario: ReactiveConfigParser handles v3 LLM actor format
Given a v3 LLM actor config dict
When I parse the v3 config through ReactiveConfigParser
Then the reactive config should have one agent
And the agent config should contain the model
And the agent config should contain skills
Scenario: ReactiveConfigParser handles v3 graph actor format
Given a v3 graph actor config dict with route
When I parse the v3 config through ReactiveConfigParser
Then the reactive config should have agents for each node
And the reactive config should have a graph route
And the graph route edges should use source and target keys
Scenario: v3 format detection returns false for v2 data
Given a v2 actor config dict with agents key
When I check if the config is v3 format
Then it should not be detected as v3
# M14: test update=True path
Scenario: ActorRegistry.add with update=True overwrites existing actor
Given a mock actor service for v3 testing
And an existing actor in the mock service
And a v3 LLM actor YAML text
When I call ActorRegistry.add with update=True for the v3 YAML
Then the actor should be persisted successfully with update
# M15: test type:tool extraction and parsing paths
# from_blob requires model for ActorConfiguration — tool actors without
# model raise ValueError. The proper v3 path is ActorRegistry.add().
Scenario: ActorConfiguration.from_blob rejects type tool without model
Given a v3 tool actor blob without model
When I call ActorConfiguration.from_blob with the v3 tool blob
Then the tool actor from_blob should raise ValueError for missing model
Scenario: ActorRegistry.add validates v3 tool actor YAML
Given a mock actor service for v3 testing
And a v3 tool actor YAML text
When I call ActorRegistry.add with the v3 tool YAML
Then the tool actor should be persisted with type tool
# m13: test _build_from_v3 with lsp as dict
Scenario: ReactiveConfigParser handles v3 LLM actor with lsp as dict
Given a v3 LLM actor config dict with lsp as dict
When I parse the v3 config through ReactiveConfigParser
Then the reactive config should have one agent
And the agent config should contain lsp as dict
# m13: test context_view, memory, env_vars, response_format propagation
Scenario: ReactiveConfigParser propagates context_view memory env_vars and response_format
Given a v3 LLM actor config dict with context_view and memory
When I parse the v3 config through ReactiveConfigParser
Then the reactive config should have one agent
And the agent config should contain context_view
And the agent config should contain memory settings
And the agent config should contain env_vars
And the agent config should contain response_format
# m13: positive _is_v3_format test
Scenario: v3 format detection returns true for v3 LLM data
Given a v3 LLM actor config dict
When I check if the v3 LLM config is v3 format
Then it should be detected as v3
# Cycle 2 review: defensive guard BDD coverage
Scenario: ReactiveConfigParser rejects graph with invalid entry_node
Given a v3 graph actor config dict with invalid entry_node
When I parse the v3 config through ReactiveConfigParser expecting error
Then a ConfigurationError should be raised mentioning entry_node
Scenario: ReactiveConfigParser skips edges with missing from_node or to_node
Given a v3 graph actor config dict with incomplete edges
When I parse the v3 config through ReactiveConfigParser
Then the graph route should have fewer edges than the raw input
Scenario: ReactiveConfigParser skips non-dict edge entries
Given a v3 graph actor config dict with non-dict edges
When I parse the v3 config through ReactiveConfigParser
Then the graph route should have only valid dict edges
# Coverage: v3_registry.py — name without slash gets local/ prefix
Scenario: ActorRegistry.add namespaces bare actor name with local prefix
Given a mock actor service for v3 testing
And a v3 LLM actor YAML text with bare name
When I call ActorRegistry.add with the bare-name v3 YAML
Then the persisted actor name should be prefixed with local
# Coverage: v3_registry.py — unsafe actor rejected without allow_unsafe
Scenario: ActorRegistry.add rejects unsafe v3 actor without allow_unsafe flag
Given a mock actor service for v3 testing
And a v3 LLM actor YAML text marked unsafe
When I call ActorRegistry.add with the unsafe v3 YAML
Then a ValidationError should be raised mentioning unsafe
# Coverage: v3_registry.py — duplicate actor rejected when update=False
Scenario: ActorRegistry.add rejects duplicate v3 actor when update is False
Given a mock actor service for v3 testing
And an existing actor in the mock service
And a v3 LLM actor YAML text
When I call ActorRegistry.add with the v3 YAML expecting error
Then a ValidationError should be raised mentioning already exists
# Coverage: v3_registry.py — ActorCompilationError during graph compilation
Scenario: ActorRegistry.add persists graph actor even when compilation fails
Given a mock actor service for v3 testing
And a v3 graph actor YAML text with route
When I call ActorRegistry.add with the v3 graph YAML and compilation fails
Then the actor should still be persisted without compiled metadata
# Coverage: registry.py — _ensure_namespaced via get()
Scenario: ActorRegistry.get namespaces bare actor name with local prefix
Given a mock actor service for v3 testing
When I call ActorRegistry.get with a bare actor name
Then the actor service should be queried with local-prefixed name
# Coverage: registry.py — add() with non-dict YAML
Scenario: ActorRegistry.add rejects non-mapping YAML
Given a mock actor service for v3 testing
When I call ActorRegistry.add with a non-mapping YAML string
Then a ValidationError should be raised mentioning mapping
# Coverage: registry.py — _add_legacy v3 schema validation failure
Scenario: ActorRegistry._add_legacy rejects invalid v3 YAML via schema validation
Given a mock actor service for v3 testing
And a legacy v3 YAML text with invalid schema
When I call ActorRegistry.add with the legacy invalid v3 YAML
Then a ValidationError should be raised mentioning invalid v3 actor
# Coverage: registry.py — _add_legacy missing provider/model in non-v3 blob
Scenario: ActorRegistry._add_legacy rejects non-v3 blob missing provider and model
Given a mock actor service for v3 testing
And a legacy non-v3 YAML text missing provider and model
When I call ActorRegistry.add with the legacy non-v3 YAML
Then a ValidationError should be raised mentioning provider and model
# Coverage: registry.py — _add_legacy unsafe flag rejection
Scenario: ActorRegistry._add_legacy rejects unsafe legacy actor without allow_unsafe
Given a mock actor service for v3 testing
And a legacy actor YAML text marked unsafe
When I call ActorRegistry.add with the legacy unsafe YAML
Then a ValidationError should be raised mentioning unsafe
# Coverage: registry.py — upsert_actor v3 validation failure
Scenario: ActorRegistry.upsert_actor rejects invalid v3 config_blob
Given a mock actor service for v3 testing
When I call ActorRegistry.upsert_actor with an invalid v3 config_blob
Then a ValidationError should be raised mentioning invalid v3 actor
# Coverage: config_parser.py — _merge with new=None
Scenario: ReactiveConfigParser merge handles None new dict gracefully
When I merge a None dict into a base config
Then the base config should remain unchanged
# Coverage: config_parser.py — missing model for llm actor
Scenario: ReactiveConfigParser rejects v3 LLM actor with missing model
Given a v3 LLM actor config dict with no model field
When I parse the v3 config through ReactiveConfigParser expecting error
Then a ConfigurationError should be raised mentioning model
# Coverage: config_parser.py — lsp_capabilities and lsp_context_enrichment propagation
Scenario: ReactiveConfigParser propagates lsp_capabilities and lsp_context_enrichment
Given a v3 LLM actor config dict with lsp_capabilities and lsp_context_enrichment
When I parse the v3 config through ReactiveConfigParser
Then the agent config should contain lsp_capabilities
And the agent config should contain lsp_context_enrichment
# Coverage: config_parser.py — graph actor without route raises ConfigurationError
Scenario: ReactiveConfigParser rejects v3 graph actor without route
Given a v3 graph actor config dict without route
When I parse the v3 config through ReactiveConfigParser expecting error
Then a ConfigurationError should be raised mentioning route
# Coverage: config_parser.py — non-dict node and empty-id node skipped in graph
Scenario: ReactiveConfigParser skips non-dict and empty-id nodes in graph route
Given a v3 graph actor config dict with malformed nodes
When I parse the v3 config through ReactiveConfigParser
Then the reactive config should only have agents for valid nodes
# Coverage: config_parser.py — skills and lsp propagated to graph nodes
Scenario: ReactiveConfigParser propagates skills and lsp bindings to graph nodes
Given a v3 graph actor config dict with skills and lsp
When I parse the v3 config through ReactiveConfigParser
Then each graph node agent should have skills propagated
And each graph node agent should have lsp propagated
# Coverage: config_parser.py — lsp as dict propagated to graph nodes (line 330)
Scenario: ReactiveConfigParser propagates lsp dict bindings to graph nodes
Given a v3 graph actor config dict with skills and lsp as dict
When I parse the v3 config through ReactiveConfigParser
Then each graph node agent should have lsp dict propagated