Files
cleveragents-core/features/actor_loading.feature
T
HAL9000 155e5dd586
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Failing after 19s
CI / push-validation (pull_request) Successful in 20s
CI / helm (pull_request) Successful in 32s
CI / quality (pull_request) Successful in 33s
CI / typecheck (pull_request) Successful in 53s
CI / security (pull_request) Successful in 1m4s
CI / coverage (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Has been skipped
CI / build (pull_request) Successful in 3m18s
CI / e2e_tests (pull_request) Successful in 6m18s
CI / integration_tests (pull_request) Successful in 7m2s
CI / unit_tests (pull_request) Successful in 8m53s
CI / docker (pull_request) Has been skipped
CI / status-check (pull_request) Failing after 1s
fix(tests): correct indentation in actor_loading.feature
Fixed Gherkin syntax error where the 'LLM actor without tools' scenario had
incorrect indentation (3 spaces instead of 2), which prevented the feature
file from being parsed correctly by Behave. This was causing the concurrency
test scenario to fail during test discovery.

ISSUES CLOSED: #8588
2026-04-14 00:16:06 +00:00

272 lines
16 KiB
Gherkin

Feature: Actor registry and loader
As a CleverAgents user
I want to discover, load, and cache actor YAML configs from the filesystem
So that actors are available for compilation and execution
#
# Discovery from search roots
#
Scenario: Discover actors from a single directory
Given a temporary actors directory with files
| filename | name | type | model |
| reviewer.yaml | assistants/reviewer | llm | gpt-4 |
| formatter.yaml | utilities/formatter | llm | gpt-4 |
When I create an actor loader with that directory as search root
And I run discovery
Then the loader should find 2 actors
And the loader should contain actor "assistants/reviewer"
And the loader should contain actor "utilities/formatter"
Scenario: Discover actors from multiple search roots
Given a temporary actors directory "root_a" with files
| filename | name | type | model |
| writer.yaml | assistants/writer | llm | gpt-4 |
And a temporary actors directory "root_b" with files
| filename | name | type | model |
| analyst.yaml | data/analyst | llm | gpt-4 |
When I create an actor loader with both directories as search roots
And I run discovery
Then the loader should find 2 actors
And the loader should contain actor "assistants/writer"
And the loader should contain actor "data/analyst"
Scenario: Only YAML files are discovered
Given a temporary actors directory with files
| filename | name | type | model |
| valid.yaml | assistants/valid | llm | gpt-4 |
And a non-YAML file "readme.txt" in the directory
And a non-YAML file "config.json" in the directory
When I create an actor loader with that directory as search root
And I run discovery
Then the loader should find 1 actors
Scenario: Nested YAML files are discovered recursively
Given a temporary actors directory with nested structure
| subdir | filename | name | type | model |
| sub | nested.yaml | assistants/nested | llm | gpt-4 |
| sub/deep | deep.yaml | assistants/deep | llm | gpt-4 |
And a top-level actor file
| filename | name | type | model |
| top.yaml | assistants/top | llm | gpt-4 |
When I create an actor loader with that directory as search root
And I run discovery
Then the loader should find 3 actors
# ────────────────────────────────────────────────────────────
# Duplicate detection
# ────────────────────────────────────────────────────────────
Scenario: Duplicate actor names across search roots emit consolidated error
Given a temporary actors directory "dup_a" with files
| filename | name | type | model |
| writer.yaml | assistants/writer | llm | gpt-4 |
And a temporary actors directory "dup_b" with files
| filename | name | type | model |
| writer2.yaml | assistants/writer | llm | gpt-4 |
When I create an actor loader with both directories as search roots
And I run discovery expecting errors
Then the loader should raise a validation error mentioning "assistants/writer"
Scenario: Duplicate actor names within a single search root emit error
Given a temporary actors directory with files
| filename | name | type | model |
| one.yaml | assistants/helper | llm | gpt-4 |
| two.yaml | assistants/helper | llm | gpt-4 |
When I create an actor loader with that directory as search root
And I run discovery expecting errors
Then the loader should raise a validation error mentioning "assistants/helper"
# ────────────────────────────────────────────────────────────
# Namespace handling
# ────────────────────────────────────────────────────────────
Scenario: Default local/ namespace applied when namespace omitted
Given a temporary actors directory with a nameless actor file
| filename | raw_name | type | model |
| bare.yaml | my-agent | llm | gpt-4 |
When I create an actor loader with that directory as search root
And I run discovery
Then the loader should contain actor "local/my-agent"
Scenario: Explicit namespace preserved as-is
Given a temporary actors directory with files
| filename | name | type | model |
| custom.yaml | myteam/my-actor | llm | gpt-4 |
When I create an actor loader with that directory as search root
And I run discovery
Then the loader should contain actor "myteam/my-actor"
# ────────────────────────────────────────────────────────────
# Namespaced lookup
# ────────────────────────────────────────────────────────────
Scenario: Get actor by namespaced name
Given a temporary actors directory with files
| filename | name | type | model |
| helper.yaml | assistants/helper | llm | gpt-4 |
When I create an actor loader with that directory as search root
And I run discovery
Then I can retrieve actor "assistants/helper" by name
And the retrieved actor type should be "llm"
Scenario: Get nonexistent actor returns None
Given a temporary actors directory with files
| filename | name | type | model |
| helper.yaml | assistants/helper | llm | gpt-4 |
When I create an actor loader with that directory as search root
And I run discovery
Then getting actor "assistants/missing" should return None
Scenario: List actors filtered by namespace
Given a temporary actors directory with files
| filename | name | type | model |
| rev.yaml | assistants/reviewer | llm | gpt-4 |
| fmt.yaml | utilities/formatter | llm | gpt-4 |
| ana.yaml | assistants/analyzer | llm | gpt-4 |
When I create an actor loader with that directory as search root
And I run discovery
Then listing loaded actors with namespace "assistants" should return 2 actors
And listing loaded actors with namespace "utilities" should return 1 actors
# ────────────────────────────────────────────────────────────
# Content hash caching
# ────────────────────────────────────────────────────────────
Scenario: Unchanged files are not reloaded on re-discovery
Given a temporary actors directory with files
| filename | name | type | model |
| cached.yaml | assistants/cached | llm | gpt-4 |
When I create an actor loader with that directory as search root
And I run discovery
And I run discovery again
Then the actor "assistants/cached" should have been loaded only once
Scenario: Modified files are reloaded on re-discovery
Given a temporary actors directory with files
| filename | name | type | model |
| mutable.yaml | assistants/mutable | llm | gpt-4 |
When I create an actor loader with that directory as search root
And I run discovery
And I modify the actor file "mutable.yaml" to change the model to "gpt-3.5-turbo"
And I run discovery again
Then the actor "assistants/mutable" model should be "gpt-3.5-turbo"
# ────────────────────────────────────────────────────────────
# Validation at load time
# ────────────────────────────────────────────────────────────
Scenario: Invalid YAML file is rejected with clear error
Given a temporary actors directory with an invalid YAML file "bad.yaml"
When I create an actor loader with that directory as search root
And I run discovery expecting errors
Then the loader should raise a validation error mentioning "bad.yaml"
Scenario: YAML file missing required fields is rejected
Given a temporary actors directory with a schema-invalid file "incomplete.yaml"
When I create an actor loader with that directory as search root
And I run discovery expecting errors
Then the loader should raise a validation error
# ────────────────────────────────────────────────────────────
# Integration with example actors
# ────────────────────────────────────────────────────────────
Scenario: Discover all example actors from examples/actors/
Given the project examples/actors directory exists
When I create an actor loader with the examples/actors directory
And I run discovery
Then the loader should find at least 5 actors
# ────────────────────────────────────────────────────────────
# Cache invalidation
# ────────────────────────────────────────────────────────────
Scenario: Clear cache removes all loaded actors
Given a temporary actors directory with files
| filename | name | type | model |
| test.yaml | assistants/test | llm | gpt-4 |
When I create an actor loader with that directory as search root
And I run discovery
And I clear the loader cache
Then the loader should find 0 actors
Scenario: Deleted actor file is removed on re-discovery
Given a temporary actors directory with files
| filename | name | type | model |
| keep.yaml | assistants/keep | llm | gpt-4 |
| remove.yaml | assistants/removable | llm | gpt-4 |
When I create an actor loader with that directory as search root
And I run discovery
And I delete the actor file "remove.yaml"
And I run discovery again
Then the loader should find 1 actors
And the loader should contain actor "assistants/keep"
And getting actor "assistants/removable" should return None
# ────────────────────────────────────────────────────────────
# Tool Registry integration
# ────────────────────────────────────────────────────────────
Scenario: Actor loader resolves tool references through tool registry
Given a tool registry with tool "files/read_file"
And a temporary actors directory with a tool-actor file
| filename | name | type | tools |
| tools.yaml | utilities/file_ops | tool | files/read_file |
When I create an actor loader with that directory and the tool registry
And I run discovery
Then the loader should contain actor "utilities/file_ops"
And the actor "utilities/file_ops" tools should include "files/read_file"
Scenario: Actor with unresolvable tool reference logs warning
Given an empty tool registry
And a temporary actors directory with a tool-actor file
| filename | name | type | tools |
| tools.yaml | utilities/ops | tool | missing/nonexistent |
When I create an actor loader with that directory and the tool registry
And I run discovery
Then the loader should contain actor "utilities/ops"
And the loader should have a warning about unresolved tool "missing/nonexistent"
# ────────────────────────────────────────────────────────────
# Edge cases for coverage
# ────────────────────────────────────────────────────────────
Scenario: Non-existent search root is skipped gracefully
Given a non-existent directory path as search root
When I create an actor loader with that directory as search root
And I run discovery
Then the loader should find 0 actors
Scenario: YAML file containing a list instead of a mapping is rejected
Given a temporary actors directory with a list-content YAML file "list.yaml"
When I create an actor loader with that directory as search root
And I run discovery expecting errors
Then the loader should raise a validation error mentioning "list.yaml"
Scenario: LLM actor without tools does not produce warnings with tool registry
Given a tool registry with tool "files/read_file"
And a temporary actors directory with files
| filename | name | type | model |
| simple.yaml | assistants/simple | llm | gpt-4 |
When I create an actor loader with that directory and the tool registry
And I run discovery
Then the loader should contain actor "assistants/simple"
And the loader should have 0 warnings
# ────────────────────────────────────────────────────────
# Concurrency and race conditions
# ────────────────────────────────────────────────────────
@unit @actor @concurrency
Scenario: list_actors with namespace filter is thread-safe under concurrent clear/discover
Given a temporary actors directory with files
| filename | name | type | model |
| rev.yaml | assistants/reviewer | llm | gpt-4 |
| fmt.yaml | utilities/formatter | llm | gpt-4 |
| ana.yaml | assistants/analyzer | llm | gpt-4 |
When I create an actor loader with that directory as search root
And I run discovery
And 5 threads concurrently call list_actors with namespace "assistants" while another thread calls clear
Then all concurrent list_actors calls should return consistent results