Files
cleveragents-core/features/skill_discovery.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

177 lines
7.5 KiB
Gherkin

Feature: Agent Skills Discovery
As a developer using CleverAgents
I want to discover Agent Skills from configured filesystem paths
So that external tool bundles are automatically registered in the ToolRegistry
Background:
Given the agent skills discovery module is available
# --- Config key ---
Scenario: Config key skills.agent_skills_paths is registered
When I check the config registry for "skills.agent_skills_paths"
Then the config entry should exist
And the config entry type should be "str"
And the config entry env var should be "CLEVERAGENTS_SKILLS_AGENT_SKILLS_PATHS"
# --- Path parsing ---
Scenario: Parse single agent skills path
When I parse agent skills paths "~/.cleveragents/agent_skills"
Then the result should contain 1 path
Scenario: Parse multiple comma-separated paths
When I parse agent skills paths "/opt/skills,/home/user/skills"
Then the result should contain 2 paths
Scenario: Parse empty agent skills paths
When I parse an empty agent skills path string
Then the result should contain 0 paths
Scenario: Parse paths with whitespace around commas
When I parse agent skills paths "/opt/skills , /home/user/skills"
Then the result should contain 2 paths
# --- Discovery ---
Scenario: Discover agent skills from directory with SKILL.md
Given a temporary directory with agent skill folders
| folder_name | skill_name | description |
| my-tool | my-tool | A test agent skill |
When I scan the directory for agent skills
Then I should discover 1 agent skill
And the discovered skill "my-tool" should have description "A test agent skill"
Scenario: Discover multiple agent skills
Given a temporary directory with agent skill folders
| folder_name | skill_name | description |
| tool-a | tool-a | First tool |
| tool-b | tool-b | Second tool |
| tool-c | tool-c | Third tool |
When I scan the directory for agent skills
Then I should discover 3 agent skills
Scenario: Skip directories without SKILL.md
Given a temporary directory with some folders missing SKILL.md
When I scan the directory for agent skills
Then I should discover 0 agent skills
Scenario: Handle non-existent directory gracefully
When I run discovery on a non-existent directory
Then the discovery result should have 0 discovered skills
And the discovery result should have errors mentioning "does not exist"
Scenario: Handle SKILL.md without front-matter
Given a temporary directory with a SKILL.md that has no front-matter
When I scan the directory for agent skills
Then I should discover 0 agent skills
Scenario: Fall back to folder name when SKILL.md has no name field
Given a temporary directory with agent skill folders
| folder_name | skill_name | description |
| fallback-tool | _none_ | Some description |
When I scan the directory for agent skills
Then I should discover 1 agent skill
And the discovered skill should use folder name as name
# --- ToolSpec building ---
Scenario: Build ToolSpec from discovered agent skill
Given a discovered agent skill named "my-tool" at "/opt/skills/my-tool"
When I build a ToolSpec from the discovered skill
Then the ToolSpec name should be "agent_skills/my-tool"
And the ToolSpec source should be "agent_skills"
And the ToolSpec source_metadata should contain path "/opt/skills/my-tool"
# --- Registration ---
Scenario: Register discovered agent skills in ToolRegistry
Given a ToolRegistry with no existing tools
And a list of 2 discovered agent skills
When I register discovered skills with "skip" conflict strategy
Then 2 tools should be registered in the ToolRegistry
And 0 conflicts should be reported
Scenario: Skip registration on name collision with skip strategy
Given a ToolRegistry with an existing tool "agent_skills/collider"
And a discovered agent skill named "collider"
When I register discovered skills with "skip" conflict strategy
Then 0 tools should be registered in the ToolRegistry
And 1 conflict should be reported with tool name "agent_skills/collider"
Scenario: Error on name collision with error strategy
Given a ToolRegistry with an existing tool "agent_skills/collider"
And a discovered agent skill named "collider"
When I register discovered skills with "error" conflict strategy
Then a discovery ValueError should be raised mentioning "name collision"
Scenario: Replace existing tool on collision with replace strategy
Given a ToolRegistry with an existing tool "agent_skills/collider"
And a discovered agent skill named "collider"
When I register discovered skills with "replace" conflict strategy
Then 1 tool should be registered in the ToolRegistry
And the tool "agent_skills/collider" should have source "agent_skills"
# --- Refresh ---
Scenario: Refresh removes old agent skills and re-discovers
Given a SkillRegistryService with a ToolRegistry
And agent skills paths pointing to a directory with 2 skills
When I call discover_and_register
Then 2 agent skills should be registered
When the directory now has 3 skills and I call refresh_agent_skills
Then 3 agent skills should be registered
# --- Edge cases ---
Scenario: Register empty discovered list returns empty
Given a ToolRegistry with no existing tools
When I register an empty discovered skills list
Then the registration should return 0 specs and 0 conflicts
Scenario: Scan non-directory path returns empty
When I scan a non-directory path for agent skills
Then I should discover 0 agent skills
Scenario: Discover with path that is a file not a directory
When I run discovery on a path that is a file
Then the discovery result should have 0 discovered skills
And the discovery result should have errors mentioning "not a directory"
Scenario: SKILL.md with invalid YAML front-matter
Given a temporary directory with a SKILL.md that has invalid YAML
When I scan the directory for agent skills
Then I should discover 0 agent skills
Scenario: SKILL.md with empty YAML block
Given a temporary directory with a SKILL.md that has empty front-matter
When I scan the directory for agent skills
Then I should discover 0 agent skills
Scenario: SKILL.md with non-dict YAML
Given a temporary directory with a SKILL.md that has non-dict YAML
When I scan the directory for agent skills
Then I should discover 0 agent skills
Scenario: Skill with non-string description in front-matter
Given a temporary directory with a SKILL.md that has numeric description
When I scan the directory for agent skills
Then I should discover 1 agent skill
Scenario: Skill with empty description falls back to default
Given a temporary directory with a SKILL.md that has empty description
When I scan the directory for agent skills
Then I should discover 1 agent skill
And the first discovered skill description should contain "Agent skill from"
Scenario: Noop handler returns expected placeholder
When I call the noop handler
Then the noop handler should return status "agent_skill_placeholder"
# --- Source metadata ---
Scenario: Source metadata is included when resolving skill tools
Given a registered skill "local/test-skill" with an agent_skill source
When I resolve tools for "local/test-skill"
Then the resolved tools should include agent_skill source entries