Feature: Skill Domain Model and Resolution As a developer I want skill domain models and a resolver for the skill registry So that skills can be registered, validated, resolved, and managed via CLI # ---- Skill Creation ---- Scenario: Create a skill with valid fields When I create a skill_model with name "local/code-tools" and description "Code editing tools" Then the skill_model should be created And the skill_model name should be "local/code-tools" And the skill_model description should be "Code editing tools" And the skill_model namespace should be "local" And the skill_model short_name should be "code-tools" Scenario: Create a skill with tool refs When I create a skill_model with tool refs "local/edit-file,local/read-file" Then the skill_model should be created And the skill_model should have 2 tool refs Scenario: Create a skill with all fields populated When I create a skill_model with all fields Then the skill_model should be created And the skill_model should have 2 tool refs And the skill_model should have 1 include And the skill_model should have 1 anonymous tool And the skill_model should have 1 mcp server And the skill_model should have 1 agent skill # ---- Skill Name Validation ---- Scenario: Skill name must match namespace/name pattern When I try to create a skill_model with invalid name "no-namespace" Then a skill_model validation error should be raised And the skill_model error should mention "namespace/name" Scenario: Skill name rejects spaces When I try to create a skill_model with invalid name "local/bad name" Then a skill_model validation error should be raised Scenario: Skill name rejects double slashes When I try to create a skill_model with invalid name "local//bad" Then a skill_model validation error should be raised Scenario: Skill name allows hyphens and underscores When I create a skill_model with name "my-ns/my_skill" and description "Test" Then the skill_model should be created And the skill_model namespace should be "my-ns" And the skill_model short_name should be "my_skill" Scenario: Skill description must not be empty When I try to create a skill_model with empty description Then a skill_model validation error should be raised # ---- Include Resolution (flat) ---- Scenario: Resolve skill with flat includes Given a skill_resolver registry with "local/basic-tools" containing refs "local/edit-file,local/read-file" And a skill_resolver root skill "local/code-tools" including "local/basic-tools" with own refs "local/format" When I resolve the skill_resolver root skill Then the skill_resolver result should have 3 tools And the skill_resolver result should contain tool "local/edit-file" And the skill_resolver result should contain tool "local/read-file" And the skill_resolver result should contain tool "local/format" # ---- Include Resolution (nested) ---- Scenario: Resolve skill with nested includes Given a skill_resolver registry with "local/base" containing refs "local/core-tool" And a skill_resolver registry with "local/mid" including "local/base" and containing refs "local/mid-tool" And a skill_resolver root skill "local/top" including "local/mid" with own refs "local/top-tool" When I resolve the skill_resolver root skill Then the skill_resolver result should have 3 tools And the skill_resolver result should contain tool "local/core-tool" And the skill_resolver result should contain tool "local/mid-tool" And the skill_resolver result should contain tool "local/top-tool" # ---- Cycle Detection ---- Scenario: Cycle detection with error message Given a skill_resolver registry with "local/a" including "local/b" And a skill_resolver registry with "local/b" including "local/a" When I try to resolve skill_resolver "local/a" Then a skill_resolver cycle error should be raised And the skill_resolver error should mention "local/a" And the skill_resolver error should mention "local/b" Scenario: Self-referencing cycle detection Given a skill_resolver registry with "local/self" including "local/self" When I try to resolve skill_resolver "local/self" Then a skill_resolver cycle error should be raised # ---- De-duplication ---- Scenario: De-duplication behavior last wins for overrides Given a skill_resolver registry with "local/a" containing refs "local/shared-tool" And a skill_resolver registry with "local/b" containing refs "local/shared-tool" And a skill_resolver root skill "local/top" including "local/a,local/b" with no own refs When I resolve the skill_resolver root skill Then the skill_resolver result should have 1 tools And the skill_resolver tool "local/shared-tool" should come from "local/b" # ---- Override Application ---- Scenario: Override application on tool refs When I create a skill_model with overrides for "local/edit-file" And I resolve the overridden skill_model Then the skill_resolver tool "local/edit-file" should have overrides # ---- Empty Skill ---- Scenario: Empty skill with no tools or includes When I create a skill_model with name "local/empty" and description "Empty skill" And I resolve the empty skill_model Then the skill_resolver result should have 0 tools # ---- from_config Loading ---- Scenario: Load skill from config dict When I load a skill_model from config with name "local/my-skill" Then the skill_model should be created And the skill_model name should be "local/my-skill" Scenario: Load skill from config missing name raises error When I try to load a skill_model from config missing "name" Then a skill_model config error should be raised with "name" Scenario: Load skill from config missing description raises error When I try to load a skill_model from config missing "description" Then a skill_model config error should be raised with "description" Scenario: Load skill from config with full YAML structure When I load a skill_model from full config Then the skill_model should be created And the skill_model should have 2 tool refs And the skill_model should have 1 include And the skill_model should have 1 anonymous tool And the skill_model should have 1 mcp server And the skill_model should have 1 agent skill Scenario: Load skill from config with string includes When I load a skill_model from config with string includes Then the skill_model should be created And the skill_model should have 1 include Scenario: Load skill from config with string agent skills When I load a skill_model from config with string agent skills Then the skill_model should be created And the skill_model should have 1 agent skill # ---- as_cli_dict Output ---- Scenario: Skill as_cli_dict has required keys When I create a skill_model and call as_cli_dict Then the skill_model cli dict should have key "name" And the skill_model cli dict should have key "description" And the skill_model cli dict should have key "namespace" And the skill_model cli dict should have key "short_name" Scenario: Skill as_cli_dict includes optional sections when set When I create a skill_model with all fields and call as_cli_dict Then the skill_model cli dict should have key "tool_refs" And the skill_model cli dict should have key "includes" And the skill_model cli dict should have key "anonymous_tools" And the skill_model cli dict should have key "mcp_servers" And the skill_model cli dict should have key "agent_skills" And the skill_model cli dict should have key "overrides" Scenario: Skill as_cli_dict omits empty sections When I create a skill_model with name "local/minimal" and description "Minimal" And I get the skill_model cli dict Then the skill_model cli dict should not have key "tool_refs" And the skill_model cli dict should not have key "includes" And the skill_model cli dict should not have key "anonymous_tools" And the skill_model cli dict should not have key "mcp_servers" And the skill_model cli dict should not have key "agent_skills" And the skill_model cli dict should not have key "overrides" # ---- Inline Tool Validation ---- Scenario: Inline tool with valid custom source When I create a skill_model inline tool with source "custom" and code "print('hi')" Then the skill_model inline tool should be created Scenario: Inline tool has default timeout of 300 When I create a skill_model inline tool with source "custom" and code "print('hi')" Then the skill_model inline tool timeout should be 300 Scenario: Inline tool timeout must be >= 1 When I try to create a skill_model inline tool with timeout 0 Then a skill_model validation error should be raised Scenario: Inline tool description must not be empty When I try to create a skill_model inline tool with empty description Then a skill_model validation error should be raised # ---- MCP Source Validation ---- Scenario: MCP source with specific tools When I create a skill_model mcp source with server "npx @mcp/server" and tools "read,write" Then the skill_model mcp source should be created And the skill_model mcp source should have 2 tools Scenario: MCP source with all tools (none specified) When I create a skill_model mcp source with server "npx @mcp/server" and no tools Then the skill_model mcp source should be created And the skill_model mcp source tools should be none Scenario: MCP source with env vars When I create a skill_model mcp source with env vars Then the skill_model mcp source should be created Scenario: MCP source server must not be empty When I try to create a skill_model mcp source with empty server Then a skill_model validation error should be raised # ---- Agent Skill Source Validation ---- Scenario: Agent skill source with valid path When I create a skill_model agent source with path "./skills/review" Then the skill_model agent source should be created Scenario: Agent skill source path must not be empty When I try to create a skill_model agent source with empty path Then a skill_model validation error should be raised # ---- CapabilitySummary Computation ---- Scenario: CapabilitySummary computation for skill with inline tools When I compute skill_model capability summary for a skill with inline tools Then the skill_model summary total tools should be 4 And the skill_model summary read_only_tools should be 1 And the skill_model summary write_tools should be 1 And the skill_model summary has_side_effects should be true And the skill_model summary mcp_sources should be 1 And the skill_model summary agent_skill_sources should be 1 Scenario: CapabilitySummary for empty skill When I compute skill_model capability summary for an empty skill Then the skill_model summary total tools should be 0 # ---- SkillToolRef ---- Scenario: SkillToolRef creation When I create a skill_model tool ref with name "local/my-tool" Then the skill_model tool ref should be created # ---- SkillInclude ---- Scenario: SkillInclude creation with overrides When I create a skill_model include with name "local/base" and overrides Then the skill_model include should be created And the skill_model include should have overrides Scenario: SkillInclude creation without overrides When I create a skill_model include with name "local/base" without overrides Then the skill_model include should be created # ---- Missing included skill ---- Scenario: Resolve with missing included skill raises error Given a skill_resolver root skill "local/broken" including "local/nonexistent" with no own refs When I try to resolve skill_resolver "local/broken" Then a skill_resolver missing skill error should be raised And the skill_resolver error should mention "local/nonexistent" # ---- MCP and agent skill resolution ---- Scenario: Resolve skill with MCP and agent skill sources When I create and resolve a skill_model with mcp and agent sources Then the skill_resolver result should have 3 tools # ---- ResolvedToolEntry ---- Scenario: ResolvedToolEntry creation When I create a skill_resolver resolved tool entry Then the skill_resolver entry should be created # ---- Robot Smoke Mirrors (Behave equivalents of robot/skill_resolution.robot) ---- Scenario: Resolver output ordering matches depth-first include order Given a skill_resolver registry with "local/base-tools" containing refs "local/edit-file,local/read-file" And a skill_resolver root skill "local/code-tools" including "local/base-tools" with own refs "local/format" When I resolve the skill_resolver root skill Then the skill_resolver result should have 3 tools And the skill_resolver tool at index 0 should be "local/edit-file" And the skill_resolver tool at index 1 should be "local/read-file" And the skill_resolver tool at index 2 should be "local/format" Scenario: Resolver de-duplicates overlapping include tools with last-wins Given a skill_resolver registry with "local/a" containing refs "local/shared-tool,local/a-only" And a skill_resolver registry with "local/b" containing refs "local/shared-tool,local/b-only" And a skill_resolver root skill "local/top" including "local/a,local/b" with no own refs When I resolve the skill_resolver root skill Then the skill_resolver result should have 3 tools And the skill_resolver tool "local/shared-tool" should come from "local/b" Scenario: Resolver includes inline tools with correct anon keys When I create and resolve a skill_model with inline tools Then the skill_resolver result should contain tool "local/inline-test/_anon_0" And the skill_resolver result should contain tool "local/inline-test/_anon_1" And the skill_resolver inline tool at index 1 should be marked inline